Matfile isn't loading the structure's field names - matlab

Background
I encountered some strange behaviour with the function "matfile" in Matlab 2016b - not sure what's going on, and I can't replicate it or create a test case.
I have a structure, which I saved to a server, like so:
PathToFile='ServerPath\My Documents\MyProj\testMatF.mat';
save(PathToFile,'-struct','myStruct'); %I tried the -v7.3 flag
Problem
Then I read it in with:
m1=matfile(PathToFile);
On other, very similar structs, I can do:
myFields=fieldnames(m1);
But for this one file I can't, all I get is the auto "Properties" field.
What I've tried
myFields=who(m1) - gives me list of fieldnames... sometimes. I don't know the who function well, but it seems, if I intersperse who m1 then myFields=who(m1) it works.
Explicitly typing m1.TheFieldName, works.
Moving the file to a location on the comp, like C:\Data\. Then using fieldnames works.
Using load, works.
Does it have to do with the server access, corrupted file, matfile properties? One other weird thing is some of my .m files in this particular folder, when I try to open them results in: Does not exist, when clearly it does, since I click on it and can use the run function with it... Additional: Windows 7. Recently updated license.
Please let me know what info you can use to help out. Either to create a new file that will work, or fix the problem with the current file. Thanks.
EDIT
Example output in my command window - seemingly incomprehensible...
m1=matfile(fullfile(projPath,'NexusMarkersProcessed.mat'),'Writable',false)
m1 =
matlab.io.MatFile
Properties:
Properties.Source: '\bontempi.medicine.utorad.utoronto.ca\home\PT\zabjeklab3\My
Documents\Data\Active Projects\JC_Hip\FL1502\FL1502\Patient
Classification 2\NexusMarkersProcessed.mat'
Properties.Writable: false
Methods
K>> m1.Properties.Source
ans =
\bontempi.medicine.utorad.utoronto.ca\home\PT\zabjeklab3\My
Documents\Data\Active Projects\JC_Hip\FL1502\FL1502\Patient
Classification 2\NexusMarkersProcessed.mat
K>> java.io.File(m1.Properties.Source).exists()
ans =
logical
0
Pause to paste in this window... go back:
java.io.File(m1.Properties.Source).exists()
ans =
logical
1
K>> who(m1)
Your variables are:
Patient10 Patient5 Patient9 Patient11 Patient6 Patient3
Patient7
K>> who(m1) K>> who(m1) K>>
java.io.File(m1.Properties.Source).exists()
ans =
logical
0
K>>
So it sometimes finds the file, and can read it in. Othertimes it cannot - is this to do with the fact that it's on a network drive?
Any help is appreciated.

This issue is caused by accessing a file on a network drive. One workaround is to copy the file to a local drive (C: is used), and then use matfile, use the result as needed, then replace the network drive file, and delete the local file, to return things to their original state. Some research made me realize things are slower than they need to be if any files, even the .m ones, are on the network. Here's a function that worked:
function [m,noData]=safeMatFile(FilePath,safeFilePath)
%FilePath: absolute path to where the file is on the network
%safeFilePath: absolute path to where the file will be temporarily copied locally, C://
%safeDir='C:\Data';
%safeFold='tempFolder12345679';
%[~,tempDir,~]=mkdir(safeDir,safeFold);
%safeFilePath=fullfile(safeDir,safeFold,FileName);
noData=0;
dirFile=dir(FilePath);
if (length(dirFile) == 1) && ~(dirFile.isdir)%OR java below OR exist(forceFilePath,'file')==2
%if there is a file, make a temp folder on the C drive
if ~(java.io.File(safeFilePath).exists() && java.io.File(safeFilePath).isFile()) %ensure file doesn't exist, check dir too: || isempty(tempFolder)
copyfile(FilePath, safeFilePath);%moves existing file to backup folder
else
warning('SKIPPING (%s) - an old file of the same name was there, delete it!\n',safeFilePath);
return
end
%Load the temp local file into matlab
m=matfile(safeFilePath,'Writable',true);
else
m=[];
noData=1;
end
end
Then do stuff with m... and at the end:
function overwriteOldFiles()
if (java.io.File(safeFilePath).exists() && java.io.File(safeFilePath).isFile())
java.io.File(FilePath).delete();
java.io.File(safeFilePath).renameTo(java.io.File(FilePath));
end
end
and
function deleteTempFiles()
if (java.io.File(safeFilePath).exists() && java.io.File(safeFilePath).isFile())
java.io.File(safeFilePath).delete();
end
end
... Then rmdir if necessary.
Note, I tried different ways of checking if the file exists (I think the first is fastest and most reliable):
dirFile=dir(FilePath); if (length(dirFile) == 1) && ~(dirFile.isdir)
if (java.io.File(FilePath).exists() && java.io.File(FilePath).isFile())
if exist(FilePath,'file')==2

