1

I am porting some Matlab code to Python. In this code there are many instances of a large matrix being sliced in many different ways, eg M(2:45,13:18), M(:12,:), V(4), V(:27), etc. It is technically possible to convert this to numpy notation manually, by replacing the parentheses with square brackets and substracting 1 to all indices (except after :) but it is incredibly tedious and there is a very high probability that I will make a typo at some point.

I tried automating this but my grep/awk/parsing skills are not good enough. Is there a script out there that will do the job?

4
  • While basic indexing is similar enough, indexing with lists/arrays, what numpy docs call advanced indexing is different. You have to use np.ix_ to get similar 'block' indexing. Commented Oct 8, 2022 at 15:55
  • Some of your examples are not even valid MATLAB syntax. Commented Oct 8, 2022 at 16:02
  • Cris Luengo: noted, but whether the input Matlab is valid is not really my issue to solve. I'm confident that my actual inputs will be valid, and I was just wondering hoe to automate the conversion. Thanks anyway. Commented Oct 9, 2022 at 18:04
  • Still, it makes no sense to translate V(:27) because it means nothing in MATLAB. Commented Oct 9, 2022 at 21:07

2 Answers 2

1

Assuming you have your matlab code in a string, you can format it in Python. You could do this with regex match replacement:

import re

def format_indexers(match):
    # Format any "(x:y:z)" into python format
    ret = match[0].replace("(", "[").replace(")", "]") # replace brackets
    ret = re.sub(r"(\[|,)(\d+)", lambda x: x[1] +  str(int(x[2]) - 1) , ret) # replaces numbers by decremented ones
    return ret    

s = "M(2:45,13:18), M(:12,:), V(4), V(:27)"

# Searches expressions between parenthesis and apply format_indexers to found matches
re.sub(r"\(.*\)", format_indexers, s)

outputs:

'M[1:45,12:18], M[:12,:], V[3], V[:27]'
Sign up to request clarification or add additional context in comments.

6 Comments

Thanks, I'll look into it. But note that M(2:45) should become M[1:45], since Matlab slices are end-inclusive.
Oh right I misunderstood the "except after :" part
Based on your example I got something working (see my new comment). What is the correct etiquette? Should I accept your answer and leave mine, or accept mine and upvote yours? Not sure what is called for. Thanks anyway.
I don't know in this case ahah, but your output is the same as me now, isn't it ?
My bad, I hadn't realized that you edited your original answer. Thanks again.
|
0

Here is another take based on PlainRavioli's original answer:

INPUT = 'M(2:45,13:18) M(:12,:) V(4) V(:27)'

import re

def my_replace(m):
    m = m.group()
    a, m = m[0], m[2:-1]
    m = m.split(',')
    for k in range(len(m)):
        if ':' in m[k]:
            m[k] = m[k].split(':')
            if m[k][0]:
                m[k][0] = str(int(m[k][0])-1)
            m[k] = ':'.join(m[k])
        else:
            m[k] = str(int(m[k])-1)
    m = ','.join(m)
    m = a + '[' + m + ']'
    return m

OUT = re.sub('\\w\\(\d*:?\d*(,\d*:?\d*)?\\)', my_replace, INPUT)
    
print(OUT)
# yields:  M[1:45,12:18] M[:12,:] V[3] V[:27]

1 Comment

You’d have to look for end in indexing and translate that correctly too. Some indexing doesn’t translate at all, for example a(end+1)=1 you can’t do in Python. And special indexing would be translated wrong with this program, a([1,2,3],[3,5,2]) does something very different from the similar-looking Python code. Be careful!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.