How to load in variable if it is present in a matfile?

I am having trouble with "conditional" loading of a variable from a matfile, depending on whether the matfile contains the variable. Here is what I am trying to do:
  1. Go through many different (large) matfiles, some of which contain mountain height in a variable called topo, and some of which contain mountain height in variable called elevation.
  2. If the matfile contains the variable topo, load that into a workspace variable called mountainHeight. If the matfile contains the variable elevation, load that into a workspace variable called mountainHeight. If neither variable is contained in matfile, do nothing.
  3. Avoid crashing the load command by trying to load variables which are not in the matfile.
Here is what I have tried (R2015a), but I'd bet there is a better/shorter way.
filename = 'topography.mat'; % A matfile that comes with matlab
m = matfile(filename); % Make a matfile object
FileInfo = whos(m); % Structure containing information about matfile including variables it contains
for iVar = 1:length(FileInfo)
if strcmp(FileInfo(iVar).name, 'topo') % Check if topo is a variable in topography.mat
mountainHeight = m.topo; % Load topo
elseif strcmp(FileInfo(iVar).name, 'elevation') % Check if elevation is a variable in topography.mat
mountainHeight = m.elevation; % Load elevation
end
end

 Respuesta aceptada

D = load('mymatfile.mat');
if isfield(D, 'elevation')
elevation = D.elevation;
else
elevation = NaN;
end
Alternately, check if the field exists and if it doesn't, add it with some placeholder data.
D = load('mymatfile.mat');
if ~isfield(D, 'elevation')
D.elevation = NaN;
end
If you want to do this with multiple fields, use dynamic field names.
D = load('mymatfile.mat');
listOfFields = {'elevation', 'material', 'price'};
isPresent = isfield(D, listOfFields);
for fieldnum = 1:length(listOfFields)
if ~isPresent(fieldnum)
F = listOfFields{fieldnum};
D.(F) = NaN;
end
end

7 comentarios

I vote for this solution. Steven beat me to it. I do this kind of thing all the time because sometimes in later versions of software I add things to the mat file, but I need it not to crash if my users use my new software for the first time and read an old version of the mat file that did not have that variable in it. If the field is not in there then I detect that and assign a default.
K E
K E el 22 de Jul. de 2015
Same thing for me: we share matfiles in my group but people are not consistent on how they name the variables the matfiles contain. I wish there was more capability for checking matfile contents and returning empty values when seeking to load a missing variable.
So K E, you want this command (if y is not present in thematfile.mat) to create a field y in the data struct array and fill it with empty data?
data = load('thematfile.mat', 'y')
I would be wary of making this the default behavior, as it means that making a typo in the name of the variable to be loaded would now just work (but not do what you want) instead of issuing a warning. But having an option for LOAD to do what you described (if you opt-in) might be useful. I recommend you send your use case and a request for such an option to Technical Support so it can be captured in the enhancement database.
Cedric
Cedric el 22 de Jul. de 2015
Editada: Cedric el 22 de Jul. de 2015
I thought that you wanted to avoid loading the full MAT-File actually. If it's a question of inconsistent naming, I would build a function that maps names, processes all MAT-Files, and exports new ones with normalized names. And this function would flag/isolate/rename MAT-Files when the mapping fails, so I can process them later by hand and there is no remaining crap that propagates then in my work.
K E
K E el 23 de Jul. de 2015
Editada: K E el 23 de Jul. de 2015
Steven - Edited post to make it clearer what I am trying to do. Sorry!
K E
K E el 23 de Jul. de 2015
Cedric - These matfiles are generated by many different authors and I want to keep track of the originals so I am stuck making my code accommodate the inconsistent names.
Cedric
Cedric el 23 de Jul. de 2015
Editada: Cedric el 23 de Jul. de 2015
Then just build a small function that does what Steven proposes, and outputs mountainHeight:
function mountainHeight = loadMountainHeight( locator )
data = load( locator ) ;
if isfield( data, 'topo' )
mountainHeight = data.topo ;
elseif isfield( data, 'elevation' )
mountainHeight = data.elevation ;
else
mountainHeight = [] ; % Or NaN or whatever you want, to tell
% the caller "field not found".
end
end
Then in your main script, you do something like the following:
dir_mat = dir( '*.mat' ) ;
for fId = 1 : numel( dir_mat )
mountainHeight = loadMountainHeight( dir_mat(fId).name ) ;
if isempty( mountainHeight )
% Throw warning, or print message, or just skip.
warning( 'File "%s" : no valid field found!', dir_mat(fId).name ) ;
continue ;
end
fprintf( 'File "%s" : processing height..\n', dir_mat(fId).name ) ;
% .. code for further processing mountainHeight ..
end

Iniciar sesión para comentar.

Más respuestas (2)

Sean de Wolski
Sean de Wolski el 21 de Jul. de 2015
Editada: Sean de Wolski el 23 de Jul. de 2015
Use this to determine what's in the MAT file, then use the MAT File class to load that variable in.

1 comentario

K E
K E el 24 de Jul. de 2015
Useful to avoid loading whole matfile (they are large).

Iniciar sesión para comentar.

Cedric
Cedric el 21 de Jul. de 2015
Editada: Cedric el 21 de Jul. de 2015
An alternate solution is to catch the warning (LOAD doesn't throw an error).
Or you can turn off this warning and just test if the output struct is empty (at least on 2015b-pre, I can't test on earlier versions now).

Categorías

Etiquetas

Preguntada:

K E
el 21 de Jul. de 2015

Comentada:

K E
el 24 de Jul. de 2015

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by