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