将 Tecplot ascii 转换为 Python numpy

Convert Tecplot ascii to Python numpy

我想将一个 Tecplot 文件转换成一个数组,但我不知道该怎么做。 这是文件的摘录:

TITLE = "Test"
VARIABLES = "x" "y"
ZONE I=18,  F=BLOCK
0.1294538E-01  0.1299554E-01  0.1303974E-01  0.1311453E-01  0.1313446E-01  0.1319080E-01
0.1322709E-01  0.1323904E-01  0.1331753E-01  0.1335821E-01  0.1340850E-01  0.1347061E-01
0.1350522E-01  0.1358302E-01  0.1359585E-01  0.1363086E-01  0.1368307E-01  0.1370017E-01
0.1377368E-01  0.1381353E-01  0.1386420E-01  0.1391916E-01  0.1395847E-01  0.1400548E-01
0.1405659E-01  0.1410006E-01  0.1417611E-01  0.1419149E-01  0.1420015E-01  0.1428019E-01
0.1434745E-01  0.1436735E-01  0.1439856E-01  0.1445430E-01  0.1448778E-01  0.1454278E-01

我想检索 xy 作为数组。所以 x 应该包含:

0.1294538E-01  0.1299554E-01  0.1303974E-01  0.1311453E-01  0.1313446E-01  0.1319080E-01
0.1322709E-01  0.1323904E-01  0.1331753E-01  0.1335821E-01  0.1340850E-01  0.1347061E-01
0.1350522E-01  0.1358302E-01  0.1359585E-01  0.1363086E-01  0.1368307E-01  0.1370017E-01

并且y应该包含:

0.1377368E-01  0.1381353E-01  0.1386420E-01  0.1391916E-01  0.1395847E-01  0.1400548E-01
0.1405659E-01  0.1410006E-01  0.1417611E-01  0.1419149E-01  0.1420015E-01  0.1428019E-01
0.1434745E-01  0.1436735E-01  0.1439856E-01  0.1445430E-01  0.1448778E-01  0.1454278E-01

我看过 np.loadtxt('./file.dat', skiprows=3) 但我找不到正确的选项来说读取所有数字并每 18 个数字分开。

此外,我开始这样的事情并不走运:

with open(file, 'r') as a:
    for line in a.readlines():
        A = re.match(r'TITLE = (.*$)', line, re.M | re.I)
        B = re.match(r'VARIABLES = (.*$)', line, re.M | re.I)
        C = re.match(r'ZONE (.*$)', line, re.M | re.I)
        if A or B or C:
                continue
        else:
            D = re.match(r'(.*$)', line, re.M | re.I)
            value = "{:.16}".format(D.group(1))
            y.append(float(value))
            j = j+1
            if j == 18:
                j = 0

感谢您的帮助!

用最后一个选项解决了它:

arrays = []
with open(file, 'r') as a:
    for line in a.readlines():
        A = re.match(r'TITLE = (.*$)', line, re.M | re.I)
        B = re.match(r'VARIABLES = (.*$)', line, re.M | re.I)
        C = re.match(r'ZONE (.*$)', line, re.M | re.I)
        if A or B or C:
                continue
        else:
            arrays.append([float(s) for s in line.split()])
arrays = np.concatenate(arrays)

len_var = len(arrays)
x = arrays[0:len_var/2-1]
y = arrays[len_var/2:len_var]

这个答案对数组的创建有很大帮助: and also this one for traveling the array: 。但最后使用 np.concatenate 似乎更好。

郑重声明,我创建这个函数是为了读取任何文件:

def tecplot_reader(file, nb_var):
    """Tecplot reader."""
    arrays = []
    with open(file, 'r') as a:
        for idx, line in enumerate(a.readlines()):
            if idx < 3:
                continue
            else:
                arrays.append([float(s) for s in line.split()])

    arrays = np.concatenate(arrays)
    output = np.split(arrays, nb_var)

    return output

所以就这样做:x, y, z = tecplot_reader('./file', 3)

这可能对其他人有用,所以我将 post 放在这里。我修改了@Y0da的代码,让他的函数可以一次性输出多个检测器的结果。也就是说,您有一个

形式的 tecplot 文件
 Title="test"
 Variables = "var1", "var2", "var3" ,
 "var4","var5"
 Zone T ="Detector =           1 "
  0.000000000000000E+000  0.000000000000000E+000  0.000000000000000E+000
  0.000000000000000E+000  0.000000000000000E+000
   50.0000000000000       0.000000000000000E+000  0.000000000000000E+000
  0.000000000000000E+000  0.000000000000000E+000

 Zone T ="Detector =           2 "
  0.000000000000000E+000  0.000000000000000E+000  0.000000000000000E+000
  0.000000000000000E+000  0.000000000000000E+000
   50.0000000000000       0.000000000000000E+000  0.000000000000000E+000
  0.000000000000000E+000  0.000000000000000E+000

请注意,格式是故意丑陋的。这是因为如果您的输出来自 FORTRAN 代码,并且您写入的文件没有明确的格式,则使用的列数是有限的。

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

path = 'path_to_file/file.plt'

def tecplot_reader(file, nb_var):
    """Tecplot reader for multiple detectors"""
    detectors = []
    with open(file, 'r') as a:
        lines = a.readlines()
        for idx, line in enumerate(lines):
            if (idx <= 3) : continue                        # If this is header line skip
            detec = re.match(r' ZONE (.*$)', line, re.M | re.I) # Determine if this is a new detector line
            if (type(detec)!=type(None)):                       # If this is a new detector line
                detector = int(line[20:-3])-1               # The detector index is between column 30 and -3 characters (counting starts at 1 for the output file)
                detectors.append([])                        # Add a new list for this detector
                continue
            else:
                detectors[detector].append([float(s) for s in line.split()])

    for i,detec in enumerate(detectors):    # For each detector
        detectors[i] = np.concatenate(np.array(detec))                            # Concatinate into one array
        detectors[i] = np.split(np.array(detectors[i]),len(detectors[i])/nb_var)  # Break into correct rows (each row has nb_vars)
        detectors[i] = np.hsplit(np.array(detectors[i]),nb_var)                   # Break up vertically
    return detectors

这个 returns 是每个检测器的变量列表。