Module services
@author: Bill Rideout @contact: brideout@haystack.mit.edu
$Id: views.py 7163 2020-08-21 14:15:04Z brideout $
Expand source code
'''
@author: Bill Rideout
@contact: brideout@haystack.mit.edu
$Id: views.py 7163 2020-08-21 14:15:04Z brideout $
'''
def get_version_service(request):
"""get_version_service runs the getVersionService.py service.
Inputs:
request (ignored)
Returns a single line of text, with the version in the form <major_version_int>.<minor_version_int>[.<sub_version_int>]
"""
madDB = madrigal.metadata.MadrigalDB()
siteID = madDB.getSiteID()
madSiteObj = madrigal.metadata.MadrigalSite(madDB)
return(HttpResponse(madSiteObj.getSiteVersion(siteID)))
def get_instruments_service(request):
"""get_instruments_service runs the getInstrumentsService.py service.
Inputs:
request (ignored)
Returns comma-delimited data, one line for each experiment, with the following fields:
1. instrument.name Example: 'Millstone Hill Incoherent Scatter Radar'
2. instrument.code Example: 30
3. instrument.mnemonic (3 char string) Example: 'mlh'
4. instrument.latitude Example: 45.0
5. instrument.longitude Example: 110.0
6. instrument.altitude Example: 0.015 (km)
7. instrument.category Example: 'Incoherent Scatter Radars'
8. contact name
9. contact email
"""
# create MadrigalDB obj
madDBObj = madrigal.metadata.MadrigalDB()
# create MadrigalInstument object
madInst = madrigal.metadata.MadrigalInstrument(madDBObj)
# get instrument list
instList = madInst.getInstrumentList()
# loop through each instrument
instStr = ''
for inst in instList:
name = inst[0]
code = inst[2]
mnemonic = inst[1]
latitude = madInst.getLatitude(code)
if latitude == None:
latitude = 0.0
longitude = madInst.getLongitude(code)
if longitude == None:
longitude = 0.0
altitude = madInst.getAltitude(code)
if altitude == None:
altitude = 0.0
category = madInst.getCategory(code)
if category == None:
category = ''
# print data
contactName = madInst.getContactName(code)
contactEmail = madInst.getContactEmail(code)
instStr += '%s,%i,%s,%f,%f,%f,%s,%s,%s\n' % (name,
code,
mnemonic,
latitude,
longitude,
altitude,
category,
str(contactName),
str(contactEmail))
return render(request, 'madweb/service.html', {'text': instStr})
def get_experiments_service(request):
"""get_experiments_service runs the getExperimentsService.py service.
Inputs:
request/url - contains arguments:
code - one or more kindat values
startyear, startmonth, startday, starthour, startmin, startsec
endyear, endmonth, endday, endhour, endmin, endsec
local (defaults to True)
Returns comma-delimited data, one line for each experiment, with the following fields:
1. experiment.id (int) Example: 10000111
2. experiment.url (string) Example: 'http://www.haystack.mit.edu/cgi-bin/madtoc/1997/mlh/03dec97'
3. experiment.name (string) Example: 'Wide Latitude Substorm Study'
4. experiment.siteid (int) Example: 1
5. experiment.sitename (string) Example: 'Millstone Hill Observatory'
6. experiment.instcode (int) Code of instrument. Example: 30
7. experiment.instname (string) Instrument name. Example: 'Millstone Hill Incoherent Scatter Radar'
8. experiment.start year (int) year of experiment start
9. experiment.start month (int) month of experiment start
10. experiment.start day (int) day of experiment start
11. experiment.start hour (int) hour of experiment start
12. experiment.start minute (int) min of experiment start
13. experiment.start second (int) sec of experiment start
14. experiment.end year (int) year of experiment end
15. experiment.end month (int) month of experiment end
16. experiment.end day (int) day of experiment end
17. experiment.end hour (int) hour of experiment end
18. experiment.end minute (int) min of experiment end
19. experiment.end second (int) sec of experiment end
20. experiment.isLocal (int) 1 if local, 0 if not
21.experiment.PI (string) Experiment PI name Example: 'Phil Erickson'
22. experiment.PIEmail (string) Experiment PI email Example: 'perickson@haystack.mit.edu'
23. utc timestamp of last update to experiment
24. security value
"""
codeList = request.GET.getlist('code')
codeList = [int(code) for code in codeList]
startyear = int(request.GET['startyear'])
startmonth = int(request.GET['startmonth'])
startday = int(request.GET['startday'])
starthour = int(request.GET['starthour'])
startmin = int(request.GET['startmin'])
startsec = int(request.GET['startsec'])
endyear = int(request.GET['endyear'])
endmonth = int(request.GET['endmonth'])
endday = int(request.GET['endday'])
endhour = int(request.GET['endhour'])
endmin = int(request.GET['endmin'])
endsec = int(request.GET['endsec'])
try:
local = int(request.GET['local'])
except:
local = 1
# if startsec or endsec in (60, 61), handle correctly
if startsec in (60, 61):
tmpTime = datetime.datetime(startyear,
startmonth,
startday,
starthour,
startmin,
59)
tmpTime += datetime.timedelta(0, startsec - 59)
startyear = tmpTime.year
startmonth = tmpTime.month
startday = tmpTime.day
starthour = tmpTime.hour
startmin = tmpTime.minute
startsec = tmpTime.second
if endsec in (60, 61):
tmpTime = datetime.datetime(endyear,
endmonth,
endday,
endhour,
endmin,
59)
tmpTime += datetime.timedelta(0, endsec - 59)
endyear = tmpTime.year
endmonth = tmpTime.month
endday = tmpTime.day
endhour = tmpTime.hour
endmin = tmpTime.minute
endsec = tmpTime.second
# if codeList is empty or contains 0, change it to only contain 0
if len(codeList) == 0 or 0 in codeList:
codeList = [0]
retStr = ''
# create MadrigalDB obj
madDBObj = madrigal.metadata.MadrigalDB()
# get the local site id
localSiteId = madDBObj.getSiteID()
# create MadrigalInstrument obj to convert kinst to instrument names
madInstObj = madrigal.metadata.MadrigalInstrument(madDBObj)
# create MadrigalSite obj to convert site id to site name
madSiteObj = madrigal.metadata.MadrigalSite(madDBObj)
madWebObj = madrigal.ui.web.MadrigalWeb(madDBObj)
trusted = madWebObj.isTrusted()
# create starttime for filter, if possible
if startyear != None:
startTimeFilter = datetime.datetime(startyear,
startmonth,
startday,
starthour,
startmin,
startsec)
else:
startTimeFilter = None
# create endtime for filter, if possible
if endyear != None:
endTimeFilter = datetime.datetime(endyear,
endmonth,
endday,
endhour,
endmin,
endsec)
else:
endTimeFilter = None
# create MadrigalExperiments for local or all files
if local == 1:
madExpObj = madrigal.metadata.MadrigalExperiment(madDBObj)
else:
# use file expTabAll.txt to get all experiments
filename = madDBObj.getMadroot()
if filename[-1] != '/':
filename += '/'
filename += 'metadata/expTabAll.txt'
madExpObj = madrigal.metadata.MadrigalExperiment(madDBObj, filename)
madExpObj.sortByDateSite()
# loop through the data
if not startTimeFilter is None:
position = madExpObj.getStartPosition(startTimeFilter)
else:
position = 0
while(True):
thisId = madExpObj.getExpIdByPosition(position)
# check for end
if thisId == None:
break
thisUrl = madExpObj.getExpUrlByPosition(position)
thisName = madExpObj.getExpNameByPosition(position)
thisSiteId = madExpObj.getExpSiteIdByPosition(position)
thisSiteName = madSiteObj.getSiteName(thisSiteId)
thisInstCode = madExpObj.getKinstByPosition(position)
thisInstName =madInstObj.getInstrumentName(thisInstCode)
thisStart = madExpObj.getExpStartDateTimeByPosition(position)
thisEnd = madExpObj.getExpEndDateTimeByPosition(position)
thisSecurity = madExpObj.getSecurityByPosition(position)
if thisSiteId == localSiteId:
thisLocal = 1
else:
thisLocal = 0
thisPI = madExpObj.getPIByPosition(position)
if thisPI in (None, ''):
thisPI = madInstObj.getContactName(thisInstCode)
thisPIEmail = madExpObj.getPIEmailByPosition(position)
if thisPIEmail in (None, ''):
thisPIEmail = madInstObj.getContactEmail(thisInstCode)
expDir = madExpObj.getExpDirByPosition(position)
position += 1
# some experiments set the end of the day to 24:00:00 - not
# technically correct - reset to 23:59:59
if (thisStart[3] == 24 and thisStart[4] == 0 and thisStart[5] == 0):
thisStart[3] = 23
thisStart[4] = 59
thisStart[5] = 59
if (thisEnd[3] == 24 and thisEnd[4] == 0 and thisEnd[5] == 0):
thisEnd[3] = 23
thisEnd[4] = 59
thisEnd[5] = 59
# apply filters
# first apply instrument code filter
if codeList[0] != 0:
if thisInstCode not in codeList:
continue
# apply starttime and endtime filters
thisStartTime = datetime.datetime(thisStart[0],
thisStart[1],
thisStart[2],
thisStart[3],
thisStart[4],
thisStart[5])
thisEndTime = datetime.datetime(thisEnd[0],
thisEnd[1],
thisEnd[2],
thisEnd[3],
thisEnd[4],
thisEnd[5])
if startTimeFilter != None:
if thisEndTime < startTimeFilter:
continue
if endTimeFilter != None:
if thisStartTime > endTimeFilter:
continue
# apply local filer
if local == 1 and thisLocal == 0:
continue
# apply security filter
if trusted == 0 and thisSecurity not in (0,2):
continue
# create exp timestamp
if local == 1:
thisUTTimestamp = int(os.stat(expDir).st_mtime + time.timezone)
else:
thisUTTimestamp = 0
# add this experiment
retStr += '%i,%s,%s,%i,%s,%i,%s,%i,%i,%i,%i,%i,%i,%i,%i,%i,%i,%i,%i,%i,%s,%s,%i,%i\n' % \
(thisId,
thisUrl,
thisName,
thisSiteId,
thisSiteName,
thisInstCode,
thisInstName,
thisStart[0],
thisStart[1],
thisStart[2],
thisStart[3],
thisStart[4],
thisStart[5],
thisEnd[0],
thisEnd[1],
thisEnd[2],
thisEnd[3],
thisEnd[4],
thisEnd[5],
thisLocal,
str(thisPI),
str(thisPIEmail),
thisUTTimestamp,
thisSecurity)
return render(request, 'madweb/service.html', {'text': retStr})
def get_experiment_files_service(request):
"""get_experiment_files_service runs the getExperimentFilesService.py service.
Inputs:
request/url - contains arguments:
id - local experiment id
Returns comma-delimited data, one line for each experiment file, with the following fields:
1. file.name (string) Example '/opt/mdarigal/blah/mlh980120g.001'
2. file.kindat (int) Kindat code. Example: 3001
3. file.kindat desc (string) Kindat description: Example 'Basic Derived Parameters'
4. file.category (int) (1=default, 2=variant, 3=history, 4=real-time)
5. file.status (string)('preliminary', 'final', or any other description)
6. file.permission (int) 0 for public, 1 for private. For now will not return private files.
7. file DOI (string) - citable url to file
Returns empty string if experiment id not found. Skips files that are not Hdf5
"""
id = int(request.GET['id'])
# create MadrigalDB obj
madDBObj = madrigal.metadata.MadrigalDB()
# create MadrigalExperiments object to get full file name
madExpObj = madrigal.metadata.MadrigalExperiment(madDBObj)
# create Madrigal Kindat to get Kindat descriptions
madKindatObj = madrigal.metadata.MadrigalKindat(madDBObj)
madWebObj = madrigal.ui.web.MadrigalWeb(madDBObj)
trusted = madWebObj.isTrusted()
retStr = ''
thisUrl = madExpObj.getExpUrlByExpId(id)
if thisUrl is None:
raise IOError('No such id: %i' % (id))
expPath = madExpObj.getExpDirByExpId(id)
kinst = madExpObj.getKinstByExpId(id)
if os.access(os.path.join(expPath, 'fileTab.txt'), os.R_OK):
madFileObj = madrigal.metadata.MadrigalMetaFile(madDBObj, os.path.join(expPath, 'fileTab.txt'))
for i in range(madFileObj.getFileCount()):
basename = madFileObj.getFilenameByPosition(i)
name = os.path.join(expPath, basename)
base_filename, file_extension = os.path.splitext(name)
if file_extension not in ('.hdf5', '.hdf', '.h5'):
continue
kindat = madFileObj.getKindatByPosition(i)
kindatdesc = madKindatObj.getKindatDescription(kindat, kinst)
category = madFileObj.getCategoryByPosition(i)
status = madFileObj.getStatusByPosition(i)
permission = madFileObj.getAccessByPosition(i)
doi = madFileObj.getFileDOIUrlByPosition(i)
# skip private files if not trusted
if trusted == 0 and int(permission) != 0:
continue
retStr += '%s,%i,%s,%i,%s,%i,%s\n' % \
(name,
kindat,
kindatdesc,
category,
status,
permission,
doi)
return render(request, 'madweb/service.html', {'text': django.utils.safestring.mark_safe(retStr)})
def get_parameters_service(request):
"""get_parameters_service runs the getParametersService.py service.
Inputs:
request/url - contains arguments:
filename=<full path to data file>
Returns backslash-delimited data, one for each parameter either measured or derivable, with the following fields:
1. parameter.mnemonic (string) Example 'dti'
2. parameter.description (string) Example:
"F10.7 Multiday average observed (Ott)"
3. parameter.isError (int) 1 if error parameter, 0 if not
4. parameter.units (string) Example "W/m2/Hz"
5. parameter.isMeasured (int) 1 if measured, 0 if derivable
6. parameter.category (string) Example: "Time Related Parameter"
7. parameter.isSure (int) - 1 if parameter can be found for every record, 0 if can only be found for some.
Not relevant to Madrigal 3, where always 1
8. parameter.isAddIncrement - 1 if additional increment, 0 if normal (Added in Madrigal 2.5)
Not relevant to Madrigal 3, where always -1
"""
filename = request.GET['filename']
# create MadrigalDB obj
madDBObj = madrigal.metadata.MadrigalDB()
# create Madrigal File object
madFileObj = madrigal.data.MadrigalFile(filename, madDBObj)
# create Madrigal Parameter object
madParmObj = madrigal.data.MadrigalParameters(madDBObj)
# create Madrigal web object
madWebObj = madrigal.ui.web.MadrigalWebFormat()
# create lists of parameters
measParmList = []
derivedParmList = []
allParmList = []
sureParmList = []
# use the comprehensive list of parameters to check if derivable
parmList = madWebObj.getFormat('Comprehensive')
# populate lists
madFileObj.getMeasDervBothParmLists(parmList,
measParmList,
derivedParmList,
allParmList,
sureParmList)
retStr = ''
# loop through allParmList and output results
for parm in allParmList:
description = madParmObj.getSimpleParmDescription(parm)
isNorm = madParmObj.getParmType(parm)
if isNorm == 1:
isError = 0
else:
isError = 1
units = madParmObj.getParmUnits(parm)
if parm in measParmList:
isMeasured = 1
else:
isMeasured = 0
if parm in sureParmList:
isSure = 1
else:
isSure = 0
category = madParmObj.getParmCategory(parm)
try:
if madParmObj.isAddIncrement(parm):
isAddIncrement = 1
else:
isAddIncrement = 0
except:
isAddIncrement = -1
# print out this parm
retStr += '%s\\%s\\%i\\%s\\%i\\%s\\%i\\%i\n' % (parm,
description,
isError,
units,
isMeasured,
category,
isSure,
isAddIncrement)
return render(request, 'madweb/service.html', {'text': retStr})
def isprint_service(request):
"""isprint_service runs the isprintService.py service.
Inputs:
request/url - contains arguments:
'file': The full path to the file to be analyzed by isprint. If over 50 MB, returns error message.
'parms': Multiple requested parameters, space (+) separated.
'filters': Multiple of filters desired, as in isprint command
'user_fullname' user name
'user_email' user email
'user_affiliation' user affiliation
'output' - option argument specifying output file basename. Will be Hdf5 format if extension in
('hdf5', 'h5', 'hdf'). Will be netCDF4 is extension is '.nc'. Otherwise ascii. If not
given, output is ascii.
'header': t for headers, f for no header. Defaults to no header. Ignored if not ascii output
Returns data as either column delimited ascii, Hdf5, or netCDF4.
"""
madDB = madrigal.metadata.MadrigalDB()
madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
# get required arguments
thisFile = request.GET['file']
parms = request.GET.getlist('parms')
filters = request.GET.getlist('filters')
user_fullname = request.GET['user_fullname']
user_email = request.GET['user_email']
user_affiliation = request.GET['user_affiliation']
# get optional arguments
try:
output = os.path.basename(request.GET['output'])
filename, file_extension = os.path.splitext(output)
if file_extension in ('.hdf5', '.h5', '.hdf'):
format = 'Hdf5'
elif file_extension in ('.nc',):
format = 'netCDF4'
else:
format = 'ascii'
except:
format = 'ascii'
output = None
# verify thisFile exists, not too big
errorMessage = None
if not os.access(thisFile, os.R_OK):
errorMessage = 'File %s not found' % (thisFile)
elif os.path.getsize(thisFile) > 200.0E6:
errorMessage = 'File %s greater than 200 MB in size - running dynamic file creation not possible. Please use -- download as is -- instead.' % (thisFile)
if not errorMessage is None:
return render(request, 'madweb/service.html', {'text': errorMessage})
if not output is None:
# we need to write to a download file
downloadFile = os.path.join(tempfile.gettempdir(), output)
if os.access(downloadFile, os.R_OK):
try:
os.remove(downloadFile)
except:
pass
try:
header = request.GET['header']
if header not in ('t', 'f'):
raise ValueError('Unknown header value <%s>' % (header))
except:
header = 'f'
# log data access
madWebObj.logDataAccess(thisFile, user_fullname, user_email, user_affiliation)
# run isprint command
cmd = '%s/bin/isprint file=%s ' % (madDB.getMadroot(), thisFile)
if not output is None:
cmd += 'output=%s ' % (downloadFile)
delimiter = ' '
cmd += delimiter.join(parms) + ' '
filterStr = delimiter.join(filters)
cmd += filterStr + ' '
if format == 'ascii':
cmd += 'summary=f '
cmd += 'header=%s ' % (header)
if output is None:
# text response
#result = subprocess.check_output(cmd.split())
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
result,errtext = p.communicate()
if p.returncode != 0:
result = errtext
if type(result) in (bytes, numpy.bytes_):
result = result.decode('utf-8')
if header == 'f':
index = result.find('\n')
result = result[index+1:]
return render(request, 'madweb/service.html', {'text': result})
else:
# file download response
#subprocess.check_call(cmd.split())
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
result,errtext = p.communicate()
if p.returncode != 0:
# write the error to result file
f = open(downloadFile, 'w')
if type(errtext) in (bytes, numpy.bytes_):
errtext = errtext.decode('utf-8')
f.write(errtext)
f.close()
f = open(downloadFile, 'rb')
filename = os.path.basename(downloadFile)
chunk_size = 8192
file_type = mimetypes.guess_type(downloadFile)[0]
if file_type is None:
file_type = 'application/octet-stream'
response = StreamingHttpResponse(FileWrapper(f, chunk_size),
content_type=file_type)
response['Content-Length'] = os.path.getsize(downloadFile)
response['Content-Disposition'] = "attachment; filename=%s" % (filename)
os.remove(downloadFile)
return(response)
def get_madfile_service(request):
"""get_madfile_service runs the getMadfile.cgi service.
Inputs:
request/url - contains arguments:
'fileName': The full path to the file to be downloaded as.
'fileType': -1 for ascii, -2 for Hdf5, -3 for netCDF4. No other values supported
'user_fullname' user name
'user_email' user email
'user_affiliation' user affiliation
Returns file as either column delimited ascii, Hdf5, or netCDF4.
"""
madDB = madrigal.metadata.MadrigalDB()
madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
# get required arguments
fileName = request.GET['fileName']
fileType = int(request.GET['fileType'])
user_fullname = request.GET['user_fullname']
user_email = request.GET['user_email']
user_affiliation = request.GET['user_affiliation']
if fileType not in (-1, -2, -3):
return(HttpResponse('<p>fileType %i not allowed: -1 for ascii, -2 for Hdf5, -3 for netCDF4</p>' % (fileType)))
# log data access
madWebObj.logDataAccess(fileName, user_fullname, user_email, user_affiliation)
if fileType in (-1, -3):
# may need to create temp file
filepath, file_extension = os.path.splitext(fileName)
basename = os.path.basename(filepath)
dirname = os.path.dirname(fileName)
if fileType == -1:
cachedTxtFile = os.path.join(dirname, 'overview', os.path.basename(fileName) + '.txt.gz')
tmpFile = os.path.join(tempfile.gettempdir(), basename + '.txt.gz')
if os.access(cachedTxtFile, os.R_OK):
shutil.copy(cachedTxtFile, tmpFile)
else:
tmpFile = os.path.join(tempfile.gettempdir(), basename + '.txt')
madrigal.cedar.convertToText(fileName, tmpFile)
else:
cachedNCFile = os.path.join(dirname, 'overview', os.path.basename(fileName) + '.nc')
tmpFile = os.path.join(tempfile.gettempdir(), basename + '.nc')
if os.access(cachedNCFile, os.R_OK):
shutil.copy(cachedNCFile, tmpFile)
else:
try:
madrigal.cedar.convertToNetCDF4(fileName, tmpFile)
except IOError:
cedarObj = madrigal.cedar.MadrigalCedarFile(fileName)
cedarObj.write('netCDF4', tmpFile)
else:
tmpFile = fileName
f = open(tmpFile, 'rb')
filename = os.path.basename(tmpFile)
chunk_size = 8192
file_type = mimetypes.guess_type(tmpFile)[0]
if file_type is None:
file_type = 'application/octet-stream'
response = StreamingHttpResponse(FileWrapper(f, chunk_size),
content_type=file_type)
response['Content-Length'] = os.path.getsize(tmpFile)
response['Content-Disposition'] = "attachment; filename=%s" % (filename)
if fileType in (-1, -3):
os.remove(tmpFile)
return(response)
def mad_calculator_service(request):
"""mad_calculator_service runs the madCalculator service.
Inputs:
request/url - contains arguments:
year, month, day, hour, min, sec
startLat - Starting geodetic latitude, -90 to 90 (float)
endLat - Ending geodetic latitude, -90 to 90 (float)
stepLat - Latitude step (0.1 to 90) (float)
startLong - Starting geodetic longitude, -180 to 180 (float)
endLong - Ending geodetic longitude, -180 to 180 (float)
stepLong - Longitude step (0.1 to 180) (float)
startAlt - Starting geodetic altitude, >= 0 (float)
endAlt - Ending geodetic altitude, > 0 (float)
stepAlt - Altitude step (>= 0.1) (float)
parms - comma delimited string of Madrigal parameters desired
oneD - zero or more mnemonics,float values to set input 1D values
Returns comma-delimited data, one line for each combination of lat, long, and alt,
with the following fields:
1. latitude
2. longitude
3. altitude
4. Values for each Madrigal parameter listed in argument parms, separated by whitespace
"""
year = int(request.GET['year'])
month = int(request.GET['month'])
day = int(request.GET['day'])
hour = int(request.GET['hour'])
minute = int(request.GET['min'])
second = int(request.GET['sec'])
try:
dt = datetime.datetime(year, month, day, hour, minute, second)
except:
return(HttpResponse('Illegal time: year %i, month %i, day %i, hour %i, minute %i, second %i' % (year, month, day, hour, minute, second)))
startLat = float(request.GET['startLat'])
endLat = float(request.GET['endLat'])
if startLat == endLat:
endLat += 0.001
elif startLat > endLat:
return(HttpResponse('startLat %s cannot be greater than endLat %s' % (str(startLat), str(endLat))))
stepLat = float(request.GET['stepLat'])
if stepLat < 0.0:
return(HttpResponse('stepLat %s cannot be less than zero' % (str(stepLat))))
elif stepLat == 0.0:
stepLat = 0.001
latList = list(numpy.arange(startLat, endLat, stepLat))
startLong = float(request.GET['startLong'])
endLong = float(request.GET['endLong'])
if startLong == endLong:
endLong += 0.001
elif startLong > endLong:
return(HttpResponse('startLong %s cannot be greater than endLong %s' % (str(startLong), str(endLong))))
stepLong = float(request.GET['stepLong'])
if stepLong < 0.0:
return(HttpResponse('stepLong %s cannot be less than zero' % (str(stepLong))))
elif stepLong == 0.0:
stepLong = 0.001
lonList = list(numpy.arange(startLong, endLong, stepLong))
startAlt = float(request.GET['startAlt'])
endAlt = float(request.GET['endAlt'])
if startAlt == endAlt:
endAlt += 0.001
elif startAlt > endAlt:
return(HttpResponse('startAlt %s cannot be greater than endAlt %s' % (str(startAlt), str(endAlt))))
stepAlt = float(request.GET['stepAlt'])
if stepAlt < 0.0:
return(HttpResponse('stepAlt %s cannot be less than zero' % (str(stepAlt))))
elif stepAlt == 0.0:
stepAlt = 0.01
altList = list(numpy.arange(startAlt, endAlt, stepAlt))
# limit total calculations to 1E5
total = len(latList) * len(lonList) * len(altList)
if total > 1.0E5:
return(HttpResponse('Too many points for madCalculatorService: %i' % (total)))
parms = request.GET['parms']
desiredParmList = [item.strip() for item in ['gdlat','glon','gdalt'] + parms.split(',')]
oneDList = request.GET.getlist('oneD')
oneDParmDict = {}
for oneDStr in oneDList:
mnem, strValue = oneDStr.split(',')
oneDParmDict[mnem] = [float(strValue)]
# capture stdout
old_stdout = sys.stdout
sys.stdout = mystdout = io.StringIO()
madrigal.isprint.MadCalculatorGrid(None, desiredParmList, [dt], latList, lonList, altList,
oneDParmDict, summary=None)
text = mystdout.getvalue()
sys.stdout = old_stdout
return render(request, 'madweb/service.html', {'text': text})
def mad_time_calculator_service(request):
"""mad_time_calculator_service runs the madTimeCalculator service. Input parameters must not be location dependent
Inputs:
request/url - contains arguments:
1. startyear - int
2. startmonth - int
3. startday - int
4. starthour - int
5. startmin - int
6. startsec - int
7. endyear - int
8. endmonth - int
9. endday - int
10. endhour - int
11. endmin - int
12. endsec - int
13. stephours - float - number of hours per time step
14. parms - comma delimited string of Madrigal parameters desired (must not depend on location)
Returns comma-delimited data, one line for each year, month, day, hour, minute, and second,
with the following fields:
1-6: year, month, day, hour, minute, and second
2. requested parm fields
"""
startyear = int(request.GET['startyear'])
startmonth = int(request.GET['startmonth'])
startday = int(request.GET['startday'])
starthour = int(request.GET['starthour'])
startminute = int(request.GET['startmin'])
startsecond = int(request.GET['startsec'])
endyear = int(request.GET['endyear'])
endmonth = int(request.GET['endmonth'])
endday = int(request.GET['endday'])
endhour = int(request.GET['endhour'])
endminute = int(request.GET['endmin'])
endsecond = int(request.GET['endsec'])
dt1 = datetime.datetime(startyear, startmonth, startday, starthour, startminute, startsecond)
dt2 = datetime.datetime(endyear, endmonth, endday, endhour, endminute, endsecond)
if dt1 > dt2:
return(HttpResponse('End Datetime %s cannot be before start datetime %s' % (str(dt2), str(dt1))))
stephours = float(request.GET['stephours'])
if stephours <= 0.0:
return(HttpResponse('stephours cannot be non-positive: %f' % (stephours)))
dtList = []
while dt1 <= dt2:
dtList.append(dt1)
dt1 += datetime.timedelta(hours=stephours)
parms = request.GET['parms']
desiredParmList = [item.strip() for item in ['year','month','day','hour','min','sec'] + parms.split(',')]
# no spatial data
latList = lonList = altList = []
# capture stdout
old_stdout = sys.stdout
sys.stdout = mystdout = io.StringIO()
madrigal.isprint.MadCalculatorGrid(None, desiredParmList, dtList, latList, lonList, altList,
summary=None)
text = mystdout.getvalue()
sys.stdout = old_stdout
return render(request, 'madweb/service.html', {'text': text})
def mad_calculator2_service(request):
"""mad_calculator2_service runs the madCalculator2 service.
Differs from madCalulator in that positions are a list rather than a grid.
Inputs:
request/url - contains arguments:
year, month, day, hour, min, sec
lats - comma separated list of latitudes to analyze
longs - comma separated list of longitudes to analyze. Len must == len(lats)
alts - comma separated list of altitudes to analyze. Len must == len(lats)
parms - comma delimited string of Madrigal parameters desired
oneD - zero or more mnemonics,float values to set input 1D values
Example: &oneD=kinst,31.0&oneD=elm,45.0
twoD - zero or more mnemonics,comma-separate float list of len(lats) to set input 2D values
Example: twoD=te,1000,1100,1200 twoD=ti,1000,1000,1000
where there are 3 lats
Returns comma-delimited data, one line for each lat value,
with the following fields:
1. latitude
2. longitude
3. altitude
4. Values for each Madrigal parameter listed in argument parms, separated by whitespace
"""
if request.method == 'POST':
reqDict = request.POST
else:
reqDict = request.GET
try:
year = int(reqDict.get('year'))
except TypeError:
return(HttpResponse('<p>madCalculator2Service requires year</p>'))
month = int(reqDict['month'])
day = int(reqDict['day'])
hour = int(reqDict['hour'])
minute = int(reqDict['min'])
second = int(reqDict['sec'])
dt = datetime.datetime(year, month, day, hour, minute, second)
latsStr = reqDict['lats']
lats = [float(item) for item in latsStr.split(',')]
longsStr = reqDict['longs']
longs = [float(item) for item in longsStr.split(',')]
altsStr = reqDict['alts']
alts = [float(item) for item in altsStr.split(',')]
parms = reqDict['parms']
desiredParmList = [item.strip() for item in ['gdlat','glon','gdalt'] + parms.split(',')]
oneDList = reqDict.getlist('oneD')
oneDParmDict = {}
for oneDStr in oneDList:
mnem, strValue = oneDStr.split(',')
oneDParmDict[mnem] = [float(strValue)]
twoDList = reqDict.getlist('twoD')
twoDParmDict = {}
for twoDStr in twoDList:
items = twoDStr.split(',')
if len(items) != 1 + len(lats):
raise ValueError('twoDstr %s not correct number of points' % (str(twoDStr)))
mnem = items[0]
floatValues = [float(item) for item in items[1:]]
# now we need to expand these values to be two dimensional 1 x len(lats)
values = numpy.zeros((1,len(lats)), dtype=numpy.float)
values[0][:] = floatValues
twoDParmDict[mnem] = values
# capture stdout
old_stdout = sys.stdout
sys.stdout = mystdout = io.StringIO()
madrigal.isprint.MadCalculatorList(None, desiredParmList, [dt], lats, longs, alts,
oneDParmDict, twoDParmDict, summary=None)
text = mystdout.getvalue()
sys.stdout = old_stdout
return render(request, 'madweb/service.html', {'text': text})
def mad_calculator3_service(request):
"""mad_calculator3_service runs the madCalculator3 service.
Differs from madCalulator in that multiple times, each with a unique list of positions, can be passed in.
Inputs:
request/url - contains arguments:
year - a comma-separated list of years - (required)
month - a comma-separated list of months - (required)
day - a comma-separated list of days - (required)
hour - a comma-separated list of hours - (required)
min - a comma-separated list of minutes - (required)
sec - a comma-separated list of seconds - (required)
numPos - a comma-sepatated list of the number of positions for each time - (required)
lats - a comma-separated list of geodetic latitudes, -90 to 90 (required). Listed
for first time, then second, etc. Total must be equal to the sum
of numPos.
longs - a comma-separated list of longitudes (required) Listed
for first time, then second, etc. Total must be equal to the sum
of numPos.
alts - a comma-separated list of geodetic altitudes in km (required) Listed
for first time, then second, etc. Total must be equal to the sum
of numPos.
parms - comma delimited string of Madrigal parameters desired (required)
oneD - string in form <parm>,<comma-separated values> This argument allows the user to
set any number of one-D parameters to be used in the calculation.
Value must be parameter name, comma, list of values as double,
where length of list is equal to number of times.
Example: &oneD=kinst,31.0,31.0&oneD=elm,45.0,50
(optional - 0 or more allowed)
twoD=<parm>,<values> (optional - 0 or more allowed) This argument allows the user to
set any number of two-D parameters to be used in the calculation.
Value must be parameter name, comma, comma-separated values.
Number of values must equal the sum of numPos. Order is
first time values first, then second time values, etc
Example: twoD=te,1000,1100,1200,1000,1100,1200 &twoD=ti,1000,1000,1000,1000,1000,1000
where numPos=3,3
Returns comma-delimited data, one line for each location. Separate times are delimited by line
TIME MM/DD/YYYY HH:MM:SS
Data lines have the following fields:
1. latitude
2. longitude
3. altitude
4. Values for each Madrigal parameter listed in argument parms, separated by whitespace
"""
if request.method == 'POST':
reqDict = request.POST
else:
reqDict = request.GET
try:
yearList = [int(item) for item in reqDict.get('year').split(',')]
except AttributeError:
return(HttpResponse('<p>madCalculator3Service requires year</p>'))
monthList = [int(item) for item in reqDict.get('month').split(',')]
dayList = [int(item) for item in reqDict.get('day').split(',')]
hourList = [int(item) for item in reqDict.get('hour').split(',')]
minList = [int(item) for item in reqDict.get('min').split(',')]
secList = [int(item) for item in reqDict.get('sec').split(',')]
dtList = [datetime.datetime(yearList[i], monthList[i], dayList[i],
hourList[i], minList[i], secList[i]) for i in range(len(yearList))]
numPosStr = reqDict['numPos']
numPosList = [int(item) for item in numPosStr.split(',')]
totalPos = 0
for numPos in numPosList:
totalPos += numPos
latsStr = reqDict['lats']
lats = [float(item) for item in latsStr.split(',')]
if len(lats) != totalPos:
return(HttpResponse('wrong number of lats, expected %i' % (totalPos)))
longsStr = reqDict['longs']
longs = [float(item) for item in longsStr.split(',')]
if len(longs) != totalPos:
return(HttpResponse('wrong number of longs, expected %i' % (totalPos)))
altsStr = reqDict['alts']
alts = [float(item) for item in altsStr.split(',')]
if len(alts) != totalPos:
return(HttpResponse('wrong number of alts, expected %i' % (totalPos)))
parms = reqDict['parms']
desiredParmList = [item.strip() for item in ['gdlat','glon','gdalt'] + parms.split(',')]
oneDList = reqDict.getlist('oneD')
twoDList = reqDict.getlist('twoD')
# since the positions can change with each call, we need to call madrigal.isprint.MadCalculatorGrid once for each time
startIndex = 0
endIndex = 0
fullText = ''
for timeIndex, numPos in enumerate(numPosList):
startIndex = endIndex
endIndex += numPos
thisLats = lats[startIndex:endIndex]
thisLongs = longs[startIndex:endIndex]
thisAlts = alts[startIndex:endIndex]
oneDParmDict = {}
for oneDStr in oneDList:
values = oneDStr.split(',')
if len(values) != 1+len(dtList):
return(HttpResponse('wrong number of values given for 1D parm %s' % (values[0])))
oneDParmDict[values[0]] = [float(values[timeIndex+1])]
twoDParmDict = {}
for twoDStr in twoDList:
values = twoDStr.split(',')
if len(values) != 1 + totalPos:
return(HttpResponse('twoDstr %s not correct number of points' % (str(twoDStr))))
mnem = values[0]
floatValues = [float(item) for item in values[1+startIndex:1+endIndex]]
# now we need to expand these values to be two dimensional - 1,len(thisLats)
values2D = numpy.zeros((1,len(thisLats)), dtype=numpy.float)
values2D[0][:] = floatValues
twoDParmDict[mnem] = values2D
# capture stdout
old_stdout = sys.stdout
sys.stdout = mystdout = io.StringIO()
madrigal.isprint.MadCalculatorList(None, desiredParmList, [dtList[timeIndex]], thisLats,
thisLongs, thisAlts,
oneDParmDict, twoDParmDict, summary=None)
text = mystdout.getvalue()
sys.stdout = old_stdout
fullText += 'TIME %s\n' % (dtList[timeIndex].strftime('%m/%d/%Y %H:%M:%S'))
fullText += text
return render(request, 'madweb/service.html', {'text': fullText})
def geodetic_to_radar_service(request):
"""geodetic_to_radar_service runs the geodeticToRadar service.
Inputs:
request/url - contains arguments:
slatgd - radar geodetic latitude
slon - radar longitude
saltgd - radar geodetic altitude
gdlat - a comma-separated list of geodetic latitude of point
glon - a comma-separated list of longitude of point. Len must be same as gdlat
gdalt - a comma-separated list of geodetic altitude of point. Len must be same as gdlat
Returns comma-delimited data, one line for point in lists (points treated as individual combinations, not grids):
1. radar azimuth in degrees (0 = north)
2. radar elevation in degrees
3. radar range in km
"""
slatgd = float(request.GET['slatgd'])
slon = float(request.GET['slon'])
saltgd = float(request.GET['saltgd'])
oneDParmDict = {'GDLATR': [slatgd],
'GDLONR': [slon],
'GALTR': [saltgd]}
gdlatStr = request.GET['gdlat']
gdlatList = [float(item) for item in gdlatStr.split(',')]
glonStr = request.GET['glon']
glonList = [float(item) for item in glonStr.split(',')]
gdaltStr = request.GET['gdalt']
gdaltList = [float(item) for item in gdaltStr.split(',')]
desiredParmList = ['azm', 'elm', 'range']
dtList = [datetime.datetime(2001,1,1)] # not relevant
if len(gdlatList) != len(glonList) or len(gdlatList) != len(gdaltList):
return(HttpResponse('all point list lengths must be equal'))
fullText = ''
delimiter = ','
for i in range(len(gdlatList)):
# capture stdout
old_stdout = sys.stdout
sys.stdout = mystdout = io.StringIO()
madrigal.isprint.MadCalculatorGrid(None, desiredParmList, dtList, [gdlatList[i]],
[glonList[i]], [gdaltList[i]], summary=None,
oneDParmDict=oneDParmDict)
text = mystdout.getvalue()
sys.stdout = old_stdout
for line in text.split('\n'):
items = line.split()
fullText += delimiter.join(items) + '\n'
return render(request, 'madweb/service.html', {'text': fullText})
def radar_to_geodetic_service(request):
"""radar_to_geodetic_service runs the radarToGeodetic service.
Inputs:
request/url - contains arguments:
slatgd - radar geodetic latitude
slon - radar longitude
saltgd - radar geodetic altitude
azs - a comma-separated list of azimuths of point
els - a comma-separated list of elevations of point. Len must be same as azs
ranges - a comma-separated list of ranges to point. Len must be same as azs
Returns comma-delimited data, one line for point in lists (points treated as individual combinations, not grids):
1. geodetic latitude
2. longitude (-180 to 180)
3. geodetic altitude in km
"""
slatgd = float(request.GET['slatgd'])
slon = float(request.GET['slon'])
saltgd = float(request.GET['saltgd'])
azStr = request.GET['az']
azList = [float(item) for item in azStr.split(',')]
elStr = request.GET['el']
elList = [float(item) for item in elStr.split(',')]
rangeStr = request.GET['range']
rangeList = [float(item) for item in rangeStr.split(',')]
if len(azList) != len(elList) or len(azList) != len(rangeList):
return(HttpResponse('all point list lengths must be equal'))
fullText = ''
for i in range(len(azList)):
gdlat,glon,gdalt = madrigal._derive.radarToGeodetic(slatgd, slon, saltgd,
azList[i], elList[i], rangeList[i])
fullText += '%f,%f,%f\n' % (gdlat,glon,gdalt)
return render(request, 'madweb/service.html', {'text': fullText})
def list_file_times_service(request):
"""list_file_times_service runs the listFileTimes service.
Inputs:
request/url - contains arguments:
Optional: expDir - experiment directory to list. Can be absolute or relative to
experiments[0-9]*. Default is all files in $MADROOT/experiments*
Returns comma-delimited data, one for each file:
1. Full path of file
2. File modification time in form YYYY-MM-DD HH:MM:SS (UT time)
"""
expDir = None
try:
expDir = request.GET['expDir']
except:
pass
madDB = madrigal.metadata.MadrigalDB()
fileList = madDB.listFileTimes(expDir)
fullText = '\n\n'
for filename, filetime in fileList:
fullText += "\'%s\', %s\n" % (filename, filetime.strftime('%Y-%m-%d %H:%M:%S'))
return render(request, 'madweb/service.html', {'text': django.utils.safestring.mark_safe(fullText)})
def download_web_file_service(request):
"""download_web_file_service runs the downloadWebFile service.
Inputs:
request/url - contains arguments:
expPath - path to file starting at experiments*
Returns comma-delimited data, one for each file:
1. Full path of file
2. File modification time in form YYYY-MM-DD HH:MM:SS (UT time)
"""
expPath = request.GET['expPath']
madDB = madrigal.metadata.MadrigalDB()
downloadFile = os.path.join(madDB.getMadroot(), expPath)
f = open(downloadFile, 'rb')
thisFile = django.core.files.File(f)
response = HttpResponse(thisFile, content_type='application/x-octet-stream')
response['Content-Disposition'] = 'attachment; filename="' + os.path.basename(downloadFile) + '"'
response['Content-Length'] = os.path.getsize(downloadFile)
return(response)
def trace_magnetic_field_service(request):
"""trace_magnetic_field_service runs the traceMagneticField service.
Inputs:
request/url - contains arguments:
year, month, day, hour, min, sec
inputType (0 for geodetic, 1 for GSM)
outputType (0 for geodetic, 1 for GSM)
The following parameter depend on inputType:
in1 - a comma-separated list of geodetic altitudes or ZGSMs of starting point
in2 - a comma-separated list of geodetic latitudes or XGSMs of starting point
in3 - a comma-separated list of longitude or YGSM of starting point
Length of all three lists must be the same
model - 0 for Tsyganenko, 1 for IGRF
qualifier - 0 for conjugate, 1 for north_alt, 2 for south_alt, 3 for apex, 4 for GSM XY plane
stopAlt - altitude in km to stop trace at, if qualifier is north_alt or south_alt.
If other qualifier, this parameter is not required.
Returns comma-delimited data, one line for point in in lists:
1. geodetic altitude or ZGSM of ending point
2. geodetic latitude or XGSM of ending point
3. longitude or YGSM of ending point
"""
year = int(request.GET['year'])
month = int(request.GET['month'])
day = int(request.GET['day'])
hour = int(request.GET['hour'])
minute = int(request.GET['min'])
second = int(request.GET['sec'])
dt = datetime.datetime(year, month, day, hour, minute, second)
inputType = int(request.GET['inputType'])
if inputType not in (0,1):
return(HttpResponse('inputType must be 0 or 1, not %i' % (inputType)))
outputType = int(request.GET['outputType'])
if outputType not in (0,1):
return(HttpResponse('outputType must be 0 or 1, not %i' % (outputType)))
in1Str = request.GET['in1']
in1List = [float(item) for item in in1Str.split(',')]
in2Str = request.GET['in2']
in2List = [float(item) for item in in2Str.split(',')]
in3Str = request.GET['in3']
in3List = [float(item) for item in in3Str.split(',')]
if len(in1List) != len(in2List) or len(in1List) != len(in3List):
return(HttpResponse('All three in* lists must have same length'))
model = int(request.GET['model'])
if model not in (0,1):
return(HttpResponse('model must be 0 or 1, not %i' % (model)))
qualifier = int(request.GET['qualifier'])
if qualifier not in (0,1,2,3,4):
return(HttpResponse('model must be in 0,1,2,3,4 not %i' % (model)))
try:
stopAlt = float(request.GET['stopAlt'])
except:
stopAlt = 0.0
fullText = ''
resultArr = numpy.zeros((3,), dtype='f8')
madDB = madrigal.metadata.MadrigalDB()
madDeriveObj = madrigal.derivation.MadrigalDerivationMethods(madDB.getMadroot())
for i in range(len(in1List)):
madDeriveObj.traceMagneticField(year, month, day, hour, minute, second,
inputType, outputType, in1List[i], in2List[i], in3List[i],
model, qualifier, stopAlt, resultArr)
fullText += '%f,%f,%f\n' % (resultArr[0], resultArr[1], resultArr[2])
return render(request, 'madweb/service.html', {'text': fullText})
def global_file_search_service(request):
"""global_file_search_service returns a list of full paths to files or citable urls based on search arguments
Inputs:
request/url - contains arguments:
startDate: start date in form YYYY-MM-DD to filter experiments before
endDate: end date in form YYYY-MM-DD to filter experiments after
inst: (optional, multiple allowed) an instrument code or name. For names,
fnmatch will be used. If not set, all instruments used.
kindat: (optional, multiple allowed) a kind of data codes or name. For names,
fnmatch will be used. If not set, all kinds of data used.
seasonalStartDate: (optional) in form MM/DD, rejects all days earlier in year. If not set
implies 01/01
seasonalEndDate: (optional) in form MM/DD, rejects all days later in year. If not set
implies 12/31
includeNonDefault: (optional) if "True", include realtime files when there are no default.
If not set, only default files.
expName: (optional) - filter experiments by the experiment name. fnmatch rules
If not set, no filtering by experiment name.
excludeExpName: (optional) - exclude experiments by the experiment name. fnmatch rules
If not set, no excluding experiments by experiment name.
fileDesc: (optional) filter files using input file Description string via fnmatch.
If not set, in no filtering by file name
returnCitation: (optional) if True, return a list of file citations. If not set, return
a list of full paths to the files selected
"""
madDB = madrigal.metadata.MadrigalDB()
madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
# get required arguments
startDate = request.GET['startDate']
endDate = request.GET['endDate']
startDate = datetime.datetime.strptime(startDate, '%Y-%m-%d')
endDate = datetime.datetime.strptime(endDate, '%Y-%m-%d')
# get optional arguments
inst = request.GET.getlist('inst')
if inst == []:
inst = None
kindat = request.GET.getlist('kindat')
if kindat == []:
kindat = None
seasonalStartDate = request.GET.get('seasonalStartDate', default = None)
seasonalEndDate = request.GET.get('seasonalEndDate', default = None)
includeNonDefault = bool(request.GET.get('includeNonDefault', default = False))
expName = request.GET.get('expName', default = None)
excludeExpName = request.GET.get('excludeExpName', default = None)
fileDesc = request.GET.get('fileDesc', default = None)
returnCitation = bool(request.GET.get('returnCitation', default = False))
result = madWebObj.global_file_search(startDate, endDate, inst, kindat,
seasonalStartDate, seasonalEndDate,
includeNonDefault, expName, excludeExpName,
fileDesc, returnCitation)
fullText = ''
for item in result:
fullText += '%s\n' % (item)
return render(request, 'madweb/service.html', {'text': django.utils.safestring.mark_safe(fullText)})
def get_url_list_from_group_id_service(request):
"""get_url_list_from_group_id_service returns a list of citable urls associated with group id.
Inputs:
request/url - contains arguments:
id - group id
Returns one line for each citable url
Returns empty string if experiment id not found. Skips files that are not Hdf5
"""
id = int(request.GET['id'])
# create MadrigalDB obj
madDBObj = madrigal.metadata.MadrigalDB()
urlList = madDBObj.getListFromGroupId(id)
retStr = ''
for url in urlList:
retStr += '%s\n' % (url)
return render(request, 'madweb/service.html', {'text': django.utils.safestring.mark_safe(retStr)})
def set_group_id_from_url_list_service(request):
"""set_group_id_from_url_list sets a list of citable urls to a group id .
Inputs:
request/url - contains arguments:
'user_fullname' user name
'user_email' user email
'user_affiliation' user affiliation
'url' - citable url. Multiple arguments allowed
Returns group id (integer) set
"""
madDB = madrigal.metadata.MadrigalDB()
print(request.GET)
# get required arguments
urls = request.GET.getlist('url')
user_fullname = request.GET['user_fullname']
user_email = request.GET['user_email']
user_affiliation = request.GET['user_affiliation']
id = madDB.createGroupIdWithList(user_fullname, user_email, user_affiliation, urls)
return render(request, 'madweb/service.html', {'text': str(id)})
Functions
def download_web_file_service(request)
-
download_web_file_service runs the downloadWebFile service.
Inputs
request/url - contains arguments:
expPath - path to file starting at experiments*
Returns comma-delimited data, one for each file:
1. Full path of file 2. File modification time in form YYYY-MM-DD HH:MM:SS (UT time)
Expand source code
def download_web_file_service(request): """download_web_file_service runs the downloadWebFile service. Inputs: request/url - contains arguments: expPath - path to file starting at experiments* Returns comma-delimited data, one for each file: 1. Full path of file 2. File modification time in form YYYY-MM-DD HH:MM:SS (UT time) """ expPath = request.GET['expPath'] madDB = madrigal.metadata.MadrigalDB() downloadFile = os.path.join(madDB.getMadroot(), expPath) f = open(downloadFile, 'rb') thisFile = django.core.files.File(f) response = HttpResponse(thisFile, content_type='application/x-octet-stream') response['Content-Disposition'] = 'attachment; filename="' + os.path.basename(downloadFile) + '"' response['Content-Length'] = os.path.getsize(downloadFile) return(response)
def geodetic_to_radar_service(request)
-
geodetic_to_radar_service runs the geodeticToRadar service.
Inputs
request/url - contains arguments:
slatgd - radar geodetic latitude
slon - radar longitude
saltgd - radar geodetic altitude
gdlat - a comma-separated list of geodetic latitude of point
glon - a comma-separated list of longitude of point. Len must be same as gdlat
gdalt - a comma-separated list of geodetic altitude of point. Len must be same as gdlat
Returns comma-delimited data, one line for point in lists (points treated as individual combinations, not grids):
1. radar azimuth in degrees (0 = north) 2. radar elevation in degrees 3. radar range in km
Expand source code
def geodetic_to_radar_service(request): """geodetic_to_radar_service runs the geodeticToRadar service. Inputs: request/url - contains arguments: slatgd - radar geodetic latitude slon - radar longitude saltgd - radar geodetic altitude gdlat - a comma-separated list of geodetic latitude of point glon - a comma-separated list of longitude of point. Len must be same as gdlat gdalt - a comma-separated list of geodetic altitude of point. Len must be same as gdlat Returns comma-delimited data, one line for point in lists (points treated as individual combinations, not grids): 1. radar azimuth in degrees (0 = north) 2. radar elevation in degrees 3. radar range in km """ slatgd = float(request.GET['slatgd']) slon = float(request.GET['slon']) saltgd = float(request.GET['saltgd']) oneDParmDict = {'GDLATR': [slatgd], 'GDLONR': [slon], 'GALTR': [saltgd]} gdlatStr = request.GET['gdlat'] gdlatList = [float(item) for item in gdlatStr.split(',')] glonStr = request.GET['glon'] glonList = [float(item) for item in glonStr.split(',')] gdaltStr = request.GET['gdalt'] gdaltList = [float(item) for item in gdaltStr.split(',')] desiredParmList = ['azm', 'elm', 'range'] dtList = [datetime.datetime(2001,1,1)] # not relevant if len(gdlatList) != len(glonList) or len(gdlatList) != len(gdaltList): return(HttpResponse('all point list lengths must be equal')) fullText = '' delimiter = ',' for i in range(len(gdlatList)): # capture stdout old_stdout = sys.stdout sys.stdout = mystdout = io.StringIO() madrigal.isprint.MadCalculatorGrid(None, desiredParmList, dtList, [gdlatList[i]], [glonList[i]], [gdaltList[i]], summary=None, oneDParmDict=oneDParmDict) text = mystdout.getvalue() sys.stdout = old_stdout for line in text.split('\n'): items = line.split() fullText += delimiter.join(items) + '\n' return render(request, 'madweb/service.html', {'text': fullText})
def get_experiment_files_service(request)
-
get_experiment_files_service runs the getExperimentFilesService.py service.
Inputs
request/url - contains arguments:
id - local experiment id
Returns comma-delimited data, one line for each experiment file, with the following fields:
1. file.name (string) Example '/opt/mdarigal/blah/mlh980120g.001' 2. file.kindat (int) Kindat code. Example: 3001 3. file.kindat desc (string) Kindat description: Example 'Basic Derived Parameters' 4. file.category (int) (1=default, 2=variant, 3=history, 4=real-time) 5. file.status (string)('preliminary', 'final', or any other description) 6. file.permission (int) 0 for public, 1 for private. For now will not return private files. 7. file DOI (string) - citable url to file
Returns empty string if experiment id not found. Skips files that are not Hdf5
Expand source code
def get_experiment_files_service(request): """get_experiment_files_service runs the getExperimentFilesService.py service. Inputs: request/url - contains arguments: id - local experiment id Returns comma-delimited data, one line for each experiment file, with the following fields: 1. file.name (string) Example '/opt/mdarigal/blah/mlh980120g.001' 2. file.kindat (int) Kindat code. Example: 3001 3. file.kindat desc (string) Kindat description: Example 'Basic Derived Parameters' 4. file.category (int) (1=default, 2=variant, 3=history, 4=real-time) 5. file.status (string)('preliminary', 'final', or any other description) 6. file.permission (int) 0 for public, 1 for private. For now will not return private files. 7. file DOI (string) - citable url to file Returns empty string if experiment id not found. Skips files that are not Hdf5 """ id = int(request.GET['id']) # create MadrigalDB obj madDBObj = madrigal.metadata.MadrigalDB() # create MadrigalExperiments object to get full file name madExpObj = madrigal.metadata.MadrigalExperiment(madDBObj) # create Madrigal Kindat to get Kindat descriptions madKindatObj = madrigal.metadata.MadrigalKindat(madDBObj) madWebObj = madrigal.ui.web.MadrigalWeb(madDBObj) trusted = madWebObj.isTrusted() retStr = '' thisUrl = madExpObj.getExpUrlByExpId(id) if thisUrl is None: raise IOError('No such id: %i' % (id)) expPath = madExpObj.getExpDirByExpId(id) kinst = madExpObj.getKinstByExpId(id) if os.access(os.path.join(expPath, 'fileTab.txt'), os.R_OK): madFileObj = madrigal.metadata.MadrigalMetaFile(madDBObj, os.path.join(expPath, 'fileTab.txt')) for i in range(madFileObj.getFileCount()): basename = madFileObj.getFilenameByPosition(i) name = os.path.join(expPath, basename) base_filename, file_extension = os.path.splitext(name) if file_extension not in ('.hdf5', '.hdf', '.h5'): continue kindat = madFileObj.getKindatByPosition(i) kindatdesc = madKindatObj.getKindatDescription(kindat, kinst) category = madFileObj.getCategoryByPosition(i) status = madFileObj.getStatusByPosition(i) permission = madFileObj.getAccessByPosition(i) doi = madFileObj.getFileDOIUrlByPosition(i) # skip private files if not trusted if trusted == 0 and int(permission) != 0: continue retStr += '%s,%i,%s,%i,%s,%i,%s\n' % \ (name, kindat, kindatdesc, category, status, permission, doi) return render(request, 'madweb/service.html', {'text': django.utils.safestring.mark_safe(retStr)})
def get_experiments_service(request)
-
get_experiments_service runs the getExperimentsService.py service.
Inputs
request/url - contains arguments:
code - one or more kindat values startyear, startmonth, startday, starthour, startmin, startsec endyear, endmonth, endday, endhour, endmin, endsec local (defaults to True)
Returns comma-delimited data, one line for each experiment, with the following fields:
1. experiment.id (int) Example: 10000111 2. experiment.url (string) Example: 'http://www.haystack.mit.edu/cgi-bin/madtoc/1997/mlh/03dec97' 3. experiment.name (string) Example: 'Wide Latitude Substorm Study' 4. experiment.siteid (int) Example: 1 5. experiment.sitename (string) Example: 'Millstone Hill Observatory' 6. experiment.instcode (int) Code of instrument. Example: 30 7. experiment.instname (string) Instrument name. Example: 'Millstone Hill Incoherent Scatter Radar' 8. experiment.start year (int) year of experiment start 9. experiment.start month (int) month of experiment start 10. experiment.start day (int) day of experiment start 11. experiment.start hour (int) hour of experiment start 12. experiment.start minute (int) min of experiment start 13. experiment.start second (int) sec of experiment start 14. experiment.end year (int) year of experiment end 15. experiment.end month (int) month of experiment end 16. experiment.end day (int) day of experiment end 17. experiment.end hour (int) hour of experiment end 18. experiment.end minute (int) min of experiment end 19. experiment.end second (int) sec of experiment end 20. experiment.isLocal (int) 1 if local, 0 if not 21.experiment.PI (string) Experiment PI name Example: 'Phil Erickson' 22. experiment.PIEmail (string) Experiment PI email Example: 'perickson@haystack.mit.edu' 23. utc timestamp of last update to experiment 24. security value
Expand source code
def get_experiments_service(request): """get_experiments_service runs the getExperimentsService.py service. Inputs: request/url - contains arguments: code - one or more kindat values startyear, startmonth, startday, starthour, startmin, startsec endyear, endmonth, endday, endhour, endmin, endsec local (defaults to True) Returns comma-delimited data, one line for each experiment, with the following fields: 1. experiment.id (int) Example: 10000111 2. experiment.url (string) Example: 'http://www.haystack.mit.edu/cgi-bin/madtoc/1997/mlh/03dec97' 3. experiment.name (string) Example: 'Wide Latitude Substorm Study' 4. experiment.siteid (int) Example: 1 5. experiment.sitename (string) Example: 'Millstone Hill Observatory' 6. experiment.instcode (int) Code of instrument. Example: 30 7. experiment.instname (string) Instrument name. Example: 'Millstone Hill Incoherent Scatter Radar' 8. experiment.start year (int) year of experiment start 9. experiment.start month (int) month of experiment start 10. experiment.start day (int) day of experiment start 11. experiment.start hour (int) hour of experiment start 12. experiment.start minute (int) min of experiment start 13. experiment.start second (int) sec of experiment start 14. experiment.end year (int) year of experiment end 15. experiment.end month (int) month of experiment end 16. experiment.end day (int) day of experiment end 17. experiment.end hour (int) hour of experiment end 18. experiment.end minute (int) min of experiment end 19. experiment.end second (int) sec of experiment end 20. experiment.isLocal (int) 1 if local, 0 if not 21.experiment.PI (string) Experiment PI name Example: 'Phil Erickson' 22. experiment.PIEmail (string) Experiment PI email Example: 'perickson@haystack.mit.edu' 23. utc timestamp of last update to experiment 24. security value """ codeList = request.GET.getlist('code') codeList = [int(code) for code in codeList] startyear = int(request.GET['startyear']) startmonth = int(request.GET['startmonth']) startday = int(request.GET['startday']) starthour = int(request.GET['starthour']) startmin = int(request.GET['startmin']) startsec = int(request.GET['startsec']) endyear = int(request.GET['endyear']) endmonth = int(request.GET['endmonth']) endday = int(request.GET['endday']) endhour = int(request.GET['endhour']) endmin = int(request.GET['endmin']) endsec = int(request.GET['endsec']) try: local = int(request.GET['local']) except: local = 1 # if startsec or endsec in (60, 61), handle correctly if startsec in (60, 61): tmpTime = datetime.datetime(startyear, startmonth, startday, starthour, startmin, 59) tmpTime += datetime.timedelta(0, startsec - 59) startyear = tmpTime.year startmonth = tmpTime.month startday = tmpTime.day starthour = tmpTime.hour startmin = tmpTime.minute startsec = tmpTime.second if endsec in (60, 61): tmpTime = datetime.datetime(endyear, endmonth, endday, endhour, endmin, 59) tmpTime += datetime.timedelta(0, endsec - 59) endyear = tmpTime.year endmonth = tmpTime.month endday = tmpTime.day endhour = tmpTime.hour endmin = tmpTime.minute endsec = tmpTime.second # if codeList is empty or contains 0, change it to only contain 0 if len(codeList) == 0 or 0 in codeList: codeList = [0] retStr = '' # create MadrigalDB obj madDBObj = madrigal.metadata.MadrigalDB() # get the local site id localSiteId = madDBObj.getSiteID() # create MadrigalInstrument obj to convert kinst to instrument names madInstObj = madrigal.metadata.MadrigalInstrument(madDBObj) # create MadrigalSite obj to convert site id to site name madSiteObj = madrigal.metadata.MadrigalSite(madDBObj) madWebObj = madrigal.ui.web.MadrigalWeb(madDBObj) trusted = madWebObj.isTrusted() # create starttime for filter, if possible if startyear != None: startTimeFilter = datetime.datetime(startyear, startmonth, startday, starthour, startmin, startsec) else: startTimeFilter = None # create endtime for filter, if possible if endyear != None: endTimeFilter = datetime.datetime(endyear, endmonth, endday, endhour, endmin, endsec) else: endTimeFilter = None # create MadrigalExperiments for local or all files if local == 1: madExpObj = madrigal.metadata.MadrigalExperiment(madDBObj) else: # use file expTabAll.txt to get all experiments filename = madDBObj.getMadroot() if filename[-1] != '/': filename += '/' filename += 'metadata/expTabAll.txt' madExpObj = madrigal.metadata.MadrigalExperiment(madDBObj, filename) madExpObj.sortByDateSite() # loop through the data if not startTimeFilter is None: position = madExpObj.getStartPosition(startTimeFilter) else: position = 0 while(True): thisId = madExpObj.getExpIdByPosition(position) # check for end if thisId == None: break thisUrl = madExpObj.getExpUrlByPosition(position) thisName = madExpObj.getExpNameByPosition(position) thisSiteId = madExpObj.getExpSiteIdByPosition(position) thisSiteName = madSiteObj.getSiteName(thisSiteId) thisInstCode = madExpObj.getKinstByPosition(position) thisInstName =madInstObj.getInstrumentName(thisInstCode) thisStart = madExpObj.getExpStartDateTimeByPosition(position) thisEnd = madExpObj.getExpEndDateTimeByPosition(position) thisSecurity = madExpObj.getSecurityByPosition(position) if thisSiteId == localSiteId: thisLocal = 1 else: thisLocal = 0 thisPI = madExpObj.getPIByPosition(position) if thisPI in (None, ''): thisPI = madInstObj.getContactName(thisInstCode) thisPIEmail = madExpObj.getPIEmailByPosition(position) if thisPIEmail in (None, ''): thisPIEmail = madInstObj.getContactEmail(thisInstCode) expDir = madExpObj.getExpDirByPosition(position) position += 1 # some experiments set the end of the day to 24:00:00 - not # technically correct - reset to 23:59:59 if (thisStart[3] == 24 and thisStart[4] == 0 and thisStart[5] == 0): thisStart[3] = 23 thisStart[4] = 59 thisStart[5] = 59 if (thisEnd[3] == 24 and thisEnd[4] == 0 and thisEnd[5] == 0): thisEnd[3] = 23 thisEnd[4] = 59 thisEnd[5] = 59 # apply filters # first apply instrument code filter if codeList[0] != 0: if thisInstCode not in codeList: continue # apply starttime and endtime filters thisStartTime = datetime.datetime(thisStart[0], thisStart[1], thisStart[2], thisStart[3], thisStart[4], thisStart[5]) thisEndTime = datetime.datetime(thisEnd[0], thisEnd[1], thisEnd[2], thisEnd[3], thisEnd[4], thisEnd[5]) if startTimeFilter != None: if thisEndTime < startTimeFilter: continue if endTimeFilter != None: if thisStartTime > endTimeFilter: continue # apply local filer if local == 1 and thisLocal == 0: continue # apply security filter if trusted == 0 and thisSecurity not in (0,2): continue # create exp timestamp if local == 1: thisUTTimestamp = int(os.stat(expDir).st_mtime + time.timezone) else: thisUTTimestamp = 0 # add this experiment retStr += '%i,%s,%s,%i,%s,%i,%s,%i,%i,%i,%i,%i,%i,%i,%i,%i,%i,%i,%i,%i,%s,%s,%i,%i\n' % \ (thisId, thisUrl, thisName, thisSiteId, thisSiteName, thisInstCode, thisInstName, thisStart[0], thisStart[1], thisStart[2], thisStart[3], thisStart[4], thisStart[5], thisEnd[0], thisEnd[1], thisEnd[2], thisEnd[3], thisEnd[4], thisEnd[5], thisLocal, str(thisPI), str(thisPIEmail), thisUTTimestamp, thisSecurity) return render(request, 'madweb/service.html', {'text': retStr})
def get_instruments_service(request)
-
get_instruments_service runs the getInstrumentsService.py service.
Inputs
request (ignored)
Returns comma-delimited data, one line for each experiment, with the following fields:
-
instrument.name Example: 'Millstone Hill Incoherent Scatter Radar'
-
instrument.code Example: 30
-
instrument.mnemonic (3 char string) Example: 'mlh'
-
instrument.latitude Example: 45.0
-
instrument.longitude Example: 110.0
-
instrument.altitude Example: 0.015 (km)
-
instrument.category Example: 'Incoherent Scatter Radars'
-
contact name
-
contact email
Expand source code
def get_instruments_service(request): """get_instruments_service runs the getInstrumentsService.py service. Inputs: request (ignored) Returns comma-delimited data, one line for each experiment, with the following fields: 1. instrument.name Example: 'Millstone Hill Incoherent Scatter Radar' 2. instrument.code Example: 30 3. instrument.mnemonic (3 char string) Example: 'mlh' 4. instrument.latitude Example: 45.0 5. instrument.longitude Example: 110.0 6. instrument.altitude Example: 0.015 (km) 7. instrument.category Example: 'Incoherent Scatter Radars' 8. contact name 9. contact email """ # create MadrigalDB obj madDBObj = madrigal.metadata.MadrigalDB() # create MadrigalInstument object madInst = madrigal.metadata.MadrigalInstrument(madDBObj) # get instrument list instList = madInst.getInstrumentList() # loop through each instrument instStr = '' for inst in instList: name = inst[0] code = inst[2] mnemonic = inst[1] latitude = madInst.getLatitude(code) if latitude == None: latitude = 0.0 longitude = madInst.getLongitude(code) if longitude == None: longitude = 0.0 altitude = madInst.getAltitude(code) if altitude == None: altitude = 0.0 category = madInst.getCategory(code) if category == None: category = '' # print data contactName = madInst.getContactName(code) contactEmail = madInst.getContactEmail(code) instStr += '%s,%i,%s,%f,%f,%f,%s,%s,%s\n' % (name, code, mnemonic, latitude, longitude, altitude, category, str(contactName), str(contactEmail)) return render(request, 'madweb/service.html', {'text': instStr})
-
def get_madfile_service(request)
-
get_madfile_service runs the getMadfile.cgi service.
Inputs
request/url - contains arguments:
'fileName': The full path to the file to be downloaded as. 'fileType': -1 for ascii, -2 for Hdf5, -3 for netCDF4. No other values supported 'user_fullname' user name 'user_email' user email 'user_affiliation' user affiliation
Returns file as either column delimited ascii, Hdf5, or netCDF4.
Expand source code
def get_madfile_service(request): """get_madfile_service runs the getMadfile.cgi service. Inputs: request/url - contains arguments: 'fileName': The full path to the file to be downloaded as. 'fileType': -1 for ascii, -2 for Hdf5, -3 for netCDF4. No other values supported 'user_fullname' user name 'user_email' user email 'user_affiliation' user affiliation Returns file as either column delimited ascii, Hdf5, or netCDF4. """ madDB = madrigal.metadata.MadrigalDB() madWebObj = madrigal.ui.web.MadrigalWeb(madDB) # get required arguments fileName = request.GET['fileName'] fileType = int(request.GET['fileType']) user_fullname = request.GET['user_fullname'] user_email = request.GET['user_email'] user_affiliation = request.GET['user_affiliation'] if fileType not in (-1, -2, -3): return(HttpResponse('<p>fileType %i not allowed: -1 for ascii, -2 for Hdf5, -3 for netCDF4</p>' % (fileType))) # log data access madWebObj.logDataAccess(fileName, user_fullname, user_email, user_affiliation) if fileType in (-1, -3): # may need to create temp file filepath, file_extension = os.path.splitext(fileName) basename = os.path.basename(filepath) dirname = os.path.dirname(fileName) if fileType == -1: cachedTxtFile = os.path.join(dirname, 'overview', os.path.basename(fileName) + '.txt.gz') tmpFile = os.path.join(tempfile.gettempdir(), basename + '.txt.gz') if os.access(cachedTxtFile, os.R_OK): shutil.copy(cachedTxtFile, tmpFile) else: tmpFile = os.path.join(tempfile.gettempdir(), basename + '.txt') madrigal.cedar.convertToText(fileName, tmpFile) else: cachedNCFile = os.path.join(dirname, 'overview', os.path.basename(fileName) + '.nc') tmpFile = os.path.join(tempfile.gettempdir(), basename + '.nc') if os.access(cachedNCFile, os.R_OK): shutil.copy(cachedNCFile, tmpFile) else: try: madrigal.cedar.convertToNetCDF4(fileName, tmpFile) except IOError: cedarObj = madrigal.cedar.MadrigalCedarFile(fileName) cedarObj.write('netCDF4', tmpFile) else: tmpFile = fileName f = open(tmpFile, 'rb') filename = os.path.basename(tmpFile) chunk_size = 8192 file_type = mimetypes.guess_type(tmpFile)[0] if file_type is None: file_type = 'application/octet-stream' response = StreamingHttpResponse(FileWrapper(f, chunk_size), content_type=file_type) response['Content-Length'] = os.path.getsize(tmpFile) response['Content-Disposition'] = "attachment; filename=%s" % (filename) if fileType in (-1, -3): os.remove(tmpFile) return(response)
def get_parameters_service(request)
-
get_parameters_service runs the getParametersService.py service.
Inputs
request/url - contains arguments:
filename=<full path to data file>
Returns backslash-delimited data, one for each parameter either measured or derivable, with the following fields:
1. parameter.mnemonic (string) Example 'dti' 2. parameter.description (string) Example: "F10.7 Multiday average observed (Ott)" 3. parameter.isError (int) 1 if error parameter, 0 if not 4. parameter.units (string) Example "W/m2/Hz" 5. parameter.isMeasured (int) 1 if measured, 0 if derivable 6. parameter.category (string) Example: "Time Related Parameter" 7. parameter.isSure (int) - 1 if parameter can be found for every record, 0 if can only be found for some. Not relevant to Madrigal 3, where always 1 8. parameter.isAddIncrement - 1 if additional increment, 0 if normal (Added in Madrigal 2.5) Not relevant to Madrigal 3, where always -1
Expand source code
def get_parameters_service(request): """get_parameters_service runs the getParametersService.py service. Inputs: request/url - contains arguments: filename=<full path to data file> Returns backslash-delimited data, one for each parameter either measured or derivable, with the following fields: 1. parameter.mnemonic (string) Example 'dti' 2. parameter.description (string) Example: "F10.7 Multiday average observed (Ott)" 3. parameter.isError (int) 1 if error parameter, 0 if not 4. parameter.units (string) Example "W/m2/Hz" 5. parameter.isMeasured (int) 1 if measured, 0 if derivable 6. parameter.category (string) Example: "Time Related Parameter" 7. parameter.isSure (int) - 1 if parameter can be found for every record, 0 if can only be found for some. Not relevant to Madrigal 3, where always 1 8. parameter.isAddIncrement - 1 if additional increment, 0 if normal (Added in Madrigal 2.5) Not relevant to Madrigal 3, where always -1 """ filename = request.GET['filename'] # create MadrigalDB obj madDBObj = madrigal.metadata.MadrigalDB() # create Madrigal File object madFileObj = madrigal.data.MadrigalFile(filename, madDBObj) # create Madrigal Parameter object madParmObj = madrigal.data.MadrigalParameters(madDBObj) # create Madrigal web object madWebObj = madrigal.ui.web.MadrigalWebFormat() # create lists of parameters measParmList = [] derivedParmList = [] allParmList = [] sureParmList = [] # use the comprehensive list of parameters to check if derivable parmList = madWebObj.getFormat('Comprehensive') # populate lists madFileObj.getMeasDervBothParmLists(parmList, measParmList, derivedParmList, allParmList, sureParmList) retStr = '' # loop through allParmList and output results for parm in allParmList: description = madParmObj.getSimpleParmDescription(parm) isNorm = madParmObj.getParmType(parm) if isNorm == 1: isError = 0 else: isError = 1 units = madParmObj.getParmUnits(parm) if parm in measParmList: isMeasured = 1 else: isMeasured = 0 if parm in sureParmList: isSure = 1 else: isSure = 0 category = madParmObj.getParmCategory(parm) try: if madParmObj.isAddIncrement(parm): isAddIncrement = 1 else: isAddIncrement = 0 except: isAddIncrement = -1 # print out this parm retStr += '%s\\%s\\%i\\%s\\%i\\%s\\%i\\%i\n' % (parm, description, isError, units, isMeasured, category, isSure, isAddIncrement) return render(request, 'madweb/service.html', {'text': retStr})
def get_url_list_from_group_id_service(request)
-
get_url_list_from_group_id_service returns a list of citable urls associated with group id.
Inputs
request/url - contains arguments:
id - group id
Returns one line for each citable url
Returns empty string if experiment id not found. Skips files that are not Hdf5
Expand source code
def get_url_list_from_group_id_service(request): """get_url_list_from_group_id_service returns a list of citable urls associated with group id. Inputs: request/url - contains arguments: id - group id Returns one line for each citable url Returns empty string if experiment id not found. Skips files that are not Hdf5 """ id = int(request.GET['id']) # create MadrigalDB obj madDBObj = madrigal.metadata.MadrigalDB() urlList = madDBObj.getListFromGroupId(id) retStr = '' for url in urlList: retStr += '%s\n' % (url) return render(request, 'madweb/service.html', {'text': django.utils.safestring.mark_safe(retStr)})
def get_version_service(request)
-
get_version_service runs the getVersionService.py service.
Inputs
request (ignored)
Returns a single line of text, with the version in the form
. [. ] Expand source code
def get_version_service(request): """get_version_service runs the getVersionService.py service. Inputs: request (ignored) Returns a single line of text, with the version in the form <major_version_int>.<minor_version_int>[.<sub_version_int>] """ madDB = madrigal.metadata.MadrigalDB() siteID = madDB.getSiteID() madSiteObj = madrigal.metadata.MadrigalSite(madDB) return(HttpResponse(madSiteObj.getSiteVersion(siteID)))
def global_file_search_service(request)
-
global_file_search_service returns a list of full paths to files or citable urls based on search arguments
Inputs
request/url - contains arguments:
startDate: start date in form YYYY-MM-DD to filter experiments before endDate: end date in form YYYY-MM-DD to filter experiments after inst: (optional, multiple allowed) an instrument code or name. For names, fnmatch will be used. If not set, all instruments used. kindat: (optional, multiple allowed) a kind of data codes or name. For names, fnmatch will be used. If not set, all kinds of data used. seasonalStartDate: (optional) in form MM/DD, rejects all days earlier in year. If not set implies 01/01 seasonalEndDate: (optional) in form MM/DD, rejects all days later in year. If not set implies 12/31 includeNonDefault: (optional) if "True", include realtime files when there are no default. If not set, only default files. expName: (optional) - filter experiments by the experiment name. fnmatch rules If not set, no filtering by experiment name. excludeExpName: (optional) - exclude experiments by the experiment name. fnmatch rules If not set, no excluding experiments by experiment name. fileDesc: (optional) filter files using input file Description string via fnmatch. If not set, in no filtering by file name returnCitation: (optional) if True, return a list of file citations. If not set, return a list of full paths to the files selected
Expand source code
def global_file_search_service(request): """global_file_search_service returns a list of full paths to files or citable urls based on search arguments Inputs: request/url - contains arguments: startDate: start date in form YYYY-MM-DD to filter experiments before endDate: end date in form YYYY-MM-DD to filter experiments after inst: (optional, multiple allowed) an instrument code or name. For names, fnmatch will be used. If not set, all instruments used. kindat: (optional, multiple allowed) a kind of data codes or name. For names, fnmatch will be used. If not set, all kinds of data used. seasonalStartDate: (optional) in form MM/DD, rejects all days earlier in year. If not set implies 01/01 seasonalEndDate: (optional) in form MM/DD, rejects all days later in year. If not set implies 12/31 includeNonDefault: (optional) if "True", include realtime files when there are no default. If not set, only default files. expName: (optional) - filter experiments by the experiment name. fnmatch rules If not set, no filtering by experiment name. excludeExpName: (optional) - exclude experiments by the experiment name. fnmatch rules If not set, no excluding experiments by experiment name. fileDesc: (optional) filter files using input file Description string via fnmatch. If not set, in no filtering by file name returnCitation: (optional) if True, return a list of file citations. If not set, return a list of full paths to the files selected """ madDB = madrigal.metadata.MadrigalDB() madWebObj = madrigal.ui.web.MadrigalWeb(madDB) # get required arguments startDate = request.GET['startDate'] endDate = request.GET['endDate'] startDate = datetime.datetime.strptime(startDate, '%Y-%m-%d') endDate = datetime.datetime.strptime(endDate, '%Y-%m-%d') # get optional arguments inst = request.GET.getlist('inst') if inst == []: inst = None kindat = request.GET.getlist('kindat') if kindat == []: kindat = None seasonalStartDate = request.GET.get('seasonalStartDate', default = None) seasonalEndDate = request.GET.get('seasonalEndDate', default = None) includeNonDefault = bool(request.GET.get('includeNonDefault', default = False)) expName = request.GET.get('expName', default = None) excludeExpName = request.GET.get('excludeExpName', default = None) fileDesc = request.GET.get('fileDesc', default = None) returnCitation = bool(request.GET.get('returnCitation', default = False)) result = madWebObj.global_file_search(startDate, endDate, inst, kindat, seasonalStartDate, seasonalEndDate, includeNonDefault, expName, excludeExpName, fileDesc, returnCitation) fullText = '' for item in result: fullText += '%s\n' % (item) return render(request, 'madweb/service.html', {'text': django.utils.safestring.mark_safe(fullText)})
def isprint_service(request)
-
isprint_service runs the isprintService.py service.
Inputs
request/url - contains arguments:
'file': The full path to the file to be analyzed by isprint. If over 50 MB, returns error message. 'parms': Multiple requested parameters, space (+) separated. 'filters': Multiple of filters desired, as in isprint command 'user_fullname' user name 'user_email' user email 'user_affiliation' user affiliation 'output' - option argument specifying output file basename. Will be Hdf5 format if extension in ('hdf5', 'h5', 'hdf'). Will be netCDF4 is extension is '.nc'. Otherwise ascii. If not given, output is ascii. 'header': t for headers, f for no header. Defaults to no header. Ignored if not ascii output
Returns data as either column delimited ascii, Hdf5, or netCDF4.
Expand source code
def isprint_service(request): """isprint_service runs the isprintService.py service. Inputs: request/url - contains arguments: 'file': The full path to the file to be analyzed by isprint. If over 50 MB, returns error message. 'parms': Multiple requested parameters, space (+) separated. 'filters': Multiple of filters desired, as in isprint command 'user_fullname' user name 'user_email' user email 'user_affiliation' user affiliation 'output' - option argument specifying output file basename. Will be Hdf5 format if extension in ('hdf5', 'h5', 'hdf'). Will be netCDF4 is extension is '.nc'. Otherwise ascii. If not given, output is ascii. 'header': t for headers, f for no header. Defaults to no header. Ignored if not ascii output Returns data as either column delimited ascii, Hdf5, or netCDF4. """ madDB = madrigal.metadata.MadrigalDB() madWebObj = madrigal.ui.web.MadrigalWeb(madDB) # get required arguments thisFile = request.GET['file'] parms = request.GET.getlist('parms') filters = request.GET.getlist('filters') user_fullname = request.GET['user_fullname'] user_email = request.GET['user_email'] user_affiliation = request.GET['user_affiliation'] # get optional arguments try: output = os.path.basename(request.GET['output']) filename, file_extension = os.path.splitext(output) if file_extension in ('.hdf5', '.h5', '.hdf'): format = 'Hdf5' elif file_extension in ('.nc',): format = 'netCDF4' else: format = 'ascii' except: format = 'ascii' output = None # verify thisFile exists, not too big errorMessage = None if not os.access(thisFile, os.R_OK): errorMessage = 'File %s not found' % (thisFile) elif os.path.getsize(thisFile) > 200.0E6: errorMessage = 'File %s greater than 200 MB in size - running dynamic file creation not possible. Please use -- download as is -- instead.' % (thisFile) if not errorMessage is None: return render(request, 'madweb/service.html', {'text': errorMessage}) if not output is None: # we need to write to a download file downloadFile = os.path.join(tempfile.gettempdir(), output) if os.access(downloadFile, os.R_OK): try: os.remove(downloadFile) except: pass try: header = request.GET['header'] if header not in ('t', 'f'): raise ValueError('Unknown header value <%s>' % (header)) except: header = 'f' # log data access madWebObj.logDataAccess(thisFile, user_fullname, user_email, user_affiliation) # run isprint command cmd = '%s/bin/isprint file=%s ' % (madDB.getMadroot(), thisFile) if not output is None: cmd += 'output=%s ' % (downloadFile) delimiter = ' ' cmd += delimiter.join(parms) + ' ' filterStr = delimiter.join(filters) cmd += filterStr + ' ' if format == 'ascii': cmd += 'summary=f ' cmd += 'header=%s ' % (header) if output is None: # text response #result = subprocess.check_output(cmd.split()) p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) result,errtext = p.communicate() if p.returncode != 0: result = errtext if type(result) in (bytes, numpy.bytes_): result = result.decode('utf-8') if header == 'f': index = result.find('\n') result = result[index+1:] return render(request, 'madweb/service.html', {'text': result}) else: # file download response #subprocess.check_call(cmd.split()) p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) result,errtext = p.communicate() if p.returncode != 0: # write the error to result file f = open(downloadFile, 'w') if type(errtext) in (bytes, numpy.bytes_): errtext = errtext.decode('utf-8') f.write(errtext) f.close() f = open(downloadFile, 'rb') filename = os.path.basename(downloadFile) chunk_size = 8192 file_type = mimetypes.guess_type(downloadFile)[0] if file_type is None: file_type = 'application/octet-stream' response = StreamingHttpResponse(FileWrapper(f, chunk_size), content_type=file_type) response['Content-Length'] = os.path.getsize(downloadFile) response['Content-Disposition'] = "attachment; filename=%s" % (filename) os.remove(downloadFile) return(response)
def list_file_times_service(request)
-
list_file_times_service runs the listFileTimes service.
Inputs
request/url - contains arguments:
Optional: expDir - experiment directory to list. Can be absolute or relative to experiments[0-9]. Default is all files in $MADROOT/experiments
Returns comma-delimited data, one for each file:
1. Full path of file 2. File modification time in form YYYY-MM-DD HH:MM:SS (UT time)
Expand source code
def list_file_times_service(request): """list_file_times_service runs the listFileTimes service. Inputs: request/url - contains arguments: Optional: expDir - experiment directory to list. Can be absolute or relative to experiments[0-9]*. Default is all files in $MADROOT/experiments* Returns comma-delimited data, one for each file: 1. Full path of file 2. File modification time in form YYYY-MM-DD HH:MM:SS (UT time) """ expDir = None try: expDir = request.GET['expDir'] except: pass madDB = madrigal.metadata.MadrigalDB() fileList = madDB.listFileTimes(expDir) fullText = '\n\n' for filename, filetime in fileList: fullText += "\'%s\', %s\n" % (filename, filetime.strftime('%Y-%m-%d %H:%M:%S')) return render(request, 'madweb/service.html', {'text': django.utils.safestring.mark_safe(fullText)})
def mad_calculator2_service(request)
-
mad_calculator2_service runs the madCalculator2 service.
Differs from madCalulator in that positions are a list rather than a grid.
Inputs
request/url - contains arguments:
year, month, day, hour, min, sec lats - comma separated list of latitudes to analyze longs - comma separated list of longitudes to analyze. Len must == len(lats) alts - comma separated list of altitudes to analyze. Len must == len(lats) parms - comma delimited string of Madrigal parameters desired oneD - zero or more mnemonics,float values to set input 1D values Example: &oneD=kinst,31.0&oneD=elm,45.0 twoD - zero or more mnemonics,comma-separate float list of len(lats) to set input 2D values Example: twoD=te,1000,1100,1200 twoD=ti,1000,1000,1000 where there are 3 lats
Returns comma-delimited data, one line for each lat value, with the following fields:
1. latitude 2. longitude 3. altitude 4. Values for each Madrigal parameter listed in argument parms, separated by whitespace
Expand source code
def mad_calculator2_service(request): """mad_calculator2_service runs the madCalculator2 service. Differs from madCalulator in that positions are a list rather than a grid. Inputs: request/url - contains arguments: year, month, day, hour, min, sec lats - comma separated list of latitudes to analyze longs - comma separated list of longitudes to analyze. Len must == len(lats) alts - comma separated list of altitudes to analyze. Len must == len(lats) parms - comma delimited string of Madrigal parameters desired oneD - zero or more mnemonics,float values to set input 1D values Example: &oneD=kinst,31.0&oneD=elm,45.0 twoD - zero or more mnemonics,comma-separate float list of len(lats) to set input 2D values Example: twoD=te,1000,1100,1200 twoD=ti,1000,1000,1000 where there are 3 lats Returns comma-delimited data, one line for each lat value, with the following fields: 1. latitude 2. longitude 3. altitude 4. Values for each Madrigal parameter listed in argument parms, separated by whitespace """ if request.method == 'POST': reqDict = request.POST else: reqDict = request.GET try: year = int(reqDict.get('year')) except TypeError: return(HttpResponse('<p>madCalculator2Service requires year</p>')) month = int(reqDict['month']) day = int(reqDict['day']) hour = int(reqDict['hour']) minute = int(reqDict['min']) second = int(reqDict['sec']) dt = datetime.datetime(year, month, day, hour, minute, second) latsStr = reqDict['lats'] lats = [float(item) for item in latsStr.split(',')] longsStr = reqDict['longs'] longs = [float(item) for item in longsStr.split(',')] altsStr = reqDict['alts'] alts = [float(item) for item in altsStr.split(',')] parms = reqDict['parms'] desiredParmList = [item.strip() for item in ['gdlat','glon','gdalt'] + parms.split(',')] oneDList = reqDict.getlist('oneD') oneDParmDict = {} for oneDStr in oneDList: mnem, strValue = oneDStr.split(',') oneDParmDict[mnem] = [float(strValue)] twoDList = reqDict.getlist('twoD') twoDParmDict = {} for twoDStr in twoDList: items = twoDStr.split(',') if len(items) != 1 + len(lats): raise ValueError('twoDstr %s not correct number of points' % (str(twoDStr))) mnem = items[0] floatValues = [float(item) for item in items[1:]] # now we need to expand these values to be two dimensional 1 x len(lats) values = numpy.zeros((1,len(lats)), dtype=numpy.float) values[0][:] = floatValues twoDParmDict[mnem] = values # capture stdout old_stdout = sys.stdout sys.stdout = mystdout = io.StringIO() madrigal.isprint.MadCalculatorList(None, desiredParmList, [dt], lats, longs, alts, oneDParmDict, twoDParmDict, summary=None) text = mystdout.getvalue() sys.stdout = old_stdout return render(request, 'madweb/service.html', {'text': text})
def mad_calculator3_service(request)
-
mad_calculator3_service runs the madCalculator3 service.
Differs from madCalulator in that multiple times, each with a unique list of positions, can be passed in.
Inputs
request/url - contains arguments:
year - a comma-separated list of years - (required)
month - a comma-separated list of months - (required)
day - a comma-separated list of days - (required)
hour - a comma-separated list of hours - (required)
min - a comma-separated list of minutes - (required)
sec - a comma-separated list of seconds - (required)
numPos - a comma-sepatated list of the number of positions for each time - (required)
lats - a comma-separated list of geodetic latitudes, -90 to 90 (required). Listed for first time, then second, etc. Total must be equal to the sum of numPos.
longs - a comma-separated list of longitudes (required) Listed for first time, then second, etc. Total must be equal to the sum of numPos.
alts - a comma-separated list of geodetic altitudes in km (required) Listed for first time, then second, etc. Total must be equal to the sum of numPos.
parms - comma delimited string of Madrigal parameters desired (required)
oneD - string in form
, This argument allows the user to set any number of one-D parameters to be used in the calculation. Value must be parameter name, comma, list of values as double, where length of list is equal to number of times. Example: &oneD=kinst,31.0,31.0&oneD=elm,45.0,50 (optional - 0 or more allowed) twoD=
, (optional - 0 or more allowed) This argument allows the user to set any number of two-D parameters to be used in the calculation. Value must be parameter name, comma, comma-separated values. Number of values must equal the sum of numPos. Order is first time values first, then second time values, etc Example: twoD=te,1000,1100,1200,1000,1100,1200 &twoD=ti,1000,1000,1000,1000,1000,1000 where numPos=3,3 Returns comma-delimited data, one line for each location. Separate times are delimited by line
TIME MM/DD/YYYY HH:MM:SS
Data lines have the following fields:
-
latitude
-
longitude
-
altitude
-
Values for each Madrigal parameter listed in argument parms, separated by whitespace
Expand source code
def mad_calculator3_service(request): """mad_calculator3_service runs the madCalculator3 service. Differs from madCalulator in that multiple times, each with a unique list of positions, can be passed in. Inputs: request/url - contains arguments: year - a comma-separated list of years - (required) month - a comma-separated list of months - (required) day - a comma-separated list of days - (required) hour - a comma-separated list of hours - (required) min - a comma-separated list of minutes - (required) sec - a comma-separated list of seconds - (required) numPos - a comma-sepatated list of the number of positions for each time - (required) lats - a comma-separated list of geodetic latitudes, -90 to 90 (required). Listed for first time, then second, etc. Total must be equal to the sum of numPos. longs - a comma-separated list of longitudes (required) Listed for first time, then second, etc. Total must be equal to the sum of numPos. alts - a comma-separated list of geodetic altitudes in km (required) Listed for first time, then second, etc. Total must be equal to the sum of numPos. parms - comma delimited string of Madrigal parameters desired (required) oneD - string in form <parm>,<comma-separated values> This argument allows the user to set any number of one-D parameters to be used in the calculation. Value must be parameter name, comma, list of values as double, where length of list is equal to number of times. Example: &oneD=kinst,31.0,31.0&oneD=elm,45.0,50 (optional - 0 or more allowed) twoD=<parm>,<values> (optional - 0 or more allowed) This argument allows the user to set any number of two-D parameters to be used in the calculation. Value must be parameter name, comma, comma-separated values. Number of values must equal the sum of numPos. Order is first time values first, then second time values, etc Example: twoD=te,1000,1100,1200,1000,1100,1200 &twoD=ti,1000,1000,1000,1000,1000,1000 where numPos=3,3 Returns comma-delimited data, one line for each location. Separate times are delimited by line TIME MM/DD/YYYY HH:MM:SS Data lines have the following fields: 1. latitude 2. longitude 3. altitude 4. Values for each Madrigal parameter listed in argument parms, separated by whitespace """ if request.method == 'POST': reqDict = request.POST else: reqDict = request.GET try: yearList = [int(item) for item in reqDict.get('year').split(',')] except AttributeError: return(HttpResponse('<p>madCalculator3Service requires year</p>')) monthList = [int(item) for item in reqDict.get('month').split(',')] dayList = [int(item) for item in reqDict.get('day').split(',')] hourList = [int(item) for item in reqDict.get('hour').split(',')] minList = [int(item) for item in reqDict.get('min').split(',')] secList = [int(item) for item in reqDict.get('sec').split(',')] dtList = [datetime.datetime(yearList[i], monthList[i], dayList[i], hourList[i], minList[i], secList[i]) for i in range(len(yearList))] numPosStr = reqDict['numPos'] numPosList = [int(item) for item in numPosStr.split(',')] totalPos = 0 for numPos in numPosList: totalPos += numPos latsStr = reqDict['lats'] lats = [float(item) for item in latsStr.split(',')] if len(lats) != totalPos: return(HttpResponse('wrong number of lats, expected %i' % (totalPos))) longsStr = reqDict['longs'] longs = [float(item) for item in longsStr.split(',')] if len(longs) != totalPos: return(HttpResponse('wrong number of longs, expected %i' % (totalPos))) altsStr = reqDict['alts'] alts = [float(item) for item in altsStr.split(',')] if len(alts) != totalPos: return(HttpResponse('wrong number of alts, expected %i' % (totalPos))) parms = reqDict['parms'] desiredParmList = [item.strip() for item in ['gdlat','glon','gdalt'] + parms.split(',')] oneDList = reqDict.getlist('oneD') twoDList = reqDict.getlist('twoD') # since the positions can change with each call, we need to call madrigal.isprint.MadCalculatorGrid once for each time startIndex = 0 endIndex = 0 fullText = '' for timeIndex, numPos in enumerate(numPosList): startIndex = endIndex endIndex += numPos thisLats = lats[startIndex:endIndex] thisLongs = longs[startIndex:endIndex] thisAlts = alts[startIndex:endIndex] oneDParmDict = {} for oneDStr in oneDList: values = oneDStr.split(',') if len(values) != 1+len(dtList): return(HttpResponse('wrong number of values given for 1D parm %s' % (values[0]))) oneDParmDict[values[0]] = [float(values[timeIndex+1])] twoDParmDict = {} for twoDStr in twoDList: values = twoDStr.split(',') if len(values) != 1 + totalPos: return(HttpResponse('twoDstr %s not correct number of points' % (str(twoDStr)))) mnem = values[0] floatValues = [float(item) for item in values[1+startIndex:1+endIndex]] # now we need to expand these values to be two dimensional - 1,len(thisLats) values2D = numpy.zeros((1,len(thisLats)), dtype=numpy.float) values2D[0][:] = floatValues twoDParmDict[mnem] = values2D # capture stdout old_stdout = sys.stdout sys.stdout = mystdout = io.StringIO() madrigal.isprint.MadCalculatorList(None, desiredParmList, [dtList[timeIndex]], thisLats, thisLongs, thisAlts, oneDParmDict, twoDParmDict, summary=None) text = mystdout.getvalue() sys.stdout = old_stdout fullText += 'TIME %s\n' % (dtList[timeIndex].strftime('%m/%d/%Y %H:%M:%S')) fullText += text return render(request, 'madweb/service.html', {'text': fullText})
-
def mad_calculator_service(request)
-
mad_calculator_service runs the madCalculator service.
Inputs
request/url - contains arguments:
year, month, day, hour, min, sec startLat - Starting geodetic latitude, -90 to 90 (float) endLat - Ending geodetic latitude, -90 to 90 (float) stepLat - Latitude step (0.1 to 90) (float) startLong - Starting geodetic longitude, -180 to 180 (float) endLong - Ending geodetic longitude, -180 to 180 (float) stepLong - Longitude step (0.1 to 180) (float) startAlt - Starting geodetic altitude, >= 0 (float) endAlt - Ending geodetic altitude, > 0 (float) stepAlt - Altitude step (>= 0.1) (float) parms - comma delimited string of Madrigal parameters desired oneD - zero or more mnemonics,float values to set input 1D values
Returns comma-delimited data, one line for each combination of lat, long, and alt, with the following fields:
1. latitude 2. longitude 3. altitude 4. Values for each Madrigal parameter listed in argument parms, separated by whitespace
Expand source code
def mad_calculator_service(request): """mad_calculator_service runs the madCalculator service. Inputs: request/url - contains arguments: year, month, day, hour, min, sec startLat - Starting geodetic latitude, -90 to 90 (float) endLat - Ending geodetic latitude, -90 to 90 (float) stepLat - Latitude step (0.1 to 90) (float) startLong - Starting geodetic longitude, -180 to 180 (float) endLong - Ending geodetic longitude, -180 to 180 (float) stepLong - Longitude step (0.1 to 180) (float) startAlt - Starting geodetic altitude, >= 0 (float) endAlt - Ending geodetic altitude, > 0 (float) stepAlt - Altitude step (>= 0.1) (float) parms - comma delimited string of Madrigal parameters desired oneD - zero or more mnemonics,float values to set input 1D values Returns comma-delimited data, one line for each combination of lat, long, and alt, with the following fields: 1. latitude 2. longitude 3. altitude 4. Values for each Madrigal parameter listed in argument parms, separated by whitespace """ year = int(request.GET['year']) month = int(request.GET['month']) day = int(request.GET['day']) hour = int(request.GET['hour']) minute = int(request.GET['min']) second = int(request.GET['sec']) try: dt = datetime.datetime(year, month, day, hour, minute, second) except: return(HttpResponse('Illegal time: year %i, month %i, day %i, hour %i, minute %i, second %i' % (year, month, day, hour, minute, second))) startLat = float(request.GET['startLat']) endLat = float(request.GET['endLat']) if startLat == endLat: endLat += 0.001 elif startLat > endLat: return(HttpResponse('startLat %s cannot be greater than endLat %s' % (str(startLat), str(endLat)))) stepLat = float(request.GET['stepLat']) if stepLat < 0.0: return(HttpResponse('stepLat %s cannot be less than zero' % (str(stepLat)))) elif stepLat == 0.0: stepLat = 0.001 latList = list(numpy.arange(startLat, endLat, stepLat)) startLong = float(request.GET['startLong']) endLong = float(request.GET['endLong']) if startLong == endLong: endLong += 0.001 elif startLong > endLong: return(HttpResponse('startLong %s cannot be greater than endLong %s' % (str(startLong), str(endLong)))) stepLong = float(request.GET['stepLong']) if stepLong < 0.0: return(HttpResponse('stepLong %s cannot be less than zero' % (str(stepLong)))) elif stepLong == 0.0: stepLong = 0.001 lonList = list(numpy.arange(startLong, endLong, stepLong)) startAlt = float(request.GET['startAlt']) endAlt = float(request.GET['endAlt']) if startAlt == endAlt: endAlt += 0.001 elif startAlt > endAlt: return(HttpResponse('startAlt %s cannot be greater than endAlt %s' % (str(startAlt), str(endAlt)))) stepAlt = float(request.GET['stepAlt']) if stepAlt < 0.0: return(HttpResponse('stepAlt %s cannot be less than zero' % (str(stepAlt)))) elif stepAlt == 0.0: stepAlt = 0.01 altList = list(numpy.arange(startAlt, endAlt, stepAlt)) # limit total calculations to 1E5 total = len(latList) * len(lonList) * len(altList) if total > 1.0E5: return(HttpResponse('Too many points for madCalculatorService: %i' % (total))) parms = request.GET['parms'] desiredParmList = [item.strip() for item in ['gdlat','glon','gdalt'] + parms.split(',')] oneDList = request.GET.getlist('oneD') oneDParmDict = {} for oneDStr in oneDList: mnem, strValue = oneDStr.split(',') oneDParmDict[mnem] = [float(strValue)] # capture stdout old_stdout = sys.stdout sys.stdout = mystdout = io.StringIO() madrigal.isprint.MadCalculatorGrid(None, desiredParmList, [dt], latList, lonList, altList, oneDParmDict, summary=None) text = mystdout.getvalue() sys.stdout = old_stdout return render(request, 'madweb/service.html', {'text': text})
def mad_time_calculator_service(request)
-
mad_time_calculator_service runs the madTimeCalculator service. Input parameters must not be location dependent
Inputs
request/url - contains arguments:
1. startyear - int 2. startmonth - int 3. startday - int 4. starthour - int 5. startmin - int 6. startsec - int 7. endyear - int 8. endmonth - int 9. endday - int 10. endhour - int 11. endmin - int 12. endsec - int 13. stephours - float - number of hours per time step 14. parms - comma delimited string of Madrigal parameters desired (must not depend on location)
Returns comma-delimited data, one line for each year, month, day, hour, minute, and second, with the following fields:
1-6: year, month, day, hour, minute, and second 2. requested parm fields
Expand source code
def mad_time_calculator_service(request): """mad_time_calculator_service runs the madTimeCalculator service. Input parameters must not be location dependent Inputs: request/url - contains arguments: 1. startyear - int 2. startmonth - int 3. startday - int 4. starthour - int 5. startmin - int 6. startsec - int 7. endyear - int 8. endmonth - int 9. endday - int 10. endhour - int 11. endmin - int 12. endsec - int 13. stephours - float - number of hours per time step 14. parms - comma delimited string of Madrigal parameters desired (must not depend on location) Returns comma-delimited data, one line for each year, month, day, hour, minute, and second, with the following fields: 1-6: year, month, day, hour, minute, and second 2. requested parm fields """ startyear = int(request.GET['startyear']) startmonth = int(request.GET['startmonth']) startday = int(request.GET['startday']) starthour = int(request.GET['starthour']) startminute = int(request.GET['startmin']) startsecond = int(request.GET['startsec']) endyear = int(request.GET['endyear']) endmonth = int(request.GET['endmonth']) endday = int(request.GET['endday']) endhour = int(request.GET['endhour']) endminute = int(request.GET['endmin']) endsecond = int(request.GET['endsec']) dt1 = datetime.datetime(startyear, startmonth, startday, starthour, startminute, startsecond) dt2 = datetime.datetime(endyear, endmonth, endday, endhour, endminute, endsecond) if dt1 > dt2: return(HttpResponse('End Datetime %s cannot be before start datetime %s' % (str(dt2), str(dt1)))) stephours = float(request.GET['stephours']) if stephours <= 0.0: return(HttpResponse('stephours cannot be non-positive: %f' % (stephours))) dtList = [] while dt1 <= dt2: dtList.append(dt1) dt1 += datetime.timedelta(hours=stephours) parms = request.GET['parms'] desiredParmList = [item.strip() for item in ['year','month','day','hour','min','sec'] + parms.split(',')] # no spatial data latList = lonList = altList = [] # capture stdout old_stdout = sys.stdout sys.stdout = mystdout = io.StringIO() madrigal.isprint.MadCalculatorGrid(None, desiredParmList, dtList, latList, lonList, altList, summary=None) text = mystdout.getvalue() sys.stdout = old_stdout return render(request, 'madweb/service.html', {'text': text})
def radar_to_geodetic_service(request)
-
radar_to_geodetic_service runs the radarToGeodetic service.
Inputs
request/url - contains arguments:
slatgd - radar geodetic latitude
slon - radar longitude
saltgd - radar geodetic altitude
azs - a comma-separated list of azimuths of point
els - a comma-separated list of elevations of point. Len must be same as azs
ranges - a comma-separated list of ranges to point. Len must be same as azs
Returns comma-delimited data, one line for point in lists (points treated as individual combinations, not grids):
1. geodetic latitude 2. longitude (-180 to 180) 3. geodetic altitude in km
Expand source code
def radar_to_geodetic_service(request): """radar_to_geodetic_service runs the radarToGeodetic service. Inputs: request/url - contains arguments: slatgd - radar geodetic latitude slon - radar longitude saltgd - radar geodetic altitude azs - a comma-separated list of azimuths of point els - a comma-separated list of elevations of point. Len must be same as azs ranges - a comma-separated list of ranges to point. Len must be same as azs Returns comma-delimited data, one line for point in lists (points treated as individual combinations, not grids): 1. geodetic latitude 2. longitude (-180 to 180) 3. geodetic altitude in km """ slatgd = float(request.GET['slatgd']) slon = float(request.GET['slon']) saltgd = float(request.GET['saltgd']) azStr = request.GET['az'] azList = [float(item) for item in azStr.split(',')] elStr = request.GET['el'] elList = [float(item) for item in elStr.split(',')] rangeStr = request.GET['range'] rangeList = [float(item) for item in rangeStr.split(',')] if len(azList) != len(elList) or len(azList) != len(rangeList): return(HttpResponse('all point list lengths must be equal')) fullText = '' for i in range(len(azList)): gdlat,glon,gdalt = madrigal._derive.radarToGeodetic(slatgd, slon, saltgd, azList[i], elList[i], rangeList[i]) fullText += '%f,%f,%f\n' % (gdlat,glon,gdalt) return render(request, 'madweb/service.html', {'text': fullText})
def set_group_id_from_url_list_service(request)
-
set_group_id_from_url_list sets a list of citable urls to a group id .
Inputs
request/url - contains arguments:
'user_fullname' user name 'user_email' user email 'user_affiliation' user affiliation 'url' - citable url. Multiple arguments allowed
Returns group id (integer) set
Expand source code
def set_group_id_from_url_list_service(request): """set_group_id_from_url_list sets a list of citable urls to a group id . Inputs: request/url - contains arguments: 'user_fullname' user name 'user_email' user email 'user_affiliation' user affiliation 'url' - citable url. Multiple arguments allowed Returns group id (integer) set """ madDB = madrigal.metadata.MadrigalDB() print(request.GET) # get required arguments urls = request.GET.getlist('url') user_fullname = request.GET['user_fullname'] user_email = request.GET['user_email'] user_affiliation = request.GET['user_affiliation'] id = madDB.createGroupIdWithList(user_fullname, user_email, user_affiliation, urls) return render(request, 'madweb/service.html', {'text': str(id)})
def trace_magnetic_field_service(request)
-
trace_magnetic_field_service runs the traceMagneticField service.
Inputs
request/url - contains arguments:
year, month, day, hour, min, sec
inputType (0 for geodetic, 1 for GSM)
outputType (0 for geodetic, 1 for GSM)
The following parameter depend on inputType:
in1 - a comma-separated list of geodetic altitudes or ZGSMs of starting point
in2 - a comma-separated list of geodetic latitudes or XGSMs of starting point
in3 - a comma-separated list of longitude or YGSM of starting point
Length of all three lists must be the same
model - 0 for Tsyganenko, 1 for IGRF
qualifier - 0 for conjugate, 1 for north_alt, 2 for south_alt, 3 for apex, 4 for GSM XY plane
stopAlt - altitude in km to stop trace at, if qualifier is north_alt or south_alt.
If other qualifier, this parameter is not required.
Returns comma-delimited data, one line for point in in lists:
1. geodetic altitude or ZGSM of ending point 2. geodetic latitude or XGSM of ending point 3. longitude or YGSM of ending point
Expand source code
def trace_magnetic_field_service(request): """trace_magnetic_field_service runs the traceMagneticField service. Inputs: request/url - contains arguments: year, month, day, hour, min, sec inputType (0 for geodetic, 1 for GSM) outputType (0 for geodetic, 1 for GSM) The following parameter depend on inputType: in1 - a comma-separated list of geodetic altitudes or ZGSMs of starting point in2 - a comma-separated list of geodetic latitudes or XGSMs of starting point in3 - a comma-separated list of longitude or YGSM of starting point Length of all three lists must be the same model - 0 for Tsyganenko, 1 for IGRF qualifier - 0 for conjugate, 1 for north_alt, 2 for south_alt, 3 for apex, 4 for GSM XY plane stopAlt - altitude in km to stop trace at, if qualifier is north_alt or south_alt. If other qualifier, this parameter is not required. Returns comma-delimited data, one line for point in in lists: 1. geodetic altitude or ZGSM of ending point 2. geodetic latitude or XGSM of ending point 3. longitude or YGSM of ending point """ year = int(request.GET['year']) month = int(request.GET['month']) day = int(request.GET['day']) hour = int(request.GET['hour']) minute = int(request.GET['min']) second = int(request.GET['sec']) dt = datetime.datetime(year, month, day, hour, minute, second) inputType = int(request.GET['inputType']) if inputType not in (0,1): return(HttpResponse('inputType must be 0 or 1, not %i' % (inputType))) outputType = int(request.GET['outputType']) if outputType not in (0,1): return(HttpResponse('outputType must be 0 or 1, not %i' % (outputType))) in1Str = request.GET['in1'] in1List = [float(item) for item in in1Str.split(',')] in2Str = request.GET['in2'] in2List = [float(item) for item in in2Str.split(',')] in3Str = request.GET['in3'] in3List = [float(item) for item in in3Str.split(',')] if len(in1List) != len(in2List) or len(in1List) != len(in3List): return(HttpResponse('All three in* lists must have same length')) model = int(request.GET['model']) if model not in (0,1): return(HttpResponse('model must be 0 or 1, not %i' % (model))) qualifier = int(request.GET['qualifier']) if qualifier not in (0,1,2,3,4): return(HttpResponse('model must be in 0,1,2,3,4 not %i' % (model))) try: stopAlt = float(request.GET['stopAlt']) except: stopAlt = 0.0 fullText = '' resultArr = numpy.zeros((3,), dtype='f8') madDB = madrigal.metadata.MadrigalDB() madDeriveObj = madrigal.derivation.MadrigalDerivationMethods(madDB.getMadroot()) for i in range(len(in1List)): madDeriveObj.traceMagneticField(year, month, day, hour, minute, second, inputType, outputType, in1List[i], in2List[i], in3List[i], model, qualifier, stopAlt, resultArr) fullText += '%f,%f,%f\n' % (resultArr[0], resultArr[1], resultArr[2]) return render(request, 'madweb/service.html', {'text': fullText})