how to change axes limits in a 3D matlab plot - matlab

I have a 3-D plot which I want to cut somehow to show the most interested part and avoid the flat parts (as shown in the picture the blue and orange parts to be the least). I think that it can be done using change of the axis limits in x but different for x_{back} and x_{front} which means I want to change the limits of x front axis to (-20,20) and x back to (-80,-40). How can I do this?

I think krisdestruction is right, it would be such an infrequently-used feature that it's probably not worth the development time or added complexity for TMW to implement.
But you could kludge it. If you were to rotate your data so that the feature aligns with the axes then you could crop the plot to the region of interest as desired. Then hide the grid and draw a new one yourself.
If you're careful you can arrange it so that you can still use the axis labels at the front, which will save you some time, but if not you can always use text to draw new ones on.
I would rotate the data using a rotational transform matrix, which will be pretty quick, and you might be able to pull the gridlines out of the gca object and apply the rotation matrix to those too, which would save you from having to compute them all explicitly.
If you expect to do this more than once or twice then you could encapsulate it all in a nice function that works out the rotation angle from a given pair of 'front' and 'back' axis limits.
Then you can post it to the file exchange : )

Related

Constructing voxels of a 3D cube in MATLAB

I want to construct a 3D cube in MATLAB. I know that the units of any 3D shape are voxels not pixels. Here is what I want to do,
First, I want to construct a cube with some given dimensions x, y, and z.
Second, according to what I understand from different image processing tutorials, this cube must consists of voxels (3D pixels). I want to give every voxel an initial color value, say gray.
Third, I want to access every voxel and change its color, but I want to distinguish the voxels that represent the faces of the cube from those that represent the internal region. I want to axis every voxel by its position x,y, z. At the end, we will end up with a cube that have different colors regions.
I've searched a lot but couldn't find a good way to implement that, but the code given here seems very close in regard to constructing the internal region of the cube,
http://www.mathworks.com/matlabcentral/fileexchange/3280-voxel
But it's not clear to me how it performs the process.
Can anyone tell me how to build such a cube in MATLAB?
Thanks.
You want to plot voxels! Good! Lets see how we can do this stuff.
First of all: yeah, the unit of 3D shapes may be voxels, but they don't need to be. You can plot an sphere in 3D without it being "blocky", thus you dont need to describe it in term of voxels, the same way you don't need to describe a sinusoidal wave in term of pixels to be able to plot it on screen. Look at the figure below. (same happens for cubes)
If you are interested in drawing voxels, I generally would recommend you to use vol3D v2 from Matlab's FEX. Why that instead of your own?
Because the best (only?) way of plotting voxels is actually plotting flat square surfaces, 6 for each cube (see answer here for function that does that). This flat surfaces will also create some artifacts for something called z-fighting in computer graphics. vol3D actually only plots 3 surfaces, the ones looking at you, saving half of the computational time, and avoiding ugly plotting artifacts. It is easy to use, you can define colors per voxel and also the alpha (transparency) of each of them, allowing you to see inside.
Example of use:
% numbers are arbitrary
cube=zeros(11,11,11);
cube(3:9,3:9,3:9)=5; % Create a cube inside the region
% Boring: faces of the cube are a different color.
cube(3:9,3:9,3)=2;
cube(3:9,3:9,9)=2;
cube(3:9,3,3:9)=2;
cube(3:9,9,3:9)=2;
cube(3,3:9,3:9)=2;
cube(9,3:9,3:9)=2;
vold3d('Cdata',cube,'alpha',cube/5)
But yeah, that still looks bad. Because if you want to see the inside, voxel plotting is not the best option. Alphas of different faces stack one on top of the other and the only way of solving this is writing advanced computer graphics ray tracing algorithms, and trust me, that's a long and tough road to take.
Very often one has 4D data, thus data that contains 3D location and a single data for each of the locations. One may think that in this case, you really want voxels, as each of them have a 3D +color, 4D data. Indeed! you can do it with voxels, but sometimes its better to describe it in some other ways. As an example, lets see this person who wanted to highlight a region in his/hers 4D space (link). To see a bigger list I suggest you look at my answer in here about 4D visualization techniques.
Lets try wits a different approach than the voxel one. Lets use the previous cube and create isosurfaces whenever the 4D data changes of value.
iso1=isosurface(cube,1);
iso2=isosurface(cube,4);
p1=patch(iso1,'facecolor','r','facealpha',0.3,'linestyle','none');
p2=patch(iso2,'facecolor','g','facealpha',1,'linestyle','none');
% below here is code for it to look "fancy"
isonormals(cube,p1)
view(3);
axis tight
axis equal
axis off
camlight
lighting gouraud
And this one looks way better, in my opinion.
Choose freely and good plotting!

How to reverse the direction of Y-Axis of MatLab figure generated by `imagesc()` function

I am trying to display data in a matrix using imagesc() function but it is showing row index in decreasing order (Assuming origin at left-bottom). Any idea what mistake i could be making or how to correct this?
The matrix only has zeros and ones in it.
Set Ydir property of the current axes to normal
By default, imagesc uses reverse for YDir
set(gca,'YDir','normal');
See Documentation for Axes properties
Before:
After:
Note: This completely flips the inside data as well (it supposed to). As you are dealing with matrices, I hope this is what you want.
If you don't want to affect inside data, you need to change order of YTickLabels instead.
There's another option which requires slightly less code:
axis ij
Reverse the coordinate system so that the y values increase from top to bottom.
As in this case (as it is already reversed), you could use
axis xy
To get back to normal, so that y values increases from bottom to top.
As mentioned in the docs of axis.

Place MATLAB legend such that it does not overlap on the plot

