Matlab repr function - python

In Matlab, one can evaluate an arbitrary string as code using the eval function. E.g.
s = '{1, 2, ''hello''}' % char
c = eval(s) % cell
Is there any way to do the inverse operation; getting the literal string representation of an arbitrary variable? That is, recover s from c?
Something like
s = repr(c)
Such a repr function is built into Python, but I've not come across anything like it in Matlab, nor do I see a clear way of how to implement it myself.
The closest thing I know of is something like disp(c) which prints out a representation of c, but in a "readable" format as opposed to a literal code format.

The closest there is in Matlab is mat2str, which works for numeric, character or logical 2D arrays (including vectors). (It doesn't work for ND arrays, cell arrays, struct arrays, or tables).
Examples:
>> a = [1 2; 3 4]; ar = mat2str(a), isequal(eval(ar), a)
ar =
'[1 2;3 4]'
ans =
logical
1
>> a = ['abc'; 'def']; ar = mat2str(a), isequal(eval(ar), a)
ar =
'['abc';'def']'
ans =
logical
1
In this related question and answers you can see:
A function I wrote for obtaining a string representation of 2D cell arrays with arbitrarily nested cell, numeric, char or logical arrays.
How to do what you want in Octave for arbitrary data types.

OK, I see your pain.
My advice would still be to provide a function of the sort of toString leveraging on fprintf, sprint, and friends, but I understand that it may be tedious if you do not know the type of the data and also requires several subcases.
For a quick fix you can use evalc with the disp function you mentioned.
Something like this should work:
function out = repr(x)
out = evalc('disp(x)');
end
Or succinctly
repr = #(x) evalc('disp(x)');

Depending on exactly why you want to do this, your use case may be resolved with matlab.io.saveVariablesToScript
Here is the doc for it.
Hope that helps!

Related

Converting MatLab for loop with array code to python

I was given code in Matlab made by someone else and asked to convert to python. However, I do not know MatLab.This is the code:
for i = 1:nWind
[input(a:b,:), t(a:b,1)] = EulerMethod(A(:,:,:,i),S(:,:,i),B(:,i),n,scale(:,i),tf,options);
fprintf("%d\n",i);
for j = 1:b
vwa = generate_wind([input(j,9);input(j,10)],A(:,:,:,i),S(:,:,i),B(:,i),n,scale(:,i));
wxa(j) = vwa(1);
wya(j) = vwa(2);
end
% Pick random indexes for filtered inputs
rand_index = randi(tf/0.01-1,1,filter_size);
inputf(c:d,:) = input(a+rand_index,:);
wxf(c:d,1) = wxa(1,a+rand_index);
wyf(c:d,1) = wya(1,a+rand_index);
wzf(c:d,1) = 0;
I am confused on what [input(a:b,:), t(a:b,1)] mean and if wxf, wzf, wyf are part of the MatLab library or if it's made. Also, EulerMethod and generate_wind are seprate classes. Can someone help me convert this code to python?
The only thing I really changed so far is changing the for loop from:
for i = 1:nWind
to
for i in range(1,nWind):
There's several things to unpack here.
First, MATLAB indexing is 1-based, while Python indexing is 0-based. So, your for i = 1:nWind from MATLAB should translate to for i in range(0,nWind) in Python (with the zero optional). For nWind = 5, MATLAB would produce 1,2,3,4,5 while Python range would produce 0,1,2,3,4.
Second, wxf, wyf, and wzf are local variables. MATLAB is unique in that you can assign into specific indices at the same time variables are declared. These lines are assigning the first rows of wxa and wya (since their first index is 1) into the first columns of wxf and wyf (since their second index is 1). MATLAB will also expand an array if you assign past its end.
Without seeing the rest of the code, I don't really know what c and d are doing. If c is initialized to 1 before the loop and there's something like c = d+1; later, then it would be that your variables wxf, wyf, and wzf are being initialized on the first iteration of the loop and expanded on later iterations. This is a common (if frowned upon) pattern in MATLAB. If this is the case, you'd replicate it in Python by initializing to an empty array before the loop and using the array's extend() method inside the loop (though I bet it's frowned upon in Python, as well). But really, we need you to edit your question to include a, b, c, and d if you want to be sure this is really the case.
Third, EulerMethod and generate_wind are functions, not classes. EulerMethod returns two outputs, which you'd probably replicate in Python by returning a tuple.
[input(a:b,:), t(a:b,1)] = EulerMethod(...); is assigning the two outputs of EulerMethod into specific ranges of input and t. Similar concepts as in points 1 and 2 apply here.
Those are the answers to what you expressed confusion about. Without sitting down and doing it myself, I don't have enough experience in Python to give more Python-specific recommendations.

string to complex matrix representation in python

I have the following example string:
s ="1 1+i\n1-i 0"
Now I have to turn this string into a complex matrix. I am aware of the np.matrix() function but it is not designed for a complex matrix. Maybe some of you can provide me some ideas of how I can go forward. I also tried to split at \n but then I have two arrays which contain exactly one element (1 1+i & 1-i 0 ). The result should be:
np.array([[1, complex(1,1)], [complex(1, -1), 0]])
Thanks in advance!
Your question has two parts.
First, we want to convert the string into a list of complex numbers (as strings), and then convert this list into the actual complex numbers.
s = "1 1+i\n1-i 0"
import re
complex_strings = re.split("\n|\s+", s.replace('i', 'j'))
complex_numbers = [complex(x) for x in complex_strings]
m = np.array(complex_numbers).reshape(2, 2)
[[1.+0.j 1.+1.j]
[1.-1.j 0.+0.j]]

Extract dependency information between the variables of a numpy expression

I want to extract dependency information between the variables in a string that contains a Python 3 NumPy expression. For example:
import numpy as np
a = np.array([10, 20, 30])
b = np.array([10, 20, 30])
c = np.array([10, 20, 30])
d = 100
# The expression string will only contain numbers, arrays, and `NumPy` functions.
expression = 'b[1:3] = a[0:3:2] + np.sum(c[:]) + d'
deps = extract_dependencies(expression)
Then, the result should be:
deps: {
'b[0]': [],
'b[1]': ['a[0]', 'c[0]', 'c[1]', 'c[2]', 'd']
'b[2]': ['a[2]', 'c[0]', 'c[1]', 'c[2]', 'd']
}
My problem is that I can't figure out how to implement extract_dependencies().
This is easy to solve if all the symbols in the expression are either not arrays or arrays with single-element indexing (e.g., foo, bar[0], baz[2]). It can be done by using either regular expressions or some basic text parsing.
However, if the variables are arrays, things get more complicated. For basic operations, one could use regular expressions to find the variables in the expression string, and then extract and map array indices accordingly. For example it is easy to extract and match the indices of the expression a[0:2] = b[1:3]. Things become more tricky when functions are used as part of the expression string because they are essentially "black boxes". You can't account for all possible function signatures, behaviors, and return values unless you hard code every single one of them.
I was wondering if this could be solved using some clever use of Python's eval, exec, or ast trees.
Any ideas? :)
Thank you.
PS: The expression string is eventually evaluated using the asteval library. Hence, a solution that utilizes asteval will get extra points! :)
I (main author of asteval) think this is not possible, at least not in general.
As you say, even with your expression
expression = 'b[1:3] = a[0:3:2] + np.sum(c[:]) + d'
you need to know:
how strides work: That [x:y:n] slice means (x, x+n, x+2n, ...) up to y-1. OK, that's not too hard for 1D arrays.
what np.sum() does -- that it returns a value with arrays summed along an axis. What happens if c = np.array([[5, 4], [9,- 2]])? The expression works, but the element-by-element dependencies change. Which means that you have to know what np.sum does in detail.
what d is. What happens if it changes from a scalar to is a 2-element array?
Basically, you're asking to figure out element-by-element dependencies lexically. You have to know what a, c, d, and np.sum are to know what the resulting dependencies will be. You cannot tell from the words alone.
Python views slices and function calls as operations to be done at run time. So it parses this expression then expects that whatever is held by d can be added to the result of whatever np.sum returns with the function argument returned by evaluating an "all-null slice" on whatever c is. If those two things cannot be added together, it will fail at run time.

