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 21 Answer
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.