d3.js - Time scale with ticks in milliseconds - d3.js

I need to plot a line graph where x-axis will have ticks representing time with milliseconds detail.
For x-scale, I am using d3.time.scale()
var xScale = d3.time.scale()
.range([0, width])
x-axis looks like:
var xAxis = d3.svg.axis()
.scale(xScale)
//.ticks(d3.time.second, 1)
.orient("bottom")
.tickFormat(d3.time.format("%H:%M %L"));
But values/ticks on x-axis are not generating as expected.
data for x-axis are date objects and they hold following values(sample data)
13:25:6 794 (%H:%M%S %L)
13:25:6 898
13:25:6 994
13:25:7 95
13:25:7 194
13:25:7 295
13:25:7 395
13:25:7 495
13:25:7 595
13:25:7 710
13:25:7 795
13:25:7 895
13:25:7 995
13:25:8 95
13:25:8 195
13:25:8 294
13:25:8 395
13:25:8 495
13:25:8 594
13:25:8 795
However if I take linear scale d3.scale.linear()
Ticks generated follow a expected series.
whats the correct way of using time scale with data having millisecond details.
How can I have tick intervals in seconds:milliseconds?
EDIT:
Also, how can I have ticks every few milliseconds say every 500 ms?
there is an API d3.time.second but nothing like d3.time.millisecond. How can I add one?
Fiddle using time scale

intervals in seconds:milliseconds means, you can try out this
.tickFormat(d3.time.format("%S %L"));

(Removed outdated previous answer)
I created an issue for this against the d3 project and it has been fixed: https://github.com/mbostock/d3/issues/1529
An example can be seen here: http://bl.ocks.org/mbostock/6618724

Related

Processing 2d scatter plot

How to load .csv file and use data in the table to create 2d scatter plot.
The data inside the table is
Name X Y Group Gender Year of Birth Grade
Victor Anderson 627 705 2 Female 2000 6
Jack Scott 808 643 1 Male 2002 4
Sean Robinson 624 627 1 Male 2002 4
William Rodriguez 423 396 1 Female 2004 2
Aaron Kelly 775 181 0 Female 2005 1
Raymond Taylor 433 731 1 Female 2000 1
Alan Foster 635 580 2 Male 2002 4
Charles Watson 884 262 0 Female 2003 3
Lillian Perez 334 190 4 Male 2005 1
Betty Moore 727 524 1 Female 2003 3
Bruce Adams 503 684 0 Male 2001 2
Kathryn Sanchez 284 246 0 Male 2001 2
Chris Hall 189 223 3 Male 2000 6
Eugene Harris 196 220 3 Female 2000 5
Gary Baker 707 559 0 Female 2001 5
Michael Ramirez 299 657 2 Male 2000 1
Walter Smith 400 755 0 Male 2005 5
Ann Murphy 0 895 1 Male 2003 3
Lois Thompson 783 631 1 Female 2003 2
Louis Jones 674 589 1 Female 2003 3
Tammy Bell 828 263 3 Male 2002 4
Carolyn Bailey 557 23 4 Male 2004 2
Larry Campbell 444 627 2 Female 2004 2
To draw a simple scatter plot from the data in the csv we need to:
Ensure X and Y columns can be read as numbers
Normalize or scale the X and Y values to the canvas size
Plot a point for each row at its scaled x and y position
Add labels
For the first item we could add code to clean up X and Y and turn them into numbers. Below I have assumed that X and Y will always be integers and removed white space so we can just call row.getInt()
The data is saved like this:
Name,X,Y,Group,Gender,Year of Birth,Grade
Victor Anderson,627,705,2,Female,2000,6
Jack Scott,808,643,1,Male,2002,4
Notice that extra white space has been removed so that we can call table and row methods without special cleanup code.
Table table;
int xMin;
int yMin;
int xMax;
int yMax;
void setup() {
size(900, 900);
table = loadTable("plot_data.csv", "header");
background(0);
fill(255);
// we get the minimum and maximum values for X and Y so we can scale to our canvas
xMin = getMin(table, "X");
yMin = getMin(table, "Y");
xMax = getMax(table, "X");
yMax = getMax(table, "Y");
}
void draw(){
background(0);
boolean labelDrawn = false;
for (TableRow row : table.rows()) {
int x = row.getInt("X");
// the map function takes our value and maps it to a value that fits on our canvas
float xPos = map(x, xMin, xMax, 0, width);
int y= row.getInt("Y");
float yPos = map(y, yMin, yMax, 0, height);
ellipse(xPos,yPos,10,10);
// Here we put a name label on the plotted data when the mouse is over it
if(dist(mouseX,mouseY,xPos,yPos)<10 && !labelDrawn){
fill(255);
text(row.getString("Name"),mouseX-10,mouseY-10);
labelDrawn = true; // only draw one label at a time
}
}
}
int getMin(Table table, String col){
int min = Integer.MAX_VALUE;
for (TableRow row : table.rows()){
if (row.getInt(col)<min){
min = row.getInt(col);
}
}
return min;
}
int getMax(Table table, String col){
int max = Integer.MIN_VALUE;
for (TableRow row : table.rows()){
if (row.getInt(col)>max){
max = row.getInt(col);
}
}
return max;
}

