How to plot a contour plot (density) of a data file with 3 columns (x, y, density) with the script automatically picking the data array dimension?

huangapple go评论60阅读模式
英文:

How to plot a contour plot (density) of a data file with 3 columns (x, y, density) with the script automatically picking the data array dimension?

问题

我有一个gnuplot脚本用于绘制以下数据的图表:(简化)

第一列是x坐标值,第二列是y坐标,第三列是密度值。
因此,这些数据的图表需要是一个5x5的等高线图。

现在我使用以下gnuplot脚本来绘制这个图表:

它自动选择数据数组的大小,而无需指定,这使得它适用于数据是5x5、128x128或其他尺寸的情况。

我尝试制作一个matplotlib脚本,完全实现这一点,但不是通用的,我必须指定数组的大小。该脚本是:

该Python脚本不具有与gnuplot脚本相同的通用性,我必须指定数组大小为5x5,例如 "reshape(5,5)"。

如何使用matplotlib实现与gnuplot脚本相同的通用性?

英文:

I have a gnuplot script I use for plotting data that is as follows: (simplified)

0 0 1.9
0 1 1.92
0 2 1.93
0 3 1.98
0 4 1.89

1 0 1.8
1 1 1.83
1 2 1.79
1 3 1.8
1 4 1.86

2 0 1.5
2 1 1.6
2 2 1.4
2 3 1.55
2 4 1.62

3 0 1.4
3 1 1.35
3 2 1.36
3 3 1.34
3 4 1.3

4 0 1.1
4 1 1.2
4 2 1.15
4 3 1.05
4 4 1.06

The first column is the x-coordinate value, the second one is the y-coordinate and the third column is the value of the density.
So the plot for this data needs to be a contour plot of 5x5..

Right now I use the following gnuplot script that was given to me to plot this:

reset

set term png size 2048, 2048
set output "n2d.png"
filename = "n2d.dat"   ## electron density ne (x,y)
set cbrange [-1 : 2] 
set size ratio 1
set palette defined (-1 "black", -0.5 "blue", 0 "white", 1 "red", 1.25 "black")
set pm3d map
splot filename notitle
set ticslevel 0

It picks up the data array size automatically without having to specify, which makes it general for whether the data is 5x5 or 128x128 or something else.

I tried to produce a matplotlib script that does exactly this but it is not general, I am having to specify the size of the array. The script is:

import matplotlib
import matplotlib.pyplot as plt
import numpy as np


data = np.loadtxt("n2d.dat", usecols=range(0,3), dtype=np.float32)
datamod = np.transpose( data[:,2].reshape(5,5) ) 
#reshapes the data into a 2D array of 5x5 with all the density values
density = plt.imshow(datamod, cmap='viridis', origin='lower', interpolation='none')
plt.colorbar(density)
plt.savefig("density.png", dpi=300)

The python script does not have the same generality as the gnuplot script, i am having to specify the array size to be 5x5 with "reshape(5,5)".

How do I achieve the same generality as the gnuplot script with matplotlib?

答案1

得分: 1

我认为这个可以实现你想要的:

import matplotlib
import matplotlib.pyplot as plt
import numpy as np

data = np.loadtxt("n2d.dat", usecols=range(0,3), dtype=np.float32)

nx = len(np.unique(data[:,0]))
ny = len(np.unique(data[:,1]))
assert nx*ny == len(data)

datamod = np.transpose(data[:,2].reshape(nx, ny))

# 将数据重塑为5x5的二维数组,带有所有密度值
density = plt.imshow(datamod, cmap='viridis', origin='lower', interpolation='none')
plt.colorbar(density)
plt.savefig("density.png", dpi=300)

注意assert语句:它基本上验证每个(x, y)对是唯一的,也就是说,在输入数据文件中没有重复的坐标(可能具有冲突的值)。可以用以下代码替换这一部分:

if nx * ny != len(data):
    raise ValueError("输入数据中存在非唯一坐标")

因为assert语句通常用于验证在程序控制之外确实不应该发生的事情。这里它用于验证输入数据,这是程序员无法控制的部分。

还有一个棘手的问题是在浮点数上使用unique。只要数据被读取,相等的坐标就应该被视为相等,因为它们对于它们的值来说,在位级上保持相同的表示,因此确实是唯一的值将被唯一计数。如果不是这种情况,assert语句可能会失败。

注:此代码还处理了非正方形的n乘以m数据。如果你知道数据是n乘以n,你可以简化事情,因为你知道n = round(np.sqrt(len(data)))。(四舍五入可能会隐藏非正方形的长度,所以你仍然需要验证n * n == len(data)。)

英文:

I think this can do what you want:

import matplotlib
import matplotlib.pyplot as plt
import numpy as np


data = np.loadtxt("n2d.dat", usecols=range(0,3), dtype=np.float32)

nx = len(np.unique(data[:,0]))
ny = len(np.unique(data[:,1]))
assert nx*ny == len(data)

datamod = np.transpose( data[:,2].reshape(nx, ny) ) 

#reshapes the data into a 2D array of 5x5 with all the density values
density = plt.imshow(datamod, cmap='viridis', origin='lower', interpolation='none')
plt.colorbar(density)
plt.savefig("density.png", dpi=300)

Note the assert statement: it basically verifies that every (x, y) pair is unique, that is, there are no duplicate coordinates (possibly with conflicting values) in the input data file. Arguably, you could replace this with an exception:

if nx * ny != len(data):
    raise ValueError("non-unique coordinates in the input data")

since an assert statement is generally seen as a way to verify that programmatically, something really shouldn't occur. Here, it's used for verification of the input data, which is outside the of the programmers control.

There is also the finicky issue of using unique with floating point numbers. As long as the data is just read in, equal coordinates should be tested equal, since they'll hold the same representation bitwise for their values, and thus unique values will indeed be uniquely counted. If that is not the case, the assert statement is likely to fail.

NB: this case also handles non-square n by m data. If you know the data is n by n, you can make things simpler, because then you know that n = round(np.sqrt(len(data))). (The rounding may hide non-square lengths, so you'd still need to verify that n * n == len(data).)

huangapple
  • 本文由 发表于 2023年4月17日 19:23:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/76034620.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定