Truth value of numpy array with one falsey element seems to depend on dtype

import numpy as np
a = np.array([0])
b = np.array([None])
c = np.array([''])
d = np.array([' '])
Why should we have this inconsistency:
>>> bool(a)
False
>>> bool(b)
False
>>> bool(c)
True
>>> bool(d)
False
For arrays with one element, the array's truth value is determined by the truth value of that element.
The main point to make is that np.array(['']) is not an array containing one empty Python string. This array is created to hold strings of exactly one byte each and NumPy pads strings that are too short with the null character. This means that the array is equal to np.array(['\0']).
In this regard, NumPy is being consistent with Python which evaluates bool('\0') as True.
In fact, the only strings which are False in NumPy arrays are strings which do not contain any non-whitespace characters ('\0' is not a whitespace character).
Details of this Boolean evaluation are presented below.
Navigating NumPy's labyrinthine source code is not always easy, but we can find the code governing how values in different datatypes are mapped to Boolean values in the arraytypes.c.src file. This will explain how bool(a), bool(b), bool(c) and bool(d) are determined.
Before we get to the code in that file, we can see that calling bool() on a NumPy array invokes the internal _array_nonzero() function. If the array is empty, we get False. If there are two or more elements we get an error. But if the array has exactly one element, we hit the line:
return PyArray_DESCR(mp)->f->nonzero(PyArray_DATA(mp), mp);
Now, PyArray_DESCR is a struct holding various properties for the array. f is a pointer to another struct PyArray_ArrFuncs that holds the array's nonzero function. In other words, NumPy is going to call upon the array's own special nonzero function to check the Boolean value of that one element.
Determining whether an element is nonzero or not is obviously going to depend on the datatype of the element. The code implementing the type-specific nonzero functions can be found in the "nonzero" section of the arraytypes.c.src file.
As we'd expect, floats, integers and complex numbers are False if they're equal with zero. This explains bool(a). In the case of object arrays, None is similarly going to be evaluated as False because NumPy just calls the PyObject_IsTrue function. This explains bool(b).
To understand the results of bool(c) and bool(d), we see that the nonzero function for string type arrays is mapped to the STRING_nonzero function:
static npy_bool
STRING_nonzero (char *ip, PyArrayObject *ap)
{
int len = PyArray_DESCR(ap)->elsize; // size of dtype (not string length)
int i;
npy_bool nonz = NPY_FALSE;
for (i = 0; i < len; i++) {
if (!Py_STRING_ISSPACE(*ip)) { // if it isn't whitespace, it's True
nonz = NPY_TRUE;
break;
}
ip++;
}
return nonz;
}
(The unicode case is more or less the same idea.)
So in arrays with a string or unicode datatype, a string is only False if it contains only whitespace characters:
>>> bool(np.array([' ']))
False
In the case of array c in the question, there is a really a null character \0 padding the seemingly-empty string:
>>> np.array(['']) == np.array(['\0'])
array([ True], dtype=bool)
The STRING_nonzero function sees this non-whitespace character and so bool(c) is True.
As noted at the start of this answer, this is consistent with Python's evaluation of strings containing a single null character: bool('\0') is also True.
Update: Wim has fixed the behaviour detailed above in NumPy's master branch by making strings which contain only null characters, or a mix of only whitespace and null characters, evaluate to False. This means that NumPy 1.10+ will see that bool(np.array([''])) is False, which is much more in line with Python's treatment of "empty" strings.
I'm pretty sure the answer is, as explained in Scalars, that:
Array scalars have the same attributes and methods as ndarrays. [1] This allows one to treat items of an array partly on the same footing as arrays, smoothing out rough edges that result when mixing scalar and array operations.
So, if it's acceptable to call bool on a scalar, it must be acceptable to call bool on an array of shape (1,), because they are, as far as possible, the same thing.
And, while it isn't directly said anywhere in the docs that I know of, it's pretty obvious from the design that NumPy's scalars are supposed to act like native Python objects.
So, that explains why np.array([0]) is falsey rather than truthy, which is what you were initially surprised about.
So, that explains the basics. But what about the specifics of case c?
First, note that your array np.array(['']) is not an array of one Python object, but an array of one NumPy <U1 null-terminated character string of length 1. Fixed-length-string values don't have the same truthiness rule as Python strings—and they really couldn't; for a fixed-length-string type, "false if empty" doesn't make any sense, because they're never empty. You could argument about whether NumPy should have been designed that way or not, but it clearly does follow that rule consistently, and I don't think the opposite rule would be any less confusing here, just different.
But there seems to be something else weird going on with strings. Consider this:
>>> np.array(['a', 'b']) != 0
True
That's not doing an elementwise comparison of the <U2 strings to 0 and returning array([True, True]) (as you'd get from np.array(['a', 'b'], dtype=object)), it's doing an array-wide comparison and deciding that no array of strings is equal to 0, which seems odd… I'm not sure whether this deserves a separate answer here or even a whole separate question, but I am pretty sure I'm not going to be the one who writes that answer, because I have no clue what's going on here. :)
Beyond arrays of shape (1,), arrays of shape () are treated the same way, but anything else is a ValueError, because otherwise it would be very easily to misuse arrays with and and other Python operators that NumPy can't automagically convert into elementwise operations.
I personally think being consistent with other arrays would be more useful than being consistent with scalars here—in other words, just raise a ValueError. I also think that, if being consistent with scalars were important here, it would be better to be consistent with the unboxed Python values. In other words, if bool(array([v])) and bool(array(v)) are going to be allowed at all, they should always return exactly the same thing as bool(v), even if that's not consistent with np.nonzero. But I can see the argument the other way.
It's fixed in master now.
I thought this was a bug, and the numpy devs agreed, so this patch was merged earlier today. We should see new behaviour in the upcoming 1.10 release.
Numpy seems to be following the same castings as builtin python**, in this context it seems to be because of which return true for calls to nonzero. Apparently len can also be used, but here, none of these arrays are empty (length 0) - so that's not directly relevant. Note that calling bool([False]) also returns True according to these rules.
a = np.array([0])
b = np.array([None])
c = np.array([''])
>>> nonzero(a)
(array([], dtype=int64),)
>>> nonzero(b)
(array([], dtype=int64),)
>>> nonzero(c)
(array([0]),)
This also seems consistent with the more enumerative description of bool casting --- where your examples are all explicitly discussed.
Interestingly, there does seem to be systematically different behavior with string arrays, e.g.
>>> a.astype(bool)
array([False], dtype=bool)
>>> b.astype(bool)
array([False], dtype=bool)
>>> c.astype(bool)
ERROR: ValueError: invalid literal for int() with base 10: ''
I think, when numpy converts something into a bool it uses the PyArray_BoolConverter function which, in turn, just calls the PyObject_IsTrue function --- i.e. the exact same function that builtin python uses, which is why numpy's results are so consistent.