d3 v4 force graph doesn't stop moving after applying links

I have this code that is working great except that the only way I can figure out to stop making it spin is to turn up the velocityDecay, which makes the animation the point when a new node is introduced to be quite slow -- and doesn't actually stabilize the animation -- it's always moving slightly.
Here's the relevant parts of the code (or tell me if there are other important components):
```
60 let simulation = d3.forceSimulation()
61 .force('link', d3.forceLink()
62 .id((d) => { return d.index + 1 })
63 .distance(200)
64 .strength(1))
65 .force('charge', d3.forceManyBody())
66 .force('x', d3.forceX())
67 .force('y', d3.forceY())
68 .alphaTarget(1)
69 .on('tick', ticked)
70 .force('center', d3.forceCenter(window.innerWidth/2, window.innerHeight/2))
71 .force('collide', d3.forceCollide( (d) => { return 150 }).iterations(16))
72
73 svg.append('g').attr('class', 'links')
74
75 let link = svg.select('.links')
76 .selectAll('.link')
77 .data(links)
78 .enter().append('path')
79 .attr('class', 'link')
80 .attr('fill', 'transparent')
81 .attr('stroke', 'black')
82 .attr('stroke-width', '10px')
83 .exit()
84 .remove()
107 link = link.data(links)
108 .enter().append('path')
109 .attr('class', (d) => {
110 return 'link link-' + d.source + '-' + d.target
111 })
112 .attr('fill', 'transparent')
113 .attr('stroke', 'black')
114 .attr('stroke-width', '10px')
115 .merge(link)
116 link.exit().remove()
147 simulation.nodes(nodes)
148 .on('tick', ticked)
149 simulation
150 .force('charge', d3.forceManyBody())
151 // .force('center', d3.forceCenter(window.innerWidth/2, window.innerHeight/2))
152 // .force('collide', d3.forceCollide( (d) => { return 150 }).iterations(156))
153 // .alphaTarget(1)
154 .alphaDecay(.5)
155 // .alpha(1)
156 // .velocityDecay(.95)
157 .force('link', d3.forceLink()
158 .id((d) => { return d.index + 1})
159 .distance(200)
160 .iterations(20)
161 .strength(1))
162 .force('x', d3.forceX())
163 .force('y', d3.forceY())
164 .force('link').links(links)
165 simulation.restart()
```

imcrop into 1 variable

