3

I'm trying to read a file (generated with Fortran) with complex numbers into Python.

Say, after using a = f1.readline().split( ), I get the following value for a:

a = ['(4.471719725275173E-003,2.163649191486555E-002)']

If I do

b = np.complex(a[0])

it produces an error

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-4-cff25069e279> in <module>()
----> 1 b = np.complex(a[0])

ValueError: complex() arg is a malformed string

I tried to do this based on the fact that numpy seems to support Fortran notation (Reading fortran double precision format into python). Is there an equivalent function for complex numbers?

If not, what would be the best way to proceed (rather than using different delimiters in the split( ) call and reconstruct the complex number by hand).

1
  • Please never use "It doesn't work." in your questions. Describe what it actually does. Commented Jan 19, 2016 at 17:16

2 Answers 2

3

You can parse it this way (https://stackoverflow.com/a/9763133/721644):

from ast import literal_eval

t = literal_eval(a[0])

b = complex(t[0], t[1])

>(0.004471719725275173+0.02163649191486555j)

It first makes a tuple of floats and than uses its components as arguments to complex().

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you! Simple and effective.
1
import numpy as np
a = ['(4.471719725275173E-003,2.163649191486555E-002)']
i, j = np.safe_eval(a[0])

print(np.complex(i, j))
(0.004471719725275173+0.02163649191486555j)

If you are reading from a file and want an array:

import numpy as np



def to_complex(f):
    conv = lambda x: np.complex(*np.safe_eval(x))
    return np.genfromtxt(f, converters={0: conv})

Output:

In [3]: cat out.txt
(4.471719725275173E-003,2.163649191486555E-002)
(6.471719725275173E-003,2.163649191486555E-002)
In [4]: print(to_complex("out.txt"))
[ 0.00447172+0.02163649j  0.00647172+0.02163649j]

Or if you just want a value at a time:

from itertools import imap
def to_complex(f):
    with open(f) as fle:
        for a, b in imap(np.safe_eval, fle):
            yield np.complex(a, b)

Output:

In [7]: print(list(to_complex("out.txt")))
[(0.004471719725275173+0.02163649191486555j), (0.006471719725275173+0.02163649191486555j)]

You could also just cast the data yourself stripping and splitting which would be faster than using safe_eval:

from itertools import imap

def to_complex(f):
    with open(f) as fle:
        for tup in imap(str.strip, fle):
            yield np.complex(*map(float, tup.strip("()").split(",")))

You can use the same logic in with genfromtxt:

from itertools import imap

def to_complex(f):
    conv = lambda x: np.complex(*imap(float, x.strip("()").split(",")))
    return np.genfromtxt(f, converters={0: conv})

Comments

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.