#!/usr/bin/env seiscomp-python from __future__ import print_function import sys, os import csv from optparse import OptionParser def quote(instr): return '"'+instr+'"' class base(object): def __init__(self, filename, fields): self.att = {} fd = open(filename) try: try: fieldNames = None for row in csv.DictReader(fd, fieldNames): id = row['id'] if id in self.att: print("multiple %s found in %s" % (id, filename)) continue for key in fields: if not row[key]: del(row[key]) del row['id'] try: row['low_freq'] = float(row['low_freq']) except KeyError: pass try: row['high_freq'] = float(row['high_freq']) except KeyError: pass self.att[id] = row except KeyError as e: raise Exception("column %s missing in %s" % (str(e), filename)) except (TypeError, ValueError) as e: raise Exception("error reading %s: %s" % (filename, str(e))) finally: fd.close() def keys(self): return list(self.att.keys()) def screname(self, what): nc = "" nu = True for c in what: if c == '_': nu = True continue if nu: nc += c.upper() nu = False else: nc += c if nc == 'LowFreq': nc = 'LowFrequency' if nc == 'HighFreq': nc = 'HighFrequency' return nc def reorder(self): att = {} if not self.att: return None for (code, row) in self.att.items(): for (k, v) in row.items(): k = self.screname(k) try: dk = att[k] except: dk = {} att[k] = dk try: dv = dk[str(v)] except: dv = [] dk[str(v)] = dv dv.append(code) return att def dump(self, fdo): att = self.reorder() lastK=None for (k, v) in att.items(): if not lastK: lastK = k if lastK != k: fdo.write("\n") for (kv, ids) in v.items(): fdo.write("Ia: %s=%s" % (k,quote(kv))) for id in ids: fdo.write(" %s" % id) fdo.write("\n") fdo.write("\n") class sensorAttributes(base): def __init__(self, filename): base.__init__(self, filename, ['id', 'type','unit', 'low_freq', 'high_freq', 'model', 'manufacturer', 'remark']) class dataloggerAttributes(base): def __init__(self, filename): base.__init__(self, filename, ['id', 'digitizer_model', 'digitizer_manufacturer', 'recorder_model', 'recorder_manufacturer', 'clock_model', 'clock_manufacturer', 'clock_type', 'remark']) class INST(object): def cleanID(self, id): nc = "" for c in id: nc += c if c == '_': nc = "" return nc def __init__(self, filename, attS, attD): self.filename = filename self.sensorA = sensorAttributes(attS) self.dataloggerA = dataloggerAttributes(attD) lines = [] f = open(filename) for line in f: line = line.strip() if not line or line[0] == '#': # Add comments line types lines.append({ 'content': line, 'type': 'C', 'id': None}) else: (id, line) = line.split(">", 1) id = id.strip() line = line.strip() # Add undefined line types lines.append({ 'content': line, 'type': 'U', 'id': id}) f.close() self.lines = lines self._filltypes() def _filltypes(self): for line in self.lines: if line['type'] != 'U': continue id = line['id'] if id.find('_FIR_') != -1: line['type'] = 'F' elif id.find('Sngl-gain_') != -1: line['type'] = 'L' line['id'] = self.cleanID(id) elif id.find('_digipaz_') != -1: line['type'] = 'P' elif id.find('_iirpaz_') != -1: line['type'] = 'I' for line in self.lines: if line['type'] != 'U': continue id = self.cleanID(line['id']) if id in list(self.sensorA.keys()): line['type'] = 'S' line['id'] = id elif id in list(self.dataloggerA.keys()): line['type'] = 'D' line['id'] = id # Those we are forcing ! elif id in ['OSIRIS-SC', 'Gaia', 'LE24', 'MALI', 'PSS', 'FDL', 'CMG-SAM', 'CMG-DCM', 'EDAS-24', 'SANIAC']: line['id'] = id line['type'] = 'D' elif id in ['Trillium-Compact', 'Reftek-151/120', 'BBVS-60', 'CMG-3ESP/60F', 'LE-1D/1', 'L4-3D/BW', 'S13', 'GS13', 'SH-1', 'MP', 'MARKL22', 'CM-3', 'CMG-6T', 'SM-6/BW']: line['id'] = id line['type'] = 'S' for line in self.lines: if line['type'] == 'U': print("'"+self.cleanID(line['id'])+"', ", end=' ') def dump(self, fdo): sa = False da = False dataloggerFieldSize = 0 sensorFieldSize = 0 for line in self.lines: if line['type'] == 'C': continue if line['type'] == 'S': if len(line['id']) > sensorFieldSize: sensorFieldSize = len(line['id']) if line['type'] == 'D': if len(line['id']) > dataloggerFieldSize: dataloggerFieldSize = len(line['id']) seLine = "Se: %%%ss %%s\n" % (-1*(sensorFieldSize+1)) dtLine = "Dl: %%%ss %%s\n" % (-1*(dataloggerFieldSize+1)) for line in self.lines: if line['type'] == 'C': fdo.write(line['content'] + "\n") continue if line['type'] == 'S': if not sa: self.sensorA.dump(fdo) sa = True fdo.write(seLine % (line['id'], line['content'])) continue if line['type'] == 'D': if not da: self.dataloggerA.dump(fdo) da = True fdo.write(dtLine % (line['id'], line['content'])) continue if line['type'] == 'L': fdo.write("Cl: %s %s\n" % (line['id'], line['content'])) continue if line['type'] == 'F': fdo.write("Ff: %s %s\n" % (line['id'], line['content'])) continue if line['type'] == 'P': fdo.write("Pz: %s %s\n" % (line['id'], line['content'])) continue if line['type'] == 'I': fdo.write("If: %s %s\n" % (line['id'], line['content'])) continue def main(): parser = OptionParser(usage="Old tab to New tab converter", version="1.0", add_help_option=True) parser.add_option("", "--sat", type="string", help="Indicates the sensor attribute file to use", dest="sat", default="sensor_attr.csv") parser.add_option("", "--dat", type="string", help="Indicates the station attribute file to use", dest="dat", default="datalogger_attr.csv") parser.add_option("-c", "--clean", action="store_true", help="Remove the comments and blank lines", dest="cleanFile", default=False) # Parsing & Error check (options, args) = parser.parse_args() errors = [] if len(args) != 1: errors.append("need an Input filename") if not os.path.isfile(options.sat): errors.append("sensor attribute file '%s' not found." % options.sat) if not os.path.isfile(options.dat): errors.append("datalogger attribute file '%s' not found." % options.dat) if len(args) == 2 and os.path.isfile(args[1]): errors.append("output file already exists, will not overwrite.") if errors: print("Found error while processing the command line:", file=sys.stderr) for error in errors: print(" %s" % error, file=sys.stderr) return 1 inputName = args[0] i= INST(inputName, options.sat, options.dat) fdo = sys.stdout if len(args) < 2 else open(args[1],"w") i.dump(fdo) fdo.close() if __name__ == "__main__": main()