MATLAB: How to NOT export data outside plot axis to SVG - matlab

Probably a too special question, but just in case someone has faced a similar problem.
I am using plot2svg to get plots from Matlab to Inkscape. It works fine, except for one pretty annoying problem. If I want to show just a zoomed part of a curve, plot2svg "captures" the whole curve and then clips it. As a result, the SVG file is much larger than it could be, and sometimes Inkscape even crashes on complex curves.
What would help is some way to remove the data outside the axis before exporting SVG. I've tried brushing (remove unbrushed), but then plot2svg fails:
Attempted to access parts(1); index out of bounds because numel(parts)=0.
Error in plot2svg>line2svg (line 2237)
if parts(1)~=1
Error in plot2svg>axchild2svg (line 1365)
line2svg(fid,groupax,axpos,x,y,scolorname,linestyle,linewidth)
Error in plot2svg>axes2svg (line 1042)
group = axchild2svg(fid,id,axIdString,ax,group,paperpos,axchild,axpos,groupax,projection,boundingBoxAxes);
Error in plot2svg (line 221)
group=axes2svg(fid,id,ax(j),group,paperpos);
Can anyone suggest any solution? I would like to avoid using the EPS or PDF export in Matlab because their quality is much worse than that of the plot2svg.
Matlab 2011b 64bit, plot2svg 10-Nov-2010, Win 7 Pro 64.

All values of your curve that lie outside the (zoomed in) axes should be set to NaN. Matlab will not draw these points and, hence, plot2svg will not export them. However, this involves redrawing the curve after zooming.
Make sure to save a handle to your curve when plotting it:
figure(1)
h = plot(yourXdata, yourYdata);
Then zoom in on your area of interest and afterwards run the following code:
figure(1)
hold on
myXlim = xlim;
myYlim = ylim;
% crop your data
yourXdata(yourXdata < myXlim(1)) = NaN;
yourXdata(yourXdata > myXlim(2)) = NaN;
yourYdata(yourYdata < myYlim(1)) = NaN;
yourYdata(yourYdata > myYlim(2)) = NaN;
% delete old curve and draw the new one
delete(h);
plot(yourXdata, yourYdata);

Related

How to avoid marker clipping in Matlab while saving two axis figure to pdf?

I have some trouble while exporting a two axis figure with Matlab to pdf. The following example code works great while creating the figure in Matlab. But in the generated pdf-file all my red markers on the x-axis get cut off (see screenshot). Curiously this problem only occures, when I use a two axis plot
Here is a screenshot of my figure
fig = figure;
x = linspace(0,25);
y = sin(x/2);
marker = linspace(0,25,5);
yyaxis left
plot(x,y,'g');
hold on;
r = x.^2/2;
yyaxis right
plot(x,r,'b');
hold on;
plot(marker,0,'rx','Markersize', 8);
saveas(gcf,'myfigure.pdf');
Can anyone please help me out here?
I’ve come into this a handful of times, super frustrating. I’ve usually tried some of the below options, and eventually something works. Some things to try:
Print as a png, then convert to PDF with gimp or something of the like (where 300 represents 300 dpi):
print(handle, savefilename, ‘-dpng’, ‘-r300’)
Print as a vector image with the painters renderer, then convert to PDF with gimp:
print(handle, savefilename, ‘-depsc’, ‘-painters’)
Try changing the marker to a different shape, or size, or both (using for example: 'markersize', 3, 'marker', 's')
Good luck. Let us know what ends up fixing it!

MATLAB: how to save a geoshow figure with faceAlpha?

