set(gcf,'PaperPositionMode','auto');
This makes an export, e.g. to EPS or PNG, of the current figure (gcf) have a bit more change of looking like the figure on the screen. This is important if one has changed a figure's size or moved parts about in it: they get hopelessly messed up with the default options.
Better, get the user-contributed add-on export_fig
, from
the matlab
website.
Aim: get a file's modification time (date/time of last change of its contents) in seconds, in a format that easily can be used for calculations such as `how long ago was this modified' and that doesn't rely on platform-specific things like
[status,age_str] = unix('echo $(( $(date +%s) - $(stat -c %Y filename.m)))')or on silly Java-based things. Matlab's
dir
command is the key here. The following does the
same as the above, using only core matlab functions, and returning the result
of the age of the file as a number rather than a string all in one line.
age = etime( clock, datevec( getfield( dir('filename.m'), 'date') ) )Note that this relies on
datevec
being able to parse
automatically the string format returned by dir
, which on
my system is in the format referred to as '0' in the documentation
for datestr
, e.g. "24-May-2010 11:15:50". Other platforms,
ages and locales may give something else. The datevec
function can instead be given a second argument to specify the format
precisely, using the 'HH:MM:SS' etc. method also described in
help datestr
.
The aim: whether the figure be large or small, have fonts on all the labels and ticks being the same actual size on the page, when included in a Latex document. There appear to be options about the specified rather than scaled size of font if using the `print preview' option. Seeking something command-based, I've gone on separately.
One way: set a font-size in all the text of the figure (by the defaults for new objects, or by going through all the existing objects -- see methods below); set the figure's 'Units' to whatever you want to use (e.g. centimeter [sorry about the spelling -- matlab insists), then the 'Position' property to make the figure width be however many such units you actually want in the document. Then export, and don't using scaling in the document.
The trouble with this is that for e.g. a sensible 12cm width, the font size (on my system, anyway) has to be about 5pt to come out sensibly, but things like a legend take lots of space; one could say the `natural-size' figure just looks too chunky. So the same basic principle has been followed, of not varying the scaling, but a uniform 50% down-scaling has been used within the document, starting the figure windows at ~24cm width. To make a smaller figure, just resize the window around the axes.
set( legend(filelist), 'Interpreter', 'none');
This allows a legend to be specified as well as setting the interpreter for the legend text: using 'none' prevents for example underscores and carets being interpreted as the (default) TeX subscripts and superscripts.
get(gca)
or similar commands to guess others, or
search the web.
set(0, 'DefaultAxesFontSize', 14) set(0, 'DefaultAxesLineStyleOrder', {'-','--',':'}) set(0, 'DefaultAxesColorOrder', [0 0 1; 1 0 0; 0 0.5 0])
set(gcf, 'DefaultAxesFontSize', 10)
set(0, ... 'DefaultFigureUnits', 'centimeters', ... 'DefaultFigurePosition', [0.5,2.0,12,12], ... 'DefaultFigureColor', 'white', ... 'DefaultFigurePaperType', 'a4', ... 'DefaultFigurePaperUnits', 'centimeters', ... 'DefaultFigurePaperPositionMode','auto', ... 'DefaultAxesColor', 'white', ... 'DefaultAxesDrawmode', 'fast', ... 'DefaultAxesFontUnits', 'points', ... 'DefaultAxesFontSize', 8, ... 'DefaultAxesFontAngle', 'normal', ... 'DefaultAxesFontName', 'Helvetica', ... 'DefaultAxesGridLineStyle', ':', ... 'DefaultAxesInterruptible', 'on', ... 'DefaultAxesLayer', 'bottom', ... 'DefaultAxesNextPlot', 'replace', ... 'DefaultAxesUnits', 'centimeters', ... % or 'normalized' 'DefaultAxesXcolor', [0, 0, 0], ... 'DefaultAxesYcolor', [0, 0, 0], ... 'DefaultAxesZcolor', [0, 0, 0], ... 'DefaultAxesVisible', 'on', ... 'DefaultLineColor', 'blue', ... 'DefaultLineLineStyle', '-', ... 'DefaultLineLineWidth', 1, ... 'DefaultLineMarker', 'none', ... 'DefaultLineMarkerSize', 6, ... 'DefaultTextColor', [0, 0, 0], ... 'DefaultTextFontUnits', 'Points', ... 'DefaultTextFontSize', 8, ... 'DefaultTextFontName', 'Helvetica', ... 'DefaultTextVerticalAlignment', 'middle', ... 'DefaultTextHorizontalAlignment', 'left' );
One way to see the possible values is to open the GUI-based figure editor and choose to set further properties, then look at all the permitted options in the drop-down lists.
When plotting multiple lines of data (a matrix rather than a vector as input) Matlab automatically colours them by cycling through a list. This isn't much help if one would like markers, for example for greyscale printing or for more clarity. The following code finds each axis in the current figure, then finds each line in that axis, and applies markers and colours from lists, besides other features such as the thickness and size. The whole thing can be had as a script to run on each figure after making it: set_linestyles.m.
% lists of colours and markers to cycle through C = [ ... % R G B 0.00 0.00 1.00 0.00 0.50 0.00 1.00 0.00 0.00 ]; M = 's+dph'; % get properties of current figure: work on each 'child' f = get(gcf()); for na = 1:numel(f.Children), % get details of this child-object: skip if not 'axes' object a = get(f.Children(na)); if ~strcmpi(a.Type,'axes'), continue; end % for each child of the axes, n = 0; L = sort(a.Children); for nl = 1:numel(L), % get details of this child: skip if not 'line' object l = L(nl); if ~strcmp(get(l,'Type'),'line'), continue; end n = n + 1; set(l, 'Color', C(mod(n-1,size(C,1))+1,:)); set(l, 'LineStyle', '-'); set(l, 'LineWidth', 0.5); set(l, 'Marker', M(mod(n-1,length(M))+1)); set(l, 'MarkerSize', 7); set(l, 'MarkerEdgeColor', 'auto'); set(l, 'MarkerFaceColor', 'none'); end end
(Alternative: use property explorers, etc., in the GUI. I prefer to avoid this, as working by scripts makes things quicker and more reliably repeatable when one will do them lots of times.)
The get()
and set()
commands are
very handy here. Having got the list of properties of the
current figure or axes, one can change particular ones
according to (generally easily guessable) rules.
% get properties of the current figure (click figure to make 'current') get(gcf) % or get for current axes (click particular plot to make it % current, or select one of the 'Children' of the result of % get(gcf), or else the last-created axes will be current get(gca) % set something: e.g. limits of an axis, and ticks set(gca, 'xlim',[0,50], 'xgrid','on', 'xminorgrid','on'); % likewise for grand-children etc (lines) and for the very % many other properties
When trying to make functions be robust and have helpful
error-messages, conditionals grow to such ones as:
if ~isempty(a) && isnumeric(a)
&& isscalar(a) && ....
It turns out that since version 2007b there have been some useful functions that can do a lot of this at once. This is particularly desirable if the variable to be checked has a long name/indexing so that repetition is undesirable:
validateattributes() validatestring()
The following code lets a rectangular array of PNG images, with names consisting of numbers starting at 'oname', be joined into a single image. See `by inspection' the needed variations for using other image formats, other numbers of images, etc. Really, the only trouble was the matter of colour indexing.
ncols = 49; % number of columns (number /in/ a row) nrows = 52; % " " rows (" column) first = 1; % number of the first file (top left) oname = 'L'; ofmt = 'png'; ncol = 64; % number of colours in indexed image (0 means not indexed) a=[]; for i=0:(nrows-1), arow=[]; for j=0:(ncols-1), imname = sprintf('%04d.gif', first+ncols*i+j); [tmp.ind,tmp.map] = imread(imname); % convert list of pixels and colour-map to standard RGB atmp = ind2rgb(tmp.ind,tmp.map); arow = [arow,atmp]; end; a = [a; arow]; end if ncol, % convert RGB back to indexed (map) for better % efficiency for diagram or cartoon type images [aind,map] = rgb2ind(a,ncol); imwrite(aind, map, [oname,'.',ofmt], ofmt); else % write image directly imwrite(a, [oname,'.',ofmt], ofmt); end
A lot of things can be done with a high-level numerically-based language without caring about anything being other than a double-precision floating point number. One might start to care when dealing with arkwardly large amounts of data of range so limited that an 8-byte representation is significantly wasteful, or when dealing with network communication, instrument control, or file input and output involving interaction with other programs. One might then start going mad realising that the scope for manipulation of bytes is highly confusing for someone versed in C (and hardly surprisingly, in some ways, since much of the point of numerical environments is to let lots of users use computers for calculations without caring about representation of numbers or management of memory).
Matlab does have functions to convert a value (scalar, vector, matrix, ...)
to other types. For example, double('help')
converts
the string (character array) help
, of length 4, to
a numeric array of double-precision numbers having the values
that the bytes representing these four characters in ASCII
would have when interpreted as integers: [ 104 101 108 112 ]
.
The function char
converts numbers to the characters
that they represent; other functions such as int8, uint8,
int16, ...
etc. convert to other data-types with
possible economies of memory, but more limited range.
See help datatypes
for more on this.
What probably shocks a C-user most is that operations on mixed datatypes give results limited to the smaller range, even when the output is not being forced into a variable of limited type. In C, arithmetic would typically be done in the range of the highest rather than the lowest-range input.
Thus, in matlab,
>> a = uint8(128) >> f = 250; >> whos Name Size Bytes Class Attributes a 1x1 1 uint8 f 1x1 8 double >> a*f ans = 255while in C,
#include <stdlib.h> #include <stdio.h> #include <stdint.h> main() { uint8_t a = 128; double f = 250.0; printf("%d * %f = %f\n", a, f, a*f); } [compile and run]: 128 * 250.000000 = 32000.000000It's certainly something to look out for when everything seems bizarre. I've opted long ago to force everything to double in matlab or octave, until I'm forced to try to save space. It keeps things simpler.
Still, for some things such as writing a mixed burst of data types as a single stream of bytes to an instrument, I've ended up doing messy things like
for ni=1:length(in), si = in(ni); if si<0, % negative values: si = double( uint16(1) + bitxor(uint16(abs(si)),uint16(2^16)) ); end bindata(2*ni-1) = (si - mod(si,256))/256; bindata(2*ni) = mod(si,256); endjust to convert some input integers (within a 16bit signed-integer range) to an array giving the uint8-values of the byte-stream that would represent these int16 numbers (in big-endian format), in order to send this and a text header all in one command. ``There must be a better way, even in [numerical-oriented] Matlab'', I'd say to myself.
There is (to some extent): typecast
allows the
underlying data (bytes) to be maintained while accessing them
as a different type --- just what we often want to do to convert
for example int16 to uint8 (above); there is also
cast
to change the type by converting the data,
which is like using one of the specific functions such as
double
.
Very handy. At last, easy type-manipulation.
For example,
d = int16([0, -2500, -1, 1, 2700]); o = typecast(d, 'uint8') o = 0 0 60 246 255 255 1 0 140 10 % check the second one (amd64 is little-endian): (256*246+60) - 2^16 ans = -2500
This allows the window containing a figure to display something other than just `Figure 1', `Figure 2' etc.
set(gcf, 'Name', '|s(t)| - s_0', 'NumberTitle', 'off')This could be handy just for selecting the right figure from a window-manager toolbar, when one is regularly plotting many attributes of data at once. Sophisticated window-managers, such as that within the KDE desktop, can also be instructed to set a window's position, focus and more, based on its name.
The matlab function urlread()
allows a http or https
URL to be read into the output character array. This is a trouble
for anything that isn't text, as the output gets converted from bytes
into unicode characters.
There are so many reasons why one might want to get a non-text url that it's surprising they should make it so hard. Some instruments can provide their data in binary format; one might want quickly to get an image for processing, or a zip-file, etc.
This function: urlget.m gets a URL as a numeric array in which each element is the numeric unsigned (0:255) value of a byte from the URL. It is limited to http, GET, and no proxy.
To make your own function with less limitation, try removing the
native2unicode(...)
function from a line near the
end of matlab's urlread()
. A little trickery will
be needed beyond just copying and modifying this function, as
its residency in $MATLAB/iofun/
gives it access to
$MATLAB/iofun/private/urlreadwrite.m
which it
requires too. And you probably don't want to change the original,
since its character-based output may be relied on by other things.
Page started: 2008-12-08
Last change: 2014-09-05