I have made a a group of new pictures using imcrop from the same file, With this code, I know it's long but since the distances are not always the same I find no other way to do it than this:
A001=imcrop(A,[65 159 95 332]);
A002=imcrop(A,[182 161 95 332]);
A003=imcrop(A,[297 164 95 332]);
A004=imcrop(A,[402 165 90 332]);
A005=imcrop(A,[495 168 90 332]);
A006=imcrop(A,[606 166 90 332]);
A007=imcrop(A,[705 171 90 332]);
A008=imcrop(A,[808 175 90 332]);
A009=imcrop(A,[922 175 90 332]);
A0010=imcrop(A,[1031 175 90 332]);
Then I have a series of tasks to be performed on each of the new images, how do i get around that the easiest way? When I import multiple jpegs from a folder I can get it to make a dataset of the files but when I try to do the same with A001:A0010 I get nothing.
This is the task that I want to perform:
greenChannel = A(:, :, 2);
BW = edge(greenChannel,'Prewitt');
figure, imshow(BW)
%Dialate Lines
se90 = strel('line', 3, 90);
se0 = strel('line', 3, 0);
BWsdil = imdilate(BW, [se90 se0]);;
figure, imshow(BWsdil), title('dilated gradient mask');
%Fill Lines
BWdfill = imfill(BWsdil, 'holes');
figure, imshow(BWdfill);
title('binary image with filled holes');
BWnobord = imclearborder(BWdfill, 4);
figure, imshow(BWnobord), title('cleared border image');
seD = strel('diamond',1);
BWfinal = imerode(BWnobord,seD);
BWfinal = imerode(BWfinal,seD);
figure, imshow(BWfinal), title('segmented image');
L = bwlabel(BWfinal);
s = regionprops(L,'centroid');
What I need help to do is somehow get A001:A0010 into A in the top and run that sequence of commands, hope someone can help me achieve that!
This is hairy, but here goes:
A = imread('peppers.png');
A = imresize(A, [1500 1500]); % to handle the indexing range.
A001=imcrop(A,[65 159 95 332]);
A002=imcrop(A,[182 161 95 332]);
A003=imcrop(A,[297 164 95 332]);
A004=imcrop(A,[402 165 90 332]);
A005=imcrop(A,[495 168 90 332]);
A006=imcrop(A,[606 166 90 332]);
A007=imcrop(A,[705 171 90 332]);
A008=imcrop(A,[808 175 90 332]);
A009=imcrop(A,[922 175 90 332]);
A0010=imcrop(A,[1031 175 90 332]);
w = who; % returns the names of all your current variables in a cell.
for i = 1:numel(w)
% A00 is unique to all the variables you want to process.
if ~isempty(strfind(w{i}, 'A00'))
% hard coding greenChannel and extracting the second plane.
eval(['greenChannel = ',w{i},'(:,:,2)']);
% do the rest of the processing here,
% from BW = edge ... to regionprops.
% You may have to save the s structure as a cell array.
end
end
This uses the who command to extract all the current variables, and the eval command to evaluate what is passed in as text, based on the variable names. Note that using eval is dangerous, and should be done only if there are no better alternatives. See Use and implications of eval('expression') in MATLAB code?

MATLAB: finding values in one array and using those locations to change values in one channel of a separate 3 channel array