I am trying to save a figure in Matlab R2014a in which I want to plot data over an Image. This is the code:
[Singapore, R] = geotiffread(file);
s = size(Singapore);
matrix = rand(s(1),s(2));
geoshow(Singapore(:,:,1:3), R)
hold on
geoshow(matrix, R, 'DisplayType', 'texturemap','facealpha',.2);
xlim([103.605,104.04])
ylim([1.2,1.475])
This one is the plot that works perfectly:
While when I am printing the figure
print(gcf, '-dpng', fullfile(FileF, 'test.png'))
the image is completely white
Many thanks for the image link!
I have tried your code (adapted for the `Singapore.tif' file you provided and an appropriate output file) and it works as expected on my system (Matlab 2013b, Linux 64-bit). This is the output file:
So I'm sorry to say that there's nothing wrong with your code, and it's probably something to do with the 'png' driver on windows or your particular installation. Have you tried printing to a different driver? (e.g. jpg or pdf?). Does it actually work if you do this from the figure's graphical menu, i.e. File->Save As; or via File->Export Setup->Export with appropriate properties?
The only other thing I can think of which may be confusing your system is the attempt to print a uint8 rgb image (your Singapore image) and an overlayed double grayscale image. You can see if converting your Singapore image to double solves this by changing:
geoshow(Singapore(:,:,1:3), R)
to
geoshow(mat2gray(Singapore(:,:,1:3)), R)
Might also be worth trying to plot the data manually and see if printing that works, e.g.:
[Singapore, R] = geotiffread('Singapore.tif');
SingaporeXYImage = cat(3, flipud(Singapore(:,:,1)), ...
flipud(Singapore(:,:,2)), ...
flipud(Singapore(:,:,3)));
s = size(Singapore);
matrix3D = repmat( rand(s(1),s(2)), [1,1,3]);
imagesc(R.LongitudeLimits, R.LatitudeLimits, mat2gray(SingaporeXYImage));
hold on;
imagesc(R.LongitudeLimits, R.LatitudeLimits, matrix3D, 'alphadata', .2);
hold off;
axis xy equal tight;
xlim([103.605,104.04])
ylim([1.2,1.475])
print(gcf, '-dpng', 'test.png');
As a bonus, here's how you might perform the same thing in Octave, in case you're interested (I find printed plots from Octave look much nicer, especially in terms of fonts!):
pkg load mapping;
pkg load image;
[SingaporeStruct, R] = rasterread('Singapore.tif');
SingaporeImage = cat(3, SingaporeStruct(1:3).data); % note this is a matrix of
% "doubles" in range [0,255]
SingaporeImage = mat2gray(SingaporeImage); % Convert to appropriate [0,1] range
% for "doubles" rgb images!
s = size (SingaporeImage);
matrix3D = repmat (rand (s(1), s(2)), [1, 1, 3]);
imagesc (R.bbox(:,1), R.bbox(:,2), ...
SingaporeImage .* 0.8 + matrix3D .* 0.2); % manually create
% transparency effect
axis xy equal tight
xlim([103.605,104.04])
ylim([1.2,1.475])
print (gcf, '-dpng', 'test.png');
Also, no disrespect to my colleague and the effort he / she put into his / her answer, but I will note that the other answer you received is essentially completely wrong and you should retract your marked accepted regardless of his / her claim and warnings about how rude it is to retract a marked answer. mapshow is specifically used for images using a MapCellsReference format: the boston.tif image is one such image. Your image however uses a GeographicCellsReference format. mapshow is used for the former, geoshow is used for the latter; geoshow would have failed for boston.tif, in the same way mapshow fails for Singapore.tif. It should have been obvious your image is a "Geo" variant because your line geoshow(Singapore(:,:,1:3), R) worked without throwing an error. Therefore the suggestion to use mapshow is not the correct answer to your question, and is misleading. Not to mention it is completely irrelevant to your actual question about why the print command does not produce the expected result from its figure handle, which should in theory have nothing to do with how the figure was produced in the first place. I would have no qualms about retracting your "accepted" mark from it. Not least because this site functions as a reference for many other viewers; it does not make sense to direct users to the wrong answer just because you got bullied into accepting it.
As suggested by mathworks, using mapshow should solve your problem. The following works for me:
[boston, R] = geotiffread('boston.tif');
figure
mapshow(boston, R);
axis image off
S = size(boston);
matrix=rand(S(1),S(2));
hold on
mapshow(matrix, R,'DisplayType','texturemap','facealpha',0.2);
print(gcf, '-dpng','test.png') ;

Semi-transparent markers on log-log scatter plot

I have been trying to get semi-transparent circle-shape markers on a log-log scatter plot. MATLAB's own scatter plot function doesn't produce semi-transparent markers (see comments below), so I am using this wonderful tool scatter_patches from Central File Exchange and it works very well:
However, I am having issues adapting this code for a log-log scatter plot. In order to obtain a log-log scatter plot with this program, I need to fix two things:
1 . Change the axes to log scale. This can be achieved by adding following after line 61:
set(cax, 'XScale', 'log');
set(cax, 'YScale', 'log');
This produces correct log scale and grid points.
2 . However, after I fixed 1., the size of the markers was not uniform in my plot. On a log plot, the lower-value regions of the axes are zoomed-in. In the scatter_patches plot, the markers at the lower side of axes are bigger while they are smaller towards the higher-value side of axes. So, the marker size is not the same on the entire plot. I tried using log10(cSize) instead of cSize on lines 221-222, but this only slimmed the difference between the largest and smallest marker sizes. It didn't yield the same size markers on the plot.
If anyone has an idea of what I might be missing here, please share.
Any help would be greatly appreciated.
Since Matlab R2014b things got really easy. No additional functions from file exchange are required, just some undocumented features. The basic idea is to get the hidden handle of the markers and apply a value < 1 for the last value in the EdgeColorData to achieve the desired transparency.
Here we go:
%// example data
x = linspace(0,3*pi,200);
y = cos(x) + rand(1,200);
%// plot scatter, get handle
h = scatter(x,y);
drawnow; %// important
%// get marker handle
hMarkers = h.MarkerHandle;
%// get current edge and face color
edgeColor = hMarkers.EdgeColorData
faceColor = hMarkers.FaceColorData
%// set face color to the same as edge color
faceColor = edgeColor;
%// opacity
opa = 0.3;
%// set marker edge and face color
hMarkers.EdgeColorData = uint8( [edgeColor(1:3); 255*opa] );
hMarkers.FaceColorData = uint8( [faceColor(1:3); 255*opa] );
In the event it helps, I have written a collection of Matlab functions for creating semi-transparent markers in plots and legends. The files are available from MATLAB Central as the MarkerTransparency package. A few examples of how to use these functions are included in the download and there is also a Wiki on GitHub. A major benefit of this package is it enables the user to have the semi-transparent markers also appear in the legend. These functions have not been tested for scatter plots but might be easily adapted to meet your needs.
On line 192 change the line with this one:
hh(end+1) = patch( exp(cSize * sin(patchSpec) / ptsPerXUnit + xs(i)), exp(cSize * cos(patchSpec) / ptsPerYUnit + ys(i)), cColor, cPatchArgs{:}); and it will work.
I just add an exp()
Do the same operation on line 222 and 223 to be sure !
Work like a charm Anindya ;).

Create 2D Spectrogram in Matlab

I am in need of plotting a 2D spectrogram of a signal in Matlab. I need it for a printed assignment, hence the 3D image makes no sense. However, when the signal is plotted using Spectrogram it automatically produces a 3D plot of the signal.
My Code:
Dataset = 1; % Dataset to be analysed
N = 1024; % Window size
Beta = 12; % Kaiser window beta value (small = narrow main lope)
Overlap = 800; % Window overlap
Threshold = -150; % Minimum magnitude before threshold
spectrogram(Enclosure{Dataset}(1:end),kaiser(N,Beta),Overlap,2048,fs,'MinThreshold',Threshold,'yaxis');
which produces a graph that looks like this:
But it is seen from the top, and the graph is really showing this:
The reason why i need it to specifically be 2D (and why i don't settle with a screenshot) is because i am using Matlab2tikz to convert Matlab figures into Tikz figures in LaTex. with the 3D images i get figures of +100 Mb and 2D will reduce the size to <1Mb.
I don't know what version of Matlab you are using but in 2015a you should be able to get a handle to the figure with the 3D plot and change the view angle to 2D:
view(0,90);
I've also got an example of how you can make your own 2D plot from the outputs of spectrogram() using a similar method:
x = [0:0.01:100];
y = sin(5*x);
y = awgn(y,0.1);
[S,F,T,P] = spectrogram(y,200,0,length(y)*5,100);
[m,n] = size(P);
figure(2)
surf(F,T,zeros(n,m),P','EdgeColor','none')
view(0,90)
xlabel('Frequency')
ylabel('Time (s)')
The output looks like this:
Hopefully since there is no altitude information, the figure size might be smaller but I can't test that since I don't have Matlab2tikz.
One option is to capture whatever its plotted and then plot it as an image. You can do this using getframe
if you do
F=getframe(gca);
cla;
imshow(F.cdata);
You'll get exactly what you will be seeing before, but as an image.
However I think it defeats a bit the purpose of Matlab2Tikz, as the idea os that you have Tikz code describing your data...
You can try the following:
[~,F,T,ps]=spectrogram(Enclosure{Dataset}(1:end),kaiser(N,Beta),Overlap,2048,fs,'MinThreshold',Threshold,'yaxis').
% Output the spectrum in ps
imagesc(T,F,10*log10(ps))
% Generate a 2d image
view(270,90)
xlabel('Time [s]')
ylabel('Frequency [Hz]')
c=colorbar;
c.Label.String='Power [dB]';
% Extra setting to make the plot look like the spectrogram
Good luck

Jagged outline using Matlab 2014b

I am plotting some maps using Matlab that use mapshow to plot the country border from a shapefile. I then export them to both a PDF and EPS format using the export_fig package. This worked completely fine using Matlab 2014a, but I have just upgraded to Matlab 2014b to take advantage of something else that has improved, and now my country border is all jagged. The border only looks jagged on the saved versions of the file. If I zoom in on the figure window, the outline isn't like that.
Here are the snippets of code that are important. It is a custom shapefile, so I don't know how to put it on here so people can replicate it.
This bit reads in the shapefile and plots it. The display type is 'polygon' if that is relevent, hence getting rid of the 'FaceColor' so I can see what I am plotting underneath (the green bits in the background of the images, plotted using pcolor).
thaiborder=shaperead('Thailandborder');
mapshow(thaiborder,'FaceColor','none');
This bit is how I am exporting the figure.
export_fig test.eps -r600 -painters
export_fig test.pdf -r600 -painters
This is the version with a smooth border from Matlab 2014a:
This is roughly the same area of the image, with the jagged border from Matlab 2014b:
Does anyone know why these differences are occurring? I want the border to be like it is in the first image, but I need the "improved" functionality of Matlab 2014b for another thing in the same image. What do I need to change?
Edit to add: I have been in contact with the creator of export_fig and he thinks it is caused by Matlab now using mitred joins rather than round ones. Apparently I have to write to MathWorks to complain. I didn't put this as an answer because someone else may be able to provide a solution for me.
Matlab acknowledged that this is known bug. For me the first fix worked.
The issue of jagged lines on the figures while exporting in the vector format is a known bug in MATLAB R2014b. It is associated with the combination of linejoins and meterlimits used in vector format.
To work around this issue, use the attached function fixeps to post process the EPS file.
You can use one of the following ways to call this fixeps function.
fixeps('input.eps','output.eps','LJ') % Will change the linejoins to round
fixeps('input.eps','output.eps','ML') % Will correct the miterlimit
function fixeps(inname,outname,fixmode)
if nargin==2
fixmode = 'LJ';
end
fi = fopen(inname,'r');
fo = fopen(outname,'w');
tline = fgets(fi);
while ischar(tline)
if (strcmp(tline,['10.0 ML' 10])) % Replace 10.0 miterlimit
switch (fixmode)
case 'LJ'
fwrite(fo,['1 LJ' 10]); % With round linejoin
case 'ML'
fwrite(fo,['2.5 ML' 10]); % With smaller miterlimit
end
else
fwrite(fo,tline);
end
tline = fgets(fi);
end
fclose(fo);
fclose(fi);
I had a similar problem that I found to be caused by the 'MarkerSize' option. It seems that in version 2014b it inherits the units of the figure. For example, if I have a figure in centimeters and I ask for ('MarkerSize', 10), the 10 will not be interpreted as points (as in 2014a) but as cm. I fixed this by changing the figure units to pt.