Getting absolute file path from function handle - matlab

Is there possibility to retrieve the absolute path to the file containing a function represented by a function handle? For example:
%child folder containing test_fun.m file
handle = #test_fun
cd ..
%root folder - test_fun not available
path = GETPATHFROMHANDLE(handle)
Is there equivalent to GETPATHFROMHANDLE function in MATLAB? It seems to by simple functionality, but I can't work it out. I know about func2str and which functions, but that doesn't work in that case.

Function handles (i.e. objects of class function_handle) have a method called functions, which will return information about the handle, including the full path of the associated file:
>> fs = functions(h)
fs =
function: 'bar'
type: 'simple'
file: 'C:\Program Files\MATLAB\R2013b\toolbox\matlab\specgraph\bar.m'
>> fs.file
ans =
C:\Program Files\MATLAB\R2013b\toolbox\matlab\specgraph\bar.m
Since the output of functions is a struct, this can be done in a single command with getfield:
>> fName = getfield(functions(h),'file')
fName =
C:\Program Files\MATLAB\R2013b\toolbox\matlab\specgraph\bar.m
However, you can use func2str and which to get the file name if you string them together:
>> h = #bar;
>> fName = which(func2str(h))
fName =
C:\Program Files\MATLAB\R2013b\toolbox\matlab\specgraph\bar.m

Related

get 'Documents' path in Matlab

