Integrals - 11 months ago 51

Python Question

Hi I am trying to make a quiver (vector field) plot from data that is stored in .dat files. I have 4 .dat files which are 1D arrays, one for the x axis, y axis, f(x,y) along x and f(x,y) along y.

Note, I am able to construct a quiver plot without importing data from .dat files, I just followed this basic example here.

However, I am unable to apply this basic example to my example in which I need to import the data from .dat files. My code is below, I am not getting any error messages but I am getting a blank quiver plot. Any help/suggestions would be greatly appreciated, thanks!

`import numpy as np`

import matplotlib.pyplot as plt

n=12

data0 = np.genfromtxt('xaxis.dat')

data1 = np.genfromtxt('yaxis.dat')

data2 = np.genfromtxt('fx.dat')

data3 = np.genfromtxt('fy.dat')

x = data0[0]

y = data1[0]

fx = data2[0]

fy = data3[0]

plt.axes([0.025, 0.025, 0.95, 0.95])

plt.quiver(x,y,fx,fy, alpha=.5)

plt.quiver(x,y,fx,fy,edgecolor='k',facecolor='none', linewidth=.5)

plt.xlim(-1,n)

plt.xticks(())

plt.ylim(-1,n)

plt.yticks(())

plt.show()

Answer Source

In the example for the quiver plot you provided all `X`

, `Y`

, `U`

and `V`

are 2D arrays, with shape `(n,n)`

.

In your example you are importing an array of values for `x`

, `y`

, `fx`

and `fy`

, and then selecting only the first line with `[0]`

.

When using the code:

```
import numpy as np
import matplotlib.pyplot as plt
n=3 # number of points, changed it
data0 = np.genfromtxt('xaxis.dat')
data1 = np.genfromtxt('yaxis.dat')
data2 = np.genfromtxt('fx.dat')
data3 = np.genfromtxt('fy.dat')
x = data0[0]
y = data1[0]
fx = data2[0]
fy = data3[0]
plt.axes([0.025, 0.025, 0.95, 0.95]) # position of bottom left point of graph inside window and its size
plt.quiver(x,y,fx,fy, alpha=.5) # draw inside of arrows, half transparent
plt.quiver(x,y,fx,fy,edgecolor='k',facecolor='none', linewidth=.5) # draw contours of arrows
plt.xlim(-1,n) # left and right most values in the x axis
plt.xticks(()) # remove the numbers from the x axis
plt.ylim(-1,n) # ...
plt.yticks(()) # ...
plt.show()
```

I get:
With `0 1 2 0 1 2 0 1 2`

in xaxis.dat and fx.dat, `0 0 0 1 1 1 2 2 2`

in yaxis.dat and `1 1 1 2 2 2 3 3 3`

in fy.dat.
If I just remove the `[0]`

from the arrays assignment, I get:
with all points shown.

One change I would make is to use `plt.xlim(min(x)-1,max(x)+1)`

and `plt.ylim(min(y)-1,max(y)+1)`

, to ensure you get to view the right area of the graph. For instance, if I make all four arrays equal to `np.random.rand(10)`

(a 1D array with 10 random elements between 0 and 1), I get:

The `plt.quiver`

will also accept the arrays in the format:

```
x = [0, 1, 2] # 1D array (list, actually...)
y = [0, 1, 2]
fx = [[0, 1, 2],
[0, 1, 2],
[0, 1, 2]] # 2D array
fy = [[0, 0, 0],
[1, 1, 1],
[2, 2, 2]]
```

But will not mesh automatically if all arrays are 1D (in which case it will repeat `x`

and `y`

without the correct structure:

```
fx = np.array(fx).flatten()
fy = np.array(fy).flatten()
```

So either have:

```
x = [0, 1, 2, 3]
y = [4, 5, 6]
fx = [[0, 1, 2, 3],
[0, 1, 2, 3],
[0, 1, 2, 3]]
fy = [[4, 4, 4, 4],
[5, 5, 5, 5],
[6, 6, 6, 6]]
```

and let `plt`

do the mesh for you, or have all arrays with the same shape and `plt.quiver`

will get each arrow's position and components from them per index:

```
x = [0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3]
y = [4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6]
fx = [0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3]
fy = [4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6]
```

[first two paragraphs]...

This means you probably noticed `genfromtxt`

returns a 2D array (as it is able to import several columns from a single file, so the returned array will mimic the 2D structure of your file if nothing else is told), making `data0[0]`

the first line on your document xaxis.dat.

**EDIT:** the sentence below is erroneous, plt.quiver can receive 1D arrays, just in the right shape.

However the `quiver`

expects 2D arrays, from where it will retrieve the values for each point: for point `i,j`

the position will be `(X[i,j], Y[i,j])`

and the arrow will be `(U[i,j], V[i,j])`

.

If you have the repeated values for x and y in the file like this:

xaxis.dat:

0, 1, 2, 0, 1, 2, 0, 1, 2

yaxix.dat:

0, 0, 0, 1, 1, 1, 2, 2, 2

You can just reshape all four of your arrays to (# points in x, # points in y) and it should work out.

If you don't you will have to use something similar to `np.mgrid`

(or `np.meshgrid`

) to make a valid combination of `X`

and `Y`

arrays, and format `fx`

and `fy`

accordingly.