def main(): args = sys.argv[1:] if len(args) == 0: usage() return if not os.path.isfile(args[0]): print "Can't find file %s"%(args[0],) return staxml = sisxmlparser.parse(args[0]) print "Find unique responses" uniq = uniqueResponses(staxml) print "NRL check unique responses" nrledUniq = checkNRL.checkRespListInNRL('nrl', uniq, 'logger_samp_rate.sort') numChans = 0 print "found %d uniq responses "%(len(uniq), ) for x in nrledUniq: for xc in x[2]: sys.stdout.write("%s "%(xc,)) sys.stdout.write(" NRL: ") sys.stdout.write(" Sensor: ") for s in x[3]: sys.stdout.write("%s "%(s,)) sys.stdout.write(" Logger: ") for l in x[4]: sys.stdout.write("%s "%(l,)) print ""
def main(): sisNamespace = "TESTING" parseArgs = initArgParser() if parseArgs.verbose: VERBOSE=True sisNamespace = parseArgs.namespace if parseArgs.stationxml: if not os.path.exists(parseArgs.stationxml): print "ERROR: can't fine stationxml file %s"%(parseArgs.stationxml,) return # validate with SIS validator # http://maui.gps.caltech.edu/SIStrac/wiki/SIS/Code if os.path.exists('xerces-2_11_0-xml-schema-1.1-beta') and os.path.exists('validator/ValidateStationXml.class'): print "Validating xml..." try: validateOut = subprocess.check_output(['java', '-cp', 'validator:xerces-2_11_0-xml-schema-1.1-beta/xercesImpl.jar:xerces-2_11_0-xml-schema-1.1-beta/xml-apis.jar:xerces-2_11_0-xml-schema-1.1-beta/serializer.jar:xerces-2_11_0-xml-schema-1.1-beta/org.eclipse.wst.xml.xpath2.processor_1.1.0.jar:.', 'ValidateStationXml', '-i', parseArgs.stationxml]) except subprocess.CalledProcessError as e: validateOut = "error calling process: " + e.output validateOut = validateOut.strip() if not validateOut == '0': print "ERROR: invalid stationxml document, errors: '%s'"%(validateOut,) return else: print "OK" else: print """ ERROR: Can't find validator: %s %s wget http://mirror.cc.columbia.edu/pub/software/apache//xerces/j/binaries/Xerces-J-bin.2.11.0-xml-schema-1.1-beta.tar.gz tar zxf Xerces-J-bin.2.11.0-xml-schema-1.1-beta.tar.gz wget http://maui.gps.caltech.edu/SIStrac/raw-attachment/wiki/SIS/Code/validator.tar.gz tar ztf validator.tar.gz We assume the directories validator and xerces-2_11_0-xml-schema-1.1-beta are in current directory for validation. """%(os.path.exists('xerces-2_11_0-xml-schema-1.1-beta') , os.path.exists('validator/ValidateStationXml.class')) return # Parse an xml file rootobj = sisxmlparser.parse(parseArgs.stationxml) origModuleURI = rootobj.ModuleURI rootobj.schemaVersion='1.0', rootobj.Source=parseArgs.namespace rootobj.Sender=parseArgs.namespace rootobj.Module='sta2extsta.py', rootobj.ModuleURI='https://github.com/crotwell/2extStationXML', rootobj.Created=datetime.datetime.now() if not hasattr(rootobj, 'comments'): rootobj.comments = [] rootobj.comments.append("From: "+origModuleURI) # del non-matching channels if parseArgs.onlychan: pattern = re.compile(parseArgs.onlychan) for n in rootobj.Network: for s in n.Station: tempChan = [] for c in s.Channel: locid = c.locationCode if locid is None or len(locid) == 0: locid = "--" if pattern.match(c.code): tempChan.append(c) elif pattern.match("%s.%s"%(locid, c.code)): tempChan.append(c) else: if VERBOSE: print "Skip %s as doesn't match --onlychan"%(checkNRL.getChanCodeId(n, s, c),) s.Channel = tempChan for n in rootobj.Network: for s in n.Station: tempChan = [] for c in s.Channel: if hasattr(c, 'Response') and hasattr(c.Response, 'Stage') and isOnlyGainStage(c.Response, 1): # for weird case of gain channels for gain-ranged channels # input and output units should be volts and we will # insert a fake unity sensor for this. if c.Response.InstrumentSensitivity.InputUnits.Name == 'V' and c.Response.Stage[1].Coefficients.InputUnits.Name == 'V': print "INFO: adding unity V to V polezero to stage 1 for %s.%s.%s.%s"%(n.code, s.code, c.locationCode, c.code) pzTemp = sisxmlparser.PolesZerosType() pzTemp.InputUnits = c.Response.InstrumentSensitivity.InputUnits pzTemp.OutputUnits = c.Response.Stage[1].Coefficients.InputUnits pzTemp.PzTransferFunctionType = "LAPLACE (RADIANS/SECOND)" pzTemp.NormalizationFactor = 1 pzTemp.NormalizationFrequency = 1 pzTemp.Zero = [] pzTemp.Pole = [] c.Response.Stage[0].PolesZeros = pzTemp else: print "WARNING: can't fix stage 1, no poleszeros for %s.%s.%s.%s"%(n.code, s.code, c.locationCode, c.code) # Cannot use 'xsi:type' as an identifier which is how it is # stored in the object. So a set function has been defined for this # one case. Use it only when the type has been extended - RootType, # StationType, ChannelType, GainType, and ResponseType rootobj.settype('sis:RootType') if not os.path.exists(parseArgs.nrl): print "ERROR: can't find nrl dir at '%s', get with 'svn checkout http://seiscode.iris.washington.edu/svn/nrl/trunk nrl"%(parseArgs.nrl,) return spsIndex = os.path.join(parseArgs.nrl, "logger_sample_rate.sort") if not os.path.exists(spsIndex): print "ERROR: can't fine sps index file for NRL. Should be logger_sample_rate.sort inside NRL directory" print "python checkNRL.py --samplerate --nrl <path_to_nrl>" return # load logger response by sample rate index file, speeds search if VERBOSE: print "load NRL sample rate index" loggerRateIndex = checkNRL.loadRespfileSampleRate(spsIndex) # find all unique responses so only check identical channels once if VERBOSE: print "find unique responses in xml" uniqResponse = uniqResponses.uniqueResponses(rootobj) # for each unique response, see if it is in the NRL so we use NRL instead of # a in file named response if VERBOSE: print "look for responses in NRL...this could take a while" uniqWithNRL = checkNRL.checkRespListInNRL(parseArgs.nrl, uniqResponse, loggerRateIndex=loggerRateIndex) for n in rootobj.Network: print "%s "%(n.code,) for s in n.Station: print " %s "%(s.code, ) if not hasattr(s, 'Operator'): s.Operator = [] sOp = sisxmlparser.OperatorType() sOp.Agency = [] sOp.Agency.append(parseArgs.operator) s.Operator.append(sOp) allChanCodes = {} tempChan = [] for c in s.Channel: if c.endDate > datetime.datetime.now() and parseArgs.delcurrent: print " %s.%s --delcurrent: delete channel ends after now %s "%(c.locationCode, c.code, checkNRL.getChanCodeId(n,s,c),) else: tempChan.append(c) s.Channel = tempChan for c in s.Channel: print " %s.%s "%(c.locationCode, c.code,) key = "%s.%s"%(c.locationCode, c.code) if not key in allChanCodes: allChanCodes[key] = [] allChanCodes[key].append(c) fixResponseNRL(n, s, c, uniqWithNRL, sisNamespace) for key, epochList in allChanCodes.iteritems(): epochList.sort(key=getStartDate) # save old stage as named and added so only add each unique stage once # this is only for logger stages as sensor is taken care of in fixResponseNRL prevAddedFilterStage = {} respGroup = sisxmlparser.ResponseDictGroupType() respGroup.ResponseDict = [] for prototypeChan, namedResponse, chanCodeList, sss, lll in uniqWithNRL: if not hasattr(namedResponse, 'Stage'): # no stages, so do not need to add continue if VERBOSE: print "add to hardware, prototype: "+prototypeChan if len(sss) == 0: # add stage 1 as sensor sensor = sisxmlparser.ResponseDictType() if hasattr(namedResponse.Stage[0], "PolesZeros"): sensor.PolesZeros = toSISPolesZeros(namedResponse.Stage[0].PolesZeros) sensor.PolesZeros.name = "S_"+prototypeChan sensor.PolesZeros.SISNamespace = sisNamespace else: print "WARNING: sensor response for %s doesnot have PolesZeros"%(prototypeChan,) return respGroup.ResponseDict.append(sensor) if len(lll) == 0: # add later stages as logger logger = sisxmlparser.ResponseDictType() logger.FilterSequence = sisxmlparser.FilterSequenceType() logger.FilterSequence.name = "L_"+prototypeChan logger.FilterSequence.SISNamespace = sisNamespace logger.FilterSequence.FilterStage = [] loggerStartStage = 2 if isOnlyGainStage(namedResponse, 2): #stage 2 is gain only, so assume preamp " loggerStartStage = 3 # array index is 0-base, stage number is 1-base, so -1 # first logger stage should be AtoD stage and SIS wants # that separate from the filter chain if not hasattr(namedResponse.Stage[loggerStartStage-1], "Coefficients"): print "ERROR: expecting AtoD stage, which should have Coefficients, but not found. %d %s"%(loggerStartStage, prototypeChan) return if not (namedResponse.Stage[loggerStartStage-1].Coefficients.InputUnits.Name == 'V' and namedResponse.Stage[loggerStartStage-1].Coefficients.OutputUnits.Name == 'COUNTS'): # no AtoD???, quit with error print "ERROR: Was expecting AtoD stage, V to COUNTS, but found %s to %s, %s"%(namedResponse.Stage[loggerStartStage-1].Coefficients.InputUnits.Name, namedResponse.Stage[loggerStartStage-1].Coefficients.OutputUnits.Name, prototypeChan) return # now deal with actual filter chain for s in namedResponse.Stage[loggerStartStage : ]: # first search to see if we have already added this filter stage found = False for oldName, oldStage in prevAddedFilterStage.iteritems(): if uniqResponses.areSameStage(s, oldStage)[0]: found=True break filterStage = sisxmlparser.FilterStageType() filterStage.SequenceNumber = s.number if hasattr(s, "Decimation"): filterStage.Decimation = s.Decimation else: print "No decimation in %s stage %d but it is required"%(prototypeChan, s.number) if hasattr(s, "StageGain"): filterStage.Gain = s.StageGain filterStage.Filter = sisxmlparser.FilterIDType() if not found: filterStage.Filter.Name = "FS_%d_%s"%(s.number, prototypeChan) rd = createResponseDict(prototypeChan, s, sisNamespace) respGroup.ResponseDict.append(rd) prevAddedFilterStage[filterStage.Filter.Name] = s else: filterStage.Filter.Name = oldName filterStage.Filter.SISNamespace = sisNamespace # set type if hasattr(s, "PolesZeros"): filterStage.Filter.Type = "PolesZeros" elif hasattr(s, "FIR"): filterStage.Filter.Type = "FIR" elif hasattr(s, "Coefficients"): filterStage.Filter.Type = "Coefficients" else: print "stage does not have PZ, FIR or Coef: %s stage %s \n%s"%(prototypeChan, s.number, dir(s)) logger.FilterSequence.FilterStage.append(filterStage) if len(namedResponse.Stage[loggerStartStage : ]) > 0: # only add if not empty respGroup.ResponseDict.append(logger) # add named non-NRL responses to HardwareResponse but not if respGroup is empty if len(respGroup.ResponseDict) > 0: if not hasattr(rootobj, "HardwareResponse"): rootobj.HardwareResponse = sisxmlparser.HardwareResponseType() if not hasattr(rootobj.HardwareResponse, "ResponseDictGroup"): rootobj.HardwareResponse.ResponseDictGroup = respGroup else: raise SISError ("rootobj already has HardwareResponse.ResponseDictGroup!") # Finally after the instance is built export it. rootobj.exportxml(parseArgs.outfile, 'FDSNStationXML', 'fsx', 0)