@@ -1,21 +1,21 | |||
|
1 | 1 | # configuration |
|
2 | 2 | |
|
3 | 3 | upstream djangomad { |
|
4 | 4 | server web:8000; |
|
5 | 5 | } |
|
6 | 6 | |
|
7 | 7 | server { |
|
8 | listen 80; | |
|
8 | listen 8080; | |
|
9 | 9 | |
|
10 | location / { | |
|
11 | proxy_http_version 1.1; | |
|
12 |
proxy_set_header |
|
|
13 | proxy_set_header Connection "upgrade"; | |
|
10 | location /madrigal { | |
|
11 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; | |
|
12 | proxy_set_header Host $host; | |
|
14 | 13 | proxy_redirect off; |
|
14 | proxy_set_header X-Script-Name /madrigal; | |
|
15 | 15 | proxy_pass http://djangomad; |
|
16 | 16 | } |
|
17 | 17 | |
|
18 | location /static/ { | |
|
18 | location /madrigal/static/ { | |
|
19 | 19 | alias /static/; |
|
20 | 20 | } |
|
21 | } No newline at end of file | |
|
21 | } |
@@ -1,83 +1,83 | |||
|
1 | 1 | |
|
2 | 2 | from django.contrib.auth.decorators import login_required |
|
3 | 3 | from django.shortcuts import render |
|
4 | 4 | from .forms import UpdataForm, ExpForm |
|
5 | 5 | from django.core.files.storage import FileSystemStorage |
|
6 | 6 | from django.contrib import messages |
|
7 | 7 | |
|
8 | 8 | import os |
|
9 | 9 | |
|
10 | 10 | # madrigal imports |
|
11 | 11 | import madrigal.metadata |
|
12 | 12 | import madrigal.ui.web |
|
13 | 13 | import madrigal.admin |
|
14 | 14 | |
|
15 | @login_required | |
|
15 | @login_required(login_url='/madrigal/accounts/login/') | |
|
16 | 16 | def index(request): |
|
17 | 17 | ''' |
|
18 | 18 | Uploading experiments data view. Allows user to upload experiment files |
|
19 | 19 | |
|
20 | 20 | ''' |
|
21 | 21 | dbAdminObj = madrigal.admin.MadrigalDBAdmin() |
|
22 | 22 | madDB = madrigal.metadata.MadrigalDB() |
|
23 | 23 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
24 | 24 | siteName, siteList = madWebObj.getSiteInfo() |
|
25 | 25 | |
|
26 | 26 | if request.method == 'POST': |
|
27 | 27 | form = UpdataForm(request.POST, request.FILES) |
|
28 | 28 | files = request.FILES.getlist('file') |
|
29 | 29 | |
|
30 | 30 | if form.is_valid(): |
|
31 | 31 | try: |
|
32 | 32 | description = form.cleaned_data['description'] |
|
33 | 33 | instCode = int(form.cleaned_data['instruments']) |
|
34 | 34 | expId = form.cleaned_data['experiments'] |
|
35 | 35 | perm = int(form.cleaned_data['type']) |
|
36 | 36 | |
|
37 | 37 | #saving file |
|
38 | 38 | for f in files: |
|
39 | 39 | fs = FileSystemStorage(location='/tmp') |
|
40 | 40 | fs.save(f.name, f) |
|
41 | 41 | madExp = madrigal.metadata.MadrigalExperiment() |
|
42 | 42 | filepath = os.path.join('/tmp', f.name) |
|
43 | 43 | expTitle = madExp.getExpNameByExpId(expId) |
|
44 | 44 | |
|
45 | 45 | dbAdminObj.createMadrigalExperiment(filepath,expTitle, perm, description, instCode) |
|
46 | 46 | |
|
47 | 47 | |
|
48 | 48 | madInstParams = madrigal.metadata.MadrigalInstrumentParameters() |
|
49 | 49 | madInstKindats = madrigal.metadata.MadrigalInstrumentKindats() |
|
50 | 50 | |
|
51 | 51 | print('*** Updating local metadata ***') |
|
52 | 52 | dbAdminObj.__updateLocalMetadata__() |
|
53 | 53 | print('*** Rebuilding instParmTab.txt ***') |
|
54 | 54 | madInstParams.rebuildInstParmTable() |
|
55 | 55 | print('*** Rebuilding instKindatTab.txt ***') |
|
56 | 56 | madInstKindats.rebuildInstKindatTable() |
|
57 | 57 | messages.success( |
|
58 | 58 | request, 'Experimento(s) creado(s) exitosamente') |
|
59 | 59 | form = UpdataForm() |
|
60 | 60 | |
|
61 | 61 | except Exception as e: |
|
62 | 62 | messages.error( |
|
63 | 63 | request, str(e)) |
|
64 | 64 | else: |
|
65 | 65 | form = UpdataForm() |
|
66 | 66 | |
|
67 | 67 | return render(request, 'updata/index.html', { |
|
68 | 68 | 'form': form, |
|
69 | 69 | 'site_name': siteName, |
|
70 | 70 | 'site_list': siteList, |
|
71 | 71 | }) |
|
72 | 72 | |
|
73 | 73 | |
|
74 | 74 | def get_experiments(request): |
|
75 | 75 | """get_experiments is a Ajax call that returns the experiments select html to support the |
|
76 | 76 | updata UI. Called when a user modifies the intruments select field. |
|
77 | 77 | |
|
78 | 78 | Inputs: |
|
79 | 79 | request |
|
80 | 80 | """ |
|
81 | 81 | form = ExpForm(request.GET) |
|
82 | 82 | |
|
83 | 83 | return render(request, 'updata/experiments.html', {'form': form}) |
@@ -1,138 +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 | 15 | # Quick-start development settings - unsuitable for production |
|
16 | 16 | # See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/ |
|
17 | 17 | |
|
18 | 18 | # SECURITY WARNING: keep the secret key used in production secret! |
|
19 | 19 | SECRET_KEY = '^c1l3d35+q28^66d2pc1qlu(k$wmw^*gg3rfitz^s)t=9eu1ui' |
|
20 | 20 | |
|
21 | 21 | # SECURITY WARNING: don't run with debug turned on in production! |
|
22 | 22 | DEBUG = True |
|
23 | 23 | |
|
24 | 24 | |
|
25 | ALLOWED_HOSTS = ['localhost:8000', '127.0.0.1', 'localhost'] | |
|
25 | ALLOWED_HOSTS = ['localhost:8000', '127.0.0.1', 'localhost', '10.10.120.60'] | |
|
26 | 26 | |
|
27 | 27 | ADMINS = (('Bill Rideout', 'brideout@haystack.mit.edu'),) |
|
28 | 28 | |
|
29 | 29 | EMAIL_HOST = 'hyperion.haystack.mit.edu' |
|
30 | 30 | |
|
31 | 31 | SEND_BROKEN_LINK_EMAILS = True |
|
32 | 32 | |
|
33 | 33 | MANAGERS = (('Bill Rideout', 'brideout@haystack.mit.edu'),) |
|
34 | 34 | |
|
35 | 35 | |
|
36 | 36 | # Application definition |
|
37 | 37 | |
|
38 | 38 | INSTALLED_APPS = ( |
|
39 | 39 | 'django.contrib.admin', |
|
40 | 40 | 'django.contrib.auth', |
|
41 | 41 | 'django.contrib.contenttypes', |
|
42 | 42 | 'django.contrib.sessions', |
|
43 | 43 | 'django.contrib.messages', |
|
44 | 44 | 'django.contrib.staticfiles', |
|
45 | 45 | 'madweb', |
|
46 | 46 | 'django_bootstrap_calendar', |
|
47 | 47 | 'bootstrap3', |
|
48 | 48 | 'apps.login', |
|
49 | 49 | 'apps.updata', |
|
50 | 50 | ) |
|
51 | 51 | |
|
52 | 52 | MIDDLEWARE = [ |
|
53 | 53 | 'django.middleware.security.SecurityMiddleware', |
|
54 | 54 | 'django.contrib.sessions.middleware.SessionMiddleware', |
|
55 | 55 | 'django.middleware.common.CommonMiddleware', |
|
56 | 56 | 'django.middleware.csrf.CsrfViewMiddleware', |
|
57 | 57 | 'django.contrib.auth.middleware.AuthenticationMiddleware', |
|
58 | 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 | 83 | 'django.template.context_processors.request', |
|
84 | 84 | ], |
|
85 | 85 | }, |
|
86 | 86 | }, |
|
87 | 87 | ] |
|
88 | 88 | |
|
89 | 89 | |
|
90 | 90 | # Database |
|
91 | 91 | # https://docs.djangoproject.com/en/1.7/ref/settings/#databases |
|
92 | 92 | |
|
93 | 93 | DATABASES = { |
|
94 | 94 | 'default': { |
|
95 | 95 | 'ENGINE': 'django.db.backends.sqlite3', |
|
96 | 96 | 'NAME': 'madrigal.sqlite', |
|
97 | 97 | } |
|
98 | 98 | } |
|
99 | 99 | |
|
100 | 100 | |
|
101 | 101 | # Internationalization |
|
102 | 102 | # https://docs.djangoproject.com/en/1.7/topics/i18n/ |
|
103 | 103 | |
|
104 | 104 | LANGUAGE_CODE = 'en-us' |
|
105 | 105 | |
|
106 | 106 | TIME_ZONE = 'UTC' |
|
107 | 107 | |
|
108 | 108 | USE_I18N = True |
|
109 | 109 | |
|
110 | 110 | USE_L10N = True |
|
111 | 111 | |
|
112 | 112 | USE_TZ = True |
|
113 | 113 | |
|
114 | 114 | |
|
115 | 115 | # Absolute filesystem path to the directory that will hold user-uploaded files. |
|
116 | 116 | # Example: "/home/media/media.lawrence.com/media/" |
|
117 | 117 | MEDIA_ROOT = os.path.join(BASE_DIR, 'media') |
|
118 | 118 | |
|
119 | 119 | # URL that handles the media served from MEDIA_ROOT. Make sure to use a |
|
120 | 120 | # trailing slash. |
|
121 | 121 | # Examples: "http://media.lawrence.com/media/", "http://example.com/media/" |
|
122 | 122 | MEDIA_URL = '/media/' |
|
123 | 123 | |
|
124 | 124 | # Absolute path to the directory static files should be collected to. |
|
125 | 125 | # Don't put anything in this directory yourself; store your static files |
|
126 | 126 | # in apps' "static/" subdirectories and in STATICFILES_DIRS. |
|
127 | 127 | # Example: "/home/media/media.lawrence.com/static/" |
|
128 | 128 | # STATIC_ROOT = os.path.join(BASE_DIR, 'static') |
|
129 | 129 | |
|
130 | 130 | # URL prefix for static files. |
|
131 | 131 | # Example: "http://media.lawrence.com/static/" |
|
132 | STATIC_URL = '/static/' | |
|
132 | STATIC_URL = '/madrigal/static/' | |
|
133 | 133 | |
|
134 | 134 | BOOTSTRAP3 = { |
|
135 | 135 | # Include jQuery with Bootstrap JavaScript (affects django-bootstrap3 template tags) |
|
136 | 'jquery_url': '/static/jquery.min.js', | |
|
136 | 'jquery_url': '/madrigal/static/jquery.min.js', | |
|
137 | 137 | 'include_jquery': True, |
|
138 | 138 | } |
@@ -1,11 +1,12 | |||
|
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 | url(r'^', include('madweb.urls')), | |
|
6 | url(r'^madrigal/', 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 | url(r'^madrigal/updata/', include('apps.updata.urls', namespace="updata")), | |
|
9 | url(r'^madrigal/accounts/', include('apps.login.urls', namespace="login")), | |
|
10 | url(r'^madrigal/admin/', admin.site.urls), | |
|
11 | # url(r'^madrigal/register/?$', madweb.views.view_registration, name='view_registration'), | |
|
11 | 12 | ] |
@@ -1,2208 +1,2220 | |||
|
1 | 1 | """Forms for madweb application |
|
2 | 2 | |
|
3 | 3 | $Id: forms.py 7288 2020-12-10 16:49:16Z brideout $ |
|
4 | 4 | """ |
|
5 | 5 | |
|
6 | 6 | # standard python imports |
|
7 | 7 | import os.path |
|
8 | 8 | import datetime |
|
9 | 9 | import itertools |
|
10 | 10 | |
|
11 | 11 | # django imports |
|
12 | 12 | import django.forms |
|
13 | 13 | import django.utils.html |
|
14 | 14 | import django.utils.safestring |
|
15 | 15 | import django.template.defaulttags |
|
16 | 16 | |
|
17 | 17 | # third party imports |
|
18 | 18 | import numpy |
|
19 | 19 | import h5py |
|
20 | 20 | |
|
21 | 21 | # Madrigal imports |
|
22 | 22 | import madrigal.metadata |
|
23 | 23 | import madrigal.ui.web |
|
24 | 24 | |
|
25 | 25 | # temp only |
|
26 | 26 | import logging |
|
27 | 27 | |
|
28 | 28 | @django.template.defaulttags.register.filter |
|
29 | 29 | def get_item(dictionary, key): |
|
30 | 30 | return(dictionary.get(key)) |
|
31 | 31 | |
|
32 | 32 | @django.template.defaulttags.register.filter |
|
33 | 33 | def modulo(num, val): |
|
34 | 34 | return(num % val == 0) |
|
35 | 35 | |
|
36 | 36 | class HorizontalRadioSelect(django.forms.RadioSelect): |
|
37 | 37 | template_name = 'madweb/horizontal_select.html' |
|
38 | 38 | |
|
39 | 39 | |
|
40 | 40 | |
|
41 | 41 | def getSelection(keyword, args, kwargs): |
|
42 | 42 | """getSelection returns '0' if keyword not a key in either args[0] or kwargs, |
|
43 | 43 | otherwise the value |
|
44 | 44 | |
|
45 | 45 | args, kwargs - arguments as passed into SingleExpDefaultForm __init__ |
|
46 | 46 | """ |
|
47 | 47 | if len(args) == 0 and len(list(kwargs.keys())) == 0: |
|
48 | 48 | return('0') # default case when no data passed in |
|
49 | 49 | elif len(args) > 0: |
|
50 | 50 | # args[0] is data dict argument to bind data |
|
51 | 51 | if keyword in args[0]: |
|
52 | 52 | return(args[0][keyword]) |
|
53 | 53 | else: |
|
54 | 54 | return('0') |
|
55 | 55 | elif keyword in kwargs: |
|
56 | 56 | return(kwargs[keyword]) |
|
57 | 57 | elif 'data' in kwargs: |
|
58 | 58 | if keyword in kwargs['data']: |
|
59 | 59 | return(kwargs['data'][keyword]) |
|
60 | 60 | else: |
|
61 | 61 | return('0') |
|
62 | 62 | else: |
|
63 | 63 | return('0') |
|
64 | 64 | |
|
65 | 65 | |
|
66 | 66 | def getIsGlobal(args, kwargs): |
|
67 | 67 | """getIsGlobal is a helper function returns True if 'isGlobal' not found in either args[0] or kwargs, |
|
68 | 68 | otherwise the bool of the value |
|
69 | 69 | |
|
70 | 70 | args, kwargs - arguments as passed into SingleExpDefaultForm __init__ |
|
71 | 71 | """ |
|
72 | 72 | if len(args) == 0 and len(list(kwargs.keys())) == 0: |
|
73 | 73 | return(True) # default case when no data passed in |
|
74 | 74 | elif len(args) > 0: |
|
75 | 75 | # args[0] is data dict argument to bind data |
|
76 | 76 | if 'isGlobal' in args[0]: |
|
77 | 77 | if args[0]['isGlobal'] == '0': |
|
78 | 78 | return(False) |
|
79 | 79 | else: |
|
80 | 80 | return(bool(args[0]['isGlobal'])) |
|
81 | 81 | else: |
|
82 | 82 | return(False) |
|
83 | 83 | elif 'data' in kwargs: |
|
84 | 84 | if 'isGlobal' in kwargs['data']: |
|
85 | 85 | if kwargs['data']['isGlobal'] == '0': |
|
86 | 86 | return(False) |
|
87 | 87 | else: |
|
88 | 88 | return(bool(kwargs['data']['isGlobal'])) |
|
89 | 89 | else: |
|
90 | 90 | return(False) |
|
91 | 91 | elif 'isGlobal' in kwargs: |
|
92 | 92 | if kwargs['isGlobal'] == '0': |
|
93 | 93 | return(False) |
|
94 | 94 | else: |
|
95 | 95 | return(bool(kwargs['isGlobal'])) |
|
96 | 96 | else: |
|
97 | 97 | return(False) |
|
98 | 98 | |
|
99 | 99 | |
|
100 | 100 | def getCategoryList(args, kwargs, madInstData, forList=False): |
|
101 | 101 | """getCategoryList is a helper function that returns the categories choices in |
|
102 | 102 | SingleExpDefaultForm.categories at runtime |
|
103 | 103 | |
|
104 | 104 | Inputs: |
|
105 | 105 | args, kwargs - arguments as passed into SingleExpDefaultForm __init__. Used only to |
|
106 | 106 | determine isGlobal |
|
107 | 107 | madInstData - madrigal.metadata.MadrigalInstrumentData object |
|
108 | 108 | forList - if False (the default) category list if for single interface, If True, for List interface |
|
109 | 109 | """ |
|
110 | 110 | if not forList: |
|
111 | 111 | local = not getIsGlobal(args, kwargs) |
|
112 | 112 | else: |
|
113 | 113 | local = False |
|
114 | 114 | categories = madInstData.getCategories(local) |
|
115 | 115 | if forList: |
|
116 | 116 | catList = [('0', 'All instrument categories'),] |
|
117 | 117 | else: |
|
118 | 118 | catList = [('0', 'Choose instrument type: '),] |
|
119 | 119 | for catID, catDesc in categories: |
|
120 | 120 | catList.append((str(catID), catDesc)) |
|
121 | 121 | return(catList) |
|
122 | 122 | |
|
123 | 123 | |
|
124 | 124 | |
|
125 | 125 | def getInstrumentList(args, kwargs, madInstData, header='Select an instrument: ', local=None, includeYears=False): |
|
126 | 126 | """getInstrumentList is a helper function that returns the instrument choices in |
|
127 | 127 | SingleExpDefaultForm.categories at runtime |
|
128 | 128 | |
|
129 | 129 | Inputs: |
|
130 | 130 | args, kwargs - arguments as passed into SingleExpDefaultForm __init__. Used to |
|
131 | 131 | determine categoryId and local |
|
132 | 132 | madInstData - madrigal.metadata.MadrigalInstrumentData object |
|
133 | 133 | header - text of first item in selection |
|
134 | 134 | local - if None (the default), set local flag via args and kwargs. If boolean, |
|
135 | 135 | set local flag to arg. |
|
136 | 136 | includeYear - if True, include data years in description. If False (the default), do not. |
|
137 | 137 | """ |
|
138 | 138 | if local is None: |
|
139 | 139 | local = not getIsGlobal(args, kwargs) |
|
140 | 140 | else: |
|
141 | 141 | local = bool(local) |
|
142 | 142 | if header == 'Select an instrument: ': |
|
143 | 143 | categoryId = int(getSelection('categories', args, kwargs)) |
|
144 | 144 | else: |
|
145 | 145 | categoryId = 0 |
|
146 | 146 | instruments = madInstData.getInstruments(categoryId, local) |
|
147 | 147 | instList = [('0', header),] |
|
148 | 148 | for kinst, instDesc, siteID in instruments: |
|
149 | 149 | if includeYears: |
|
150 | 150 | instYears = madInstData.getInstrumentYears(kinst) |
|
151 | 151 | instList.append((str(kinst), '%s [%i-%i]' % (instDesc, instYears[0], instYears[-1]))) |
|
152 | 152 | else: |
|
153 | 153 | instList.append((str(kinst), instDesc)) |
|
154 | 154 | return(instList) |
|
155 | 155 | |
|
156 | 156 | |
|
157 | 157 | def getYearList(args, kwargs, madInstData): |
|
158 | 158 | """getYearList is a helper function that returns the year choices in |
|
159 | 159 | SingleExpDefaultForm.categories at runtime |
|
160 | 160 | |
|
161 | 161 | Inputs: |
|
162 | 162 | args, kwargs - arguments as passed into SingleExpDefaultForm __init__. Used to |
|
163 | 163 | determine categoryId and local and kinst |
|
164 | 164 | madInstData - madrigal.metadata.MadrigalInstrumentData object |
|
165 | 165 | """ |
|
166 | 166 | local = not getIsGlobal(args, kwargs) |
|
167 | 167 | kinst = int(getSelection('instruments', args, kwargs)) |
|
168 | 168 | years = madInstData.getInstrumentYears(kinst) |
|
169 | 169 | yearsList = [('0', 'Select a year: '),] |
|
170 | 170 | for thisYear in reversed(years): |
|
171 | 171 | yearsList.append((str(thisYear), str(thisYear))) |
|
172 | 172 | return(yearsList) |
|
173 | 173 | |
|
174 | 174 | |
|
175 | 175 | def getMonthList(args, kwargs, madWebObj): |
|
176 | 176 | """getMonthList is a helper function that returns the month choices in |
|
177 | 177 | SingleExpDefaultForm.categories at runtime. Value is (month number, |
|
178 | 178 | month name) |
|
179 | 179 | |
|
180 | 180 | Inputs: |
|
181 | 181 | args, kwargs - arguments as passed into SingleExpDefaultForm __init__. Used to |
|
182 | 182 | determine and kinst and year |
|
183 | 183 | madWebObj - madrigal.ui.web.MadrigalWeb object |
|
184 | 184 | """ |
|
185 | 185 | kinst = int(getSelection('instruments', args, kwargs)) |
|
186 | 186 | year = int(getSelection('years', args, kwargs)) |
|
187 | 187 | monthList = [('0', 'Select a month: '),] |
|
188 | 188 | addedMonthList = madWebObj.getMonths(kinst, year) |
|
189 | 189 | if len(addedMonthList) == 0: |
|
190 | 190 | addedMonthList = madWebObj.getMonths(kinst, year, optimize=False) |
|
191 | 191 | monthList += addedMonthList |
|
192 | 192 | return([(str(monthNumber), monthName) for monthNumber, monthName in monthList]) |
|
193 | 193 | |
|
194 | 194 | |
|
195 | 195 | def getDayList(): |
|
196 | 196 | """always returns 1 ... 31 |
|
197 | 197 | """ |
|
198 | 198 | dayList = [(i, str(i)) for i in range(1,32)] |
|
199 | 199 | return(dayList) |
|
200 | 200 | |
|
201 | 201 | |
|
202 | 202 | def getExpList(args, kwargs, madWebObj): |
|
203 | 203 | """getExpList is a helper function that returns the experiment choices in |
|
204 | 204 | SingleExpDefaultForm.categories at runtime. Value is (expId, |
|
205 | 205 | expDesc, expDir, pi_name, pi_email) |
|
206 | 206 | |
|
207 | 207 | Inputs: |
|
208 | 208 | args, kwargs - arguments as passed into SingleExpDefaultForm __init__. Used to |
|
209 | 209 | determine and kinst, year, month, day |
|
210 | 210 | madWebObj - madrigal.ui.web.MadrigalWeb object |
|
211 | 211 | """ |
|
212 | 212 | kinst = int(getSelection('instruments', args, kwargs)) |
|
213 | 213 | year = int(getSelection('years', args, kwargs)) |
|
214 | 214 | month = int(getSelection('months', args, kwargs)) |
|
215 | 215 | day = int(getSelection('days', args, kwargs)) |
|
216 | 216 | expList = madWebObj.getExpsOnDate(kinst, year, month, day) |
|
217 | 217 | if len(expList) == 0: |
|
218 | 218 | expList = madWebObj.getExpsOnDate(kinst, year, month, day, optimize=False) |
|
219 | 219 | return(expList) |
|
220 | 220 | |
|
221 | 221 | |
|
222 | 222 | def handle_registration(kwargs, user_email, expUrl, kinst, madDB): |
|
223 | 223 | """handle_registration causes the user to register or unregister interest in getting emails |
|
224 | 224 | when a particular experiment or instrument is updated |
|
225 | 225 | |
|
226 | 226 | Inputs: |
|
227 | 227 | kwargs - dictionary as passed into form |
|
228 | 228 | user_email - users email address |
|
229 | 229 | expUrl - experiment url (part after /madtoc/) |
|
230 | 230 | kinst - instrument code |
|
231 | 231 | madDB - madrigal.metadata.MadrigalDB object |
|
232 | 232 | """ |
|
233 | 233 | # first find out if this exp or inst is already registered |
|
234 | 234 | madUserObj = madrigal.ui.userData.MadrigalUserData(madDB) |
|
235 | 235 | expsRegistered = madUserObj.getRegisteredExperiments(user_email) |
|
236 | 236 | if expUrl in expsRegistered: |
|
237 | 237 | thisExpRegistered = True |
|
238 | 238 | else: |
|
239 | 239 | thisExpRegistered = False |
|
240 | 240 | instsRegistered = madUserObj.getRegisteredInstruments(user_email) |
|
241 | 241 | if kinst in instsRegistered: |
|
242 | 242 | thisInstRegistered = True |
|
243 | 243 | else: |
|
244 | 244 | thisInstRegistered = False |
|
245 | 245 | |
|
246 | 246 | # check registration status, update if needed, and let form know how to print this |
|
247 | 247 | # 0 - no registration, 1 - exp registered, 2 - inst registered |
|
248 | 248 | if 'registerExp' in kwargs: |
|
249 | 249 | if not thisExpRegistered: |
|
250 | 250 | madUserObj.registerExperiment(user_email, expUrl) |
|
251 | 251 | return('1') |
|
252 | 252 | elif 'registerInst' in kwargs: |
|
253 | 253 | if not thisInstRegistered: |
|
254 | 254 | madUserObj.registerInstrument(user_email, kinst) |
|
255 | 255 | return('2') |
|
256 | 256 | elif 'unregisterExp' in kwargs: |
|
257 | 257 | if thisExpRegistered: |
|
258 | 258 | madUserObj.unregisterExperiment(user_email, expUrl) |
|
259 | 259 | return('0') |
|
260 | 260 | elif 'unregisterInst' in kwargs: |
|
261 | 261 | if thisInstRegistered: |
|
262 | 262 | madUserObj.unregisterInstrument(user_email, kinst) |
|
263 | 263 | return('0') |
|
264 | 264 | elif thisExpRegistered: |
|
265 | 265 | return('1') |
|
266 | 266 | elif thisInstRegistered: |
|
267 | 267 | return('2') |
|
268 | 268 | else: |
|
269 | 269 | return('0') |
|
270 | 270 | |
|
271 | 271 | |
|
272 | 272 | def getFormatChoices(basename, expID): |
|
273 | 273 | """getFormatChoices returns a list with 3 tuples, where each tuple |
|
274 | 274 | is 1. filename with correct extension, 2. Format |
|
275 | 275 | |
|
276 | 276 | Inputs: |
|
277 | 277 | basename - basename of Madrigal Hdf5 file |
|
278 | 278 | expID - needed to determine if cached file available in near real time |
|
279 | 279 | """ |
|
280 | 280 | madWebObj = madrigal.ui.web.MadrigalWeb() |
|
281 | 281 | formats = madWebObj.getFormatsAvailable(expID, basename) |
|
282 | 282 | fileName, fileExtension = os.path.splitext(basename) |
|
283 | 283 | retList = [] |
|
284 | 284 | retList.append((basename, 'Hdf5')) # file is assumed to be in Hdf5 format |
|
285 | 285 | if 'ascii' in formats: |
|
286 | 286 | retList.append((fileName + '.txt', 'Space-delimited ascii')) |
|
287 | 287 | if 'netCDF4' in formats: |
|
288 | 288 | retList.append((fileName + '.nc', 'netCDF4')) |
|
289 | 289 | return(retList) |
|
290 | 290 | |
|
291 | 291 | |
|
292 | 292 | class RegisterForm(django.forms.Form): |
|
293 | 293 | """RegisterForm is the form class that supports the Register page |
|
294 | 294 | """ |
|
295 | 295 | def __init__(self, *args, **kwargs): |
|
296 | 296 | super(RegisterForm, self).__init__(*args, **kwargs) |
|
297 | 297 | self.fields['user_fullname'] = django.forms.CharField(label='Full name', min_length=2, max_length=256) |
|
298 | 298 | self.fields['user_email'] = django.forms.EmailField(label='Email') |
|
299 | 299 | self.fields['user_affiliation'] = django.forms.CharField(label='Affliation (type "None" if individual)', min_length=2, max_length=256) |
|
300 | 300 | |
|
301 | 301 | |
|
302 | 302 | |
|
303 | 303 | class SingleExpDefaultForm(django.forms.Form): |
|
304 | 304 | """SingleExpDefaultForm is a Form class for the default fields in the Single Experiment interface |
|
305 | 305 | (formally the Simple interface) |
|
306 | 306 | """ |
|
307 | 307 | def __init__(self, *args, **kwargs): |
|
308 | 308 | super(SingleExpDefaultForm, self).__init__(*args, **kwargs) |
|
309 | 309 | madDB = madrigal.metadata.MadrigalDB() |
|
310 | 310 | madInstData = madrigal.metadata.MadrigalInstrumentData(madDB) |
|
311 | 311 | user_email = getSelection('user_email', args, kwargs) |
|
312 | 312 | self.fields['isGlobal'] = django.forms.BooleanField(widget = django.forms.CheckboxInput(attrs={"onChange":'populateCat(this)'}), |
|
313 | 313 | required=False, label='Use all Madrigal sites: ', |
|
314 | 314 | initial=getIsGlobal(args, kwargs)) |
|
315 | 315 | |
|
316 | 316 | |
|
317 | 317 | categoriesSelection = getSelection('categories', args, kwargs) |
|
318 | 318 | self.fields['categories'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'populateInst(this)'}), |
|
319 | 319 | choices=getCategoryList(args, kwargs, madInstData), |
|
320 | 320 | initial=categoriesSelection, |
|
321 | 321 | label='Instrument category:') |
|
322 | 322 | |
|
323 | 323 | # the following fields may or may not be populated. All are also available as individual classes |
|
324 | 324 | # to allow AJAX calls to not need to create this full object |
|
325 | 325 | |
|
326 | 326 | if categoriesSelection != '0': |
|
327 | 327 | instrumentSelection = getSelection('instruments', args, kwargs) |
|
328 | 328 | self.fields['instruments'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'populateYear(this)'}), |
|
329 | 329 | choices=getInstrumentList(args, kwargs, madInstData), |
|
330 | 330 | initial=instrumentSelection, |
|
331 | 331 | required=False, label='Instrument:') |
|
332 | 332 | else: |
|
333 | 333 | return # no need to create any further fields |
|
334 | 334 | |
|
335 | 335 | if instrumentSelection != '0': |
|
336 | 336 | yearSelection = getSelection('years', args, kwargs) |
|
337 | 337 | self.fields['years'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'populateMonth(this)'}), |
|
338 | 338 | choices=getYearList(args, kwargs, madInstData), |
|
339 | 339 | initial=yearSelection, |
|
340 | 340 | required=False, label='Year:') |
|
341 | 341 | |
|
342 | 342 | else: |
|
343 | 343 | return # no need to create any further fields |
|
344 | 344 | |
|
345 | 345 | if yearSelection != '0': |
|
346 | 346 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
347 | 347 | monthSelection = getSelection('months', args, kwargs) |
|
348 | 348 | self.fields['months'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'populateCalendar(this)'}), |
|
349 | 349 | choices=getMonthList(args, kwargs, madWebObj), |
|
350 | 350 | initial=monthSelection, label='Month:') |
|
351 | 351 | |
|
352 | 352 | else: |
|
353 | 353 | return # no need to create any further fields |
|
354 | 354 | |
|
355 | 355 | |
|
356 | 356 | if monthSelection != '0': |
|
357 | 357 | daySelection = getSelection('days', args, kwargs) |
|
358 | 358 | # this field is only used to help display the calendar |
|
359 | 359 | self.fields['days'] = django.forms.ChoiceField(required=False, choices=getDayList()) |
|
360 | 360 | |
|
361 | 361 | else: |
|
362 | 362 | return # no need to create any further fields |
|
363 | 363 | |
|
364 | 364 | if daySelection != '0': |
|
365 | 365 | expFullList = getExpList(args, kwargs, madWebObj) |
|
366 | 366 | expIdSelection = None |
|
367 | 367 | if len(expFullList) > 1: |
|
368 | 368 | expList = [('0', 'Select one of multiple experiments')] + [(items[0], items[1]) for items in expFullList] |
|
369 | 369 | expIdSelection = getSelection('experiment_list', args, kwargs) |
|
370 | 370 | self.fields['experiment_list'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'populateFile(this)'}), |
|
371 | 371 | choices=expList, initial=expIdSelection, |
|
372 | 372 | required=False, label='Select experiment:') |
|
373 | 373 | |
|
374 | 374 | if expIdSelection == '0': |
|
375 | 375 | # no need to create any further fields |
|
376 | 376 | return |
|
377 | 377 | |
|
378 | 378 | if expIdSelection is None: |
|
379 | 379 | expIdSelection = expFullList[0][0] |
|
380 | 380 | expDir = expFullList[0][2] |
|
381 | 381 | else: |
|
382 | 382 | expDir = None |
|
383 | 383 | for expId, thisExpDesc, thisExpDir in expFullList: |
|
384 | 384 | if int(expIdSelection) == int(expId): |
|
385 | 385 | expDir = thisExpDir |
|
386 | 386 | break |
|
387 | 387 | |
|
388 | 388 | fileList = madWebObj.getFileFromExpDir(expDir, int(instrumentSelection)) |
|
389 | 389 | fileList = [('0', 'Select file')] + fileList |
|
390 | 390 | fileSelection = getSelection('file_list', args, kwargs) |
|
391 | 391 | self.fields['file_list'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'changeFile(this)'}), |
|
392 | 392 | choices=fileList, initial=fileSelection, |
|
393 | 393 | required=False, label='Select file:') |
|
394 | 394 | self.fields['exp_id'] = django.forms.CharField(initial=str(expIdSelection), |
|
395 | 395 | widget=django.forms.HiddenInput(attrs={'value': str(expIdSelection)}), |
|
396 | 396 | required=False, |
|
397 | 397 | label=str(expIdSelection)) |
|
398 | 398 | |
|
399 | 399 | pi_name, pi_email, expUrl, kinst, expDesc, kinstDesc = madWebObj.getExpInfoFromExpID(int(expIdSelection)) |
|
400 | 400 | |
|
401 | 401 | self.fields['exp_desc'] = django.forms.CharField(initial=str(expDesc), |
|
402 | 402 | widget=django.forms.HiddenInput(attrs={'value': str(expDesc)}), |
|
403 | 403 | required=False, |
|
404 | 404 | label=str(expDesc)) |
|
405 | 405 | self.fields['user_email'] = django.forms.CharField(initial=str(user_email), |
|
406 | 406 | widget=django.forms.HiddenInput(attrs={'value': str(user_email)}), |
|
407 | 407 | required=False, |
|
408 | 408 | label=str(user_email)) |
|
409 | 409 | self.fields['inst_desc'] = django.forms.CharField(initial=str(kinstDesc), |
|
410 | 410 | widget=django.forms.HiddenInput(attrs={'value': str(kinstDesc)}), |
|
411 | 411 | required=False, |
|
412 | 412 | label=str(kinstDesc)) |
|
413 | 413 | self.fields['pi_name'] = django.forms.CharField(initial=pi_name, |
|
414 | 414 | widget=django.forms.HiddenInput(attrs={'value': pi_name}), |
|
415 | 415 | required=False, |
|
416 | 416 | label=pi_name) |
|
417 | 417 | self.fields['pi_email'] = django.forms.CharField(initial=pi_email, |
|
418 | 418 | widget=django.forms.HiddenInput(attrs={'value': pi_email}), |
|
419 | 419 | required=False, |
|
420 | 420 | label=pi_email) |
|
421 | 421 | |
|
422 | 422 | # handle any needed registration or unregistration |
|
423 | 423 | register = handle_registration(args[0], user_email, expUrl, kinst, madDB) |
|
424 | 424 | self.fields['register'] = django.forms.CharField(initial=register, |
|
425 | 425 | widget=django.forms.HiddenInput(attrs={'value': register}), |
|
426 | 426 | required=False, |
|
427 | 427 | label=register) |
|
428 | 428 | |
|
429 | 429 | |
|
430 | 430 | else: |
|
431 | 431 | return # no need to create any further fields |
|
432 | 432 | |
|
433 | 433 | if fileSelection != '0': |
|
434 | 434 | self.fields['file_buttons'] = django.forms.CharField(initial='', |
|
435 | 435 | widget=django.forms.HiddenInput(attrs={'value': ''}), |
|
436 | 436 | required=False, |
|
437 | 437 | label='') |
|
438 | 438 | |
|
439 | 439 | |
|
440 | 440 | else: |
|
441 | 441 | return # no need to create any further fields |
|
442 | 442 | |
|
443 | 443 | |
|
444 | 444 | |
|
445 | 445 | |
|
446 | 446 | |
|
447 | 447 | |
|
448 | 448 | |
|
449 | 449 | |
|
450 | 450 | |
|
451 | 451 | class SingleExpInstForm(django.forms.Form): |
|
452 | 452 | """SingleExpInstForm is a Form class for the instrument select field in the Single Experiment interface. |
|
453 | 453 | Use this because its faster to create than the full SingleExpDefaultForm |
|
454 | 454 | """ |
|
455 | 455 | def __init__(self, *args, **kwargs): |
|
456 | 456 | super(SingleExpInstForm, self).__init__(*args, **kwargs) |
|
457 | 457 | madDB = madrigal.metadata.MadrigalDB() |
|
458 | 458 | madInstData = madrigal.metadata.MadrigalInstrumentData(madDB) |
|
459 | 459 | instrumentSelection = getSelection('instruments', args, kwargs) |
|
460 | 460 | self.fields['instruments'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'populateYear(this)'}), |
|
461 | 461 | choices=getInstrumentList(args, kwargs, madInstData), |
|
462 | 462 | initial=instrumentSelection, |
|
463 | 463 | label='Instrument:') |
|
464 | 464 | |
|
465 | 465 | class SingleExpYearForm(django.forms.Form): |
|
466 | 466 | """SingleExpYearForm is a Form class for the year select field in the Single Experiment interface. |
|
467 | 467 | Use this because its faster to create than the full SingleExpDefaultForm |
|
468 | 468 | """ |
|
469 | 469 | def __init__(self, *args, **kwargs): |
|
470 | 470 | super(SingleExpYearForm, self).__init__(*args, **kwargs) |
|
471 | 471 | madDB = madrigal.metadata.MadrigalDB() |
|
472 | 472 | madInstData = madrigal.metadata.MadrigalInstrumentData(madDB) |
|
473 | 473 | yearSelection = getSelection('years', args, kwargs) |
|
474 | 474 | self.fields['years'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'populateMonth(this)'}), |
|
475 | 475 | choices=getYearList(args, kwargs, madInstData), |
|
476 | 476 | initial=yearSelection, label='Year:') |
|
477 | 477 | |
|
478 | 478 | |
|
479 | 479 | class SingleExpMonthForm(django.forms.Form): |
|
480 | 480 | """SingleExpMonthForm is a Form class for the month select field in the Single Experiment interface. |
|
481 | 481 | Use this because its faster to create than the full SingleExpDefaultForm |
|
482 | 482 | """ |
|
483 | 483 | def __init__(self, *args, **kwargs): |
|
484 | 484 | super(SingleExpMonthForm, self).__init__(*args, **kwargs) |
|
485 | 485 | madDB = madrigal.metadata.MadrigalDB() |
|
486 | 486 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
487 | 487 | monthSelection = getSelection('months', args, kwargs) |
|
488 | 488 | self.fields['months'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'populateCalendar(this)'}), |
|
489 | 489 | choices=getMonthList(args, kwargs, madWebObj), |
|
490 | 490 | initial=monthSelection, label='Month:') |
|
491 | 491 | |
|
492 | 492 | |
|
493 | 493 | class SingleExpCalendarForm(django.forms.Form): |
|
494 | 494 | """SingleExpCalendarForm is a Form class for the calendar field in the Single Experiment interface. |
|
495 | 495 | Use this because its faster to create than the full SingleExpDefaultForm |
|
496 | 496 | """ |
|
497 | 497 | def __init__(self, *args, **kwargs): |
|
498 | 498 | super(SingleExpCalendarForm, self).__init__(*args, **kwargs) |
|
499 | 499 | madDB = madrigal.metadata.MadrigalDB() |
|
500 | 500 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
501 | 501 | |
|
502 | 502 | |
|
503 | 503 | class SingleExpFileForm(django.forms.Form): |
|
504 | 504 | """SingleExpFileForm is a Form class for the file select field in the Single Experiment interface. |
|
505 | 505 | Use this because its faster to create than the full SingleExpDefaultForm |
|
506 | 506 | """ |
|
507 | 507 | def __init__(self, *args, **kwargs): |
|
508 | 508 | super(SingleExpFileForm, self).__init__(*args, **kwargs) |
|
509 | 509 | madDB = madrigal.metadata.MadrigalDB() |
|
510 | 510 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
511 | 511 | expID = getSelection('experiment_list', args, kwargs) |
|
512 | 512 | try: |
|
513 | 513 | expID = int(expID) |
|
514 | 514 | except ValueError: |
|
515 | 515 | # convert expPath to expID |
|
516 | 516 | expID = madWebObj.getExpIDFromExpPath(expID, True) |
|
517 | 517 | user_email = getSelection('user_email', args, kwargs) |
|
518 | 518 | include_non_default = getSelection('includeNonDefault', args, kwargs) |
|
519 | 519 | if include_non_default == '0': |
|
520 | 520 | include_non_default = False |
|
521 | 521 | fileList = madWebObj.getFileFromExpID(expID, include_non_default) |
|
522 | 522 | fileList = [('0', 'Select file')] + fileList |
|
523 | 523 | |
|
524 | 524 | fileSelection = getSelection('file_list', args, kwargs) |
|
525 | 525 | self.fields['file_list'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'changeFile(this)'}), |
|
526 | 526 | choices=fileList, initial=fileSelection, |
|
527 | 527 | required=False, label='Select file:') |
|
528 | 528 | if int(expID) != 0: |
|
529 | 529 | self.fields['exp_id'] = django.forms.CharField(initial=str(expID), |
|
530 | 530 | widget=django.forms.HiddenInput(attrs={'value': str(expID)}), |
|
531 | 531 | required=False, |
|
532 | 532 | label=str(expID)) |
|
533 | 533 | pi_name, pi_email, expUrl, kinst, expDesc, kinstDesc = madWebObj.getExpInfoFromExpID(int(expID)) |
|
534 | 534 | |
|
535 | 535 | self.fields['exp_desc'] = django.forms.CharField(initial=str(expDesc), |
|
536 | 536 | widget=django.forms.HiddenInput(attrs={'value': str(expDesc)}), |
|
537 | 537 | required=False, |
|
538 | 538 | label=str(expDesc)) |
|
539 | 539 | self.fields['user_email'] = django.forms.CharField(initial=str(user_email), |
|
540 | 540 | widget=django.forms.HiddenInput(attrs={'value': str(user_email)}), |
|
541 | 541 | required=False, |
|
542 | 542 | label=str(user_email)) |
|
543 | 543 | self.fields['inst_desc'] = django.forms.CharField(initial=str(kinstDesc), |
|
544 | 544 | widget=django.forms.HiddenInput(attrs={'value': str(kinstDesc)}), |
|
545 | 545 | required=False, |
|
546 | 546 | label=str(kinstDesc)) |
|
547 | 547 | self.fields['pi_name'] = django.forms.CharField(initial=pi_name, |
|
548 | 548 | widget=django.forms.HiddenInput(attrs={'value': pi_name}), |
|
549 | 549 | required=False, |
|
550 | 550 | label=pi_name) |
|
551 | 551 | self.fields['pi_email'] = django.forms.CharField(initial=pi_email, |
|
552 | 552 | widget=django.forms.HiddenInput(attrs={'value': pi_email}), |
|
553 | 553 | required=False, |
|
554 | 554 | label=pi_email) |
|
555 | 555 | self.fields['includeNonDefault'] = django.forms.BooleanField(widget = django.forms.CheckboxInput(attrs={"onChange":'reloadFiles(this)'}), |
|
556 | 556 | required=False, label='Show non-default files: ', |
|
557 | 557 | initial=include_non_default) |
|
558 | 558 | # handle any needed registration or unregistration |
|
559 | 559 | register = handle_registration(args[0], user_email, expUrl, kinst, madDB) |
|
560 | 560 | self.fields['register'] = django.forms.CharField(initial=register, |
|
561 | 561 | widget=django.forms.HiddenInput(attrs={'value': register}), |
|
562 | 562 | required=False, |
|
563 | 563 | label=register) |
|
564 | 564 | |
|
565 | 565 | if fileSelection != '0': |
|
566 | 566 | self.fields['file_buttons'] = django.forms.CharField(initial='', |
|
567 | 567 | widget=django.forms.HiddenInput(attrs={'value': ''}), |
|
568 | 568 | required=False, |
|
569 | 569 | label='') |
|
570 | 570 | self.fields['basename'] = django.forms.CharField(initial=str(fileSelection), |
|
571 | 571 | widget=django.forms.HiddenInput(attrs={'value': str(fileSelection)}), |
|
572 | 572 | required=False, |
|
573 | 573 | label=str(fileSelection)) |
|
574 | 574 | |
|
575 | 575 | |
|
576 | 576 | |
|
577 | 577 | |
|
578 | 578 | |
|
579 | 579 | class SingleExpButtonsForm(django.forms.Form): |
|
580 | 580 | """SingleExpButtonsForm is a Form class for the file buttons field in the Single Experiment interface. |
|
581 | 581 | Use this because its faster to create than the full SingleExpDefaultForm |
|
582 | 582 | """ |
|
583 | 583 | def __init__(self, *args, **kwargs): |
|
584 | 584 | super(SingleExpButtonsForm, self).__init__(*args, **kwargs) |
|
585 | 585 | madDB = madrigal.metadata.MadrigalDB() |
|
586 | 586 | madExpObj = madrigal.metadata.MadrigalExperiment(madDB) |
|
587 | 587 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
588 | 588 | expID = getSelection('experiment_list', args, kwargs) |
|
589 | 589 | try: |
|
590 | 590 | expID = int(expID) |
|
591 | 591 | except ValueError: |
|
592 | 592 | # convert expPath to expID |
|
593 | 593 | expID = madWebObj.getExpIDFromExpPath(expID, True) |
|
594 | 594 | |
|
595 | 595 | fileSelection = getSelection('file_list', args, kwargs) |
|
596 | 596 | |
|
597 | 597 | expDir = madExpObj.getExpDirByExpId(int(expID)) |
|
598 | 598 | filesize = os.path.getsize(os.path.join(expDir, str(fileSelection))) |
|
599 | 599 | |
|
600 | 600 | self.fields['file_buttons'] = django.forms.CharField(initial='', |
|
601 | 601 | widget=django.forms.HiddenInput(attrs={'value': ''}), |
|
602 | 602 | required=False, |
|
603 | 603 | label='') |
|
604 | 604 | self.fields['exp_id'] = django.forms.CharField(initial=str(expID), |
|
605 | 605 | widget=django.forms.HiddenInput(attrs={'value': str(expID)}), |
|
606 | 606 | required=False, |
|
607 | 607 | label=str(expID)) |
|
608 | 608 | self.fields['basename'] = django.forms.CharField(initial=str(fileSelection), |
|
609 | 609 | widget=django.forms.HiddenInput(attrs={'value': str(fileSelection)}), |
|
610 | 610 | required=False, |
|
611 | 611 | label=str(fileSelection)) |
|
612 | 612 | self.fields['filesize'] = django.forms.IntegerField(initial=filesize, |
|
613 | 613 | widget=django.forms.HiddenInput(attrs={'value': filesize}), |
|
614 | 614 | required=False, |
|
615 | 615 | label=str(filesize)) |
|
616 | 616 | |
|
617 | 617 | |
|
618 | 618 | class SingleExpPlotsForm(django.forms.Form): |
|
619 | 619 | """SingleExpPlotsForm is a Form class for the file data/show plots field in the Single Experiment interface. |
|
620 | 620 | Use this because its faster to create than the full SingleExpDefaultForm |
|
621 | 621 | """ |
|
622 | 622 | def __init__(self, *args, **kwargs): |
|
623 | 623 | super(SingleExpPlotsForm, self).__init__(*args, **kwargs) |
|
624 | 624 | madDB = madrigal.metadata.MadrigalDB() |
|
625 | 625 | madExpObj = madrigal.metadata.MadrigalExperiment(madDB) |
|
626 | 626 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
627 | 627 | expID = getSelection('experiment_list', args, kwargs) |
|
628 | 628 | try: |
|
629 | 629 | expID = int(expID) |
|
630 | 630 | except ValueError: |
|
631 | 631 | # convert expPath to expID |
|
632 | 632 | expID = madWebObj.getExpIDFromExpPath(expID, True) |
|
633 | 633 | plotList = madExpObj.getExpLinksByExpId(expID) |
|
634 | 634 | if len(plotList) == 0: |
|
635 | 635 | plotList = [('No plots available', '')] |
|
636 | 636 | |
|
637 | 637 | self.fields['plot_list'] = django.forms.ChoiceField(widget = django.forms.Select(), |
|
638 | 638 | choices=plotList, |
|
639 | 639 | required=False) |
|
640 | 640 | |
|
641 | 641 | '''get_params2 retrieves a list of 1d and 2d parameters of type 1 hdf5 files''' |
|
642 | 642 | |
|
643 | 643 | def check_mnemonic(s): |
|
644 | 644 | |
|
645 | s.replace('vipe1', 'vipe') | |
|
646 | s.replace('vipe2', 'vipe') | |
|
647 | s.replace('vipn1', 'vipn') | |
|
648 | s.replace('vipn2', 'vipn') | |
|
649 | s.replace('vi72', 'vi7') | |
|
650 | s.replace('vi82', 'vi8') | |
|
651 | s.replace('dvipe1', 'dvipe') | |
|
652 | s.replace('dvipe2', 'dvipe') | |
|
653 | s.replace('dvipn1', 'dvipn') | |
|
654 | s.replace('dvipn2', 'dvipn') | |
|
655 | s.replace('dvi72', 'dvi7') | |
|
656 | s.replace('dvi82', 'dvi8') | |
|
645 | 657 | return s.replace('+', '%2b') |
|
646 | 658 | |
|
647 | 659 | def get_params1(args, kwargs, madExpObj, madWebObj): |
|
648 | 660 | |
|
649 | 661 | expID = getSelection('experiment_list', args, kwargs) |
|
650 | 662 | expDir = madExpObj.getExpDirByExpId(expID) |
|
651 | 663 | fileList = madWebObj.getFileFromExpID(expID, False) |
|
652 | 664 | |
|
653 | 665 | firsttuple = [a_tuple[0] for a_tuple in fileList] |
|
654 | 666 | basename = firsttuple[0] |
|
655 | 667 | fullFilename = os.path.join(expDir, basename) |
|
656 | 668 | f = h5py.File(fullFilename, "r") |
|
657 | 669 | |
|
658 | 670 | data = f['Data'] |
|
659 | 671 | |
|
660 | 672 | choices1d = [(check_mnemonic(x[0].decode().lower()), x[1].decode()) for x in data['Array Layout']['1D Parameters']['Data Parameters']] |
|
661 | 673 | choices2d = [(check_mnemonic(x[0].decode().lower()), x[1].decode()) for x in data['Array Layout']['2D Parameters']['Data Parameters']] |
|
662 | 674 | choices = [[('0', 'Select Parameter')] + choices1d, [('0', 'Select Parameter')] + choices2d] |
|
663 | 675 | f.close() |
|
664 | 676 | return choices |
|
665 | 677 | |
|
666 | 678 | |
|
667 | 679 | '''get params2 retrieves a list of 1d parameters of type 2 of hdf5 files''' |
|
668 | 680 | def get_params2(args, kwargs, madExpObj, madWebObj): |
|
669 | 681 | |
|
670 | 682 | expID = getSelection('experiment_list', args, kwargs) |
|
671 | 683 | expDir = madExpObj.getExpDirByExpId(expID) |
|
672 | 684 | fileList = madWebObj.getFileFromExpID(expID, False) |
|
673 | 685 | |
|
674 | 686 | firsttuple = [a_tuple[0] for a_tuple in fileList] |
|
675 | 687 | basename = firsttuple[0] |
|
676 | 688 | fullFilename = os.path.join(expDir, basename) |
|
677 | 689 | f = h5py.File(fullFilename, "r") |
|
678 | 690 | parameters = [(x[0].decode().lower(), x[1].decode()) for x in f['Metadata']['Data Parameters']] |
|
679 | 691 | f.close() |
|
680 | 692 | return [('0', 'Select Parameter')] + parameters |
|
681 | 693 | |
|
682 | 694 | |
|
683 | 695 | class SingleExpPlotsSelectionForm(django.forms.Form): |
|
684 | 696 | """SingleExpPlotsSselectionForm is a Form class for the parameters selection for plotting in the Single Experiment interface. |
|
685 | 697 | Use this because its faster to create than the full SingleExpDefaultForm |
|
686 | 698 | """ |
|
687 | 699 | |
|
688 | 700 | def __init__(self, *args, **kwargs): |
|
689 | 701 | super(SingleExpPlotsSelectionForm, self).__init__(*args, **kwargs) |
|
690 | 702 | madDB = madrigal.metadata.MadrigalDB() |
|
691 | 703 | madExpObj = madrigal.metadata.MadrigalExperiment(madDB) |
|
692 | 704 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
693 | 705 | expID = getSelection('experiment_list', args, kwargs) |
|
694 | 706 | try: |
|
695 | 707 | expID = int(expID) |
|
696 | 708 | except ValueError: |
|
697 | 709 | # convert expPath to expID |
|
698 | 710 | expID = madWebObj.getExpIDFromExpPath(expID, True) |
|
699 | 711 | expDir = madExpObj.getExpDirByExpId(expID) |
|
700 | 712 | fileList = madWebObj.getFileFromExpID(expID, False) |
|
701 | 713 | |
|
702 | 714 | firsttuple = [a_tuple[0] for a_tuple in fileList] |
|
703 | 715 | basename = firsttuple[0] |
|
704 | 716 | fullFilename = os.path.join(expDir, basename) |
|
705 | 717 | f = h5py.File(fullFilename, "r") |
|
706 | 718 | data = f[list(f.keys())[0]] |
|
707 | 719 | |
|
708 | 720 | if 'Array Layout' in list(data.keys()): |
|
709 | 721 | choices = get_params1(args, kwargs, madExpObj, madWebObj) |
|
710 | 722 | params1d = choices[0] |
|
711 | 723 | params2d = choices[1] |
|
712 | 724 | self.fields['param_list1d'] = django.forms.ChoiceField(widget = django.forms.Select(), choices=params1d, label="1D Parameters", required=False) |
|
713 | 725 | self.fields['param_list2d'] = django.forms.ChoiceField(widget = django.forms.Select(), choices=params2d, label="2D Parameters", required=False) |
|
714 | 726 | |
|
715 | 727 | else: |
|
716 | 728 | params1d = get_params2(args, kwargs, madExpObj, madWebObj) |
|
717 | 729 | self.fields['param_list1d'] = django.forms.ChoiceField(widget = django.forms.Select(), choices=params1d, label="1D Parameters", required=False) |
|
718 | 730 | |
|
719 | 731 | |
|
720 | 732 | class SingleExpDownloadAsIsForm(django.forms.Form): |
|
721 | 733 | """SingleExpDownloadAsIsForm is a Form class for the download as is field in the Single Experiment interface. |
|
722 | 734 | Use this because its faster to create than the full SingleExpDefaultForm |
|
723 | 735 | """ |
|
724 | 736 | def __init__(self, *args, **kwargs): |
|
725 | 737 | super(SingleExpDownloadAsIsForm, self).__init__(*args, **kwargs) |
|
726 | 738 | basename = getSelection('format_select', args, kwargs) |
|
727 | 739 | expID = int(getSelection('expID', args, kwargs)) |
|
728 | 740 | formatChoices = getFormatChoices(basename, expID) |
|
729 | 741 | |
|
730 | 742 | self.fields['format_select'] = django.forms.ChoiceField(widget = HorizontalRadioSelect(attrs={"onChange":'changeFormat(this)'}), |
|
731 | 743 | choices=formatChoices, |
|
732 | 744 | required=False) |
|
733 | 745 | |
|
734 | 746 | |
|
735 | 747 | |
|
736 | 748 | |
|
737 | 749 | class IsprintChoiceField(django.forms.TypedMultipleChoiceField): |
|
738 | 750 | """IsprintChoiceField is subclass of TypedMultipleChoiceField |
|
739 | 751 | """ |
|
740 | 752 | def __init__(self, *args, **kwargs): |
|
741 | 753 | """__init__ allows all the arguments of TypedMultipleChoiceField, plus extra |
|
742 | 754 | keyword arguments: |
|
743 | 755 | madWebObject madrigal.ui.web.MadrigalWeb object |
|
744 | 756 | """ |
|
745 | 757 | self.isDerivedDict = kwargs.pop('isDerivedDict') |
|
746 | 758 | self.parmDescDict = kwargs.pop('parmDescDict') |
|
747 | 759 | try: |
|
748 | 760 | self.separateProlog = kwargs.pop('separateProlog') |
|
749 | 761 | except: |
|
750 | 762 | self.separateProlog = False |
|
751 | 763 | |
|
752 | 764 | kwargs['widget'] = IsprintWidget(attrs={'isDerivedDict':self.isDerivedDict, |
|
753 | 765 | 'parmDescDict':self.parmDescDict, |
|
754 | 766 | 'separateProlog':self.separateProlog}) |
|
755 | 767 | super(IsprintChoiceField, self).__init__(*args, **kwargs) |
|
756 | 768 | self.widget.set_parm_lists(self.isDerivedDict, self.parmDescDict, self.separateProlog) |
|
757 | 769 | |
|
758 | 770 | |
|
759 | 771 | |
|
760 | 772 | |
|
761 | 773 | class IsprintWidget(django.forms.CheckboxSelectMultiple): |
|
762 | 774 | """IsprintWidget is a subclass of CheckboxSelectMultiple with additional parameters passed in |
|
763 | 775 | to modify rendering |
|
764 | 776 | """ |
|
765 | 777 | def __init__(self, *args, **kwargs): |
|
766 | 778 | """__init__ allows all the arguments of CheckboxSelectMultiple, plus extra |
|
767 | 779 | keyword arguments: |
|
768 | 780 | madWebObject madrigal.ui.web.MadrigalWeb object |
|
769 | 781 | """ |
|
770 | 782 | super(IsprintWidget, self).__init__(*args, **kwargs) |
|
771 | 783 | self.renderer = django.forms.CheckboxSelectMultiple |
|
772 | 784 | self.template_name = 'madweb/parameter_multiple.html' |
|
773 | 785 | |
|
774 | 786 | |
|
775 | 787 | def set_parm_lists(self, isDerivedDict, parmDescDict, separateProlog=False): |
|
776 | 788 | """set_parm_lists sets class variables used by the html renderer |
|
777 | 789 | |
|
778 | 790 | measParmList - parms in the file |
|
779 | 791 | derivedParmList - parms derivable |
|
780 | 792 | allParmList - above lists combined |
|
781 | 793 | separateProlog - if true, create separate div tags so prolog parms can be hidden or not. |
|
782 | 794 | Default is False, in which case no div tags are used |
|
783 | 795 | """ |
|
784 | 796 | self.renderer.isDerivedDict = isDerivedDict |
|
785 | 797 | self.renderer.parmDescDict = parmDescDict |
|
786 | 798 | self.renderer.iterator = itertools.count() |
|
787 | 799 | self.renderer.separateProlog = separateProlog |
|
788 | 800 | |
|
789 | 801 | |
|
790 | 802 | |
|
791 | 803 | |
|
792 | 804 | class IsprintForm(django.forms.Form): |
|
793 | 805 | """IsprintForm is the form for the enhanced isprint page |
|
794 | 806 | """ |
|
795 | 807 | def __init__(self, *args, **kwargs): |
|
796 | 808 | |
|
797 | 809 | madFileObj = getSelection('madFileObj', args, kwargs) |
|
798 | 810 | type = getSelection('type', args, kwargs) |
|
799 | 811 | formatChoices = [('ascii', 'Space-delimited ascii')] |
|
800 | 812 | if type == 'download': |
|
801 | 813 | formatChoices.insert(0, ('netCDF4', 'netCDF4')) |
|
802 | 814 | formatChoices.insert(0, ('Hdf5', 'Hdf5')) |
|
803 | 815 | separateProlog = True |
|
804 | 816 | else: |
|
805 | 817 | separateProlog = False |
|
806 | 818 | |
|
807 | 819 | madDB = getSelection('madDB', args, kwargs) |
|
808 | 820 | madParmObj = getSelection('madParmObj', args, kwargs) |
|
809 | 821 | derivedParmList = getSelection('derivedParmList', args, kwargs) |
|
810 | 822 | allParmList = getSelection('allParmList', args, kwargs) |
|
811 | 823 | allParmDescList = getSelection('allParmDescList', args, kwargs) |
|
812 | 824 | self.parmList = list(zip(allParmList, allParmDescList)) |
|
813 | 825 | super(IsprintForm, self).__init__(*args, **kwargs) |
|
814 | 826 | |
|
815 | 827 | madCatObj = madrigal.metadata.MadrigalParmCategory(madDB) |
|
816 | 828 | |
|
817 | 829 | catList = madCatObj.getCategoryList() |
|
818 | 830 | catDict = madParmObj.getCategoryDict(allParmList) |
|
819 | 831 | |
|
820 | 832 | choices = [] |
|
821 | 833 | isDerivedDict = {} |
|
822 | 834 | parmDescDict = {} |
|
823 | 835 | for catDesc, catID in catList: |
|
824 | 836 | if catID not in list(catDict.keys()): |
|
825 | 837 | continue |
|
826 | 838 | theseParms = [] |
|
827 | 839 | for parm in catDict[catID][1]: |
|
828 | 840 | theseParms.append((parm, parm)) |
|
829 | 841 | if parm in derivedParmList: |
|
830 | 842 | isDerivedDict[parm] = True |
|
831 | 843 | else: |
|
832 | 844 | isDerivedDict[parm] = False |
|
833 | 845 | parmDescDict[parm] = madParmObj.getParmDescription(parm) |
|
834 | 846 | choices.append((catDesc, theseParms)) |
|
835 | 847 | |
|
836 | 848 | choices_with_null = [('None', 'None')] + choices |
|
837 | 849 | |
|
838 | 850 | earliestTime = madFileObj.getEarliestTime() |
|
839 | 851 | latestTime = madFileObj.getLatestTime() |
|
840 | 852 | earliestDT = datetime.datetime(*earliestTime) |
|
841 | 853 | latestDT = datetime.datetime(*latestTime) |
|
842 | 854 | earliestStr = earliestDT.strftime('%Y-%m-%d %H:%M:%S') |
|
843 | 855 | latestStr = latestDT.strftime('%Y-%m-%d %H:%M:%S') |
|
844 | 856 | |
|
845 | 857 | self.fields['fullFilename'] = django.forms.CharField(required=False, widget=django.forms.HiddenInput()) |
|
846 | 858 | self.fields['type'] = django.forms.CharField(required=False, widget=django.forms.HiddenInput()) |
|
847 | 859 | |
|
848 | 860 | # format fields |
|
849 | 861 | self.fields['formats'] = django.forms.ChoiceField(widget = HorizontalRadioSelect(attrs={"onChange":'changeFormat(this)'}), |
|
850 | 862 | choices=formatChoices, initial='ascii', |
|
851 | 863 | required=False, label='Select output format:') |
|
852 | 864 | |
|
853 | 865 | self.fields['showHeaders'] = django.forms.BooleanField(required=False, label='Show headers:', |
|
854 | 866 | help_text="Select this to show a header line before each record") |
|
855 | 867 | |
|
856 | 868 | self.fields['missing'] = django.forms.CharField(required=False, |
|
857 | 869 | label='Missing value string: ', |
|
858 | 870 | help_text='Modify this field to display something other than NaN for missing or assumed or known bad data.') |
|
859 | 871 | |
|
860 | 872 | # form fields |
|
861 | 873 | self.fields['parameters'] = IsprintChoiceField(choices=choices, |
|
862 | 874 | required=False, |
|
863 | 875 | initial=['YEAR', 'MIN'], |
|
864 | 876 | isDerivedDict=isDerivedDict, |
|
865 | 877 | parmDescDict=parmDescDict, |
|
866 | 878 | separateProlog=separateProlog, |
|
867 | 879 | label = "") |
|
868 | 880 | |
|
869 | 881 | # time selection |
|
870 | 882 | self.fields['start_date'] = django.forms.DateTimeField(input_formats=['%Y-%m-%dT%H:%M:%S'], |
|
871 | 883 | label='Start datetime', |
|
872 | 884 | help_text='Modify this field to remove all records before this start time. Initial start datetime is the time of the first record.', |
|
873 | 885 | widget=django.forms.DateTimeInput(format='%Y-%m-%dT%H:%M:%S'), |
|
874 | 886 | required=False) |
|
875 | 887 | |
|
876 | 888 | self.fields['end_date'] = django.forms.DateTimeField(input_formats=['%Y-%m-%dT%H:%M:%S'], |
|
877 | 889 | label='End datetime', |
|
878 | 890 | help_text='Modify this field to remove all records after this end time. Initial end datetime is the time of the last record.', |
|
879 | 891 | widget=django.forms.DateTimeInput(format='%Y-%m-%dT%H:%M:%S'), |
|
880 | 892 | required=False) |
|
881 | 893 | |
|
882 | 894 | self.fields['parm_1'] = django.forms.ChoiceField(required=False, |
|
883 | 895 | choices=choices_with_null) |
|
884 | 896 | self.fields['parm_1_lower'] = django.forms.CharField(required=False, initial='') |
|
885 | 897 | self.fields['parm_1_upper'] = django.forms.CharField(required=False, initial='') |
|
886 | 898 | |
|
887 | 899 | self.fields['parm_2'] = django.forms.ChoiceField(required=False, |
|
888 | 900 | choices=choices_with_null) |
|
889 | 901 | self.fields['parm_2_lower'] = django.forms.CharField(required=False, initial='') |
|
890 | 902 | self.fields['parm_2_upper'] = django.forms.CharField(required=False, initial='') |
|
891 | 903 | |
|
892 | 904 | self.fields['parm_3'] = django.forms.ChoiceField(required=False, |
|
893 | 905 | choices=choices_with_null) |
|
894 | 906 | self.fields['parm_3_lower'] = django.forms.CharField(required=False, initial='') |
|
895 | 907 | self.fields['parm_3_upper'] = django.forms.CharField(required=False, initial='') |
|
896 | 908 | |
|
897 | 909 | # add optional fields |
|
898 | 910 | if 'GDALT' in allParmList: |
|
899 | 911 | min_alt_value = getSelection('min_alt', args, kwargs) |
|
900 | 912 | max_alt_value = getSelection('max_alt', args, kwargs) |
|
901 | 913 | if min_alt_value != max_alt_value: |
|
902 | 914 | self.fields['min_alt'] = django.forms.CharField(required=False, |
|
903 | 915 | label='Min altitude:', |
|
904 | 916 | help_text='Modify this field to remove all data with altitudes below this level.') |
|
905 | 917 | self.fields['max_alt'] = django.forms.CharField(required=False, |
|
906 | 918 | label='Max altitude:', |
|
907 | 919 | help_text='Modify this field to remove all data with altitudes above this level.') |
|
908 | 920 | |
|
909 | 921 | if 'AZM' in allParmList: |
|
910 | 922 | self.fields['min_az'] = django.forms.CharField(required=False, |
|
911 | 923 | label='Min azimuth:', |
|
912 | 924 | 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.') |
|
913 | 925 | self.fields['max_az'] = django.forms.CharField(required=False, |
|
914 | 926 | label='Max azimuth:', |
|
915 | 927 | 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.') |
|
916 | 928 | self.fields['min_az2'] = django.forms.CharField(required=False, |
|
917 | 929 | label='Min azimuth 2:', |
|
918 | 930 | help_text='Modify this field to have a second allowed azimuth range. This would set the lower limit of the second range.') |
|
919 | 931 | self.fields['max_az2'] = django.forms.CharField(required=False, |
|
920 | 932 | label='Max azimuth 2:', |
|
921 | 933 | help_text='Modify this field to have a second allowed azimuth range. This would set the upper limit of the second range.') |
|
922 | 934 | |
|
923 | 935 | if 'ELM' in allParmList: |
|
924 | 936 | self.fields['min_el'] = django.forms.CharField(required=False, |
|
925 | 937 | label='Min elevation:', |
|
926 | 938 | 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.') |
|
927 | 939 | self.fields['max_el'] = django.forms.CharField(required=False, |
|
928 | 940 | label='Max elevation:', |
|
929 | 941 | 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.') |
|
930 | 942 | self.fields['min_el2'] = django.forms.CharField(required=False, |
|
931 | 943 | label='Min elevation 2:', |
|
932 | 944 | help_text='Modify this field to have a second allowed elevation range. This would set the lower limit of the second range.') |
|
933 | 945 | self.fields['max_el2'] = django.forms.CharField(required=False, |
|
934 | 946 | label='Max elevation 2:', |
|
935 | 947 | help_text='Modify this field to have a second allowed elevation range. This would set the upper limit of the second range.') |
|
936 | 948 | |
|
937 | 949 | if 'PL' in allParmList: |
|
938 | 950 | min_pl_value = getSelection('min_pl', args, kwargs) |
|
939 | 951 | max_pl_value = getSelection('max_pl', args, kwargs) |
|
940 | 952 | self.fields['min_pl'] = django.forms.CharField(required=False, |
|
941 | 953 | label='Min pulse len (microsec): ', |
|
942 | 954 | help_text='Modify this field to remove all pulse lengths in microsecs below this value.') |
|
943 | 955 | self.fields['max_pl'] = django.forms.CharField(required=False, |
|
944 | 956 | label='Max pulse len (microsec): ', |
|
945 | 957 | help_text='Modify this field to remove all pulse lengths in microsecs above this value.') |
|
946 | 958 | |
|
947 | 959 | |
|
948 | 960 | def clean_fullFilename(self): |
|
949 | 961 | fullFilename = self.cleaned_data['fullFilename'] |
|
950 | 962 | # make sure the file exists |
|
951 | 963 | if not os.access(fullFilename, os.R_OK): |
|
952 | 964 | raise django.forms.ValidationError('Invalid filename: %(value)s cannot be opened', |
|
953 | 965 | code='io_error', |
|
954 | 966 | params={'value': fullFilename}) |
|
955 | 967 | |
|
956 | 968 | return(fullFilename) |
|
957 | 969 | |
|
958 | 970 | |
|
959 | 971 | def clean_formats(self): |
|
960 | 972 | formats = self.cleaned_data['formats'] |
|
961 | 973 | # make sure the format valid |
|
962 | 974 | if formats not in ('Hdf5', 'netCDF4', 'ascii'): |
|
963 | 975 | raise django.forms.ValidationError('Invalid format: %(value)s not legal format', |
|
964 | 976 | code='invalid', |
|
965 | 977 | params={'value': formats}) |
|
966 | 978 | |
|
967 | 979 | return(formats) |
|
968 | 980 | |
|
969 | 981 | |
|
970 | 982 | def clean_min_alt(self): |
|
971 | 983 | min_alt = self.cleaned_data['min_alt'] |
|
972 | 984 | if len(min_alt) != 0: |
|
973 | 985 | try: |
|
974 | 986 | min_alt_value = float(min_alt) |
|
975 | 987 | except: |
|
976 | 988 | raise django.forms.ValidationError('Invalid minimum altitude: %(value)s cannot be converted to a float', |
|
977 | 989 | code='invalid', |
|
978 | 990 | params={'value': min_alt}) |
|
979 | 991 | if min_alt_value < 0.0: |
|
980 | 992 | raise django.forms.ValidationError('Invalid minimum altitude: %(value)s cannot be less than 0.0 kilometers', |
|
981 | 993 | code='invalid', |
|
982 | 994 | params={'value': min_alt}) |
|
983 | 995 | return(min_alt) |
|
984 | 996 | |
|
985 | 997 | def clean_max_alt(self): |
|
986 | 998 | max_alt = self.cleaned_data['max_alt'] |
|
987 | 999 | if len(max_alt) != 0: |
|
988 | 1000 | try: |
|
989 | 1001 | max_alt_value = float(max_alt) |
|
990 | 1002 | except: |
|
991 | 1003 | raise django.forms.ValidationError('Invalid maximum altitude: %(value)s cannot be converted to a float', |
|
992 | 1004 | code='invalid', |
|
993 | 1005 | params={'value': max_alt}) |
|
994 | 1006 | if max_alt_value < 0.0: |
|
995 | 1007 | raise django.forms.ValidationError('Invalid maximum altitude: %(value)s cannot be less than 0.0 kilometers', |
|
996 | 1008 | code='invalid', |
|
997 | 1009 | params={'value': max_alt}) |
|
998 | 1010 | return(max_alt) |
|
999 | 1011 | |
|
1000 | 1012 | |
|
1001 | 1013 | def clean_min_az(self): |
|
1002 | 1014 | min_az = self.cleaned_data['min_az'] |
|
1003 | 1015 | if len(min_az) != 0: |
|
1004 | 1016 | try: |
|
1005 | 1017 | min_az_value = float(min_az) |
|
1006 | 1018 | except: |
|
1007 | 1019 | raise django.forms.ValidationError('Invalid minimum azimuth: %(value)s cannot be converted to a float', |
|
1008 | 1020 | code='invalid', |
|
1009 | 1021 | params={'value': min_az}) |
|
1010 | 1022 | if min_az_value < -180.0: |
|
1011 | 1023 | raise django.forms.ValidationError('Invalid minimum azimuth: %(value)s cannot be less than -180 degrees', |
|
1012 | 1024 | code='invalid', |
|
1013 | 1025 | params={'value': min_az}) |
|
1014 | 1026 | if min_az_value > 180.0: |
|
1015 | 1027 | raise django.forms.ValidationError('Invalid minimum azimuth: %(value)s cannot be more than 180 degrees', |
|
1016 | 1028 | code='invalid', |
|
1017 | 1029 | params={'value': min_az}) |
|
1018 | 1030 | return(min_az) |
|
1019 | 1031 | |
|
1020 | 1032 | |
|
1021 | 1033 | def clean_max_az(self): |
|
1022 | 1034 | max_az = self.cleaned_data['max_az'] |
|
1023 | 1035 | if len(max_az) != 0: |
|
1024 | 1036 | try: |
|
1025 | 1037 | max_az_value = float(max_az) |
|
1026 | 1038 | except: |
|
1027 | 1039 | raise django.forms.ValidationError('Invalid maximum azimuth: %(value)s cannot be converted to a float', |
|
1028 | 1040 | code='invalid', |
|
1029 | 1041 | params={'value': max_az}) |
|
1030 | 1042 | if max_az_value < -180.0: |
|
1031 | 1043 | raise django.forms.ValidationError('Invalid maximum azimuth: %(value)s cannot be less than -180 degrees', |
|
1032 | 1044 | code='invalid', |
|
1033 | 1045 | params={'value': max_az}) |
|
1034 | 1046 | if max_az_value > 180.0: |
|
1035 | 1047 | raise django.forms.ValidationError('Invalid maximum azimuth: %(value)s cannot be more than 180 degrees', |
|
1036 | 1048 | code='invalid', |
|
1037 | 1049 | params={'value': max_az}) |
|
1038 | 1050 | return(max_az) |
|
1039 | 1051 | |
|
1040 | 1052 | |
|
1041 | 1053 | def clean_min_el(self): |
|
1042 | 1054 | min_el = self.cleaned_data['min_el'] |
|
1043 | 1055 | if len(min_el) != 0: |
|
1044 | 1056 | try: |
|
1045 | 1057 | min_el_value = float(min_el) |
|
1046 | 1058 | except: |
|
1047 | 1059 | raise django.forms.ValidationError('Invalid minimum elevation: %(value)s cannot be converted to a float', |
|
1048 | 1060 | code='invalid', |
|
1049 | 1061 | params={'value': min_el}) |
|
1050 | 1062 | if min_el_value < 0.0: |
|
1051 | 1063 | raise django.forms.ValidationError('Invalid minimum elevation: %(value)s cannot be less than 0 degrees', |
|
1052 | 1064 | code='invalid', |
|
1053 | 1065 | params={'value': min_el}) |
|
1054 | 1066 | if min_el_value > 90.0: |
|
1055 | 1067 | raise django.forms.ValidationError('Invalid minimum elevation: %(value)s cannot be more than 90 degrees', |
|
1056 | 1068 | code='invalid', |
|
1057 | 1069 | params={'value': min_el}) |
|
1058 | 1070 | return(min_el) |
|
1059 | 1071 | |
|
1060 | 1072 | |
|
1061 | 1073 | def clean_max_el(self): |
|
1062 | 1074 | max_el = self.cleaned_data['max_el'] |
|
1063 | 1075 | if len(max_el) != 0: |
|
1064 | 1076 | try: |
|
1065 | 1077 | max_el_value = float(max_el) |
|
1066 | 1078 | except: |
|
1067 | 1079 | raise django.forms.ValidationError('Invalid maximum elevation: %(value)s cannot be converted to a float', |
|
1068 | 1080 | code='invalid', |
|
1069 | 1081 | params={'value': max_el}) |
|
1070 | 1082 | if max_el_value < 0.0: |
|
1071 | 1083 | raise django.forms.ValidationError('Invalid maximum elevation: %(value)s cannot be less than 0 degrees', |
|
1072 | 1084 | code='invalid', |
|
1073 | 1085 | params={'value': max_el}) |
|
1074 | 1086 | if max_el_value > 90.0: |
|
1075 | 1087 | raise django.forms.ValidationError('Invalid maximum elevation: %(value)s cannot be more than 90 degrees', |
|
1076 | 1088 | code='invalid', |
|
1077 | 1089 | params={'value': max_el}) |
|
1078 | 1090 | return(max_el) |
|
1079 | 1091 | |
|
1080 | 1092 | |
|
1081 | 1093 | def clean_min_az2(self): |
|
1082 | 1094 | min_az2 = self.cleaned_data['min_az2'] |
|
1083 | 1095 | if len(min_az2) != 0: |
|
1084 | 1096 | try: |
|
1085 | 1097 | min_az2_value = float(min_az2) |
|
1086 | 1098 | except: |
|
1087 | 1099 | raise django.forms.ValidationError('Invalid minimum azimuth 2: %(value)s cannot be converted to a float', |
|
1088 | 1100 | code='invalid', |
|
1089 | 1101 | params={'value': min_az2}) |
|
1090 | 1102 | if min_az2_value < -180.0: |
|
1091 | 1103 | raise django.forms.ValidationError('Invalid minimum azimuth 2: %(value)s cannot be less than -180 degrees', |
|
1092 | 1104 | code='invalid', |
|
1093 | 1105 | params={'value': min_az2}) |
|
1094 | 1106 | if min_az2_value > 180.0: |
|
1095 | 1107 | raise django.forms.ValidationError('Invalid minimum azimuth 2: %(value)s cannot be more than 180 degrees', |
|
1096 | 1108 | code='invalid', |
|
1097 | 1109 | params={'value': min_az2}) |
|
1098 | 1110 | return(min_az2) |
|
1099 | 1111 | |
|
1100 | 1112 | |
|
1101 | 1113 | def clean_max_az2(self): |
|
1102 | 1114 | max_az2 = self.cleaned_data['max_az2'] |
|
1103 | 1115 | if len(max_az2) != 0: |
|
1104 | 1116 | try: |
|
1105 | 1117 | max_az2_value = float(max_az2) |
|
1106 | 1118 | except: |
|
1107 | 1119 | raise django.forms.ValidationError('Invalid maximum azimuth 2: %(value)s cannot be converted to a float', |
|
1108 | 1120 | code='invalid', |
|
1109 | 1121 | params={'value': max_az2}) |
|
1110 | 1122 | if max_az2_value < -180.0: |
|
1111 | 1123 | raise django.forms.ValidationError('Invalid maximum azimuth 2: %(value)s cannot be less than -180 degrees', |
|
1112 | 1124 | code='invalid', |
|
1113 | 1125 | params={'value': max_az2}) |
|
1114 | 1126 | if max_az2_value > 180.0: |
|
1115 | 1127 | raise django.forms.ValidationError('Invalid maximum azimuth 2: %(value)s cannot be more than 180 degrees', |
|
1116 | 1128 | code='invalid', |
|
1117 | 1129 | params={'value': max_az2}) |
|
1118 | 1130 | return(max_az2) |
|
1119 | 1131 | |
|
1120 | 1132 | |
|
1121 | 1133 | def clean_min_el2(self): |
|
1122 | 1134 | min_el2 = self.cleaned_data['min_el2'] |
|
1123 | 1135 | if len(min_el2) != 0: |
|
1124 | 1136 | try: |
|
1125 | 1137 | min_el2_value = float(min_el2) |
|
1126 | 1138 | except: |
|
1127 | 1139 | raise django.forms.ValidationError('Invalid minimum elevation 2: %(value)s cannot be converted to a float', |
|
1128 | 1140 | code='invalid', |
|
1129 | 1141 | params={'value': min_el2}) |
|
1130 | 1142 | if min_el2_value < 0.0: |
|
1131 | 1143 | raise django.forms.ValidationError('Invalid minimum elevation 2: %(value)s cannot be less than 0 degrees', |
|
1132 | 1144 | code='invalid', |
|
1133 | 1145 | params={'value': min_el2}) |
|
1134 | 1146 | if min_el2_value > 90.0: |
|
1135 | 1147 | raise django.forms.ValidationError('Invalid minimum elevation 2: %(value)s cannot be more than 90 degrees', |
|
1136 | 1148 | code='invalid', |
|
1137 | 1149 | params={'value': min_el2}) |
|
1138 | 1150 | return(min_el2) |
|
1139 | 1151 | |
|
1140 | 1152 | |
|
1141 | 1153 | def clean_max_el2(self): |
|
1142 | 1154 | max_el2 = self.cleaned_data['max_el2'] |
|
1143 | 1155 | if len(max_el2) != 0: |
|
1144 | 1156 | try: |
|
1145 | 1157 | max_el2_value = float(max_el2) |
|
1146 | 1158 | except: |
|
1147 | 1159 | raise django.forms.ValidationError('Invalid maximum elevation 2: %(value)s cannot be converted to a float', |
|
1148 | 1160 | code='invalid', |
|
1149 | 1161 | params={'value': max_el2}) |
|
1150 | 1162 | if max_el2_value < 0.0: |
|
1151 | 1163 | raise django.forms.ValidationError('Invalid maximum elevation 2: %(value)s cannot be less than 0 degrees', |
|
1152 | 1164 | code='invalid', |
|
1153 | 1165 | params={'value': max_el2}) |
|
1154 | 1166 | if max_el2_value > 90.0: |
|
1155 | 1167 | raise django.forms.ValidationError('Invalid maximum elevation 2: %(value)s cannot be more than 90 degrees', |
|
1156 | 1168 | code='invalid', |
|
1157 | 1169 | params={'value': max_el2}) |
|
1158 | 1170 | return(max_el2) |
|
1159 | 1171 | |
|
1160 | 1172 | |
|
1161 | 1173 | def clean_min_pl(self): |
|
1162 | 1174 | min_pl = self.cleaned_data['min_pl'] |
|
1163 | 1175 | if len(min_pl) != 0: |
|
1164 | 1176 | try: |
|
1165 | 1177 | min_pl_value = float(min_pl) |
|
1166 | 1178 | except: |
|
1167 | 1179 | raise django.forms.ValidationError('Invalid lower limit for pulse length: %(value)s cannot be converted to a float', |
|
1168 | 1180 | code='invalid', |
|
1169 | 1181 | params={'value': min_pl}) |
|
1170 | 1182 | return(min_pl) |
|
1171 | 1183 | |
|
1172 | 1184 | |
|
1173 | 1185 | def clean_max_pl(self): |
|
1174 | 1186 | max_pl = self.cleaned_data['max_pl'] |
|
1175 | 1187 | if len(max_pl) != 0: |
|
1176 | 1188 | try: |
|
1177 | 1189 | max_pl_value = float(max_pl) |
|
1178 | 1190 | except: |
|
1179 | 1191 | raise django.forms.ValidationError('Invalid upper limit for pulse length: %(value)s cannot be converted to a float', |
|
1180 | 1192 | code='invalid', |
|
1181 | 1193 | params={'value': max_pl}) |
|
1182 | 1194 | return(max_pl) |
|
1183 | 1195 | |
|
1184 | 1196 | |
|
1185 | 1197 | def clean_parm_1_lower(self): |
|
1186 | 1198 | parm_1_lower = self.cleaned_data['parm_1_lower'] |
|
1187 | 1199 | if len(parm_1_lower) != 0: |
|
1188 | 1200 | try: |
|
1189 | 1201 | parm_1_lower_value = float(parm_1_lower) |
|
1190 | 1202 | except: |
|
1191 | 1203 | raise django.forms.ValidationError('Invalid lower limit for parm 1: %(value)s cannot be converted to a float', |
|
1192 | 1204 | code='invalid', |
|
1193 | 1205 | params={'value': parm_1_lower}) |
|
1194 | 1206 | return(parm_1_lower) |
|
1195 | 1207 | |
|
1196 | 1208 | |
|
1197 | 1209 | def clean_parm_1_upper(self): |
|
1198 | 1210 | parm_1_upper = self.cleaned_data['parm_1_upper'] |
|
1199 | 1211 | if len(parm_1_upper) != 0: |
|
1200 | 1212 | try: |
|
1201 | 1213 | parm_1_upper_value = float(parm_1_upper) |
|
1202 | 1214 | except: |
|
1203 | 1215 | raise django.forms.ValidationError('Invalid upper limit for parm 1: %(value)s cannot be converted to a float', |
|
1204 | 1216 | code='invalid', |
|
1205 | 1217 | params={'value': parm_1_upper}) |
|
1206 | 1218 | return(parm_1_upper) |
|
1207 | 1219 | |
|
1208 | 1220 | |
|
1209 | 1221 | def clean_parm_2_lower(self): |
|
1210 | 1222 | parm_2_lower = self.cleaned_data['parm_2_lower'] |
|
1211 | 1223 | if len(parm_2_lower) != 0: |
|
1212 | 1224 | try: |
|
1213 | 1225 | parm_2_lower_value = float(parm_2_lower) |
|
1214 | 1226 | except: |
|
1215 | 1227 | raise django.forms.ValidationError('Invalid lower limit for parm 2: %(value)s cannot be converted to a float', |
|
1216 | 1228 | code='invalid', |
|
1217 | 1229 | params={'value': parm_2_lower}) |
|
1218 | 1230 | return(parm_2_lower) |
|
1219 | 1231 | |
|
1220 | 1232 | |
|
1221 | 1233 | def clean_parm_2_upper(self): |
|
1222 | 1234 | parm_2_upper = self.cleaned_data['parm_2_upper'] |
|
1223 | 1235 | if len(parm_2_upper) != 0: |
|
1224 | 1236 | try: |
|
1225 | 1237 | parm_2_upper_value = float(parm_2_upper) |
|
1226 | 1238 | except: |
|
1227 | 1239 | raise django.forms.ValidationError('Invalid upper limit for parm 2: %(value)s cannot be converted to a float', |
|
1228 | 1240 | code='invalid', |
|
1229 | 1241 | params={'value': parm_2_upper}) |
|
1230 | 1242 | return(parm_2_upper) |
|
1231 | 1243 | |
|
1232 | 1244 | |
|
1233 | 1245 | def clean_parm_3_lower(self): |
|
1234 | 1246 | parm_3_lower = self.cleaned_data['parm_3_lower'] |
|
1235 | 1247 | if len(parm_3_lower) != 0: |
|
1236 | 1248 | try: |
|
1237 | 1249 | parm_3_lower_value = float(parm_3_lower) |
|
1238 | 1250 | except: |
|
1239 | 1251 | raise django.forms.ValidationError('Invalid lower limit for parm 3: %(value)s cannot be converted to a float', |
|
1240 | 1252 | code='invalid', |
|
1241 | 1253 | params={'value': parm_3_lower}) |
|
1242 | 1254 | return(parm_3_lower) |
|
1243 | 1255 | |
|
1244 | 1256 | |
|
1245 | 1257 | def clean_parm_3_upper(self): |
|
1246 | 1258 | parm_3_upper = self.cleaned_data['parm_3_upper'] |
|
1247 | 1259 | if len(parm_3_upper) != 0: |
|
1248 | 1260 | try: |
|
1249 | 1261 | parm_3_upper_value = float(parm_3_upper) |
|
1250 | 1262 | except: |
|
1251 | 1263 | raise django.forms.ValidationError('Invalid upper limit for parm 3: %(value)s cannot be converted to a float', |
|
1252 | 1264 | code='invalid', |
|
1253 | 1265 | params={'value': parm_3_upper}) |
|
1254 | 1266 | return(parm_3_upper) |
|
1255 | 1267 | |
|
1256 | 1268 | |
|
1257 | 1269 | |
|
1258 | 1270 | |
|
1259 | 1271 | def clean(self): |
|
1260 | 1272 | """clean in the Django method to validate things in a form that require looking at multiple fields |
|
1261 | 1273 | """ |
|
1262 | 1274 | # rule 1 - start_date < end_date |
|
1263 | 1275 | if self.cleaned_data['start_date'] > self.cleaned_data['end_date']: |
|
1264 | 1276 | raise django.forms.ValidationError('Error - start datetime greater than end datetime.') |
|
1265 | 1277 | |
|
1266 | 1278 | # rule 2 - min_alt <= max_alt |
|
1267 | 1279 | try: |
|
1268 | 1280 | min_alt = float(self.cleaned_data['min_alt']) |
|
1269 | 1281 | max_alt = float(self.cleaned_data['max_alt']) |
|
1270 | 1282 | except: |
|
1271 | 1283 | min_alt = 0.0 |
|
1272 | 1284 | max_alt = 1.0 |
|
1273 | 1285 | if min_alt > max_alt: |
|
1274 | 1286 | raise django.forms.ValidationError('Error - Minimum altitude greater than maximum altitude.') |
|
1275 | 1287 | |
|
1276 | 1288 | # rule 3 - min_az <= max_az |
|
1277 | 1289 | try: |
|
1278 | 1290 | min_az = float(self.cleaned_data['min_az']) |
|
1279 | 1291 | max_az = float(self.cleaned_data['max_az']) |
|
1280 | 1292 | except: |
|
1281 | 1293 | min_az = 0.0 |
|
1282 | 1294 | max_az = 1.0 |
|
1283 | 1295 | if min_az > max_az: |
|
1284 | 1296 | raise django.forms.ValidationError('Error - Minimum azimuth greater than maximum azimuth.') |
|
1285 | 1297 | |
|
1286 | 1298 | # rule 4 - min_el <= max_el |
|
1287 | 1299 | try: |
|
1288 | 1300 | min_el = float(self.cleaned_data['min_el']) |
|
1289 | 1301 | max_el = float(self.cleaned_data['max_el']) |
|
1290 | 1302 | except: |
|
1291 | 1303 | min_el = 0.0 |
|
1292 | 1304 | max_el = 1.0 |
|
1293 | 1305 | if min_el > max_el: |
|
1294 | 1306 | raise django.forms.ValidationError('Error - Minimum elevation greater than maximum elevation.') |
|
1295 | 1307 | |
|
1296 | 1308 | # rule 5 - min_az2 <= max_az2 |
|
1297 | 1309 | try: |
|
1298 | 1310 | min_az2 = float(self.cleaned_data['min_az2']) |
|
1299 | 1311 | max_az2 = float(self.cleaned_data['max_az2']) |
|
1300 | 1312 | except: |
|
1301 | 1313 | min_az2 = 0.0 |
|
1302 | 1314 | max_az2 = 1.0 |
|
1303 | 1315 | if min_az2 > max_az2: |
|
1304 | 1316 | raise django.forms.ValidationError('Error - Minimum azimuth 2 greater than maximum azimuth 2.') |
|
1305 | 1317 | |
|
1306 | 1318 | # rule 6 - min_el2 <= max_el2 |
|
1307 | 1319 | try: |
|
1308 | 1320 | min_el2 = float(self.cleaned_data['min_el2']) |
|
1309 | 1321 | max_el2 = float(self.cleaned_data['max_el2']) |
|
1310 | 1322 | except: |
|
1311 | 1323 | min_el2 = 0.0 |
|
1312 | 1324 | max_el2 = 1.0 |
|
1313 | 1325 | if min_el2 > max_el2: |
|
1314 | 1326 | raise django.forms.ValidationError('Error - Minimum elevation 2 greater than maximum elevation 2.') |
|
1315 | 1327 | |
|
1316 | 1328 | # rule 7 - min_pl <= max_pl |
|
1317 | 1329 | try: |
|
1318 | 1330 | min_pl = float(self.cleaned_data['min_pl']) |
|
1319 | 1331 | max_pl = float(self.cleaned_data['max_pl']) |
|
1320 | 1332 | except: |
|
1321 | 1333 | min_pl = 0.0 |
|
1322 | 1334 | max_pl = 1.0 |
|
1323 | 1335 | if min_pl > max_pl: |
|
1324 | 1336 | raise django.forms.ValidationError('Error - Minimum pulse length greater than maximum pulse length.') |
|
1325 | 1337 | |
|
1326 | 1338 | # rule 8 - parm_1_lower <= parm_1_upper |
|
1327 | 1339 | try: |
|
1328 | 1340 | parm_1_lower = float(self.cleaned_data['parm_1_lower']) |
|
1329 | 1341 | parm_1_upper = float(self.cleaned_data['parm_1_upper']) |
|
1330 | 1342 | except: |
|
1331 | 1343 | parm_1_lower = 0.0 |
|
1332 | 1344 | parm_1_upper = 1.0 |
|
1333 | 1345 | if parm_1_lower > parm_1_upper: |
|
1334 | 1346 | raise django.forms.ValidationError('Error - parm 1 lower limit greater than upper limit.') |
|
1335 | 1347 | |
|
1336 | 1348 | # rule 9 - parm_2_lower <= parm_2_upper |
|
1337 | 1349 | try: |
|
1338 | 1350 | parm_2_lower = float(self.cleaned_data['parm_2_lower']) |
|
1339 | 1351 | parm_2_upper = float(self.cleaned_data['parm_2_upper']) |
|
1340 | 1352 | except: |
|
1341 | 1353 | parm_2_lower = 0.0 |
|
1342 | 1354 | parm_2_upper = 1.0 |
|
1343 | 1355 | if parm_2_lower > parm_2_upper: |
|
1344 | 1356 | raise django.forms.ValidationError('Error - parm 2 lower limit greater than upper limit.') |
|
1345 | 1357 | |
|
1346 | 1358 | # rule 10 - parm_3_lower <= parm_3_upper |
|
1347 | 1359 | try: |
|
1348 | 1360 | parm_3_lower = float(self.cleaned_data['parm_3_lower']) |
|
1349 | 1361 | parm_3_upper = float(self.cleaned_data['parm_3_upper']) |
|
1350 | 1362 | except: |
|
1351 | 1363 | parm_3_lower = 0.0 |
|
1352 | 1364 | parm_3_upper = 1.0 |
|
1353 | 1365 | if parm_3_lower > parm_3_upper: |
|
1354 | 1366 | raise django.forms.ValidationError('Error - parm 3 lower limit greater than upper limit.') |
|
1355 | 1367 | |
|
1356 | 1368 | |
|
1357 | 1369 | class ListExpForm(django.forms.Form): |
|
1358 | 1370 | """ListExpForm is a Form class for the default fields in the List Experiment interface |
|
1359 | 1371 | """ |
|
1360 | 1372 | def __init__(self, *args, **kwargs): |
|
1361 | 1373 | super(ListExpForm, self).__init__(*args, **kwargs) |
|
1362 | 1374 | madDB = madrigal.metadata.MadrigalDB() |
|
1363 | 1375 | madInstData = madrigal.metadata.MadrigalInstrumentData(madDB) |
|
1364 | 1376 | isGlobal = True # default load |
|
1365 | 1377 | now = datetime.datetime.now() |
|
1366 | 1378 | endDateTime = datetime.datetime(now.year, 12, 31, 23, 59, 59) |
|
1367 | 1379 | self.fields['isGlobal'] = django.forms.BooleanField(widget = django.forms.CheckboxInput(attrs={"onChange":'changeGlobal(this.form)'}), |
|
1368 | 1380 | required=False, label='Use all Madrigal sites: ', |
|
1369 | 1381 | initial=isGlobal) |
|
1370 | 1382 | |
|
1371 | 1383 | |
|
1372 | 1384 | categoriesSelection = '0' |
|
1373 | 1385 | self.fields['categories'] = django.forms.MultipleChoiceField(widget=django.forms.SelectMultiple(attrs={"onChange":"updateInstruments(this.form)"}), |
|
1374 | 1386 | choices=getCategoryList(args, kwargs, madInstData, True), |
|
1375 | 1387 | initial='0', |
|
1376 | 1388 | label='Choose instrument category(s):') |
|
1377 | 1389 | |
|
1378 | 1390 | self.fields['instruments'] = django.forms.MultipleChoiceField(widget = django.forms.SelectMultiple(), |
|
1379 | 1391 | choices=getInstrumentList(args, kwargs, madInstData, 'All instruments', local=False, includeYears=True), |
|
1380 | 1392 | initial='0', label='Choose instrument(s)') |
|
1381 | 1393 | |
|
1382 | 1394 | self.fields['showDefault'] = django.forms.BooleanField(widget = django.forms.CheckboxInput(), |
|
1383 | 1395 | label='Show only default files: ', |
|
1384 | 1396 | initial=True) |
|
1385 | 1397 | |
|
1386 | 1398 | # time selection |
|
1387 | 1399 | self.fields['start_date'] = django.forms.SplitDateTimeField(input_date_formats=['%Y-%m-%d'], input_time_formats=['%H:%M:%S'], |
|
1388 | 1400 | label='Start date', |
|
1389 | 1401 | help_text='Modify this field to select experiments after this start time.', |
|
1390 | 1402 | initial=datetime.datetime(1950,1,1)) |
|
1391 | 1403 | |
|
1392 | 1404 | self.fields['end_date'] = django.forms.SplitDateTimeField(input_date_formats=['%Y-%m-%d'], input_time_formats=['%H:%M:%S'], |
|
1393 | 1405 | label='End date', |
|
1394 | 1406 | help_text='Modify this field to select experiments before this end time.', |
|
1395 | 1407 | initial=endDateTime) |
|
1396 | 1408 | |
|
1397 | 1409 | |
|
1398 | 1410 | |
|
1399 | 1411 | # attributes to support javascript |
|
1400 | 1412 | local_categories = madInstData.getCategories(True) |
|
1401 | 1413 | global_categories = madInstData.getCategories(False) |
|
1402 | 1414 | local_category_ids = [cat[0] for cat in local_categories] |
|
1403 | 1415 | self.categories = [] # each item a tuple of (category description, category id, global only js bool) |
|
1404 | 1416 | self.instruments = [] # each item a tiple of (instrument desc, category id, kinst, local start year, local end year, global sy, global ey) |
|
1405 | 1417 | for id, desc in global_categories: |
|
1406 | 1418 | if id in local_category_ids: |
|
1407 | 1419 | localBool = 'false' |
|
1408 | 1420 | else: |
|
1409 | 1421 | localBool = 'true' |
|
1410 | 1422 | self.categories.append((desc, id, localBool)) |
|
1411 | 1423 | for kinst, instDesc, siteId in madInstData.getInstruments(id): |
|
1412 | 1424 | if siteId == madDB.getSiteID(): |
|
1413 | 1425 | localInst = True |
|
1414 | 1426 | else: |
|
1415 | 1427 | localInst = False |
|
1416 | 1428 | yearList = madInstData.getInstrumentYears(kinst) |
|
1417 | 1429 | if localInst: |
|
1418 | 1430 | self.instruments.append((instDesc, id, kinst, yearList[0], yearList[-1], yearList[0], yearList[-1])) |
|
1419 | 1431 | else: |
|
1420 | 1432 | self.instruments.append((instDesc, id, kinst, 0, 0, yearList[0], yearList[-1])) |
|
1421 | 1433 | |
|
1422 | 1434 | |
|
1423 | 1435 | def clean(self): |
|
1424 | 1436 | """clean in the Django method to validate things in a form that require looking at multiple fields |
|
1425 | 1437 | """ |
|
1426 | 1438 | # rule 1 - start_date < end_date |
|
1427 | 1439 | if self.cleaned_data['start_date'] > self.cleaned_data['end_date']: |
|
1428 | 1440 | raise django.forms.ValidationError('Error - start datetime greater than end datetime.') |
|
1429 | 1441 | |
|
1430 | 1442 | |
|
1431 | 1443 | class DownloadAsIsScriptForm(django.forms.Form): |
|
1432 | 1444 | """DownloadAsIsScriptForm is a Form class for the default fields in the download files as is script generator interface |
|
1433 | 1445 | """ |
|
1434 | 1446 | def __init__(self, *args, **kwargs): |
|
1435 | 1447 | super(DownloadAsIsScriptForm, self).__init__(*args, **kwargs) |
|
1436 | 1448 | madDB = madrigal.metadata.MadrigalDB() |
|
1437 | 1449 | madInstData = madrigal.metadata.MadrigalInstrumentData(madDB) |
|
1438 | 1450 | madKindatObj = madrigal.metadata.MadrigalKindat(madDB) |
|
1439 | 1451 | madInstKindatObj = madrigal.metadata.MadrigalInstrumentKindats(madDB) |
|
1440 | 1452 | now = datetime.datetime.now() |
|
1441 | 1453 | endDateTime = datetime.datetime(now.year, 12, 31, 23, 59, 59) |
|
1442 | 1454 | kwargs['isGlobal'] = '0' |
|
1443 | 1455 | formatChoices = (('hdf5', 'Hdf5'), ('ascii', 'Space-delimited ascii'), ('netCDF4', 'netCDF4')) |
|
1444 | 1456 | languageChoices = (('python', 'python'), ('Matlab', 'Matlab'), ('IDL', 'IDL')) |
|
1445 | 1457 | |
|
1446 | 1458 | categoriesSelection = '0' |
|
1447 | 1459 | self.fields['categories'] = django.forms.ChoiceField(widget=django.forms.Select(attrs={"onChange":"updateInstruments(this.form)"}), |
|
1448 | 1460 | choices=getCategoryList(args, kwargs, madInstData), |
|
1449 | 1461 | initial='0', |
|
1450 | 1462 | label='Choose an instrument category if desired:') |
|
1451 | 1463 | |
|
1452 | 1464 | self.fields['instruments'] = django.forms.ChoiceField(widget=django.forms.Select(attrs={"onChange":"updateKindats(this.form)"}), |
|
1453 | 1465 | choices=getInstrumentList(args, kwargs, madInstData, local=True, includeYears=True), |
|
1454 | 1466 | initial='0', label='Choose one instrument') |
|
1455 | 1467 | |
|
1456 | 1468 | # time selection |
|
1457 | 1469 | self.fields['start_date'] = django.forms.DateField(input_formats=['%Y-%m-%d'], |
|
1458 | 1470 | label='Start date', |
|
1459 | 1471 | help_text='Modify this field to select experiments after this start time.', |
|
1460 | 1472 | initial=datetime.datetime(1950,1,1)) |
|
1461 | 1473 | |
|
1462 | 1474 | |
|
1463 | 1475 | self.fields['end_date'] = django.forms.DateField(input_formats=['%Y-%m-%d'], |
|
1464 | 1476 | label='End date', |
|
1465 | 1477 | help_text='Modify this field to select experiments before this end time.', |
|
1466 | 1478 | initial=endDateTime) |
|
1467 | 1479 | |
|
1468 | 1480 | self.fields['format_select'] = django.forms.ChoiceField(widget = HorizontalRadioSelect(), |
|
1469 | 1481 | choices=formatChoices, |
|
1470 | 1482 | initial=formatChoices[0][0], |
|
1471 | 1483 | label='File format to download:') |
|
1472 | 1484 | |
|
1473 | 1485 | self.fields['language_select'] = django.forms.ChoiceField(widget = HorizontalRadioSelect(), |
|
1474 | 1486 | choices=languageChoices, |
|
1475 | 1487 | initial=languageChoices[0][0], |
|
1476 | 1488 | label='Choose scripting language:') |
|
1477 | 1489 | |
|
1478 | 1490 | choices=(('0', 'Select an instrument first to see list'),) |
|
1479 | 1491 | if len(args) > 0: |
|
1480 | 1492 | if 'kindat_select' in args[0]: |
|
1481 | 1493 | choices = [(kindat, kindat) for kindat in args[0].getlist('kindat_select')] |
|
1482 | 1494 | self.fields['kindat_select'] = django.forms.MultipleChoiceField(choices=choices, |
|
1483 | 1495 | initial='0', |
|
1484 | 1496 | label='Choose one or more kinds of data:', |
|
1485 | 1497 | required=False) |
|
1486 | 1498 | self.fields['kindat_select'].widget.attrs['style']="max-width:100%;" |
|
1487 | 1499 | |
|
1488 | 1500 | self.fields['expName'] = django.forms.CharField(max_length=256, required=False) |
|
1489 | 1501 | |
|
1490 | 1502 | self.fields['fileDesc'] = django.forms.CharField(max_length=256, required=False) |
|
1491 | 1503 | |
|
1492 | 1504 | |
|
1493 | 1505 | |
|
1494 | 1506 | # attributes to support javascript |
|
1495 | 1507 | local_categories = madInstData.getCategories(True) |
|
1496 | 1508 | local_category_ids = [cat[0] for cat in local_categories] |
|
1497 | 1509 | self.categories = [] # each item a tuple of (category description, category id, global only js bool) |
|
1498 | 1510 | self.instruments = [] # each item a tiple of (instrument desc, category id, kinst, local start year, local end year) |
|
1499 | 1511 | self.kindats = [] # each item is a tuple of (kindat, kindatDesc, kinst) |
|
1500 | 1512 | for id, desc in local_categories: |
|
1501 | 1513 | self.categories.append((desc, id)) |
|
1502 | 1514 | for kinst, instDesc, siteId in madInstData.getInstruments(id): |
|
1503 | 1515 | if siteId != madDB.getSiteID(): |
|
1504 | 1516 | continue |
|
1505 | 1517 | yearList = madInstData.getInstrumentYears(kinst) |
|
1506 | 1518 | self.instruments.append((instDesc, id, kinst, yearList[0], yearList[-1])) |
|
1507 | 1519 | kindatList = madInstKindatObj.getKindatListForInstruments([kinst]) |
|
1508 | 1520 | for kindat in kindatList: |
|
1509 | 1521 | self.kindats.append((kindat, madKindatObj.getKindatDescription(kindat, kinst), |
|
1510 | 1522 | kinst)) |
|
1511 | 1523 | |
|
1512 | 1524 | |
|
1513 | 1525 | def clean(self): |
|
1514 | 1526 | """clean is the Django method to validate things in a form that require looking at multiple fields |
|
1515 | 1527 | """ |
|
1516 | 1528 | # rule 1 - start_date < end_date |
|
1517 | 1529 | if self.cleaned_data['start_date'] > self.cleaned_data['end_date']: |
|
1518 | 1530 | raise django.forms.ValidationError('Error - start datetime greater than end datetime.') |
|
1519 | 1531 | |
|
1520 | 1532 | |
|
1521 | 1533 | class DownloadAdvancedScriptForm(django.forms.Form): |
|
1522 | 1534 | """DownloadAdvancedScriptForm is a Form class for the default fields in the download advanced script generator interface |
|
1523 | 1535 | """ |
|
1524 | 1536 | def __init__(self, *args, **kwargs): |
|
1525 | 1537 | super(DownloadAdvancedScriptForm, self).__init__(*args, **kwargs) |
|
1526 | 1538 | madDB = madrigal.metadata.MadrigalDB() |
|
1527 | 1539 | madInstData = madrigal.metadata.MadrigalInstrumentData(madDB) |
|
1528 | 1540 | madKindatObj = madrigal.metadata.MadrigalKindat(madDB) |
|
1529 | 1541 | madInstKindatObj = madrigal.metadata.MadrigalInstrumentKindats(madDB) |
|
1530 | 1542 | now = datetime.datetime.now() |
|
1531 | 1543 | endDateTime = datetime.datetime(now.year, 12, 31, 23, 59, 59) |
|
1532 | 1544 | kwargs['isGlobal'] = '0' |
|
1533 | 1545 | formatChoices = (('hdf5', 'Hdf5'), ('ascii', 'Space-delimited ascii'), ('netCDF4', 'netCDF4')) |
|
1534 | 1546 | directoryChoices = (('Directory', 'Directory'), ('File', 'File')) |
|
1535 | 1547 | languageChoices = (('python', 'python'), ('Matlab', 'Matlab'), ('IDL', 'IDL')) |
|
1536 | 1548 | |
|
1537 | 1549 | categoriesSelection = '0' |
|
1538 | 1550 | self.fields['categories'] = django.forms.ChoiceField(widget=django.forms.Select(attrs={"onChange":"updateInstruments(this.form)"}), |
|
1539 | 1551 | choices=getCategoryList(args, kwargs, madInstData), |
|
1540 | 1552 | initial='0', |
|
1541 | 1553 | label='Choose an instrument category if desired:') |
|
1542 | 1554 | |
|
1543 | 1555 | self.fields['instruments'] = django.forms.ChoiceField(widget=django.forms.Select(attrs={"onChange":"updateParmsKindats(this.form)"}), |
|
1544 | 1556 | choices=getInstrumentList(args, kwargs, madInstData, local=True, includeYears=True), |
|
1545 | 1557 | initial='0', label='Choose one instrument') |
|
1546 | 1558 | |
|
1547 | 1559 | # time selection |
|
1548 | 1560 | self.fields['start_date'] = django.forms.DateField(input_formats=['%Y-%m-%d'], |
|
1549 | 1561 | label='Start date', |
|
1550 | 1562 | help_text='Modify this field to select experiments after this start time.', |
|
1551 | 1563 | initial=datetime.datetime(1950,1,1)) |
|
1552 | 1564 | |
|
1553 | 1565 | self.fields['end_date'] = django.forms.DateField(input_formats=['%Y-%m-%d'], |
|
1554 | 1566 | label='End date', |
|
1555 | 1567 | help_text='Modify this field to select experiments before this end time.', |
|
1556 | 1568 | initial=endDateTime) |
|
1557 | 1569 | |
|
1558 | 1570 | self.fields['format_select'] = django.forms.ChoiceField(widget = HorizontalRadioSelect(attrs={"onChange":'changeFormat(this)'}), |
|
1559 | 1571 | choices=formatChoices, |
|
1560 | 1572 | initial=formatChoices[0][0], |
|
1561 | 1573 | label='File format to download:') |
|
1562 | 1574 | |
|
1563 | 1575 | self.fields['directory_select'] = django.forms.ChoiceField(widget = HorizontalRadioSelect(), |
|
1564 | 1576 | choices=directoryChoices, |
|
1565 | 1577 | initial=directoryChoices[0][0], |
|
1566 | 1578 | label='If ascii, download result to:') |
|
1567 | 1579 | |
|
1568 | 1580 | self.fields['language_select'] = django.forms.ChoiceField(widget = HorizontalRadioSelect(), |
|
1569 | 1581 | choices=languageChoices, |
|
1570 | 1582 | initial=languageChoices[0][0], |
|
1571 | 1583 | label='Choose scripting language:') |
|
1572 | 1584 | |
|
1573 | 1585 | choices=(('0', 'Select an instrument first to see list'),) |
|
1574 | 1586 | if len(args) > 0: |
|
1575 | 1587 | if 'kindat_select' in args[0]: |
|
1576 | 1588 | choices = [(kindat, kindat) for kindat in args[0].getlist('kindat_select')] |
|
1577 | 1589 | self.fields['kindat_select'] = django.forms.MultipleChoiceField(choices=choices, |
|
1578 | 1590 | initial='0', |
|
1579 | 1591 | label='Choose one or more kinds of data:', |
|
1580 | 1592 | required=False) |
|
1581 | 1593 | self.fields['kindat_select'].widget.attrs['style']="max-width:100%;" |
|
1582 | 1594 | |
|
1583 | 1595 | self.fields['expName'] = django.forms.CharField(max_length=256, required=False) |
|
1584 | 1596 | |
|
1585 | 1597 | self.fields['fileDesc'] = django.forms.CharField(max_length=256, required=False) |
|
1586 | 1598 | |
|
1587 | 1599 | self.fields['seasonalStartDay'] = django.forms.IntegerField(min_value=1, max_value=31, initial=1) |
|
1588 | 1600 | self.fields['seasonalStartMonth'] = django.forms.IntegerField(min_value=1, max_value=12, initial=1) |
|
1589 | 1601 | self.fields['seasonalEndDay'] = django.forms.IntegerField(min_value=1, max_value=31, initial=31) |
|
1590 | 1602 | self.fields['seasonalEndMonth'] = django.forms.IntegerField(min_value=1, max_value=12, initial=12) |
|
1591 | 1603 | |
|
1592 | 1604 | |
|
1593 | 1605 | # attributes to support javascript |
|
1594 | 1606 | local_categories = madInstData.getCategories(True) |
|
1595 | 1607 | local_category_ids = [cat[0] for cat in local_categories] |
|
1596 | 1608 | self.categories = [] # each item a tuple of (category description, category id, global only js bool) |
|
1597 | 1609 | self.instruments = [] # each item a tiple of (instrument desc, category id, kinst, local start year, local end year) |
|
1598 | 1610 | self.kindats = [] # each item is a tuple of (kindat, kindatDesc, kinst) |
|
1599 | 1611 | for id, desc in local_categories: |
|
1600 | 1612 | self.categories.append((desc, id)) |
|
1601 | 1613 | for kinst, instDesc, siteId in madInstData.getInstruments(id): |
|
1602 | 1614 | if siteId != madDB.getSiteID(): |
|
1603 | 1615 | continue |
|
1604 | 1616 | yearList = madInstData.getInstrumentYears(kinst) |
|
1605 | 1617 | self.instruments.append((instDesc, id, kinst, yearList[0], yearList[-1])) |
|
1606 | 1618 | kindatList = madInstKindatObj.getKindatListForInstruments([kinst]) |
|
1607 | 1619 | for kindat in kindatList: |
|
1608 | 1620 | self.kindats.append((kindat, madKindatObj.getKindatDescription(kindat, kinst), |
|
1609 | 1621 | kinst)) |
|
1610 | 1622 | |
|
1611 | 1623 | |
|
1612 | 1624 | def clean(self): |
|
1613 | 1625 | """clean is the Django method to validate things in a form that require looking at multiple fields |
|
1614 | 1626 | """ |
|
1615 | 1627 | # rule 1 - start_date < end_date |
|
1616 | 1628 | if self.cleaned_data['start_date'] > self.cleaned_data['end_date']: |
|
1617 | 1629 | raise django.forms.ValidationError('Error - start datetime greater than end datetime.') |
|
1618 | 1630 | |
|
1619 | 1631 | # rule 2 - seasonal start must be before seasonal end |
|
1620 | 1632 | if ((self.cleaned_data['seasonalStartDay'] + 31*self.cleaned_data['seasonalStartMonth']) > \ |
|
1621 | 1633 | (self.cleaned_data['seasonalEndDay'] + 31*self.cleaned_data['seasonalEndMonth'])): |
|
1622 | 1634 | raise django.forms.ValidationError('Error - seasonal start after seasonal end.') |
|
1623 | 1635 | |
|
1624 | 1636 | |
|
1625 | 1637 | |
|
1626 | 1638 | class AdvScriptParmsForm(django.forms.Form): |
|
1627 | 1639 | """AdvScriptParmsForm is the form for the parameters |
|
1628 | 1640 | """ |
|
1629 | 1641 | def __init__(self, *args, **kwargs): |
|
1630 | 1642 | |
|
1631 | 1643 | kinst = int(getSelection('instruments', args, kwargs)) |
|
1632 | 1644 | if kinst == 0: |
|
1633 | 1645 | raise ValueError('kinst should never be zero') |
|
1634 | 1646 | madDB = madrigal.metadata.MadrigalDB() |
|
1635 | 1647 | madParmObj = madrigal.data.MadrigalParameters(madDB) |
|
1636 | 1648 | parmList = madParmObj.getParametersForInstruments([kinst]) |
|
1637 | 1649 | self.parmList = [] |
|
1638 | 1650 | for parm in parmList: |
|
1639 | 1651 | self.parmList.append((parm, madParmObj.getSimpleParmDescription(parm))) |
|
1640 | 1652 | |
|
1641 | 1653 | madCatObj = madrigal.metadata.MadrigalParmCategory(madDB) |
|
1642 | 1654 | |
|
1643 | 1655 | catList = madCatObj.getCategoryList() |
|
1644 | 1656 | catDict = madParmObj.getCategoryDict(parmList) |
|
1645 | 1657 | |
|
1646 | 1658 | choices = [] |
|
1647 | 1659 | isDerivedDict = {} |
|
1648 | 1660 | parmDescDict = {} |
|
1649 | 1661 | for catDesc, catID in catList: |
|
1650 | 1662 | if catID not in list(catDict.keys()): |
|
1651 | 1663 | continue |
|
1652 | 1664 | theseParms = [] |
|
1653 | 1665 | for parm in catDict[catID][1]: |
|
1654 | 1666 | theseParms.append((parm, parm)) |
|
1655 | 1667 | isDerivedDict[parm] = False |
|
1656 | 1668 | parmDescDict[parm] = madParmObj.getParmDescription(parm) |
|
1657 | 1669 | choices.append((catDesc, theseParms)) |
|
1658 | 1670 | |
|
1659 | 1671 | super(AdvScriptParmsForm, self).__init__(*args, **kwargs) |
|
1660 | 1672 | |
|
1661 | 1673 | self.fields['parameters'] = IsprintChoiceField(choices=choices, |
|
1662 | 1674 | initial=['YEAR', 'MIN'], |
|
1663 | 1675 | required=False, |
|
1664 | 1676 | isDerivedDict=isDerivedDict, |
|
1665 | 1677 | parmDescDict=parmDescDict, |
|
1666 | 1678 | separateProlog=False, |
|
1667 | 1679 | label = "") |
|
1668 | 1680 | |
|
1669 | 1681 | |
|
1670 | 1682 | class AdvScriptParmsFiltersForm(django.forms.Form): |
|
1671 | 1683 | """AdvScriptParmsFiltersForm is the form for the parameter filters in the scrip generator |
|
1672 | 1684 | """ |
|
1673 | 1685 | def __init__(self, *args, **kwargs): |
|
1674 | 1686 | |
|
1675 | 1687 | kinst = int(getSelection('instruments', args, kwargs)) |
|
1676 | 1688 | if kinst == 0: |
|
1677 | 1689 | raise ValueError('kinst should never be zero') |
|
1678 | 1690 | madDB = madrigal.metadata.MadrigalDB() |
|
1679 | 1691 | madParmObj = madrigal.data.MadrigalParameters(madDB) |
|
1680 | 1692 | parmList = madParmObj.getParametersForInstruments([kinst]) |
|
1681 | 1693 | self.parmList = [] |
|
1682 | 1694 | for parm in parmList: |
|
1683 | 1695 | self.parmList.append((parm, madParmObj.getSimpleParmDescription(parm))) |
|
1684 | 1696 | |
|
1685 | 1697 | super(AdvScriptParmsFiltersForm, self).__init__(*args, **kwargs) |
|
1686 | 1698 | |
|
1687 | 1699 | choices = [(parm, parm) for parm in parmList] |
|
1688 | 1700 | choices_with_null = [('None', 'None')] + choices |
|
1689 | 1701 | |
|
1690 | 1702 | self.fields['parm_1'] = django.forms.ChoiceField(required=False, |
|
1691 | 1703 | choices=choices_with_null) |
|
1692 | 1704 | self.fields['parm_1_lower'] = django.forms.CharField(required=False, initial='') |
|
1693 | 1705 | self.fields['parm_1_upper'] = django.forms.CharField(required=False, initial='') |
|
1694 | 1706 | |
|
1695 | 1707 | self.fields['parm_2'] = django.forms.ChoiceField(required=False, |
|
1696 | 1708 | choices=choices_with_null) |
|
1697 | 1709 | self.fields['parm_2_lower'] = django.forms.CharField(required=False, initial='') |
|
1698 | 1710 | self.fields['parm_2_upper'] = django.forms.CharField(required=False, initial='') |
|
1699 | 1711 | |
|
1700 | 1712 | self.fields['parm_3'] = django.forms.ChoiceField(required=False, |
|
1701 | 1713 | choices=choices_with_null) |
|
1702 | 1714 | self.fields['parm_3_lower'] = django.forms.CharField(required=False, initial='') |
|
1703 | 1715 | self.fields['parm_3_upper'] = django.forms.CharField(required=False, initial='') |
|
1704 | 1716 | |
|
1705 | 1717 | |
|
1706 | 1718 | |
|
1707 | 1719 | class MadCalculatorForm(django.forms.Form): |
|
1708 | 1720 | """MadCalculatorForm is the form for the madCalculator page |
|
1709 | 1721 | """ |
|
1710 | 1722 | def __init__(self, *args, **kwargs): |
|
1711 | 1723 | """ |
|
1712 | 1724 | """ |
|
1713 | 1725 | madDB = madrigal.metadata.MadrigalDB() |
|
1714 | 1726 | madParmObj = madrigal.data.MadrigalParameters(madDB) |
|
1715 | 1727 | super(MadCalculatorForm, self).__init__(*args, **kwargs) |
|
1716 | 1728 | fullDerivedParmList = madrigal.derivation.getDerivableParms(['gdalt', 'gdlat', 'glon']) |
|
1717 | 1729 | |
|
1718 | 1730 | # removed unwanted time and prolog parameters |
|
1719 | 1731 | rejectedCats = ('Time Related Parameter', 'Prolog Parameters', 'Radar Instrument Operation Parameter', |
|
1720 | 1732 | 'Madrigal Hdf5 Prolog Parameters') |
|
1721 | 1733 | # define time parameters that do make sense to calculate |
|
1722 | 1734 | neededTimeParms = ('APLT', 'CONJ_SUNRISE_H', 'CONJ_SUNSET_H', |
|
1723 | 1735 | 'SUNRISE_H', 'SUNSET_H', 'MLT') |
|
1724 | 1736 | |
|
1725 | 1737 | # skip parms related to inst location |
|
1726 | 1738 | instLocationParms = ('AZM','ELM','GALTR','GDLONR','GDLATR','RANGE', 'ASPECT', |
|
1727 | 1739 | 'GDALT', 'GDLAT', 'GLON', 'CXR', 'CYR', 'CZR') |
|
1728 | 1740 | |
|
1729 | 1741 | madCatObj = madrigal.metadata.MadrigalParmCategory(madDB) |
|
1730 | 1742 | |
|
1731 | 1743 | catList = madCatObj.getCategoryList() |
|
1732 | 1744 | catDict = madParmObj.getCategoryDict(fullDerivedParmList) |
|
1733 | 1745 | choices = [] |
|
1734 | 1746 | isDerivedDict = {} |
|
1735 | 1747 | self.parmDescDict = {} |
|
1736 | 1748 | for catDesc, catID in catList: |
|
1737 | 1749 | if catDesc in rejectedCats[1:]: |
|
1738 | 1750 | continue |
|
1739 | 1751 | if catID not in list(catDict.keys()): |
|
1740 | 1752 | continue |
|
1741 | 1753 | theseParms = [] |
|
1742 | 1754 | for parm in catDict[catID][1]: |
|
1743 | 1755 | if parm in instLocationParms: |
|
1744 | 1756 | continue |
|
1745 | 1757 | if catDesc in rejectedCats and parm not in neededTimeParms: |
|
1746 | 1758 | continue |
|
1747 | 1759 | if not parm in fullDerivedParmList: |
|
1748 | 1760 | continue |
|
1749 | 1761 | theseParms.append((parm, parm)) |
|
1750 | 1762 | isDerivedDict[parm] = True |
|
1751 | 1763 | self.parmDescDict[parm] = madParmObj.getParmDescription(parm) |
|
1752 | 1764 | choices.append((catDesc, theseParms)) |
|
1753 | 1765 | |
|
1754 | 1766 | |
|
1755 | 1767 | |
|
1756 | 1768 | # form fields |
|
1757 | 1769 | self.fields['min_latitude'] = django.forms.FloatField(initial=-90.0, min_value=-90.0, |
|
1758 | 1770 | max_value=90.0) |
|
1759 | 1771 | self.fields['max_latitude'] = django.forms.FloatField(initial=90.0, min_value=-90.0, |
|
1760 | 1772 | max_value=90.0) |
|
1761 | 1773 | self.fields['delta_latitude'] = django.forms.FloatField(initial=45, min_value=1.0E-6) |
|
1762 | 1774 | |
|
1763 | 1775 | self.fields['min_longitude'] = django.forms.FloatField(initial=-180.0, min_value=-180.0, |
|
1764 | 1776 | max_value=180.0) |
|
1765 | 1777 | self.fields['max_longitude'] = django.forms.FloatField(initial=180.0, min_value=-180.0, |
|
1766 | 1778 | max_value=180.0) |
|
1767 | 1779 | self.fields['delta_longitude'] = django.forms.FloatField(initial=90, min_value=1.0E-6) |
|
1768 | 1780 | |
|
1769 | 1781 | self.fields['min_altitude'] = django.forms.FloatField(initial=0.0, min_value=0.0) |
|
1770 | 1782 | self.fields['max_altitude'] = django.forms.FloatField(initial=600.0, min_value=0.0) |
|
1771 | 1783 | self.fields['delta_altitude'] = django.forms.FloatField(initial=200, min_value=1.0E-6) |
|
1772 | 1784 | |
|
1773 | 1785 | # time selection |
|
1774 | 1786 | now = datetime.datetime.utcnow() |
|
1775 | 1787 | self.fields['datetime'] = django.forms.SplitDateTimeField(input_date_formats=['%Y-%m-%d'], input_time_formats=['%H:%M:%S'], |
|
1776 | 1788 | label='Select UT datetime', |
|
1777 | 1789 | help_text='Select the UT time at which to run this calcuation', |
|
1778 | 1790 | initial=datetime.datetime(now.year,1,1)) |
|
1779 | 1791 | |
|
1780 | 1792 | self.fields['parameters'] = IsprintChoiceField(choices=choices, |
|
1781 | 1793 | required=False, |
|
1782 | 1794 | isDerivedDict=isDerivedDict, |
|
1783 | 1795 | parmDescDict=self.parmDescDict, |
|
1784 | 1796 | separateProlog=False, |
|
1785 | 1797 | label = "") |
|
1786 | 1798 | |
|
1787 | 1799 | |
|
1788 | 1800 | def clean(self): |
|
1789 | 1801 | """clean is the Django method to validate things in a form that require looking at multiple fields |
|
1790 | 1802 | """ |
|
1791 | 1803 | max_len = 1.0E5 |
|
1792 | 1804 | try: |
|
1793 | 1805 | a1 = numpy.arange(self.cleaned_data['min_latitude'], self.cleaned_data['max_latitude'], self.cleaned_data['delta_latitude']) |
|
1794 | 1806 | if len(a1) > max_len: |
|
1795 | 1807 | raise django.forms.ValidationError('Too many latitudes: %i.' % (len(a1))) |
|
1796 | 1808 | except ZeroDivisionError: |
|
1797 | 1809 | raise django.forms.ValidationError('Infinite latitudes') |
|
1798 | 1810 | |
|
1799 | 1811 | try: |
|
1800 | 1812 | a2 = numpy.arange(self.cleaned_data['min_longitude'], self.cleaned_data['max_longitude'], self.cleaned_data['delta_longitude']) |
|
1801 | 1813 | if len(a1) > max_len: |
|
1802 | 1814 | raise django.forms.ValidationError('Too many longitudes: %i.' % (len(a1))) |
|
1803 | 1815 | except ZeroDivisionError: |
|
1804 | 1816 | raise django.forms.ValidationError('Infinite longitudes') |
|
1805 | 1817 | |
|
1806 | 1818 | try: |
|
1807 | 1819 | a3 = numpy.arange(self.cleaned_data['min_altitude'], self.cleaned_data['max_altitude'], self.cleaned_data['delta_altitude']) |
|
1808 | 1820 | if len(a1) > max_len: |
|
1809 | 1821 | raise django.forms.ValidationError('Too many altitudes: %i.' % (len(a1))) |
|
1810 | 1822 | except ZeroDivisionError: |
|
1811 | 1823 | raise django.forms.ValidationError('Infinite altitudes') |
|
1812 | 1824 | |
|
1813 | 1825 | total = len(a1) * len(a2) * len(a3) |
|
1814 | 1826 | if total > max_len: |
|
1815 | 1827 | raise django.forms.ValidationError('Too many calculations: %i' % (total)) |
|
1816 | 1828 | |
|
1817 | 1829 | |
|
1818 | 1830 | |
|
1819 | 1831 | class GetMetadataForm(django.forms.Form): |
|
1820 | 1832 | """GetMetadataForm is the form for the getMetadata page |
|
1821 | 1833 | """ |
|
1822 | 1834 | def __init__(self, *args, **kwargs): |
|
1823 | 1835 | """ |
|
1824 | 1836 | """ |
|
1825 | 1837 | super(GetMetadataForm, self).__init__(*args, **kwargs) |
|
1826 | 1838 | |
|
1827 | 1839 | fileTypeChoices = (("0", "Experiment Table"), |
|
1828 | 1840 | ("1", "File Table"), |
|
1829 | 1841 | ("3", "Instrument Table"), |
|
1830 | 1842 | ("4", "Parameter Table"), |
|
1831 | 1843 | ("5", "Site Table"), |
|
1832 | 1844 | ("6", "Type Table"), |
|
1833 | 1845 | ("7", "Instrument Kindat Table"), |
|
1834 | 1846 | ("8", "Instrument Parameter Table"), |
|
1835 | 1847 | ("9", "Madrigal categories table"), |
|
1836 | 1848 | ("10", "Instrument categories table"),) |
|
1837 | 1849 | |
|
1838 | 1850 | self.fields['fileType'] = django.forms.ChoiceField(widget = django.forms.RadioSelect, |
|
1839 | 1851 | choices=fileTypeChoices, |
|
1840 | 1852 | initial="0", |
|
1841 | 1853 | label="Choose the metadata file type to download") |
|
1842 | 1854 | |
|
1843 | 1855 | |
|
1844 | 1856 | class LookerSelectForm(django.forms.Form): |
|
1845 | 1857 | """LookerSelectForm is the form for the looker_form page |
|
1846 | 1858 | """ |
|
1847 | 1859 | def __init__(self, *args, **kwargs): |
|
1848 | 1860 | """ |
|
1849 | 1861 | """ |
|
1850 | 1862 | super(LookerSelectForm, self).__init__(*args, **kwargs) |
|
1851 | 1863 | |
|
1852 | 1864 | lookerOptionChoices = (("1", "Geodetic latitude, longitude and altitude of the points"), |
|
1853 | 1865 | ("2", "Apex latitude, longitude and altitude of the points"), |
|
1854 | 1866 | ("3", "Geodetic latitude, longitude and altitude of the points"), |
|
1855 | 1867 | ("4", "Azimuth, elevation and range of the points from a specified instrument (output includes aspect angle)"), |
|
1856 | 1868 | ("5", "Azimuth, elevation, range from specified instrument"), |
|
1857 | 1869 | ("6", "Geodetic latitude, longitude, altitude of a point on the field line"), |
|
1858 | 1870 | ("7", "Apex latitude, longitude of the field line"), |
|
1859 | 1871 | ("8", "Geodetic latitude, longitude and altitude of the points")) |
|
1860 | 1872 | |
|
1861 | 1873 | self.fields['looker_options'] = django.forms.ChoiceField(widget = django.forms.RadioSelect, |
|
1862 | 1874 | choices=lookerOptionChoices, |
|
1863 | 1875 | initial="1") |
|
1864 | 1876 | |
|
1865 | 1877 | |
|
1866 | 1878 | class LookerGeodeticRadar(django.forms.Form): |
|
1867 | 1879 | """LookerGeodeticRadar is the form for the geodetic to radar page |
|
1868 | 1880 | """ |
|
1869 | 1881 | def __init__(self, *args, **kwargs): |
|
1870 | 1882 | """ |
|
1871 | 1883 | """ |
|
1872 | 1884 | super(LookerGeodeticRadar, self).__init__(*args, **kwargs) |
|
1873 | 1885 | madDB = madrigal.metadata.MadrigalDB() |
|
1874 | 1886 | madInstData = madrigal.metadata.MadrigalInstrumentData(madDB) |
|
1875 | 1887 | dict1 = {'isGlobal': True, 'categories': "0"} |
|
1876 | 1888 | |
|
1877 | 1889 | self.fields['looker_options'] = django.forms.CharField(initial="1", |
|
1878 | 1890 | widget=django.forms.HiddenInput(attrs={'value': "1"})) |
|
1879 | 1891 | |
|
1880 | 1892 | self.fields['instruments'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={'size':'3'}), |
|
1881 | 1893 | choices=getInstrumentList([], dict1, madInstData, 'Set location manually', local=False), |
|
1882 | 1894 | required=False, label='Instrument: ') |
|
1883 | 1895 | |
|
1884 | 1896 | self.fields['inst_lat'] = django.forms.FloatField(initial=0.0, min_value=-90.0, max_value=90.0, |
|
1885 | 1897 | widget=django.forms.TextInput(attrs={'size':5})) |
|
1886 | 1898 | self.fields['inst_lon'] = django.forms.FloatField(initial=0.0, min_value=-180.0, max_value=180.0, |
|
1887 | 1899 | widget=django.forms.TextInput(attrs={'size':5})) |
|
1888 | 1900 | self.fields['inst_alt'] = django.forms.FloatField(initial=0.0, min_value=0.0, |
|
1889 | 1901 | widget=django.forms.TextInput(attrs={'size':5})) |
|
1890 | 1902 | self.fields['start_lat'] = django.forms.FloatField(initial=30.0, min_value=-90.0, max_value=90.0, |
|
1891 | 1903 | widget=django.forms.TextInput(attrs={'size':5})) |
|
1892 | 1904 | self.fields['stop_lat'] = django.forms.FloatField(initial=50.0, min_value=-90.0, max_value=90.0, |
|
1893 | 1905 | widget=django.forms.TextInput(attrs={'size':5})) |
|
1894 | 1906 | self.fields['step_lat'] = django.forms.FloatField(initial=10.0, min_value=0.0, |
|
1895 | 1907 | widget=django.forms.TextInput(attrs={'size':5})) |
|
1896 | 1908 | self.fields['start_lon'] = django.forms.FloatField(initial=-100.0, min_value=-180.0, max_value=180.0, |
|
1897 | 1909 | widget=django.forms.TextInput(attrs={'size':5})) |
|
1898 | 1910 | self.fields['stop_lon'] = django.forms.FloatField(initial=-80.0, min_value=-180.0, max_value=180.0, |
|
1899 | 1911 | widget=django.forms.TextInput(attrs={'size':5})) |
|
1900 | 1912 | self.fields['step_lon'] = django.forms.FloatField(initial=10.0, min_value=0.0, |
|
1901 | 1913 | widget=django.forms.TextInput(attrs={'size':5})) |
|
1902 | 1914 | self.fields['start_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0, |
|
1903 | 1915 | widget=django.forms.TextInput(attrs={'size':5})) |
|
1904 | 1916 | self.fields['stop_alt'] = django.forms.FloatField(initial=500.0, min_value=0.0, |
|
1905 | 1917 | widget=django.forms.TextInput(attrs={'size':5})) |
|
1906 | 1918 | self.fields['step_alt'] = django.forms.FloatField(initial=500.0, min_value=0.0, |
|
1907 | 1919 | widget=django.forms.TextInput(attrs={'size':5})) |
|
1908 | 1920 | |
|
1909 | 1921 | |
|
1910 | 1922 | class LookerGeomagRadar(django.forms.Form): |
|
1911 | 1923 | """LookerGeomagRadar is the form for the geomagnetic to radar page |
|
1912 | 1924 | """ |
|
1913 | 1925 | def __init__(self, *args, **kwargs): |
|
1914 | 1926 | """ |
|
1915 | 1927 | """ |
|
1916 | 1928 | super(LookerGeomagRadar, self).__init__(*args, **kwargs) |
|
1917 | 1929 | madDB = madrigal.metadata.MadrigalDB() |
|
1918 | 1930 | madInstData = madrigal.metadata.MadrigalInstrumentData(madDB) |
|
1919 | 1931 | dict1 = {'isGlobal': True, 'categories': "0"} |
|
1920 | 1932 | |
|
1921 | 1933 | self.fields['looker_options'] = django.forms.CharField(initial="2", |
|
1922 | 1934 | widget=django.forms.HiddenInput(attrs={'value': "2"})) |
|
1923 | 1935 | |
|
1924 | 1936 | self.fields['instruments'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={'size':'3'}), |
|
1925 | 1937 | choices=getInstrumentList([], dict1, madInstData, 'Set location manually', local=False), |
|
1926 | 1938 | required=False, label='Instrument: ') |
|
1927 | 1939 | |
|
1928 | 1940 | self.fields['inst_lat'] = django.forms.FloatField(initial=0.0, min_value=-90.0, max_value=90.0, |
|
1929 | 1941 | widget=django.forms.TextInput(attrs={'size':5})) |
|
1930 | 1942 | self.fields['inst_lon'] = django.forms.FloatField(initial=0.0, min_value=-180.0, max_value=180.0, |
|
1931 | 1943 | widget=django.forms.TextInput(attrs={'size':5})) |
|
1932 | 1944 | self.fields['inst_alt'] = django.forms.FloatField(initial=0.0, min_value=0.0, |
|
1933 | 1945 | widget=django.forms.TextInput(attrs={'size':5})) |
|
1934 | 1946 | self.fields['start_lat'] = django.forms.FloatField(initial=30.0, min_value=-90.0, max_value=90.0, |
|
1935 | 1947 | widget=django.forms.TextInput(attrs={'size':5})) |
|
1936 | 1948 | self.fields['stop_lat'] = django.forms.FloatField(initial=50.0, min_value=-90.0, max_value=90.0, |
|
1937 | 1949 | widget=django.forms.TextInput(attrs={'size':5})) |
|
1938 | 1950 | self.fields['step_lat'] = django.forms.FloatField(initial=10.0, min_value=0.0, |
|
1939 | 1951 | widget=django.forms.TextInput(attrs={'size':5})) |
|
1940 | 1952 | self.fields['start_lon'] = django.forms.FloatField(initial=-100.0, min_value=-180.0, max_value=180.0, |
|
1941 | 1953 | widget=django.forms.TextInput(attrs={'size':5})) |
|
1942 | 1954 | self.fields['stop_lon'] = django.forms.FloatField(initial=-80.0, min_value=-180.0, max_value=180.0, |
|
1943 | 1955 | widget=django.forms.TextInput(attrs={'size':5})) |
|
1944 | 1956 | self.fields['step_lon'] = django.forms.FloatField(initial=10.0, min_value=0.0, |
|
1945 | 1957 | widget=django.forms.TextInput(attrs={'size':5})) |
|
1946 | 1958 | self.fields['start_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0, |
|
1947 | 1959 | widget=django.forms.TextInput(attrs={'size':5})) |
|
1948 | 1960 | self.fields['stop_alt'] = django.forms.FloatField(initial=500.0, min_value=0.0, |
|
1949 | 1961 | widget=django.forms.TextInput(attrs={'size':5})) |
|
1950 | 1962 | self.fields['step_alt'] = django.forms.FloatField(initial=500.0, min_value=0.0, |
|
1951 | 1963 | widget=django.forms.TextInput(attrs={'size':5})) |
|
1952 | 1964 | now = datetime.datetime.utcnow() |
|
1953 | 1965 | self.fields['year'] = django.forms.FloatField(initial=float(now.year), min_value=1950.0, |
|
1954 | 1966 | widget=django.forms.TextInput(attrs={'size':5})) |
|
1955 | 1967 | |
|
1956 | 1968 | class LookerGeomagFromGeodetic(django.forms.Form): |
|
1957 | 1969 | """LookerGeomagFromGeodetic is the form for the geomagnetic from geodetic page |
|
1958 | 1970 | """ |
|
1959 | 1971 | def __init__(self, *args, **kwargs): |
|
1960 | 1972 | """ |
|
1961 | 1973 | """ |
|
1962 | 1974 | super(LookerGeomagFromGeodetic, self).__init__(*args, **kwargs) |
|
1963 | 1975 | |
|
1964 | 1976 | self.fields['looker_options'] = django.forms.CharField(initial="3", |
|
1965 | 1977 | widget=django.forms.HiddenInput(attrs={'value': "3"})) |
|
1966 | 1978 | |
|
1967 | 1979 | self.fields['start_lat'] = django.forms.FloatField(initial=30.0, min_value=-90.0, max_value=90.0, |
|
1968 | 1980 | widget=django.forms.TextInput(attrs={'size':5})) |
|
1969 | 1981 | self.fields['stop_lat'] = django.forms.FloatField(initial=50.0, min_value=-90.0, max_value=90.0, |
|
1970 | 1982 | widget=django.forms.TextInput(attrs={'size':5})) |
|
1971 | 1983 | self.fields['step_lat'] = django.forms.FloatField(initial=10.0, min_value=0.0, |
|
1972 | 1984 | widget=django.forms.TextInput(attrs={'size':5})) |
|
1973 | 1985 | self.fields['start_lon'] = django.forms.FloatField(initial=-100.0, min_value=-180.0, max_value=180.0, |
|
1974 | 1986 | widget=django.forms.TextInput(attrs={'size':5})) |
|
1975 | 1987 | self.fields['stop_lon'] = django.forms.FloatField(initial=-80.0, min_value=-180.0, max_value=180.0, |
|
1976 | 1988 | widget=django.forms.TextInput(attrs={'size':5})) |
|
1977 | 1989 | self.fields['step_lon'] = django.forms.FloatField(initial=10.0, min_value=0.0, |
|
1978 | 1990 | widget=django.forms.TextInput(attrs={'size':5})) |
|
1979 | 1991 | self.fields['start_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0, |
|
1980 | 1992 | widget=django.forms.TextInput(attrs={'size':5})) |
|
1981 | 1993 | self.fields['stop_alt'] = django.forms.FloatField(initial=500.0, min_value=0.0, |
|
1982 | 1994 | widget=django.forms.TextInput(attrs={'size':5})) |
|
1983 | 1995 | self.fields['step_alt'] = django.forms.FloatField(initial=500.0, min_value=0.0, |
|
1984 | 1996 | widget=django.forms.TextInput(attrs={'size':5})) |
|
1985 | 1997 | now = datetime.datetime.utcnow() |
|
1986 | 1998 | self.fields['year'] = django.forms.FloatField(initial=float(now.year), min_value=1950.0, |
|
1987 | 1999 | widget=django.forms.TextInput(attrs={'size':5})) |
|
1988 | 2000 | |
|
1989 | 2001 | class LookerGeomagFromRadar(django.forms.Form): |
|
1990 | 2002 | """LookerGeomagFromRadar is the form for the geomagnetic from radar page |
|
1991 | 2003 | """ |
|
1992 | 2004 | def __init__(self, *args, **kwargs): |
|
1993 | 2005 | """ |
|
1994 | 2006 | """ |
|
1995 | 2007 | super(LookerGeomagFromRadar, self).__init__(*args, **kwargs) |
|
1996 | 2008 | madDB = madrigal.metadata.MadrigalDB() |
|
1997 | 2009 | madInstData = madrigal.metadata.MadrigalInstrumentData(madDB) |
|
1998 | 2010 | dict1 = {'isGlobal': True, 'categories': "0"} |
|
1999 | 2011 | |
|
2000 | 2012 | self.fields['looker_options'] = django.forms.CharField(initial="4", |
|
2001 | 2013 | widget=django.forms.HiddenInput(attrs={'value': "4"})) |
|
2002 | 2014 | |
|
2003 | 2015 | self.fields['instruments'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={'size':'3'}), |
|
2004 | 2016 | choices=getInstrumentList([], dict1, madInstData, local=False)[1:], |
|
2005 | 2017 | required=False, label='Instrument: ') |
|
2006 | 2018 | |
|
2007 | 2019 | self.fields['inst_lat'] = django.forms.FloatField(initial=0.0, min_value=-90.0, max_value=90.0, |
|
2008 | 2020 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2009 | 2021 | self.fields['inst_lon'] = django.forms.FloatField(initial=0.0, min_value=-180.0, max_value=180.0, |
|
2010 | 2022 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2011 | 2023 | self.fields['inst_alt'] = django.forms.FloatField(initial=0.0, min_value=0.0, |
|
2012 | 2024 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2013 | 2025 | self.fields['start_az'] = django.forms.FloatField(initial=-180.0, min_value=-180.0, max_value=180.0, |
|
2014 | 2026 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2015 | 2027 | self.fields['stop_az'] = django.forms.FloatField(initial=180.0, min_value=-180.0, max_value=180.0, |
|
2016 | 2028 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2017 | 2029 | self.fields['step_az'] = django.forms.FloatField(initial=45.0, min_value=0.0, |
|
2018 | 2030 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2019 | 2031 | self.fields['start_el'] = django.forms.FloatField(initial=0.0, min_value=0.0, max_value=90.0, |
|
2020 | 2032 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2021 | 2033 | self.fields['stop_el'] = django.forms.FloatField(initial=90.0, min_value=0.0, max_value=90.0, |
|
2022 | 2034 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2023 | 2035 | self.fields['step_el'] = django.forms.FloatField(initial=30.0, min_value=0.0, |
|
2024 | 2036 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2025 | 2037 | self.fields['start_range'] = django.forms.FloatField(initial=0.0, min_value=0.0, |
|
2026 | 2038 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2027 | 2039 | self.fields['stop_range'] = django.forms.FloatField(initial=600.0, min_value=0.0, |
|
2028 | 2040 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2029 | 2041 | self.fields['step_range'] = django.forms.FloatField(initial=200.0, min_value=0.0, |
|
2030 | 2042 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2031 | 2043 | now = datetime.datetime.utcnow() |
|
2032 | 2044 | self.fields['year'] = django.forms.FloatField(initial=float(now.year), min_value=1950.0, |
|
2033 | 2045 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2034 | 2046 | |
|
2035 | 2047 | |
|
2036 | 2048 | class LookerFieldLineFromRadar(django.forms.Form): |
|
2037 | 2049 | """LookerFieldLineFromRadar is the form for the field line from radar page |
|
2038 | 2050 | """ |
|
2039 | 2051 | def __init__(self, *args, **kwargs): |
|
2040 | 2052 | """ |
|
2041 | 2053 | """ |
|
2042 | 2054 | super(LookerFieldLineFromRadar, self).__init__(*args, **kwargs) |
|
2043 | 2055 | madDB = madrigal.metadata.MadrigalDB() |
|
2044 | 2056 | madInstData = madrigal.metadata.MadrigalInstrumentData(madDB) |
|
2045 | 2057 | dict1 = {'isGlobal': True, 'categories': "0"} |
|
2046 | 2058 | |
|
2047 | 2059 | self.fields['looker_options'] = django.forms.CharField(initial="5", |
|
2048 | 2060 | widget=django.forms.HiddenInput(attrs={'value': "5"})) |
|
2049 | 2061 | |
|
2050 | 2062 | self.fields['instruments'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={'size':'3'}), |
|
2051 | 2063 | choices=getInstrumentList([], dict1, madInstData, 'Set location manually', local=False), |
|
2052 | 2064 | required=False, label='Instrument: ') |
|
2053 | 2065 | |
|
2054 | 2066 | self.fields['inst_lat'] = django.forms.FloatField(initial=0.0, min_value=-90.0, max_value=90.0, |
|
2055 | 2067 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2056 | 2068 | self.fields['inst_lon'] = django.forms.FloatField(initial=0.0, min_value=-180.0, max_value=180.0, |
|
2057 | 2069 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2058 | 2070 | self.fields['inst_alt'] = django.forms.FloatField(initial=0.0, min_value=0.0, |
|
2059 | 2071 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2060 | 2072 | self.fields['fl_az'] = django.forms.FloatField(initial=0.0, min_value=-180.0, max_value=180.0, |
|
2061 | 2073 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2062 | 2074 | self.fields['fl_el'] = django.forms.FloatField(initial=45.0, min_value=0.0, max_value=90.0, |
|
2063 | 2075 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2064 | 2076 | self.fields['fl_range'] = django.forms.FloatField(initial=1000.0, min_value=0.0, |
|
2065 | 2077 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2066 | 2078 | |
|
2067 | 2079 | self.fields['start_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0, |
|
2068 | 2080 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2069 | 2081 | self.fields['stop_alt'] = django.forms.FloatField(initial=1000.0, min_value=0.0, |
|
2070 | 2082 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2071 | 2083 | self.fields['step_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0, |
|
2072 | 2084 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2073 | 2085 | now = datetime.datetime.utcnow() |
|
2074 | 2086 | self.fields['year'] = django.forms.FloatField(initial=float(now.year), min_value=1950.0, |
|
2075 | 2087 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2076 | 2088 | |
|
2077 | 2089 | |
|
2078 | 2090 | |
|
2079 | 2091 | class LookerFieldLineFromGeodetic(django.forms.Form): |
|
2080 | 2092 | """LookerFieldLineFromGeodetic is the form for the field line from geodetic page |
|
2081 | 2093 | """ |
|
2082 | 2094 | def __init__(self, *args, **kwargs): |
|
2083 | 2095 | """ |
|
2084 | 2096 | """ |
|
2085 | 2097 | super(LookerFieldLineFromGeodetic, self).__init__(*args, **kwargs) |
|
2086 | 2098 | madDB = madrigal.metadata.MadrigalDB() |
|
2087 | 2099 | madInstData = madrigal.metadata.MadrigalInstrumentData(madDB) |
|
2088 | 2100 | dict1 = {'isGlobal': True, 'categories': "0"} |
|
2089 | 2101 | |
|
2090 | 2102 | self.fields['looker_options'] = django.forms.CharField(initial="6", |
|
2091 | 2103 | widget=django.forms.HiddenInput(attrs={'value': "6"})) |
|
2092 | 2104 | |
|
2093 | 2105 | self.fields['instruments'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={'size':'3'}), |
|
2094 | 2106 | choices=getInstrumentList([], dict1, madInstData, 'Set location manually', local=False), |
|
2095 | 2107 | required=False, label='Instrument: ') |
|
2096 | 2108 | |
|
2097 | 2109 | self.fields['inst_lat'] = django.forms.FloatField(initial=0.0, min_value=-90.0, max_value=90.0, |
|
2098 | 2110 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2099 | 2111 | self.fields['inst_lon'] = django.forms.FloatField(initial=0.0, min_value=-180.0, max_value=180.0, |
|
2100 | 2112 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2101 | 2113 | self.fields['inst_alt'] = django.forms.FloatField(initial=0.0, min_value=0.0, |
|
2102 | 2114 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2103 | 2115 | self.fields['fl_lat'] = django.forms.FloatField(initial=45.0, min_value=-90.0, max_value=90.0, |
|
2104 | 2116 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2105 | 2117 | self.fields['fl_lon'] = django.forms.FloatField(initial=-90.0, min_value=-180.0, max_value=180.0, |
|
2106 | 2118 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2107 | 2119 | self.fields['fl_alt'] = django.forms.FloatField(initial=0.0, min_value=0.0, |
|
2108 | 2120 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2109 | 2121 | |
|
2110 | 2122 | self.fields['start_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0, |
|
2111 | 2123 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2112 | 2124 | self.fields['stop_alt'] = django.forms.FloatField(initial=1000.0, min_value=0.0, |
|
2113 | 2125 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2114 | 2126 | self.fields['step_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0, |
|
2115 | 2127 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2116 | 2128 | now = datetime.datetime.utcnow() |
|
2117 | 2129 | self.fields['year'] = django.forms.FloatField(initial=float(now.year), min_value=1950.0, |
|
2118 | 2130 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2119 | 2131 | |
|
2120 | 2132 | |
|
2121 | 2133 | class LookerFieldLineFromApex(django.forms.Form): |
|
2122 | 2134 | """LookerFieldLineFromApex is the form for the field line from apex coordinates page |
|
2123 | 2135 | """ |
|
2124 | 2136 | def __init__(self, *args, **kwargs): |
|
2125 | 2137 | """ |
|
2126 | 2138 | """ |
|
2127 | 2139 | super(LookerFieldLineFromApex, self).__init__(*args, **kwargs) |
|
2128 | 2140 | madDB = madrigal.metadata.MadrigalDB() |
|
2129 | 2141 | madInstData = madrigal.metadata.MadrigalInstrumentData(madDB) |
|
2130 | 2142 | dict1 = {'isGlobal': True, 'categories': "0"} |
|
2131 | 2143 | |
|
2132 | 2144 | self.fields['looker_options'] = django.forms.CharField(initial="7", |
|
2133 | 2145 | widget=django.forms.HiddenInput(attrs={'value': "7"})) |
|
2134 | 2146 | |
|
2135 | 2147 | self.fields['instruments'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={'size':'3'}), |
|
2136 | 2148 | choices=getInstrumentList([], dict1, madInstData, 'Set location manually', local=False), |
|
2137 | 2149 | required=False, label='Instrument: ') |
|
2138 | 2150 | |
|
2139 | 2151 | self.fields['inst_lat'] = django.forms.FloatField(initial=0.0, min_value=-90.0, max_value=90.0, |
|
2140 | 2152 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2141 | 2153 | self.fields['inst_lon'] = django.forms.FloatField(initial=0.0, min_value=-180.0, max_value=180.0, |
|
2142 | 2154 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2143 | 2155 | self.fields['inst_alt'] = django.forms.FloatField(initial=0.0, min_value=0.0, |
|
2144 | 2156 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2145 | 2157 | self.fields['fl_apex_lat'] = django.forms.FloatField(initial=65.0, min_value=-00.0, max_value=90.0, |
|
2146 | 2158 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2147 | 2159 | self.fields['fl_apex_lon'] = django.forms.FloatField(initial=-90.0, min_value=-180.0, max_value=180.0, |
|
2148 | 2160 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2149 | 2161 | |
|
2150 | 2162 | self.fields['start_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0, |
|
2151 | 2163 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2152 | 2164 | self.fields['stop_alt'] = django.forms.FloatField(initial=1000.0, min_value=0.0, |
|
2153 | 2165 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2154 | 2166 | self.fields['step_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0, |
|
2155 | 2167 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2156 | 2168 | now = datetime.datetime.utcnow() |
|
2157 | 2169 | self.fields['year'] = django.forms.FloatField(initial=float(now.year), min_value=1950.0, |
|
2158 | 2170 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2159 | 2171 | |
|
2160 | 2172 | |
|
2161 | 2173 | class LookerConjugateFromGeodetic(django.forms.Form): |
|
2162 | 2174 | """LookerConjugateFromGeodetic is the form for the geomagnetic/conjugate from geodetic page |
|
2163 | 2175 | """ |
|
2164 | 2176 | def __init__(self, *args, **kwargs): |
|
2165 | 2177 | """ |
|
2166 | 2178 | """ |
|
2167 | 2179 | super(LookerConjugateFromGeodetic, self).__init__(*args, **kwargs) |
|
2168 | 2180 | |
|
2169 | 2181 | parmChoices = [("MAGCONJLAT", 'Magnetic conjugate latitude'), |
|
2170 | 2182 | ("MAGCONJLON", 'Magnetic conjugate longitude'), |
|
2171 | 2183 | ("SZEN", 'Solar zenith angle'), |
|
2172 | 2184 | ("SZENC", 'Magnetic conjugate solar zenith angle'), |
|
2173 | 2185 | ("SDWHT", 'Shadow height (km)'), |
|
2174 | 2186 | ("MAGCONJSDWHT", 'Magnetic conjugate shadow height (km)')] |
|
2175 | 2187 | parmInitial = [key for key, value in parmChoices] |
|
2176 | 2188 | |
|
2177 | 2189 | self.fields['looker_options'] = django.forms.CharField(initial="8", |
|
2178 | 2190 | widget=django.forms.HiddenInput(attrs={'value': "8"})) |
|
2179 | 2191 | |
|
2180 | 2192 | self.fields['start_lat'] = django.forms.FloatField(initial=30.0, min_value=-90.0, max_value=90.0, |
|
2181 | 2193 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2182 | 2194 | self.fields['stop_lat'] = django.forms.FloatField(initial=50.0, min_value=-90.0, max_value=90.0, |
|
2183 | 2195 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2184 | 2196 | self.fields['step_lat'] = django.forms.FloatField(initial=10.0, min_value=0.0, |
|
2185 | 2197 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2186 | 2198 | self.fields['start_lon'] = django.forms.FloatField(initial=-100.0, min_value=-180.0, max_value=180.0, |
|
2187 | 2199 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2188 | 2200 | self.fields['stop_lon'] = django.forms.FloatField(initial=-80.0, min_value=-180.0, max_value=180.0, |
|
2189 | 2201 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2190 | 2202 | self.fields['step_lon'] = django.forms.FloatField(initial=10.0, min_value=0.0, |
|
2191 | 2203 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2192 | 2204 | self.fields['start_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0, |
|
2193 | 2205 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2194 | 2206 | self.fields['stop_alt'] = django.forms.FloatField(initial=500.0, min_value=0.0, |
|
2195 | 2207 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2196 | 2208 | self.fields['step_alt'] = django.forms.FloatField(initial=500.0, min_value=0.0, |
|
2197 | 2209 | widget=django.forms.TextInput(attrs={'size':5})) |
|
2198 | 2210 | |
|
2199 | 2211 | # time selection |
|
2200 | 2212 | now = datetime.datetime.utcnow() |
|
2201 | 2213 | self.fields['datetime'] = django.forms.SplitDateTimeField(input_date_formats=['%Y-%m-%d'], input_time_formats=['%H:%M:%S'], |
|
2202 | 2214 | label='Select UT datetime', |
|
2203 | 2215 | help_text='Select the UT time at which to run this calcuation', |
|
2204 | 2216 | initial=datetime.datetime(now.year,1,1)) |
|
2205 | 2217 | |
|
2206 | 2218 | self.fields['pList'] = django.forms.MultipleChoiceField(widget=django.forms.CheckboxSelectMultiple(), |
|
2207 | 2219 | choices=parmChoices, initial=parmInitial) |
|
2208 | 2220 |
|
1 | NO CONTENT: modified file, binary diff hidden |
@@ -1,75 +1,75 | |||
|
1 | 1 | {% load static %} |
|
2 | 2 | |
|
3 | 3 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
|
4 | 4 | <html xmlns="http://www.w3.org/1999/xhtml"><!-- InstanceBegin template="/Templates/doc_template.dwt" codeOutsideHTMLIsLocked="false" --> |
|
5 | 5 | <head> |
|
6 | 6 | <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> |
|
7 | 7 | <!-- InstanceBeginEditable name="doctitle" --> |
|
8 | 8 | <title>Madrigal administrator's guide</title> |
|
9 | 9 | <!-- InstanceEndEditable --><!-- InstanceBeginEditable name="head" --><!-- InstanceEndEditable --> |
|
10 | <link href="/static/madrigal.css" rel="stylesheet" type="text/css" /> | |
|
10 | <link href="/madrigal/static/madrigal.css" rel="stylesheet" type="text/css" /> | |
|
11 | 11 | <style type="text/css"> |
|
12 | 12 | html body { |
|
13 | 13 | background-color: {{bg_color}}; |
|
14 | 14 | } |
|
15 | 15 | </style> |
|
16 | 16 | <!-- InstanceParam name="href_up_top" type="text" value="madContents.html" --><!-- InstanceParam name="href_next_top" type="text" value="ad_appropriate.html" --><!-- InstanceParam name="href_back_top" type="text" value="rr_fortran95.html" --><!-- InstanceParam name="href_back_bottom" type="text" value="rr_fortran95.html" --><!-- InstanceParam name="href_up_bottom" type="text" value="madContents.html" --><!-- InstanceParam name="href_next_bottom" type="text" value="ad_appropriate.html" --><!-- InstanceParam name="href_prev_top" type="text" value="rr_fortran95.html" --><!-- InstanceParam name="href_uptitle_top" type="text" value="madContents.html" --><!-- InstanceParam name="href_nexttitle_top" type="text" value="ad_appropriate.html" --><!-- InstanceParam name="href_prevtitle_bottom" type="text" value="rr_fortran95.html" --><!-- InstanceParam name="href_uptitle_bottom" type="text" value="madContents.html" --><!-- InstanceParam name="href_nexttitle_bottom" type="text" value="ad_appropriate.html" --> |
|
17 | 17 | </head> |
|
18 | 18 | |
|
19 | 19 | <body> |
|
20 | 20 | <table width="100%" border="1" cellpadding="0" cellspacing="2" class="navigation"> |
|
21 | 21 | <tr> |
|
22 |
|
|
|
23 |
|
|
|
24 |
|
|
|
22 | <td width="5%"><a href="{% url 'docs' 'rr_fortran95.html' %}"><img src="{% static 'previous.png' %}" alt="previous" width="32" height="32" /></a></td> | |
|
23 | <td width="5%"><a href="{% url 'docs' 'madContents.html' %}"><img src="{% static 'up.png' %}" alt="up" width="32" height="32" /></a></td> | |
|
24 | <td width="5%"><a href="{% url 'docs' 'ad_appropriate.html' %}"><img src="{% static 'next.png' %}" alt="next" width="32" height="32" /></a></td> | |
|
25 | 25 | <td width="54%"><!-- InstanceBeginEditable name="EditTitleTop" -->Madrigal administrator's guide<!-- InstanceEndEditable --></td> |
|
26 | 26 | <td width="13%"><a href="{% url 'docs' 'madContents.html' %}">Doc home </a></td> |
|
27 | 27 | <td width="18%"><a href="/">Madrigal home</a></td> |
|
28 | 28 | </tr> |
|
29 | 29 | </table> |
|
30 | 30 | <div class='online-navigation'> |
|
31 | 31 | <b class="navlabel">Previous:</b> |
|
32 | 32 | <a class="sectref" href="{% url 'docs' 'rr_fortran95.html' %}"><!-- InstanceBeginEditable name="PreviousTitle" -->Fortran95 remote API reference <!-- InstanceEndEditable --></A> |
|
33 | 33 | <b class="navlabel"> Up:</b> |
|
34 | 34 | <a class="sectref" href="{% url 'docs' 'madContents.html' %}"><!-- InstanceBeginEditable name="UpTitle" -->Doc home <!-- InstanceEndEditable --></A> |
|
35 | 35 | <b class="navlabel"> Next:</b> |
|
36 | 36 | <a class="sectref" href="{% url 'docs' 'ad_appropriate.html' %}"><!-- InstanceBeginEditable name="NextTitle" -->Is Madrigal appropriate?<!-- InstanceEndEditable --></A></div> |
|
37 | 37 | <hr/> |
|
38 | 38 | <!-- InstanceBeginEditable name="EditDoc" --> |
|
39 | 39 | <h1 align="center">Madrigal administrator's guide</h1> |
|
40 | 40 | <p>This section of the Madrigal documentation is meant for people considering installing Madrigal to hold data from their instruments, or those who have already installed Madrigal and are responsible for administering or updating it. This guide describes how to determine whether Madrigal is right for your data, and how to install it if it is. It also discusses how to create Madrigal data files, and how to add them to Madrigal. </p> |
|
41 | 41 | <ul> |
|
42 | 42 | <li><a href="{% url 'docs' 'ad_appropriate.html' %}">Is Madrigal appropriate for my instrument(s)?</a></li> |
|
43 | 43 | <li><a href="{% url 'docs' 'ad_install.html' %}">Installing Madrigal for the first time </a></li> |
|
44 | 44 | <li><a href="{% url 'docs' 'ad_upgrade.html' %}">Upgrading Madrigal to the latest release</a></li> |
|
45 | 45 | <li><a href="{% url 'docs' 'ad_metadata.html' %}">The Madrigal data model and metadata files</a></li> |
|
46 | 46 | <li><a href="{% url 'docs' 'ad_experiments.html' %}">How Madrigal data is organized</a></li> |
|
47 | 47 | <li><a href="{% url 'docs' 'ad_createFiles.html' %}">Creating Madrigal data files</a></li> |
|
48 | 48 | <li><a href="{% url 'docs' 'ad_createExp.html' %}">Creating and updating Madrigal experiments</a></li> |
|
49 | 49 | <li><a href="{% url 'docs' 'ad_other.html' %}">Other administrative tasks</a></li> |
|
50 | 50 | <li><a href="{% url 'docs' 'ad_logging.html' %}">User access logging</a></li> |
|
51 | 51 | <li><a href="{% url 'docs' 'ad_links.html' %}">Creating direct links to experiments/files</a></li> |
|
52 | 52 | <li><a href="{% url 'docs' 'ad_isprint.html' %}">Using isprint for file quick looks</a></li> |
|
53 | 53 | </ul> |
|
54 | 54 | <!-- InstanceEndEditable --> |
|
55 | 55 | <table width="100%" border="1" cellpadding="0" cellspacing="2" class="navigation"> |
|
56 | 56 | <tr> |
|
57 |
|
|
|
58 |
<td width="5%"><a href="{% url 'docs' 'madContents.html' %}"><img src=" |
|
|
59 |
<td width="5%"><a href="{% url 'docs' 'ad_appropriate.html' %}"><img src=" |
|
|
57 | <td width="5%"><a href="{% url 'docs' 'rr_fortran95.html' %}"><img src="{% static 'previous.png' %}" alt="previous" width="32" height="32" /></a></td> | |
|
58 | <td width="5%"><a href="{% url 'docs' 'madContents.html' %}"><img src="{% static 'up.png' %}" alt="up" width="32" height="32" /></a></td> | |
|
59 | <td width="5%"><a href="{% url 'docs' 'ad_appropriate.html' %}"><img src="{% static 'next.png' %}" alt="next" width="32" height="32" /></a></td> | |
|
60 | 60 | <td width="54%"><!-- InstanceBeginEditable name="EditTitleBottom" -->Madrigal administrator's guide<!-- InstanceEndEditable --></td> |
|
61 | 61 | <td width="13%"><a href="{% url 'docs' 'madContents.html' %}">Doc home </a></td> |
|
62 | 62 | <td width="18%"><a href="/">Madrigal home</a></td> |
|
63 | 63 | </tr> |
|
64 | 64 | </table> |
|
65 | 65 | <div class='online-navigation'> |
|
66 | 66 | <b class="navlabel">Previous:</b> |
|
67 | 67 | <a class="sectref" href="{% url 'docs' 'rr_fortran95.html' %}"><!-- InstanceBeginEditable name="PreviousTitle2" -->Fortran95 remote API reference <!-- InstanceEndEditable --></A> |
|
68 | 68 | <b class="navlabel"> Up:</b> |
|
69 | 69 | <a class="sectref" href="{% url 'docs' 'madContents.html' %}"><!-- InstanceBeginEditable name="UpTitle2" -->Doc home <!-- InstanceEndEditable --></A> |
|
70 | 70 | <b class="navlabel"> Next:</b> |
|
71 | 71 | <a class="sectref" href="{% url 'docs' 'ad_appropriate.html' %}"><!-- InstanceBeginEditable name="NextTitle2" -->Is Madrigal appropriate? <!-- InstanceEndEditable --></A></div> |
|
72 | 72 | <hr/> |
|
73 | 73 | <p> </p> |
|
74 | 74 | </body> |
|
75 | 75 | <!-- InstanceEnd --></html> |
@@ -1,87 +1,87 | |||
|
1 | 1 | {% load static %} |
|
2 | 2 | |
|
3 | 3 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
|
4 | 4 | <html xmlns="http://www.w3.org/1999/xhtml"><!-- InstanceBegin template="/Templates/doc_template.dwt" codeOutsideHTMLIsLocked="false" --> |
|
5 | 5 | <head> |
|
6 | 6 | <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> |
|
7 | 7 | <!-- InstanceBeginEditable name="doctitle" --> |
|
8 | 8 | <title>Madrigal developer's guide</title> |
|
9 | 9 | <!-- InstanceEndEditable --><!-- InstanceBeginEditable name="head" --><!-- InstanceEndEditable --> |
|
10 |
<link href=" |
|
|
10 | <link href="{% static 'madrigal.css' %}" rel="stylesheet" type="text/css" /> | |
|
11 | 11 | <style type="text/css"> |
|
12 | 12 | html body { |
|
13 | 13 | background-color: {{bg_color}}; |
|
14 | 14 | } |
|
15 | 15 | </style> |
|
16 | 16 | <!-- InstanceParam name="href_up_top" type="text" value="madContents.html" --><!-- InstanceParam name="href_next_top" type="text" value="madrigal/index.html" --><!-- InstanceParam name="href_back_top" type="text" value="ad_isprint.html" --><!-- InstanceParam name="href_back_bottom" type="text" value="ad_isprint.html" --><!-- InstanceParam name="href_up_bottom" type="text" value="madContents.html" --><!-- InstanceParam name="href_next_bottom" type="text" value="madrigal/index.html" --><!-- InstanceParam name="href_prev_top" type="text" value="ad_isprint.html" --><!-- InstanceParam name="href_uptitle_top" type="text" value="madContents.html" --><!-- InstanceParam name="href_nexttitle_top" type="text" value="madrigal/index.html" --><!-- InstanceParam name="href_prevtitle_bottom" type="text" value="ad_isprint.html" --><!-- InstanceParam name="href_uptitle_bottom" type="text" value="madContents.html" --><!-- InstanceParam name="href_nexttitle_bottom" type="text" value="madrigal/index.html" --> |
|
17 | 17 | </head> |
|
18 | 18 | |
|
19 | 19 | <body> |
|
20 | 20 | <table width="100%" border="1" cellpadding="0" cellspacing="2" class="navigation"> |
|
21 | 21 | <tr> |
|
22 |
|
|
|
23 |
|
|
|
24 |
|
|
|
22 | <td width="5%"><a href="{% url 'docs' 'ad_isprint.html' %}"><img src="{% static 'previous.png' %}" alt="previous" width="32" height="32" /></a></td> | |
|
23 | <td width="5%"><a href="{% url 'docs' 'madContents.html' %}"><img src="{% static 'up.png' %}" alt="up" width="32" height="32" /></a></td> | |
|
24 | <td width="5%"><a href="{% url 'docs' 'madrigal/index.html' %}"><img src="{% static 'next.png' %}" alt="next" width="32" height="32" /></a></td> | |
|
25 | 25 | <td width="54%"><!-- InstanceBeginEditable name="EditTitleTop" -->Madrigal developer's guide <!-- InstanceEndEditable --></td> |
|
26 | 26 | <td width="13%"><a href="{% url 'docs' 'madContents.html' %}">Doc home </a></td> |
|
27 | 27 | <td width="18%"><a href="/">Madrigal home</a></td> |
|
28 | 28 | </tr> |
|
29 | 29 | </table> |
|
30 | 30 | <div class='online-navigation'> |
|
31 | 31 | <b class="navlabel">Previous:</b> |
|
32 | 32 | <a class="sectref" href="{% url 'docs' 'ad_isprint.html' %}"><!-- InstanceBeginEditable name="PreviousTitle" -->Using isprint<!-- InstanceEndEditable --></A> |
|
33 | 33 | <b class="navlabel"> Up:</b> |
|
34 | 34 | <a class="sectref" href="{% url 'docs' 'madContents.html' %}"><!-- InstanceBeginEditable name="UpTitle" -->Doc home <!-- InstanceEndEditable --></A> |
|
35 | 35 | <b class="navlabel"> Next:</b> |
|
36 | 36 | <a class="sectref" href="{% url 'docs' 'madrigal/index.html' %}"><!-- InstanceBeginEditable name="NextTitle" -->Internal python API<!-- InstanceEndEditable --></A></div> |
|
37 | 37 | <hr/> |
|
38 | 38 | <!-- InstanceBeginEditable name="EditDoc" --> |
|
39 | 39 | <h1 align="center">Madrigal developer's guide</h1> |
|
40 | 40 | <p>This section of the Madrigal documentation is meant for developers working to extend or modify Madrigal. It is not meant for users of Madrigal or Madrigal administrators. </p> |
|
41 | 41 | <p>With the release of Madrigal 3.0, Madrigal has only a single python API. The C and Fortran code installed in Madrigal is purely scientific code used in the derivation engine, and is exposed only as a python extension, madrigal._derive.</p> |
|
42 | 42 | <p>The web interface is now a Django web application, and no direct cgi scripts remain. The django application is contained in MADROOT/source/madpy/djangoMad.</p> |
|
43 | 43 | <ul> |
|
44 | 44 | <li><a href="madrigal/index.html">Internal Madrigal Python API</a> |
|
45 | 45 | <ul> |
|
46 | 46 | <li><a href="{% url 'docs' 'madrigal/admin.m.html' %}">madrigal.admin</a></li> |
|
47 | 47 | <li><a href="{% url 'docs' 'madrigal/cedar.m.html' %}">madrigal.cedar</a></li> |
|
48 | 48 | <li><a href="{% url 'docs' 'madrigal/data.m.html' %}">madrigal.data</a></li> |
|
49 | 49 | <li><a href="{% url 'docs' 'madrigal/derivation.m.html' %}">madrigal.derivation</a></li> |
|
50 | 50 | <li><a href="{% url 'docs' 'madrigal/isprint.m.html' %}">madrigal.isprint</a></li> |
|
51 | 51 | <li><a href="{% url 'docs' 'madrigal/metadata.m.html' %}">madrigal.metadata</a></li> |
|
52 | 52 | <li><a href="{% url 'docs' 'madrigal/openmadrigal.m.html' %}">madrigal.openmadrigal</a></li> |
|
53 | 53 | <li><a href="{% url 'docs' 'madrigal/ui/index.html' %}">madrigal.ui</a> |
|
54 | 54 | <ul> |
|
55 | 55 | <li><a href="{% url 'docs' 'madrigal/ui/madrigalPlot.m.html' %}">madrigal.ui.madrigalPlot</a></li> |
|
56 | 56 | <li><a href="{% url 'docs' 'madrigal/ui/userData.m.html' %}">madrigal.ui.userData</a></li> |
|
57 | 57 | <li><a href="{% url 'docs' 'madrigal/ui/web.m.html' %}">madrigal.ui.web</a></li> |
|
58 | 58 | </ul> |
|
59 | 59 | </li> |
|
60 | 60 | </ul> |
|
61 | 61 | </li> |
|
62 | 62 | <li><a href="{% url 'docs' 'dev_derivation.html' %}">Madrigal derivation engine</a></li> |
|
63 | 63 | <li><a href="/static/CEDARMadrigalHdf5Format.pdf">CEDAR Madrigal Hdf5 file format</a></li> |
|
64 | 64 | <li><a href="/static/cedarFormat.pdf">Deprecated Cedar file format</a></li> |
|
65 | 65 | </ul> |
|
66 | 66 | <!-- InstanceEndEditable --> |
|
67 | 67 | <table width="100%" border="1" cellpadding="0" cellspacing="2" class="navigation"> |
|
68 | 68 | <tr> |
|
69 |
|
|
|
70 |
|
|
|
71 |
|
|
|
69 | <td width="5%"><a href="{% url 'docs' 'ad_isprint.html' %}"><img src="{% static 'previous.png' %}" alt="previous" width="32" height="32" /></a></td> | |
|
70 | <td width="5%"><a href="{% url 'docs' 'madContents.html' %}"><img src="{% static 'up.png' %}" alt="up" width="32" height="32" /></a></td> | |
|
71 | <td width="5%"><a href="{% url 'docs' 'madrigal/index.html' %}"><img src="{% static 'next.png' %}" alt="next" width="32" height="32" /></a></td> | |
|
72 | 72 | <td width="54%"><!-- InstanceBeginEditable name="EditTitleBottom" -->Madrigal developer's guide<!-- InstanceEndEditable --></td> |
|
73 | 73 | <td width="13%"><a href="{% url 'docs' 'madContents.html' %}">Doc home </a></td> |
|
74 | 74 | <td width="18%"><a href="/">Madrigal home</a></td> |
|
75 | 75 | </tr> |
|
76 | 76 | </table> |
|
77 | 77 | <div class='online-navigation'> |
|
78 | 78 | <b class="navlabel">Previous:</b> |
|
79 | 79 | <a class="sectref" href="{% url 'docs' 'ad_isprint.html' %}"><!-- InstanceBeginEditable name="PreviousTitle2" -->Using isprint <!-- InstanceEndEditable --></A> |
|
80 | 80 | <b class="navlabel"> Up:</b> |
|
81 | 81 | <a class="sectref" href="{% url 'docs' 'madContents.html' %}"><!-- InstanceBeginEditable name="UpTitle2" -->Doc home <!-- InstanceEndEditable --></A> |
|
82 | 82 | <b class="navlabel"> Next:</b> |
|
83 | 83 | <a class="sectref" href="{% url 'docs' 'madrigal/index.html' %}"><!-- InstanceBeginEditable name="NextTitle2" -->Internal python API <!-- InstanceEndEditable --></A></div> |
|
84 | 84 | <hr/> |
|
85 | 85 | <p> </p> |
|
86 | 86 | </body> |
|
87 | 87 | <!-- InstanceEnd --></html> |
@@ -1,50 +1,50 | |||
|
1 | 1 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
|
2 | 2 | <html xmlns="http://www.w3.org/1999/xhtml"> |
|
3 | 3 | <head> |
|
4 | 4 | <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> |
|
5 | 5 | <title>Madrigal documentation - v3.0</title> |
|
6 | <link href="/static/madrigal.css" rel="stylesheet" type="text/css" /> | |
|
6 | <link href="/madrigal/static/madrigal.css" rel="stylesheet" type="text/css" /> | |
|
7 | 7 | <style type="text/css"> |
|
8 | 8 | html body { |
|
9 | 9 | background-color: {{bg_color}}; |
|
10 | 10 | } |
|
11 | 11 | </style> |
|
12 | 12 | </head> |
|
13 | 13 | |
|
14 | 14 | <body> |
|
15 | 15 | <center> |
|
16 | 16 | <h1>Madrigal Database v3.2.1 Documentation - Contents</h1> |
|
17 | 17 | <table width="100%" border="1"> |
|
18 | 18 | <tr> |
|
19 | 19 | <td class="navigation"><a href="/">Home</a></td> |
|
20 | 20 | </tr> |
|
21 | 21 | </table> |
|
22 | 22 | </center> |
|
23 | 23 | <hr size="4" /> |
|
24 | 24 | <ul> |
|
25 | 25 | <li><a href="{% url 'docs' 'madIntroduction.html' %}">1. Brief history of Madrigal</a></li> |
|
26 | 26 | </ul> |
|
27 | 27 | <ul> |
|
28 | 28 | <li><a href="{% url 'docs' 'whatsNew.html' %}">2. What's new in Madrigal 3.2.1</a></li> |
|
29 | 29 | </ul> |
|
30 | 30 | <ul> |
|
31 | 31 | <li><a href="{% url 'docs' 'wt_usersGuide.html' %}">3. Madrigal user's guide (How do I access Madrigal data?) </a> |
|
32 | 32 | <ul> |
|
33 | 33 | <li><a href="{% url 'docs' 'wt_contents.html' %}">2.1 Web interface tutorial </a></li> |
|
34 | 34 | <li><a href="{% url 'docs' 'rt_contents.html' %}">2.2 Remote data access programming tutorial</a></li> |
|
35 | 35 | <li><a href="{% url 'docs' 'rr_contents.html' %}">2.3 Remote data access programming reference guide</a></li> |
|
36 | 36 | </ul> |
|
37 | 37 | </li> |
|
38 | 38 | </ul> |
|
39 | 39 | <ul> |
|
40 | 40 | <li><a href="{% url 'docs' 'admin.html' %}">4. Madrigal Administrator's Guide</a></li> |
|
41 | 41 | </ul> |
|
42 | 42 | <ul> |
|
43 | 43 | <li><a href="{% url 'docs' 'dev_contents.html' %}">5. Madrigal Developer's Guide</a></li> |
|
44 | 44 | </ul> |
|
45 | 45 | <ul> |
|
46 | 46 | <li><a href="{{ siteSpecific }}">6. Site specific documentation</a></li> |
|
47 | 47 | </ul> |
|
48 | 48 | <p> </p> |
|
49 | 49 | </body> |
|
50 | 50 | </html> |
@@ -1,71 +1,71 | |||
|
1 | 1 | {% load static %} |
|
2 | 2 | |
|
3 | 3 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
|
4 | 4 | <html xmlns="http://www.w3.org/1999/xhtml"><!-- InstanceBegin template="/Templates/doc_template.dwt" codeOutsideHTMLIsLocked="false" --> |
|
5 | 5 | <head> |
|
6 | 6 | <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> |
|
7 | 7 | <!-- InstanceBeginEditable name="doctitle" --> |
|
8 | 8 | <title>Madrigal history</title> |
|
9 | 9 | <!-- InstanceEndEditable --><!-- InstanceBeginEditable name="head" --> |
|
10 | 10 | <!-- InstanceEndEditable --> |
|
11 | <link href="/static/madrigal.css" rel="stylesheet" type="text/css" /> | |
|
11 | <link href="/madrigal/static/madrigal.css" rel="stylesheet" type="text/css" /> | |
|
12 | 12 | <style type="text/css"> |
|
13 | 13 | html body { |
|
14 | 14 | background-color: {{bg_color}}; |
|
15 | 15 | } |
|
16 | 16 | </style> |
|
17 | 17 | <!-- InstanceParam name="href_up_top" type="text" value="madContents.html" --><!-- InstanceParam name="href_next_top" type="text" value="whatsNew.html" --><!-- InstanceParam name="href_back_top" type="text" value="madContents.html" --><!-- InstanceParam name="href_back_bottom" type="text" value="madContents.html" --><!-- InstanceParam name="href_up_bottom" type="text" value="madContents.html" --><!-- InstanceParam name="href_next_bottom" type="text" value="whatsNew.html" --><!-- InstanceParam name="href_prev_top" type="text" value="madContents.html" --><!-- InstanceParam name="href_uptitle_top" type="text" value="madContents.html" --><!-- InstanceParam name="href_nexttitle_top" type="text" value="whatsNew.html" --><!-- InstanceParam name="href_prevtitle_bottom" type="text" value="madContents.html" --><!-- InstanceParam name="href_uptitle_bottom" type="text" value="madContents.html" --><!-- InstanceParam name="href_nexttitle_bottom" type="text" value="whatsNew.html" --> |
|
18 | 18 | </head> |
|
19 | 19 | |
|
20 | 20 | <body> |
|
21 | 21 | <table width="100%" border="1" cellpadding="0" cellspacing="2" class="navigation"> |
|
22 | 22 | <tr> |
|
23 | <td width="5%"><a href="{% url 'docs' 'madContents.html' %}"><img src="/static/previous.png" alt="previous" width="32" height="32" /></a></td> | |
|
24 | <td width="5%"><a href="{% url 'docs' 'madContents.html' %}"><img src="/static/up.png" alt="up" width="32" height="32" /></a></td> | |
|
25 | <td width="5%"><a href="{% url 'docs' 'whatsNew.html' %}"><img src="/static/next.png" alt="next" width="32" height="32" /></a></td> | |
|
23 | <td width="5%"><a href="{% url 'docs' 'madContents.html' %}"><img src="/madrigal/static/previous.png" alt="previous" width="32" height="32" /></a></td> | |
|
24 | <td width="5%"><a href="{% url 'docs' 'madContents.html' %}"><img src="/madrigal/static/up.png" alt="up" width="32" height="32" /></a></td> | |
|
25 | <td width="5%"><a href="{% url 'docs' 'whatsNew.html' %}"><img src="/madrigal/static/next.png" alt="next" width="32" height="32" /></a></td> | |
|
26 | 26 | <td width="54%"><!-- InstanceBeginEditable name="EditTitleTop" -->Brief history of Madrigal <!-- InstanceEndEditable --></td> |
|
27 | 27 | <td width="13%"><a href="{% url 'docs' 'madContents.html' %}">Doc home </a></td> |
|
28 | 28 | <td width="18%"><a href="/">Madrigal home</a></td> |
|
29 | 29 | </tr> |
|
30 | 30 | </table> |
|
31 | 31 | <div class='online-navigation'> |
|
32 | 32 | <b class="navlabel">Previous:</b> |
|
33 | 33 | <a class="sectref" href="{% url 'docs' 'madContents.html' %}"><!-- InstanceBeginEditable name="PreviousTitle" -->Doc home <!-- InstanceEndEditable --></A> |
|
34 | 34 | <b class="navlabel"> Up:</b> |
|
35 | 35 | <a class="sectref" href="{% url 'docs' 'madContents.html' %}"><!-- InstanceBeginEditable name="UpTitle" -->Doc home <!-- InstanceEndEditable --></A> |
|
36 | 36 | <b class="navlabel"> Next:</b> |
|
37 | 37 | <a class="sectref" href="{% url 'docs' 'whatsNew.html' %}"><!-- InstanceBeginEditable name="NextTitle" -->What's new in Madrigal 3.0? <!-- InstanceEndEditable --></A></div> |
|
38 | 38 | <hr/> |
|
39 | 39 | <!-- InstanceBeginEditable name="EditDoc" --> |
|
40 | 40 | <center> |
|
41 | 41 | <h1>Brief history of Madrigal </h1> |
|
42 | 42 | </center> |
|
43 | 43 | <p>Madrigal is a database of ground-based measurements and models of the Earth's upper atmosphere and ionosphere. It is the community database of the Coupling, Energetics and Dynamics of Atmospheric Regions (<a href="http://cedarweb.vsp.ucar.edu/wiki/index.php/Main_Page">CEDAR</a>) program, which is devoted to the characterization and understanding of the atmosphere above about 60 km, with emphasis on the various processes that determine the basic structure and composition of the atmosphere, and on the mechanisms that couple different atmospheric regions. Instruments developed or upgraded under CEDAR include interferometers, spectrometers, imagers, lidars and medium, high-frequency and incoherent scatter radars. The success of CEDAR has been due, in large measure, to its ability to encourage collaborative efforts coalescing observations, theory and modeling. The CEDAR community includes about 800 scientists and students from around the world.</p> |
|
44 | 44 | <p>From the inception of the CEDAR program in 1988, there has been a great concern among the members of the CEDAR community to make the data collected by the CEDAR instruments easily accessible for joint studies. Consequently, a high priority was placed on establishing a repository for CEDAR data and model results. An incoherent scatter radar database had been established at the National Center for Atmospheric Research (NCAR) in 1985, and this evolved into the CEDAR Database in 1989. By the end of 1997, it had grown to include data from 44 instruments and 16 models. Over 200 users have requested information from the Database. In 2012, the Madrigal database and the CEDAR database were combined into a single database system, the Madrigal CEDAR database, based at MIT Haystack Observatory.</p> |
|
45 | <p>A central element of the CEDAR Database is a standard data format. With Madrigal 3.0 the file format is now Hdf5, with a well-defined layout and parameters. This new CEDAR Hdf5 format is described <a href="/static/CEDARMadrigalHdf5Format.pdf" target="_blank">here</a>. This format replaced the old <a href="/static/cedarFormat.pdf">16 bit integer based format</a> that evolved from the format used by the earlier incoherent scatter database, which in turn evolved from an earlier version of Madrigal developed at the MIT Haystack Observatory in 1980. </p> | |
|
45 | <p>A central element of the CEDAR Database is a standard data format. With Madrigal 3.0 the file format is now Hdf5, with a well-defined layout and parameters. This new CEDAR Hdf5 format is described <a href="/madrigal/static/CEDARMadrigalHdf5Format.pdf" target="_blank">here</a>. This format replaced the old <a href="/madrigal/static/cedarFormat.pdf">16 bit integer based format</a> that evolved from the format used by the earlier incoherent scatter database, which in turn evolved from an earlier version of Madrigal developed at the MIT Haystack Observatory in 1980. </p> | |
|
46 | 46 | <p>Haystack maintains and develops the Madrigal CEDAR database as an open-source project with community contributions. With the Madrigal CEDAR database, the site owner stores only their own data, which they can add to or update at any time. However, because the Madrigal database shares its metadata with all other Madrigal sites, users browsing any Madrigal site can search for data at any other Madrigal site. In addition, a central archival Madrigal site (<a href="http://cedar.openmadrigal.org" target="_self">cedar.openmadrigal.org</a>) archives all Madrigal sites and stores data not stored at other Madrigal sites.</p> |
|
47 | 47 | <p>Madrigal data are arranged into "experiments", which may contain data files, images, documentation, links, etc. A key feature of Madrigal is its seamless integration of archival and real-time data. A realtime file on Madrigal is accessed in exactly the same way as any archival file.</p> |
|
48 | 48 | <p>Madrigal has been installed at numerous locations in addition to Millstone Hill, including EISCAT, SRI International, and Jicamarca. The inventories of experiments available at each installation are available to the other installations through shared metadata. New Madrigal sites can be automatically added at any time.</p> |
|
49 | 49 | <p>Madrigal is an open source project with a central <a href="http://cedar.openmadrigal.org/openmadrigal">developer's web site</a> and a <a href="http://atlas.haystack.mit.edu/cgi-bin/millstone_viewvc.cgi/openmadrigal/" target="_self">central repository</a>. A complete Subversion archive of all Madrigal software, including software which is not included with the standard distribution, is available at the developer's web site. There is also an Open Madrigal mailing list and developer's forum. Any group wishing to install Madrigal to distribute their instrument's data is welcome to - see the http://cedar.openmadrigal.org/openmadrigal web site for details. The <a href="http://atlas.haystack.mit.edu/cgi-bin/millstone_viewvc.cgi/openmadrigal/" target="_self">central repository</a> link is a place where all data from all Madrigal sites is archived. It can also be used to access data, although accessing the local sites is preferred.</p> |
|
50 | 50 | <!-- InstanceEndEditable --> |
|
51 | 51 | <table width="100%" border="1" cellpadding="0" cellspacing="2" class="navigation"> |
|
52 | 52 | <tr> |
|
53 | <td width="5%"><a href="{% url 'docs' 'madContents.html' %}"><img src="/static/previous.png" alt="previous" width="32" height="32" /></a></td> | |
|
54 | <td width="5%"><a href="{% url 'docs' 'madContents.html' %}"><img src="/static/up.png" alt="up" width="32" height="32" /></a></td> | |
|
55 | <td width="5%"><a href="{% url 'docs' 'whatsNew.html' %}"><img src="/static/next.png" alt="next" width="32" height="32" /></a></td> | |
|
53 | <td width="5%"><a href="{% url 'docs' 'madContents.html' %}"><img src="/madrigal/static/previous.png" alt="previous" width="32" height="32" /></a></td> | |
|
54 | <td width="5%"><a href="{% url 'docs' 'madContents.html' %}"><img src="/madrigal/static/up.png" alt="up" width="32" height="32" /></a></td> | |
|
55 | <td width="5%"><a href="{% url 'docs' 'whatsNew.html' %}"><img src="/madrigal/static/next.png" alt="next" width="32" height="32" /></a></td> | |
|
56 | 56 | <td width="54%"><!-- InstanceBeginEditable name="EditTitleBottom" -->Brief overview of Madrigal <!-- InstanceEndEditable --></td> |
|
57 | 57 | <td width="13%"><a href="{% url 'docs' 'madContents.html' %}">Doc home </a></td> |
|
58 | 58 | <td width="18%"><a href="/">Madrigal home</a></td> |
|
59 | 59 | </tr> |
|
60 | 60 | </table> |
|
61 | 61 | <div class='online-navigation'> |
|
62 | 62 | <b class="navlabel">Previous:</b> |
|
63 | 63 | <a class="sectref" href="{% url 'docs' 'madContents.html' %}"><!-- InstanceBeginEditable name="PreviousTitle2" -->Doc Home <!-- InstanceEndEditable --></A> |
|
64 | 64 | <b class="navlabel"> Up:</b> |
|
65 | 65 | <a class="sectref" href="{% url 'docs' 'madContents.html' %}"><!-- InstanceBeginEditable name="UpTitle2" -->Doc home <!-- InstanceEndEditable --></A> |
|
66 | 66 | <b class="navlabel"> Next:</b> |
|
67 | 67 | <a class="sectref" href="{% url 'docs' 'whatsNew.html' %}"><!-- InstanceBeginEditable name="NextTitle2" -->What's new in Madrigal 3.0? <!-- InstanceEndEditable --></A></div> |
|
68 | 68 | <hr/> |
|
69 | 69 | <p> </p> |
|
70 | 70 | </body> |
|
71 | 71 | <!-- InstanceEnd --></html> |
@@ -1,50 +1,50 | |||
|
1 | 1 | <div class="row" style="margin-bottom: 20px"> |
|
2 | 2 | Select parameter: <br> |
|
3 | 3 | {{ form.param_list1d.label }} |
|
4 | 4 | {{ form.param_list1d }} |
|
5 | 5 | {% if form.param_list2d %} |
|
6 | 6 | {{ form.param_list2d.label }} |
|
7 | 7 | {{ form.param_list2d }} |
|
8 | 8 | {% endif %} |
|
9 | 9 | |
|
10 | 10 | </div> |
|
11 | 11 | |
|
12 | 12 | <script> |
|
13 | 13 | $('#id_param_list2d').bind('change', function (e) { |
|
14 | 14 | var expID = '{{ expID }}'; |
|
15 | 15 | var param = $(this).val(); |
|
16 | var url = '{% url 'plot' %}' + '?expID=' + expID + '¶m2d=' + param; | |
|
16 | var url = '{% url 'plot' %}' + '?expID=' + expID + '¶m2d=' + param + '&filename=' + $('#id_file_list').val(); | |
|
17 | 17 | console.log(url) |
|
18 | 18 | // first delete all forms that are now out of date |
|
19 | 19 | divIndex = $(".single_form").index($( "#file_plot" )) |
|
20 | 20 | $(".single_form").slice(divIndex).empty() |
|
21 | 21 | // second populate the file_plot html if '0' not selected |
|
22 | 22 | if (param != '0') { |
|
23 | 23 | $(".single_form").slice(divIndex,divIndex+1).html("<img src=\"static/loader.gif\" class=\"load_center\"/>").load(url); |
|
24 | 24 | } |
|
25 | 25 | }) |
|
26 | 26 | $('#id_param_list1d').bind('change', function (e) { |
|
27 | 27 | var expID = '{{ expID }}'; |
|
28 | 28 | var param = $(this).val(); |
|
29 | var url = '{% url 'plot' %}' + '?expID=' + expID + '¶m1d=' + param; | |
|
29 | var url = '{% url 'plot' %}' + '?expID=' + expID + '¶m1d=' + param + '&filename=' + $('#id_file_list').val(); | |
|
30 | 30 | console.log(url) |
|
31 | 31 | // first delete all forms that are now out of date |
|
32 | 32 | divIndex = $(".single_form").index($( "#file_plot" )) |
|
33 | 33 | $(".single_form").slice(divIndex).empty() |
|
34 | 34 | // second populate the file_plot html if '0' not selected |
|
35 | 35 | if (param != '0') { |
|
36 | 36 | $(".single_form").slice(divIndex,divIndex+1).html("<img src=\"static/loader.gif\" class =\"load_center\"/>").load(url); |
|
37 | 37 | } |
|
38 | 38 | }) |
|
39 | 39 | </script> |
|
40 | 40 | <style> |
|
41 | 41 | .load_center { |
|
42 | 42 | display: block; |
|
43 | 43 | margin-left: auto; |
|
44 | 44 | margin-right: auto; |
|
45 | 45 | margin-top: 100px; |
|
46 | 46 | margin-bottom: 100px; |
|
47 | 47 | width: 4%; |
|
48 | 48 | align-items: center; |
|
49 | 49 | } |
|
50 | </style> No newline at end of file | |
|
50 | </style> |
@@ -1,363 +1,363 | |||
|
1 | 1 | {% load static %} |
|
2 | 2 | |
|
3 | 3 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
|
4 | 4 | <html xmlns="http://www.w3.org/1999/xhtml"><!-- InstanceBegin template="/Templates/doc_template.dwt" codeOutsideHTMLIsLocked="false" --> |
|
5 | 5 | <head> |
|
6 | 6 | <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> |
|
7 | 7 | <!-- InstanceBeginEditable name="doctitle" --> |
|
8 | 8 | <title>What's new in Madrigal 3.2?</title> |
|
9 | 9 | <!-- InstanceEndEditable --><!-- InstanceBeginEditable name="head" --><!-- InstanceEndEditable --> |
|
10 | <link href="/static/madrigal.css" rel="stylesheet" type="text/css" /> | |
|
10 | <link href="/madrigal/static/madrigal.css" rel="stylesheet" type="text/css" /> | |
|
11 | 11 | <style type="text/css"> |
|
12 | 12 | html body { |
|
13 | 13 | background-color: {{bg_color}}; |
|
14 | 14 | } |
|
15 | 15 | </style> |
|
16 | 16 | <!-- InstanceParam name="href_up_top" type="text" value="madContents.html" --><!-- InstanceParam name="href_next_top" type="text" value="wt_usersGuide.html" --><!-- InstanceParam name="href_back_top" type="text" value="madIntroduction.html" --><!-- InstanceParam name="href_back_bottom" type="text" value="madIntroduction.html" --><!-- InstanceParam name="href_up_bottom" type="text" value="madContents.html" --><!-- InstanceParam name="href_next_bottom" type="text" value="wt_usersGuide.html" --><!-- InstanceParam name="href_prev_top" type="text" value="madIntroduction.html" --><!-- InstanceParam name="href_uptitle_top" type="text" value="madContents.html" --><!-- InstanceParam name="href_nexttitle_top" type="text" value="wt_usersGuide.html" --><!-- InstanceParam name="href_prevtitle_bottom" type="text" value="madIntroduction.html" --><!-- InstanceParam name="href_uptitle_bottom" type="text" value="madContents.html" --><!-- InstanceParam name="href_nexttitle_bottom" type="text" value="wt_usersGuide.html" --> |
|
17 | 17 | </head> |
|
18 | 18 | |
|
19 | 19 | <body> |
|
20 | 20 | <table width="100%" border="1" cellpadding="0" cellspacing="2" class="navigation"> |
|
21 | 21 | <tr> |
|
22 | <td width="5%"><a href="{% url 'docs' 'madIntroduction.html' %}"><img src="/static/previous.png" alt="previous" width="32" height="32" /></a></td> | |
|
23 | <td width="5%"><a href="{% url 'docs' 'madContents.html' %}"><img src="/static/up.png" alt="up" width="32" height="32" /></a></td> | |
|
24 | <td width="5%"><a href="{% url 'docs' 'wt_usersGuide.html' %}"><img src="/static/next.png" alt="next" width="32" height="32" /></a></td> | |
|
22 | <td width="5%"><a href="{% url 'docs' 'madIntroduction.html' %}"><img src="/madrigal/static/previous.png" alt="previous" width="32" height="32" /></a></td> | |
|
23 | <td width="5%"><a href="{% url 'docs' 'madContents.html' %}"><img src="/madrigal/static/up.png" alt="up" width="32" height="32" /></a></td> | |
|
24 | <td width="5%"><a href="{% url 'docs' 'wt_usersGuide.html' %}"><img src="/madrigal/static/next.png" alt="next" width="32" height="32" /></a></td> | |
|
25 | 25 | <td width="54%"><!-- InstanceBeginEditable name="EditTitleTop" -->What's new in Madrigal 3.0? <!-- InstanceEndEditable --></td> |
|
26 | 26 | <td width="13%"><a href="{% url 'docs' 'madContents.html' %}">Doc home </a></td> |
|
27 | 27 | <td width="18%"><a href="/">Madrigal home</a></td> |
|
28 | 28 | </tr> |
|
29 | 29 | </table> |
|
30 | 30 | <div class='online-navigation'> |
|
31 | 31 | <b class="navlabel">Previous:</b> |
|
32 | 32 | <a class="sectref" href="{% url 'docs' 'madIntroduction.html' %}"><!-- InstanceBeginEditable name="PreviousTitle" -->Brief History <!-- InstanceEndEditable --></A> |
|
33 | 33 | <b class="navlabel"> Up:</b> |
|
34 | 34 | <a class="sectref" href="{% url 'docs' 'madContents.html' %}"><!-- InstanceBeginEditable name="UpTitle" -->Doc home <!-- InstanceEndEditable --></A> |
|
35 | 35 | <b class="navlabel"> Next:</b> |
|
36 | 36 | <a class="sectref" href="{% url 'docs' 'wt_usersGuide.html' %}"><!-- InstanceBeginEditable name="NextTitle" -->Madrigal user's guide <!-- InstanceEndEditable --></A></div> |
|
37 | 37 | <hr/> |
|
38 | 38 | <!-- InstanceBeginEditable name="EditDoc" --> |
|
39 | 39 | |
|
40 | 40 | <h1 align="center">What's new in Madrigal 3.2.2?</h1> |
|
41 | 41 | <h1 align="center" style="text-align: left">Madrigal 3.2.2 Release - Jan 2021</h1> |
|
42 | 42 | <p align="center" style="text-align: left">Fixed bug in linking to external data using the Select Single Experiment user interface. </p> |
|
43 | 43 | |
|
44 | 44 | |
|
45 | 45 | <h1 align="center">What's new in Madrigal 3.2.1?</h1> |
|
46 | 46 | <h1 align="center" style="text-align: left">Madrigal 3.2.1 Release - Nov 2020</h1> |
|
47 | 47 | <h2 align="center" style="text-align: left">Allows Madrigal to create citations to groups of files</h2> |
|
48 | 48 | <p align="center" style="text-align: left">With Madrigal 3.2.1, users can use the API to create citations to groups of files, and can display those groups with that citation. </p> |
|
49 | 49 | |
|
50 | 50 | |
|
51 | 51 | <h1 align="center">What's new in Madrigal 3.1.1?</h1> |
|
52 | 52 | <h1 align="center" style="text-align: left">Madrigal 3.1.1 Release - Nov 2019</h1> |
|
53 | 53 | <h2 align="center" style="text-align: left">Allows Madrigal to run using https</h2> |
|
54 | 54 | <p align="center" style="text-align: left">With Madrigal 3.1.1, the code is compatable with https. Instructions are given to install or convert Madrigal to https. </p> |
|
55 | 55 | |
|
56 | 56 | <h1 align="center">What's new in Madrigal 3.1?</h1> |
|
57 | 57 | <h1 align="center" style="text-align: left">Madrigal 3.1 Release - Oct 2019</h1> |
|
58 | 58 | <h2 align="center" style="text-align: left">Conversion to Python 3</h2> |
|
59 | 59 | <p align="center" style="text-align: left">With Madrigal 3.1, all python code has been updated to use python 3 instead of python 2. The functionality is unchanged from Madrigal 3.0.</p> |
|
60 | 60 | |
|
61 | 61 | <h1 align="center" style="text-align: left">Madrigal 3.0 Release - Sept 2017</h1> |
|
62 | 62 | <blockquote> |
|
63 | 63 | <h2 align="center" style="text-align: left">Migration to Hdf5 file format</h2> |
|
64 | 64 | <p align="center" style="text-align: left">With Madrigal 3.0, the old 16 bit integer based file format has been replaced with Hdf5. However, all the data model and well-defined parameters have been retained. The CEDAR Hdf5 format is designed to be completely self-contained. That is, any user with an Hdf5 reader can fully understand all data in the file without any reference to documentation. A full description of the format can be found <a href="/static/CEDARMadrigalHdf5Format.pdf">here</a>.</p> |
|
65 | 65 | <h2 align="center" style="text-align: left">Web interface generates scripts to download any amount of data</h2> |
|
66 | 66 | <p align="center" style="text-align: left">With Madrigal 3, you can generate a script command to download a whole series of files with a few click. You can also create a script that will filter those same files and allow you to choose the parameters you want, again with just a few clicks. These scripts can be run with python, Matlab, or IDL.</p> |
|
67 | 67 | <h2 align="center" style="text-align: left">Download files in a new format</h2> |
|
68 | 68 | <p align="center" style="text-align: left">Prior to Madrigal 3, files could be downloaded only as ascii or Hdf5 (or the difficult to understand CEDAR format). Now they can be downloaded as ascii, Hdf5, or netCDF4.</p> |
|
69 | 69 | <h2 align="center" style="text-align: left">Get data with selected/derived parameters and filters in new formats</h2> |
|
70 | 70 | <p align="center" style="text-align: left">Prior to Madrigal 3, data with selected/derived parameters and filters was available |
|
71 | 71 | only as ascii. Now it can be downloaded as ascii, Hdf5, or netCDF4.</p> |
|
72 | 72 | <h2 align="center" style="text-align: left">Independent spatial parameters now built in to data model</h2> |
|
73 | 73 | <p align="center" style="text-align: left">Prior to Madrigal 3.0, there was no way to automatically tell what the independent spatial parameters were in vector data. With Madrigal 3.0, any data with vector data must define its independent spatial parameters, which can be found in the Hdf5 Metadata group. This allows Madrigal to automatically add array layouts of the data, making for easier plotting.</p> |
|
74 | 74 | <h2 align="center" style="text-align: left">All new web interface</h2> |
|
75 | 75 | <p align="center" style="text-align: left">A much simplified web interface based on Django and bootstrap. Developed with much assistance from Jicamarca Observatory and Jose Antonio Sal y Rosas Celi.</p> |
|
76 | 76 | <h2 align="center" style="text-align: left">Simple FTP-like web interface added</h2> |
|
77 | 77 | <p align="center" style="text-align: left">Designed for non-native English speakers. The url follows a very simple pattern that can be easily parsed if the user in unable to understand the Madrigal API's and automatically generated scripts.</p> |
|
78 | 78 | <h2 align="center" style="text-align: left">Create CEDAR Hdf5 files with either Matlab or python</h2> |
|
79 | 79 | <p align="center" style="text-align: left">Prior to Madrigal 3, there was only a python API to easily create Madrigal files. Now both Matlab and python can be used to create CEDAR Hdf5 files.</p> |
|
80 | 80 | <h2 align="center" style="text-align: left">All metadata easily accessible</h2> |
|
81 | 81 | <p align="center" style="text-align: left">The <em>Access metadata</em> menu item on the main navigation menu allows easy access to all Madrigal CEDAR metadata, including Madrigal sites, instruments, parameter definitions, and kind of data codes.</p> |
|
82 | 82 | </blockquote> |
|
83 | 83 | <h1>Madrigal 2.6.3.2 Release - March 22, 2012</h1> |
|
84 | 84 | <p>Added support to file download cgi scripts to allow logging of remote API requests to download files.</p> |
|
85 | 85 | <h1>Madrigal 2.6.3.1 Release - March 13, 2012</h1> |
|
86 | 86 | <p>Added popup javascript window to warn users not to click "Download File" button multiple times.</p> |
|
87 | 87 | <h1>Madrigal 2.6.3 Release - Febuary 27, 2012</h1> |
|
88 | 88 | <p>Small bug fixes in 3 cgi scripts affecting plots: madExperiment.cgi, madDataDisplay, getMadplot.py</p> |
|
89 | 89 | <h1>Madrigal 2.6.2 Release - Febuary 8, 2012</h1> |
|
90 | 90 | <p>Small bug fix involving creating Hdf5 export files in data.py.</p> |
|
91 | 91 | <h1>Madrigal 2.6.1 Release - January 20, 2012</h1> |
|
92 | 92 | <p>Small bug fix involving a memory leak in _Madrec.c and a rare problem creating Hdf5 export files in data.py. </p> |
|
93 | 93 | <h1>Madrigal 2.6 Release - November 2011 </h1> |
|
94 | 94 | <blockquote> |
|
95 | 95 | <h2>New simple local web user interface </h2> |
|
96 | 96 | <p>A new easy to use interface to access local Madrigal data was developed by Jicamarca with support from Millstone Hill staff. This interface in now very robust and has been tested with data from all Madrigal sites.</p> |
|
97 | 97 | <h2>HDF5 file download availablity</h2> |
|
98 | 98 | <p>Users can now download data files as HDF5, in addition to simple column delimited ascii and the more complex <a href="/static/cedarFormat.pdf" target="_self">CEDAR formats</a>. This is also the result of a Jicamarca/Millstone Hill collaborations.</p> |
|
99 | 99 | <h2>Users can register interest in experiments or instruments</h2> |
|
100 | 100 | <p>Users can now register interest in experiments or instruments, and get emails whenever that Madrigal experiment or instrument is updated.</p> |
|
101 | 101 | <h2>Administrative improvements - can now add external disks to experiments</h2> |
|
102 | 102 | <p>It is now easy to expand the Madrigal database by <a href="ad_other.html#experiments" target="_self">mounting additional hard disks</a> to make more room for data.</p> |
|
103 | 103 | <h2>New metadata - experiment PI's and analyst</h2> |
|
104 | 104 | <p>Experiments now have direct email links to the experiment PI. These PI's can be updated on an experiment or intrument basis.</p> |
|
105 | 105 | <h2>Global seach now more robust</h2> |
|
106 | 106 | <p>The global search UI now generates scripts so you can run the global search right from your computer using either the <a href="rt_python.html" target="_self">python remote API</a>, the <a href="rt_matlab.html" target="_self">Matlab remote API</a>, or the<a href="rt_idl.html" target="_self"> IDL remote API</a>.</p> |
|
107 | 107 | <p> </p> |
|
108 | 108 | </blockquote> |
|
109 | 109 | <hr /> |
|
110 | 110 | <p> </p> |
|
111 | 111 | <h1>Madrigal 2.5.2 Release - May 2009</h1> |
|
112 | 112 | <blockquote> |
|
113 | 113 | <p>A bug fix release - no new features. </p> |
|
114 | 114 | </blockquote> |
|
115 | 115 | <h1>Madrigal 2.5.1 Release - March 2009</h1> |
|
116 | 116 | <blockquote> |
|
117 | 117 | <p>This minor revision to Madrigal 2.5 was needed to support using Madrigal as an archiving database. The experiment metadata was expanded to allow archived experiments. Archived experiments are not shared between Madrigal sites, but are visible as local experiments. </p> |
|
118 | 118 | </blockquote> |
|
119 | 119 | <h1>Madrigal 2.5 Release - February 2009 </h1> |
|
120 | 120 | <blockquote> |
|
121 | 121 | <h2>Simplification of Web User Interface </h2> |
|
122 | 122 | <p>Both the Browse for Individual Madrigal Experiments and the Global Madrigal Database Report web interface have been simplified. Searching for instruments under Browse for Individual Madrigal Experiments is now easier through the use of an instrument category selector.</p> |
|
123 | 123 | <h2>One step file printing available</h2> |
|
124 | 124 | <p>Under Browse for Individual Madrigal Experiments, users can now choose to print an ascii version of any Madrigal file with one click. With this option they can not include any derived parameters or data filters.</p> |
|
125 | 125 | <h2>Installation simplified </h2> |
|
126 | 126 | <p>Autotools is now used to compile all code, significantly reducing the number of parameters in the madrigal.cfg configuration file.</p> |
|
127 | 127 | <h2>64-bit tested </h2> |
|
128 | 128 | <p>Madrigal has now been fully tested as a 64-bit application. It is important that all Madrigal installations switch to 64-bit machines by the year 2037, because 32-bit unix cannot handle dates beyond then.</p> |
|
129 | 129 | <h2>International Reference Ionosphere (IRI) derived parameters now available</h2> |
|
130 | 130 | <p>All parameters calculated by the International Reference Ionosphere (IRI) model can now be selected as derived parameters.</p> |
|
131 | 131 | <h2>Additional automatic sharing of metadata added</h2> |
|
132 | 132 | <p>For administrators: Now when new sites or instruments are added to Madrigal, these metadata files are automatically added to your site. </p> |
|
133 | 133 | <h2>Experiment level security</h2> |
|
134 | 134 | <p>Previously, individual Madrigal files could be made public or private. Now entire experiments can be made public, private, or hidden altogether. See the script <a href="ad_createExp.html#changeExpStatus">changeExpStatus.py</a> for details. </p> |
|
135 | 135 | <h2>Experiment directory naming convention modified </h2> |
|
136 | 136 | <p>Previous to Madrigal 2.5, all Madrigal experiments had to be stored in directory paths in the form:</p> |
|
137 | 137 | <pre>$MADROOT/experiments/YYYY/<3 letter inst mnemonic>/ddMMMyy[letter], |
|
138 | 138 | Example: /opt/madrigal/experiments/1998/mlh/20jan98b.</pre> |
|
139 | 139 | <p>Under this convention, the date of the directory name represented the start date of the experiment, with one letter optionally added. This meant there was a limited number of experiments that could be created for a particular day for a particular experiment. This part of the directory naming convention has been dropped, and now the convention is:</p> |
|
140 | 140 | <pre>$MADROOT/experiments/YYYY/<3 letter inst mnemonic>/*, |
|
141 | 141 | Example: /opt/madrigal/experiments/1998/mlh/mlh_exp_234. |
|
142 | 142 | </pre> |
|
143 | 143 | </blockquote> |
|
144 | 144 | |
|
145 | 145 | <hr /> |
|
146 | 146 | <h1>Madrigal 2.4 Release - February 2006 </h1> |
|
147 | 147 | <blockquote> |
|
148 | 148 | <h2>Simple web UI added</h2> |
|
149 | 149 | <p>A new web user-interface has been added that allows easy printing and plotting of basic Madrigal data. To make it easy to use, advanced Madrigal features such as derived parameters and filtering of data have been removed.</p> |
|
150 | 150 | <h2>On-demand plot creation</h2> |
|
151 | 151 | <p>Madrigal now allows users to create basic scatter plots and pcolor plots versus range or altitude of any measured or derived parameter in a data set.</p> |
|
152 | 152 | <h2>Logging of user data access</h2> |
|
153 | 153 | <p>Madrigal now <a href="ad_logging.html">logs user's names, emails, and affiliations</a> whenever data files are directly accessed in a file administrators can access. </p> |
|
154 | 154 | <h2>Automatic updating of all geophysical data</h2> |
|
155 | 155 | <p>Madrigal now automatically updates all its internal geophysical files (e.g., Kp, Fof2, Dst, Imf, etc) every time updateMaster is run. </p> |
|
156 | 156 | <h2>Simple-to-use python module to create and edit Madrigal files</h2> |
|
157 | 157 | <p>There is now a <a href="ad_createFiles.html#python">simple-to-use python module</a> to create and edit Madrigal files. </p> |
|
158 | 158 | <h2>New administrative scripts to manage Madrigal experiments</h2> |
|
159 | 159 | <p>Administrators can now add or modify all Madrigal experiments using <a href="ad_createExp.html">simple administrative scripts</a>, instead of trying to edit Madrigal metadata files themselves or use the complex genExp script. </p> |
|
160 | 160 | <h2>Complete documentation rewrite</h2> |
|
161 | 161 | <p>Madrigal documentation has now been completely rewritten and reorganized into three manuals: one for <a href="wt_usersGuide.html">users</a>, one for <a href="admin.html">administrators</a>, and one for <a href="dev_contents.html">developers</a>. </p> |
|
162 | 162 | <h2>Automatic graphics conversion</h2> |
|
163 | 163 | <p>Madrigal will now allow users to select any graphics format they prefer for <a href="ad_createExp.html#auxillary">graphics administrators place in experiments</a>. This feature was contributed by Eiscat. </p> |
|
164 | 164 | <h2>Update of IGRF/MSIS</h2> |
|
165 | 165 | <p>The Madrigal derivation engine is now using the <a href="http://www.ngdc.noaa.gov/IAGA/vmod/igrf.html">IGRF 2010 coefficients</a>, and the <a href="https://omniweb.gsfc.nasa.gov/vitmo/msis_vitmo.html">MSIS 2000 model</a>. </p> |
|
166 | 166 | <h2>Limiting of disk space used for global search files</h2> |
|
167 | 167 | <p>Administrators can now limit the maximum amount of disk space used to store temporary global search files. See the section on editing the madrigal.cfg file in the installation guide. </p> |
|
168 | 168 | </blockquote> |
|
169 | 169 | <p> </p> |
|
170 | 170 | <hr /> |
|
171 | 171 | <p> </p> |
|
172 | 172 | <h1>Madrigal 2.3 Release - March 2004</h1> |
|
173 | 173 | |
|
174 | 174 | <blockquote> |
|
175 | 175 | <h2>Remote programming access to Madrigal via web services using any platform</h2> |
|
176 | 176 | <p>Madrigal now exposes all the information and capabilities it has as web services, which allows |
|
177 | 177 | easy access to Madrigal from any computer on the internet using any platform (Unix, Windows, Mac, etc). |
|
178 | 178 | Madrigal's web services are basically cgi scripts with simple output that allows easy parsing of the |
|
179 | 179 | information. Any language that supports the HTTP standard can then access any Madrigal site. We have |
|
180 | 180 | written remote API's using python and Matlab, but almost any language could be used. See the section |
|
181 | 181 | on <a href="{% url 'docs' 'rt_contents.html' %}">remote programming access</a> for details of these APIs and the underlying web services.</p> |
|
182 | 182 | <p>Note that this approach of remotely accessing Madrigal data has been always possible before by parsing the |
|
183 | 183 | html output meant to be displayed in a web browser (this general programming method is referred to as "screen |
|
184 | 184 | scraping"). However, not only is this parsing difficult; but the code often breaks when the user interface |
|
185 | 185 | is modified in any way. With web services the returned cgi scripts are designed to be both simple to parse |
|
186 | 186 | and stable.</p> |
|
187 | 187 | <p>The web services are not implemented according to the SOAP or XMLRPC standard since not all scripting |
|
188 | 188 | languages have support for these standards (or for XML parsing). Instead they use the simple approach |
|
189 | 189 | of returning data requested via a query as a delimited text file. These web services are fully |
|
190 | 190 | documented <a href="{% url 'docs' 'rt_webServices.html' %}">here.</a></p> |
|
191 | 191 | <p>Users who want only to write programs to remotely access Madrigal, and not to install a Madrigal server |
|
192 | 192 | themselves, are now able to <a href="http://www.haystack.mit.edu/madrigal/madDownload.html"> download </a> |
|
193 | 193 | the remote python and Matlab API's from the |
|
194 | 194 | <a href="http://www.openmadrigal.org">OpenMadrigal</a> site.</p> |
|
195 | 195 | <h2> Command-line global search</h2> |
|
196 | 196 | <p>As an example of remote programming access to Madrigal via web services, an application |
|
197 | 197 | <a href="rt_python.html#globalIsprint">globalIsprint</a> was written |
|
198 | 198 | using the python remote API that does a global search of data on any Madrigal site that has installed Madrigal version |
|
199 | 199 | 2.3. This application is installed as part of Madrigal, and also when the standalone remote python |
|
200 | 200 | API is installed. It has all the filtering ability of the web-based global search.</p> |
|
201 | 201 | <h2>Calculate any derivable Madrigal parameter for any time and point(s) in space</h2> |
|
202 | 202 | <p>By clicking on "Run Models", users can calculate any derived Madrigal parameter (such as magnetic fields, |
|
203 | 203 | or geophysical parameters) for arbitrary times and ranges of position. Note that this capability is also |
|
204 | 204 | available as a web service, and through the remote python and Matlab API's.</p> |
|
205 | 205 | <h2>New derived parameters</h2> |
|
206 | 206 | <ul> |
|
207 | 207 | <li> |
|
208 | 208 | CGM_LAT: <b>Corrected geomagnetic latitude</b> (deg) <br> |
|
209 | 209 | This parameter gives the location of a point in Corrected geomagnetic latitude. |
|
210 | 210 | This method uses code developed by Vladimir Papitashvili. For more information on CGM coordinates |
|
211 | 211 | and this code, click <a href="https://omniweb.gsfc.nasa.gov/vitmo/cgmm_des.html"> here.</a></li> |
|
212 | 212 | <li> |
|
213 | 213 | CGM_LONG: <b>Corrected geomagnetic longitude</b> (deg) <br> |
|
214 | 214 | This parameter gives the location of a point in Corrected geomagnetic longitude. |
|
215 | 215 | This method uses code developed by Vladimir Papitashvili. For more information on CGM coordinates |
|
216 | 216 | and this code, click <a href="https://omniweb.gsfc.nasa.gov/vitmo/cgmm_des.html"> here.</a></li> |
|
217 | 217 | <li> |
|
218 | 218 | TSYG_EQ_XGSM: <b>Tsyganenko field GSM XY plane X point</b> (earth radii) <br> |
|
219 | 219 | This parameter gives the X value in GSM coordinates of where the field line associated |
|
220 | 220 | with a given input point in space and time crosses the GSM XY plane (the magnetic equatorial plane). GSM stands for |
|
221 | 221 | Geocentric Solar Magnetospheric System, and its XY plane is the equatorial plane of |
|
222 | 222 | the earth's magnetic dipole field. The field lines are traced using the |
|
223 | 223 | Tsyganenko |
|
224 | 224 | Magnetospheric model, so external effects on the earth's magnetic field such the solar wind are |
|
225 | 225 | taken into account. This code uses the 2001 Tsyganenko model, which averages solar wind values |
|
226 | 226 | over the past hour, instead of simply using present values.</li> |
|
227 | 227 | <li> TSYG_EQ_YGSM: <b>Tsyganenko field GSM XY plane Y point</b> (earth radii) <br> |
|
228 | 228 | This parameter gives the Y value in GSM coordinates of where the field line associated |
|
229 | 229 | with a given input point in space and time crosses the GSM XY plane (the magnetic equatorial plane). GSM stands for |
|
230 | 230 | Geocentric Solar Magnetospheric System, and its XY plane is the equatorial plane of |
|
231 | 231 | the earth's magnetic dipole field. The field lines are traced using the Tsyganenko |
|
232 | 232 | Magnetospheric model, so external effects on the earth's magnetic field such the solar wind are |
|
233 | 233 | taken into account. This code uses the 2001 Tsyganenko model, which averages solar wind values |
|
234 | 234 | over the past hour, instead of simply using present values.</li> |
|
235 | 235 | <li> TSYG_EQ_XGSM: <b>Tsyganenko field GSE XY plane X point</b> (earth radii) <br> |
|
236 | 236 | This parameter gives the X value in GSE coordinates of where the field line associated |
|
237 | 237 | with a given input point in space and time crosses the GSE XY plane (the equatorial plane). GSE stands for |
|
238 | 238 | Geocentric Solar Ecliptic System, and its XY plane is the equatorial plane of |
|
239 | 239 | the earth's rotation. The field lines are traced using the Tsyganenko |
|
240 | 240 | Magnetospheric model, so external effects on the earth's magnetic field such the solar wind are |
|
241 | 241 | taken into account. This code uses the 2001 Tsyganenko model, which averages solar wind values |
|
242 | 242 | over the past hour, instead of simply using present values.</li> |
|
243 | 243 | <li> TSYG_EQ_YGSM: <b>Tsyganenko field GSE XY plane Y point</b> (earth radii) <br> |
|
244 | 244 | This parameter gives the Y value in GSE coordinates of where the field line associated |
|
245 | 245 | with a given input point in space and time crosses the GSE XY plane (the equatorial plane). GSE stands for |
|
246 | 246 | Geocentric Solar Ecliptic System, and its XY plane is the equatorial plane of |
|
247 | 247 | the earth's rotation. The field lines are traced using the Tsyganenko |
|
248 | 248 | Magnetospheric model, so external effects on the earth's magnetic field such the solar wind are |
|
249 | 249 | taken into account. This code uses the 2001 Tsyganenko model, which averages solar wind values |
|
250 | 250 | over the past hour, instead of simply using present values.</li> |
|
251 | 251 | <li> BHHMMSS and EHHMMSS: <b>Start and end time in HHMMSS</b> (suggested by Mary McCready at SRI)</li> |
|
252 | 252 | </ul> |
|
253 | 253 | <h2>Bug fixes</h2> |
|
254 | 254 | <p>The Madrigal C API now no longer aborts when a Cedar file contains cycle marks (Cedar |
|
255 | 255 | parameter 95) that are not in order. (Reported by Angela Li, SRI)</p> |
|
256 | 256 | <p>A problem launching the global search with the python module os.spawnlp was fixed. |
|
257 | 257 | (Reported by Angela Li, SRI)</p> |
|
258 | 258 | </blockquote> |
|
259 | 259 | <p> </p> |
|
260 | 260 | <hr></hr> |
|
261 | 261 | <h1> |
|
262 | 262 | Madrigal 2.2 Release - Feb 2003</h1> |
|
263 | 263 | |
|
264 | 264 | |
|
265 | 265 | <blockquote> |
|
266 | 266 | <h2>New derived parameters</h2> |
|
267 | 267 | <ul> |
|
268 | 268 | <li> |
|
269 | 269 | SUNRISE_HOUR - <b>Ionospheric sunrise</b> (hour)<br> |
|
270 | 270 | This parameter gives the hour UT that sunrise occurs at that particular |
|
271 | 271 | point in space that particular day. If that point in space is either in sunlight or in shadow |
|
272 | 272 | the entire UT day, sunrise_hour will be missing. To find out which, display the |
|
273 | 273 | Shadow height (SDWHT) parameter. If shadow height is less that the altitude of the |
|
274 | 274 | point, its in sunlight; if shadow height is greater than the altitude, its in the earth's shadow.</li> |
|
275 | 275 | <li>SUNSET_HOUR - <b>Ionospheric sunset</b> (hour)<br> |
|
276 | 276 | This parameter gives the hour UT that sunset occurs at that particular |
|
277 | 277 | point in space that particular day. If that point in space is either in sunlight or in shadow |
|
278 | 278 | the entire UT day, sunset_hour will be missing. To find out which, display the |
|
279 | 279 | Shadow height (SDWHT) parameter. If shadow height is less that the altitude of the |
|
280 | 280 | point, its in sunlight; if shadow height is greater than the altitude, its in the earth's shadow.</li> |
|
281 | 281 | <li>CONJ_SUNRISE_H - <b>Magnetic conjugate point sunrise</b> (hour)<br> |
|
282 | 282 | This parameter gives the hour UT that sunrise occurs at the magnetic conjugate point of the particular |
|
283 | 283 | point in space that particular day.</li> |
|
284 | 284 | <li>CONJ_SUNSET_H - <b>Magnetic conjugate point sunset</b> (hour)<br> |
|
285 | 285 | This parameter gives the hour UT that sunset occurs at the magnetic conjugate point of the particular |
|
286 | 286 | point in space that particular day.</li> |
|
287 | 287 | <li>SZEN - <b>Solar zenith angle in measurement vol</b> (deg) <br> |
|
288 | 288 | This parameter gives the solar zenith angle in degrees. If 0 degrees, the sun is directly |
|
289 | 289 | overhead. A solar zenith angle of between 90 and 180 degrees does not mean the sun is not |
|
290 | 290 | visible, due to the finite solid angle of the sun and the altitude the point may be above the |
|
291 | 291 | earth's surface.</li> |
|
292 | 292 | <li>SZENC - <b>Conjugate solar zenith angle</b> (deg) <br> |
|
293 | 293 | This parameter gives the solar zenith angle at the magnetic conjugate point in degrees.</li> |
|
294 | 294 | <li>SDWHT - <b>Shadow height</b> (km) <br> |
|
295 | 295 | This parameter gives the height above the earth's surface at which any part of the sun can be seen. It depends only |
|
296 | 296 | on the time, and on the geodetic latitude and longitude. During the day shadow height will be zero. Since the sun is |
|
297 | 297 | larger than the earth, the shadow height is always finite. If shadow height is less that the altitude of a given |
|
298 | 298 | point in space, its in sunlight; if shadow height is greater than the altitude, its in the earth's shadow.</li> |
|
299 | 299 | <li>MAGCONJSDWHT - <b>Magnetic conjugate shadow height</b> (km) <br> |
|
300 | 300 | This parameter gives the height above the earth's surface at the magnetic conjugate point's latitude and longitude at |
|
301 | 301 | which any part of the sun can be seen. </li> |
|
302 | 302 | <li><b>10 Interplanetary Magnetic Field parameters</b><br> |
|
303 | 303 | Includes field strength in GSM or GSE coordinates, solar wind plasma density, speed, and measuring satellite id. |
|
304 | 304 | Click on any parameter to see the definition of the two coordinate systems.</li> |
|
305 | 305 | </ul> |
|
306 | 306 | <h2>Filtering using any parameter</h2> |
|
307 | 307 | <ul> |
|
308 | 308 | <li>There are now also free-form filters at the end |
|
309 | 309 | of the filter section, which allow you to set up filters based on any |
|
310 | 310 | single parameter or on two parameters either added, |
|
311 | 311 | subtracted, multiplied, or divided together. For example, you can now filter on |
|
312 | 312 | Ti, the ratio Ti/dTi, or gdalt-sdwht (which is positive if the point is in sunlight). |
|
313 | 313 | See the tutorial for more details.</li> |
|
314 | 314 | </ul> |
|
315 | 315 | <h2>Better help understanding what each parameter means</h2> |
|
316 | 316 | <ul> |
|
317 | 317 | <li>Complex parameters now have full html descriptions accessible from the isprint page. |
|
318 | 318 | Just click on the parameter name and you'll see the short description. For more complex |
|
319 | 319 | parameters you'll also see a link to a more detailed explanation.</li> |
|
320 | 320 | </ul> |
|
321 | 321 | <h2>Improved data output</h2> |
|
322 | 322 | <ul> |
|
323 | 323 | <li>If you select only 1D parameters, or derived parameters that depend only on other 1D parameters, |
|
324 | 324 | isprint will only print a single line per record, making it easier to read.</li> |
|
325 | 325 | <li>All filters used are printed at the beginning of the report. Trivial filters that don't exclude |
|
326 | 326 | data (such as elevation from 0 to 90 degrees) are ignored.</li> |
|
327 | 327 | </ul> |
|
328 | 328 | <h2>Better consistency with Cedar standard</h2> |
|
329 | 329 | <ul> |
|
330 | 330 | <li>All units are now consistent with the Cedar standard (when displaying Cedar parameters).</li> |
|
331 | 331 | <li>The special Cedar values "missing", "assumed", and "known bad" are differentiated in isprint output, |
|
332 | 332 | and not all lumped together as "missing" as before.</li> |
|
333 | 333 | <li>Unknown parameter codes displayed with a scale factor of 1.0.</li> |
|
334 | 334 | </ul> |
|
335 | 335 | <h2>New derived parameters are simple to add</h2> |
|
336 | 336 | <ul> |
|
337 | 337 | <li>The isprint web page is now based on the madc library, and has been designed to |
|
338 | 338 | make it extremely simple to add new derived parameters. See the |
|
339 | 339 | madc API documentation for details.</li> |
|
340 | 340 | </ul> |
|
341 | 341 | </blockquote> |
|
342 | 342 | <!-- InstanceEndEditable --> |
|
343 | 343 | <table width="100%" border="1" cellpadding="0" cellspacing="2" class="navigation"> |
|
344 | 344 | <tr> |
|
345 | <td width="5%"><a href="{% url 'docs' 'madIntroduction.html' %}"><img src="/static/previous.png" alt="previous" width="32" height="32" /></a></td> | |
|
346 | <td width="5%"><a href="{% url 'docs' 'madContents.html' %}"><img src="/static/up.png" alt="up" width="32" height="32" /></a></td> | |
|
347 | <td width="5%"><a href="{% url 'docs' 'wt_usersGuide.html' %}"><img src="/static/next.png" alt="next" width="32" height="32" /></a></td> | |
|
345 | <td width="5%"><a href="{% url 'docs' 'madIntroduction.html' %}"><img src="/madrigal/static/previous.png" alt="previous" width="32" height="32" /></a></td> | |
|
346 | <td width="5%"><a href="{% url 'docs' 'madContents.html' %}"><img src="/madrigal/static/up.png" alt="up" width="32" height="32" /></a></td> | |
|
347 | <td width="5%"><a href="{% url 'docs' 'wt_usersGuide.html' %}"><img src="/madrigal/static/next.png" alt="next" width="32" height="32" /></a></td> | |
|
348 | 348 | <td width="54%"><!-- InstanceBeginEditable name="EditTitleBottom" -->What's new in Madrigal 3.0?<!-- InstanceEndEditable --></td> |
|
349 | 349 | <td width="13%"><a href="{% url 'docs' 'madContents.html' %}">Doc home </a></td> |
|
350 | 350 | <td width="18%"><a href="/">Madrigal home</a></td> |
|
351 | 351 | </tr> |
|
352 | 352 | </table> |
|
353 | 353 | <div class='online-navigation'> |
|
354 | 354 | <b class="navlabel">Previous:</b> |
|
355 | 355 | <a class="sectref" href="{% url 'docs' 'madIntroduction.html' %}"><!-- InstanceBeginEditable name="PreviousTitle2" -->Brief History <!-- InstanceEndEditable --></A> |
|
356 | 356 | <b class="navlabel"> Up:</b> |
|
357 | 357 | <a class="sectref" href="{% url 'docs' 'madContents.html' %}"><!-- InstanceBeginEditable name="UpTitle2" -->Doc home <!-- InstanceEndEditable --></A> |
|
358 | 358 | <b class="navlabel"> Next:</b> |
|
359 | 359 | <a class="sectref" href="{% url 'docs' 'wt_usersGuide.html' %}"><!-- InstanceBeginEditable name="NextTitle2" -->Madrigal user's guide <!-- InstanceEndEditable --></A></div> |
|
360 | 360 | <hr/> |
|
361 | 361 | <p> </p> |
|
362 | 362 | </body> |
|
363 | 363 | <!-- InstanceEnd --></html> |
@@ -1,242 +1,241 | |||
|
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 | 54 | url(r'^view_plot/?$', |
|
55 | 55 | views.view_plot, |
|
56 | 56 | name='plot'), |
|
57 | 57 | url(r'^downloadAsIs/?$', |
|
58 | 58 | views.download_as_is, |
|
59 | 59 | name='download_as_is'), |
|
60 | 60 | url(r'^downloadFileAsIs/?$', |
|
61 | 61 | views.download_file_as_is, |
|
62 | 62 | name='download_file_as_is'), |
|
63 | 63 | url(r'^printAsIs/?$', |
|
64 | 64 | views.print_as_is, |
|
65 | 65 | name='print_as_is'), |
|
66 | 66 | url(r'^listRecords/?$', |
|
67 | 67 | views.list_records, |
|
68 | 68 | name='list_records'), |
|
69 | 69 | url(r'^showInfo/?$', |
|
70 | 70 | views.show_info, |
|
71 | 71 | name='show_info'), |
|
72 | 72 | url(r'^showDoi/?$', |
|
73 | 73 | views.show_doi, |
|
74 | 74 | name='show_doi'), |
|
75 | 75 | url(r'^getAdvanced/?$', |
|
76 | 76 | views.get_advanced, |
|
77 | 77 | name='get_advanced'), |
|
78 | 78 | url(r'^advancedDownload/?$', |
|
79 | 79 | views.advanced_download, |
|
80 | 80 | name='advanced_download'), |
|
81 | 81 | url(r'^advancedPrint/?$', |
|
82 | 82 | views.advanced_print, |
|
83 | 83 | name='advanced_print'), |
|
84 | 84 | url(r'^list/?$', |
|
85 | 85 | views.check_registration(views.view_list), |
|
86 | 86 | name='view_list'), |
|
87 | 87 | url(r'^downloadAsIsScript/?$', |
|
88 | 88 | views.download_as_is_script, |
|
89 | 89 | name='download_as_is_script'), |
|
90 | 90 | url(r'^generateDownloadFilesScript/?$', |
|
91 | 91 | views.generate_download_files_script, |
|
92 | 92 | name='generate_download_files_script'), |
|
93 | 93 | url(r'^downloadAdvancedScript/?$', |
|
94 | 94 | views.download_advanced_script, |
|
95 | 95 | name='download_advanced_script'), |
|
96 | 96 | url(r'^generateDownloadAdvancedScript/?$', |
|
97 | 97 | views.generate_download_advanced_script, |
|
98 | 98 | name='generate_download_advanced_script'), |
|
99 | 99 | url(r'^generateParmsScript/?$', |
|
100 | 100 | views.generate_parms_script, |
|
101 | 101 | name='generate_parms_script'), |
|
102 | 102 | url(r'^generateParmsFiltersScript/?$', |
|
103 | 103 | views.generate_parms_filters_script, |
|
104 | 104 | name='generate_parms_filters_script'), |
|
105 | 105 | url(r'^listExperiments/?$', |
|
106 | 106 | views.list_experiments, |
|
107 | 107 | name='list_experiments'), |
|
108 | 108 | url(r'^viewRecordPlot/?$', |
|
109 | 109 | views.view_record_plot, |
|
110 | 110 | name='view_record_plot'), |
|
111 | 111 | url(r'^viewRecordImage/?$', |
|
112 | 112 | views.view_record_image, |
|
113 | 113 | name='view_record_image'), |
|
114 | 114 | url(r'^showExperiment/?$', |
|
115 | 115 | views.check_registration(views.show_experiment), |
|
116 | 116 | name='show_experiment'), |
|
117 | 117 | url(r'^madExperiment.cgi/*$', |
|
118 | 118 | views.check_registration(views.show_experiment_v2), |
|
119 | 119 | name='show_experiment_v2'), |
|
120 | 120 | url(r'^chooseScript/?$', |
|
121 | 121 | views.check_registration(views.choose_script), |
|
122 | 122 | name='choose_script'), |
|
123 | 123 | url(r'^ftp/$', |
|
124 | 124 | views.check_registration(views.ftp), |
|
125 | 125 | name='ftp'), |
|
126 | 126 | url(r'^ftp/fullname/([^/]+)/email/([^/]+)/affiliation/([^/]+)/kinst/(\d+)/$', |
|
127 | 127 | views.ftp_instrument, |
|
128 | 128 | name='ftp_instrument'), |
|
129 | 129 | url(r'^ftp/fullname/([^/]+)/email/([^/]+)/affiliation/([^/]+)/kinst/(\d+)/year/(\d+)/$', |
|
130 | 130 | views.ftp_year, |
|
131 | 131 | name='ftp_year'), |
|
132 | 132 | url(r'^ftp/fullname/([^/]+)/email/([^/]+)/affiliation/([^/]+)/kinst/(\d+)/year/(\d+)/kindat/(\d+)/$', |
|
133 | 133 | views.ftp_kindat, |
|
134 | 134 | name='ftp_kindat'), |
|
135 | 135 | url(r'^ftp/fullname/([^/]+)/email/([^/]+)/affiliation/([^/]+)/kinst/(\d+)/year/(\d+)/kindat/(\d+)/format/([^/]+)/$', |
|
136 | 136 | views.ftp_files, |
|
137 | 137 | name='ftp_files'), |
|
138 | 138 | url(r'^ftp/fullname/([^/]+)/email/([^/]+)/affiliation/([^/]+)/kinst/(\d+)/year/(\d+)/kindat/(\d+)/format/([^/]+)/fullFilename/([^/]+)/$', |
|
139 | 139 | views.ftp_download, |
|
140 | 140 | name='ftp_download'), |
|
141 | 141 | url(r'ftpMultipleDownload/$', |
|
142 | 142 | views.ftp_multiple_download, |
|
143 | 143 | name='ftp_multiple_download'), |
|
144 | 144 | url(r'^instMetadata/?$', |
|
145 | 145 | views.instrument_metadata, |
|
146 | 146 | name='instrument_metadata'), |
|
147 | 147 | url(r'^siteMetadata/?$', |
|
148 | 148 | views.site_metadata, |
|
149 | 149 | name='site_metadata'), |
|
150 | 150 | url(r'^parameterMetadata/?$', |
|
151 | 151 | views.parameter_metadata, |
|
152 | 152 | name='parameter_metadata'), |
|
153 | 153 | url(r'^kindatMetadata/?$', |
|
154 | 154 | views.kindat_metadata, |
|
155 | 155 | name='kindat_metadata'), |
|
156 | 156 | url(r'^madCalculator/?$', |
|
157 | 157 | views.madrigal_calculator, |
|
158 | 158 | name='madrigal_calculator'), |
|
159 | 159 | url(r'^madCalculatorOutput/?$', |
|
160 | 160 | views.madrigal_calculator_output, |
|
161 | 161 | name='madrigal_calculator_output'), |
|
162 | 162 | url(r'^getMetadata/*$', |
|
163 | 163 | views.get_metadata, |
|
164 | 164 | name='get_metadata'), |
|
165 | 165 | url(r'^looker/?$', |
|
166 | 166 | views.looker_main, |
|
167 | 167 | name='looker_main'), |
|
168 | 168 | url(r'^lookerForm/?$', |
|
169 | 169 | views.looker_form, |
|
170 | 170 | name='looker_form'), |
|
171 | 171 | url(r'^lookerOutput/?$', |
|
172 | 172 | views.looker_output, |
|
173 | 173 | name='looker_output'), |
|
174 | 174 | url(r'^getVersionService.py/*$', |
|
175 | 175 | views.get_version_service, |
|
176 | 176 | name='get_version_service'), |
|
177 | 177 | url(r'^getInstrumentsService.py/*$', |
|
178 | 178 | views.get_instruments_service, |
|
179 | 179 | name='get_instruments_service'), |
|
180 | 180 | url(r'^getExperimentsService.py/*$', |
|
181 | 181 | views.get_experiments_service, |
|
182 | 182 | name='get_experiments_service'), |
|
183 | 183 | url(r'^getExperimentFilesService.py/*$', |
|
184 | 184 | views.get_experiment_files_service, |
|
185 | 185 | name='get_experiment_files_service'), |
|
186 | 186 | url(r'^getParametersService.py/*$', |
|
187 | 187 | views.get_parameters_service, |
|
188 | 188 | name='get_parameters_service'), |
|
189 | 189 | url(r'^isprintService.py/*$', |
|
190 | 190 | views.isprint_service, |
|
191 | 191 | name='isprint_service'), |
|
192 | 192 | url(r'^getMadfile.cgi/*$', |
|
193 | 193 | views.get_madfile_service, |
|
194 | 194 | name='get_madfile_service'), |
|
195 | 195 | url(r'^madCalculatorService.py/*$', |
|
196 | 196 | views.mad_calculator_service, |
|
197 | 197 | name='mad_calculator_service'), |
|
198 | 198 | url(r'^madTimeCalculatorService.py/*$', |
|
199 | 199 | views.mad_time_calculator_service, |
|
200 | 200 | name='mad_time_calculator_service'), |
|
201 | 201 | url(r'^madCalculator2Service.py/*$', |
|
202 | 202 | views.mad_calculator2_service, |
|
203 | 203 | name='mad_calculator2_service'), |
|
204 | 204 | url(r'^madCalculator2Service.py', |
|
205 | 205 | views.mad_calculator2_service, |
|
206 | 206 | name='mad_calculator2_service'), |
|
207 | 207 | url(r'^madCalculator3Service.py/*$', |
|
208 | 208 | views.mad_calculator3_service, |
|
209 | 209 | name='mad_calculator3_service'), |
|
210 | 210 | url(r'^madCalculator3Service.py', |
|
211 | 211 | views.mad_calculator3_service, |
|
212 | 212 | name='mad_calculator3_service'), |
|
213 | 213 | url(r'^geodeticToRadarService.py', |
|
214 | 214 | views.geodetic_to_radar_service, |
|
215 | 215 | name='geodetic_to_radar_service'), |
|
216 | 216 | url(r'^radarToGeodeticService.py', |
|
217 | 217 | views.radar_to_geodetic_service, |
|
218 | 218 | name='radar_to_geodetic_service'), |
|
219 | 219 | url(r'^listFileTimesService.py', |
|
220 | 220 | views.list_file_times_service, |
|
221 | 221 | name='list_file_times_service'), |
|
222 | 222 | url(r'^downloadWebFileService.py', |
|
223 | 223 | views.download_web_file_service, |
|
224 | 224 | name='download_web_file_service'), |
|
225 | 225 | url(r'^traceMagneticFieldService.py', |
|
226 | 226 | views.trace_magnetic_field_service, |
|
227 | 227 | name='trace_magnetic_field_service'), |
|
228 | 228 | url(r'^globalFileSearchService.py', |
|
229 | 229 | views.global_file_search_service, |
|
230 | 230 | name='global_file_search_service'), |
|
231 | 231 | url(r'^getUrlListFromGroupIdService.py', |
|
232 | 232 | views.get_url_list_from_group_id_service, |
|
233 | 233 | name='get_url_list_from_group_id_service'), |
|
234 | 234 | url(r'^setGroupIdFromUrlListService.py', |
|
235 | 235 | views.set_group_id_from_url_list_service, |
|
236 | 236 | name='set_group_id_from_url_list_service'), |
|
237 | 237 | url(r'docs/name/(.+)$', |
|
238 | 238 | views.docs, |
|
239 | 239 | name='docs'), |
|
240 | 240 | |
|
241 | 241 | ] |
|
242 |
@@ -1,3518 +1,3530 | |||
|
1 | 1 | ''' |
|
2 | 2 | |
|
3 | 3 | @author: Bill Rideout |
|
4 | 4 | @contact: brideout@haystack.mit.edu |
|
5 | 5 | |
|
6 | 6 | $Id: views.py 7345 2021-03-30 18:30:32Z brideout $ |
|
7 | 7 | ''' |
|
8 | 8 | # standard python imports |
|
9 | 9 | import os.path |
|
10 | 10 | import urllib |
|
11 | 11 | import os, sys |
|
12 | 12 | import json |
|
13 | 13 | import datetime, time |
|
14 | 14 | import glob |
|
15 | 15 | import re |
|
16 | 16 | import subprocess |
|
17 | 17 | import io |
|
18 | 18 | import collections |
|
19 | 19 | import shutil |
|
20 | 20 | import mimetypes |
|
21 | 21 | import tempfile |
|
22 | 22 | import random |
|
23 | 23 | |
|
24 | 24 | # django imports |
|
25 | 25 | from django.shortcuts import render, redirect |
|
26 | 26 | from django.views.decorators.csrf import csrf_exempt |
|
27 | 27 | from django.template.context import RequestContext |
|
28 | 28 | #from django.conf import settings |
|
29 | 29 | try: |
|
30 | 30 | from django.urls import reverse |
|
31 | 31 | except ImportError: |
|
32 | 32 | from django.core.urlresolvers import reverse |
|
33 | 33 | from django.http import HttpResponse, HttpResponseRedirect, StreamingHttpResponse |
|
34 | 34 | import django.utils.http |
|
35 | 35 | import django.core.files |
|
36 | 36 | import django.utils.safestring |
|
37 | 37 | from wsgiref.util import FileWrapper |
|
38 | 38 | |
|
39 | 39 | # third party imports |
|
40 | 40 | import numpy |
|
41 | 41 | import plotly.offline as py |
|
42 | 42 | import plotly.graph_objs as go |
|
43 | 43 | import h5py |
|
44 | 44 | |
|
45 | 45 | |
|
46 | 46 | # madrigal imports |
|
47 | 47 | import madrigal._derive |
|
48 | 48 | import madrigal.metadata |
|
49 | 49 | import madrigal.ui.web |
|
50 | 50 | import madrigal.cedar |
|
51 | 51 | import madrigal.isprint |
|
52 | 52 | import madweb.forms |
|
53 | 53 | |
|
54 | 54 | |
|
55 | 55 | # temp only |
|
56 | 56 | import logging |
|
57 | 57 | |
|
58 | 58 | |
|
59 | 59 | # constants |
|
60 | 60 | formatDict = collections.OrderedDict() |
|
61 | 61 | formatDict['hdf5'] = 'Hdf5' |
|
62 | 62 | formatDict['netCDF4'] = 'netCDF4' |
|
63 | 63 | formatDict['ascii'] = 'Column-delimited ascii' |
|
64 | 64 | maxSize = 50000000 # 50 MB cutoff |
|
65 | 65 | |
|
66 | 66 | |
|
67 | 67 | |
|
68 | 68 | |
|
69 | 69 | def index(request): |
|
70 | 70 | """index is the home page view |
|
71 | 71 | """ |
|
72 | 72 | madDB = madrigal.metadata.MadrigalDB() |
|
73 | 73 | bg_color = madDB.getBackgroundColor() |
|
74 | 74 | welcome = madDB.getIndexHead() |
|
75 | 75 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
76 | 76 | siteName, siteList = madWebObj.getSiteInfo() |
|
77 | 77 | rulesRoadHtml = madDB.getLocalRulesOfRoad() |
|
78 | 78 | template_dict = {'home_active': 'class="active"', 'site_name': siteName, 'site_list': siteList, |
|
79 | 79 | 'rulesOfRoad':django.utils.safestring.mark_safe(rulesRoadHtml), |
|
80 | 80 | 'bg_color': bg_color, 'welcome': welcome} |
|
81 | 81 | return render(request, 'madweb/index.html', template_dict) |
|
82 | 82 | |
|
83 | 83 | @csrf_exempt |
|
84 | 84 | def check_registration(view): |
|
85 | 85 | def check_cookies(request, *args, **kwargs): |
|
86 | 86 | # this view checks if all the needed cookies are set |
|
87 | 87 | cookieDict = request.COOKIES |
|
88 | 88 | try: |
|
89 | 89 | cookieDict['user_fullname'] |
|
90 | 90 | cookieDict['user_email'] |
|
91 | 91 | cookieDict['user_affiliation'] |
|
92 | 92 | # no need to register |
|
93 | 93 | return(view(request, *args, **kwargs)) |
|
94 | 94 | except KeyError: |
|
95 | 95 | return(HttpResponseRedirect(reverse('view_registration') + '?redirect=%s' % (request.get_full_path()))) |
|
96 | 96 | |
|
97 | 97 | return(check_cookies) |
|
98 | 98 | |
|
99 | 99 | |
|
100 | 100 | def view_registration(request): |
|
101 | 101 | madDB = madrigal.metadata.MadrigalDB() |
|
102 | 102 | madWeb = madrigal.ui.web.MadrigalWeb(madDB) |
|
103 | 103 | siteName, siteList = madWeb.getSiteInfo() |
|
104 | 104 | redirect = 'index' # default is to redirect to home page |
|
105 | 105 | if request.method == 'GET': |
|
106 | 106 | if 'redirect' in request.GET: |
|
107 | 107 | redirect = request.GET['redirect'] |
|
108 | 108 | for key in request.GET: |
|
109 | 109 | if key not in ('redirect', 'user_fullname', 'user_email', 'user_affiliation'): |
|
110 | 110 | redirect += '&%s=%s' % (key, request.GET[key]) |
|
111 | 111 | if len(list(request.GET.keys())) > 0 and 'user_fullname' in request.GET: |
|
112 | 112 | form = madweb.forms.RegisterForm(request.GET) |
|
113 | 113 | if form.is_valid(): |
|
114 | 114 | # write cookies and continue to main page |
|
115 | 115 | max_age = 3600*24*365 # one year |
|
116 | 116 | if redirect == 'index': |
|
117 | 117 | response = HttpResponseRedirect(reverse('index')) |
|
118 | 118 | else: |
|
119 | 119 | response = HttpResponseRedirect(redirect) |
|
120 | 120 | response.set_cookie('user_fullname', form.cleaned_data['user_fullname'], max_age=max_age, samesite='Strict') |
|
121 | 121 | response.set_cookie('user_email', form.cleaned_data['user_email'], max_age=max_age, samesite='Strict') |
|
122 | 122 | response.set_cookie('user_affiliation', form.cleaned_data['user_affiliation'], max_age=max_age, samesite='Strict') |
|
123 | 123 | return(response) |
|
124 | 124 | else: |
|
125 | 125 | form = madweb.forms.RegisterForm() |
|
126 | 126 | |
|
127 | 127 | else: |
|
128 | 128 | form = madweb.forms.RegisterForm() |
|
129 | 129 | return render(request, 'madweb/register.html', {'form': form, 'home_active': 'class="active"', |
|
130 | 130 | 'site_name': siteName, 'site_list': siteList, |
|
131 | 131 | 'redirect': redirect}) |
|
132 | 132 | |
|
133 | 133 | |
|
134 | 134 | |
|
135 | 135 | |
|
136 | 136 | |
|
137 | 137 | |
|
138 | 138 | def view_single(request): |
|
139 | 139 | """view_single is the single experiment view. It is supplemented by ajax views to speed performamnce, |
|
140 | 140 | but this view can also create the entire page given a complete query string |
|
141 | 141 | """ |
|
142 | 142 | responseDict = {'single_active': 'class="active"'} |
|
143 | 143 | cookieDict = request.COOKIES |
|
144 | 144 | user_email = cookieDict['user_email'] |
|
145 | 145 | queryDict = request.GET.copy() |
|
146 | 146 | queryDict['user_email'] = user_email |
|
147 | 147 | madDB = madrigal.metadata.MadrigalDB() |
|
148 | 148 | bg_color = madDB.getBackgroundColor() |
|
149 | 149 | madWeb = madrigal.ui.web.MadrigalWeb(madDB) |
|
150 | 150 | siteName, siteList = madWeb.getSiteInfo() |
|
151 | 151 | form = madweb.forms.SingleExpDefaultForm(queryDict) |
|
152 | 152 | if not form.is_valid(): |
|
153 | 153 | # new page |
|
154 | 154 | form = madweb.forms.SingleExpDefaultForm() |
|
155 | 155 | responseDict['form'] = form |
|
156 | 156 | responseDict['site_name'] = siteName |
|
157 | 157 | responseDict['site_list'] = siteList |
|
158 | 158 | responseDict['redirect_list'] = madWeb.getSingleRedirectList() |
|
159 | 159 | if 'instruments' in request.GET: |
|
160 | 160 | responseDict['instruments'] = request.GET['instruments'] |
|
161 | 161 | if 'years' in request.GET: |
|
162 | 162 | responseDict['years'] = request.GET['years'] |
|
163 | 163 | if 'months' in request.GET: |
|
164 | 164 | responseDict['months'] = request.GET['months'] |
|
165 | 165 | try: |
|
166 | 166 | # add extra keys if choosing a file |
|
167 | 167 | form.fields['file_list'] |
|
168 | 168 | responseDict['loader'] = 'loadSingleForm' |
|
169 | 169 | responseDict['redirect'] = reverse('get_files') |
|
170 | 170 | # handle the case with no files |
|
171 | 171 | if len(form.fields['file_list'].choices) < 2: |
|
172 | 172 | form2 = madweb.forms.SingleExpPlotsForm({'experiment_list':form['exp_id'].initial}) |
|
173 | 173 | form.fields['plot_list'] = form2.fields['plot_list'] |
|
174 | 174 | except: |
|
175 | 175 | pass |
|
176 | 176 | responseDict['bg_color'] = bg_color |
|
177 | 177 | return render(request, 'madweb/single.html', responseDict) |
|
178 | 178 | |
|
179 | 179 | |
|
180 | 180 | def get_categories(request): |
|
181 | 181 | """get_categories is a Ajax call that returns the categories select html to support the |
|
182 | 182 | single experiment UI. Called when a user modifies the isGlobal checkbox. |
|
183 | 183 | |
|
184 | 184 | Inputs: |
|
185 | 185 | request |
|
186 | 186 | """ |
|
187 | 187 | form = madweb.forms.SingleExpDefaultForm(request.GET) |
|
188 | 188 | |
|
189 | 189 | return render(request, 'madweb/categories.html', {'form': form}) |
|
190 | 190 | |
|
191 | 191 | |
|
192 | 192 | def get_instruments(request): |
|
193 | 193 | """get_instruments is a Ajax call that returns the instruments select html to support the |
|
194 | 194 | single experiment UI. Called when a user modifies the categories select field. |
|
195 | 195 | |
|
196 | 196 | Inputs: |
|
197 | 197 | request |
|
198 | 198 | """ |
|
199 | 199 | form = madweb.forms.SingleExpInstForm(request.GET) |
|
200 | 200 | |
|
201 | 201 | return render(request, 'madweb/instruments.html', {'form': form}) |
|
202 | 202 | |
|
203 | 203 | |
|
204 | 204 | def get_years(request): |
|
205 | 205 | """get_years is a Ajax call that returns the years select html to support the |
|
206 | 206 | single experiment UI. Called when a user modifies the instruments select field. |
|
207 | 207 | |
|
208 | 208 | Inputs: |
|
209 | 209 | request |
|
210 | 210 | """ |
|
211 | 211 | form = madweb.forms.SingleExpYearForm(request.GET) |
|
212 | 212 | |
|
213 | 213 | is_global = madweb.forms.getIsGlobal([], request.GET) |
|
214 | 214 | |
|
215 | 215 | return render(request, 'madweb/years.html', {'isGlobal': is_global, |
|
216 | 216 | 'form': form}) |
|
217 | 217 | |
|
218 | 218 | |
|
219 | 219 | def get_months(request): |
|
220 | 220 | """get_months is a Ajax call that returns the months select html to support the |
|
221 | 221 | single experiment UI. Called when a user modifies the years select field. |
|
222 | 222 | |
|
223 | 223 | Inputs: |
|
224 | 224 | request |
|
225 | 225 | """ |
|
226 | 226 | form = madweb.forms.SingleExpMonthForm(request.GET) |
|
227 | 227 | |
|
228 | 228 | is_global = madweb.forms.getIsGlobal([], request.GET) |
|
229 | 229 | year = int(request.GET['years']) |
|
230 | 230 | kinst =int(request.GET['instruments']) |
|
231 | 231 | |
|
232 | 232 | return render(request, 'madweb/months.html', {'isGlobal': is_global, |
|
233 | 233 | 'years': year, |
|
234 | 234 | 'form': form}) |
|
235 | 235 | |
|
236 | 236 | |
|
237 | 237 | def get_calendar(request): |
|
238 | 238 | """get_calendar is a Ajax call that returns the calendar html to support the |
|
239 | 239 | single experiment UI. Called when a user selects month field. |
|
240 | 240 | |
|
241 | 241 | Inputs: |
|
242 | 242 | request |
|
243 | 243 | """ |
|
244 | 244 | is_global = madweb.forms.getIsGlobal([], request.GET) |
|
245 | 245 | year = int(request.GET['years']) |
|
246 | 246 | month = int(request.GET['months']) |
|
247 | 247 | kinst =int(request.GET['instruments']) |
|
248 | 248 | |
|
249 | 249 | form = madweb.forms.SingleExpCalendarForm({'years': year, |
|
250 | 250 | 'months': month, |
|
251 | 251 | 'instruments': kinst}) |
|
252 | 252 | |
|
253 | 253 | return render(request, 'madweb/calendar.html', {'isGlobal': is_global, |
|
254 | 254 | 'years': year, |
|
255 | 255 | 'months': month, |
|
256 | 256 | 'instruments': kinst, |
|
257 | 257 | 'form': form}) |
|
258 | 258 | |
|
259 | 259 | |
|
260 | 260 | def populate_calendar_experiment(request): |
|
261 | 261 | """populate_calendar_experiment is a ajax view that returns a json object used by the |
|
262 | 262 | calender widget to populate itself. |
|
263 | 263 | |
|
264 | 264 | Inputs: |
|
265 | 265 | request |
|
266 | 266 | """ |
|
267 | 267 | is_global = madweb.forms.getIsGlobal([], request.GET) |
|
268 | 268 | year = int(request.GET['years']) |
|
269 | 269 | month = int(request.GET['months']) |
|
270 | 270 | kinst =int(request.GET['instruments']) |
|
271 | 271 | madDB = madrigal.metadata.MadrigalDB() |
|
272 | 272 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
273 | 273 | madInstObj = madrigal.metadata.MadrigalInstrument(madDB) |
|
274 | 274 | catId = madInstObj.getCategoryId(kinst) |
|
275 | 275 | |
|
276 | 276 | expDays = madWebObj.getDays(kinst, year, month) |
|
277 | 277 | |
|
278 | 278 | if len(expDays) == 0: |
|
279 | 279 | expDays = madWebObj.getDays(kinst, year, month, optimize=False) |
|
280 | 280 | |
|
281 | 281 | color = "#999" |
|
282 | 282 | jsonListFinal = [] |
|
283 | 283 | for expDay in expDays: |
|
284 | 284 | newdate = '%i/%i/%i' % (expDay.day, expDay.month, expDay.year) |
|
285 | 285 | urlperDate = reverse('view_single') |
|
286 | 286 | query_str = '?' |
|
287 | 287 | if is_global: |
|
288 | 288 | query_str += 'isGlobal=on&' |
|
289 | 289 | query_str += 'categories=%i&instruments=%i&years=%i&months=%i&days=%i' % (catId, kinst, year, |
|
290 | 290 | expDay.month, expDay.day) |
|
291 | 291 | urlperDate += query_str |
|
292 | 292 | dayList = [newdate, "", urlperDate, color] |
|
293 | 293 | jsonListFinal.append(dayList) |
|
294 | 294 | |
|
295 | 295 | return HttpResponse(json.dumps(jsonListFinal), content_type='application/json') |
|
296 | 296 | |
|
297 | 297 | |
|
298 | 298 | def get_files(request): |
|
299 | 299 | """get_files is a Ajax call that returns the files select html to support the |
|
300 | 300 | single experiment UI. Called when a user modifies the calendar or experiments fields. |
|
301 | 301 | |
|
302 | 302 | Inputs: |
|
303 | 303 | request |
|
304 | 304 | """ |
|
305 | 305 | cookieDict = request.COOKIES |
|
306 | 306 | user_email = cookieDict['user_email'] |
|
307 | 307 | queryDict = request.GET.copy() |
|
308 | 308 | queryDict['user_email'] = user_email |
|
309 | 309 | form = madweb.forms.SingleExpFileForm(queryDict) |
|
310 | 310 | |
|
311 | 311 | is_global = madweb.forms.getIsGlobal([], request.GET) |
|
312 | 312 | |
|
313 | 313 | return render(request, 'madweb/file_list.html', {'isGlobal': is_global, |
|
314 | 314 | 'form': form, |
|
315 | 315 | 'loader': 'loadSingleForm', |
|
316 | 316 | 'redirect': reverse('get_files')}) |
|
317 | 317 | |
|
318 | 318 | |
|
319 | 319 | def change_files(request): |
|
320 | 320 | """change_files is a Ajax call that returns the files options html to support the |
|
321 | 321 | single experiment UI. Called when a user modifies the files select field. |
|
322 | 322 | |
|
323 | 323 | Inputs: |
|
324 | 324 | request |
|
325 | 325 | """ |
|
326 | 326 | expID =int(request.GET['experiment_list']) |
|
327 | 327 | basename = request.GET['file_list'] |
|
328 | 328 | madDB = madrigal.metadata.MadrigalDB() |
|
329 | 329 | form = madweb.forms.SingleExpButtonsForm(request.GET) |
|
330 | 330 | |
|
331 | 331 | return render(request, 'madweb/file_buttons.html', {'form': form, |
|
332 | 332 | 'plot_label': madDB.getPlotButtonLabel()}) |
|
333 | 333 | |
|
334 | 334 | |
|
335 | 335 | def show_plots(request): |
|
336 | 336 | """show_plots is a Ajax call that returns the files data html with plots to support the |
|
337 | 337 | single experiment UI. Called when a user modifies the files select field. |
|
338 | 338 | |
|
339 | 339 | Inputs: |
|
340 | 340 | request |
|
341 | 341 | """ |
|
342 | 342 | madDB = madrigal.metadata.MadrigalDB() |
|
343 | 343 | madExpObj = madrigal.metadata.MadrigalExperiment(madDB) |
|
344 | 344 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
345 | 345 | |
|
346 | 346 | try: |
|
347 | 347 | expID = int(request.GET['experiment_list']) |
|
348 | 348 | except ValueError: |
|
349 | 349 | # convert expPath to expID |
|
350 | 350 | expID = madWebObj.getExpIDFromExpPath(request.GET['experiment_list'], True) |
|
351 | 351 | plotList = madExpObj.getExpLinksByExpId(expID) |
|
352 | 352 | if len(plotList) != 0: |
|
353 | 353 | form = madweb.forms.SingleExpPlotsForm(request.GET) |
|
354 | 354 | template = 'madweb/show_plots.html' |
|
355 | 355 | context = {'form': form} |
|
356 | 356 | else: |
|
357 | 357 | template = 'madweb/parameter_selection.html' |
|
358 | 358 | form = madweb.forms.SingleExpPlotsSelectionForm(request.GET) |
|
359 | 359 | context = {'form': form, 'expID': expID} |
|
360 | 360 | |
|
361 | 361 | return render(request, template, context) |
|
362 | 362 | |
|
363 | 363 | |
|
364 | 364 | def view_plot(request): |
|
365 | 365 | |
|
366 | 366 | param1d = request.GET.get('param1d', 0) |
|
367 | 367 | param2d = request.GET.get('param2d', 0) |
|
368 | 368 | |
|
369 | 369 | madDB = madrigal.metadata.MadrigalDB() |
|
370 | 370 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
371 | 371 | madExpObj = madrigal.metadata.MadrigalExperiment(madDB) |
|
372 | 372 | |
|
373 | 373 | expID =int(request.GET['expID']) |
|
374 | 374 | expDir = madExpObj.getExpDirByExpId(expID) |
|
375 | 375 | if expDir is None: |
|
376 | 376 | raise ValueError('No expDir found for exp_id %i' % (int(expID))) |
|
377 | 377 | |
|
378 | fileList = madWebObj.getFileFromExpID(expID, False) | |
|
379 | firsttuple = [a_tuple[0] for a_tuple in fileList] | |
|
380 |
basename = |
|
|
378 | # fileList = madWebObj.getFileFromExpID(expID, False) | |
|
379 | # firsttuple = [a_tuple[0] for a_tuple in fileList] | |
|
380 | basename = request.GET['filename']#firsttuple[0] | |
|
381 | 381 | fullFilename = os.path.join(expDir, basename) |
|
382 | 382 | |
|
383 | 383 | with h5py.File(fullFilename, "r") as f: |
|
384 | 384 | |
|
385 | 385 | # Get the data |
|
386 | 386 | |
|
387 | 387 | data = f['Data'] |
|
388 | 388 | |
|
389 | 389 | if 'Array Layout' in data: |
|
390 | 390 | array = data['Array Layout'] |
|
391 | datatime = [datetime.datetime.fromtimestamp(t) for t in array['timestamps']] | |
|
392 | yrange = array['gdalt'] | |
|
391 | datatime = [datetime.datetime.utcfromtimestamp(t-5*60*60) for t in array['timestamps']] | |
|
392 | if 'gdalt' in array: | |
|
393 | yrange = array['gdalt'] | |
|
394 | elif 'range' in array: | |
|
395 | yrange = array['range'] | |
|
396 | else: | |
|
397 | return HttpResponse("There is no valid data for this plot: gdalt and/or range missing") | |
|
393 | 398 | |
|
394 | 399 | if param1d==0: |
|
395 | plot = plot_heatmap(datatime, yrange, array['2D Parameters'][param2d], param2d) | |
|
400 | kindat = data['Table Layout']['kindat'][0] | |
|
401 | if kindat in (1950, 1911, 1913): | |
|
402 | plot = plot_scatter(datatime, array['2D Parameters'][param2d][0], param2d, array['2D Parameters']['d'+param2d][0]) | |
|
403 | else: | |
|
404 | plot = plot_heatmap(datatime, yrange, array['2D Parameters'][param2d], param2d) | |
|
396 | 405 | else: |
|
397 | 406 | plot = plot_scatter(datatime, array['1D Parameters'][param1d], param1d) |
|
398 | 407 | |
|
399 | 408 | else: |
|
400 | 409 | table = data['Table Layout'] |
|
401 | 410 | datatime = [datetime.datetime.fromtimestamp(t) for t in table['ut2_unix']] |
|
402 | 411 | plot = plot_scatter(datatime,table[param1d],param1d) |
|
403 | 412 | |
|
404 | 413 | return HttpResponse(plot) |
|
405 | 414 | |
|
406 | def plot_scatter(datatime,dataparam,paramname): | |
|
415 | def plot_scatter(datatime,dataparam,paramname, error=[]): | |
|
407 | 416 | if (numpy.isnan(dataparam).all()): |
|
408 | plot = "There is no valid data available for this plot" | |
|
417 | plot = "There is no valid data available for this plot: Empty array" | |
|
409 | 418 | |
|
410 | 419 | else: |
|
420 | mode = 'markers' if len(error)>0 else 'lines' | |
|
411 | 421 | fig = go.Figure() |
|
412 | fig.add_trace(go.Scatter(x=datatime, y=dataparam)) | |
|
422 | fig.add_trace(go.Scatter(x=datatime, y=dataparam, mode=mode, error_y={'type':'data', 'array':error, 'visible':True, 'color':'rgba(255, 144, 14, 0.7)'})) | |
|
413 | 423 | fig.update_yaxes(title_text=paramname) |
|
424 | fig.update_xaxes(title_text='Time [LT]') | |
|
414 | 425 | |
|
415 | 426 | delta = datatime[-1] - datatime[1] |
|
416 | 427 | |
|
417 | 428 | if (delta>datetime.timedelta(days=30)): |
|
418 | 429 | # Add range slider |
|
419 | 430 | fig.update_layout( |
|
420 | 431 | xaxis=dict( |
|
421 | 432 | rangeselector=dict( |
|
422 | 433 | buttons=list([ |
|
423 | 434 | dict(count=1, |
|
424 | 435 | label="1m", |
|
425 | 436 | step="month", |
|
426 | 437 | stepmode="backward"), |
|
427 | 438 | dict(count=6, |
|
428 | 439 | label="6m", |
|
429 | 440 | step="month", |
|
430 | 441 | stepmode="backward"), |
|
431 | 442 | dict(count=1, |
|
432 | 443 | label="1y", |
|
433 | 444 | step="year", |
|
434 | 445 | stepmode="backward"), |
|
435 | 446 | dict(step="all") |
|
436 | 447 | ]) |
|
437 | 448 | ), |
|
438 | 449 | rangeslider=dict( |
|
439 | 450 | visible=True |
|
440 | 451 | ), |
|
441 | 452 | type="date" |
|
442 | 453 | ) |
|
443 | 454 | ) |
|
444 | 455 | |
|
445 | 456 | |
|
446 | 457 | plot = py.plot(fig, include_plotlyjs=False, output_type='div') |
|
447 | 458 | |
|
448 | 459 | |
|
449 | 460 | return plot |
|
450 | 461 | |
|
451 | 462 | |
|
452 | 463 | def plot_heatmap(datatime,datarange,dataparam,paramname): |
|
453 | 464 | if (numpy.all(numpy.isnan(dataparam))): |
|
454 | plot = "There is no valid data available for this plot" | |
|
465 | plot = "There is no valid data available for this plot: Empty array" | |
|
455 | 466 | else: |
|
456 | 467 | fig = go.Figure() |
|
457 | 468 | fig.add_trace(go.Heatmap(x=datatime,y=datarange,z= dataparam,colorscale='Jet',colorbar={"title":paramname})) |
|
458 | 469 | fig.update_yaxes(title_text="range") |
|
470 | fig.update_xaxes(title_text="Time [LT]") | |
|
459 | 471 | fig.update_layout( |
|
460 | 472 | updatemenus=[ |
|
461 | 473 | dict( |
|
462 | 474 | buttons=list([ |
|
463 | 475 | dict( |
|
464 | 476 | args=["colorscale", "Jet"], |
|
465 | 477 | label="Jet", |
|
466 | 478 | method="restyle" |
|
467 | 479 | ), |
|
468 | 480 | dict( |
|
469 | 481 | args=["colorscale", "RdBu"], |
|
470 | 482 | label="Red-Blue", |
|
471 | 483 | method="restyle" |
|
472 | 484 | ), |
|
473 | 485 | dict( |
|
474 | 486 | args=["colorscale", "Viridis"], |
|
475 | 487 | label="Viridis", |
|
476 | 488 | method="restyle" |
|
477 | 489 | ), |
|
478 | 490 | dict( |
|
479 | 491 | args=["colorscale", "Cividis"], |
|
480 | 492 | label="Cividis", |
|
481 | 493 | method="restyle" |
|
482 | 494 | ), |
|
483 | 495 | dict( |
|
484 | 496 | args=["colorscale", "Greens"], |
|
485 | 497 | label="Greens", |
|
486 | 498 | method="restyle" |
|
487 | 499 | ), |
|
488 | 500 | ]), |
|
489 | 501 | type = "dropdown", |
|
490 | 502 | direction="down", |
|
491 | 503 | pad={"r": 10, "t": -10}, |
|
492 | 504 | showactive=True, |
|
493 | 505 | x=0.1, |
|
494 | 506 | xanchor="left", |
|
495 | 507 | y=1.05, |
|
496 | 508 | yanchor="top" |
|
497 | 509 | ), |
|
498 | 510 | dict( |
|
499 | 511 | buttons=list([ |
|
500 | 512 | dict( |
|
501 | 513 | args=[{"contours.showlines": False, "type": "contour"}], |
|
502 | 514 | label="Hide lines", |
|
503 | 515 | method="restyle" |
|
504 | 516 | ), |
|
505 | 517 | dict( |
|
506 | 518 | args=[{"contours.showlines": True, "type": "contour"}], |
|
507 | 519 | label="Show lines", |
|
508 | 520 | method="restyle" |
|
509 | 521 | ), |
|
510 | 522 | ]), |
|
511 | 523 | direction="down", |
|
512 | 524 | pad={"r": 10, "t": -10}, |
|
513 | 525 | showactive=True, |
|
514 | 526 | x=0.32, |
|
515 | 527 | xanchor="left", |
|
516 | 528 | y=1.05, |
|
517 | 529 | yanchor="top" |
|
518 | 530 | ), |
|
519 | 531 | |
|
520 | 532 | ] |
|
521 | 533 | ) |
|
522 | 534 | |
|
523 | 535 | fig.update_layout( |
|
524 | 536 | annotations=[ |
|
525 | 537 | dict(text="Colorscale", showarrow=False, |
|
526 | 538 | x=0, xref="paper", y=1.05, yref="paper", align="left"), |
|
527 | 539 | dict(text="Lines", x=0.25, xref="paper", y=1.05, yref="paper", |
|
528 | 540 | showarrow=False) |
|
529 | 541 | ] |
|
530 | 542 | ) |
|
531 | 543 | |
|
532 | 544 | |
|
533 | 545 | plot = py.plot(fig, include_plotlyjs=False, output_type='div') |
|
534 | 546 | |
|
535 | 547 | return plot |
|
536 | 548 | |
|
537 | 549 | |
|
538 | 550 | def download_as_is(request): |
|
539 | 551 | """download_as_is is a Ajax call that returns the download as is html to support the |
|
540 | 552 | single experiment UI. Called when a user selects download/as is link. |
|
541 | 553 | |
|
542 | 554 | Inputs: |
|
543 | 555 | request |
|
544 | 556 | """ |
|
545 | 557 | cookieDict = request.COOKIES |
|
546 | 558 | if not 'user_fullname' in cookieDict: |
|
547 | 559 | return(HttpResponse('<p>Cookie with user_fullname required for downloadAsIs</p>')) |
|
548 | 560 | user_fullname = django.utils.http.urlquote_plus(cookieDict['user_fullname']) |
|
549 | 561 | user_email = cookieDict['user_email'] |
|
550 | 562 | user_affiliation = django.utils.http.urlquote_plus(cookieDict['user_affiliation']) |
|
551 | 563 | expID =int(request.GET['experiment_list']) |
|
552 | 564 | file_list = request.GET['file_list'] |
|
553 | 565 | form = madweb.forms.SingleExpDownloadAsIsForm({'format_select':file_list, |
|
554 | 566 | 'expID': expID}) |
|
555 | 567 | |
|
556 | 568 | return render(request, 'madweb/download_as_is.html', {'form': form, 'exp_id':expID, |
|
557 | 569 | 'user_fullname':user_fullname, |
|
558 | 570 | 'user_email':user_email, |
|
559 | 571 | 'user_affiliation': user_affiliation}) |
|
560 | 572 | |
|
561 | 573 | |
|
562 | 574 | def download_file_as_is(request): |
|
563 | 575 | """download_file_as_is is a Ajax call that actually downloads a madrigal file. |
|
564 | 576 | |
|
565 | 577 | Inputs: |
|
566 | 578 | request |
|
567 | 579 | """ |
|
568 | 580 | madDB = madrigal.metadata.MadrigalDB() |
|
569 | 581 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
570 | 582 | user_fullname = urllib.parse.unquote_plus(request.GET['user_fullname']) |
|
571 | 583 | user_email = request.GET['user_email'] |
|
572 | 584 | user_affiliation = urllib.parse.unquote_plus(request.GET['user_affiliation']) |
|
573 | 585 | exp_id = request.GET['exp_id'] |
|
574 | 586 | basename = request.GET['basename'] |
|
575 | 587 | downloadFile = madWebObj.downloadFileAsIs(exp_id, basename, user_fullname, user_email, user_affiliation) |
|
576 | 588 | f = open(downloadFile, 'rb') |
|
577 | 589 | filename = os.path.basename(downloadFile) |
|
578 | 590 | chunk_size = 8192 |
|
579 | 591 | file_type = mimetypes.guess_type(downloadFile)[0] |
|
580 | 592 | if file_type is None: |
|
581 | 593 | file_type = 'application/octet-stream' |
|
582 | 594 | response = StreamingHttpResponse(FileWrapper(f, chunk_size), |
|
583 | 595 | content_type=file_type) |
|
584 | 596 | response['Content-Length'] = os.path.getsize(downloadFile) |
|
585 | 597 | response['Content-Disposition'] = "attachment; filename=%s" % (filename) |
|
586 | 598 | response.set_cookie('fileDownload', 'true', path='/', samesite='Strict') |
|
587 | 599 | return(response) |
|
588 | 600 | |
|
589 | 601 | |
|
590 | 602 | def print_as_is(request): |
|
591 | 603 | """print_as_is is a Ajax call that returns the text of the ascii file to support the |
|
592 | 604 | single experiment UI if request.GET has key "text", or the length of the file to be |
|
593 | 605 | downloaded if not. Called when a user selects print/as is link. |
|
594 | 606 | |
|
595 | 607 | Inputs: |
|
596 | 608 | request |
|
597 | 609 | """ |
|
598 | 610 | madDB = madrigal.metadata.MadrigalDB() |
|
599 | 611 | madExpObj = madrigal.metadata.MadrigalExperiment(madDB) |
|
600 | 612 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
601 | 613 | madParmObj = madrigal.data.MadrigalParameters(madDB) |
|
602 | 614 | |
|
603 | 615 | cookieDict = request.COOKIES |
|
604 | 616 | if not 'user_fullname' in cookieDict: |
|
605 | 617 | return(HttpResponse('<p>Cookie with user_fullname required for printAsIs</p>')) |
|
606 | 618 | user_fullname = django.utils.http.urlquote_plus(cookieDict['user_fullname']) |
|
607 | 619 | user_email = cookieDict['user_email'] |
|
608 | 620 | user_affiliation = django.utils.http.urlquote_plus(cookieDict['user_affiliation']) |
|
609 | 621 | expID =int(request.GET['experiment_list']) |
|
610 | 622 | basename = request.GET['file_list'] |
|
611 | 623 | expDir = madExpObj.getExpDirByExpId(int(expID)) |
|
612 | 624 | if expDir is None: |
|
613 | 625 | raise ValueError('No expDir found for exp_id %i' % (int(expID))) |
|
614 | 626 | fullFilename = os.path.join(expDir, basename) |
|
615 | 627 | |
|
616 | 628 | # determine if we need to return the full file text, or just the size and name |
|
617 | 629 | if 'text' in request.GET: |
|
618 | 630 | madFileObj = madrigal.data.MadrigalFile(fullFilename, madDB) |
|
619 | 631 | measParms = madFileObj.getMeasuredParmList() |
|
620 | 632 | measParmMnemList = madParmObj.getParmMnemonicList(measParms) + madFileObj.getStandardParms(upper=True) |
|
621 | 633 | measParmDescList = madParmObj.getParmDescriptionList(measParmMnemList) |
|
622 | 634 | parmList = list(zip(measParmMnemList, measParmDescList)) |
|
623 | 635 | f = open(request.GET['text']) |
|
624 | 636 | text = f.read() |
|
625 | 637 | f.close() |
|
626 | 638 | |
|
627 | 639 | return render(request, 'madweb/print_as_is.html', {'text': text, 'parmList': parmList}) |
|
628 | 640 | |
|
629 | 641 | else: |
|
630 | 642 | tmpFilename = madWebObj.printFileAsIs(fullFilename, user_fullname, user_email, user_affiliation) |
|
631 | 643 | filesize = os.path.getsize(tmpFilename) |
|
632 | 644 | return(HttpResponse('%s:%s' % (filesize, tmpFilename))) |
|
633 | 645 | |
|
634 | 646 | |
|
635 | 647 | def list_records(request): |
|
636 | 648 | """list_records is a Ajax call that returns the list records text. |
|
637 | 649 | |
|
638 | 650 | Inputs: |
|
639 | 651 | request |
|
640 | 652 | """ |
|
641 | 653 | madDB = madrigal.metadata.MadrigalDB() |
|
642 | 654 | madExpObj = madrigal.metadata.MadrigalExperiment(madDB) |
|
643 | 655 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
644 | 656 | |
|
645 | 657 | expID =int(request.GET['experiment_list']) |
|
646 | 658 | basename = request.GET['file_list'] |
|
647 | 659 | expDir = madExpObj.getExpDirByExpId(int(expID)) |
|
648 | 660 | if expDir is None: |
|
649 | 661 | raise ValueError('No expDir found for exp_id %i' % (int(expID))) |
|
650 | 662 | fullFilename = os.path.join(expDir, basename) |
|
651 | 663 | |
|
652 | 664 | text = madWebObj.listRecords(fullFilename) |
|
653 | 665 | |
|
654 | 666 | return render(request, 'madweb/list_records.html', {'expDir': expDir, |
|
655 | 667 | 'basename': basename, |
|
656 | 668 | 'text': text}) |
|
657 | 669 | |
|
658 | 670 | |
|
659 | 671 | def view_record_plot(request): |
|
660 | 672 | """view_record_plot returns the view individual record page. |
|
661 | 673 | |
|
662 | 674 | Inputs: |
|
663 | 675 | request |
|
664 | 676 | """ |
|
665 | 677 | expDir = request.GET['expDir'] |
|
666 | 678 | basename = request.GET['basename'] |
|
667 | 679 | recno = int(request.GET['recno']) |
|
668 | 680 | |
|
669 | 681 | return render(request, 'madweb/view_record_plot.html', {'expDir': expDir, |
|
670 | 682 | 'basename': basename, |
|
671 | 683 | 'recno': recno}) |
|
672 | 684 | |
|
673 | 685 | |
|
674 | 686 | def view_record_image(request): |
|
675 | 687 | """view_record_plot is a Ajax call that returns the record plot. |
|
676 | 688 | |
|
677 | 689 | Inputs: |
|
678 | 690 | request |
|
679 | 691 | """ |
|
680 | 692 | expDir = request.GET['expDir'] |
|
681 | 693 | basename = request.GET['basename'] |
|
682 | 694 | recno = int(request.GET['recno']) |
|
683 | 695 | pngFiles = glob.glob(os.path.join(expDir, 'plots', basename, 'records/*%05i*.png' % (recno))) |
|
684 | 696 | |
|
685 | 697 | image_data = open(pngFiles[0], "rb").read() |
|
686 | 698 | return HttpResponse(image_data, content_type="image/png") |
|
687 | 699 | |
|
688 | 700 | |
|
689 | 701 | |
|
690 | 702 | |
|
691 | 703 | def show_info(request): |
|
692 | 704 | """show_info is a Ajax call that returns the text of the catalog/header text to support the |
|
693 | 705 | single experiment UI. Called when a user selects show info link. |
|
694 | 706 | |
|
695 | 707 | Inputs: |
|
696 | 708 | request |
|
697 | 709 | """ |
|
698 | 710 | madDB = madrigal.metadata.MadrigalDB() |
|
699 | 711 | madExpObj = madrigal.metadata.MadrigalExperiment(madDB) |
|
700 | 712 | |
|
701 | 713 | expID =int(request.GET['experiment_list']) |
|
702 | 714 | basename = request.GET['file_list'] |
|
703 | 715 | expDir = madExpObj.getExpDirByExpId(int(expID)) |
|
704 | 716 | if expDir is None: |
|
705 | 717 | raise ValueError('No expDir found for exp_id %i' % (int(expID))) |
|
706 | 718 | fullFilename = os.path.join(expDir, basename) |
|
707 | 719 | |
|
708 | 720 | madFileObj = madrigal.data.MadrigalFile(fullFilename, madDB) |
|
709 | 721 | text = madFileObj.getCatalogHeaderStr() |
|
710 | 722 | |
|
711 | 723 | return render(request, 'madweb/show_info.html', {'text':text}) |
|
712 | 724 | |
|
713 | 725 | |
|
714 | 726 | def show_doi(request): |
|
715 | 727 | """show_doi is a Ajax call that returns the permanent url for references to support the |
|
716 | 728 | single experiment UI. Called when a user selects show doi link. |
|
717 | 729 | |
|
718 | 730 | Inputs: |
|
719 | 731 | request |
|
720 | 732 | """ |
|
721 | 733 | madDB = madrigal.metadata.MadrigalDB() |
|
722 | 734 | madExpObj = madrigal.metadata.MadrigalExperiment(madDB) |
|
723 | 735 | madInstObj = madrigal.metadata.MadrigalInstrument(madDB) |
|
724 | 736 | |
|
725 | 737 | expID =request.GET['experiment_list'] |
|
726 | 738 | basename = request.GET['file_list'] |
|
727 | 739 | expDir = madExpObj.getExpDirByExpId(int(expID)) |
|
728 | 740 | # get experiment PI and institution |
|
729 | 741 | PI = madExpObj.getPIByExpId(int(expID)) |
|
730 | 742 | kinst = madExpObj.getKinstByExpId(int(expID)) |
|
731 | 743 | startDTList = madExpObj.getExpStartDateTimeByExpId(int(expID)) |
|
732 | 744 | yearStr = str(startDTList[0]) |
|
733 | 745 | if PI is None: |
|
734 | 746 | PI = madInstObj.getContactName(kinst) |
|
735 | 747 | institution = madInstObj.getContactAddress1(kinst) |
|
736 | 748 | |
|
737 | 749 | try: |
|
738 | 750 | madFileObj = madrigal.metadata.MadrigalMetaFile(madDB, os.path.join(expDir, 'fileTab.txt')) |
|
739 | 751 | url = madFileObj.getFileDOIUrlByFilename(basename) |
|
740 | 752 | except: |
|
741 | 753 | url = 'Unknown - please contact madrigal@haystack.mit.edu' |
|
742 | 754 | |
|
743 | 755 | return render(request, 'madweb/show_doi.html', {'url':url, 'PI': PI, 'year': yearStr, |
|
744 | 756 | 'institution': institution}) |
|
745 | 757 | |
|
746 | 758 | |
|
747 | 759 | def get_advanced(request): |
|
748 | 760 | """get_advanced is a view that allows user to download/print files with selected parms |
|
749 | 761 | and filters. |
|
750 | 762 | |
|
751 | 763 | Inputs: |
|
752 | 764 | request |
|
753 | 765 | """ |
|
754 | 766 | madDB = madrigal.metadata.MadrigalDB() |
|
755 | 767 | bg_color = madDB.getBackgroundColor() |
|
756 | 768 | madWeb = madrigal.ui.web.MadrigalWeb(madDB) |
|
757 | 769 | siteName, siteList = madWeb.getSiteInfo() |
|
758 | 770 | madExpObj = madrigal.metadata.MadrigalExperiment(madDB) |
|
759 | 771 | webFormatObj = madrigal.ui.web.MadrigalWebFormat() |
|
760 | 772 | madParmObj = madrigal.data.MadrigalParameters(madDB) |
|
761 | 773 | parmList = webFormatObj.getFormat('Comprehensive') |
|
762 | 774 | measParmList = [] |
|
763 | 775 | derivedParmList = [] |
|
764 | 776 | allParmList = [] |
|
765 | 777 | sureParmList = [] |
|
766 | 778 | |
|
767 | 779 | if 'experiment_list' in request.GET: |
|
768 | 780 | expID = int(request.GET['experiment_list']) |
|
769 | 781 | else: |
|
770 | 782 | return(HttpResponse('<p>experiment_list required for getAdvanced</p>')) |
|
771 | 783 | basename = request.GET['file_list'] |
|
772 | 784 | type = request.GET['type'] |
|
773 | 785 | expDir = madExpObj.getExpDirByExpId(int(expID)) |
|
774 | 786 | if expDir is None: |
|
775 | 787 | raise ValueError('No expDir found for exp_id %i' % (int(expID))) |
|
776 | 788 | fullFilename = os.path.join(expDir, basename) |
|
777 | 789 | expName, kindatDesc = madWeb.getInfoFromFile(fullFilename) |
|
778 | 790 | madFileObj = madrigal.data.MadrigalFile(fullFilename, madDB) |
|
779 | 791 | earliestTime = madFileObj.getEarliestTime() |
|
780 | 792 | latestTime = madFileObj.getLatestTime() |
|
781 | 793 | earliestDT = datetime.datetime(*earliestTime) |
|
782 | 794 | latestDT = datetime.datetime(*latestTime) |
|
783 | 795 | madFileObj.getMeasDervBothParmLists(parmList, measParmList, derivedParmList, allParmList, sureParmList) |
|
784 | 796 | allParmDescList = madParmObj.getParmDescriptionList(allParmList) |
|
785 | 797 | |
|
786 | 798 | dataDict = {'type': type, |
|
787 | 799 | 'fullFilename': fullFilename, |
|
788 | 800 | 'madFileObj': madFileObj, 'parameters': [], |
|
789 | 801 | 'measParmList': measParmList, 'derivedParmList': derivedParmList, |
|
790 | 802 | 'allParmList': allParmList, 'allParmDescList': allParmDescList, |
|
791 | 803 | 'madDB': madDB, 'madParmObj': madParmObj} |
|
792 | 804 | |
|
793 | 805 | min_alt = madFileObj.getMinValidAltitude() |
|
794 | 806 | max_alt = madFileObj.getMaxValidAltitude() |
|
795 | 807 | try: |
|
796 | 808 | float(min_alt) |
|
797 | 809 | float(max_alt) |
|
798 | 810 | dataDict['min_alt'] = '%9.2f' % (min_alt) |
|
799 | 811 | dataDict['max_alt'] = '%9.2f' % (max_alt) |
|
800 | 812 | except: |
|
801 | 813 | pass |
|
802 | 814 | |
|
803 | 815 | if 'AZM' in allParmList: |
|
804 | 816 | dataDict['min_az'] = '-180.0' |
|
805 | 817 | dataDict['max_az'] = '180.0' |
|
806 | 818 | dataDict['min_az2'] = '0.0' |
|
807 | 819 | dataDict['max_az2'] = '0.0' |
|
808 | 820 | |
|
809 | 821 | if 'ELM' in allParmList: |
|
810 | 822 | dataDict['min_el'] = '0.0' |
|
811 | 823 | dataDict['max_el'] = '90.0' |
|
812 | 824 | dataDict['min_el2'] = '0.0' |
|
813 | 825 | dataDict['max_el2'] = '0.0' |
|
814 | 826 | |
|
815 | 827 | if 'PL' in allParmList: |
|
816 | 828 | min_pl = madFileObj.getMinPulseLength() |
|
817 | 829 | max_pl = madFileObj.getMaxPulseLength() |
|
818 | 830 | try: |
|
819 | 831 | float(min_pl) |
|
820 | 832 | float(max_pl) |
|
821 | 833 | dataDict['min_pl'] = '%9.2f' % (min_pl) |
|
822 | 834 | dataDict['max_pl'] = '%9.2f' % (max_pl) |
|
823 | 835 | except: |
|
824 | 836 | pass |
|
825 | 837 | |
|
826 | 838 | if type == 'download': |
|
827 | 839 | defaultFormat = 'Hdf5' |
|
828 | 840 | else: |
|
829 | 841 | defaultFormat = 'ascii' |
|
830 | 842 | dataDict['formats'] = defaultFormat |
|
831 | 843 | dataDict['missing'] = 'NaN' |
|
832 | 844 | dataDict['start_date'] = earliestDT |
|
833 | 845 | dataDict['end_date'] = latestDT |
|
834 | 846 | |
|
835 | 847 | |
|
836 | 848 | isprintForm = madweb.forms.IsprintForm(dataDict) |
|
837 | 849 | |
|
838 | 850 | return render(request, 'madweb/get_advanced.html', {'form': isprintForm, |
|
839 | 851 | 'parmList': isprintForm.parmList, |
|
840 | 852 | 'measParmList': measParmList, |
|
841 | 853 | 'site_name': siteName, 'site_list': siteList, |
|
842 | 854 | 'expName': expName, 'kindatDesc': kindatDesc, |
|
843 | 855 | 'basename': os.path.basename(fullFilename), |
|
844 | 856 | 'type': type, 'bg_color': bg_color, |
|
845 | 857 | 'datetime': True}) |
|
846 | 858 | |
|
847 | 859 | def advanced_download(request): |
|
848 | 860 | """advanced_download is a view that downloads a file with selected parms |
|
849 | 861 | and filters. |
|
850 | 862 | |
|
851 | 863 | Inputs: |
|
852 | 864 | request |
|
853 | 865 | """ |
|
854 | 866 | madDB = madrigal.metadata.MadrigalDB() |
|
855 | 867 | madWeb = madrigal.ui.web.MadrigalWeb(madDB) |
|
856 | 868 | webFormatObj = madrigal.ui.web.MadrigalWebFormat() |
|
857 | 869 | madParmObj = madrigal.data.MadrigalParameters(madDB) |
|
858 | 870 | |
|
859 | 871 | cookieDict = request.COOKIES |
|
860 | 872 | if not 'user_fullname' in cookieDict: |
|
861 | 873 | return(HttpResponse('<p>Cookie with user_fullname required for advancedDownload</p>')) |
|
862 | 874 | user_fullname = django.utils.http.urlquote_plus(cookieDict['user_fullname']) |
|
863 | 875 | user_email = cookieDict['user_email'] |
|
864 | 876 | user_affiliation = django.utils.http.urlquote_plus(cookieDict['user_affiliation']) |
|
865 | 877 | |
|
866 | 878 | parmList = webFormatObj.getFormat('Comprehensive') |
|
867 | 879 | measParmList = [] |
|
868 | 880 | derivedParmList = [] |
|
869 | 881 | allParmList = [] |
|
870 | 882 | sureParmList = [] |
|
871 | 883 | madFileObj = madrigal.data.MadrigalFile(request.GET['fullFilename'], madDB) |
|
872 | 884 | madFileObj.getMeasDervBothParmLists(parmList, measParmList, derivedParmList, allParmList, sureParmList) |
|
873 | 885 | allParmDescList = madParmObj.getParmDescriptionList(allParmList) |
|
874 | 886 | |
|
875 | 887 | request.GET._mutable = True |
|
876 | 888 | request.GET['madFileObj']=madFileObj |
|
877 | 889 | request.GET['measParmList']=measParmList |
|
878 | 890 | request.GET['derivedParmList']=derivedParmList |
|
879 | 891 | request.GET['allParmList']=allParmList |
|
880 | 892 | request.GET['allParmDescList']=allParmDescList |
|
881 | 893 | request.GET['start_date'] = request.GET['start_date'].strip() |
|
882 | 894 | request.GET['end_date'] = request.GET['end_date'].strip() |
|
883 | 895 | # convert dates to datetime |
|
884 | 896 | request.GET['start_date'] = datetime.datetime.strptime(request.GET['start_date'], '%Y-%m-%dT%H:%M:%S') |
|
885 | 897 | request.GET['end_date'] = datetime.datetime.strptime(request.GET['end_date'], '%Y-%m-%dT%H:%M:%S') |
|
886 | 898 | request.GET['madDB'] = madDB |
|
887 | 899 | request.GET['madParmObj'] = madParmObj |
|
888 | 900 | |
|
889 | 901 | |
|
890 | 902 | isprintForm = madweb.forms.IsprintForm(request.GET) |
|
891 | 903 | |
|
892 | 904 | |
|
893 | 905 | if not isprintForm.is_valid(): |
|
894 | 906 | raise ValueError(str(isprintForm.errors)) |
|
895 | 907 | |
|
896 | 908 | downloadFile = madWeb.downloadIsprintFileFromIsprintForm(isprintForm.cleaned_data, user_fullname, user_email, user_affiliation) |
|
897 | 909 | |
|
898 | 910 | |
|
899 | 911 | f = open(downloadFile, 'rb') |
|
900 | 912 | filename = os.path.basename(downloadFile) |
|
901 | 913 | chunk_size = 8192 |
|
902 | 914 | file_type = mimetypes.guess_type(downloadFile)[0] |
|
903 | 915 | if file_type is None: |
|
904 | 916 | file_type = 'application/octet-stream' |
|
905 | 917 | response = StreamingHttpResponse(FileWrapper(f, chunk_size), |
|
906 | 918 | content_type=file_type) |
|
907 | 919 | response['Content-Length'] = os.path.getsize(downloadFile) |
|
908 | 920 | response['Content-Disposition'] = "attachment; filename=%s" % (filename) |
|
909 | 921 | return(response) |
|
910 | 922 | |
|
911 | 923 | |
|
912 | 924 | def advanced_print(request): |
|
913 | 925 | """advanced_download is a view that print a file with selected parms |
|
914 | 926 | and filters. |
|
915 | 927 | |
|
916 | 928 | Inputs: |
|
917 | 929 | request |
|
918 | 930 | """ |
|
919 | 931 | madDB = madrigal.metadata.MadrigalDB() |
|
920 | 932 | bg_color = madDB.getBackgroundColor() |
|
921 | 933 | madWeb = madrigal.ui.web.MadrigalWeb(madDB) |
|
922 | 934 | webFormatObj = madrigal.ui.web.MadrigalWebFormat() |
|
923 | 935 | madParmObj = madrigal.data.MadrigalParameters(madDB) |
|
924 | 936 | |
|
925 | 937 | cookieDict = request.COOKIES |
|
926 | 938 | if not 'user_fullname' in cookieDict: |
|
927 | 939 | return(HttpResponse('<p>Cookie with user_fullname required for advancedPrint</p>')) |
|
928 | 940 | user_fullname = django.utils.http.urlquote_plus(cookieDict['user_fullname']) |
|
929 | 941 | user_email = cookieDict['user_email'] |
|
930 | 942 | user_affiliation = django.utils.http.urlquote_plus(cookieDict['user_affiliation']) |
|
931 | 943 | |
|
932 | 944 | parmList = webFormatObj.getFormat('Comprehensive') |
|
933 | 945 | measParmList = [] |
|
934 | 946 | derivedParmList = [] |
|
935 | 947 | allParmList = [] |
|
936 | 948 | sureParmList = [] |
|
937 | 949 | madFileObj = madrigal.data.MadrigalFile(request.GET['fullFilename'], madDB) |
|
938 | 950 | madFileObj.getMeasDervBothParmLists(parmList, measParmList, derivedParmList, allParmList, sureParmList) |
|
939 | 951 | allParmDescList = madParmObj.getParmDescriptionList(allParmList) |
|
940 | 952 | fullFilename = request.GET['fullFilename'] |
|
941 | 953 | expName, kindatDesc = madWeb.getInfoFromFile(fullFilename) |
|
942 | 954 | |
|
943 | 955 | request.GET._mutable = True |
|
944 | 956 | request.GET['madFileObj']=madFileObj |
|
945 | 957 | request.GET['measParmList']=measParmList |
|
946 | 958 | request.GET['derivedParmList']=derivedParmList |
|
947 | 959 | request.GET['allParmList']=allParmList |
|
948 | 960 | request.GET['allParmDescList']=allParmDescList |
|
949 | 961 | request.GET['start_date'] = request.GET['start_date'].strip() |
|
950 | 962 | request.GET['end_date'] = request.GET['end_date'].strip() |
|
951 | 963 | # convert dates to datetime |
|
952 | 964 | request.GET['start_date'] = datetime.datetime.strptime(request.GET['start_date'], '%Y-%m-%dT%H:%M:%S') |
|
953 | 965 | request.GET['end_date'] = datetime.datetime.strptime(request.GET['end_date'], '%Y-%m-%dT%H:%M:%S') |
|
954 | 966 | request.GET['madDB'] = madDB |
|
955 | 967 | request.GET['madParmObj'] = madParmObj |
|
956 | 968 | |
|
957 | 969 | isprintForm = madweb.forms.IsprintForm(request.GET) |
|
958 | 970 | |
|
959 | 971 | |
|
960 | 972 | if not isprintForm.is_valid(): |
|
961 | 973 | raise ValueError(str(isprintForm.errors)) |
|
962 | 974 | |
|
963 | 975 | downloadFile = madWeb.downloadIsprintFileFromIsprintForm(isprintForm.cleaned_data, user_fullname, user_email, user_affiliation) |
|
964 | 976 | |
|
965 | 977 | f = open(downloadFile, 'r') |
|
966 | 978 | file_text = f.read() |
|
967 | 979 | f.close() |
|
968 | 980 | os.remove(downloadFile) |
|
969 | 981 | return render(request, 'madweb/advanced_print.html', {'expName': expName, 'kindatDesc': kindatDesc, |
|
970 | 982 | 'basename': os.path.basename(fullFilename), |
|
971 | 983 | 'file_text': file_text, 'bg_color': bg_color}) |
|
972 | 984 | |
|
973 | 985 | |
|
974 | 986 | def view_list(request): |
|
975 | 987 | """view_list is the list experiment view. |
|
976 | 988 | """ |
|
977 | 989 | madDB = madrigal.metadata.MadrigalDB() |
|
978 | 990 | bg_color = madDB.getBackgroundColor() |
|
979 | 991 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
980 | 992 | siteName, siteList = madWebObj.getSiteInfo() |
|
981 | 993 | responseDict = {'list_active': 'class="active"'} |
|
982 | 994 | form = madweb.forms.ListExpForm() |
|
983 | 995 | responseDict['form'] = form |
|
984 | 996 | responseDict['categoryList'] = form.categories |
|
985 | 997 | responseDict['instrumentList'] = form.instruments |
|
986 | 998 | responseDict['site_name'] = siteName |
|
987 | 999 | responseDict['site_list'] = siteList |
|
988 | 1000 | responseDict['datetime'] = True |
|
989 | 1001 | responseDict['bg_color'] = bg_color |
|
990 | 1002 | |
|
991 | 1003 | return render(request, 'madweb/list.html', responseDict) |
|
992 | 1004 | |
|
993 | 1005 | |
|
994 | 1006 | def list_experiments(request): |
|
995 | 1007 | """list_experiments is a view that lists all selected experiments. |
|
996 | 1008 | |
|
997 | 1009 | Inputs: |
|
998 | 1010 | request |
|
999 | 1011 | """ |
|
1000 | 1012 | madDB = madrigal.metadata.MadrigalDB() |
|
1001 | 1013 | bg_color = madDB.getBackgroundColor() |
|
1002 | 1014 | madWeb = madrigal.ui.web.MadrigalWeb(madDB) |
|
1003 | 1015 | siteName, siteList = madWeb.getSiteInfo() |
|
1004 | 1016 | |
|
1005 | 1017 | listForm = madweb.forms.ListExpForm(request.GET) |
|
1006 | 1018 | try: |
|
1007 | 1019 | if not listForm.is_valid(): |
|
1008 | 1020 | return(HttpResponse(str(listForm.errors))) |
|
1009 | 1021 | except KeyError: |
|
1010 | 1022 | return(HttpResponse('<p>Missing arguments in list_experiments</p>')) |
|
1011 | 1023 | |
|
1012 | 1024 | kinstList = [int(kinst) for kinst in listForm.cleaned_data['instruments']] |
|
1013 | 1025 | startDate = listForm.cleaned_data['start_date'] |
|
1014 | 1026 | startDT = datetime.datetime(startDate.year, startDate.month, startDate.day, 0, 0, 0) |
|
1015 | 1027 | endDate = listForm.cleaned_data['end_date'] |
|
1016 | 1028 | endDT = datetime.datetime(endDate.year, endDate.month, endDate.day, 23, 59, 59) |
|
1017 | 1029 | localOnly = not listForm.cleaned_data['isGlobal'] |
|
1018 | 1030 | expList = madWeb.getExperimentList(kinstList, startDT, endDT, localOnly) |
|
1019 | 1031 | |
|
1020 | 1032 | return render(request, 'madweb/list_experiments.html', {'expList':expList, 'localOnly':localOnly, |
|
1021 | 1033 | 'list_active': 'class="active"', 'site_name': siteName, |
|
1022 | 1034 | 'site_list': siteList, 'bg_color': bg_color}) |
|
1023 | 1035 | |
|
1024 | 1036 | |
|
1025 | 1037 | def show_experiment(request): |
|
1026 | 1038 | """show_experiment call that returns the experiment page to support the list experiments UI. |
|
1027 | 1039 | |
|
1028 | 1040 | Inputs: |
|
1029 | 1041 | request |
|
1030 | 1042 | """ |
|
1031 | 1043 | madDB = madrigal.metadata.MadrigalDB() |
|
1032 | 1044 | bg_color = madDB.getBackgroundColor() |
|
1033 | 1045 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
1034 | 1046 | siteName, siteList = madWebObj.getSiteInfo() |
|
1035 | 1047 | cookieDict = request.COOKIES |
|
1036 | 1048 | user_email = cookieDict['user_email'] |
|
1037 | 1049 | queryDict = request.GET.copy() |
|
1038 | 1050 | queryDict['user_email'] = user_email |
|
1039 | 1051 | if 'show_plots' in queryDict: |
|
1040 | 1052 | plotsForm = madweb.forms.SingleExpPlotsForm(queryDict) |
|
1041 | 1053 | form = madweb.forms.SingleExpFileForm(queryDict) |
|
1042 | 1054 | if 'show_plots' in queryDict: |
|
1043 | 1055 | form.fields['plot_list'] = plotsForm.fields['plot_list'] |
|
1044 | 1056 | if len(form.fields['file_list'].choices) > 1: |
|
1045 | 1057 | # this experiment has data files |
|
1046 | 1058 | return render(request, 'madweb/show_experiment.html', {'list_active': 'class="active"', |
|
1047 | 1059 | 'form': form, 'site_name': siteName, |
|
1048 | 1060 | 'site_list': siteList, |
|
1049 | 1061 | 'loader': 'loadPage', |
|
1050 | 1062 | 'bg_color': bg_color, |
|
1051 | 1063 | 'redirect': reverse('show_experiment')}) |
|
1052 | 1064 | |
|
1053 | 1065 | else: |
|
1054 | 1066 | # this experiment has no data files |
|
1055 | 1067 | form2 = madweb.forms.SingleExpPlotsForm(request.GET) |
|
1056 | 1068 | exp_desc = form.fields['exp_desc'].label |
|
1057 | 1069 | return render(request, 'madweb/show_exp_no_files.html', {'list_active': 'class="active"', |
|
1058 | 1070 | 'form': form2, 'exp_desc': exp_desc, |
|
1059 | 1071 | 'site_name': siteName, |
|
1060 | 1072 | 'site_list': siteList, |
|
1061 | 1073 | 'loader': 'loadPage', |
|
1062 | 1074 | 'bg_color': bg_color, |
|
1063 | 1075 | 'redirect': reverse('show_experiment')}) |
|
1064 | 1076 | |
|
1065 | 1077 | |
|
1066 | 1078 | def show_experiment_v2(request): |
|
1067 | 1079 | """show_experiment_v2 is a slight variant of show_experiment to accept old form |
|
1068 | 1080 | calls from Madrigal2 sites. |
|
1069 | 1081 | |
|
1070 | 1082 | Inputs: |
|
1071 | 1083 | request |
|
1072 | 1084 | """ |
|
1073 | 1085 | madDB = madrigal.metadata.MadrigalDB() |
|
1074 | 1086 | bg_color = madDB.getBackgroundColor() |
|
1075 | 1087 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
1076 | 1088 | siteName, siteList = madWebObj.getSiteInfo() |
|
1077 | 1089 | cookieDict = request.COOKIES |
|
1078 | 1090 | user_email = cookieDict['user_email'] |
|
1079 | 1091 | queryDict = request.GET.copy() |
|
1080 | 1092 | queryDict['user_email'] = user_email |
|
1081 | 1093 | queryDict['experiment_list'] = queryDict['exp'] |
|
1082 | 1094 | form = madweb.forms.SingleExpFileForm(queryDict) |
|
1083 | 1095 | |
|
1084 | 1096 | return render(request, 'madweb/show_experiment.html', {'list_active': 'class="active"', |
|
1085 | 1097 | 'form': form, 'site_name': siteName, |
|
1086 | 1098 | 'site_list': siteList, |
|
1087 | 1099 | 'loader': 'loadPage', |
|
1088 | 1100 | 'bg_color': bg_color, |
|
1089 | 1101 | 'redirect': reverse('show_experiment')}) |
|
1090 | 1102 | |
|
1091 | 1103 | |
|
1092 | 1104 | def choose_script(request): |
|
1093 | 1105 | """choose_script that returns the choose script page. |
|
1094 | 1106 | |
|
1095 | 1107 | Inputs: |
|
1096 | 1108 | request |
|
1097 | 1109 | """ |
|
1098 | 1110 | madDB = madrigal.metadata.MadrigalDB() |
|
1099 | 1111 | bg_color = madDB.getBackgroundColor() |
|
1100 | 1112 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
1101 | 1113 | siteName, siteList = madWebObj.getSiteInfo() |
|
1102 | 1114 | return render(request, 'madweb/choose_script.html', {'script_active': 'class="active"', 'site_name': siteName, |
|
1103 | 1115 | 'site_list': siteList, 'bg_color': bg_color}) |
|
1104 | 1116 | |
|
1105 | 1117 | |
|
1106 | 1118 | def download_as_is_script(request): |
|
1107 | 1119 | """download_as_is_script that returns the download_as_is_script script page. |
|
1108 | 1120 | |
|
1109 | 1121 | Inputs: |
|
1110 | 1122 | request |
|
1111 | 1123 | """ |
|
1112 | 1124 | madDB = madrigal.metadata.MadrigalDB() |
|
1113 | 1125 | bg_color = madDB.getBackgroundColor() |
|
1114 | 1126 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
1115 | 1127 | siteName, siteList = madWebObj.getSiteInfo() |
|
1116 | 1128 | responseDict = {'script_active': 'class="active"'} |
|
1117 | 1129 | form = madweb.forms.DownloadAsIsScriptForm() |
|
1118 | 1130 | responseDict['form'] = form |
|
1119 | 1131 | responseDict['categoryList'] = form.categories |
|
1120 | 1132 | responseDict['instrumentList'] = form.instruments |
|
1121 | 1133 | responseDict['kindatList'] = form.kindats |
|
1122 | 1134 | responseDict['site_name'] = siteName |
|
1123 | 1135 | responseDict['site_list'] = siteList |
|
1124 | 1136 | responseDict['datetime'] = True |
|
1125 | 1137 | responseDict['bg_color'] = bg_color |
|
1126 | 1138 | |
|
1127 | 1139 | return render(request, 'madweb/download_as_is_script.html', responseDict) |
|
1128 | 1140 | |
|
1129 | 1141 | |
|
1130 | 1142 | def generate_download_files_script(request): |
|
1131 | 1143 | """generate_download_files_script is a Ajax call that returns the generated file download script. |
|
1132 | 1144 | |
|
1133 | 1145 | Inputs: |
|
1134 | 1146 | request |
|
1135 | 1147 | """ |
|
1136 | 1148 | form = madweb.forms.DownloadAsIsScriptForm(request.GET) |
|
1137 | 1149 | if not form.is_valid(): |
|
1138 | 1150 | raise ValueError('Form error: %s' % (form.errors)) |
|
1139 | 1151 | cookieDict = request.COOKIES |
|
1140 | 1152 | if not 'user_fullname' in cookieDict: |
|
1141 | 1153 | return(HttpResponse('<p>Cookie with user_fullname required for generateDownloadFilesScript</p>')) |
|
1142 | 1154 | user_fullname = django.utils.http.urlquote_plus(cookieDict['user_fullname']) |
|
1143 | 1155 | user_email = cookieDict['user_email'] |
|
1144 | 1156 | user_affiliation = django.utils.http.urlquote_plus(cookieDict['user_affiliation']) |
|
1145 | 1157 | madWebObj = madrigal.ui.web.MadrigalWeb() |
|
1146 | 1158 | script_text = madWebObj.generateDownloadFileScriptFromForm(form.cleaned_data, user_fullname, |
|
1147 | 1159 | user_email, user_affiliation) |
|
1148 | 1160 | return render(request, 'madweb/download_files_script.html', {'script_text': script_text}) |
|
1149 | 1161 | |
|
1150 | 1162 | |
|
1151 | 1163 | def download_advanced_script(request): |
|
1152 | 1164 | """download_advanced_script that returns the download_advanced_script script page. |
|
1153 | 1165 | |
|
1154 | 1166 | Inputs: |
|
1155 | 1167 | request |
|
1156 | 1168 | """ |
|
1157 | 1169 | madDB = madrigal.metadata.MadrigalDB() |
|
1158 | 1170 | bg_color = madDB.getBackgroundColor() |
|
1159 | 1171 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
1160 | 1172 | siteName, siteList = madWebObj.getSiteInfo() |
|
1161 | 1173 | responseDict = {'script_active': 'class="active"'} |
|
1162 | 1174 | form = madweb.forms.DownloadAdvancedScriptForm() |
|
1163 | 1175 | responseDict['form'] = form |
|
1164 | 1176 | responseDict['categoryList'] = form.categories |
|
1165 | 1177 | responseDict['instrumentList'] = form.instruments |
|
1166 | 1178 | responseDict['kindatList'] = form.kindats |
|
1167 | 1179 | responseDict['site_name'] = siteName |
|
1168 | 1180 | responseDict['site_list'] = siteList |
|
1169 | 1181 | responseDict['datetime'] = True |
|
1170 | 1182 | responseDict['bg_color'] = bg_color |
|
1171 | 1183 | |
|
1172 | 1184 | return render(request, 'madweb/download_advanced_script.html', responseDict) |
|
1173 | 1185 | |
|
1174 | 1186 | |
|
1175 | 1187 | def generate_download_advanced_script(request): |
|
1176 | 1188 | """generate_download_advanced_script is a Ajax call that returns the generated advanced download script. |
|
1177 | 1189 | |
|
1178 | 1190 | Inputs: |
|
1179 | 1191 | request |
|
1180 | 1192 | """ |
|
1181 | 1193 | form1 = madweb.forms.DownloadAdvancedScriptForm(request.GET) |
|
1182 | 1194 | if not form1.is_valid(): |
|
1183 | 1195 | raise ValueError('Form error: %s' % (form1.errors)) |
|
1184 | 1196 | form2 = madweb.forms.AdvScriptParmsForm(request.GET) |
|
1185 | 1197 | if not form2.is_valid(): |
|
1186 | 1198 | raise ValueError('Form error: %s' % (form2.errors)) |
|
1187 | 1199 | form3 = madweb.forms.AdvScriptParmsFiltersForm(request.GET) |
|
1188 | 1200 | if not form3.is_valid(): |
|
1189 | 1201 | raise ValueError('Form error: %s' % (form3.errors)) |
|
1190 | 1202 | cookieDict = request.COOKIES |
|
1191 | 1203 | if not 'user_fullname' in cookieDict: |
|
1192 | 1204 | return(HttpResponse('<p>Cookie with user_fullname required for generateAdvancedDownloadScript</p>')) |
|
1193 | 1205 | user_fullname = django.utils.http.urlquote_plus(cookieDict['user_fullname']) |
|
1194 | 1206 | user_email = cookieDict['user_email'] |
|
1195 | 1207 | user_affiliation = django.utils.http.urlquote_plus(cookieDict['user_affiliation']) |
|
1196 | 1208 | madWebObj = madrigal.ui.web.MadrigalWeb() |
|
1197 | 1209 | script_text = madWebObj.generateGlobalIsprintScriptFromForm(form1.cleaned_data, form2.cleaned_data, |
|
1198 | 1210 | form3.cleaned_data, user_fullname, |
|
1199 | 1211 | user_email, user_affiliation) |
|
1200 | 1212 | return render(request, 'madweb/download_files_script.html', {'script_text': script_text}) |
|
1201 | 1213 | |
|
1202 | 1214 | |
|
1203 | 1215 | def generate_parms_script(request): |
|
1204 | 1216 | """generate_parms_script is a Ajax call that returns the generated parameter script. |
|
1205 | 1217 | |
|
1206 | 1218 | Inputs: |
|
1207 | 1219 | request |
|
1208 | 1220 | """ |
|
1209 | 1221 | form = madweb.forms.AdvScriptParmsForm(request.GET) |
|
1210 | 1222 | return render(request, 'madweb/download_adv_parms_script.html', {'form': form, |
|
1211 | 1223 | 'parmList': form.parmList}) |
|
1212 | 1224 | |
|
1213 | 1225 | |
|
1214 | 1226 | def generate_parms_filters_script(request): |
|
1215 | 1227 | """generate_parms_filters_script is a Ajax call that returns the generated parameter filters script. |
|
1216 | 1228 | |
|
1217 | 1229 | Inputs: |
|
1218 | 1230 | request |
|
1219 | 1231 | """ |
|
1220 | 1232 | form = madweb.forms.AdvScriptParmsFiltersForm(request.GET) |
|
1221 | 1233 | return render(request, 'madweb/download_adv_parms_filters_script.html', {'form': form}) |
|
1222 | 1234 | |
|
1223 | 1235 | |
|
1224 | 1236 | def ftp(request): |
|
1225 | 1237 | """ftp creates the first ftp page listing instruments |
|
1226 | 1238 | """ |
|
1227 | 1239 | madDB = madrigal.metadata.MadrigalDB() |
|
1228 | 1240 | bg_color = madDB.getBackgroundColor() |
|
1229 | 1241 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
1230 | 1242 | siteName, siteList = madWebObj.getSiteInfo() |
|
1231 | 1243 | cookieDict = request.COOKIES |
|
1232 | 1244 | if not 'user_fullname' in cookieDict: |
|
1233 | 1245 | return(HttpResponse('<p>Cookie with user_fullname required for ftp</p>')) |
|
1234 | 1246 | fullname = django.utils.http.urlquote_plus(cookieDict['user_fullname']) |
|
1235 | 1247 | email = cookieDict['user_email'] |
|
1236 | 1248 | affiliation = django.utils.http.urlquote_plus(cookieDict['user_affiliation']) |
|
1237 | 1249 | # create instrument with data list with tuple (instrument_name, kinst) |
|
1238 | 1250 | madInstDataObj = madrigal.metadata.MadrigalInstrumentData(madDB) |
|
1239 | 1251 | madInstList = [(instrument_name, kinst) for kinst, instrument_name, site_id in madInstDataObj.getInstruments(local=True)] |
|
1240 | 1252 | return render(request, 'madweb/ftp_instruments.html', {'madInstList': madInstList, 'fullname': fullname, |
|
1241 | 1253 | 'email': email, 'affiliation':affiliation, 'site_name': siteName, |
|
1242 | 1254 | 'site_list': siteList, 'bg_color': bg_color}) |
|
1243 | 1255 | |
|
1244 | 1256 | |
|
1245 | 1257 | def ftp_instrument(request, fullname, email, affiliation, kinst): |
|
1246 | 1258 | """ftp_instrument creates the first ftp instrument page listing years |
|
1247 | 1259 | Inputs: kinst selected |
|
1248 | 1260 | """ |
|
1249 | 1261 | kinst = int(kinst) |
|
1250 | 1262 | madDB = madrigal.metadata.MadrigalDB() |
|
1251 | 1263 | bg_color = madDB.getBackgroundColor() |
|
1252 | 1264 | madInstDataObj = madrigal.metadata.MadrigalInstrumentData(madDB) |
|
1253 | 1265 | madInstObj = madrigal.metadata.MadrigalInstrument(madDB) |
|
1254 | 1266 | inst_name = madInstObj.getInstrumentName(kinst) |
|
1255 | 1267 | yearList = madInstDataObj.getInstrumentYears(kinst) |
|
1256 | 1268 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
1257 | 1269 | siteName, siteList = madWebObj.getSiteInfo() |
|
1258 | 1270 | return render(request, 'madweb/ftp_years.html',{'yearList':yearList, 'kinst':kinst, |
|
1259 | 1271 | 'inst_name':inst_name, 'fullname': fullname, |
|
1260 | 1272 | 'email': email, 'affiliation':affiliation, |
|
1261 | 1273 | 'site_name': siteName, 'site_list': siteList, |
|
1262 | 1274 | 'bg_color': bg_color }) |
|
1263 | 1275 | |
|
1264 | 1276 | |
|
1265 | 1277 | def ftp_year(request, fullname, email, affiliation, kinst, year): |
|
1266 | 1278 | """ftp_year creates the first ftp year page listing kindats |
|
1267 | 1279 | Inputs: kinst selected, year selected |
|
1268 | 1280 | """ |
|
1269 | 1281 | kinst = int(kinst) |
|
1270 | 1282 | year = int(year) |
|
1271 | 1283 | madDB = madrigal.metadata.MadrigalDB() |
|
1272 | 1284 | bg_color = madDB.getBackgroundColor() |
|
1273 | 1285 | madInstObj = madrigal.metadata.MadrigalInstrument(madDB) |
|
1274 | 1286 | inst_name = madInstObj.getInstrumentName(kinst) |
|
1275 | 1287 | madInstKindatObj = madrigal.metadata.MadrigalInstrumentKindats(madDB) |
|
1276 | 1288 | kindatList = madInstKindatObj.getKindatListForInstrumentYear(kinst, year) |
|
1277 | 1289 | madKindatObj = madrigal.metadata.MadrigalKindat(madDB) |
|
1278 | 1290 | # create kindatDescList, a list of tuples of (kindat_desc, kindat) for that kinst, year |
|
1279 | 1291 | kindatDescList = [] |
|
1280 | 1292 | for kindat in kindatList: |
|
1281 | 1293 | kindatDescList.append((madKindatObj.getKindatDescription(kindat, kinst), kindat)) |
|
1282 | 1294 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
1283 | 1295 | siteName, siteList = madWebObj.getSiteInfo() |
|
1284 | 1296 | return render(request, 'madweb/ftp_kindats.html', {'kindatDescList': kindatDescList, 'year': year, |
|
1285 | 1297 | 'kinst': kinst, 'inst_name':inst_name, 'fullname': fullname, |
|
1286 | 1298 | 'email': email, 'affiliation':affiliation, |
|
1287 | 1299 | 'site_name': siteName, 'site_list': siteList, |
|
1288 | 1300 | 'bg_color': bg_color }) |
|
1289 | 1301 | |
|
1290 | 1302 | |
|
1291 | 1303 | def ftp_kindat(request, fullname, email, affiliation, kinst, year, kindat): |
|
1292 | 1304 | """ftp_kindat creates the first ftp format page listing formats to choose from |
|
1293 | 1305 | Inputs: kinst selected, year selected, kindat selected |
|
1294 | 1306 | """ |
|
1295 | 1307 | kinst = int(kinst) |
|
1296 | 1308 | kindat = int(kindat) |
|
1297 | 1309 | madDB = madrigal.metadata.MadrigalDB() |
|
1298 | 1310 | bg_color = madDB.getBackgroundColor() |
|
1299 | 1311 | madKindatObj = madrigal.metadata.MadrigalKindat(madDB) |
|
1300 | 1312 | kindat_desc = madKindatObj.getKindatDescription(kindat, kinst) |
|
1301 | 1313 | madInstObj = madrigal.metadata.MadrigalInstrument(madDB) |
|
1302 | 1314 | inst_name = madInstObj.getInstrumentName(kinst) |
|
1303 | 1315 | formatDescList = [(formatDict[key], key) for key in list(formatDict.keys())] |
|
1304 | 1316 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
1305 | 1317 | siteName, siteList = madWebObj.getSiteInfo() |
|
1306 | 1318 | return render(request, 'madweb/ftp_formats.html', {'formatDescList': formatDescList, 'year': year, |
|
1307 | 1319 | 'kinst': kinst, 'inst_name': inst_name, 'kindat': kindat, |
|
1308 | 1320 | 'kindat_desc': kindat_desc, 'fullname': fullname, |
|
1309 | 1321 | 'email': email, 'affiliation': affiliation, |
|
1310 | 1322 | 'site_name': siteName, 'site_list': siteList, |
|
1311 | 1323 | 'bg_color': bg_color } ) |
|
1312 | 1324 | |
|
1313 | 1325 | |
|
1314 | 1326 | def ftp_files(request, fullname, email, affiliation, kinst, year, kindat, format): |
|
1315 | 1327 | """ftp_files creates the ftp files page listing individual files |
|
1316 | 1328 | Inputs: kinst selected, year selected, kindat selected |
|
1317 | 1329 | """ |
|
1318 | 1330 | kinst = int(kinst) |
|
1319 | 1331 | year = int(year) |
|
1320 | 1332 | dt = datetime.datetime(year,1,1) # speed up search |
|
1321 | 1333 | kindat = int(kindat) |
|
1322 | 1334 | if format not in ('hdf5', 'netCDF4', 'ascii'): |
|
1323 | 1335 | raise ValueError('Unknown format %s' % (format)) |
|
1324 | 1336 | if format == 'netCDF4': |
|
1325 | 1337 | thisExt = '.nc' |
|
1326 | 1338 | elif format == 'ascii': |
|
1327 | 1339 | thisExt = '.txt' |
|
1328 | 1340 | format_desc = formatDict[format] |
|
1329 | 1341 | # create a list of full names, where each item is a tuple of |
|
1330 | 1342 | # (fullFilename in Madrigal, output basename with correct extension, date string) |
|
1331 | 1343 | fileList = [] |
|
1332 | 1344 | madDB = madrigal.metadata.MadrigalDB() |
|
1333 | 1345 | bg_color = madDB.getBackgroundColor() |
|
1334 | 1346 | madKindatObj = madrigal.metadata.MadrigalKindat(madDB) |
|
1335 | 1347 | kindat_desc = madKindatObj.getKindatDescription(kindat, kinst) |
|
1336 | 1348 | madInstObj = madrigal.metadata.MadrigalInstrument(madDB) |
|
1337 | 1349 | inst_name = madInstObj.getInstrumentName(kinst) |
|
1338 | 1350 | pi = madInstObj.getContactName(kinst) |
|
1339 | 1351 | pi_email = madInstObj.getContactEmail(kinst) |
|
1340 | 1352 | madExpObj = madrigal.metadata.MadrigalExperiment(madDB) |
|
1341 | 1353 | startIndex = madExpObj.getStartPosition(dt) + 1 |
|
1342 | 1354 | for loop in (0,1): |
|
1343 | 1355 | # we normally only loop once, but sometimes multi-year experiments require a slow full search |
|
1344 | 1356 | if loop == 0: |
|
1345 | 1357 | thisStartIndex = startIndex |
|
1346 | 1358 | else: |
|
1347 | 1359 | thisStartIndex = 0 # should only get to this case for rare multi-year experiments |
|
1348 | 1360 | for i in range(thisStartIndex, madExpObj.getExpCount()): |
|
1349 | 1361 | if kinst != madExpObj.getKinstByPosition(i): |
|
1350 | 1362 | continue |
|
1351 | 1363 | stTuple = madExpObj.getExpStartDateTimeByPosition(i)[0:6] |
|
1352 | 1364 | etTuple = madExpObj.getExpEndDateTimeByPosition(i)[0:6] |
|
1353 | 1365 | expTitle = madExpObj.getExpNameByPosition(i) |
|
1354 | 1366 | sDT = datetime.datetime(*stTuple) |
|
1355 | 1367 | eDT = datetime.datetime(*etTuple) |
|
1356 | 1368 | if sDT.year > year: |
|
1357 | 1369 | break |
|
1358 | 1370 | if eDT.year < year: |
|
1359 | 1371 | continue |
|
1360 | 1372 | dateStr = ' From %s to %s: %s' % (sDT.strftime('%Y-%m-%d %H:%M:%S'), eDT.strftime('%Y-%m-%d %H:%M:%S'), str(expTitle)) |
|
1361 | 1373 | expDir = madExpObj.getExpDirByPosition(i) |
|
1362 | 1374 | # look at this exp for the right kindat |
|
1363 | 1375 | try: |
|
1364 | 1376 | madFileObj = madrigal.metadata.MadrigalMetaFile(madDB, os.path.join(expDir, 'fileTab.txt')) |
|
1365 | 1377 | except: |
|
1366 | 1378 | pass |
|
1367 | 1379 | for j in range(madFileObj.getFileCount()): |
|
1368 | 1380 | if madFileObj.getCategoryByPosition(j) not in (0,1): |
|
1369 | 1381 | # skip history and alternate files |
|
1370 | 1382 | continue |
|
1371 | 1383 | if madFileObj.getKindatByPosition(j) != kindat: |
|
1372 | 1384 | continue |
|
1373 | 1385 | statusStr = ' : %s' % (str(madFileObj.getStatusByPosition(j))) |
|
1374 | 1386 | fullFilename = os.path.join(expDir, madFileObj.getFilenameByPosition(j)) |
|
1375 | 1387 | fullBasename = os.path.basename(fullFilename) |
|
1376 | 1388 | if format != 'hdf5': |
|
1377 | 1389 | base, file_extension = os.path.splitext(fullFilename) |
|
1378 | 1390 | basename = os.path.basename(base + thisExt) |
|
1379 | 1391 | else: |
|
1380 | 1392 | basename = os.path.basename(fullFilename) |
|
1381 | 1393 | # make sure this file isn't too big to create a cache |
|
1382 | 1394 | file_size = os.path.getsize(fullFilename) |
|
1383 | 1395 | if file_size > maxSize and format != 'hdf5': |
|
1384 | 1396 | # make sure cached file exists before adding |
|
1385 | 1397 | if format == 'netCDF4': |
|
1386 | 1398 | cachedFile = os.path.join(expDir, 'overview', fullBasename + thisExt) |
|
1387 | 1399 | else: |
|
1388 | 1400 | cachedFile = os.path.join(expDir, 'overview', fullBasename + thisExt + '.gz') |
|
1389 | 1401 | if not os.path.exists(cachedFile): |
|
1390 | 1402 | continue |
|
1391 | 1403 | fileList.append((urllib.parse.quote_plus(fullFilename), basename, dateStr + statusStr)) |
|
1392 | 1404 | |
|
1393 | 1405 | if len(fileList) > 0: |
|
1394 | 1406 | break # usually we avoid the slow full loop |
|
1395 | 1407 | |
|
1396 | 1408 | |
|
1397 | 1409 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
1398 | 1410 | siteName, siteList = madWebObj.getSiteInfo() |
|
1399 | 1411 | |
|
1400 | 1412 | return render(request, 'madweb/ftp_files.html', {'fullFilenames': fileList, 'year': year, 'kindat_desc': kindat_desc, |
|
1401 | 1413 | 'kinst': kinst, 'inst_name':inst_name, 'fullname': fullname, |
|
1402 | 1414 | 'kindat': kindat, 'format': format, 'format_desc': format_desc, |
|
1403 | 1415 | 'email': email, 'affiliation':affiliation, |
|
1404 | 1416 | 'site_name': siteName, 'site_list': siteList, |
|
1405 | 1417 | 'pi_email': pi_email, 'pi_name': pi, |
|
1406 | 1418 | 'bg_color': bg_color}) |
|
1407 | 1419 | |
|
1408 | 1420 | |
|
1409 | 1421 | def ftp_download(request, user_fullname, user_email, user_affiliation, kinst, year, kindat, format, fullHdf5Filename): |
|
1410 | 1422 | """ftp_download creates the first ftp kindat page listing individual files |
|
1411 | 1423 | Inputs: kinst selected, year selected, kindat selected |
|
1412 | 1424 | """ |
|
1413 | 1425 | madDB = madrigal.metadata.MadrigalDB() |
|
1414 | 1426 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
1415 | 1427 | user_fullname = urllib.parse.unquote_plus(user_fullname) |
|
1416 | 1428 | user_affiliation = urllib.parse.unquote_plus(user_affiliation) |
|
1417 | 1429 | fullHdf5Filename = urllib.parse.unquote_plus(fullHdf5Filename) |
|
1418 | 1430 | fullFilename = madWebObj.downloadFullFileAsIs(fullHdf5Filename, format, user_fullname, user_email, user_affiliation) |
|
1419 | 1431 | |
|
1420 | 1432 | f = open(fullFilename, 'rb') |
|
1421 | 1433 | filename = os.path.basename(fullFilename) |
|
1422 | 1434 | chunk_size = 8192 |
|
1423 | 1435 | file_type = mimetypes.guess_type(fullFilename)[0] |
|
1424 | 1436 | if file_type is None: |
|
1425 | 1437 | file_type = 'application/octet-stream' |
|
1426 | 1438 | response = StreamingHttpResponse(FileWrapper(f, chunk_size), |
|
1427 | 1439 | content_type=file_type) |
|
1428 | 1440 | response['Content-Length'] = os.path.getsize(fullFilename) |
|
1429 | 1441 | response['Content-Disposition'] = "attachment; filename=%s" % (filename) |
|
1430 | 1442 | return(response) |
|
1431 | 1443 | |
|
1432 | 1444 | |
|
1433 | 1445 | @csrf_exempt |
|
1434 | 1446 | def ftp_multiple_download(request): |
|
1435 | 1447 | """ftp_download creates the first ftp kindat page listing individual files |
|
1436 | 1448 | Inputs: kinst selected, year selected, kindat selected |
|
1437 | 1449 | """ |
|
1438 | 1450 | if request.method == 'POST': |
|
1439 | 1451 | reqDict = request.POST |
|
1440 | 1452 | else: |
|
1441 | 1453 | reqDict = request.GET |
|
1442 | 1454 | madDB = madrigal.metadata.MadrigalDB() |
|
1443 | 1455 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
1444 | 1456 | user_fullname = urllib.parse.unquote_plus(reqDict.get('user_fullname')) |
|
1445 | 1457 | user_email = reqDict.get('user_email') |
|
1446 | 1458 | user_affiliation = urllib.parse.unquote_plus(reqDict.get('user_affiliation')) |
|
1447 | 1459 | format = reqDict.get('format') |
|
1448 | 1460 | fileList = reqDict.getlist('fullFilename') |
|
1449 | 1461 | fileList = [urllib.parse.unquote_plus(filename) for filename in fileList] |
|
1450 | 1462 | if len(fileList) > 10: |
|
1451 | 1463 | # send user an email with warning |
|
1452 | 1464 | tmpDir = os.path.join(madDB.getMadroot(), 'experiments/stage') |
|
1453 | 1465 | fullFilename = os.path.join(tmpDir, 'result_error_%06i.txt' % (random.randint(0,999999))) |
|
1454 | 1466 | f = open(fullFilename, 'w') |
|
1455 | 1467 | f.write('Error - you requested %i files, maximum is 10\n' % (len(fileList))) |
|
1456 | 1468 | f.close() |
|
1457 | 1469 | else: |
|
1458 | 1470 | fullFilename = madWebObj.downloadMultipleFiles(fileList, format, user_fullname, user_email, user_affiliation) |
|
1459 | 1471 | |
|
1460 | 1472 | f = open(fullFilename, 'rb') |
|
1461 | 1473 | filename = os.path.basename(fullFilename) |
|
1462 | 1474 | chunk_size = 8192 |
|
1463 | 1475 | file_type = mimetypes.guess_type(fullFilename)[0] |
|
1464 | 1476 | if file_type is None: |
|
1465 | 1477 | file_type = 'application/octet-stream' |
|
1466 | 1478 | response = StreamingHttpResponse(FileWrapper(f, chunk_size), |
|
1467 | 1479 | content_type=file_type) |
|
1468 | 1480 | response['Content-Length'] = os.path.getsize(fullFilename) |
|
1469 | 1481 | response['Content-Disposition'] = "attachment; filename=%s" % (filename) |
|
1470 | 1482 | return(response) |
|
1471 | 1483 | |
|
1472 | 1484 | |
|
1473 | 1485 | def instrument_metadata(request): |
|
1474 | 1486 | """instrument_metadata returns the instrument_metadata page. |
|
1475 | 1487 | |
|
1476 | 1488 | Inputs: |
|
1477 | 1489 | request |
|
1478 | 1490 | """ |
|
1479 | 1491 | # create a list of tuples of (kinst, name, category, latitude, longitude, altitude, pi, pi_email, mnemonic) |
|
1480 | 1492 | madDB = madrigal.metadata.MadrigalDB() |
|
1481 | 1493 | bg_color = madDB.getBackgroundColor() |
|
1482 | 1494 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
1483 | 1495 | siteName, siteList = madWebObj.getSiteInfo() |
|
1484 | 1496 | madInstObj = madrigal.metadata.MadrigalInstrument(madDB) |
|
1485 | 1497 | instList = [] |
|
1486 | 1498 | for name, mnemonic, kinst, category, catID in madInstObj.getOrderedInstrumentList(): |
|
1487 | 1499 | latitude = madInstObj.getLatitude(kinst) |
|
1488 | 1500 | longitude = madInstObj.getLongitude(kinst) |
|
1489 | 1501 | altitude = madInstObj.getAltitude(kinst) |
|
1490 | 1502 | pi = madInstObj.getContactName(kinst) |
|
1491 | 1503 | pi_email = madInstObj.getContactEmail(kinst) |
|
1492 | 1504 | instList.append((kinst, name, category, latitude, longitude, altitude, pi, pi_email, mnemonic)) |
|
1493 | 1505 | |
|
1494 | 1506 | responseDict = {'inst_active': 'class="active"', 'instList': instList, |
|
1495 | 1507 | 'site_name': siteName, 'site_list': siteList, 'bg_color': bg_color} |
|
1496 | 1508 | return render(request, 'madweb/instrument_metadata.html', responseDict) |
|
1497 | 1509 | |
|
1498 | 1510 | |
|
1499 | 1511 | def site_metadata(request): |
|
1500 | 1512 | """site_metadata returns the site_metadata page. |
|
1501 | 1513 | |
|
1502 | 1514 | Inputs: |
|
1503 | 1515 | request |
|
1504 | 1516 | """ |
|
1505 | 1517 | # create a list of tuples of (siteId, name, url, contact, contact email, version) |
|
1506 | 1518 | madDB = madrigal.metadata.MadrigalDB() |
|
1507 | 1519 | bg_color = madDB.getBackgroundColor() |
|
1508 | 1520 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
1509 | 1521 | siteName, otherSiteList = madWebObj.getSiteInfo() |
|
1510 | 1522 | madSiteObj = madrigal.metadata.MadrigalSite(madDB) |
|
1511 | 1523 | siteList = [] |
|
1512 | 1524 | for siteId, siteName in madSiteObj.getSiteList(): |
|
1513 | 1525 | if madSiteObj.getSiteServer(siteId).find('http') == -1: |
|
1514 | 1526 | url = 'http://' + os.path.join(madSiteObj.getSiteServer(siteId), |
|
1515 | 1527 | madSiteObj.getSiteDocRoot(siteId)) |
|
1516 | 1528 | else: |
|
1517 | 1529 | url = os.path.join(madSiteObj.getSiteServer(siteId), |
|
1518 | 1530 | madSiteObj.getSiteDocRoot(siteId)) |
|
1519 | 1531 | contact = madSiteObj.getSiteContactName(siteId) |
|
1520 | 1532 | contact_email = madSiteObj.getSiteEmail(siteId) |
|
1521 | 1533 | version = madSiteObj.getSiteVersion(siteId) |
|
1522 | 1534 | siteList.append((siteId, siteName, url, contact, contact_email, version)) |
|
1523 | 1535 | |
|
1524 | 1536 | responseDict = {'site_active': 'class="active"', 'siteList': siteList, |
|
1525 | 1537 | 'site_name': siteName, 'site_list': otherSiteList, 'bg_color': bg_color} |
|
1526 | 1538 | return render(request, 'madweb/site_metadata.html', responseDict) |
|
1527 | 1539 | |
|
1528 | 1540 | |
|
1529 | 1541 | def parameter_metadata(request): |
|
1530 | 1542 | """parameter_metadata returns the site_metadata page. |
|
1531 | 1543 | |
|
1532 | 1544 | Inputs: |
|
1533 | 1545 | request |
|
1534 | 1546 | """ |
|
1535 | 1547 | madDB = madrigal.metadata.MadrigalDB() |
|
1536 | 1548 | bg_color = madDB.getBackgroundColor() |
|
1537 | 1549 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
1538 | 1550 | siteName, siteList = madWebObj.getSiteInfo() |
|
1539 | 1551 | madParmObj = madrigal.data.MadrigalParameters(madDB) |
|
1540 | 1552 | madParmCatObj = madrigal.metadata.MadrigalParmCategory(madDB) |
|
1541 | 1553 | parmDict = {} # key is category string, value is list of category tuples (mnemonic, description, units, code) |
|
1542 | 1554 | parmList = [] # list of tuples, each tuple either a single category, or (mnemonic, description, units, code) |
|
1543 | 1555 | categoryList = [] |
|
1544 | 1556 | categoryUrlList = [] |
|
1545 | 1557 | for mnemonic in madParmObj.getSortedMnemonicList(): |
|
1546 | 1558 | description = madParmObj.getSimpleParmDescription(mnemonic) |
|
1547 | 1559 | units = madParmObj.getParmUnits(mnemonic) |
|
1548 | 1560 | code = madParmObj.getParmCodeFromMnemonic(mnemonic) |
|
1549 | 1561 | category = madParmObj.getParmCategory(mnemonic) |
|
1550 | 1562 | if category is None: |
|
1551 | 1563 | # deprecated prolog parm |
|
1552 | 1564 | continue |
|
1553 | 1565 | if category in list(parmDict.keys()): |
|
1554 | 1566 | parmDict[category].append((mnemonic, description, units, code)) |
|
1555 | 1567 | else: |
|
1556 | 1568 | parmDict[category] = [(mnemonic, description, units, code)] |
|
1557 | 1569 | |
|
1558 | 1570 | # now loop through all categories |
|
1559 | 1571 | for thisCategory, catId in madParmCatObj.getCategoryList(): |
|
1560 | 1572 | parmList.append((thisCategory,)) |
|
1561 | 1573 | categoryList.append(thisCategory) |
|
1562 | 1574 | categoryAnchor = thisCategory.replace(' ','_') |
|
1563 | 1575 | categoryUrlList.append('<a href="#%s">%s</a>' % (categoryAnchor, thisCategory)) |
|
1564 | 1576 | for values in parmDict[thisCategory]: |
|
1565 | 1577 | parmList.append(values) |
|
1566 | 1578 | |
|
1567 | 1579 | responseDict = {'parm_active': 'class="active"', 'parmList': parmList, |
|
1568 | 1580 | 'categoryUrlList':categoryUrlList, |
|
1569 | 1581 | 'site_name': siteName, 'site_list': siteList, 'bg_color': bg_color} |
|
1570 | 1582 | return render(request, 'madweb/parameter_metadata.html', responseDict) |
|
1571 | 1583 | |
|
1572 | 1584 | |
|
1573 | 1585 | def kindat_metadata(request): |
|
1574 | 1586 | """kindat_metadata returns the kindat_metadata page. |
|
1575 | 1587 | |
|
1576 | 1588 | Inputs: |
|
1577 | 1589 | request |
|
1578 | 1590 | """ |
|
1579 | 1591 | # create a list of tuples of (kindat, description, kinst, instrument_name) |
|
1580 | 1592 | madDB = madrigal.metadata.MadrigalDB() |
|
1581 | 1593 | bg_color = madDB.getBackgroundColor() |
|
1582 | 1594 | madKindatObj = madrigal.metadata.MadrigalKindat(madDB) |
|
1583 | 1595 | madInstObj = madrigal.metadata.MadrigalInstrument(madDB) |
|
1584 | 1596 | madInstKindatObj = madrigal.metadata.MadrigalInstrumentKindats(madDB) |
|
1585 | 1597 | # create a dict of key = kindat code, value list of associated instruments |
|
1586 | 1598 | kindatDict = {} |
|
1587 | 1599 | for name, mnem, kinst in madInstObj.getInstrumentList(): |
|
1588 | 1600 | thisKindatList = madInstKindatObj.getKindatListForInstruments(kinst) |
|
1589 | 1601 | for kindat in thisKindatList: |
|
1590 | 1602 | if kindat not in kindatDict: |
|
1591 | 1603 | kindatDict[kindat] = [kinst] |
|
1592 | 1604 | else: |
|
1593 | 1605 | kindatDict[kindat].append(kinst) |
|
1594 | 1606 | |
|
1595 | 1607 | kindatList = [] |
|
1596 | 1608 | for description, code_str in madKindatObj.getKindatList(): |
|
1597 | 1609 | try: |
|
1598 | 1610 | kinst, kindat = code_str.split('_') |
|
1599 | 1611 | instName = madInstObj.getInstrumentName(int(kinst)) |
|
1600 | 1612 | except: |
|
1601 | 1613 | kindat = code_str |
|
1602 | 1614 | try: |
|
1603 | 1615 | kinst = str(kindatDict[int(kindat)][0]) |
|
1604 | 1616 | instName = madInstObj.getInstrumentName(int(kinst)) |
|
1605 | 1617 | except KeyError: |
|
1606 | 1618 | kinst = '-' |
|
1607 | 1619 | instName = 'Unspecified' |
|
1608 | 1620 | kindatList.append((kindat, description, kinst, instName)) |
|
1609 | 1621 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
1610 | 1622 | siteName, siteList = madWebObj.getSiteInfo() |
|
1611 | 1623 | |
|
1612 | 1624 | responseDict = {'kindat_active': 'class="active"', 'kindatList': kindatList, |
|
1613 | 1625 | 'site_name': siteName, 'site_list': siteList, 'bg_color': bg_color} |
|
1614 | 1626 | return render(request, 'madweb/kindat_metadata.html', responseDict) |
|
1615 | 1627 | |
|
1616 | 1628 | |
|
1617 | 1629 | def madrigal_calculator(request): |
|
1618 | 1630 | """madrigal_calculator returns the Madrigal Calculator page. |
|
1619 | 1631 | |
|
1620 | 1632 | Inputs: |
|
1621 | 1633 | request |
|
1622 | 1634 | """ |
|
1623 | 1635 | madDB = madrigal.metadata.MadrigalDB() |
|
1624 | 1636 | bg_color = madDB.getBackgroundColor() |
|
1625 | 1637 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
1626 | 1638 | siteName, siteList = madWebObj.getSiteInfo() |
|
1627 | 1639 | # original blank form |
|
1628 | 1640 | madCalculatorForm = madweb.forms.MadCalculatorForm() |
|
1629 | 1641 | parmList = [(parm, madCalculatorForm.parmDescDict[parm]) for parm in list(madCalculatorForm.parmDescDict.keys())] |
|
1630 | 1642 | return render(request, 'madweb/madrigal_calculator.html', {'madCalculator_active': 'class="active"', |
|
1631 | 1643 | 'form': madCalculatorForm, |
|
1632 | 1644 | 'parmList': parmList, |
|
1633 | 1645 | 'site_name': siteName, 'site_list': siteList, |
|
1634 | 1646 | 'bg_color': bg_color, 'datetime': True}) |
|
1635 | 1647 | |
|
1636 | 1648 | def madrigal_calculator_output(request): |
|
1637 | 1649 | """madrigal_calculator returns the output from the Madrigal Calculator page. |
|
1638 | 1650 | |
|
1639 | 1651 | Inputs: |
|
1640 | 1652 | request |
|
1641 | 1653 | """ |
|
1642 | 1654 | madDB = madrigal.metadata.MadrigalDB() |
|
1643 | 1655 | bg_color = madDB.getBackgroundColor() |
|
1644 | 1656 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
1645 | 1657 | siteName, siteList = madWebObj.getSiteInfo() |
|
1646 | 1658 | |
|
1647 | 1659 | madCalculatorForm = madweb.forms.MadCalculatorForm(request.GET) |
|
1648 | 1660 | |
|
1649 | 1661 | try: |
|
1650 | 1662 | if not madCalculatorForm.is_valid(): |
|
1651 | 1663 | return(HttpResponse(str(madCalculatorForm.errors))) |
|
1652 | 1664 | except KeyError: |
|
1653 | 1665 | return(HttpResponse('<p>Missing arguments in madCalculatorOutput</p>')) |
|
1654 | 1666 | |
|
1655 | 1667 | text = madWebObj.runMadrigalCalculatorFromForm(madCalculatorForm.cleaned_data) |
|
1656 | 1668 | |
|
1657 | 1669 | return render(request, 'madweb/madrigal_calculator_output.html', {'madCalculator_active': 'class="active"', |
|
1658 | 1670 | 'text': text, |
|
1659 | 1671 | 'site_name': siteName, 'site_list': siteList, |
|
1660 | 1672 | 'bg_color': bg_color}) |
|
1661 | 1673 | |
|
1662 | 1674 | |
|
1663 | 1675 | def get_metadata(request): |
|
1664 | 1676 | """get_metadata allows local metadata files to be downloaded. |
|
1665 | 1677 | |
|
1666 | 1678 | Inputs: |
|
1667 | 1679 | request |
|
1668 | 1680 | """ |
|
1669 | 1681 | fileDict = {'0':'expTab.txt', |
|
1670 | 1682 | '1': 'fileTab.txt', |
|
1671 | 1683 | '3': 'instTab.txt', |
|
1672 | 1684 | '4': 'parmCodes.txt', |
|
1673 | 1685 | '5': 'siteTab.txt', |
|
1674 | 1686 | '6': 'typeTab.txt', |
|
1675 | 1687 | '7': 'instKindatTab.txt', |
|
1676 | 1688 | '8': 'instParmTab.txt', |
|
1677 | 1689 | '9': 'madCatTab.txt', |
|
1678 | 1690 | '10': 'instType.txt'} |
|
1679 | 1691 | form = madweb.forms.GetMetadataForm(request.GET) |
|
1680 | 1692 | if form.is_valid(): |
|
1681 | 1693 | madDB = madrigal.metadata.MadrigalDB() |
|
1682 | 1694 | downloadFile = os.path.join(madDB.getMetadataDir(), |
|
1683 | 1695 | fileDict[form.cleaned_data['fileType']]) |
|
1684 | 1696 | |
|
1685 | 1697 | |
|
1686 | 1698 | f = open(downloadFile, 'rb') |
|
1687 | 1699 | filename = os.path.basename(downloadFile) |
|
1688 | 1700 | chunk_size = 8192 |
|
1689 | 1701 | response = StreamingHttpResponse(FileWrapper(f, chunk_size), |
|
1690 | 1702 | content_type=mimetypes.guess_type(downloadFile)[0]) |
|
1691 | 1703 | response['Content-Length'] = os.path.getsize(downloadFile) |
|
1692 | 1704 | response['Content-Disposition'] = "attachment; filename=%s" % (filename) |
|
1693 | 1705 | return(response) |
|
1694 | 1706 | |
|
1695 | 1707 | else: |
|
1696 | 1708 | madDB = madrigal.metadata.MadrigalDB() |
|
1697 | 1709 | bg_color = madDB.getBackgroundColor() |
|
1698 | 1710 | form = madweb.forms.GetMetadataForm() |
|
1699 | 1711 | return render(request, 'madweb/get_metadata.html', {'form': form, 'bg_color': bg_color}) |
|
1700 | 1712 | |
|
1701 | 1713 | |
|
1702 | 1714 | def looker_main(request): |
|
1703 | 1715 | """looker_main loads the main looker selection form. |
|
1704 | 1716 | |
|
1705 | 1717 | Inputs: |
|
1706 | 1718 | request |
|
1707 | 1719 | """ |
|
1708 | 1720 | madDB = madrigal.metadata.MadrigalDB() |
|
1709 | 1721 | bg_color = madDB.getBackgroundColor() |
|
1710 | 1722 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
1711 | 1723 | siteName, siteList = madWebObj.getSiteInfo() |
|
1712 | 1724 | lookerSelectForm = madweb.forms.LookerSelectForm() |
|
1713 | 1725 | return render(request, 'madweb/looker_main.html', {'looker_active': 'class="active"', |
|
1714 | 1726 | 'form': lookerSelectForm, |
|
1715 | 1727 | 'site_name': siteName, 'site_list': siteList, |
|
1716 | 1728 | 'bg_color': bg_color}) |
|
1717 | 1729 | |
|
1718 | 1730 | |
|
1719 | 1731 | def looker_form(request): |
|
1720 | 1732 | """looker_form loads the appropriate looker form. |
|
1721 | 1733 | |
|
1722 | 1734 | Inputs: |
|
1723 | 1735 | request |
|
1724 | 1736 | """ |
|
1725 | 1737 | madDB = madrigal.metadata.MadrigalDB() |
|
1726 | 1738 | bg_color = madDB.getBackgroundColor() |
|
1727 | 1739 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
1728 | 1740 | siteName, siteList = madWebObj.getSiteInfo() |
|
1729 | 1741 | if not 'looker_options' in request.GET: |
|
1730 | 1742 | return(HttpResponse('<p>looker form requires looker_options</p>')) |
|
1731 | 1743 | form = madweb.forms.LookerSelectForm(request.GET) |
|
1732 | 1744 | if form.is_valid(): |
|
1733 | 1745 | option = form.cleaned_data['looker_options'] |
|
1734 | 1746 | if option == '1': |
|
1735 | 1747 | form = madweb.forms.LookerGeodeticRadar() |
|
1736 | 1748 | return render(request, 'madweb/looker_geodetic_to_radar.html', {'looker_active': 'class="active"', |
|
1737 | 1749 | 'form': form, |
|
1738 | 1750 | 'site_name': siteName, 'site_list': siteList, |
|
1739 | 1751 | 'bg_color': bg_color}) |
|
1740 | 1752 | elif option == '2': |
|
1741 | 1753 | form = madweb.forms.LookerGeomagRadar() |
|
1742 | 1754 | return render(request, 'madweb/looker_geomagnetic_to_radar.html', {'looker_active': 'class="active"', |
|
1743 | 1755 | 'form': form, |
|
1744 | 1756 | 'site_name': siteName, 'site_list': siteList, |
|
1745 | 1757 | 'bg_color': bg_color}) |
|
1746 | 1758 | elif option == '3': |
|
1747 | 1759 | form = madweb.forms.LookerGeomagFromGeodetic() |
|
1748 | 1760 | return render(request, 'madweb/looker_geomagnetic_from_geodetic.html', {'looker_active': 'class="active"', |
|
1749 | 1761 | 'form': form, |
|
1750 | 1762 | 'site_name': siteName, 'site_list': siteList, |
|
1751 | 1763 | 'bg_color': bg_color}) |
|
1752 | 1764 | elif option == '4': |
|
1753 | 1765 | form = madweb.forms.LookerGeomagFromRadar() |
|
1754 | 1766 | return render(request, 'madweb/looker_geomagnetic_from_radar.html', {'looker_active': 'class="active"', |
|
1755 | 1767 | 'form': form, |
|
1756 | 1768 | 'site_name': siteName, 'site_list': siteList, |
|
1757 | 1769 | 'bg_color': bg_color}) |
|
1758 | 1770 | elif option == '5': |
|
1759 | 1771 | form = madweb.forms.LookerFieldLineFromRadar() |
|
1760 | 1772 | return render(request, 'madweb/looker_field_line_from_radar.html', {'looker_active': 'class="active"', |
|
1761 | 1773 | 'form': form, |
|
1762 | 1774 | 'site_name': siteName, 'site_list': siteList, |
|
1763 | 1775 | 'bg_color': bg_color}) |
|
1764 | 1776 | elif option == '6': |
|
1765 | 1777 | form = madweb.forms.LookerFieldLineFromGeodetic() |
|
1766 | 1778 | return render(request, 'madweb/looker_field_line_from_geodetic.html', {'looker_active': 'class="active"', |
|
1767 | 1779 | 'form': form, |
|
1768 | 1780 | 'site_name': siteName, 'site_list': siteList, |
|
1769 | 1781 | 'bg_color': bg_color}) |
|
1770 | 1782 | elif option == '7': |
|
1771 | 1783 | form = madweb.forms.LookerFieldLineFromApex() |
|
1772 | 1784 | return render(request, 'madweb/looker_field_line_from_apex.html', {'looker_active': 'class="active"', |
|
1773 | 1785 | 'form': form, |
|
1774 | 1786 | 'site_name': siteName, 'site_list': siteList, |
|
1775 | 1787 | 'bg_color': bg_color}) |
|
1776 | 1788 | elif option == '8': |
|
1777 | 1789 | form = madweb.forms.LookerConjugateFromGeodetic() |
|
1778 | 1790 | return render(request, 'madweb/looker_conjugate_from_geodetic.html', {'looker_active': 'class="active"', |
|
1779 | 1791 | 'form': form, |
|
1780 | 1792 | 'site_name': siteName, 'site_list': siteList, |
|
1781 | 1793 | 'bg_color': bg_color, |
|
1782 | 1794 | 'datetime': True}) |
|
1783 | 1795 | else: |
|
1784 | 1796 | raise ValueError(str(form.errors)) |
|
1785 | 1797 | |
|
1786 | 1798 | |
|
1787 | 1799 | def looker_output(request): |
|
1788 | 1800 | """looker_output loads the appropriate looker output. |
|
1789 | 1801 | |
|
1790 | 1802 | Inputs: |
|
1791 | 1803 | request |
|
1792 | 1804 | """ |
|
1793 | 1805 | madDB = madrigal.metadata.MadrigalDB() |
|
1794 | 1806 | bg_color = madDB.getBackgroundColor() |
|
1795 | 1807 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
1796 | 1808 | siteName, siteList = madWebObj.getSiteInfo() |
|
1797 | 1809 | |
|
1798 | 1810 | if not 'looker_options' in request.GET: |
|
1799 | 1811 | return(HttpResponse('<p>looker missing arguments</p>')) |
|
1800 | 1812 | |
|
1801 | 1813 | if request.GET['looker_options'] == "1": |
|
1802 | 1814 | form = madweb.forms.LookerGeodeticRadar(request.GET) |
|
1803 | 1815 | if form.is_valid(): |
|
1804 | 1816 | text = madWebObj.runLookerFromForm(form.cleaned_data) |
|
1805 | 1817 | return render(request, 'madweb/looker_output.html', {'looker_active': 'class="active"', |
|
1806 | 1818 | 'type': 'Az, El, Range to Geodetic points', |
|
1807 | 1819 | 'text': text, |
|
1808 | 1820 | 'site_name': siteName, 'site_list': siteList, |
|
1809 | 1821 | 'bg_color': bg_color}) |
|
1810 | 1822 | else: |
|
1811 | 1823 | raise ValueError(str(form.errors)) |
|
1812 | 1824 | elif request.GET['looker_options'] == "2": |
|
1813 | 1825 | form = madweb.forms.LookerGeomagRadar(request.GET) |
|
1814 | 1826 | if form.is_valid(): |
|
1815 | 1827 | text = madWebObj.runLookerFromForm(form.cleaned_data) |
|
1816 | 1828 | return render(request, 'madweb/looker_output.html', {'looker_active': 'class="active"', |
|
1817 | 1829 | 'type': 'Az, El, Range to Geomagnetic (apex) points', |
|
1818 | 1830 | 'text': text, |
|
1819 | 1831 | 'site_name': siteName, 'site_list': siteList, |
|
1820 | 1832 | 'bg_color': bg_color}) |
|
1821 | 1833 | else: |
|
1822 | 1834 | raise ValueError(str(form.errors)) |
|
1823 | 1835 | elif request.GET['looker_options'] == "3": |
|
1824 | 1836 | form = madweb.forms.LookerGeomagFromGeodetic(request.GET) |
|
1825 | 1837 | if form.is_valid(): |
|
1826 | 1838 | text = madWebObj.runLookerFromForm(form.cleaned_data) |
|
1827 | 1839 | return render(request, 'madweb/looker_output.html', {'looker_active': 'class="active"', |
|
1828 | 1840 | 'type': 'Apex Geomagnetic coordinates from Geodetic grid', |
|
1829 | 1841 | 'text': text, |
|
1830 | 1842 | 'site_name': siteName, 'site_list': siteList, |
|
1831 | 1843 | 'bg_color': bg_color}) |
|
1832 | 1844 | else: |
|
1833 | 1845 | raise ValueError(str(form.errors)) |
|
1834 | 1846 | elif request.GET['looker_options'] == "4": |
|
1835 | 1847 | form = madweb.forms.LookerGeomagFromRadar(request.GET) |
|
1836 | 1848 | if form.is_valid(): |
|
1837 | 1849 | text = madWebObj.runLookerFromForm(form.cleaned_data) |
|
1838 | 1850 | return render(request, 'madweb/looker_output.html', {'looker_active': 'class="active"', |
|
1839 | 1851 | 'type': 'Apex Geomagnetic and geodetic coordinates and aspect angle from a grid of azimuth, elevation, and range', |
|
1840 | 1852 | 'text': text, |
|
1841 | 1853 | 'site_name': siteName, 'site_list': siteList, |
|
1842 | 1854 | 'bg_color': bg_color}) |
|
1843 | 1855 | else: |
|
1844 | 1856 | raise ValueError(str(form.errors)) |
|
1845 | 1857 | elif request.GET['looker_options'] == "5": |
|
1846 | 1858 | form = madweb.forms.LookerFieldLineFromRadar(request.GET) |
|
1847 | 1859 | if form.is_valid(): |
|
1848 | 1860 | text = madWebObj.runLookerFromForm(form.cleaned_data) |
|
1849 | 1861 | return render(request, 'madweb/looker_output.html', {'looker_active': 'class="active"', |
|
1850 | 1862 | 'type': 'Field line coordinates for a field line set by radar parameters', |
|
1851 | 1863 | 'text': text, |
|
1852 | 1864 | 'site_name': siteName, 'site_list': siteList, |
|
1853 | 1865 | 'bg_color': bg_color}) |
|
1854 | 1866 | else: |
|
1855 | 1867 | raise ValueError(str(form.errors)) |
|
1856 | 1868 | elif request.GET['looker_options'] == "6": |
|
1857 | 1869 | form = madweb.forms.LookerFieldLineFromGeodetic(request.GET) |
|
1858 | 1870 | if form.is_valid(): |
|
1859 | 1871 | text = madWebObj.runLookerFromForm(form.cleaned_data) |
|
1860 | 1872 | return render(request, 'madweb/looker_output.html', {'looker_active': 'class="active"', |
|
1861 | 1873 | 'type': 'Field line coordinates and radar look parameters for given field line', |
|
1862 | 1874 | 'text': text, |
|
1863 | 1875 | 'site_name': siteName, 'site_list': siteList, |
|
1864 | 1876 | 'bg_color': bg_color}) |
|
1865 | 1877 | else: |
|
1866 | 1878 | raise ValueError(str(form.errors)) |
|
1867 | 1879 | elif request.GET['looker_options'] == "7": |
|
1868 | 1880 | form = madweb.forms.LookerFieldLineFromApex(request.GET) |
|
1869 | 1881 | if form.is_valid(): |
|
1870 | 1882 | text = madWebObj.runLookerFromForm(form.cleaned_data) |
|
1871 | 1883 | return render(request, 'madweb/looker_output.html', {'looker_active': 'class="active"', |
|
1872 | 1884 | 'type': 'Field line coordinates and radar look parameters for given field line', |
|
1873 | 1885 | 'text': text, |
|
1874 | 1886 | 'site_name': siteName, 'site_list': siteList, |
|
1875 | 1887 | 'bg_color': bg_color}) |
|
1876 | 1888 | else: |
|
1877 | 1889 | raise ValueError(str(form.errors)) |
|
1878 | 1890 | elif request.GET['looker_options'] == "8": |
|
1879 | 1891 | form = madweb.forms.LookerConjugateFromGeodetic(request.GET) |
|
1880 | 1892 | if form.is_valid(): |
|
1881 | 1893 | text = madWebObj.runLookerFromForm(form.cleaned_data) |
|
1882 | 1894 | return render(request, 'madweb/looker_output.html', {'looker_active': 'class="active"', |
|
1883 | 1895 | 'type': 'Point/Magnetic Conjugate Point vs Latitude, Longitude, Altitude', |
|
1884 | 1896 | 'datetime': form.cleaned_data['datetime'], |
|
1885 | 1897 | 'text': text, |
|
1886 | 1898 | 'site_name': siteName, 'site_list': siteList, |
|
1887 | 1899 | 'bg_color': bg_color}) |
|
1888 | 1900 | else: |
|
1889 | 1901 | raise ValueError(str(form.errors)) |
|
1890 | 1902 | |
|
1891 | 1903 | else: |
|
1892 | 1904 | raise ValueError('Unknown looker_option <%s>' % (str(request.GET['looker_options']))) |
|
1893 | 1905 | |
|
1894 | 1906 | |
|
1895 | 1907 | |
|
1896 | 1908 | def get_version_service(request): |
|
1897 | 1909 | """get_version_service runs the getVersionService.py service. |
|
1898 | 1910 | |
|
1899 | 1911 | Inputs: |
|
1900 | 1912 | request (ignored) |
|
1901 | 1913 | |
|
1902 | 1914 | Returns a single line of text, with the version in the form <major_version_int>.<minor_version_int>[.<sub_version_int>] |
|
1903 | 1915 | """ |
|
1904 | 1916 | madDB = madrigal.metadata.MadrigalDB() |
|
1905 | 1917 | siteID = madDB.getSiteID() |
|
1906 | 1918 | madSiteObj = madrigal.metadata.MadrigalSite(madDB) |
|
1907 | 1919 | return(HttpResponse(madSiteObj.getSiteVersion(siteID))) |
|
1908 | 1920 | |
|
1909 | 1921 | |
|
1910 | 1922 | |
|
1911 | 1923 | def get_instruments_service(request): |
|
1912 | 1924 | """get_instruments_service runs the getInstrumentsService.py service. |
|
1913 | 1925 | |
|
1914 | 1926 | Inputs: |
|
1915 | 1927 | request (ignored) |
|
1916 | 1928 | |
|
1917 | 1929 | Returns comma-delimited data, one line for each experiment, with the following fields: |
|
1918 | 1930 | |
|
1919 | 1931 | 1. instrument.name Example: 'Millstone Hill Incoherent Scatter Radar' |
|
1920 | 1932 | |
|
1921 | 1933 | 2. instrument.code Example: 30 |
|
1922 | 1934 | |
|
1923 | 1935 | 3. instrument.mnemonic (3 char string) Example: 'mlh' |
|
1924 | 1936 | |
|
1925 | 1937 | 4. instrument.latitude Example: 45.0 |
|
1926 | 1938 | |
|
1927 | 1939 | 5. instrument.longitude Example: 110.0 |
|
1928 | 1940 | |
|
1929 | 1941 | 6. instrument.altitude Example: 0.015 (km) |
|
1930 | 1942 | |
|
1931 | 1943 | 7. instrument.category Example: 'Incoherent Scatter Radars' |
|
1932 | 1944 | |
|
1933 | 1945 | 8. contact name |
|
1934 | 1946 | |
|
1935 | 1947 | 9. contact email |
|
1936 | 1948 | """ |
|
1937 | 1949 | # create MadrigalDB obj |
|
1938 | 1950 | madDBObj = madrigal.metadata.MadrigalDB() |
|
1939 | 1951 | |
|
1940 | 1952 | # create MadrigalInstument object |
|
1941 | 1953 | madInst = madrigal.metadata.MadrigalInstrument(madDBObj) |
|
1942 | 1954 | |
|
1943 | 1955 | # get instrument list |
|
1944 | 1956 | instList = madInst.getInstrumentList() |
|
1945 | 1957 | |
|
1946 | 1958 | # loop through each instrument |
|
1947 | 1959 | instStr = '' |
|
1948 | 1960 | for inst in instList: |
|
1949 | 1961 | name = inst[0] |
|
1950 | 1962 | code = inst[2] |
|
1951 | 1963 | mnemonic = inst[1] |
|
1952 | 1964 | latitude = madInst.getLatitude(code) |
|
1953 | 1965 | if latitude == None: |
|
1954 | 1966 | latitude = 0.0 |
|
1955 | 1967 | longitude = madInst.getLongitude(code) |
|
1956 | 1968 | if longitude == None: |
|
1957 | 1969 | longitude = 0.0 |
|
1958 | 1970 | altitude = madInst.getAltitude(code) |
|
1959 | 1971 | if altitude == None: |
|
1960 | 1972 | altitude = 0.0 |
|
1961 | 1973 | category = madInst.getCategory(code) |
|
1962 | 1974 | if category == None: |
|
1963 | 1975 | category = '' |
|
1964 | 1976 | # print data |
|
1965 | 1977 | contactName = madInst.getContactName(code) |
|
1966 | 1978 | contactEmail = madInst.getContactEmail(code) |
|
1967 | 1979 | instStr += '%s,%i,%s,%f,%f,%f,%s,%s,%s\n' % (name, |
|
1968 | 1980 | code, |
|
1969 | 1981 | mnemonic, |
|
1970 | 1982 | latitude, |
|
1971 | 1983 | longitude, |
|
1972 | 1984 | altitude, |
|
1973 | 1985 | category, |
|
1974 | 1986 | str(contactName), |
|
1975 | 1987 | str(contactEmail)) |
|
1976 | 1988 | |
|
1977 | 1989 | return render(request, 'madweb/service.html', {'text': instStr}) |
|
1978 | 1990 | |
|
1979 | 1991 | |
|
1980 | 1992 | def get_experiments_service(request): |
|
1981 | 1993 | """get_experiments_service runs the getExperimentsService.py service. |
|
1982 | 1994 | |
|
1983 | 1995 | Inputs: |
|
1984 | 1996 | request/url - contains arguments: |
|
1985 | 1997 | |
|
1986 | 1998 | code - one or more kindat values |
|
1987 | 1999 | |
|
1988 | 2000 | startyear, startmonth, startday, starthour, startmin, startsec |
|
1989 | 2001 | |
|
1990 | 2002 | endyear, endmonth, endday, endhour, endmin, endsec |
|
1991 | 2003 | |
|
1992 | 2004 | local (defaults to True) |
|
1993 | 2005 | |
|
1994 | 2006 | Returns comma-delimited data, one line for each experiment, with the following fields: |
|
1995 | 2007 | |
|
1996 | 2008 | 1. experiment.id (int) Example: 10000111 |
|
1997 | 2009 | |
|
1998 | 2010 | 2. experiment.url (string) Example: 'http://www.haystack.mit.edu/cgi-bin/madtoc/1997/mlh/03dec97' |
|
1999 | 2011 | |
|
2000 | 2012 | 3. experiment.name (string) Example: 'Wide Latitude Substorm Study' |
|
2001 | 2013 | |
|
2002 | 2014 | 4. experiment.siteid (int) Example: 1 |
|
2003 | 2015 | |
|
2004 | 2016 | 5. experiment.sitename (string) Example: 'Millstone Hill Observatory' |
|
2005 | 2017 | |
|
2006 | 2018 | 6. experiment.instcode (int) Code of instrument. Example: 30 |
|
2007 | 2019 | |
|
2008 | 2020 | 7. experiment.instname (string) Instrument name. Example: 'Millstone Hill Incoherent Scatter Radar' |
|
2009 | 2021 | |
|
2010 | 2022 | 8. experiment.start year (int) year of experiment start |
|
2011 | 2023 | |
|
2012 | 2024 | 9. experiment.start month (int) month of experiment start |
|
2013 | 2025 | |
|
2014 | 2026 | 10. experiment.start day (int) day of experiment start |
|
2015 | 2027 | |
|
2016 | 2028 | 11. experiment.start hour (int) hour of experiment start |
|
2017 | 2029 | |
|
2018 | 2030 | 12. experiment.start minute (int) min of experiment start |
|
2019 | 2031 | |
|
2020 | 2032 | 13. experiment.start second (int) sec of experiment start |
|
2021 | 2033 | |
|
2022 | 2034 | 14. experiment.end year (int) year of experiment end |
|
2023 | 2035 | |
|
2024 | 2036 | 15. experiment.end month (int) month of experiment end |
|
2025 | 2037 | |
|
2026 | 2038 | 16. experiment.end day (int) day of experiment end |
|
2027 | 2039 | |
|
2028 | 2040 | 17. experiment.end hour (int) hour of experiment end |
|
2029 | 2041 | |
|
2030 | 2042 | 18. experiment.end minute (int) min of experiment end |
|
2031 | 2043 | |
|
2032 | 2044 | 19. experiment.end second (int) sec of experiment end |
|
2033 | 2045 | |
|
2034 | 2046 | 20. experiment.isLocal (int) 1 if local, 0 if not |
|
2035 | 2047 | |
|
2036 | 2048 | 21.experiment.PI (string) Experiment PI name Example: 'Phil Erickson' |
|
2037 | 2049 | |
|
2038 | 2050 | 22. experiment.PIEmail (string) Experiment PI email Example: 'perickson@haystack.mit.edu' |
|
2039 | 2051 | |
|
2040 | 2052 | 23. utc timestamp of last update to experiment |
|
2041 | 2053 | |
|
2042 | 2054 | 24. security value |
|
2043 | 2055 | |
|
2044 | 2056 | """ |
|
2045 | 2057 | codeList = request.GET.getlist('code') |
|
2046 | 2058 | codeList = [int(code) for code in codeList] |
|
2047 | 2059 | startyear = int(request.GET['startyear']) |
|
2048 | 2060 | startmonth = int(request.GET['startmonth']) |
|
2049 | 2061 | startday = int(request.GET['startday']) |
|
2050 | 2062 | starthour = int(request.GET['starthour']) |
|
2051 | 2063 | startmin = int(request.GET['startmin']) |
|
2052 | 2064 | startsec = int(request.GET['startsec']) |
|
2053 | 2065 | endyear = int(request.GET['endyear']) |
|
2054 | 2066 | endmonth = int(request.GET['endmonth']) |
|
2055 | 2067 | endday = int(request.GET['endday']) |
|
2056 | 2068 | endhour = int(request.GET['endhour']) |
|
2057 | 2069 | endmin = int(request.GET['endmin']) |
|
2058 | 2070 | endsec = int(request.GET['endsec']) |
|
2059 | 2071 | try: |
|
2060 | 2072 | local = int(request.GET['local']) |
|
2061 | 2073 | except: |
|
2062 | 2074 | local = 1 |
|
2063 | 2075 | |
|
2064 | 2076 | |
|
2065 | 2077 | # if startsec or endsec in (60, 61), handle correctly |
|
2066 | 2078 | if startsec in (60, 61): |
|
2067 | 2079 | tmpTime = datetime.datetime(startyear, |
|
2068 | 2080 | startmonth, |
|
2069 | 2081 | startday, |
|
2070 | 2082 | starthour, |
|
2071 | 2083 | startmin, |
|
2072 | 2084 | 59) |
|
2073 | 2085 | tmpTime += datetime.timedelta(0, startsec - 59) |
|
2074 | 2086 | startyear = tmpTime.year |
|
2075 | 2087 | startmonth = tmpTime.month |
|
2076 | 2088 | startday = tmpTime.day |
|
2077 | 2089 | starthour = tmpTime.hour |
|
2078 | 2090 | startmin = tmpTime.minute |
|
2079 | 2091 | startsec = tmpTime.second |
|
2080 | 2092 | |
|
2081 | 2093 | if endsec in (60, 61): |
|
2082 | 2094 | tmpTime = datetime.datetime(endyear, |
|
2083 | 2095 | endmonth, |
|
2084 | 2096 | endday, |
|
2085 | 2097 | endhour, |
|
2086 | 2098 | endmin, |
|
2087 | 2099 | 59) |
|
2088 | 2100 | tmpTime += datetime.timedelta(0, endsec - 59) |
|
2089 | 2101 | endyear = tmpTime.year |
|
2090 | 2102 | endmonth = tmpTime.month |
|
2091 | 2103 | endday = tmpTime.day |
|
2092 | 2104 | endhour = tmpTime.hour |
|
2093 | 2105 | endmin = tmpTime.minute |
|
2094 | 2106 | endsec = tmpTime.second |
|
2095 | 2107 | |
|
2096 | 2108 | # if codeList is empty or contains 0, change it to only contain 0 |
|
2097 | 2109 | if len(codeList) == 0 or 0 in codeList: |
|
2098 | 2110 | codeList = [0] |
|
2099 | 2111 | |
|
2100 | 2112 | retStr = '' |
|
2101 | 2113 | |
|
2102 | 2114 | # create MadrigalDB obj |
|
2103 | 2115 | madDBObj = madrigal.metadata.MadrigalDB() |
|
2104 | 2116 | |
|
2105 | 2117 | # get the local site id |
|
2106 | 2118 | localSiteId = madDBObj.getSiteID() |
|
2107 | 2119 | |
|
2108 | 2120 | # create MadrigalInstrument obj to convert kinst to instrument names |
|
2109 | 2121 | madInstObj = madrigal.metadata.MadrigalInstrument(madDBObj) |
|
2110 | 2122 | |
|
2111 | 2123 | # create MadrigalSite obj to convert site id to site name |
|
2112 | 2124 | madSiteObj = madrigal.metadata.MadrigalSite(madDBObj) |
|
2113 | 2125 | |
|
2114 | 2126 | madWebObj = madrigal.ui.web.MadrigalWeb(madDBObj) |
|
2115 | 2127 | trusted = madWebObj.isTrusted() |
|
2116 | 2128 | |
|
2117 | 2129 | # create starttime for filter, if possible |
|
2118 | 2130 | if startyear != None: |
|
2119 | 2131 | startTimeFilter = datetime.datetime(startyear, |
|
2120 | 2132 | startmonth, |
|
2121 | 2133 | startday, |
|
2122 | 2134 | starthour, |
|
2123 | 2135 | startmin, |
|
2124 | 2136 | startsec) |
|
2125 | 2137 | else: |
|
2126 | 2138 | startTimeFilter = None |
|
2127 | 2139 | |
|
2128 | 2140 | # create endtime for filter, if possible |
|
2129 | 2141 | if endyear != None: |
|
2130 | 2142 | endTimeFilter = datetime.datetime(endyear, |
|
2131 | 2143 | endmonth, |
|
2132 | 2144 | endday, |
|
2133 | 2145 | endhour, |
|
2134 | 2146 | endmin, |
|
2135 | 2147 | endsec) |
|
2136 | 2148 | else: |
|
2137 | 2149 | endTimeFilter = None |
|
2138 | 2150 | |
|
2139 | 2151 | # create MadrigalExperiments for local or all files |
|
2140 | 2152 | if local == 1: |
|
2141 | 2153 | madExpObj = madrigal.metadata.MadrigalExperiment(madDBObj) |
|
2142 | 2154 | else: |
|
2143 | 2155 | # use file expTabAll.txt to get all experiments |
|
2144 | 2156 | filename = madDBObj.getMadroot() |
|
2145 | 2157 | if filename[-1] != '/': |
|
2146 | 2158 | filename += '/' |
|
2147 | 2159 | filename += 'metadata/expTabAll.txt' |
|
2148 | 2160 | madExpObj = madrigal.metadata.MadrigalExperiment(madDBObj, filename) |
|
2149 | 2161 | |
|
2150 | 2162 | madExpObj.sortByDateSite() |
|
2151 | 2163 | |
|
2152 | 2164 | |
|
2153 | 2165 | # loop through the data |
|
2154 | 2166 | if not startTimeFilter is None: |
|
2155 | 2167 | position = madExpObj.getStartPosition(startTimeFilter) |
|
2156 | 2168 | else: |
|
2157 | 2169 | position = 0 |
|
2158 | 2170 | while(True): |
|
2159 | 2171 | thisId = madExpObj.getExpIdByPosition(position) |
|
2160 | 2172 | # check for end |
|
2161 | 2173 | if thisId == None: |
|
2162 | 2174 | break |
|
2163 | 2175 | thisUrl = madExpObj.getExpUrlByPosition(position) |
|
2164 | 2176 | thisName = madExpObj.getExpNameByPosition(position) |
|
2165 | 2177 | thisSiteId = madExpObj.getExpSiteIdByPosition(position) |
|
2166 | 2178 | thisSiteName = madSiteObj.getSiteName(thisSiteId) |
|
2167 | 2179 | thisInstCode = madExpObj.getKinstByPosition(position) |
|
2168 | 2180 | thisInstName =madInstObj.getInstrumentName(thisInstCode) |
|
2169 | 2181 | thisStart = madExpObj.getExpStartDateTimeByPosition(position) |
|
2170 | 2182 | thisEnd = madExpObj.getExpEndDateTimeByPosition(position) |
|
2171 | 2183 | thisSecurity = madExpObj.getSecurityByPosition(position) |
|
2172 | 2184 | if thisSiteId == localSiteId: |
|
2173 | 2185 | thisLocal = 1 |
|
2174 | 2186 | else: |
|
2175 | 2187 | thisLocal = 0 |
|
2176 | 2188 | thisPI = madExpObj.getPIByPosition(position) |
|
2177 | 2189 | if thisPI in (None, ''): |
|
2178 | 2190 | thisPI = madInstObj.getContactName(thisInstCode) |
|
2179 | 2191 | thisPIEmail = madExpObj.getPIEmailByPosition(position) |
|
2180 | 2192 | if thisPIEmail in (None, ''): |
|
2181 | 2193 | thisPIEmail = madInstObj.getContactEmail(thisInstCode) |
|
2182 | 2194 | expDir = madExpObj.getExpDirByPosition(position) |
|
2183 | 2195 | |
|
2184 | 2196 | position += 1 |
|
2185 | 2197 | |
|
2186 | 2198 | # some experiments set the end of the day to 24:00:00 - not |
|
2187 | 2199 | # technically correct - reset to 23:59:59 |
|
2188 | 2200 | |
|
2189 | 2201 | if (thisStart[3] == 24 and thisStart[4] == 0 and thisStart[5] == 0): |
|
2190 | 2202 | thisStart[3] = 23 |
|
2191 | 2203 | thisStart[4] = 59 |
|
2192 | 2204 | thisStart[5] = 59 |
|
2193 | 2205 | |
|
2194 | 2206 | if (thisEnd[3] == 24 and thisEnd[4] == 0 and thisEnd[5] == 0): |
|
2195 | 2207 | thisEnd[3] = 23 |
|
2196 | 2208 | thisEnd[4] = 59 |
|
2197 | 2209 | thisEnd[5] = 59 |
|
2198 | 2210 | |
|
2199 | 2211 | # apply filters |
|
2200 | 2212 | |
|
2201 | 2213 | # first apply instrument code filter |
|
2202 | 2214 | if codeList[0] != 0: |
|
2203 | 2215 | if thisInstCode not in codeList: |
|
2204 | 2216 | continue |
|
2205 | 2217 | |
|
2206 | 2218 | # apply starttime and endtime filters |
|
2207 | 2219 | thisStartTime = datetime.datetime(thisStart[0], |
|
2208 | 2220 | thisStart[1], |
|
2209 | 2221 | thisStart[2], |
|
2210 | 2222 | thisStart[3], |
|
2211 | 2223 | thisStart[4], |
|
2212 | 2224 | thisStart[5]) |
|
2213 | 2225 | |
|
2214 | 2226 | thisEndTime = datetime.datetime(thisEnd[0], |
|
2215 | 2227 | thisEnd[1], |
|
2216 | 2228 | thisEnd[2], |
|
2217 | 2229 | thisEnd[3], |
|
2218 | 2230 | thisEnd[4], |
|
2219 | 2231 | thisEnd[5]) |
|
2220 | 2232 | |
|
2221 | 2233 | if startTimeFilter != None: |
|
2222 | 2234 | if thisEndTime < startTimeFilter: |
|
2223 | 2235 | continue |
|
2224 | 2236 | |
|
2225 | 2237 | if endTimeFilter != None: |
|
2226 | 2238 | if thisStartTime > endTimeFilter: |
|
2227 | 2239 | continue |
|
2228 | 2240 | |
|
2229 | 2241 | # apply local filer |
|
2230 | 2242 | if local == 1 and thisLocal == 0: |
|
2231 | 2243 | continue |
|
2232 | 2244 | |
|
2233 | 2245 | # apply security filter |
|
2234 | 2246 | if trusted == 0 and thisSecurity not in (0,2): |
|
2235 | 2247 | continue |
|
2236 | 2248 | |
|
2237 | 2249 | # create exp timestamp |
|
2238 | 2250 | if local == 1: |
|
2239 | 2251 | thisUTTimestamp = int(os.stat(expDir).st_mtime + time.timezone) |
|
2240 | 2252 | else: |
|
2241 | 2253 | thisUTTimestamp = 0 |
|
2242 | 2254 | |
|
2243 | 2255 | # add this experiment |
|
2244 | 2256 | 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' % \ |
|
2245 | 2257 | (thisId, |
|
2246 | 2258 | thisUrl, |
|
2247 | 2259 | thisName, |
|
2248 | 2260 | thisSiteId, |
|
2249 | 2261 | thisSiteName, |
|
2250 | 2262 | thisInstCode, |
|
2251 | 2263 | thisInstName, |
|
2252 | 2264 | thisStart[0], |
|
2253 | 2265 | thisStart[1], |
|
2254 | 2266 | thisStart[2], |
|
2255 | 2267 | thisStart[3], |
|
2256 | 2268 | thisStart[4], |
|
2257 | 2269 | thisStart[5], |
|
2258 | 2270 | thisEnd[0], |
|
2259 | 2271 | thisEnd[1], |
|
2260 | 2272 | thisEnd[2], |
|
2261 | 2273 | thisEnd[3], |
|
2262 | 2274 | thisEnd[4], |
|
2263 | 2275 | thisEnd[5], |
|
2264 | 2276 | thisLocal, |
|
2265 | 2277 | str(thisPI), |
|
2266 | 2278 | str(thisPIEmail), |
|
2267 | 2279 | thisUTTimestamp, |
|
2268 | 2280 | thisSecurity) |
|
2269 | 2281 | |
|
2270 | 2282 | return render(request, 'madweb/service.html', {'text': retStr}) |
|
2271 | 2283 | |
|
2272 | 2284 | |
|
2273 | 2285 | def get_experiment_files_service(request): |
|
2274 | 2286 | """get_experiment_files_service runs the getExperimentFilesService.py service. |
|
2275 | 2287 | |
|
2276 | 2288 | Inputs: |
|
2277 | 2289 | request/url - contains arguments: |
|
2278 | 2290 | |
|
2279 | 2291 | id - local experiment id |
|
2280 | 2292 | |
|
2281 | 2293 | Returns comma-delimited data, one line for each experiment file, with the following fields: |
|
2282 | 2294 | |
|
2283 | 2295 | 1. file.name (string) Example '/opt/mdarigal/blah/mlh980120g.001' |
|
2284 | 2296 | |
|
2285 | 2297 | 2. file.kindat (int) Kindat code. Example: 3001 |
|
2286 | 2298 | |
|
2287 | 2299 | 3. file.kindat desc (string) Kindat description: Example 'Basic Derived Parameters' |
|
2288 | 2300 | |
|
2289 | 2301 | 4. file.category (int) (1=default, 2=variant, 3=history, 4=real-time) |
|
2290 | 2302 | |
|
2291 | 2303 | 5. file.status (string)('preliminary', 'final', or any other description) |
|
2292 | 2304 | |
|
2293 | 2305 | 6. file.permission (int) 0 for public, 1 for private. For now will not return private files. |
|
2294 | 2306 | |
|
2295 | 2307 | 7. file DOI (string) - citable url to file |
|
2296 | 2308 | |
|
2297 | 2309 | Returns empty string if experiment id not found. Skips files that are not Hdf5 |
|
2298 | 2310 | """ |
|
2299 | 2311 | id = int(request.GET['id']) |
|
2300 | 2312 | |
|
2301 | 2313 | # create MadrigalDB obj |
|
2302 | 2314 | madDBObj = madrigal.metadata.MadrigalDB() |
|
2303 | 2315 | |
|
2304 | 2316 | # create MadrigalExperiments object to get full file name |
|
2305 | 2317 | madExpObj = madrigal.metadata.MadrigalExperiment(madDBObj) |
|
2306 | 2318 | |
|
2307 | 2319 | # create Madrigal Kindat to get Kindat descriptions |
|
2308 | 2320 | madKindatObj = madrigal.metadata.MadrigalKindat(madDBObj) |
|
2309 | 2321 | |
|
2310 | 2322 | madWebObj = madrigal.ui.web.MadrigalWeb(madDBObj) |
|
2311 | 2323 | trusted = madWebObj.isTrusted() |
|
2312 | 2324 | |
|
2313 | 2325 | |
|
2314 | 2326 | retStr = '' |
|
2315 | 2327 | thisUrl = madExpObj.getExpUrlByExpId(id) |
|
2316 | 2328 | if thisUrl is None: |
|
2317 | 2329 | raise IOError('No such id: %i' % (id)) |
|
2318 | 2330 | expPath = madExpObj.getExpDirByExpId(id) |
|
2319 | 2331 | kinst = madExpObj.getKinstByExpId(id) |
|
2320 | 2332 | if os.access(os.path.join(expPath, 'fileTab.txt'), os.R_OK): |
|
2321 | 2333 | madFileObj = madrigal.metadata.MadrigalMetaFile(madDBObj, os.path.join(expPath, 'fileTab.txt')) |
|
2322 | 2334 | for i in range(madFileObj.getFileCount()): |
|
2323 | 2335 | basename = madFileObj.getFilenameByPosition(i) |
|
2324 | 2336 | name = os.path.join(expPath, basename) |
|
2325 | 2337 | base_filename, file_extension = os.path.splitext(name) |
|
2326 | 2338 | if file_extension not in ('.hdf5', '.hdf', '.h5'): |
|
2327 | 2339 | continue |
|
2328 | 2340 | kindat = madFileObj.getKindatByPosition(i) |
|
2329 | 2341 | kindatdesc = madKindatObj.getKindatDescription(kindat, kinst) |
|
2330 | 2342 | category = madFileObj.getCategoryByPosition(i) |
|
2331 | 2343 | status = madFileObj.getStatusByPosition(i) |
|
2332 | 2344 | permission = madFileObj.getAccessByPosition(i) |
|
2333 | 2345 | doi = madFileObj.getFileDOIUrlByPosition(i) |
|
2334 | 2346 | |
|
2335 | 2347 | # skip private files if not trusted |
|
2336 | 2348 | if trusted == 0 and int(permission) != 0: |
|
2337 | 2349 | continue |
|
2338 | 2350 | |
|
2339 | 2351 | retStr += '%s,%i,%s,%i,%s,%i,%s\n' % \ |
|
2340 | 2352 | (name, |
|
2341 | 2353 | kindat, |
|
2342 | 2354 | kindatdesc, |
|
2343 | 2355 | category, |
|
2344 | 2356 | status, |
|
2345 | 2357 | permission, |
|
2346 | 2358 | doi) |
|
2347 | 2359 | |
|
2348 | 2360 | |
|
2349 | 2361 | |
|
2350 | 2362 | return render(request, 'madweb/service.html', {'text': django.utils.safestring.mark_safe(retStr)}) |
|
2351 | 2363 | |
|
2352 | 2364 | |
|
2353 | 2365 | def get_parameters_service(request): |
|
2354 | 2366 | """get_parameters_service runs the getParametersService.py service. |
|
2355 | 2367 | |
|
2356 | 2368 | Inputs: |
|
2357 | 2369 | request/url - contains arguments: |
|
2358 | 2370 | |
|
2359 | 2371 | filename=<full path to data file> |
|
2360 | 2372 | |
|
2361 | 2373 | Returns backslash-delimited data, one for each parameter either measured or derivable, with the following fields: |
|
2362 | 2374 | |
|
2363 | 2375 | 1. parameter.mnemonic (string) Example 'dti' |
|
2364 | 2376 | |
|
2365 | 2377 | 2. parameter.description (string) Example: |
|
2366 | 2378 | "F10.7 Multiday average observed (Ott)" |
|
2367 | 2379 | |
|
2368 | 2380 | 3. parameter.isError (int) 1 if error parameter, 0 if not |
|
2369 | 2381 | |
|
2370 | 2382 | 4. parameter.units (string) Example "W/m2/Hz" |
|
2371 | 2383 | |
|
2372 | 2384 | 5. parameter.isMeasured (int) 1 if measured, 0 if derivable |
|
2373 | 2385 | |
|
2374 | 2386 | 6. parameter.category (string) Example: "Time Related Parameter" |
|
2375 | 2387 | |
|
2376 | 2388 | 7. parameter.isSure (int) - 1 if parameter can be found for every record, 0 if can only be found for some. |
|
2377 | 2389 | Not relevant to Madrigal 3, where always 1 |
|
2378 | 2390 | |
|
2379 | 2391 | 8. parameter.isAddIncrement - 1 if additional increment, 0 if normal (Added in Madrigal 2.5) |
|
2380 | 2392 | Not relevant to Madrigal 3, where always -1 |
|
2381 | 2393 | """ |
|
2382 | 2394 | filename = request.GET['filename'] |
|
2383 | 2395 | |
|
2384 | 2396 | # create MadrigalDB obj |
|
2385 | 2397 | madDBObj = madrigal.metadata.MadrigalDB() |
|
2386 | 2398 | |
|
2387 | 2399 | # create Madrigal File object |
|
2388 | 2400 | madFileObj = madrigal.data.MadrigalFile(filename, madDBObj) |
|
2389 | 2401 | |
|
2390 | 2402 | # create Madrigal Parameter object |
|
2391 | 2403 | madParmObj = madrigal.data.MadrigalParameters(madDBObj) |
|
2392 | 2404 | |
|
2393 | 2405 | # create Madrigal web object |
|
2394 | 2406 | madWebObj = madrigal.ui.web.MadrigalWebFormat() |
|
2395 | 2407 | |
|
2396 | 2408 | |
|
2397 | 2409 | # create lists of parameters |
|
2398 | 2410 | measParmList = [] |
|
2399 | 2411 | derivedParmList = [] |
|
2400 | 2412 | allParmList = [] |
|
2401 | 2413 | sureParmList = [] |
|
2402 | 2414 | |
|
2403 | 2415 | # use the comprehensive list of parameters to check if derivable |
|
2404 | 2416 | parmList = madWebObj.getFormat('Comprehensive') |
|
2405 | 2417 | |
|
2406 | 2418 | # populate lists |
|
2407 | 2419 | madFileObj.getMeasDervBothParmLists(parmList, |
|
2408 | 2420 | measParmList, |
|
2409 | 2421 | derivedParmList, |
|
2410 | 2422 | allParmList, |
|
2411 | 2423 | sureParmList) |
|
2412 | 2424 | |
|
2413 | 2425 | retStr = '' |
|
2414 | 2426 | |
|
2415 | 2427 | # loop through allParmList and output results |
|
2416 | 2428 | for parm in allParmList: |
|
2417 | 2429 | description = madParmObj.getSimpleParmDescription(parm) |
|
2418 | 2430 | isNorm = madParmObj.getParmType(parm) |
|
2419 | 2431 | if isNorm == 1: |
|
2420 | 2432 | isError = 0 |
|
2421 | 2433 | else: |
|
2422 | 2434 | isError = 1 |
|
2423 | 2435 | units = madParmObj.getParmUnits(parm) |
|
2424 | 2436 | if parm in measParmList: |
|
2425 | 2437 | isMeasured = 1 |
|
2426 | 2438 | else: |
|
2427 | 2439 | isMeasured = 0 |
|
2428 | 2440 | if parm in sureParmList: |
|
2429 | 2441 | isSure = 1 |
|
2430 | 2442 | else: |
|
2431 | 2443 | isSure = 0 |
|
2432 | 2444 | category = madParmObj.getParmCategory(parm) |
|
2433 | 2445 | try: |
|
2434 | 2446 | if madParmObj.isAddIncrement(parm): |
|
2435 | 2447 | isAddIncrement = 1 |
|
2436 | 2448 | else: |
|
2437 | 2449 | isAddIncrement = 0 |
|
2438 | 2450 | except: |
|
2439 | 2451 | isAddIncrement = -1 |
|
2440 | 2452 | # print out this parm |
|
2441 | 2453 | retStr += '%s\\%s\\%i\\%s\\%i\\%s\\%i\\%i\n' % (parm, |
|
2442 | 2454 | description, |
|
2443 | 2455 | isError, |
|
2444 | 2456 | units, |
|
2445 | 2457 | isMeasured, |
|
2446 | 2458 | category, |
|
2447 | 2459 | isSure, |
|
2448 | 2460 | isAddIncrement) |
|
2449 | 2461 | |
|
2450 | 2462 | return render(request, 'madweb/service.html', {'text': retStr}) |
|
2451 | 2463 | |
|
2452 | 2464 | |
|
2453 | 2465 | |
|
2454 | 2466 | def isprint_service(request): |
|
2455 | 2467 | """isprint_service runs the isprintService.py service. |
|
2456 | 2468 | |
|
2457 | 2469 | Inputs: |
|
2458 | 2470 | request/url - contains arguments: |
|
2459 | 2471 | |
|
2460 | 2472 | 'file': The full path to the file to be analyzed by isprint. If over 50 MB, returns error message. |
|
2461 | 2473 | |
|
2462 | 2474 | 'parms': Multiple requested parameters, space (+) separated. |
|
2463 | 2475 | |
|
2464 | 2476 | 'filters': Multiple of filters desired, as in isprint command |
|
2465 | 2477 | |
|
2466 | 2478 | 'user_fullname' user name |
|
2467 | 2479 | |
|
2468 | 2480 | 'user_email' user email |
|
2469 | 2481 | |
|
2470 | 2482 | 'user_affiliation' user affiliation |
|
2471 | 2483 | |
|
2472 | 2484 | 'output' - option argument specifying output file basename. Will be Hdf5 format if extension in |
|
2473 | 2485 | ('hdf5', 'h5', 'hdf'). Will be netCDF4 is extension is '.nc'. Otherwise ascii. If not |
|
2474 | 2486 | given, output is ascii. |
|
2475 | 2487 | |
|
2476 | 2488 | 'header': t for headers, f for no header. Defaults to no header. Ignored if not ascii output |
|
2477 | 2489 | |
|
2478 | 2490 | Returns data as either column delimited ascii, Hdf5, or netCDF4. |
|
2479 | 2491 | """ |
|
2480 | 2492 | madDB = madrigal.metadata.MadrigalDB() |
|
2481 | 2493 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
2482 | 2494 | |
|
2483 | 2495 | # get required arguments |
|
2484 | 2496 | thisFile = request.GET['file'] |
|
2485 | 2497 | parms = request.GET.getlist('parms') |
|
2486 | 2498 | filters = request.GET.getlist('filters') |
|
2487 | 2499 | user_fullname = request.GET['user_fullname'] |
|
2488 | 2500 | user_email = request.GET['user_email'] |
|
2489 | 2501 | user_affiliation = request.GET['user_affiliation'] |
|
2490 | 2502 | |
|
2491 | 2503 | # get optional arguments |
|
2492 | 2504 | try: |
|
2493 | 2505 | output = os.path.basename(request.GET['output']) |
|
2494 | 2506 | filename, file_extension = os.path.splitext(output) |
|
2495 | 2507 | if file_extension in ('.hdf5', '.h5', '.hdf'): |
|
2496 | 2508 | format = 'Hdf5' |
|
2497 | 2509 | elif file_extension in ('.nc',): |
|
2498 | 2510 | format = 'netCDF4' |
|
2499 | 2511 | else: |
|
2500 | 2512 | format = 'ascii' |
|
2501 | 2513 | except: |
|
2502 | 2514 | format = 'ascii' |
|
2503 | 2515 | output = None |
|
2504 | 2516 | |
|
2505 | 2517 | # verify thisFile exists, not too big |
|
2506 | 2518 | errorMessage = None |
|
2507 | 2519 | if not os.access(thisFile, os.R_OK): |
|
2508 | 2520 | errorMessage = 'File %s not found' % (thisFile) |
|
2509 | 2521 | elif os.path.getsize(thisFile) > 200.0E6: |
|
2510 | 2522 | errorMessage = 'File %s greater than 200 MB in size - running dynamic file creation not possible. Please use -- download as is -- instead.' % (thisFile) |
|
2511 | 2523 | if not errorMessage is None: |
|
2512 | 2524 | return render(request, 'madweb/service.html', {'text': errorMessage}) |
|
2513 | 2525 | |
|
2514 | 2526 | if not output is None: |
|
2515 | 2527 | # we need to write to a download file |
|
2516 | 2528 | downloadFile = os.path.join(tempfile.gettempdir(), output) |
|
2517 | 2529 | if os.access(downloadFile, os.R_OK): |
|
2518 | 2530 | try: |
|
2519 | 2531 | os.remove(downloadFile) |
|
2520 | 2532 | except: |
|
2521 | 2533 | pass |
|
2522 | 2534 | try: |
|
2523 | 2535 | header = request.GET['header'] |
|
2524 | 2536 | if header not in ('t', 'f'): |
|
2525 | 2537 | raise ValueError('Unknown header value <%s>' % (header)) |
|
2526 | 2538 | except: |
|
2527 | 2539 | header = 'f' |
|
2528 | 2540 | |
|
2529 | 2541 | # log data access |
|
2530 | 2542 | madWebObj.logDataAccess(thisFile, user_fullname, user_email, user_affiliation) |
|
2531 | 2543 | |
|
2532 | 2544 | # run isprint command |
|
2533 | 2545 | cmd = '%s/bin/isprint file=%s ' % (madDB.getMadroot(), thisFile) |
|
2534 | 2546 | if not output is None: |
|
2535 | 2547 | cmd += 'output=%s ' % (downloadFile) |
|
2536 | 2548 | delimiter = ' ' |
|
2537 | 2549 | cmd += delimiter.join(parms) + ' ' |
|
2538 | 2550 | filterStr = delimiter.join(filters) |
|
2539 | 2551 | cmd += filterStr + ' ' |
|
2540 | 2552 | if format == 'ascii': |
|
2541 | 2553 | cmd += 'summary=f ' |
|
2542 | 2554 | cmd += 'header=%s ' % (header) |
|
2543 | 2555 | |
|
2544 | 2556 | if output is None: |
|
2545 | 2557 | # text response |
|
2546 | 2558 | #result = subprocess.check_output(cmd.split()) |
|
2547 | 2559 | p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) |
|
2548 | 2560 | result,errtext = p.communicate() |
|
2549 | 2561 | if p.returncode != 0: |
|
2550 | 2562 | result = errtext |
|
2551 | 2563 | if type(result) in (bytes, numpy.bytes_): |
|
2552 | 2564 | result = result.decode('utf-8') |
|
2553 | 2565 | if header == 'f': |
|
2554 | 2566 | index = result.find('\n') |
|
2555 | 2567 | result = result[index+1:] |
|
2556 | 2568 | return render(request, 'madweb/service.html', {'text': result}) |
|
2557 | 2569 | else: |
|
2558 | 2570 | # file download response |
|
2559 | 2571 | #subprocess.check_call(cmd.split()) |
|
2560 | 2572 | p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) |
|
2561 | 2573 | result,errtext = p.communicate() |
|
2562 | 2574 | if p.returncode != 0: |
|
2563 | 2575 | # write the error to result file |
|
2564 | 2576 | f = open(downloadFile, 'w') |
|
2565 | 2577 | if type(errtext) in (bytes, numpy.bytes_): |
|
2566 | 2578 | errtext = errtext.decode('utf-8') |
|
2567 | 2579 | f.write(errtext) |
|
2568 | 2580 | f.close() |
|
2569 | 2581 | |
|
2570 | 2582 | f = open(downloadFile, 'rb') |
|
2571 | 2583 | filename = os.path.basename(downloadFile) |
|
2572 | 2584 | chunk_size = 8192 |
|
2573 | 2585 | file_type = mimetypes.guess_type(downloadFile)[0] |
|
2574 | 2586 | if file_type is None: |
|
2575 | 2587 | file_type = 'application/octet-stream' |
|
2576 | 2588 | response = StreamingHttpResponse(FileWrapper(f, chunk_size), |
|
2577 | 2589 | content_type=file_type) |
|
2578 | 2590 | response['Content-Length'] = os.path.getsize(downloadFile) |
|
2579 | 2591 | response['Content-Disposition'] = "attachment; filename=%s" % (filename) |
|
2580 | 2592 | os.remove(downloadFile) |
|
2581 | 2593 | return(response) |
|
2582 | 2594 | |
|
2583 | 2595 | |
|
2584 | 2596 | def get_madfile_service(request): |
|
2585 | 2597 | """get_madfile_service runs the getMadfile.cgi service. |
|
2586 | 2598 | |
|
2587 | 2599 | Inputs: |
|
2588 | 2600 | request/url - contains arguments: |
|
2589 | 2601 | |
|
2590 | 2602 | 'fileName': The full path to the file to be downloaded as. |
|
2591 | 2603 | |
|
2592 | 2604 | 'fileType': -1 for ascii, -2 for Hdf5, -3 for netCDF4. No other values supported |
|
2593 | 2605 | |
|
2594 | 2606 | 'user_fullname' user name |
|
2595 | 2607 | |
|
2596 | 2608 | 'user_email' user email |
|
2597 | 2609 | |
|
2598 | 2610 | 'user_affiliation' user affiliation |
|
2599 | 2611 | |
|
2600 | 2612 | Returns file as either column delimited ascii, Hdf5, or netCDF4. |
|
2601 | 2613 | """ |
|
2602 | 2614 | madDB = madrigal.metadata.MadrigalDB() |
|
2603 | 2615 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
2604 | 2616 | |
|
2605 | 2617 | # get required arguments |
|
2606 | 2618 | fileName = request.GET['fileName'] |
|
2607 | 2619 | fileType = int(request.GET['fileType']) |
|
2608 | 2620 | user_fullname = request.GET['user_fullname'] |
|
2609 | 2621 | user_email = request.GET['user_email'] |
|
2610 | 2622 | user_affiliation = request.GET['user_affiliation'] |
|
2611 | 2623 | |
|
2612 | 2624 | if fileType not in (-1, -2, -3): |
|
2613 | 2625 | return(HttpResponse('<p>fileType %i not allowed: -1 for ascii, -2 for Hdf5, -3 for netCDF4</p>' % (fileType))) |
|
2614 | 2626 | |
|
2615 | 2627 | # log data access |
|
2616 | 2628 | madWebObj.logDataAccess(fileName, user_fullname, user_email, user_affiliation) |
|
2617 | 2629 | |
|
2618 | 2630 | if fileType in (-1, -3): |
|
2619 | 2631 | # may need to create temp file |
|
2620 | 2632 | filepath, file_extension = os.path.splitext(fileName) |
|
2621 | 2633 | basename = os.path.basename(filepath) |
|
2622 | 2634 | dirname = os.path.dirname(fileName) |
|
2623 | 2635 | if fileType == -1: |
|
2624 | 2636 | cachedTxtFile = os.path.join(dirname, 'overview', os.path.basename(fileName) + '.txt.gz') |
|
2625 | 2637 | tmpFile = os.path.join(tempfile.gettempdir(), basename + '.txt.gz') |
|
2626 | 2638 | if os.access(cachedTxtFile, os.R_OK): |
|
2627 | 2639 | shutil.copy(cachedTxtFile, tmpFile) |
|
2628 | 2640 | else: |
|
2629 | 2641 | tmpFile = os.path.join(tempfile.gettempdir(), basename + '.txt') |
|
2630 | 2642 | madrigal.cedar.convertToText(fileName, tmpFile) |
|
2631 | 2643 | else: |
|
2632 | 2644 | cachedNCFile = os.path.join(dirname, 'overview', os.path.basename(fileName) + '.nc') |
|
2633 | 2645 | tmpFile = os.path.join(tempfile.gettempdir(), basename + '.nc') |
|
2634 | 2646 | if os.access(cachedNCFile, os.R_OK): |
|
2635 | 2647 | shutil.copy(cachedNCFile, tmpFile) |
|
2636 | 2648 | else: |
|
2637 | 2649 | try: |
|
2638 | 2650 | madrigal.cedar.convertToNetCDF4(fileName, tmpFile) |
|
2639 | 2651 | except IOError: |
|
2640 | 2652 | cedarObj = madrigal.cedar.MadrigalCedarFile(fileName) |
|
2641 | 2653 | cedarObj.write('netCDF4', tmpFile) |
|
2642 | 2654 | |
|
2643 | 2655 | else: |
|
2644 | 2656 | tmpFile = fileName |
|
2645 | 2657 | |
|
2646 | 2658 | f = open(tmpFile, 'rb') |
|
2647 | 2659 | filename = os.path.basename(tmpFile) |
|
2648 | 2660 | chunk_size = 8192 |
|
2649 | 2661 | file_type = mimetypes.guess_type(tmpFile)[0] |
|
2650 | 2662 | if file_type is None: |
|
2651 | 2663 | file_type = 'application/octet-stream' |
|
2652 | 2664 | response = StreamingHttpResponse(FileWrapper(f, chunk_size), |
|
2653 | 2665 | content_type=file_type) |
|
2654 | 2666 | response['Content-Length'] = os.path.getsize(tmpFile) |
|
2655 | 2667 | response['Content-Disposition'] = "attachment; filename=%s" % (filename) |
|
2656 | 2668 | if fileType in (-1, -3): |
|
2657 | 2669 | os.remove(tmpFile) |
|
2658 | 2670 | return(response) |
|
2659 | 2671 | |
|
2660 | 2672 | |
|
2661 | 2673 | def mad_calculator_service(request): |
|
2662 | 2674 | """mad_calculator_service runs the madCalculator service. |
|
2663 | 2675 | |
|
2664 | 2676 | Inputs: |
|
2665 | 2677 | request/url - contains arguments: |
|
2666 | 2678 | |
|
2667 | 2679 | year, month, day, hour, min, sec |
|
2668 | 2680 | |
|
2669 | 2681 | startLat - Starting geodetic latitude, -90 to 90 (float) |
|
2670 | 2682 | |
|
2671 | 2683 | endLat - Ending geodetic latitude, -90 to 90 (float) |
|
2672 | 2684 | |
|
2673 | 2685 | stepLat - Latitude step (0.1 to 90) (float) |
|
2674 | 2686 | |
|
2675 | 2687 | startLong - Starting geodetic longitude, -180 to 180 (float) |
|
2676 | 2688 | |
|
2677 | 2689 | endLong - Ending geodetic longitude, -180 to 180 (float) |
|
2678 | 2690 | |
|
2679 | 2691 | stepLong - Longitude step (0.1 to 180) (float) |
|
2680 | 2692 | |
|
2681 | 2693 | startAlt - Starting geodetic altitude, >= 0 (float) |
|
2682 | 2694 | |
|
2683 | 2695 | endAlt - Ending geodetic altitude, > 0 (float) |
|
2684 | 2696 | |
|
2685 | 2697 | stepAlt - Altitude step (>= 0.1) (float) |
|
2686 | 2698 | |
|
2687 | 2699 | parms - comma delimited string of Madrigal parameters desired |
|
2688 | 2700 | |
|
2689 | 2701 | oneD - zero or more mnemonics,float values to set input 1D values |
|
2690 | 2702 | |
|
2691 | 2703 | Returns comma-delimited data, one line for each combination of lat, long, and alt, |
|
2692 | 2704 | with the following fields: |
|
2693 | 2705 | |
|
2694 | 2706 | 1. latitude |
|
2695 | 2707 | |
|
2696 | 2708 | 2. longitude |
|
2697 | 2709 | |
|
2698 | 2710 | 3. altitude |
|
2699 | 2711 | |
|
2700 | 2712 | 4. Values for each Madrigal parameter listed in argument parms, separated by whitespace |
|
2701 | 2713 | """ |
|
2702 | 2714 | year = int(request.GET['year']) |
|
2703 | 2715 | month = int(request.GET['month']) |
|
2704 | 2716 | day = int(request.GET['day']) |
|
2705 | 2717 | hour = int(request.GET['hour']) |
|
2706 | 2718 | minute = int(request.GET['min']) |
|
2707 | 2719 | second = int(request.GET['sec']) |
|
2708 | 2720 | try: |
|
2709 | 2721 | dt = datetime.datetime(year, month, day, hour, minute, second) |
|
2710 | 2722 | except: |
|
2711 | 2723 | return(HttpResponse('Illegal time: year %i, month %i, day %i, hour %i, minute %i, second %i' % (year, month, day, hour, minute, second))) |
|
2712 | 2724 | |
|
2713 | 2725 | startLat = float(request.GET['startLat']) |
|
2714 | 2726 | endLat = float(request.GET['endLat']) |
|
2715 | 2727 | if startLat == endLat: |
|
2716 | 2728 | endLat += 0.001 |
|
2717 | 2729 | elif startLat > endLat: |
|
2718 | 2730 | return(HttpResponse('startLat %s cannot be greater than endLat %s' % (str(startLat), str(endLat)))) |
|
2719 | 2731 | stepLat = float(request.GET['stepLat']) |
|
2720 | 2732 | if stepLat < 0.0: |
|
2721 | 2733 | return(HttpResponse('stepLat %s cannot be less than zero' % (str(stepLat)))) |
|
2722 | 2734 | elif stepLat == 0.0: |
|
2723 | 2735 | stepLat = 0.001 |
|
2724 | 2736 | latList = list(numpy.arange(startLat, endLat, stepLat)) |
|
2725 | 2737 | |
|
2726 | 2738 | startLong = float(request.GET['startLong']) |
|
2727 | 2739 | endLong = float(request.GET['endLong']) |
|
2728 | 2740 | if startLong == endLong: |
|
2729 | 2741 | endLong += 0.001 |
|
2730 | 2742 | elif startLong > endLong: |
|
2731 | 2743 | return(HttpResponse('startLong %s cannot be greater than endLong %s' % (str(startLong), str(endLong)))) |
|
2732 | 2744 | stepLong = float(request.GET['stepLong']) |
|
2733 | 2745 | if stepLong < 0.0: |
|
2734 | 2746 | return(HttpResponse('stepLong %s cannot be less than zero' % (str(stepLong)))) |
|
2735 | 2747 | elif stepLong == 0.0: |
|
2736 | 2748 | stepLong = 0.001 |
|
2737 | 2749 | lonList = list(numpy.arange(startLong, endLong, stepLong)) |
|
2738 | 2750 | |
|
2739 | 2751 | startAlt = float(request.GET['startAlt']) |
|
2740 | 2752 | endAlt = float(request.GET['endAlt']) |
|
2741 | 2753 | if startAlt == endAlt: |
|
2742 | 2754 | endAlt += 0.001 |
|
2743 | 2755 | elif startAlt > endAlt: |
|
2744 | 2756 | return(HttpResponse('startAlt %s cannot be greater than endAlt %s' % (str(startAlt), str(endAlt)))) |
|
2745 | 2757 | stepAlt = float(request.GET['stepAlt']) |
|
2746 | 2758 | if stepAlt < 0.0: |
|
2747 | 2759 | return(HttpResponse('stepAlt %s cannot be less than zero' % (str(stepAlt)))) |
|
2748 | 2760 | elif stepAlt == 0.0: |
|
2749 | 2761 | stepAlt = 0.01 |
|
2750 | 2762 | altList = list(numpy.arange(startAlt, endAlt, stepAlt)) |
|
2751 | 2763 | |
|
2752 | 2764 | # limit total calculations to 1E5 |
|
2753 | 2765 | total = len(latList) * len(lonList) * len(altList) |
|
2754 | 2766 | if total > 1.0E5: |
|
2755 | 2767 | return(HttpResponse('Too many points for madCalculatorService: %i' % (total))) |
|
2756 | 2768 | |
|
2757 | 2769 | parms = request.GET['parms'] |
|
2758 | 2770 | desiredParmList = [item.strip() for item in ['gdlat','glon','gdalt'] + parms.split(',')] |
|
2759 | 2771 | |
|
2760 | 2772 | oneDList = request.GET.getlist('oneD') |
|
2761 | 2773 | oneDParmDict = {} |
|
2762 | 2774 | for oneDStr in oneDList: |
|
2763 | 2775 | mnem, strValue = oneDStr.split(',') |
|
2764 | 2776 | oneDParmDict[mnem] = [float(strValue)] |
|
2765 | 2777 | |
|
2766 | 2778 | # capture stdout |
|
2767 | 2779 | old_stdout = sys.stdout |
|
2768 | 2780 | sys.stdout = mystdout = io.StringIO() |
|
2769 | 2781 | madrigal.isprint.MadCalculatorGrid(None, desiredParmList, [dt], latList, lonList, altList, |
|
2770 | 2782 | oneDParmDict, summary=None) |
|
2771 | 2783 | text = mystdout.getvalue() |
|
2772 | 2784 | sys.stdout = old_stdout |
|
2773 | 2785 | |
|
2774 | 2786 | return render(request, 'madweb/service.html', {'text': text}) |
|
2775 | 2787 | |
|
2776 | 2788 | |
|
2777 | 2789 | def mad_time_calculator_service(request): |
|
2778 | 2790 | """mad_time_calculator_service runs the madTimeCalculator service. Input parameters must not be location dependent |
|
2779 | 2791 | |
|
2780 | 2792 | Inputs: |
|
2781 | 2793 | request/url - contains arguments: |
|
2782 | 2794 | |
|
2783 | 2795 | 1. startyear - int |
|
2784 | 2796 | |
|
2785 | 2797 | 2. startmonth - int |
|
2786 | 2798 | |
|
2787 | 2799 | 3. startday - int |
|
2788 | 2800 | |
|
2789 | 2801 | 4. starthour - int |
|
2790 | 2802 | |
|
2791 | 2803 | 5. startmin - int |
|
2792 | 2804 | |
|
2793 | 2805 | 6. startsec - int |
|
2794 | 2806 | |
|
2795 | 2807 | 7. endyear - int |
|
2796 | 2808 | |
|
2797 | 2809 | 8. endmonth - int |
|
2798 | 2810 | |
|
2799 | 2811 | 9. endday - int |
|
2800 | 2812 | |
|
2801 | 2813 | 10. endhour - int |
|
2802 | 2814 | |
|
2803 | 2815 | 11. endmin - int |
|
2804 | 2816 | |
|
2805 | 2817 | 12. endsec - int |
|
2806 | 2818 | |
|
2807 | 2819 | 13. stephours - float - number of hours per time step |
|
2808 | 2820 | |
|
2809 | 2821 | 14. parms - comma delimited string of Madrigal parameters desired (must not depend on location) |
|
2810 | 2822 | |
|
2811 | 2823 | Returns comma-delimited data, one line for each year, month, day, hour, minute, and second, |
|
2812 | 2824 | with the following fields: |
|
2813 | 2825 | |
|
2814 | 2826 | 1-6: year, month, day, hour, minute, and second |
|
2815 | 2827 | |
|
2816 | 2828 | 2. requested parm fields |
|
2817 | 2829 | """ |
|
2818 | 2830 | startyear = int(request.GET['startyear']) |
|
2819 | 2831 | startmonth = int(request.GET['startmonth']) |
|
2820 | 2832 | startday = int(request.GET['startday']) |
|
2821 | 2833 | starthour = int(request.GET['starthour']) |
|
2822 | 2834 | startminute = int(request.GET['startmin']) |
|
2823 | 2835 | startsecond = int(request.GET['startsec']) |
|
2824 | 2836 | endyear = int(request.GET['endyear']) |
|
2825 | 2837 | endmonth = int(request.GET['endmonth']) |
|
2826 | 2838 | endday = int(request.GET['endday']) |
|
2827 | 2839 | endhour = int(request.GET['endhour']) |
|
2828 | 2840 | endminute = int(request.GET['endmin']) |
|
2829 | 2841 | endsecond = int(request.GET['endsec']) |
|
2830 | 2842 | dt1 = datetime.datetime(startyear, startmonth, startday, starthour, startminute, startsecond) |
|
2831 | 2843 | dt2 = datetime.datetime(endyear, endmonth, endday, endhour, endminute, endsecond) |
|
2832 | 2844 | if dt1 > dt2: |
|
2833 | 2845 | return(HttpResponse('End Datetime %s cannot be before start datetime %s' % (str(dt2), str(dt1)))) |
|
2834 | 2846 | |
|
2835 | 2847 | stephours = float(request.GET['stephours']) |
|
2836 | 2848 | if stephours <= 0.0: |
|
2837 | 2849 | return(HttpResponse('stephours cannot be non-positive: %f' % (stephours))) |
|
2838 | 2850 | |
|
2839 | 2851 | dtList = [] |
|
2840 | 2852 | while dt1 <= dt2: |
|
2841 | 2853 | dtList.append(dt1) |
|
2842 | 2854 | dt1 += datetime.timedelta(hours=stephours) |
|
2843 | 2855 | |
|
2844 | 2856 | parms = request.GET['parms'] |
|
2845 | 2857 | desiredParmList = [item.strip() for item in ['year','month','day','hour','min','sec'] + parms.split(',')] |
|
2846 | 2858 | |
|
2847 | 2859 | # no spatial data |
|
2848 | 2860 | latList = lonList = altList = [] |
|
2849 | 2861 | # capture stdout |
|
2850 | 2862 | old_stdout = sys.stdout |
|
2851 | 2863 | sys.stdout = mystdout = io.StringIO() |
|
2852 | 2864 | madrigal.isprint.MadCalculatorGrid(None, desiredParmList, dtList, latList, lonList, altList, |
|
2853 | 2865 | summary=None) |
|
2854 | 2866 | text = mystdout.getvalue() |
|
2855 | 2867 | sys.stdout = old_stdout |
|
2856 | 2868 | |
|
2857 | 2869 | return render(request, 'madweb/service.html', {'text': text}) |
|
2858 | 2870 | |
|
2859 | 2871 | |
|
2860 | 2872 | |
|
2861 | 2873 | @csrf_exempt |
|
2862 | 2874 | def mad_calculator2_service(request): |
|
2863 | 2875 | """mad_calculator2_service runs the madCalculator2 service. |
|
2864 | 2876 | |
|
2865 | 2877 | Differs from madCalulator in that positions are a list rather than a grid. |
|
2866 | 2878 | |
|
2867 | 2879 | Inputs: |
|
2868 | 2880 | request/url - contains arguments: |
|
2869 | 2881 | |
|
2870 | 2882 | year, month, day, hour, min, sec |
|
2871 | 2883 | |
|
2872 | 2884 | lats - comma separated list of latitudes to analyze |
|
2873 | 2885 | |
|
2874 | 2886 | longs - comma separated list of longitudes to analyze. Len must == len(lats) |
|
2875 | 2887 | |
|
2876 | 2888 | alts - comma separated list of altitudes to analyze. Len must == len(lats) |
|
2877 | 2889 | |
|
2878 | 2890 | parms - comma delimited string of Madrigal parameters desired |
|
2879 | 2891 | |
|
2880 | 2892 | oneD - zero or more mnemonics,float values to set input 1D values |
|
2881 | 2893 | Example: &oneD=kinst,31.0&oneD=elm,45.0 |
|
2882 | 2894 | |
|
2883 | 2895 | twoD - zero or more mnemonics,comma-separate float list of len(lats) to set input 2D values |
|
2884 | 2896 | Example: twoD=te,1000,1100,1200 twoD=ti,1000,1000,1000 |
|
2885 | 2897 | where there are 3 lats |
|
2886 | 2898 | |
|
2887 | 2899 | Returns comma-delimited data, one line for each lat value, |
|
2888 | 2900 | with the following fields: |
|
2889 | 2901 | |
|
2890 | 2902 | 1. latitude |
|
2891 | 2903 | |
|
2892 | 2904 | 2. longitude |
|
2893 | 2905 | |
|
2894 | 2906 | 3. altitude |
|
2895 | 2907 | |
|
2896 | 2908 | 4. Values for each Madrigal parameter listed in argument parms, separated by whitespace |
|
2897 | 2909 | """ |
|
2898 | 2910 | if request.method == 'POST': |
|
2899 | 2911 | reqDict = request.POST |
|
2900 | 2912 | else: |
|
2901 | 2913 | reqDict = request.GET |
|
2902 | 2914 | try: |
|
2903 | 2915 | year = int(reqDict.get('year')) |
|
2904 | 2916 | except TypeError: |
|
2905 | 2917 | return(HttpResponse('<p>madCalculator2Service requires year</p>')) |
|
2906 | 2918 | month = int(reqDict['month']) |
|
2907 | 2919 | day = int(reqDict['day']) |
|
2908 | 2920 | hour = int(reqDict['hour']) |
|
2909 | 2921 | minute = int(reqDict['min']) |
|
2910 | 2922 | second = int(reqDict['sec']) |
|
2911 | 2923 | dt = datetime.datetime(year, month, day, hour, minute, second) |
|
2912 | 2924 | |
|
2913 | 2925 | latsStr = reqDict['lats'] |
|
2914 | 2926 | lats = [float(item) for item in latsStr.split(',')] |
|
2915 | 2927 | longsStr = reqDict['longs'] |
|
2916 | 2928 | longs = [float(item) for item in longsStr.split(',')] |
|
2917 | 2929 | altsStr = reqDict['alts'] |
|
2918 | 2930 | alts = [float(item) for item in altsStr.split(',')] |
|
2919 | 2931 | |
|
2920 | 2932 | parms = reqDict['parms'] |
|
2921 | 2933 | desiredParmList = [item.strip() for item in ['gdlat','glon','gdalt'] + parms.split(',')] |
|
2922 | 2934 | |
|
2923 | 2935 | oneDList = reqDict.getlist('oneD') |
|
2924 | 2936 | oneDParmDict = {} |
|
2925 | 2937 | for oneDStr in oneDList: |
|
2926 | 2938 | mnem, strValue = oneDStr.split(',') |
|
2927 | 2939 | oneDParmDict[mnem] = [float(strValue)] |
|
2928 | 2940 | |
|
2929 | 2941 | twoDList = reqDict.getlist('twoD') |
|
2930 | 2942 | |
|
2931 | 2943 | twoDParmDict = {} |
|
2932 | 2944 | for twoDStr in twoDList: |
|
2933 | 2945 | items = twoDStr.split(',') |
|
2934 | 2946 | if len(items) != 1 + len(lats): |
|
2935 | 2947 | raise ValueError('twoDstr %s not correct number of points' % (str(twoDStr))) |
|
2936 | 2948 | mnem = items[0] |
|
2937 | 2949 | floatValues = [float(item) for item in items[1:]] |
|
2938 | 2950 | # now we need to expand these values to be two dimensional 1 x len(lats) |
|
2939 | 2951 | values = numpy.zeros((1,len(lats)), dtype=numpy.float) |
|
2940 | 2952 | values[0][:] = floatValues |
|
2941 | 2953 | twoDParmDict[mnem] = values |
|
2942 | 2954 | |
|
2943 | 2955 | # capture stdout |
|
2944 | 2956 | old_stdout = sys.stdout |
|
2945 | 2957 | sys.stdout = mystdout = io.StringIO() |
|
2946 | 2958 | madrigal.isprint.MadCalculatorList(None, desiredParmList, [dt], lats, longs, alts, |
|
2947 | 2959 | oneDParmDict, twoDParmDict, summary=None) |
|
2948 | 2960 | text = mystdout.getvalue() |
|
2949 | 2961 | sys.stdout = old_stdout |
|
2950 | 2962 | |
|
2951 | 2963 | return render(request, 'madweb/service.html', {'text': text}) |
|
2952 | 2964 | |
|
2953 | 2965 | |
|
2954 | 2966 | |
|
2955 | 2967 | |
|
2956 | 2968 | @csrf_exempt |
|
2957 | 2969 | def mad_calculator3_service(request): |
|
2958 | 2970 | """mad_calculator3_service runs the madCalculator3 service. |
|
2959 | 2971 | |
|
2960 | 2972 | Differs from madCalulator in that multiple times, each with a unique list of positions, can be passed in. |
|
2961 | 2973 | |
|
2962 | 2974 | Inputs: |
|
2963 | 2975 | request/url - contains arguments: |
|
2964 | 2976 | |
|
2965 | 2977 | year - a comma-separated list of years - (required) |
|
2966 | 2978 | |
|
2967 | 2979 | month - a comma-separated list of months - (required) |
|
2968 | 2980 | |
|
2969 | 2981 | day - a comma-separated list of days - (required) |
|
2970 | 2982 | |
|
2971 | 2983 | hour - a comma-separated list of hours - (required) |
|
2972 | 2984 | |
|
2973 | 2985 | min - a comma-separated list of minutes - (required) |
|
2974 | 2986 | |
|
2975 | 2987 | sec - a comma-separated list of seconds - (required) |
|
2976 | 2988 | |
|
2977 | 2989 | numPos - a comma-sepatated list of the number of positions for each time - (required) |
|
2978 | 2990 | |
|
2979 | 2991 | lats - a comma-separated list of geodetic latitudes, -90 to 90 (required). Listed |
|
2980 | 2992 | for first time, then second, etc. Total must be equal to the sum |
|
2981 | 2993 | of numPos. |
|
2982 | 2994 | |
|
2983 | 2995 | longs - a comma-separated list of longitudes (required) Listed |
|
2984 | 2996 | for first time, then second, etc. Total must be equal to the sum |
|
2985 | 2997 | of numPos. |
|
2986 | 2998 | |
|
2987 | 2999 | alts - a comma-separated list of geodetic altitudes in km (required) Listed |
|
2988 | 3000 | for first time, then second, etc. Total must be equal to the sum |
|
2989 | 3001 | of numPos. |
|
2990 | 3002 | |
|
2991 | 3003 | parms - comma delimited string of Madrigal parameters desired (required) |
|
2992 | 3004 | |
|
2993 | 3005 | oneD - string in form <parm>,<comma-separated values> This argument allows the user to |
|
2994 | 3006 | set any number of one-D parameters to be used in the calculation. |
|
2995 | 3007 | Value must be parameter name, comma, list of values as double, |
|
2996 | 3008 | where length of list is equal to number of times. |
|
2997 | 3009 | Example: &oneD=kinst,31.0,31.0&oneD=elm,45.0,50 |
|
2998 | 3010 | (optional - 0 or more allowed) |
|
2999 | 3011 | |
|
3000 | 3012 | twoD=<parm>,<values> (optional - 0 or more allowed) This argument allows the user to |
|
3001 | 3013 | set any number of two-D parameters to be used in the calculation. |
|
3002 | 3014 | Value must be parameter name, comma, comma-separated values. |
|
3003 | 3015 | Number of values must equal the sum of numPos. Order is |
|
3004 | 3016 | first time values first, then second time values, etc |
|
3005 | 3017 | Example: twoD=te,1000,1100,1200,1000,1100,1200 &twoD=ti,1000,1000,1000,1000,1000,1000 |
|
3006 | 3018 | where numPos=3,3 |
|
3007 | 3019 | |
|
3008 | 3020 | Returns comma-delimited data, one line for each location. Separate times are delimited by line |
|
3009 | 3021 | |
|
3010 | 3022 | TIME MM/DD/YYYY HH:MM:SS |
|
3011 | 3023 | |
|
3012 | 3024 | Data lines have the following fields: |
|
3013 | 3025 | |
|
3014 | 3026 | 1. latitude |
|
3015 | 3027 | |
|
3016 | 3028 | 2. longitude |
|
3017 | 3029 | |
|
3018 | 3030 | 3. altitude |
|
3019 | 3031 | |
|
3020 | 3032 | 4. Values for each Madrigal parameter listed in argument parms, separated by whitespace |
|
3021 | 3033 | """ |
|
3022 | 3034 | if request.method == 'POST': |
|
3023 | 3035 | reqDict = request.POST |
|
3024 | 3036 | else: |
|
3025 | 3037 | reqDict = request.GET |
|
3026 | 3038 | try: |
|
3027 | 3039 | yearList = [int(item) for item in reqDict.get('year').split(',')] |
|
3028 | 3040 | except AttributeError: |
|
3029 | 3041 | return(HttpResponse('<p>madCalculator3Service requires year</p>')) |
|
3030 | 3042 | monthList = [int(item) for item in reqDict.get('month').split(',')] |
|
3031 | 3043 | dayList = [int(item) for item in reqDict.get('day').split(',')] |
|
3032 | 3044 | hourList = [int(item) for item in reqDict.get('hour').split(',')] |
|
3033 | 3045 | minList = [int(item) for item in reqDict.get('min').split(',')] |
|
3034 | 3046 | secList = [int(item) for item in reqDict.get('sec').split(',')] |
|
3035 | 3047 | dtList = [datetime.datetime(yearList[i], monthList[i], dayList[i], |
|
3036 | 3048 | hourList[i], minList[i], secList[i]) for i in range(len(yearList))] |
|
3037 | 3049 | numPosStr = reqDict['numPos'] |
|
3038 | 3050 | numPosList = [int(item) for item in numPosStr.split(',')] |
|
3039 | 3051 | totalPos = 0 |
|
3040 | 3052 | for numPos in numPosList: |
|
3041 | 3053 | totalPos += numPos |
|
3042 | 3054 | latsStr = reqDict['lats'] |
|
3043 | 3055 | lats = [float(item) for item in latsStr.split(',')] |
|
3044 | 3056 | if len(lats) != totalPos: |
|
3045 | 3057 | return(HttpResponse('wrong number of lats, expected %i' % (totalPos))) |
|
3046 | 3058 | longsStr = reqDict['longs'] |
|
3047 | 3059 | longs = [float(item) for item in longsStr.split(',')] |
|
3048 | 3060 | if len(longs) != totalPos: |
|
3049 | 3061 | return(HttpResponse('wrong number of longs, expected %i' % (totalPos))) |
|
3050 | 3062 | altsStr = reqDict['alts'] |
|
3051 | 3063 | alts = [float(item) for item in altsStr.split(',')] |
|
3052 | 3064 | if len(alts) != totalPos: |
|
3053 | 3065 | return(HttpResponse('wrong number of alts, expected %i' % (totalPos))) |
|
3054 | 3066 | |
|
3055 | 3067 | parms = reqDict['parms'] |
|
3056 | 3068 | desiredParmList = [item.strip() for item in ['gdlat','glon','gdalt'] + parms.split(',')] |
|
3057 | 3069 | |
|
3058 | 3070 | oneDList = reqDict.getlist('oneD') |
|
3059 | 3071 | twoDList = reqDict.getlist('twoD') |
|
3060 | 3072 | |
|
3061 | 3073 | # since the positions can change with each call, we need to call madrigal.isprint.MadCalculatorGrid once for each time |
|
3062 | 3074 | startIndex = 0 |
|
3063 | 3075 | endIndex = 0 |
|
3064 | 3076 | fullText = '' |
|
3065 | 3077 | for timeIndex, numPos in enumerate(numPosList): |
|
3066 | 3078 | startIndex = endIndex |
|
3067 | 3079 | endIndex += numPos |
|
3068 | 3080 | thisLats = lats[startIndex:endIndex] |
|
3069 | 3081 | thisLongs = longs[startIndex:endIndex] |
|
3070 | 3082 | thisAlts = alts[startIndex:endIndex] |
|
3071 | 3083 | |
|
3072 | 3084 | oneDParmDict = {} |
|
3073 | 3085 | for oneDStr in oneDList: |
|
3074 | 3086 | values = oneDStr.split(',') |
|
3075 | 3087 | if len(values) != 1+len(dtList): |
|
3076 | 3088 | return(HttpResponse('wrong number of values given for 1D parm %s' % (values[0]))) |
|
3077 | 3089 | oneDParmDict[values[0]] = [float(values[timeIndex+1])] |
|
3078 | 3090 | |
|
3079 | 3091 | twoDParmDict = {} |
|
3080 | 3092 | |
|
3081 | 3093 | for twoDStr in twoDList: |
|
3082 | 3094 | values = twoDStr.split(',') |
|
3083 | 3095 | if len(values) != 1 + totalPos: |
|
3084 | 3096 | return(HttpResponse('twoDstr %s not correct number of points' % (str(twoDStr)))) |
|
3085 | 3097 | mnem = values[0] |
|
3086 | 3098 | floatValues = [float(item) for item in values[1+startIndex:1+endIndex]] |
|
3087 | 3099 | # now we need to expand these values to be two dimensional - 1,len(thisLats) |
|
3088 | 3100 | values2D = numpy.zeros((1,len(thisLats)), dtype=numpy.float) |
|
3089 | 3101 | values2D[0][:] = floatValues |
|
3090 | 3102 | twoDParmDict[mnem] = values2D |
|
3091 | 3103 | |
|
3092 | 3104 | |
|
3093 | 3105 | |
|
3094 | 3106 | # capture stdout |
|
3095 | 3107 | old_stdout = sys.stdout |
|
3096 | 3108 | sys.stdout = mystdout = io.StringIO() |
|
3097 | 3109 | madrigal.isprint.MadCalculatorList(None, desiredParmList, [dtList[timeIndex]], thisLats, |
|
3098 | 3110 | thisLongs, thisAlts, |
|
3099 | 3111 | oneDParmDict, twoDParmDict, summary=None) |
|
3100 | 3112 | text = mystdout.getvalue() |
|
3101 | 3113 | sys.stdout = old_stdout |
|
3102 | 3114 | |
|
3103 | 3115 | fullText += 'TIME %s\n' % (dtList[timeIndex].strftime('%m/%d/%Y %H:%M:%S')) |
|
3104 | 3116 | fullText += text |
|
3105 | 3117 | |
|
3106 | 3118 | return render(request, 'madweb/service.html', {'text': fullText}) |
|
3107 | 3119 | |
|
3108 | 3120 | |
|
3109 | 3121 | |
|
3110 | 3122 | def geodetic_to_radar_service(request): |
|
3111 | 3123 | """geodetic_to_radar_service runs the geodeticToRadar service. |
|
3112 | 3124 | |
|
3113 | 3125 | Inputs: |
|
3114 | 3126 | request/url - contains arguments: |
|
3115 | 3127 | |
|
3116 | 3128 | slatgd - radar geodetic latitude |
|
3117 | 3129 | |
|
3118 | 3130 | slon - radar longitude |
|
3119 | 3131 | |
|
3120 | 3132 | saltgd - radar geodetic altitude |
|
3121 | 3133 | |
|
3122 | 3134 | gdlat - a comma-separated list of geodetic latitude of point |
|
3123 | 3135 | |
|
3124 | 3136 | glon - a comma-separated list of longitude of point. Len must be same as gdlat |
|
3125 | 3137 | |
|
3126 | 3138 | gdalt - a comma-separated list of geodetic altitude of point. Len must be same as gdlat |
|
3127 | 3139 | |
|
3128 | 3140 | |
|
3129 | 3141 | Returns comma-delimited data, one line for point in lists (points treated as individual combinations, not grids): |
|
3130 | 3142 | |
|
3131 | 3143 | 1. radar azimuth in degrees (0 = north) |
|
3132 | 3144 | |
|
3133 | 3145 | 2. radar elevation in degrees |
|
3134 | 3146 | |
|
3135 | 3147 | 3. radar range in km |
|
3136 | 3148 | """ |
|
3137 | 3149 | slatgd = float(request.GET['slatgd']) |
|
3138 | 3150 | slon = float(request.GET['slon']) |
|
3139 | 3151 | saltgd = float(request.GET['saltgd']) |
|
3140 | 3152 | oneDParmDict = {'GDLATR': [slatgd], |
|
3141 | 3153 | 'GDLONR': [slon], |
|
3142 | 3154 | 'GALTR': [saltgd]} |
|
3143 | 3155 | gdlatStr = request.GET['gdlat'] |
|
3144 | 3156 | gdlatList = [float(item) for item in gdlatStr.split(',')] |
|
3145 | 3157 | glonStr = request.GET['glon'] |
|
3146 | 3158 | glonList = [float(item) for item in glonStr.split(',')] |
|
3147 | 3159 | gdaltStr = request.GET['gdalt'] |
|
3148 | 3160 | gdaltList = [float(item) for item in gdaltStr.split(',')] |
|
3149 | 3161 | desiredParmList = ['azm', 'elm', 'range'] |
|
3150 | 3162 | dtList = [datetime.datetime(2001,1,1)] # not relevant |
|
3151 | 3163 | if len(gdlatList) != len(glonList) or len(gdlatList) != len(gdaltList): |
|
3152 | 3164 | return(HttpResponse('all point list lengths must be equal')) |
|
3153 | 3165 | |
|
3154 | 3166 | fullText = '' |
|
3155 | 3167 | |
|
3156 | 3168 | delimiter = ',' |
|
3157 | 3169 | for i in range(len(gdlatList)): |
|
3158 | 3170 | # capture stdout |
|
3159 | 3171 | old_stdout = sys.stdout |
|
3160 | 3172 | sys.stdout = mystdout = io.StringIO() |
|
3161 | 3173 | madrigal.isprint.MadCalculatorGrid(None, desiredParmList, dtList, [gdlatList[i]], |
|
3162 | 3174 | [glonList[i]], [gdaltList[i]], summary=None, |
|
3163 | 3175 | oneDParmDict=oneDParmDict) |
|
3164 | 3176 | text = mystdout.getvalue() |
|
3165 | 3177 | sys.stdout = old_stdout |
|
3166 | 3178 | for line in text.split('\n'): |
|
3167 | 3179 | items = line.split() |
|
3168 | 3180 | fullText += delimiter.join(items) + '\n' |
|
3169 | 3181 | |
|
3170 | 3182 | return render(request, 'madweb/service.html', {'text': fullText}) |
|
3171 | 3183 | |
|
3172 | 3184 | |
|
3173 | 3185 | def radar_to_geodetic_service(request): |
|
3174 | 3186 | """radar_to_geodetic_service runs the radarToGeodetic service. |
|
3175 | 3187 | |
|
3176 | 3188 | Inputs: |
|
3177 | 3189 | request/url - contains arguments: |
|
3178 | 3190 | |
|
3179 | 3191 | slatgd - radar geodetic latitude |
|
3180 | 3192 | |
|
3181 | 3193 | slon - radar longitude |
|
3182 | 3194 | |
|
3183 | 3195 | saltgd - radar geodetic altitude |
|
3184 | 3196 | |
|
3185 | 3197 | azs - a comma-separated list of azimuths of point |
|
3186 | 3198 | |
|
3187 | 3199 | els - a comma-separated list of elevations of point. Len must be same as azs |
|
3188 | 3200 | |
|
3189 | 3201 | ranges - a comma-separated list of ranges to point. Len must be same as azs |
|
3190 | 3202 | |
|
3191 | 3203 | |
|
3192 | 3204 | Returns comma-delimited data, one line for point in lists (points treated as individual combinations, not grids): |
|
3193 | 3205 | |
|
3194 | 3206 | 1. geodetic latitude |
|
3195 | 3207 | |
|
3196 | 3208 | 2. longitude (-180 to 180) |
|
3197 | 3209 | |
|
3198 | 3210 | 3. geodetic altitude in km |
|
3199 | 3211 | """ |
|
3200 | 3212 | slatgd = float(request.GET['slatgd']) |
|
3201 | 3213 | slon = float(request.GET['slon']) |
|
3202 | 3214 | saltgd = float(request.GET['saltgd']) |
|
3203 | 3215 | azStr = request.GET['az'] |
|
3204 | 3216 | azList = [float(item) for item in azStr.split(',')] |
|
3205 | 3217 | elStr = request.GET['el'] |
|
3206 | 3218 | elList = [float(item) for item in elStr.split(',')] |
|
3207 | 3219 | rangeStr = request.GET['range'] |
|
3208 | 3220 | rangeList = [float(item) for item in rangeStr.split(',')] |
|
3209 | 3221 | if len(azList) != len(elList) or len(azList) != len(rangeList): |
|
3210 | 3222 | return(HttpResponse('all point list lengths must be equal')) |
|
3211 | 3223 | |
|
3212 | 3224 | fullText = '' |
|
3213 | 3225 | |
|
3214 | 3226 | for i in range(len(azList)): |
|
3215 | 3227 | gdlat,glon,gdalt = madrigal._derive.radarToGeodetic(slatgd, slon, saltgd, |
|
3216 | 3228 | azList[i], elList[i], rangeList[i]) |
|
3217 | 3229 | fullText += '%f,%f,%f\n' % (gdlat,glon,gdalt) |
|
3218 | 3230 | |
|
3219 | 3231 | return render(request, 'madweb/service.html', {'text': fullText}) |
|
3220 | 3232 | |
|
3221 | 3233 | |
|
3222 | 3234 | |
|
3223 | 3235 | def list_file_times_service(request): |
|
3224 | 3236 | """list_file_times_service runs the listFileTimes service. |
|
3225 | 3237 | |
|
3226 | 3238 | Inputs: |
|
3227 | 3239 | request/url - contains arguments: |
|
3228 | 3240 | |
|
3229 | 3241 | Optional: expDir - experiment directory to list. Can be absolute or relative to |
|
3230 | 3242 | experiments[0-9]*. Default is all files in $MADROOT/experiments* |
|
3231 | 3243 | |
|
3232 | 3244 | Returns comma-delimited data, one for each file: |
|
3233 | 3245 | |
|
3234 | 3246 | 1. Full path of file |
|
3235 | 3247 | |
|
3236 | 3248 | 2. File modification time in form YYYY-MM-DD HH:MM:SS (UT time) |
|
3237 | 3249 | """ |
|
3238 | 3250 | expDir = None |
|
3239 | 3251 | try: |
|
3240 | 3252 | expDir = request.GET['expDir'] |
|
3241 | 3253 | except: |
|
3242 | 3254 | pass |
|
3243 | 3255 | madDB = madrigal.metadata.MadrigalDB() |
|
3244 | 3256 | fileList = madDB.listFileTimes(expDir) |
|
3245 | 3257 | fullText = '\n\n' |
|
3246 | 3258 | for filename, filetime in fileList: |
|
3247 | 3259 | fullText += "\'%s\', %s\n" % (filename, filetime.strftime('%Y-%m-%d %H:%M:%S')) |
|
3248 | 3260 | |
|
3249 | 3261 | return render(request, 'madweb/service.html', {'text': django.utils.safestring.mark_safe(fullText)}) |
|
3250 | 3262 | |
|
3251 | 3263 | |
|
3252 | 3264 | def download_web_file_service(request): |
|
3253 | 3265 | """download_web_file_service runs the downloadWebFile service. |
|
3254 | 3266 | |
|
3255 | 3267 | Inputs: |
|
3256 | 3268 | request/url - contains arguments: |
|
3257 | 3269 | |
|
3258 | 3270 | expPath - path to file starting at experiments* |
|
3259 | 3271 | |
|
3260 | 3272 | Returns comma-delimited data, one for each file: |
|
3261 | 3273 | |
|
3262 | 3274 | 1. Full path of file |
|
3263 | 3275 | |
|
3264 | 3276 | 2. File modification time in form YYYY-MM-DD HH:MM:SS (UT time) |
|
3265 | 3277 | """ |
|
3266 | 3278 | expPath = request.GET['expPath'] |
|
3267 | 3279 | madDB = madrigal.metadata.MadrigalDB() |
|
3268 | 3280 | downloadFile = os.path.join(madDB.getMadroot(), expPath) |
|
3269 | 3281 | f = open(downloadFile, 'rb') |
|
3270 | 3282 | thisFile = django.core.files.File(f) |
|
3271 | 3283 | response = HttpResponse(thisFile, content_type='application/x-octet-stream') |
|
3272 | 3284 | response['Content-Disposition'] = 'attachment; filename="' + os.path.basename(downloadFile) + '"' |
|
3273 | 3285 | response['Content-Length'] = os.path.getsize(downloadFile) |
|
3274 | 3286 | return(response) |
|
3275 | 3287 | |
|
3276 | 3288 | |
|
3277 | 3289 | def trace_magnetic_field_service(request): |
|
3278 | 3290 | """trace_magnetic_field_service runs the traceMagneticField service. |
|
3279 | 3291 | |
|
3280 | 3292 | Inputs: |
|
3281 | 3293 | request/url - contains arguments: |
|
3282 | 3294 | |
|
3283 | 3295 | year, month, day, hour, min, sec |
|
3284 | 3296 | |
|
3285 | 3297 | inputType (0 for geodetic, 1 for GSM) |
|
3286 | 3298 | |
|
3287 | 3299 | outputType (0 for geodetic, 1 for GSM) |
|
3288 | 3300 | |
|
3289 | 3301 | The following parameter depend on inputType: |
|
3290 | 3302 | |
|
3291 | 3303 | in1 - a comma-separated list of geodetic altitudes or ZGSMs of starting point |
|
3292 | 3304 | |
|
3293 | 3305 | in2 - a comma-separated list of geodetic latitudes or XGSMs of starting point |
|
3294 | 3306 | |
|
3295 | 3307 | in3 - a comma-separated list of longitude or YGSM of starting point |
|
3296 | 3308 | |
|
3297 | 3309 | Length of all three lists must be the same |
|
3298 | 3310 | |
|
3299 | 3311 | model - 0 for Tsyganenko, 1 for IGRF |
|
3300 | 3312 | |
|
3301 | 3313 | qualifier - 0 for conjugate, 1 for north_alt, 2 for south_alt, 3 for apex, 4 for GSM XY plane |
|
3302 | 3314 | |
|
3303 | 3315 | stopAlt - altitude in km to stop trace at, if qualifier is north_alt or south_alt. |
|
3304 | 3316 | |
|
3305 | 3317 | If other qualifier, this parameter is not required. |
|
3306 | 3318 | |
|
3307 | 3319 | Returns comma-delimited data, one line for point in in lists: |
|
3308 | 3320 | |
|
3309 | 3321 | 1. geodetic altitude or ZGSM of ending point |
|
3310 | 3322 | |
|
3311 | 3323 | 2. geodetic latitude or XGSM of ending point |
|
3312 | 3324 | |
|
3313 | 3325 | 3. longitude or YGSM of ending point |
|
3314 | 3326 | """ |
|
3315 | 3327 | year = int(request.GET['year']) |
|
3316 | 3328 | month = int(request.GET['month']) |
|
3317 | 3329 | day = int(request.GET['day']) |
|
3318 | 3330 | hour = int(request.GET['hour']) |
|
3319 | 3331 | minute = int(request.GET['min']) |
|
3320 | 3332 | second = int(request.GET['sec']) |
|
3321 | 3333 | dt = datetime.datetime(year, month, day, hour, minute, second) |
|
3322 | 3334 | inputType = int(request.GET['inputType']) |
|
3323 | 3335 | if inputType not in (0,1): |
|
3324 | 3336 | return(HttpResponse('inputType must be 0 or 1, not %i' % (inputType))) |
|
3325 | 3337 | outputType = int(request.GET['outputType']) |
|
3326 | 3338 | if outputType not in (0,1): |
|
3327 | 3339 | return(HttpResponse('outputType must be 0 or 1, not %i' % (outputType))) |
|
3328 | 3340 | in1Str = request.GET['in1'] |
|
3329 | 3341 | in1List = [float(item) for item in in1Str.split(',')] |
|
3330 | 3342 | in2Str = request.GET['in2'] |
|
3331 | 3343 | in2List = [float(item) for item in in2Str.split(',')] |
|
3332 | 3344 | in3Str = request.GET['in3'] |
|
3333 | 3345 | in3List = [float(item) for item in in3Str.split(',')] |
|
3334 | 3346 | if len(in1List) != len(in2List) or len(in1List) != len(in3List): |
|
3335 | 3347 | return(HttpResponse('All three in* lists must have same length')) |
|
3336 | 3348 | model = int(request.GET['model']) |
|
3337 | 3349 | if model not in (0,1): |
|
3338 | 3350 | return(HttpResponse('model must be 0 or 1, not %i' % (model))) |
|
3339 | 3351 | qualifier = int(request.GET['qualifier']) |
|
3340 | 3352 | if qualifier not in (0,1,2,3,4): |
|
3341 | 3353 | return(HttpResponse('model must be in 0,1,2,3,4 not %i' % (model))) |
|
3342 | 3354 | try: |
|
3343 | 3355 | stopAlt = float(request.GET['stopAlt']) |
|
3344 | 3356 | except: |
|
3345 | 3357 | stopAlt = 0.0 |
|
3346 | 3358 | |
|
3347 | 3359 | fullText = '' |
|
3348 | 3360 | resultArr = numpy.zeros((3,), dtype='f8') |
|
3349 | 3361 | madDB = madrigal.metadata.MadrigalDB() |
|
3350 | 3362 | madDeriveObj = madrigal.derivation.MadrigalDerivationMethods(madDB.getMadroot()) |
|
3351 | 3363 | for i in range(len(in1List)): |
|
3352 | 3364 | madDeriveObj.traceMagneticField(year, month, day, hour, minute, second, |
|
3353 | 3365 | inputType, outputType, in1List[i], in2List[i], in3List[i], |
|
3354 | 3366 | model, qualifier, stopAlt, resultArr) |
|
3355 | 3367 | fullText += '%f,%f,%f\n' % (resultArr[0], resultArr[1], resultArr[2]) |
|
3356 | 3368 | |
|
3357 | 3369 | return render(request, 'madweb/service.html', {'text': fullText}) |
|
3358 | 3370 | |
|
3359 | 3371 | |
|
3360 | 3372 | def global_file_search_service(request): |
|
3361 | 3373 | """global_file_search_service returns a list of full paths to files or citable urls based on search arguments |
|
3362 | 3374 | |
|
3363 | 3375 | Inputs: |
|
3364 | 3376 | request/url - contains arguments: |
|
3365 | 3377 | |
|
3366 | 3378 | startDate: start date in form YYYY-MM-DD to filter experiments before |
|
3367 | 3379 | endDate: end date in form YYYY-MM-DD to filter experiments after |
|
3368 | 3380 | inst: (optional, multiple allowed) an instrument code or name. For names, |
|
3369 | 3381 | fnmatch will be used. If not set, all instruments used. |
|
3370 | 3382 | kindat: (optional, multiple allowed) a kind of data codes or name. For names, |
|
3371 | 3383 | fnmatch will be used. If not set, all kinds of data used. |
|
3372 | 3384 | seasonalStartDate: (optional) in form MM/DD, rejects all days earlier in year. If not set |
|
3373 | 3385 | implies 01/01 |
|
3374 | 3386 | seasonalEndDate: (optional) in form MM/DD, rejects all days later in year. If not set |
|
3375 | 3387 | implies 12/31 |
|
3376 | 3388 | includeNonDefault: (optional) if "True", include realtime files when there are no default. |
|
3377 | 3389 | If not set, only default files. |
|
3378 | 3390 | expName: (optional) - filter experiments by the experiment name. fnmatch rules |
|
3379 | 3391 | If not set, no filtering by experiment name. |
|
3380 | 3392 | excludeExpName: (optional) - exclude experiments by the experiment name. fnmatch rules |
|
3381 | 3393 | If not set, no excluding experiments by experiment name. |
|
3382 | 3394 | fileDesc: (optional) filter files using input file Description string via fnmatch. |
|
3383 | 3395 | If not set, in no filtering by file name |
|
3384 | 3396 | returnCitation: (optional) if True, return a list of file citations. If not set, return |
|
3385 | 3397 | a list of full paths to the files selected |
|
3386 | 3398 | |
|
3387 | 3399 | """ |
|
3388 | 3400 | madDB = madrigal.metadata.MadrigalDB() |
|
3389 | 3401 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
3390 | 3402 | |
|
3391 | 3403 | # get required arguments |
|
3392 | 3404 | startDate = request.GET['startDate'] |
|
3393 | 3405 | endDate = request.GET['endDate'] |
|
3394 | 3406 | startDate = datetime.datetime.strptime(startDate, '%Y-%m-%d') |
|
3395 | 3407 | endDate = datetime.datetime.strptime(endDate, '%Y-%m-%d') |
|
3396 | 3408 | |
|
3397 | 3409 | # get optional arguments |
|
3398 | 3410 | inst = request.GET.getlist('inst') |
|
3399 | 3411 | if inst == []: |
|
3400 | 3412 | inst = None |
|
3401 | 3413 | kindat = request.GET.getlist('kindat') |
|
3402 | 3414 | if kindat == []: |
|
3403 | 3415 | kindat = None |
|
3404 | 3416 | seasonalStartDate = request.GET.get('seasonalStartDate', default = None) |
|
3405 | 3417 | seasonalEndDate = request.GET.get('seasonalEndDate', default = None) |
|
3406 | 3418 | includeNonDefault = bool(request.GET.get('includeNonDefault', default = False)) |
|
3407 | 3419 | expName = request.GET.get('expName', default = None) |
|
3408 | 3420 | excludeExpName = request.GET.get('excludeExpName', default = None) |
|
3409 | 3421 | fileDesc = request.GET.get('fileDesc', default = None) |
|
3410 | 3422 | returnCitation = bool(request.GET.get('returnCitation', default = False)) |
|
3411 | 3423 | |
|
3412 | 3424 | result = madWebObj.global_file_search(startDate, endDate, inst, kindat, |
|
3413 | 3425 | seasonalStartDate, seasonalEndDate, |
|
3414 | 3426 | includeNonDefault, expName, excludeExpName, |
|
3415 | 3427 | fileDesc, returnCitation) |
|
3416 | 3428 | |
|
3417 | 3429 | fullText = '' |
|
3418 | 3430 | for item in result: |
|
3419 | 3431 | fullText += '%s\n' % (item) |
|
3420 | 3432 | |
|
3421 | 3433 | return render(request, 'madweb/service.html', {'text': django.utils.safestring.mark_safe(fullText)}) |
|
3422 | 3434 | |
|
3423 | 3435 | |
|
3424 | 3436 | |
|
3425 | 3437 | |
|
3426 | 3438 | def get_url_list_from_group_id_service(request): |
|
3427 | 3439 | """get_url_list_from_group_id_service returns a list of citable urls associated with group id. |
|
3428 | 3440 | |
|
3429 | 3441 | Inputs: |
|
3430 | 3442 | request/url - contains arguments: |
|
3431 | 3443 | |
|
3432 | 3444 | id - group id |
|
3433 | 3445 | |
|
3434 | 3446 | Returns one line for each citable url |
|
3435 | 3447 | |
|
3436 | 3448 | Returns empty string if experiment id not found. Skips files that are not Hdf5 |
|
3437 | 3449 | """ |
|
3438 | 3450 | id = int(request.GET['id']) |
|
3439 | 3451 | |
|
3440 | 3452 | # create MadrigalDB obj |
|
3441 | 3453 | madDBObj = madrigal.metadata.MadrigalDB() |
|
3442 | 3454 | |
|
3443 | 3455 | urlList = madDBObj.getListFromGroupId(id) |
|
3444 | 3456 | |
|
3445 | 3457 | retStr = '' |
|
3446 | 3458 | for url in urlList: |
|
3447 | 3459 | retStr += '%s\n' % (url) |
|
3448 | 3460 | |
|
3449 | 3461 | return render(request, 'madweb/service.html', {'text': django.utils.safestring.mark_safe(retStr)}) |
|
3450 | 3462 | |
|
3451 | 3463 | |
|
3452 | 3464 | def set_group_id_from_url_list_service(request): |
|
3453 | 3465 | """set_group_id_from_url_list sets a list of citable urls to a group id . |
|
3454 | 3466 | |
|
3455 | 3467 | Inputs: |
|
3456 | 3468 | request/url - contains arguments: |
|
3457 | 3469 | |
|
3458 | 3470 | 'user_fullname' user name |
|
3459 | 3471 | |
|
3460 | 3472 | 'user_email' user email |
|
3461 | 3473 | |
|
3462 | 3474 | 'user_affiliation' user affiliation |
|
3463 | 3475 | |
|
3464 | 3476 | 'url' - citable url. Multiple arguments allowed |
|
3465 | 3477 | |
|
3466 | 3478 | Returns group id (integer) set |
|
3467 | 3479 | """ |
|
3468 | 3480 | madDB = madrigal.metadata.MadrigalDB() |
|
3469 | 3481 | |
|
3470 | 3482 | print(request.GET) |
|
3471 | 3483 | |
|
3472 | 3484 | # get required arguments |
|
3473 | 3485 | urls = request.GET.getlist('url') |
|
3474 | 3486 | user_fullname = request.GET['user_fullname'] |
|
3475 | 3487 | user_email = request.GET['user_email'] |
|
3476 | 3488 | user_affiliation = request.GET['user_affiliation'] |
|
3477 | 3489 | |
|
3478 | 3490 | id = madDB.createGroupIdWithList(user_fullname, user_email, user_affiliation, urls) |
|
3479 | 3491 | |
|
3480 | 3492 | return render(request, 'madweb/service.html', {'text': str(id)}) |
|
3481 | 3493 | |
|
3482 | 3494 | |
|
3483 | 3495 | ### doc pages ### |
|
3484 | 3496 | |
|
3485 | 3497 | def docs(request, name): |
|
3486 | 3498 | madDB = madrigal.metadata.MadrigalDB() |
|
3487 | 3499 | openMadObj = madrigal.openmadrigal.OpenMadrigal(madDB) |
|
3488 | 3500 | bg_color = madDB.getBackgroundColor() |
|
3489 | 3501 | if name.find('..') != -1: |
|
3490 | 3502 | # no trying to look elsewhere |
|
3491 | 3503 | return(HttpResponse('Illegal name passed to docs: <%s>' % (name))) |
|
3492 | 3504 | # check if siteSpecitic.html |
|
3493 | 3505 | siteSpecificPath = os.path.join(madDB.getMadroot(), 'source/madpy/djangoMad/madweb/templates/madweb/siteSpecific.html') |
|
3494 | 3506 | if os.access(siteSpecificPath, os.R_OK): |
|
3495 | 3507 | siteSpecific = reverse('docs', args=['siteSpecific.html']) |
|
3496 | 3508 | else: |
|
3497 | 3509 | siteSpecific = '#' |
|
3498 | 3510 | openmadrigal = openMadObj.getOpenMadrigalUrl() |
|
3499 | 3511 | # since google insists filenames are case insensitive, convert to right name if there is no direct match if possible |
|
3500 | 3512 | this_file = os.path.join(madDB.getMadroot(), 'source/madpy/djangoMad/madweb/templates/madweb', name) |
|
3501 | 3513 | if not os.access(this_file, os.R_OK): |
|
3502 | 3514 | found = False |
|
3503 | 3515 | existing_files = glob.glob(os.path.join(madDB.getMadroot(), 'source/madpy/djangoMad/madweb/templates/madweb/*.html')) |
|
3504 | 3516 | for existing_file in existing_files: |
|
3505 | 3517 | if name.lower() == os.path.basename(existing_file).lower(): |
|
3506 | 3518 | name = os.path.basename(existing_file) |
|
3507 | 3519 | found = True |
|
3508 | 3520 | break # correct name found and name modified |
|
3509 | 3521 | if not found: |
|
3510 | 3522 | return(HttpResponse('<p>Cannot find %s</p>' % (str(name)))) |
|
3511 | 3523 | |
|
3512 | 3524 | if os.path.isdir(this_file): |
|
3513 | 3525 | return(HttpResponse('<p>%s is a directory</p>' % (str(name)))) |
|
3514 | 3526 | |
|
3515 | 3527 | return render(request, 'madweb/%s' % (name), {'bg_color': bg_color, 'siteSpecific': siteSpecific, |
|
3516 | 3528 | 'openmadrigal': openmadrigal}) |
|
3517 | 3529 | |
|
3518 | No newline at end of file | |
|
3530 |
General Comments 0
You need to be logged in to leave comments.
Login now