durden2.0
durden2.0

Reputation: 9552

Proper way to read/write fortran order array with numpy

I'm writing an application that reads an ascii file with fortran-ordered arrays, modifies values, then writes that data back out (in fortran order) in ascii. What is the correct way to read this array into numpy, denote the array is in fortran order, then write the data back out in fortran order?

Assume I have a file with the following ascii text:

0.0 1.0 2.0 3.0 4.0 5.0 6.0 7.0

These numbers represent a 2x2x2 array written in fortran order.

The ascii format is a bit more complicated than above. However, suffice it to say the format is not really well suited for using any of the automatic numpy ascii loaders like numpy.loadtxt, etc.

I'm executing a line similar to the following to create the array:

x = numpy.array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0], order='F')

I know this is in-efficient and does a lot of extra data copying, etc. I'm more worried about the ordering though.

So, at this point x is ordered in memory like a fortran array, I think. Now, when I export this array should I use numpy.nditer(x, order='F')?

Upvotes: 3

Views: 3279

Answers (2)

Sven
Sven

Reputation: 995

Here is what works. The transposition works around the fact that numpy tofile() only knows C order.

import numpy as np
file_path = 'C:/Temp/arr.txt'
x = np.array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0])
xf = x.reshape((2, 2, 2), order='F')
xf.T.tofile(file_path, sep=' ') # T is transpose, so it gets written in correct order
xn = np.fromfile(file_path, sep=' ')
xnr = np.reshape(xn, (2,2,2),order='F')
assert (xf==xnr).all()

# show the transpose is necessary
xf.tofile(file_path, sep=' ') # no .T, write in wrong order
xn = np.fromfile(file_path, sep=' ')
xnr = np.reshape(xn, (2,2,2),order='F')
assert (xf==xnr).all()==False

Upvotes: 1

NPE
NPE

Reputation: 500943

Consider the following:

In [11]: x = numpy.array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0])

In [12]: xf = x.reshape((2, 2, 2), order='F')

Here, xf is a 2x2x2 Fortran-ordered view onto x. You could modify it and x will change accordingly:

In [22]: xf[0,:,1] = [11, 12]

In [23]: x
Out[23]: array([  0.,   1.,   2.,   3.,  11.,   5.,  12.,   7.])

Exporting x would preserve the original ordering.

Upvotes: 1

Related Questions