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