简体   繁体   中英

3d surface plot genfromtxt

I was facing a problem in plotting a 3d surface plot by reading a text file. The problem is, I am using a different datatypes, like float, int and string.. I have attached the code with the sample data to be parsed.. I would appreciate with any comments with the code to make it functional...

The error which I got now is ValueError: size of tuple must match number of fields.

Thnx in advance....

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from numpy import genfromtxt
fig = plt.figure(figsize=(12,12))
ax = fig.add_subplot(111, projection='3d') #ax = Axes3D(fig) 
ax.set_title("Plot 3d",fontsize=14)
ax.set_xlabel('Voltage (V)', fontsize=12)
ax.set_ylabel('Pulse Delay(ms)', fontsize=12)
ax.set_zlabel('Pulse Width(ms)', fontsize=12)
ax.grid(True, linestyle='-', color='0.75')
x,y,z,m =genfromtxt('sample.txt', dtype=[('col1', 'f15'), ('col2', 'i15'), ('col3',   'i15'), ('col4', 'S15')],  unpack=True)

use_colours = []
for tmp in m:
    if tmp=='PASS':
        use_colours.append('g')
    else:
        use_colours.append('r')

ax.scatter(x,y,z, s=50, c=use_colours, marker = 'o', linewidths=0);
plt.show()



sample.txt

6.000000    15.000000   21.000000   PASS
6.000000    15.000000   53.000000   PASS
6.000000    15.000000   91.000000   PASS
6.000000    15.000000   104.000000  PASS

While trying to execute your code, I have discovered some misuse that is difficult to prevent without knowing the correct functioning of matplotlib libraries.

Here is a commented code that works:

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
fig = plt.figure(figsize=(12, 12))

ax = Axes3D(fig) # ax = fig.add_subplot(111, projection='3d')
ax.set_title("Plot 3d",fontsize=14)
ax.set_xlabel('Voltage (V)', fontsize=12)
ax.set_ylabel('Pulse Delay(ms)', fontsize=12)
ax.set_zlabel('Pulse Width(ms)', fontsize=12)
ax.grid(True, linestyle='-', color='0.75')

# 'i15' and 'f15' are not known as numerical types.
# You can use only 'i8' (np.int64) and 'f16' (np.float128) or 'f8' (np.float64).
# 'f16' seems not to be recognized as a valid type for the scatter library.
# I think that 'f8' and 'i8' are quoit enough.
data = np.genfromtxt('./sample.txt', dtype=[('col1', 'f8'), ('col2', 'i8'), ('col3',   'i8'), ('col4', 'S15')])

# scatter does not take for the c option a list of colours such as ['g', 'g', 'r', ...].
# In this case, we will define data for each colour, not a color for each scatter point.
m = data["col4"]
data1 = data[m == "PASS"]
data2 = data[m != "PASS"]

for dat, color in [(data1, 'g'), (data2, 'r')]:
    # Don't forget that having empty data columns may raise exceptions ...
    try:
        x, y, z = dat['col1'], dat['col2'], dat['col3']
        ax.scatter(xs=x, ys=y, zs=z, s=50, c=color, marker='o', linewidths=0)
    except:
        pass

plt.show()

The error code you are getting suggests that at some point you are passing in information that does not fit the variables. This appears to be coming from the unpack=true flag in your genfromtxt call. Looking at some of the docs regarding genfromtxt it appears that using the unpack=True flag will result in "the returned array is transposed, so that arguments may be unpacked using x, y, z = loadtxt(...)" which, ultimatly is resulting in your x, y, z and m values looking like:

x = (6.0, 15, 21, 'PASS') 
y = (6.0, 15, 53, 'PASS') 
z = (6.0, 15, 91, 'PASS')
m = (6.0, 15, 104, 'PASS')

These values will not work with what you have in your code obviously. Interestingly this only works if you have 4 lines in your sample.txt and are trying to unpack 4 variables.

A solution to this is to not flag unpack=true. Instead something like this should work:

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np

## takes a matrix and a column index, returns a list of the values
## in that column
def column(matrix, i):
    return [row[i] for row in matrix]

fig = plt.figure(figsize=(12,12))
ax = fig.add_subplot(111, projection='3d') #ax = Axes3D(fig) 
ax.set_title("Plot 3d",fontsize=14)
ax.set_xlabel('Voltage (V)', fontsize=12)
ax.set_ylabel('Pulse Delay(ms)', fontsize=12)
ax.set_zlabel('Pulse Width(ms)', fontsize=12)
ax.grid(True, linestyle='-', color='0.75')

## Your original call
#x,y,z,m =genfromtxt('sample.txt', delimiter="""", dtype=[('col1', 'f15'),
##('col2','i15'), ('col3',   'i15'), ('col4', 'S15')],  unpack=True)

## The modified call
data = np.genfromtxt('sample.txt', 
                     delimiter='\t', 
                     usecols=(0,1,2,3),
                     dtype=[('col1', 'f15'), 
                           ('col2', 'i15'), 
                           ('col3', 'i15'), 
                           ('col4', 'S15')])

## split the data so that each column in the 2d array ends up in a variable.
## There is a numpy way of doing this, you should look into that
x = column(data, 0)
y = column(data, 1)
z = column(data, 2)
m = column(data, 3)

use_colours = []
for tmp in m:
    if tmp=='PASS':
        use_colours.append('g')
    else:
        use_colours.append('r')

## Let's make sure the values look like we expect:
print x
print "\n"
print y
print "\n"
print z
print "\n"
print m

ax.scatter(x,y,z, s=50, c=use_colours, marker = 'o', linewidths=0);
plt.show()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM