How to automatically save files in Matlab? - matlab

I have a neural network and am generating figures and I wish to save those figures automatically with the filename as the training function and the hidden layer size, as well as the percentage correct
I have the following
... trainFcn=trainscg
This changes between a couple of options: scg, rp, lm, etc
I also have the
hiddenLayerSize=[10 10 10]
These values also change often.
I run my neural network and output a confusion matrix:
figure, plotconfusion(nnOutput, target)
I then do
saveas(gcf, trainFcn+hiddenLayerSize)
This does not work when I add the variables like that and also fails when I put a comma instead of a plus. How can I make this saveas work and make the filename my variables? I don't need to have the accuracy in the filename but if I can then it'd be great.

Your method does not work because the function expects a string as a filename but trainFcn+hiddenLayerSize is not one. Try the following:
% convert size vector to a string
sizeString = sprintf('%dx', hiddenLayerSize);
sizeString = sizeString(1:end-1); % removes the trailing x
% auto-generate your filename
filename = sprintf('%s_%s', func2str(trainFcn), sizeString);
saveas(gcf, filename);
This assumes that you have defined trainFcn like trainFcn = #trainscg; or something similar.

Related

How to define multiple objects under a class in a for loop in matlab? [duplicate]

I have 200 time points. For each time point, there is an image, the size of which is 40*40 double, corresponds to this time point. For example, image 1 corresponds to time point 1; image k corresponds to time point k (k = 1,2,...,200).
The time points are T = 1:200, with the images named as Image_T, thus Image_1, Image_2 etc.
I want to put all these 200 images together. The final size is 40*40*200 double. The final image looks like fMRI image (fmri_szX = 40, fmri_szY = 40 and fmri_szT = 200). How to achieve that?
Thanks!
Dynamic variables
Note that whilst this is possible, it's considered to be bad programming (see for instance here, or this blog by Loren and even the Mathworks in their documentation tell you not to do this). It would be much better to load your images directly into either a 3D array or a cell structure, avoiding dynamic variable names. I just posted this for completeness; if you ever happen to have to use this solution, you should change to a (cell-) array immediately.
The gist of the linked articles as to why eval is such a bad idea, is that MATLAB can no longer predict what the outcome of the operation will be. For instance A=3*(2:4) is recognised by MATLAB to output a double-array. If you eval stuff, MATLAB can no longer do this. MATLAB is an interpreted language, i.e. each line of code is read then ran, without compiling the entire code beforehand. This means that each time MATLAB encounters eval, it has to stop, evaluate the expression, then check the output, store that, and continue. Most of the speed-engines employed by MATLAB (JIT/MAGMA etc) can't work without predicting the outcome of statements, and will therefore shut down during the eval evaluation, rendering your code very slow.
Also there's a security aspect to the usage of eval. Consider the following:
var1 = 1;
var2 = 2;
var3 = 3;
varnames = {'var1', 'var2; disp(''GOTCHA''); %', 'var3'};
accumvar = [];
for k = 1:numel(varnames)
vname = varnames{k};
disp(['Reading from variable named ' vname]); eval(['accumvar(end+1) = ' vname ';']);
end
Now accumvar will contain the desired variable names. But if you don't set accumvar as output, you might as well not use a disp, but e.g. eval('rm -rf ~/*') which would format your entire disk without even telling you it's doing so.
Loop approach
for ii = 200:-1:1
str = sprintf('Image_%d',ii);
A(:, :, :, ii) = eval(str);
end
This creates your matrix. Note that I let the for loop run backwards, so as to initialise A in its largest size.
Semi-vectorised approach
str = strsplit(sprintf('image_%d ',1:200),' '); % Create all your names
str(end) = []; % Delete the last entry (empty)
%Problem: eval cannot handle cells, loop anyway:
for ii = 200:-1:1
A(:, :, :, ii) = eval(str{ii});
end
eval does not support arrays, so you cannot directly plug the cellarray strin.
Dynamic file names
Despite having a similar title as above, this implies having your file names structured, so in the file browser, and not MATLAB. I'm assuming .jpg files here, but you can add every supported image extension. Also, be sure to have all images in a single folder and no additional images with that extension, or you have to modify the dir() call to include only the desired images.
filenames = dir('*.jpg');
for ii = length(filenames):-1:1
A(:,:,:,ii) = imread(filenames{ii});
end
Images are usually read as m*n*3 files, where m*n is your image size in pixels and the 3 stems from the fact that they're read as RGB by imread. Therefore A is now a 4D matrix, structured as m*n*3*T, where the last index corresponds to the time of the image, and the first three are your image in RGB format.
Since you do not specify how you obtain your 40*40 double, I have left the 4D matrix. Could be you read them and then switch to using a uint16 interpretation of RGB, which is a single number, which would result in a m*n*1*T variable, which you can reduce to a 3D variable by calling A = squeeze(A(:,:,1,:));

pixelLabelDatastore from loaded image in workspace

I have multiple small *.mat files, each containing 4 input images (template{1:4} and a second channel template2{1:4}) and 4 output images (region_of_interests{1:4}), a binarized ('mask') image to train a deep neural network.
I basically followed an example on Mathworks and it suggests to use a function (in this example #matreader) to read in custom file formats.
However ...
It seems impossible to load multiple images from one *.mat file using any load function as it only allows one output, and imageDatastore doen't seem to allow loading data from workspace. How could this be achieved?
Similarly, it seems impossible to load a pixelLabelDatastore from a workspace variable. As a workaround I ended up saving the contents of my *.mat file to an image (using imwrite, saving to save_dir), and re-loading it from there (in this case, the function doesn't even allow to load *.mat files.). (How) can this be achieved without re-saving the file as image?
Here my failed attempt to do so:
%main script
image_dir = pwd; %location of *.mat files
save_dir = [pwd '/a/']; %location of saved output masks
imds = imageDatastore(image_dir,'FileExtensions','.mat','ReadFcn',#matreader); %load template (input) images
pxds = pixelLabelDatastore(save_dir,{'nothing','something'},[0 255]);%load region_of_interests (output) image
%etc, etc, go on to train network
%matreader function, save as separate file
function data=matreader(filename)
in=1; %give up the 3 other images stored in template{1:4}
load(filename); %loads template and template2, containing 4x input images each
data=cat(3,template{in},template2{in}); %concatinate 2 template input images in 3rd dimension
end
%generate example data for this question, will save into a file 'example.mat' in workspace
for ind=1:4
template{ind}=rand([200,400]);
template2{ind}=rand([200,400]);
region_of_interests{ind}=rand([200,400])>.5;
end
save('example','template','template2','output')
You should be able to achieve this using the standard load and save function. Have a look at this code:
image_dir = pwd;
save_dir = pwd;
imds = imageDatastore(image_dir,'FileExtensions',{'.jpg','.tif'});
pxds = pixelLabelDatastore(save_dir,{'nothing','something'},[0 255]);
save('images.mat','imds', 'pxds')
clear
load('images.mat') % gives you the variable "imds" and "pxds" directly -> might override previous variables
tmp = load('images.mat'); % saves all variables in a struct, access it via tmp.imds and tmp.pxds
If you only want to select the variables you want to load use:
load('images.mat','imds') % loads "imds" variable
load('images.mat','pxds') % loads "pxds" variable
load('images.mat','imds','pxds') % loads both variables
EDIT
Now I get the problem, but I fear this is not how it is going to work. The Idea behind the Datastore objects is, that it is used if the data is too big to fit in memory as a whole, but every little piece is small enough to fit in memory. You can use the Datastore object than to easily process and read multiple files on a disk.
This means for you: Simply save your images not as one big *mat file but as multiple small *.mat files that only contain one image.
EDIT 2
Is it strictly necessary to use an imageDatastore for this task? If not you can use something like the following:
image_dir = pwd;
matFiles = dir([image_dir '*.mat']);
for i=1:length(matFiles)
data = load(matFiles(i).name);
img = convertMatToImage(data); % write custom function which converts the mat input to your image
% or something like this:
% for j=1:4
% img(:,:,j) = cat(3,template{j},template2{j});
% end
% process image
end
another alternative would be to create a "image" in your 'matreader' which does not only have 2 bands but to simply put all bands (all templates) on top of each other providing a "datacube" and then in an second step after iterating over all small mat files and reading them splitting the single images out of the one bigger datacube.
would look something like this:
function data=matreader(filename)
load(filename);
for in=1:4
data=cat(3,template{in},template2{in});
end
end
and in your main file, you have to simply split the data into 4 pieces.
I have never tested it but maybe it is possible to return a cell instead of a matrix?
function data=matreader(filename)
load(filename);
data = cell(1,4)
for in=1:4
data{in}=cat(3,template{in},template2{in});
end
end
Not sure if this would work.
However, the right way to go forward from here really depends on how you plan to use the images from imds and if it is really necessary to use a imageDatastore.

Looping through a list of elements from the workspace in Matlab [duplicate]

I have 200 time points. For each time point, there is an image, the size of which is 40*40 double, corresponds to this time point. For example, image 1 corresponds to time point 1; image k corresponds to time point k (k = 1,2,...,200).
The time points are T = 1:200, with the images named as Image_T, thus Image_1, Image_2 etc.
I want to put all these 200 images together. The final size is 40*40*200 double. The final image looks like fMRI image (fmri_szX = 40, fmri_szY = 40 and fmri_szT = 200). How to achieve that?
Thanks!
Dynamic variables
Note that whilst this is possible, it's considered to be bad programming (see for instance here, or this blog by Loren and even the Mathworks in their documentation tell you not to do this). It would be much better to load your images directly into either a 3D array or a cell structure, avoiding dynamic variable names. I just posted this for completeness; if you ever happen to have to use this solution, you should change to a (cell-) array immediately.
The gist of the linked articles as to why eval is such a bad idea, is that MATLAB can no longer predict what the outcome of the operation will be. For instance A=3*(2:4) is recognised by MATLAB to output a double-array. If you eval stuff, MATLAB can no longer do this. MATLAB is an interpreted language, i.e. each line of code is read then ran, without compiling the entire code beforehand. This means that each time MATLAB encounters eval, it has to stop, evaluate the expression, then check the output, store that, and continue. Most of the speed-engines employed by MATLAB (JIT/MAGMA etc) can't work without predicting the outcome of statements, and will therefore shut down during the eval evaluation, rendering your code very slow.
Also there's a security aspect to the usage of eval. Consider the following:
var1 = 1;
var2 = 2;
var3 = 3;
varnames = {'var1', 'var2; disp(''GOTCHA''); %', 'var3'};
accumvar = [];
for k = 1:numel(varnames)
vname = varnames{k};
disp(['Reading from variable named ' vname]); eval(['accumvar(end+1) = ' vname ';']);
end
Now accumvar will contain the desired variable names. But if you don't set accumvar as output, you might as well not use a disp, but e.g. eval('rm -rf ~/*') which would format your entire disk without even telling you it's doing so.
Loop approach
for ii = 200:-1:1
str = sprintf('Image_%d',ii);
A(:, :, :, ii) = eval(str);
end
This creates your matrix. Note that I let the for loop run backwards, so as to initialise A in its largest size.
Semi-vectorised approach
str = strsplit(sprintf('image_%d ',1:200),' '); % Create all your names
str(end) = []; % Delete the last entry (empty)
%Problem: eval cannot handle cells, loop anyway:
for ii = 200:-1:1
A(:, :, :, ii) = eval(str{ii});
end
eval does not support arrays, so you cannot directly plug the cellarray strin.
Dynamic file names
Despite having a similar title as above, this implies having your file names structured, so in the file browser, and not MATLAB. I'm assuming .jpg files here, but you can add every supported image extension. Also, be sure to have all images in a single folder and no additional images with that extension, or you have to modify the dir() call to include only the desired images.
filenames = dir('*.jpg');
for ii = length(filenames):-1:1
A(:,:,:,ii) = imread(filenames{ii});
end
Images are usually read as m*n*3 files, where m*n is your image size in pixels and the 3 stems from the fact that they're read as RGB by imread. Therefore A is now a 4D matrix, structured as m*n*3*T, where the last index corresponds to the time of the image, and the first three are your image in RGB format.
Since you do not specify how you obtain your 40*40 double, I have left the 4D matrix. Could be you read them and then switch to using a uint16 interpretation of RGB, which is a single number, which would result in a m*n*1*T variable, which you can reduce to a 3D variable by calling A = squeeze(A(:,:,1,:));

MATLAB Get a list of color map names

I am writing a GUI that would benefit from a user-selection of colormaps by name. However, I am at a bit of a quandary in that I can't seem to programmatically get a list of supported colormap names!
While I could hardcode the names; my code may be run on older versions of matlab which may have different colormaps. My primary concern is with the parula colormap which, if I recall correctly, was not present in MATLAB 2014.
Any thoughts?
Alternatively, you can hardcode them and have an if statement with graphicsversion(fhandle) on it.
It returns returns true if the default graphics system is the old
handle graphics one.
You could also try to get an extensive list, and then check if colormapname.m is a file in matlabroot\toolbox\matlab\graph3d. If the function is there, the colormap comes in that version. You'd still need to hardcode an extensive list though.
EDIT: as #thewaywewalk suggests, you could open Contents.min matlabroot\toolbox\matlab\graph3d and esarch for % Color maps. It has a list of the colormaps included in the version. In 2014b its on lines 29-48
I'm not 100% sure it works in MATLAB As #BillBokeey points out in the comments this does not work in MATLAB, but in Octave you can use:
CM = colormap('list');
It will return a cell array of strings containing all of the valid colormaps.
CM =
{
[1,1] = autumn
[1,2] = bone
[1,3] = cool
[1,4] = copper
[1,5] = flag
[1,6] = gmap40
[1,7] = gray
[1,8] = hot
[1,9] = hsv
[1,10] = jet
[1,11] = lines
[1,12] = ocean
[1,13] = pink
[1,14] = prism
[1,15] = rainbow
[1,16] = spring
[1,17] = summer
[1,18] = white
[1,19] = winter
}
A possibility to get an extensive list of available colormaps :
In matlabroot\help\matlab\ref, you can find previews of all available colormaps whose filenames are of the form colormap_colormapname.png
In order to get your list, you can use :
CurrFolder=pwd;
cd(strcat(matlabroot,'\help\matlab\ref'))
Colormaps=dir('*colormap_*.png');
TmpColormapsList={Colormaps.name};
TmpColormapsList=cellfun(#(S)strrep(S,'colormap_',''),TmpColormapsList,'UniformOutput',false);
ColormapsList=cellfun(#(S)strrep(S,'.png',''),TmpColormapsList,'UniformOutput',false);
cd(CurrFolder);
This will output a cell array of string containing the names of the available colormaps.
Pretty ugly hack, but at least it works on 2014b (Please check it for your version if you have another one)
Another way (hack) might be to extract the string out the the colormapeditor function:
colormapeditorString = fileread(strcat(matlabroot,'\toolbox\matlab\graph3d\colormapeditor.m'));
posStart = strfind(colormapeditorString,'stdcmap(maptype');
posEnd = strfind(colormapeditorString(posStart:end),'end') + posStart;
stdcmapString = colormapeditorString(posStart:posEnd);
split = strsplit(stdcmapString, '(mapsize)');
list = cellfun(#(x)x(find(x==' ', 1,'last'):end), split,'uni',0);
list(end) = [];
If everything fails you can try the callback routine:
function=ChangeCMap()
CMList=get(CMapList,'string'); %% Read colormap names
CMVal =get(CMapList,'value'); %% Get the index of desired colormap
try
colormap(Ax,CMList{CMVal}); %% Try to set the colormap...
catch Msg %% ... if it fails, then:
if strcmp(Msg.stack.name,'colormap') %% Check if error was caused by colormap function
set(Ax,'colormap`,'jet'); %% set "default" colormap (optional)
indices=1:length(CMList);
set(CMapList,'string',CMList{indices~=CMVal}) %% remove the colormap name thet caused error
else
disp(Msg) %% Print the error message in matlab shell
end
end
end
In this example shared variables CMapList - handle to the popup menu - and Ax - handle of the axes - are expected.
When the function is called it tries to set the colormap. If it fails it set the default colormap and remove the problematic name from the menu.
Be sure that first and last colormaps won't cause error, otherwise the CMapList update will have to handle those options.
You can also benefit from the fact, that each colormap has its own .m file so you don't need to wait until error occurs.
CMap='bone'; %% example
if exist(CMap,'file')
colormap(Ax,CMap) %% bone.m exist somewhere in the matlab paths
else
colormap(Ax,'jet') %% bone.m does not exist in the matlab paths
end
This raises one point - you can define your own colormaps and make the algorithm to generate missing .m files...
Given that any function that returns a 3-column matrix, or even a .MAT file containing a cmap variable with such a matrix, can be used by colormap, it doesn't make sense to ask for a list of “all” colormaps.
You might use exist (i.e., exist('parula', 'file')), or try clauses, to check for the existence of certain functions and offer them as colormaps in your GUI, though that might be problematic if the user has custom functions with the same name that don't yield colormaps.
I have users who love making totally custom colormaps, which they save in MAT files, so for them, I'd make the colormap a customizable textfield, and do some validation to ensure that it is indeed a valid colormap.
I've recently had the same issue building an app in app generator. After finding the above attempts overly cumbersome, I have decided to provide my approach.
Matlab stores it's colormaps as *.m files in a single directory, so select for the filenames in this directory.
coldir = dir([matlabroot '\toolbox\matlab\graphics\color']);
maps={};
for i=1:length(coldir)
if coldir(i).isdir, continue, end
maps{end+1}=replace(coldir(i).name,'.m','');
end

Saving a Matrix in MatLab

I have a MatLab program that generates a large 1000x1000 matrix. How can I save this matrix for use in future programs. Ideally, I want to save it as a particular variable. Here is the code that I am using.
function A = generateSPDmatrix(n)
A = rand(n,n); % generate a random n x n matrix
A = A+A';
A = A*A';
A = A + n*eye(n);
end
If you want to use it in future Matlab programs, you could do it like this:
save('A.mat', 'A');
To load, just do it like this:
load('A.mat');
% the file path is current path.
save('A.txt', 'A','-ascii');
% save to your file path
save('D:\test.txt','m','-ascii')
'D:\test.txt': file name and path
'm': your matrix
'-ascii': 8-digit ASCII format
See the matlab Help. Search the save(Save workspace variables to file) function
save(filename, variables, format) saves in the specified format: '-mat' or '-ascii'. You can specify the format option with additional inputs such as variables, '-struct' , '-append', or version.