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)