#!PYTHONEXE """This script is the isprint application for Madrigal 3.0, that uses the new Hdf5 format $Id: isprint 7046 2019-10-07 19:57:14Z brideout $ """ # standard python imports import sys import os # third party imports import numpy usageStr = """Usage: isprint file= output=. If not given, default is text file to stdout. If given and extension is one of <.hdf5, .h5, .hdf>, then will save as Hdf5 file. If extension is .nc, will be saved as netCDF4. In all other cases, will be saved as ascii text. If hdf5 or netCDF4, arguments (header, summary, badval, assumed, and knownbad) ignored if given. date1= time1= date2= time2= (in the follow arguments, any value missing may be used to indicate no lower or upper limit) z=,[or,...] (km) az=,[or,...] (from -180 to 180) el=,[or,...] (from 0 to 90) plen=,[or,...] (pulse len in sec) header= (defaults to header=t, show headers) summary= (defaults to summary=t, show summary) badval= (defaults to "NaN") assumed= (defaults to "-1") knownbad= (defaults to "-2") filter=<[mnemonic] or [mnemonic1,[+-*/]mnemonic2]>,,[or,...] (any number of filters may be added) indSpatialParms=. Used only if saving to an hdf5 or netCDF4 file. If not given, the default is to use the independent parms in the original file. Ignored if only 1D parms requested. (will be show in order listed, but duplicates are ignored) ignoreEmptyFile= If False, raise IOError when trying to create an Hdf5 or netCDF4 file with no records. If True (the default), then simply create 0 byte file. Ignored if output not hdf5 or netCDF4. Example: isprint file=/opt/madrigal/experiments/1998/mlh/20jan98/mil980120g.003 date1=01/20/1998 time1=15:00:00 date2=01/20/1998 time2=16:00:00 z=200,300or500,600 badval=noData filter=gdalt,-,sdwht,0, filter=ti,500,1000 uth gdalt gdlat glon ti te This example would show data from mil980120g.003 between 15 and 16 UT on 01/20/1998 where altitude is either between 200 and 300 km or between 500 and 600 km, and where gdalt-sdwht is greater than 0 (point is in sunlight), and where ti is between 500 and 1000. "noData" would be printed if data was not available. See complete instructions at http://www.haystack.mit.edu/madrigal/isprint.html """ # catch any exception, and write an appropriate message try: # check if pythonlibpath env variable exists # written 'PYTHON' + 'LIBPATH' to stop automatic replacement during setup temp = os.environ.get('PYTHON' + 'LIBPATH') if temp != None: sys.path.append(temp) # append path madroot/lib (needed only if python not installed by setup) # what is this????sys.path.append('MADROOT/lib/python') # prepare to handle MadrigalError import madrigal.admin except ImportError: # Fatal error - madpy library not found print("Unable to import the madrigal python library - please alert the sys admin!") sys.exit(0) import madrigal.metadata import madrigal.data import madrigal._derive import madrigal.derivation import madrigal.isprint # create MadrigalDB obj madDBObj = madrigal.metadata.MadrigalDB() # create MadrigalParm obj madParmObj = madrigal.data.MadrigalParameters(madDBObj) # create an empty filter filterList = [] # inital values desiredParmList = [] filename = '' header = True summary = 'summary' badvalStr = None assumedStr = None knownbadStr = None date1 = '' time1 = '' date2 = '' time2 = '' output = None format = 'text' indSpatialParms = None ignoreEmptyFile = True # parse arguments if len(sys.argv) == 1: print(usageStr) sys.exit(0) for arg in sys.argv[1:]: rangeList = [] # check if its a parameter if arg.find('=') == -1: if madParmObj.getParmType(arg) == -1: raise IOError("Illegal parameter: " + str(arg)) if madParmObj.getParmMnemonic(arg).lower() not in desiredParmList: desiredParmList.append(madParmObj.getParmMnemonic(arg).lower()) continue # check if its a file if arg.find('file=') != -1: filename = arg[arg.find('=')+1:] continue # check if its output if arg.find('output=') != -1: output = arg[arg.find('=')+1:] # see if its an Hdf5 or nbetCDF4 file fileName, fileExtension = os.path.splitext(output) if fileExtension.lower() in ('.hdf5', '.h5', '.hdf'): format = 'hdf5' elif fileExtension.lower() in ('.nc'): format = 'netCDF4' else: format = 'text' continue # check for header if arg[:7] == 'header=': if arg[7] in ['f', 'F']: header = False elif arg[7] not in ['t', 'T']: raise IOError("Bad argument for header, must be t or f") continue # check for summary if arg[:8] == 'summary=': if arg[8] in ['f', 'F']: summary = 'plain' elif arg[8] not in ['t', 'T']: raise IOError("Bad argument for summary, must be t, or T or f or F") continue # check for badval if arg[:7] == 'badval=': badvalStr = arg[7:] continue # check for assumed if arg[:8] == 'assumed=': assumedStr = arg[8:] continue # check for knownbad if arg[:9] == 'knownbad=': knownbadStr = arg[9:] continue # check for summary if arg[:8] == 'ignoreEmptyFile=': if arg[8] in ['f', 'F']: ignoreEmptyFile = False elif arg[8] not in ['t', 'T']: raise IOError("Bad argument for ignoreEmptyFile, must be t, or T or f or F") continue # check if its date1 if arg[:6] == 'date1=': date1 = arg[arg.find('=')+1:] continue # check if its time1 if arg[:6] == 'time1=': time1 = arg[arg.find('=')+1:] continue # check if its date2 if arg[:6] == 'date2=': date2 = arg[arg.find('=')+1:] continue # check if its time2 if arg[:6] == 'time2=': time2 = arg[arg.find('=')+1:] continue # check if its z argument if arg[:2] == 'z=': argStr = arg[arg.find('=')+1:] # get number of ranges zRangeList = argStr.split('or') for zRange in zRangeList: limList = zRange.split(',') if len(limList) != 2: raise IOError("Illegal range in z filter") lower, upper = numpy.nan, numpy.nan if len(limList[0]): lower = float(limList[0]) if len(limList[1]): upper = float(limList[1]) rangeList.append((lower,upper)) #append filter filterList.append(madrigal.derivation.MadrigalFilter('gdalt', rangeList, madParmObj)) continue # check if its az argument if arg[:3] == 'az=': argStr = arg[arg.find('=')+1:] # get number of ranges azList = argStr.split('or') for az in azList: limList = az.split(',') if len(limList) != 2: raise IOError("Illegal range in az filter") lower, upper = numpy.nan, numpy.nan if len(limList[0]): lower = float(limList[0]) if len(limList[1]): upper = float(limList[1]) rangeList.append((lower,upper)) # check for valid az for az in (lower, upper): if not numpy.isnan(az): if az < -180.0 or az > 180.0: raise IOError("Illegal az %f - must be -180 to 180: " % (az)) #append filter filterList.append(madrigal.derivation.MadrigalFilter('azm', rangeList, madParmObj)) continue # check if its el argument if arg[:3] == 'el=': argStr = arg[arg.find('=')+1:] # get number of ranges elList = argStr.split('or') for el in elList: limList = el.split(',') if len(limList) != 2: raise IOError("Illegal range in el filter") lower, upper = numpy.nan, numpy.nan if len(limList[0]): lower = float(limList[0]) if len(limList[1]): upper = float(limList[1]) rangeList.append((lower,upper)) # check for valid el for el in (lower, upper): if not numpy.isnan(el): if el < -90.0 or el > 90.0: raise IOError("Illegal el %f - must be -90 to 90: " % (az)) #append filter filterList.append(madrigal.derivation.MadrigalFilter('elm', rangeList, madParmObj)) continue # check if its plen argument if arg[:5] == 'plen=': argStr = arg[arg.find('=')+1:] # get number of ranges plList = argStr.split('or') for pl in plList: limList = pl.split(',') if len(limList) != 2: raise IOError("Illegal range in pulse length filter") lower, upper = numpy.nan, numpy.nan if len(limList[0]): lower = float(limList[0]) if len(limList[1]): upper = float(limList[1]) rangeList.append((lower,upper)) #append filter filterList.append(madrigal.derivation.MadrigalFilter('pl', rangeList, madParmObj)) continue if arg[:16] == 'indSpatialParms=': indSpatialParms = [] indSpatialParmsStr = arg[arg.find('=')+1:] parmList = indSpatialParmsStr.split(',') for parm in parmList: if madParmObj.getParmType(parm) == -1: raise IOError("Illegal indSpatialParm: " + str(parm)) indSpatialParms.append(madParmObj.getParmMnemonic(parm)) if indSpatialParms[-1] not in desiredParmList: desiredParmList.append(indSpatialParms[-1]) # finally, check if its a filter argument if arg[:7] == 'filter=': argStr = arg[arg.find('=')+1:] #get mnemonic string itemList = argStr.split(',') if itemList[1] in ['+','-','*','/']: # two mnemonics used twoMnem = 1 mnem1 = itemList[0] operator = itemList[1] mnem2 = itemList[2] # check that both are valid if madParmObj.getParmType(mnem1) == -1: raise IOError("Illegal parameter: " + str(mnem1)) if madParmObj.getParmType(mnem2) == -1: raise IOError("Illegal parameter: " + str(mnem2)) else: # one menmonic twoMnem = 0 mnem1 = itemList[0] operator = None mnem2 = None # check mnem1 is valid if madParmObj.getParmType(mnem1) == -1: raise IOError("Illegal parameter: " + str(mnem1)) # get ranges delimiter = ',' rangeStr = delimiter.join(itemList[1 + 2*twoMnem:]) rangeStrList = rangeStr.split('or') rangeList = [] for thisRange in rangeStrList: limList = thisRange.split(',') if len(limList) != 2: raise IOError("Illegal range in filter") lower, upper = numpy.nan, numpy.nan if len(limList[0]): lower = float(limList[0]) if len(limList[1]): upper = float(limList[1]) rangeList.append((lower,upper)) #append filter filterList.append(madrigal.derivation.MadrigalFilter(mnem1, rangeList, madParmObj, mnem2, operator)) continue # unknown argument print('Argument %s is unknown - see usage' % arg) print() print(usageStr) sys.exit(0) # command line fully parsed - finally set up the time filter based on # date, time args if needed if len(date1) or len(time1) or len(date2) or len(time2): # if time1 is given but not date1, set up a UTH filter if len(time1) and len(date1)==0: time1List = time1.split(':') if len(time1List) != 3: raise IOError("Illegal value for time1: " + time1) beg_uth = float(time1List[0]) beg_uth += float(time1List[1])/60.0 beg_uth += float(time1List[2])/3600.0 rangeList = [(beg_uth,numpy.nan)] filterList.append(madrigal.derivation.MadrigalFilter('uth', rangeList, madParmObj)) # if time2 is given but not date1 or date2, set up a UTH filter if len(time2) and len(date1)==0 and len(date2)==0: time2List = time2.split(':') if len(time2List) != 3: raise IOError("Illegal value for time2: " + time2) end_uth = float(time2List[0]) end_uth += float(time2List[1])/60.0 end_uth += float(time2List[2])/3600.0 rangeList = [(numpy.nan, end_uth)] filterList.append(madrigal.derivation.MadrigalFilter('uth', rangeList, madParmObj)) # set up UT1 filter if both date and times given beg_ut1 = numpy.nan end_ut1 = numpy.nan if (date1): if time1 == '': time1 = '00:00:00' time1List = time1.split(':') if len(time1List) != 3: raise IOError("Illegal value for time1: " + time1) date1List = date1.split('/') if len(date1List) != 3: raise IOError("Illegal value for date1: " + date1) beg_ut1 = madrigal._derive.getUtFromDate(int(date1List[2]), int(date1List[0]), int(date1List[1]), int(time1List[0]), int(time1List[1]), int(time1List[2]), 0) # now check for the case that time2 given, but not date2 # in which case time2 referes to date1 if len(time2) and len(date2)==0: end_ut1 = madrigal._derive.getUtFromDate(int(date1List[2]), int(date1List[0]), int(date1List[1]), 0, 0, 0, 0) time2List = time2.split(':') if len(time2List) != 3: raise IOError("Illegal value for time2: " + time2) end_ut1 += float(time2List[0]) * 3600.0 end_ut1 += float(time2List[1]) * 60.0 end_ut1 += float(time2List[2]) if len(date2): if time2 == '': time2 = '00:00:00' time2List = time2.split(':') if len(time2List) != 3: raise IOError("Illegal value for time2: " + time2) date2List = date2.split('/') if len(date2List) != 3: raise IOError("Illegal value for date2: " + date2) end_ut1 = madrigal._derive.getUtFromDate(int(date2List[2]), int(date2List[0]), int(date2List[1]), int(time2List[0]), int(time2List[1]), int(time2List[2]), 0) # append ut1 filter if needed if not numpy.isnan(beg_ut1) or not numpy.isnan(end_ut1): rangeList = [(beg_ut1, end_ut1)] filterList.append(madrigal.derivation.MadrigalFilter('ut1', rangeList, madParmObj)) # check that filename was given if len(filename) == 0: raise IOError('Required argument file missing') madrigal.isprint.Isprint(filename, output, desiredParmList, filterList, indSpatialParms, summary, header, badvalStr, assumedStr, knownbadStr, ignoreEmptyFile=ignoreEmptyFile) # end script