isprint
463 lines
| 16.5 KiB
| text/plain
|
TextLexer
r0 | #!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=<path to file> | ||||
output=<output file>. 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=<mm/dd/yyyy - starting date to be examined - defaults to first day> | ||||
time1=<hh:mm:ss - starting UT time to be examined - defaults to 0> | ||||
date2=<mm/dd/yyyy - ending date to be examined - defaults to last day> | ||||
time2=<hh:mm:ss - ending UT time to be examined - defaults to 24> | ||||
(in the follow arguments, any value missing may be used to indicate no lower or upper limit) | ||||
z=<lower alt limit1>,<upper alt limit1>[or<lower alt limit2>,<upper alt limit2>...] (km) | ||||
az=<lower az limit1>,<upper az limit1>[or<lower az limit2>,<upper az limit2>...] (from -180 to 180) | ||||
el=<lower el limit1>,<upper el limit1>[or<lower el limit2>,<upper el limit2>...] (from 0 to 90) | ||||
plen=<lower pl limit1>,<upper pl limit1>[or<lower pl limit2>,<upper pl limit2>...] (pulse len in sec) | ||||
header=<t or f> (defaults to header=t, show headers) | ||||
summary=<t or f> (defaults to summary=t, show summary) | ||||
badval=<bad value string> (defaults to "NaN") | ||||
assumed=<assumed value string> (defaults to "-1") | ||||
knownbad=<known bad value string> (defaults to "-2") | ||||
filter=<[mnemonic] or [mnemonic1,[+-*/]mnemonic2]>,<lower limit1>,<upper limit1>[or<lower limit2>,<upper limit2>...] | ||||
(any number of filters may be added) | ||||
indSpatialParms=<comma separated list of parms>. 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. | ||||
<list of mnemonics to display> (will be show in order listed, but duplicates are ignored) | ||||
ignoreEmptyFile=<t or f> 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 | ||||