import adcptool.adcpimport #@UnusedImport (actually used in the eval() parts) import adcptool.outliers #@UnusedImport class DataClass(): ''' a class to store and manage all the ADCP data in this tool. automatic retrieval and updating included. ''' def __init__(self, parent=0): # method register (pretty unpythonic) self.methreg = dict( rawprofile='adcptool.adcpimport.RawProfileObj(self.cfg["rawprofile"])', cellmatrix='adcptool.outliers.get_cell_matrix(self.rawprofile)', valuematrix='adcptool.outliers.get_valuematrix_from_cellmatrix(self.cellmatrix, self.cfg["valuematrix"], 1)', goodvaluematrix='adcptool.outliers.get_valuematrix_from_cellmatrix(self.cellmatrix, self.cfg["valuematrix"], 2)', relatdev='adcptool.outliers.get_relative_deviation_simple(self.valuematrix, self.goodvaluematrix, self.cfg["relatdev"])', outliermatrix='adcptool.outliers.get_outliers(self.relatdev, self.goodvaluematrix, self.cfg["outliermatrix"])' ) self.depencies = { 'rawprofile':[], 'cellmatrix':['rawprofile'], 'valuematrix':['cellmatrix'], 'goodvaluematrix':['cellmatrix'], 'relatdev':['valuematrix', 'goodvaluematrix'], 'outliermatrix':['relatdev'] } # # populate dicts from methreg self.data = dict(list(zip(list(self.methreg.keys()), [None] * len(self.methreg)))) # hold the actual data self.cfg = dict(list(zip(list(self.methreg.keys()), [None] * len(self.methreg)))) # stores the public cfg self.cfg_saved = dict(list(zip(list(self.methreg.keys()), [None] * len(self.methreg)))) # store private cfg (the one that has been used for creating data) self.testa = dict(list(zip(list(self.methreg.keys()), [None] * len(self.methreg)))) # store private cfg (the one that has been used for creating data) self.testb = dict(list(zip(list(self.methreg.keys()), [None] * len(self.methreg)))) # store private cfg (the one that has been used for creating data) def __getattr__(self, m): ''' this is called to retrieve an arbitrary attribute. they have to be named like in the self.methreg in order to work ''' # print '-----------------------------------' # print('a:{}, b:{}'.format(self.testa['rawprofile'], self.testb['rawprofile'])) # self.testa['rawprofile'] = 'foobar' # print '-----------------------------------' # print('a:{}, b:{}'.format(self.testa['rawprofile'], self.testb['rawprofile'])) # print('DBG: DataClass(): {} * requested.'.format(m)) # print('DBG: DataClass(): OLD config:') # self.print_cfg( self.cfg_saved[m]) # print('DBG: DataClass(): NEW config:') # self.print_cfg( self.cfg[m]) # print '-----------------------------------' if self.data[m] == None or self.cfg[m] != self.cfg_saved[m] or self.depcheck(m): # if needed: create the data (again) # print('DBG: DataClass(): {} + updating.'.format(m)) if type(self.cfg[m]) == type(dict()): self.cfg_saved[m] = self.cfg[m].copy() else: self.cfg_saved[m] = self.cfg[m] self.data[m] = eval(self.methreg[m]) # print m, type(self.data[m]), type(self.cfg[m]), type(self.cfg_saved[m]) return self.data[m] def print_cfg(self, x): ''' a debug function that prints out the config dictionary nicely ''' print(x) def depcheck(self, m): ''' somehow make the dependency chekcing ''' for dep in self.depencies[m]: # print('depcheck: {}:{}'.format(m, dep)) if self.cfg[dep] != self.cfg_saved[dep]: # print('depcheck: {}:{}: cfg has changed'.format(m, dep)) return True else: return self.depcheck(dep) def get_guicfg(tk): ''' return an empty dictionary that contains the structure that hold the Tk/Variables. unfortunately this is not the same structure as the "real data structure" which is based on the method names in DataClass() ''' guicfg = dict( inputfile = tk.StringVar(), outliers = dict( enabled=tk.BooleanVar(), radius_h=tk.IntVar(), radius_v=tk.IntVar(), limit=tk.StringVar() ) ) return guicfg def gui2cfg(guicfg, cfg, module=False): ''' read field variables from the GUI and write it into cfg. depending on module, it either writes all or only the specified module ''' # if module: # for key in guicfg[module].keys(): # if not hasattr(guicfg[module][key], 'get'): # cfg[key] = guicfg[module][key] # else: # cfg[key] = guicfg[module][key].get() cfg['rawprofile'] = guicfg['inputfile'].get() cfg['relatdev']['radius_h'] = int(guicfg['outliers']['radius_h'].get()) cfg['relatdev']['radius_v'] = int(guicfg['outliers']['radius_v'].get()) cfg['relatdev']['enabled'] = bool(guicfg['outliers']['enabled'].get()) cfg['outliermatrix']['limit'] = float(guicfg['outliers']['limit'].get()) cfg['outliermatrix']['enabled'] = bool(guicfg['outliers']['enabled'].get()) return cfg def cfg2gui(guicfg, cfg, module=False): ''' write the data from the cfg dictionary to the GUI variables. ''' # if module: # for key in guicfg: # print('module: {}, key: {}, value:{}'.format(module, key, cfg[module][key])) # guicfg[module][key].set(cfg[module][key]) #ugly but works guicfg['inputfile'].set(cfg['rawprofile']) guicfg['outliers']['radius_h'].set(cfg['relatdev']['radius_h']) guicfg['outliers']['radius_v'].set(cfg['relatdev']['radius_v']) guicfg['outliers']['enabled'].set(cfg['relatdev']['enabled']) guicfg['outliers']['limit'].set(cfg['outliermatrix']['limit']) guicfg['outliers']['enabled'].set(cfg['outliermatrix']['enabled']) return guicfg def get_default_cfg(): ''' return a default config that can be used as suggestion to the user and also provides settings that cannot be changed in the GUI ''' cfg = dict( rawprofile = '../testfiles/demodata.txt', valuematrix = '.velocity_comp.v', relatdev = dict(radius_h=5, radius_v=0, enabled=1), outliermatrix = dict(limit=2.5, enabled=1), goodvaluematrix = None, cellmatrix = None, outfolder = '../testfiles/' ) return cfg # ----------------------------------------------------------------------------- if __name__ == '__main__': dc = DataClass() dc.cfg = get_default_cfg() print(dc.cfg) rd = dc.relatdev ol = dc.outliermatrix print(dc.cfg_saved, '\n', dc.cfg) print('#### updating #######################################################') dc.cfg['relatdev']['radius_h'] = 7 print(dc.cfg_saved, '\n', dc.cfg) ol = dc.relatdev