How do I interpret the .dat file to use some values as input?

Question:

I developed a code to interpret airfoil .dat files, in which I use one file at a time and do some mathematical operations.

Currrently, I define three values at the beginning of the code: the chord, the alpha (angle of attack), and the z-translation. Then I use those values to perform operations on a long series of data points read from the file. However, rather than hard coding the chord and alpha, I would like to read them from the first two lines of the .dat file. Once the inputs are used, I would like to save only the list of (modified) points to a new .dat file, discarding the parameters from the beginning of the original file.

I have attached my code and the .dat file I want to create. The idea is to use the two initial lines as input to use in math operations and save in the New.dat file with only the modified points.

import math


chord = 1.138
alpha = -3.427960
z_trans = -0.25*chord


with open('Airfoils/ffaw3241.dat') as data:
    mylist = [line.rstrip('n') for line in data]    
zs = []
ys = []
for line in mylist:
         if len(line) > 1:
                z, y = line.split(None, 2)
                zs.append(float(z))
                ys.append(float(y))
data = tuple(zip(zs, ys))
print(chord)
#Scale the foil with provided chord

zs = []
ys = []
for point in data:
    z, y = point
    zs.append(float(z)*chord)
    ys.append(float(y)*chord)
        
data = tuple(zip(zs, ys))
#print (data) 


#rotate the airfoil with provided alpha

oz, oy = (0, 0)
        
zs = []
ys = []
for point in data:
            z, y = point
            zs.append(oz + math.cos(math.radians(alpha)) * (float(z) - oz) - math.sin(math.radians(alpha)) * (float(y) - oy))
            ys.append(oy + math.sin(math.radians(alpha)) * (float(z) - oz) + math.cos(math.radians(alpha)) * (float(y) - oy))
            
data = tuple(zip(zs, ys))

#translate the airfoil to the center of pressure (25% of chord) 
zs = []
ys = []
for point in data:
    z, y = point
    zs.append(round (float(z),5) + z_trans)
    #ys.append(round (float(y),5) + y_trans)
            
data = tuple(zip(zs, ys))

with open("Airfoils/ffaw3241New.dat", "w") as output:
    output.write(str(data))
1.138 #chord
-3.427960 #alpha
1.00000   -0.00360
0.98338   -0.00140
0.96457   0.00096
0.94365   0.00311
0.92072   0.00466
0.89589   0.00528
0.86928   0.00473
0.84102   0.00291
0.81124   -0.00030
0.78010   -0.00514
0.74772   -0.01183
0.71428   -0.02024
0.67994   -0.03015
0.64485   -0.04127
0.60918   -0.05308
0.57311   -0.06502
0.53681   -0.07651
0.50045   -0.08706
0.46422   -0.09623
0.42827   -0.10370
0.39279   -0.10938
0.35794   -0.11324
0.32389   -0.11531
0.29081   -0.11567
0.25885   -0.11441
0.22817   -0.11167
0.19891   -0.10754
0.17121   -0.10213
0.14522   -0.09560
0.12104   -0.08811
0.09880   -0.07985
0.07861   -0.07104
0.06056   -0.06188
0.04474   -0.05258
0.03122   -0.04334
0.02006   -0.03427
0.01133   -0.02550
0.00507   -0.01700
0.00130   -0.00903
0.00000   0.00000
0.00130   0.00956
0.00507   0.02005
0.01133   0.03033
0.02006   0.04087
0.03122   0.05135
0.04474   0.06170
0.06056   0.07176
0.07861   0.08139
0.09880   0.09044
0.12104   0.09873
0.14522   0.10613
0.17121   0.11247
0.19891   0.11764
0.22817   0.12153
0.25885   0.12409
0.29081   0.12526
0.32389   0.12504
0.35794   0.12350
0.39279   0.12076
0.42827   0.11696
0.46422   0.11223
0.50045   0.10670
0.53681   0.10052
0.57311   0.09382
0.60918   0.08672
0.64485   0.07935
0.67994   0.07187
0.71428   0.06441
0.74772   0.05707
0.78010   0.04996
0.81124   0.04316
0.84102   0.03673
0.86928   0.03070
0.89589   0.02510
0.92072   0.01996
0.94365   0.01529
0.96457   0.01107
0.98338   0.00727
1.00000   0.00391
Asked By: awgomes

||

Answers:

You can use the next function to "manually" consume the next item from a generator, such as a file. This is a handy way to grab the first (or in this case, first two) items before iterating through the rest. Here’s a fairly simple way to do it, based on your code:

with open('input.dat') as file:
    chord = next(file).split()[0]
    alpha = next(file).split()[0]
    data = []
    for line in file:
        line = line.split()
        z = float(line[0])
        y = float(line[1])
        data.append((z, y))

This could be further condensed with a couple of list comprehensions (okay, technically one list comprehension and one generator expression):

with open('input.dat') as file:
    chord = next(file).split()[0]
    alpha = next(file).split()[0]
    data = [tuple(float(i) for i in line.split()) for line in file]

Personally I think this is a case where I’d use map for the float conversion, but tastes differ. map is handy when all you want to do to multiple things is apply the same function to all of them.

with open('input.dat') as file:
    chord = next(file).split()[0]
    alpha = next(file).split()[0]
    data = [tuple(map(float, line.split())) for line in file]

Notes:

  • All these produce a list of tuples, rather than a tuple of tuples as in your code. It could be easily converted, but I think this makes more sense.
  • There’s no need to first strip newlines if you’re also going to use split(), since that automatically removes any trailing whitespace.
  • If your file may contain blank (newline-only) lines, you can add if not line.isspace() at the end of the list comprehension to skip those.
Answered By: CrazyChucky
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.