def tr2sitechan(tr): """Provide a sac header dictionary, get a filled sitechan table instance.""" #1) from obspy header sitechandict = _map_header({'station': 'sta', 'channel': 'chan'}, tr.stats, OBSPYDEFAULT) #2) from sac header try: sac2sitechan = {'cmpaz': 'hang', 'cmpinc': 'vang', 'stdp': 'edepth'} sitechandict.update(_map_header(sac2sitechan, tr.stats.sac, SACDEFAULT)) try: sitechandict['edepth'] /= 1000. except (TypeError, KeyError): #edepth is None or missing pass except (AttributeError, KeyError): # no tr.stats.sac pass if sitechandict: sitechan = Sitechan(**sitechandict) else: sitechan = None return sitechan
def tr2site(tr): """ Provide an ObsPy Trace, get a filled site table instance, using available header. """ sitedict = {} #1) from obspy header first if tr.stats.station: sitedict['sta'] = tr.stats.station #2) get from sac header try: sac2site = {'stla': 'lat', 'stlo': 'lon', 'stel': 'elev'} sitedict.update(_map_header(sac2site, tr.stats.sac, SACDEFAULT)) try: sitedict['elev'] /= 1000 except KeyError: #no 'elev' pass except (AttributeError, KeyError): # tr.stats has no "sac" attribute pass if sitedict: site = Site(**sitedict) else: site = None return site
def tr2affiliation(tr): #1) from obspy header affildict = _map_header({'network': 'net', 'station': 'sta'}, tr.stats, OBSPYDEFAULT) #2) from sac header try: sac2affiliation = {'knetwk': 'net', 'kstnm': 'sta'} affildict.update(_map_header(sac2affiliation, tr.stats.sac, SACDEFAULT)) except (AttributeError, KeyError): # no tr.stats.sac or 'knetwk', etc. pass if affildict: affil = Affiliation(**affildict) else: affil = None return affil
def tr2event(tr): eventdict = {} try: eventdict.update(_map_header({'nevid': 'evid', 'kevnm': 'evname'}, tr.stats.sac, SACDEFAULT)) except AttributeError: #no tr.stats.sac pass if eventdict: event = Event(**eventdict) else: event = None return event
def tr2instrument(tr): #TODO: investigate hdr['resp0-9'] values #1) from sac header instrdict = {'samprate': int(tr.stats.sampling_rate)} try: instrdict = _map_header({'kinst': 'ins', 'iinst': 'instype'}, tr.stats.sac, SACDEFAULT) except AttributeError: #no tr.stats.sac pass if instrdict: instr = Instrument(**instrdict) else: instr = None return instr
def sachdr2reftime(hdr): """Get SAC reference UTCDateTime from header dictionary. """ # reftime = nzyear + nzjday + nzhour + nzminute + nzsecond + nzmsec*1000 tdict = {'year': 1970, 'month': 1, 'day': 1, 'minute': 0, 'microsecond': 0} # for non-default values in hdr, return desired values, mapped to new keys mapdict = _map_header({'nzyear': 'year', 'nzjday':'julday', 'nzhour':'hour', 'nzmin':'minute', 'nzsec':'second', 'nzmsec':'microsecond'}, hdr, SACDEFAULT) tdict.update(mapdict) if tdict['microsecond']: tdict['microsecond'] *= 1000. #tdict = {} #tdict.update((key, val) for key, val in tmpdict.iteritems() \ # if val is not None) t0 = UTCDateTime(**tdict)
def tr2wfdisc(tr): """Produce wfdisc kbcore table instance from sac header dictionary. Clearly this will be a skeleton instance, as the all-important 'dir' and 'dfile' must be filled in later. Note: if you read a little-endian SAC file onto a big-endian machine, it seems that obspy.sac.sacio.SacIO.swap_byte_order has trouble. """ # from obspy header wfdict = {} wfdict['nsamp'] = tr.stats.npts wfdict['time'] = tr.stats.starttime.timestamp wfdict['endtime'] = tr.stats.endtime.timestamp wfdict['jdate'] = int(tr.stats.starttime.strftime('%Y%j')) wfdict['samprate'] = int(tr.stats.sampling_rate) if tr.stats.station: wfdict['sta'] = tr.stats.station if tr.stats.channel: wfdict['chan'] = tr.stats.channel if tr.stats.calib: wfdict['calib'] = tr.stats.calib #from sac header try: wfdict.update(_map_header({'nwfid': 'wfid'}, tr.stats.sac, SACDEFAULT)) wfdict['foff'] = 634 if sys.byteorder == 'little': wfdict['datatype'] = 'f4' else: wfdict['datatype'] = 't4' except AttributeError: #no tr.stats.sac pass return Wfdisc(**wfdict)
def tr2assoc(tr, pickmap=None): """ Takes a sac header dictionary, and produces a list of up to 10 Assoc instances. Header->phase mappings follow SAC2000, i.e.: * t0: P * t1: Pn * t2: Pg * t3: S * t4: Sn * t5: Sg * t6: Lg * t7: LR * t8: Rg * t9: pP An alternate mapping for some or all picks can be supplied, however, as a dictionary of strings in the above form. Note: arid values will not be filled in, so do: >>> for assoc in kbio.tables['assoc']: assoc.arid = lastarid+1 lastarid += 1 """ pick2phase = {'t0': 'P', 't1': 'Pn', 't2': 'Pg', 't3': 'S', 't4': 'Sn', 't5': 'Sg', 't6': 'Lg', 't7': 'LR', 't8': 'Rg', 't9': 'pP'} #overwrite defaults with supplied map if pickmap: pick2phase.update(pickmap) #geographic relations # obspy.read tries to calculate these values if lcalca is True and needed #header info is there, so we only need to try to if lcalca is False. #XXX: I just calculate it if no values are currently filled in. assocdict = {} try: assocdict.update(_map_header({'az': 'esaz', 'baz': 'seaz', 'gcarc': 'delta'}, tr.stats.sac, SACDEFAULT)) except AttributeError: # no tr.stats.sac pass #overwrite if any are None if not assocdict: try: delta = geod.locations2degrees(tr.stats.sac.stla, tr.stats.sac.stlo, tr.stats.sac.evla, tr.stats.sac.evlo) m, seaz, esaz = geod.gps2DistAzimuth(tr.stats.sac.stla, tr.stats.sac.stlo, tr.stats.sac.evla, tr.stats.sac.evlo) assocdict['esaz'] = esaz assocdict['seaz'] = seaz assocdict['delta'] = delta except (AttributeError, TypeError): #some sac header values are None pass if tr.stats.station: assocdict['sta'] = tr.stats.station assocdict.update(_map_header({'norid': 'orid'}, tr.stats.sac, SACDEFAULT)) #now, do the phase arrival mappings #for each pick in hdr, make a separate dictionary containing assocdict plus #the new phase info. assocs = [] for key in pick2phase: kkey = 'k' + key #if there's a value in t[0-9] if tr.stats.sac[key] != SACDEFAULT[key]: #if the phase name kt[0-9] is null if tr.stats.sac[kkey] == SACDEFAULT[kkey]: #take it from the map iassoc = {'phase': pick2phase[key]} else: #take it directly iassoc = {'phase': tr.stats.sac[kkey]} iassoc.update(assocdict) assocs.append(iassoc) return [Assoc(**assoc) for assoc in assocs]
def tr2origin(tr): """ Provide a sac header dictionary, get a filled origin table instance. A few things: 1) If sac reference time isn't event-based, origin time is unknown 2) magnitude is taken first from hdr['mag'], hdr['imagtyp'] if defined, then replaced by hdr['user0'],hdr['kuser0'] 3) sac moment, duration, and user-defined magnitude headers aren't put into the origin table 4) origin.auth is taken first from hdr['imagsrc'], then replaced by hdr['kuser1'] if defined. the imagsrc->auth translations are: * INEIC -> ISC:NEIC * IPDE -> PDE * IISC -> ISC * IBRK -> ISC:BERK * IUSGS, ICALTECH, ILLNL, IEVLOC, IJSOP, IUSER, IUNKNOWN -> unchanged """ # simple SAC translations sac2origin = {'evla': 'lat', 'evlo': 'lon', 'norid': 'orid', 'nevid': 'evid', 'ievreg': 'grn', 'evdp': 'depth'} try: origindict = _map_header(sac2origin, tr.stats.sac, SACDEFAULT) except AttributeError: #no tr.stats.sac pass #depth try: origindict['depth'] = tr.stats.sac['evdp']/1000. except (TypeError, AttributeError): #evdp is None, or no tr.stats.sac pass #etype translations edict = {37: 'en', 38: 'ex', 39: 'ex', 40: 'qt', 41: 'qt', 42: 'qt', 43: 'ec', 72: 'me', 73: 'me', 74: 'me', 75: 'me', 76: 'mb', 77: 'qt', 78: 'qt', 79: 'qt', 80: 'ex', 81: 'ex', 82: 'en', 83: 'mc'} try: origindict['etype'] = edict[tr.stats.sac['ievtype']] except (AttributeError, KeyError): #ievtyp is None, or not a key in edict (e.g. sac default value) pass #1: try: t = get_sac_reftime(tr) if tr.stats.sac['iztype'] == 11: #reference time is an origin time if tr.stats.sac.o is SACDEFAULT['o']: o = 0.0 else: o = tr.stats.sac.o origindict['time'] = t.timestamp - o origindict['jdate'] = int((t-o).strftime('%Y%j')) except (AttributeError, KeyError): # no trace.stats.sac, no iztype pass #2: magnitude magdict = {52: 'mb', 53: 'ms', 54: 'ml'} try: origindict[magdict[tr.stats.sac['imagtyp']]] = tr.stats.sac['mag'] except KeyError: #imagtyp is None or not a key in magdict pass # is kuser0 is a recognized magnitude type, overwrite mag #XXX: this is a LANL wfdisc2sac thing try: magtype = tr.stats.sac['kuser0'].strip() if magtype in magdict.values(): origindict[magtype] = tr.stats.sac['user0'] except AttributeError: #kuser0 is None pass #3: origin author authdict = {58: 'ISC:NEIC', 61: 'PDE', 62: 'ISC', 63: 'REB-ICD', 64: 'IUSGS', 65: 'ISC:BERK', 66: 'ICALTECH', 67: 'ILLNL', 68: 'IEVLOC', 69: 'IJSOP', 70: 'IUSER', 71: 'IUNKNOWN'} try: origindict['auth'] = authdict[tr.stats.sac['imagsrc']] except KeyError: # imagsrc not in authdict (i.e. sac default value) pass #XXX: this is LANL wfdisc2sac thing. maybe turn it off? if tr.stats.sac['kuser1']: origindict['auth'] = tr.stats.sac['kuser1'] if origindict: origin = Origin(**origindict) else: origin = None return origin