I understand you can probably use the following code to get the job done in most cases:
mydocpath = fullfile(getenv('USERPROFILE'), 'Documents');
However, if the user has moved 'Doucments' folder to a different location, for example: E:\Documents, the above code won't work, since getenv('USERPROFILE') always returns C:\Users\MY_USER_NAME.
In C#, one can use Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), which always returns the correct path regardless where 'Documents' is. Is there anything similar in Matlab?
My current solution is rather clumsy and probably unsafe:
% search in the MATLAB path lists
% this method assumes that there is always a path containing \Documents\MATLAB registered already
searchPtn = '\Documents\MATLAB';
pathList = strsplit(path,';');
strIdx = strfind(pathList, searchPtn);
candidateIdx = strIdx{find(cellfun(#isempty,strIdx)==0, 1)}(1);
myDocPath = pathList{candidateIdx}(1 : strIdx{candidateIdx}+ numel(searchPtn));
Based on #excaza 's suggestion, I came up with a solution using dos and the cmd command found here to query the registry.
% query the registry
[~,res]=dos('reg query "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v Personal');
% parse result
res = strsplit(res, ' ');
myDocPath = strtrim(res{numel(res)});
Edit:
If the document folder in customer's PC has not been relocated or moved to one of the environment path such as %SYSTEMROOT%, the above method would return
%SOME_ENVIRONMENT_PATH%/Documents(Or a custom folder name)
The above path will not work in Matlab's functions such as mkdir or exist, which will take %SOME_ENVIRONMENT_PATH% as a folder name. Therefore we need to check for the existence of environment path in the return value and get the correct path:
[startidx, endidx] = regexp(myDocPath,'%[A-Z]+%');
if ~isempty(startidx)
myDocPath = fullfile(getenv(myDocPath(startidx(1)+1:endidx(1)-1)), myDocPath(endidx(1)+1:end));
end
Full code:
% query the registry
[~,res]=dos('reg query "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v Personal');
% parse result
res = strsplit(res, ' ');
% get path
myDocPath = strtrim(res{numel(res)});
% if it returns %AAAAA%/xxxx, meaning the Documents folder is
% in some environment path.
[startidx, endidx] = regexp(myDocPath,'%[A-Z]+%');
if ~isempty(startidx)
myDocPath = fullfile(getenv(myDocPath(startidx(1)+1:endidx(1)-1)), myDocPath(endidx(1)+1:end));
end

Reconstruct directories from file MATLAB

Thanks for your help.
The problem is:
I need the user to select a file based on an extension lets say .tif. I used the standard method, i.e.
[flnm,locn]=uigetfile({'*.tif','Image files'}, 'Select an image');
ext = '.tif';
But I need to fetch other image files from other subdirectories. Say the directory name returned to locn is: /user/blade/checklist/exp1/trial_1/run_1/exp001.tif. Image goes to exp100.tif.
I want to access:
/user/blade/checklist/exp1/trial_1/run_2/exp001.tif.
Also access:
/user/blade/checklist/exp1/trial_2/run_2/exp001.tif.
Up to trial_n
But if I list directory in /user/blade/checklist/exp1/, I get all folders therein from where I can reconstruct the right path. The naming structure is orderly.
My current solution is
[flnm,locn]=uigetfile({'*.tif','Image files'}, 'Select an image');
ext = '.tif';
parts = strsplit(locn, '/');
f = fullfile(((parts{end-5}),(parts{end-4}),(parts{end-3}),(parts{end-2}),(parts{end-1}));
Which is really ugly and I also lose the first /. Any help is appreciated.
Thanks!
First, get the file location as you did; note a small change I've made to make use of the variable ext.
ext = '.txt';
[flnm,locn]=uigetfile({['*',ext]}, 'Select an image');
parts = strsplit(locn,'/');
root = parts(1:end-4);
parts has 2 information - 1) path of the selected file; 2) path of your working folder, checklist, which you need. So root has the working folder.
Then, list out all the files you wanted, and put them in a cell array.
The file names should contain partial (subfolder) paths; it's not difficult to follow the pattern.
flist = {'trial_1/run_1/exp001.tif', ...
'trial_1/run_1/exp002.tif', ...
'trial_1/run_2/exp001.tif', ...
'trial_2/run_1/exp001.tif', ...
'trial_2/run_2/exp001.tif'};
I just enumerated a few; you can use a for loop to automatically generate trial_n and expxxx.tif. An example code to generate the complete file list (but not "full paths") -
flist = cell(10*2*100,1);
for ii = 1:10
for jj = 1:2
for kk = 1:100
flist{sub2ind([10,2,100],ii,jj,kk)} = ...
sprintf('trial_%d/run_%d/exp%03d%s', ii,...
jj, kk, ext);
end
end
end
Finally, use strjoin to concatenate the first part (your working folder) and second part (needed files in subfolders). Use cellfun to call strjoin for each cell in the file list cell array, so for every file you want you get a full path.
full_flist = cellfun(#(x) strjoin([root, x],'/'), ...
flist, 'UniformOutput', false);
Example output -
>> locn
locn =
/home/user/Downloads/exp1/trial_1/run_1/
>> for ii = 1:5
full_flist{ii}
end
ans =
/home/user/Downloads/trial_1/run_1/exp001.tif
ans =
/home/user/Downloads/trial_1/run_1/exp002.tif
ans =
/home/user/Downloads/trial_1/run_2/exp001.tif
ans =
/home/user/Downloads/trial_2/run_1/exp001.tif
ans =
/home/user/Downloads/trial_2/run_2/exp001.tif
>>
Note: You can either use
strjoin(str1, str2, '/')
or
sprintf('%s/%s', str1, str2)
They are equivalent.

Load Multiple .mat Files to Matlab workspace

I'm trying to load several .mat files to the workspace. However, they seem to overwrite each other. Instead, I want them to append. I am aware that I can do something like:
S=load(file1)
R=load(file2)
etc.
and then append the variables manually.
But there's a ton of variables, and making an append statement for each one is extremely undesirable (though possible as a last resort). Is there some way for me to load .mat files to the workspace (by using the load() command without assignment) and have them append?
Its not entirely clear what you mean by "append" but here's a way to get the data loaded into a format that should be easy to deal with:
file_list = {'file1';'file2';...};
for file = file_list'
loaded.(char(file)) = load(file);
end
This makes use of dynamic field references to load the contents of each file in the list into its own field of the loaded structure. You can iterate over the fields and manipulate the data however you'd like from here.
It sounds like you have a situation in which each file contains a matrix variable A and you want to load into memory the concatenation of all these matrices along some dimension. I had a similar need, and wrote the following function to handle it.
function var = loadCat( dim, files, varname )
%LOADCAT Concatenate variables of same name appearing in multiple MAT files
%
% where dim is dimension to concatenate along,
% files is a cell array of file names, and
% varname is a string containing the name of the desired variable
if( isempty( files ) )
var = [];
return;
end
var = load( files{1}, varname );
var = var.(varname);
for f = 2:numel(files),
newvar = load( files{f}, varname );
if( isfield( newvar, varname ) )
var = cat( dim, var, newvar.(varname) );
else
warning( 'loadCat:missingvar', [ 'File ' files{f} ' does not contain variable ' varname ] );
end
end
end
Clark's answer and function actually solved my situation perfectly... I just added the following bit of code to make it a little less tedious. Just add this to the beginning and get rid of the "files" argument:
[files,pathname] = uigetfile('*.mat', 'Select MAT files (use CTRL/COMM or SHIFT)', ...
'MultiSelect', 'on');
Alternatively, it could be even more efficient to just start with this bit:
[pathname] = uigetdir('C:\');
files = dir( fullfile(pathname,'*.mat') ); %# list all *.mat files
files = {files.name}'; %# file names
data = cell(numel(files),1); %# store file contents
for i=1:numel(files)
fname = fullfile(pathname,files{i}); %# full path to file
data{i} = load(fname); %# load file
end
(modified from process a list of files with a specific extension name in matlab).
Thanks,
Jason

Import variables from file

Hi so I have a file called config.m that contains a list of variables along with some comments. I wanted to basically load that script up through another matlab script so that the variables would be recognized and used and could also be changed easily. Here is what my file with the variables looks like.
%~~~~~~~~~~~~~~~~~
%~~~[General]~~~~~
%~~~~~~~~~~~~~~~~~
%path to samtools executable
samtools_path = '/home/pubseq/BioSw/samtools/0.1.8/samtools';
%output_path should be to existing directory, script will then create tumour
%and normal folders and link the bam files inside respectively
output_path = '/projects/dmacmillanprj/testbams';
prefix = %prefix for output files
source_file = % from get_random_lines.pl, what is this?
% The window size
winSize = '200';
% Between 0 and 1, i.e. 0.7 for 70% tumour content
tumour_content = '1';
% Should be between 0 and 0.0001
gc_window = 0.005;
% Path to tumour bam file
sample_bam = '/projects/analysis/analysis5/HS2310/620GBAAXX_4/bwa/620GBAAXX_4_dupsFlagged.bam';
% Path to normal bam file
control_bam = '/projects/analysis/analysis5/HS2381/620GBAAXX_6/bwa/620GBAAXX_6_dupsFlagged.bam';
I have tried this:
load('configfile.m')
??? Error using ==> load
Number of columns on line 2 of ASCII file /home/you/CNV/branches/config_file/CopyNumber/configfile.m
must be the same as previous lines.
Just run the script config.m inside another script as
config
Remember config.m file should be in the working directory or in MATLAB path.
However I would recommend you to create a function from this script and return a structure with all the parameters as fields. Then you will be more flexible in your main script since you can assign any name to this structure.
function param = config()
param.samtools_path = '/home/pubseq/BioSw/samtools/0.1.8/samtools';
param.output_path = '/projects/dmacmillanprj/testbams';
% ... define other parameteres
In the main script:
P = config;
st_dir = P.samtools_path;
% ...etc...
Alternatively, you could define a class with constant properties in your config.m file:
classdef config
properties (Constant)
samtools_path = '/home/pubseq/BioSw/samtools/0.1.8/samtools';
output_path = '/projects/dmacmillanprj/testbams';
end
end
Thereby, you can access the class properties in another script:
config.samtools_path
config.output_path
To round it up, you could place your config.m file into a package (+ folder) and import it explicitly in your script. Assuming your package would be called "foo" and the "+foo" folder on your Matlab path, your script would look as follows:
import foo.config
foo.config.samtools_path
foo.config.output_path
load() is not suitable for files that contain text (even in the form of matlab comments.)
You should use textscan() or dlmread(), specifying to them that you want to skip two header lines or that you want to treat '%' as indicating a comment.

Why i get this following error when using dir in Matlab?

Matlab keep give me following error message :
??? Error using ==> dir
Argument must contain a string.
Error in ==> Awal at 15
x = dir(subDirs)
Below is my codes :
%MY PROGRAM
clear all;
clc;
close all;
%-----Create Database-----
TrainDB = uigetdir('','Select Database Directory');
TrainFiles = dir(TrainDB);
dirIndex = [TrainFiles.isdir];
[s subDirNumber] = size(dirIndex);
for i = 3:subDirNumber
subDirs = {TrainFiles(i).name};
subDirs = strcat(TrainDB,'\',subDirs);
x = dir(subDirs) %<-------Error Here
end
Is something wrong with the codes? Your help will be appreciated.
I'm sorry for my bad English.
The problem is with this line:
subDirs = {TrainFiles(i).name};
When you strcat on the next line, you are strcat-ing two strings with a cell containing a string. The result in subDirs is a cell containing a string which dir() apparently doesn't like. You can either use
subDirs = TrainFiles(i).name;
or
x = dir(subDirs(1))
I would recommend the first option.
When I run your code I get the error message:
??? Error using ==> dir
Function is not defined for 'cell' inputs.
What MATLAB is telling you is that when you call dir(subDirs) subDirs is a cell rather than a string which is what dir wants. Something like dir(subDirs{1,1}) will do what (I think) you want. I'll leave it to you to rewrite your code.
with subDirs = {TrainFiles(i).name}; you create a cell-array of stings. dir is not defined for that type. Just omit the {} around the name
BTW: Your code does not only list directories, but all files. Check find on the isdir attribute to get only directory's indices!