Related

Reading files frame by frame

I have a folder containing .ply files. I want to read them and plot them like an animation. Initially i am trying to read the files and plot individually using the following code:
testfiledir = 'Files\';
plyfiles = dir(fullfile(testfiledir, '*.ply'));
for k=1:length(plyfiles)
FileNames = plyfiles(k).name;
plys=pcread(FileNames);
pcshow(plys)
end
But while running the script i get the error:
Error using pcread (line 51)
File "val0.ply" does not exist.
Error in read_pcd (line 6)
plys=pcread(FileNames);
val0.ply is one my first frame which is read in the variable 'plyfiles'
Where am I making mistake?
Use a datastore it is much easier and will keep track of everything for you. E.g.
ds = fileDatastore("Files/","ReadFcn",#pcread,"FileExtensions",".ply");
then you can read the files from it using read or readall, e.g.
while hasdata(ds)
plys = read(ds);
pcshow(plys)
end
It is slightly slower than if you can make the optimal implementation, but I prefer it big-time for its ease.

Execute script but don't touch workspace in Matlab

Can I execute script, but make it doesn't touch any current workspace variables? I.e. turn script into function?
Also it would be good to have access this script's variables after run.
I tried
evalin('myworkspace', 'myscript')
but it failed.
I tried
evalin('caller', 'myscript')
but it changed variables.
Is it possible to accomplish?
The trivial way to accomplish this without changing the script itself would be to:
save
myscript
% ... examine variables
clear
load
save saves the current workspace to a MAT-file called "matlab.mat". You can give it a different name if you prefer. load loads it in again. If you specified a different name for save, give the same name to load.
If you have the parallel computing toolbox, you can do it by submitting the script to your local cluster. (Just to emphasise, your local cluster is your own pc.)
E.g. if you have a script SO.m with the line
a = randn;
then you can submit and wait using
job = batch('SO', 'Profile', 'local');
wait(job);
Once it have finished running, you can load the variables using
M = load(job);
then all the variables are fields of M.
>> M.a
ans =
0.4010

How can I change the name of the file being saved without editing the code? MatLab

I am working on an experiment that take a lot of data samples and save it to different video files. For example, I take data and save it to a file called "slowmotion.avi" and then I take another set of data and save it to another file called "normalspeed.avi".
I am trying to find a way that I could change the name of file being saved without editing the code. The way I am using right now makes me have to open the code and change the name of the file directory within the code and then save the code. I want to make it a lot faster and easier to use.
I have tried the following code to fix this problem but it doesn't work.
graph=input('Graph of experiment: ');
vidObj = VideoWriter('%3.1f.avi\n',graph);
.....
Hope I didn't confuse you.
A possible solution:
graph=input('Graph of experiment: ','s');
vidObj = VideoWriter([graph,'.avi']);
The 's' in the input() function indicates that the expected input is a string, and [graph,'.avi'] simply concatenates both strings.

Function to convert relative paths to absolute paths?

I've spent quite some time to no avail looking for a built-in MATLAB function to convert relative file paths to absolute file paths (portably).
Is there one?
I'm looking for something preferably "built-in" (i.e. available somewhere in the MATLAB distribution, including one of its toolboxes). Even a "package-private" function would be acceptable, as long as I can examine the source code of function. Second best would be a third-party function, as long as it comes with a decent test suite. I am not looking for a function written in response to this question.1
Absent any of the above, even a function to test (portably) whether a path is absolute or not would do (with the same conditions as before: either a "built-in" function or a third-party function with a test suite).
1 The difficulty with implementing such a function is not writing the function itself, but rather writing a sufficiently complete test suite for it (and, of course, making sure that the function passes all the tests!).
fullfile(pwd, relative_path) converts a relative to a absolute path.
You can test if a path is absolute using
javaFileObj = java.io.File(pathToBeTested);
javaFileObj.isAbsolute()
Unlike char(javaFileObj.getCanonicalPath()), which indeed sometimes incorrectly returns a non-existent path relative to C:\Windows\System32, isAbsolute() seems to work properly (tested on Win7, MATLAB 2015b) Therefore the code for constructing the absolute path would look like
function F = rel2abs(F)
if ~java.io.File(F).isAbsolute
F = fullfile(pwd,F);
end
This function has the advantage of being idempotent.
The fullfile(pwd, relative_path) hack works well for me, but if you want something to get you the canonical form, there is no built-in (as of 2015b), but there is a well regarded downloadable script.
http://www.mathworks.com/matlabcentral/fileexchange/28249-getfullpath
See if which fulfills your requirements:
full_path = which(relative_path);
OK, let's resurrect an old thread, if anyone is looking for this.
Here is a method, if you want the absolute path relative to your current working directory (or pwd).
% pwd: 'C:\first\branch'
dir('.\').folder % returns same as pwd, 'C:\first\branch'
dir('..\').folder % returns path one level up from pwd, 'C:\first'
dir('..\parallel_branch').folder % returns the absolute path to "parallel_branch" folder next to pwd, 'C:\first\parallel_branch'
Here's the method that MathWorks themselves uses:
[status, info] = fileattrib(file);
if status
% Return the full path if fileattrib found the file.
fullFilePath = info.Name;
end
For someone landing here with slightly relaxed portability requirements (or a suitable test bench), another idea is to create a folder listing containing only a single file using the built-in dir function, followed by path concatenation using fullfile.
dirListing = dir(relPath);
absPath = fullfile(dirListing(1).folder, dirListing(1).name);
Pros:
Idempotent, i.e. rel2abs(rel2abs(path)) = rel2abs(path)
Simplifies out any /. and /.. in the relative path
Cons:
This only works if the file exists
Tested using Matlab R2020a on Windows

Matlab - Locating file on a path that's inside package

Been trying (unsucessfully) to use 'which' to locate a .m file inside a package. For example, calling "which('Company.m')", when Company.m is inside a +Contents folder.
So if my current folder is C:\Users\Documents\Contents (path added to Matlab paths), "which('Company.m')" indicates no file found, but if my current folder is C:\Users***\Documents\Contents\ +Contents, then it will know the location.
Why is this? I thought that the 'which' command recursively searches through all subdirectories? Is there anyway to retrieve the path name of 'Company.m' without having to specifically source into that folder?
That should be:
which Contents.Company
If you dont know beforehand in which package it resides (or if its even in one), you could import them all:
import Contents.*
import OtherPackage.*
which -all Company
If you are still not satisfied, you could get a list of all top-level packages available, and search the methods they expose for the function you want:
%# warning: this might take more than a few seconds
p = meta.package.getAllPackages;
b = cellfun(#(pkg) ismember('Company',{pkg.FunctionList.Name}), p);
idx = find(b, 1, 'first');
p{idx}.Name