So I have a labeled array (array1) with connected regions of interest (background is all zeros, connected regions are all 1's for the first region, all 2's for the second, 3's for the 3rd etc.) I also have a vector (vector1) of the region labels I find important (ex. 1,6,9). I want to find the locations of these values in the labeled array and then change values in one channel of a separate 3 channel array at the same locations (want to color certain parts of an image green based regions of interest found in another image).
I can use the below code to change all channels, but don't know how to specify (img(y,x,1=0), img(y,x,2=0), img(y,x,3=255)).
for i=1:1:length(vector1)
img(array1==vector1(i))=255;
end
If I understand you correctly, you have a label map of objects - each with an associated ID with 0 as the background. You also have a vector of important IDs and a colour image that is associated with this label map.
You wish to set all locations that have an important ID to 1 colour. I would first create a logical mask where true means that the pixel is important and false otherwise. What I mean by important is that the pixel is either 1, 6 or 9 if we go with your example. You can use bsxfun combined with any to create this mask, then we can use this to index into your image and set the right colour to these locations.
Therefore, do this:
%// Create your logical mask
mask3D = bsxfun(#eq, array1, permute(vector(:), [3 2 1]));
mask = any(mask3D, 3);
%// Set the image pixels to blue at these locations
red = img(:,:,1);
green = img(:,:,2);
blue = img(:,:,3);
red(mask) = 0;
green(mask) = 0;
blue(mask) = 255;
img = cat(3, red, green, blue);
Here's a quick example run. Suppose we have this image with squares:
We can see that there are three squares. Let's change object 1 and object 3 to blue. Before we do that, we need to get a label map:
%// Originally a binary image
im = imread('http://i.stack.imgur.com/DnYQS.png');
%// Get label map
array1 = bwlabel(im);
%// Create colour version out of this binary image
img = 255*uint8(im);
img = cat(3, img, img, img);
array1 is our label map as you have also mentioned in your question and img is the colour version of the input image. Now, vector = [1 3] so we can change those objects. The labelling is such that the top left square is label 1, the middle is label 2 and the bottom right is label 3.
Once I do this and I run the above code, this is the image I get:
You can achieve it in two lines -
%// Create a 3D mask to select the labels [1,6,9] only, as listed in "vector1"
mask = bsxfun(#and,ismember(array1,vector1),ones(1,1,3));
%// Map "img" with "mask" and set them to tuple:[0,0,255] (blue color)
img(mask) = reshape(repmat([0 0 255],nnz(mask)/3,1),[],1)
Sample run -
array1 = %// Input
2 0 1 1 0 6
0 0 1 0 0 6
9 0 0 0 0 6
9 9 0 4 0 0
vector1 = %// Input
1 6 9
img(:,:,1) = %// Input: Before code run
228 19 175 30 192 188
204 23 34 164 149 248
188 204 185 84 189 222
14 241 29 167 60 22
img(:,:,2) =
94 202 197 59 200 136
95 94 53 164 26 24
175 53 100 124 75 104
153 23 141 39 61 27
img(:,:,3) =
29 246 111 48 197 172
201 111 168 68 101 110
75 178 28 204 70 116
154 194 239 125 10 156
img(:,:,1) = %// Output: After code run
228 19 0 0 192 0
204 23 0 164 149 0
0 204 185 84 189 0
0 0 29 167 60 22
img(:,:,2) =
94 202 0 0 200 0
95 94 0 164 26 0
0 53 100 124 75 0
0 0 141 39 61 27
img(:,:,3) =
29 246 255 255 197 255
201 111 255 68 101 255
255 178 28 204 70 255
255 255 239 125 10 156
Notice the positions of the values [1,6,9] in array1 and the corresponding value changes in img1 before and after code runs.

How to speed up matplotlib scatter ploting?

I need to draw a batch of scatter charts in matplotlib, and found the speed of matplotlib is slow, then I lineprofile the function, and found the hotspot is fig, ax = plt.subplots(), It costs 56.1% of time to creat a blank figure and axes !!
How to speed it up ? I mean, how can I reuse fig and ax to avoid creating them each time ?
Attach the profile report here (I cut some of the line to make it simple)
Total time: 0.733771 s
Line # Hits Time Per Hit % Time Line Contents
==============================================================
517 #profile
518 def df_scatter(df):
519 ''' draw the scatter plot for Pandas dataframe 'df'
533 '''
536
537 1 75 75.0 0.0 biggest_area = 1000
538 1 117 117.0 0.0 mycm = matplotlib.cm.get_cmap('jet') # 'spectral'
539
541 1 78 78.0 0.0 col_qty = len(df.columns)
543
544 1 1859 1859.0 0.1 x = list(df.ix[:,0].values)
545 1 1258 1258.0 0.0 y = list(df.ix[:,1].values)
551
552 1 1472345 1472345.0 56.1 fig, ax = plt.subplots()
556
557 1 7007 7007.0 0.3 plt.subplots_adjust(left=0.07, right=0.92, bottom=0.1, top=0.95)
558 1 179 179.0 0.0 x_margin, y_margin = (max(x)-min(x))/20, (max(y)-min(y))/20
563
564 1 71 71.0 0.0 if col_qty > 2:
565 1 1602 1602.0 0.1 r = list(df.ix[:,2].values)
566 1 309 309.0 0.0 size_r = np.array(biggest_area)*r/max(r)
585
586 1 34712 34712.0 1.3 sc = plt.scatter(x, y, marker='o', s=size_r, cmap=mycm, alpha=0.65)
587
588 # adding colorbar
589 1 542417 542417.0 20.7 cbaxes = fig.add_axes([0.94, 0.25, 0.02, 0.70])
590 1 165719 165719.0 6.3 cbar = plt.colorbar(sc, cax=cbaxes)
591 1 122 122.0 0.0 cbar.solids.set_edgecolor('face')
595
602 1 1061 1061.0 0.0 plt.figtext(0.94,0.10,"%0.1f"%(max(r)), fontproperties=TEXT_FONT_MEDIUM)
639 1 66 66.0 0.0 return fig
I think that the best way to do it is calling
fig = plt.figure()
ax=fig.add_subplot(111)
from outside of df_scatter. Then, pass it to df_scatter as arguments:
df_scatter(df,fig,ax):
or simply do inside df_scatter:
def df_scatter(df):
fig = plt.gcf()
ax = plt.gca()
after the creation of fig & axis was done.

Resources