I have a C code that computes some physical variable on a 2D space (e.g. x-velocity "u" and y-velocity "v", where "u" and "v" are functions of spacial coordinates "x" and "y" : "u=u(x,y)" and "v=v(x,y)").

It then exports the results in a binary file (data type is "double"). I then open the data file with a python script so that I can make some post-processing and plot the data using matplotlib.

As you know there are two ways to scan a 2D array :

  • either you first select a line and scan each cell inside the line
  • or you do exactly the opposite : first select a column and scan each cell in the column

Obviously, I face an issue where the direction in which the array is saved by my C code is different from the direction the array is read by my python script.

The C file uses the fwrite() function, and I want to keep it as it is.

fwrite(vect , sizeof(double), nbcols*nbrows, file);

The python file uses the struct module to unpack the array :

unpackFormat = '%dd' % nDim
zx = np.array([struct.unpack(unpackFormat,f.read())]).reshape(v.N,v.M)

In my particular case, I can find a workaround but it is ugly and might not work in all situations. So here's my question : is there any way to unpack the array so that it is scanned in the other direction than the default one ?

My array only contains doubles, and if I understand properly, array.fromfile can handle that kind of situations, so if you happen to know the answer for array.fromfile, feel free to share it !


Extra information on my particular case

In the following, I include more details that are specific to my problem, though what I have just expressed should be enough for you to understand my problem. Note : there is going to be some numpy+matplolib in the following, even though my problem is related to the struct module more than it is related to matplotlib.

What I want is to do is a quiver plot of a velocity field. This means I want to plot a "field of arrows" as in [here][1] where an arrow on point (x,y) corresponds to the vector (u(x,y),v(x,y)). Here is the interesting part of my script :

# gen x,y coordinates
y, x = np.mgrid[0:1:complex(0,v.N),
                0:1:complex(0,v.M)]

# load data for the x-direction
f = open(filePathX, 'rb')
unpackFormat = '%dd' % nDim
zx = np.array([struct.unpack(unpackFormat,f.read())]).reshape(v.N,v.M)
f.close()

# load data for the y-direction
f = open(filePathY, 'rb')
unpackFormat = '%dd' % nDim
zy = np.array([struct.unpack(unpackFormat,f.read())]).reshape(v.N,v.M)
f.close()

# plotting
plt.quiver(x[::10,::10], y[::10,::10], zx[::10,::10], zy[::10,::10])

With this script, the plot is not well plotted : it is as if the x and y coordinates of the output vectors zx and zy had been swapped. In other words, each arrow corresponds to vector (v,u) instead of vector (u,v). I attribute this to struct.unpack reading the array in the other direction that the one I would have hoped for.

In my particular case, I was hopping for a rotating velocity field, but instead the arrows point either inwards or outwards on the X and Y axes.

Important precision : Matplotlib does no allow me to swap x and y arrays.

A work around is to do the following :

plt.quiver(x[::10,::10], y[::10,::10], -zy[::10,::10], -zx[::10,::10])

But I do not like this way of doing things, so I am hoping for you to suggest a better way to fix my issue

Thanks in advance !

有帮助吗?

解决方案

Silly me just found the answer :

use :

zx = np.array([struct.unpack(unpackFormat,f.read())]).reshape(v.N,v.M,order='F')

instead of :

zx = np.array([struct.unpack(unpackFormat,f.read())]).reshape(v.N,v.M)

Doing so changes the way the array is read. Actually the problem did not come from struct.unpack but from np.array.reshape. The latter has an optional argument to set the scanning direction. Here I chose the F option for "fortran" scanning convention (even though my data was saved by a C code) instead of the default C value (for C scanning convention).

I suppose I must have stored the arrays in an odd fashion from the start in my C code and therefore I need to read them in an unconventional way. Still bothers me, but at least it the script looks clean.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top