将Tecplot ascii转换为Python numpy

时间:2016-08-17 16:28:01

标签: python numpy io converter

我想将 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

感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

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

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]

这个答案对于创建数组有很大的帮助:https://stackoverflow.com/a/4289557/6522112以及用于传播数组的这个:https://stackoverflow.com/a/952952/6522112。但最终使用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)

答案 1 :(得分:0)

这可能对其他人有用,所以我会在这里发布。我修改了@ 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

返回的是每个探测器的变量列表。