AJMR-Python-Baird/Mustique/adcptool/adcpimport.py

199 lines
5.3 KiB
Python

import sys
sys.dont_write_bytecode = True
import datetime
from adcptool.vector import Vector
#
# some 'constant' values that might be needed
bad_velocity = -32768
bad_discharge = 2147483647
bad_latlong = 30000
#
# handy functions
def line_as_list(f):
''' returns a list from the next line of the given file object '''
return f.pop(0).rstrip('\n').split()
def readnextline(f):
pass
def print_type(o):
print(type(o).__name__)
class RawProfileObj:
'''holds general data and all the ensembles'''
def __init__(self, filename):
self.ensembles = []
# python 3.x vs 2.x
try:
self.f = open(filename,'rt', encoding='latin-1').read().split('\n')
except TypeError:
self.f = open(filename,'rt').read().split('\n')
#
# general header stuff
# read something to get warm with python
self.note1 = self.f.pop(0)
self.note2 = self.f.pop(0)
l = line_as_list(self.f)
self.depth_cell_length = float(l[0])
self.number_of_depth_cells = l[3]
#
# add the ensembles
i = 0
while True:
#print('adding ensemble no',i)
self.ensembles.append(EnsembleObj(self.f, self.note1))
self.f = self.ensembles[i].f
if len(self.f) <= 1:
del self.f
break;
i += 1
def __getstate__(self):
# Copy the object's state from self.__dict__ which contains
# all our instance attributes. Always use the dict.copy()
# method to avoid modifying the original state.
state = self.__dict__.copy()
# Remove the unpickabel entries.
#del state['f']
return state
class EnsembleObj:
'''
holds an ensemble (set of different measurements on the same
(river surface) position
'''
def __init__(self, f, note1):
self.f = f
self.cells = []
#
# ensemble header stuff
firstline = self.f.pop(0)
# test if this line is actually what we want
if firstline == note1 or len(firstline) == 0:
exit('error: it looks like there are multiple transsects (profiles) in one ASCII file! (or there is an empty line in it which should never happen)')
else:
l = firstline.rstrip('\n').split()
time = [int(i) for i in l[0:7]]
time[0] += 2000 # in the source, they start counting in year 2000
time[6] *= 10000 # 1/100 seconds to microseconds
# compile time to python time format
self.ens_time = datetime.datetime(time[0], time[1], time[2], time[3], time[4], time[5], time[6])
self.ens_number = int(l[7])
self.corrected_heading = float(l[12])
# line "2"
l = line_as_list(self.f)
self.depth_reading = [float(i) for i in l[8:12]]
# line "3"
l = line_as_list(self.f)
self.total_elapsed_distance = float(l[0])
self.total_elapsed_time = float(l[1])
self.total_distance_traveled_north = float(l[2])
self.total_distance_traveled_east = float(l[3])
self.total_distance_made_good = float(l[4])
# skip line "4"
l = line_as_list(self.f)
self.lat = float(l[0])
self.lon = float(l[1])
# skip line "5"
l = line_as_list(self.f)
# line "6"
l = line_as_list(self.f)
self.measurement_units = l[1] # the units only apply to the velocity apparently
self.number_of_cells = int(l[0])
self.number_of_good_cells = 0
#
# add the bins/cells
for i in range(self.number_of_cells):
i = len(self.cells)
self.cells.append(CellObj(self.f))
self.f = self.cells[i].f
if self.cells[i].cell_is_good:
self.number_of_good_cells += 1
else:
# remove broken cells again
self.cells.pop()
def __getstate__(self):
# Copy the object's state from self.__dict__ which contains
# all our instance attributes. Always use the dict.copy()
# method to avoid modifying the original state.
state = self.__dict__.copy()
# Remove the unpicklable entries.
#del state['f']
return state
class CellObj:
''' holds the actual measured data '''
def __init__(self, f):
self.f = f
l = line_as_list(self.f)
if float(l[1]) != -32768:
self.cell_is_good = True
self.depth = float(l[0])
self.velocity_magn = float(l[1])
self.velocity_dir = float(l[2])
self.velocity_comp = Vector([float(i) for i in l[3:6]])
self.velocity_error = float(l[6])
self.percent_good = float(l[11])
else:
self.cell_is_good = False
def __getstate__(self):
# allows the class to be pickled
state = self.__dict__.copy()
# Remove the unpicklable entries.
#del state['f']
return state