##// END OF EJS Templates
Optmize plots mods
jespinoza -
r3:83075d03134d
parent child
Show More
@@ -1,2263 +1,2208
1 1 """Forms for madweb application
2 2
3 3 $Id: forms.py 7288 2020-12-10 16:49:16Z brideout $
4 4 """
5 5
6 6 # standard python imports
7 7 import os.path
8 8 import datetime
9 9 import itertools
10 10
11 11 # django imports
12 12 import django.forms
13 13 import django.utils.html
14 14 import django.utils.safestring
15 15 import django.template.defaulttags
16 16
17 17 # third party imports
18 18 import numpy
19 19 import h5py
20 20
21 21 # Madrigal imports
22 22 import madrigal.metadata
23 23 import madrigal.ui.web
24 24
25 25 # temp only
26 26 import logging
27 27
28 28 @django.template.defaulttags.register.filter
29 29 def get_item(dictionary, key):
30 30 return(dictionary.get(key))
31 31
32 32 @django.template.defaulttags.register.filter
33 33 def modulo(num, val):
34 34 return(num % val == 0)
35 35
36 36 class HorizontalRadioSelect(django.forms.RadioSelect):
37 37 template_name = 'madweb/horizontal_select.html'
38 38
39 39
40 40
41 41 def getSelection(keyword, args, kwargs):
42 42 """getSelection returns '0' if keyword not a key in either args[0] or kwargs,
43 43 otherwise the value
44 44
45 45 args, kwargs - arguments as passed into SingleExpDefaultForm __init__
46 46 """
47 47 if len(args) == 0 and len(list(kwargs.keys())) == 0:
48 48 return('0') # default case when no data passed in
49 49 elif len(args) > 0:
50 50 # args[0] is data dict argument to bind data
51 51 if keyword in args[0]:
52 52 return(args[0][keyword])
53 53 else:
54 54 return('0')
55 55 elif keyword in kwargs:
56 56 return(kwargs[keyword])
57 57 elif 'data' in kwargs:
58 58 if keyword in kwargs['data']:
59 59 return(kwargs['data'][keyword])
60 60 else:
61 61 return('0')
62 62 else:
63 63 return('0')
64 64
65 65
66 66 def getIsGlobal(args, kwargs):
67 67 """getIsGlobal is a helper function returns True if 'isGlobal' not found in either args[0] or kwargs,
68 68 otherwise the bool of the value
69 69
70 70 args, kwargs - arguments as passed into SingleExpDefaultForm __init__
71 71 """
72 72 if len(args) == 0 and len(list(kwargs.keys())) == 0:
73 73 return(True) # default case when no data passed in
74 74 elif len(args) > 0:
75 75 # args[0] is data dict argument to bind data
76 76 if 'isGlobal' in args[0]:
77 77 if args[0]['isGlobal'] == '0':
78 78 return(False)
79 79 else:
80 80 return(bool(args[0]['isGlobal']))
81 81 else:
82 82 return(False)
83 83 elif 'data' in kwargs:
84 84 if 'isGlobal' in kwargs['data']:
85 85 if kwargs['data']['isGlobal'] == '0':
86 86 return(False)
87 87 else:
88 88 return(bool(kwargs['data']['isGlobal']))
89 89 else:
90 90 return(False)
91 91 elif 'isGlobal' in kwargs:
92 92 if kwargs['isGlobal'] == '0':
93 93 return(False)
94 94 else:
95 95 return(bool(kwargs['isGlobal']))
96 96 else:
97 97 return(False)
98 98
99 99
100 100 def getCategoryList(args, kwargs, madInstData, forList=False):
101 101 """getCategoryList is a helper function that returns the categories choices in
102 102 SingleExpDefaultForm.categories at runtime
103 103
104 104 Inputs:
105 105 args, kwargs - arguments as passed into SingleExpDefaultForm __init__. Used only to
106 106 determine isGlobal
107 107 madInstData - madrigal.metadata.MadrigalInstrumentData object
108 108 forList - if False (the default) category list if for single interface, If True, for List interface
109 109 """
110 110 if not forList:
111 111 local = not getIsGlobal(args, kwargs)
112 112 else:
113 113 local = False
114 114 categories = madInstData.getCategories(local)
115 115 if forList:
116 116 catList = [('0', 'All instrument categories'),]
117 117 else:
118 118 catList = [('0', 'Choose instrument type: '),]
119 119 for catID, catDesc in categories:
120 120 catList.append((str(catID), catDesc))
121 121 return(catList)
122 122
123 123
124 124
125 125 def getInstrumentList(args, kwargs, madInstData, header='Select an instrument: ', local=None, includeYears=False):
126 126 """getInstrumentList is a helper function that returns the instrument choices in
127 127 SingleExpDefaultForm.categories at runtime
128 128
129 129 Inputs:
130 130 args, kwargs - arguments as passed into SingleExpDefaultForm __init__. Used to
131 131 determine categoryId and local
132 132 madInstData - madrigal.metadata.MadrigalInstrumentData object
133 133 header - text of first item in selection
134 134 local - if None (the default), set local flag via args and kwargs. If boolean,
135 135 set local flag to arg.
136 136 includeYear - if True, include data years in description. If False (the default), do not.
137 137 """
138 138 if local is None:
139 139 local = not getIsGlobal(args, kwargs)
140 140 else:
141 141 local = bool(local)
142 142 if header == 'Select an instrument: ':
143 143 categoryId = int(getSelection('categories', args, kwargs))
144 144 else:
145 145 categoryId = 0
146 146 instruments = madInstData.getInstruments(categoryId, local)
147 147 instList = [('0', header),]
148 148 for kinst, instDesc, siteID in instruments:
149 149 if includeYears:
150 150 instYears = madInstData.getInstrumentYears(kinst)
151 151 instList.append((str(kinst), '%s [%i-%i]' % (instDesc, instYears[0], instYears[-1])))
152 152 else:
153 153 instList.append((str(kinst), instDesc))
154 154 return(instList)
155 155
156 156
157 157 def getYearList(args, kwargs, madInstData):
158 158 """getYearList is a helper function that returns the year choices in
159 159 SingleExpDefaultForm.categories at runtime
160 160
161 161 Inputs:
162 162 args, kwargs - arguments as passed into SingleExpDefaultForm __init__. Used to
163 163 determine categoryId and local and kinst
164 164 madInstData - madrigal.metadata.MadrigalInstrumentData object
165 165 """
166 166 local = not getIsGlobal(args, kwargs)
167 167 kinst = int(getSelection('instruments', args, kwargs))
168 168 years = madInstData.getInstrumentYears(kinst)
169 169 yearsList = [('0', 'Select a year: '),]
170 170 for thisYear in reversed(years):
171 171 yearsList.append((str(thisYear), str(thisYear)))
172 172 return(yearsList)
173 173
174 174
175 175 def getMonthList(args, kwargs, madWebObj):
176 176 """getMonthList is a helper function that returns the month choices in
177 177 SingleExpDefaultForm.categories at runtime. Value is (month number,
178 178 month name)
179 179
180 180 Inputs:
181 181 args, kwargs - arguments as passed into SingleExpDefaultForm __init__. Used to
182 182 determine and kinst and year
183 183 madWebObj - madrigal.ui.web.MadrigalWeb object
184 184 """
185 185 kinst = int(getSelection('instruments', args, kwargs))
186 186 year = int(getSelection('years', args, kwargs))
187 187 monthList = [('0', 'Select a month: '),]
188 188 addedMonthList = madWebObj.getMonths(kinst, year)
189 189 if len(addedMonthList) == 0:
190 190 addedMonthList = madWebObj.getMonths(kinst, year, optimize=False)
191 191 monthList += addedMonthList
192 192 return([(str(monthNumber), monthName) for monthNumber, monthName in monthList])
193 193
194 194
195 195 def getDayList():
196 196 """always returns 1 ... 31
197 197 """
198 198 dayList = [(i, str(i)) for i in range(1,32)]
199 199 return(dayList)
200 200
201 201
202 202 def getExpList(args, kwargs, madWebObj):
203 203 """getExpList is a helper function that returns the experiment choices in
204 204 SingleExpDefaultForm.categories at runtime. Value is (expId,
205 205 expDesc, expDir, pi_name, pi_email)
206 206
207 207 Inputs:
208 208 args, kwargs - arguments as passed into SingleExpDefaultForm __init__. Used to
209 209 determine and kinst, year, month, day
210 210 madWebObj - madrigal.ui.web.MadrigalWeb object
211 211 """
212 212 kinst = int(getSelection('instruments', args, kwargs))
213 213 year = int(getSelection('years', args, kwargs))
214 214 month = int(getSelection('months', args, kwargs))
215 215 day = int(getSelection('days', args, kwargs))
216 216 expList = madWebObj.getExpsOnDate(kinst, year, month, day)
217 217 if len(expList) == 0:
218 218 expList = madWebObj.getExpsOnDate(kinst, year, month, day, optimize=False)
219 219 return(expList)
220 220
221 221
222 222 def handle_registration(kwargs, user_email, expUrl, kinst, madDB):
223 223 """handle_registration causes the user to register or unregister interest in getting emails
224 224 when a particular experiment or instrument is updated
225 225
226 226 Inputs:
227 227 kwargs - dictionary as passed into form
228 228 user_email - users email address
229 229 expUrl - experiment url (part after /madtoc/)
230 230 kinst - instrument code
231 231 madDB - madrigal.metadata.MadrigalDB object
232 232 """
233 233 # first find out if this exp or inst is already registered
234 234 madUserObj = madrigal.ui.userData.MadrigalUserData(madDB)
235 235 expsRegistered = madUserObj.getRegisteredExperiments(user_email)
236 236 if expUrl in expsRegistered:
237 237 thisExpRegistered = True
238 238 else:
239 239 thisExpRegistered = False
240 240 instsRegistered = madUserObj.getRegisteredInstruments(user_email)
241 241 if kinst in instsRegistered:
242 242 thisInstRegistered = True
243 243 else:
244 244 thisInstRegistered = False
245 245
246 246 # check registration status, update if needed, and let form know how to print this
247 247 # 0 - no registration, 1 - exp registered, 2 - inst registered
248 248 if 'registerExp' in kwargs:
249 249 if not thisExpRegistered:
250 250 madUserObj.registerExperiment(user_email, expUrl)
251 251 return('1')
252 252 elif 'registerInst' in kwargs:
253 253 if not thisInstRegistered:
254 254 madUserObj.registerInstrument(user_email, kinst)
255 255 return('2')
256 256 elif 'unregisterExp' in kwargs:
257 257 if thisExpRegistered:
258 258 madUserObj.unregisterExperiment(user_email, expUrl)
259 259 return('0')
260 260 elif 'unregisterInst' in kwargs:
261 261 if thisInstRegistered:
262 262 madUserObj.unregisterInstrument(user_email, kinst)
263 263 return('0')
264 264 elif thisExpRegistered:
265 265 return('1')
266 266 elif thisInstRegistered:
267 267 return('2')
268 268 else:
269 269 return('0')
270 270
271 271
272 272 def getFormatChoices(basename, expID):
273 273 """getFormatChoices returns a list with 3 tuples, where each tuple
274 274 is 1. filename with correct extension, 2. Format
275 275
276 276 Inputs:
277 277 basename - basename of Madrigal Hdf5 file
278 278 expID - needed to determine if cached file available in near real time
279 279 """
280 280 madWebObj = madrigal.ui.web.MadrigalWeb()
281 281 formats = madWebObj.getFormatsAvailable(expID, basename)
282 282 fileName, fileExtension = os.path.splitext(basename)
283 283 retList = []
284 284 retList.append((basename, 'Hdf5')) # file is assumed to be in Hdf5 format
285 285 if 'ascii' in formats:
286 286 retList.append((fileName + '.txt', 'Space-delimited ascii'))
287 287 if 'netCDF4' in formats:
288 288 retList.append((fileName + '.nc', 'netCDF4'))
289 289 return(retList)
290 290
291 291
292 292 class RegisterForm(django.forms.Form):
293 293 """RegisterForm is the form class that supports the Register page
294 294 """
295 295 def __init__(self, *args, **kwargs):
296 296 super(RegisterForm, self).__init__(*args, **kwargs)
297 297 self.fields['user_fullname'] = django.forms.CharField(label='Full name', min_length=2, max_length=256)
298 298 self.fields['user_email'] = django.forms.EmailField(label='Email')
299 299 self.fields['user_affiliation'] = django.forms.CharField(label='Affliation (type "None" if individual)', min_length=2, max_length=256)
300 300
301 301
302 302
303 303 class SingleExpDefaultForm(django.forms.Form):
304 304 """SingleExpDefaultForm is a Form class for the default fields in the Single Experiment interface
305 305 (formally the Simple interface)
306 306 """
307 307 def __init__(self, *args, **kwargs):
308 308 super(SingleExpDefaultForm, self).__init__(*args, **kwargs)
309 309 madDB = madrigal.metadata.MadrigalDB()
310 310 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
311 311 user_email = getSelection('user_email', args, kwargs)
312 312 self.fields['isGlobal'] = django.forms.BooleanField(widget = django.forms.CheckboxInput(attrs={"onChange":'populateCat(this)'}),
313 313 required=False, label='Use all Madrigal sites: ',
314 314 initial=getIsGlobal(args, kwargs))
315 315
316 316
317 317 categoriesSelection = getSelection('categories', args, kwargs)
318 318 self.fields['categories'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'populateInst(this)'}),
319 319 choices=getCategoryList(args, kwargs, madInstData),
320 320 initial=categoriesSelection,
321 321 label='Instrument category:')
322 322
323 323 # the following fields may or may not be populated. All are also available as individual classes
324 324 # to allow AJAX calls to not need to create this full object
325 325
326 326 if categoriesSelection != '0':
327 327 instrumentSelection = getSelection('instruments', args, kwargs)
328 328 self.fields['instruments'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'populateYear(this)'}),
329 329 choices=getInstrumentList(args, kwargs, madInstData),
330 330 initial=instrumentSelection,
331 331 required=False, label='Instrument:')
332 332 else:
333 333 return # no need to create any further fields
334 334
335 335 if instrumentSelection != '0':
336 336 yearSelection = getSelection('years', args, kwargs)
337 337 self.fields['years'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'populateMonth(this)'}),
338 338 choices=getYearList(args, kwargs, madInstData),
339 339 initial=yearSelection,
340 340 required=False, label='Year:')
341 341
342 342 else:
343 343 return # no need to create any further fields
344 344
345 345 if yearSelection != '0':
346 346 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
347 347 monthSelection = getSelection('months', args, kwargs)
348 348 self.fields['months'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'populateCalendar(this)'}),
349 349 choices=getMonthList(args, kwargs, madWebObj),
350 350 initial=monthSelection, label='Month:')
351 351
352 352 else:
353 353 return # no need to create any further fields
354 354
355 355
356 356 if monthSelection != '0':
357 357 daySelection = getSelection('days', args, kwargs)
358 358 # this field is only used to help display the calendar
359 359 self.fields['days'] = django.forms.ChoiceField(required=False, choices=getDayList())
360 360
361 361 else:
362 362 return # no need to create any further fields
363 363
364 364 if daySelection != '0':
365 365 expFullList = getExpList(args, kwargs, madWebObj)
366 366 expIdSelection = None
367 367 if len(expFullList) > 1:
368 368 expList = [('0', 'Select one of multiple experiments')] + [(items[0], items[1]) for items in expFullList]
369 369 expIdSelection = getSelection('experiment_list', args, kwargs)
370 370 self.fields['experiment_list'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'populateFile(this)'}),
371 371 choices=expList, initial=expIdSelection,
372 372 required=False, label='Select experiment:')
373 373
374 374 if expIdSelection == '0':
375 375 # no need to create any further fields
376 376 return
377 377
378 378 if expIdSelection is None:
379 379 expIdSelection = expFullList[0][0]
380 380 expDir = expFullList[0][2]
381 381 else:
382 382 expDir = None
383 383 for expId, thisExpDesc, thisExpDir in expFullList:
384 384 if int(expIdSelection) == int(expId):
385 385 expDir = thisExpDir
386 386 break
387 387
388 388 fileList = madWebObj.getFileFromExpDir(expDir, int(instrumentSelection))
389 389 fileList = [('0', 'Select file')] + fileList
390 390 fileSelection = getSelection('file_list', args, kwargs)
391 391 self.fields['file_list'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'changeFile(this)'}),
392 392 choices=fileList, initial=fileSelection,
393 393 required=False, label='Select file:')
394 394 self.fields['exp_id'] = django.forms.CharField(initial=str(expIdSelection),
395 395 widget=django.forms.HiddenInput(attrs={'value': str(expIdSelection)}),
396 396 required=False,
397 397 label=str(expIdSelection))
398 398
399 399 pi_name, pi_email, expUrl, kinst, expDesc, kinstDesc = madWebObj.getExpInfoFromExpID(int(expIdSelection))
400 400
401 401 self.fields['exp_desc'] = django.forms.CharField(initial=str(expDesc),
402 402 widget=django.forms.HiddenInput(attrs={'value': str(expDesc)}),
403 403 required=False,
404 404 label=str(expDesc))
405 405 self.fields['user_email'] = django.forms.CharField(initial=str(user_email),
406 406 widget=django.forms.HiddenInput(attrs={'value': str(user_email)}),
407 407 required=False,
408 408 label=str(user_email))
409 409 self.fields['inst_desc'] = django.forms.CharField(initial=str(kinstDesc),
410 410 widget=django.forms.HiddenInput(attrs={'value': str(kinstDesc)}),
411 411 required=False,
412 412 label=str(kinstDesc))
413 413 self.fields['pi_name'] = django.forms.CharField(initial=pi_name,
414 414 widget=django.forms.HiddenInput(attrs={'value': pi_name}),
415 415 required=False,
416 416 label=pi_name)
417 417 self.fields['pi_email'] = django.forms.CharField(initial=pi_email,
418 418 widget=django.forms.HiddenInput(attrs={'value': pi_email}),
419 419 required=False,
420 420 label=pi_email)
421 421
422 422 # handle any needed registration or unregistration
423 423 register = handle_registration(args[0], user_email, expUrl, kinst, madDB)
424 424 self.fields['register'] = django.forms.CharField(initial=register,
425 425 widget=django.forms.HiddenInput(attrs={'value': register}),
426 426 required=False,
427 427 label=register)
428 428
429 429
430 430 else:
431 431 return # no need to create any further fields
432 432
433 433 if fileSelection != '0':
434 434 self.fields['file_buttons'] = django.forms.CharField(initial='',
435 435 widget=django.forms.HiddenInput(attrs={'value': ''}),
436 436 required=False,
437 437 label='')
438 438
439 439
440 440 else:
441 441 return # no need to create any further fields
442 442
443 443
444 444
445 445
446 446
447 447
448 448
449 449
450 450
451 451 class SingleExpInstForm(django.forms.Form):
452 452 """SingleExpInstForm is a Form class for the instrument select field in the Single Experiment interface.
453 453 Use this because its faster to create than the full SingleExpDefaultForm
454 454 """
455 455 def __init__(self, *args, **kwargs):
456 456 super(SingleExpInstForm, self).__init__(*args, **kwargs)
457 457 madDB = madrigal.metadata.MadrigalDB()
458 458 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
459 459 instrumentSelection = getSelection('instruments', args, kwargs)
460 460 self.fields['instruments'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'populateYear(this)'}),
461 461 choices=getInstrumentList(args, kwargs, madInstData),
462 462 initial=instrumentSelection,
463 463 label='Instrument:')
464 464
465 465 class SingleExpYearForm(django.forms.Form):
466 466 """SingleExpYearForm is a Form class for the year select field in the Single Experiment interface.
467 467 Use this because its faster to create than the full SingleExpDefaultForm
468 468 """
469 469 def __init__(self, *args, **kwargs):
470 470 super(SingleExpYearForm, self).__init__(*args, **kwargs)
471 471 madDB = madrigal.metadata.MadrigalDB()
472 472 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
473 473 yearSelection = getSelection('years', args, kwargs)
474 474 self.fields['years'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'populateMonth(this)'}),
475 475 choices=getYearList(args, kwargs, madInstData),
476 476 initial=yearSelection, label='Year:')
477 477
478 478
479 479 class SingleExpMonthForm(django.forms.Form):
480 480 """SingleExpMonthForm is a Form class for the month select field in the Single Experiment interface.
481 481 Use this because its faster to create than the full SingleExpDefaultForm
482 482 """
483 483 def __init__(self, *args, **kwargs):
484 484 super(SingleExpMonthForm, self).__init__(*args, **kwargs)
485 485 madDB = madrigal.metadata.MadrigalDB()
486 486 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
487 487 monthSelection = getSelection('months', args, kwargs)
488 488 self.fields['months'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'populateCalendar(this)'}),
489 489 choices=getMonthList(args, kwargs, madWebObj),
490 490 initial=monthSelection, label='Month:')
491 491
492 492
493 493 class SingleExpCalendarForm(django.forms.Form):
494 494 """SingleExpCalendarForm is a Form class for the calendar field in the Single Experiment interface.
495 495 Use this because its faster to create than the full SingleExpDefaultForm
496 496 """
497 497 def __init__(self, *args, **kwargs):
498 498 super(SingleExpCalendarForm, self).__init__(*args, **kwargs)
499 499 madDB = madrigal.metadata.MadrigalDB()
500 500 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
501 501
502 502
503 503 class SingleExpFileForm(django.forms.Form):
504 504 """SingleExpFileForm is a Form class for the file select field in the Single Experiment interface.
505 505 Use this because its faster to create than the full SingleExpDefaultForm
506 506 """
507 507 def __init__(self, *args, **kwargs):
508 508 super(SingleExpFileForm, self).__init__(*args, **kwargs)
509 509 madDB = madrigal.metadata.MadrigalDB()
510 510 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
511 511 expID = getSelection('experiment_list', args, kwargs)
512 512 try:
513 513 expID = int(expID)
514 514 except ValueError:
515 515 # convert expPath to expID
516 516 expID = madWebObj.getExpIDFromExpPath(expID, True)
517 517 user_email = getSelection('user_email', args, kwargs)
518 518 include_non_default = getSelection('includeNonDefault', args, kwargs)
519 519 if include_non_default == '0':
520 520 include_non_default = False
521 521 fileList = madWebObj.getFileFromExpID(expID, include_non_default)
522 522 fileList = [('0', 'Select file')] + fileList
523 523
524 524 fileSelection = getSelection('file_list', args, kwargs)
525 525 self.fields['file_list'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'changeFile(this)'}),
526 526 choices=fileList, initial=fileSelection,
527 527 required=False, label='Select file:')
528 528 if int(expID) != 0:
529 529 self.fields['exp_id'] = django.forms.CharField(initial=str(expID),
530 530 widget=django.forms.HiddenInput(attrs={'value': str(expID)}),
531 531 required=False,
532 532 label=str(expID))
533 533 pi_name, pi_email, expUrl, kinst, expDesc, kinstDesc = madWebObj.getExpInfoFromExpID(int(expID))
534 534
535 535 self.fields['exp_desc'] = django.forms.CharField(initial=str(expDesc),
536 536 widget=django.forms.HiddenInput(attrs={'value': str(expDesc)}),
537 537 required=False,
538 538 label=str(expDesc))
539 539 self.fields['user_email'] = django.forms.CharField(initial=str(user_email),
540 540 widget=django.forms.HiddenInput(attrs={'value': str(user_email)}),
541 541 required=False,
542 542 label=str(user_email))
543 543 self.fields['inst_desc'] = django.forms.CharField(initial=str(kinstDesc),
544 544 widget=django.forms.HiddenInput(attrs={'value': str(kinstDesc)}),
545 545 required=False,
546 546 label=str(kinstDesc))
547 547 self.fields['pi_name'] = django.forms.CharField(initial=pi_name,
548 548 widget=django.forms.HiddenInput(attrs={'value': pi_name}),
549 549 required=False,
550 550 label=pi_name)
551 551 self.fields['pi_email'] = django.forms.CharField(initial=pi_email,
552 552 widget=django.forms.HiddenInput(attrs={'value': pi_email}),
553 553 required=False,
554 554 label=pi_email)
555 555 self.fields['includeNonDefault'] = django.forms.BooleanField(widget = django.forms.CheckboxInput(attrs={"onChange":'reloadFiles(this)'}),
556 556 required=False, label='Show non-default files: ',
557 557 initial=include_non_default)
558 558 # handle any needed registration or unregistration
559 559 register = handle_registration(args[0], user_email, expUrl, kinst, madDB)
560 560 self.fields['register'] = django.forms.CharField(initial=register,
561 561 widget=django.forms.HiddenInput(attrs={'value': register}),
562 562 required=False,
563 563 label=register)
564 564
565 565 if fileSelection != '0':
566 566 self.fields['file_buttons'] = django.forms.CharField(initial='',
567 567 widget=django.forms.HiddenInput(attrs={'value': ''}),
568 568 required=False,
569 569 label='')
570 570 self.fields['basename'] = django.forms.CharField(initial=str(fileSelection),
571 571 widget=django.forms.HiddenInput(attrs={'value': str(fileSelection)}),
572 572 required=False,
573 573 label=str(fileSelection))
574 574
575 575
576 576
577 577
578 578
579 579 class SingleExpButtonsForm(django.forms.Form):
580 580 """SingleExpButtonsForm is a Form class for the file buttons field in the Single Experiment interface.
581 581 Use this because its faster to create than the full SingleExpDefaultForm
582 582 """
583 583 def __init__(self, *args, **kwargs):
584 584 super(SingleExpButtonsForm, self).__init__(*args, **kwargs)
585 585 madDB = madrigal.metadata.MadrigalDB()
586 586 madExpObj = madrigal.metadata.MadrigalExperiment(madDB)
587 587 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
588 588 expID = getSelection('experiment_list', args, kwargs)
589 589 try:
590 590 expID = int(expID)
591 591 except ValueError:
592 592 # convert expPath to expID
593 593 expID = madWebObj.getExpIDFromExpPath(expID, True)
594 594
595 595 fileSelection = getSelection('file_list', args, kwargs)
596 596
597 597 expDir = madExpObj.getExpDirByExpId(int(expID))
598 598 filesize = os.path.getsize(os.path.join(expDir, str(fileSelection)))
599 599
600 600 self.fields['file_buttons'] = django.forms.CharField(initial='',
601 601 widget=django.forms.HiddenInput(attrs={'value': ''}),
602 602 required=False,
603 603 label='')
604 604 self.fields['exp_id'] = django.forms.CharField(initial=str(expID),
605 605 widget=django.forms.HiddenInput(attrs={'value': str(expID)}),
606 606 required=False,
607 607 label=str(expID))
608 608 self.fields['basename'] = django.forms.CharField(initial=str(fileSelection),
609 609 widget=django.forms.HiddenInput(attrs={'value': str(fileSelection)}),
610 610 required=False,
611 611 label=str(fileSelection))
612 612 self.fields['filesize'] = django.forms.IntegerField(initial=filesize,
613 613 widget=django.forms.HiddenInput(attrs={'value': filesize}),
614 614 required=False,
615 615 label=str(filesize))
616 616
617 617
618 618 class SingleExpPlotsForm(django.forms.Form):
619 619 """SingleExpPlotsForm is a Form class for the file data/show plots field in the Single Experiment interface.
620 620 Use this because its faster to create than the full SingleExpDefaultForm
621 621 """
622 622 def __init__(self, *args, **kwargs):
623 623 super(SingleExpPlotsForm, self).__init__(*args, **kwargs)
624 624 madDB = madrigal.metadata.MadrigalDB()
625 625 madExpObj = madrigal.metadata.MadrigalExperiment(madDB)
626 626 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
627 627 expID = getSelection('experiment_list', args, kwargs)
628 628 try:
629 629 expID = int(expID)
630 630 except ValueError:
631 631 # convert expPath to expID
632 632 expID = madWebObj.getExpIDFromExpPath(expID, True)
633 633 plotList = madExpObj.getExpLinksByExpId(expID)
634 634 if len(plotList) == 0:
635 635 plotList = [('No plots available', '')]
636 636
637 637 self.fields['plot_list'] = django.forms.ChoiceField(widget = django.forms.Select(),
638 638 choices=plotList,
639 639 required=False)
640 640
641 641 '''get_params2 retrieves a list of 1d and 2d parameters of type 1 hdf5 files'''
642
643 def check_mnemonic(s):
644
645 return s.replace('+', '%2b')
646
642 647 def get_params1(args, kwargs, madExpObj, madWebObj):
643 648
644 649 expID = getSelection('experiment_list', args, kwargs)
645 650 expDir = madExpObj.getExpDirByExpId(expID)
646 651 fileList = madWebObj.getFileFromExpID(expID, False)
647 652
648 653 firsttuple = [a_tuple[0] for a_tuple in fileList]
649 654 basename = firsttuple[0]
650 655 fullFilename = os.path.join(expDir, basename)
651 656 f = h5py.File(fullFilename, "r")
652 data = f[list(f.keys())[0]]
653 array = data[list(data.keys())[0]]
654
655 param1d = array[list(array.keys())[0]]
656 param2d = array[list(array.keys())[1]]
657 paramch1d = list(param1d.keys())
658 paramch2d = list(param2d.keys())
659
660 dataparameters = param1d[list(param1d.keys())[0]]
661 paramch_mn_bin = list(dataparameters['mnemonic'])
662 paramch_bin = list(dataparameters['description'])
663 paramch_mn = list()
664 paramch = list()
665
666 for i in range(len(paramch_bin)):
667 paramch_mn.append(paramch_mn_bin[i].decode("utf-8"))
668 paramch.append(paramch_bin[i].decode("utf-8"))
669
670 choices1d = ['Select parameter']
671 for ch in paramch1d[1:]:
672 aux = paramch[paramch_mn.index(ch.upper())]
673 choices1d.append(aux)
674
675
676 dataparameters = param2d[list(param2d.keys())[0]]
677 paramch_mn_bin = list(dataparameters['mnemonic'])
678 paramch_mn = list()
679 paramch_bin = list(dataparameters['description'])
680 paramch = list()
681
682 for i in range(len(paramch_bin)):
683 paramch_mn.append(paramch_mn_bin[i].decode("utf-8"))
684 paramch.append(paramch_bin[i].decode("utf-8"))
685
686 choices2d = ['Select parameter']
687 for ch in paramch2d[1:]:
688 aux = paramch[paramch_mn.index(ch.upper())]
689 choices2d.append(aux)
690
691
692 choices = [choices1d,choices2d]
657
658 data = f['Data']
659
660 choices1d = [(check_mnemonic(x[0].decode().lower()), x[1].decode()) for x in data['Array Layout']['1D Parameters']['Data Parameters']]
661 choices2d = [(check_mnemonic(x[0].decode().lower()), x[1].decode()) for x in data['Array Layout']['2D Parameters']['Data Parameters']]
662 choices = [[('0', 'Select Parameter')] + choices1d, [('0', 'Select Parameter')] + choices2d]
663 f.close()
693 664 return choices
694 665
695 666
696 667 '''get params2 retrieves a list of 1d parameters of type 2 of hdf5 files'''
697 668 def get_params2(args, kwargs, madExpObj, madWebObj):
698 669
699 670 expID = getSelection('experiment_list', args, kwargs)
700 671 expDir = madExpObj.getExpDirByExpId(expID)
701 672 fileList = madWebObj.getFileFromExpID(expID, False)
702 673
703 674 firsttuple = [a_tuple[0] for a_tuple in fileList]
704 675 basename = firsttuple[0]
705 676 fullFilename = os.path.join(expDir, basename)
706 677 f = h5py.File(fullFilename, "r")
707
708 metadata = f[list(f.keys())[1]]
709 table = metadata[list(metadata.keys())[0]]
710 param_mn_bin = list(table['mnemonic'])
711 param_mn = list()
712 for p in param_mn_bin:
713 param_mn.append(p.decode("utf"))
714
715 index = param_mn.index('UT2_UNIX')
716 params = list(table['description'])
717 choices = ['Select parameter']
718 for p in params[index+1:]:
719 choices.append(p.decode("utf-8"))
720
721 return choices
678 parameters = [(x[0].decode().lower(), x[1].decode()) for x in f['Metadata']['Data Parameters']]
679 f.close()
680 return [('0', 'Select Parameter')] + parameters
722 681
723 682
724 683 class SingleExpPlotsSelectionForm(django.forms.Form):
725 684 """SingleExpPlotsSselectionForm is a Form class for the parameters selection for plotting in the Single Experiment interface.
726 685 Use this because its faster to create than the full SingleExpDefaultForm
727 686 """
728 687
729 688 def __init__(self, *args, **kwargs):
730 689 super(SingleExpPlotsSelectionForm, self).__init__(*args, **kwargs)
731 690 madDB = madrigal.metadata.MadrigalDB()
732 691 madExpObj = madrigal.metadata.MadrigalExperiment(madDB)
733 692 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
734 693 expID = getSelection('experiment_list', args, kwargs)
735 694 try:
736 695 expID = int(expID)
737 696 except ValueError:
738 697 # convert expPath to expID
739 698 expID = madWebObj.getExpIDFromExpPath(expID, True)
740 699 expDir = madExpObj.getExpDirByExpId(expID)
741 700 fileList = madWebObj.getFileFromExpID(expID, False)
742 701
743 702 firsttuple = [a_tuple[0] for a_tuple in fileList]
744 703 basename = firsttuple[0]
745 704 fullFilename = os.path.join(expDir, basename)
746 705 f = h5py.File(fullFilename, "r")
747 706 data = f[list(f.keys())[0]]
748 707
749 708 if 'Array Layout' in list(data.keys()):
750 709 choices = get_params1(args, kwargs, madExpObj, madWebObj)
751 710 params1d = choices[0]
752 711 params2d = choices[1]
753
754 index = list(range(len(params1d)))
755 paramchoices1d = list(zip(index, params1d))
756
757
758 index = list(range(len(params2d)))
759 paramchoices2d = list(zip(index, params2d))
760
761
762 self.fields['param_list2d'] = django.forms.ChoiceField(widget = django.forms.Select(), choices=paramchoices2d, label="2D Parameters", required=False)
712 self.fields['param_list1d'] = django.forms.ChoiceField(widget = django.forms.Select(), choices=params1d, label="1D Parameters", required=False)
713 self.fields['param_list2d'] = django.forms.ChoiceField(widget = django.forms.Select(), choices=params2d, label="2D Parameters", required=False)
763 714
764 715 else:
765 716 params1d = get_params2(args, kwargs, madExpObj, madWebObj)
766 #if params1d[0] == 'ut2_unix':
767 # params1d[0] = 'Select parameter'
768 index = list(range(len(params1d)))
769 paramchoices1d = list(zip(index, params1d))
770
771 self.fields['param_list1d'] = django.forms.ChoiceField(widget = django.forms.Select(), choices=paramchoices1d, label="1D Parameters", required=False)
717 self.fields['param_list1d'] = django.forms.ChoiceField(widget = django.forms.Select(), choices=params1d, label="1D Parameters", required=False)
772 718
773 719
774
775 720 class SingleExpDownloadAsIsForm(django.forms.Form):
776 721 """SingleExpDownloadAsIsForm is a Form class for the download as is field in the Single Experiment interface.
777 722 Use this because its faster to create than the full SingleExpDefaultForm
778 723 """
779 724 def __init__(self, *args, **kwargs):
780 725 super(SingleExpDownloadAsIsForm, self).__init__(*args, **kwargs)
781 726 basename = getSelection('format_select', args, kwargs)
782 727 expID = int(getSelection('expID', args, kwargs))
783 728 formatChoices = getFormatChoices(basename, expID)
784 729
785 730 self.fields['format_select'] = django.forms.ChoiceField(widget = HorizontalRadioSelect(attrs={"onChange":'changeFormat(this)'}),
786 731 choices=formatChoices,
787 732 required=False)
788 733
789 734
790 735
791 736
792 737 class IsprintChoiceField(django.forms.TypedMultipleChoiceField):
793 738 """IsprintChoiceField is subclass of TypedMultipleChoiceField
794 739 """
795 740 def __init__(self, *args, **kwargs):
796 741 """__init__ allows all the arguments of TypedMultipleChoiceField, plus extra
797 742 keyword arguments:
798 743 madWebObject madrigal.ui.web.MadrigalWeb object
799 744 """
800 745 self.isDerivedDict = kwargs.pop('isDerivedDict')
801 746 self.parmDescDict = kwargs.pop('parmDescDict')
802 747 try:
803 748 self.separateProlog = kwargs.pop('separateProlog')
804 749 except:
805 750 self.separateProlog = False
806 751
807 752 kwargs['widget'] = IsprintWidget(attrs={'isDerivedDict':self.isDerivedDict,
808 753 'parmDescDict':self.parmDescDict,
809 754 'separateProlog':self.separateProlog})
810 755 super(IsprintChoiceField, self).__init__(*args, **kwargs)
811 756 self.widget.set_parm_lists(self.isDerivedDict, self.parmDescDict, self.separateProlog)
812 757
813 758
814 759
815 760
816 761 class IsprintWidget(django.forms.CheckboxSelectMultiple):
817 762 """IsprintWidget is a subclass of CheckboxSelectMultiple with additional parameters passed in
818 763 to modify rendering
819 764 """
820 765 def __init__(self, *args, **kwargs):
821 766 """__init__ allows all the arguments of CheckboxSelectMultiple, plus extra
822 767 keyword arguments:
823 768 madWebObject madrigal.ui.web.MadrigalWeb object
824 769 """
825 770 super(IsprintWidget, self).__init__(*args, **kwargs)
826 771 self.renderer = django.forms.CheckboxSelectMultiple
827 772 self.template_name = 'madweb/parameter_multiple.html'
828 773
829 774
830 775 def set_parm_lists(self, isDerivedDict, parmDescDict, separateProlog=False):
831 776 """set_parm_lists sets class variables used by the html renderer
832 777
833 778 measParmList - parms in the file
834 779 derivedParmList - parms derivable
835 780 allParmList - above lists combined
836 781 separateProlog - if true, create separate div tags so prolog parms can be hidden or not.
837 782 Default is False, in which case no div tags are used
838 783 """
839 784 self.renderer.isDerivedDict = isDerivedDict
840 785 self.renderer.parmDescDict = parmDescDict
841 786 self.renderer.iterator = itertools.count()
842 787 self.renderer.separateProlog = separateProlog
843 788
844 789
845 790
846 791
847 792 class IsprintForm(django.forms.Form):
848 793 """IsprintForm is the form for the enhanced isprint page
849 794 """
850 795 def __init__(self, *args, **kwargs):
851 796
852 797 madFileObj = getSelection('madFileObj', args, kwargs)
853 798 type = getSelection('type', args, kwargs)
854 799 formatChoices = [('ascii', 'Space-delimited ascii')]
855 800 if type == 'download':
856 801 formatChoices.insert(0, ('netCDF4', 'netCDF4'))
857 802 formatChoices.insert(0, ('Hdf5', 'Hdf5'))
858 803 separateProlog = True
859 804 else:
860 805 separateProlog = False
861 806
862 807 madDB = getSelection('madDB', args, kwargs)
863 808 madParmObj = getSelection('madParmObj', args, kwargs)
864 809 derivedParmList = getSelection('derivedParmList', args, kwargs)
865 810 allParmList = getSelection('allParmList', args, kwargs)
866 811 allParmDescList = getSelection('allParmDescList', args, kwargs)
867 812 self.parmList = list(zip(allParmList, allParmDescList))
868 813 super(IsprintForm, self).__init__(*args, **kwargs)
869 814
870 815 madCatObj = madrigal.metadata.MadrigalParmCategory(madDB)
871 816
872 817 catList = madCatObj.getCategoryList()
873 818 catDict = madParmObj.getCategoryDict(allParmList)
874 819
875 820 choices = []
876 821 isDerivedDict = {}
877 822 parmDescDict = {}
878 823 for catDesc, catID in catList:
879 824 if catID not in list(catDict.keys()):
880 825 continue
881 826 theseParms = []
882 827 for parm in catDict[catID][1]:
883 828 theseParms.append((parm, parm))
884 829 if parm in derivedParmList:
885 830 isDerivedDict[parm] = True
886 831 else:
887 832 isDerivedDict[parm] = False
888 833 parmDescDict[parm] = madParmObj.getParmDescription(parm)
889 834 choices.append((catDesc, theseParms))
890 835
891 836 choices_with_null = [('None', 'None')] + choices
892 837
893 838 earliestTime = madFileObj.getEarliestTime()
894 839 latestTime = madFileObj.getLatestTime()
895 840 earliestDT = datetime.datetime(*earliestTime)
896 841 latestDT = datetime.datetime(*latestTime)
897 842 earliestStr = earliestDT.strftime('%Y-%m-%d %H:%M:%S')
898 843 latestStr = latestDT.strftime('%Y-%m-%d %H:%M:%S')
899 844
900 845 self.fields['fullFilename'] = django.forms.CharField(required=False, widget=django.forms.HiddenInput())
901 846 self.fields['type'] = django.forms.CharField(required=False, widget=django.forms.HiddenInput())
902 847
903 848 # format fields
904 849 self.fields['formats'] = django.forms.ChoiceField(widget = HorizontalRadioSelect(attrs={"onChange":'changeFormat(this)'}),
905 850 choices=formatChoices, initial='ascii',
906 851 required=False, label='Select output format:')
907 852
908 853 self.fields['showHeaders'] = django.forms.BooleanField(required=False, label='Show headers:',
909 854 help_text="Select this to show a header line before each record")
910 855
911 856 self.fields['missing'] = django.forms.CharField(required=False,
912 857 label='Missing value string: ',
913 858 help_text='Modify this field to display something other than NaN for missing or assumed or known bad data.')
914 859
915 860 # form fields
916 861 self.fields['parameters'] = IsprintChoiceField(choices=choices,
917 862 required=False,
918 863 initial=['YEAR', 'MIN'],
919 864 isDerivedDict=isDerivedDict,
920 865 parmDescDict=parmDescDict,
921 866 separateProlog=separateProlog,
922 867 label = "")
923 868
924 869 # time selection
925 870 self.fields['start_date'] = django.forms.DateTimeField(input_formats=['%Y-%m-%dT%H:%M:%S'],
926 871 label='Start datetime',
927 872 help_text='Modify this field to remove all records before this start time. Initial start datetime is the time of the first record.',
928 873 widget=django.forms.DateTimeInput(format='%Y-%m-%dT%H:%M:%S'),
929 874 required=False)
930 875
931 876 self.fields['end_date'] = django.forms.DateTimeField(input_formats=['%Y-%m-%dT%H:%M:%S'],
932 877 label='End datetime',
933 878 help_text='Modify this field to remove all records after this end time. Initial end datetime is the time of the last record.',
934 879 widget=django.forms.DateTimeInput(format='%Y-%m-%dT%H:%M:%S'),
935 880 required=False)
936 881
937 882 self.fields['parm_1'] = django.forms.ChoiceField(required=False,
938 883 choices=choices_with_null)
939 884 self.fields['parm_1_lower'] = django.forms.CharField(required=False, initial='')
940 885 self.fields['parm_1_upper'] = django.forms.CharField(required=False, initial='')
941 886
942 887 self.fields['parm_2'] = django.forms.ChoiceField(required=False,
943 888 choices=choices_with_null)
944 889 self.fields['parm_2_lower'] = django.forms.CharField(required=False, initial='')
945 890 self.fields['parm_2_upper'] = django.forms.CharField(required=False, initial='')
946 891
947 892 self.fields['parm_3'] = django.forms.ChoiceField(required=False,
948 893 choices=choices_with_null)
949 894 self.fields['parm_3_lower'] = django.forms.CharField(required=False, initial='')
950 895 self.fields['parm_3_upper'] = django.forms.CharField(required=False, initial='')
951 896
952 897 # add optional fields
953 898 if 'GDALT' in allParmList:
954 899 min_alt_value = getSelection('min_alt', args, kwargs)
955 900 max_alt_value = getSelection('max_alt', args, kwargs)
956 901 if min_alt_value != max_alt_value:
957 902 self.fields['min_alt'] = django.forms.CharField(required=False,
958 903 label='Min altitude:',
959 904 help_text='Modify this field to remove all data with altitudes below this level.')
960 905 self.fields['max_alt'] = django.forms.CharField(required=False,
961 906 label='Max altitude:',
962 907 help_text='Modify this field to remove all data with altitudes above this level.')
963 908
964 909 if 'AZM' in allParmList:
965 910 self.fields['min_az'] = django.forms.CharField(required=False,
966 911 label='Min azimuth:',
967 912 help_text='Modify this field to remove all azimuths (-180 to 180) below this value. You can also have two separate azimuth ranges by using the Azimuth 2 fields.')
968 913 self.fields['max_az'] = django.forms.CharField(required=False,
969 914 label='Max azimuth:',
970 915 help_text='Modify this field to remove all azimuths (-180 to 180) above this value. You can also have two separate azimuth ranges by using the Azimuth 2 fields.')
971 916 self.fields['min_az2'] = django.forms.CharField(required=False,
972 917 label='Min azimuth 2:',
973 918 help_text='Modify this field to have a second allowed azimuth range. This would set the lower limit of the second range.')
974 919 self.fields['max_az2'] = django.forms.CharField(required=False,
975 920 label='Max azimuth 2:',
976 921 help_text='Modify this field to have a second allowed azimuth range. This would set the upper limit of the second range.')
977 922
978 923 if 'ELM' in allParmList:
979 924 self.fields['min_el'] = django.forms.CharField(required=False,
980 925 label='Min elevation:',
981 926 help_text='Modify this field to remove all elevations (0 to 90) below this value. You can also have two separate elevations ranges by using the Elevations 2 fields.')
982 927 self.fields['max_el'] = django.forms.CharField(required=False,
983 928 label='Max elevation:',
984 929 help_text='Modify this field to remove all elevations (0 to 90) above this value. You can also have two separate elevations ranges by using the Elevations 2 fields.')
985 930 self.fields['min_el2'] = django.forms.CharField(required=False,
986 931 label='Min elevation 2:',
987 932 help_text='Modify this field to have a second allowed elevation range. This would set the lower limit of the second range.')
988 933 self.fields['max_el2'] = django.forms.CharField(required=False,
989 934 label='Max elevation 2:',
990 935 help_text='Modify this field to have a second allowed elevation range. This would set the upper limit of the second range.')
991 936
992 937 if 'PL' in allParmList:
993 938 min_pl_value = getSelection('min_pl', args, kwargs)
994 939 max_pl_value = getSelection('max_pl', args, kwargs)
995 940 self.fields['min_pl'] = django.forms.CharField(required=False,
996 941 label='Min pulse len (microsec): ',
997 942 help_text='Modify this field to remove all pulse lengths in microsecs below this value.')
998 943 self.fields['max_pl'] = django.forms.CharField(required=False,
999 944 label='Max pulse len (microsec): ',
1000 945 help_text='Modify this field to remove all pulse lengths in microsecs above this value.')
1001 946
1002 947
1003 948 def clean_fullFilename(self):
1004 949 fullFilename = self.cleaned_data['fullFilename']
1005 950 # make sure the file exists
1006 951 if not os.access(fullFilename, os.R_OK):
1007 952 raise django.forms.ValidationError('Invalid filename: %(value)s cannot be opened',
1008 953 code='io_error',
1009 954 params={'value': fullFilename})
1010 955
1011 956 return(fullFilename)
1012 957
1013 958
1014 959 def clean_formats(self):
1015 960 formats = self.cleaned_data['formats']
1016 961 # make sure the format valid
1017 962 if formats not in ('Hdf5', 'netCDF4', 'ascii'):
1018 963 raise django.forms.ValidationError('Invalid format: %(value)s not legal format',
1019 964 code='invalid',
1020 965 params={'value': formats})
1021 966
1022 967 return(formats)
1023 968
1024 969
1025 970 def clean_min_alt(self):
1026 971 min_alt = self.cleaned_data['min_alt']
1027 972 if len(min_alt) != 0:
1028 973 try:
1029 974 min_alt_value = float(min_alt)
1030 975 except:
1031 976 raise django.forms.ValidationError('Invalid minimum altitude: %(value)s cannot be converted to a float',
1032 977 code='invalid',
1033 978 params={'value': min_alt})
1034 979 if min_alt_value < 0.0:
1035 980 raise django.forms.ValidationError('Invalid minimum altitude: %(value)s cannot be less than 0.0 kilometers',
1036 981 code='invalid',
1037 982 params={'value': min_alt})
1038 983 return(min_alt)
1039 984
1040 985 def clean_max_alt(self):
1041 986 max_alt = self.cleaned_data['max_alt']
1042 987 if len(max_alt) != 0:
1043 988 try:
1044 989 max_alt_value = float(max_alt)
1045 990 except:
1046 991 raise django.forms.ValidationError('Invalid maximum altitude: %(value)s cannot be converted to a float',
1047 992 code='invalid',
1048 993 params={'value': max_alt})
1049 994 if max_alt_value < 0.0:
1050 995 raise django.forms.ValidationError('Invalid maximum altitude: %(value)s cannot be less than 0.0 kilometers',
1051 996 code='invalid',
1052 997 params={'value': max_alt})
1053 998 return(max_alt)
1054 999
1055 1000
1056 1001 def clean_min_az(self):
1057 1002 min_az = self.cleaned_data['min_az']
1058 1003 if len(min_az) != 0:
1059 1004 try:
1060 1005 min_az_value = float(min_az)
1061 1006 except:
1062 1007 raise django.forms.ValidationError('Invalid minimum azimuth: %(value)s cannot be converted to a float',
1063 1008 code='invalid',
1064 1009 params={'value': min_az})
1065 1010 if min_az_value < -180.0:
1066 1011 raise django.forms.ValidationError('Invalid minimum azimuth: %(value)s cannot be less than -180 degrees',
1067 1012 code='invalid',
1068 1013 params={'value': min_az})
1069 1014 if min_az_value > 180.0:
1070 1015 raise django.forms.ValidationError('Invalid minimum azimuth: %(value)s cannot be more than 180 degrees',
1071 1016 code='invalid',
1072 1017 params={'value': min_az})
1073 1018 return(min_az)
1074 1019
1075 1020
1076 1021 def clean_max_az(self):
1077 1022 max_az = self.cleaned_data['max_az']
1078 1023 if len(max_az) != 0:
1079 1024 try:
1080 1025 max_az_value = float(max_az)
1081 1026 except:
1082 1027 raise django.forms.ValidationError('Invalid maximum azimuth: %(value)s cannot be converted to a float',
1083 1028 code='invalid',
1084 1029 params={'value': max_az})
1085 1030 if max_az_value < -180.0:
1086 1031 raise django.forms.ValidationError('Invalid maximum azimuth: %(value)s cannot be less than -180 degrees',
1087 1032 code='invalid',
1088 1033 params={'value': max_az})
1089 1034 if max_az_value > 180.0:
1090 1035 raise django.forms.ValidationError('Invalid maximum azimuth: %(value)s cannot be more than 180 degrees',
1091 1036 code='invalid',
1092 1037 params={'value': max_az})
1093 1038 return(max_az)
1094 1039
1095 1040
1096 1041 def clean_min_el(self):
1097 1042 min_el = self.cleaned_data['min_el']
1098 1043 if len(min_el) != 0:
1099 1044 try:
1100 1045 min_el_value = float(min_el)
1101 1046 except:
1102 1047 raise django.forms.ValidationError('Invalid minimum elevation: %(value)s cannot be converted to a float',
1103 1048 code='invalid',
1104 1049 params={'value': min_el})
1105 1050 if min_el_value < 0.0:
1106 1051 raise django.forms.ValidationError('Invalid minimum elevation: %(value)s cannot be less than 0 degrees',
1107 1052 code='invalid',
1108 1053 params={'value': min_el})
1109 1054 if min_el_value > 90.0:
1110 1055 raise django.forms.ValidationError('Invalid minimum elevation: %(value)s cannot be more than 90 degrees',
1111 1056 code='invalid',
1112 1057 params={'value': min_el})
1113 1058 return(min_el)
1114 1059
1115 1060
1116 1061 def clean_max_el(self):
1117 1062 max_el = self.cleaned_data['max_el']
1118 1063 if len(max_el) != 0:
1119 1064 try:
1120 1065 max_el_value = float(max_el)
1121 1066 except:
1122 1067 raise django.forms.ValidationError('Invalid maximum elevation: %(value)s cannot be converted to a float',
1123 1068 code='invalid',
1124 1069 params={'value': max_el})
1125 1070 if max_el_value < 0.0:
1126 1071 raise django.forms.ValidationError('Invalid maximum elevation: %(value)s cannot be less than 0 degrees',
1127 1072 code='invalid',
1128 1073 params={'value': max_el})
1129 1074 if max_el_value > 90.0:
1130 1075 raise django.forms.ValidationError('Invalid maximum elevation: %(value)s cannot be more than 90 degrees',
1131 1076 code='invalid',
1132 1077 params={'value': max_el})
1133 1078 return(max_el)
1134 1079
1135 1080
1136 1081 def clean_min_az2(self):
1137 1082 min_az2 = self.cleaned_data['min_az2']
1138 1083 if len(min_az2) != 0:
1139 1084 try:
1140 1085 min_az2_value = float(min_az2)
1141 1086 except:
1142 1087 raise django.forms.ValidationError('Invalid minimum azimuth 2: %(value)s cannot be converted to a float',
1143 1088 code='invalid',
1144 1089 params={'value': min_az2})
1145 1090 if min_az2_value < -180.0:
1146 1091 raise django.forms.ValidationError('Invalid minimum azimuth 2: %(value)s cannot be less than -180 degrees',
1147 1092 code='invalid',
1148 1093 params={'value': min_az2})
1149 1094 if min_az2_value > 180.0:
1150 1095 raise django.forms.ValidationError('Invalid minimum azimuth 2: %(value)s cannot be more than 180 degrees',
1151 1096 code='invalid',
1152 1097 params={'value': min_az2})
1153 1098 return(min_az2)
1154 1099
1155 1100
1156 1101 def clean_max_az2(self):
1157 1102 max_az2 = self.cleaned_data['max_az2']
1158 1103 if len(max_az2) != 0:
1159 1104 try:
1160 1105 max_az2_value = float(max_az2)
1161 1106 except:
1162 1107 raise django.forms.ValidationError('Invalid maximum azimuth 2: %(value)s cannot be converted to a float',
1163 1108 code='invalid',
1164 1109 params={'value': max_az2})
1165 1110 if max_az2_value < -180.0:
1166 1111 raise django.forms.ValidationError('Invalid maximum azimuth 2: %(value)s cannot be less than -180 degrees',
1167 1112 code='invalid',
1168 1113 params={'value': max_az2})
1169 1114 if max_az2_value > 180.0:
1170 1115 raise django.forms.ValidationError('Invalid maximum azimuth 2: %(value)s cannot be more than 180 degrees',
1171 1116 code='invalid',
1172 1117 params={'value': max_az2})
1173 1118 return(max_az2)
1174 1119
1175 1120
1176 1121 def clean_min_el2(self):
1177 1122 min_el2 = self.cleaned_data['min_el2']
1178 1123 if len(min_el2) != 0:
1179 1124 try:
1180 1125 min_el2_value = float(min_el2)
1181 1126 except:
1182 1127 raise django.forms.ValidationError('Invalid minimum elevation 2: %(value)s cannot be converted to a float',
1183 1128 code='invalid',
1184 1129 params={'value': min_el2})
1185 1130 if min_el2_value < 0.0:
1186 1131 raise django.forms.ValidationError('Invalid minimum elevation 2: %(value)s cannot be less than 0 degrees',
1187 1132 code='invalid',
1188 1133 params={'value': min_el2})
1189 1134 if min_el2_value > 90.0:
1190 1135 raise django.forms.ValidationError('Invalid minimum elevation 2: %(value)s cannot be more than 90 degrees',
1191 1136 code='invalid',
1192 1137 params={'value': min_el2})
1193 1138 return(min_el2)
1194 1139
1195 1140
1196 1141 def clean_max_el2(self):
1197 1142 max_el2 = self.cleaned_data['max_el2']
1198 1143 if len(max_el2) != 0:
1199 1144 try:
1200 1145 max_el2_value = float(max_el2)
1201 1146 except:
1202 1147 raise django.forms.ValidationError('Invalid maximum elevation 2: %(value)s cannot be converted to a float',
1203 1148 code='invalid',
1204 1149 params={'value': max_el2})
1205 1150 if max_el2_value < 0.0:
1206 1151 raise django.forms.ValidationError('Invalid maximum elevation 2: %(value)s cannot be less than 0 degrees',
1207 1152 code='invalid',
1208 1153 params={'value': max_el2})
1209 1154 if max_el2_value > 90.0:
1210 1155 raise django.forms.ValidationError('Invalid maximum elevation 2: %(value)s cannot be more than 90 degrees',
1211 1156 code='invalid',
1212 1157 params={'value': max_el2})
1213 1158 return(max_el2)
1214 1159
1215 1160
1216 1161 def clean_min_pl(self):
1217 1162 min_pl = self.cleaned_data['min_pl']
1218 1163 if len(min_pl) != 0:
1219 1164 try:
1220 1165 min_pl_value = float(min_pl)
1221 1166 except:
1222 1167 raise django.forms.ValidationError('Invalid lower limit for pulse length: %(value)s cannot be converted to a float',
1223 1168 code='invalid',
1224 1169 params={'value': min_pl})
1225 1170 return(min_pl)
1226 1171
1227 1172
1228 1173 def clean_max_pl(self):
1229 1174 max_pl = self.cleaned_data['max_pl']
1230 1175 if len(max_pl) != 0:
1231 1176 try:
1232 1177 max_pl_value = float(max_pl)
1233 1178 except:
1234 1179 raise django.forms.ValidationError('Invalid upper limit for pulse length: %(value)s cannot be converted to a float',
1235 1180 code='invalid',
1236 1181 params={'value': max_pl})
1237 1182 return(max_pl)
1238 1183
1239 1184
1240 1185 def clean_parm_1_lower(self):
1241 1186 parm_1_lower = self.cleaned_data['parm_1_lower']
1242 1187 if len(parm_1_lower) != 0:
1243 1188 try:
1244 1189 parm_1_lower_value = float(parm_1_lower)
1245 1190 except:
1246 1191 raise django.forms.ValidationError('Invalid lower limit for parm 1: %(value)s cannot be converted to a float',
1247 1192 code='invalid',
1248 1193 params={'value': parm_1_lower})
1249 1194 return(parm_1_lower)
1250 1195
1251 1196
1252 1197 def clean_parm_1_upper(self):
1253 1198 parm_1_upper = self.cleaned_data['parm_1_upper']
1254 1199 if len(parm_1_upper) != 0:
1255 1200 try:
1256 1201 parm_1_upper_value = float(parm_1_upper)
1257 1202 except:
1258 1203 raise django.forms.ValidationError('Invalid upper limit for parm 1: %(value)s cannot be converted to a float',
1259 1204 code='invalid',
1260 1205 params={'value': parm_1_upper})
1261 1206 return(parm_1_upper)
1262 1207
1263 1208
1264 1209 def clean_parm_2_lower(self):
1265 1210 parm_2_lower = self.cleaned_data['parm_2_lower']
1266 1211 if len(parm_2_lower) != 0:
1267 1212 try:
1268 1213 parm_2_lower_value = float(parm_2_lower)
1269 1214 except:
1270 1215 raise django.forms.ValidationError('Invalid lower limit for parm 2: %(value)s cannot be converted to a float',
1271 1216 code='invalid',
1272 1217 params={'value': parm_2_lower})
1273 1218 return(parm_2_lower)
1274 1219
1275 1220
1276 1221 def clean_parm_2_upper(self):
1277 1222 parm_2_upper = self.cleaned_data['parm_2_upper']
1278 1223 if len(parm_2_upper) != 0:
1279 1224 try:
1280 1225 parm_2_upper_value = float(parm_2_upper)
1281 1226 except:
1282 1227 raise django.forms.ValidationError('Invalid upper limit for parm 2: %(value)s cannot be converted to a float',
1283 1228 code='invalid',
1284 1229 params={'value': parm_2_upper})
1285 1230 return(parm_2_upper)
1286 1231
1287 1232
1288 1233 def clean_parm_3_lower(self):
1289 1234 parm_3_lower = self.cleaned_data['parm_3_lower']
1290 1235 if len(parm_3_lower) != 0:
1291 1236 try:
1292 1237 parm_3_lower_value = float(parm_3_lower)
1293 1238 except:
1294 1239 raise django.forms.ValidationError('Invalid lower limit for parm 3: %(value)s cannot be converted to a float',
1295 1240 code='invalid',
1296 1241 params={'value': parm_3_lower})
1297 1242 return(parm_3_lower)
1298 1243
1299 1244
1300 1245 def clean_parm_3_upper(self):
1301 1246 parm_3_upper = self.cleaned_data['parm_3_upper']
1302 1247 if len(parm_3_upper) != 0:
1303 1248 try:
1304 1249 parm_3_upper_value = float(parm_3_upper)
1305 1250 except:
1306 1251 raise django.forms.ValidationError('Invalid upper limit for parm 3: %(value)s cannot be converted to a float',
1307 1252 code='invalid',
1308 1253 params={'value': parm_3_upper})
1309 1254 return(parm_3_upper)
1310 1255
1311 1256
1312 1257
1313 1258
1314 1259 def clean(self):
1315 1260 """clean in the Django method to validate things in a form that require looking at multiple fields
1316 1261 """
1317 1262 # rule 1 - start_date < end_date
1318 1263 if self.cleaned_data['start_date'] > self.cleaned_data['end_date']:
1319 1264 raise django.forms.ValidationError('Error - start datetime greater than end datetime.')
1320 1265
1321 1266 # rule 2 - min_alt <= max_alt
1322 1267 try:
1323 1268 min_alt = float(self.cleaned_data['min_alt'])
1324 1269 max_alt = float(self.cleaned_data['max_alt'])
1325 1270 except:
1326 1271 min_alt = 0.0
1327 1272 max_alt = 1.0
1328 1273 if min_alt > max_alt:
1329 1274 raise django.forms.ValidationError('Error - Minimum altitude greater than maximum altitude.')
1330 1275
1331 1276 # rule 3 - min_az <= max_az
1332 1277 try:
1333 1278 min_az = float(self.cleaned_data['min_az'])
1334 1279 max_az = float(self.cleaned_data['max_az'])
1335 1280 except:
1336 1281 min_az = 0.0
1337 1282 max_az = 1.0
1338 1283 if min_az > max_az:
1339 1284 raise django.forms.ValidationError('Error - Minimum azimuth greater than maximum azimuth.')
1340 1285
1341 1286 # rule 4 - min_el <= max_el
1342 1287 try:
1343 1288 min_el = float(self.cleaned_data['min_el'])
1344 1289 max_el = float(self.cleaned_data['max_el'])
1345 1290 except:
1346 1291 min_el = 0.0
1347 1292 max_el = 1.0
1348 1293 if min_el > max_el:
1349 1294 raise django.forms.ValidationError('Error - Minimum elevation greater than maximum elevation.')
1350 1295
1351 1296 # rule 5 - min_az2 <= max_az2
1352 1297 try:
1353 1298 min_az2 = float(self.cleaned_data['min_az2'])
1354 1299 max_az2 = float(self.cleaned_data['max_az2'])
1355 1300 except:
1356 1301 min_az2 = 0.0
1357 1302 max_az2 = 1.0
1358 1303 if min_az2 > max_az2:
1359 1304 raise django.forms.ValidationError('Error - Minimum azimuth 2 greater than maximum azimuth 2.')
1360 1305
1361 1306 # rule 6 - min_el2 <= max_el2
1362 1307 try:
1363 1308 min_el2 = float(self.cleaned_data['min_el2'])
1364 1309 max_el2 = float(self.cleaned_data['max_el2'])
1365 1310 except:
1366 1311 min_el2 = 0.0
1367 1312 max_el2 = 1.0
1368 1313 if min_el2 > max_el2:
1369 1314 raise django.forms.ValidationError('Error - Minimum elevation 2 greater than maximum elevation 2.')
1370 1315
1371 1316 # rule 7 - min_pl <= max_pl
1372 1317 try:
1373 1318 min_pl = float(self.cleaned_data['min_pl'])
1374 1319 max_pl = float(self.cleaned_data['max_pl'])
1375 1320 except:
1376 1321 min_pl = 0.0
1377 1322 max_pl = 1.0
1378 1323 if min_pl > max_pl:
1379 1324 raise django.forms.ValidationError('Error - Minimum pulse length greater than maximum pulse length.')
1380 1325
1381 1326 # rule 8 - parm_1_lower <= parm_1_upper
1382 1327 try:
1383 1328 parm_1_lower = float(self.cleaned_data['parm_1_lower'])
1384 1329 parm_1_upper = float(self.cleaned_data['parm_1_upper'])
1385 1330 except:
1386 1331 parm_1_lower = 0.0
1387 1332 parm_1_upper = 1.0
1388 1333 if parm_1_lower > parm_1_upper:
1389 1334 raise django.forms.ValidationError('Error - parm 1 lower limit greater than upper limit.')
1390 1335
1391 1336 # rule 9 - parm_2_lower <= parm_2_upper
1392 1337 try:
1393 1338 parm_2_lower = float(self.cleaned_data['parm_2_lower'])
1394 1339 parm_2_upper = float(self.cleaned_data['parm_2_upper'])
1395 1340 except:
1396 1341 parm_2_lower = 0.0
1397 1342 parm_2_upper = 1.0
1398 1343 if parm_2_lower > parm_2_upper:
1399 1344 raise django.forms.ValidationError('Error - parm 2 lower limit greater than upper limit.')
1400 1345
1401 1346 # rule 10 - parm_3_lower <= parm_3_upper
1402 1347 try:
1403 1348 parm_3_lower = float(self.cleaned_data['parm_3_lower'])
1404 1349 parm_3_upper = float(self.cleaned_data['parm_3_upper'])
1405 1350 except:
1406 1351 parm_3_lower = 0.0
1407 1352 parm_3_upper = 1.0
1408 1353 if parm_3_lower > parm_3_upper:
1409 1354 raise django.forms.ValidationError('Error - parm 3 lower limit greater than upper limit.')
1410 1355
1411 1356
1412 1357 class ListExpForm(django.forms.Form):
1413 1358 """ListExpForm is a Form class for the default fields in the List Experiment interface
1414 1359 """
1415 1360 def __init__(self, *args, **kwargs):
1416 1361 super(ListExpForm, self).__init__(*args, **kwargs)
1417 1362 madDB = madrigal.metadata.MadrigalDB()
1418 1363 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
1419 1364 isGlobal = True # default load
1420 1365 now = datetime.datetime.now()
1421 1366 endDateTime = datetime.datetime(now.year, 12, 31, 23, 59, 59)
1422 1367 self.fields['isGlobal'] = django.forms.BooleanField(widget = django.forms.CheckboxInput(attrs={"onChange":'changeGlobal(this.form)'}),
1423 1368 required=False, label='Use all Madrigal sites: ',
1424 1369 initial=isGlobal)
1425 1370
1426 1371
1427 1372 categoriesSelection = '0'
1428 1373 self.fields['categories'] = django.forms.MultipleChoiceField(widget=django.forms.SelectMultiple(attrs={"onChange":"updateInstruments(this.form)"}),
1429 1374 choices=getCategoryList(args, kwargs, madInstData, True),
1430 1375 initial='0',
1431 1376 label='Choose instrument category(s):')
1432 1377
1433 1378 self.fields['instruments'] = django.forms.MultipleChoiceField(widget = django.forms.SelectMultiple(),
1434 1379 choices=getInstrumentList(args, kwargs, madInstData, 'All instruments', local=False, includeYears=True),
1435 1380 initial='0', label='Choose instrument(s)')
1436 1381
1437 1382 self.fields['showDefault'] = django.forms.BooleanField(widget = django.forms.CheckboxInput(),
1438 1383 label='Show only default files: ',
1439 1384 initial=True)
1440 1385
1441 1386 # time selection
1442 1387 self.fields['start_date'] = django.forms.SplitDateTimeField(input_date_formats=['%Y-%m-%d'], input_time_formats=['%H:%M:%S'],
1443 1388 label='Start date',
1444 1389 help_text='Modify this field to select experiments after this start time.',
1445 1390 initial=datetime.datetime(1950,1,1))
1446 1391
1447 1392 self.fields['end_date'] = django.forms.SplitDateTimeField(input_date_formats=['%Y-%m-%d'], input_time_formats=['%H:%M:%S'],
1448 1393 label='End date',
1449 1394 help_text='Modify this field to select experiments before this end time.',
1450 1395 initial=endDateTime)
1451 1396
1452 1397
1453 1398
1454 1399 # attributes to support javascript
1455 1400 local_categories = madInstData.getCategories(True)
1456 1401 global_categories = madInstData.getCategories(False)
1457 1402 local_category_ids = [cat[0] for cat in local_categories]
1458 1403 self.categories = [] # each item a tuple of (category description, category id, global only js bool)
1459 1404 self.instruments = [] # each item a tiple of (instrument desc, category id, kinst, local start year, local end year, global sy, global ey)
1460 1405 for id, desc in global_categories:
1461 1406 if id in local_category_ids:
1462 1407 localBool = 'false'
1463 1408 else:
1464 1409 localBool = 'true'
1465 1410 self.categories.append((desc, id, localBool))
1466 1411 for kinst, instDesc, siteId in madInstData.getInstruments(id):
1467 1412 if siteId == madDB.getSiteID():
1468 1413 localInst = True
1469 1414 else:
1470 1415 localInst = False
1471 1416 yearList = madInstData.getInstrumentYears(kinst)
1472 1417 if localInst:
1473 1418 self.instruments.append((instDesc, id, kinst, yearList[0], yearList[-1], yearList[0], yearList[-1]))
1474 1419 else:
1475 1420 self.instruments.append((instDesc, id, kinst, 0, 0, yearList[0], yearList[-1]))
1476 1421
1477 1422
1478 1423 def clean(self):
1479 1424 """clean in the Django method to validate things in a form that require looking at multiple fields
1480 1425 """
1481 1426 # rule 1 - start_date < end_date
1482 1427 if self.cleaned_data['start_date'] > self.cleaned_data['end_date']:
1483 1428 raise django.forms.ValidationError('Error - start datetime greater than end datetime.')
1484 1429
1485 1430
1486 1431 class DownloadAsIsScriptForm(django.forms.Form):
1487 1432 """DownloadAsIsScriptForm is a Form class for the default fields in the download files as is script generator interface
1488 1433 """
1489 1434 def __init__(self, *args, **kwargs):
1490 1435 super(DownloadAsIsScriptForm, self).__init__(*args, **kwargs)
1491 1436 madDB = madrigal.metadata.MadrigalDB()
1492 1437 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
1493 1438 madKindatObj = madrigal.metadata.MadrigalKindat(madDB)
1494 1439 madInstKindatObj = madrigal.metadata.MadrigalInstrumentKindats(madDB)
1495 1440 now = datetime.datetime.now()
1496 1441 endDateTime = datetime.datetime(now.year, 12, 31, 23, 59, 59)
1497 1442 kwargs['isGlobal'] = '0'
1498 1443 formatChoices = (('hdf5', 'Hdf5'), ('ascii', 'Space-delimited ascii'), ('netCDF4', 'netCDF4'))
1499 1444 languageChoices = (('python', 'python'), ('Matlab', 'Matlab'), ('IDL', 'IDL'))
1500 1445
1501 1446 categoriesSelection = '0'
1502 1447 self.fields['categories'] = django.forms.ChoiceField(widget=django.forms.Select(attrs={"onChange":"updateInstruments(this.form)"}),
1503 1448 choices=getCategoryList(args, kwargs, madInstData),
1504 1449 initial='0',
1505 1450 label='Choose an instrument category if desired:')
1506 1451
1507 1452 self.fields['instruments'] = django.forms.ChoiceField(widget=django.forms.Select(attrs={"onChange":"updateKindats(this.form)"}),
1508 1453 choices=getInstrumentList(args, kwargs, madInstData, local=True, includeYears=True),
1509 1454 initial='0', label='Choose one instrument')
1510 1455
1511 1456 # time selection
1512 1457 self.fields['start_date'] = django.forms.DateField(input_formats=['%Y-%m-%d'],
1513 1458 label='Start date',
1514 1459 help_text='Modify this field to select experiments after this start time.',
1515 1460 initial=datetime.datetime(1950,1,1))
1516 1461
1517 1462
1518 1463 self.fields['end_date'] = django.forms.DateField(input_formats=['%Y-%m-%d'],
1519 1464 label='End date',
1520 1465 help_text='Modify this field to select experiments before this end time.',
1521 1466 initial=endDateTime)
1522 1467
1523 1468 self.fields['format_select'] = django.forms.ChoiceField(widget = HorizontalRadioSelect(),
1524 1469 choices=formatChoices,
1525 1470 initial=formatChoices[0][0],
1526 1471 label='File format to download:')
1527 1472
1528 1473 self.fields['language_select'] = django.forms.ChoiceField(widget = HorizontalRadioSelect(),
1529 1474 choices=languageChoices,
1530 1475 initial=languageChoices[0][0],
1531 1476 label='Choose scripting language:')
1532 1477
1533 1478 choices=(('0', 'Select an instrument first to see list'),)
1534 1479 if len(args) > 0:
1535 1480 if 'kindat_select' in args[0]:
1536 1481 choices = [(kindat, kindat) for kindat in args[0].getlist('kindat_select')]
1537 1482 self.fields['kindat_select'] = django.forms.MultipleChoiceField(choices=choices,
1538 1483 initial='0',
1539 1484 label='Choose one or more kinds of data:',
1540 1485 required=False)
1541 1486 self.fields['kindat_select'].widget.attrs['style']="max-width:100%;"
1542 1487
1543 1488 self.fields['expName'] = django.forms.CharField(max_length=256, required=False)
1544 1489
1545 1490 self.fields['fileDesc'] = django.forms.CharField(max_length=256, required=False)
1546 1491
1547 1492
1548 1493
1549 1494 # attributes to support javascript
1550 1495 local_categories = madInstData.getCategories(True)
1551 1496 local_category_ids = [cat[0] for cat in local_categories]
1552 1497 self.categories = [] # each item a tuple of (category description, category id, global only js bool)
1553 1498 self.instruments = [] # each item a tiple of (instrument desc, category id, kinst, local start year, local end year)
1554 1499 self.kindats = [] # each item is a tuple of (kindat, kindatDesc, kinst)
1555 1500 for id, desc in local_categories:
1556 1501 self.categories.append((desc, id))
1557 1502 for kinst, instDesc, siteId in madInstData.getInstruments(id):
1558 1503 if siteId != madDB.getSiteID():
1559 1504 continue
1560 1505 yearList = madInstData.getInstrumentYears(kinst)
1561 1506 self.instruments.append((instDesc, id, kinst, yearList[0], yearList[-1]))
1562 1507 kindatList = madInstKindatObj.getKindatListForInstruments([kinst])
1563 1508 for kindat in kindatList:
1564 1509 self.kindats.append((kindat, madKindatObj.getKindatDescription(kindat, kinst),
1565 1510 kinst))
1566 1511
1567 1512
1568 1513 def clean(self):
1569 1514 """clean is the Django method to validate things in a form that require looking at multiple fields
1570 1515 """
1571 1516 # rule 1 - start_date < end_date
1572 1517 if self.cleaned_data['start_date'] > self.cleaned_data['end_date']:
1573 1518 raise django.forms.ValidationError('Error - start datetime greater than end datetime.')
1574 1519
1575 1520
1576 1521 class DownloadAdvancedScriptForm(django.forms.Form):
1577 1522 """DownloadAdvancedScriptForm is a Form class for the default fields in the download advanced script generator interface
1578 1523 """
1579 1524 def __init__(self, *args, **kwargs):
1580 1525 super(DownloadAdvancedScriptForm, self).__init__(*args, **kwargs)
1581 1526 madDB = madrigal.metadata.MadrigalDB()
1582 1527 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
1583 1528 madKindatObj = madrigal.metadata.MadrigalKindat(madDB)
1584 1529 madInstKindatObj = madrigal.metadata.MadrigalInstrumentKindats(madDB)
1585 1530 now = datetime.datetime.now()
1586 1531 endDateTime = datetime.datetime(now.year, 12, 31, 23, 59, 59)
1587 1532 kwargs['isGlobal'] = '0'
1588 1533 formatChoices = (('hdf5', 'Hdf5'), ('ascii', 'Space-delimited ascii'), ('netCDF4', 'netCDF4'))
1589 1534 directoryChoices = (('Directory', 'Directory'), ('File', 'File'))
1590 1535 languageChoices = (('python', 'python'), ('Matlab', 'Matlab'), ('IDL', 'IDL'))
1591 1536
1592 1537 categoriesSelection = '0'
1593 1538 self.fields['categories'] = django.forms.ChoiceField(widget=django.forms.Select(attrs={"onChange":"updateInstruments(this.form)"}),
1594 1539 choices=getCategoryList(args, kwargs, madInstData),
1595 1540 initial='0',
1596 1541 label='Choose an instrument category if desired:')
1597 1542
1598 1543 self.fields['instruments'] = django.forms.ChoiceField(widget=django.forms.Select(attrs={"onChange":"updateParmsKindats(this.form)"}),
1599 1544 choices=getInstrumentList(args, kwargs, madInstData, local=True, includeYears=True),
1600 1545 initial='0', label='Choose one instrument')
1601 1546
1602 1547 # time selection
1603 1548 self.fields['start_date'] = django.forms.DateField(input_formats=['%Y-%m-%d'],
1604 1549 label='Start date',
1605 1550 help_text='Modify this field to select experiments after this start time.',
1606 1551 initial=datetime.datetime(1950,1,1))
1607 1552
1608 1553 self.fields['end_date'] = django.forms.DateField(input_formats=['%Y-%m-%d'],
1609 1554 label='End date',
1610 1555 help_text='Modify this field to select experiments before this end time.',
1611 1556 initial=endDateTime)
1612 1557
1613 1558 self.fields['format_select'] = django.forms.ChoiceField(widget = HorizontalRadioSelect(attrs={"onChange":'changeFormat(this)'}),
1614 1559 choices=formatChoices,
1615 1560 initial=formatChoices[0][0],
1616 1561 label='File format to download:')
1617 1562
1618 1563 self.fields['directory_select'] = django.forms.ChoiceField(widget = HorizontalRadioSelect(),
1619 1564 choices=directoryChoices,
1620 1565 initial=directoryChoices[0][0],
1621 1566 label='If ascii, download result to:')
1622 1567
1623 1568 self.fields['language_select'] = django.forms.ChoiceField(widget = HorizontalRadioSelect(),
1624 1569 choices=languageChoices,
1625 1570 initial=languageChoices[0][0],
1626 1571 label='Choose scripting language:')
1627 1572
1628 1573 choices=(('0', 'Select an instrument first to see list'),)
1629 1574 if len(args) > 0:
1630 1575 if 'kindat_select' in args[0]:
1631 1576 choices = [(kindat, kindat) for kindat in args[0].getlist('kindat_select')]
1632 1577 self.fields['kindat_select'] = django.forms.MultipleChoiceField(choices=choices,
1633 1578 initial='0',
1634 1579 label='Choose one or more kinds of data:',
1635 1580 required=False)
1636 1581 self.fields['kindat_select'].widget.attrs['style']="max-width:100%;"
1637 1582
1638 1583 self.fields['expName'] = django.forms.CharField(max_length=256, required=False)
1639 1584
1640 1585 self.fields['fileDesc'] = django.forms.CharField(max_length=256, required=False)
1641 1586
1642 1587 self.fields['seasonalStartDay'] = django.forms.IntegerField(min_value=1, max_value=31, initial=1)
1643 1588 self.fields['seasonalStartMonth'] = django.forms.IntegerField(min_value=1, max_value=12, initial=1)
1644 1589 self.fields['seasonalEndDay'] = django.forms.IntegerField(min_value=1, max_value=31, initial=31)
1645 1590 self.fields['seasonalEndMonth'] = django.forms.IntegerField(min_value=1, max_value=12, initial=12)
1646 1591
1647 1592
1648 1593 # attributes to support javascript
1649 1594 local_categories = madInstData.getCategories(True)
1650 1595 local_category_ids = [cat[0] for cat in local_categories]
1651 1596 self.categories = [] # each item a tuple of (category description, category id, global only js bool)
1652 1597 self.instruments = [] # each item a tiple of (instrument desc, category id, kinst, local start year, local end year)
1653 1598 self.kindats = [] # each item is a tuple of (kindat, kindatDesc, kinst)
1654 1599 for id, desc in local_categories:
1655 1600 self.categories.append((desc, id))
1656 1601 for kinst, instDesc, siteId in madInstData.getInstruments(id):
1657 1602 if siteId != madDB.getSiteID():
1658 1603 continue
1659 1604 yearList = madInstData.getInstrumentYears(kinst)
1660 1605 self.instruments.append((instDesc, id, kinst, yearList[0], yearList[-1]))
1661 1606 kindatList = madInstKindatObj.getKindatListForInstruments([kinst])
1662 1607 for kindat in kindatList:
1663 1608 self.kindats.append((kindat, madKindatObj.getKindatDescription(kindat, kinst),
1664 1609 kinst))
1665 1610
1666 1611
1667 1612 def clean(self):
1668 1613 """clean is the Django method to validate things in a form that require looking at multiple fields
1669 1614 """
1670 1615 # rule 1 - start_date < end_date
1671 1616 if self.cleaned_data['start_date'] > self.cleaned_data['end_date']:
1672 1617 raise django.forms.ValidationError('Error - start datetime greater than end datetime.')
1673 1618
1674 1619 # rule 2 - seasonal start must be before seasonal end
1675 1620 if ((self.cleaned_data['seasonalStartDay'] + 31*self.cleaned_data['seasonalStartMonth']) > \
1676 1621 (self.cleaned_data['seasonalEndDay'] + 31*self.cleaned_data['seasonalEndMonth'])):
1677 1622 raise django.forms.ValidationError('Error - seasonal start after seasonal end.')
1678 1623
1679 1624
1680 1625
1681 1626 class AdvScriptParmsForm(django.forms.Form):
1682 1627 """AdvScriptParmsForm is the form for the parameters
1683 1628 """
1684 1629 def __init__(self, *args, **kwargs):
1685 1630
1686 1631 kinst = int(getSelection('instruments', args, kwargs))
1687 1632 if kinst == 0:
1688 1633 raise ValueError('kinst should never be zero')
1689 1634 madDB = madrigal.metadata.MadrigalDB()
1690 1635 madParmObj = madrigal.data.MadrigalParameters(madDB)
1691 1636 parmList = madParmObj.getParametersForInstruments([kinst])
1692 1637 self.parmList = []
1693 1638 for parm in parmList:
1694 1639 self.parmList.append((parm, madParmObj.getSimpleParmDescription(parm)))
1695 1640
1696 1641 madCatObj = madrigal.metadata.MadrigalParmCategory(madDB)
1697 1642
1698 1643 catList = madCatObj.getCategoryList()
1699 1644 catDict = madParmObj.getCategoryDict(parmList)
1700 1645
1701 1646 choices = []
1702 1647 isDerivedDict = {}
1703 1648 parmDescDict = {}
1704 1649 for catDesc, catID in catList:
1705 1650 if catID not in list(catDict.keys()):
1706 1651 continue
1707 1652 theseParms = []
1708 1653 for parm in catDict[catID][1]:
1709 1654 theseParms.append((parm, parm))
1710 1655 isDerivedDict[parm] = False
1711 1656 parmDescDict[parm] = madParmObj.getParmDescription(parm)
1712 1657 choices.append((catDesc, theseParms))
1713 1658
1714 1659 super(AdvScriptParmsForm, self).__init__(*args, **kwargs)
1715 1660
1716 1661 self.fields['parameters'] = IsprintChoiceField(choices=choices,
1717 1662 initial=['YEAR', 'MIN'],
1718 1663 required=False,
1719 1664 isDerivedDict=isDerivedDict,
1720 1665 parmDescDict=parmDescDict,
1721 1666 separateProlog=False,
1722 1667 label = "")
1723 1668
1724 1669
1725 1670 class AdvScriptParmsFiltersForm(django.forms.Form):
1726 1671 """AdvScriptParmsFiltersForm is the form for the parameter filters in the scrip generator
1727 1672 """
1728 1673 def __init__(self, *args, **kwargs):
1729 1674
1730 1675 kinst = int(getSelection('instruments', args, kwargs))
1731 1676 if kinst == 0:
1732 1677 raise ValueError('kinst should never be zero')
1733 1678 madDB = madrigal.metadata.MadrigalDB()
1734 1679 madParmObj = madrigal.data.MadrigalParameters(madDB)
1735 1680 parmList = madParmObj.getParametersForInstruments([kinst])
1736 1681 self.parmList = []
1737 1682 for parm in parmList:
1738 1683 self.parmList.append((parm, madParmObj.getSimpleParmDescription(parm)))
1739 1684
1740 1685 super(AdvScriptParmsFiltersForm, self).__init__(*args, **kwargs)
1741 1686
1742 1687 choices = [(parm, parm) for parm in parmList]
1743 1688 choices_with_null = [('None', 'None')] + choices
1744 1689
1745 1690 self.fields['parm_1'] = django.forms.ChoiceField(required=False,
1746 1691 choices=choices_with_null)
1747 1692 self.fields['parm_1_lower'] = django.forms.CharField(required=False, initial='')
1748 1693 self.fields['parm_1_upper'] = django.forms.CharField(required=False, initial='')
1749 1694
1750 1695 self.fields['parm_2'] = django.forms.ChoiceField(required=False,
1751 1696 choices=choices_with_null)
1752 1697 self.fields['parm_2_lower'] = django.forms.CharField(required=False, initial='')
1753 1698 self.fields['parm_2_upper'] = django.forms.CharField(required=False, initial='')
1754 1699
1755 1700 self.fields['parm_3'] = django.forms.ChoiceField(required=False,
1756 1701 choices=choices_with_null)
1757 1702 self.fields['parm_3_lower'] = django.forms.CharField(required=False, initial='')
1758 1703 self.fields['parm_3_upper'] = django.forms.CharField(required=False, initial='')
1759 1704
1760 1705
1761 1706
1762 1707 class MadCalculatorForm(django.forms.Form):
1763 1708 """MadCalculatorForm is the form for the madCalculator page
1764 1709 """
1765 1710 def __init__(self, *args, **kwargs):
1766 1711 """
1767 1712 """
1768 1713 madDB = madrigal.metadata.MadrigalDB()
1769 1714 madParmObj = madrigal.data.MadrigalParameters(madDB)
1770 1715 super(MadCalculatorForm, self).__init__(*args, **kwargs)
1771 1716 fullDerivedParmList = madrigal.derivation.getDerivableParms(['gdalt', 'gdlat', 'glon'])
1772 1717
1773 1718 # removed unwanted time and prolog parameters
1774 1719 rejectedCats = ('Time Related Parameter', 'Prolog Parameters', 'Radar Instrument Operation Parameter',
1775 1720 'Madrigal Hdf5 Prolog Parameters')
1776 1721 # define time parameters that do make sense to calculate
1777 1722 neededTimeParms = ('APLT', 'CONJ_SUNRISE_H', 'CONJ_SUNSET_H',
1778 1723 'SUNRISE_H', 'SUNSET_H', 'MLT')
1779 1724
1780 1725 # skip parms related to inst location
1781 1726 instLocationParms = ('AZM','ELM','GALTR','GDLONR','GDLATR','RANGE', 'ASPECT',
1782 1727 'GDALT', 'GDLAT', 'GLON', 'CXR', 'CYR', 'CZR')
1783 1728
1784 1729 madCatObj = madrigal.metadata.MadrigalParmCategory(madDB)
1785 1730
1786 1731 catList = madCatObj.getCategoryList()
1787 1732 catDict = madParmObj.getCategoryDict(fullDerivedParmList)
1788 1733 choices = []
1789 1734 isDerivedDict = {}
1790 1735 self.parmDescDict = {}
1791 1736 for catDesc, catID in catList:
1792 1737 if catDesc in rejectedCats[1:]:
1793 1738 continue
1794 1739 if catID not in list(catDict.keys()):
1795 1740 continue
1796 1741 theseParms = []
1797 1742 for parm in catDict[catID][1]:
1798 1743 if parm in instLocationParms:
1799 1744 continue
1800 1745 if catDesc in rejectedCats and parm not in neededTimeParms:
1801 1746 continue
1802 1747 if not parm in fullDerivedParmList:
1803 1748 continue
1804 1749 theseParms.append((parm, parm))
1805 1750 isDerivedDict[parm] = True
1806 1751 self.parmDescDict[parm] = madParmObj.getParmDescription(parm)
1807 1752 choices.append((catDesc, theseParms))
1808 1753
1809 1754
1810 1755
1811 1756 # form fields
1812 1757 self.fields['min_latitude'] = django.forms.FloatField(initial=-90.0, min_value=-90.0,
1813 1758 max_value=90.0)
1814 1759 self.fields['max_latitude'] = django.forms.FloatField(initial=90.0, min_value=-90.0,
1815 1760 max_value=90.0)
1816 1761 self.fields['delta_latitude'] = django.forms.FloatField(initial=45, min_value=1.0E-6)
1817 1762
1818 1763 self.fields['min_longitude'] = django.forms.FloatField(initial=-180.0, min_value=-180.0,
1819 1764 max_value=180.0)
1820 1765 self.fields['max_longitude'] = django.forms.FloatField(initial=180.0, min_value=-180.0,
1821 1766 max_value=180.0)
1822 1767 self.fields['delta_longitude'] = django.forms.FloatField(initial=90, min_value=1.0E-6)
1823 1768
1824 1769 self.fields['min_altitude'] = django.forms.FloatField(initial=0.0, min_value=0.0)
1825 1770 self.fields['max_altitude'] = django.forms.FloatField(initial=600.0, min_value=0.0)
1826 1771 self.fields['delta_altitude'] = django.forms.FloatField(initial=200, min_value=1.0E-6)
1827 1772
1828 1773 # time selection
1829 1774 now = datetime.datetime.utcnow()
1830 1775 self.fields['datetime'] = django.forms.SplitDateTimeField(input_date_formats=['%Y-%m-%d'], input_time_formats=['%H:%M:%S'],
1831 1776 label='Select UT datetime',
1832 1777 help_text='Select the UT time at which to run this calcuation',
1833 1778 initial=datetime.datetime(now.year,1,1))
1834 1779
1835 1780 self.fields['parameters'] = IsprintChoiceField(choices=choices,
1836 1781 required=False,
1837 1782 isDerivedDict=isDerivedDict,
1838 1783 parmDescDict=self.parmDescDict,
1839 1784 separateProlog=False,
1840 1785 label = "")
1841 1786
1842 1787
1843 1788 def clean(self):
1844 1789 """clean is the Django method to validate things in a form that require looking at multiple fields
1845 1790 """
1846 1791 max_len = 1.0E5
1847 1792 try:
1848 1793 a1 = numpy.arange(self.cleaned_data['min_latitude'], self.cleaned_data['max_latitude'], self.cleaned_data['delta_latitude'])
1849 1794 if len(a1) > max_len:
1850 1795 raise django.forms.ValidationError('Too many latitudes: %i.' % (len(a1)))
1851 1796 except ZeroDivisionError:
1852 1797 raise django.forms.ValidationError('Infinite latitudes')
1853 1798
1854 1799 try:
1855 1800 a2 = numpy.arange(self.cleaned_data['min_longitude'], self.cleaned_data['max_longitude'], self.cleaned_data['delta_longitude'])
1856 1801 if len(a1) > max_len:
1857 1802 raise django.forms.ValidationError('Too many longitudes: %i.' % (len(a1)))
1858 1803 except ZeroDivisionError:
1859 1804 raise django.forms.ValidationError('Infinite longitudes')
1860 1805
1861 1806 try:
1862 1807 a3 = numpy.arange(self.cleaned_data['min_altitude'], self.cleaned_data['max_altitude'], self.cleaned_data['delta_altitude'])
1863 1808 if len(a1) > max_len:
1864 1809 raise django.forms.ValidationError('Too many altitudes: %i.' % (len(a1)))
1865 1810 except ZeroDivisionError:
1866 1811 raise django.forms.ValidationError('Infinite altitudes')
1867 1812
1868 1813 total = len(a1) * len(a2) * len(a3)
1869 1814 if total > max_len:
1870 1815 raise django.forms.ValidationError('Too many calculations: %i' % (total))
1871 1816
1872 1817
1873 1818
1874 1819 class GetMetadataForm(django.forms.Form):
1875 1820 """GetMetadataForm is the form for the getMetadata page
1876 1821 """
1877 1822 def __init__(self, *args, **kwargs):
1878 1823 """
1879 1824 """
1880 1825 super(GetMetadataForm, self).__init__(*args, **kwargs)
1881 1826
1882 1827 fileTypeChoices = (("0", "Experiment Table"),
1883 1828 ("1", "File Table"),
1884 1829 ("3", "Instrument Table"),
1885 1830 ("4", "Parameter Table"),
1886 1831 ("5", "Site Table"),
1887 1832 ("6", "Type Table"),
1888 1833 ("7", "Instrument Kindat Table"),
1889 1834 ("8", "Instrument Parameter Table"),
1890 1835 ("9", "Madrigal categories table"),
1891 1836 ("10", "Instrument categories table"),)
1892 1837
1893 1838 self.fields['fileType'] = django.forms.ChoiceField(widget = django.forms.RadioSelect,
1894 1839 choices=fileTypeChoices,
1895 1840 initial="0",
1896 1841 label="Choose the metadata file type to download")
1897 1842
1898 1843
1899 1844 class LookerSelectForm(django.forms.Form):
1900 1845 """LookerSelectForm is the form for the looker_form page
1901 1846 """
1902 1847 def __init__(self, *args, **kwargs):
1903 1848 """
1904 1849 """
1905 1850 super(LookerSelectForm, self).__init__(*args, **kwargs)
1906 1851
1907 1852 lookerOptionChoices = (("1", "Geodetic latitude, longitude and altitude of the points"),
1908 1853 ("2", "Apex latitude, longitude and altitude of the points"),
1909 1854 ("3", "Geodetic latitude, longitude and altitude of the points"),
1910 1855 ("4", "Azimuth, elevation and range of the points from a specified instrument (output includes aspect angle)"),
1911 1856 ("5", "Azimuth, elevation, range from specified instrument"),
1912 1857 ("6", "Geodetic latitude, longitude, altitude of a point on the field line"),
1913 1858 ("7", "Apex latitude, longitude of the field line"),
1914 1859 ("8", "Geodetic latitude, longitude and altitude of the points"))
1915 1860
1916 1861 self.fields['looker_options'] = django.forms.ChoiceField(widget = django.forms.RadioSelect,
1917 1862 choices=lookerOptionChoices,
1918 1863 initial="1")
1919 1864
1920 1865
1921 1866 class LookerGeodeticRadar(django.forms.Form):
1922 1867 """LookerGeodeticRadar is the form for the geodetic to radar page
1923 1868 """
1924 1869 def __init__(self, *args, **kwargs):
1925 1870 """
1926 1871 """
1927 1872 super(LookerGeodeticRadar, self).__init__(*args, **kwargs)
1928 1873 madDB = madrigal.metadata.MadrigalDB()
1929 1874 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
1930 1875 dict1 = {'isGlobal': True, 'categories': "0"}
1931 1876
1932 1877 self.fields['looker_options'] = django.forms.CharField(initial="1",
1933 1878 widget=django.forms.HiddenInput(attrs={'value': "1"}))
1934 1879
1935 1880 self.fields['instruments'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={'size':'3'}),
1936 1881 choices=getInstrumentList([], dict1, madInstData, 'Set location manually', local=False),
1937 1882 required=False, label='Instrument: ')
1938 1883
1939 1884 self.fields['inst_lat'] = django.forms.FloatField(initial=0.0, min_value=-90.0, max_value=90.0,
1940 1885 widget=django.forms.TextInput(attrs={'size':5}))
1941 1886 self.fields['inst_lon'] = django.forms.FloatField(initial=0.0, min_value=-180.0, max_value=180.0,
1942 1887 widget=django.forms.TextInput(attrs={'size':5}))
1943 1888 self.fields['inst_alt'] = django.forms.FloatField(initial=0.0, min_value=0.0,
1944 1889 widget=django.forms.TextInput(attrs={'size':5}))
1945 1890 self.fields['start_lat'] = django.forms.FloatField(initial=30.0, min_value=-90.0, max_value=90.0,
1946 1891 widget=django.forms.TextInput(attrs={'size':5}))
1947 1892 self.fields['stop_lat'] = django.forms.FloatField(initial=50.0, min_value=-90.0, max_value=90.0,
1948 1893 widget=django.forms.TextInput(attrs={'size':5}))
1949 1894 self.fields['step_lat'] = django.forms.FloatField(initial=10.0, min_value=0.0,
1950 1895 widget=django.forms.TextInput(attrs={'size':5}))
1951 1896 self.fields['start_lon'] = django.forms.FloatField(initial=-100.0, min_value=-180.0, max_value=180.0,
1952 1897 widget=django.forms.TextInput(attrs={'size':5}))
1953 1898 self.fields['stop_lon'] = django.forms.FloatField(initial=-80.0, min_value=-180.0, max_value=180.0,
1954 1899 widget=django.forms.TextInput(attrs={'size':5}))
1955 1900 self.fields['step_lon'] = django.forms.FloatField(initial=10.0, min_value=0.0,
1956 1901 widget=django.forms.TextInput(attrs={'size':5}))
1957 1902 self.fields['start_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0,
1958 1903 widget=django.forms.TextInput(attrs={'size':5}))
1959 1904 self.fields['stop_alt'] = django.forms.FloatField(initial=500.0, min_value=0.0,
1960 1905 widget=django.forms.TextInput(attrs={'size':5}))
1961 1906 self.fields['step_alt'] = django.forms.FloatField(initial=500.0, min_value=0.0,
1962 1907 widget=django.forms.TextInput(attrs={'size':5}))
1963 1908
1964 1909
1965 1910 class LookerGeomagRadar(django.forms.Form):
1966 1911 """LookerGeomagRadar is the form for the geomagnetic to radar page
1967 1912 """
1968 1913 def __init__(self, *args, **kwargs):
1969 1914 """
1970 1915 """
1971 1916 super(LookerGeomagRadar, self).__init__(*args, **kwargs)
1972 1917 madDB = madrigal.metadata.MadrigalDB()
1973 1918 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
1974 1919 dict1 = {'isGlobal': True, 'categories': "0"}
1975 1920
1976 1921 self.fields['looker_options'] = django.forms.CharField(initial="2",
1977 1922 widget=django.forms.HiddenInput(attrs={'value': "2"}))
1978 1923
1979 1924 self.fields['instruments'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={'size':'3'}),
1980 1925 choices=getInstrumentList([], dict1, madInstData, 'Set location manually', local=False),
1981 1926 required=False, label='Instrument: ')
1982 1927
1983 1928 self.fields['inst_lat'] = django.forms.FloatField(initial=0.0, min_value=-90.0, max_value=90.0,
1984 1929 widget=django.forms.TextInput(attrs={'size':5}))
1985 1930 self.fields['inst_lon'] = django.forms.FloatField(initial=0.0, min_value=-180.0, max_value=180.0,
1986 1931 widget=django.forms.TextInput(attrs={'size':5}))
1987 1932 self.fields['inst_alt'] = django.forms.FloatField(initial=0.0, min_value=0.0,
1988 1933 widget=django.forms.TextInput(attrs={'size':5}))
1989 1934 self.fields['start_lat'] = django.forms.FloatField(initial=30.0, min_value=-90.0, max_value=90.0,
1990 1935 widget=django.forms.TextInput(attrs={'size':5}))
1991 1936 self.fields['stop_lat'] = django.forms.FloatField(initial=50.0, min_value=-90.0, max_value=90.0,
1992 1937 widget=django.forms.TextInput(attrs={'size':5}))
1993 1938 self.fields['step_lat'] = django.forms.FloatField(initial=10.0, min_value=0.0,
1994 1939 widget=django.forms.TextInput(attrs={'size':5}))
1995 1940 self.fields['start_lon'] = django.forms.FloatField(initial=-100.0, min_value=-180.0, max_value=180.0,
1996 1941 widget=django.forms.TextInput(attrs={'size':5}))
1997 1942 self.fields['stop_lon'] = django.forms.FloatField(initial=-80.0, min_value=-180.0, max_value=180.0,
1998 1943 widget=django.forms.TextInput(attrs={'size':5}))
1999 1944 self.fields['step_lon'] = django.forms.FloatField(initial=10.0, min_value=0.0,
2000 1945 widget=django.forms.TextInput(attrs={'size':5}))
2001 1946 self.fields['start_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0,
2002 1947 widget=django.forms.TextInput(attrs={'size':5}))
2003 1948 self.fields['stop_alt'] = django.forms.FloatField(initial=500.0, min_value=0.0,
2004 1949 widget=django.forms.TextInput(attrs={'size':5}))
2005 1950 self.fields['step_alt'] = django.forms.FloatField(initial=500.0, min_value=0.0,
2006 1951 widget=django.forms.TextInput(attrs={'size':5}))
2007 1952 now = datetime.datetime.utcnow()
2008 1953 self.fields['year'] = django.forms.FloatField(initial=float(now.year), min_value=1950.0,
2009 1954 widget=django.forms.TextInput(attrs={'size':5}))
2010 1955
2011 1956 class LookerGeomagFromGeodetic(django.forms.Form):
2012 1957 """LookerGeomagFromGeodetic is the form for the geomagnetic from geodetic page
2013 1958 """
2014 1959 def __init__(self, *args, **kwargs):
2015 1960 """
2016 1961 """
2017 1962 super(LookerGeomagFromGeodetic, self).__init__(*args, **kwargs)
2018 1963
2019 1964 self.fields['looker_options'] = django.forms.CharField(initial="3",
2020 1965 widget=django.forms.HiddenInput(attrs={'value': "3"}))
2021 1966
2022 1967 self.fields['start_lat'] = django.forms.FloatField(initial=30.0, min_value=-90.0, max_value=90.0,
2023 1968 widget=django.forms.TextInput(attrs={'size':5}))
2024 1969 self.fields['stop_lat'] = django.forms.FloatField(initial=50.0, min_value=-90.0, max_value=90.0,
2025 1970 widget=django.forms.TextInput(attrs={'size':5}))
2026 1971 self.fields['step_lat'] = django.forms.FloatField(initial=10.0, min_value=0.0,
2027 1972 widget=django.forms.TextInput(attrs={'size':5}))
2028 1973 self.fields['start_lon'] = django.forms.FloatField(initial=-100.0, min_value=-180.0, max_value=180.0,
2029 1974 widget=django.forms.TextInput(attrs={'size':5}))
2030 1975 self.fields['stop_lon'] = django.forms.FloatField(initial=-80.0, min_value=-180.0, max_value=180.0,
2031 1976 widget=django.forms.TextInput(attrs={'size':5}))
2032 1977 self.fields['step_lon'] = django.forms.FloatField(initial=10.0, min_value=0.0,
2033 1978 widget=django.forms.TextInput(attrs={'size':5}))
2034 1979 self.fields['start_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0,
2035 1980 widget=django.forms.TextInput(attrs={'size':5}))
2036 1981 self.fields['stop_alt'] = django.forms.FloatField(initial=500.0, min_value=0.0,
2037 1982 widget=django.forms.TextInput(attrs={'size':5}))
2038 1983 self.fields['step_alt'] = django.forms.FloatField(initial=500.0, min_value=0.0,
2039 1984 widget=django.forms.TextInput(attrs={'size':5}))
2040 1985 now = datetime.datetime.utcnow()
2041 1986 self.fields['year'] = django.forms.FloatField(initial=float(now.year), min_value=1950.0,
2042 1987 widget=django.forms.TextInput(attrs={'size':5}))
2043 1988
2044 1989 class LookerGeomagFromRadar(django.forms.Form):
2045 1990 """LookerGeomagFromRadar is the form for the geomagnetic from radar page
2046 1991 """
2047 1992 def __init__(self, *args, **kwargs):
2048 1993 """
2049 1994 """
2050 1995 super(LookerGeomagFromRadar, self).__init__(*args, **kwargs)
2051 1996 madDB = madrigal.metadata.MadrigalDB()
2052 1997 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
2053 1998 dict1 = {'isGlobal': True, 'categories': "0"}
2054 1999
2055 2000 self.fields['looker_options'] = django.forms.CharField(initial="4",
2056 2001 widget=django.forms.HiddenInput(attrs={'value': "4"}))
2057 2002
2058 2003 self.fields['instruments'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={'size':'3'}),
2059 2004 choices=getInstrumentList([], dict1, madInstData, local=False)[1:],
2060 2005 required=False, label='Instrument: ')
2061 2006
2062 2007 self.fields['inst_lat'] = django.forms.FloatField(initial=0.0, min_value=-90.0, max_value=90.0,
2063 2008 widget=django.forms.TextInput(attrs={'size':5}))
2064 2009 self.fields['inst_lon'] = django.forms.FloatField(initial=0.0, min_value=-180.0, max_value=180.0,
2065 2010 widget=django.forms.TextInput(attrs={'size':5}))
2066 2011 self.fields['inst_alt'] = django.forms.FloatField(initial=0.0, min_value=0.0,
2067 2012 widget=django.forms.TextInput(attrs={'size':5}))
2068 2013 self.fields['start_az'] = django.forms.FloatField(initial=-180.0, min_value=-180.0, max_value=180.0,
2069 2014 widget=django.forms.TextInput(attrs={'size':5}))
2070 2015 self.fields['stop_az'] = django.forms.FloatField(initial=180.0, min_value=-180.0, max_value=180.0,
2071 2016 widget=django.forms.TextInput(attrs={'size':5}))
2072 2017 self.fields['step_az'] = django.forms.FloatField(initial=45.0, min_value=0.0,
2073 2018 widget=django.forms.TextInput(attrs={'size':5}))
2074 2019 self.fields['start_el'] = django.forms.FloatField(initial=0.0, min_value=0.0, max_value=90.0,
2075 2020 widget=django.forms.TextInput(attrs={'size':5}))
2076 2021 self.fields['stop_el'] = django.forms.FloatField(initial=90.0, min_value=0.0, max_value=90.0,
2077 2022 widget=django.forms.TextInput(attrs={'size':5}))
2078 2023 self.fields['step_el'] = django.forms.FloatField(initial=30.0, min_value=0.0,
2079 2024 widget=django.forms.TextInput(attrs={'size':5}))
2080 2025 self.fields['start_range'] = django.forms.FloatField(initial=0.0, min_value=0.0,
2081 2026 widget=django.forms.TextInput(attrs={'size':5}))
2082 2027 self.fields['stop_range'] = django.forms.FloatField(initial=600.0, min_value=0.0,
2083 2028 widget=django.forms.TextInput(attrs={'size':5}))
2084 2029 self.fields['step_range'] = django.forms.FloatField(initial=200.0, min_value=0.0,
2085 2030 widget=django.forms.TextInput(attrs={'size':5}))
2086 2031 now = datetime.datetime.utcnow()
2087 2032 self.fields['year'] = django.forms.FloatField(initial=float(now.year), min_value=1950.0,
2088 2033 widget=django.forms.TextInput(attrs={'size':5}))
2089 2034
2090 2035
2091 2036 class LookerFieldLineFromRadar(django.forms.Form):
2092 2037 """LookerFieldLineFromRadar is the form for the field line from radar page
2093 2038 """
2094 2039 def __init__(self, *args, **kwargs):
2095 2040 """
2096 2041 """
2097 2042 super(LookerFieldLineFromRadar, self).__init__(*args, **kwargs)
2098 2043 madDB = madrigal.metadata.MadrigalDB()
2099 2044 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
2100 2045 dict1 = {'isGlobal': True, 'categories': "0"}
2101 2046
2102 2047 self.fields['looker_options'] = django.forms.CharField(initial="5",
2103 2048 widget=django.forms.HiddenInput(attrs={'value': "5"}))
2104 2049
2105 2050 self.fields['instruments'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={'size':'3'}),
2106 2051 choices=getInstrumentList([], dict1, madInstData, 'Set location manually', local=False),
2107 2052 required=False, label='Instrument: ')
2108 2053
2109 2054 self.fields['inst_lat'] = django.forms.FloatField(initial=0.0, min_value=-90.0, max_value=90.0,
2110 2055 widget=django.forms.TextInput(attrs={'size':5}))
2111 2056 self.fields['inst_lon'] = django.forms.FloatField(initial=0.0, min_value=-180.0, max_value=180.0,
2112 2057 widget=django.forms.TextInput(attrs={'size':5}))
2113 2058 self.fields['inst_alt'] = django.forms.FloatField(initial=0.0, min_value=0.0,
2114 2059 widget=django.forms.TextInput(attrs={'size':5}))
2115 2060 self.fields['fl_az'] = django.forms.FloatField(initial=0.0, min_value=-180.0, max_value=180.0,
2116 2061 widget=django.forms.TextInput(attrs={'size':5}))
2117 2062 self.fields['fl_el'] = django.forms.FloatField(initial=45.0, min_value=0.0, max_value=90.0,
2118 2063 widget=django.forms.TextInput(attrs={'size':5}))
2119 2064 self.fields['fl_range'] = django.forms.FloatField(initial=1000.0, min_value=0.0,
2120 2065 widget=django.forms.TextInput(attrs={'size':5}))
2121 2066
2122 2067 self.fields['start_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0,
2123 2068 widget=django.forms.TextInput(attrs={'size':5}))
2124 2069 self.fields['stop_alt'] = django.forms.FloatField(initial=1000.0, min_value=0.0,
2125 2070 widget=django.forms.TextInput(attrs={'size':5}))
2126 2071 self.fields['step_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0,
2127 2072 widget=django.forms.TextInput(attrs={'size':5}))
2128 2073 now = datetime.datetime.utcnow()
2129 2074 self.fields['year'] = django.forms.FloatField(initial=float(now.year), min_value=1950.0,
2130 2075 widget=django.forms.TextInput(attrs={'size':5}))
2131 2076
2132 2077
2133 2078
2134 2079 class LookerFieldLineFromGeodetic(django.forms.Form):
2135 2080 """LookerFieldLineFromGeodetic is the form for the field line from geodetic page
2136 2081 """
2137 2082 def __init__(self, *args, **kwargs):
2138 2083 """
2139 2084 """
2140 2085 super(LookerFieldLineFromGeodetic, self).__init__(*args, **kwargs)
2141 2086 madDB = madrigal.metadata.MadrigalDB()
2142 2087 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
2143 2088 dict1 = {'isGlobal': True, 'categories': "0"}
2144 2089
2145 2090 self.fields['looker_options'] = django.forms.CharField(initial="6",
2146 2091 widget=django.forms.HiddenInput(attrs={'value': "6"}))
2147 2092
2148 2093 self.fields['instruments'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={'size':'3'}),
2149 2094 choices=getInstrumentList([], dict1, madInstData, 'Set location manually', local=False),
2150 2095 required=False, label='Instrument: ')
2151 2096
2152 2097 self.fields['inst_lat'] = django.forms.FloatField(initial=0.0, min_value=-90.0, max_value=90.0,
2153 2098 widget=django.forms.TextInput(attrs={'size':5}))
2154 2099 self.fields['inst_lon'] = django.forms.FloatField(initial=0.0, min_value=-180.0, max_value=180.0,
2155 2100 widget=django.forms.TextInput(attrs={'size':5}))
2156 2101 self.fields['inst_alt'] = django.forms.FloatField(initial=0.0, min_value=0.0,
2157 2102 widget=django.forms.TextInput(attrs={'size':5}))
2158 2103 self.fields['fl_lat'] = django.forms.FloatField(initial=45.0, min_value=-90.0, max_value=90.0,
2159 2104 widget=django.forms.TextInput(attrs={'size':5}))
2160 2105 self.fields['fl_lon'] = django.forms.FloatField(initial=-90.0, min_value=-180.0, max_value=180.0,
2161 2106 widget=django.forms.TextInput(attrs={'size':5}))
2162 2107 self.fields['fl_alt'] = django.forms.FloatField(initial=0.0, min_value=0.0,
2163 2108 widget=django.forms.TextInput(attrs={'size':5}))
2164 2109
2165 2110 self.fields['start_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0,
2166 2111 widget=django.forms.TextInput(attrs={'size':5}))
2167 2112 self.fields['stop_alt'] = django.forms.FloatField(initial=1000.0, min_value=0.0,
2168 2113 widget=django.forms.TextInput(attrs={'size':5}))
2169 2114 self.fields['step_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0,
2170 2115 widget=django.forms.TextInput(attrs={'size':5}))
2171 2116 now = datetime.datetime.utcnow()
2172 2117 self.fields['year'] = django.forms.FloatField(initial=float(now.year), min_value=1950.0,
2173 2118 widget=django.forms.TextInput(attrs={'size':5}))
2174 2119
2175 2120
2176 2121 class LookerFieldLineFromApex(django.forms.Form):
2177 2122 """LookerFieldLineFromApex is the form for the field line from apex coordinates page
2178 2123 """
2179 2124 def __init__(self, *args, **kwargs):
2180 2125 """
2181 2126 """
2182 2127 super(LookerFieldLineFromApex, self).__init__(*args, **kwargs)
2183 2128 madDB = madrigal.metadata.MadrigalDB()
2184 2129 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
2185 2130 dict1 = {'isGlobal': True, 'categories': "0"}
2186 2131
2187 2132 self.fields['looker_options'] = django.forms.CharField(initial="7",
2188 2133 widget=django.forms.HiddenInput(attrs={'value': "7"}))
2189 2134
2190 2135 self.fields['instruments'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={'size':'3'}),
2191 2136 choices=getInstrumentList([], dict1, madInstData, 'Set location manually', local=False),
2192 2137 required=False, label='Instrument: ')
2193 2138
2194 2139 self.fields['inst_lat'] = django.forms.FloatField(initial=0.0, min_value=-90.0, max_value=90.0,
2195 2140 widget=django.forms.TextInput(attrs={'size':5}))
2196 2141 self.fields['inst_lon'] = django.forms.FloatField(initial=0.0, min_value=-180.0, max_value=180.0,
2197 2142 widget=django.forms.TextInput(attrs={'size':5}))
2198 2143 self.fields['inst_alt'] = django.forms.FloatField(initial=0.0, min_value=0.0,
2199 2144 widget=django.forms.TextInput(attrs={'size':5}))
2200 2145 self.fields['fl_apex_lat'] = django.forms.FloatField(initial=65.0, min_value=-00.0, max_value=90.0,
2201 2146 widget=django.forms.TextInput(attrs={'size':5}))
2202 2147 self.fields['fl_apex_lon'] = django.forms.FloatField(initial=-90.0, min_value=-180.0, max_value=180.0,
2203 2148 widget=django.forms.TextInput(attrs={'size':5}))
2204 2149
2205 2150 self.fields['start_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0,
2206 2151 widget=django.forms.TextInput(attrs={'size':5}))
2207 2152 self.fields['stop_alt'] = django.forms.FloatField(initial=1000.0, min_value=0.0,
2208 2153 widget=django.forms.TextInput(attrs={'size':5}))
2209 2154 self.fields['step_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0,
2210 2155 widget=django.forms.TextInput(attrs={'size':5}))
2211 2156 now = datetime.datetime.utcnow()
2212 2157 self.fields['year'] = django.forms.FloatField(initial=float(now.year), min_value=1950.0,
2213 2158 widget=django.forms.TextInput(attrs={'size':5}))
2214 2159
2215 2160
2216 2161 class LookerConjugateFromGeodetic(django.forms.Form):
2217 2162 """LookerConjugateFromGeodetic is the form for the geomagnetic/conjugate from geodetic page
2218 2163 """
2219 2164 def __init__(self, *args, **kwargs):
2220 2165 """
2221 2166 """
2222 2167 super(LookerConjugateFromGeodetic, self).__init__(*args, **kwargs)
2223 2168
2224 2169 parmChoices = [("MAGCONJLAT", 'Magnetic conjugate latitude'),
2225 2170 ("MAGCONJLON", 'Magnetic conjugate longitude'),
2226 2171 ("SZEN", 'Solar zenith angle'),
2227 2172 ("SZENC", 'Magnetic conjugate solar zenith angle'),
2228 2173 ("SDWHT", 'Shadow height (km)'),
2229 2174 ("MAGCONJSDWHT", 'Magnetic conjugate shadow height (km)')]
2230 2175 parmInitial = [key for key, value in parmChoices]
2231 2176
2232 2177 self.fields['looker_options'] = django.forms.CharField(initial="8",
2233 2178 widget=django.forms.HiddenInput(attrs={'value': "8"}))
2234 2179
2235 2180 self.fields['start_lat'] = django.forms.FloatField(initial=30.0, min_value=-90.0, max_value=90.0,
2236 2181 widget=django.forms.TextInput(attrs={'size':5}))
2237 2182 self.fields['stop_lat'] = django.forms.FloatField(initial=50.0, min_value=-90.0, max_value=90.0,
2238 2183 widget=django.forms.TextInput(attrs={'size':5}))
2239 2184 self.fields['step_lat'] = django.forms.FloatField(initial=10.0, min_value=0.0,
2240 2185 widget=django.forms.TextInput(attrs={'size':5}))
2241 2186 self.fields['start_lon'] = django.forms.FloatField(initial=-100.0, min_value=-180.0, max_value=180.0,
2242 2187 widget=django.forms.TextInput(attrs={'size':5}))
2243 2188 self.fields['stop_lon'] = django.forms.FloatField(initial=-80.0, min_value=-180.0, max_value=180.0,
2244 2189 widget=django.forms.TextInput(attrs={'size':5}))
2245 2190 self.fields['step_lon'] = django.forms.FloatField(initial=10.0, min_value=0.0,
2246 2191 widget=django.forms.TextInput(attrs={'size':5}))
2247 2192 self.fields['start_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0,
2248 2193 widget=django.forms.TextInput(attrs={'size':5}))
2249 2194 self.fields['stop_alt'] = django.forms.FloatField(initial=500.0, min_value=0.0,
2250 2195 widget=django.forms.TextInput(attrs={'size':5}))
2251 2196 self.fields['step_alt'] = django.forms.FloatField(initial=500.0, min_value=0.0,
2252 2197 widget=django.forms.TextInput(attrs={'size':5}))
2253 2198
2254 2199 # time selection
2255 2200 now = datetime.datetime.utcnow()
2256 2201 self.fields['datetime'] = django.forms.SplitDateTimeField(input_date_formats=['%Y-%m-%d'], input_time_formats=['%H:%M:%S'],
2257 2202 label='Select UT datetime',
2258 2203 help_text='Select the UT time at which to run this calcuation',
2259 2204 initial=datetime.datetime(now.year,1,1))
2260 2205
2261 2206 self.fields['pList'] = django.forms.MultipleChoiceField(widget=django.forms.CheckboxSelectMultiple(),
2262 2207 choices=parmChoices, initial=parmInitial)
2263 2208
@@ -1,67 +1,68
1 1 {% extends "base.html" %}
2 2
3 3 {% comment %}
4 4 Written by Bill Rideout brideout@haystack.mit.edu
5 5
6 6 Base template for Madrigal show experiment web interface
7 7
8 8 $Id: show_experiment.html 7310 2021-03-02 14:31:06Z brideout $
9 9 {% endcomment %}
10 10
11 11 {% block title %}Show Madrigal experiment{% endblock %}
12 12
13 13 {% block extra_head %}
14 <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
14 15 <script>
15 16
16 17 function changeFile (select) {
17 18 var basename = select.options[select.selectedIndex].value;
18 19 {% if form.exp_id %}
19 20 var url = '{% url 'change_files' %}' + '?experiment_list={{ form.exp_id.label }}&file_list=' + basename;
20 21 {% else %}
21 22 var exp_id = $("#id_experiment_list")[0].options[$("#id_experiment_list")[0].selectedIndex].value;
22 23 var url = '{% url 'change_files' %}' + '?experiment_list=' + exp_id + '&file_list=' + basename;
23 24 {% endif %}
24 25 // first delete all forms that are now out of date
25 26 divIndex = $(".single_form").index($( "#file_buttons" ))
26 27 $(".single_form").slice(divIndex).empty()
27 28 // second populate the file_list html if '0' not selected
28 29 if (basename != '0') {
29 30 $(".single_form").slice(divIndex,divIndex+1).load(url);
30 31 }
31 32 }
32 33
33 34 {% include "madweb/fileDownload.js" %}
34 35
35 36 </script>
36 37 {% endblock %}
37 38
38 39 {% block content %}
39 40 <center><h4> {{ form.exp_desc.label }} </h4></center>
40 41
41 42 {% include "madweb/file_list.html" %}
42 43
43 44 <!-- file select div -->
44 45 <div class="col-md-12 single_form" id="file_buttons">
45 46 {% if form.file_buttons %}
46 47 {% include "madweb/file_buttons.html" %}
47 48 {% endif %}
48 49 </div> <!-- end subdivide -->
49 50 <div>&nbsp;</div>
50 51
51 52 <!-- file select div -->
52 53 <div class="col-md-12 single_form" id="file_data">
53 54 {% if form.show_plots %}
54 55 {% include "madweb/show_plots.html" %}
55 56 {% elif form.plot_list %}
56 57 {% include "madweb/show_plots.html" %}
57 58 {% endif %}
58 59 </div> <!-- end subdivide -->
59 60
60 61 <!-- file select div -->
61 62 <div class="col-md-12 single_form" id="file_plot">
62 63 {% if form.show_plots %}
63 64 {% include "madweb/parameter_selection.html" %}
64 65 {% endif %}
65 66 </div> <!-- end subdivide -->
66 67
67 68 {% endblock %} No newline at end of file
@@ -1,3535 +1,3518
1 1 '''
2 2
3 3 @author: Bill Rideout
4 4 @contact: brideout@haystack.mit.edu
5 5
6 6 $Id: views.py 7345 2021-03-30 18:30:32Z brideout $
7 7 '''
8 8 # standard python imports
9 9 import os.path
10 10 import urllib
11 11 import os, sys
12 12 import json
13 13 import datetime, time
14 14 import glob
15 15 import re
16 16 import subprocess
17 17 import io
18 18 import collections
19 19 import shutil
20 20 import mimetypes
21 21 import tempfile
22 22 import random
23 23
24 24 # django imports
25 25 from django.shortcuts import render, redirect
26 26 from django.views.decorators.csrf import csrf_exempt
27 27 from django.template.context import RequestContext
28 28 #from django.conf import settings
29 29 try:
30 30 from django.urls import reverse
31 31 except ImportError:
32 32 from django.core.urlresolvers import reverse
33 33 from django.http import HttpResponse, HttpResponseRedirect, StreamingHttpResponse
34 34 import django.utils.http
35 35 import django.core.files
36 36 import django.utils.safestring
37 37 from wsgiref.util import FileWrapper
38 38
39 39 # third party imports
40 40 import numpy
41 41 import plotly.offline as py
42 42 import plotly.graph_objs as go
43 43 import h5py
44 44
45 45
46 46 # madrigal imports
47 47 import madrigal._derive
48 48 import madrigal.metadata
49 49 import madrigal.ui.web
50 50 import madrigal.cedar
51 51 import madrigal.isprint
52 52 import madweb.forms
53 53
54 54
55 55 # temp only
56 56 import logging
57 57
58 58
59 59 # constants
60 60 formatDict = collections.OrderedDict()
61 61 formatDict['hdf5'] = 'Hdf5'
62 62 formatDict['netCDF4'] = 'netCDF4'
63 63 formatDict['ascii'] = 'Column-delimited ascii'
64 64 maxSize = 50000000 # 50 MB cutoff
65 65
66 66
67 67
68 68
69 69 def index(request):
70 70 """index is the home page view
71 71 """
72 72 madDB = madrigal.metadata.MadrigalDB()
73 73 bg_color = madDB.getBackgroundColor()
74 74 welcome = madDB.getIndexHead()
75 75 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
76 76 siteName, siteList = madWebObj.getSiteInfo()
77 77 rulesRoadHtml = madDB.getLocalRulesOfRoad()
78 78 template_dict = {'home_active': 'class="active"', 'site_name': siteName, 'site_list': siteList,
79 79 'rulesOfRoad':django.utils.safestring.mark_safe(rulesRoadHtml),
80 80 'bg_color': bg_color, 'welcome': welcome}
81 81 return render(request, 'madweb/index.html', template_dict)
82 82
83 83 @csrf_exempt
84 84 def check_registration(view):
85 85 def check_cookies(request, *args, **kwargs):
86 86 # this view checks if all the needed cookies are set
87 87 cookieDict = request.COOKIES
88 88 try:
89 89 cookieDict['user_fullname']
90 90 cookieDict['user_email']
91 91 cookieDict['user_affiliation']
92 92 # no need to register
93 93 return(view(request, *args, **kwargs))
94 94 except KeyError:
95 95 return(HttpResponseRedirect(reverse('view_registration') + '?redirect=%s' % (request.get_full_path())))
96 96
97 97 return(check_cookies)
98 98
99 99
100 100 def view_registration(request):
101 101 madDB = madrigal.metadata.MadrigalDB()
102 102 madWeb = madrigal.ui.web.MadrigalWeb(madDB)
103 103 siteName, siteList = madWeb.getSiteInfo()
104 104 redirect = 'index' # default is to redirect to home page
105 105 if request.method == 'GET':
106 106 if 'redirect' in request.GET:
107 107 redirect = request.GET['redirect']
108 108 for key in request.GET:
109 109 if key not in ('redirect', 'user_fullname', 'user_email', 'user_affiliation'):
110 110 redirect += '&%s=%s' % (key, request.GET[key])
111 111 if len(list(request.GET.keys())) > 0 and 'user_fullname' in request.GET:
112 112 form = madweb.forms.RegisterForm(request.GET)
113 113 if form.is_valid():
114 114 # write cookies and continue to main page
115 115 max_age = 3600*24*365 # one year
116 116 if redirect == 'index':
117 117 response = HttpResponseRedirect(reverse('index'))
118 118 else:
119 119 response = HttpResponseRedirect(redirect)
120 120 response.set_cookie('user_fullname', form.cleaned_data['user_fullname'], max_age=max_age, samesite='Strict')
121 121 response.set_cookie('user_email', form.cleaned_data['user_email'], max_age=max_age, samesite='Strict')
122 122 response.set_cookie('user_affiliation', form.cleaned_data['user_affiliation'], max_age=max_age, samesite='Strict')
123 123 return(response)
124 124 else:
125 125 form = madweb.forms.RegisterForm()
126 126
127 127 else:
128 128 form = madweb.forms.RegisterForm()
129 129 return render(request, 'madweb/register.html', {'form': form, 'home_active': 'class="active"',
130 130 'site_name': siteName, 'site_list': siteList,
131 131 'redirect': redirect})
132 132
133 133
134 134
135 135
136 136
137 137
138 138 def view_single(request):
139 139 """view_single is the single experiment view. It is supplemented by ajax views to speed performamnce,
140 140 but this view can also create the entire page given a complete query string
141 141 """
142 142 responseDict = {'single_active': 'class="active"'}
143 143 cookieDict = request.COOKIES
144 144 user_email = cookieDict['user_email']
145 145 queryDict = request.GET.copy()
146 146 queryDict['user_email'] = user_email
147 147 madDB = madrigal.metadata.MadrigalDB()
148 148 bg_color = madDB.getBackgroundColor()
149 149 madWeb = madrigal.ui.web.MadrigalWeb(madDB)
150 150 siteName, siteList = madWeb.getSiteInfo()
151 151 form = madweb.forms.SingleExpDefaultForm(queryDict)
152 152 if not form.is_valid():
153 153 # new page
154 154 form = madweb.forms.SingleExpDefaultForm()
155 155 responseDict['form'] = form
156 156 responseDict['site_name'] = siteName
157 157 responseDict['site_list'] = siteList
158 158 responseDict['redirect_list'] = madWeb.getSingleRedirectList()
159 159 if 'instruments' in request.GET:
160 160 responseDict['instruments'] = request.GET['instruments']
161 161 if 'years' in request.GET:
162 162 responseDict['years'] = request.GET['years']
163 163 if 'months' in request.GET:
164 164 responseDict['months'] = request.GET['months']
165 165 try:
166 166 # add extra keys if choosing a file
167 167 form.fields['file_list']
168 168 responseDict['loader'] = 'loadSingleForm'
169 169 responseDict['redirect'] = reverse('get_files')
170 170 # handle the case with no files
171 171 if len(form.fields['file_list'].choices) < 2:
172 172 form2 = madweb.forms.SingleExpPlotsForm({'experiment_list':form['exp_id'].initial})
173 173 form.fields['plot_list'] = form2.fields['plot_list']
174 174 except:
175 175 pass
176 176 responseDict['bg_color'] = bg_color
177 177 return render(request, 'madweb/single.html', responseDict)
178 178
179 179
180 180 def get_categories(request):
181 181 """get_categories is a Ajax call that returns the categories select html to support the
182 182 single experiment UI. Called when a user modifies the isGlobal checkbox.
183 183
184 184 Inputs:
185 185 request
186 186 """
187 187 form = madweb.forms.SingleExpDefaultForm(request.GET)
188 188
189 189 return render(request, 'madweb/categories.html', {'form': form})
190 190
191 191
192 192 def get_instruments(request):
193 193 """get_instruments is a Ajax call that returns the instruments select html to support the
194 194 single experiment UI. Called when a user modifies the categories select field.
195 195
196 196 Inputs:
197 197 request
198 198 """
199 199 form = madweb.forms.SingleExpInstForm(request.GET)
200 200
201 201 return render(request, 'madweb/instruments.html', {'form': form})
202 202
203 203
204 204 def get_years(request):
205 205 """get_years is a Ajax call that returns the years select html to support the
206 206 single experiment UI. Called when a user modifies the instruments select field.
207 207
208 208 Inputs:
209 209 request
210 210 """
211 211 form = madweb.forms.SingleExpYearForm(request.GET)
212 212
213 213 is_global = madweb.forms.getIsGlobal([], request.GET)
214 214
215 215 return render(request, 'madweb/years.html', {'isGlobal': is_global,
216 216 'form': form})
217 217
218 218
219 219 def get_months(request):
220 220 """get_months is a Ajax call that returns the months select html to support the
221 221 single experiment UI. Called when a user modifies the years select field.
222 222
223 223 Inputs:
224 224 request
225 225 """
226 226 form = madweb.forms.SingleExpMonthForm(request.GET)
227 227
228 228 is_global = madweb.forms.getIsGlobal([], request.GET)
229 229 year = int(request.GET['years'])
230 230 kinst =int(request.GET['instruments'])
231 231
232 232 return render(request, 'madweb/months.html', {'isGlobal': is_global,
233 233 'years': year,
234 234 'form': form})
235 235
236 236
237 237 def get_calendar(request):
238 238 """get_calendar is a Ajax call that returns the calendar html to support the
239 239 single experiment UI. Called when a user selects month field.
240 240
241 241 Inputs:
242 242 request
243 243 """
244 244 is_global = madweb.forms.getIsGlobal([], request.GET)
245 245 year = int(request.GET['years'])
246 246 month = int(request.GET['months'])
247 247 kinst =int(request.GET['instruments'])
248 248
249 249 form = madweb.forms.SingleExpCalendarForm({'years': year,
250 250 'months': month,
251 251 'instruments': kinst})
252 252
253 253 return render(request, 'madweb/calendar.html', {'isGlobal': is_global,
254 254 'years': year,
255 255 'months': month,
256 256 'instruments': kinst,
257 257 'form': form})
258 258
259 259
260 260 def populate_calendar_experiment(request):
261 261 """populate_calendar_experiment is a ajax view that returns a json object used by the
262 262 calender widget to populate itself.
263 263
264 264 Inputs:
265 265 request
266 266 """
267 267 is_global = madweb.forms.getIsGlobal([], request.GET)
268 268 year = int(request.GET['years'])
269 269 month = int(request.GET['months'])
270 270 kinst =int(request.GET['instruments'])
271 271 madDB = madrigal.metadata.MadrigalDB()
272 272 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
273 273 madInstObj = madrigal.metadata.MadrigalInstrument(madDB)
274 274 catId = madInstObj.getCategoryId(kinst)
275 275
276 276 expDays = madWebObj.getDays(kinst, year, month)
277 277
278 278 if len(expDays) == 0:
279 279 expDays = madWebObj.getDays(kinst, year, month, optimize=False)
280 280
281 281 color = "#999"
282 282 jsonListFinal = []
283 283 for expDay in expDays:
284 284 newdate = '%i/%i/%i' % (expDay.day, expDay.month, expDay.year)
285 285 urlperDate = reverse('view_single')
286 286 query_str = '?'
287 287 if is_global:
288 288 query_str += 'isGlobal=on&'
289 289 query_str += 'categories=%i&instruments=%i&years=%i&months=%i&days=%i' % (catId, kinst, year,
290 290 expDay.month, expDay.day)
291 291 urlperDate += query_str
292 292 dayList = [newdate, "", urlperDate, color]
293 293 jsonListFinal.append(dayList)
294 294
295 295 return HttpResponse(json.dumps(jsonListFinal), content_type='application/json')
296 296
297 297
298 298 def get_files(request):
299 299 """get_files is a Ajax call that returns the files select html to support the
300 300 single experiment UI. Called when a user modifies the calendar or experiments fields.
301 301
302 302 Inputs:
303 303 request
304 304 """
305 305 cookieDict = request.COOKIES
306 306 user_email = cookieDict['user_email']
307 307 queryDict = request.GET.copy()
308 308 queryDict['user_email'] = user_email
309 309 form = madweb.forms.SingleExpFileForm(queryDict)
310 310
311 311 is_global = madweb.forms.getIsGlobal([], request.GET)
312 312
313 313 return render(request, 'madweb/file_list.html', {'isGlobal': is_global,
314 314 'form': form,
315 315 'loader': 'loadSingleForm',
316 316 'redirect': reverse('get_files')})
317 317
318 318
319 319 def change_files(request):
320 320 """change_files is a Ajax call that returns the files options html to support the
321 321 single experiment UI. Called when a user modifies the files select field.
322 322
323 323 Inputs:
324 324 request
325 325 """
326 326 expID =int(request.GET['experiment_list'])
327 327 basename = request.GET['file_list']
328 328 madDB = madrigal.metadata.MadrigalDB()
329 329 form = madweb.forms.SingleExpButtonsForm(request.GET)
330 330
331 331 return render(request, 'madweb/file_buttons.html', {'form': form,
332 332 'plot_label': madDB.getPlotButtonLabel()})
333 333
334 334
335 335 def show_plots(request):
336 336 """show_plots is a Ajax call that returns the files data html with plots to support the
337 337 single experiment UI. Called when a user modifies the files select field.
338 338
339 339 Inputs:
340 340 request
341 341 """
342 342 madDB = madrigal.metadata.MadrigalDB()
343 343 madExpObj = madrigal.metadata.MadrigalExperiment(madDB)
344 344 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
345 345
346 346 try:
347 347 expID = int(request.GET['experiment_list'])
348 348 except ValueError:
349 349 # convert expPath to expID
350 350 expID = madWebObj.getExpIDFromExpPath(request.GET['experiment_list'], True)
351 351 plotList = madExpObj.getExpLinksByExpId(expID)
352 352 if len(plotList) != 0:
353 353 form = madweb.forms.SingleExpPlotsForm(request.GET)
354 354 template = 'madweb/show_plots.html'
355 355 context = {'form': form}
356 356 else:
357 357 template = 'madweb/parameter_selection.html'
358 358 form = madweb.forms.SingleExpPlotsSelectionForm(request.GET)
359 359 context = {'form': form, 'expID': expID}
360 360
361 361 return render(request, template, context)
362 362
363 363
364 364 def view_plot(request):
365 365
366 param1d = int(request.GET.get('param1d','0'))
367 param2d = int(request.GET.get('param2d','0'))
366 param1d = request.GET.get('param1d', 0)
367 param2d = request.GET.get('param2d', 0)
368 368
369 369 madDB = madrigal.metadata.MadrigalDB()
370 370 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
371 371 madExpObj = madrigal.metadata.MadrigalExperiment(madDB)
372 372
373 373 expID =int(request.GET['expID'])
374 374 expDir = madExpObj.getExpDirByExpId(expID)
375 375 if expDir is None:
376 376 raise ValueError('No expDir found for exp_id %i' % (int(expID)))
377 377
378 378 fileList = madWebObj.getFileFromExpID(expID, False)
379 379 firsttuple = [a_tuple[0] for a_tuple in fileList]
380 380 basename = firsttuple[0]
381 381 fullFilename = os.path.join(expDir, basename)
382 382
383 383 with h5py.File(fullFilename, "r") as f:
384 384
385 385 # Get the data
386 386
387 data = f[list(f.keys())[0]]
387 data = f['Data']
388 388
389 if 'Array Layout' in list(data.keys()):
390 array = data[list(data.keys())[0]]
391 timestamps = array[list(array.keys())[4]]
392 datatime = [datetime.datetime.fromtimestamp(t) for t in list(timestamps)]
393
394 range = array[list(array.keys())[3]]
395 datarange = list(range)
396
389 if 'Array Layout' in data:
390 array = data['Array Layout']
391 datatime = [datetime.datetime.fromtimestamp(t) for t in array['timestamps']]
392 yrange = array['gdalt']
397 393
398 394 if param1d==0:
399 parameters_2d = array[list(array.keys())[1]]
400 paramname = list(parameters_2d.keys())[param2d]
401 param = parameters_2d[list(parameters_2d.keys())[param2d]]
402 dataparam = list(param)
403 plot = plot_heatmap(datatime,datarange,dataparam,paramname)
404
395 plot = plot_heatmap(datatime, yrange, array['2D Parameters'][param2d], param2d)
405 396 else:
406 parameters_1d = array[list(array.keys())[0]]
407 paramname = list(parameters_1d.keys())[param1d]
408 param = parameters_1d[list(parameters_1d.keys())[param1d]]
409 dataparam = list(param)
410 plot = plot_scatter(datatime,dataparam,paramname)
397 plot = plot_scatter(datatime, array['1D Parameters'][param1d], param1d)
411 398
412 399 else:
413 table = data[list(data.keys())[0]]
414 a = list(table.dtype.fields.keys())
415 index = a.index('ut2_unix')
416 v = a[index:]
417 paramname = v[param1d]
418 dataparam = list(table[paramname])
419 datatime = [datetime.datetime.fromtimestamp(t) for t in list(table['ut2_unix'])]
420 plot = plot_scatter(datatime,dataparam,paramname)
400 table = data['Table Layout']
401 datatime = [datetime.datetime.fromtimestamp(t) for t in table['ut2_unix']]
402 plot = plot_scatter(datatime,table[param1d],param1d)
421 403
422 404 return HttpResponse(plot)
423 405
424 406 def plot_scatter(datatime,dataparam,paramname):
425 407 if (numpy.isnan(dataparam).all()):
426 408 plot = "There is no valid data available for this plot"
427 409
428 410 else:
429 411 fig = go.Figure()
430 412 fig.add_trace(go.Scatter(x=datatime, y=dataparam))
431 413 fig.update_yaxes(title_text=paramname)
432 414
433 415 delta = datatime[-1] - datatime[1]
434 416
435 417 if (delta>datetime.timedelta(days=30)):
436 418 # Add range slider
437 419 fig.update_layout(
438 420 xaxis=dict(
439 421 rangeselector=dict(
440 422 buttons=list([
441 423 dict(count=1,
442 424 label="1m",
443 425 step="month",
444 426 stepmode="backward"),
445 427 dict(count=6,
446 428 label="6m",
447 429 step="month",
448 430 stepmode="backward"),
449 431 dict(count=1,
450 432 label="1y",
451 433 step="year",
452 434 stepmode="backward"),
453 435 dict(step="all")
454 436 ])
455 437 ),
456 438 rangeslider=dict(
457 439 visible=True
458 440 ),
459 441 type="date"
460 442 )
461 443 )
462 444
463 445
464 446 plot = py.plot(fig, include_plotlyjs=False, output_type='div')
465 447
466 448
467 449 return plot
468 450
469 451
470 452 def plot_heatmap(datatime,datarange,dataparam,paramname):
471 if (numpy.isnan(dataparam).all()):
453 if (numpy.all(numpy.isnan(dataparam))):
472 454 plot = "There is no valid data available for this plot"
473 455 else:
474 456 fig = go.Figure()
475 457 fig.add_trace(go.Heatmap(x=datatime,y=datarange,z= dataparam,colorscale='Jet',colorbar={"title":paramname}))
476 458 fig.update_yaxes(title_text="range")
477 459 fig.update_layout(
478 460 updatemenus=[
479 461 dict(
480 462 buttons=list([
481 463 dict(
482 464 args=["colorscale", "Jet"],
483 465 label="Jet",
484 466 method="restyle"
485 467 ),
486 468 dict(
487 469 args=["colorscale", "RdBu"],
488 470 label="Red-Blue",
489 471 method="restyle"
490 472 ),
491 473 dict(
492 474 args=["colorscale", "Viridis"],
493 475 label="Viridis",
494 476 method="restyle"
495 477 ),
496 478 dict(
497 479 args=["colorscale", "Cividis"],
498 480 label="Cividis",
499 481 method="restyle"
500 482 ),
501 483 dict(
502 484 args=["colorscale", "Greens"],
503 485 label="Greens",
504 486 method="restyle"
505 487 ),
506 488 ]),
507 489 type = "dropdown",
508 490 direction="down",
509 pad={"r": 10, "t": 10},
491 pad={"r": 10, "t": -10},
510 492 showactive=True,
511 493 x=0.1,
512 494 xanchor="left",
513 495 y=1.05,
514 496 yanchor="top"
515 497 ),
516 498 dict(
517 499 buttons=list([
518 500 dict(
519 501 args=[{"contours.showlines": False, "type": "contour"}],
520 502 label="Hide lines",
521 503 method="restyle"
522 504 ),
523 505 dict(
524 506 args=[{"contours.showlines": True, "type": "contour"}],
525 507 label="Show lines",
526 508 method="restyle"
527 509 ),
528 510 ]),
529 511 direction="down",
530 pad={"r": 10, "t": 10},
512 pad={"r": 10, "t": -10},
531 513 showactive=True,
532 514 x=0.32,
533 515 xanchor="left",
534 516 y=1.05,
535 517 yanchor="top"
536 518 ),
519
537 520 ]
538 521 )
539 522
540 523 fig.update_layout(
541 524 annotations=[
542 525 dict(text="Colorscale", showarrow=False,
543 x=0, xref="paper", y=1.03, yref="paper", align="left"),
544 dict(text="Lines", x=0.25, xref="paper", y=1.03, yref="paper",
526 x=0, xref="paper", y=1.05, yref="paper", align="left"),
527 dict(text="Lines", x=0.25, xref="paper", y=1.05, yref="paper",
545 528 showarrow=False)
546 529 ]
547 530 )
548 531
549 532
550 533 plot = py.plot(fig, include_plotlyjs=False, output_type='div')
551 534
552 535 return plot
553 536
554 537
555 538 def download_as_is(request):
556 539 """download_as_is is a Ajax call that returns the download as is html to support the
557 540 single experiment UI. Called when a user selects download/as is link.
558 541
559 542 Inputs:
560 543 request
561 544 """
562 545 cookieDict = request.COOKIES
563 546 if not 'user_fullname' in cookieDict:
564 547 return(HttpResponse('<p>Cookie with user_fullname required for downloadAsIs</p>'))
565 548 user_fullname = django.utils.http.urlquote_plus(cookieDict['user_fullname'])
566 549 user_email = cookieDict['user_email']
567 550 user_affiliation = django.utils.http.urlquote_plus(cookieDict['user_affiliation'])
568 551 expID =int(request.GET['experiment_list'])
569 552 file_list = request.GET['file_list']
570 553 form = madweb.forms.SingleExpDownloadAsIsForm({'format_select':file_list,
571 554 'expID': expID})
572 555
573 556 return render(request, 'madweb/download_as_is.html', {'form': form, 'exp_id':expID,
574 557 'user_fullname':user_fullname,
575 558 'user_email':user_email,
576 559 'user_affiliation': user_affiliation})
577 560
578 561
579 562 def download_file_as_is(request):
580 563 """download_file_as_is is a Ajax call that actually downloads a madrigal file.
581 564
582 565 Inputs:
583 566 request
584 567 """
585 568 madDB = madrigal.metadata.MadrigalDB()
586 569 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
587 570 user_fullname = urllib.parse.unquote_plus(request.GET['user_fullname'])
588 571 user_email = request.GET['user_email']
589 572 user_affiliation = urllib.parse.unquote_plus(request.GET['user_affiliation'])
590 573 exp_id = request.GET['exp_id']
591 574 basename = request.GET['basename']
592 575 downloadFile = madWebObj.downloadFileAsIs(exp_id, basename, user_fullname, user_email, user_affiliation)
593 576 f = open(downloadFile, 'rb')
594 577 filename = os.path.basename(downloadFile)
595 578 chunk_size = 8192
596 579 file_type = mimetypes.guess_type(downloadFile)[0]
597 580 if file_type is None:
598 581 file_type = 'application/octet-stream'
599 582 response = StreamingHttpResponse(FileWrapper(f, chunk_size),
600 583 content_type=file_type)
601 584 response['Content-Length'] = os.path.getsize(downloadFile)
602 585 response['Content-Disposition'] = "attachment; filename=%s" % (filename)
603 586 response.set_cookie('fileDownload', 'true', path='/', samesite='Strict')
604 587 return(response)
605 588
606 589
607 590 def print_as_is(request):
608 591 """print_as_is is a Ajax call that returns the text of the ascii file to support the
609 592 single experiment UI if request.GET has key "text", or the length of the file to be
610 593 downloaded if not. Called when a user selects print/as is link.
611 594
612 595 Inputs:
613 596 request
614 597 """
615 598 madDB = madrigal.metadata.MadrigalDB()
616 599 madExpObj = madrigal.metadata.MadrigalExperiment(madDB)
617 600 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
618 601 madParmObj = madrigal.data.MadrigalParameters(madDB)
619 602
620 603 cookieDict = request.COOKIES
621 604 if not 'user_fullname' in cookieDict:
622 605 return(HttpResponse('<p>Cookie with user_fullname required for printAsIs</p>'))
623 606 user_fullname = django.utils.http.urlquote_plus(cookieDict['user_fullname'])
624 607 user_email = cookieDict['user_email']
625 608 user_affiliation = django.utils.http.urlquote_plus(cookieDict['user_affiliation'])
626 609 expID =int(request.GET['experiment_list'])
627 610 basename = request.GET['file_list']
628 611 expDir = madExpObj.getExpDirByExpId(int(expID))
629 612 if expDir is None:
630 613 raise ValueError('No expDir found for exp_id %i' % (int(expID)))
631 614 fullFilename = os.path.join(expDir, basename)
632 615
633 616 # determine if we need to return the full file text, or just the size and name
634 617 if 'text' in request.GET:
635 618 madFileObj = madrigal.data.MadrigalFile(fullFilename, madDB)
636 619 measParms = madFileObj.getMeasuredParmList()
637 620 measParmMnemList = madParmObj.getParmMnemonicList(measParms) + madFileObj.getStandardParms(upper=True)
638 621 measParmDescList = madParmObj.getParmDescriptionList(measParmMnemList)
639 622 parmList = list(zip(measParmMnemList, measParmDescList))
640 623 f = open(request.GET['text'])
641 624 text = f.read()
642 625 f.close()
643 626
644 627 return render(request, 'madweb/print_as_is.html', {'text': text, 'parmList': parmList})
645 628
646 629 else:
647 630 tmpFilename = madWebObj.printFileAsIs(fullFilename, user_fullname, user_email, user_affiliation)
648 631 filesize = os.path.getsize(tmpFilename)
649 632 return(HttpResponse('%s:%s' % (filesize, tmpFilename)))
650 633
651 634
652 635 def list_records(request):
653 636 """list_records is a Ajax call that returns the list records text.
654 637
655 638 Inputs:
656 639 request
657 640 """
658 641 madDB = madrigal.metadata.MadrigalDB()
659 642 madExpObj = madrigal.metadata.MadrigalExperiment(madDB)
660 643 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
661 644
662 645 expID =int(request.GET['experiment_list'])
663 646 basename = request.GET['file_list']
664 647 expDir = madExpObj.getExpDirByExpId(int(expID))
665 648 if expDir is None:
666 649 raise ValueError('No expDir found for exp_id %i' % (int(expID)))
667 650 fullFilename = os.path.join(expDir, basename)
668 651
669 652 text = madWebObj.listRecords(fullFilename)
670 653
671 654 return render(request, 'madweb/list_records.html', {'expDir': expDir,
672 655 'basename': basename,
673 656 'text': text})
674 657
675 658
676 659 def view_record_plot(request):
677 660 """view_record_plot returns the view individual record page.
678 661
679 662 Inputs:
680 663 request
681 664 """
682 665 expDir = request.GET['expDir']
683 666 basename = request.GET['basename']
684 667 recno = int(request.GET['recno'])
685 668
686 669 return render(request, 'madweb/view_record_plot.html', {'expDir': expDir,
687 670 'basename': basename,
688 671 'recno': recno})
689 672
690 673
691 674 def view_record_image(request):
692 675 """view_record_plot is a Ajax call that returns the record plot.
693 676
694 677 Inputs:
695 678 request
696 679 """
697 680 expDir = request.GET['expDir']
698 681 basename = request.GET['basename']
699 682 recno = int(request.GET['recno'])
700 683 pngFiles = glob.glob(os.path.join(expDir, 'plots', basename, 'records/*%05i*.png' % (recno)))
701 684
702 685 image_data = open(pngFiles[0], "rb").read()
703 686 return HttpResponse(image_data, content_type="image/png")
704 687
705 688
706 689
707 690
708 691 def show_info(request):
709 692 """show_info is a Ajax call that returns the text of the catalog/header text to support the
710 693 single experiment UI. Called when a user selects show info link.
711 694
712 695 Inputs:
713 696 request
714 697 """
715 698 madDB = madrigal.metadata.MadrigalDB()
716 699 madExpObj = madrigal.metadata.MadrigalExperiment(madDB)
717 700
718 701 expID =int(request.GET['experiment_list'])
719 702 basename = request.GET['file_list']
720 703 expDir = madExpObj.getExpDirByExpId(int(expID))
721 704 if expDir is None:
722 705 raise ValueError('No expDir found for exp_id %i' % (int(expID)))
723 706 fullFilename = os.path.join(expDir, basename)
724 707
725 708 madFileObj = madrigal.data.MadrigalFile(fullFilename, madDB)
726 709 text = madFileObj.getCatalogHeaderStr()
727 710
728 711 return render(request, 'madweb/show_info.html', {'text':text})
729 712
730 713
731 714 def show_doi(request):
732 715 """show_doi is a Ajax call that returns the permanent url for references to support the
733 716 single experiment UI. Called when a user selects show doi link.
734 717
735 718 Inputs:
736 719 request
737 720 """
738 721 madDB = madrigal.metadata.MadrigalDB()
739 722 madExpObj = madrigal.metadata.MadrigalExperiment(madDB)
740 723 madInstObj = madrigal.metadata.MadrigalInstrument(madDB)
741 724
742 725 expID =request.GET['experiment_list']
743 726 basename = request.GET['file_list']
744 727 expDir = madExpObj.getExpDirByExpId(int(expID))
745 728 # get experiment PI and institution
746 729 PI = madExpObj.getPIByExpId(int(expID))
747 730 kinst = madExpObj.getKinstByExpId(int(expID))
748 731 startDTList = madExpObj.getExpStartDateTimeByExpId(int(expID))
749 732 yearStr = str(startDTList[0])
750 733 if PI is None:
751 734 PI = madInstObj.getContactName(kinst)
752 735 institution = madInstObj.getContactAddress1(kinst)
753 736
754 737 try:
755 738 madFileObj = madrigal.metadata.MadrigalMetaFile(madDB, os.path.join(expDir, 'fileTab.txt'))
756 739 url = madFileObj.getFileDOIUrlByFilename(basename)
757 740 except:
758 741 url = 'Unknown - please contact madrigal@haystack.mit.edu'
759 742
760 743 return render(request, 'madweb/show_doi.html', {'url':url, 'PI': PI, 'year': yearStr,
761 744 'institution': institution})
762 745
763 746
764 747 def get_advanced(request):
765 748 """get_advanced is a view that allows user to download/print files with selected parms
766 749 and filters.
767 750
768 751 Inputs:
769 752 request
770 753 """
771 754 madDB = madrigal.metadata.MadrigalDB()
772 755 bg_color = madDB.getBackgroundColor()
773 756 madWeb = madrigal.ui.web.MadrigalWeb(madDB)
774 757 siteName, siteList = madWeb.getSiteInfo()
775 758 madExpObj = madrigal.metadata.MadrigalExperiment(madDB)
776 759 webFormatObj = madrigal.ui.web.MadrigalWebFormat()
777 760 madParmObj = madrigal.data.MadrigalParameters(madDB)
778 761 parmList = webFormatObj.getFormat('Comprehensive')
779 762 measParmList = []
780 763 derivedParmList = []
781 764 allParmList = []
782 765 sureParmList = []
783 766
784 767 if 'experiment_list' in request.GET:
785 768 expID = int(request.GET['experiment_list'])
786 769 else:
787 770 return(HttpResponse('<p>experiment_list required for getAdvanced</p>'))
788 771 basename = request.GET['file_list']
789 772 type = request.GET['type']
790 773 expDir = madExpObj.getExpDirByExpId(int(expID))
791 774 if expDir is None:
792 775 raise ValueError('No expDir found for exp_id %i' % (int(expID)))
793 776 fullFilename = os.path.join(expDir, basename)
794 777 expName, kindatDesc = madWeb.getInfoFromFile(fullFilename)
795 778 madFileObj = madrigal.data.MadrigalFile(fullFilename, madDB)
796 779 earliestTime = madFileObj.getEarliestTime()
797 780 latestTime = madFileObj.getLatestTime()
798 781 earliestDT = datetime.datetime(*earliestTime)
799 782 latestDT = datetime.datetime(*latestTime)
800 783 madFileObj.getMeasDervBothParmLists(parmList, measParmList, derivedParmList, allParmList, sureParmList)
801 784 allParmDescList = madParmObj.getParmDescriptionList(allParmList)
802 785
803 786 dataDict = {'type': type,
804 787 'fullFilename': fullFilename,
805 788 'madFileObj': madFileObj, 'parameters': [],
806 789 'measParmList': measParmList, 'derivedParmList': derivedParmList,
807 790 'allParmList': allParmList, 'allParmDescList': allParmDescList,
808 791 'madDB': madDB, 'madParmObj': madParmObj}
809 792
810 793 min_alt = madFileObj.getMinValidAltitude()
811 794 max_alt = madFileObj.getMaxValidAltitude()
812 795 try:
813 796 float(min_alt)
814 797 float(max_alt)
815 798 dataDict['min_alt'] = '%9.2f' % (min_alt)
816 799 dataDict['max_alt'] = '%9.2f' % (max_alt)
817 800 except:
818 801 pass
819 802
820 803 if 'AZM' in allParmList:
821 804 dataDict['min_az'] = '-180.0'
822 805 dataDict['max_az'] = '180.0'
823 806 dataDict['min_az2'] = '0.0'
824 807 dataDict['max_az2'] = '0.0'
825 808
826 809 if 'ELM' in allParmList:
827 810 dataDict['min_el'] = '0.0'
828 811 dataDict['max_el'] = '90.0'
829 812 dataDict['min_el2'] = '0.0'
830 813 dataDict['max_el2'] = '0.0'
831 814
832 815 if 'PL' in allParmList:
833 816 min_pl = madFileObj.getMinPulseLength()
834 817 max_pl = madFileObj.getMaxPulseLength()
835 818 try:
836 819 float(min_pl)
837 820 float(max_pl)
838 821 dataDict['min_pl'] = '%9.2f' % (min_pl)
839 822 dataDict['max_pl'] = '%9.2f' % (max_pl)
840 823 except:
841 824 pass
842 825
843 826 if type == 'download':
844 827 defaultFormat = 'Hdf5'
845 828 else:
846 829 defaultFormat = 'ascii'
847 830 dataDict['formats'] = defaultFormat
848 831 dataDict['missing'] = 'NaN'
849 832 dataDict['start_date'] = earliestDT
850 833 dataDict['end_date'] = latestDT
851 834
852 835
853 836 isprintForm = madweb.forms.IsprintForm(dataDict)
854 837
855 838 return render(request, 'madweb/get_advanced.html', {'form': isprintForm,
856 839 'parmList': isprintForm.parmList,
857 840 'measParmList': measParmList,
858 841 'site_name': siteName, 'site_list': siteList,
859 842 'expName': expName, 'kindatDesc': kindatDesc,
860 843 'basename': os.path.basename(fullFilename),
861 844 'type': type, 'bg_color': bg_color,
862 845 'datetime': True})
863 846
864 847 def advanced_download(request):
865 848 """advanced_download is a view that downloads a file with selected parms
866 849 and filters.
867 850
868 851 Inputs:
869 852 request
870 853 """
871 854 madDB = madrigal.metadata.MadrigalDB()
872 855 madWeb = madrigal.ui.web.MadrigalWeb(madDB)
873 856 webFormatObj = madrigal.ui.web.MadrigalWebFormat()
874 857 madParmObj = madrigal.data.MadrigalParameters(madDB)
875 858
876 859 cookieDict = request.COOKIES
877 860 if not 'user_fullname' in cookieDict:
878 861 return(HttpResponse('<p>Cookie with user_fullname required for advancedDownload</p>'))
879 862 user_fullname = django.utils.http.urlquote_plus(cookieDict['user_fullname'])
880 863 user_email = cookieDict['user_email']
881 864 user_affiliation = django.utils.http.urlquote_plus(cookieDict['user_affiliation'])
882 865
883 866 parmList = webFormatObj.getFormat('Comprehensive')
884 867 measParmList = []
885 868 derivedParmList = []
886 869 allParmList = []
887 870 sureParmList = []
888 871 madFileObj = madrigal.data.MadrigalFile(request.GET['fullFilename'], madDB)
889 872 madFileObj.getMeasDervBothParmLists(parmList, measParmList, derivedParmList, allParmList, sureParmList)
890 873 allParmDescList = madParmObj.getParmDescriptionList(allParmList)
891 874
892 875 request.GET._mutable = True
893 876 request.GET['madFileObj']=madFileObj
894 877 request.GET['measParmList']=measParmList
895 878 request.GET['derivedParmList']=derivedParmList
896 879 request.GET['allParmList']=allParmList
897 880 request.GET['allParmDescList']=allParmDescList
898 881 request.GET['start_date'] = request.GET['start_date'].strip()
899 882 request.GET['end_date'] = request.GET['end_date'].strip()
900 883 # convert dates to datetime
901 884 request.GET['start_date'] = datetime.datetime.strptime(request.GET['start_date'], '%Y-%m-%dT%H:%M:%S')
902 885 request.GET['end_date'] = datetime.datetime.strptime(request.GET['end_date'], '%Y-%m-%dT%H:%M:%S')
903 886 request.GET['madDB'] = madDB
904 887 request.GET['madParmObj'] = madParmObj
905 888
906 889
907 890 isprintForm = madweb.forms.IsprintForm(request.GET)
908 891
909 892
910 893 if not isprintForm.is_valid():
911 894 raise ValueError(str(isprintForm.errors))
912 895
913 896 downloadFile = madWeb.downloadIsprintFileFromIsprintForm(isprintForm.cleaned_data, user_fullname, user_email, user_affiliation)
914 897
915 898
916 899 f = open(downloadFile, 'rb')
917 900 filename = os.path.basename(downloadFile)
918 901 chunk_size = 8192
919 902 file_type = mimetypes.guess_type(downloadFile)[0]
920 903 if file_type is None:
921 904 file_type = 'application/octet-stream'
922 905 response = StreamingHttpResponse(FileWrapper(f, chunk_size),
923 906 content_type=file_type)
924 907 response['Content-Length'] = os.path.getsize(downloadFile)
925 908 response['Content-Disposition'] = "attachment; filename=%s" % (filename)
926 909 return(response)
927 910
928 911
929 912 def advanced_print(request):
930 913 """advanced_download is a view that print a file with selected parms
931 914 and filters.
932 915
933 916 Inputs:
934 917 request
935 918 """
936 919 madDB = madrigal.metadata.MadrigalDB()
937 920 bg_color = madDB.getBackgroundColor()
938 921 madWeb = madrigal.ui.web.MadrigalWeb(madDB)
939 922 webFormatObj = madrigal.ui.web.MadrigalWebFormat()
940 923 madParmObj = madrigal.data.MadrigalParameters(madDB)
941 924
942 925 cookieDict = request.COOKIES
943 926 if not 'user_fullname' in cookieDict:
944 927 return(HttpResponse('<p>Cookie with user_fullname required for advancedPrint</p>'))
945 928 user_fullname = django.utils.http.urlquote_plus(cookieDict['user_fullname'])
946 929 user_email = cookieDict['user_email']
947 930 user_affiliation = django.utils.http.urlquote_plus(cookieDict['user_affiliation'])
948 931
949 932 parmList = webFormatObj.getFormat('Comprehensive')
950 933 measParmList = []
951 934 derivedParmList = []
952 935 allParmList = []
953 936 sureParmList = []
954 937 madFileObj = madrigal.data.MadrigalFile(request.GET['fullFilename'], madDB)
955 938 madFileObj.getMeasDervBothParmLists(parmList, measParmList, derivedParmList, allParmList, sureParmList)
956 939 allParmDescList = madParmObj.getParmDescriptionList(allParmList)
957 940 fullFilename = request.GET['fullFilename']
958 941 expName, kindatDesc = madWeb.getInfoFromFile(fullFilename)
959 942
960 943 request.GET._mutable = True
961 944 request.GET['madFileObj']=madFileObj
962 945 request.GET['measParmList']=measParmList
963 946 request.GET['derivedParmList']=derivedParmList
964 947 request.GET['allParmList']=allParmList
965 948 request.GET['allParmDescList']=allParmDescList
966 949 request.GET['start_date'] = request.GET['start_date'].strip()
967 950 request.GET['end_date'] = request.GET['end_date'].strip()
968 951 # convert dates to datetime
969 952 request.GET['start_date'] = datetime.datetime.strptime(request.GET['start_date'], '%Y-%m-%dT%H:%M:%S')
970 953 request.GET['end_date'] = datetime.datetime.strptime(request.GET['end_date'], '%Y-%m-%dT%H:%M:%S')
971 954 request.GET['madDB'] = madDB
972 955 request.GET['madParmObj'] = madParmObj
973 956
974 957 isprintForm = madweb.forms.IsprintForm(request.GET)
975 958
976 959
977 960 if not isprintForm.is_valid():
978 961 raise ValueError(str(isprintForm.errors))
979 962
980 963 downloadFile = madWeb.downloadIsprintFileFromIsprintForm(isprintForm.cleaned_data, user_fullname, user_email, user_affiliation)
981 964
982 965 f = open(downloadFile, 'r')
983 966 file_text = f.read()
984 967 f.close()
985 968 os.remove(downloadFile)
986 969 return render(request, 'madweb/advanced_print.html', {'expName': expName, 'kindatDesc': kindatDesc,
987 970 'basename': os.path.basename(fullFilename),
988 971 'file_text': file_text, 'bg_color': bg_color})
989 972
990 973
991 974 def view_list(request):
992 975 """view_list is the list experiment view.
993 976 """
994 977 madDB = madrigal.metadata.MadrigalDB()
995 978 bg_color = madDB.getBackgroundColor()
996 979 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
997 980 siteName, siteList = madWebObj.getSiteInfo()
998 981 responseDict = {'list_active': 'class="active"'}
999 982 form = madweb.forms.ListExpForm()
1000 983 responseDict['form'] = form
1001 984 responseDict['categoryList'] = form.categories
1002 985 responseDict['instrumentList'] = form.instruments
1003 986 responseDict['site_name'] = siteName
1004 987 responseDict['site_list'] = siteList
1005 988 responseDict['datetime'] = True
1006 989 responseDict['bg_color'] = bg_color
1007 990
1008 991 return render(request, 'madweb/list.html', responseDict)
1009 992
1010 993
1011 994 def list_experiments(request):
1012 995 """list_experiments is a view that lists all selected experiments.
1013 996
1014 997 Inputs:
1015 998 request
1016 999 """
1017 1000 madDB = madrigal.metadata.MadrigalDB()
1018 1001 bg_color = madDB.getBackgroundColor()
1019 1002 madWeb = madrigal.ui.web.MadrigalWeb(madDB)
1020 1003 siteName, siteList = madWeb.getSiteInfo()
1021 1004
1022 1005 listForm = madweb.forms.ListExpForm(request.GET)
1023 1006 try:
1024 1007 if not listForm.is_valid():
1025 1008 return(HttpResponse(str(listForm.errors)))
1026 1009 except KeyError:
1027 1010 return(HttpResponse('<p>Missing arguments in list_experiments</p>'))
1028 1011
1029 1012 kinstList = [int(kinst) for kinst in listForm.cleaned_data['instruments']]
1030 1013 startDate = listForm.cleaned_data['start_date']
1031 1014 startDT = datetime.datetime(startDate.year, startDate.month, startDate.day, 0, 0, 0)
1032 1015 endDate = listForm.cleaned_data['end_date']
1033 1016 endDT = datetime.datetime(endDate.year, endDate.month, endDate.day, 23, 59, 59)
1034 1017 localOnly = not listForm.cleaned_data['isGlobal']
1035 1018 expList = madWeb.getExperimentList(kinstList, startDT, endDT, localOnly)
1036 1019
1037 1020 return render(request, 'madweb/list_experiments.html', {'expList':expList, 'localOnly':localOnly,
1038 1021 'list_active': 'class="active"', 'site_name': siteName,
1039 1022 'site_list': siteList, 'bg_color': bg_color})
1040 1023
1041 1024
1042 1025 def show_experiment(request):
1043 1026 """show_experiment call that returns the experiment page to support the list experiments UI.
1044 1027
1045 1028 Inputs:
1046 1029 request
1047 1030 """
1048 1031 madDB = madrigal.metadata.MadrigalDB()
1049 1032 bg_color = madDB.getBackgroundColor()
1050 1033 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1051 1034 siteName, siteList = madWebObj.getSiteInfo()
1052 1035 cookieDict = request.COOKIES
1053 1036 user_email = cookieDict['user_email']
1054 1037 queryDict = request.GET.copy()
1055 1038 queryDict['user_email'] = user_email
1056 1039 if 'show_plots' in queryDict:
1057 1040 plotsForm = madweb.forms.SingleExpPlotsForm(queryDict)
1058 1041 form = madweb.forms.SingleExpFileForm(queryDict)
1059 1042 if 'show_plots' in queryDict:
1060 1043 form.fields['plot_list'] = plotsForm.fields['plot_list']
1061 1044 if len(form.fields['file_list'].choices) > 1:
1062 1045 # this experiment has data files
1063 1046 return render(request, 'madweb/show_experiment.html', {'list_active': 'class="active"',
1064 1047 'form': form, 'site_name': siteName,
1065 1048 'site_list': siteList,
1066 1049 'loader': 'loadPage',
1067 1050 'bg_color': bg_color,
1068 1051 'redirect': reverse('show_experiment')})
1069 1052
1070 1053 else:
1071 1054 # this experiment has no data files
1072 1055 form2 = madweb.forms.SingleExpPlotsForm(request.GET)
1073 1056 exp_desc = form.fields['exp_desc'].label
1074 1057 return render(request, 'madweb/show_exp_no_files.html', {'list_active': 'class="active"',
1075 1058 'form': form2, 'exp_desc': exp_desc,
1076 1059 'site_name': siteName,
1077 1060 'site_list': siteList,
1078 1061 'loader': 'loadPage',
1079 1062 'bg_color': bg_color,
1080 1063 'redirect': reverse('show_experiment')})
1081 1064
1082 1065
1083 1066 def show_experiment_v2(request):
1084 1067 """show_experiment_v2 is a slight variant of show_experiment to accept old form
1085 1068 calls from Madrigal2 sites.
1086 1069
1087 1070 Inputs:
1088 1071 request
1089 1072 """
1090 1073 madDB = madrigal.metadata.MadrigalDB()
1091 1074 bg_color = madDB.getBackgroundColor()
1092 1075 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1093 1076 siteName, siteList = madWebObj.getSiteInfo()
1094 1077 cookieDict = request.COOKIES
1095 1078 user_email = cookieDict['user_email']
1096 1079 queryDict = request.GET.copy()
1097 1080 queryDict['user_email'] = user_email
1098 1081 queryDict['experiment_list'] = queryDict['exp']
1099 1082 form = madweb.forms.SingleExpFileForm(queryDict)
1100 1083
1101 1084 return render(request, 'madweb/show_experiment.html', {'list_active': 'class="active"',
1102 1085 'form': form, 'site_name': siteName,
1103 1086 'site_list': siteList,
1104 1087 'loader': 'loadPage',
1105 1088 'bg_color': bg_color,
1106 1089 'redirect': reverse('show_experiment')})
1107 1090
1108 1091
1109 1092 def choose_script(request):
1110 1093 """choose_script that returns the choose script page.
1111 1094
1112 1095 Inputs:
1113 1096 request
1114 1097 """
1115 1098 madDB = madrigal.metadata.MadrigalDB()
1116 1099 bg_color = madDB.getBackgroundColor()
1117 1100 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1118 1101 siteName, siteList = madWebObj.getSiteInfo()
1119 1102 return render(request, 'madweb/choose_script.html', {'script_active': 'class="active"', 'site_name': siteName,
1120 1103 'site_list': siteList, 'bg_color': bg_color})
1121 1104
1122 1105
1123 1106 def download_as_is_script(request):
1124 1107 """download_as_is_script that returns the download_as_is_script script page.
1125 1108
1126 1109 Inputs:
1127 1110 request
1128 1111 """
1129 1112 madDB = madrigal.metadata.MadrigalDB()
1130 1113 bg_color = madDB.getBackgroundColor()
1131 1114 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1132 1115 siteName, siteList = madWebObj.getSiteInfo()
1133 1116 responseDict = {'script_active': 'class="active"'}
1134 1117 form = madweb.forms.DownloadAsIsScriptForm()
1135 1118 responseDict['form'] = form
1136 1119 responseDict['categoryList'] = form.categories
1137 1120 responseDict['instrumentList'] = form.instruments
1138 1121 responseDict['kindatList'] = form.kindats
1139 1122 responseDict['site_name'] = siteName
1140 1123 responseDict['site_list'] = siteList
1141 1124 responseDict['datetime'] = True
1142 1125 responseDict['bg_color'] = bg_color
1143 1126
1144 1127 return render(request, 'madweb/download_as_is_script.html', responseDict)
1145 1128
1146 1129
1147 1130 def generate_download_files_script(request):
1148 1131 """generate_download_files_script is a Ajax call that returns the generated file download script.
1149 1132
1150 1133 Inputs:
1151 1134 request
1152 1135 """
1153 1136 form = madweb.forms.DownloadAsIsScriptForm(request.GET)
1154 1137 if not form.is_valid():
1155 1138 raise ValueError('Form error: %s' % (form.errors))
1156 1139 cookieDict = request.COOKIES
1157 1140 if not 'user_fullname' in cookieDict:
1158 1141 return(HttpResponse('<p>Cookie with user_fullname required for generateDownloadFilesScript</p>'))
1159 1142 user_fullname = django.utils.http.urlquote_plus(cookieDict['user_fullname'])
1160 1143 user_email = cookieDict['user_email']
1161 1144 user_affiliation = django.utils.http.urlquote_plus(cookieDict['user_affiliation'])
1162 1145 madWebObj = madrigal.ui.web.MadrigalWeb()
1163 1146 script_text = madWebObj.generateDownloadFileScriptFromForm(form.cleaned_data, user_fullname,
1164 1147 user_email, user_affiliation)
1165 1148 return render(request, 'madweb/download_files_script.html', {'script_text': script_text})
1166 1149
1167 1150
1168 1151 def download_advanced_script(request):
1169 1152 """download_advanced_script that returns the download_advanced_script script page.
1170 1153
1171 1154 Inputs:
1172 1155 request
1173 1156 """
1174 1157 madDB = madrigal.metadata.MadrigalDB()
1175 1158 bg_color = madDB.getBackgroundColor()
1176 1159 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1177 1160 siteName, siteList = madWebObj.getSiteInfo()
1178 1161 responseDict = {'script_active': 'class="active"'}
1179 1162 form = madweb.forms.DownloadAdvancedScriptForm()
1180 1163 responseDict['form'] = form
1181 1164 responseDict['categoryList'] = form.categories
1182 1165 responseDict['instrumentList'] = form.instruments
1183 1166 responseDict['kindatList'] = form.kindats
1184 1167 responseDict['site_name'] = siteName
1185 1168 responseDict['site_list'] = siteList
1186 1169 responseDict['datetime'] = True
1187 1170 responseDict['bg_color'] = bg_color
1188 1171
1189 1172 return render(request, 'madweb/download_advanced_script.html', responseDict)
1190 1173
1191 1174
1192 1175 def generate_download_advanced_script(request):
1193 1176 """generate_download_advanced_script is a Ajax call that returns the generated advanced download script.
1194 1177
1195 1178 Inputs:
1196 1179 request
1197 1180 """
1198 1181 form1 = madweb.forms.DownloadAdvancedScriptForm(request.GET)
1199 1182 if not form1.is_valid():
1200 1183 raise ValueError('Form error: %s' % (form1.errors))
1201 1184 form2 = madweb.forms.AdvScriptParmsForm(request.GET)
1202 1185 if not form2.is_valid():
1203 1186 raise ValueError('Form error: %s' % (form2.errors))
1204 1187 form3 = madweb.forms.AdvScriptParmsFiltersForm(request.GET)
1205 1188 if not form3.is_valid():
1206 1189 raise ValueError('Form error: %s' % (form3.errors))
1207 1190 cookieDict = request.COOKIES
1208 1191 if not 'user_fullname' in cookieDict:
1209 1192 return(HttpResponse('<p>Cookie with user_fullname required for generateAdvancedDownloadScript</p>'))
1210 1193 user_fullname = django.utils.http.urlquote_plus(cookieDict['user_fullname'])
1211 1194 user_email = cookieDict['user_email']
1212 1195 user_affiliation = django.utils.http.urlquote_plus(cookieDict['user_affiliation'])
1213 1196 madWebObj = madrigal.ui.web.MadrigalWeb()
1214 1197 script_text = madWebObj.generateGlobalIsprintScriptFromForm(form1.cleaned_data, form2.cleaned_data,
1215 1198 form3.cleaned_data, user_fullname,
1216 1199 user_email, user_affiliation)
1217 1200 return render(request, 'madweb/download_files_script.html', {'script_text': script_text})
1218 1201
1219 1202
1220 1203 def generate_parms_script(request):
1221 1204 """generate_parms_script is a Ajax call that returns the generated parameter script.
1222 1205
1223 1206 Inputs:
1224 1207 request
1225 1208 """
1226 1209 form = madweb.forms.AdvScriptParmsForm(request.GET)
1227 1210 return render(request, 'madweb/download_adv_parms_script.html', {'form': form,
1228 1211 'parmList': form.parmList})
1229 1212
1230 1213
1231 1214 def generate_parms_filters_script(request):
1232 1215 """generate_parms_filters_script is a Ajax call that returns the generated parameter filters script.
1233 1216
1234 1217 Inputs:
1235 1218 request
1236 1219 """
1237 1220 form = madweb.forms.AdvScriptParmsFiltersForm(request.GET)
1238 1221 return render(request, 'madweb/download_adv_parms_filters_script.html', {'form': form})
1239 1222
1240 1223
1241 1224 def ftp(request):
1242 1225 """ftp creates the first ftp page listing instruments
1243 1226 """
1244 1227 madDB = madrigal.metadata.MadrigalDB()
1245 1228 bg_color = madDB.getBackgroundColor()
1246 1229 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1247 1230 siteName, siteList = madWebObj.getSiteInfo()
1248 1231 cookieDict = request.COOKIES
1249 1232 if not 'user_fullname' in cookieDict:
1250 1233 return(HttpResponse('<p>Cookie with user_fullname required for ftp</p>'))
1251 1234 fullname = django.utils.http.urlquote_plus(cookieDict['user_fullname'])
1252 1235 email = cookieDict['user_email']
1253 1236 affiliation = django.utils.http.urlquote_plus(cookieDict['user_affiliation'])
1254 1237 # create instrument with data list with tuple (instrument_name, kinst)
1255 1238 madInstDataObj = madrigal.metadata.MadrigalInstrumentData(madDB)
1256 1239 madInstList = [(instrument_name, kinst) for kinst, instrument_name, site_id in madInstDataObj.getInstruments(local=True)]
1257 1240 return render(request, 'madweb/ftp_instruments.html', {'madInstList': madInstList, 'fullname': fullname,
1258 1241 'email': email, 'affiliation':affiliation, 'site_name': siteName,
1259 1242 'site_list': siteList, 'bg_color': bg_color})
1260 1243
1261 1244
1262 1245 def ftp_instrument(request, fullname, email, affiliation, kinst):
1263 1246 """ftp_instrument creates the first ftp instrument page listing years
1264 1247 Inputs: kinst selected
1265 1248 """
1266 1249 kinst = int(kinst)
1267 1250 madDB = madrigal.metadata.MadrigalDB()
1268 1251 bg_color = madDB.getBackgroundColor()
1269 1252 madInstDataObj = madrigal.metadata.MadrigalInstrumentData(madDB)
1270 1253 madInstObj = madrigal.metadata.MadrigalInstrument(madDB)
1271 1254 inst_name = madInstObj.getInstrumentName(kinst)
1272 1255 yearList = madInstDataObj.getInstrumentYears(kinst)
1273 1256 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1274 1257 siteName, siteList = madWebObj.getSiteInfo()
1275 1258 return render(request, 'madweb/ftp_years.html',{'yearList':yearList, 'kinst':kinst,
1276 1259 'inst_name':inst_name, 'fullname': fullname,
1277 1260 'email': email, 'affiliation':affiliation,
1278 1261 'site_name': siteName, 'site_list': siteList,
1279 1262 'bg_color': bg_color })
1280 1263
1281 1264
1282 1265 def ftp_year(request, fullname, email, affiliation, kinst, year):
1283 1266 """ftp_year creates the first ftp year page listing kindats
1284 1267 Inputs: kinst selected, year selected
1285 1268 """
1286 1269 kinst = int(kinst)
1287 1270 year = int(year)
1288 1271 madDB = madrigal.metadata.MadrigalDB()
1289 1272 bg_color = madDB.getBackgroundColor()
1290 1273 madInstObj = madrigal.metadata.MadrigalInstrument(madDB)
1291 1274 inst_name = madInstObj.getInstrumentName(kinst)
1292 1275 madInstKindatObj = madrigal.metadata.MadrigalInstrumentKindats(madDB)
1293 1276 kindatList = madInstKindatObj.getKindatListForInstrumentYear(kinst, year)
1294 1277 madKindatObj = madrigal.metadata.MadrigalKindat(madDB)
1295 1278 # create kindatDescList, a list of tuples of (kindat_desc, kindat) for that kinst, year
1296 1279 kindatDescList = []
1297 1280 for kindat in kindatList:
1298 1281 kindatDescList.append((madKindatObj.getKindatDescription(kindat, kinst), kindat))
1299 1282 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1300 1283 siteName, siteList = madWebObj.getSiteInfo()
1301 1284 return render(request, 'madweb/ftp_kindats.html', {'kindatDescList': kindatDescList, 'year': year,
1302 1285 'kinst': kinst, 'inst_name':inst_name, 'fullname': fullname,
1303 1286 'email': email, 'affiliation':affiliation,
1304 1287 'site_name': siteName, 'site_list': siteList,
1305 1288 'bg_color': bg_color })
1306 1289
1307 1290
1308 1291 def ftp_kindat(request, fullname, email, affiliation, kinst, year, kindat):
1309 1292 """ftp_kindat creates the first ftp format page listing formats to choose from
1310 1293 Inputs: kinst selected, year selected, kindat selected
1311 1294 """
1312 1295 kinst = int(kinst)
1313 1296 kindat = int(kindat)
1314 1297 madDB = madrigal.metadata.MadrigalDB()
1315 1298 bg_color = madDB.getBackgroundColor()
1316 1299 madKindatObj = madrigal.metadata.MadrigalKindat(madDB)
1317 1300 kindat_desc = madKindatObj.getKindatDescription(kindat, kinst)
1318 1301 madInstObj = madrigal.metadata.MadrigalInstrument(madDB)
1319 1302 inst_name = madInstObj.getInstrumentName(kinst)
1320 1303 formatDescList = [(formatDict[key], key) for key in list(formatDict.keys())]
1321 1304 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1322 1305 siteName, siteList = madWebObj.getSiteInfo()
1323 1306 return render(request, 'madweb/ftp_formats.html', {'formatDescList': formatDescList, 'year': year,
1324 1307 'kinst': kinst, 'inst_name': inst_name, 'kindat': kindat,
1325 1308 'kindat_desc': kindat_desc, 'fullname': fullname,
1326 1309 'email': email, 'affiliation': affiliation,
1327 1310 'site_name': siteName, 'site_list': siteList,
1328 1311 'bg_color': bg_color } )
1329 1312
1330 1313
1331 1314 def ftp_files(request, fullname, email, affiliation, kinst, year, kindat, format):
1332 1315 """ftp_files creates the ftp files page listing individual files
1333 1316 Inputs: kinst selected, year selected, kindat selected
1334 1317 """
1335 1318 kinst = int(kinst)
1336 1319 year = int(year)
1337 1320 dt = datetime.datetime(year,1,1) # speed up search
1338 1321 kindat = int(kindat)
1339 1322 if format not in ('hdf5', 'netCDF4', 'ascii'):
1340 1323 raise ValueError('Unknown format %s' % (format))
1341 1324 if format == 'netCDF4':
1342 1325 thisExt = '.nc'
1343 1326 elif format == 'ascii':
1344 1327 thisExt = '.txt'
1345 1328 format_desc = formatDict[format]
1346 1329 # create a list of full names, where each item is a tuple of
1347 1330 # (fullFilename in Madrigal, output basename with correct extension, date string)
1348 1331 fileList = []
1349 1332 madDB = madrigal.metadata.MadrigalDB()
1350 1333 bg_color = madDB.getBackgroundColor()
1351 1334 madKindatObj = madrigal.metadata.MadrigalKindat(madDB)
1352 1335 kindat_desc = madKindatObj.getKindatDescription(kindat, kinst)
1353 1336 madInstObj = madrigal.metadata.MadrigalInstrument(madDB)
1354 1337 inst_name = madInstObj.getInstrumentName(kinst)
1355 1338 pi = madInstObj.getContactName(kinst)
1356 1339 pi_email = madInstObj.getContactEmail(kinst)
1357 1340 madExpObj = madrigal.metadata.MadrigalExperiment(madDB)
1358 1341 startIndex = madExpObj.getStartPosition(dt) + 1
1359 1342 for loop in (0,1):
1360 1343 # we normally only loop once, but sometimes multi-year experiments require a slow full search
1361 1344 if loop == 0:
1362 1345 thisStartIndex = startIndex
1363 1346 else:
1364 1347 thisStartIndex = 0 # should only get to this case for rare multi-year experiments
1365 1348 for i in range(thisStartIndex, madExpObj.getExpCount()):
1366 1349 if kinst != madExpObj.getKinstByPosition(i):
1367 1350 continue
1368 1351 stTuple = madExpObj.getExpStartDateTimeByPosition(i)[0:6]
1369 1352 etTuple = madExpObj.getExpEndDateTimeByPosition(i)[0:6]
1370 1353 expTitle = madExpObj.getExpNameByPosition(i)
1371 1354 sDT = datetime.datetime(*stTuple)
1372 1355 eDT = datetime.datetime(*etTuple)
1373 1356 if sDT.year > year:
1374 1357 break
1375 1358 if eDT.year < year:
1376 1359 continue
1377 1360 dateStr = ' From %s to %s: %s' % (sDT.strftime('%Y-%m-%d %H:%M:%S'), eDT.strftime('%Y-%m-%d %H:%M:%S'), str(expTitle))
1378 1361 expDir = madExpObj.getExpDirByPosition(i)
1379 1362 # look at this exp for the right kindat
1380 1363 try:
1381 1364 madFileObj = madrigal.metadata.MadrigalMetaFile(madDB, os.path.join(expDir, 'fileTab.txt'))
1382 1365 except:
1383 1366 pass
1384 1367 for j in range(madFileObj.getFileCount()):
1385 1368 if madFileObj.getCategoryByPosition(j) not in (0,1):
1386 1369 # skip history and alternate files
1387 1370 continue
1388 1371 if madFileObj.getKindatByPosition(j) != kindat:
1389 1372 continue
1390 1373 statusStr = ' : %s' % (str(madFileObj.getStatusByPosition(j)))
1391 1374 fullFilename = os.path.join(expDir, madFileObj.getFilenameByPosition(j))
1392 1375 fullBasename = os.path.basename(fullFilename)
1393 1376 if format != 'hdf5':
1394 1377 base, file_extension = os.path.splitext(fullFilename)
1395 1378 basename = os.path.basename(base + thisExt)
1396 1379 else:
1397 1380 basename = os.path.basename(fullFilename)
1398 1381 # make sure this file isn't too big to create a cache
1399 1382 file_size = os.path.getsize(fullFilename)
1400 1383 if file_size > maxSize and format != 'hdf5':
1401 1384 # make sure cached file exists before adding
1402 1385 if format == 'netCDF4':
1403 1386 cachedFile = os.path.join(expDir, 'overview', fullBasename + thisExt)
1404 1387 else:
1405 1388 cachedFile = os.path.join(expDir, 'overview', fullBasename + thisExt + '.gz')
1406 1389 if not os.path.exists(cachedFile):
1407 1390 continue
1408 1391 fileList.append((urllib.parse.quote_plus(fullFilename), basename, dateStr + statusStr))
1409 1392
1410 1393 if len(fileList) > 0:
1411 1394 break # usually we avoid the slow full loop
1412 1395
1413 1396
1414 1397 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1415 1398 siteName, siteList = madWebObj.getSiteInfo()
1416 1399
1417 1400 return render(request, 'madweb/ftp_files.html', {'fullFilenames': fileList, 'year': year, 'kindat_desc': kindat_desc,
1418 1401 'kinst': kinst, 'inst_name':inst_name, 'fullname': fullname,
1419 1402 'kindat': kindat, 'format': format, 'format_desc': format_desc,
1420 1403 'email': email, 'affiliation':affiliation,
1421 1404 'site_name': siteName, 'site_list': siteList,
1422 1405 'pi_email': pi_email, 'pi_name': pi,
1423 1406 'bg_color': bg_color})
1424 1407
1425 1408
1426 1409 def ftp_download(request, user_fullname, user_email, user_affiliation, kinst, year, kindat, format, fullHdf5Filename):
1427 1410 """ftp_download creates the first ftp kindat page listing individual files
1428 1411 Inputs: kinst selected, year selected, kindat selected
1429 1412 """
1430 1413 madDB = madrigal.metadata.MadrigalDB()
1431 1414 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1432 1415 user_fullname = urllib.parse.unquote_plus(user_fullname)
1433 1416 user_affiliation = urllib.parse.unquote_plus(user_affiliation)
1434 1417 fullHdf5Filename = urllib.parse.unquote_plus(fullHdf5Filename)
1435 1418 fullFilename = madWebObj.downloadFullFileAsIs(fullHdf5Filename, format, user_fullname, user_email, user_affiliation)
1436 1419
1437 1420 f = open(fullFilename, 'rb')
1438 1421 filename = os.path.basename(fullFilename)
1439 1422 chunk_size = 8192
1440 1423 file_type = mimetypes.guess_type(fullFilename)[0]
1441 1424 if file_type is None:
1442 1425 file_type = 'application/octet-stream'
1443 1426 response = StreamingHttpResponse(FileWrapper(f, chunk_size),
1444 1427 content_type=file_type)
1445 1428 response['Content-Length'] = os.path.getsize(fullFilename)
1446 1429 response['Content-Disposition'] = "attachment; filename=%s" % (filename)
1447 1430 return(response)
1448 1431
1449 1432
1450 1433 @csrf_exempt
1451 1434 def ftp_multiple_download(request):
1452 1435 """ftp_download creates the first ftp kindat page listing individual files
1453 1436 Inputs: kinst selected, year selected, kindat selected
1454 1437 """
1455 1438 if request.method == 'POST':
1456 1439 reqDict = request.POST
1457 1440 else:
1458 1441 reqDict = request.GET
1459 1442 madDB = madrigal.metadata.MadrigalDB()
1460 1443 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1461 1444 user_fullname = urllib.parse.unquote_plus(reqDict.get('user_fullname'))
1462 1445 user_email = reqDict.get('user_email')
1463 1446 user_affiliation = urllib.parse.unquote_plus(reqDict.get('user_affiliation'))
1464 1447 format = reqDict.get('format')
1465 1448 fileList = reqDict.getlist('fullFilename')
1466 1449 fileList = [urllib.parse.unquote_plus(filename) for filename in fileList]
1467 1450 if len(fileList) > 10:
1468 1451 # send user an email with warning
1469 1452 tmpDir = os.path.join(madDB.getMadroot(), 'experiments/stage')
1470 1453 fullFilename = os.path.join(tmpDir, 'result_error_%06i.txt' % (random.randint(0,999999)))
1471 1454 f = open(fullFilename, 'w')
1472 1455 f.write('Error - you requested %i files, maximum is 10\n' % (len(fileList)))
1473 1456 f.close()
1474 1457 else:
1475 1458 fullFilename = madWebObj.downloadMultipleFiles(fileList, format, user_fullname, user_email, user_affiliation)
1476 1459
1477 1460 f = open(fullFilename, 'rb')
1478 1461 filename = os.path.basename(fullFilename)
1479 1462 chunk_size = 8192
1480 1463 file_type = mimetypes.guess_type(fullFilename)[0]
1481 1464 if file_type is None:
1482 1465 file_type = 'application/octet-stream'
1483 1466 response = StreamingHttpResponse(FileWrapper(f, chunk_size),
1484 1467 content_type=file_type)
1485 1468 response['Content-Length'] = os.path.getsize(fullFilename)
1486 1469 response['Content-Disposition'] = "attachment; filename=%s" % (filename)
1487 1470 return(response)
1488 1471
1489 1472
1490 1473 def instrument_metadata(request):
1491 1474 """instrument_metadata returns the instrument_metadata page.
1492 1475
1493 1476 Inputs:
1494 1477 request
1495 1478 """
1496 1479 # create a list of tuples of (kinst, name, category, latitude, longitude, altitude, pi, pi_email, mnemonic)
1497 1480 madDB = madrigal.metadata.MadrigalDB()
1498 1481 bg_color = madDB.getBackgroundColor()
1499 1482 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1500 1483 siteName, siteList = madWebObj.getSiteInfo()
1501 1484 madInstObj = madrigal.metadata.MadrigalInstrument(madDB)
1502 1485 instList = []
1503 1486 for name, mnemonic, kinst, category, catID in madInstObj.getOrderedInstrumentList():
1504 1487 latitude = madInstObj.getLatitude(kinst)
1505 1488 longitude = madInstObj.getLongitude(kinst)
1506 1489 altitude = madInstObj.getAltitude(kinst)
1507 1490 pi = madInstObj.getContactName(kinst)
1508 1491 pi_email = madInstObj.getContactEmail(kinst)
1509 1492 instList.append((kinst, name, category, latitude, longitude, altitude, pi, pi_email, mnemonic))
1510 1493
1511 1494 responseDict = {'inst_active': 'class="active"', 'instList': instList,
1512 1495 'site_name': siteName, 'site_list': siteList, 'bg_color': bg_color}
1513 1496 return render(request, 'madweb/instrument_metadata.html', responseDict)
1514 1497
1515 1498
1516 1499 def site_metadata(request):
1517 1500 """site_metadata returns the site_metadata page.
1518 1501
1519 1502 Inputs:
1520 1503 request
1521 1504 """
1522 1505 # create a list of tuples of (siteId, name, url, contact, contact email, version)
1523 1506 madDB = madrigal.metadata.MadrigalDB()
1524 1507 bg_color = madDB.getBackgroundColor()
1525 1508 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1526 1509 siteName, otherSiteList = madWebObj.getSiteInfo()
1527 1510 madSiteObj = madrigal.metadata.MadrigalSite(madDB)
1528 1511 siteList = []
1529 1512 for siteId, siteName in madSiteObj.getSiteList():
1530 1513 if madSiteObj.getSiteServer(siteId).find('http') == -1:
1531 1514 url = 'http://' + os.path.join(madSiteObj.getSiteServer(siteId),
1532 1515 madSiteObj.getSiteDocRoot(siteId))
1533 1516 else:
1534 1517 url = os.path.join(madSiteObj.getSiteServer(siteId),
1535 1518 madSiteObj.getSiteDocRoot(siteId))
1536 1519 contact = madSiteObj.getSiteContactName(siteId)
1537 1520 contact_email = madSiteObj.getSiteEmail(siteId)
1538 1521 version = madSiteObj.getSiteVersion(siteId)
1539 1522 siteList.append((siteId, siteName, url, contact, contact_email, version))
1540 1523
1541 1524 responseDict = {'site_active': 'class="active"', 'siteList': siteList,
1542 1525 'site_name': siteName, 'site_list': otherSiteList, 'bg_color': bg_color}
1543 1526 return render(request, 'madweb/site_metadata.html', responseDict)
1544 1527
1545 1528
1546 1529 def parameter_metadata(request):
1547 1530 """parameter_metadata returns the site_metadata page.
1548 1531
1549 1532 Inputs:
1550 1533 request
1551 1534 """
1552 1535 madDB = madrigal.metadata.MadrigalDB()
1553 1536 bg_color = madDB.getBackgroundColor()
1554 1537 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1555 1538 siteName, siteList = madWebObj.getSiteInfo()
1556 1539 madParmObj = madrigal.data.MadrigalParameters(madDB)
1557 1540 madParmCatObj = madrigal.metadata.MadrigalParmCategory(madDB)
1558 1541 parmDict = {} # key is category string, value is list of category tuples (mnemonic, description, units, code)
1559 1542 parmList = [] # list of tuples, each tuple either a single category, or (mnemonic, description, units, code)
1560 1543 categoryList = []
1561 1544 categoryUrlList = []
1562 1545 for mnemonic in madParmObj.getSortedMnemonicList():
1563 1546 description = madParmObj.getSimpleParmDescription(mnemonic)
1564 1547 units = madParmObj.getParmUnits(mnemonic)
1565 1548 code = madParmObj.getParmCodeFromMnemonic(mnemonic)
1566 1549 category = madParmObj.getParmCategory(mnemonic)
1567 1550 if category is None:
1568 1551 # deprecated prolog parm
1569 1552 continue
1570 1553 if category in list(parmDict.keys()):
1571 1554 parmDict[category].append((mnemonic, description, units, code))
1572 1555 else:
1573 1556 parmDict[category] = [(mnemonic, description, units, code)]
1574 1557
1575 1558 # now loop through all categories
1576 1559 for thisCategory, catId in madParmCatObj.getCategoryList():
1577 1560 parmList.append((thisCategory,))
1578 1561 categoryList.append(thisCategory)
1579 1562 categoryAnchor = thisCategory.replace(' ','_')
1580 1563 categoryUrlList.append('<a href="#%s">%s</a>' % (categoryAnchor, thisCategory))
1581 1564 for values in parmDict[thisCategory]:
1582 1565 parmList.append(values)
1583 1566
1584 1567 responseDict = {'parm_active': 'class="active"', 'parmList': parmList,
1585 1568 'categoryUrlList':categoryUrlList,
1586 1569 'site_name': siteName, 'site_list': siteList, 'bg_color': bg_color}
1587 1570 return render(request, 'madweb/parameter_metadata.html', responseDict)
1588 1571
1589 1572
1590 1573 def kindat_metadata(request):
1591 1574 """kindat_metadata returns the kindat_metadata page.
1592 1575
1593 1576 Inputs:
1594 1577 request
1595 1578 """
1596 1579 # create a list of tuples of (kindat, description, kinst, instrument_name)
1597 1580 madDB = madrigal.metadata.MadrigalDB()
1598 1581 bg_color = madDB.getBackgroundColor()
1599 1582 madKindatObj = madrigal.metadata.MadrigalKindat(madDB)
1600 1583 madInstObj = madrigal.metadata.MadrigalInstrument(madDB)
1601 1584 madInstKindatObj = madrigal.metadata.MadrigalInstrumentKindats(madDB)
1602 1585 # create a dict of key = kindat code, value list of associated instruments
1603 1586 kindatDict = {}
1604 1587 for name, mnem, kinst in madInstObj.getInstrumentList():
1605 1588 thisKindatList = madInstKindatObj.getKindatListForInstruments(kinst)
1606 1589 for kindat in thisKindatList:
1607 1590 if kindat not in kindatDict:
1608 1591 kindatDict[kindat] = [kinst]
1609 1592 else:
1610 1593 kindatDict[kindat].append(kinst)
1611 1594
1612 1595 kindatList = []
1613 1596 for description, code_str in madKindatObj.getKindatList():
1614 1597 try:
1615 1598 kinst, kindat = code_str.split('_')
1616 1599 instName = madInstObj.getInstrumentName(int(kinst))
1617 1600 except:
1618 1601 kindat = code_str
1619 1602 try:
1620 1603 kinst = str(kindatDict[int(kindat)][0])
1621 1604 instName = madInstObj.getInstrumentName(int(kinst))
1622 1605 except KeyError:
1623 1606 kinst = '-'
1624 1607 instName = 'Unspecified'
1625 1608 kindatList.append((kindat, description, kinst, instName))
1626 1609 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1627 1610 siteName, siteList = madWebObj.getSiteInfo()
1628 1611
1629 1612 responseDict = {'kindat_active': 'class="active"', 'kindatList': kindatList,
1630 1613 'site_name': siteName, 'site_list': siteList, 'bg_color': bg_color}
1631 1614 return render(request, 'madweb/kindat_metadata.html', responseDict)
1632 1615
1633 1616
1634 1617 def madrigal_calculator(request):
1635 1618 """madrigal_calculator returns the Madrigal Calculator page.
1636 1619
1637 1620 Inputs:
1638 1621 request
1639 1622 """
1640 1623 madDB = madrigal.metadata.MadrigalDB()
1641 1624 bg_color = madDB.getBackgroundColor()
1642 1625 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1643 1626 siteName, siteList = madWebObj.getSiteInfo()
1644 1627 # original blank form
1645 1628 madCalculatorForm = madweb.forms.MadCalculatorForm()
1646 1629 parmList = [(parm, madCalculatorForm.parmDescDict[parm]) for parm in list(madCalculatorForm.parmDescDict.keys())]
1647 1630 return render(request, 'madweb/madrigal_calculator.html', {'madCalculator_active': 'class="active"',
1648 1631 'form': madCalculatorForm,
1649 1632 'parmList': parmList,
1650 1633 'site_name': siteName, 'site_list': siteList,
1651 1634 'bg_color': bg_color, 'datetime': True})
1652 1635
1653 1636 def madrigal_calculator_output(request):
1654 1637 """madrigal_calculator returns the output from the Madrigal Calculator page.
1655 1638
1656 1639 Inputs:
1657 1640 request
1658 1641 """
1659 1642 madDB = madrigal.metadata.MadrigalDB()
1660 1643 bg_color = madDB.getBackgroundColor()
1661 1644 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1662 1645 siteName, siteList = madWebObj.getSiteInfo()
1663 1646
1664 1647 madCalculatorForm = madweb.forms.MadCalculatorForm(request.GET)
1665 1648
1666 1649 try:
1667 1650 if not madCalculatorForm.is_valid():
1668 1651 return(HttpResponse(str(madCalculatorForm.errors)))
1669 1652 except KeyError:
1670 1653 return(HttpResponse('<p>Missing arguments in madCalculatorOutput</p>'))
1671 1654
1672 1655 text = madWebObj.runMadrigalCalculatorFromForm(madCalculatorForm.cleaned_data)
1673 1656
1674 1657 return render(request, 'madweb/madrigal_calculator_output.html', {'madCalculator_active': 'class="active"',
1675 1658 'text': text,
1676 1659 'site_name': siteName, 'site_list': siteList,
1677 1660 'bg_color': bg_color})
1678 1661
1679 1662
1680 1663 def get_metadata(request):
1681 1664 """get_metadata allows local metadata files to be downloaded.
1682 1665
1683 1666 Inputs:
1684 1667 request
1685 1668 """
1686 1669 fileDict = {'0':'expTab.txt',
1687 1670 '1': 'fileTab.txt',
1688 1671 '3': 'instTab.txt',
1689 1672 '4': 'parmCodes.txt',
1690 1673 '5': 'siteTab.txt',
1691 1674 '6': 'typeTab.txt',
1692 1675 '7': 'instKindatTab.txt',
1693 1676 '8': 'instParmTab.txt',
1694 1677 '9': 'madCatTab.txt',
1695 1678 '10': 'instType.txt'}
1696 1679 form = madweb.forms.GetMetadataForm(request.GET)
1697 1680 if form.is_valid():
1698 1681 madDB = madrigal.metadata.MadrigalDB()
1699 1682 downloadFile = os.path.join(madDB.getMetadataDir(),
1700 1683 fileDict[form.cleaned_data['fileType']])
1701 1684
1702 1685
1703 1686 f = open(downloadFile, 'rb')
1704 1687 filename = os.path.basename(downloadFile)
1705 1688 chunk_size = 8192
1706 1689 response = StreamingHttpResponse(FileWrapper(f, chunk_size),
1707 1690 content_type=mimetypes.guess_type(downloadFile)[0])
1708 1691 response['Content-Length'] = os.path.getsize(downloadFile)
1709 1692 response['Content-Disposition'] = "attachment; filename=%s" % (filename)
1710 1693 return(response)
1711 1694
1712 1695 else:
1713 1696 madDB = madrigal.metadata.MadrigalDB()
1714 1697 bg_color = madDB.getBackgroundColor()
1715 1698 form = madweb.forms.GetMetadataForm()
1716 1699 return render(request, 'madweb/get_metadata.html', {'form': form, 'bg_color': bg_color})
1717 1700
1718 1701
1719 1702 def looker_main(request):
1720 1703 """looker_main loads the main looker selection form.
1721 1704
1722 1705 Inputs:
1723 1706 request
1724 1707 """
1725 1708 madDB = madrigal.metadata.MadrigalDB()
1726 1709 bg_color = madDB.getBackgroundColor()
1727 1710 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1728 1711 siteName, siteList = madWebObj.getSiteInfo()
1729 1712 lookerSelectForm = madweb.forms.LookerSelectForm()
1730 1713 return render(request, 'madweb/looker_main.html', {'looker_active': 'class="active"',
1731 1714 'form': lookerSelectForm,
1732 1715 'site_name': siteName, 'site_list': siteList,
1733 1716 'bg_color': bg_color})
1734 1717
1735 1718
1736 1719 def looker_form(request):
1737 1720 """looker_form loads the appropriate looker form.
1738 1721
1739 1722 Inputs:
1740 1723 request
1741 1724 """
1742 1725 madDB = madrigal.metadata.MadrigalDB()
1743 1726 bg_color = madDB.getBackgroundColor()
1744 1727 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1745 1728 siteName, siteList = madWebObj.getSiteInfo()
1746 1729 if not 'looker_options' in request.GET:
1747 1730 return(HttpResponse('<p>looker form requires looker_options</p>'))
1748 1731 form = madweb.forms.LookerSelectForm(request.GET)
1749 1732 if form.is_valid():
1750 1733 option = form.cleaned_data['looker_options']
1751 1734 if option == '1':
1752 1735 form = madweb.forms.LookerGeodeticRadar()
1753 1736 return render(request, 'madweb/looker_geodetic_to_radar.html', {'looker_active': 'class="active"',
1754 1737 'form': form,
1755 1738 'site_name': siteName, 'site_list': siteList,
1756 1739 'bg_color': bg_color})
1757 1740 elif option == '2':
1758 1741 form = madweb.forms.LookerGeomagRadar()
1759 1742 return render(request, 'madweb/looker_geomagnetic_to_radar.html', {'looker_active': 'class="active"',
1760 1743 'form': form,
1761 1744 'site_name': siteName, 'site_list': siteList,
1762 1745 'bg_color': bg_color})
1763 1746 elif option == '3':
1764 1747 form = madweb.forms.LookerGeomagFromGeodetic()
1765 1748 return render(request, 'madweb/looker_geomagnetic_from_geodetic.html', {'looker_active': 'class="active"',
1766 1749 'form': form,
1767 1750 'site_name': siteName, 'site_list': siteList,
1768 1751 'bg_color': bg_color})
1769 1752 elif option == '4':
1770 1753 form = madweb.forms.LookerGeomagFromRadar()
1771 1754 return render(request, 'madweb/looker_geomagnetic_from_radar.html', {'looker_active': 'class="active"',
1772 1755 'form': form,
1773 1756 'site_name': siteName, 'site_list': siteList,
1774 1757 'bg_color': bg_color})
1775 1758 elif option == '5':
1776 1759 form = madweb.forms.LookerFieldLineFromRadar()
1777 1760 return render(request, 'madweb/looker_field_line_from_radar.html', {'looker_active': 'class="active"',
1778 1761 'form': form,
1779 1762 'site_name': siteName, 'site_list': siteList,
1780 1763 'bg_color': bg_color})
1781 1764 elif option == '6':
1782 1765 form = madweb.forms.LookerFieldLineFromGeodetic()
1783 1766 return render(request, 'madweb/looker_field_line_from_geodetic.html', {'looker_active': 'class="active"',
1784 1767 'form': form,
1785 1768 'site_name': siteName, 'site_list': siteList,
1786 1769 'bg_color': bg_color})
1787 1770 elif option == '7':
1788 1771 form = madweb.forms.LookerFieldLineFromApex()
1789 1772 return render(request, 'madweb/looker_field_line_from_apex.html', {'looker_active': 'class="active"',
1790 1773 'form': form,
1791 1774 'site_name': siteName, 'site_list': siteList,
1792 1775 'bg_color': bg_color})
1793 1776 elif option == '8':
1794 1777 form = madweb.forms.LookerConjugateFromGeodetic()
1795 1778 return render(request, 'madweb/looker_conjugate_from_geodetic.html', {'looker_active': 'class="active"',
1796 1779 'form': form,
1797 1780 'site_name': siteName, 'site_list': siteList,
1798 1781 'bg_color': bg_color,
1799 1782 'datetime': True})
1800 1783 else:
1801 1784 raise ValueError(str(form.errors))
1802 1785
1803 1786
1804 1787 def looker_output(request):
1805 1788 """looker_output loads the appropriate looker output.
1806 1789
1807 1790 Inputs:
1808 1791 request
1809 1792 """
1810 1793 madDB = madrigal.metadata.MadrigalDB()
1811 1794 bg_color = madDB.getBackgroundColor()
1812 1795 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1813 1796 siteName, siteList = madWebObj.getSiteInfo()
1814 1797
1815 1798 if not 'looker_options' in request.GET:
1816 1799 return(HttpResponse('<p>looker missing arguments</p>'))
1817 1800
1818 1801 if request.GET['looker_options'] == "1":
1819 1802 form = madweb.forms.LookerGeodeticRadar(request.GET)
1820 1803 if form.is_valid():
1821 1804 text = madWebObj.runLookerFromForm(form.cleaned_data)
1822 1805 return render(request, 'madweb/looker_output.html', {'looker_active': 'class="active"',
1823 1806 'type': 'Az, El, Range to Geodetic points',
1824 1807 'text': text,
1825 1808 'site_name': siteName, 'site_list': siteList,
1826 1809 'bg_color': bg_color})
1827 1810 else:
1828 1811 raise ValueError(str(form.errors))
1829 1812 elif request.GET['looker_options'] == "2":
1830 1813 form = madweb.forms.LookerGeomagRadar(request.GET)
1831 1814 if form.is_valid():
1832 1815 text = madWebObj.runLookerFromForm(form.cleaned_data)
1833 1816 return render(request, 'madweb/looker_output.html', {'looker_active': 'class="active"',
1834 1817 'type': 'Az, El, Range to Geomagnetic (apex) points',
1835 1818 'text': text,
1836 1819 'site_name': siteName, 'site_list': siteList,
1837 1820 'bg_color': bg_color})
1838 1821 else:
1839 1822 raise ValueError(str(form.errors))
1840 1823 elif request.GET['looker_options'] == "3":
1841 1824 form = madweb.forms.LookerGeomagFromGeodetic(request.GET)
1842 1825 if form.is_valid():
1843 1826 text = madWebObj.runLookerFromForm(form.cleaned_data)
1844 1827 return render(request, 'madweb/looker_output.html', {'looker_active': 'class="active"',
1845 1828 'type': 'Apex Geomagnetic coordinates from Geodetic grid',
1846 1829 'text': text,
1847 1830 'site_name': siteName, 'site_list': siteList,
1848 1831 'bg_color': bg_color})
1849 1832 else:
1850 1833 raise ValueError(str(form.errors))
1851 1834 elif request.GET['looker_options'] == "4":
1852 1835 form = madweb.forms.LookerGeomagFromRadar(request.GET)
1853 1836 if form.is_valid():
1854 1837 text = madWebObj.runLookerFromForm(form.cleaned_data)
1855 1838 return render(request, 'madweb/looker_output.html', {'looker_active': 'class="active"',
1856 1839 'type': 'Apex Geomagnetic and geodetic coordinates and aspect angle from a grid of azimuth, elevation, and range',
1857 1840 'text': text,
1858 1841 'site_name': siteName, 'site_list': siteList,
1859 1842 'bg_color': bg_color})
1860 1843 else:
1861 1844 raise ValueError(str(form.errors))
1862 1845 elif request.GET['looker_options'] == "5":
1863 1846 form = madweb.forms.LookerFieldLineFromRadar(request.GET)
1864 1847 if form.is_valid():
1865 1848 text = madWebObj.runLookerFromForm(form.cleaned_data)
1866 1849 return render(request, 'madweb/looker_output.html', {'looker_active': 'class="active"',
1867 1850 'type': 'Field line coordinates for a field line set by radar parameters',
1868 1851 'text': text,
1869 1852 'site_name': siteName, 'site_list': siteList,
1870 1853 'bg_color': bg_color})
1871 1854 else:
1872 1855 raise ValueError(str(form.errors))
1873 1856 elif request.GET['looker_options'] == "6":
1874 1857 form = madweb.forms.LookerFieldLineFromGeodetic(request.GET)
1875 1858 if form.is_valid():
1876 1859 text = madWebObj.runLookerFromForm(form.cleaned_data)
1877 1860 return render(request, 'madweb/looker_output.html', {'looker_active': 'class="active"',
1878 1861 'type': 'Field line coordinates and radar look parameters for given field line',
1879 1862 'text': text,
1880 1863 'site_name': siteName, 'site_list': siteList,
1881 1864 'bg_color': bg_color})
1882 1865 else:
1883 1866 raise ValueError(str(form.errors))
1884 1867 elif request.GET['looker_options'] == "7":
1885 1868 form = madweb.forms.LookerFieldLineFromApex(request.GET)
1886 1869 if form.is_valid():
1887 1870 text = madWebObj.runLookerFromForm(form.cleaned_data)
1888 1871 return render(request, 'madweb/looker_output.html', {'looker_active': 'class="active"',
1889 1872 'type': 'Field line coordinates and radar look parameters for given field line',
1890 1873 'text': text,
1891 1874 'site_name': siteName, 'site_list': siteList,
1892 1875 'bg_color': bg_color})
1893 1876 else:
1894 1877 raise ValueError(str(form.errors))
1895 1878 elif request.GET['looker_options'] == "8":
1896 1879 form = madweb.forms.LookerConjugateFromGeodetic(request.GET)
1897 1880 if form.is_valid():
1898 1881 text = madWebObj.runLookerFromForm(form.cleaned_data)
1899 1882 return render(request, 'madweb/looker_output.html', {'looker_active': 'class="active"',
1900 1883 'type': 'Point/Magnetic Conjugate Point vs Latitude, Longitude, Altitude',
1901 1884 'datetime': form.cleaned_data['datetime'],
1902 1885 'text': text,
1903 1886 'site_name': siteName, 'site_list': siteList,
1904 1887 'bg_color': bg_color})
1905 1888 else:
1906 1889 raise ValueError(str(form.errors))
1907 1890
1908 1891 else:
1909 1892 raise ValueError('Unknown looker_option <%s>' % (str(request.GET['looker_options'])))
1910 1893
1911 1894
1912 1895
1913 1896 def get_version_service(request):
1914 1897 """get_version_service runs the getVersionService.py service.
1915 1898
1916 1899 Inputs:
1917 1900 request (ignored)
1918 1901
1919 1902 Returns a single line of text, with the version in the form <major_version_int>.<minor_version_int>[.<sub_version_int>]
1920 1903 """
1921 1904 madDB = madrigal.metadata.MadrigalDB()
1922 1905 siteID = madDB.getSiteID()
1923 1906 madSiteObj = madrigal.metadata.MadrigalSite(madDB)
1924 1907 return(HttpResponse(madSiteObj.getSiteVersion(siteID)))
1925 1908
1926 1909
1927 1910
1928 1911 def get_instruments_service(request):
1929 1912 """get_instruments_service runs the getInstrumentsService.py service.
1930 1913
1931 1914 Inputs:
1932 1915 request (ignored)
1933 1916
1934 1917 Returns comma-delimited data, one line for each experiment, with the following fields:
1935 1918
1936 1919 1. instrument.name Example: 'Millstone Hill Incoherent Scatter Radar'
1937 1920
1938 1921 2. instrument.code Example: 30
1939 1922
1940 1923 3. instrument.mnemonic (3 char string) Example: 'mlh'
1941 1924
1942 1925 4. instrument.latitude Example: 45.0
1943 1926
1944 1927 5. instrument.longitude Example: 110.0
1945 1928
1946 1929 6. instrument.altitude Example: 0.015 (km)
1947 1930
1948 1931 7. instrument.category Example: 'Incoherent Scatter Radars'
1949 1932
1950 1933 8. contact name
1951 1934
1952 1935 9. contact email
1953 1936 """
1954 1937 # create MadrigalDB obj
1955 1938 madDBObj = madrigal.metadata.MadrigalDB()
1956 1939
1957 1940 # create MadrigalInstument object
1958 1941 madInst = madrigal.metadata.MadrigalInstrument(madDBObj)
1959 1942
1960 1943 # get instrument list
1961 1944 instList = madInst.getInstrumentList()
1962 1945
1963 1946 # loop through each instrument
1964 1947 instStr = ''
1965 1948 for inst in instList:
1966 1949 name = inst[0]
1967 1950 code = inst[2]
1968 1951 mnemonic = inst[1]
1969 1952 latitude = madInst.getLatitude(code)
1970 1953 if latitude == None:
1971 1954 latitude = 0.0
1972 1955 longitude = madInst.getLongitude(code)
1973 1956 if longitude == None:
1974 1957 longitude = 0.0
1975 1958 altitude = madInst.getAltitude(code)
1976 1959 if altitude == None:
1977 1960 altitude = 0.0
1978 1961 category = madInst.getCategory(code)
1979 1962 if category == None:
1980 1963 category = ''
1981 1964 # print data
1982 1965 contactName = madInst.getContactName(code)
1983 1966 contactEmail = madInst.getContactEmail(code)
1984 1967 instStr += '%s,%i,%s,%f,%f,%f,%s,%s,%s\n' % (name,
1985 1968 code,
1986 1969 mnemonic,
1987 1970 latitude,
1988 1971 longitude,
1989 1972 altitude,
1990 1973 category,
1991 1974 str(contactName),
1992 1975 str(contactEmail))
1993 1976
1994 1977 return render(request, 'madweb/service.html', {'text': instStr})
1995 1978
1996 1979
1997 1980 def get_experiments_service(request):
1998 1981 """get_experiments_service runs the getExperimentsService.py service.
1999 1982
2000 1983 Inputs:
2001 1984 request/url - contains arguments:
2002 1985
2003 1986 code - one or more kindat values
2004 1987
2005 1988 startyear, startmonth, startday, starthour, startmin, startsec
2006 1989
2007 1990 endyear, endmonth, endday, endhour, endmin, endsec
2008 1991
2009 1992 local (defaults to True)
2010 1993
2011 1994 Returns comma-delimited data, one line for each experiment, with the following fields:
2012 1995
2013 1996 1. experiment.id (int) Example: 10000111
2014 1997
2015 1998 2. experiment.url (string) Example: 'http://www.haystack.mit.edu/cgi-bin/madtoc/1997/mlh/03dec97'
2016 1999
2017 2000 3. experiment.name (string) Example: 'Wide Latitude Substorm Study'
2018 2001
2019 2002 4. experiment.siteid (int) Example: 1
2020 2003
2021 2004 5. experiment.sitename (string) Example: 'Millstone Hill Observatory'
2022 2005
2023 2006 6. experiment.instcode (int) Code of instrument. Example: 30
2024 2007
2025 2008 7. experiment.instname (string) Instrument name. Example: 'Millstone Hill Incoherent Scatter Radar'
2026 2009
2027 2010 8. experiment.start year (int) year of experiment start
2028 2011
2029 2012 9. experiment.start month (int) month of experiment start
2030 2013
2031 2014 10. experiment.start day (int) day of experiment start
2032 2015
2033 2016 11. experiment.start hour (int) hour of experiment start
2034 2017
2035 2018 12. experiment.start minute (int) min of experiment start
2036 2019
2037 2020 13. experiment.start second (int) sec of experiment start
2038 2021
2039 2022 14. experiment.end year (int) year of experiment end
2040 2023
2041 2024 15. experiment.end month (int) month of experiment end
2042 2025
2043 2026 16. experiment.end day (int) day of experiment end
2044 2027
2045 2028 17. experiment.end hour (int) hour of experiment end
2046 2029
2047 2030 18. experiment.end minute (int) min of experiment end
2048 2031
2049 2032 19. experiment.end second (int) sec of experiment end
2050 2033
2051 2034 20. experiment.isLocal (int) 1 if local, 0 if not
2052 2035
2053 2036 21.experiment.PI (string) Experiment PI name Example: 'Phil Erickson'
2054 2037
2055 2038 22. experiment.PIEmail (string) Experiment PI email Example: 'perickson@haystack.mit.edu'
2056 2039
2057 2040 23. utc timestamp of last update to experiment
2058 2041
2059 2042 24. security value
2060 2043
2061 2044 """
2062 2045 codeList = request.GET.getlist('code')
2063 2046 codeList = [int(code) for code in codeList]
2064 2047 startyear = int(request.GET['startyear'])
2065 2048 startmonth = int(request.GET['startmonth'])
2066 2049 startday = int(request.GET['startday'])
2067 2050 starthour = int(request.GET['starthour'])
2068 2051 startmin = int(request.GET['startmin'])
2069 2052 startsec = int(request.GET['startsec'])
2070 2053 endyear = int(request.GET['endyear'])
2071 2054 endmonth = int(request.GET['endmonth'])
2072 2055 endday = int(request.GET['endday'])
2073 2056 endhour = int(request.GET['endhour'])
2074 2057 endmin = int(request.GET['endmin'])
2075 2058 endsec = int(request.GET['endsec'])
2076 2059 try:
2077 2060 local = int(request.GET['local'])
2078 2061 except:
2079 2062 local = 1
2080 2063
2081 2064
2082 2065 # if startsec or endsec in (60, 61), handle correctly
2083 2066 if startsec in (60, 61):
2084 2067 tmpTime = datetime.datetime(startyear,
2085 2068 startmonth,
2086 2069 startday,
2087 2070 starthour,
2088 2071 startmin,
2089 2072 59)
2090 2073 tmpTime += datetime.timedelta(0, startsec - 59)
2091 2074 startyear = tmpTime.year
2092 2075 startmonth = tmpTime.month
2093 2076 startday = tmpTime.day
2094 2077 starthour = tmpTime.hour
2095 2078 startmin = tmpTime.minute
2096 2079 startsec = tmpTime.second
2097 2080
2098 2081 if endsec in (60, 61):
2099 2082 tmpTime = datetime.datetime(endyear,
2100 2083 endmonth,
2101 2084 endday,
2102 2085 endhour,
2103 2086 endmin,
2104 2087 59)
2105 2088 tmpTime += datetime.timedelta(0, endsec - 59)
2106 2089 endyear = tmpTime.year
2107 2090 endmonth = tmpTime.month
2108 2091 endday = tmpTime.day
2109 2092 endhour = tmpTime.hour
2110 2093 endmin = tmpTime.minute
2111 2094 endsec = tmpTime.second
2112 2095
2113 2096 # if codeList is empty or contains 0, change it to only contain 0
2114 2097 if len(codeList) == 0 or 0 in codeList:
2115 2098 codeList = [0]
2116 2099
2117 2100 retStr = ''
2118 2101
2119 2102 # create MadrigalDB obj
2120 2103 madDBObj = madrigal.metadata.MadrigalDB()
2121 2104
2122 2105 # get the local site id
2123 2106 localSiteId = madDBObj.getSiteID()
2124 2107
2125 2108 # create MadrigalInstrument obj to convert kinst to instrument names
2126 2109 madInstObj = madrigal.metadata.MadrigalInstrument(madDBObj)
2127 2110
2128 2111 # create MadrigalSite obj to convert site id to site name
2129 2112 madSiteObj = madrigal.metadata.MadrigalSite(madDBObj)
2130 2113
2131 2114 madWebObj = madrigal.ui.web.MadrigalWeb(madDBObj)
2132 2115 trusted = madWebObj.isTrusted()
2133 2116
2134 2117 # create starttime for filter, if possible
2135 2118 if startyear != None:
2136 2119 startTimeFilter = datetime.datetime(startyear,
2137 2120 startmonth,
2138 2121 startday,
2139 2122 starthour,
2140 2123 startmin,
2141 2124 startsec)
2142 2125 else:
2143 2126 startTimeFilter = None
2144 2127
2145 2128 # create endtime for filter, if possible
2146 2129 if endyear != None:
2147 2130 endTimeFilter = datetime.datetime(endyear,
2148 2131 endmonth,
2149 2132 endday,
2150 2133 endhour,
2151 2134 endmin,
2152 2135 endsec)
2153 2136 else:
2154 2137 endTimeFilter = None
2155 2138
2156 2139 # create MadrigalExperiments for local or all files
2157 2140 if local == 1:
2158 2141 madExpObj = madrigal.metadata.MadrigalExperiment(madDBObj)
2159 2142 else:
2160 2143 # use file expTabAll.txt to get all experiments
2161 2144 filename = madDBObj.getMadroot()
2162 2145 if filename[-1] != '/':
2163 2146 filename += '/'
2164 2147 filename += 'metadata/expTabAll.txt'
2165 2148 madExpObj = madrigal.metadata.MadrigalExperiment(madDBObj, filename)
2166 2149
2167 2150 madExpObj.sortByDateSite()
2168 2151
2169 2152
2170 2153 # loop through the data
2171 2154 if not startTimeFilter is None:
2172 2155 position = madExpObj.getStartPosition(startTimeFilter)
2173 2156 else:
2174 2157 position = 0
2175 2158 while(True):
2176 2159 thisId = madExpObj.getExpIdByPosition(position)
2177 2160 # check for end
2178 2161 if thisId == None:
2179 2162 break
2180 2163 thisUrl = madExpObj.getExpUrlByPosition(position)
2181 2164 thisName = madExpObj.getExpNameByPosition(position)
2182 2165 thisSiteId = madExpObj.getExpSiteIdByPosition(position)
2183 2166 thisSiteName = madSiteObj.getSiteName(thisSiteId)
2184 2167 thisInstCode = madExpObj.getKinstByPosition(position)
2185 2168 thisInstName =madInstObj.getInstrumentName(thisInstCode)
2186 2169 thisStart = madExpObj.getExpStartDateTimeByPosition(position)
2187 2170 thisEnd = madExpObj.getExpEndDateTimeByPosition(position)
2188 2171 thisSecurity = madExpObj.getSecurityByPosition(position)
2189 2172 if thisSiteId == localSiteId:
2190 2173 thisLocal = 1
2191 2174 else:
2192 2175 thisLocal = 0
2193 2176 thisPI = madExpObj.getPIByPosition(position)
2194 2177 if thisPI in (None, ''):
2195 2178 thisPI = madInstObj.getContactName(thisInstCode)
2196 2179 thisPIEmail = madExpObj.getPIEmailByPosition(position)
2197 2180 if thisPIEmail in (None, ''):
2198 2181 thisPIEmail = madInstObj.getContactEmail(thisInstCode)
2199 2182 expDir = madExpObj.getExpDirByPosition(position)
2200 2183
2201 2184 position += 1
2202 2185
2203 2186 # some experiments set the end of the day to 24:00:00 - not
2204 2187 # technically correct - reset to 23:59:59
2205 2188
2206 2189 if (thisStart[3] == 24 and thisStart[4] == 0 and thisStart[5] == 0):
2207 2190 thisStart[3] = 23
2208 2191 thisStart[4] = 59
2209 2192 thisStart[5] = 59
2210 2193
2211 2194 if (thisEnd[3] == 24 and thisEnd[4] == 0 and thisEnd[5] == 0):
2212 2195 thisEnd[3] = 23
2213 2196 thisEnd[4] = 59
2214 2197 thisEnd[5] = 59
2215 2198
2216 2199 # apply filters
2217 2200
2218 2201 # first apply instrument code filter
2219 2202 if codeList[0] != 0:
2220 2203 if thisInstCode not in codeList:
2221 2204 continue
2222 2205
2223 2206 # apply starttime and endtime filters
2224 2207 thisStartTime = datetime.datetime(thisStart[0],
2225 2208 thisStart[1],
2226 2209 thisStart[2],
2227 2210 thisStart[3],
2228 2211 thisStart[4],
2229 2212 thisStart[5])
2230 2213
2231 2214 thisEndTime = datetime.datetime(thisEnd[0],
2232 2215 thisEnd[1],
2233 2216 thisEnd[2],
2234 2217 thisEnd[3],
2235 2218 thisEnd[4],
2236 2219 thisEnd[5])
2237 2220
2238 2221 if startTimeFilter != None:
2239 2222 if thisEndTime < startTimeFilter:
2240 2223 continue
2241 2224
2242 2225 if endTimeFilter != None:
2243 2226 if thisStartTime > endTimeFilter:
2244 2227 continue
2245 2228
2246 2229 # apply local filer
2247 2230 if local == 1 and thisLocal == 0:
2248 2231 continue
2249 2232
2250 2233 # apply security filter
2251 2234 if trusted == 0 and thisSecurity not in (0,2):
2252 2235 continue
2253 2236
2254 2237 # create exp timestamp
2255 2238 if local == 1:
2256 2239 thisUTTimestamp = int(os.stat(expDir).st_mtime + time.timezone)
2257 2240 else:
2258 2241 thisUTTimestamp = 0
2259 2242
2260 2243 # add this experiment
2261 2244 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' % \
2262 2245 (thisId,
2263 2246 thisUrl,
2264 2247 thisName,
2265 2248 thisSiteId,
2266 2249 thisSiteName,
2267 2250 thisInstCode,
2268 2251 thisInstName,
2269 2252 thisStart[0],
2270 2253 thisStart[1],
2271 2254 thisStart[2],
2272 2255 thisStart[3],
2273 2256 thisStart[4],
2274 2257 thisStart[5],
2275 2258 thisEnd[0],
2276 2259 thisEnd[1],
2277 2260 thisEnd[2],
2278 2261 thisEnd[3],
2279 2262 thisEnd[4],
2280 2263 thisEnd[5],
2281 2264 thisLocal,
2282 2265 str(thisPI),
2283 2266 str(thisPIEmail),
2284 2267 thisUTTimestamp,
2285 2268 thisSecurity)
2286 2269
2287 2270 return render(request, 'madweb/service.html', {'text': retStr})
2288 2271
2289 2272
2290 2273 def get_experiment_files_service(request):
2291 2274 """get_experiment_files_service runs the getExperimentFilesService.py service.
2292 2275
2293 2276 Inputs:
2294 2277 request/url - contains arguments:
2295 2278
2296 2279 id - local experiment id
2297 2280
2298 2281 Returns comma-delimited data, one line for each experiment file, with the following fields:
2299 2282
2300 2283 1. file.name (string) Example '/opt/mdarigal/blah/mlh980120g.001'
2301 2284
2302 2285 2. file.kindat (int) Kindat code. Example: 3001
2303 2286
2304 2287 3. file.kindat desc (string) Kindat description: Example 'Basic Derived Parameters'
2305 2288
2306 2289 4. file.category (int) (1=default, 2=variant, 3=history, 4=real-time)
2307 2290
2308 2291 5. file.status (string)('preliminary', 'final', or any other description)
2309 2292
2310 2293 6. file.permission (int) 0 for public, 1 for private. For now will not return private files.
2311 2294
2312 2295 7. file DOI (string) - citable url to file
2313 2296
2314 2297 Returns empty string if experiment id not found. Skips files that are not Hdf5
2315 2298 """
2316 2299 id = int(request.GET['id'])
2317 2300
2318 2301 # create MadrigalDB obj
2319 2302 madDBObj = madrigal.metadata.MadrigalDB()
2320 2303
2321 2304 # create MadrigalExperiments object to get full file name
2322 2305 madExpObj = madrigal.metadata.MadrigalExperiment(madDBObj)
2323 2306
2324 2307 # create Madrigal Kindat to get Kindat descriptions
2325 2308 madKindatObj = madrigal.metadata.MadrigalKindat(madDBObj)
2326 2309
2327 2310 madWebObj = madrigal.ui.web.MadrigalWeb(madDBObj)
2328 2311 trusted = madWebObj.isTrusted()
2329 2312
2330 2313
2331 2314 retStr = ''
2332 2315 thisUrl = madExpObj.getExpUrlByExpId(id)
2333 2316 if thisUrl is None:
2334 2317 raise IOError('No such id: %i' % (id))
2335 2318 expPath = madExpObj.getExpDirByExpId(id)
2336 2319 kinst = madExpObj.getKinstByExpId(id)
2337 2320 if os.access(os.path.join(expPath, 'fileTab.txt'), os.R_OK):
2338 2321 madFileObj = madrigal.metadata.MadrigalMetaFile(madDBObj, os.path.join(expPath, 'fileTab.txt'))
2339 2322 for i in range(madFileObj.getFileCount()):
2340 2323 basename = madFileObj.getFilenameByPosition(i)
2341 2324 name = os.path.join(expPath, basename)
2342 2325 base_filename, file_extension = os.path.splitext(name)
2343 2326 if file_extension not in ('.hdf5', '.hdf', '.h5'):
2344 2327 continue
2345 2328 kindat = madFileObj.getKindatByPosition(i)
2346 2329 kindatdesc = madKindatObj.getKindatDescription(kindat, kinst)
2347 2330 category = madFileObj.getCategoryByPosition(i)
2348 2331 status = madFileObj.getStatusByPosition(i)
2349 2332 permission = madFileObj.getAccessByPosition(i)
2350 2333 doi = madFileObj.getFileDOIUrlByPosition(i)
2351 2334
2352 2335 # skip private files if not trusted
2353 2336 if trusted == 0 and int(permission) != 0:
2354 2337 continue
2355 2338
2356 2339 retStr += '%s,%i,%s,%i,%s,%i,%s\n' % \
2357 2340 (name,
2358 2341 kindat,
2359 2342 kindatdesc,
2360 2343 category,
2361 2344 status,
2362 2345 permission,
2363 2346 doi)
2364 2347
2365 2348
2366 2349
2367 2350 return render(request, 'madweb/service.html', {'text': django.utils.safestring.mark_safe(retStr)})
2368 2351
2369 2352
2370 2353 def get_parameters_service(request):
2371 2354 """get_parameters_service runs the getParametersService.py service.
2372 2355
2373 2356 Inputs:
2374 2357 request/url - contains arguments:
2375 2358
2376 2359 filename=<full path to data file>
2377 2360
2378 2361 Returns backslash-delimited data, one for each parameter either measured or derivable, with the following fields:
2379 2362
2380 2363 1. parameter.mnemonic (string) Example 'dti'
2381 2364
2382 2365 2. parameter.description (string) Example:
2383 2366 "F10.7 Multiday average observed (Ott)"
2384 2367
2385 2368 3. parameter.isError (int) 1 if error parameter, 0 if not
2386 2369
2387 2370 4. parameter.units (string) Example "W/m2/Hz"
2388 2371
2389 2372 5. parameter.isMeasured (int) 1 if measured, 0 if derivable
2390 2373
2391 2374 6. parameter.category (string) Example: "Time Related Parameter"
2392 2375
2393 2376 7. parameter.isSure (int) - 1 if parameter can be found for every record, 0 if can only be found for some.
2394 2377 Not relevant to Madrigal 3, where always 1
2395 2378
2396 2379 8. parameter.isAddIncrement - 1 if additional increment, 0 if normal (Added in Madrigal 2.5)
2397 2380 Not relevant to Madrigal 3, where always -1
2398 2381 """
2399 2382 filename = request.GET['filename']
2400 2383
2401 2384 # create MadrigalDB obj
2402 2385 madDBObj = madrigal.metadata.MadrigalDB()
2403 2386
2404 2387 # create Madrigal File object
2405 2388 madFileObj = madrigal.data.MadrigalFile(filename, madDBObj)
2406 2389
2407 2390 # create Madrigal Parameter object
2408 2391 madParmObj = madrigal.data.MadrigalParameters(madDBObj)
2409 2392
2410 2393 # create Madrigal web object
2411 2394 madWebObj = madrigal.ui.web.MadrigalWebFormat()
2412 2395
2413 2396
2414 2397 # create lists of parameters
2415 2398 measParmList = []
2416 2399 derivedParmList = []
2417 2400 allParmList = []
2418 2401 sureParmList = []
2419 2402
2420 2403 # use the comprehensive list of parameters to check if derivable
2421 2404 parmList = madWebObj.getFormat('Comprehensive')
2422 2405
2423 2406 # populate lists
2424 2407 madFileObj.getMeasDervBothParmLists(parmList,
2425 2408 measParmList,
2426 2409 derivedParmList,
2427 2410 allParmList,
2428 2411 sureParmList)
2429 2412
2430 2413 retStr = ''
2431 2414
2432 2415 # loop through allParmList and output results
2433 2416 for parm in allParmList:
2434 2417 description = madParmObj.getSimpleParmDescription(parm)
2435 2418 isNorm = madParmObj.getParmType(parm)
2436 2419 if isNorm == 1:
2437 2420 isError = 0
2438 2421 else:
2439 2422 isError = 1
2440 2423 units = madParmObj.getParmUnits(parm)
2441 2424 if parm in measParmList:
2442 2425 isMeasured = 1
2443 2426 else:
2444 2427 isMeasured = 0
2445 2428 if parm in sureParmList:
2446 2429 isSure = 1
2447 2430 else:
2448 2431 isSure = 0
2449 2432 category = madParmObj.getParmCategory(parm)
2450 2433 try:
2451 2434 if madParmObj.isAddIncrement(parm):
2452 2435 isAddIncrement = 1
2453 2436 else:
2454 2437 isAddIncrement = 0
2455 2438 except:
2456 2439 isAddIncrement = -1
2457 2440 # print out this parm
2458 2441 retStr += '%s\\%s\\%i\\%s\\%i\\%s\\%i\\%i\n' % (parm,
2459 2442 description,
2460 2443 isError,
2461 2444 units,
2462 2445 isMeasured,
2463 2446 category,
2464 2447 isSure,
2465 2448 isAddIncrement)
2466 2449
2467 2450 return render(request, 'madweb/service.html', {'text': retStr})
2468 2451
2469 2452
2470 2453
2471 2454 def isprint_service(request):
2472 2455 """isprint_service runs the isprintService.py service.
2473 2456
2474 2457 Inputs:
2475 2458 request/url - contains arguments:
2476 2459
2477 2460 'file': The full path to the file to be analyzed by isprint. If over 50 MB, returns error message.
2478 2461
2479 2462 'parms': Multiple requested parameters, space (+) separated.
2480 2463
2481 2464 'filters': Multiple of filters desired, as in isprint command
2482 2465
2483 2466 'user_fullname' user name
2484 2467
2485 2468 'user_email' user email
2486 2469
2487 2470 'user_affiliation' user affiliation
2488 2471
2489 2472 'output' - option argument specifying output file basename. Will be Hdf5 format if extension in
2490 2473 ('hdf5', 'h5', 'hdf'). Will be netCDF4 is extension is '.nc'. Otherwise ascii. If not
2491 2474 given, output is ascii.
2492 2475
2493 2476 'header': t for headers, f for no header. Defaults to no header. Ignored if not ascii output
2494 2477
2495 2478 Returns data as either column delimited ascii, Hdf5, or netCDF4.
2496 2479 """
2497 2480 madDB = madrigal.metadata.MadrigalDB()
2498 2481 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
2499 2482
2500 2483 # get required arguments
2501 2484 thisFile = request.GET['file']
2502 2485 parms = request.GET.getlist('parms')
2503 2486 filters = request.GET.getlist('filters')
2504 2487 user_fullname = request.GET['user_fullname']
2505 2488 user_email = request.GET['user_email']
2506 2489 user_affiliation = request.GET['user_affiliation']
2507 2490
2508 2491 # get optional arguments
2509 2492 try:
2510 2493 output = os.path.basename(request.GET['output'])
2511 2494 filename, file_extension = os.path.splitext(output)
2512 2495 if file_extension in ('.hdf5', '.h5', '.hdf'):
2513 2496 format = 'Hdf5'
2514 2497 elif file_extension in ('.nc',):
2515 2498 format = 'netCDF4'
2516 2499 else:
2517 2500 format = 'ascii'
2518 2501 except:
2519 2502 format = 'ascii'
2520 2503 output = None
2521 2504
2522 2505 # verify thisFile exists, not too big
2523 2506 errorMessage = None
2524 2507 if not os.access(thisFile, os.R_OK):
2525 2508 errorMessage = 'File %s not found' % (thisFile)
2526 2509 elif os.path.getsize(thisFile) > 200.0E6:
2527 2510 errorMessage = 'File %s greater than 200 MB in size - running dynamic file creation not possible. Please use -- download as is -- instead.' % (thisFile)
2528 2511 if not errorMessage is None:
2529 2512 return render(request, 'madweb/service.html', {'text': errorMessage})
2530 2513
2531 2514 if not output is None:
2532 2515 # we need to write to a download file
2533 2516 downloadFile = os.path.join(tempfile.gettempdir(), output)
2534 2517 if os.access(downloadFile, os.R_OK):
2535 2518 try:
2536 2519 os.remove(downloadFile)
2537 2520 except:
2538 2521 pass
2539 2522 try:
2540 2523 header = request.GET['header']
2541 2524 if header not in ('t', 'f'):
2542 2525 raise ValueError('Unknown header value <%s>' % (header))
2543 2526 except:
2544 2527 header = 'f'
2545 2528
2546 2529 # log data access
2547 2530 madWebObj.logDataAccess(thisFile, user_fullname, user_email, user_affiliation)
2548 2531
2549 2532 # run isprint command
2550 2533 cmd = '%s/bin/isprint file=%s ' % (madDB.getMadroot(), thisFile)
2551 2534 if not output is None:
2552 2535 cmd += 'output=%s ' % (downloadFile)
2553 2536 delimiter = ' '
2554 2537 cmd += delimiter.join(parms) + ' '
2555 2538 filterStr = delimiter.join(filters)
2556 2539 cmd += filterStr + ' '
2557 2540 if format == 'ascii':
2558 2541 cmd += 'summary=f '
2559 2542 cmd += 'header=%s ' % (header)
2560 2543
2561 2544 if output is None:
2562 2545 # text response
2563 2546 #result = subprocess.check_output(cmd.split())
2564 2547 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
2565 2548 result,errtext = p.communicate()
2566 2549 if p.returncode != 0:
2567 2550 result = errtext
2568 2551 if type(result) in (bytes, numpy.bytes_):
2569 2552 result = result.decode('utf-8')
2570 2553 if header == 'f':
2571 2554 index = result.find('\n')
2572 2555 result = result[index+1:]
2573 2556 return render(request, 'madweb/service.html', {'text': result})
2574 2557 else:
2575 2558 # file download response
2576 2559 #subprocess.check_call(cmd.split())
2577 2560 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
2578 2561 result,errtext = p.communicate()
2579 2562 if p.returncode != 0:
2580 2563 # write the error to result file
2581 2564 f = open(downloadFile, 'w')
2582 2565 if type(errtext) in (bytes, numpy.bytes_):
2583 2566 errtext = errtext.decode('utf-8')
2584 2567 f.write(errtext)
2585 2568 f.close()
2586 2569
2587 2570 f = open(downloadFile, 'rb')
2588 2571 filename = os.path.basename(downloadFile)
2589 2572 chunk_size = 8192
2590 2573 file_type = mimetypes.guess_type(downloadFile)[0]
2591 2574 if file_type is None:
2592 2575 file_type = 'application/octet-stream'
2593 2576 response = StreamingHttpResponse(FileWrapper(f, chunk_size),
2594 2577 content_type=file_type)
2595 2578 response['Content-Length'] = os.path.getsize(downloadFile)
2596 2579 response['Content-Disposition'] = "attachment; filename=%s" % (filename)
2597 2580 os.remove(downloadFile)
2598 2581 return(response)
2599 2582
2600 2583
2601 2584 def get_madfile_service(request):
2602 2585 """get_madfile_service runs the getMadfile.cgi service.
2603 2586
2604 2587 Inputs:
2605 2588 request/url - contains arguments:
2606 2589
2607 2590 'fileName': The full path to the file to be downloaded as.
2608 2591
2609 2592 'fileType': -1 for ascii, -2 for Hdf5, -3 for netCDF4. No other values supported
2610 2593
2611 2594 'user_fullname' user name
2612 2595
2613 2596 'user_email' user email
2614 2597
2615 2598 'user_affiliation' user affiliation
2616 2599
2617 2600 Returns file as either column delimited ascii, Hdf5, or netCDF4.
2618 2601 """
2619 2602 madDB = madrigal.metadata.MadrigalDB()
2620 2603 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
2621 2604
2622 2605 # get required arguments
2623 2606 fileName = request.GET['fileName']
2624 2607 fileType = int(request.GET['fileType'])
2625 2608 user_fullname = request.GET['user_fullname']
2626 2609 user_email = request.GET['user_email']
2627 2610 user_affiliation = request.GET['user_affiliation']
2628 2611
2629 2612 if fileType not in (-1, -2, -3):
2630 2613 return(HttpResponse('<p>fileType %i not allowed: -1 for ascii, -2 for Hdf5, -3 for netCDF4</p>' % (fileType)))
2631 2614
2632 2615 # log data access
2633 2616 madWebObj.logDataAccess(fileName, user_fullname, user_email, user_affiliation)
2634 2617
2635 2618 if fileType in (-1, -3):
2636 2619 # may need to create temp file
2637 2620 filepath, file_extension = os.path.splitext(fileName)
2638 2621 basename = os.path.basename(filepath)
2639 2622 dirname = os.path.dirname(fileName)
2640 2623 if fileType == -1:
2641 2624 cachedTxtFile = os.path.join(dirname, 'overview', os.path.basename(fileName) + '.txt.gz')
2642 2625 tmpFile = os.path.join(tempfile.gettempdir(), basename + '.txt.gz')
2643 2626 if os.access(cachedTxtFile, os.R_OK):
2644 2627 shutil.copy(cachedTxtFile, tmpFile)
2645 2628 else:
2646 2629 tmpFile = os.path.join(tempfile.gettempdir(), basename + '.txt')
2647 2630 madrigal.cedar.convertToText(fileName, tmpFile)
2648 2631 else:
2649 2632 cachedNCFile = os.path.join(dirname, 'overview', os.path.basename(fileName) + '.nc')
2650 2633 tmpFile = os.path.join(tempfile.gettempdir(), basename + '.nc')
2651 2634 if os.access(cachedNCFile, os.R_OK):
2652 2635 shutil.copy(cachedNCFile, tmpFile)
2653 2636 else:
2654 2637 try:
2655 2638 madrigal.cedar.convertToNetCDF4(fileName, tmpFile)
2656 2639 except IOError:
2657 2640 cedarObj = madrigal.cedar.MadrigalCedarFile(fileName)
2658 2641 cedarObj.write('netCDF4', tmpFile)
2659 2642
2660 2643 else:
2661 2644 tmpFile = fileName
2662 2645
2663 2646 f = open(tmpFile, 'rb')
2664 2647 filename = os.path.basename(tmpFile)
2665 2648 chunk_size = 8192
2666 2649 file_type = mimetypes.guess_type(tmpFile)[0]
2667 2650 if file_type is None:
2668 2651 file_type = 'application/octet-stream'
2669 2652 response = StreamingHttpResponse(FileWrapper(f, chunk_size),
2670 2653 content_type=file_type)
2671 2654 response['Content-Length'] = os.path.getsize(tmpFile)
2672 2655 response['Content-Disposition'] = "attachment; filename=%s" % (filename)
2673 2656 if fileType in (-1, -3):
2674 2657 os.remove(tmpFile)
2675 2658 return(response)
2676 2659
2677 2660
2678 2661 def mad_calculator_service(request):
2679 2662 """mad_calculator_service runs the madCalculator service.
2680 2663
2681 2664 Inputs:
2682 2665 request/url - contains arguments:
2683 2666
2684 2667 year, month, day, hour, min, sec
2685 2668
2686 2669 startLat - Starting geodetic latitude, -90 to 90 (float)
2687 2670
2688 2671 endLat - Ending geodetic latitude, -90 to 90 (float)
2689 2672
2690 2673 stepLat - Latitude step (0.1 to 90) (float)
2691 2674
2692 2675 startLong - Starting geodetic longitude, -180 to 180 (float)
2693 2676
2694 2677 endLong - Ending geodetic longitude, -180 to 180 (float)
2695 2678
2696 2679 stepLong - Longitude step (0.1 to 180) (float)
2697 2680
2698 2681 startAlt - Starting geodetic altitude, >= 0 (float)
2699 2682
2700 2683 endAlt - Ending geodetic altitude, > 0 (float)
2701 2684
2702 2685 stepAlt - Altitude step (>= 0.1) (float)
2703 2686
2704 2687 parms - comma delimited string of Madrigal parameters desired
2705 2688
2706 2689 oneD - zero or more mnemonics,float values to set input 1D values
2707 2690
2708 2691 Returns comma-delimited data, one line for each combination of lat, long, and alt,
2709 2692 with the following fields:
2710 2693
2711 2694 1. latitude
2712 2695
2713 2696 2. longitude
2714 2697
2715 2698 3. altitude
2716 2699
2717 2700 4. Values for each Madrigal parameter listed in argument parms, separated by whitespace
2718 2701 """
2719 2702 year = int(request.GET['year'])
2720 2703 month = int(request.GET['month'])
2721 2704 day = int(request.GET['day'])
2722 2705 hour = int(request.GET['hour'])
2723 2706 minute = int(request.GET['min'])
2724 2707 second = int(request.GET['sec'])
2725 2708 try:
2726 2709 dt = datetime.datetime(year, month, day, hour, minute, second)
2727 2710 except:
2728 2711 return(HttpResponse('Illegal time: year %i, month %i, day %i, hour %i, minute %i, second %i' % (year, month, day, hour, minute, second)))
2729 2712
2730 2713 startLat = float(request.GET['startLat'])
2731 2714 endLat = float(request.GET['endLat'])
2732 2715 if startLat == endLat:
2733 2716 endLat += 0.001
2734 2717 elif startLat > endLat:
2735 2718 return(HttpResponse('startLat %s cannot be greater than endLat %s' % (str(startLat), str(endLat))))
2736 2719 stepLat = float(request.GET['stepLat'])
2737 2720 if stepLat < 0.0:
2738 2721 return(HttpResponse('stepLat %s cannot be less than zero' % (str(stepLat))))
2739 2722 elif stepLat == 0.0:
2740 2723 stepLat = 0.001
2741 2724 latList = list(numpy.arange(startLat, endLat, stepLat))
2742 2725
2743 2726 startLong = float(request.GET['startLong'])
2744 2727 endLong = float(request.GET['endLong'])
2745 2728 if startLong == endLong:
2746 2729 endLong += 0.001
2747 2730 elif startLong > endLong:
2748 2731 return(HttpResponse('startLong %s cannot be greater than endLong %s' % (str(startLong), str(endLong))))
2749 2732 stepLong = float(request.GET['stepLong'])
2750 2733 if stepLong < 0.0:
2751 2734 return(HttpResponse('stepLong %s cannot be less than zero' % (str(stepLong))))
2752 2735 elif stepLong == 0.0:
2753 2736 stepLong = 0.001
2754 2737 lonList = list(numpy.arange(startLong, endLong, stepLong))
2755 2738
2756 2739 startAlt = float(request.GET['startAlt'])
2757 2740 endAlt = float(request.GET['endAlt'])
2758 2741 if startAlt == endAlt:
2759 2742 endAlt += 0.001
2760 2743 elif startAlt > endAlt:
2761 2744 return(HttpResponse('startAlt %s cannot be greater than endAlt %s' % (str(startAlt), str(endAlt))))
2762 2745 stepAlt = float(request.GET['stepAlt'])
2763 2746 if stepAlt < 0.0:
2764 2747 return(HttpResponse('stepAlt %s cannot be less than zero' % (str(stepAlt))))
2765 2748 elif stepAlt == 0.0:
2766 2749 stepAlt = 0.01
2767 2750 altList = list(numpy.arange(startAlt, endAlt, stepAlt))
2768 2751
2769 2752 # limit total calculations to 1E5
2770 2753 total = len(latList) * len(lonList) * len(altList)
2771 2754 if total > 1.0E5:
2772 2755 return(HttpResponse('Too many points for madCalculatorService: %i' % (total)))
2773 2756
2774 2757 parms = request.GET['parms']
2775 2758 desiredParmList = [item.strip() for item in ['gdlat','glon','gdalt'] + parms.split(',')]
2776 2759
2777 2760 oneDList = request.GET.getlist('oneD')
2778 2761 oneDParmDict = {}
2779 2762 for oneDStr in oneDList:
2780 2763 mnem, strValue = oneDStr.split(',')
2781 2764 oneDParmDict[mnem] = [float(strValue)]
2782 2765
2783 2766 # capture stdout
2784 2767 old_stdout = sys.stdout
2785 2768 sys.stdout = mystdout = io.StringIO()
2786 2769 madrigal.isprint.MadCalculatorGrid(None, desiredParmList, [dt], latList, lonList, altList,
2787 2770 oneDParmDict, summary=None)
2788 2771 text = mystdout.getvalue()
2789 2772 sys.stdout = old_stdout
2790 2773
2791 2774 return render(request, 'madweb/service.html', {'text': text})
2792 2775
2793 2776
2794 2777 def mad_time_calculator_service(request):
2795 2778 """mad_time_calculator_service runs the madTimeCalculator service. Input parameters must not be location dependent
2796 2779
2797 2780 Inputs:
2798 2781 request/url - contains arguments:
2799 2782
2800 2783 1. startyear - int
2801 2784
2802 2785 2. startmonth - int
2803 2786
2804 2787 3. startday - int
2805 2788
2806 2789 4. starthour - int
2807 2790
2808 2791 5. startmin - int
2809 2792
2810 2793 6. startsec - int
2811 2794
2812 2795 7. endyear - int
2813 2796
2814 2797 8. endmonth - int
2815 2798
2816 2799 9. endday - int
2817 2800
2818 2801 10. endhour - int
2819 2802
2820 2803 11. endmin - int
2821 2804
2822 2805 12. endsec - int
2823 2806
2824 2807 13. stephours - float - number of hours per time step
2825 2808
2826 2809 14. parms - comma delimited string of Madrigal parameters desired (must not depend on location)
2827 2810
2828 2811 Returns comma-delimited data, one line for each year, month, day, hour, minute, and second,
2829 2812 with the following fields:
2830 2813
2831 2814 1-6: year, month, day, hour, minute, and second
2832 2815
2833 2816 2. requested parm fields
2834 2817 """
2835 2818 startyear = int(request.GET['startyear'])
2836 2819 startmonth = int(request.GET['startmonth'])
2837 2820 startday = int(request.GET['startday'])
2838 2821 starthour = int(request.GET['starthour'])
2839 2822 startminute = int(request.GET['startmin'])
2840 2823 startsecond = int(request.GET['startsec'])
2841 2824 endyear = int(request.GET['endyear'])
2842 2825 endmonth = int(request.GET['endmonth'])
2843 2826 endday = int(request.GET['endday'])
2844 2827 endhour = int(request.GET['endhour'])
2845 2828 endminute = int(request.GET['endmin'])
2846 2829 endsecond = int(request.GET['endsec'])
2847 2830 dt1 = datetime.datetime(startyear, startmonth, startday, starthour, startminute, startsecond)
2848 2831 dt2 = datetime.datetime(endyear, endmonth, endday, endhour, endminute, endsecond)
2849 2832 if dt1 > dt2:
2850 2833 return(HttpResponse('End Datetime %s cannot be before start datetime %s' % (str(dt2), str(dt1))))
2851 2834
2852 2835 stephours = float(request.GET['stephours'])
2853 2836 if stephours <= 0.0:
2854 2837 return(HttpResponse('stephours cannot be non-positive: %f' % (stephours)))
2855 2838
2856 2839 dtList = []
2857 2840 while dt1 <= dt2:
2858 2841 dtList.append(dt1)
2859 2842 dt1 += datetime.timedelta(hours=stephours)
2860 2843
2861 2844 parms = request.GET['parms']
2862 2845 desiredParmList = [item.strip() for item in ['year','month','day','hour','min','sec'] + parms.split(',')]
2863 2846
2864 2847 # no spatial data
2865 2848 latList = lonList = altList = []
2866 2849 # capture stdout
2867 2850 old_stdout = sys.stdout
2868 2851 sys.stdout = mystdout = io.StringIO()
2869 2852 madrigal.isprint.MadCalculatorGrid(None, desiredParmList, dtList, latList, lonList, altList,
2870 2853 summary=None)
2871 2854 text = mystdout.getvalue()
2872 2855 sys.stdout = old_stdout
2873 2856
2874 2857 return render(request, 'madweb/service.html', {'text': text})
2875 2858
2876 2859
2877 2860
2878 2861 @csrf_exempt
2879 2862 def mad_calculator2_service(request):
2880 2863 """mad_calculator2_service runs the madCalculator2 service.
2881 2864
2882 2865 Differs from madCalulator in that positions are a list rather than a grid.
2883 2866
2884 2867 Inputs:
2885 2868 request/url - contains arguments:
2886 2869
2887 2870 year, month, day, hour, min, sec
2888 2871
2889 2872 lats - comma separated list of latitudes to analyze
2890 2873
2891 2874 longs - comma separated list of longitudes to analyze. Len must == len(lats)
2892 2875
2893 2876 alts - comma separated list of altitudes to analyze. Len must == len(lats)
2894 2877
2895 2878 parms - comma delimited string of Madrigal parameters desired
2896 2879
2897 2880 oneD - zero or more mnemonics,float values to set input 1D values
2898 2881 Example: &oneD=kinst,31.0&oneD=elm,45.0
2899 2882
2900 2883 twoD - zero or more mnemonics,comma-separate float list of len(lats) to set input 2D values
2901 2884 Example: twoD=te,1000,1100,1200 twoD=ti,1000,1000,1000
2902 2885 where there are 3 lats
2903 2886
2904 2887 Returns comma-delimited data, one line for each lat value,
2905 2888 with the following fields:
2906 2889
2907 2890 1. latitude
2908 2891
2909 2892 2. longitude
2910 2893
2911 2894 3. altitude
2912 2895
2913 2896 4. Values for each Madrigal parameter listed in argument parms, separated by whitespace
2914 2897 """
2915 2898 if request.method == 'POST':
2916 2899 reqDict = request.POST
2917 2900 else:
2918 2901 reqDict = request.GET
2919 2902 try:
2920 2903 year = int(reqDict.get('year'))
2921 2904 except TypeError:
2922 2905 return(HttpResponse('<p>madCalculator2Service requires year</p>'))
2923 2906 month = int(reqDict['month'])
2924 2907 day = int(reqDict['day'])
2925 2908 hour = int(reqDict['hour'])
2926 2909 minute = int(reqDict['min'])
2927 2910 second = int(reqDict['sec'])
2928 2911 dt = datetime.datetime(year, month, day, hour, minute, second)
2929 2912
2930 2913 latsStr = reqDict['lats']
2931 2914 lats = [float(item) for item in latsStr.split(',')]
2932 2915 longsStr = reqDict['longs']
2933 2916 longs = [float(item) for item in longsStr.split(',')]
2934 2917 altsStr = reqDict['alts']
2935 2918 alts = [float(item) for item in altsStr.split(',')]
2936 2919
2937 2920 parms = reqDict['parms']
2938 2921 desiredParmList = [item.strip() for item in ['gdlat','glon','gdalt'] + parms.split(',')]
2939 2922
2940 2923 oneDList = reqDict.getlist('oneD')
2941 2924 oneDParmDict = {}
2942 2925 for oneDStr in oneDList:
2943 2926 mnem, strValue = oneDStr.split(',')
2944 2927 oneDParmDict[mnem] = [float(strValue)]
2945 2928
2946 2929 twoDList = reqDict.getlist('twoD')
2947 2930
2948 2931 twoDParmDict = {}
2949 2932 for twoDStr in twoDList:
2950 2933 items = twoDStr.split(',')
2951 2934 if len(items) != 1 + len(lats):
2952 2935 raise ValueError('twoDstr %s not correct number of points' % (str(twoDStr)))
2953 2936 mnem = items[0]
2954 2937 floatValues = [float(item) for item in items[1:]]
2955 2938 # now we need to expand these values to be two dimensional 1 x len(lats)
2956 2939 values = numpy.zeros((1,len(lats)), dtype=numpy.float)
2957 2940 values[0][:] = floatValues
2958 2941 twoDParmDict[mnem] = values
2959 2942
2960 2943 # capture stdout
2961 2944 old_stdout = sys.stdout
2962 2945 sys.stdout = mystdout = io.StringIO()
2963 2946 madrigal.isprint.MadCalculatorList(None, desiredParmList, [dt], lats, longs, alts,
2964 2947 oneDParmDict, twoDParmDict, summary=None)
2965 2948 text = mystdout.getvalue()
2966 2949 sys.stdout = old_stdout
2967 2950
2968 2951 return render(request, 'madweb/service.html', {'text': text})
2969 2952
2970 2953
2971 2954
2972 2955
2973 2956 @csrf_exempt
2974 2957 def mad_calculator3_service(request):
2975 2958 """mad_calculator3_service runs the madCalculator3 service.
2976 2959
2977 2960 Differs from madCalulator in that multiple times, each with a unique list of positions, can be passed in.
2978 2961
2979 2962 Inputs:
2980 2963 request/url - contains arguments:
2981 2964
2982 2965 year - a comma-separated list of years - (required)
2983 2966
2984 2967 month - a comma-separated list of months - (required)
2985 2968
2986 2969 day - a comma-separated list of days - (required)
2987 2970
2988 2971 hour - a comma-separated list of hours - (required)
2989 2972
2990 2973 min - a comma-separated list of minutes - (required)
2991 2974
2992 2975 sec - a comma-separated list of seconds - (required)
2993 2976
2994 2977 numPos - a comma-sepatated list of the number of positions for each time - (required)
2995 2978
2996 2979 lats - a comma-separated list of geodetic latitudes, -90 to 90 (required). Listed
2997 2980 for first time, then second, etc. Total must be equal to the sum
2998 2981 of numPos.
2999 2982
3000 2983 longs - a comma-separated list of longitudes (required) Listed
3001 2984 for first time, then second, etc. Total must be equal to the sum
3002 2985 of numPos.
3003 2986
3004 2987 alts - a comma-separated list of geodetic altitudes in km (required) Listed
3005 2988 for first time, then second, etc. Total must be equal to the sum
3006 2989 of numPos.
3007 2990
3008 2991 parms - comma delimited string of Madrigal parameters desired (required)
3009 2992
3010 2993 oneD - string in form <parm>,<comma-separated values> This argument allows the user to
3011 2994 set any number of one-D parameters to be used in the calculation.
3012 2995 Value must be parameter name, comma, list of values as double,
3013 2996 where length of list is equal to number of times.
3014 2997 Example: &oneD=kinst,31.0,31.0&oneD=elm,45.0,50
3015 2998 (optional - 0 or more allowed)
3016 2999
3017 3000 twoD=<parm>,<values> (optional - 0 or more allowed) This argument allows the user to
3018 3001 set any number of two-D parameters to be used in the calculation.
3019 3002 Value must be parameter name, comma, comma-separated values.
3020 3003 Number of values must equal the sum of numPos. Order is
3021 3004 first time values first, then second time values, etc
3022 3005 Example: twoD=te,1000,1100,1200,1000,1100,1200 &twoD=ti,1000,1000,1000,1000,1000,1000
3023 3006 where numPos=3,3
3024 3007
3025 3008 Returns comma-delimited data, one line for each location. Separate times are delimited by line
3026 3009
3027 3010 TIME MM/DD/YYYY HH:MM:SS
3028 3011
3029 3012 Data lines have the following fields:
3030 3013
3031 3014 1. latitude
3032 3015
3033 3016 2. longitude
3034 3017
3035 3018 3. altitude
3036 3019
3037 3020 4. Values for each Madrigal parameter listed in argument parms, separated by whitespace
3038 3021 """
3039 3022 if request.method == 'POST':
3040 3023 reqDict = request.POST
3041 3024 else:
3042 3025 reqDict = request.GET
3043 3026 try:
3044 3027 yearList = [int(item) for item in reqDict.get('year').split(',')]
3045 3028 except AttributeError:
3046 3029 return(HttpResponse('<p>madCalculator3Service requires year</p>'))
3047 3030 monthList = [int(item) for item in reqDict.get('month').split(',')]
3048 3031 dayList = [int(item) for item in reqDict.get('day').split(',')]
3049 3032 hourList = [int(item) for item in reqDict.get('hour').split(',')]
3050 3033 minList = [int(item) for item in reqDict.get('min').split(',')]
3051 3034 secList = [int(item) for item in reqDict.get('sec').split(',')]
3052 3035 dtList = [datetime.datetime(yearList[i], monthList[i], dayList[i],
3053 3036 hourList[i], minList[i], secList[i]) for i in range(len(yearList))]
3054 3037 numPosStr = reqDict['numPos']
3055 3038 numPosList = [int(item) for item in numPosStr.split(',')]
3056 3039 totalPos = 0
3057 3040 for numPos in numPosList:
3058 3041 totalPos += numPos
3059 3042 latsStr = reqDict['lats']
3060 3043 lats = [float(item) for item in latsStr.split(',')]
3061 3044 if len(lats) != totalPos:
3062 3045 return(HttpResponse('wrong number of lats, expected %i' % (totalPos)))
3063 3046 longsStr = reqDict['longs']
3064 3047 longs = [float(item) for item in longsStr.split(',')]
3065 3048 if len(longs) != totalPos:
3066 3049 return(HttpResponse('wrong number of longs, expected %i' % (totalPos)))
3067 3050 altsStr = reqDict['alts']
3068 3051 alts = [float(item) for item in altsStr.split(',')]
3069 3052 if len(alts) != totalPos:
3070 3053 return(HttpResponse('wrong number of alts, expected %i' % (totalPos)))
3071 3054
3072 3055 parms = reqDict['parms']
3073 3056 desiredParmList = [item.strip() for item in ['gdlat','glon','gdalt'] + parms.split(',')]
3074 3057
3075 3058 oneDList = reqDict.getlist('oneD')
3076 3059 twoDList = reqDict.getlist('twoD')
3077 3060
3078 3061 # since the positions can change with each call, we need to call madrigal.isprint.MadCalculatorGrid once for each time
3079 3062 startIndex = 0
3080 3063 endIndex = 0
3081 3064 fullText = ''
3082 3065 for timeIndex, numPos in enumerate(numPosList):
3083 3066 startIndex = endIndex
3084 3067 endIndex += numPos
3085 3068 thisLats = lats[startIndex:endIndex]
3086 3069 thisLongs = longs[startIndex:endIndex]
3087 3070 thisAlts = alts[startIndex:endIndex]
3088 3071
3089 3072 oneDParmDict = {}
3090 3073 for oneDStr in oneDList:
3091 3074 values = oneDStr.split(',')
3092 3075 if len(values) != 1+len(dtList):
3093 3076 return(HttpResponse('wrong number of values given for 1D parm %s' % (values[0])))
3094 3077 oneDParmDict[values[0]] = [float(values[timeIndex+1])]
3095 3078
3096 3079 twoDParmDict = {}
3097 3080
3098 3081 for twoDStr in twoDList:
3099 3082 values = twoDStr.split(',')
3100 3083 if len(values) != 1 + totalPos:
3101 3084 return(HttpResponse('twoDstr %s not correct number of points' % (str(twoDStr))))
3102 3085 mnem = values[0]
3103 3086 floatValues = [float(item) for item in values[1+startIndex:1+endIndex]]
3104 3087 # now we need to expand these values to be two dimensional - 1,len(thisLats)
3105 3088 values2D = numpy.zeros((1,len(thisLats)), dtype=numpy.float)
3106 3089 values2D[0][:] = floatValues
3107 3090 twoDParmDict[mnem] = values2D
3108 3091
3109 3092
3110 3093
3111 3094 # capture stdout
3112 3095 old_stdout = sys.stdout
3113 3096 sys.stdout = mystdout = io.StringIO()
3114 3097 madrigal.isprint.MadCalculatorList(None, desiredParmList, [dtList[timeIndex]], thisLats,
3115 3098 thisLongs, thisAlts,
3116 3099 oneDParmDict, twoDParmDict, summary=None)
3117 3100 text = mystdout.getvalue()
3118 3101 sys.stdout = old_stdout
3119 3102
3120 3103 fullText += 'TIME %s\n' % (dtList[timeIndex].strftime('%m/%d/%Y %H:%M:%S'))
3121 3104 fullText += text
3122 3105
3123 3106 return render(request, 'madweb/service.html', {'text': fullText})
3124 3107
3125 3108
3126 3109
3127 3110 def geodetic_to_radar_service(request):
3128 3111 """geodetic_to_radar_service runs the geodeticToRadar service.
3129 3112
3130 3113 Inputs:
3131 3114 request/url - contains arguments:
3132 3115
3133 3116 slatgd - radar geodetic latitude
3134 3117
3135 3118 slon - radar longitude
3136 3119
3137 3120 saltgd - radar geodetic altitude
3138 3121
3139 3122 gdlat - a comma-separated list of geodetic latitude of point
3140 3123
3141 3124 glon - a comma-separated list of longitude of point. Len must be same as gdlat
3142 3125
3143 3126 gdalt - a comma-separated list of geodetic altitude of point. Len must be same as gdlat
3144 3127
3145 3128
3146 3129 Returns comma-delimited data, one line for point in lists (points treated as individual combinations, not grids):
3147 3130
3148 3131 1. radar azimuth in degrees (0 = north)
3149 3132
3150 3133 2. radar elevation in degrees
3151 3134
3152 3135 3. radar range in km
3153 3136 """
3154 3137 slatgd = float(request.GET['slatgd'])
3155 3138 slon = float(request.GET['slon'])
3156 3139 saltgd = float(request.GET['saltgd'])
3157 3140 oneDParmDict = {'GDLATR': [slatgd],
3158 3141 'GDLONR': [slon],
3159 3142 'GALTR': [saltgd]}
3160 3143 gdlatStr = request.GET['gdlat']
3161 3144 gdlatList = [float(item) for item in gdlatStr.split(',')]
3162 3145 glonStr = request.GET['glon']
3163 3146 glonList = [float(item) for item in glonStr.split(',')]
3164 3147 gdaltStr = request.GET['gdalt']
3165 3148 gdaltList = [float(item) for item in gdaltStr.split(',')]
3166 3149 desiredParmList = ['azm', 'elm', 'range']
3167 3150 dtList = [datetime.datetime(2001,1,1)] # not relevant
3168 3151 if len(gdlatList) != len(glonList) or len(gdlatList) != len(gdaltList):
3169 3152 return(HttpResponse('all point list lengths must be equal'))
3170 3153
3171 3154 fullText = ''
3172 3155
3173 3156 delimiter = ','
3174 3157 for i in range(len(gdlatList)):
3175 3158 # capture stdout
3176 3159 old_stdout = sys.stdout
3177 3160 sys.stdout = mystdout = io.StringIO()
3178 3161 madrigal.isprint.MadCalculatorGrid(None, desiredParmList, dtList, [gdlatList[i]],
3179 3162 [glonList[i]], [gdaltList[i]], summary=None,
3180 3163 oneDParmDict=oneDParmDict)
3181 3164 text = mystdout.getvalue()
3182 3165 sys.stdout = old_stdout
3183 3166 for line in text.split('\n'):
3184 3167 items = line.split()
3185 3168 fullText += delimiter.join(items) + '\n'
3186 3169
3187 3170 return render(request, 'madweb/service.html', {'text': fullText})
3188 3171
3189 3172
3190 3173 def radar_to_geodetic_service(request):
3191 3174 """radar_to_geodetic_service runs the radarToGeodetic service.
3192 3175
3193 3176 Inputs:
3194 3177 request/url - contains arguments:
3195 3178
3196 3179 slatgd - radar geodetic latitude
3197 3180
3198 3181 slon - radar longitude
3199 3182
3200 3183 saltgd - radar geodetic altitude
3201 3184
3202 3185 azs - a comma-separated list of azimuths of point
3203 3186
3204 3187 els - a comma-separated list of elevations of point. Len must be same as azs
3205 3188
3206 3189 ranges - a comma-separated list of ranges to point. Len must be same as azs
3207 3190
3208 3191
3209 3192 Returns comma-delimited data, one line for point in lists (points treated as individual combinations, not grids):
3210 3193
3211 3194 1. geodetic latitude
3212 3195
3213 3196 2. longitude (-180 to 180)
3214 3197
3215 3198 3. geodetic altitude in km
3216 3199 """
3217 3200 slatgd = float(request.GET['slatgd'])
3218 3201 slon = float(request.GET['slon'])
3219 3202 saltgd = float(request.GET['saltgd'])
3220 3203 azStr = request.GET['az']
3221 3204 azList = [float(item) for item in azStr.split(',')]
3222 3205 elStr = request.GET['el']
3223 3206 elList = [float(item) for item in elStr.split(',')]
3224 3207 rangeStr = request.GET['range']
3225 3208 rangeList = [float(item) for item in rangeStr.split(',')]
3226 3209 if len(azList) != len(elList) or len(azList) != len(rangeList):
3227 3210 return(HttpResponse('all point list lengths must be equal'))
3228 3211
3229 3212 fullText = ''
3230 3213
3231 3214 for i in range(len(azList)):
3232 3215 gdlat,glon,gdalt = madrigal._derive.radarToGeodetic(slatgd, slon, saltgd,
3233 3216 azList[i], elList[i], rangeList[i])
3234 3217 fullText += '%f,%f,%f\n' % (gdlat,glon,gdalt)
3235 3218
3236 3219 return render(request, 'madweb/service.html', {'text': fullText})
3237 3220
3238 3221
3239 3222
3240 3223 def list_file_times_service(request):
3241 3224 """list_file_times_service runs the listFileTimes service.
3242 3225
3243 3226 Inputs:
3244 3227 request/url - contains arguments:
3245 3228
3246 3229 Optional: expDir - experiment directory to list. Can be absolute or relative to
3247 3230 experiments[0-9]*. Default is all files in $MADROOT/experiments*
3248 3231
3249 3232 Returns comma-delimited data, one for each file:
3250 3233
3251 3234 1. Full path of file
3252 3235
3253 3236 2. File modification time in form YYYY-MM-DD HH:MM:SS (UT time)
3254 3237 """
3255 3238 expDir = None
3256 3239 try:
3257 3240 expDir = request.GET['expDir']
3258 3241 except:
3259 3242 pass
3260 3243 madDB = madrigal.metadata.MadrigalDB()
3261 3244 fileList = madDB.listFileTimes(expDir)
3262 3245 fullText = '\n\n'
3263 3246 for filename, filetime in fileList:
3264 3247 fullText += "\'%s\', %s\n" % (filename, filetime.strftime('%Y-%m-%d %H:%M:%S'))
3265 3248
3266 3249 return render(request, 'madweb/service.html', {'text': django.utils.safestring.mark_safe(fullText)})
3267 3250
3268 3251
3269 3252 def download_web_file_service(request):
3270 3253 """download_web_file_service runs the downloadWebFile service.
3271 3254
3272 3255 Inputs:
3273 3256 request/url - contains arguments:
3274 3257
3275 3258 expPath - path to file starting at experiments*
3276 3259
3277 3260 Returns comma-delimited data, one for each file:
3278 3261
3279 3262 1. Full path of file
3280 3263
3281 3264 2. File modification time in form YYYY-MM-DD HH:MM:SS (UT time)
3282 3265 """
3283 3266 expPath = request.GET['expPath']
3284 3267 madDB = madrigal.metadata.MadrigalDB()
3285 3268 downloadFile = os.path.join(madDB.getMadroot(), expPath)
3286 3269 f = open(downloadFile, 'rb')
3287 3270 thisFile = django.core.files.File(f)
3288 3271 response = HttpResponse(thisFile, content_type='application/x-octet-stream')
3289 3272 response['Content-Disposition'] = 'attachment; filename="' + os.path.basename(downloadFile) + '"'
3290 3273 response['Content-Length'] = os.path.getsize(downloadFile)
3291 3274 return(response)
3292 3275
3293 3276
3294 3277 def trace_magnetic_field_service(request):
3295 3278 """trace_magnetic_field_service runs the traceMagneticField service.
3296 3279
3297 3280 Inputs:
3298 3281 request/url - contains arguments:
3299 3282
3300 3283 year, month, day, hour, min, sec
3301 3284
3302 3285 inputType (0 for geodetic, 1 for GSM)
3303 3286
3304 3287 outputType (0 for geodetic, 1 for GSM)
3305 3288
3306 3289 The following parameter depend on inputType:
3307 3290
3308 3291 in1 - a comma-separated list of geodetic altitudes or ZGSMs of starting point
3309 3292
3310 3293 in2 - a comma-separated list of geodetic latitudes or XGSMs of starting point
3311 3294
3312 3295 in3 - a comma-separated list of longitude or YGSM of starting point
3313 3296
3314 3297 Length of all three lists must be the same
3315 3298
3316 3299 model - 0 for Tsyganenko, 1 for IGRF
3317 3300
3318 3301 qualifier - 0 for conjugate, 1 for north_alt, 2 for south_alt, 3 for apex, 4 for GSM XY plane
3319 3302
3320 3303 stopAlt - altitude in km to stop trace at, if qualifier is north_alt or south_alt.
3321 3304
3322 3305 If other qualifier, this parameter is not required.
3323 3306
3324 3307 Returns comma-delimited data, one line for point in in lists:
3325 3308
3326 3309 1. geodetic altitude or ZGSM of ending point
3327 3310
3328 3311 2. geodetic latitude or XGSM of ending point
3329 3312
3330 3313 3. longitude or YGSM of ending point
3331 3314 """
3332 3315 year = int(request.GET['year'])
3333 3316 month = int(request.GET['month'])
3334 3317 day = int(request.GET['day'])
3335 3318 hour = int(request.GET['hour'])
3336 3319 minute = int(request.GET['min'])
3337 3320 second = int(request.GET['sec'])
3338 3321 dt = datetime.datetime(year, month, day, hour, minute, second)
3339 3322 inputType = int(request.GET['inputType'])
3340 3323 if inputType not in (0,1):
3341 3324 return(HttpResponse('inputType must be 0 or 1, not %i' % (inputType)))
3342 3325 outputType = int(request.GET['outputType'])
3343 3326 if outputType not in (0,1):
3344 3327 return(HttpResponse('outputType must be 0 or 1, not %i' % (outputType)))
3345 3328 in1Str = request.GET['in1']
3346 3329 in1List = [float(item) for item in in1Str.split(',')]
3347 3330 in2Str = request.GET['in2']
3348 3331 in2List = [float(item) for item in in2Str.split(',')]
3349 3332 in3Str = request.GET['in3']
3350 3333 in3List = [float(item) for item in in3Str.split(',')]
3351 3334 if len(in1List) != len(in2List) or len(in1List) != len(in3List):
3352 3335 return(HttpResponse('All three in* lists must have same length'))
3353 3336 model = int(request.GET['model'])
3354 3337 if model not in (0,1):
3355 3338 return(HttpResponse('model must be 0 or 1, not %i' % (model)))
3356 3339 qualifier = int(request.GET['qualifier'])
3357 3340 if qualifier not in (0,1,2,3,4):
3358 3341 return(HttpResponse('model must be in 0,1,2,3,4 not %i' % (model)))
3359 3342 try:
3360 3343 stopAlt = float(request.GET['stopAlt'])
3361 3344 except:
3362 3345 stopAlt = 0.0
3363 3346
3364 3347 fullText = ''
3365 3348 resultArr = numpy.zeros((3,), dtype='f8')
3366 3349 madDB = madrigal.metadata.MadrigalDB()
3367 3350 madDeriveObj = madrigal.derivation.MadrigalDerivationMethods(madDB.getMadroot())
3368 3351 for i in range(len(in1List)):
3369 3352 madDeriveObj.traceMagneticField(year, month, day, hour, minute, second,
3370 3353 inputType, outputType, in1List[i], in2List[i], in3List[i],
3371 3354 model, qualifier, stopAlt, resultArr)
3372 3355 fullText += '%f,%f,%f\n' % (resultArr[0], resultArr[1], resultArr[2])
3373 3356
3374 3357 return render(request, 'madweb/service.html', {'text': fullText})
3375 3358
3376 3359
3377 3360 def global_file_search_service(request):
3378 3361 """global_file_search_service returns a list of full paths to files or citable urls based on search arguments
3379 3362
3380 3363 Inputs:
3381 3364 request/url - contains arguments:
3382 3365
3383 3366 startDate: start date in form YYYY-MM-DD to filter experiments before
3384 3367 endDate: end date in form YYYY-MM-DD to filter experiments after
3385 3368 inst: (optional, multiple allowed) an instrument code or name. For names,
3386 3369 fnmatch will be used. If not set, all instruments used.
3387 3370 kindat: (optional, multiple allowed) a kind of data codes or name. For names,
3388 3371 fnmatch will be used. If not set, all kinds of data used.
3389 3372 seasonalStartDate: (optional) in form MM/DD, rejects all days earlier in year. If not set
3390 3373 implies 01/01
3391 3374 seasonalEndDate: (optional) in form MM/DD, rejects all days later in year. If not set
3392 3375 implies 12/31
3393 3376 includeNonDefault: (optional) if "True", include realtime files when there are no default.
3394 3377 If not set, only default files.
3395 3378 expName: (optional) - filter experiments by the experiment name. fnmatch rules
3396 3379 If not set, no filtering by experiment name.
3397 3380 excludeExpName: (optional) - exclude experiments by the experiment name. fnmatch rules
3398 3381 If not set, no excluding experiments by experiment name.
3399 3382 fileDesc: (optional) filter files using input file Description string via fnmatch.
3400 3383 If not set, in no filtering by file name
3401 3384 returnCitation: (optional) if True, return a list of file citations. If not set, return
3402 3385 a list of full paths to the files selected
3403 3386
3404 3387 """
3405 3388 madDB = madrigal.metadata.MadrigalDB()
3406 3389 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
3407 3390
3408 3391 # get required arguments
3409 3392 startDate = request.GET['startDate']
3410 3393 endDate = request.GET['endDate']
3411 3394 startDate = datetime.datetime.strptime(startDate, '%Y-%m-%d')
3412 3395 endDate = datetime.datetime.strptime(endDate, '%Y-%m-%d')
3413 3396
3414 3397 # get optional arguments
3415 3398 inst = request.GET.getlist('inst')
3416 3399 if inst == []:
3417 3400 inst = None
3418 3401 kindat = request.GET.getlist('kindat')
3419 3402 if kindat == []:
3420 3403 kindat = None
3421 3404 seasonalStartDate = request.GET.get('seasonalStartDate', default = None)
3422 3405 seasonalEndDate = request.GET.get('seasonalEndDate', default = None)
3423 3406 includeNonDefault = bool(request.GET.get('includeNonDefault', default = False))
3424 3407 expName = request.GET.get('expName', default = None)
3425 3408 excludeExpName = request.GET.get('excludeExpName', default = None)
3426 3409 fileDesc = request.GET.get('fileDesc', default = None)
3427 3410 returnCitation = bool(request.GET.get('returnCitation', default = False))
3428 3411
3429 3412 result = madWebObj.global_file_search(startDate, endDate, inst, kindat,
3430 3413 seasonalStartDate, seasonalEndDate,
3431 3414 includeNonDefault, expName, excludeExpName,
3432 3415 fileDesc, returnCitation)
3433 3416
3434 3417 fullText = ''
3435 3418 for item in result:
3436 3419 fullText += '%s\n' % (item)
3437 3420
3438 3421 return render(request, 'madweb/service.html', {'text': django.utils.safestring.mark_safe(fullText)})
3439 3422
3440 3423
3441 3424
3442 3425
3443 3426 def get_url_list_from_group_id_service(request):
3444 3427 """get_url_list_from_group_id_service returns a list of citable urls associated with group id.
3445 3428
3446 3429 Inputs:
3447 3430 request/url - contains arguments:
3448 3431
3449 3432 id - group id
3450 3433
3451 3434 Returns one line for each citable url
3452 3435
3453 3436 Returns empty string if experiment id not found. Skips files that are not Hdf5
3454 3437 """
3455 3438 id = int(request.GET['id'])
3456 3439
3457 3440 # create MadrigalDB obj
3458 3441 madDBObj = madrigal.metadata.MadrigalDB()
3459 3442
3460 3443 urlList = madDBObj.getListFromGroupId(id)
3461 3444
3462 3445 retStr = ''
3463 3446 for url in urlList:
3464 3447 retStr += '%s\n' % (url)
3465 3448
3466 3449 return render(request, 'madweb/service.html', {'text': django.utils.safestring.mark_safe(retStr)})
3467 3450
3468 3451
3469 3452 def set_group_id_from_url_list_service(request):
3470 3453 """set_group_id_from_url_list sets a list of citable urls to a group id .
3471 3454
3472 3455 Inputs:
3473 3456 request/url - contains arguments:
3474 3457
3475 3458 'user_fullname' user name
3476 3459
3477 3460 'user_email' user email
3478 3461
3479 3462 'user_affiliation' user affiliation
3480 3463
3481 3464 'url' - citable url. Multiple arguments allowed
3482 3465
3483 3466 Returns group id (integer) set
3484 3467 """
3485 3468 madDB = madrigal.metadata.MadrigalDB()
3486 3469
3487 3470 print(request.GET)
3488 3471
3489 3472 # get required arguments
3490 3473 urls = request.GET.getlist('url')
3491 3474 user_fullname = request.GET['user_fullname']
3492 3475 user_email = request.GET['user_email']
3493 3476 user_affiliation = request.GET['user_affiliation']
3494 3477
3495 3478 id = madDB.createGroupIdWithList(user_fullname, user_email, user_affiliation, urls)
3496 3479
3497 3480 return render(request, 'madweb/service.html', {'text': str(id)})
3498 3481
3499 3482
3500 3483 ### doc pages ###
3501 3484
3502 3485 def docs(request, name):
3503 3486 madDB = madrigal.metadata.MadrigalDB()
3504 3487 openMadObj = madrigal.openmadrigal.OpenMadrigal(madDB)
3505 3488 bg_color = madDB.getBackgroundColor()
3506 3489 if name.find('..') != -1:
3507 3490 # no trying to look elsewhere
3508 3491 return(HttpResponse('Illegal name passed to docs: <%s>' % (name)))
3509 3492 # check if siteSpecitic.html
3510 3493 siteSpecificPath = os.path.join(madDB.getMadroot(), 'source/madpy/djangoMad/madweb/templates/madweb/siteSpecific.html')
3511 3494 if os.access(siteSpecificPath, os.R_OK):
3512 3495 siteSpecific = reverse('docs', args=['siteSpecific.html'])
3513 3496 else:
3514 3497 siteSpecific = '#'
3515 3498 openmadrigal = openMadObj.getOpenMadrigalUrl()
3516 3499 # since google insists filenames are case insensitive, convert to right name if there is no direct match if possible
3517 3500 this_file = os.path.join(madDB.getMadroot(), 'source/madpy/djangoMad/madweb/templates/madweb', name)
3518 3501 if not os.access(this_file, os.R_OK):
3519 3502 found = False
3520 3503 existing_files = glob.glob(os.path.join(madDB.getMadroot(), 'source/madpy/djangoMad/madweb/templates/madweb/*.html'))
3521 3504 for existing_file in existing_files:
3522 3505 if name.lower() == os.path.basename(existing_file).lower():
3523 3506 name = os.path.basename(existing_file)
3524 3507 found = True
3525 3508 break # correct name found and name modified
3526 3509 if not found:
3527 3510 return(HttpResponse('<p>Cannot find %s</p>' % (str(name))))
3528 3511
3529 3512 if os.path.isdir(this_file):
3530 3513 return(HttpResponse('<p>%s is a directory</p>' % (str(name))))
3531 3514
3532 3515 return render(request, 'madweb/%s' % (name), {'bg_color': bg_color, 'siteSpecific': siteSpecific,
3533 3516 'openmadrigal': openmadrigal})
3534 3517
3535 3518 No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now