I am producing a number of charts in a loop, using example code below
forvalues i = 1/11 {
local t: label (countryID) `i'
twoway line Var1 Var2 Var3 year if countryID == `i', ylabel(, valuelabel grid ///
angle(horizontal)) xlabel(1999(2)2013) xtitle("") ///
lpattern("l" "dash_dot" "longdash") legend(size(small)) title("`t'")
graph export output/PredictLaw`t'.png, replace
}
The values of each variable are labeled, but only at integer level. The variable itself can take any value between two integers, though. Consequently, I would like to ensure somehow that the yaxis uses only integers as distance, e.g. always in steps of 1.
However, since the range for each country is different, I would like Stata to determine how long the range of the y-axis has to be, as shorter ranges of course produce neater looking graphs. Hence, I would rather not use something in the form of ylabel(1(1)21, ....
Is there a way to define the spacing of the y-axis, while keeping the range of the y-axis a Stata determined variable?
After
summarize whatever, meanonly
local ymin = floor(r(min))
local ymax = ceil(r(max))
give integer results you can invoke in graph calls. The small detail here that you round down the minimum, if you do any rounding, and round up the maximum, ditto, given floor() and ceil() functions, could add a smidgen of space that suits graphical purposes.
Related
I want to do scattered interpolation in Matlab, but scatteredInterpolant does not do quite what I want.
scatteredInterpolant allows me to provide a set of input sampling positions and the corresponding sample values. Then I can query the interpolated values by supplying a set of positions:
F = scatteredInterpolant(xpos, ypos, samplevals)
interpvals = F(xgrid, ygrid)
This is sort of the opposite of what I want. I already have a fixed set of sample positions, xpos/ypos, and output grid, xgrid/ygrid, and then I want to vary the sample values. The use case is that I have many quantities sampled at the same sampling positions, that should all be interpolated to the same output grid.
I have an idea how to do this for nearest neighbor and linear interpolation, but not for more general cases, in particular for natural neighbor interpolation.
This is what I want, in mock code:
G = myScatteredInterpolant(xpos, ypos, xgrid, ygrid, interp_method)
interpvals = G(samplevals)
In terms of what this means, I suppose G holds a (presumably sparse) matrix of weights, W, and then G(samplevals) basically does W * samplevals, where the weights in the matrix W depends on the input and output grid, as well as the interpolation method (nearest neighbor, linear, natural neighbor). Calculating the matrix W is probably much more expensive than evaluating the product W * samplevals, which is why I want this to be reused.
Is there any code in Matlab, or in a similar language that I could adapt, that does this? Can it somehow be extracted from scatteredInterpolant in reasonable processing time?
Assume we have a 3D grid that spans some 3D space. This grid is made out of cubes, the cubes need not have integer length, they can have any possible floating point length.
Our goal is, given a point and a direction, to check linearly each cube in our path once and exactly once.
So if this was just a regular 3D array and the direction is say in the X direction, starting at position (1,2,0) the algorithm would be:
for(i in number of cubes)
{
grid[1+i][2][0]
}
But of course the origin and the direction are arbitrary and floating point numbers, so it's not as easy as iterating through only one dimension of a 3D array. And the fact the side lengths of the cubes are also arbitrary floats makes it slightly harder as well.
Assume that your cube side lengths are s = (sx, sy, sz), your ray direction is d = (dx, dy, dz), and your starting point is p = (px, py, pz). Then, the ray that you want to traverse is r(t) = p + t * d, where t is an arbitrary positive number.
Let's focus on a single dimension. If you are currently at the lower boundary of a cube, then the step length dt that you need to make on your ray in order to get to the upper boundary of the cube is: dt = s / d. And we can calculate this step length for each of the three dimensions, i.e. dt is also a 3D vector.
Now, the idea is as follows: Find the cell where the ray's starting point lies in and find the parameter values t where the first intersection with the grid occurs per dimension. Then, you can incrementally find the parameter values where you switch from one cube to the next for each dimension. Sort the changes by the respective t value and just iterate.
Some more details:
cell = floor(p - gridLowerBound) / s <-- the / is component-wise division
I will only cover the case where the direction is positive. There are some minor changes if you go in the negative direction but I am sure that you can do these.
Find the first intersections per dimension (nextIntersection is a 3D vector):
nextIntersection = ((cell + (1, 1, 1)) * s - p) / d
And calculate the step length:
dt = s / d
Now, just iterate:
if(nextIntersection.x < nextIntersection.y && nextIntersection.x < nextIntersection.z)
cell.x++
nextIntersection.x += dt.x
else if(nextIntersection.y < nextIntersection.z)
cell.y++
nextIntersection.y += dt.y
else
cell.z++
nextIntersection.z += dt.z
end if
if cell is outside of grid
terminate
I have omitted the case where two or three cells are changed at the same time. The above code will only change one at a time. If you need this, feel free to adapt the code accordingly.
Well if you are working with floats, you can make the equation for the line in direction specifiedd. Which is parameterized by t. Because in between any two floats there is a finite number of points, you can simply check each of these points which cube they are in easily cause you have point (x,y,z) whose components should be in, a respective interval defining a cube.
The issue gets a little bit harder if you consider intervals that are, dense.
The key here is even with floats this is a discrete problem of searching. The fact that the equation of a line between any two points is a discrete set of points means you merely need to check them all to the cube intervals. What's better is there is a symmetry (a line) allowing you to enumerate each point easily with arithmetic expression, one after another for checking.
Also perhaps consider integer case first as it is same but slightly simpler in determining the discrete points as it is a line in Z_2^8?
I have a matrix named figmat from which I obtain the following pcolor plot (Matlab-Version R 2016b).
Basically I only want to extract the bottom red high intensity line from this plot.
I thought of doing it in some way of extracting the maximum values from the matrix and creating some sort of mask on the main matrix. But I'm not understanding a possible way to achieve this. Can it be accomplished with the help of any edge/image detection algorithms?
I was trying something like this with the following code to create a mask
A=max(figmat);
figmat(figmat~=A)=0;
imagesc(figmat);
But this gives only the boundary of maximum values. I also need the entire red color band.
Okay, I assume that the red line is linear and its values can uniquely be separated from the rest of the picture. Let's generate some test data...
[x,y] = meshgrid(-5:.2:5, -5:.2:5);
n = size(x,1)*size(x,2);
z = -0.2*(y-(0.2*x+1)).^2 + 5 + randn(size(x))*0.1;
figure
surf(x,y,z);
This script generates a surface function. Its set of maximum values (x,y) can be described by a linear function y = 0.2*x+1. I added a bit of noise to it to make it a bit more realistic.
We now select all points where z is smaller than, let's say, 95 % of the maximum value. Therefore find can be used. Later, we want to use one-dimensional data, so we reshape everything.
thresh = min(min(z)) + (max(max(z))-min(min(z)))*0.95;
mask = reshape(z > thresh,1,n);
idx = find(mask>0);
xvec = reshape(x,1,n);
yvec = reshape(y,1,n);
xvec and yvec now contain the coordinates of all values > thresh.
The last step is to do some linear polynomial over all points.
pp = polyfit(xvec(idx),yvec(idx),1)
pp =
0.1946 1.0134
Obviously these are roughly the coefficients of y = 0.2*x+1 as it should be.
I do not know, if this also works with your data, since I made some assumptions. The threshold level must be chosen carefully. Maybe some preprocessing must be done to dynamically detect this level if you really want to process your images automatically. There might also be a simpler way to do it... but for me this one was straight forward without the need of any toolboxes.
By assuming:
There is only one band to extract.
It always has the maximum values.
It is linear.
I can adopt my previous answer to this case as well, with few minor changes:
First, we get the distribution of the values in the matrix and look for a population in the top values, that can be distinguished from the smaller values. This is done by finding the maximum value x(i) on the histogram that:
Is a local maximum (its bin is higher than that of x(i+1) and x(i-1))
Has more values above it than within it (the sum of the height of bins x(i+1) to x(end) < the height of bin x):
This is how it is done:
[h,x] = histcounts(figmat); % get the distribution of intesities
d = diff(fliplr(h)); % The diffrence in bin height from large x to small x
band_min_ind = find(cumsum(d)>size(figmat,2) & d<0, 1); % 1st bin that fit the conditions
flp_val = fliplr(x); % the value of x from large to small
band_min = flp_val(band_min_ind); % the value of x that fit the conditions
Now we continue as before. Mask all the unwanted values, interpolate the linear line:
mA = figmat>band_min; % mask all values below the top value mode
[y1,x1] = find(mA,1); % find the first nonzero row
[y2,x2] = find(mA,1,'last'); % find the last nonzero row
m = (y1-y2)/(x1-x2); % the line slope
n = y1-m*x1; % the intercept
f_line = #(x) m.*x+n; % the line function
And if we plot it we can see the red line where the band for detection was:
Next, we can make this line thicker for a better representation of this line:
thick = max(sum(mA)); % mode thickness of the line
tmp = (1:thick)-ceil(thick/2); % helper vector for expanding
rows = bsxfun(#plus,tmp.',floor(f_line(1:size(A,2)))); % all the rows for each column
rows(rows<1) = 1; % make sure to not get out of range
rows(rows>size(A,1)) = size(A,1); % make sure to not get out of range
inds = sub2ind(size(A),rows,repmat(1:size(A,2),thick,1)); % convert to linear indecies
mA(inds) = true; % add the interpolation to the mask
result = figmat.*mA; % apply the mask on figmat
Finally, we can plot that result after masking, excluding the unwanted areas:
imagesc(result(any(result,2),:))
What does the d3.scale.sqrt() scale do? As per the documentation it is similar to d3.scale.pow().exponent(.5), so the returned scale is equivalent to the sqrt function for numbers; for example:
sqrt(0.25) returns 0.5.
so when we apply a domain similar to this:
d3.scale.sqrt().domain([1, 100]).range([10, 39])
does it signify it takes the value between 1-100 and return the sqrt function which ranges between 10-39? Could anybody clarify and provide more details on how this scale works?
The way scales work in D3 is that they map input values (defined by .domain()) to output values (defined by .range()). So
d3.scale.sqrt().domain([1, 100]).range([10, 39])
maps values from 1 to 100 to the 10 to 39 range. That is, 1 corresponds to 10 and 100 to 39. This has nothing to do with the transformation the scale applies, which only affects the distribution of values within the range. For the sqrt function, the growth is sub-linear, which means that more of the input values will fall into the latter part of the output range.
I am trying to plot contour of the Shifted Schwefel Problem function but keep having this error: Z must be size 2x2 or greater. I have searched on this forum and the information i have helped a little, but could not fix the above error. The information i got from this forum lead me to trying this code:
min = -50;
max = 50;
steps = 20;
c = linspace(min, max, steps); % Create the mesh
[x, y] = meshgrid(c, c); % Create the grid
%o=-50+100*rand(1,2);
%c = c - repmat(o,1,10);
for I=1:length(x)
for J=1:length(y)
o=-50+100*rand(1,2);
x=x-repmat(o,20,10);
f = max(abs(x), [], 2);
end
end
figure,
contour(x,y,f);
figure,
surfc(x, y,f);
Now i have error that z, which the the value of f most be atleast 2x2 or greater. I know my f is taking only one input and therefore will output only one. I tried having it in a nested for loops, but still giving me a array of vectors not matrix of atleast 2x2. if the input was two, then the problem will be fine, but the problem is, it is one input. Does anyone know how i can make this "f" output a matrix of atleast 2x2 so that i can plot the z of the contour?
There are a few things to note:
1.) As Jacob Robbins pointed out correctly in his comment, you should avoid using names from Matlab functions as variable names (in your case min and max). One very easy way to do this, is to use only upper case letters for variable names.
2.) You are correct in saying that your fis only one output (though one output in this case is not a single number, but a vector). That is, because you don't assign any indexing to it within the loop.
3.) Yes, both contour and surfc need at least 2x2 - because they plot information on a grid, which is itself at least 2x2 in nature.
4.) In your particular case, two loops may not be necessary. You seem to only be manipulating the x-vector and your grid is regular. Hence you might want to try this loop:
for I=1:length(x)
o=-50+100*rand(1,2);
x=x-repmat(o,20,10);
f(:,I) = max(abs(x), [], 2);
end
Now, f will be of size 20x20, which corresponds to your x- and y-grid. Also, now your contour and surfc command will produce plots.
5.) One last comment: The output of your function and the results of a web-search for "Shifted Schwefel function" are very different. But the question if your implementation of the Shifted Schwefel function is correct, should be asked as a new question.