I am generating multiple plots of different datasets in succession using MATLAB. I would like the legend positions to be such that they don't overlap on the plotted lines and it would be ideal if this placement could be done automatically.
I am aware of setting the 'Location' to 'best' to achieve this but the placement of the legend tends to be awkward when 'best' is used (below). Also, I would like the legend to be inside the plot. I also came across a way to make the legend transparent (here) so that it does not render the plotted data invisible, but explicitly placing the legend elsewhere is what I am looking for.
Is there a way to place the legend at the extremes of the image ('NorthWest', 'SouthWest' etc) automatically such that it does not overlap on the plotted data (apart from the methods suggested above)?
So, you have tried using Location instead of Position? For example:
x =1:100;
y = x.^2;
lgd = legend('y = x.^2');
set(lgd,'Location','best')
and you are getting odd results correct? A quick way of solving this would be to still use Location, with best, and extract the coordinates:
lgd.Position
You should get something like this:
ans =
0.7734 0.3037 0.1082 0.0200
which maps to:
[left bottom width height]
You will need to focus on left and bottom. These two values, left and bottom, specify the distance from the lower left corner of the figure to the lower left corner of the legend, and they are analogous to the grid frame you are using.
Then, depending on the size of the frame (I would suggest you use axis([XMIN XMAX YMIN YMAX]) for this, if possible), you can pinpoint the position of the legend within the grid. What you can do next, is check if and which of your graphs in the plot cross paths with the legend (maybe define a relative distance function based on some distance threshold) and if they do, then randomly reposition the legend (i.e. change the values of left and bottom) and repeat until your conditions are met.
If this still troubles you I can write a short snippet. Finally, know that you can always opt for placing the legend on the outside:
set(lgd,'Location','BestOutside')

How to neatly cut off an extreme value in a plot that compresses the rest of a plot?

So basically, the graph labeled "Thermal Wind" has an extreme value that compresses the y-values for all the other plots, making it much harder to see any of the individual variations in the other plots. Is there a way to neatly cut off this extreme value? I could just rescale the y limit to a maximum of 40, but then this looks ugly.
As for the alternative I've tried - it's here:
I would recommend trying to plot it on a log scale. The function you'll want to consider using is semilogx, though for completeness I recommend also reading the help file on loglog.
Alternately, you could use subplot to generate multiple plots, one of which is zoomed into a region of interest.
Are the outlier points errors in the data, or do they represent extreme cases?
If they are not valid data, just manually exclude them from the data, plot the graph, and include a text clarification when describing the graph. If they are valid data, then trimming them would misrepresent the data, which isn't a good thing.
Graphs of data aren't art: their main goal isn't to be pretty; it's to provide a useful visualization of data. There are some minimum requirements on appearance, however: the axes have to be labeled, the units have to be meaningful, the different curves have to be visually distinct, etc. As long as your graph has these things, you shouldn't expect to lose marks for presentation.
There are two approaches that I use:
One approach would be transform the data so it will fill the plot nicely. Make the transform so that it wouldn't touch the range - say -10 to +10. In your case you could choose it so that 100 transforms to +15 and -100 to -15.
For clarity you need to then also set and label the y ticks appropriately. And for nice style make sure the line changes slope when it goes over the border.
I plot the data as is. But set the axis limits say from -10 to +10. Where points lay outside I place upwards and downwards triangles along the border to mark in which direction the "outliers" would be. Obviously this is only good when there aren't too many.

CorePlot polar plot

It became apparent that I needed to attempt to modify CorePlot code to allow me to plot Polar/Radar plots, due to heavy memory usage trying to plot circles/spokes as ScatterPlots.
I realised I could continue to use CPTScatterPlot for the actual polar data, however somehow I needed to modify the drawGridLinesInContext, such that instead of straight lines at each location, CPTXCoordinate would draw the circular line, CPTYCoordinate would be ignored, and CPTZCoordinate would draw the spokes.
I had to create new classes based on their XY siblings viz CPTPolarGraph, CPTPolarPlotSpace, CPTPolarAxisSet, CPTPolarAxis. The new code continues to use X and Y axis to plot those axes, however a Z axis was introduced to manage the spokes.
Now I seem to have cracked this, however if I scroll up and down, the circles continue to pass through the X and Y axis ticks, as they should do, but when I scroll left and right, the circles get redrawn and no longer sit on the ticks.
I obviously got some more debugging to do here, but was hoping for some pointers from the CorePlot crew, as to what might be happening
.
I can zip my modified version of CorePlot_1.1, including a example polar scatter plot, and forward if needs be.
The positioning of the centreViewPoint tracks precisely, as the spokes are always generated from the same point, wherever the centre is in the plotArea. The rings are also always generated from the same centre.
It seems to me that somehow, the diameters of the rings when I scroll left right get changed from the first plot presentation, yet when I scrolled Up-down they don't. Notice that when the plot is scrolled to left edge or right edge the major rings are line up on the major ticks again, as are the minor.
I tried reversing the code such that only the CPTCoordinateY get plotted, and I see the same effect, except scrolling up-down exhibits the changing in ring diameter size.
Now perhaps CGPoint startViewPoint = [thePlotSpace plotAreaViewPointForPlotPoint:startPlotPoint]; which establishes the diameter of a ring from its x-coordinate, is not returning correctly. Although perhaps also the locations set are changing, but why should they if no zooming has been done.
I'm kind of struggling here, as when I walk through the code the locations don't appear to change.
This is likely a pixel alignment issue. The tick drawing code aligns the tick marks with the pixel grid but the new axis drawing does not. Look at CPTAlignRectToUserSpace() and the other alignment functions in CPTUtilities.h.
Edit:
You also may need a custom setter method for the zRange in the plot space. Make it similar to the xRange and yRange setters. The notifications fired by these methods are important—they force other parts of the graph to redraw when the plot space changes.