get/edit code of function with Ipython - ipython

when you enter function??, besides the info you get the source code of the function if there is available.
Is there a way of?:
1) get the code as str object
2) edit in place similar to %load

Assuming that you have the module and function names as "module" and "function" string variables, then
from inspect import getmembers, isfunction, getsource
internal_module = __import__(module)
internal_functions = dict(getmembers(internal_module, isfunction))
source_code = getsource(internal_functions[function])
will give you a dictionary (internal_functions) containing all functions in the module and a string (source_code) containing the source of that specific function.
You would then have to manipulate the string in order to edit the function, I think.

Related

Programmatically return a list of all functions

I want to programmatically get a list of available functions in the current MATLAB namespace, as well the available functions in a package. How can this be done?
We can use package metadata for this:
pkgs = meta.package.getAllPackages();
% Or if the specific package name is known:
mp = meta.package.fromName('matlab')
The cell array returned in the 1st case, pkgs, contains objects such as this:
package with properties:
Name: 'Sldv'
Description: ''
DetailedDescription: ''
ClassList: [29×1 meta.class]
FunctionList: [8×1 meta.method]
PackageList: [9×1 meta.package]
ContainingPackage: [0×0 meta.package]
So all that's left to do is iterate through the packages and sub-packages tand collect their FunctionList entries.
I'm not sure how to get the functions that belong to the "default" namespace, other than by parsing the function list doc page, for example using the Python API and BeautifulSoup:
fl = arrayfun(#(x)string(x{1}.string.char), py.bs4.BeautifulSoup( ...
fileread(fullfile(docroot,'matlab','functionlist-alpha.html')), ...
'html.parser').find_all("code")).';
Further to Dev-iL's answer, parsing the function list documentation web page is pretty easy because of the useful "function" class that the web devs have (currently) used to tag each function name with! Each function looks like this within the HTML:
<code class="function">accumarray</code>
So we can use urlread to grab the source, and regular expressions to strip out the inner text of each "function" class item:
str = urlread('https://mathworks.com/help/matlab/functionlist-alpha.html');
funcs = regexp( str, '(?<="function">)[0-9A-Za-z.]+', 'match' );
Note: "alpha" in the URL is for "alphabetical" rather than to denote early testing!
funcs is a cell array with all the function names on that page.
The page used above is for the most recent MATLAB version. For a specific version, use the historic documentation pages structured like so:
https://mathworks.com/help/releases/R2017b/matlab/functionlist.html

Matlab Array of structures: string not working

I am reading an input from a file and importing it into my data to run in Matlab:
parts = strread(tline,'%s','delimiter',';')
employee(i).name = parts(1);
employee(i).salary= str2double(parts(2));
Then I try to print it out:
for i = 1:3
fprintf('salary: %.2f\n',employee(i).salary);
fprintf('employee name: %s\n',employee(i).name);
end
The salary prints with no problem. But the for the variable "name" it gives an error:
Error using fprintf
Function is not defined for 'cell' inputs.
fprintf('employee name: %s\n',employee(i).name);
I looked for some other examples:
access struct data (matlab)
How do I access structure fields dynamically?
Matlab Error: Function is not defined for 'cell' inputs
How do i define a structure in Matlab
But there is nothing to address this case, where only string is not working.
I have not explicitly declared the data as struct, i.e. inside the code there is nowhere the "struct" word is included, but Matlab apparently automatically understand it as an "Array of structures".
Any hints what might be missing here?
All comments are highly appreciated!
The issue is that employee(k).name is a cell (check with iscell(employee(1).name)) and the format string %s doesn't know how to handle that.
The reason that it is a cell is because strread returns a cell array. To grab an element from the result (parts), you want to use {} indexing which returns a string rather than () which will return a cell.
employee(i).name = parts{1};

Using Scispark can we know all the variables included in a netcdf file ?

val data = sc.NetcdfDFSFile("/home/akhilav/Downloads/120mb.nc",variable,3)
here i give variable as latitude. beacause I know the variables.If we r not familiar with variables how can we extract from netcdf file through code.
Import org.dia.loaders.NetCDFReader
...
netcdfPath = "--**PATH TO A NETCDF FILE**--"
varNames = NetCDFReader.loadNetCDFVar(netcdfPath)
The only caveat here is that the netcdfPath string needs to be a local path not an HDFS path. loadNetCDFVar() opens a netcdffile, extracts all its variables, and returns it as a list of strings. You can then pass that list when calling the NetcdfDFSFile() function.

Calling the function doesn't work

I have a cell array of stucts, each containing the personalia of a person. I put it into this function to get them listed in a text file of a chosen name.
function store( filename, persons )
fid = fopen(filename,'w');
for i=1:length(persons)
fprintf(fid, '%s',serialize_person(persons{i}));
end
Now this function works fine: I enter a <1x3 cell> and get out a text file with three listed persons. However, I want to call this function from another:
function process_store()
list=input('Write in the list of persons you want listed: ');
fprintf('\n')
newfile=input('Give the text file a name: ','s');
store(filename,list)
end
Here I enter the name of the <1x3 cell> as before, but I get a error message "Error using input,Undefined function or variable 'persons'."
Why is this? Am I not using the exact same data as Im using in 'store'?
The problem is that the variable persons isn't accessible inside the function process_store. In Matlab (and most other programming languages) functions can't access variables defined in their calling functions. To understand this better, I recommend having a read of the Wikipedia article on levels of scope.
You essentially have two options here:
Make persons a global variable, both in your workspace and in the function process_store, by using the declaration global persons. I wouldn't recommend this.
Use the function evalin to allow process_store to access variables in its parent workspace.
I'd go with option 2 if I were you. It's a little tricky, so let me explain how it works. Let's create a variable persons in the global workspace.
>> persons = {'John', 'Jack', 'Jill'};
Now say we have the following function
function example()
x = input('Give me a variable name: ');
disp(x)
end
What happens if we try to use it?
>> example()
Give me a variable name: persons
Error using input
Undefined function of variable 'persons'
Error in example (line 2)
x = input('Give me a variable name: ');
Oh dear. That's because the function example doesn't have access to the global workspace, which is where persons is defined. But instead, we can store the name of the variable we want to access, and then check out its value in the global workspace by using evalin, like this
function example()
s = input('Give me a variable name: ', 's');
x = evalin('caller', s);
disp(x)
end
Now if we use it:
>> example()
Give me a variable name: persons
'John' 'Jack' 'Jill'
It works as we expected! Great!
Massive disclaimer
There is almost never a good reason to use functions like evalin (or eval, or assignin or any other function that messes around executing strings as code). There's almost certainly a better way of doing what you want to do. But without knowing what it is you're trying to do, it's hard to give you better advice.
At the prompt
Write in the list of persons you want listed:
if you typed
persons
then you would get exactly that error message if the variable persons was not defined.

MATLAB : passing cell arguments

I have a function :
function myFunc(myStruct)
% file can contains one or a list of files
file = {fullfile(pwd,myStruct.name)}
end
from another file , when I call myFunc
myStruct.name = {'toto','titi','tata'}
myFunc(myStruct);
I got an error ,function isn't definied for cell
and I would like to pass to the field myStruct.name a string or a list of strings :
I mean that myStruct.name can accept one argument 'toto' or list of arguments {'toto','titi'}
When
How could I do that ?
Thanks
Finally we have a complete question.
Read the exception carefully, how you asked your question tells me that you did not understand it. The exception says that fullfile is not defined for cell inputs, which is simply fact. You have to call fullfile for each folder that should be generated, thus a for-loop is required, with something like file{idx} = fullfile(pwd,myStruct.name{idx}) in it.