Plot3D Data FormatΒΆ

Data format for plot3D comes from this 1990s manual pdf Plot3D is a simple way to construct a structured grid using 4 points to define a cell in 2D and 8 points for 3D.

Plot3D files are organized as follows

 1 8                                   # Number of blocks
 2    5       5       5                # Block 1 is shaped 5x5x5 in i,j,k this is 125 nodes
 3    5       5       5                # Block 2 shape
 4    5       5       5
 5    5       5       5
 6    5       5       5
 7    5       5       5
 8    5       5       5
 9    5       5       5
10 1.08569236018e-07  2.89960779720e-07  2.99150448968e-07  2.55513369907e-07          # First 125 values describe are X, next 25 are Y, last 25 are Z
11 2.12244548714e-07  1.01483086157e-07  2.67218012828e-07  2.71062573276e-07
12 2.24420893535e-07  1.78210401103e-07  7.47886754748e-08  1.93926065872e-07
13 1.84719158858e-07  1.38925249638e-07  1.00523800506e-07  1.71518139691e-08
14 9.37154616132e-08  9.36074304736e-08  5.80944219397e-08  2.00380892990e-08
15 -5.46866818496e-08 -1.24404013757e-08  1.15859071226e-08 -4.76059469623e-09

Knowing this, reading the files is fairly simple to do in python. The following code blocks demonstrate how to read a simple ASCII or binary file. Calling the function read_plot3D(filename:str, binary:bool=True,big_endian:bool=False)

  1import numpy as np
  2import os.path as osp
  3import struct
  4from typing import List
  5from .block import Block
  6
  7def __read_plot3D_chunk_binary(f,IMAX:int,JMAX:int,KMAX:int, big_endian:bool=False):
  8    """Reads and formats a binary chunk of data into a plot3D block
  9
 10    Args:
 11        f (io): file handle
 12        IMAX (int): maximum I index
 13        JMAX (int): maximum J index
 14        KMAX (int): maximum K index
 15        big_endian (bool, Optional): Use big endian format for reading binary files. Defaults False.
 16
 17    Returns:
 18        numpy.ndarray: Plot3D variable either X,Y, or Z
 19    """
 20    A = np.empty(shape=(IMAX, JMAX, KMAX))
 21    for k in range(KMAX):
 22        for j in range(JMAX):
 23            for i in range(IMAX):
 24                A[i,j,k] = struct.unpack(">f",f.read(4))[0] if big_endian else struct.unpack("f",f.read(4))[0]
 25    return A
 26
 27def __read_plot3D_chunk_ASCII(tokenArray:List[str],offset:int,IMAX:int,JMAX:int,KMAX:int):
 28    """Reads an ascii chunk of plot3D data into a block
 29
 30    Args:
 31        tokenArray (List[str]): this is a list of strings separated by a space, new line character removed ["12","22", ... etc]
 32        offset (int): how many entries to skip in the array based on block size (IMAX*JMAX*KMAX) of the previous block
 33        IMAX (int): maximum I index
 34        JMAX (int): maximum J index
 35        KMAX (int): maximum K index
 36
 37    Returns:
 38        numpy.ndarray: Plot3D variable either X,Y, or Z
 39    """
 40    '''Works for ASCII files
 41    '''
 42    A = np.empty(shape=(IMAX, JMAX, KMAX))
 43    for k in range(KMAX):
 44        for j in range(JMAX):
 45            for i in range(IMAX):
 46                A[i,j,k] = tokenArray[offset]
 47                offset+=1
 48
 49    return A, offset
 50
 51def read_plot3D(filename:str, binary:bool=True,big_endian:bool=False):
 52    """Reads a plot3d file and returns Blocks
 53
 54    Args:
 55        filename (str): name of the file to read, .p3d, .xyz, .pdc, .plot3d?
 56        binary (bool, optional): indicates if the file is binary. Defaults to True.
 57        big_endian (bool, optional): use big endian format for reading binary files
 58
 59    Returns:
 60        List[Block]: List of blocks insdie the plot3d file
 61    """
 62
 63    blocks = list()
 64    if osp.isfile(filename):
 65        if binary:
 66            with open(filename,'rb') as f:
 67                nblocks = struct.unpack(">I",f.read(4))[0] if big_endian else struct.unpack("I",f.read(4))[0] # Read bytes
 68                IMAX = list(); JMAX = list(); KMAX = list()
 69                for b in range(nblocks):
 70                    if big_endian:
 71                        IMAX.append(struct.unpack(">I",f.read(4))[0]) # Read bytes
 72                        JMAX.append(struct.unpack(">I",f.read(4))[0]) # Read bytes
 73                        KMAX.append(struct.unpack(">I",f.read(4))[0]) # Read bytes
 74                    else:
 75                        IMAX.append(struct.unpack("I",f.read(4))[0]) # Read bytes
 76                        JMAX.append(struct.unpack("I",f.read(4))[0]) # Read bytes
 77                        KMAX.append(struct.unpack("I",f.read(4))[0]) # Read bytes
 78
 79                for b in range(nblocks):
 80                    X = __read_plot3D_chunk_binary(f,IMAX[b],JMAX[b],KMAX[b], big_endian)
 81                    Y = __read_plot3D_chunk_binary(f,IMAX[b],JMAX[b],KMAX[b], big_endian)
 82                    Z = __read_plot3D_chunk_binary(f,IMAX[b],JMAX[b],KMAX[b], big_endian)
 83                    b_temp = Block(X,Y,Z)
 84                    blocks.append(b_temp)
 85        else:
 86            with open(filename,'r') as f:
 87                nblocks = int(f.readline())
 88                IMAX = list(); JMAX = list(); KMAX = list()
 89
 90                for b in range(nblocks):
 91                    tokens = [int(w.replace('\n','')) for w in f.readline().split(' ') if w]
 92                    IMAX.append(tokens[0])
 93                    JMAX.append(tokens[1])
 94                    KMAX.append(tokens[2])
 95
 96                lines = [l.replace('\n','').split(' ') for l in f.readlines()] # Basically an array of strings representing numbers
 97                lines = [item for sublist in lines for item in sublist]         # Flatten list of lists https://stackabuse.com/python-how-to-flatten-list-of-lists/
 98
 99                tokenArray = [float(entry) for entry in lines if entry] # Convert everything to float
100                offset = 0
101                for b in range(nblocks):
102                    X, offset = __read_plot3D_chunk_ASCII(tokenArray,offset,IMAX[b],JMAX[b],KMAX[b])
103                    Y, offset = __read_plot3D_chunk_ASCII(tokenArray,offset,IMAX[b],JMAX[b],KMAX[b])
104                    Z, offset = __read_plot3D_chunk_ASCII(tokenArray,offset,IMAX[b],JMAX[b],KMAX[b])
105                    b_temp = Block(X,Y,Z)
106                    blocks.append(b_temp)
107    return blocks