Lowpass Filter in python

I am trying to convert a Matlab code to Python. I want to implement fdesign.lowpass() of Matlab in Python. What will be the exact substitute of this Matlab code using scipy.signal.firwin():
demod_1_a = mod_noisy * 2.*cos(2*pi*Fc*t+phi);
d = fdesign.lowpass('N,Fc', 10, 40, 1600);
Hd = design(d);
y = filter(Hd, demod_1_a);
A very basic approach would be to invoke
# spell out the args that were passed to the Matlab function
N = 10
Fc = 40
Fs = 1600
# provide them to firwin
h = scipy.signal.firwin(numtaps=N, cutoff=40, nyq=Fs/2)
# 'x' is the time-series data you are filtering
y = scipy.signal.lfilter(h, 1.0, x)
This should yield a filter similar to the one that ends up being made in the Matlab code.
If your goal is to obtain functionally equivalent results, this should provide a useful
filter.
However, if your goal is that the python code provide exactly the same results,
then you'll have to look under the hood of the design call (in Matlab); From my quick check, it's not trivial to parse through the Matlab calls to identify exactly what it is doing, i.e. what design method is used and so on, and how to map that into corresponding scipy calls. If you really want compatibility, and you only need to do this for a limited number
of filters, you could, by hand, look at the Hd.Numerator field -- this array of numbers directly corresponds to the h variable in the python code above. So if you copy those
numbers into an array by hand, you'll get numerically equivalent results.

Categories

Resources