I have a large text file (~2GB) full of data. The data (sample below) gives an x, y, z coordinate, and a corresponding result on each line (there is other stuff but I don't care about it). The single large text file is too large to be useful, so I want to split it into several smaller files. However, I want each file to contain all the points on one y-plane. The first few lines of the file are below:
mcnp version 6 ld=05/08/13 probid = 09/09/15 23:06:39
Detector Test
Number of histories used for normalizing tallies = 2237295223.00
Mesh Tally Number 14
photon mesh tally.
Tally bin boundaries:
X direction: -600.00 -598.00 -596.00 ... 1236.00 1238.00 1240.00 1242.00 1244.00 1258.00 1260.00
Y direction: 0.00 10.00 20.00 ... 740.00 750.00 760.00 770.00 780.00 790.00 800.00 810.00 820.00 830.00 840.00 850.00 860.00
Z direction: -60.00 -58.00 -56.00 ... 592.00 594.00 596.00 598.00 600.00
Energy bin boundaries: 1.00E-03 1.00E+36
Energy X Y Z Result Rel Error Volume Rslt * Vol
1.000E+36 -599.000 5.000 -59.000 0.00000E+00 0.00000E+00 4.00000E+01 0.00000E+00
1.000E+36 -599.000 5.000 -57.000 0.00000E+00 0.00000E+00 4.00000E+01 0.00000E+00
1.000E+36 -599.000 5.000 -55.000 0.00000E+00 0.00000E+00 4.00000E+01 0.00000E+00
... and repeat forever...
I've truncated some of it for readability, but you get the idea. The data I want is the four last lines.
The code currently does the following:
- Find the line data headers (
Energy X Y ...
) - Find the y value of the first line of data
- Add the data to a list until we find data with a different y value
- Dump the list to a file named with the y value, delete the list
- Repeat steps 3 and 4 until the end of the file.
Not all the data for each y plane is together, so if I encounter data at a y-value I've seen before, the data is appended to an existing file.
My code is below, it functions, but I feel like I could improve efficiency somewhere (execution took ~30 min). As always, readability/style improvements are welcome, but performance is the primary goal.
import os
with open("meshtal", 'r') as f:
i = 0
coords = []
curY = 0
for l in f:
#If data header already found
if i:
line = l.split()
#If this is the first line of data
if i == 1:
curY = line[2]
coords.extend([(line[1],line[2],line[3],line[4])])
i += 1
else:
#If data has the same y value as previous
if curY == line[2]:
coords.extend([(line[1],line[2],line[3],line[4])])
i += 1
#New y value, dump existing data to file
else:
fname = "Y={}.txt".format(curY)
#if y value has already been encountered, append existing file
if os.path.exists(fname):
with open("Y={}.txt".format(curY), 'a') as out:
for coord in coords:
out.write("{:10}{:10}{:10}{:10}\n".format(*coord))
#New y value, create new file
else:
with open("Y={}.txt".format(curY), 'w') as out:
out.write("X Y Z Result \n")
for coord in coords:
out.write("{:10}{:10}{:10}{:10}\n".format(*coord))
i = 1
coords = []
curY = line[2]
coords.extend([(line[1],line[2],line[3],line[4])])
i += 1
#If no data header has been found
else:
#If current line is data header, raise flag
if l.lstrip().startswith("Energy X Y Z Result Rel Error Volume Rslt * Vol"):
i += 1
print "found start"