Can someone provide some insight on how scales and extents work together in cubism.js
.call(context.horizon()
.extent([-100, 100])
.scale(d3.scale.linear().domain([-10,10]).range([-100,100])
)
);
For example what does the code above do? If the values are generated using a random number generator (numbers between -10 and 10)
I know extent is used to set the maximum and minimum.
I know how to define a scale, example:
var scale = d3.scale.threshold().domain([100]).range([0,100])
console.log(scale(1)) // returns 0
console.log(scale(99.9)) // returns 0
console.log(scale(88.9)) // returns 0
console.log(scale(100)) // returns 100
I read about d3.scales here http://alignedleft.com/tutorials/d3/scales/
My main issue is that I want to define thresholds for my data, very simple
0-98 Red
98-100 Pink
100 Blue
Or maybe just
0-99.99 Red
100 Blue
But I'm not being able to use all what I've read to construct something that works.
I'm guessing that you just want to use a different color to represent anomalies in your data. If that is true, you don't need to create a domain and range.
You can just create a custom color palette like this:
var custom_colors = ['#ef3b2c', '#084594', '#2171b5', '#4292c6', '#6baed6', '#9ecae1', '#c6dbef', '#deebf7', '#f7fbff', '#f7fcf5', '#e5f5e0', '#c7e9c0', '#a1d99b', '#74c476', '#41ab5d', '#238b45', '#006d2c', '#00441b'];
This color palette was constructed using the palette on this page with an extra red color tacked on to the end.
Then just call the custom colors like this:
d3.select("#testdiv")
.selectAll(".horizon")
...
.call(context.horizon()
.colors(custom_colors)
));
Play around with the colors until you find a combination that you like. In this above example, only the outlier will be in red while the rest will follow the blue and green pattern.
Hope this helps!
Related
I can't grok the docs on d3's ordinal scales. The way I read it (and the way it works for linear scales, I feel I should be able to proceed like this:
color = d3.scale.ordinal();
color.domain([0, 100]); // Input is any percentage point 0-100
color.range([ // Output is a scale of colors from "bad" to "good"
'red','orange','blue','green'
]);
This doesn't give me the results I expect:
color(0); // "red". Ok, that makes sense
color(1); // "blue". Huh? This should be "red"
color(100); // "orange". Really? I'm confused. What's the range?
color.range(); //["red", "orange", "blue", "green"]. That looks right...
color.domain(); // [0,1,100]. Um...
It looks like it's treating inputs as discrete categorical values when I want to treat them like numbers.
The correct approach for mapping a range of numbers to discrete outputs is to use quantize. The difference wasn't clear to me and ordinal seemed intuitive. Figured it out now.
A working solution looks like this:
color = d3.scale.quantize();
color.domain([0, 100]);
color.range([
'red','orange','blue','green'
]);
color(0); // "red"
color(1); // "red"
color(99); // "green"
These links here helpful in figuring this out:
http://roadtolarissa.com/blog/2015/01/04/coloring-maps-with-d3/
What is the difference between d3.scale.quantize() and d3.scale.quantile()?
The approach to this is not exactly how it works. The domain you listed will point to 2 specific values in the range, the 2 first values - red and orange. Any other value that you add to the domain via color(n); will extend the domain array, eg. 1 is considered the 3rd index, therefore it is assigned the 3rd item in the range, if you were to call another item with color(n) you would get the 4th index. That is how the range method works.
I was looking for a way to change the default colors of the different categories in d3.js.
I found where the colors are laid out in the main d3.js. They look like this for one category:
var ml = [2062260, 16744206, 2924588, 14034728, 9725885, 9197131, 14907330, 8355711, 12369186, 1556175].map(yt)
I've tried replacing these values with everything from Hex codes to HSL to RGB and it never yields the expected colors.
Any ideas how I can generate the proper numbers for whatever colors I want?
Thanks.
First, just FYI, to see the RGB (i.e. hex) value that corresponds to these numbers:
(2062260).toString(16); // 16 for hex, aka base 16
> "1f77b4"
Next, given an RGB (again, hex) that you want to convert to number:
parseInt("1f77b4", 16); // 16 for hex
> 2062260
And that would be the number you want to use.
The colors you got from the d3 source are used to construct what you get from d3.scale.category10(). You can get the same thing but with your own colors — and without modifying d3's source code — by constructing a d3.scale.ordinal:
var myCategory3 = d3.scale.ordinal()
.domain(["red", "#1f77b4", "rgb(128, 255, 128)"]);// All kinds of colors are possible
myCategory3("X");// "red"
myCategory3("blabla");// "#1f77b4"
myCategory3("X");// "red"
myCategory3(123456);// "rgb(128, 255, 128)"
I have a histology image like this:
From the image, we can observe there are two kinds of different cells.
and
Is there any way that I can separate these two types of cells into two groups?
How about using your raw image and previous code to achieve this?
% % % your old code
I=imread(file);
t1=graythresh(I);
k1=im2bw(I,t1);
k1=~k1;
se = strel('disk',1);
k0=imfill(~k1,'holes');
cc = conncomp(k0);
k0(cc.PixelIdxList{1})=0;
k1=imfill(k1,'holes');
mask=k0 | k1;
%%%%%%%%%%%%%%%%%%
This will give you:
I=rgb2hsv(I);
I=double(I);
I1=I(:,:,1); % again, the channel that can maximizing the margin between donut and full circle
Imask=(I1-0.2).*(I1-0.9)<0;
k2=mask-Imask;
k2=bwareaopen(k2,100);
This will give you:
k2=mask-Imask;
I2=zeros(size(I1,1),size(I1,2),3);
I2(:,:,1)=(k2==1)*255;
I2(:,:,3)=((I1-0.2).*(I1-0.9)<0)*255;
imshow(I2)
will finally give you (the two types are stored in two channels in the rgb image):
I would use regionprops
props=regionprops(YourBinaryImage, 'Solidity');
The objects with a high solidity will be the disks, those with a lower solidity will be the circles.
(Edit) More formally:
I=imread('yourimage.jpg');
Bw=~im2bw(I, 0.5);
BWnobord = imclearborder(Bw, 4); % clears the partial objects
Props=regionprops(BWnobord, 'All');
solidity=cell2mat({Props.Solidity});
Images={Props.Image};
Access the elements of Images where the value in solidity is higher than 0.9 and you get your disks. The circles are the other ones.
Hope it helps
Is there a way in d3 to not draw overlapping tick labels? For example, if I have a bar chart, but the bars are only 5 pixels wide and the labels are 10 pixels wide, I end up with a cluttered mess. I'm currently working on an implementation to only draw the labels when they do not overlap. I can't find any existing way to do that, but wasn't sure if anyone else had dealt with this problem.
There is no way of doing this automatically in D3. You can set the number of ticks or the tick values explicitly (see the documentation), but you'll have to figure out the respective numbers/values yourself. Another option would be to rotate the labels such that there is less chance of them overlapping.
Alternatively, like suggested in the other answer, you could try using a force layout to place the labels. To clarify, you would use the force layout on the labels only -- this is completely independent of the type of chart. I have done this in this example, which is slightly more relevant than the one linked in the other answer.
Note that if you go with the force layout solution, you don't have to animate the position of the labels. You could simply compute the force layout until it converges and then plot the labels.
I've had a similar problem with multiple (sub-)axis, where the last tick overlaps my vertical axis in some situations (depending on the screen width), so I've just wrote a little function that compares the position of the end of the text label with the position of the next axis. This code is very specific to my use case, but could adapted easily to your needs:
var $svg = $('#svg');
// get the last tick of each of my sub-axis
$('.tick-axis').find('.tick:last-of-type').each(function() {
// get position of the end of this text field
var endOfTextField = $(this).offset().left + $(this).find('text').width();
// get the next vertical axis
var $nextAxis = $('line[data-axis="' + $(this).closest('.tick-axis').attr('data-axis') + '"]');
// there is no axis on the very right, so just use the svg width
var positionOfAxis = ($nextAxis.length > 0) ? $nextAxis.offset().left : $svg.offset().left + $svg.width();
// hide the ugly ones!
if (endOfTextField > positionOfAxis) {
$(this).attr('class', 'tick hide');
}
});
The ticks with color: aqua are the hidden ones:
I made a simulation of 10000 times and want to view part of simulation between 5000-5200. I am able to view it with the code below, but the x-axis says 0-250. I want the x-axis to display the exact figure of 5000-5200. Also there seems to be a small gap at the end of the figure as the axis runs up to 250 for some reason. I just want to view the figure in for this set time with the x-axis showing the exact labels and without the gap at the end.
Thanks
N=10000;%Number of simulation
P=0.02;
Q = zeros(N,1); %current value of queue
X=zeros(N,1);%simulation data
Ci=0;
L=0.9;
Bu=zeros(N,1);
Bs=30;
Bd1=50;
Bd2=270;
Ti=0;
for Ti=2:N
U=rand(1);
a=log10(U);
b=log10(1-P);
c=(a/b);
d=1+c;
X(Ti)=round(d);
Ci=Ci+1;
if X(Ti)< (L)*(Bs)
Bu(Ti)=Bs;
else if X(Ti) < (L)*(Bs+Bd1)
Bu(Ti)=Bs+Bd1;
else
Bu(Ti)=Bs+Bd1+Bd2;
end
end
Ti=Ti+1;
end
plot(X(5000:5200,1),'r');
set (gca,'ylim',[0 400]);
hold on;
plot(Bu(5000:5200,1),'b');
set (gca,'ylim',[0 400]);
hold off
Plot expects two inputs, the first depicting the horizontal axis and the second depicting the vertical axis. When you do not supply two inputs, then it computes the length of the single input (in this case that length is 5200-5000 = 200), and it just uses 1 through that length (1:200 in this case) as if it is the values for the horizontal axis variable.
I think you want to issue the command:
plot(5000:5200, X(5000:5200,1), 'r')
Often Matlab will adjust plot axes for better default views, so it's probably showing the axis out to the index 250 just by virtue of some default plotting convention. You can similarly use set(gca, 'xlim', [5000 5200]) if you wish.