##// END OF EJS Templates
Fix bugs and plots
jespinoza -
r6:7771bbd8f772
parent child
Show More
@@ -1,21 +1,21
1 # configuration
1 # configuration
2
2
3 upstream djangomad {
3 upstream djangomad {
4 server web:8000;
4 server web:8000;
5 }
5 }
6
6
7 server {
7 server {
8 listen 80;
8 listen 8080;
9
9
10 location / {
10 location /madrigal {
11 proxy_http_version 1.1;
11 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
12 proxy_set_header Upgrade $http_upgrade;
12 proxy_set_header Host $host;
13 proxy_set_header Connection "upgrade";
14 proxy_redirect off;
13 proxy_redirect off;
14 proxy_set_header X-Script-Name /madrigal;
15 proxy_pass http://djangomad;
15 proxy_pass http://djangomad;
16 }
16 }
17
17
18 location /static/ {
18 location /madrigal/static/ {
19 alias /static/;
19 alias /static/;
20 }
20 }
21 } No newline at end of file
21 }
@@ -1,83 +1,83
1
1
2 from django.contrib.auth.decorators import login_required
2 from django.contrib.auth.decorators import login_required
3 from django.shortcuts import render
3 from django.shortcuts import render
4 from .forms import UpdataForm, ExpForm
4 from .forms import UpdataForm, ExpForm
5 from django.core.files.storage import FileSystemStorage
5 from django.core.files.storage import FileSystemStorage
6 from django.contrib import messages
6 from django.contrib import messages
7
7
8 import os
8 import os
9
9
10 # madrigal imports
10 # madrigal imports
11 import madrigal.metadata
11 import madrigal.metadata
12 import madrigal.ui.web
12 import madrigal.ui.web
13 import madrigal.admin
13 import madrigal.admin
14
14
15 @login_required
15 @login_required(login_url='/madrigal/accounts/login/')
16 def index(request):
16 def index(request):
17 '''
17 '''
18 Uploading experiments data view. Allows user to upload experiment files
18 Uploading experiments data view. Allows user to upload experiment files
19
19
20 '''
20 '''
21 dbAdminObj = madrigal.admin.MadrigalDBAdmin()
21 dbAdminObj = madrigal.admin.MadrigalDBAdmin()
22 madDB = madrigal.metadata.MadrigalDB()
22 madDB = madrigal.metadata.MadrigalDB()
23 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
23 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
24 siteName, siteList = madWebObj.getSiteInfo()
24 siteName, siteList = madWebObj.getSiteInfo()
25
25
26 if request.method == 'POST':
26 if request.method == 'POST':
27 form = UpdataForm(request.POST, request.FILES)
27 form = UpdataForm(request.POST, request.FILES)
28 files = request.FILES.getlist('file')
28 files = request.FILES.getlist('file')
29
29
30 if form.is_valid():
30 if form.is_valid():
31 try:
31 try:
32 description = form.cleaned_data['description']
32 description = form.cleaned_data['description']
33 instCode = int(form.cleaned_data['instruments'])
33 instCode = int(form.cleaned_data['instruments'])
34 expId = form.cleaned_data['experiments']
34 expId = form.cleaned_data['experiments']
35 perm = int(form.cleaned_data['type'])
35 perm = int(form.cleaned_data['type'])
36
36
37 #saving file
37 #saving file
38 for f in files:
38 for f in files:
39 fs = FileSystemStorage(location='/tmp')
39 fs = FileSystemStorage(location='/tmp')
40 fs.save(f.name, f)
40 fs.save(f.name, f)
41 madExp = madrigal.metadata.MadrigalExperiment()
41 madExp = madrigal.metadata.MadrigalExperiment()
42 filepath = os.path.join('/tmp', f.name)
42 filepath = os.path.join('/tmp', f.name)
43 expTitle = madExp.getExpNameByExpId(expId)
43 expTitle = madExp.getExpNameByExpId(expId)
44
44
45 dbAdminObj.createMadrigalExperiment(filepath,expTitle, perm, description, instCode)
45 dbAdminObj.createMadrigalExperiment(filepath,expTitle, perm, description, instCode)
46
46
47
47
48 madInstParams = madrigal.metadata.MadrigalInstrumentParameters()
48 madInstParams = madrigal.metadata.MadrigalInstrumentParameters()
49 madInstKindats = madrigal.metadata.MadrigalInstrumentKindats()
49 madInstKindats = madrigal.metadata.MadrigalInstrumentKindats()
50
50
51 print('*** Updating local metadata ***')
51 print('*** Updating local metadata ***')
52 dbAdminObj.__updateLocalMetadata__()
52 dbAdminObj.__updateLocalMetadata__()
53 print('*** Rebuilding instParmTab.txt ***')
53 print('*** Rebuilding instParmTab.txt ***')
54 madInstParams.rebuildInstParmTable()
54 madInstParams.rebuildInstParmTable()
55 print('*** Rebuilding instKindatTab.txt ***')
55 print('*** Rebuilding instKindatTab.txt ***')
56 madInstKindats.rebuildInstKindatTable()
56 madInstKindats.rebuildInstKindatTable()
57 messages.success(
57 messages.success(
58 request, 'Experimento(s) creado(s) exitosamente')
58 request, 'Experimento(s) creado(s) exitosamente')
59 form = UpdataForm()
59 form = UpdataForm()
60
60
61 except Exception as e:
61 except Exception as e:
62 messages.error(
62 messages.error(
63 request, str(e))
63 request, str(e))
64 else:
64 else:
65 form = UpdataForm()
65 form = UpdataForm()
66
66
67 return render(request, 'updata/index.html', {
67 return render(request, 'updata/index.html', {
68 'form': form,
68 'form': form,
69 'site_name': siteName,
69 'site_name': siteName,
70 'site_list': siteList,
70 'site_list': siteList,
71 })
71 })
72
72
73
73
74 def get_experiments(request):
74 def get_experiments(request):
75 """get_experiments is a Ajax call that returns the experiments select html to support the
75 """get_experiments is a Ajax call that returns the experiments select html to support the
76 updata UI. Called when a user modifies the intruments select field.
76 updata UI. Called when a user modifies the intruments select field.
77
77
78 Inputs:
78 Inputs:
79 request
79 request
80 """
80 """
81 form = ExpForm(request.GET)
81 form = ExpForm(request.GET)
82
82
83 return render(request, 'updata/experiments.html', {'form': form})
83 return render(request, 'updata/experiments.html', {'form': form})
@@ -1,138 +1,138
1 """
1 """
2 Django settings for djangoMad project.
2 Django settings for djangoMad project.
3
3
4 For more information on this file, see
4 For more information on this file, see
5 https://docs.djangoproject.com/en/1.7/topics/settings/
5 https://docs.djangoproject.com/en/1.7/topics/settings/
6
6
7 For the full list of settings and their values, see
7 For the full list of settings and their values, see
8 https://docs.djangoproject.com/en/1.7/ref/settings/
8 https://docs.djangoproject.com/en/1.7/ref/settings/
9 """
9 """
10
10
11 # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
11 # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
12 import os
12 import os
13 BASE_DIR = os.path.dirname(os.path.dirname(__file__))
13 BASE_DIR = os.path.dirname(os.path.dirname(__file__))
14
14
15 # Quick-start development settings - unsuitable for production
15 # Quick-start development settings - unsuitable for production
16 # See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/
16 # See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/
17
17
18 # SECURITY WARNING: keep the secret key used in production secret!
18 # SECURITY WARNING: keep the secret key used in production secret!
19 SECRET_KEY = '^c1l3d35+q28^66d2pc1qlu(k$wmw^*gg3rfitz^s)t=9eu1ui'
19 SECRET_KEY = '^c1l3d35+q28^66d2pc1qlu(k$wmw^*gg3rfitz^s)t=9eu1ui'
20
20
21 # SECURITY WARNING: don't run with debug turned on in production!
21 # SECURITY WARNING: don't run with debug turned on in production!
22 DEBUG = True
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 ADMINS = (('Bill Rideout', 'brideout@haystack.mit.edu'),)
27 ADMINS = (('Bill Rideout', 'brideout@haystack.mit.edu'),)
28
28
29 EMAIL_HOST = 'hyperion.haystack.mit.edu'
29 EMAIL_HOST = 'hyperion.haystack.mit.edu'
30
30
31 SEND_BROKEN_LINK_EMAILS = True
31 SEND_BROKEN_LINK_EMAILS = True
32
32
33 MANAGERS = (('Bill Rideout', 'brideout@haystack.mit.edu'),)
33 MANAGERS = (('Bill Rideout', 'brideout@haystack.mit.edu'),)
34
34
35
35
36 # Application definition
36 # Application definition
37
37
38 INSTALLED_APPS = (
38 INSTALLED_APPS = (
39 'django.contrib.admin',
39 'django.contrib.admin',
40 'django.contrib.auth',
40 'django.contrib.auth',
41 'django.contrib.contenttypes',
41 'django.contrib.contenttypes',
42 'django.contrib.sessions',
42 'django.contrib.sessions',
43 'django.contrib.messages',
43 'django.contrib.messages',
44 'django.contrib.staticfiles',
44 'django.contrib.staticfiles',
45 'madweb',
45 'madweb',
46 'django_bootstrap_calendar',
46 'django_bootstrap_calendar',
47 'bootstrap3',
47 'bootstrap3',
48 'apps.login',
48 'apps.login',
49 'apps.updata',
49 'apps.updata',
50 )
50 )
51
51
52 MIDDLEWARE = [
52 MIDDLEWARE = [
53 'django.middleware.security.SecurityMiddleware',
53 'django.middleware.security.SecurityMiddleware',
54 'django.contrib.sessions.middleware.SessionMiddleware',
54 'django.contrib.sessions.middleware.SessionMiddleware',
55 'django.middleware.common.CommonMiddleware',
55 'django.middleware.common.CommonMiddleware',
56 'django.middleware.csrf.CsrfViewMiddleware',
56 'django.middleware.csrf.CsrfViewMiddleware',
57 'django.contrib.auth.middleware.AuthenticationMiddleware',
57 'django.contrib.auth.middleware.AuthenticationMiddleware',
58 'django.contrib.messages.middleware.MessageMiddleware',
58 'django.contrib.messages.middleware.MessageMiddleware',
59 'django.middleware.clickjacking.XFrameOptionsMiddleware',
59 'django.middleware.clickjacking.XFrameOptionsMiddleware',
60 ]
60 ]
61
61
62 ROOT_URLCONF = 'djangoMad.urls'
62 ROOT_URLCONF = 'djangoMad.urls'
63
63
64 WSGI_APPLICATION = 'djangoMad.wsgi.application'
64 WSGI_APPLICATION = 'djangoMad.wsgi.application'
65
65
66
66
67 TEMPLATES = [
67 TEMPLATES = [
68 {
68 {
69 'BACKEND': 'django.template.backends.django.DjangoTemplates',
69 'BACKEND': 'django.template.backends.django.DjangoTemplates',
70 'DIRS': [
70 'DIRS': [
71 os.path.join(BASE_DIR, "templates"),
71 os.path.join(BASE_DIR, "templates"),
72 ],
72 ],
73 'APP_DIRS': True,
73 'APP_DIRS': True,
74 'OPTIONS': {
74 'OPTIONS': {
75 'context_processors': [
75 'context_processors': [
76 'django.contrib.auth.context_processors.auth',
76 'django.contrib.auth.context_processors.auth',
77 'django.template.context_processors.debug',
77 'django.template.context_processors.debug',
78 'django.template.context_processors.i18n',
78 'django.template.context_processors.i18n',
79 'django.template.context_processors.media',
79 'django.template.context_processors.media',
80 'django.template.context_processors.static',
80 'django.template.context_processors.static',
81 'django.template.context_processors.tz',
81 'django.template.context_processors.tz',
82 'django.contrib.messages.context_processors.messages',
82 'django.contrib.messages.context_processors.messages',
83 'django.template.context_processors.request',
83 'django.template.context_processors.request',
84 ],
84 ],
85 },
85 },
86 },
86 },
87 ]
87 ]
88
88
89
89
90 # Database
90 # Database
91 # https://docs.djangoproject.com/en/1.7/ref/settings/#databases
91 # https://docs.djangoproject.com/en/1.7/ref/settings/#databases
92
92
93 DATABASES = {
93 DATABASES = {
94 'default': {
94 'default': {
95 'ENGINE': 'django.db.backends.sqlite3',
95 'ENGINE': 'django.db.backends.sqlite3',
96 'NAME': 'madrigal.sqlite',
96 'NAME': 'madrigal.sqlite',
97 }
97 }
98 }
98 }
99
99
100
100
101 # Internationalization
101 # Internationalization
102 # https://docs.djangoproject.com/en/1.7/topics/i18n/
102 # https://docs.djangoproject.com/en/1.7/topics/i18n/
103
103
104 LANGUAGE_CODE = 'en-us'
104 LANGUAGE_CODE = 'en-us'
105
105
106 TIME_ZONE = 'UTC'
106 TIME_ZONE = 'UTC'
107
107
108 USE_I18N = True
108 USE_I18N = True
109
109
110 USE_L10N = True
110 USE_L10N = True
111
111
112 USE_TZ = True
112 USE_TZ = True
113
113
114
114
115 # Absolute filesystem path to the directory that will hold user-uploaded files.
115 # Absolute filesystem path to the directory that will hold user-uploaded files.
116 # Example: "/home/media/media.lawrence.com/media/"
116 # Example: "/home/media/media.lawrence.com/media/"
117 MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
117 MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
118
118
119 # URL that handles the media served from MEDIA_ROOT. Make sure to use a
119 # URL that handles the media served from MEDIA_ROOT. Make sure to use a
120 # trailing slash.
120 # trailing slash.
121 # Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
121 # Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
122 MEDIA_URL = '/media/'
122 MEDIA_URL = '/media/'
123
123
124 # Absolute path to the directory static files should be collected to.
124 # Absolute path to the directory static files should be collected to.
125 # Don't put anything in this directory yourself; store your static files
125 # Don't put anything in this directory yourself; store your static files
126 # in apps' "static/" subdirectories and in STATICFILES_DIRS.
126 # in apps' "static/" subdirectories and in STATICFILES_DIRS.
127 # Example: "/home/media/media.lawrence.com/static/"
127 # Example: "/home/media/media.lawrence.com/static/"
128 # STATIC_ROOT = os.path.join(BASE_DIR, 'static')
128 # STATIC_ROOT = os.path.join(BASE_DIR, 'static')
129
129
130 # URL prefix for static files.
130 # URL prefix for static files.
131 # Example: "http://media.lawrence.com/static/"
131 # Example: "http://media.lawrence.com/static/"
132 STATIC_URL = '/static/'
132 STATIC_URL = '/madrigal/static/'
133
133
134 BOOTSTRAP3 = {
134 BOOTSTRAP3 = {
135 # Include jQuery with Bootstrap JavaScript (affects django-bootstrap3 template tags)
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 'include_jquery': True,
137 'include_jquery': True,
138 }
138 }
@@ -1,11 +1,12
1 from django.conf.urls import include, url
1 from django.conf.urls import include, url
2 from django.contrib import admin
2 from django.contrib import admin
3 import madweb.views
3 import madweb.views
4
4
5 urlpatterns = [
5 urlpatterns = [
6 url(r'^', include('madweb.urls')),
6 url(r'^madrigal/', include('madweb.urls')),
7 url(r'^$', madweb.views.index),
7 url(r'^$', madweb.views.index),
8 url(r'^updata/', include('apps.updata.urls', namespace="updata")),
8 url(r'^madrigal/updata/', include('apps.updata.urls', namespace="updata")),
9 url(r'^accounts/', include('apps.login.urls', namespace="login")),
9 url(r'^madrigal/accounts/', include('apps.login.urls', namespace="login")),
10 url(r'^admin/', admin.site.urls),
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 """Forms for madweb application
1 """Forms for madweb application
2
2
3 $Id: forms.py 7288 2020-12-10 16:49:16Z brideout $
3 $Id: forms.py 7288 2020-12-10 16:49:16Z brideout $
4 """
4 """
5
5
6 # standard python imports
6 # standard python imports
7 import os.path
7 import os.path
8 import datetime
8 import datetime
9 import itertools
9 import itertools
10
10
11 # django imports
11 # django imports
12 import django.forms
12 import django.forms
13 import django.utils.html
13 import django.utils.html
14 import django.utils.safestring
14 import django.utils.safestring
15 import django.template.defaulttags
15 import django.template.defaulttags
16
16
17 # third party imports
17 # third party imports
18 import numpy
18 import numpy
19 import h5py
19 import h5py
20
20
21 # Madrigal imports
21 # Madrigal imports
22 import madrigal.metadata
22 import madrigal.metadata
23 import madrigal.ui.web
23 import madrigal.ui.web
24
24
25 # temp only
25 # temp only
26 import logging
26 import logging
27
27
28 @django.template.defaulttags.register.filter
28 @django.template.defaulttags.register.filter
29 def get_item(dictionary, key):
29 def get_item(dictionary, key):
30 return(dictionary.get(key))
30 return(dictionary.get(key))
31
31
32 @django.template.defaulttags.register.filter
32 @django.template.defaulttags.register.filter
33 def modulo(num, val):
33 def modulo(num, val):
34 return(num % val == 0)
34 return(num % val == 0)
35
35
36 class HorizontalRadioSelect(django.forms.RadioSelect):
36 class HorizontalRadioSelect(django.forms.RadioSelect):
37 template_name = 'madweb/horizontal_select.html'
37 template_name = 'madweb/horizontal_select.html'
38
38
39
39
40
40
41 def getSelection(keyword, args, kwargs):
41 def getSelection(keyword, args, kwargs):
42 """getSelection returns '0' if keyword not a key in either args[0] or kwargs,
42 """getSelection returns '0' if keyword not a key in either args[0] or kwargs,
43 otherwise the value
43 otherwise the value
44
44
45 args, kwargs - arguments as passed into SingleExpDefaultForm __init__
45 args, kwargs - arguments as passed into SingleExpDefaultForm __init__
46 """
46 """
47 if len(args) == 0 and len(list(kwargs.keys())) == 0:
47 if len(args) == 0 and len(list(kwargs.keys())) == 0:
48 return('0') # default case when no data passed in
48 return('0') # default case when no data passed in
49 elif len(args) > 0:
49 elif len(args) > 0:
50 # args[0] is data dict argument to bind data
50 # args[0] is data dict argument to bind data
51 if keyword in args[0]:
51 if keyword in args[0]:
52 return(args[0][keyword])
52 return(args[0][keyword])
53 else:
53 else:
54 return('0')
54 return('0')
55 elif keyword in kwargs:
55 elif keyword in kwargs:
56 return(kwargs[keyword])
56 return(kwargs[keyword])
57 elif 'data' in kwargs:
57 elif 'data' in kwargs:
58 if keyword in kwargs['data']:
58 if keyword in kwargs['data']:
59 return(kwargs['data'][keyword])
59 return(kwargs['data'][keyword])
60 else:
60 else:
61 return('0')
61 return('0')
62 else:
62 else:
63 return('0')
63 return('0')
64
64
65
65
66 def getIsGlobal(args, kwargs):
66 def getIsGlobal(args, kwargs):
67 """getIsGlobal is a helper function returns True if 'isGlobal' not found in either args[0] or kwargs,
67 """getIsGlobal is a helper function returns True if 'isGlobal' not found in either args[0] or kwargs,
68 otherwise the bool of the value
68 otherwise the bool of the value
69
69
70 args, kwargs - arguments as passed into SingleExpDefaultForm __init__
70 args, kwargs - arguments as passed into SingleExpDefaultForm __init__
71 """
71 """
72 if len(args) == 0 and len(list(kwargs.keys())) == 0:
72 if len(args) == 0 and len(list(kwargs.keys())) == 0:
73 return(True) # default case when no data passed in
73 return(True) # default case when no data passed in
74 elif len(args) > 0:
74 elif len(args) > 0:
75 # args[0] is data dict argument to bind data
75 # args[0] is data dict argument to bind data
76 if 'isGlobal' in args[0]:
76 if 'isGlobal' in args[0]:
77 if args[0]['isGlobal'] == '0':
77 if args[0]['isGlobal'] == '0':
78 return(False)
78 return(False)
79 else:
79 else:
80 return(bool(args[0]['isGlobal']))
80 return(bool(args[0]['isGlobal']))
81 else:
81 else:
82 return(False)
82 return(False)
83 elif 'data' in kwargs:
83 elif 'data' in kwargs:
84 if 'isGlobal' in kwargs['data']:
84 if 'isGlobal' in kwargs['data']:
85 if kwargs['data']['isGlobal'] == '0':
85 if kwargs['data']['isGlobal'] == '0':
86 return(False)
86 return(False)
87 else:
87 else:
88 return(bool(kwargs['data']['isGlobal']))
88 return(bool(kwargs['data']['isGlobal']))
89 else:
89 else:
90 return(False)
90 return(False)
91 elif 'isGlobal' in kwargs:
91 elif 'isGlobal' in kwargs:
92 if kwargs['isGlobal'] == '0':
92 if kwargs['isGlobal'] == '0':
93 return(False)
93 return(False)
94 else:
94 else:
95 return(bool(kwargs['isGlobal']))
95 return(bool(kwargs['isGlobal']))
96 else:
96 else:
97 return(False)
97 return(False)
98
98
99
99
100 def getCategoryList(args, kwargs, madInstData, forList=False):
100 def getCategoryList(args, kwargs, madInstData, forList=False):
101 """getCategoryList is a helper function that returns the categories choices in
101 """getCategoryList is a helper function that returns the categories choices in
102 SingleExpDefaultForm.categories at runtime
102 SingleExpDefaultForm.categories at runtime
103
103
104 Inputs:
104 Inputs:
105 args, kwargs - arguments as passed into SingleExpDefaultForm __init__. Used only to
105 args, kwargs - arguments as passed into SingleExpDefaultForm __init__. Used only to
106 determine isGlobal
106 determine isGlobal
107 madInstData - madrigal.metadata.MadrigalInstrumentData object
107 madInstData - madrigal.metadata.MadrigalInstrumentData object
108 forList - if False (the default) category list if for single interface, If True, for List interface
108 forList - if False (the default) category list if for single interface, If True, for List interface
109 """
109 """
110 if not forList:
110 if not forList:
111 local = not getIsGlobal(args, kwargs)
111 local = not getIsGlobal(args, kwargs)
112 else:
112 else:
113 local = False
113 local = False
114 categories = madInstData.getCategories(local)
114 categories = madInstData.getCategories(local)
115 if forList:
115 if forList:
116 catList = [('0', 'All instrument categories'),]
116 catList = [('0', 'All instrument categories'),]
117 else:
117 else:
118 catList = [('0', 'Choose instrument type: '),]
118 catList = [('0', 'Choose instrument type: '),]
119 for catID, catDesc in categories:
119 for catID, catDesc in categories:
120 catList.append((str(catID), catDesc))
120 catList.append((str(catID), catDesc))
121 return(catList)
121 return(catList)
122
122
123
123
124
124
125 def getInstrumentList(args, kwargs, madInstData, header='Select an instrument: ', local=None, includeYears=False):
125 def getInstrumentList(args, kwargs, madInstData, header='Select an instrument: ', local=None, includeYears=False):
126 """getInstrumentList is a helper function that returns the instrument choices in
126 """getInstrumentList is a helper function that returns the instrument choices in
127 SingleExpDefaultForm.categories at runtime
127 SingleExpDefaultForm.categories at runtime
128
128
129 Inputs:
129 Inputs:
130 args, kwargs - arguments as passed into SingleExpDefaultForm __init__. Used to
130 args, kwargs - arguments as passed into SingleExpDefaultForm __init__. Used to
131 determine categoryId and local
131 determine categoryId and local
132 madInstData - madrigal.metadata.MadrigalInstrumentData object
132 madInstData - madrigal.metadata.MadrigalInstrumentData object
133 header - text of first item in selection
133 header - text of first item in selection
134 local - if None (the default), set local flag via args and kwargs. If boolean,
134 local - if None (the default), set local flag via args and kwargs. If boolean,
135 set local flag to arg.
135 set local flag to arg.
136 includeYear - if True, include data years in description. If False (the default), do not.
136 includeYear - if True, include data years in description. If False (the default), do not.
137 """
137 """
138 if local is None:
138 if local is None:
139 local = not getIsGlobal(args, kwargs)
139 local = not getIsGlobal(args, kwargs)
140 else:
140 else:
141 local = bool(local)
141 local = bool(local)
142 if header == 'Select an instrument: ':
142 if header == 'Select an instrument: ':
143 categoryId = int(getSelection('categories', args, kwargs))
143 categoryId = int(getSelection('categories', args, kwargs))
144 else:
144 else:
145 categoryId = 0
145 categoryId = 0
146 instruments = madInstData.getInstruments(categoryId, local)
146 instruments = madInstData.getInstruments(categoryId, local)
147 instList = [('0', header),]
147 instList = [('0', header),]
148 for kinst, instDesc, siteID in instruments:
148 for kinst, instDesc, siteID in instruments:
149 if includeYears:
149 if includeYears:
150 instYears = madInstData.getInstrumentYears(kinst)
150 instYears = madInstData.getInstrumentYears(kinst)
151 instList.append((str(kinst), '%s [%i-%i]' % (instDesc, instYears[0], instYears[-1])))
151 instList.append((str(kinst), '%s [%i-%i]' % (instDesc, instYears[0], instYears[-1])))
152 else:
152 else:
153 instList.append((str(kinst), instDesc))
153 instList.append((str(kinst), instDesc))
154 return(instList)
154 return(instList)
155
155
156
156
157 def getYearList(args, kwargs, madInstData):
157 def getYearList(args, kwargs, madInstData):
158 """getYearList is a helper function that returns the year choices in
158 """getYearList is a helper function that returns the year choices in
159 SingleExpDefaultForm.categories at runtime
159 SingleExpDefaultForm.categories at runtime
160
160
161 Inputs:
161 Inputs:
162 args, kwargs - arguments as passed into SingleExpDefaultForm __init__. Used to
162 args, kwargs - arguments as passed into SingleExpDefaultForm __init__. Used to
163 determine categoryId and local and kinst
163 determine categoryId and local and kinst
164 madInstData - madrigal.metadata.MadrigalInstrumentData object
164 madInstData - madrigal.metadata.MadrigalInstrumentData object
165 """
165 """
166 local = not getIsGlobal(args, kwargs)
166 local = not getIsGlobal(args, kwargs)
167 kinst = int(getSelection('instruments', args, kwargs))
167 kinst = int(getSelection('instruments', args, kwargs))
168 years = madInstData.getInstrumentYears(kinst)
168 years = madInstData.getInstrumentYears(kinst)
169 yearsList = [('0', 'Select a year: '),]
169 yearsList = [('0', 'Select a year: '),]
170 for thisYear in reversed(years):
170 for thisYear in reversed(years):
171 yearsList.append((str(thisYear), str(thisYear)))
171 yearsList.append((str(thisYear), str(thisYear)))
172 return(yearsList)
172 return(yearsList)
173
173
174
174
175 def getMonthList(args, kwargs, madWebObj):
175 def getMonthList(args, kwargs, madWebObj):
176 """getMonthList is a helper function that returns the month choices in
176 """getMonthList is a helper function that returns the month choices in
177 SingleExpDefaultForm.categories at runtime. Value is (month number,
177 SingleExpDefaultForm.categories at runtime. Value is (month number,
178 month name)
178 month name)
179
179
180 Inputs:
180 Inputs:
181 args, kwargs - arguments as passed into SingleExpDefaultForm __init__. Used to
181 args, kwargs - arguments as passed into SingleExpDefaultForm __init__. Used to
182 determine and kinst and year
182 determine and kinst and year
183 madWebObj - madrigal.ui.web.MadrigalWeb object
183 madWebObj - madrigal.ui.web.MadrigalWeb object
184 """
184 """
185 kinst = int(getSelection('instruments', args, kwargs))
185 kinst = int(getSelection('instruments', args, kwargs))
186 year = int(getSelection('years', args, kwargs))
186 year = int(getSelection('years', args, kwargs))
187 monthList = [('0', 'Select a month: '),]
187 monthList = [('0', 'Select a month: '),]
188 addedMonthList = madWebObj.getMonths(kinst, year)
188 addedMonthList = madWebObj.getMonths(kinst, year)
189 if len(addedMonthList) == 0:
189 if len(addedMonthList) == 0:
190 addedMonthList = madWebObj.getMonths(kinst, year, optimize=False)
190 addedMonthList = madWebObj.getMonths(kinst, year, optimize=False)
191 monthList += addedMonthList
191 monthList += addedMonthList
192 return([(str(monthNumber), monthName) for monthNumber, monthName in monthList])
192 return([(str(monthNumber), monthName) for monthNumber, monthName in monthList])
193
193
194
194
195 def getDayList():
195 def getDayList():
196 """always returns 1 ... 31
196 """always returns 1 ... 31
197 """
197 """
198 dayList = [(i, str(i)) for i in range(1,32)]
198 dayList = [(i, str(i)) for i in range(1,32)]
199 return(dayList)
199 return(dayList)
200
200
201
201
202 def getExpList(args, kwargs, madWebObj):
202 def getExpList(args, kwargs, madWebObj):
203 """getExpList is a helper function that returns the experiment choices in
203 """getExpList is a helper function that returns the experiment choices in
204 SingleExpDefaultForm.categories at runtime. Value is (expId,
204 SingleExpDefaultForm.categories at runtime. Value is (expId,
205 expDesc, expDir, pi_name, pi_email)
205 expDesc, expDir, pi_name, pi_email)
206
206
207 Inputs:
207 Inputs:
208 args, kwargs - arguments as passed into SingleExpDefaultForm __init__. Used to
208 args, kwargs - arguments as passed into SingleExpDefaultForm __init__. Used to
209 determine and kinst, year, month, day
209 determine and kinst, year, month, day
210 madWebObj - madrigal.ui.web.MadrigalWeb object
210 madWebObj - madrigal.ui.web.MadrigalWeb object
211 """
211 """
212 kinst = int(getSelection('instruments', args, kwargs))
212 kinst = int(getSelection('instruments', args, kwargs))
213 year = int(getSelection('years', args, kwargs))
213 year = int(getSelection('years', args, kwargs))
214 month = int(getSelection('months', args, kwargs))
214 month = int(getSelection('months', args, kwargs))
215 day = int(getSelection('days', args, kwargs))
215 day = int(getSelection('days', args, kwargs))
216 expList = madWebObj.getExpsOnDate(kinst, year, month, day)
216 expList = madWebObj.getExpsOnDate(kinst, year, month, day)
217 if len(expList) == 0:
217 if len(expList) == 0:
218 expList = madWebObj.getExpsOnDate(kinst, year, month, day, optimize=False)
218 expList = madWebObj.getExpsOnDate(kinst, year, month, day, optimize=False)
219 return(expList)
219 return(expList)
220
220
221
221
222 def handle_registration(kwargs, user_email, expUrl, kinst, madDB):
222 def handle_registration(kwargs, user_email, expUrl, kinst, madDB):
223 """handle_registration causes the user to register or unregister interest in getting emails
223 """handle_registration causes the user to register or unregister interest in getting emails
224 when a particular experiment or instrument is updated
224 when a particular experiment or instrument is updated
225
225
226 Inputs:
226 Inputs:
227 kwargs - dictionary as passed into form
227 kwargs - dictionary as passed into form
228 user_email - users email address
228 user_email - users email address
229 expUrl - experiment url (part after /madtoc/)
229 expUrl - experiment url (part after /madtoc/)
230 kinst - instrument code
230 kinst - instrument code
231 madDB - madrigal.metadata.MadrigalDB object
231 madDB - madrigal.metadata.MadrigalDB object
232 """
232 """
233 # first find out if this exp or inst is already registered
233 # first find out if this exp or inst is already registered
234 madUserObj = madrigal.ui.userData.MadrigalUserData(madDB)
234 madUserObj = madrigal.ui.userData.MadrigalUserData(madDB)
235 expsRegistered = madUserObj.getRegisteredExperiments(user_email)
235 expsRegistered = madUserObj.getRegisteredExperiments(user_email)
236 if expUrl in expsRegistered:
236 if expUrl in expsRegistered:
237 thisExpRegistered = True
237 thisExpRegistered = True
238 else:
238 else:
239 thisExpRegistered = False
239 thisExpRegistered = False
240 instsRegistered = madUserObj.getRegisteredInstruments(user_email)
240 instsRegistered = madUserObj.getRegisteredInstruments(user_email)
241 if kinst in instsRegistered:
241 if kinst in instsRegistered:
242 thisInstRegistered = True
242 thisInstRegistered = True
243 else:
243 else:
244 thisInstRegistered = False
244 thisInstRegistered = False
245
245
246 # check registration status, update if needed, and let form know how to print this
246 # check registration status, update if needed, and let form know how to print this
247 # 0 - no registration, 1 - exp registered, 2 - inst registered
247 # 0 - no registration, 1 - exp registered, 2 - inst registered
248 if 'registerExp' in kwargs:
248 if 'registerExp' in kwargs:
249 if not thisExpRegistered:
249 if not thisExpRegistered:
250 madUserObj.registerExperiment(user_email, expUrl)
250 madUserObj.registerExperiment(user_email, expUrl)
251 return('1')
251 return('1')
252 elif 'registerInst' in kwargs:
252 elif 'registerInst' in kwargs:
253 if not thisInstRegistered:
253 if not thisInstRegistered:
254 madUserObj.registerInstrument(user_email, kinst)
254 madUserObj.registerInstrument(user_email, kinst)
255 return('2')
255 return('2')
256 elif 'unregisterExp' in kwargs:
256 elif 'unregisterExp' in kwargs:
257 if thisExpRegistered:
257 if thisExpRegistered:
258 madUserObj.unregisterExperiment(user_email, expUrl)
258 madUserObj.unregisterExperiment(user_email, expUrl)
259 return('0')
259 return('0')
260 elif 'unregisterInst' in kwargs:
260 elif 'unregisterInst' in kwargs:
261 if thisInstRegistered:
261 if thisInstRegistered:
262 madUserObj.unregisterInstrument(user_email, kinst)
262 madUserObj.unregisterInstrument(user_email, kinst)
263 return('0')
263 return('0')
264 elif thisExpRegistered:
264 elif thisExpRegistered:
265 return('1')
265 return('1')
266 elif thisInstRegistered:
266 elif thisInstRegistered:
267 return('2')
267 return('2')
268 else:
268 else:
269 return('0')
269 return('0')
270
270
271
271
272 def getFormatChoices(basename, expID):
272 def getFormatChoices(basename, expID):
273 """getFormatChoices returns a list with 3 tuples, where each tuple
273 """getFormatChoices returns a list with 3 tuples, where each tuple
274 is 1. filename with correct extension, 2. Format
274 is 1. filename with correct extension, 2. Format
275
275
276 Inputs:
276 Inputs:
277 basename - basename of Madrigal Hdf5 file
277 basename - basename of Madrigal Hdf5 file
278 expID - needed to determine if cached file available in near real time
278 expID - needed to determine if cached file available in near real time
279 """
279 """
280 madWebObj = madrigal.ui.web.MadrigalWeb()
280 madWebObj = madrigal.ui.web.MadrigalWeb()
281 formats = madWebObj.getFormatsAvailable(expID, basename)
281 formats = madWebObj.getFormatsAvailable(expID, basename)
282 fileName, fileExtension = os.path.splitext(basename)
282 fileName, fileExtension = os.path.splitext(basename)
283 retList = []
283 retList = []
284 retList.append((basename, 'Hdf5')) # file is assumed to be in Hdf5 format
284 retList.append((basename, 'Hdf5')) # file is assumed to be in Hdf5 format
285 if 'ascii' in formats:
285 if 'ascii' in formats:
286 retList.append((fileName + '.txt', 'Space-delimited ascii'))
286 retList.append((fileName + '.txt', 'Space-delimited ascii'))
287 if 'netCDF4' in formats:
287 if 'netCDF4' in formats:
288 retList.append((fileName + '.nc', 'netCDF4'))
288 retList.append((fileName + '.nc', 'netCDF4'))
289 return(retList)
289 return(retList)
290
290
291
291
292 class RegisterForm(django.forms.Form):
292 class RegisterForm(django.forms.Form):
293 """RegisterForm is the form class that supports the Register page
293 """RegisterForm is the form class that supports the Register page
294 """
294 """
295 def __init__(self, *args, **kwargs):
295 def __init__(self, *args, **kwargs):
296 super(RegisterForm, self).__init__(*args, **kwargs)
296 super(RegisterForm, self).__init__(*args, **kwargs)
297 self.fields['user_fullname'] = django.forms.CharField(label='Full name', min_length=2, max_length=256)
297 self.fields['user_fullname'] = django.forms.CharField(label='Full name', min_length=2, max_length=256)
298 self.fields['user_email'] = django.forms.EmailField(label='Email')
298 self.fields['user_email'] = django.forms.EmailField(label='Email')
299 self.fields['user_affiliation'] = django.forms.CharField(label='Affliation (type "None" if individual)', min_length=2, max_length=256)
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 class SingleExpDefaultForm(django.forms.Form):
303 class SingleExpDefaultForm(django.forms.Form):
304 """SingleExpDefaultForm is a Form class for the default fields in the Single Experiment interface
304 """SingleExpDefaultForm is a Form class for the default fields in the Single Experiment interface
305 (formally the Simple interface)
305 (formally the Simple interface)
306 """
306 """
307 def __init__(self, *args, **kwargs):
307 def __init__(self, *args, **kwargs):
308 super(SingleExpDefaultForm, self).__init__(*args, **kwargs)
308 super(SingleExpDefaultForm, self).__init__(*args, **kwargs)
309 madDB = madrigal.metadata.MadrigalDB()
309 madDB = madrigal.metadata.MadrigalDB()
310 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
310 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
311 user_email = getSelection('user_email', args, kwargs)
311 user_email = getSelection('user_email', args, kwargs)
312 self.fields['isGlobal'] = django.forms.BooleanField(widget = django.forms.CheckboxInput(attrs={"onChange":'populateCat(this)'}),
312 self.fields['isGlobal'] = django.forms.BooleanField(widget = django.forms.CheckboxInput(attrs={"onChange":'populateCat(this)'}),
313 required=False, label='Use all Madrigal sites: ',
313 required=False, label='Use all Madrigal sites: ',
314 initial=getIsGlobal(args, kwargs))
314 initial=getIsGlobal(args, kwargs))
315
315
316
316
317 categoriesSelection = getSelection('categories', args, kwargs)
317 categoriesSelection = getSelection('categories', args, kwargs)
318 self.fields['categories'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'populateInst(this)'}),
318 self.fields['categories'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'populateInst(this)'}),
319 choices=getCategoryList(args, kwargs, madInstData),
319 choices=getCategoryList(args, kwargs, madInstData),
320 initial=categoriesSelection,
320 initial=categoriesSelection,
321 label='Instrument category:')
321 label='Instrument category:')
322
322
323 # the following fields may or may not be populated. All are also available as individual classes
323 # the following fields may or may not be populated. All are also available as individual classes
324 # to allow AJAX calls to not need to create this full object
324 # to allow AJAX calls to not need to create this full object
325
325
326 if categoriesSelection != '0':
326 if categoriesSelection != '0':
327 instrumentSelection = getSelection('instruments', args, kwargs)
327 instrumentSelection = getSelection('instruments', args, kwargs)
328 self.fields['instruments'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'populateYear(this)'}),
328 self.fields['instruments'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'populateYear(this)'}),
329 choices=getInstrumentList(args, kwargs, madInstData),
329 choices=getInstrumentList(args, kwargs, madInstData),
330 initial=instrumentSelection,
330 initial=instrumentSelection,
331 required=False, label='Instrument:')
331 required=False, label='Instrument:')
332 else:
332 else:
333 return # no need to create any further fields
333 return # no need to create any further fields
334
334
335 if instrumentSelection != '0':
335 if instrumentSelection != '0':
336 yearSelection = getSelection('years', args, kwargs)
336 yearSelection = getSelection('years', args, kwargs)
337 self.fields['years'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'populateMonth(this)'}),
337 self.fields['years'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'populateMonth(this)'}),
338 choices=getYearList(args, kwargs, madInstData),
338 choices=getYearList(args, kwargs, madInstData),
339 initial=yearSelection,
339 initial=yearSelection,
340 required=False, label='Year:')
340 required=False, label='Year:')
341
341
342 else:
342 else:
343 return # no need to create any further fields
343 return # no need to create any further fields
344
344
345 if yearSelection != '0':
345 if yearSelection != '0':
346 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
346 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
347 monthSelection = getSelection('months', args, kwargs)
347 monthSelection = getSelection('months', args, kwargs)
348 self.fields['months'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'populateCalendar(this)'}),
348 self.fields['months'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'populateCalendar(this)'}),
349 choices=getMonthList(args, kwargs, madWebObj),
349 choices=getMonthList(args, kwargs, madWebObj),
350 initial=monthSelection, label='Month:')
350 initial=monthSelection, label='Month:')
351
351
352 else:
352 else:
353 return # no need to create any further fields
353 return # no need to create any further fields
354
354
355
355
356 if monthSelection != '0':
356 if monthSelection != '0':
357 daySelection = getSelection('days', args, kwargs)
357 daySelection = getSelection('days', args, kwargs)
358 # this field is only used to help display the calendar
358 # this field is only used to help display the calendar
359 self.fields['days'] = django.forms.ChoiceField(required=False, choices=getDayList())
359 self.fields['days'] = django.forms.ChoiceField(required=False, choices=getDayList())
360
360
361 else:
361 else:
362 return # no need to create any further fields
362 return # no need to create any further fields
363
363
364 if daySelection != '0':
364 if daySelection != '0':
365 expFullList = getExpList(args, kwargs, madWebObj)
365 expFullList = getExpList(args, kwargs, madWebObj)
366 expIdSelection = None
366 expIdSelection = None
367 if len(expFullList) > 1:
367 if len(expFullList) > 1:
368 expList = [('0', 'Select one of multiple experiments')] + [(items[0], items[1]) for items in expFullList]
368 expList = [('0', 'Select one of multiple experiments')] + [(items[0], items[1]) for items in expFullList]
369 expIdSelection = getSelection('experiment_list', args, kwargs)
369 expIdSelection = getSelection('experiment_list', args, kwargs)
370 self.fields['experiment_list'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'populateFile(this)'}),
370 self.fields['experiment_list'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'populateFile(this)'}),
371 choices=expList, initial=expIdSelection,
371 choices=expList, initial=expIdSelection,
372 required=False, label='Select experiment:')
372 required=False, label='Select experiment:')
373
373
374 if expIdSelection == '0':
374 if expIdSelection == '0':
375 # no need to create any further fields
375 # no need to create any further fields
376 return
376 return
377
377
378 if expIdSelection is None:
378 if expIdSelection is None:
379 expIdSelection = expFullList[0][0]
379 expIdSelection = expFullList[0][0]
380 expDir = expFullList[0][2]
380 expDir = expFullList[0][2]
381 else:
381 else:
382 expDir = None
382 expDir = None
383 for expId, thisExpDesc, thisExpDir in expFullList:
383 for expId, thisExpDesc, thisExpDir in expFullList:
384 if int(expIdSelection) == int(expId):
384 if int(expIdSelection) == int(expId):
385 expDir = thisExpDir
385 expDir = thisExpDir
386 break
386 break
387
387
388 fileList = madWebObj.getFileFromExpDir(expDir, int(instrumentSelection))
388 fileList = madWebObj.getFileFromExpDir(expDir, int(instrumentSelection))
389 fileList = [('0', 'Select file')] + fileList
389 fileList = [('0', 'Select file')] + fileList
390 fileSelection = getSelection('file_list', args, kwargs)
390 fileSelection = getSelection('file_list', args, kwargs)
391 self.fields['file_list'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'changeFile(this)'}),
391 self.fields['file_list'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'changeFile(this)'}),
392 choices=fileList, initial=fileSelection,
392 choices=fileList, initial=fileSelection,
393 required=False, label='Select file:')
393 required=False, label='Select file:')
394 self.fields['exp_id'] = django.forms.CharField(initial=str(expIdSelection),
394 self.fields['exp_id'] = django.forms.CharField(initial=str(expIdSelection),
395 widget=django.forms.HiddenInput(attrs={'value': str(expIdSelection)}),
395 widget=django.forms.HiddenInput(attrs={'value': str(expIdSelection)}),
396 required=False,
396 required=False,
397 label=str(expIdSelection))
397 label=str(expIdSelection))
398
398
399 pi_name, pi_email, expUrl, kinst, expDesc, kinstDesc = madWebObj.getExpInfoFromExpID(int(expIdSelection))
399 pi_name, pi_email, expUrl, kinst, expDesc, kinstDesc = madWebObj.getExpInfoFromExpID(int(expIdSelection))
400
400
401 self.fields['exp_desc'] = django.forms.CharField(initial=str(expDesc),
401 self.fields['exp_desc'] = django.forms.CharField(initial=str(expDesc),
402 widget=django.forms.HiddenInput(attrs={'value': str(expDesc)}),
402 widget=django.forms.HiddenInput(attrs={'value': str(expDesc)}),
403 required=False,
403 required=False,
404 label=str(expDesc))
404 label=str(expDesc))
405 self.fields['user_email'] = django.forms.CharField(initial=str(user_email),
405 self.fields['user_email'] = django.forms.CharField(initial=str(user_email),
406 widget=django.forms.HiddenInput(attrs={'value': str(user_email)}),
406 widget=django.forms.HiddenInput(attrs={'value': str(user_email)}),
407 required=False,
407 required=False,
408 label=str(user_email))
408 label=str(user_email))
409 self.fields['inst_desc'] = django.forms.CharField(initial=str(kinstDesc),
409 self.fields['inst_desc'] = django.forms.CharField(initial=str(kinstDesc),
410 widget=django.forms.HiddenInput(attrs={'value': str(kinstDesc)}),
410 widget=django.forms.HiddenInput(attrs={'value': str(kinstDesc)}),
411 required=False,
411 required=False,
412 label=str(kinstDesc))
412 label=str(kinstDesc))
413 self.fields['pi_name'] = django.forms.CharField(initial=pi_name,
413 self.fields['pi_name'] = django.forms.CharField(initial=pi_name,
414 widget=django.forms.HiddenInput(attrs={'value': pi_name}),
414 widget=django.forms.HiddenInput(attrs={'value': pi_name}),
415 required=False,
415 required=False,
416 label=pi_name)
416 label=pi_name)
417 self.fields['pi_email'] = django.forms.CharField(initial=pi_email,
417 self.fields['pi_email'] = django.forms.CharField(initial=pi_email,
418 widget=django.forms.HiddenInput(attrs={'value': pi_email}),
418 widget=django.forms.HiddenInput(attrs={'value': pi_email}),
419 required=False,
419 required=False,
420 label=pi_email)
420 label=pi_email)
421
421
422 # handle any needed registration or unregistration
422 # handle any needed registration or unregistration
423 register = handle_registration(args[0], user_email, expUrl, kinst, madDB)
423 register = handle_registration(args[0], user_email, expUrl, kinst, madDB)
424 self.fields['register'] = django.forms.CharField(initial=register,
424 self.fields['register'] = django.forms.CharField(initial=register,
425 widget=django.forms.HiddenInput(attrs={'value': register}),
425 widget=django.forms.HiddenInput(attrs={'value': register}),
426 required=False,
426 required=False,
427 label=register)
427 label=register)
428
428
429
429
430 else:
430 else:
431 return # no need to create any further fields
431 return # no need to create any further fields
432
432
433 if fileSelection != '0':
433 if fileSelection != '0':
434 self.fields['file_buttons'] = django.forms.CharField(initial='',
434 self.fields['file_buttons'] = django.forms.CharField(initial='',
435 widget=django.forms.HiddenInput(attrs={'value': ''}),
435 widget=django.forms.HiddenInput(attrs={'value': ''}),
436 required=False,
436 required=False,
437 label='')
437 label='')
438
438
439
439
440 else:
440 else:
441 return # no need to create any further fields
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 class SingleExpInstForm(django.forms.Form):
451 class SingleExpInstForm(django.forms.Form):
452 """SingleExpInstForm is a Form class for the instrument select field in the Single Experiment interface.
452 """SingleExpInstForm is a Form class for the instrument select field in the Single Experiment interface.
453 Use this because its faster to create than the full SingleExpDefaultForm
453 Use this because its faster to create than the full SingleExpDefaultForm
454 """
454 """
455 def __init__(self, *args, **kwargs):
455 def __init__(self, *args, **kwargs):
456 super(SingleExpInstForm, self).__init__(*args, **kwargs)
456 super(SingleExpInstForm, self).__init__(*args, **kwargs)
457 madDB = madrigal.metadata.MadrigalDB()
457 madDB = madrigal.metadata.MadrigalDB()
458 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
458 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
459 instrumentSelection = getSelection('instruments', args, kwargs)
459 instrumentSelection = getSelection('instruments', args, kwargs)
460 self.fields['instruments'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'populateYear(this)'}),
460 self.fields['instruments'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'populateYear(this)'}),
461 choices=getInstrumentList(args, kwargs, madInstData),
461 choices=getInstrumentList(args, kwargs, madInstData),
462 initial=instrumentSelection,
462 initial=instrumentSelection,
463 label='Instrument:')
463 label='Instrument:')
464
464
465 class SingleExpYearForm(django.forms.Form):
465 class SingleExpYearForm(django.forms.Form):
466 """SingleExpYearForm is a Form class for the year select field in the Single Experiment interface.
466 """SingleExpYearForm is a Form class for the year select field in the Single Experiment interface.
467 Use this because its faster to create than the full SingleExpDefaultForm
467 Use this because its faster to create than the full SingleExpDefaultForm
468 """
468 """
469 def __init__(self, *args, **kwargs):
469 def __init__(self, *args, **kwargs):
470 super(SingleExpYearForm, self).__init__(*args, **kwargs)
470 super(SingleExpYearForm, self).__init__(*args, **kwargs)
471 madDB = madrigal.metadata.MadrigalDB()
471 madDB = madrigal.metadata.MadrigalDB()
472 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
472 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
473 yearSelection = getSelection('years', args, kwargs)
473 yearSelection = getSelection('years', args, kwargs)
474 self.fields['years'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'populateMonth(this)'}),
474 self.fields['years'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'populateMonth(this)'}),
475 choices=getYearList(args, kwargs, madInstData),
475 choices=getYearList(args, kwargs, madInstData),
476 initial=yearSelection, label='Year:')
476 initial=yearSelection, label='Year:')
477
477
478
478
479 class SingleExpMonthForm(django.forms.Form):
479 class SingleExpMonthForm(django.forms.Form):
480 """SingleExpMonthForm is a Form class for the month select field in the Single Experiment interface.
480 """SingleExpMonthForm is a Form class for the month select field in the Single Experiment interface.
481 Use this because its faster to create than the full SingleExpDefaultForm
481 Use this because its faster to create than the full SingleExpDefaultForm
482 """
482 """
483 def __init__(self, *args, **kwargs):
483 def __init__(self, *args, **kwargs):
484 super(SingleExpMonthForm, self).__init__(*args, **kwargs)
484 super(SingleExpMonthForm, self).__init__(*args, **kwargs)
485 madDB = madrigal.metadata.MadrigalDB()
485 madDB = madrigal.metadata.MadrigalDB()
486 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
486 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
487 monthSelection = getSelection('months', args, kwargs)
487 monthSelection = getSelection('months', args, kwargs)
488 self.fields['months'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'populateCalendar(this)'}),
488 self.fields['months'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'populateCalendar(this)'}),
489 choices=getMonthList(args, kwargs, madWebObj),
489 choices=getMonthList(args, kwargs, madWebObj),
490 initial=monthSelection, label='Month:')
490 initial=monthSelection, label='Month:')
491
491
492
492
493 class SingleExpCalendarForm(django.forms.Form):
493 class SingleExpCalendarForm(django.forms.Form):
494 """SingleExpCalendarForm is a Form class for the calendar field in the Single Experiment interface.
494 """SingleExpCalendarForm is a Form class for the calendar field in the Single Experiment interface.
495 Use this because its faster to create than the full SingleExpDefaultForm
495 Use this because its faster to create than the full SingleExpDefaultForm
496 """
496 """
497 def __init__(self, *args, **kwargs):
497 def __init__(self, *args, **kwargs):
498 super(SingleExpCalendarForm, self).__init__(*args, **kwargs)
498 super(SingleExpCalendarForm, self).__init__(*args, **kwargs)
499 madDB = madrigal.metadata.MadrigalDB()
499 madDB = madrigal.metadata.MadrigalDB()
500 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
500 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
501
501
502
502
503 class SingleExpFileForm(django.forms.Form):
503 class SingleExpFileForm(django.forms.Form):
504 """SingleExpFileForm is a Form class for the file select field in the Single Experiment interface.
504 """SingleExpFileForm is a Form class for the file select field in the Single Experiment interface.
505 Use this because its faster to create than the full SingleExpDefaultForm
505 Use this because its faster to create than the full SingleExpDefaultForm
506 """
506 """
507 def __init__(self, *args, **kwargs):
507 def __init__(self, *args, **kwargs):
508 super(SingleExpFileForm, self).__init__(*args, **kwargs)
508 super(SingleExpFileForm, self).__init__(*args, **kwargs)
509 madDB = madrigal.metadata.MadrigalDB()
509 madDB = madrigal.metadata.MadrigalDB()
510 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
510 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
511 expID = getSelection('experiment_list', args, kwargs)
511 expID = getSelection('experiment_list', args, kwargs)
512 try:
512 try:
513 expID = int(expID)
513 expID = int(expID)
514 except ValueError:
514 except ValueError:
515 # convert expPath to expID
515 # convert expPath to expID
516 expID = madWebObj.getExpIDFromExpPath(expID, True)
516 expID = madWebObj.getExpIDFromExpPath(expID, True)
517 user_email = getSelection('user_email', args, kwargs)
517 user_email = getSelection('user_email', args, kwargs)
518 include_non_default = getSelection('includeNonDefault', args, kwargs)
518 include_non_default = getSelection('includeNonDefault', args, kwargs)
519 if include_non_default == '0':
519 if include_non_default == '0':
520 include_non_default = False
520 include_non_default = False
521 fileList = madWebObj.getFileFromExpID(expID, include_non_default)
521 fileList = madWebObj.getFileFromExpID(expID, include_non_default)
522 fileList = [('0', 'Select file')] + fileList
522 fileList = [('0', 'Select file')] + fileList
523
523
524 fileSelection = getSelection('file_list', args, kwargs)
524 fileSelection = getSelection('file_list', args, kwargs)
525 self.fields['file_list'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'changeFile(this)'}),
525 self.fields['file_list'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'changeFile(this)'}),
526 choices=fileList, initial=fileSelection,
526 choices=fileList, initial=fileSelection,
527 required=False, label='Select file:')
527 required=False, label='Select file:')
528 if int(expID) != 0:
528 if int(expID) != 0:
529 self.fields['exp_id'] = django.forms.CharField(initial=str(expID),
529 self.fields['exp_id'] = django.forms.CharField(initial=str(expID),
530 widget=django.forms.HiddenInput(attrs={'value': str(expID)}),
530 widget=django.forms.HiddenInput(attrs={'value': str(expID)}),
531 required=False,
531 required=False,
532 label=str(expID))
532 label=str(expID))
533 pi_name, pi_email, expUrl, kinst, expDesc, kinstDesc = madWebObj.getExpInfoFromExpID(int(expID))
533 pi_name, pi_email, expUrl, kinst, expDesc, kinstDesc = madWebObj.getExpInfoFromExpID(int(expID))
534
534
535 self.fields['exp_desc'] = django.forms.CharField(initial=str(expDesc),
535 self.fields['exp_desc'] = django.forms.CharField(initial=str(expDesc),
536 widget=django.forms.HiddenInput(attrs={'value': str(expDesc)}),
536 widget=django.forms.HiddenInput(attrs={'value': str(expDesc)}),
537 required=False,
537 required=False,
538 label=str(expDesc))
538 label=str(expDesc))
539 self.fields['user_email'] = django.forms.CharField(initial=str(user_email),
539 self.fields['user_email'] = django.forms.CharField(initial=str(user_email),
540 widget=django.forms.HiddenInput(attrs={'value': str(user_email)}),
540 widget=django.forms.HiddenInput(attrs={'value': str(user_email)}),
541 required=False,
541 required=False,
542 label=str(user_email))
542 label=str(user_email))
543 self.fields['inst_desc'] = django.forms.CharField(initial=str(kinstDesc),
543 self.fields['inst_desc'] = django.forms.CharField(initial=str(kinstDesc),
544 widget=django.forms.HiddenInput(attrs={'value': str(kinstDesc)}),
544 widget=django.forms.HiddenInput(attrs={'value': str(kinstDesc)}),
545 required=False,
545 required=False,
546 label=str(kinstDesc))
546 label=str(kinstDesc))
547 self.fields['pi_name'] = django.forms.CharField(initial=pi_name,
547 self.fields['pi_name'] = django.forms.CharField(initial=pi_name,
548 widget=django.forms.HiddenInput(attrs={'value': pi_name}),
548 widget=django.forms.HiddenInput(attrs={'value': pi_name}),
549 required=False,
549 required=False,
550 label=pi_name)
550 label=pi_name)
551 self.fields['pi_email'] = django.forms.CharField(initial=pi_email,
551 self.fields['pi_email'] = django.forms.CharField(initial=pi_email,
552 widget=django.forms.HiddenInput(attrs={'value': pi_email}),
552 widget=django.forms.HiddenInput(attrs={'value': pi_email}),
553 required=False,
553 required=False,
554 label=pi_email)
554 label=pi_email)
555 self.fields['includeNonDefault'] = django.forms.BooleanField(widget = django.forms.CheckboxInput(attrs={"onChange":'reloadFiles(this)'}),
555 self.fields['includeNonDefault'] = django.forms.BooleanField(widget = django.forms.CheckboxInput(attrs={"onChange":'reloadFiles(this)'}),
556 required=False, label='Show non-default files: ',
556 required=False, label='Show non-default files: ',
557 initial=include_non_default)
557 initial=include_non_default)
558 # handle any needed registration or unregistration
558 # handle any needed registration or unregistration
559 register = handle_registration(args[0], user_email, expUrl, kinst, madDB)
559 register = handle_registration(args[0], user_email, expUrl, kinst, madDB)
560 self.fields['register'] = django.forms.CharField(initial=register,
560 self.fields['register'] = django.forms.CharField(initial=register,
561 widget=django.forms.HiddenInput(attrs={'value': register}),
561 widget=django.forms.HiddenInput(attrs={'value': register}),
562 required=False,
562 required=False,
563 label=register)
563 label=register)
564
564
565 if fileSelection != '0':
565 if fileSelection != '0':
566 self.fields['file_buttons'] = django.forms.CharField(initial='',
566 self.fields['file_buttons'] = django.forms.CharField(initial='',
567 widget=django.forms.HiddenInput(attrs={'value': ''}),
567 widget=django.forms.HiddenInput(attrs={'value': ''}),
568 required=False,
568 required=False,
569 label='')
569 label='')
570 self.fields['basename'] = django.forms.CharField(initial=str(fileSelection),
570 self.fields['basename'] = django.forms.CharField(initial=str(fileSelection),
571 widget=django.forms.HiddenInput(attrs={'value': str(fileSelection)}),
571 widget=django.forms.HiddenInput(attrs={'value': str(fileSelection)}),
572 required=False,
572 required=False,
573 label=str(fileSelection))
573 label=str(fileSelection))
574
574
575
575
576
576
577
577
578
578
579 class SingleExpButtonsForm(django.forms.Form):
579 class SingleExpButtonsForm(django.forms.Form):
580 """SingleExpButtonsForm is a Form class for the file buttons field in the Single Experiment interface.
580 """SingleExpButtonsForm is a Form class for the file buttons field in the Single Experiment interface.
581 Use this because its faster to create than the full SingleExpDefaultForm
581 Use this because its faster to create than the full SingleExpDefaultForm
582 """
582 """
583 def __init__(self, *args, **kwargs):
583 def __init__(self, *args, **kwargs):
584 super(SingleExpButtonsForm, self).__init__(*args, **kwargs)
584 super(SingleExpButtonsForm, self).__init__(*args, **kwargs)
585 madDB = madrigal.metadata.MadrigalDB()
585 madDB = madrigal.metadata.MadrigalDB()
586 madExpObj = madrigal.metadata.MadrigalExperiment(madDB)
586 madExpObj = madrigal.metadata.MadrigalExperiment(madDB)
587 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
587 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
588 expID = getSelection('experiment_list', args, kwargs)
588 expID = getSelection('experiment_list', args, kwargs)
589 try:
589 try:
590 expID = int(expID)
590 expID = int(expID)
591 except ValueError:
591 except ValueError:
592 # convert expPath to expID
592 # convert expPath to expID
593 expID = madWebObj.getExpIDFromExpPath(expID, True)
593 expID = madWebObj.getExpIDFromExpPath(expID, True)
594
594
595 fileSelection = getSelection('file_list', args, kwargs)
595 fileSelection = getSelection('file_list', args, kwargs)
596
596
597 expDir = madExpObj.getExpDirByExpId(int(expID))
597 expDir = madExpObj.getExpDirByExpId(int(expID))
598 filesize = os.path.getsize(os.path.join(expDir, str(fileSelection)))
598 filesize = os.path.getsize(os.path.join(expDir, str(fileSelection)))
599
599
600 self.fields['file_buttons'] = django.forms.CharField(initial='',
600 self.fields['file_buttons'] = django.forms.CharField(initial='',
601 widget=django.forms.HiddenInput(attrs={'value': ''}),
601 widget=django.forms.HiddenInput(attrs={'value': ''}),
602 required=False,
602 required=False,
603 label='')
603 label='')
604 self.fields['exp_id'] = django.forms.CharField(initial=str(expID),
604 self.fields['exp_id'] = django.forms.CharField(initial=str(expID),
605 widget=django.forms.HiddenInput(attrs={'value': str(expID)}),
605 widget=django.forms.HiddenInput(attrs={'value': str(expID)}),
606 required=False,
606 required=False,
607 label=str(expID))
607 label=str(expID))
608 self.fields['basename'] = django.forms.CharField(initial=str(fileSelection),
608 self.fields['basename'] = django.forms.CharField(initial=str(fileSelection),
609 widget=django.forms.HiddenInput(attrs={'value': str(fileSelection)}),
609 widget=django.forms.HiddenInput(attrs={'value': str(fileSelection)}),
610 required=False,
610 required=False,
611 label=str(fileSelection))
611 label=str(fileSelection))
612 self.fields['filesize'] = django.forms.IntegerField(initial=filesize,
612 self.fields['filesize'] = django.forms.IntegerField(initial=filesize,
613 widget=django.forms.HiddenInput(attrs={'value': filesize}),
613 widget=django.forms.HiddenInput(attrs={'value': filesize}),
614 required=False,
614 required=False,
615 label=str(filesize))
615 label=str(filesize))
616
616
617
617
618 class SingleExpPlotsForm(django.forms.Form):
618 class SingleExpPlotsForm(django.forms.Form):
619 """SingleExpPlotsForm is a Form class for the file data/show plots field in the Single Experiment interface.
619 """SingleExpPlotsForm is a Form class for the file data/show plots field in the Single Experiment interface.
620 Use this because its faster to create than the full SingleExpDefaultForm
620 Use this because its faster to create than the full SingleExpDefaultForm
621 """
621 """
622 def __init__(self, *args, **kwargs):
622 def __init__(self, *args, **kwargs):
623 super(SingleExpPlotsForm, self).__init__(*args, **kwargs)
623 super(SingleExpPlotsForm, self).__init__(*args, **kwargs)
624 madDB = madrigal.metadata.MadrigalDB()
624 madDB = madrigal.metadata.MadrigalDB()
625 madExpObj = madrigal.metadata.MadrigalExperiment(madDB)
625 madExpObj = madrigal.metadata.MadrigalExperiment(madDB)
626 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
626 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
627 expID = getSelection('experiment_list', args, kwargs)
627 expID = getSelection('experiment_list', args, kwargs)
628 try:
628 try:
629 expID = int(expID)
629 expID = int(expID)
630 except ValueError:
630 except ValueError:
631 # convert expPath to expID
631 # convert expPath to expID
632 expID = madWebObj.getExpIDFromExpPath(expID, True)
632 expID = madWebObj.getExpIDFromExpPath(expID, True)
633 plotList = madExpObj.getExpLinksByExpId(expID)
633 plotList = madExpObj.getExpLinksByExpId(expID)
634 if len(plotList) == 0:
634 if len(plotList) == 0:
635 plotList = [('No plots available', '')]
635 plotList = [('No plots available', '')]
636
636
637 self.fields['plot_list'] = django.forms.ChoiceField(widget = django.forms.Select(),
637 self.fields['plot_list'] = django.forms.ChoiceField(widget = django.forms.Select(),
638 choices=plotList,
638 choices=plotList,
639 required=False)
639 required=False)
640
640
641 '''get_params2 retrieves a list of 1d and 2d parameters of type 1 hdf5 files'''
641 '''get_params2 retrieves a list of 1d and 2d parameters of type 1 hdf5 files'''
642
642
643 def check_mnemonic(s):
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 return s.replace('+', '%2b')
657 return s.replace('+', '%2b')
646
658
647 def get_params1(args, kwargs, madExpObj, madWebObj):
659 def get_params1(args, kwargs, madExpObj, madWebObj):
648
660
649 expID = getSelection('experiment_list', args, kwargs)
661 expID = getSelection('experiment_list', args, kwargs)
650 expDir = madExpObj.getExpDirByExpId(expID)
662 expDir = madExpObj.getExpDirByExpId(expID)
651 fileList = madWebObj.getFileFromExpID(expID, False)
663 fileList = madWebObj.getFileFromExpID(expID, False)
652
664
653 firsttuple = [a_tuple[0] for a_tuple in fileList]
665 firsttuple = [a_tuple[0] for a_tuple in fileList]
654 basename = firsttuple[0]
666 basename = firsttuple[0]
655 fullFilename = os.path.join(expDir, basename)
667 fullFilename = os.path.join(expDir, basename)
656 f = h5py.File(fullFilename, "r")
668 f = h5py.File(fullFilename, "r")
657
669
658 data = f['Data']
670 data = f['Data']
659
671
660 choices1d = [(check_mnemonic(x[0].decode().lower()), x[1].decode()) for x in data['Array Layout']['1D Parameters']['Data Parameters']]
672 choices1d = [(check_mnemonic(x[0].decode().lower()), x[1].decode()) for x in data['Array Layout']['1D Parameters']['Data Parameters']]
661 choices2d = [(check_mnemonic(x[0].decode().lower()), x[1].decode()) for x in data['Array Layout']['2D Parameters']['Data Parameters']]
673 choices2d = [(check_mnemonic(x[0].decode().lower()), x[1].decode()) for x in data['Array Layout']['2D Parameters']['Data Parameters']]
662 choices = [[('0', 'Select Parameter')] + choices1d, [('0', 'Select Parameter')] + choices2d]
674 choices = [[('0', 'Select Parameter')] + choices1d, [('0', 'Select Parameter')] + choices2d]
663 f.close()
675 f.close()
664 return choices
676 return choices
665
677
666
678
667 '''get params2 retrieves a list of 1d parameters of type 2 of hdf5 files'''
679 '''get params2 retrieves a list of 1d parameters of type 2 of hdf5 files'''
668 def get_params2(args, kwargs, madExpObj, madWebObj):
680 def get_params2(args, kwargs, madExpObj, madWebObj):
669
681
670 expID = getSelection('experiment_list', args, kwargs)
682 expID = getSelection('experiment_list', args, kwargs)
671 expDir = madExpObj.getExpDirByExpId(expID)
683 expDir = madExpObj.getExpDirByExpId(expID)
672 fileList = madWebObj.getFileFromExpID(expID, False)
684 fileList = madWebObj.getFileFromExpID(expID, False)
673
685
674 firsttuple = [a_tuple[0] for a_tuple in fileList]
686 firsttuple = [a_tuple[0] for a_tuple in fileList]
675 basename = firsttuple[0]
687 basename = firsttuple[0]
676 fullFilename = os.path.join(expDir, basename)
688 fullFilename = os.path.join(expDir, basename)
677 f = h5py.File(fullFilename, "r")
689 f = h5py.File(fullFilename, "r")
678 parameters = [(x[0].decode().lower(), x[1].decode()) for x in f['Metadata']['Data Parameters']]
690 parameters = [(x[0].decode().lower(), x[1].decode()) for x in f['Metadata']['Data Parameters']]
679 f.close()
691 f.close()
680 return [('0', 'Select Parameter')] + parameters
692 return [('0', 'Select Parameter')] + parameters
681
693
682
694
683 class SingleExpPlotsSelectionForm(django.forms.Form):
695 class SingleExpPlotsSelectionForm(django.forms.Form):
684 """SingleExpPlotsSselectionForm is a Form class for the parameters selection for plotting in the Single Experiment interface.
696 """SingleExpPlotsSselectionForm is a Form class for the parameters selection for plotting in the Single Experiment interface.
685 Use this because its faster to create than the full SingleExpDefaultForm
697 Use this because its faster to create than the full SingleExpDefaultForm
686 """
698 """
687
699
688 def __init__(self, *args, **kwargs):
700 def __init__(self, *args, **kwargs):
689 super(SingleExpPlotsSelectionForm, self).__init__(*args, **kwargs)
701 super(SingleExpPlotsSelectionForm, self).__init__(*args, **kwargs)
690 madDB = madrigal.metadata.MadrigalDB()
702 madDB = madrigal.metadata.MadrigalDB()
691 madExpObj = madrigal.metadata.MadrigalExperiment(madDB)
703 madExpObj = madrigal.metadata.MadrigalExperiment(madDB)
692 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
704 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
693 expID = getSelection('experiment_list', args, kwargs)
705 expID = getSelection('experiment_list', args, kwargs)
694 try:
706 try:
695 expID = int(expID)
707 expID = int(expID)
696 except ValueError:
708 except ValueError:
697 # convert expPath to expID
709 # convert expPath to expID
698 expID = madWebObj.getExpIDFromExpPath(expID, True)
710 expID = madWebObj.getExpIDFromExpPath(expID, True)
699 expDir = madExpObj.getExpDirByExpId(expID)
711 expDir = madExpObj.getExpDirByExpId(expID)
700 fileList = madWebObj.getFileFromExpID(expID, False)
712 fileList = madWebObj.getFileFromExpID(expID, False)
701
713
702 firsttuple = [a_tuple[0] for a_tuple in fileList]
714 firsttuple = [a_tuple[0] for a_tuple in fileList]
703 basename = firsttuple[0]
715 basename = firsttuple[0]
704 fullFilename = os.path.join(expDir, basename)
716 fullFilename = os.path.join(expDir, basename)
705 f = h5py.File(fullFilename, "r")
717 f = h5py.File(fullFilename, "r")
706 data = f[list(f.keys())[0]]
718 data = f[list(f.keys())[0]]
707
719
708 if 'Array Layout' in list(data.keys()):
720 if 'Array Layout' in list(data.keys()):
709 choices = get_params1(args, kwargs, madExpObj, madWebObj)
721 choices = get_params1(args, kwargs, madExpObj, madWebObj)
710 params1d = choices[0]
722 params1d = choices[0]
711 params2d = choices[1]
723 params2d = choices[1]
712 self.fields['param_list1d'] = django.forms.ChoiceField(widget = django.forms.Select(), choices=params1d, label="1D Parameters", required=False)
724 self.fields['param_list1d'] = django.forms.ChoiceField(widget = django.forms.Select(), choices=params1d, label="1D Parameters", required=False)
713 self.fields['param_list2d'] = django.forms.ChoiceField(widget = django.forms.Select(), choices=params2d, label="2D Parameters", required=False)
725 self.fields['param_list2d'] = django.forms.ChoiceField(widget = django.forms.Select(), choices=params2d, label="2D Parameters", required=False)
714
726
715 else:
727 else:
716 params1d = get_params2(args, kwargs, madExpObj, madWebObj)
728 params1d = get_params2(args, kwargs, madExpObj, madWebObj)
717 self.fields['param_list1d'] = django.forms.ChoiceField(widget = django.forms.Select(), choices=params1d, label="1D Parameters", required=False)
729 self.fields['param_list1d'] = django.forms.ChoiceField(widget = django.forms.Select(), choices=params1d, label="1D Parameters", required=False)
718
730
719
731
720 class SingleExpDownloadAsIsForm(django.forms.Form):
732 class SingleExpDownloadAsIsForm(django.forms.Form):
721 """SingleExpDownloadAsIsForm is a Form class for the download as is field in the Single Experiment interface.
733 """SingleExpDownloadAsIsForm is a Form class for the download as is field in the Single Experiment interface.
722 Use this because its faster to create than the full SingleExpDefaultForm
734 Use this because its faster to create than the full SingleExpDefaultForm
723 """
735 """
724 def __init__(self, *args, **kwargs):
736 def __init__(self, *args, **kwargs):
725 super(SingleExpDownloadAsIsForm, self).__init__(*args, **kwargs)
737 super(SingleExpDownloadAsIsForm, self).__init__(*args, **kwargs)
726 basename = getSelection('format_select', args, kwargs)
738 basename = getSelection('format_select', args, kwargs)
727 expID = int(getSelection('expID', args, kwargs))
739 expID = int(getSelection('expID', args, kwargs))
728 formatChoices = getFormatChoices(basename, expID)
740 formatChoices = getFormatChoices(basename, expID)
729
741
730 self.fields['format_select'] = django.forms.ChoiceField(widget = HorizontalRadioSelect(attrs={"onChange":'changeFormat(this)'}),
742 self.fields['format_select'] = django.forms.ChoiceField(widget = HorizontalRadioSelect(attrs={"onChange":'changeFormat(this)'}),
731 choices=formatChoices,
743 choices=formatChoices,
732 required=False)
744 required=False)
733
745
734
746
735
747
736
748
737 class IsprintChoiceField(django.forms.TypedMultipleChoiceField):
749 class IsprintChoiceField(django.forms.TypedMultipleChoiceField):
738 """IsprintChoiceField is subclass of TypedMultipleChoiceField
750 """IsprintChoiceField is subclass of TypedMultipleChoiceField
739 """
751 """
740 def __init__(self, *args, **kwargs):
752 def __init__(self, *args, **kwargs):
741 """__init__ allows all the arguments of TypedMultipleChoiceField, plus extra
753 """__init__ allows all the arguments of TypedMultipleChoiceField, plus extra
742 keyword arguments:
754 keyword arguments:
743 madWebObject madrigal.ui.web.MadrigalWeb object
755 madWebObject madrigal.ui.web.MadrigalWeb object
744 """
756 """
745 self.isDerivedDict = kwargs.pop('isDerivedDict')
757 self.isDerivedDict = kwargs.pop('isDerivedDict')
746 self.parmDescDict = kwargs.pop('parmDescDict')
758 self.parmDescDict = kwargs.pop('parmDescDict')
747 try:
759 try:
748 self.separateProlog = kwargs.pop('separateProlog')
760 self.separateProlog = kwargs.pop('separateProlog')
749 except:
761 except:
750 self.separateProlog = False
762 self.separateProlog = False
751
763
752 kwargs['widget'] = IsprintWidget(attrs={'isDerivedDict':self.isDerivedDict,
764 kwargs['widget'] = IsprintWidget(attrs={'isDerivedDict':self.isDerivedDict,
753 'parmDescDict':self.parmDescDict,
765 'parmDescDict':self.parmDescDict,
754 'separateProlog':self.separateProlog})
766 'separateProlog':self.separateProlog})
755 super(IsprintChoiceField, self).__init__(*args, **kwargs)
767 super(IsprintChoiceField, self).__init__(*args, **kwargs)
756 self.widget.set_parm_lists(self.isDerivedDict, self.parmDescDict, self.separateProlog)
768 self.widget.set_parm_lists(self.isDerivedDict, self.parmDescDict, self.separateProlog)
757
769
758
770
759
771
760
772
761 class IsprintWidget(django.forms.CheckboxSelectMultiple):
773 class IsprintWidget(django.forms.CheckboxSelectMultiple):
762 """IsprintWidget is a subclass of CheckboxSelectMultiple with additional parameters passed in
774 """IsprintWidget is a subclass of CheckboxSelectMultiple with additional parameters passed in
763 to modify rendering
775 to modify rendering
764 """
776 """
765 def __init__(self, *args, **kwargs):
777 def __init__(self, *args, **kwargs):
766 """__init__ allows all the arguments of CheckboxSelectMultiple, plus extra
778 """__init__ allows all the arguments of CheckboxSelectMultiple, plus extra
767 keyword arguments:
779 keyword arguments:
768 madWebObject madrigal.ui.web.MadrigalWeb object
780 madWebObject madrigal.ui.web.MadrigalWeb object
769 """
781 """
770 super(IsprintWidget, self).__init__(*args, **kwargs)
782 super(IsprintWidget, self).__init__(*args, **kwargs)
771 self.renderer = django.forms.CheckboxSelectMultiple
783 self.renderer = django.forms.CheckboxSelectMultiple
772 self.template_name = 'madweb/parameter_multiple.html'
784 self.template_name = 'madweb/parameter_multiple.html'
773
785
774
786
775 def set_parm_lists(self, isDerivedDict, parmDescDict, separateProlog=False):
787 def set_parm_lists(self, isDerivedDict, parmDescDict, separateProlog=False):
776 """set_parm_lists sets class variables used by the html renderer
788 """set_parm_lists sets class variables used by the html renderer
777
789
778 measParmList - parms in the file
790 measParmList - parms in the file
779 derivedParmList - parms derivable
791 derivedParmList - parms derivable
780 allParmList - above lists combined
792 allParmList - above lists combined
781 separateProlog - if true, create separate div tags so prolog parms can be hidden or not.
793 separateProlog - if true, create separate div tags so prolog parms can be hidden or not.
782 Default is False, in which case no div tags are used
794 Default is False, in which case no div tags are used
783 """
795 """
784 self.renderer.isDerivedDict = isDerivedDict
796 self.renderer.isDerivedDict = isDerivedDict
785 self.renderer.parmDescDict = parmDescDict
797 self.renderer.parmDescDict = parmDescDict
786 self.renderer.iterator = itertools.count()
798 self.renderer.iterator = itertools.count()
787 self.renderer.separateProlog = separateProlog
799 self.renderer.separateProlog = separateProlog
788
800
789
801
790
802
791
803
792 class IsprintForm(django.forms.Form):
804 class IsprintForm(django.forms.Form):
793 """IsprintForm is the form for the enhanced isprint page
805 """IsprintForm is the form for the enhanced isprint page
794 """
806 """
795 def __init__(self, *args, **kwargs):
807 def __init__(self, *args, **kwargs):
796
808
797 madFileObj = getSelection('madFileObj', args, kwargs)
809 madFileObj = getSelection('madFileObj', args, kwargs)
798 type = getSelection('type', args, kwargs)
810 type = getSelection('type', args, kwargs)
799 formatChoices = [('ascii', 'Space-delimited ascii')]
811 formatChoices = [('ascii', 'Space-delimited ascii')]
800 if type == 'download':
812 if type == 'download':
801 formatChoices.insert(0, ('netCDF4', 'netCDF4'))
813 formatChoices.insert(0, ('netCDF4', 'netCDF4'))
802 formatChoices.insert(0, ('Hdf5', 'Hdf5'))
814 formatChoices.insert(0, ('Hdf5', 'Hdf5'))
803 separateProlog = True
815 separateProlog = True
804 else:
816 else:
805 separateProlog = False
817 separateProlog = False
806
818
807 madDB = getSelection('madDB', args, kwargs)
819 madDB = getSelection('madDB', args, kwargs)
808 madParmObj = getSelection('madParmObj', args, kwargs)
820 madParmObj = getSelection('madParmObj', args, kwargs)
809 derivedParmList = getSelection('derivedParmList', args, kwargs)
821 derivedParmList = getSelection('derivedParmList', args, kwargs)
810 allParmList = getSelection('allParmList', args, kwargs)
822 allParmList = getSelection('allParmList', args, kwargs)
811 allParmDescList = getSelection('allParmDescList', args, kwargs)
823 allParmDescList = getSelection('allParmDescList', args, kwargs)
812 self.parmList = list(zip(allParmList, allParmDescList))
824 self.parmList = list(zip(allParmList, allParmDescList))
813 super(IsprintForm, self).__init__(*args, **kwargs)
825 super(IsprintForm, self).__init__(*args, **kwargs)
814
826
815 madCatObj = madrigal.metadata.MadrigalParmCategory(madDB)
827 madCatObj = madrigal.metadata.MadrigalParmCategory(madDB)
816
828
817 catList = madCatObj.getCategoryList()
829 catList = madCatObj.getCategoryList()
818 catDict = madParmObj.getCategoryDict(allParmList)
830 catDict = madParmObj.getCategoryDict(allParmList)
819
831
820 choices = []
832 choices = []
821 isDerivedDict = {}
833 isDerivedDict = {}
822 parmDescDict = {}
834 parmDescDict = {}
823 for catDesc, catID in catList:
835 for catDesc, catID in catList:
824 if catID not in list(catDict.keys()):
836 if catID not in list(catDict.keys()):
825 continue
837 continue
826 theseParms = []
838 theseParms = []
827 for parm in catDict[catID][1]:
839 for parm in catDict[catID][1]:
828 theseParms.append((parm, parm))
840 theseParms.append((parm, parm))
829 if parm in derivedParmList:
841 if parm in derivedParmList:
830 isDerivedDict[parm] = True
842 isDerivedDict[parm] = True
831 else:
843 else:
832 isDerivedDict[parm] = False
844 isDerivedDict[parm] = False
833 parmDescDict[parm] = madParmObj.getParmDescription(parm)
845 parmDescDict[parm] = madParmObj.getParmDescription(parm)
834 choices.append((catDesc, theseParms))
846 choices.append((catDesc, theseParms))
835
847
836 choices_with_null = [('None', 'None')] + choices
848 choices_with_null = [('None', 'None')] + choices
837
849
838 earliestTime = madFileObj.getEarliestTime()
850 earliestTime = madFileObj.getEarliestTime()
839 latestTime = madFileObj.getLatestTime()
851 latestTime = madFileObj.getLatestTime()
840 earliestDT = datetime.datetime(*earliestTime)
852 earliestDT = datetime.datetime(*earliestTime)
841 latestDT = datetime.datetime(*latestTime)
853 latestDT = datetime.datetime(*latestTime)
842 earliestStr = earliestDT.strftime('%Y-%m-%d %H:%M:%S')
854 earliestStr = earliestDT.strftime('%Y-%m-%d %H:%M:%S')
843 latestStr = latestDT.strftime('%Y-%m-%d %H:%M:%S')
855 latestStr = latestDT.strftime('%Y-%m-%d %H:%M:%S')
844
856
845 self.fields['fullFilename'] = django.forms.CharField(required=False, widget=django.forms.HiddenInput())
857 self.fields['fullFilename'] = django.forms.CharField(required=False, widget=django.forms.HiddenInput())
846 self.fields['type'] = django.forms.CharField(required=False, widget=django.forms.HiddenInput())
858 self.fields['type'] = django.forms.CharField(required=False, widget=django.forms.HiddenInput())
847
859
848 # format fields
860 # format fields
849 self.fields['formats'] = django.forms.ChoiceField(widget = HorizontalRadioSelect(attrs={"onChange":'changeFormat(this)'}),
861 self.fields['formats'] = django.forms.ChoiceField(widget = HorizontalRadioSelect(attrs={"onChange":'changeFormat(this)'}),
850 choices=formatChoices, initial='ascii',
862 choices=formatChoices, initial='ascii',
851 required=False, label='Select output format:')
863 required=False, label='Select output format:')
852
864
853 self.fields['showHeaders'] = django.forms.BooleanField(required=False, label='Show headers:',
865 self.fields['showHeaders'] = django.forms.BooleanField(required=False, label='Show headers:',
854 help_text="Select this to show a header line before each record")
866 help_text="Select this to show a header line before each record")
855
867
856 self.fields['missing'] = django.forms.CharField(required=False,
868 self.fields['missing'] = django.forms.CharField(required=False,
857 label='Missing value string: ',
869 label='Missing value string: ',
858 help_text='Modify this field to display something other than NaN for missing or assumed or known bad data.')
870 help_text='Modify this field to display something other than NaN for missing or assumed or known bad data.')
859
871
860 # form fields
872 # form fields
861 self.fields['parameters'] = IsprintChoiceField(choices=choices,
873 self.fields['parameters'] = IsprintChoiceField(choices=choices,
862 required=False,
874 required=False,
863 initial=['YEAR', 'MIN'],
875 initial=['YEAR', 'MIN'],
864 isDerivedDict=isDerivedDict,
876 isDerivedDict=isDerivedDict,
865 parmDescDict=parmDescDict,
877 parmDescDict=parmDescDict,
866 separateProlog=separateProlog,
878 separateProlog=separateProlog,
867 label = "")
879 label = "")
868
880
869 # time selection
881 # time selection
870 self.fields['start_date'] = django.forms.DateTimeField(input_formats=['%Y-%m-%dT%H:%M:%S'],
882 self.fields['start_date'] = django.forms.DateTimeField(input_formats=['%Y-%m-%dT%H:%M:%S'],
871 label='Start datetime',
883 label='Start datetime',
872 help_text='Modify this field to remove all records before this start time. Initial start datetime is the time of the first record.',
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 widget=django.forms.DateTimeInput(format='%Y-%m-%dT%H:%M:%S'),
885 widget=django.forms.DateTimeInput(format='%Y-%m-%dT%H:%M:%S'),
874 required=False)
886 required=False)
875
887
876 self.fields['end_date'] = django.forms.DateTimeField(input_formats=['%Y-%m-%dT%H:%M:%S'],
888 self.fields['end_date'] = django.forms.DateTimeField(input_formats=['%Y-%m-%dT%H:%M:%S'],
877 label='End datetime',
889 label='End datetime',
878 help_text='Modify this field to remove all records after this end time. Initial end datetime is the time of the last record.',
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 widget=django.forms.DateTimeInput(format='%Y-%m-%dT%H:%M:%S'),
891 widget=django.forms.DateTimeInput(format='%Y-%m-%dT%H:%M:%S'),
880 required=False)
892 required=False)
881
893
882 self.fields['parm_1'] = django.forms.ChoiceField(required=False,
894 self.fields['parm_1'] = django.forms.ChoiceField(required=False,
883 choices=choices_with_null)
895 choices=choices_with_null)
884 self.fields['parm_1_lower'] = django.forms.CharField(required=False, initial='')
896 self.fields['parm_1_lower'] = django.forms.CharField(required=False, initial='')
885 self.fields['parm_1_upper'] = django.forms.CharField(required=False, initial='')
897 self.fields['parm_1_upper'] = django.forms.CharField(required=False, initial='')
886
898
887 self.fields['parm_2'] = django.forms.ChoiceField(required=False,
899 self.fields['parm_2'] = django.forms.ChoiceField(required=False,
888 choices=choices_with_null)
900 choices=choices_with_null)
889 self.fields['parm_2_lower'] = django.forms.CharField(required=False, initial='')
901 self.fields['parm_2_lower'] = django.forms.CharField(required=False, initial='')
890 self.fields['parm_2_upper'] = django.forms.CharField(required=False, initial='')
902 self.fields['parm_2_upper'] = django.forms.CharField(required=False, initial='')
891
903
892 self.fields['parm_3'] = django.forms.ChoiceField(required=False,
904 self.fields['parm_3'] = django.forms.ChoiceField(required=False,
893 choices=choices_with_null)
905 choices=choices_with_null)
894 self.fields['parm_3_lower'] = django.forms.CharField(required=False, initial='')
906 self.fields['parm_3_lower'] = django.forms.CharField(required=False, initial='')
895 self.fields['parm_3_upper'] = django.forms.CharField(required=False, initial='')
907 self.fields['parm_3_upper'] = django.forms.CharField(required=False, initial='')
896
908
897 # add optional fields
909 # add optional fields
898 if 'GDALT' in allParmList:
910 if 'GDALT' in allParmList:
899 min_alt_value = getSelection('min_alt', args, kwargs)
911 min_alt_value = getSelection('min_alt', args, kwargs)
900 max_alt_value = getSelection('max_alt', args, kwargs)
912 max_alt_value = getSelection('max_alt', args, kwargs)
901 if min_alt_value != max_alt_value:
913 if min_alt_value != max_alt_value:
902 self.fields['min_alt'] = django.forms.CharField(required=False,
914 self.fields['min_alt'] = django.forms.CharField(required=False,
903 label='Min altitude:',
915 label='Min altitude:',
904 help_text='Modify this field to remove all data with altitudes below this level.')
916 help_text='Modify this field to remove all data with altitudes below this level.')
905 self.fields['max_alt'] = django.forms.CharField(required=False,
917 self.fields['max_alt'] = django.forms.CharField(required=False,
906 label='Max altitude:',
918 label='Max altitude:',
907 help_text='Modify this field to remove all data with altitudes above this level.')
919 help_text='Modify this field to remove all data with altitudes above this level.')
908
920
909 if 'AZM' in allParmList:
921 if 'AZM' in allParmList:
910 self.fields['min_az'] = django.forms.CharField(required=False,
922 self.fields['min_az'] = django.forms.CharField(required=False,
911 label='Min azimuth:',
923 label='Min azimuth:',
912 help_text='Modify this field to remove all azimuths (-180 to 180) below this value. You can also have two separate azimuth ranges by using the Azimuth 2 fields.')
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 self.fields['max_az'] = django.forms.CharField(required=False,
925 self.fields['max_az'] = django.forms.CharField(required=False,
914 label='Max azimuth:',
926 label='Max azimuth:',
915 help_text='Modify this field to remove all azimuths (-180 to 180) above this value. You can also have two separate azimuth ranges by using the Azimuth 2 fields.')
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 self.fields['min_az2'] = django.forms.CharField(required=False,
928 self.fields['min_az2'] = django.forms.CharField(required=False,
917 label='Min azimuth 2:',
929 label='Min azimuth 2:',
918 help_text='Modify this field to have a second allowed azimuth range. This would set the lower limit of the second range.')
930 help_text='Modify this field to have a second allowed azimuth range. This would set the lower limit of the second range.')
919 self.fields['max_az2'] = django.forms.CharField(required=False,
931 self.fields['max_az2'] = django.forms.CharField(required=False,
920 label='Max azimuth 2:',
932 label='Max azimuth 2:',
921 help_text='Modify this field to have a second allowed azimuth range. This would set the upper limit of the second range.')
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 if 'ELM' in allParmList:
935 if 'ELM' in allParmList:
924 self.fields['min_el'] = django.forms.CharField(required=False,
936 self.fields['min_el'] = django.forms.CharField(required=False,
925 label='Min elevation:',
937 label='Min elevation:',
926 help_text='Modify this field to remove all elevations (0 to 90) below this value. You can also have two separate elevations ranges by using the Elevations 2 fields.')
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 self.fields['max_el'] = django.forms.CharField(required=False,
939 self.fields['max_el'] = django.forms.CharField(required=False,
928 label='Max elevation:',
940 label='Max elevation:',
929 help_text='Modify this field to remove all elevations (0 to 90) above this value. You can also have two separate elevations ranges by using the Elevations 2 fields.')
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 self.fields['min_el2'] = django.forms.CharField(required=False,
942 self.fields['min_el2'] = django.forms.CharField(required=False,
931 label='Min elevation 2:',
943 label='Min elevation 2:',
932 help_text='Modify this field to have a second allowed elevation range. This would set the lower limit of the second range.')
944 help_text='Modify this field to have a second allowed elevation range. This would set the lower limit of the second range.')
933 self.fields['max_el2'] = django.forms.CharField(required=False,
945 self.fields['max_el2'] = django.forms.CharField(required=False,
934 label='Max elevation 2:',
946 label='Max elevation 2:',
935 help_text='Modify this field to have a second allowed elevation range. This would set the upper limit of the second range.')
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 if 'PL' in allParmList:
949 if 'PL' in allParmList:
938 min_pl_value = getSelection('min_pl', args, kwargs)
950 min_pl_value = getSelection('min_pl', args, kwargs)
939 max_pl_value = getSelection('max_pl', args, kwargs)
951 max_pl_value = getSelection('max_pl', args, kwargs)
940 self.fields['min_pl'] = django.forms.CharField(required=False,
952 self.fields['min_pl'] = django.forms.CharField(required=False,
941 label='Min pulse len (microsec): ',
953 label='Min pulse len (microsec): ',
942 help_text='Modify this field to remove all pulse lengths in microsecs below this value.')
954 help_text='Modify this field to remove all pulse lengths in microsecs below this value.')
943 self.fields['max_pl'] = django.forms.CharField(required=False,
955 self.fields['max_pl'] = django.forms.CharField(required=False,
944 label='Max pulse len (microsec): ',
956 label='Max pulse len (microsec): ',
945 help_text='Modify this field to remove all pulse lengths in microsecs above this value.')
957 help_text='Modify this field to remove all pulse lengths in microsecs above this value.')
946
958
947
959
948 def clean_fullFilename(self):
960 def clean_fullFilename(self):
949 fullFilename = self.cleaned_data['fullFilename']
961 fullFilename = self.cleaned_data['fullFilename']
950 # make sure the file exists
962 # make sure the file exists
951 if not os.access(fullFilename, os.R_OK):
963 if not os.access(fullFilename, os.R_OK):
952 raise django.forms.ValidationError('Invalid filename: %(value)s cannot be opened',
964 raise django.forms.ValidationError('Invalid filename: %(value)s cannot be opened',
953 code='io_error',
965 code='io_error',
954 params={'value': fullFilename})
966 params={'value': fullFilename})
955
967
956 return(fullFilename)
968 return(fullFilename)
957
969
958
970
959 def clean_formats(self):
971 def clean_formats(self):
960 formats = self.cleaned_data['formats']
972 formats = self.cleaned_data['formats']
961 # make sure the format valid
973 # make sure the format valid
962 if formats not in ('Hdf5', 'netCDF4', 'ascii'):
974 if formats not in ('Hdf5', 'netCDF4', 'ascii'):
963 raise django.forms.ValidationError('Invalid format: %(value)s not legal format',
975 raise django.forms.ValidationError('Invalid format: %(value)s not legal format',
964 code='invalid',
976 code='invalid',
965 params={'value': formats})
977 params={'value': formats})
966
978
967 return(formats)
979 return(formats)
968
980
969
981
970 def clean_min_alt(self):
982 def clean_min_alt(self):
971 min_alt = self.cleaned_data['min_alt']
983 min_alt = self.cleaned_data['min_alt']
972 if len(min_alt) != 0:
984 if len(min_alt) != 0:
973 try:
985 try:
974 min_alt_value = float(min_alt)
986 min_alt_value = float(min_alt)
975 except:
987 except:
976 raise django.forms.ValidationError('Invalid minimum altitude: %(value)s cannot be converted to a float',
988 raise django.forms.ValidationError('Invalid minimum altitude: %(value)s cannot be converted to a float',
977 code='invalid',
989 code='invalid',
978 params={'value': min_alt})
990 params={'value': min_alt})
979 if min_alt_value < 0.0:
991 if min_alt_value < 0.0:
980 raise django.forms.ValidationError('Invalid minimum altitude: %(value)s cannot be less than 0.0 kilometers',
992 raise django.forms.ValidationError('Invalid minimum altitude: %(value)s cannot be less than 0.0 kilometers',
981 code='invalid',
993 code='invalid',
982 params={'value': min_alt})
994 params={'value': min_alt})
983 return(min_alt)
995 return(min_alt)
984
996
985 def clean_max_alt(self):
997 def clean_max_alt(self):
986 max_alt = self.cleaned_data['max_alt']
998 max_alt = self.cleaned_data['max_alt']
987 if len(max_alt) != 0:
999 if len(max_alt) != 0:
988 try:
1000 try:
989 max_alt_value = float(max_alt)
1001 max_alt_value = float(max_alt)
990 except:
1002 except:
991 raise django.forms.ValidationError('Invalid maximum altitude: %(value)s cannot be converted to a float',
1003 raise django.forms.ValidationError('Invalid maximum altitude: %(value)s cannot be converted to a float',
992 code='invalid',
1004 code='invalid',
993 params={'value': max_alt})
1005 params={'value': max_alt})
994 if max_alt_value < 0.0:
1006 if max_alt_value < 0.0:
995 raise django.forms.ValidationError('Invalid maximum altitude: %(value)s cannot be less than 0.0 kilometers',
1007 raise django.forms.ValidationError('Invalid maximum altitude: %(value)s cannot be less than 0.0 kilometers',
996 code='invalid',
1008 code='invalid',
997 params={'value': max_alt})
1009 params={'value': max_alt})
998 return(max_alt)
1010 return(max_alt)
999
1011
1000
1012
1001 def clean_min_az(self):
1013 def clean_min_az(self):
1002 min_az = self.cleaned_data['min_az']
1014 min_az = self.cleaned_data['min_az']
1003 if len(min_az) != 0:
1015 if len(min_az) != 0:
1004 try:
1016 try:
1005 min_az_value = float(min_az)
1017 min_az_value = float(min_az)
1006 except:
1018 except:
1007 raise django.forms.ValidationError('Invalid minimum azimuth: %(value)s cannot be converted to a float',
1019 raise django.forms.ValidationError('Invalid minimum azimuth: %(value)s cannot be converted to a float',
1008 code='invalid',
1020 code='invalid',
1009 params={'value': min_az})
1021 params={'value': min_az})
1010 if min_az_value < -180.0:
1022 if min_az_value < -180.0:
1011 raise django.forms.ValidationError('Invalid minimum azimuth: %(value)s cannot be less than -180 degrees',
1023 raise django.forms.ValidationError('Invalid minimum azimuth: %(value)s cannot be less than -180 degrees',
1012 code='invalid',
1024 code='invalid',
1013 params={'value': min_az})
1025 params={'value': min_az})
1014 if min_az_value > 180.0:
1026 if min_az_value > 180.0:
1015 raise django.forms.ValidationError('Invalid minimum azimuth: %(value)s cannot be more than 180 degrees',
1027 raise django.forms.ValidationError('Invalid minimum azimuth: %(value)s cannot be more than 180 degrees',
1016 code='invalid',
1028 code='invalid',
1017 params={'value': min_az})
1029 params={'value': min_az})
1018 return(min_az)
1030 return(min_az)
1019
1031
1020
1032
1021 def clean_max_az(self):
1033 def clean_max_az(self):
1022 max_az = self.cleaned_data['max_az']
1034 max_az = self.cleaned_data['max_az']
1023 if len(max_az) != 0:
1035 if len(max_az) != 0:
1024 try:
1036 try:
1025 max_az_value = float(max_az)
1037 max_az_value = float(max_az)
1026 except:
1038 except:
1027 raise django.forms.ValidationError('Invalid maximum azimuth: %(value)s cannot be converted to a float',
1039 raise django.forms.ValidationError('Invalid maximum azimuth: %(value)s cannot be converted to a float',
1028 code='invalid',
1040 code='invalid',
1029 params={'value': max_az})
1041 params={'value': max_az})
1030 if max_az_value < -180.0:
1042 if max_az_value < -180.0:
1031 raise django.forms.ValidationError('Invalid maximum azimuth: %(value)s cannot be less than -180 degrees',
1043 raise django.forms.ValidationError('Invalid maximum azimuth: %(value)s cannot be less than -180 degrees',
1032 code='invalid',
1044 code='invalid',
1033 params={'value': max_az})
1045 params={'value': max_az})
1034 if max_az_value > 180.0:
1046 if max_az_value > 180.0:
1035 raise django.forms.ValidationError('Invalid maximum azimuth: %(value)s cannot be more than 180 degrees',
1047 raise django.forms.ValidationError('Invalid maximum azimuth: %(value)s cannot be more than 180 degrees',
1036 code='invalid',
1048 code='invalid',
1037 params={'value': max_az})
1049 params={'value': max_az})
1038 return(max_az)
1050 return(max_az)
1039
1051
1040
1052
1041 def clean_min_el(self):
1053 def clean_min_el(self):
1042 min_el = self.cleaned_data['min_el']
1054 min_el = self.cleaned_data['min_el']
1043 if len(min_el) != 0:
1055 if len(min_el) != 0:
1044 try:
1056 try:
1045 min_el_value = float(min_el)
1057 min_el_value = float(min_el)
1046 except:
1058 except:
1047 raise django.forms.ValidationError('Invalid minimum elevation: %(value)s cannot be converted to a float',
1059 raise django.forms.ValidationError('Invalid minimum elevation: %(value)s cannot be converted to a float',
1048 code='invalid',
1060 code='invalid',
1049 params={'value': min_el})
1061 params={'value': min_el})
1050 if min_el_value < 0.0:
1062 if min_el_value < 0.0:
1051 raise django.forms.ValidationError('Invalid minimum elevation: %(value)s cannot be less than 0 degrees',
1063 raise django.forms.ValidationError('Invalid minimum elevation: %(value)s cannot be less than 0 degrees',
1052 code='invalid',
1064 code='invalid',
1053 params={'value': min_el})
1065 params={'value': min_el})
1054 if min_el_value > 90.0:
1066 if min_el_value > 90.0:
1055 raise django.forms.ValidationError('Invalid minimum elevation: %(value)s cannot be more than 90 degrees',
1067 raise django.forms.ValidationError('Invalid minimum elevation: %(value)s cannot be more than 90 degrees',
1056 code='invalid',
1068 code='invalid',
1057 params={'value': min_el})
1069 params={'value': min_el})
1058 return(min_el)
1070 return(min_el)
1059
1071
1060
1072
1061 def clean_max_el(self):
1073 def clean_max_el(self):
1062 max_el = self.cleaned_data['max_el']
1074 max_el = self.cleaned_data['max_el']
1063 if len(max_el) != 0:
1075 if len(max_el) != 0:
1064 try:
1076 try:
1065 max_el_value = float(max_el)
1077 max_el_value = float(max_el)
1066 except:
1078 except:
1067 raise django.forms.ValidationError('Invalid maximum elevation: %(value)s cannot be converted to a float',
1079 raise django.forms.ValidationError('Invalid maximum elevation: %(value)s cannot be converted to a float',
1068 code='invalid',
1080 code='invalid',
1069 params={'value': max_el})
1081 params={'value': max_el})
1070 if max_el_value < 0.0:
1082 if max_el_value < 0.0:
1071 raise django.forms.ValidationError('Invalid maximum elevation: %(value)s cannot be less than 0 degrees',
1083 raise django.forms.ValidationError('Invalid maximum elevation: %(value)s cannot be less than 0 degrees',
1072 code='invalid',
1084 code='invalid',
1073 params={'value': max_el})
1085 params={'value': max_el})
1074 if max_el_value > 90.0:
1086 if max_el_value > 90.0:
1075 raise django.forms.ValidationError('Invalid maximum elevation: %(value)s cannot be more than 90 degrees',
1087 raise django.forms.ValidationError('Invalid maximum elevation: %(value)s cannot be more than 90 degrees',
1076 code='invalid',
1088 code='invalid',
1077 params={'value': max_el})
1089 params={'value': max_el})
1078 return(max_el)
1090 return(max_el)
1079
1091
1080
1092
1081 def clean_min_az2(self):
1093 def clean_min_az2(self):
1082 min_az2 = self.cleaned_data['min_az2']
1094 min_az2 = self.cleaned_data['min_az2']
1083 if len(min_az2) != 0:
1095 if len(min_az2) != 0:
1084 try:
1096 try:
1085 min_az2_value = float(min_az2)
1097 min_az2_value = float(min_az2)
1086 except:
1098 except:
1087 raise django.forms.ValidationError('Invalid minimum azimuth 2: %(value)s cannot be converted to a float',
1099 raise django.forms.ValidationError('Invalid minimum azimuth 2: %(value)s cannot be converted to a float',
1088 code='invalid',
1100 code='invalid',
1089 params={'value': min_az2})
1101 params={'value': min_az2})
1090 if min_az2_value < -180.0:
1102 if min_az2_value < -180.0:
1091 raise django.forms.ValidationError('Invalid minimum azimuth 2: %(value)s cannot be less than -180 degrees',
1103 raise django.forms.ValidationError('Invalid minimum azimuth 2: %(value)s cannot be less than -180 degrees',
1092 code='invalid',
1104 code='invalid',
1093 params={'value': min_az2})
1105 params={'value': min_az2})
1094 if min_az2_value > 180.0:
1106 if min_az2_value > 180.0:
1095 raise django.forms.ValidationError('Invalid minimum azimuth 2: %(value)s cannot be more than 180 degrees',
1107 raise django.forms.ValidationError('Invalid minimum azimuth 2: %(value)s cannot be more than 180 degrees',
1096 code='invalid',
1108 code='invalid',
1097 params={'value': min_az2})
1109 params={'value': min_az2})
1098 return(min_az2)
1110 return(min_az2)
1099
1111
1100
1112
1101 def clean_max_az2(self):
1113 def clean_max_az2(self):
1102 max_az2 = self.cleaned_data['max_az2']
1114 max_az2 = self.cleaned_data['max_az2']
1103 if len(max_az2) != 0:
1115 if len(max_az2) != 0:
1104 try:
1116 try:
1105 max_az2_value = float(max_az2)
1117 max_az2_value = float(max_az2)
1106 except:
1118 except:
1107 raise django.forms.ValidationError('Invalid maximum azimuth 2: %(value)s cannot be converted to a float',
1119 raise django.forms.ValidationError('Invalid maximum azimuth 2: %(value)s cannot be converted to a float',
1108 code='invalid',
1120 code='invalid',
1109 params={'value': max_az2})
1121 params={'value': max_az2})
1110 if max_az2_value < -180.0:
1122 if max_az2_value < -180.0:
1111 raise django.forms.ValidationError('Invalid maximum azimuth 2: %(value)s cannot be less than -180 degrees',
1123 raise django.forms.ValidationError('Invalid maximum azimuth 2: %(value)s cannot be less than -180 degrees',
1112 code='invalid',
1124 code='invalid',
1113 params={'value': max_az2})
1125 params={'value': max_az2})
1114 if max_az2_value > 180.0:
1126 if max_az2_value > 180.0:
1115 raise django.forms.ValidationError('Invalid maximum azimuth 2: %(value)s cannot be more than 180 degrees',
1127 raise django.forms.ValidationError('Invalid maximum azimuth 2: %(value)s cannot be more than 180 degrees',
1116 code='invalid',
1128 code='invalid',
1117 params={'value': max_az2})
1129 params={'value': max_az2})
1118 return(max_az2)
1130 return(max_az2)
1119
1131
1120
1132
1121 def clean_min_el2(self):
1133 def clean_min_el2(self):
1122 min_el2 = self.cleaned_data['min_el2']
1134 min_el2 = self.cleaned_data['min_el2']
1123 if len(min_el2) != 0:
1135 if len(min_el2) != 0:
1124 try:
1136 try:
1125 min_el2_value = float(min_el2)
1137 min_el2_value = float(min_el2)
1126 except:
1138 except:
1127 raise django.forms.ValidationError('Invalid minimum elevation 2: %(value)s cannot be converted to a float',
1139 raise django.forms.ValidationError('Invalid minimum elevation 2: %(value)s cannot be converted to a float',
1128 code='invalid',
1140 code='invalid',
1129 params={'value': min_el2})
1141 params={'value': min_el2})
1130 if min_el2_value < 0.0:
1142 if min_el2_value < 0.0:
1131 raise django.forms.ValidationError('Invalid minimum elevation 2: %(value)s cannot be less than 0 degrees',
1143 raise django.forms.ValidationError('Invalid minimum elevation 2: %(value)s cannot be less than 0 degrees',
1132 code='invalid',
1144 code='invalid',
1133 params={'value': min_el2})
1145 params={'value': min_el2})
1134 if min_el2_value > 90.0:
1146 if min_el2_value > 90.0:
1135 raise django.forms.ValidationError('Invalid minimum elevation 2: %(value)s cannot be more than 90 degrees',
1147 raise django.forms.ValidationError('Invalid minimum elevation 2: %(value)s cannot be more than 90 degrees',
1136 code='invalid',
1148 code='invalid',
1137 params={'value': min_el2})
1149 params={'value': min_el2})
1138 return(min_el2)
1150 return(min_el2)
1139
1151
1140
1152
1141 def clean_max_el2(self):
1153 def clean_max_el2(self):
1142 max_el2 = self.cleaned_data['max_el2']
1154 max_el2 = self.cleaned_data['max_el2']
1143 if len(max_el2) != 0:
1155 if len(max_el2) != 0:
1144 try:
1156 try:
1145 max_el2_value = float(max_el2)
1157 max_el2_value = float(max_el2)
1146 except:
1158 except:
1147 raise django.forms.ValidationError('Invalid maximum elevation 2: %(value)s cannot be converted to a float',
1159 raise django.forms.ValidationError('Invalid maximum elevation 2: %(value)s cannot be converted to a float',
1148 code='invalid',
1160 code='invalid',
1149 params={'value': max_el2})
1161 params={'value': max_el2})
1150 if max_el2_value < 0.0:
1162 if max_el2_value < 0.0:
1151 raise django.forms.ValidationError('Invalid maximum elevation 2: %(value)s cannot be less than 0 degrees',
1163 raise django.forms.ValidationError('Invalid maximum elevation 2: %(value)s cannot be less than 0 degrees',
1152 code='invalid',
1164 code='invalid',
1153 params={'value': max_el2})
1165 params={'value': max_el2})
1154 if max_el2_value > 90.0:
1166 if max_el2_value > 90.0:
1155 raise django.forms.ValidationError('Invalid maximum elevation 2: %(value)s cannot be more than 90 degrees',
1167 raise django.forms.ValidationError('Invalid maximum elevation 2: %(value)s cannot be more than 90 degrees',
1156 code='invalid',
1168 code='invalid',
1157 params={'value': max_el2})
1169 params={'value': max_el2})
1158 return(max_el2)
1170 return(max_el2)
1159
1171
1160
1172
1161 def clean_min_pl(self):
1173 def clean_min_pl(self):
1162 min_pl = self.cleaned_data['min_pl']
1174 min_pl = self.cleaned_data['min_pl']
1163 if len(min_pl) != 0:
1175 if len(min_pl) != 0:
1164 try:
1176 try:
1165 min_pl_value = float(min_pl)
1177 min_pl_value = float(min_pl)
1166 except:
1178 except:
1167 raise django.forms.ValidationError('Invalid lower limit for pulse length: %(value)s cannot be converted to a float',
1179 raise django.forms.ValidationError('Invalid lower limit for pulse length: %(value)s cannot be converted to a float',
1168 code='invalid',
1180 code='invalid',
1169 params={'value': min_pl})
1181 params={'value': min_pl})
1170 return(min_pl)
1182 return(min_pl)
1171
1183
1172
1184
1173 def clean_max_pl(self):
1185 def clean_max_pl(self):
1174 max_pl = self.cleaned_data['max_pl']
1186 max_pl = self.cleaned_data['max_pl']
1175 if len(max_pl) != 0:
1187 if len(max_pl) != 0:
1176 try:
1188 try:
1177 max_pl_value = float(max_pl)
1189 max_pl_value = float(max_pl)
1178 except:
1190 except:
1179 raise django.forms.ValidationError('Invalid upper limit for pulse length: %(value)s cannot be converted to a float',
1191 raise django.forms.ValidationError('Invalid upper limit for pulse length: %(value)s cannot be converted to a float',
1180 code='invalid',
1192 code='invalid',
1181 params={'value': max_pl})
1193 params={'value': max_pl})
1182 return(max_pl)
1194 return(max_pl)
1183
1195
1184
1196
1185 def clean_parm_1_lower(self):
1197 def clean_parm_1_lower(self):
1186 parm_1_lower = self.cleaned_data['parm_1_lower']
1198 parm_1_lower = self.cleaned_data['parm_1_lower']
1187 if len(parm_1_lower) != 0:
1199 if len(parm_1_lower) != 0:
1188 try:
1200 try:
1189 parm_1_lower_value = float(parm_1_lower)
1201 parm_1_lower_value = float(parm_1_lower)
1190 except:
1202 except:
1191 raise django.forms.ValidationError('Invalid lower limit for parm 1: %(value)s cannot be converted to a float',
1203 raise django.forms.ValidationError('Invalid lower limit for parm 1: %(value)s cannot be converted to a float',
1192 code='invalid',
1204 code='invalid',
1193 params={'value': parm_1_lower})
1205 params={'value': parm_1_lower})
1194 return(parm_1_lower)
1206 return(parm_1_lower)
1195
1207
1196
1208
1197 def clean_parm_1_upper(self):
1209 def clean_parm_1_upper(self):
1198 parm_1_upper = self.cleaned_data['parm_1_upper']
1210 parm_1_upper = self.cleaned_data['parm_1_upper']
1199 if len(parm_1_upper) != 0:
1211 if len(parm_1_upper) != 0:
1200 try:
1212 try:
1201 parm_1_upper_value = float(parm_1_upper)
1213 parm_1_upper_value = float(parm_1_upper)
1202 except:
1214 except:
1203 raise django.forms.ValidationError('Invalid upper limit for parm 1: %(value)s cannot be converted to a float',
1215 raise django.forms.ValidationError('Invalid upper limit for parm 1: %(value)s cannot be converted to a float',
1204 code='invalid',
1216 code='invalid',
1205 params={'value': parm_1_upper})
1217 params={'value': parm_1_upper})
1206 return(parm_1_upper)
1218 return(parm_1_upper)
1207
1219
1208
1220
1209 def clean_parm_2_lower(self):
1221 def clean_parm_2_lower(self):
1210 parm_2_lower = self.cleaned_data['parm_2_lower']
1222 parm_2_lower = self.cleaned_data['parm_2_lower']
1211 if len(parm_2_lower) != 0:
1223 if len(parm_2_lower) != 0:
1212 try:
1224 try:
1213 parm_2_lower_value = float(parm_2_lower)
1225 parm_2_lower_value = float(parm_2_lower)
1214 except:
1226 except:
1215 raise django.forms.ValidationError('Invalid lower limit for parm 2: %(value)s cannot be converted to a float',
1227 raise django.forms.ValidationError('Invalid lower limit for parm 2: %(value)s cannot be converted to a float',
1216 code='invalid',
1228 code='invalid',
1217 params={'value': parm_2_lower})
1229 params={'value': parm_2_lower})
1218 return(parm_2_lower)
1230 return(parm_2_lower)
1219
1231
1220
1232
1221 def clean_parm_2_upper(self):
1233 def clean_parm_2_upper(self):
1222 parm_2_upper = self.cleaned_data['parm_2_upper']
1234 parm_2_upper = self.cleaned_data['parm_2_upper']
1223 if len(parm_2_upper) != 0:
1235 if len(parm_2_upper) != 0:
1224 try:
1236 try:
1225 parm_2_upper_value = float(parm_2_upper)
1237 parm_2_upper_value = float(parm_2_upper)
1226 except:
1238 except:
1227 raise django.forms.ValidationError('Invalid upper limit for parm 2: %(value)s cannot be converted to a float',
1239 raise django.forms.ValidationError('Invalid upper limit for parm 2: %(value)s cannot be converted to a float',
1228 code='invalid',
1240 code='invalid',
1229 params={'value': parm_2_upper})
1241 params={'value': parm_2_upper})
1230 return(parm_2_upper)
1242 return(parm_2_upper)
1231
1243
1232
1244
1233 def clean_parm_3_lower(self):
1245 def clean_parm_3_lower(self):
1234 parm_3_lower = self.cleaned_data['parm_3_lower']
1246 parm_3_lower = self.cleaned_data['parm_3_lower']
1235 if len(parm_3_lower) != 0:
1247 if len(parm_3_lower) != 0:
1236 try:
1248 try:
1237 parm_3_lower_value = float(parm_3_lower)
1249 parm_3_lower_value = float(parm_3_lower)
1238 except:
1250 except:
1239 raise django.forms.ValidationError('Invalid lower limit for parm 3: %(value)s cannot be converted to a float',
1251 raise django.forms.ValidationError('Invalid lower limit for parm 3: %(value)s cannot be converted to a float',
1240 code='invalid',
1252 code='invalid',
1241 params={'value': parm_3_lower})
1253 params={'value': parm_3_lower})
1242 return(parm_3_lower)
1254 return(parm_3_lower)
1243
1255
1244
1256
1245 def clean_parm_3_upper(self):
1257 def clean_parm_3_upper(self):
1246 parm_3_upper = self.cleaned_data['parm_3_upper']
1258 parm_3_upper = self.cleaned_data['parm_3_upper']
1247 if len(parm_3_upper) != 0:
1259 if len(parm_3_upper) != 0:
1248 try:
1260 try:
1249 parm_3_upper_value = float(parm_3_upper)
1261 parm_3_upper_value = float(parm_3_upper)
1250 except:
1262 except:
1251 raise django.forms.ValidationError('Invalid upper limit for parm 3: %(value)s cannot be converted to a float',
1263 raise django.forms.ValidationError('Invalid upper limit for parm 3: %(value)s cannot be converted to a float',
1252 code='invalid',
1264 code='invalid',
1253 params={'value': parm_3_upper})
1265 params={'value': parm_3_upper})
1254 return(parm_3_upper)
1266 return(parm_3_upper)
1255
1267
1256
1268
1257
1269
1258
1270
1259 def clean(self):
1271 def clean(self):
1260 """clean in the Django method to validate things in a form that require looking at multiple fields
1272 """clean in the Django method to validate things in a form that require looking at multiple fields
1261 """
1273 """
1262 # rule 1 - start_date < end_date
1274 # rule 1 - start_date < end_date
1263 if self.cleaned_data['start_date'] > self.cleaned_data['end_date']:
1275 if self.cleaned_data['start_date'] > self.cleaned_data['end_date']:
1264 raise django.forms.ValidationError('Error - start datetime greater than end datetime.')
1276 raise django.forms.ValidationError('Error - start datetime greater than end datetime.')
1265
1277
1266 # rule 2 - min_alt <= max_alt
1278 # rule 2 - min_alt <= max_alt
1267 try:
1279 try:
1268 min_alt = float(self.cleaned_data['min_alt'])
1280 min_alt = float(self.cleaned_data['min_alt'])
1269 max_alt = float(self.cleaned_data['max_alt'])
1281 max_alt = float(self.cleaned_data['max_alt'])
1270 except:
1282 except:
1271 min_alt = 0.0
1283 min_alt = 0.0
1272 max_alt = 1.0
1284 max_alt = 1.0
1273 if min_alt > max_alt:
1285 if min_alt > max_alt:
1274 raise django.forms.ValidationError('Error - Minimum altitude greater than maximum altitude.')
1286 raise django.forms.ValidationError('Error - Minimum altitude greater than maximum altitude.')
1275
1287
1276 # rule 3 - min_az <= max_az
1288 # rule 3 - min_az <= max_az
1277 try:
1289 try:
1278 min_az = float(self.cleaned_data['min_az'])
1290 min_az = float(self.cleaned_data['min_az'])
1279 max_az = float(self.cleaned_data['max_az'])
1291 max_az = float(self.cleaned_data['max_az'])
1280 except:
1292 except:
1281 min_az = 0.0
1293 min_az = 0.0
1282 max_az = 1.0
1294 max_az = 1.0
1283 if min_az > max_az:
1295 if min_az > max_az:
1284 raise django.forms.ValidationError('Error - Minimum azimuth greater than maximum azimuth.')
1296 raise django.forms.ValidationError('Error - Minimum azimuth greater than maximum azimuth.')
1285
1297
1286 # rule 4 - min_el <= max_el
1298 # rule 4 - min_el <= max_el
1287 try:
1299 try:
1288 min_el = float(self.cleaned_data['min_el'])
1300 min_el = float(self.cleaned_data['min_el'])
1289 max_el = float(self.cleaned_data['max_el'])
1301 max_el = float(self.cleaned_data['max_el'])
1290 except:
1302 except:
1291 min_el = 0.0
1303 min_el = 0.0
1292 max_el = 1.0
1304 max_el = 1.0
1293 if min_el > max_el:
1305 if min_el > max_el:
1294 raise django.forms.ValidationError('Error - Minimum elevation greater than maximum elevation.')
1306 raise django.forms.ValidationError('Error - Minimum elevation greater than maximum elevation.')
1295
1307
1296 # rule 5 - min_az2 <= max_az2
1308 # rule 5 - min_az2 <= max_az2
1297 try:
1309 try:
1298 min_az2 = float(self.cleaned_data['min_az2'])
1310 min_az2 = float(self.cleaned_data['min_az2'])
1299 max_az2 = float(self.cleaned_data['max_az2'])
1311 max_az2 = float(self.cleaned_data['max_az2'])
1300 except:
1312 except:
1301 min_az2 = 0.0
1313 min_az2 = 0.0
1302 max_az2 = 1.0
1314 max_az2 = 1.0
1303 if min_az2 > max_az2:
1315 if min_az2 > max_az2:
1304 raise django.forms.ValidationError('Error - Minimum azimuth 2 greater than maximum azimuth 2.')
1316 raise django.forms.ValidationError('Error - Minimum azimuth 2 greater than maximum azimuth 2.')
1305
1317
1306 # rule 6 - min_el2 <= max_el2
1318 # rule 6 - min_el2 <= max_el2
1307 try:
1319 try:
1308 min_el2 = float(self.cleaned_data['min_el2'])
1320 min_el2 = float(self.cleaned_data['min_el2'])
1309 max_el2 = float(self.cleaned_data['max_el2'])
1321 max_el2 = float(self.cleaned_data['max_el2'])
1310 except:
1322 except:
1311 min_el2 = 0.0
1323 min_el2 = 0.0
1312 max_el2 = 1.0
1324 max_el2 = 1.0
1313 if min_el2 > max_el2:
1325 if min_el2 > max_el2:
1314 raise django.forms.ValidationError('Error - Minimum elevation 2 greater than maximum elevation 2.')
1326 raise django.forms.ValidationError('Error - Minimum elevation 2 greater than maximum elevation 2.')
1315
1327
1316 # rule 7 - min_pl <= max_pl
1328 # rule 7 - min_pl <= max_pl
1317 try:
1329 try:
1318 min_pl = float(self.cleaned_data['min_pl'])
1330 min_pl = float(self.cleaned_data['min_pl'])
1319 max_pl = float(self.cleaned_data['max_pl'])
1331 max_pl = float(self.cleaned_data['max_pl'])
1320 except:
1332 except:
1321 min_pl = 0.0
1333 min_pl = 0.0
1322 max_pl = 1.0
1334 max_pl = 1.0
1323 if min_pl > max_pl:
1335 if min_pl > max_pl:
1324 raise django.forms.ValidationError('Error - Minimum pulse length greater than maximum pulse length.')
1336 raise django.forms.ValidationError('Error - Minimum pulse length greater than maximum pulse length.')
1325
1337
1326 # rule 8 - parm_1_lower <= parm_1_upper
1338 # rule 8 - parm_1_lower <= parm_1_upper
1327 try:
1339 try:
1328 parm_1_lower = float(self.cleaned_data['parm_1_lower'])
1340 parm_1_lower = float(self.cleaned_data['parm_1_lower'])
1329 parm_1_upper = float(self.cleaned_data['parm_1_upper'])
1341 parm_1_upper = float(self.cleaned_data['parm_1_upper'])
1330 except:
1342 except:
1331 parm_1_lower = 0.0
1343 parm_1_lower = 0.0
1332 parm_1_upper = 1.0
1344 parm_1_upper = 1.0
1333 if parm_1_lower > parm_1_upper:
1345 if parm_1_lower > parm_1_upper:
1334 raise django.forms.ValidationError('Error - parm 1 lower limit greater than upper limit.')
1346 raise django.forms.ValidationError('Error - parm 1 lower limit greater than upper limit.')
1335
1347
1336 # rule 9 - parm_2_lower <= parm_2_upper
1348 # rule 9 - parm_2_lower <= parm_2_upper
1337 try:
1349 try:
1338 parm_2_lower = float(self.cleaned_data['parm_2_lower'])
1350 parm_2_lower = float(self.cleaned_data['parm_2_lower'])
1339 parm_2_upper = float(self.cleaned_data['parm_2_upper'])
1351 parm_2_upper = float(self.cleaned_data['parm_2_upper'])
1340 except:
1352 except:
1341 parm_2_lower = 0.0
1353 parm_2_lower = 0.0
1342 parm_2_upper = 1.0
1354 parm_2_upper = 1.0
1343 if parm_2_lower > parm_2_upper:
1355 if parm_2_lower > parm_2_upper:
1344 raise django.forms.ValidationError('Error - parm 2 lower limit greater than upper limit.')
1356 raise django.forms.ValidationError('Error - parm 2 lower limit greater than upper limit.')
1345
1357
1346 # rule 10 - parm_3_lower <= parm_3_upper
1358 # rule 10 - parm_3_lower <= parm_3_upper
1347 try:
1359 try:
1348 parm_3_lower = float(self.cleaned_data['parm_3_lower'])
1360 parm_3_lower = float(self.cleaned_data['parm_3_lower'])
1349 parm_3_upper = float(self.cleaned_data['parm_3_upper'])
1361 parm_3_upper = float(self.cleaned_data['parm_3_upper'])
1350 except:
1362 except:
1351 parm_3_lower = 0.0
1363 parm_3_lower = 0.0
1352 parm_3_upper = 1.0
1364 parm_3_upper = 1.0
1353 if parm_3_lower > parm_3_upper:
1365 if parm_3_lower > parm_3_upper:
1354 raise django.forms.ValidationError('Error - parm 3 lower limit greater than upper limit.')
1366 raise django.forms.ValidationError('Error - parm 3 lower limit greater than upper limit.')
1355
1367
1356
1368
1357 class ListExpForm(django.forms.Form):
1369 class ListExpForm(django.forms.Form):
1358 """ListExpForm is a Form class for the default fields in the List Experiment interface
1370 """ListExpForm is a Form class for the default fields in the List Experiment interface
1359 """
1371 """
1360 def __init__(self, *args, **kwargs):
1372 def __init__(self, *args, **kwargs):
1361 super(ListExpForm, self).__init__(*args, **kwargs)
1373 super(ListExpForm, self).__init__(*args, **kwargs)
1362 madDB = madrigal.metadata.MadrigalDB()
1374 madDB = madrigal.metadata.MadrigalDB()
1363 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
1375 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
1364 isGlobal = True # default load
1376 isGlobal = True # default load
1365 now = datetime.datetime.now()
1377 now = datetime.datetime.now()
1366 endDateTime = datetime.datetime(now.year, 12, 31, 23, 59, 59)
1378 endDateTime = datetime.datetime(now.year, 12, 31, 23, 59, 59)
1367 self.fields['isGlobal'] = django.forms.BooleanField(widget = django.forms.CheckboxInput(attrs={"onChange":'changeGlobal(this.form)'}),
1379 self.fields['isGlobal'] = django.forms.BooleanField(widget = django.forms.CheckboxInput(attrs={"onChange":'changeGlobal(this.form)'}),
1368 required=False, label='Use all Madrigal sites: ',
1380 required=False, label='Use all Madrigal sites: ',
1369 initial=isGlobal)
1381 initial=isGlobal)
1370
1382
1371
1383
1372 categoriesSelection = '0'
1384 categoriesSelection = '0'
1373 self.fields['categories'] = django.forms.MultipleChoiceField(widget=django.forms.SelectMultiple(attrs={"onChange":"updateInstruments(this.form)"}),
1385 self.fields['categories'] = django.forms.MultipleChoiceField(widget=django.forms.SelectMultiple(attrs={"onChange":"updateInstruments(this.form)"}),
1374 choices=getCategoryList(args, kwargs, madInstData, True),
1386 choices=getCategoryList(args, kwargs, madInstData, True),
1375 initial='0',
1387 initial='0',
1376 label='Choose instrument category(s):')
1388 label='Choose instrument category(s):')
1377
1389
1378 self.fields['instruments'] = django.forms.MultipleChoiceField(widget = django.forms.SelectMultiple(),
1390 self.fields['instruments'] = django.forms.MultipleChoiceField(widget = django.forms.SelectMultiple(),
1379 choices=getInstrumentList(args, kwargs, madInstData, 'All instruments', local=False, includeYears=True),
1391 choices=getInstrumentList(args, kwargs, madInstData, 'All instruments', local=False, includeYears=True),
1380 initial='0', label='Choose instrument(s)')
1392 initial='0', label='Choose instrument(s)')
1381
1393
1382 self.fields['showDefault'] = django.forms.BooleanField(widget = django.forms.CheckboxInput(),
1394 self.fields['showDefault'] = django.forms.BooleanField(widget = django.forms.CheckboxInput(),
1383 label='Show only default files: ',
1395 label='Show only default files: ',
1384 initial=True)
1396 initial=True)
1385
1397
1386 # time selection
1398 # time selection
1387 self.fields['start_date'] = django.forms.SplitDateTimeField(input_date_formats=['%Y-%m-%d'], input_time_formats=['%H:%M:%S'],
1399 self.fields['start_date'] = django.forms.SplitDateTimeField(input_date_formats=['%Y-%m-%d'], input_time_formats=['%H:%M:%S'],
1388 label='Start date',
1400 label='Start date',
1389 help_text='Modify this field to select experiments after this start time.',
1401 help_text='Modify this field to select experiments after this start time.',
1390 initial=datetime.datetime(1950,1,1))
1402 initial=datetime.datetime(1950,1,1))
1391
1403
1392 self.fields['end_date'] = django.forms.SplitDateTimeField(input_date_formats=['%Y-%m-%d'], input_time_formats=['%H:%M:%S'],
1404 self.fields['end_date'] = django.forms.SplitDateTimeField(input_date_formats=['%Y-%m-%d'], input_time_formats=['%H:%M:%S'],
1393 label='End date',
1405 label='End date',
1394 help_text='Modify this field to select experiments before this end time.',
1406 help_text='Modify this field to select experiments before this end time.',
1395 initial=endDateTime)
1407 initial=endDateTime)
1396
1408
1397
1409
1398
1410
1399 # attributes to support javascript
1411 # attributes to support javascript
1400 local_categories = madInstData.getCategories(True)
1412 local_categories = madInstData.getCategories(True)
1401 global_categories = madInstData.getCategories(False)
1413 global_categories = madInstData.getCategories(False)
1402 local_category_ids = [cat[0] for cat in local_categories]
1414 local_category_ids = [cat[0] for cat in local_categories]
1403 self.categories = [] # each item a tuple of (category description, category id, global only js bool)
1415 self.categories = [] # each item a tuple of (category description, category id, global only js bool)
1404 self.instruments = [] # each item a tiple of (instrument desc, category id, kinst, local start year, local end year, global sy, global ey)
1416 self.instruments = [] # each item a tiple of (instrument desc, category id, kinst, local start year, local end year, global sy, global ey)
1405 for id, desc in global_categories:
1417 for id, desc in global_categories:
1406 if id in local_category_ids:
1418 if id in local_category_ids:
1407 localBool = 'false'
1419 localBool = 'false'
1408 else:
1420 else:
1409 localBool = 'true'
1421 localBool = 'true'
1410 self.categories.append((desc, id, localBool))
1422 self.categories.append((desc, id, localBool))
1411 for kinst, instDesc, siteId in madInstData.getInstruments(id):
1423 for kinst, instDesc, siteId in madInstData.getInstruments(id):
1412 if siteId == madDB.getSiteID():
1424 if siteId == madDB.getSiteID():
1413 localInst = True
1425 localInst = True
1414 else:
1426 else:
1415 localInst = False
1427 localInst = False
1416 yearList = madInstData.getInstrumentYears(kinst)
1428 yearList = madInstData.getInstrumentYears(kinst)
1417 if localInst:
1429 if localInst:
1418 self.instruments.append((instDesc, id, kinst, yearList[0], yearList[-1], yearList[0], yearList[-1]))
1430 self.instruments.append((instDesc, id, kinst, yearList[0], yearList[-1], yearList[0], yearList[-1]))
1419 else:
1431 else:
1420 self.instruments.append((instDesc, id, kinst, 0, 0, yearList[0], yearList[-1]))
1432 self.instruments.append((instDesc, id, kinst, 0, 0, yearList[0], yearList[-1]))
1421
1433
1422
1434
1423 def clean(self):
1435 def clean(self):
1424 """clean in the Django method to validate things in a form that require looking at multiple fields
1436 """clean in the Django method to validate things in a form that require looking at multiple fields
1425 """
1437 """
1426 # rule 1 - start_date < end_date
1438 # rule 1 - start_date < end_date
1427 if self.cleaned_data['start_date'] > self.cleaned_data['end_date']:
1439 if self.cleaned_data['start_date'] > self.cleaned_data['end_date']:
1428 raise django.forms.ValidationError('Error - start datetime greater than end datetime.')
1440 raise django.forms.ValidationError('Error - start datetime greater than end datetime.')
1429
1441
1430
1442
1431 class DownloadAsIsScriptForm(django.forms.Form):
1443 class DownloadAsIsScriptForm(django.forms.Form):
1432 """DownloadAsIsScriptForm is a Form class for the default fields in the download files as is script generator interface
1444 """DownloadAsIsScriptForm is a Form class for the default fields in the download files as is script generator interface
1433 """
1445 """
1434 def __init__(self, *args, **kwargs):
1446 def __init__(self, *args, **kwargs):
1435 super(DownloadAsIsScriptForm, self).__init__(*args, **kwargs)
1447 super(DownloadAsIsScriptForm, self).__init__(*args, **kwargs)
1436 madDB = madrigal.metadata.MadrigalDB()
1448 madDB = madrigal.metadata.MadrigalDB()
1437 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
1449 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
1438 madKindatObj = madrigal.metadata.MadrigalKindat(madDB)
1450 madKindatObj = madrigal.metadata.MadrigalKindat(madDB)
1439 madInstKindatObj = madrigal.metadata.MadrigalInstrumentKindats(madDB)
1451 madInstKindatObj = madrigal.metadata.MadrigalInstrumentKindats(madDB)
1440 now = datetime.datetime.now()
1452 now = datetime.datetime.now()
1441 endDateTime = datetime.datetime(now.year, 12, 31, 23, 59, 59)
1453 endDateTime = datetime.datetime(now.year, 12, 31, 23, 59, 59)
1442 kwargs['isGlobal'] = '0'
1454 kwargs['isGlobal'] = '0'
1443 formatChoices = (('hdf5', 'Hdf5'), ('ascii', 'Space-delimited ascii'), ('netCDF4', 'netCDF4'))
1455 formatChoices = (('hdf5', 'Hdf5'), ('ascii', 'Space-delimited ascii'), ('netCDF4', 'netCDF4'))
1444 languageChoices = (('python', 'python'), ('Matlab', 'Matlab'), ('IDL', 'IDL'))
1456 languageChoices = (('python', 'python'), ('Matlab', 'Matlab'), ('IDL', 'IDL'))
1445
1457
1446 categoriesSelection = '0'
1458 categoriesSelection = '0'
1447 self.fields['categories'] = django.forms.ChoiceField(widget=django.forms.Select(attrs={"onChange":"updateInstruments(this.form)"}),
1459 self.fields['categories'] = django.forms.ChoiceField(widget=django.forms.Select(attrs={"onChange":"updateInstruments(this.form)"}),
1448 choices=getCategoryList(args, kwargs, madInstData),
1460 choices=getCategoryList(args, kwargs, madInstData),
1449 initial='0',
1461 initial='0',
1450 label='Choose an instrument category if desired:')
1462 label='Choose an instrument category if desired:')
1451
1463
1452 self.fields['instruments'] = django.forms.ChoiceField(widget=django.forms.Select(attrs={"onChange":"updateKindats(this.form)"}),
1464 self.fields['instruments'] = django.forms.ChoiceField(widget=django.forms.Select(attrs={"onChange":"updateKindats(this.form)"}),
1453 choices=getInstrumentList(args, kwargs, madInstData, local=True, includeYears=True),
1465 choices=getInstrumentList(args, kwargs, madInstData, local=True, includeYears=True),
1454 initial='0', label='Choose one instrument')
1466 initial='0', label='Choose one instrument')
1455
1467
1456 # time selection
1468 # time selection
1457 self.fields['start_date'] = django.forms.DateField(input_formats=['%Y-%m-%d'],
1469 self.fields['start_date'] = django.forms.DateField(input_formats=['%Y-%m-%d'],
1458 label='Start date',
1470 label='Start date',
1459 help_text='Modify this field to select experiments after this start time.',
1471 help_text='Modify this field to select experiments after this start time.',
1460 initial=datetime.datetime(1950,1,1))
1472 initial=datetime.datetime(1950,1,1))
1461
1473
1462
1474
1463 self.fields['end_date'] = django.forms.DateField(input_formats=['%Y-%m-%d'],
1475 self.fields['end_date'] = django.forms.DateField(input_formats=['%Y-%m-%d'],
1464 label='End date',
1476 label='End date',
1465 help_text='Modify this field to select experiments before this end time.',
1477 help_text='Modify this field to select experiments before this end time.',
1466 initial=endDateTime)
1478 initial=endDateTime)
1467
1479
1468 self.fields['format_select'] = django.forms.ChoiceField(widget = HorizontalRadioSelect(),
1480 self.fields['format_select'] = django.forms.ChoiceField(widget = HorizontalRadioSelect(),
1469 choices=formatChoices,
1481 choices=formatChoices,
1470 initial=formatChoices[0][0],
1482 initial=formatChoices[0][0],
1471 label='File format to download:')
1483 label='File format to download:')
1472
1484
1473 self.fields['language_select'] = django.forms.ChoiceField(widget = HorizontalRadioSelect(),
1485 self.fields['language_select'] = django.forms.ChoiceField(widget = HorizontalRadioSelect(),
1474 choices=languageChoices,
1486 choices=languageChoices,
1475 initial=languageChoices[0][0],
1487 initial=languageChoices[0][0],
1476 label='Choose scripting language:')
1488 label='Choose scripting language:')
1477
1489
1478 choices=(('0', 'Select an instrument first to see list'),)
1490 choices=(('0', 'Select an instrument first to see list'),)
1479 if len(args) > 0:
1491 if len(args) > 0:
1480 if 'kindat_select' in args[0]:
1492 if 'kindat_select' in args[0]:
1481 choices = [(kindat, kindat) for kindat in args[0].getlist('kindat_select')]
1493 choices = [(kindat, kindat) for kindat in args[0].getlist('kindat_select')]
1482 self.fields['kindat_select'] = django.forms.MultipleChoiceField(choices=choices,
1494 self.fields['kindat_select'] = django.forms.MultipleChoiceField(choices=choices,
1483 initial='0',
1495 initial='0',
1484 label='Choose one or more kinds of data:',
1496 label='Choose one or more kinds of data:',
1485 required=False)
1497 required=False)
1486 self.fields['kindat_select'].widget.attrs['style']="max-width:100%;"
1498 self.fields['kindat_select'].widget.attrs['style']="max-width:100%;"
1487
1499
1488 self.fields['expName'] = django.forms.CharField(max_length=256, required=False)
1500 self.fields['expName'] = django.forms.CharField(max_length=256, required=False)
1489
1501
1490 self.fields['fileDesc'] = django.forms.CharField(max_length=256, required=False)
1502 self.fields['fileDesc'] = django.forms.CharField(max_length=256, required=False)
1491
1503
1492
1504
1493
1505
1494 # attributes to support javascript
1506 # attributes to support javascript
1495 local_categories = madInstData.getCategories(True)
1507 local_categories = madInstData.getCategories(True)
1496 local_category_ids = [cat[0] for cat in local_categories]
1508 local_category_ids = [cat[0] for cat in local_categories]
1497 self.categories = [] # each item a tuple of (category description, category id, global only js bool)
1509 self.categories = [] # each item a tuple of (category description, category id, global only js bool)
1498 self.instruments = [] # each item a tiple of (instrument desc, category id, kinst, local start year, local end year)
1510 self.instruments = [] # each item a tiple of (instrument desc, category id, kinst, local start year, local end year)
1499 self.kindats = [] # each item is a tuple of (kindat, kindatDesc, kinst)
1511 self.kindats = [] # each item is a tuple of (kindat, kindatDesc, kinst)
1500 for id, desc in local_categories:
1512 for id, desc in local_categories:
1501 self.categories.append((desc, id))
1513 self.categories.append((desc, id))
1502 for kinst, instDesc, siteId in madInstData.getInstruments(id):
1514 for kinst, instDesc, siteId in madInstData.getInstruments(id):
1503 if siteId != madDB.getSiteID():
1515 if siteId != madDB.getSiteID():
1504 continue
1516 continue
1505 yearList = madInstData.getInstrumentYears(kinst)
1517 yearList = madInstData.getInstrumentYears(kinst)
1506 self.instruments.append((instDesc, id, kinst, yearList[0], yearList[-1]))
1518 self.instruments.append((instDesc, id, kinst, yearList[0], yearList[-1]))
1507 kindatList = madInstKindatObj.getKindatListForInstruments([kinst])
1519 kindatList = madInstKindatObj.getKindatListForInstruments([kinst])
1508 for kindat in kindatList:
1520 for kindat in kindatList:
1509 self.kindats.append((kindat, madKindatObj.getKindatDescription(kindat, kinst),
1521 self.kindats.append((kindat, madKindatObj.getKindatDescription(kindat, kinst),
1510 kinst))
1522 kinst))
1511
1523
1512
1524
1513 def clean(self):
1525 def clean(self):
1514 """clean is the Django method to validate things in a form that require looking at multiple fields
1526 """clean is the Django method to validate things in a form that require looking at multiple fields
1515 """
1527 """
1516 # rule 1 - start_date < end_date
1528 # rule 1 - start_date < end_date
1517 if self.cleaned_data['start_date'] > self.cleaned_data['end_date']:
1529 if self.cleaned_data['start_date'] > self.cleaned_data['end_date']:
1518 raise django.forms.ValidationError('Error - start datetime greater than end datetime.')
1530 raise django.forms.ValidationError('Error - start datetime greater than end datetime.')
1519
1531
1520
1532
1521 class DownloadAdvancedScriptForm(django.forms.Form):
1533 class DownloadAdvancedScriptForm(django.forms.Form):
1522 """DownloadAdvancedScriptForm is a Form class for the default fields in the download advanced script generator interface
1534 """DownloadAdvancedScriptForm is a Form class for the default fields in the download advanced script generator interface
1523 """
1535 """
1524 def __init__(self, *args, **kwargs):
1536 def __init__(self, *args, **kwargs):
1525 super(DownloadAdvancedScriptForm, self).__init__(*args, **kwargs)
1537 super(DownloadAdvancedScriptForm, self).__init__(*args, **kwargs)
1526 madDB = madrigal.metadata.MadrigalDB()
1538 madDB = madrigal.metadata.MadrigalDB()
1527 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
1539 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
1528 madKindatObj = madrigal.metadata.MadrigalKindat(madDB)
1540 madKindatObj = madrigal.metadata.MadrigalKindat(madDB)
1529 madInstKindatObj = madrigal.metadata.MadrigalInstrumentKindats(madDB)
1541 madInstKindatObj = madrigal.metadata.MadrigalInstrumentKindats(madDB)
1530 now = datetime.datetime.now()
1542 now = datetime.datetime.now()
1531 endDateTime = datetime.datetime(now.year, 12, 31, 23, 59, 59)
1543 endDateTime = datetime.datetime(now.year, 12, 31, 23, 59, 59)
1532 kwargs['isGlobal'] = '0'
1544 kwargs['isGlobal'] = '0'
1533 formatChoices = (('hdf5', 'Hdf5'), ('ascii', 'Space-delimited ascii'), ('netCDF4', 'netCDF4'))
1545 formatChoices = (('hdf5', 'Hdf5'), ('ascii', 'Space-delimited ascii'), ('netCDF4', 'netCDF4'))
1534 directoryChoices = (('Directory', 'Directory'), ('File', 'File'))
1546 directoryChoices = (('Directory', 'Directory'), ('File', 'File'))
1535 languageChoices = (('python', 'python'), ('Matlab', 'Matlab'), ('IDL', 'IDL'))
1547 languageChoices = (('python', 'python'), ('Matlab', 'Matlab'), ('IDL', 'IDL'))
1536
1548
1537 categoriesSelection = '0'
1549 categoriesSelection = '0'
1538 self.fields['categories'] = django.forms.ChoiceField(widget=django.forms.Select(attrs={"onChange":"updateInstruments(this.form)"}),
1550 self.fields['categories'] = django.forms.ChoiceField(widget=django.forms.Select(attrs={"onChange":"updateInstruments(this.form)"}),
1539 choices=getCategoryList(args, kwargs, madInstData),
1551 choices=getCategoryList(args, kwargs, madInstData),
1540 initial='0',
1552 initial='0',
1541 label='Choose an instrument category if desired:')
1553 label='Choose an instrument category if desired:')
1542
1554
1543 self.fields['instruments'] = django.forms.ChoiceField(widget=django.forms.Select(attrs={"onChange":"updateParmsKindats(this.form)"}),
1555 self.fields['instruments'] = django.forms.ChoiceField(widget=django.forms.Select(attrs={"onChange":"updateParmsKindats(this.form)"}),
1544 choices=getInstrumentList(args, kwargs, madInstData, local=True, includeYears=True),
1556 choices=getInstrumentList(args, kwargs, madInstData, local=True, includeYears=True),
1545 initial='0', label='Choose one instrument')
1557 initial='0', label='Choose one instrument')
1546
1558
1547 # time selection
1559 # time selection
1548 self.fields['start_date'] = django.forms.DateField(input_formats=['%Y-%m-%d'],
1560 self.fields['start_date'] = django.forms.DateField(input_formats=['%Y-%m-%d'],
1549 label='Start date',
1561 label='Start date',
1550 help_text='Modify this field to select experiments after this start time.',
1562 help_text='Modify this field to select experiments after this start time.',
1551 initial=datetime.datetime(1950,1,1))
1563 initial=datetime.datetime(1950,1,1))
1552
1564
1553 self.fields['end_date'] = django.forms.DateField(input_formats=['%Y-%m-%d'],
1565 self.fields['end_date'] = django.forms.DateField(input_formats=['%Y-%m-%d'],
1554 label='End date',
1566 label='End date',
1555 help_text='Modify this field to select experiments before this end time.',
1567 help_text='Modify this field to select experiments before this end time.',
1556 initial=endDateTime)
1568 initial=endDateTime)
1557
1569
1558 self.fields['format_select'] = django.forms.ChoiceField(widget = HorizontalRadioSelect(attrs={"onChange":'changeFormat(this)'}),
1570 self.fields['format_select'] = django.forms.ChoiceField(widget = HorizontalRadioSelect(attrs={"onChange":'changeFormat(this)'}),
1559 choices=formatChoices,
1571 choices=formatChoices,
1560 initial=formatChoices[0][0],
1572 initial=formatChoices[0][0],
1561 label='File format to download:')
1573 label='File format to download:')
1562
1574
1563 self.fields['directory_select'] = django.forms.ChoiceField(widget = HorizontalRadioSelect(),
1575 self.fields['directory_select'] = django.forms.ChoiceField(widget = HorizontalRadioSelect(),
1564 choices=directoryChoices,
1576 choices=directoryChoices,
1565 initial=directoryChoices[0][0],
1577 initial=directoryChoices[0][0],
1566 label='If ascii, download result to:')
1578 label='If ascii, download result to:')
1567
1579
1568 self.fields['language_select'] = django.forms.ChoiceField(widget = HorizontalRadioSelect(),
1580 self.fields['language_select'] = django.forms.ChoiceField(widget = HorizontalRadioSelect(),
1569 choices=languageChoices,
1581 choices=languageChoices,
1570 initial=languageChoices[0][0],
1582 initial=languageChoices[0][0],
1571 label='Choose scripting language:')
1583 label='Choose scripting language:')
1572
1584
1573 choices=(('0', 'Select an instrument first to see list'),)
1585 choices=(('0', 'Select an instrument first to see list'),)
1574 if len(args) > 0:
1586 if len(args) > 0:
1575 if 'kindat_select' in args[0]:
1587 if 'kindat_select' in args[0]:
1576 choices = [(kindat, kindat) for kindat in args[0].getlist('kindat_select')]
1588 choices = [(kindat, kindat) for kindat in args[0].getlist('kindat_select')]
1577 self.fields['kindat_select'] = django.forms.MultipleChoiceField(choices=choices,
1589 self.fields['kindat_select'] = django.forms.MultipleChoiceField(choices=choices,
1578 initial='0',
1590 initial='0',
1579 label='Choose one or more kinds of data:',
1591 label='Choose one or more kinds of data:',
1580 required=False)
1592 required=False)
1581 self.fields['kindat_select'].widget.attrs['style']="max-width:100%;"
1593 self.fields['kindat_select'].widget.attrs['style']="max-width:100%;"
1582
1594
1583 self.fields['expName'] = django.forms.CharField(max_length=256, required=False)
1595 self.fields['expName'] = django.forms.CharField(max_length=256, required=False)
1584
1596
1585 self.fields['fileDesc'] = django.forms.CharField(max_length=256, required=False)
1597 self.fields['fileDesc'] = django.forms.CharField(max_length=256, required=False)
1586
1598
1587 self.fields['seasonalStartDay'] = django.forms.IntegerField(min_value=1, max_value=31, initial=1)
1599 self.fields['seasonalStartDay'] = django.forms.IntegerField(min_value=1, max_value=31, initial=1)
1588 self.fields['seasonalStartMonth'] = django.forms.IntegerField(min_value=1, max_value=12, initial=1)
1600 self.fields['seasonalStartMonth'] = django.forms.IntegerField(min_value=1, max_value=12, initial=1)
1589 self.fields['seasonalEndDay'] = django.forms.IntegerField(min_value=1, max_value=31, initial=31)
1601 self.fields['seasonalEndDay'] = django.forms.IntegerField(min_value=1, max_value=31, initial=31)
1590 self.fields['seasonalEndMonth'] = django.forms.IntegerField(min_value=1, max_value=12, initial=12)
1602 self.fields['seasonalEndMonth'] = django.forms.IntegerField(min_value=1, max_value=12, initial=12)
1591
1603
1592
1604
1593 # attributes to support javascript
1605 # attributes to support javascript
1594 local_categories = madInstData.getCategories(True)
1606 local_categories = madInstData.getCategories(True)
1595 local_category_ids = [cat[0] for cat in local_categories]
1607 local_category_ids = [cat[0] for cat in local_categories]
1596 self.categories = [] # each item a tuple of (category description, category id, global only js bool)
1608 self.categories = [] # each item a tuple of (category description, category id, global only js bool)
1597 self.instruments = [] # each item a tiple of (instrument desc, category id, kinst, local start year, local end year)
1609 self.instruments = [] # each item a tiple of (instrument desc, category id, kinst, local start year, local end year)
1598 self.kindats = [] # each item is a tuple of (kindat, kindatDesc, kinst)
1610 self.kindats = [] # each item is a tuple of (kindat, kindatDesc, kinst)
1599 for id, desc in local_categories:
1611 for id, desc in local_categories:
1600 self.categories.append((desc, id))
1612 self.categories.append((desc, id))
1601 for kinst, instDesc, siteId in madInstData.getInstruments(id):
1613 for kinst, instDesc, siteId in madInstData.getInstruments(id):
1602 if siteId != madDB.getSiteID():
1614 if siteId != madDB.getSiteID():
1603 continue
1615 continue
1604 yearList = madInstData.getInstrumentYears(kinst)
1616 yearList = madInstData.getInstrumentYears(kinst)
1605 self.instruments.append((instDesc, id, kinst, yearList[0], yearList[-1]))
1617 self.instruments.append((instDesc, id, kinst, yearList[0], yearList[-1]))
1606 kindatList = madInstKindatObj.getKindatListForInstruments([kinst])
1618 kindatList = madInstKindatObj.getKindatListForInstruments([kinst])
1607 for kindat in kindatList:
1619 for kindat in kindatList:
1608 self.kindats.append((kindat, madKindatObj.getKindatDescription(kindat, kinst),
1620 self.kindats.append((kindat, madKindatObj.getKindatDescription(kindat, kinst),
1609 kinst))
1621 kinst))
1610
1622
1611
1623
1612 def clean(self):
1624 def clean(self):
1613 """clean is the Django method to validate things in a form that require looking at multiple fields
1625 """clean is the Django method to validate things in a form that require looking at multiple fields
1614 """
1626 """
1615 # rule 1 - start_date < end_date
1627 # rule 1 - start_date < end_date
1616 if self.cleaned_data['start_date'] > self.cleaned_data['end_date']:
1628 if self.cleaned_data['start_date'] > self.cleaned_data['end_date']:
1617 raise django.forms.ValidationError('Error - start datetime greater than end datetime.')
1629 raise django.forms.ValidationError('Error - start datetime greater than end datetime.')
1618
1630
1619 # rule 2 - seasonal start must be before seasonal end
1631 # rule 2 - seasonal start must be before seasonal end
1620 if ((self.cleaned_data['seasonalStartDay'] + 31*self.cleaned_data['seasonalStartMonth']) > \
1632 if ((self.cleaned_data['seasonalStartDay'] + 31*self.cleaned_data['seasonalStartMonth']) > \
1621 (self.cleaned_data['seasonalEndDay'] + 31*self.cleaned_data['seasonalEndMonth'])):
1633 (self.cleaned_data['seasonalEndDay'] + 31*self.cleaned_data['seasonalEndMonth'])):
1622 raise django.forms.ValidationError('Error - seasonal start after seasonal end.')
1634 raise django.forms.ValidationError('Error - seasonal start after seasonal end.')
1623
1635
1624
1636
1625
1637
1626 class AdvScriptParmsForm(django.forms.Form):
1638 class AdvScriptParmsForm(django.forms.Form):
1627 """AdvScriptParmsForm is the form for the parameters
1639 """AdvScriptParmsForm is the form for the parameters
1628 """
1640 """
1629 def __init__(self, *args, **kwargs):
1641 def __init__(self, *args, **kwargs):
1630
1642
1631 kinst = int(getSelection('instruments', args, kwargs))
1643 kinst = int(getSelection('instruments', args, kwargs))
1632 if kinst == 0:
1644 if kinst == 0:
1633 raise ValueError('kinst should never be zero')
1645 raise ValueError('kinst should never be zero')
1634 madDB = madrigal.metadata.MadrigalDB()
1646 madDB = madrigal.metadata.MadrigalDB()
1635 madParmObj = madrigal.data.MadrigalParameters(madDB)
1647 madParmObj = madrigal.data.MadrigalParameters(madDB)
1636 parmList = madParmObj.getParametersForInstruments([kinst])
1648 parmList = madParmObj.getParametersForInstruments([kinst])
1637 self.parmList = []
1649 self.parmList = []
1638 for parm in parmList:
1650 for parm in parmList:
1639 self.parmList.append((parm, madParmObj.getSimpleParmDescription(parm)))
1651 self.parmList.append((parm, madParmObj.getSimpleParmDescription(parm)))
1640
1652
1641 madCatObj = madrigal.metadata.MadrigalParmCategory(madDB)
1653 madCatObj = madrigal.metadata.MadrigalParmCategory(madDB)
1642
1654
1643 catList = madCatObj.getCategoryList()
1655 catList = madCatObj.getCategoryList()
1644 catDict = madParmObj.getCategoryDict(parmList)
1656 catDict = madParmObj.getCategoryDict(parmList)
1645
1657
1646 choices = []
1658 choices = []
1647 isDerivedDict = {}
1659 isDerivedDict = {}
1648 parmDescDict = {}
1660 parmDescDict = {}
1649 for catDesc, catID in catList:
1661 for catDesc, catID in catList:
1650 if catID not in list(catDict.keys()):
1662 if catID not in list(catDict.keys()):
1651 continue
1663 continue
1652 theseParms = []
1664 theseParms = []
1653 for parm in catDict[catID][1]:
1665 for parm in catDict[catID][1]:
1654 theseParms.append((parm, parm))
1666 theseParms.append((parm, parm))
1655 isDerivedDict[parm] = False
1667 isDerivedDict[parm] = False
1656 parmDescDict[parm] = madParmObj.getParmDescription(parm)
1668 parmDescDict[parm] = madParmObj.getParmDescription(parm)
1657 choices.append((catDesc, theseParms))
1669 choices.append((catDesc, theseParms))
1658
1670
1659 super(AdvScriptParmsForm, self).__init__(*args, **kwargs)
1671 super(AdvScriptParmsForm, self).__init__(*args, **kwargs)
1660
1672
1661 self.fields['parameters'] = IsprintChoiceField(choices=choices,
1673 self.fields['parameters'] = IsprintChoiceField(choices=choices,
1662 initial=['YEAR', 'MIN'],
1674 initial=['YEAR', 'MIN'],
1663 required=False,
1675 required=False,
1664 isDerivedDict=isDerivedDict,
1676 isDerivedDict=isDerivedDict,
1665 parmDescDict=parmDescDict,
1677 parmDescDict=parmDescDict,
1666 separateProlog=False,
1678 separateProlog=False,
1667 label = "")
1679 label = "")
1668
1680
1669
1681
1670 class AdvScriptParmsFiltersForm(django.forms.Form):
1682 class AdvScriptParmsFiltersForm(django.forms.Form):
1671 """AdvScriptParmsFiltersForm is the form for the parameter filters in the scrip generator
1683 """AdvScriptParmsFiltersForm is the form for the parameter filters in the scrip generator
1672 """
1684 """
1673 def __init__(self, *args, **kwargs):
1685 def __init__(self, *args, **kwargs):
1674
1686
1675 kinst = int(getSelection('instruments', args, kwargs))
1687 kinst = int(getSelection('instruments', args, kwargs))
1676 if kinst == 0:
1688 if kinst == 0:
1677 raise ValueError('kinst should never be zero')
1689 raise ValueError('kinst should never be zero')
1678 madDB = madrigal.metadata.MadrigalDB()
1690 madDB = madrigal.metadata.MadrigalDB()
1679 madParmObj = madrigal.data.MadrigalParameters(madDB)
1691 madParmObj = madrigal.data.MadrigalParameters(madDB)
1680 parmList = madParmObj.getParametersForInstruments([kinst])
1692 parmList = madParmObj.getParametersForInstruments([kinst])
1681 self.parmList = []
1693 self.parmList = []
1682 for parm in parmList:
1694 for parm in parmList:
1683 self.parmList.append((parm, madParmObj.getSimpleParmDescription(parm)))
1695 self.parmList.append((parm, madParmObj.getSimpleParmDescription(parm)))
1684
1696
1685 super(AdvScriptParmsFiltersForm, self).__init__(*args, **kwargs)
1697 super(AdvScriptParmsFiltersForm, self).__init__(*args, **kwargs)
1686
1698
1687 choices = [(parm, parm) for parm in parmList]
1699 choices = [(parm, parm) for parm in parmList]
1688 choices_with_null = [('None', 'None')] + choices
1700 choices_with_null = [('None', 'None')] + choices
1689
1701
1690 self.fields['parm_1'] = django.forms.ChoiceField(required=False,
1702 self.fields['parm_1'] = django.forms.ChoiceField(required=False,
1691 choices=choices_with_null)
1703 choices=choices_with_null)
1692 self.fields['parm_1_lower'] = django.forms.CharField(required=False, initial='')
1704 self.fields['parm_1_lower'] = django.forms.CharField(required=False, initial='')
1693 self.fields['parm_1_upper'] = django.forms.CharField(required=False, initial='')
1705 self.fields['parm_1_upper'] = django.forms.CharField(required=False, initial='')
1694
1706
1695 self.fields['parm_2'] = django.forms.ChoiceField(required=False,
1707 self.fields['parm_2'] = django.forms.ChoiceField(required=False,
1696 choices=choices_with_null)
1708 choices=choices_with_null)
1697 self.fields['parm_2_lower'] = django.forms.CharField(required=False, initial='')
1709 self.fields['parm_2_lower'] = django.forms.CharField(required=False, initial='')
1698 self.fields['parm_2_upper'] = django.forms.CharField(required=False, initial='')
1710 self.fields['parm_2_upper'] = django.forms.CharField(required=False, initial='')
1699
1711
1700 self.fields['parm_3'] = django.forms.ChoiceField(required=False,
1712 self.fields['parm_3'] = django.forms.ChoiceField(required=False,
1701 choices=choices_with_null)
1713 choices=choices_with_null)
1702 self.fields['parm_3_lower'] = django.forms.CharField(required=False, initial='')
1714 self.fields['parm_3_lower'] = django.forms.CharField(required=False, initial='')
1703 self.fields['parm_3_upper'] = django.forms.CharField(required=False, initial='')
1715 self.fields['parm_3_upper'] = django.forms.CharField(required=False, initial='')
1704
1716
1705
1717
1706
1718
1707 class MadCalculatorForm(django.forms.Form):
1719 class MadCalculatorForm(django.forms.Form):
1708 """MadCalculatorForm is the form for the madCalculator page
1720 """MadCalculatorForm is the form for the madCalculator page
1709 """
1721 """
1710 def __init__(self, *args, **kwargs):
1722 def __init__(self, *args, **kwargs):
1711 """
1723 """
1712 """
1724 """
1713 madDB = madrigal.metadata.MadrigalDB()
1725 madDB = madrigal.metadata.MadrigalDB()
1714 madParmObj = madrigal.data.MadrigalParameters(madDB)
1726 madParmObj = madrigal.data.MadrigalParameters(madDB)
1715 super(MadCalculatorForm, self).__init__(*args, **kwargs)
1727 super(MadCalculatorForm, self).__init__(*args, **kwargs)
1716 fullDerivedParmList = madrigal.derivation.getDerivableParms(['gdalt', 'gdlat', 'glon'])
1728 fullDerivedParmList = madrigal.derivation.getDerivableParms(['gdalt', 'gdlat', 'glon'])
1717
1729
1718 # removed unwanted time and prolog parameters
1730 # removed unwanted time and prolog parameters
1719 rejectedCats = ('Time Related Parameter', 'Prolog Parameters', 'Radar Instrument Operation Parameter',
1731 rejectedCats = ('Time Related Parameter', 'Prolog Parameters', 'Radar Instrument Operation Parameter',
1720 'Madrigal Hdf5 Prolog Parameters')
1732 'Madrigal Hdf5 Prolog Parameters')
1721 # define time parameters that do make sense to calculate
1733 # define time parameters that do make sense to calculate
1722 neededTimeParms = ('APLT', 'CONJ_SUNRISE_H', 'CONJ_SUNSET_H',
1734 neededTimeParms = ('APLT', 'CONJ_SUNRISE_H', 'CONJ_SUNSET_H',
1723 'SUNRISE_H', 'SUNSET_H', 'MLT')
1735 'SUNRISE_H', 'SUNSET_H', 'MLT')
1724
1736
1725 # skip parms related to inst location
1737 # skip parms related to inst location
1726 instLocationParms = ('AZM','ELM','GALTR','GDLONR','GDLATR','RANGE', 'ASPECT',
1738 instLocationParms = ('AZM','ELM','GALTR','GDLONR','GDLATR','RANGE', 'ASPECT',
1727 'GDALT', 'GDLAT', 'GLON', 'CXR', 'CYR', 'CZR')
1739 'GDALT', 'GDLAT', 'GLON', 'CXR', 'CYR', 'CZR')
1728
1740
1729 madCatObj = madrigal.metadata.MadrigalParmCategory(madDB)
1741 madCatObj = madrigal.metadata.MadrigalParmCategory(madDB)
1730
1742
1731 catList = madCatObj.getCategoryList()
1743 catList = madCatObj.getCategoryList()
1732 catDict = madParmObj.getCategoryDict(fullDerivedParmList)
1744 catDict = madParmObj.getCategoryDict(fullDerivedParmList)
1733 choices = []
1745 choices = []
1734 isDerivedDict = {}
1746 isDerivedDict = {}
1735 self.parmDescDict = {}
1747 self.parmDescDict = {}
1736 for catDesc, catID in catList:
1748 for catDesc, catID in catList:
1737 if catDesc in rejectedCats[1:]:
1749 if catDesc in rejectedCats[1:]:
1738 continue
1750 continue
1739 if catID not in list(catDict.keys()):
1751 if catID not in list(catDict.keys()):
1740 continue
1752 continue
1741 theseParms = []
1753 theseParms = []
1742 for parm in catDict[catID][1]:
1754 for parm in catDict[catID][1]:
1743 if parm in instLocationParms:
1755 if parm in instLocationParms:
1744 continue
1756 continue
1745 if catDesc in rejectedCats and parm not in neededTimeParms:
1757 if catDesc in rejectedCats and parm not in neededTimeParms:
1746 continue
1758 continue
1747 if not parm in fullDerivedParmList:
1759 if not parm in fullDerivedParmList:
1748 continue
1760 continue
1749 theseParms.append((parm, parm))
1761 theseParms.append((parm, parm))
1750 isDerivedDict[parm] = True
1762 isDerivedDict[parm] = True
1751 self.parmDescDict[parm] = madParmObj.getParmDescription(parm)
1763 self.parmDescDict[parm] = madParmObj.getParmDescription(parm)
1752 choices.append((catDesc, theseParms))
1764 choices.append((catDesc, theseParms))
1753
1765
1754
1766
1755
1767
1756 # form fields
1768 # form fields
1757 self.fields['min_latitude'] = django.forms.FloatField(initial=-90.0, min_value=-90.0,
1769 self.fields['min_latitude'] = django.forms.FloatField(initial=-90.0, min_value=-90.0,
1758 max_value=90.0)
1770 max_value=90.0)
1759 self.fields['max_latitude'] = django.forms.FloatField(initial=90.0, min_value=-90.0,
1771 self.fields['max_latitude'] = django.forms.FloatField(initial=90.0, min_value=-90.0,
1760 max_value=90.0)
1772 max_value=90.0)
1761 self.fields['delta_latitude'] = django.forms.FloatField(initial=45, min_value=1.0E-6)
1773 self.fields['delta_latitude'] = django.forms.FloatField(initial=45, min_value=1.0E-6)
1762
1774
1763 self.fields['min_longitude'] = django.forms.FloatField(initial=-180.0, min_value=-180.0,
1775 self.fields['min_longitude'] = django.forms.FloatField(initial=-180.0, min_value=-180.0,
1764 max_value=180.0)
1776 max_value=180.0)
1765 self.fields['max_longitude'] = django.forms.FloatField(initial=180.0, min_value=-180.0,
1777 self.fields['max_longitude'] = django.forms.FloatField(initial=180.0, min_value=-180.0,
1766 max_value=180.0)
1778 max_value=180.0)
1767 self.fields['delta_longitude'] = django.forms.FloatField(initial=90, min_value=1.0E-6)
1779 self.fields['delta_longitude'] = django.forms.FloatField(initial=90, min_value=1.0E-6)
1768
1780
1769 self.fields['min_altitude'] = django.forms.FloatField(initial=0.0, min_value=0.0)
1781 self.fields['min_altitude'] = django.forms.FloatField(initial=0.0, min_value=0.0)
1770 self.fields['max_altitude'] = django.forms.FloatField(initial=600.0, min_value=0.0)
1782 self.fields['max_altitude'] = django.forms.FloatField(initial=600.0, min_value=0.0)
1771 self.fields['delta_altitude'] = django.forms.FloatField(initial=200, min_value=1.0E-6)
1783 self.fields['delta_altitude'] = django.forms.FloatField(initial=200, min_value=1.0E-6)
1772
1784
1773 # time selection
1785 # time selection
1774 now = datetime.datetime.utcnow()
1786 now = datetime.datetime.utcnow()
1775 self.fields['datetime'] = django.forms.SplitDateTimeField(input_date_formats=['%Y-%m-%d'], input_time_formats=['%H:%M:%S'],
1787 self.fields['datetime'] = django.forms.SplitDateTimeField(input_date_formats=['%Y-%m-%d'], input_time_formats=['%H:%M:%S'],
1776 label='Select UT datetime',
1788 label='Select UT datetime',
1777 help_text='Select the UT time at which to run this calcuation',
1789 help_text='Select the UT time at which to run this calcuation',
1778 initial=datetime.datetime(now.year,1,1))
1790 initial=datetime.datetime(now.year,1,1))
1779
1791
1780 self.fields['parameters'] = IsprintChoiceField(choices=choices,
1792 self.fields['parameters'] = IsprintChoiceField(choices=choices,
1781 required=False,
1793 required=False,
1782 isDerivedDict=isDerivedDict,
1794 isDerivedDict=isDerivedDict,
1783 parmDescDict=self.parmDescDict,
1795 parmDescDict=self.parmDescDict,
1784 separateProlog=False,
1796 separateProlog=False,
1785 label = "")
1797 label = "")
1786
1798
1787
1799
1788 def clean(self):
1800 def clean(self):
1789 """clean is the Django method to validate things in a form that require looking at multiple fields
1801 """clean is the Django method to validate things in a form that require looking at multiple fields
1790 """
1802 """
1791 max_len = 1.0E5
1803 max_len = 1.0E5
1792 try:
1804 try:
1793 a1 = numpy.arange(self.cleaned_data['min_latitude'], self.cleaned_data['max_latitude'], self.cleaned_data['delta_latitude'])
1805 a1 = numpy.arange(self.cleaned_data['min_latitude'], self.cleaned_data['max_latitude'], self.cleaned_data['delta_latitude'])
1794 if len(a1) > max_len:
1806 if len(a1) > max_len:
1795 raise django.forms.ValidationError('Too many latitudes: %i.' % (len(a1)))
1807 raise django.forms.ValidationError('Too many latitudes: %i.' % (len(a1)))
1796 except ZeroDivisionError:
1808 except ZeroDivisionError:
1797 raise django.forms.ValidationError('Infinite latitudes')
1809 raise django.forms.ValidationError('Infinite latitudes')
1798
1810
1799 try:
1811 try:
1800 a2 = numpy.arange(self.cleaned_data['min_longitude'], self.cleaned_data['max_longitude'], self.cleaned_data['delta_longitude'])
1812 a2 = numpy.arange(self.cleaned_data['min_longitude'], self.cleaned_data['max_longitude'], self.cleaned_data['delta_longitude'])
1801 if len(a1) > max_len:
1813 if len(a1) > max_len:
1802 raise django.forms.ValidationError('Too many longitudes: %i.' % (len(a1)))
1814 raise django.forms.ValidationError('Too many longitudes: %i.' % (len(a1)))
1803 except ZeroDivisionError:
1815 except ZeroDivisionError:
1804 raise django.forms.ValidationError('Infinite longitudes')
1816 raise django.forms.ValidationError('Infinite longitudes')
1805
1817
1806 try:
1818 try:
1807 a3 = numpy.arange(self.cleaned_data['min_altitude'], self.cleaned_data['max_altitude'], self.cleaned_data['delta_altitude'])
1819 a3 = numpy.arange(self.cleaned_data['min_altitude'], self.cleaned_data['max_altitude'], self.cleaned_data['delta_altitude'])
1808 if len(a1) > max_len:
1820 if len(a1) > max_len:
1809 raise django.forms.ValidationError('Too many altitudes: %i.' % (len(a1)))
1821 raise django.forms.ValidationError('Too many altitudes: %i.' % (len(a1)))
1810 except ZeroDivisionError:
1822 except ZeroDivisionError:
1811 raise django.forms.ValidationError('Infinite altitudes')
1823 raise django.forms.ValidationError('Infinite altitudes')
1812
1824
1813 total = len(a1) * len(a2) * len(a3)
1825 total = len(a1) * len(a2) * len(a3)
1814 if total > max_len:
1826 if total > max_len:
1815 raise django.forms.ValidationError('Too many calculations: %i' % (total))
1827 raise django.forms.ValidationError('Too many calculations: %i' % (total))
1816
1828
1817
1829
1818
1830
1819 class GetMetadataForm(django.forms.Form):
1831 class GetMetadataForm(django.forms.Form):
1820 """GetMetadataForm is the form for the getMetadata page
1832 """GetMetadataForm is the form for the getMetadata page
1821 """
1833 """
1822 def __init__(self, *args, **kwargs):
1834 def __init__(self, *args, **kwargs):
1823 """
1835 """
1824 """
1836 """
1825 super(GetMetadataForm, self).__init__(*args, **kwargs)
1837 super(GetMetadataForm, self).__init__(*args, **kwargs)
1826
1838
1827 fileTypeChoices = (("0", "Experiment Table"),
1839 fileTypeChoices = (("0", "Experiment Table"),
1828 ("1", "File Table"),
1840 ("1", "File Table"),
1829 ("3", "Instrument Table"),
1841 ("3", "Instrument Table"),
1830 ("4", "Parameter Table"),
1842 ("4", "Parameter Table"),
1831 ("5", "Site Table"),
1843 ("5", "Site Table"),
1832 ("6", "Type Table"),
1844 ("6", "Type Table"),
1833 ("7", "Instrument Kindat Table"),
1845 ("7", "Instrument Kindat Table"),
1834 ("8", "Instrument Parameter Table"),
1846 ("8", "Instrument Parameter Table"),
1835 ("9", "Madrigal categories table"),
1847 ("9", "Madrigal categories table"),
1836 ("10", "Instrument categories table"),)
1848 ("10", "Instrument categories table"),)
1837
1849
1838 self.fields['fileType'] = django.forms.ChoiceField(widget = django.forms.RadioSelect,
1850 self.fields['fileType'] = django.forms.ChoiceField(widget = django.forms.RadioSelect,
1839 choices=fileTypeChoices,
1851 choices=fileTypeChoices,
1840 initial="0",
1852 initial="0",
1841 label="Choose the metadata file type to download")
1853 label="Choose the metadata file type to download")
1842
1854
1843
1855
1844 class LookerSelectForm(django.forms.Form):
1856 class LookerSelectForm(django.forms.Form):
1845 """LookerSelectForm is the form for the looker_form page
1857 """LookerSelectForm is the form for the looker_form page
1846 """
1858 """
1847 def __init__(self, *args, **kwargs):
1859 def __init__(self, *args, **kwargs):
1848 """
1860 """
1849 """
1861 """
1850 super(LookerSelectForm, self).__init__(*args, **kwargs)
1862 super(LookerSelectForm, self).__init__(*args, **kwargs)
1851
1863
1852 lookerOptionChoices = (("1", "Geodetic latitude, longitude and altitude of the points"),
1864 lookerOptionChoices = (("1", "Geodetic latitude, longitude and altitude of the points"),
1853 ("2", "Apex latitude, longitude and altitude of the points"),
1865 ("2", "Apex latitude, longitude and altitude of the points"),
1854 ("3", "Geodetic latitude, longitude and altitude of the points"),
1866 ("3", "Geodetic latitude, longitude and altitude of the points"),
1855 ("4", "Azimuth, elevation and range of the points from a specified instrument (output includes aspect angle)"),
1867 ("4", "Azimuth, elevation and range of the points from a specified instrument (output includes aspect angle)"),
1856 ("5", "Azimuth, elevation, range from specified instrument"),
1868 ("5", "Azimuth, elevation, range from specified instrument"),
1857 ("6", "Geodetic latitude, longitude, altitude of a point on the field line"),
1869 ("6", "Geodetic latitude, longitude, altitude of a point on the field line"),
1858 ("7", "Apex latitude, longitude of the field line"),
1870 ("7", "Apex latitude, longitude of the field line"),
1859 ("8", "Geodetic latitude, longitude and altitude of the points"))
1871 ("8", "Geodetic latitude, longitude and altitude of the points"))
1860
1872
1861 self.fields['looker_options'] = django.forms.ChoiceField(widget = django.forms.RadioSelect,
1873 self.fields['looker_options'] = django.forms.ChoiceField(widget = django.forms.RadioSelect,
1862 choices=lookerOptionChoices,
1874 choices=lookerOptionChoices,
1863 initial="1")
1875 initial="1")
1864
1876
1865
1877
1866 class LookerGeodeticRadar(django.forms.Form):
1878 class LookerGeodeticRadar(django.forms.Form):
1867 """LookerGeodeticRadar is the form for the geodetic to radar page
1879 """LookerGeodeticRadar is the form for the geodetic to radar page
1868 """
1880 """
1869 def __init__(self, *args, **kwargs):
1881 def __init__(self, *args, **kwargs):
1870 """
1882 """
1871 """
1883 """
1872 super(LookerGeodeticRadar, self).__init__(*args, **kwargs)
1884 super(LookerGeodeticRadar, self).__init__(*args, **kwargs)
1873 madDB = madrigal.metadata.MadrigalDB()
1885 madDB = madrigal.metadata.MadrigalDB()
1874 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
1886 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
1875 dict1 = {'isGlobal': True, 'categories': "0"}
1887 dict1 = {'isGlobal': True, 'categories': "0"}
1876
1888
1877 self.fields['looker_options'] = django.forms.CharField(initial="1",
1889 self.fields['looker_options'] = django.forms.CharField(initial="1",
1878 widget=django.forms.HiddenInput(attrs={'value': "1"}))
1890 widget=django.forms.HiddenInput(attrs={'value': "1"}))
1879
1891
1880 self.fields['instruments'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={'size':'3'}),
1892 self.fields['instruments'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={'size':'3'}),
1881 choices=getInstrumentList([], dict1, madInstData, 'Set location manually', local=False),
1893 choices=getInstrumentList([], dict1, madInstData, 'Set location manually', local=False),
1882 required=False, label='Instrument: ')
1894 required=False, label='Instrument: ')
1883
1895
1884 self.fields['inst_lat'] = django.forms.FloatField(initial=0.0, min_value=-90.0, max_value=90.0,
1896 self.fields['inst_lat'] = django.forms.FloatField(initial=0.0, min_value=-90.0, max_value=90.0,
1885 widget=django.forms.TextInput(attrs={'size':5}))
1897 widget=django.forms.TextInput(attrs={'size':5}))
1886 self.fields['inst_lon'] = django.forms.FloatField(initial=0.0, min_value=-180.0, max_value=180.0,
1898 self.fields['inst_lon'] = django.forms.FloatField(initial=0.0, min_value=-180.0, max_value=180.0,
1887 widget=django.forms.TextInput(attrs={'size':5}))
1899 widget=django.forms.TextInput(attrs={'size':5}))
1888 self.fields['inst_alt'] = django.forms.FloatField(initial=0.0, min_value=0.0,
1900 self.fields['inst_alt'] = django.forms.FloatField(initial=0.0, min_value=0.0,
1889 widget=django.forms.TextInput(attrs={'size':5}))
1901 widget=django.forms.TextInput(attrs={'size':5}))
1890 self.fields['start_lat'] = django.forms.FloatField(initial=30.0, min_value=-90.0, max_value=90.0,
1902 self.fields['start_lat'] = django.forms.FloatField(initial=30.0, min_value=-90.0, max_value=90.0,
1891 widget=django.forms.TextInput(attrs={'size':5}))
1903 widget=django.forms.TextInput(attrs={'size':5}))
1892 self.fields['stop_lat'] = django.forms.FloatField(initial=50.0, min_value=-90.0, max_value=90.0,
1904 self.fields['stop_lat'] = django.forms.FloatField(initial=50.0, min_value=-90.0, max_value=90.0,
1893 widget=django.forms.TextInput(attrs={'size':5}))
1905 widget=django.forms.TextInput(attrs={'size':5}))
1894 self.fields['step_lat'] = django.forms.FloatField(initial=10.0, min_value=0.0,
1906 self.fields['step_lat'] = django.forms.FloatField(initial=10.0, min_value=0.0,
1895 widget=django.forms.TextInput(attrs={'size':5}))
1907 widget=django.forms.TextInput(attrs={'size':5}))
1896 self.fields['start_lon'] = django.forms.FloatField(initial=-100.0, min_value=-180.0, max_value=180.0,
1908 self.fields['start_lon'] = django.forms.FloatField(initial=-100.0, min_value=-180.0, max_value=180.0,
1897 widget=django.forms.TextInput(attrs={'size':5}))
1909 widget=django.forms.TextInput(attrs={'size':5}))
1898 self.fields['stop_lon'] = django.forms.FloatField(initial=-80.0, min_value=-180.0, max_value=180.0,
1910 self.fields['stop_lon'] = django.forms.FloatField(initial=-80.0, min_value=-180.0, max_value=180.0,
1899 widget=django.forms.TextInput(attrs={'size':5}))
1911 widget=django.forms.TextInput(attrs={'size':5}))
1900 self.fields['step_lon'] = django.forms.FloatField(initial=10.0, min_value=0.0,
1912 self.fields['step_lon'] = django.forms.FloatField(initial=10.0, min_value=0.0,
1901 widget=django.forms.TextInput(attrs={'size':5}))
1913 widget=django.forms.TextInput(attrs={'size':5}))
1902 self.fields['start_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0,
1914 self.fields['start_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0,
1903 widget=django.forms.TextInput(attrs={'size':5}))
1915 widget=django.forms.TextInput(attrs={'size':5}))
1904 self.fields['stop_alt'] = django.forms.FloatField(initial=500.0, min_value=0.0,
1916 self.fields['stop_alt'] = django.forms.FloatField(initial=500.0, min_value=0.0,
1905 widget=django.forms.TextInput(attrs={'size':5}))
1917 widget=django.forms.TextInput(attrs={'size':5}))
1906 self.fields['step_alt'] = django.forms.FloatField(initial=500.0, min_value=0.0,
1918 self.fields['step_alt'] = django.forms.FloatField(initial=500.0, min_value=0.0,
1907 widget=django.forms.TextInput(attrs={'size':5}))
1919 widget=django.forms.TextInput(attrs={'size':5}))
1908
1920
1909
1921
1910 class LookerGeomagRadar(django.forms.Form):
1922 class LookerGeomagRadar(django.forms.Form):
1911 """LookerGeomagRadar is the form for the geomagnetic to radar page
1923 """LookerGeomagRadar is the form for the geomagnetic to radar page
1912 """
1924 """
1913 def __init__(self, *args, **kwargs):
1925 def __init__(self, *args, **kwargs):
1914 """
1926 """
1915 """
1927 """
1916 super(LookerGeomagRadar, self).__init__(*args, **kwargs)
1928 super(LookerGeomagRadar, self).__init__(*args, **kwargs)
1917 madDB = madrigal.metadata.MadrigalDB()
1929 madDB = madrigal.metadata.MadrigalDB()
1918 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
1930 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
1919 dict1 = {'isGlobal': True, 'categories': "0"}
1931 dict1 = {'isGlobal': True, 'categories': "0"}
1920
1932
1921 self.fields['looker_options'] = django.forms.CharField(initial="2",
1933 self.fields['looker_options'] = django.forms.CharField(initial="2",
1922 widget=django.forms.HiddenInput(attrs={'value': "2"}))
1934 widget=django.forms.HiddenInput(attrs={'value': "2"}))
1923
1935
1924 self.fields['instruments'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={'size':'3'}),
1936 self.fields['instruments'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={'size':'3'}),
1925 choices=getInstrumentList([], dict1, madInstData, 'Set location manually', local=False),
1937 choices=getInstrumentList([], dict1, madInstData, 'Set location manually', local=False),
1926 required=False, label='Instrument: ')
1938 required=False, label='Instrument: ')
1927
1939
1928 self.fields['inst_lat'] = django.forms.FloatField(initial=0.0, min_value=-90.0, max_value=90.0,
1940 self.fields['inst_lat'] = django.forms.FloatField(initial=0.0, min_value=-90.0, max_value=90.0,
1929 widget=django.forms.TextInput(attrs={'size':5}))
1941 widget=django.forms.TextInput(attrs={'size':5}))
1930 self.fields['inst_lon'] = django.forms.FloatField(initial=0.0, min_value=-180.0, max_value=180.0,
1942 self.fields['inst_lon'] = django.forms.FloatField(initial=0.0, min_value=-180.0, max_value=180.0,
1931 widget=django.forms.TextInput(attrs={'size':5}))
1943 widget=django.forms.TextInput(attrs={'size':5}))
1932 self.fields['inst_alt'] = django.forms.FloatField(initial=0.0, min_value=0.0,
1944 self.fields['inst_alt'] = django.forms.FloatField(initial=0.0, min_value=0.0,
1933 widget=django.forms.TextInput(attrs={'size':5}))
1945 widget=django.forms.TextInput(attrs={'size':5}))
1934 self.fields['start_lat'] = django.forms.FloatField(initial=30.0, min_value=-90.0, max_value=90.0,
1946 self.fields['start_lat'] = django.forms.FloatField(initial=30.0, min_value=-90.0, max_value=90.0,
1935 widget=django.forms.TextInput(attrs={'size':5}))
1947 widget=django.forms.TextInput(attrs={'size':5}))
1936 self.fields['stop_lat'] = django.forms.FloatField(initial=50.0, min_value=-90.0, max_value=90.0,
1948 self.fields['stop_lat'] = django.forms.FloatField(initial=50.0, min_value=-90.0, max_value=90.0,
1937 widget=django.forms.TextInput(attrs={'size':5}))
1949 widget=django.forms.TextInput(attrs={'size':5}))
1938 self.fields['step_lat'] = django.forms.FloatField(initial=10.0, min_value=0.0,
1950 self.fields['step_lat'] = django.forms.FloatField(initial=10.0, min_value=0.0,
1939 widget=django.forms.TextInput(attrs={'size':5}))
1951 widget=django.forms.TextInput(attrs={'size':5}))
1940 self.fields['start_lon'] = django.forms.FloatField(initial=-100.0, min_value=-180.0, max_value=180.0,
1952 self.fields['start_lon'] = django.forms.FloatField(initial=-100.0, min_value=-180.0, max_value=180.0,
1941 widget=django.forms.TextInput(attrs={'size':5}))
1953 widget=django.forms.TextInput(attrs={'size':5}))
1942 self.fields['stop_lon'] = django.forms.FloatField(initial=-80.0, min_value=-180.0, max_value=180.0,
1954 self.fields['stop_lon'] = django.forms.FloatField(initial=-80.0, min_value=-180.0, max_value=180.0,
1943 widget=django.forms.TextInput(attrs={'size':5}))
1955 widget=django.forms.TextInput(attrs={'size':5}))
1944 self.fields['step_lon'] = django.forms.FloatField(initial=10.0, min_value=0.0,
1956 self.fields['step_lon'] = django.forms.FloatField(initial=10.0, min_value=0.0,
1945 widget=django.forms.TextInput(attrs={'size':5}))
1957 widget=django.forms.TextInput(attrs={'size':5}))
1946 self.fields['start_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0,
1958 self.fields['start_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0,
1947 widget=django.forms.TextInput(attrs={'size':5}))
1959 widget=django.forms.TextInput(attrs={'size':5}))
1948 self.fields['stop_alt'] = django.forms.FloatField(initial=500.0, min_value=0.0,
1960 self.fields['stop_alt'] = django.forms.FloatField(initial=500.0, min_value=0.0,
1949 widget=django.forms.TextInput(attrs={'size':5}))
1961 widget=django.forms.TextInput(attrs={'size':5}))
1950 self.fields['step_alt'] = django.forms.FloatField(initial=500.0, min_value=0.0,
1962 self.fields['step_alt'] = django.forms.FloatField(initial=500.0, min_value=0.0,
1951 widget=django.forms.TextInput(attrs={'size':5}))
1963 widget=django.forms.TextInput(attrs={'size':5}))
1952 now = datetime.datetime.utcnow()
1964 now = datetime.datetime.utcnow()
1953 self.fields['year'] = django.forms.FloatField(initial=float(now.year), min_value=1950.0,
1965 self.fields['year'] = django.forms.FloatField(initial=float(now.year), min_value=1950.0,
1954 widget=django.forms.TextInput(attrs={'size':5}))
1966 widget=django.forms.TextInput(attrs={'size':5}))
1955
1967
1956 class LookerGeomagFromGeodetic(django.forms.Form):
1968 class LookerGeomagFromGeodetic(django.forms.Form):
1957 """LookerGeomagFromGeodetic is the form for the geomagnetic from geodetic page
1969 """LookerGeomagFromGeodetic is the form for the geomagnetic from geodetic page
1958 """
1970 """
1959 def __init__(self, *args, **kwargs):
1971 def __init__(self, *args, **kwargs):
1960 """
1972 """
1961 """
1973 """
1962 super(LookerGeomagFromGeodetic, self).__init__(*args, **kwargs)
1974 super(LookerGeomagFromGeodetic, self).__init__(*args, **kwargs)
1963
1975
1964 self.fields['looker_options'] = django.forms.CharField(initial="3",
1976 self.fields['looker_options'] = django.forms.CharField(initial="3",
1965 widget=django.forms.HiddenInput(attrs={'value': "3"}))
1977 widget=django.forms.HiddenInput(attrs={'value': "3"}))
1966
1978
1967 self.fields['start_lat'] = django.forms.FloatField(initial=30.0, min_value=-90.0, max_value=90.0,
1979 self.fields['start_lat'] = django.forms.FloatField(initial=30.0, min_value=-90.0, max_value=90.0,
1968 widget=django.forms.TextInput(attrs={'size':5}))
1980 widget=django.forms.TextInput(attrs={'size':5}))
1969 self.fields['stop_lat'] = django.forms.FloatField(initial=50.0, min_value=-90.0, max_value=90.0,
1981 self.fields['stop_lat'] = django.forms.FloatField(initial=50.0, min_value=-90.0, max_value=90.0,
1970 widget=django.forms.TextInput(attrs={'size':5}))
1982 widget=django.forms.TextInput(attrs={'size':5}))
1971 self.fields['step_lat'] = django.forms.FloatField(initial=10.0, min_value=0.0,
1983 self.fields['step_lat'] = django.forms.FloatField(initial=10.0, min_value=0.0,
1972 widget=django.forms.TextInput(attrs={'size':5}))
1984 widget=django.forms.TextInput(attrs={'size':5}))
1973 self.fields['start_lon'] = django.forms.FloatField(initial=-100.0, min_value=-180.0, max_value=180.0,
1985 self.fields['start_lon'] = django.forms.FloatField(initial=-100.0, min_value=-180.0, max_value=180.0,
1974 widget=django.forms.TextInput(attrs={'size':5}))
1986 widget=django.forms.TextInput(attrs={'size':5}))
1975 self.fields['stop_lon'] = django.forms.FloatField(initial=-80.0, min_value=-180.0, max_value=180.0,
1987 self.fields['stop_lon'] = django.forms.FloatField(initial=-80.0, min_value=-180.0, max_value=180.0,
1976 widget=django.forms.TextInput(attrs={'size':5}))
1988 widget=django.forms.TextInput(attrs={'size':5}))
1977 self.fields['step_lon'] = django.forms.FloatField(initial=10.0, min_value=0.0,
1989 self.fields['step_lon'] = django.forms.FloatField(initial=10.0, min_value=0.0,
1978 widget=django.forms.TextInput(attrs={'size':5}))
1990 widget=django.forms.TextInput(attrs={'size':5}))
1979 self.fields['start_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0,
1991 self.fields['start_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0,
1980 widget=django.forms.TextInput(attrs={'size':5}))
1992 widget=django.forms.TextInput(attrs={'size':5}))
1981 self.fields['stop_alt'] = django.forms.FloatField(initial=500.0, min_value=0.0,
1993 self.fields['stop_alt'] = django.forms.FloatField(initial=500.0, min_value=0.0,
1982 widget=django.forms.TextInput(attrs={'size':5}))
1994 widget=django.forms.TextInput(attrs={'size':5}))
1983 self.fields['step_alt'] = django.forms.FloatField(initial=500.0, min_value=0.0,
1995 self.fields['step_alt'] = django.forms.FloatField(initial=500.0, min_value=0.0,
1984 widget=django.forms.TextInput(attrs={'size':5}))
1996 widget=django.forms.TextInput(attrs={'size':5}))
1985 now = datetime.datetime.utcnow()
1997 now = datetime.datetime.utcnow()
1986 self.fields['year'] = django.forms.FloatField(initial=float(now.year), min_value=1950.0,
1998 self.fields['year'] = django.forms.FloatField(initial=float(now.year), min_value=1950.0,
1987 widget=django.forms.TextInput(attrs={'size':5}))
1999 widget=django.forms.TextInput(attrs={'size':5}))
1988
2000
1989 class LookerGeomagFromRadar(django.forms.Form):
2001 class LookerGeomagFromRadar(django.forms.Form):
1990 """LookerGeomagFromRadar is the form for the geomagnetic from radar page
2002 """LookerGeomagFromRadar is the form for the geomagnetic from radar page
1991 """
2003 """
1992 def __init__(self, *args, **kwargs):
2004 def __init__(self, *args, **kwargs):
1993 """
2005 """
1994 """
2006 """
1995 super(LookerGeomagFromRadar, self).__init__(*args, **kwargs)
2007 super(LookerGeomagFromRadar, self).__init__(*args, **kwargs)
1996 madDB = madrigal.metadata.MadrigalDB()
2008 madDB = madrigal.metadata.MadrigalDB()
1997 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
2009 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
1998 dict1 = {'isGlobal': True, 'categories': "0"}
2010 dict1 = {'isGlobal': True, 'categories': "0"}
1999
2011
2000 self.fields['looker_options'] = django.forms.CharField(initial="4",
2012 self.fields['looker_options'] = django.forms.CharField(initial="4",
2001 widget=django.forms.HiddenInput(attrs={'value': "4"}))
2013 widget=django.forms.HiddenInput(attrs={'value': "4"}))
2002
2014
2003 self.fields['instruments'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={'size':'3'}),
2015 self.fields['instruments'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={'size':'3'}),
2004 choices=getInstrumentList([], dict1, madInstData, local=False)[1:],
2016 choices=getInstrumentList([], dict1, madInstData, local=False)[1:],
2005 required=False, label='Instrument: ')
2017 required=False, label='Instrument: ')
2006
2018
2007 self.fields['inst_lat'] = django.forms.FloatField(initial=0.0, min_value=-90.0, max_value=90.0,
2019 self.fields['inst_lat'] = django.forms.FloatField(initial=0.0, min_value=-90.0, max_value=90.0,
2008 widget=django.forms.TextInput(attrs={'size':5}))
2020 widget=django.forms.TextInput(attrs={'size':5}))
2009 self.fields['inst_lon'] = django.forms.FloatField(initial=0.0, min_value=-180.0, max_value=180.0,
2021 self.fields['inst_lon'] = django.forms.FloatField(initial=0.0, min_value=-180.0, max_value=180.0,
2010 widget=django.forms.TextInput(attrs={'size':5}))
2022 widget=django.forms.TextInput(attrs={'size':5}))
2011 self.fields['inst_alt'] = django.forms.FloatField(initial=0.0, min_value=0.0,
2023 self.fields['inst_alt'] = django.forms.FloatField(initial=0.0, min_value=0.0,
2012 widget=django.forms.TextInput(attrs={'size':5}))
2024 widget=django.forms.TextInput(attrs={'size':5}))
2013 self.fields['start_az'] = django.forms.FloatField(initial=-180.0, min_value=-180.0, max_value=180.0,
2025 self.fields['start_az'] = django.forms.FloatField(initial=-180.0, min_value=-180.0, max_value=180.0,
2014 widget=django.forms.TextInput(attrs={'size':5}))
2026 widget=django.forms.TextInput(attrs={'size':5}))
2015 self.fields['stop_az'] = django.forms.FloatField(initial=180.0, min_value=-180.0, max_value=180.0,
2027 self.fields['stop_az'] = django.forms.FloatField(initial=180.0, min_value=-180.0, max_value=180.0,
2016 widget=django.forms.TextInput(attrs={'size':5}))
2028 widget=django.forms.TextInput(attrs={'size':5}))
2017 self.fields['step_az'] = django.forms.FloatField(initial=45.0, min_value=0.0,
2029 self.fields['step_az'] = django.forms.FloatField(initial=45.0, min_value=0.0,
2018 widget=django.forms.TextInput(attrs={'size':5}))
2030 widget=django.forms.TextInput(attrs={'size':5}))
2019 self.fields['start_el'] = django.forms.FloatField(initial=0.0, min_value=0.0, max_value=90.0,
2031 self.fields['start_el'] = django.forms.FloatField(initial=0.0, min_value=0.0, max_value=90.0,
2020 widget=django.forms.TextInput(attrs={'size':5}))
2032 widget=django.forms.TextInput(attrs={'size':5}))
2021 self.fields['stop_el'] = django.forms.FloatField(initial=90.0, min_value=0.0, max_value=90.0,
2033 self.fields['stop_el'] = django.forms.FloatField(initial=90.0, min_value=0.0, max_value=90.0,
2022 widget=django.forms.TextInput(attrs={'size':5}))
2034 widget=django.forms.TextInput(attrs={'size':5}))
2023 self.fields['step_el'] = django.forms.FloatField(initial=30.0, min_value=0.0,
2035 self.fields['step_el'] = django.forms.FloatField(initial=30.0, min_value=0.0,
2024 widget=django.forms.TextInput(attrs={'size':5}))
2036 widget=django.forms.TextInput(attrs={'size':5}))
2025 self.fields['start_range'] = django.forms.FloatField(initial=0.0, min_value=0.0,
2037 self.fields['start_range'] = django.forms.FloatField(initial=0.0, min_value=0.0,
2026 widget=django.forms.TextInput(attrs={'size':5}))
2038 widget=django.forms.TextInput(attrs={'size':5}))
2027 self.fields['stop_range'] = django.forms.FloatField(initial=600.0, min_value=0.0,
2039 self.fields['stop_range'] = django.forms.FloatField(initial=600.0, min_value=0.0,
2028 widget=django.forms.TextInput(attrs={'size':5}))
2040 widget=django.forms.TextInput(attrs={'size':5}))
2029 self.fields['step_range'] = django.forms.FloatField(initial=200.0, min_value=0.0,
2041 self.fields['step_range'] = django.forms.FloatField(initial=200.0, min_value=0.0,
2030 widget=django.forms.TextInput(attrs={'size':5}))
2042 widget=django.forms.TextInput(attrs={'size':5}))
2031 now = datetime.datetime.utcnow()
2043 now = datetime.datetime.utcnow()
2032 self.fields['year'] = django.forms.FloatField(initial=float(now.year), min_value=1950.0,
2044 self.fields['year'] = django.forms.FloatField(initial=float(now.year), min_value=1950.0,
2033 widget=django.forms.TextInput(attrs={'size':5}))
2045 widget=django.forms.TextInput(attrs={'size':5}))
2034
2046
2035
2047
2036 class LookerFieldLineFromRadar(django.forms.Form):
2048 class LookerFieldLineFromRadar(django.forms.Form):
2037 """LookerFieldLineFromRadar is the form for the field line from radar page
2049 """LookerFieldLineFromRadar is the form for the field line from radar page
2038 """
2050 """
2039 def __init__(self, *args, **kwargs):
2051 def __init__(self, *args, **kwargs):
2040 """
2052 """
2041 """
2053 """
2042 super(LookerFieldLineFromRadar, self).__init__(*args, **kwargs)
2054 super(LookerFieldLineFromRadar, self).__init__(*args, **kwargs)
2043 madDB = madrigal.metadata.MadrigalDB()
2055 madDB = madrigal.metadata.MadrigalDB()
2044 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
2056 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
2045 dict1 = {'isGlobal': True, 'categories': "0"}
2057 dict1 = {'isGlobal': True, 'categories': "0"}
2046
2058
2047 self.fields['looker_options'] = django.forms.CharField(initial="5",
2059 self.fields['looker_options'] = django.forms.CharField(initial="5",
2048 widget=django.forms.HiddenInput(attrs={'value': "5"}))
2060 widget=django.forms.HiddenInput(attrs={'value': "5"}))
2049
2061
2050 self.fields['instruments'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={'size':'3'}),
2062 self.fields['instruments'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={'size':'3'}),
2051 choices=getInstrumentList([], dict1, madInstData, 'Set location manually', local=False),
2063 choices=getInstrumentList([], dict1, madInstData, 'Set location manually', local=False),
2052 required=False, label='Instrument: ')
2064 required=False, label='Instrument: ')
2053
2065
2054 self.fields['inst_lat'] = django.forms.FloatField(initial=0.0, min_value=-90.0, max_value=90.0,
2066 self.fields['inst_lat'] = django.forms.FloatField(initial=0.0, min_value=-90.0, max_value=90.0,
2055 widget=django.forms.TextInput(attrs={'size':5}))
2067 widget=django.forms.TextInput(attrs={'size':5}))
2056 self.fields['inst_lon'] = django.forms.FloatField(initial=0.0, min_value=-180.0, max_value=180.0,
2068 self.fields['inst_lon'] = django.forms.FloatField(initial=0.0, min_value=-180.0, max_value=180.0,
2057 widget=django.forms.TextInput(attrs={'size':5}))
2069 widget=django.forms.TextInput(attrs={'size':5}))
2058 self.fields['inst_alt'] = django.forms.FloatField(initial=0.0, min_value=0.0,
2070 self.fields['inst_alt'] = django.forms.FloatField(initial=0.0, min_value=0.0,
2059 widget=django.forms.TextInput(attrs={'size':5}))
2071 widget=django.forms.TextInput(attrs={'size':5}))
2060 self.fields['fl_az'] = django.forms.FloatField(initial=0.0, min_value=-180.0, max_value=180.0,
2072 self.fields['fl_az'] = django.forms.FloatField(initial=0.0, min_value=-180.0, max_value=180.0,
2061 widget=django.forms.TextInput(attrs={'size':5}))
2073 widget=django.forms.TextInput(attrs={'size':5}))
2062 self.fields['fl_el'] = django.forms.FloatField(initial=45.0, min_value=0.0, max_value=90.0,
2074 self.fields['fl_el'] = django.forms.FloatField(initial=45.0, min_value=0.0, max_value=90.0,
2063 widget=django.forms.TextInput(attrs={'size':5}))
2075 widget=django.forms.TextInput(attrs={'size':5}))
2064 self.fields['fl_range'] = django.forms.FloatField(initial=1000.0, min_value=0.0,
2076 self.fields['fl_range'] = django.forms.FloatField(initial=1000.0, min_value=0.0,
2065 widget=django.forms.TextInput(attrs={'size':5}))
2077 widget=django.forms.TextInput(attrs={'size':5}))
2066
2078
2067 self.fields['start_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0,
2079 self.fields['start_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0,
2068 widget=django.forms.TextInput(attrs={'size':5}))
2080 widget=django.forms.TextInput(attrs={'size':5}))
2069 self.fields['stop_alt'] = django.forms.FloatField(initial=1000.0, min_value=0.0,
2081 self.fields['stop_alt'] = django.forms.FloatField(initial=1000.0, min_value=0.0,
2070 widget=django.forms.TextInput(attrs={'size':5}))
2082 widget=django.forms.TextInput(attrs={'size':5}))
2071 self.fields['step_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0,
2083 self.fields['step_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0,
2072 widget=django.forms.TextInput(attrs={'size':5}))
2084 widget=django.forms.TextInput(attrs={'size':5}))
2073 now = datetime.datetime.utcnow()
2085 now = datetime.datetime.utcnow()
2074 self.fields['year'] = django.forms.FloatField(initial=float(now.year), min_value=1950.0,
2086 self.fields['year'] = django.forms.FloatField(initial=float(now.year), min_value=1950.0,
2075 widget=django.forms.TextInput(attrs={'size':5}))
2087 widget=django.forms.TextInput(attrs={'size':5}))
2076
2088
2077
2089
2078
2090
2079 class LookerFieldLineFromGeodetic(django.forms.Form):
2091 class LookerFieldLineFromGeodetic(django.forms.Form):
2080 """LookerFieldLineFromGeodetic is the form for the field line from geodetic page
2092 """LookerFieldLineFromGeodetic is the form for the field line from geodetic page
2081 """
2093 """
2082 def __init__(self, *args, **kwargs):
2094 def __init__(self, *args, **kwargs):
2083 """
2095 """
2084 """
2096 """
2085 super(LookerFieldLineFromGeodetic, self).__init__(*args, **kwargs)
2097 super(LookerFieldLineFromGeodetic, self).__init__(*args, **kwargs)
2086 madDB = madrigal.metadata.MadrigalDB()
2098 madDB = madrigal.metadata.MadrigalDB()
2087 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
2099 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
2088 dict1 = {'isGlobal': True, 'categories': "0"}
2100 dict1 = {'isGlobal': True, 'categories': "0"}
2089
2101
2090 self.fields['looker_options'] = django.forms.CharField(initial="6",
2102 self.fields['looker_options'] = django.forms.CharField(initial="6",
2091 widget=django.forms.HiddenInput(attrs={'value': "6"}))
2103 widget=django.forms.HiddenInput(attrs={'value': "6"}))
2092
2104
2093 self.fields['instruments'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={'size':'3'}),
2105 self.fields['instruments'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={'size':'3'}),
2094 choices=getInstrumentList([], dict1, madInstData, 'Set location manually', local=False),
2106 choices=getInstrumentList([], dict1, madInstData, 'Set location manually', local=False),
2095 required=False, label='Instrument: ')
2107 required=False, label='Instrument: ')
2096
2108
2097 self.fields['inst_lat'] = django.forms.FloatField(initial=0.0, min_value=-90.0, max_value=90.0,
2109 self.fields['inst_lat'] = django.forms.FloatField(initial=0.0, min_value=-90.0, max_value=90.0,
2098 widget=django.forms.TextInput(attrs={'size':5}))
2110 widget=django.forms.TextInput(attrs={'size':5}))
2099 self.fields['inst_lon'] = django.forms.FloatField(initial=0.0, min_value=-180.0, max_value=180.0,
2111 self.fields['inst_lon'] = django.forms.FloatField(initial=0.0, min_value=-180.0, max_value=180.0,
2100 widget=django.forms.TextInput(attrs={'size':5}))
2112 widget=django.forms.TextInput(attrs={'size':5}))
2101 self.fields['inst_alt'] = django.forms.FloatField(initial=0.0, min_value=0.0,
2113 self.fields['inst_alt'] = django.forms.FloatField(initial=0.0, min_value=0.0,
2102 widget=django.forms.TextInput(attrs={'size':5}))
2114 widget=django.forms.TextInput(attrs={'size':5}))
2103 self.fields['fl_lat'] = django.forms.FloatField(initial=45.0, min_value=-90.0, max_value=90.0,
2115 self.fields['fl_lat'] = django.forms.FloatField(initial=45.0, min_value=-90.0, max_value=90.0,
2104 widget=django.forms.TextInput(attrs={'size':5}))
2116 widget=django.forms.TextInput(attrs={'size':5}))
2105 self.fields['fl_lon'] = django.forms.FloatField(initial=-90.0, min_value=-180.0, max_value=180.0,
2117 self.fields['fl_lon'] = django.forms.FloatField(initial=-90.0, min_value=-180.0, max_value=180.0,
2106 widget=django.forms.TextInput(attrs={'size':5}))
2118 widget=django.forms.TextInput(attrs={'size':5}))
2107 self.fields['fl_alt'] = django.forms.FloatField(initial=0.0, min_value=0.0,
2119 self.fields['fl_alt'] = django.forms.FloatField(initial=0.0, min_value=0.0,
2108 widget=django.forms.TextInput(attrs={'size':5}))
2120 widget=django.forms.TextInput(attrs={'size':5}))
2109
2121
2110 self.fields['start_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0,
2122 self.fields['start_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0,
2111 widget=django.forms.TextInput(attrs={'size':5}))
2123 widget=django.forms.TextInput(attrs={'size':5}))
2112 self.fields['stop_alt'] = django.forms.FloatField(initial=1000.0, min_value=0.0,
2124 self.fields['stop_alt'] = django.forms.FloatField(initial=1000.0, min_value=0.0,
2113 widget=django.forms.TextInput(attrs={'size':5}))
2125 widget=django.forms.TextInput(attrs={'size':5}))
2114 self.fields['step_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0,
2126 self.fields['step_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0,
2115 widget=django.forms.TextInput(attrs={'size':5}))
2127 widget=django.forms.TextInput(attrs={'size':5}))
2116 now = datetime.datetime.utcnow()
2128 now = datetime.datetime.utcnow()
2117 self.fields['year'] = django.forms.FloatField(initial=float(now.year), min_value=1950.0,
2129 self.fields['year'] = django.forms.FloatField(initial=float(now.year), min_value=1950.0,
2118 widget=django.forms.TextInput(attrs={'size':5}))
2130 widget=django.forms.TextInput(attrs={'size':5}))
2119
2131
2120
2132
2121 class LookerFieldLineFromApex(django.forms.Form):
2133 class LookerFieldLineFromApex(django.forms.Form):
2122 """LookerFieldLineFromApex is the form for the field line from apex coordinates page
2134 """LookerFieldLineFromApex is the form for the field line from apex coordinates page
2123 """
2135 """
2124 def __init__(self, *args, **kwargs):
2136 def __init__(self, *args, **kwargs):
2125 """
2137 """
2126 """
2138 """
2127 super(LookerFieldLineFromApex, self).__init__(*args, **kwargs)
2139 super(LookerFieldLineFromApex, self).__init__(*args, **kwargs)
2128 madDB = madrigal.metadata.MadrigalDB()
2140 madDB = madrigal.metadata.MadrigalDB()
2129 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
2141 madInstData = madrigal.metadata.MadrigalInstrumentData(madDB)
2130 dict1 = {'isGlobal': True, 'categories': "0"}
2142 dict1 = {'isGlobal': True, 'categories': "0"}
2131
2143
2132 self.fields['looker_options'] = django.forms.CharField(initial="7",
2144 self.fields['looker_options'] = django.forms.CharField(initial="7",
2133 widget=django.forms.HiddenInput(attrs={'value': "7"}))
2145 widget=django.forms.HiddenInput(attrs={'value': "7"}))
2134
2146
2135 self.fields['instruments'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={'size':'3'}),
2147 self.fields['instruments'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={'size':'3'}),
2136 choices=getInstrumentList([], dict1, madInstData, 'Set location manually', local=False),
2148 choices=getInstrumentList([], dict1, madInstData, 'Set location manually', local=False),
2137 required=False, label='Instrument: ')
2149 required=False, label='Instrument: ')
2138
2150
2139 self.fields['inst_lat'] = django.forms.FloatField(initial=0.0, min_value=-90.0, max_value=90.0,
2151 self.fields['inst_lat'] = django.forms.FloatField(initial=0.0, min_value=-90.0, max_value=90.0,
2140 widget=django.forms.TextInput(attrs={'size':5}))
2152 widget=django.forms.TextInput(attrs={'size':5}))
2141 self.fields['inst_lon'] = django.forms.FloatField(initial=0.0, min_value=-180.0, max_value=180.0,
2153 self.fields['inst_lon'] = django.forms.FloatField(initial=0.0, min_value=-180.0, max_value=180.0,
2142 widget=django.forms.TextInput(attrs={'size':5}))
2154 widget=django.forms.TextInput(attrs={'size':5}))
2143 self.fields['inst_alt'] = django.forms.FloatField(initial=0.0, min_value=0.0,
2155 self.fields['inst_alt'] = django.forms.FloatField(initial=0.0, min_value=0.0,
2144 widget=django.forms.TextInput(attrs={'size':5}))
2156 widget=django.forms.TextInput(attrs={'size':5}))
2145 self.fields['fl_apex_lat'] = django.forms.FloatField(initial=65.0, min_value=-00.0, max_value=90.0,
2157 self.fields['fl_apex_lat'] = django.forms.FloatField(initial=65.0, min_value=-00.0, max_value=90.0,
2146 widget=django.forms.TextInput(attrs={'size':5}))
2158 widget=django.forms.TextInput(attrs={'size':5}))
2147 self.fields['fl_apex_lon'] = django.forms.FloatField(initial=-90.0, min_value=-180.0, max_value=180.0,
2159 self.fields['fl_apex_lon'] = django.forms.FloatField(initial=-90.0, min_value=-180.0, max_value=180.0,
2148 widget=django.forms.TextInput(attrs={'size':5}))
2160 widget=django.forms.TextInput(attrs={'size':5}))
2149
2161
2150 self.fields['start_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0,
2162 self.fields['start_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0,
2151 widget=django.forms.TextInput(attrs={'size':5}))
2163 widget=django.forms.TextInput(attrs={'size':5}))
2152 self.fields['stop_alt'] = django.forms.FloatField(initial=1000.0, min_value=0.0,
2164 self.fields['stop_alt'] = django.forms.FloatField(initial=1000.0, min_value=0.0,
2153 widget=django.forms.TextInput(attrs={'size':5}))
2165 widget=django.forms.TextInput(attrs={'size':5}))
2154 self.fields['step_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0,
2166 self.fields['step_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0,
2155 widget=django.forms.TextInput(attrs={'size':5}))
2167 widget=django.forms.TextInput(attrs={'size':5}))
2156 now = datetime.datetime.utcnow()
2168 now = datetime.datetime.utcnow()
2157 self.fields['year'] = django.forms.FloatField(initial=float(now.year), min_value=1950.0,
2169 self.fields['year'] = django.forms.FloatField(initial=float(now.year), min_value=1950.0,
2158 widget=django.forms.TextInput(attrs={'size':5}))
2170 widget=django.forms.TextInput(attrs={'size':5}))
2159
2171
2160
2172
2161 class LookerConjugateFromGeodetic(django.forms.Form):
2173 class LookerConjugateFromGeodetic(django.forms.Form):
2162 """LookerConjugateFromGeodetic is the form for the geomagnetic/conjugate from geodetic page
2174 """LookerConjugateFromGeodetic is the form for the geomagnetic/conjugate from geodetic page
2163 """
2175 """
2164 def __init__(self, *args, **kwargs):
2176 def __init__(self, *args, **kwargs):
2165 """
2177 """
2166 """
2178 """
2167 super(LookerConjugateFromGeodetic, self).__init__(*args, **kwargs)
2179 super(LookerConjugateFromGeodetic, self).__init__(*args, **kwargs)
2168
2180
2169 parmChoices = [("MAGCONJLAT", 'Magnetic conjugate latitude'),
2181 parmChoices = [("MAGCONJLAT", 'Magnetic conjugate latitude'),
2170 ("MAGCONJLON", 'Magnetic conjugate longitude'),
2182 ("MAGCONJLON", 'Magnetic conjugate longitude'),
2171 ("SZEN", 'Solar zenith angle'),
2183 ("SZEN", 'Solar zenith angle'),
2172 ("SZENC", 'Magnetic conjugate solar zenith angle'),
2184 ("SZENC", 'Magnetic conjugate solar zenith angle'),
2173 ("SDWHT", 'Shadow height (km)'),
2185 ("SDWHT", 'Shadow height (km)'),
2174 ("MAGCONJSDWHT", 'Magnetic conjugate shadow height (km)')]
2186 ("MAGCONJSDWHT", 'Magnetic conjugate shadow height (km)')]
2175 parmInitial = [key for key, value in parmChoices]
2187 parmInitial = [key for key, value in parmChoices]
2176
2188
2177 self.fields['looker_options'] = django.forms.CharField(initial="8",
2189 self.fields['looker_options'] = django.forms.CharField(initial="8",
2178 widget=django.forms.HiddenInput(attrs={'value': "8"}))
2190 widget=django.forms.HiddenInput(attrs={'value': "8"}))
2179
2191
2180 self.fields['start_lat'] = django.forms.FloatField(initial=30.0, min_value=-90.0, max_value=90.0,
2192 self.fields['start_lat'] = django.forms.FloatField(initial=30.0, min_value=-90.0, max_value=90.0,
2181 widget=django.forms.TextInput(attrs={'size':5}))
2193 widget=django.forms.TextInput(attrs={'size':5}))
2182 self.fields['stop_lat'] = django.forms.FloatField(initial=50.0, min_value=-90.0, max_value=90.0,
2194 self.fields['stop_lat'] = django.forms.FloatField(initial=50.0, min_value=-90.0, max_value=90.0,
2183 widget=django.forms.TextInput(attrs={'size':5}))
2195 widget=django.forms.TextInput(attrs={'size':5}))
2184 self.fields['step_lat'] = django.forms.FloatField(initial=10.0, min_value=0.0,
2196 self.fields['step_lat'] = django.forms.FloatField(initial=10.0, min_value=0.0,
2185 widget=django.forms.TextInput(attrs={'size':5}))
2197 widget=django.forms.TextInput(attrs={'size':5}))
2186 self.fields['start_lon'] = django.forms.FloatField(initial=-100.0, min_value=-180.0, max_value=180.0,
2198 self.fields['start_lon'] = django.forms.FloatField(initial=-100.0, min_value=-180.0, max_value=180.0,
2187 widget=django.forms.TextInput(attrs={'size':5}))
2199 widget=django.forms.TextInput(attrs={'size':5}))
2188 self.fields['stop_lon'] = django.forms.FloatField(initial=-80.0, min_value=-180.0, max_value=180.0,
2200 self.fields['stop_lon'] = django.forms.FloatField(initial=-80.0, min_value=-180.0, max_value=180.0,
2189 widget=django.forms.TextInput(attrs={'size':5}))
2201 widget=django.forms.TextInput(attrs={'size':5}))
2190 self.fields['step_lon'] = django.forms.FloatField(initial=10.0, min_value=0.0,
2202 self.fields['step_lon'] = django.forms.FloatField(initial=10.0, min_value=0.0,
2191 widget=django.forms.TextInput(attrs={'size':5}))
2203 widget=django.forms.TextInput(attrs={'size':5}))
2192 self.fields['start_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0,
2204 self.fields['start_alt'] = django.forms.FloatField(initial=100.0, min_value=0.0,
2193 widget=django.forms.TextInput(attrs={'size':5}))
2205 widget=django.forms.TextInput(attrs={'size':5}))
2194 self.fields['stop_alt'] = django.forms.FloatField(initial=500.0, min_value=0.0,
2206 self.fields['stop_alt'] = django.forms.FloatField(initial=500.0, min_value=0.0,
2195 widget=django.forms.TextInput(attrs={'size':5}))
2207 widget=django.forms.TextInput(attrs={'size':5}))
2196 self.fields['step_alt'] = django.forms.FloatField(initial=500.0, min_value=0.0,
2208 self.fields['step_alt'] = django.forms.FloatField(initial=500.0, min_value=0.0,
2197 widget=django.forms.TextInput(attrs={'size':5}))
2209 widget=django.forms.TextInput(attrs={'size':5}))
2198
2210
2199 # time selection
2211 # time selection
2200 now = datetime.datetime.utcnow()
2212 now = datetime.datetime.utcnow()
2201 self.fields['datetime'] = django.forms.SplitDateTimeField(input_date_formats=['%Y-%m-%d'], input_time_formats=['%H:%M:%S'],
2213 self.fields['datetime'] = django.forms.SplitDateTimeField(input_date_formats=['%Y-%m-%d'], input_time_formats=['%H:%M:%S'],
2202 label='Select UT datetime',
2214 label='Select UT datetime',
2203 help_text='Select the UT time at which to run this calcuation',
2215 help_text='Select the UT time at which to run this calcuation',
2204 initial=datetime.datetime(now.year,1,1))
2216 initial=datetime.datetime(now.year,1,1))
2205
2217
2206 self.fields['pList'] = django.forms.MultipleChoiceField(widget=django.forms.CheckboxSelectMultiple(),
2218 self.fields['pList'] = django.forms.MultipleChoiceField(widget=django.forms.CheckboxSelectMultiple(),
2207 choices=parmChoices, initial=parmInitial)
2219 choices=parmChoices, initial=parmInitial)
2208
2220
1 NO CONTENT: modified file, binary diff hidden
NO CONTENT: modified file, binary diff hidden
@@ -1,75 +1,75
1 {% load static %}
1 {% load static %}
2
2
3 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
4 <html xmlns="http://www.w3.org/1999/xhtml"><!-- InstanceBegin template="/Templates/doc_template.dwt" codeOutsideHTMLIsLocked="false" -->
4 <html xmlns="http://www.w3.org/1999/xhtml"><!-- InstanceBegin template="/Templates/doc_template.dwt" codeOutsideHTMLIsLocked="false" -->
5 <head>
5 <head>
6 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
6 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
7 <!-- InstanceBeginEditable name="doctitle" -->
7 <!-- InstanceBeginEditable name="doctitle" -->
8 <title>Madrigal administrator's guide</title>
8 <title>Madrigal administrator's guide</title>
9 <!-- InstanceEndEditable --><!-- InstanceBeginEditable name="head" --><!-- InstanceEndEditable -->
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 <style type="text/css">
11 <style type="text/css">
12 html body {
12 html body {
13 background-color: {{bg_color}};
13 background-color: {{bg_color}};
14 }
14 }
15 </style>
15 </style>
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" -->
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 </head>
17 </head>
18
18
19 <body>
19 <body>
20 <table width="100%" border="1" cellpadding="0" cellspacing="2" class="navigation">
20 <table width="100%" border="1" cellpadding="0" cellspacing="2" class="navigation">
21 <tr>
21 <tr>
22 <td width="5%"><a href="{% url 'docs' 'rr_fortran95.html' %}"><img src="/static/previous.png" alt="previous" width="32" height="32" /></a></td>
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>
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>
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 <td width="54%"><!-- InstanceBeginEditable name="EditTitleTop" -->Madrigal administrator's guide<!-- InstanceEndEditable --></td>
25 <td width="54%"><!-- InstanceBeginEditable name="EditTitleTop" -->Madrigal administrator's guide<!-- InstanceEndEditable --></td>
26 <td width="13%"><a href="{% url 'docs' 'madContents.html' %}">Doc home </a></td>
26 <td width="13%"><a href="{% url 'docs' 'madContents.html' %}">Doc home </a></td>
27 <td width="18%"><a href="/">Madrigal home</a></td>
27 <td width="18%"><a href="/">Madrigal home</a></td>
28 </tr>
28 </tr>
29 </table>
29 </table>
30 <div class='online-navigation'>
30 <div class='online-navigation'>
31 <b class="navlabel">Previous:</b>
31 <b class="navlabel">Previous:</b>
32 <a class="sectref" href="{% url 'docs' 'rr_fortran95.html' %}"><!-- InstanceBeginEditable name="PreviousTitle" -->Fortran95 remote API reference <!-- InstanceEndEditable --></A>
32 <a class="sectref" href="{% url 'docs' 'rr_fortran95.html' %}"><!-- InstanceBeginEditable name="PreviousTitle" -->Fortran95 remote API reference <!-- InstanceEndEditable --></A>
33 <b class="navlabel">&nbsp;&nbsp;Up:</b>
33 <b class="navlabel">&nbsp;&nbsp;Up:</b>
34 <a class="sectref" href="{% url 'docs' 'madContents.html' %}"><!-- InstanceBeginEditable name="UpTitle" -->Doc home <!-- InstanceEndEditable --></A>
34 <a class="sectref" href="{% url 'docs' 'madContents.html' %}"><!-- InstanceBeginEditable name="UpTitle" -->Doc home <!-- InstanceEndEditable --></A>
35 <b class="navlabel">&nbsp;&nbsp;Next:</b>
35 <b class="navlabel">&nbsp;&nbsp;Next:</b>
36 <a class="sectref" href="{% url 'docs' 'ad_appropriate.html' %}"><!-- InstanceBeginEditable name="NextTitle" -->Is Madrigal appropriate?<!-- InstanceEndEditable --></A></div>
36 <a class="sectref" href="{% url 'docs' 'ad_appropriate.html' %}"><!-- InstanceBeginEditable name="NextTitle" -->Is Madrigal appropriate?<!-- InstanceEndEditable --></A></div>
37 <hr/>
37 <hr/>
38 <!-- InstanceBeginEditable name="EditDoc" -->
38 <!-- InstanceBeginEditable name="EditDoc" -->
39 <h1 align="center">Madrigal administrator's guide</h1>
39 <h1 align="center">Madrigal administrator's guide</h1>
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>
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 <ul>
41 <ul>
42 <li><a href="{% url 'docs' 'ad_appropriate.html' %}">Is Madrigal appropriate for my instrument(s)?</a></li>
42 <li><a href="{% url 'docs' 'ad_appropriate.html' %}">Is Madrigal appropriate for my instrument(s)?</a></li>
43 <li><a href="{% url 'docs' 'ad_install.html' %}">Installing Madrigal for the first time </a></li>
43 <li><a href="{% url 'docs' 'ad_install.html' %}">Installing Madrigal for the first time </a></li>
44 <li><a href="{% url 'docs' 'ad_upgrade.html' %}">Upgrading Madrigal to the latest release</a></li>
44 <li><a href="{% url 'docs' 'ad_upgrade.html' %}">Upgrading Madrigal to the latest release</a></li>
45 <li><a href="{% url 'docs' 'ad_metadata.html' %}">The Madrigal data model and metadata files</a></li>
45 <li><a href="{% url 'docs' 'ad_metadata.html' %}">The Madrigal data model and metadata files</a></li>
46 <li><a href="{% url 'docs' 'ad_experiments.html' %}">How Madrigal data is organized</a></li>
46 <li><a href="{% url 'docs' 'ad_experiments.html' %}">How Madrigal data is organized</a></li>
47 <li><a href="{% url 'docs' 'ad_createFiles.html' %}">Creating Madrigal data files</a></li>
47 <li><a href="{% url 'docs' 'ad_createFiles.html' %}">Creating Madrigal data files</a></li>
48 <li><a href="{% url 'docs' 'ad_createExp.html' %}">Creating and updating Madrigal experiments</a></li>
48 <li><a href="{% url 'docs' 'ad_createExp.html' %}">Creating and updating Madrigal experiments</a></li>
49 <li><a href="{% url 'docs' 'ad_other.html' %}">Other administrative tasks</a></li>
49 <li><a href="{% url 'docs' 'ad_other.html' %}">Other administrative tasks</a></li>
50 <li><a href="{% url 'docs' 'ad_logging.html' %}">User access logging</a></li>
50 <li><a href="{% url 'docs' 'ad_logging.html' %}">User access logging</a></li>
51 <li><a href="{% url 'docs' 'ad_links.html' %}">Creating direct links to experiments/files</a></li>
51 <li><a href="{% url 'docs' 'ad_links.html' %}">Creating direct links to experiments/files</a></li>
52 <li><a href="{% url 'docs' 'ad_isprint.html' %}">Using isprint for file quick looks</a></li>
52 <li><a href="{% url 'docs' 'ad_isprint.html' %}">Using isprint for file quick looks</a></li>
53 </ul>
53 </ul>
54 <!-- InstanceEndEditable -->
54 <!-- InstanceEndEditable -->
55 <table width="100%" border="1" cellpadding="0" cellspacing="2" class="navigation">
55 <table width="100%" border="1" cellpadding="0" cellspacing="2" class="navigation">
56 <tr>
56 <tr>
57 <td width="5%"><a href="{% url 'docs' 'rr_fortran95.html' %}"><img src="/static/previous.png" alt="previous" width="32" height="32" /></a></td>
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>
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>
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 <td width="54%"><!-- InstanceBeginEditable name="EditTitleBottom" -->Madrigal administrator's guide<!-- InstanceEndEditable --></td>
60 <td width="54%"><!-- InstanceBeginEditable name="EditTitleBottom" -->Madrigal administrator's guide<!-- InstanceEndEditable --></td>
61 <td width="13%"><a href="{% url 'docs' 'madContents.html' %}">Doc home </a></td>
61 <td width="13%"><a href="{% url 'docs' 'madContents.html' %}">Doc home </a></td>
62 <td width="18%"><a href="/">Madrigal home</a></td>
62 <td width="18%"><a href="/">Madrigal home</a></td>
63 </tr>
63 </tr>
64 </table>
64 </table>
65 <div class='online-navigation'>
65 <div class='online-navigation'>
66 <b class="navlabel">Previous:</b>
66 <b class="navlabel">Previous:</b>
67 <a class="sectref" href="{% url 'docs' 'rr_fortran95.html' %}"><!-- InstanceBeginEditable name="PreviousTitle2" -->Fortran95 remote API reference <!-- InstanceEndEditable --></A>
67 <a class="sectref" href="{% url 'docs' 'rr_fortran95.html' %}"><!-- InstanceBeginEditable name="PreviousTitle2" -->Fortran95 remote API reference <!-- InstanceEndEditable --></A>
68 <b class="navlabel">&nbsp;&nbsp;Up:</b>
68 <b class="navlabel">&nbsp;&nbsp;Up:</b>
69 <a class="sectref" href="{% url 'docs' 'madContents.html' %}"><!-- InstanceBeginEditable name="UpTitle2" -->Doc home <!-- InstanceEndEditable --></A>
69 <a class="sectref" href="{% url 'docs' 'madContents.html' %}"><!-- InstanceBeginEditable name="UpTitle2" -->Doc home <!-- InstanceEndEditable --></A>
70 <b class="navlabel">&nbsp;&nbsp;Next:</b>
70 <b class="navlabel">&nbsp;&nbsp;Next:</b>
71 <a class="sectref" href="{% url 'docs' 'ad_appropriate.html' %}"><!-- InstanceBeginEditable name="NextTitle2" -->Is Madrigal appropriate? <!-- InstanceEndEditable --></A></div>
71 <a class="sectref" href="{% url 'docs' 'ad_appropriate.html' %}"><!-- InstanceBeginEditable name="NextTitle2" -->Is Madrigal appropriate? <!-- InstanceEndEditable --></A></div>
72 <hr/>
72 <hr/>
73 <p>&nbsp;</p>
73 <p>&nbsp;</p>
74 </body>
74 </body>
75 <!-- InstanceEnd --></html>
75 <!-- InstanceEnd --></html>
@@ -1,87 +1,87
1 {% load static %}
1 {% load static %}
2
2
3 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
4 <html xmlns="http://www.w3.org/1999/xhtml"><!-- InstanceBegin template="/Templates/doc_template.dwt" codeOutsideHTMLIsLocked="false" -->
4 <html xmlns="http://www.w3.org/1999/xhtml"><!-- InstanceBegin template="/Templates/doc_template.dwt" codeOutsideHTMLIsLocked="false" -->
5 <head>
5 <head>
6 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
6 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
7 <!-- InstanceBeginEditable name="doctitle" -->
7 <!-- InstanceBeginEditable name="doctitle" -->
8 <title>Madrigal developer's guide</title>
8 <title>Madrigal developer's guide</title>
9 <!-- InstanceEndEditable --><!-- InstanceBeginEditable name="head" --><!-- InstanceEndEditable -->
9 <!-- InstanceEndEditable --><!-- InstanceBeginEditable name="head" --><!-- InstanceEndEditable -->
10 <link href="/static/madrigal.css" rel="stylesheet" type="text/css" />
10 <link href="{% static 'madrigal.css' %}" rel="stylesheet" type="text/css" />
11 <style type="text/css">
11 <style type="text/css">
12 html body {
12 html body {
13 background-color: {{bg_color}};
13 background-color: {{bg_color}};
14 }
14 }
15 </style>
15 </style>
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" -->
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 </head>
17 </head>
18
18
19 <body>
19 <body>
20 <table width="100%" border="1" cellpadding="0" cellspacing="2" class="navigation">
20 <table width="100%" border="1" cellpadding="0" cellspacing="2" class="navigation">
21 <tr>
21 <tr>
22 <td width="5%"><a href="{% url 'docs' 'ad_isprint.html' %}"><img src="/static/previous.png" alt="previous" width="32" height="32" /></a></td>
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>
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>
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 <td width="54%"><!-- InstanceBeginEditable name="EditTitleTop" -->Madrigal developer's guide <!-- InstanceEndEditable --></td>
25 <td width="54%"><!-- InstanceBeginEditable name="EditTitleTop" -->Madrigal developer's guide <!-- InstanceEndEditable --></td>
26 <td width="13%"><a href="{% url 'docs' 'madContents.html' %}">Doc home </a></td>
26 <td width="13%"><a href="{% url 'docs' 'madContents.html' %}">Doc home </a></td>
27 <td width="18%"><a href="/">Madrigal home</a></td>
27 <td width="18%"><a href="/">Madrigal home</a></td>
28 </tr>
28 </tr>
29 </table>
29 </table>
30 <div class='online-navigation'>
30 <div class='online-navigation'>
31 <b class="navlabel">Previous:</b>
31 <b class="navlabel">Previous:</b>
32 <a class="sectref" href="{% url 'docs' 'ad_isprint.html' %}"><!-- InstanceBeginEditable name="PreviousTitle" -->Using isprint<!-- InstanceEndEditable --></A>
32 <a class="sectref" href="{% url 'docs' 'ad_isprint.html' %}"><!-- InstanceBeginEditable name="PreviousTitle" -->Using isprint<!-- InstanceEndEditable --></A>
33 <b class="navlabel">&nbsp;&nbsp;Up:</b>
33 <b class="navlabel">&nbsp;&nbsp;Up:</b>
34 <a class="sectref" href="{% url 'docs' 'madContents.html' %}"><!-- InstanceBeginEditable name="UpTitle" -->Doc home <!-- InstanceEndEditable --></A>
34 <a class="sectref" href="{% url 'docs' 'madContents.html' %}"><!-- InstanceBeginEditable name="UpTitle" -->Doc home <!-- InstanceEndEditable --></A>
35 <b class="navlabel">&nbsp;&nbsp;Next:</b>
35 <b class="navlabel">&nbsp;&nbsp;Next:</b>
36 <a class="sectref" href="{% url 'docs' 'madrigal/index.html' %}"><!-- InstanceBeginEditable name="NextTitle" -->Internal python API<!-- InstanceEndEditable --></A></div>
36 <a class="sectref" href="{% url 'docs' 'madrigal/index.html' %}"><!-- InstanceBeginEditable name="NextTitle" -->Internal python API<!-- InstanceEndEditable --></A></div>
37 <hr/>
37 <hr/>
38 <!-- InstanceBeginEditable name="EditDoc" -->
38 <!-- InstanceBeginEditable name="EditDoc" -->
39 <h1 align="center">Madrigal developer's guide</h1>
39 <h1 align="center">Madrigal developer's guide</h1>
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>
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 <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>
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 <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>
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 <ul>
43 <ul>
44 <li><a href="madrigal/index.html">Internal Madrigal Python API</a>
44 <li><a href="madrigal/index.html">Internal Madrigal Python API</a>
45 <ul>
45 <ul>
46 <li><a href="{% url 'docs' 'madrigal/admin.m.html' %}">madrigal.admin</a></li>
46 <li><a href="{% url 'docs' 'madrigal/admin.m.html' %}">madrigal.admin</a></li>
47 <li><a href="{% url 'docs' 'madrigal/cedar.m.html' %}">madrigal.cedar</a></li>
47 <li><a href="{% url 'docs' 'madrigal/cedar.m.html' %}">madrigal.cedar</a></li>
48 <li><a href="{% url 'docs' 'madrigal/data.m.html' %}">madrigal.data</a></li>
48 <li><a href="{% url 'docs' 'madrigal/data.m.html' %}">madrigal.data</a></li>
49 <li><a href="{% url 'docs' 'madrigal/derivation.m.html' %}">madrigal.derivation</a></li>
49 <li><a href="{% url 'docs' 'madrigal/derivation.m.html' %}">madrigal.derivation</a></li>
50 <li><a href="{% url 'docs' 'madrigal/isprint.m.html' %}">madrigal.isprint</a></li>
50 <li><a href="{% url 'docs' 'madrigal/isprint.m.html' %}">madrigal.isprint</a></li>
51 <li><a href="{% url 'docs' 'madrigal/metadata.m.html' %}">madrigal.metadata</a></li>
51 <li><a href="{% url 'docs' 'madrigal/metadata.m.html' %}">madrigal.metadata</a></li>
52 <li><a href="{% url 'docs' 'madrigal/openmadrigal.m.html' %}">madrigal.openmadrigal</a></li>
52 <li><a href="{% url 'docs' 'madrigal/openmadrigal.m.html' %}">madrigal.openmadrigal</a></li>
53 <li><a href="{% url 'docs' 'madrigal/ui/index.html' %}">madrigal.ui</a>
53 <li><a href="{% url 'docs' 'madrigal/ui/index.html' %}">madrigal.ui</a>
54 <ul>
54 <ul>
55 <li><a href="{% url 'docs' 'madrigal/ui/madrigalPlot.m.html' %}">madrigal.ui.madrigalPlot</a></li>
55 <li><a href="{% url 'docs' 'madrigal/ui/madrigalPlot.m.html' %}">madrigal.ui.madrigalPlot</a></li>
56 <li><a href="{% url 'docs' 'madrigal/ui/userData.m.html' %}">madrigal.ui.userData</a></li>
56 <li><a href="{% url 'docs' 'madrigal/ui/userData.m.html' %}">madrigal.ui.userData</a></li>
57 <li><a href="{% url 'docs' 'madrigal/ui/web.m.html' %}">madrigal.ui.web</a></li>
57 <li><a href="{% url 'docs' 'madrigal/ui/web.m.html' %}">madrigal.ui.web</a></li>
58 </ul>
58 </ul>
59 </li>
59 </li>
60 </ul>
60 </ul>
61 </li>
61 </li>
62 <li><a href="{% url 'docs' 'dev_derivation.html' %}">Madrigal derivation engine</a></li>
62 <li><a href="{% url 'docs' 'dev_derivation.html' %}">Madrigal derivation engine</a></li>
63 <li><a href="/static/CEDARMadrigalHdf5Format.pdf">CEDAR Madrigal Hdf5 file format</a></li>
63 <li><a href="/static/CEDARMadrigalHdf5Format.pdf">CEDAR Madrigal Hdf5 file format</a></li>
64 <li><a href="/static/cedarFormat.pdf">Deprecated Cedar file format</a></li>
64 <li><a href="/static/cedarFormat.pdf">Deprecated Cedar file format</a></li>
65 </ul>
65 </ul>
66 <!-- InstanceEndEditable -->
66 <!-- InstanceEndEditable -->
67 <table width="100%" border="1" cellpadding="0" cellspacing="2" class="navigation">
67 <table width="100%" border="1" cellpadding="0" cellspacing="2" class="navigation">
68 <tr>
68 <tr>
69 <td width="5%"><a href="{% url 'docs' 'ad_isprint.html' %}"><img src="/static/previous.png" alt="previous" width="32" height="32" /></a></td>
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>
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>
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 <td width="54%"><!-- InstanceBeginEditable name="EditTitleBottom" -->Madrigal developer's guide<!-- InstanceEndEditable --></td>
72 <td width="54%"><!-- InstanceBeginEditable name="EditTitleBottom" -->Madrigal developer's guide<!-- InstanceEndEditable --></td>
73 <td width="13%"><a href="{% url 'docs' 'madContents.html' %}">Doc home </a></td>
73 <td width="13%"><a href="{% url 'docs' 'madContents.html' %}">Doc home </a></td>
74 <td width="18%"><a href="/">Madrigal home</a></td>
74 <td width="18%"><a href="/">Madrigal home</a></td>
75 </tr>
75 </tr>
76 </table>
76 </table>
77 <div class='online-navigation'>
77 <div class='online-navigation'>
78 <b class="navlabel">Previous:</b>
78 <b class="navlabel">Previous:</b>
79 <a class="sectref" href="{% url 'docs' 'ad_isprint.html' %}"><!-- InstanceBeginEditable name="PreviousTitle2" -->Using isprint <!-- InstanceEndEditable --></A>
79 <a class="sectref" href="{% url 'docs' 'ad_isprint.html' %}"><!-- InstanceBeginEditable name="PreviousTitle2" -->Using isprint <!-- InstanceEndEditable --></A>
80 <b class="navlabel">&nbsp;&nbsp;Up:</b>
80 <b class="navlabel">&nbsp;&nbsp;Up:</b>
81 <a class="sectref" href="{% url 'docs' 'madContents.html' %}"><!-- InstanceBeginEditable name="UpTitle2" -->Doc home <!-- InstanceEndEditable --></A>
81 <a class="sectref" href="{% url 'docs' 'madContents.html' %}"><!-- InstanceBeginEditable name="UpTitle2" -->Doc home <!-- InstanceEndEditable --></A>
82 <b class="navlabel">&nbsp;&nbsp;Next:</b>
82 <b class="navlabel">&nbsp;&nbsp;Next:</b>
83 <a class="sectref" href="{% url 'docs' 'madrigal/index.html' %}"><!-- InstanceBeginEditable name="NextTitle2" -->Internal python API <!-- InstanceEndEditable --></A></div>
83 <a class="sectref" href="{% url 'docs' 'madrigal/index.html' %}"><!-- InstanceBeginEditable name="NextTitle2" -->Internal python API <!-- InstanceEndEditable --></A></div>
84 <hr/>
84 <hr/>
85 <p>&nbsp;</p>
85 <p>&nbsp;</p>
86 </body>
86 </body>
87 <!-- InstanceEnd --></html>
87 <!-- InstanceEnd --></html>
@@ -1,50 +1,50
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2 <html xmlns="http://www.w3.org/1999/xhtml">
2 <html xmlns="http://www.w3.org/1999/xhtml">
3 <head>
3 <head>
4 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
4 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
5 <title>Madrigal documentation - v3.0</title>
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 <style type="text/css">
7 <style type="text/css">
8 html body {
8 html body {
9 background-color: {{bg_color}};
9 background-color: {{bg_color}};
10 }
10 }
11 </style>
11 </style>
12 </head>
12 </head>
13
13
14 <body>
14 <body>
15 <center>
15 <center>
16 <h1>Madrigal Database v3.2.1 Documentation - Contents</h1>
16 <h1>Madrigal Database v3.2.1 Documentation - Contents</h1>
17 <table width="100%" border="1">
17 <table width="100%" border="1">
18 <tr>
18 <tr>
19 <td class="navigation"><a href="/">Home</a></td>
19 <td class="navigation"><a href="/">Home</a></td>
20 </tr>
20 </tr>
21 </table>
21 </table>
22 </center>
22 </center>
23 <hr size="4" />
23 <hr size="4" />
24 <ul>
24 <ul>
25 <li><a href="{% url 'docs' 'madIntroduction.html' %}">1. Brief history of Madrigal</a></li>
25 <li><a href="{% url 'docs' 'madIntroduction.html' %}">1. Brief history of Madrigal</a></li>
26 </ul>
26 </ul>
27 <ul>
27 <ul>
28 <li><a href="{% url 'docs' 'whatsNew.html' %}">2. What's new in Madrigal 3.2.1</a></li>
28 <li><a href="{% url 'docs' 'whatsNew.html' %}">2. What's new in Madrigal 3.2.1</a></li>
29 </ul>
29 </ul>
30 <ul>
30 <ul>
31 <li><a href="{% url 'docs' 'wt_usersGuide.html' %}">3. Madrigal user's guide (How do I access Madrigal data?) </a>
31 <li><a href="{% url 'docs' 'wt_usersGuide.html' %}">3. Madrigal user's guide (How do I access Madrigal data?) </a>
32 <ul>
32 <ul>
33 <li><a href="{% url 'docs' 'wt_contents.html' %}">2.1 Web interface tutorial </a></li>
33 <li><a href="{% url 'docs' 'wt_contents.html' %}">2.1 Web interface tutorial </a></li>
34 <li><a href="{% url 'docs' 'rt_contents.html' %}">2.2 Remote data access programming tutorial</a></li>
34 <li><a href="{% url 'docs' 'rt_contents.html' %}">2.2 Remote data access programming tutorial</a></li>
35 <li><a href="{% url 'docs' 'rr_contents.html' %}">2.3 Remote data access programming reference guide</a></li>
35 <li><a href="{% url 'docs' 'rr_contents.html' %}">2.3 Remote data access programming reference guide</a></li>
36 </ul>
36 </ul>
37 </li>
37 </li>
38 </ul>
38 </ul>
39 <ul>
39 <ul>
40 <li><a href="{% url 'docs' 'admin.html' %}">4. Madrigal Administrator's Guide</a></li>
40 <li><a href="{% url 'docs' 'admin.html' %}">4. Madrigal Administrator's Guide</a></li>
41 </ul>
41 </ul>
42 <ul>
42 <ul>
43 <li><a href="{% url 'docs' 'dev_contents.html' %}">5. Madrigal Developer's Guide</a></li>
43 <li><a href="{% url 'docs' 'dev_contents.html' %}">5. Madrigal Developer's Guide</a></li>
44 </ul>
44 </ul>
45 <ul>
45 <ul>
46 <li><a href="{{ siteSpecific }}">6. Site specific documentation</a></li>
46 <li><a href="{{ siteSpecific }}">6. Site specific documentation</a></li>
47 </ul>
47 </ul>
48 <p>&nbsp;</p>
48 <p>&nbsp;</p>
49 </body>
49 </body>
50 </html>
50 </html>
@@ -1,71 +1,71
1 {% load static %}
1 {% load static %}
2
2
3 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
4 <html xmlns="http://www.w3.org/1999/xhtml"><!-- InstanceBegin template="/Templates/doc_template.dwt" codeOutsideHTMLIsLocked="false" -->
4 <html xmlns="http://www.w3.org/1999/xhtml"><!-- InstanceBegin template="/Templates/doc_template.dwt" codeOutsideHTMLIsLocked="false" -->
5 <head>
5 <head>
6 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
6 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
7 <!-- InstanceBeginEditable name="doctitle" -->
7 <!-- InstanceBeginEditable name="doctitle" -->
8 <title>Madrigal history</title>
8 <title>Madrigal history</title>
9 <!-- InstanceEndEditable --><!-- InstanceBeginEditable name="head" -->
9 <!-- InstanceEndEditable --><!-- InstanceBeginEditable name="head" -->
10 <!-- InstanceEndEditable -->
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 <style type="text/css">
12 <style type="text/css">
13 html body {
13 html body {
14 background-color: {{bg_color}};
14 background-color: {{bg_color}};
15 }
15 }
16 </style>
16 </style>
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" -->
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 </head>
18 </head>
19
19
20 <body>
20 <body>
21 <table width="100%" border="1" cellpadding="0" cellspacing="2" class="navigation">
21 <table width="100%" border="1" cellpadding="0" cellspacing="2" class="navigation">
22 <tr>
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>
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="/static/up.png" alt="up" 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="/static/next.png" alt="next" 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 <td width="54%"><!-- InstanceBeginEditable name="EditTitleTop" -->Brief history of Madrigal <!-- InstanceEndEditable --></td>
26 <td width="54%"><!-- InstanceBeginEditable name="EditTitleTop" -->Brief history of Madrigal <!-- InstanceEndEditable --></td>
27 <td width="13%"><a href="{% url 'docs' 'madContents.html' %}">Doc home </a></td>
27 <td width="13%"><a href="{% url 'docs' 'madContents.html' %}">Doc home </a></td>
28 <td width="18%"><a href="/">Madrigal home</a></td>
28 <td width="18%"><a href="/">Madrigal home</a></td>
29 </tr>
29 </tr>
30 </table>
30 </table>
31 <div class='online-navigation'>
31 <div class='online-navigation'>
32 <b class="navlabel">Previous:</b>
32 <b class="navlabel">Previous:</b>
33 <a class="sectref" href="{% url 'docs' 'madContents.html' %}"><!-- InstanceBeginEditable name="PreviousTitle" -->Doc home <!-- InstanceEndEditable --></A>
33 <a class="sectref" href="{% url 'docs' 'madContents.html' %}"><!-- InstanceBeginEditable name="PreviousTitle" -->Doc home <!-- InstanceEndEditable --></A>
34 <b class="navlabel">&nbsp;&nbsp;Up:</b>
34 <b class="navlabel">&nbsp;&nbsp;Up:</b>
35 <a class="sectref" href="{% url 'docs' 'madContents.html' %}"><!-- InstanceBeginEditable name="UpTitle" -->Doc home <!-- InstanceEndEditable --></A>
35 <a class="sectref" href="{% url 'docs' 'madContents.html' %}"><!-- InstanceBeginEditable name="UpTitle" -->Doc home <!-- InstanceEndEditable --></A>
36 <b class="navlabel">&nbsp;&nbsp;Next:</b>
36 <b class="navlabel">&nbsp;&nbsp;Next:</b>
37 <a class="sectref" href="{% url 'docs' 'whatsNew.html' %}"><!-- InstanceBeginEditable name="NextTitle" -->What's new in Madrigal 3.0? <!-- InstanceEndEditable --></A></div>
37 <a class="sectref" href="{% url 'docs' 'whatsNew.html' %}"><!-- InstanceBeginEditable name="NextTitle" -->What's new in Madrigal 3.0? <!-- InstanceEndEditable --></A></div>
38 <hr/>
38 <hr/>
39 <!-- InstanceBeginEditable name="EditDoc" -->
39 <!-- InstanceBeginEditable name="EditDoc" -->
40 <center>
40 <center>
41 <h1>Brief history of Madrigal </h1>
41 <h1>Brief history of Madrigal </h1>
42 </center>
42 </center>
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>
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 <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>
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 <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>
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 <p>Madrigal data are arranged into &quot;experiments&quot;, 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>
47 <p>Madrigal data are arranged into &quot;experiments&quot;, 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 <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>
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 <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>
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 <!-- InstanceEndEditable -->
50 <!-- InstanceEndEditable -->
51 <table width="100%" border="1" cellpadding="0" cellspacing="2" class="navigation">
51 <table width="100%" border="1" cellpadding="0" cellspacing="2" class="navigation">
52 <tr>
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>
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="/static/up.png" alt="up" 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="/static/next.png" alt="next" 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 <td width="54%"><!-- InstanceBeginEditable name="EditTitleBottom" -->Brief overview of Madrigal <!-- InstanceEndEditable --></td>
56 <td width="54%"><!-- InstanceBeginEditable name="EditTitleBottom" -->Brief overview of Madrigal <!-- InstanceEndEditable --></td>
57 <td width="13%"><a href="{% url 'docs' 'madContents.html' %}">Doc home </a></td>
57 <td width="13%"><a href="{% url 'docs' 'madContents.html' %}">Doc home </a></td>
58 <td width="18%"><a href="/">Madrigal home</a></td>
58 <td width="18%"><a href="/">Madrigal home</a></td>
59 </tr>
59 </tr>
60 </table>
60 </table>
61 <div class='online-navigation'>
61 <div class='online-navigation'>
62 <b class="navlabel">Previous:</b>
62 <b class="navlabel">Previous:</b>
63 <a class="sectref" href="{% url 'docs' 'madContents.html' %}"><!-- InstanceBeginEditable name="PreviousTitle2" -->Doc Home <!-- InstanceEndEditable --></A>
63 <a class="sectref" href="{% url 'docs' 'madContents.html' %}"><!-- InstanceBeginEditable name="PreviousTitle2" -->Doc Home <!-- InstanceEndEditable --></A>
64 <b class="navlabel">&nbsp;&nbsp;Up:</b>
64 <b class="navlabel">&nbsp;&nbsp;Up:</b>
65 <a class="sectref" href="{% url 'docs' 'madContents.html' %}"><!-- InstanceBeginEditable name="UpTitle2" -->Doc home <!-- InstanceEndEditable --></A>
65 <a class="sectref" href="{% url 'docs' 'madContents.html' %}"><!-- InstanceBeginEditable name="UpTitle2" -->Doc home <!-- InstanceEndEditable --></A>
66 <b class="navlabel">&nbsp;&nbsp;Next:</b>
66 <b class="navlabel">&nbsp;&nbsp;Next:</b>
67 <a class="sectref" href="{% url 'docs' 'whatsNew.html' %}"><!-- InstanceBeginEditable name="NextTitle2" -->What's new in Madrigal 3.0? <!-- InstanceEndEditable --></A></div>
67 <a class="sectref" href="{% url 'docs' 'whatsNew.html' %}"><!-- InstanceBeginEditable name="NextTitle2" -->What's new in Madrigal 3.0? <!-- InstanceEndEditable --></A></div>
68 <hr/>
68 <hr/>
69 <p>&nbsp;</p>
69 <p>&nbsp;</p>
70 </body>
70 </body>
71 <!-- InstanceEnd --></html>
71 <!-- InstanceEnd --></html>
@@ -1,50 +1,50
1 <div class="row" style="margin-bottom: 20px">
1 <div class="row" style="margin-bottom: 20px">
2 Select parameter: <br>
2 Select parameter: <br>
3 {{ form.param_list1d.label }}
3 {{ form.param_list1d.label }}
4 {{ form.param_list1d }}
4 {{ form.param_list1d }}
5 {% if form.param_list2d %}
5 {% if form.param_list2d %}
6 {{ form.param_list2d.label }}
6 {{ form.param_list2d.label }}
7 {{ form.param_list2d }}
7 {{ form.param_list2d }}
8 {% endif %}
8 {% endif %}
9
9
10 </div>
10 </div>
11
11
12 <script>
12 <script>
13 $('#id_param_list2d').bind('change', function (e) {
13 $('#id_param_list2d').bind('change', function (e) {
14 var expID = '{{ expID }}';
14 var expID = '{{ expID }}';
15 var param = $(this).val();
15 var param = $(this).val();
16 var url = '{% url 'plot' %}' + '?expID=' + expID + '&param2d=' + param;
16 var url = '{% url 'plot' %}' + '?expID=' + expID + '&param2d=' + param + '&filename=' + $('#id_file_list').val();
17 console.log(url)
17 console.log(url)
18 // first delete all forms that are now out of date
18 // first delete all forms that are now out of date
19 divIndex = $(".single_form").index($( "#file_plot" ))
19 divIndex = $(".single_form").index($( "#file_plot" ))
20 $(".single_form").slice(divIndex).empty()
20 $(".single_form").slice(divIndex).empty()
21 // second populate the file_plot html if '0' not selected
21 // second populate the file_plot html if '0' not selected
22 if (param != '0') {
22 if (param != '0') {
23 $(".single_form").slice(divIndex,divIndex+1).html("<img src=\"static/loader.gif\" class=\"load_center\"/>").load(url);
23 $(".single_form").slice(divIndex,divIndex+1).html("<img src=\"static/loader.gif\" class=\"load_center\"/>").load(url);
24 }
24 }
25 })
25 })
26 $('#id_param_list1d').bind('change', function (e) {
26 $('#id_param_list1d').bind('change', function (e) {
27 var expID = '{{ expID }}';
27 var expID = '{{ expID }}';
28 var param = $(this).val();
28 var param = $(this).val();
29 var url = '{% url 'plot' %}' + '?expID=' + expID + '&param1d=' + param;
29 var url = '{% url 'plot' %}' + '?expID=' + expID + '&param1d=' + param + '&filename=' + $('#id_file_list').val();
30 console.log(url)
30 console.log(url)
31 // first delete all forms that are now out of date
31 // first delete all forms that are now out of date
32 divIndex = $(".single_form").index($( "#file_plot" ))
32 divIndex = $(".single_form").index($( "#file_plot" ))
33 $(".single_form").slice(divIndex).empty()
33 $(".single_form").slice(divIndex).empty()
34 // second populate the file_plot html if '0' not selected
34 // second populate the file_plot html if '0' not selected
35 if (param != '0') {
35 if (param != '0') {
36 $(".single_form").slice(divIndex,divIndex+1).html("<img src=\"static/loader.gif\" class =\"load_center\"/>").load(url);
36 $(".single_form").slice(divIndex,divIndex+1).html("<img src=\"static/loader.gif\" class =\"load_center\"/>").load(url);
37 }
37 }
38 })
38 })
39 </script>
39 </script>
40 <style>
40 <style>
41 .load_center {
41 .load_center {
42 display: block;
42 display: block;
43 margin-left: auto;
43 margin-left: auto;
44 margin-right: auto;
44 margin-right: auto;
45 margin-top: 100px;
45 margin-top: 100px;
46 margin-bottom: 100px;
46 margin-bottom: 100px;
47 width: 4%;
47 width: 4%;
48 align-items: center;
48 align-items: center;
49 }
49 }
50 </style> No newline at end of file
50 </style>
@@ -1,363 +1,363
1 {% load static %}
1 {% load static %}
2
2
3 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
4 <html xmlns="http://www.w3.org/1999/xhtml"><!-- InstanceBegin template="/Templates/doc_template.dwt" codeOutsideHTMLIsLocked="false" -->
4 <html xmlns="http://www.w3.org/1999/xhtml"><!-- InstanceBegin template="/Templates/doc_template.dwt" codeOutsideHTMLIsLocked="false" -->
5 <head>
5 <head>
6 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
6 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
7 <!-- InstanceBeginEditable name="doctitle" -->
7 <!-- InstanceBeginEditable name="doctitle" -->
8 <title>What's new in Madrigal 3.2?</title>
8 <title>What's new in Madrigal 3.2?</title>
9 <!-- InstanceEndEditable --><!-- InstanceBeginEditable name="head" --><!-- InstanceEndEditable -->
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 <style type="text/css">
11 <style type="text/css">
12 html body {
12 html body {
13 background-color: {{bg_color}};
13 background-color: {{bg_color}};
14 }
14 }
15 </style>
15 </style>
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" -->
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 </head>
17 </head>
18
18
19 <body>
19 <body>
20 <table width="100%" border="1" cellpadding="0" cellspacing="2" class="navigation">
20 <table width="100%" border="1" cellpadding="0" cellspacing="2" class="navigation">
21 <tr>
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>
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="/static/up.png" alt="up" 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="/static/next.png" alt="next" 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 <td width="54%"><!-- InstanceBeginEditable name="EditTitleTop" -->What's new in Madrigal 3.0? <!-- InstanceEndEditable --></td>
25 <td width="54%"><!-- InstanceBeginEditable name="EditTitleTop" -->What's new in Madrigal 3.0? <!-- InstanceEndEditable --></td>
26 <td width="13%"><a href="{% url 'docs' 'madContents.html' %}">Doc home </a></td>
26 <td width="13%"><a href="{% url 'docs' 'madContents.html' %}">Doc home </a></td>
27 <td width="18%"><a href="/">Madrigal home</a></td>
27 <td width="18%"><a href="/">Madrigal home</a></td>
28 </tr>
28 </tr>
29 </table>
29 </table>
30 <div class='online-navigation'>
30 <div class='online-navigation'>
31 <b class="navlabel">Previous:</b>
31 <b class="navlabel">Previous:</b>
32 <a class="sectref" href="{% url 'docs' 'madIntroduction.html' %}"><!-- InstanceBeginEditable name="PreviousTitle" -->Brief History <!-- InstanceEndEditable --></A>
32 <a class="sectref" href="{% url 'docs' 'madIntroduction.html' %}"><!-- InstanceBeginEditable name="PreviousTitle" -->Brief History <!-- InstanceEndEditable --></A>
33 <b class="navlabel">&nbsp;&nbsp;Up:</b>
33 <b class="navlabel">&nbsp;&nbsp;Up:</b>
34 <a class="sectref" href="{% url 'docs' 'madContents.html' %}"><!-- InstanceBeginEditable name="UpTitle" -->Doc home <!-- InstanceEndEditable --></A>
34 <a class="sectref" href="{% url 'docs' 'madContents.html' %}"><!-- InstanceBeginEditable name="UpTitle" -->Doc home <!-- InstanceEndEditable --></A>
35 <b class="navlabel">&nbsp;&nbsp;Next:</b>
35 <b class="navlabel">&nbsp;&nbsp;Next:</b>
36 <a class="sectref" href="{% url 'docs' 'wt_usersGuide.html' %}"><!-- InstanceBeginEditable name="NextTitle" -->Madrigal user's guide <!-- InstanceEndEditable --></A></div>
36 <a class="sectref" href="{% url 'docs' 'wt_usersGuide.html' %}"><!-- InstanceBeginEditable name="NextTitle" -->Madrigal user's guide <!-- InstanceEndEditable --></A></div>
37 <hr/>
37 <hr/>
38 <!-- InstanceBeginEditable name="EditDoc" -->
38 <!-- InstanceBeginEditable name="EditDoc" -->
39
39
40 <h1 align="center">What's new in Madrigal 3.2.2?</h1>
40 <h1 align="center">What's new in Madrigal 3.2.2?</h1>
41 <h1 align="center" style="text-align: left">Madrigal 3.2.2 Release - Jan 2021</h1>
41 <h1 align="center" style="text-align: left">Madrigal 3.2.2 Release - Jan 2021</h1>
42 <p align="center" style="text-align: left">Fixed bug in linking to external data using the Select Single Experiment user interface. </p>
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 <h1 align="center">What's new in Madrigal 3.2.1?</h1>
45 <h1 align="center">What's new in Madrigal 3.2.1?</h1>
46 <h1 align="center" style="text-align: left">Madrigal 3.2.1 Release - Nov 2020</h1>
46 <h1 align="center" style="text-align: left">Madrigal 3.2.1 Release - Nov 2020</h1>
47 <h2 align="center" style="text-align: left">Allows Madrigal to create citations to groups of files</h2>
47 <h2 align="center" style="text-align: left">Allows Madrigal to create citations to groups of files</h2>
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>
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 <h1 align="center">What's new in Madrigal 3.1.1?</h1>
51 <h1 align="center">What's new in Madrigal 3.1.1?</h1>
52 <h1 align="center" style="text-align: left">Madrigal 3.1.1 Release - Nov 2019</h1>
52 <h1 align="center" style="text-align: left">Madrigal 3.1.1 Release - Nov 2019</h1>
53 <h2 align="center" style="text-align: left">Allows Madrigal to run using https</h2>
53 <h2 align="center" style="text-align: left">Allows Madrigal to run using https</h2>
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>
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 <h1 align="center">What's new in Madrigal 3.1?</h1>
56 <h1 align="center">What's new in Madrigal 3.1?</h1>
57 <h1 align="center" style="text-align: left">Madrigal 3.1 Release - Oct 2019</h1>
57 <h1 align="center" style="text-align: left">Madrigal 3.1 Release - Oct 2019</h1>
58 <h2 align="center" style="text-align: left">Conversion to Python 3</h2>
58 <h2 align="center" style="text-align: left">Conversion to Python 3</h2>
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>
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 <h1 align="center" style="text-align: left">Madrigal 3.0 Release - Sept 2017</h1>
61 <h1 align="center" style="text-align: left">Madrigal 3.0 Release - Sept 2017</h1>
62 <blockquote>
62 <blockquote>
63 <h2 align="center" style="text-align: left">Migration to Hdf5 file format</h2>
63 <h2 align="center" style="text-align: left">Migration to Hdf5 file format</h2>
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>
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 <h2 align="center" style="text-align: left">Web interface generates scripts to download any amount of data</h2>
65 <h2 align="center" style="text-align: left">Web interface generates scripts to download any amount of data</h2>
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>
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 <h2 align="center" style="text-align: left">Download files in a new format</h2>
67 <h2 align="center" style="text-align: left">Download files in a new format</h2>
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>
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 <h2 align="center" style="text-align: left">Get data with selected/derived parameters and filters in new formats</h2>
69 <h2 align="center" style="text-align: left">Get data with selected/derived parameters and filters in new formats</h2>
70 <p align="center" style="text-align: left">Prior to Madrigal 3, data with selected/derived parameters and filters was available
70 <p align="center" style="text-align: left">Prior to Madrigal 3, data with selected/derived parameters and filters was available
71 only as ascii. Now it can be downloaded as ascii, Hdf5, or netCDF4.</p>
71 only as ascii. Now it can be downloaded as ascii, Hdf5, or netCDF4.</p>
72 <h2 align="center" style="text-align: left">Independent spatial parameters now built in to data model</h2>
72 <h2 align="center" style="text-align: left">Independent spatial parameters now built in to data model</h2>
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>
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 <h2 align="center" style="text-align: left">All new web interface</h2>
74 <h2 align="center" style="text-align: left">All new web interface</h2>
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>
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 <h2 align="center" style="text-align: left">Simple FTP-like web interface added</h2>
76 <h2 align="center" style="text-align: left">Simple FTP-like web interface added</h2>
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>
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 <h2 align="center" style="text-align: left">Create CEDAR Hdf5 files with either Matlab or python</h2>
78 <h2 align="center" style="text-align: left">Create CEDAR Hdf5 files with either Matlab or python</h2>
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>
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 <h2 align="center" style="text-align: left">All metadata easily accessible</h2>
80 <h2 align="center" style="text-align: left">All metadata easily accessible</h2>
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>
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 </blockquote>
82 </blockquote>
83 <h1>Madrigal 2.6.3.2 Release - March 22, 2012</h1>
83 <h1>Madrigal 2.6.3.2 Release - March 22, 2012</h1>
84 <p>Added support to file download cgi scripts to allow logging of remote API requests to download files.</p>
84 <p>Added support to file download cgi scripts to allow logging of remote API requests to download files.</p>
85 <h1>Madrigal 2.6.3.1 Release - March 13, 2012</h1>
85 <h1>Madrigal 2.6.3.1 Release - March 13, 2012</h1>
86 <p>Added popup javascript window to warn users not to click &quot;Download File&quot; button multiple times.</p>
86 <p>Added popup javascript window to warn users not to click &quot;Download File&quot; button multiple times.</p>
87 <h1>Madrigal 2.6.3 Release - Febuary 27, 2012</h1>
87 <h1>Madrigal 2.6.3 Release - Febuary 27, 2012</h1>
88 <p>Small bug fixes in 3 cgi scripts affecting plots: madExperiment.cgi, madDataDisplay, getMadplot.py</p>
88 <p>Small bug fixes in 3 cgi scripts affecting plots: madExperiment.cgi, madDataDisplay, getMadplot.py</p>
89 <h1>Madrigal 2.6.2 Release - Febuary 8, 2012</h1>
89 <h1>Madrigal 2.6.2 Release - Febuary 8, 2012</h1>
90 <p>Small bug fix involving creating Hdf5 export files in data.py.</p>
90 <p>Small bug fix involving creating Hdf5 export files in data.py.</p>
91 <h1>Madrigal 2.6.1 Release - January 20, 2012</h1>
91 <h1>Madrigal 2.6.1 Release - January 20, 2012</h1>
92 <p>Small bug fix involving a memory leak in _Madrec.c and a rare problem creating Hdf5 export files in data.py. </p>
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 <h1>Madrigal 2.6 Release - November 2011 </h1>
93 <h1>Madrigal 2.6 Release - November 2011 </h1>
94 <blockquote>
94 <blockquote>
95 <h2>New simple local web user interface </h2>
95 <h2>New simple local web user interface </h2>
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>
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 <h2>HDF5 file download availablity</h2>
97 <h2>HDF5 file download availablity</h2>
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>
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 <h2>Users can register interest in experiments or instruments</h2>
99 <h2>Users can register interest in experiments or instruments</h2>
100 <p>Users can now register interest in experiments or instruments, and get emails whenever that Madrigal experiment or instrument is updated.</p>
100 <p>Users can now register interest in experiments or instruments, and get emails whenever that Madrigal experiment or instrument is updated.</p>
101 <h2>Administrative improvements - can now add external disks to experiments</h2>
101 <h2>Administrative improvements - can now add external disks to experiments</h2>
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>
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 <h2>New metadata - experiment PI's and analyst</h2>
103 <h2>New metadata - experiment PI's and analyst</h2>
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>
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 <h2>Global seach now more robust</h2>
105 <h2>Global seach now more robust</h2>
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>
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 <p>&nbsp;</p>
107 <p>&nbsp;</p>
108 </blockquote>
108 </blockquote>
109 <hr />
109 <hr />
110 <p>&nbsp;</p>
110 <p>&nbsp;</p>
111 <h1>Madrigal 2.5.2 Release - May 2009</h1>
111 <h1>Madrigal 2.5.2 Release - May 2009</h1>
112 <blockquote>
112 <blockquote>
113 <p>A bug fix release - no new features. </p>
113 <p>A bug fix release - no new features. </p>
114 </blockquote>
114 </blockquote>
115 <h1>Madrigal 2.5.1 Release - March 2009</h1>
115 <h1>Madrigal 2.5.1 Release - March 2009</h1>
116 <blockquote>
116 <blockquote>
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>
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 </blockquote>
118 </blockquote>
119 <h1>Madrigal 2.5 Release - February 2009 </h1>
119 <h1>Madrigal 2.5 Release - February 2009 </h1>
120 <blockquote>
120 <blockquote>
121 <h2>Simplification of Web User Interface </h2>
121 <h2>Simplification of Web User Interface </h2>
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>
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 <h2>One step file printing available</h2>
123 <h2>One step file printing available</h2>
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>
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 <h2>Installation simplified </h2>
125 <h2>Installation simplified </h2>
126 <p>Autotools is now used to compile all code, significantly reducing the number of parameters in the madrigal.cfg configuration file.</p>
126 <p>Autotools is now used to compile all code, significantly reducing the number of parameters in the madrigal.cfg configuration file.</p>
127 <h2>64-bit tested </h2>
127 <h2>64-bit tested </h2>
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>
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 <h2>International Reference Ionosphere (IRI) derived parameters now available</h2>
129 <h2>International Reference Ionosphere (IRI) derived parameters now available</h2>
130 <p>All parameters calculated by the International Reference Ionosphere (IRI) model can now be selected as derived parameters.</p>
130 <p>All parameters calculated by the International Reference Ionosphere (IRI) model can now be selected as derived parameters.</p>
131 <h2>Additional automatic sharing of metadata added</h2>
131 <h2>Additional automatic sharing of metadata added</h2>
132 <p>For administrators: Now when new sites or instruments are added to Madrigal, these metadata files are automatically added to your site. </p>
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 <h2>Experiment level security</h2>
133 <h2>Experiment level security</h2>
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>
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 <h2>Experiment directory naming convention modified </h2>
135 <h2>Experiment directory naming convention modified </h2>
136 <p>Previous to Madrigal 2.5, all Madrigal experiments had to be stored in directory paths in the form:</p>
136 <p>Previous to Madrigal 2.5, all Madrigal experiments had to be stored in directory paths in the form:</p>
137 <pre>$MADROOT/experiments/YYYY/&lt;3 letter inst mnemonic&gt;/ddMMMyy[letter],
137 <pre>$MADROOT/experiments/YYYY/&lt;3 letter inst mnemonic&gt;/ddMMMyy[letter],
138 Example: /opt/madrigal/experiments/1998/mlh/20jan98b.</pre>
138 Example: /opt/madrigal/experiments/1998/mlh/20jan98b.</pre>
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>
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 <pre>$MADROOT/experiments/YYYY/&lt;3 letter inst mnemonic&gt;/*,
140 <pre>$MADROOT/experiments/YYYY/&lt;3 letter inst mnemonic&gt;/*,
141 Example: /opt/madrigal/experiments/1998/mlh/mlh_exp_234.
141 Example: /opt/madrigal/experiments/1998/mlh/mlh_exp_234.
142 </pre>
142 </pre>
143 </blockquote>
143 </blockquote>
144
144
145 <hr />
145 <hr />
146 <h1>Madrigal 2.4 Release - February 2006 </h1>
146 <h1>Madrigal 2.4 Release - February 2006 </h1>
147 <blockquote>
147 <blockquote>
148 <h2>Simple web UI added</h2>
148 <h2>Simple web UI added</h2>
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>
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 <h2>On-demand plot creation</h2>
150 <h2>On-demand plot creation</h2>
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>
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 <h2>Logging of user data access</h2>
152 <h2>Logging of user data access</h2>
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>
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 <h2>Automatic updating of all geophysical data</h2>
154 <h2>Automatic updating of all geophysical data</h2>
155 <p>Madrigal now automatically updates all its internal geophysical files (e.g., Kp, Fof2, Dst, Imf, etc) every time updateMaster is run. </p>
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 <h2>Simple-to-use python module to create and edit Madrigal files</h2>
156 <h2>Simple-to-use python module to create and edit Madrigal files</h2>
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>
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 <h2>New administrative scripts to manage Madrigal experiments</h2>
158 <h2>New administrative scripts to manage Madrigal experiments</h2>
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>
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 <h2>Complete documentation rewrite</h2>
160 <h2>Complete documentation rewrite</h2>
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>
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 <h2>Automatic graphics conversion</h2>
162 <h2>Automatic graphics conversion</h2>
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>
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 <h2>Update of IGRF/MSIS</h2>
164 <h2>Update of IGRF/MSIS</h2>
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>
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 <h2>Limiting of disk space used for global search files</h2>
166 <h2>Limiting of disk space used for global search files</h2>
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>
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 </blockquote>
168 </blockquote>
169 <p>&nbsp;</p>
169 <p>&nbsp;</p>
170 <hr />
170 <hr />
171 <p>&nbsp;</p>
171 <p>&nbsp;</p>
172 <h1>Madrigal 2.3 Release - March 2004</h1>
172 <h1>Madrigal 2.3 Release - March 2004</h1>
173
173
174 <blockquote>
174 <blockquote>
175 <h2>Remote programming access to Madrigal via web services using any platform</h2>
175 <h2>Remote programming access to Madrigal via web services using any platform</h2>
176 <p>Madrigal now exposes all the information and capabilities it has as web services, which allows
176 <p>Madrigal now exposes all the information and capabilities it has as web services, which allows
177 easy access to Madrigal from any computer on the internet using any platform (Unix, Windows, Mac, etc).
177 easy access to Madrigal from any computer on the internet using any platform (Unix, Windows, Mac, etc).
178 Madrigal's web services are basically cgi scripts with simple output that allows easy parsing of the
178 Madrigal's web services are basically cgi scripts with simple output that allows easy parsing of the
179 information. Any language that supports the HTTP standard can then access any Madrigal site. We have
179 information. Any language that supports the HTTP standard can then access any Madrigal site. We have
180 written remote API's using python and Matlab, but almost any language could be used. See the section
180 written remote API's using python and Matlab, but almost any language could be used. See the section
181 on <a href="{% url 'docs' 'rt_contents.html' %}">remote programming access</a> for details of these APIs and the underlying web services.</p>
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 <p>Note that this approach of remotely accessing Madrigal data has been always possible before by parsing the
182 <p>Note that this approach of remotely accessing Madrigal data has been always possible before by parsing the
183 html output meant to be displayed in a web browser (this general programming method is referred to as "screen
183 html output meant to be displayed in a web browser (this general programming method is referred to as "screen
184 scraping"). However, not only is this parsing difficult; but the code often breaks when the user interface
184 scraping"). However, not only is this parsing difficult; but the code often breaks when the user interface
185 is modified in any way. With web services the returned cgi scripts are designed to be both simple to parse
185 is modified in any way. With web services the returned cgi scripts are designed to be both simple to parse
186 and stable.</p>
186 and stable.</p>
187 <p>The web services are not implemented according to the SOAP or XMLRPC standard since not all scripting
187 <p>The web services are not implemented according to the SOAP or XMLRPC standard since not all scripting
188 languages have support for these standards (or for XML parsing). Instead they use the simple approach
188 languages have support for these standards (or for XML parsing). Instead they use the simple approach
189 of returning data requested via a query as a delimited text file. These web services are fully
189 of returning data requested via a query as a delimited text file. These web services are fully
190 documented <a href="{% url 'docs' 'rt_webServices.html' %}">here.</a></p>
190 documented <a href="{% url 'docs' 'rt_webServices.html' %}">here.</a></p>
191 <p>Users who want only to write programs to remotely access Madrigal, and not to install a Madrigal server
191 <p>Users who want only to write programs to remotely access Madrigal, and not to install a Madrigal server
192 themselves, are now able to <a href="http://www.haystack.mit.edu/madrigal/madDownload.html"> download </a>
192 themselves, are now able to <a href="http://www.haystack.mit.edu/madrigal/madDownload.html"> download </a>
193 the remote python and Matlab API's from the
193 the remote python and Matlab API's from the
194 <a href="http://www.openmadrigal.org">OpenMadrigal</a> site.</p>
194 <a href="http://www.openmadrigal.org">OpenMadrigal</a> site.</p>
195 <h2> Command-line global search</h2>
195 <h2> Command-line global search</h2>
196 <p>As an example of remote programming access to Madrigal via web services, an application
196 <p>As an example of remote programming access to Madrigal via web services, an application
197 <a href="rt_python.html#globalIsprint">globalIsprint</a> was written
197 <a href="rt_python.html#globalIsprint">globalIsprint</a> was written
198 using the python remote API that does a global search of data on any Madrigal site that has installed Madrigal version
198 using the python remote API that does a global search of data on any Madrigal site that has installed Madrigal version
199 2.3. This application is installed as part of Madrigal, and also when the standalone remote python
199 2.3. This application is installed as part of Madrigal, and also when the standalone remote python
200 API is installed. It has all the filtering ability of the web-based global search.</p>
200 API is installed. It has all the filtering ability of the web-based global search.</p>
201 <h2>Calculate any derivable Madrigal parameter for any time and point(s) in space</h2>
201 <h2>Calculate any derivable Madrigal parameter for any time and point(s) in space</h2>
202 <p>By clicking on "Run Models", users can calculate any derived Madrigal parameter (such as magnetic fields,
202 <p>By clicking on "Run Models", users can calculate any derived Madrigal parameter (such as magnetic fields,
203 or geophysical parameters) for arbitrary times and ranges of position. Note that this capability is also
203 or geophysical parameters) for arbitrary times and ranges of position. Note that this capability is also
204 available as a web service, and through the remote python and Matlab API's.</p>
204 available as a web service, and through the remote python and Matlab API's.</p>
205 <h2>New derived parameters</h2>
205 <h2>New derived parameters</h2>
206 <ul>
206 <ul>
207 <li>
207 <li>
208 CGM_LAT: <b>Corrected geomagnetic latitude</b> (deg) <br>
208 CGM_LAT: <b>Corrected geomagnetic latitude</b> (deg) <br>
209 This parameter gives the location of a point in Corrected geomagnetic latitude.
209 This parameter gives the location of a point in Corrected geomagnetic latitude.
210 This method uses code developed by Vladimir Papitashvili. For more information on CGM coordinates
210 This method uses code developed by Vladimir Papitashvili. For more information on CGM coordinates
211 and this code, click <a href="https://omniweb.gsfc.nasa.gov/vitmo/cgmm_des.html"> here.</a></li>
211 and this code, click <a href="https://omniweb.gsfc.nasa.gov/vitmo/cgmm_des.html"> here.</a></li>
212 <li>
212 <li>
213 CGM_LONG: <b>Corrected geomagnetic longitude</b> (deg) <br>
213 CGM_LONG: <b>Corrected geomagnetic longitude</b> (deg) <br>
214 This parameter gives the location of a point in Corrected geomagnetic longitude.
214 This parameter gives the location of a point in Corrected geomagnetic longitude.
215 This method uses code developed by Vladimir Papitashvili. For more information on CGM coordinates
215 This method uses code developed by Vladimir Papitashvili. For more information on CGM coordinates
216 and this code, click <a href="https://omniweb.gsfc.nasa.gov/vitmo/cgmm_des.html"> here.</a></li>
216 and this code, click <a href="https://omniweb.gsfc.nasa.gov/vitmo/cgmm_des.html"> here.</a></li>
217 <li>
217 <li>
218 TSYG_EQ_XGSM: <b>Tsyganenko field GSM XY plane X point</b> (earth radii) <br>
218 TSYG_EQ_XGSM: <b>Tsyganenko field GSM XY plane X point</b> (earth radii) <br>
219 This parameter gives the X value in GSM coordinates of where the field line associated
219 This parameter gives the X value in GSM coordinates of where the field line associated
220 with a given input point in space and time crosses the GSM XY plane (the magnetic equatorial plane). GSM stands for
220 with a given input point in space and time crosses the GSM XY plane (the magnetic equatorial plane). GSM stands for
221 Geocentric Solar Magnetospheric System, and its XY plane is the equatorial plane of
221 Geocentric Solar Magnetospheric System, and its XY plane is the equatorial plane of
222 the earth's magnetic dipole field. The field lines are traced using the
222 the earth's magnetic dipole field. The field lines are traced using the
223 Tsyganenko
223 Tsyganenko
224 Magnetospheric model, so external effects on the earth's magnetic field such the solar wind are
224 Magnetospheric model, so external effects on the earth's magnetic field such the solar wind are
225 taken into account. This code uses the 2001 Tsyganenko model, which averages solar wind values
225 taken into account. This code uses the 2001 Tsyganenko model, which averages solar wind values
226 over the past hour, instead of simply using present values.</li>
226 over the past hour, instead of simply using present values.</li>
227 <li> TSYG_EQ_YGSM: <b>Tsyganenko field GSM XY plane Y point</b> (earth radii) <br>
227 <li> TSYG_EQ_YGSM: <b>Tsyganenko field GSM XY plane Y point</b> (earth radii) <br>
228 This parameter gives the Y value in GSM coordinates of where the field line associated
228 This parameter gives the Y value in GSM coordinates of where the field line associated
229 with a given input point in space and time crosses the GSM XY plane (the magnetic equatorial plane). GSM stands for
229 with a given input point in space and time crosses the GSM XY plane (the magnetic equatorial plane). GSM stands for
230 Geocentric Solar Magnetospheric System, and its XY plane is the equatorial plane of
230 Geocentric Solar Magnetospheric System, and its XY plane is the equatorial plane of
231 the earth's magnetic dipole field. The field lines are traced using the Tsyganenko
231 the earth's magnetic dipole field. The field lines are traced using the Tsyganenko
232 Magnetospheric model, so external effects on the earth's magnetic field such the solar wind are
232 Magnetospheric model, so external effects on the earth's magnetic field such the solar wind are
233 taken into account. This code uses the 2001 Tsyganenko model, which averages solar wind values
233 taken into account. This code uses the 2001 Tsyganenko model, which averages solar wind values
234 over the past hour, instead of simply using present values.</li>
234 over the past hour, instead of simply using present values.</li>
235 <li> TSYG_EQ_XGSM: <b>Tsyganenko field GSE XY plane X point</b> (earth radii) <br>
235 <li> TSYG_EQ_XGSM: <b>Tsyganenko field GSE XY plane X point</b> (earth radii) <br>
236 This parameter gives the X value in GSE coordinates of where the field line associated
236 This parameter gives the X value in GSE coordinates of where the field line associated
237 with a given input point in space and time crosses the GSE XY plane (the equatorial plane). GSE stands for
237 with a given input point in space and time crosses the GSE XY plane (the equatorial plane). GSE stands for
238 Geocentric Solar Ecliptic System, and its XY plane is the equatorial plane of
238 Geocentric Solar Ecliptic System, and its XY plane is the equatorial plane of
239 the earth's rotation. The field lines are traced using the Tsyganenko
239 the earth's rotation. The field lines are traced using the Tsyganenko
240 Magnetospheric model, so external effects on the earth's magnetic field such the solar wind are
240 Magnetospheric model, so external effects on the earth's magnetic field such the solar wind are
241 taken into account. This code uses the 2001 Tsyganenko model, which averages solar wind values
241 taken into account. This code uses the 2001 Tsyganenko model, which averages solar wind values
242 over the past hour, instead of simply using present values.</li>
242 over the past hour, instead of simply using present values.</li>
243 <li> TSYG_EQ_YGSM: <b>Tsyganenko field GSE XY plane Y point</b> (earth radii) <br>
243 <li> TSYG_EQ_YGSM: <b>Tsyganenko field GSE XY plane Y point</b> (earth radii) <br>
244 This parameter gives the Y value in GSE coordinates of where the field line associated
244 This parameter gives the Y value in GSE coordinates of where the field line associated
245 with a given input point in space and time crosses the GSE XY plane (the equatorial plane). GSE stands for
245 with a given input point in space and time crosses the GSE XY plane (the equatorial plane). GSE stands for
246 Geocentric Solar Ecliptic System, and its XY plane is the equatorial plane of
246 Geocentric Solar Ecliptic System, and its XY plane is the equatorial plane of
247 the earth's rotation. The field lines are traced using the Tsyganenko
247 the earth's rotation. The field lines are traced using the Tsyganenko
248 Magnetospheric model, so external effects on the earth's magnetic field such the solar wind are
248 Magnetospheric model, so external effects on the earth's magnetic field such the solar wind are
249 taken into account. This code uses the 2001 Tsyganenko model, which averages solar wind values
249 taken into account. This code uses the 2001 Tsyganenko model, which averages solar wind values
250 over the past hour, instead of simply using present values.</li>
250 over the past hour, instead of simply using present values.</li>
251 <li> BHHMMSS and EHHMMSS: <b>Start and end time in HHMMSS</b> (suggested by Mary McCready at SRI)</li>
251 <li> BHHMMSS and EHHMMSS: <b>Start and end time in HHMMSS</b> (suggested by Mary McCready at SRI)</li>
252 </ul>
252 </ul>
253 <h2>Bug fixes</h2>
253 <h2>Bug fixes</h2>
254 <p>The Madrigal C API now no longer aborts when a Cedar file contains cycle marks (Cedar
254 <p>The Madrigal C API now no longer aborts when a Cedar file contains cycle marks (Cedar
255 parameter 95) that are not in order. (Reported by Angela Li, SRI)</p>
255 parameter 95) that are not in order. (Reported by Angela Li, SRI)</p>
256 <p>A problem launching the global search with the python module os.spawnlp was fixed.
256 <p>A problem launching the global search with the python module os.spawnlp was fixed.
257 (Reported by Angela Li, SRI)</p>
257 (Reported by Angela Li, SRI)</p>
258 </blockquote>
258 </blockquote>
259 <p>&nbsp;</p>
259 <p>&nbsp;</p>
260 <hr></hr>
260 <hr></hr>
261 <h1>
261 <h1>
262 Madrigal 2.2 Release - Feb 2003</h1>
262 Madrigal 2.2 Release - Feb 2003</h1>
263
263
264
264
265 <blockquote>
265 <blockquote>
266 <h2>New derived parameters</h2>
266 <h2>New derived parameters</h2>
267 <ul>
267 <ul>
268 <li>
268 <li>
269 SUNRISE_HOUR - <b>Ionospheric sunrise</b> (hour)<br>
269 SUNRISE_HOUR - <b>Ionospheric sunrise</b> (hour)<br>
270 This parameter gives the hour UT that sunrise occurs at that particular
270 This parameter gives the hour UT that sunrise occurs at that particular
271 point in space that particular day. If that point in space is either in sunlight or in shadow
271 point in space that particular day. If that point in space is either in sunlight or in shadow
272 the entire UT day, sunrise_hour will be missing. To find out which, display the
272 the entire UT day, sunrise_hour will be missing. To find out which, display the
273 Shadow height (SDWHT) parameter. If shadow height is less that the altitude of the
273 Shadow height (SDWHT) parameter. If shadow height is less that the altitude of the
274 point, its in sunlight; if shadow height is greater than the altitude, its in the earth's shadow.</li>
274 point, its in sunlight; if shadow height is greater than the altitude, its in the earth's shadow.</li>
275 <li>SUNSET_HOUR - <b>Ionospheric sunset</b> (hour)<br>
275 <li>SUNSET_HOUR - <b>Ionospheric sunset</b> (hour)<br>
276 This parameter gives the hour UT that sunset occurs at that particular
276 This parameter gives the hour UT that sunset occurs at that particular
277 point in space that particular day. If that point in space is either in sunlight or in shadow
277 point in space that particular day. If that point in space is either in sunlight or in shadow
278 the entire UT day, sunset_hour will be missing. To find out which, display the
278 the entire UT day, sunset_hour will be missing. To find out which, display the
279 Shadow height (SDWHT) parameter. If shadow height is less that the altitude of the
279 Shadow height (SDWHT) parameter. If shadow height is less that the altitude of the
280 point, its in sunlight; if shadow height is greater than the altitude, its in the earth's shadow.</li>
280 point, its in sunlight; if shadow height is greater than the altitude, its in the earth's shadow.</li>
281 <li>CONJ_SUNRISE_H - <b>Magnetic conjugate point sunrise</b> (hour)<br>
281 <li>CONJ_SUNRISE_H - <b>Magnetic conjugate point sunrise</b> (hour)<br>
282 This parameter gives the hour UT that sunrise occurs at the magnetic conjugate point of the particular
282 This parameter gives the hour UT that sunrise occurs at the magnetic conjugate point of the particular
283 point in space that particular day.</li>
283 point in space that particular day.</li>
284 <li>CONJ_SUNSET_H - <b>Magnetic conjugate point sunset</b> (hour)<br>
284 <li>CONJ_SUNSET_H - <b>Magnetic conjugate point sunset</b> (hour)<br>
285 This parameter gives the hour UT that sunset occurs at the magnetic conjugate point of the particular
285 This parameter gives the hour UT that sunset occurs at the magnetic conjugate point of the particular
286 point in space that particular day.</li>
286 point in space that particular day.</li>
287 <li>SZEN - <b>Solar zenith angle in measurement vol</b> (deg) <br>
287 <li>SZEN - <b>Solar zenith angle in measurement vol</b> (deg) <br>
288 This parameter gives the solar zenith angle in degrees. If 0 degrees, the sun is directly
288 This parameter gives the solar zenith angle in degrees. If 0 degrees, the sun is directly
289 overhead. A solar zenith angle of between 90 and 180 degrees does not mean the sun is not
289 overhead. A solar zenith angle of between 90 and 180 degrees does not mean the sun is not
290 visible, due to the finite solid angle of the sun and the altitude the point may be above the
290 visible, due to the finite solid angle of the sun and the altitude the point may be above the
291 earth's surface.</li>
291 earth's surface.</li>
292 <li>SZENC - <b>Conjugate solar zenith angle</b> (deg) <br>
292 <li>SZENC - <b>Conjugate solar zenith angle</b> (deg) <br>
293 This parameter gives the solar zenith angle at the magnetic conjugate point in degrees.</li>
293 This parameter gives the solar zenith angle at the magnetic conjugate point in degrees.</li>
294 <li>SDWHT - <b>Shadow height</b> (km) <br>
294 <li>SDWHT - <b>Shadow height</b> (km) <br>
295 This parameter gives the height above the earth's surface at which any part of the sun can be seen. It depends only
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 on the time, and on the geodetic latitude and longitude. During the day shadow height will be zero. Since the sun is
296 on the time, and on the geodetic latitude and longitude. During the day shadow height will be zero. Since the sun is
297 larger than the earth, the shadow height is always finite. If shadow height is less that the altitude of a given
297 larger than the earth, the shadow height is always finite. If shadow height is less that the altitude of a given
298 point in space, its in sunlight; if shadow height is greater than the altitude, its in the earth's shadow.</li>
298 point in space, its in sunlight; if shadow height is greater than the altitude, its in the earth's shadow.</li>
299 <li>MAGCONJSDWHT - <b>Magnetic conjugate shadow height</b> (km) <br>
299 <li>MAGCONJSDWHT - <b>Magnetic conjugate shadow height</b> (km) <br>
300 This parameter gives the height above the earth's surface at the magnetic conjugate point's latitude and longitude at
300 This parameter gives the height above the earth's surface at the magnetic conjugate point's latitude and longitude at
301 which any part of the sun can be seen. </li>
301 which any part of the sun can be seen. </li>
302 <li><b>10 Interplanetary Magnetic Field parameters</b><br>
302 <li><b>10 Interplanetary Magnetic Field parameters</b><br>
303 Includes field strength in GSM or GSE coordinates, solar wind plasma density, speed, and measuring satellite id.
303 Includes field strength in GSM or GSE coordinates, solar wind plasma density, speed, and measuring satellite id.
304 Click on any parameter to see the definition of the two coordinate systems.</li>
304 Click on any parameter to see the definition of the two coordinate systems.</li>
305 </ul>
305 </ul>
306 <h2>Filtering using any parameter</h2>
306 <h2>Filtering using any parameter</h2>
307 <ul>
307 <ul>
308 <li>There are now also free-form filters at the end
308 <li>There are now also free-form filters at the end
309 of the filter section, which allow you to set up filters based on any
309 of the filter section, which allow you to set up filters based on any
310 single parameter or on two parameters either added,
310 single parameter or on two parameters either added,
311 subtracted, multiplied, or divided together. For example, you can now filter on
311 subtracted, multiplied, or divided together. For example, you can now filter on
312 Ti, the ratio Ti/dTi, or gdalt-sdwht (which is positive if the point is in sunlight).
312 Ti, the ratio Ti/dTi, or gdalt-sdwht (which is positive if the point is in sunlight).
313 See the tutorial for more details.</li>
313 See the tutorial for more details.</li>
314 </ul>
314 </ul>
315 <h2>Better help understanding what each parameter means</h2>
315 <h2>Better help understanding what each parameter means</h2>
316 <ul>
316 <ul>
317 <li>Complex parameters now have full html descriptions accessible from the isprint page.
317 <li>Complex parameters now have full html descriptions accessible from the isprint page.
318 Just click on the parameter name and you'll see the short description. For more complex
318 Just click on the parameter name and you'll see the short description. For more complex
319 parameters you'll also see a link to a more detailed explanation.</li>
319 parameters you'll also see a link to a more detailed explanation.</li>
320 </ul>
320 </ul>
321 <h2>Improved data output</h2>
321 <h2>Improved data output</h2>
322 <ul>
322 <ul>
323 <li>If you select only 1D parameters, or derived parameters that depend only on other 1D parameters,
323 <li>If you select only 1D parameters, or derived parameters that depend only on other 1D parameters,
324 isprint will only print a single line per record, making it easier to read.</li>
324 isprint will only print a single line per record, making it easier to read.</li>
325 <li>All filters used are printed at the beginning of the report. Trivial filters that don't exclude
325 <li>All filters used are printed at the beginning of the report. Trivial filters that don't exclude
326 data (such as elevation from 0 to 90 degrees) are ignored.</li>
326 data (such as elevation from 0 to 90 degrees) are ignored.</li>
327 </ul>
327 </ul>
328 <h2>Better consistency with Cedar standard</h2>
328 <h2>Better consistency with Cedar standard</h2>
329 <ul>
329 <ul>
330 <li>All units are now consistent with the Cedar standard (when displaying Cedar parameters).</li>
330 <li>All units are now consistent with the Cedar standard (when displaying Cedar parameters).</li>
331 <li>The special Cedar values "missing", "assumed", and "known bad" are differentiated in isprint output,
331 <li>The special Cedar values "missing", "assumed", and "known bad" are differentiated in isprint output,
332 and not all lumped together as "missing" as before.</li>
332 and not all lumped together as "missing" as before.</li>
333 <li>Unknown parameter codes displayed with a scale factor of 1.0.</li>
333 <li>Unknown parameter codes displayed with a scale factor of 1.0.</li>
334 </ul>
334 </ul>
335 <h2>New derived parameters are simple to add</h2>
335 <h2>New derived parameters are simple to add</h2>
336 <ul>
336 <ul>
337 <li>The isprint web page is now based on the madc library, and has been designed to
337 <li>The isprint web page is now based on the madc library, and has been designed to
338 make it extremely simple to add new derived parameters. See the
338 make it extremely simple to add new derived parameters. See the
339 madc API documentation for details.</li>
339 madc API documentation for details.</li>
340 </ul>
340 </ul>
341 </blockquote>
341 </blockquote>
342 <!-- InstanceEndEditable -->
342 <!-- InstanceEndEditable -->
343 <table width="100%" border="1" cellpadding="0" cellspacing="2" class="navigation">
343 <table width="100%" border="1" cellpadding="0" cellspacing="2" class="navigation">
344 <tr>
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>
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="/static/up.png" alt="up" 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="/static/next.png" alt="next" 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 <td width="54%"><!-- InstanceBeginEditable name="EditTitleBottom" -->What's new in Madrigal 3.0?<!-- InstanceEndEditable --></td>
348 <td width="54%"><!-- InstanceBeginEditable name="EditTitleBottom" -->What's new in Madrigal 3.0?<!-- InstanceEndEditable --></td>
349 <td width="13%"><a href="{% url 'docs' 'madContents.html' %}">Doc home </a></td>
349 <td width="13%"><a href="{% url 'docs' 'madContents.html' %}">Doc home </a></td>
350 <td width="18%"><a href="/">Madrigal home</a></td>
350 <td width="18%"><a href="/">Madrigal home</a></td>
351 </tr>
351 </tr>
352 </table>
352 </table>
353 <div class='online-navigation'>
353 <div class='online-navigation'>
354 <b class="navlabel">Previous:</b>
354 <b class="navlabel">Previous:</b>
355 <a class="sectref" href="{% url 'docs' 'madIntroduction.html' %}"><!-- InstanceBeginEditable name="PreviousTitle2" -->Brief History <!-- InstanceEndEditable --></A>
355 <a class="sectref" href="{% url 'docs' 'madIntroduction.html' %}"><!-- InstanceBeginEditable name="PreviousTitle2" -->Brief History <!-- InstanceEndEditable --></A>
356 <b class="navlabel">&nbsp;&nbsp;Up:</b>
356 <b class="navlabel">&nbsp;&nbsp;Up:</b>
357 <a class="sectref" href="{% url 'docs' 'madContents.html' %}"><!-- InstanceBeginEditable name="UpTitle2" -->Doc home <!-- InstanceEndEditable --></A>
357 <a class="sectref" href="{% url 'docs' 'madContents.html' %}"><!-- InstanceBeginEditable name="UpTitle2" -->Doc home <!-- InstanceEndEditable --></A>
358 <b class="navlabel">&nbsp;&nbsp;Next:</b>
358 <b class="navlabel">&nbsp;&nbsp;Next:</b>
359 <a class="sectref" href="{% url 'docs' 'wt_usersGuide.html' %}"><!-- InstanceBeginEditable name="NextTitle2" -->Madrigal user's guide <!-- InstanceEndEditable --></A></div>
359 <a class="sectref" href="{% url 'docs' 'wt_usersGuide.html' %}"><!-- InstanceBeginEditable name="NextTitle2" -->Madrigal user's guide <!-- InstanceEndEditable --></A></div>
360 <hr/>
360 <hr/>
361 <p>&nbsp;</p>
361 <p>&nbsp;</p>
362 </body>
362 </body>
363 <!-- InstanceEnd --></html>
363 <!-- InstanceEnd --></html>
@@ -1,242 +1,241
1 '''
1 '''
2 Created on Jul 16, 2013
2 Created on Jul 16, 2013
3
3
4 @author: Jose Antonio Sal y Rosas Celi
4 @author: Jose Antonio Sal y Rosas Celi
5 @contact: arturo.jasyrc@gmail.com
5 @contact: arturo.jasyrc@gmail.com
6
6
7 As imported and slightly modified by Bill Rideout Jan 20, 2015
7 As imported and slightly modified by Bill Rideout Jan 20, 2015
8
8
9 $Id: urls.py 7246 2020-10-12 14:54:26Z brideout $
9 $Id: urls.py 7246 2020-10-12 14:54:26Z brideout $
10 '''
10 '''
11
11
12 from django.conf.urls import url
12 from django.conf.urls import url
13 from . import views
13 from . import views
14
14
15 urlpatterns = [ url(r'^$',
15 urlpatterns = [ url(r'^$',
16 views.index,
16 views.index,
17 name='index'),
17 name='index'),
18 url(r'^index.html/?$',
18 url(r'^index.html/?$',
19 views.index,
19 views.index,
20 name='index'),
20 name='index'),
21 url(r'^single/?$',
21 url(r'^single/?$',
22 views.check_registration(views.view_single),
22 views.check_registration(views.view_single),
23 name='view_single'),
23 name='view_single'),
24 url(r'^register/?$',
24 url(r'^register/?$',
25 views.view_registration,
25 views.view_registration,
26 name='view_registration'),
26 name='view_registration'),
27 url(r'^getCategories/?$',
27 url(r'^getCategories/?$',
28 views.get_categories,
28 views.get_categories,
29 name='get_categories'),
29 name='get_categories'),
30 url(r'^getInstruments/?$',
30 url(r'^getInstruments/?$',
31 views.get_instruments,
31 views.get_instruments,
32 name='get_instruments'),
32 name='get_instruments'),
33 url(r'^getYears/?$',
33 url(r'^getYears/?$',
34 views.get_years,
34 views.get_years,
35 name='get_years'),
35 name='get_years'),
36 url(r'^getMonths/?$',
36 url(r'^getMonths/?$',
37 views.get_months,
37 views.get_months,
38 name='get_months'),
38 name='get_months'),
39 url(r'^getCalendar/?$',
39 url(r'^getCalendar/?$',
40 views.get_calendar,
40 views.get_calendar,
41 name='get_calendar'),
41 name='get_calendar'),
42 url(r'^populateCalendarExperiment/?$',
42 url(r'^populateCalendarExperiment/?$',
43 views.populate_calendar_experiment,
43 views.populate_calendar_experiment,
44 name='populate_calendar_experiment'),
44 name='populate_calendar_experiment'),
45 url(r'^getFiles/?$',
45 url(r'^getFiles/?$',
46 views.get_files,
46 views.get_files,
47 name='get_files'),
47 name='get_files'),
48 url(r'^changeFiles/?$',
48 url(r'^changeFiles/?$',
49 views.change_files,
49 views.change_files,
50 name='change_files'),
50 name='change_files'),
51 url(r'^showPlots/?$',
51 url(r'^showPlots/?$',
52 views.show_plots,
52 views.show_plots,
53 name='show_plots'),
53 name='show_plots'),
54 url(r'^view_plot/?$',
54 url(r'^view_plot/?$',
55 views.view_plot,
55 views.view_plot,
56 name='plot'),
56 name='plot'),
57 url(r'^downloadAsIs/?$',
57 url(r'^downloadAsIs/?$',
58 views.download_as_is,
58 views.download_as_is,
59 name='download_as_is'),
59 name='download_as_is'),
60 url(r'^downloadFileAsIs/?$',
60 url(r'^downloadFileAsIs/?$',
61 views.download_file_as_is,
61 views.download_file_as_is,
62 name='download_file_as_is'),
62 name='download_file_as_is'),
63 url(r'^printAsIs/?$',
63 url(r'^printAsIs/?$',
64 views.print_as_is,
64 views.print_as_is,
65 name='print_as_is'),
65 name='print_as_is'),
66 url(r'^listRecords/?$',
66 url(r'^listRecords/?$',
67 views.list_records,
67 views.list_records,
68 name='list_records'),
68 name='list_records'),
69 url(r'^showInfo/?$',
69 url(r'^showInfo/?$',
70 views.show_info,
70 views.show_info,
71 name='show_info'),
71 name='show_info'),
72 url(r'^showDoi/?$',
72 url(r'^showDoi/?$',
73 views.show_doi,
73 views.show_doi,
74 name='show_doi'),
74 name='show_doi'),
75 url(r'^getAdvanced/?$',
75 url(r'^getAdvanced/?$',
76 views.get_advanced,
76 views.get_advanced,
77 name='get_advanced'),
77 name='get_advanced'),
78 url(r'^advancedDownload/?$',
78 url(r'^advancedDownload/?$',
79 views.advanced_download,
79 views.advanced_download,
80 name='advanced_download'),
80 name='advanced_download'),
81 url(r'^advancedPrint/?$',
81 url(r'^advancedPrint/?$',
82 views.advanced_print,
82 views.advanced_print,
83 name='advanced_print'),
83 name='advanced_print'),
84 url(r'^list/?$',
84 url(r'^list/?$',
85 views.check_registration(views.view_list),
85 views.check_registration(views.view_list),
86 name='view_list'),
86 name='view_list'),
87 url(r'^downloadAsIsScript/?$',
87 url(r'^downloadAsIsScript/?$',
88 views.download_as_is_script,
88 views.download_as_is_script,
89 name='download_as_is_script'),
89 name='download_as_is_script'),
90 url(r'^generateDownloadFilesScript/?$',
90 url(r'^generateDownloadFilesScript/?$',
91 views.generate_download_files_script,
91 views.generate_download_files_script,
92 name='generate_download_files_script'),
92 name='generate_download_files_script'),
93 url(r'^downloadAdvancedScript/?$',
93 url(r'^downloadAdvancedScript/?$',
94 views.download_advanced_script,
94 views.download_advanced_script,
95 name='download_advanced_script'),
95 name='download_advanced_script'),
96 url(r'^generateDownloadAdvancedScript/?$',
96 url(r'^generateDownloadAdvancedScript/?$',
97 views.generate_download_advanced_script,
97 views.generate_download_advanced_script,
98 name='generate_download_advanced_script'),
98 name='generate_download_advanced_script'),
99 url(r'^generateParmsScript/?$',
99 url(r'^generateParmsScript/?$',
100 views.generate_parms_script,
100 views.generate_parms_script,
101 name='generate_parms_script'),
101 name='generate_parms_script'),
102 url(r'^generateParmsFiltersScript/?$',
102 url(r'^generateParmsFiltersScript/?$',
103 views.generate_parms_filters_script,
103 views.generate_parms_filters_script,
104 name='generate_parms_filters_script'),
104 name='generate_parms_filters_script'),
105 url(r'^listExperiments/?$',
105 url(r'^listExperiments/?$',
106 views.list_experiments,
106 views.list_experiments,
107 name='list_experiments'),
107 name='list_experiments'),
108 url(r'^viewRecordPlot/?$',
108 url(r'^viewRecordPlot/?$',
109 views.view_record_plot,
109 views.view_record_plot,
110 name='view_record_plot'),
110 name='view_record_plot'),
111 url(r'^viewRecordImage/?$',
111 url(r'^viewRecordImage/?$',
112 views.view_record_image,
112 views.view_record_image,
113 name='view_record_image'),
113 name='view_record_image'),
114 url(r'^showExperiment/?$',
114 url(r'^showExperiment/?$',
115 views.check_registration(views.show_experiment),
115 views.check_registration(views.show_experiment),
116 name='show_experiment'),
116 name='show_experiment'),
117 url(r'^madExperiment.cgi/*$',
117 url(r'^madExperiment.cgi/*$',
118 views.check_registration(views.show_experiment_v2),
118 views.check_registration(views.show_experiment_v2),
119 name='show_experiment_v2'),
119 name='show_experiment_v2'),
120 url(r'^chooseScript/?$',
120 url(r'^chooseScript/?$',
121 views.check_registration(views.choose_script),
121 views.check_registration(views.choose_script),
122 name='choose_script'),
122 name='choose_script'),
123 url(r'^ftp/$',
123 url(r'^ftp/$',
124 views.check_registration(views.ftp),
124 views.check_registration(views.ftp),
125 name='ftp'),
125 name='ftp'),
126 url(r'^ftp/fullname/([^/]+)/email/([^/]+)/affiliation/([^/]+)/kinst/(\d+)/$',
126 url(r'^ftp/fullname/([^/]+)/email/([^/]+)/affiliation/([^/]+)/kinst/(\d+)/$',
127 views.ftp_instrument,
127 views.ftp_instrument,
128 name='ftp_instrument'),
128 name='ftp_instrument'),
129 url(r'^ftp/fullname/([^/]+)/email/([^/]+)/affiliation/([^/]+)/kinst/(\d+)/year/(\d+)/$',
129 url(r'^ftp/fullname/([^/]+)/email/([^/]+)/affiliation/([^/]+)/kinst/(\d+)/year/(\d+)/$',
130 views.ftp_year,
130 views.ftp_year,
131 name='ftp_year'),
131 name='ftp_year'),
132 url(r'^ftp/fullname/([^/]+)/email/([^/]+)/affiliation/([^/]+)/kinst/(\d+)/year/(\d+)/kindat/(\d+)/$',
132 url(r'^ftp/fullname/([^/]+)/email/([^/]+)/affiliation/([^/]+)/kinst/(\d+)/year/(\d+)/kindat/(\d+)/$',
133 views.ftp_kindat,
133 views.ftp_kindat,
134 name='ftp_kindat'),
134 name='ftp_kindat'),
135 url(r'^ftp/fullname/([^/]+)/email/([^/]+)/affiliation/([^/]+)/kinst/(\d+)/year/(\d+)/kindat/(\d+)/format/([^/]+)/$',
135 url(r'^ftp/fullname/([^/]+)/email/([^/]+)/affiliation/([^/]+)/kinst/(\d+)/year/(\d+)/kindat/(\d+)/format/([^/]+)/$',
136 views.ftp_files,
136 views.ftp_files,
137 name='ftp_files'),
137 name='ftp_files'),
138 url(r'^ftp/fullname/([^/]+)/email/([^/]+)/affiliation/([^/]+)/kinst/(\d+)/year/(\d+)/kindat/(\d+)/format/([^/]+)/fullFilename/([^/]+)/$',
138 url(r'^ftp/fullname/([^/]+)/email/([^/]+)/affiliation/([^/]+)/kinst/(\d+)/year/(\d+)/kindat/(\d+)/format/([^/]+)/fullFilename/([^/]+)/$',
139 views.ftp_download,
139 views.ftp_download,
140 name='ftp_download'),
140 name='ftp_download'),
141 url(r'ftpMultipleDownload/$',
141 url(r'ftpMultipleDownload/$',
142 views.ftp_multiple_download,
142 views.ftp_multiple_download,
143 name='ftp_multiple_download'),
143 name='ftp_multiple_download'),
144 url(r'^instMetadata/?$',
144 url(r'^instMetadata/?$',
145 views.instrument_metadata,
145 views.instrument_metadata,
146 name='instrument_metadata'),
146 name='instrument_metadata'),
147 url(r'^siteMetadata/?$',
147 url(r'^siteMetadata/?$',
148 views.site_metadata,
148 views.site_metadata,
149 name='site_metadata'),
149 name='site_metadata'),
150 url(r'^parameterMetadata/?$',
150 url(r'^parameterMetadata/?$',
151 views.parameter_metadata,
151 views.parameter_metadata,
152 name='parameter_metadata'),
152 name='parameter_metadata'),
153 url(r'^kindatMetadata/?$',
153 url(r'^kindatMetadata/?$',
154 views.kindat_metadata,
154 views.kindat_metadata,
155 name='kindat_metadata'),
155 name='kindat_metadata'),
156 url(r'^madCalculator/?$',
156 url(r'^madCalculator/?$',
157 views.madrigal_calculator,
157 views.madrigal_calculator,
158 name='madrigal_calculator'),
158 name='madrigal_calculator'),
159 url(r'^madCalculatorOutput/?$',
159 url(r'^madCalculatorOutput/?$',
160 views.madrigal_calculator_output,
160 views.madrigal_calculator_output,
161 name='madrigal_calculator_output'),
161 name='madrigal_calculator_output'),
162 url(r'^getMetadata/*$',
162 url(r'^getMetadata/*$',
163 views.get_metadata,
163 views.get_metadata,
164 name='get_metadata'),
164 name='get_metadata'),
165 url(r'^looker/?$',
165 url(r'^looker/?$',
166 views.looker_main,
166 views.looker_main,
167 name='looker_main'),
167 name='looker_main'),
168 url(r'^lookerForm/?$',
168 url(r'^lookerForm/?$',
169 views.looker_form,
169 views.looker_form,
170 name='looker_form'),
170 name='looker_form'),
171 url(r'^lookerOutput/?$',
171 url(r'^lookerOutput/?$',
172 views.looker_output,
172 views.looker_output,
173 name='looker_output'),
173 name='looker_output'),
174 url(r'^getVersionService.py/*$',
174 url(r'^getVersionService.py/*$',
175 views.get_version_service,
175 views.get_version_service,
176 name='get_version_service'),
176 name='get_version_service'),
177 url(r'^getInstrumentsService.py/*$',
177 url(r'^getInstrumentsService.py/*$',
178 views.get_instruments_service,
178 views.get_instruments_service,
179 name='get_instruments_service'),
179 name='get_instruments_service'),
180 url(r'^getExperimentsService.py/*$',
180 url(r'^getExperimentsService.py/*$',
181 views.get_experiments_service,
181 views.get_experiments_service,
182 name='get_experiments_service'),
182 name='get_experiments_service'),
183 url(r'^getExperimentFilesService.py/*$',
183 url(r'^getExperimentFilesService.py/*$',
184 views.get_experiment_files_service,
184 views.get_experiment_files_service,
185 name='get_experiment_files_service'),
185 name='get_experiment_files_service'),
186 url(r'^getParametersService.py/*$',
186 url(r'^getParametersService.py/*$',
187 views.get_parameters_service,
187 views.get_parameters_service,
188 name='get_parameters_service'),
188 name='get_parameters_service'),
189 url(r'^isprintService.py/*$',
189 url(r'^isprintService.py/*$',
190 views.isprint_service,
190 views.isprint_service,
191 name='isprint_service'),
191 name='isprint_service'),
192 url(r'^getMadfile.cgi/*$',
192 url(r'^getMadfile.cgi/*$',
193 views.get_madfile_service,
193 views.get_madfile_service,
194 name='get_madfile_service'),
194 name='get_madfile_service'),
195 url(r'^madCalculatorService.py/*$',
195 url(r'^madCalculatorService.py/*$',
196 views.mad_calculator_service,
196 views.mad_calculator_service,
197 name='mad_calculator_service'),
197 name='mad_calculator_service'),
198 url(r'^madTimeCalculatorService.py/*$',
198 url(r'^madTimeCalculatorService.py/*$',
199 views.mad_time_calculator_service,
199 views.mad_time_calculator_service,
200 name='mad_time_calculator_service'),
200 name='mad_time_calculator_service'),
201 url(r'^madCalculator2Service.py/*$',
201 url(r'^madCalculator2Service.py/*$',
202 views.mad_calculator2_service,
202 views.mad_calculator2_service,
203 name='mad_calculator2_service'),
203 name='mad_calculator2_service'),
204 url(r'^madCalculator2Service.py',
204 url(r'^madCalculator2Service.py',
205 views.mad_calculator2_service,
205 views.mad_calculator2_service,
206 name='mad_calculator2_service'),
206 name='mad_calculator2_service'),
207 url(r'^madCalculator3Service.py/*$',
207 url(r'^madCalculator3Service.py/*$',
208 views.mad_calculator3_service,
208 views.mad_calculator3_service,
209 name='mad_calculator3_service'),
209 name='mad_calculator3_service'),
210 url(r'^madCalculator3Service.py',
210 url(r'^madCalculator3Service.py',
211 views.mad_calculator3_service,
211 views.mad_calculator3_service,
212 name='mad_calculator3_service'),
212 name='mad_calculator3_service'),
213 url(r'^geodeticToRadarService.py',
213 url(r'^geodeticToRadarService.py',
214 views.geodetic_to_radar_service,
214 views.geodetic_to_radar_service,
215 name='geodetic_to_radar_service'),
215 name='geodetic_to_radar_service'),
216 url(r'^radarToGeodeticService.py',
216 url(r'^radarToGeodeticService.py',
217 views.radar_to_geodetic_service,
217 views.radar_to_geodetic_service,
218 name='radar_to_geodetic_service'),
218 name='radar_to_geodetic_service'),
219 url(r'^listFileTimesService.py',
219 url(r'^listFileTimesService.py',
220 views.list_file_times_service,
220 views.list_file_times_service,
221 name='list_file_times_service'),
221 name='list_file_times_service'),
222 url(r'^downloadWebFileService.py',
222 url(r'^downloadWebFileService.py',
223 views.download_web_file_service,
223 views.download_web_file_service,
224 name='download_web_file_service'),
224 name='download_web_file_service'),
225 url(r'^traceMagneticFieldService.py',
225 url(r'^traceMagneticFieldService.py',
226 views.trace_magnetic_field_service,
226 views.trace_magnetic_field_service,
227 name='trace_magnetic_field_service'),
227 name='trace_magnetic_field_service'),
228 url(r'^globalFileSearchService.py',
228 url(r'^globalFileSearchService.py',
229 views.global_file_search_service,
229 views.global_file_search_service,
230 name='global_file_search_service'),
230 name='global_file_search_service'),
231 url(r'^getUrlListFromGroupIdService.py',
231 url(r'^getUrlListFromGroupIdService.py',
232 views.get_url_list_from_group_id_service,
232 views.get_url_list_from_group_id_service,
233 name='get_url_list_from_group_id_service'),
233 name='get_url_list_from_group_id_service'),
234 url(r'^setGroupIdFromUrlListService.py',
234 url(r'^setGroupIdFromUrlListService.py',
235 views.set_group_id_from_url_list_service,
235 views.set_group_id_from_url_list_service,
236 name='set_group_id_from_url_list_service'),
236 name='set_group_id_from_url_list_service'),
237 url(r'docs/name/(.+)$',
237 url(r'docs/name/(.+)$',
238 views.docs,
238 views.docs,
239 name='docs'),
239 name='docs'),
240
240
241 ]
241 ]
242
@@ -1,3518 +1,3530
1 '''
1 '''
2
2
3 @author: Bill Rideout
3 @author: Bill Rideout
4 @contact: brideout@haystack.mit.edu
4 @contact: brideout@haystack.mit.edu
5
5
6 $Id: views.py 7345 2021-03-30 18:30:32Z brideout $
6 $Id: views.py 7345 2021-03-30 18:30:32Z brideout $
7 '''
7 '''
8 # standard python imports
8 # standard python imports
9 import os.path
9 import os.path
10 import urllib
10 import urllib
11 import os, sys
11 import os, sys
12 import json
12 import json
13 import datetime, time
13 import datetime, time
14 import glob
14 import glob
15 import re
15 import re
16 import subprocess
16 import subprocess
17 import io
17 import io
18 import collections
18 import collections
19 import shutil
19 import shutil
20 import mimetypes
20 import mimetypes
21 import tempfile
21 import tempfile
22 import random
22 import random
23
23
24 # django imports
24 # django imports
25 from django.shortcuts import render, redirect
25 from django.shortcuts import render, redirect
26 from django.views.decorators.csrf import csrf_exempt
26 from django.views.decorators.csrf import csrf_exempt
27 from django.template.context import RequestContext
27 from django.template.context import RequestContext
28 #from django.conf import settings
28 #from django.conf import settings
29 try:
29 try:
30 from django.urls import reverse
30 from django.urls import reverse
31 except ImportError:
31 except ImportError:
32 from django.core.urlresolvers import reverse
32 from django.core.urlresolvers import reverse
33 from django.http import HttpResponse, HttpResponseRedirect, StreamingHttpResponse
33 from django.http import HttpResponse, HttpResponseRedirect, StreamingHttpResponse
34 import django.utils.http
34 import django.utils.http
35 import django.core.files
35 import django.core.files
36 import django.utils.safestring
36 import django.utils.safestring
37 from wsgiref.util import FileWrapper
37 from wsgiref.util import FileWrapper
38
38
39 # third party imports
39 # third party imports
40 import numpy
40 import numpy
41 import plotly.offline as py
41 import plotly.offline as py
42 import plotly.graph_objs as go
42 import plotly.graph_objs as go
43 import h5py
43 import h5py
44
44
45
45
46 # madrigal imports
46 # madrigal imports
47 import madrigal._derive
47 import madrigal._derive
48 import madrigal.metadata
48 import madrigal.metadata
49 import madrigal.ui.web
49 import madrigal.ui.web
50 import madrigal.cedar
50 import madrigal.cedar
51 import madrigal.isprint
51 import madrigal.isprint
52 import madweb.forms
52 import madweb.forms
53
53
54
54
55 # temp only
55 # temp only
56 import logging
56 import logging
57
57
58
58
59 # constants
59 # constants
60 formatDict = collections.OrderedDict()
60 formatDict = collections.OrderedDict()
61 formatDict['hdf5'] = 'Hdf5'
61 formatDict['hdf5'] = 'Hdf5'
62 formatDict['netCDF4'] = 'netCDF4'
62 formatDict['netCDF4'] = 'netCDF4'
63 formatDict['ascii'] = 'Column-delimited ascii'
63 formatDict['ascii'] = 'Column-delimited ascii'
64 maxSize = 50000000 # 50 MB cutoff
64 maxSize = 50000000 # 50 MB cutoff
65
65
66
66
67
67
68
68
69 def index(request):
69 def index(request):
70 """index is the home page view
70 """index is the home page view
71 """
71 """
72 madDB = madrigal.metadata.MadrigalDB()
72 madDB = madrigal.metadata.MadrigalDB()
73 bg_color = madDB.getBackgroundColor()
73 bg_color = madDB.getBackgroundColor()
74 welcome = madDB.getIndexHead()
74 welcome = madDB.getIndexHead()
75 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
75 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
76 siteName, siteList = madWebObj.getSiteInfo()
76 siteName, siteList = madWebObj.getSiteInfo()
77 rulesRoadHtml = madDB.getLocalRulesOfRoad()
77 rulesRoadHtml = madDB.getLocalRulesOfRoad()
78 template_dict = {'home_active': 'class="active"', 'site_name': siteName, 'site_list': siteList,
78 template_dict = {'home_active': 'class="active"', 'site_name': siteName, 'site_list': siteList,
79 'rulesOfRoad':django.utils.safestring.mark_safe(rulesRoadHtml),
79 'rulesOfRoad':django.utils.safestring.mark_safe(rulesRoadHtml),
80 'bg_color': bg_color, 'welcome': welcome}
80 'bg_color': bg_color, 'welcome': welcome}
81 return render(request, 'madweb/index.html', template_dict)
81 return render(request, 'madweb/index.html', template_dict)
82
82
83 @csrf_exempt
83 @csrf_exempt
84 def check_registration(view):
84 def check_registration(view):
85 def check_cookies(request, *args, **kwargs):
85 def check_cookies(request, *args, **kwargs):
86 # this view checks if all the needed cookies are set
86 # this view checks if all the needed cookies are set
87 cookieDict = request.COOKIES
87 cookieDict = request.COOKIES
88 try:
88 try:
89 cookieDict['user_fullname']
89 cookieDict['user_fullname']
90 cookieDict['user_email']
90 cookieDict['user_email']
91 cookieDict['user_affiliation']
91 cookieDict['user_affiliation']
92 # no need to register
92 # no need to register
93 return(view(request, *args, **kwargs))
93 return(view(request, *args, **kwargs))
94 except KeyError:
94 except KeyError:
95 return(HttpResponseRedirect(reverse('view_registration') + '?redirect=%s' % (request.get_full_path())))
95 return(HttpResponseRedirect(reverse('view_registration') + '?redirect=%s' % (request.get_full_path())))
96
96
97 return(check_cookies)
97 return(check_cookies)
98
98
99
99
100 def view_registration(request):
100 def view_registration(request):
101 madDB = madrigal.metadata.MadrigalDB()
101 madDB = madrigal.metadata.MadrigalDB()
102 madWeb = madrigal.ui.web.MadrigalWeb(madDB)
102 madWeb = madrigal.ui.web.MadrigalWeb(madDB)
103 siteName, siteList = madWeb.getSiteInfo()
103 siteName, siteList = madWeb.getSiteInfo()
104 redirect = 'index' # default is to redirect to home page
104 redirect = 'index' # default is to redirect to home page
105 if request.method == 'GET':
105 if request.method == 'GET':
106 if 'redirect' in request.GET:
106 if 'redirect' in request.GET:
107 redirect = request.GET['redirect']
107 redirect = request.GET['redirect']
108 for key in request.GET:
108 for key in request.GET:
109 if key not in ('redirect', 'user_fullname', 'user_email', 'user_affiliation'):
109 if key not in ('redirect', 'user_fullname', 'user_email', 'user_affiliation'):
110 redirect += '&%s=%s' % (key, request.GET[key])
110 redirect += '&%s=%s' % (key, request.GET[key])
111 if len(list(request.GET.keys())) > 0 and 'user_fullname' in request.GET:
111 if len(list(request.GET.keys())) > 0 and 'user_fullname' in request.GET:
112 form = madweb.forms.RegisterForm(request.GET)
112 form = madweb.forms.RegisterForm(request.GET)
113 if form.is_valid():
113 if form.is_valid():
114 # write cookies and continue to main page
114 # write cookies and continue to main page
115 max_age = 3600*24*365 # one year
115 max_age = 3600*24*365 # one year
116 if redirect == 'index':
116 if redirect == 'index':
117 response = HttpResponseRedirect(reverse('index'))
117 response = HttpResponseRedirect(reverse('index'))
118 else:
118 else:
119 response = HttpResponseRedirect(redirect)
119 response = HttpResponseRedirect(redirect)
120 response.set_cookie('user_fullname', form.cleaned_data['user_fullname'], max_age=max_age, samesite='Strict')
120 response.set_cookie('user_fullname', form.cleaned_data['user_fullname'], max_age=max_age, samesite='Strict')
121 response.set_cookie('user_email', form.cleaned_data['user_email'], max_age=max_age, samesite='Strict')
121 response.set_cookie('user_email', form.cleaned_data['user_email'], max_age=max_age, samesite='Strict')
122 response.set_cookie('user_affiliation', form.cleaned_data['user_affiliation'], max_age=max_age, samesite='Strict')
122 response.set_cookie('user_affiliation', form.cleaned_data['user_affiliation'], max_age=max_age, samesite='Strict')
123 return(response)
123 return(response)
124 else:
124 else:
125 form = madweb.forms.RegisterForm()
125 form = madweb.forms.RegisterForm()
126
126
127 else:
127 else:
128 form = madweb.forms.RegisterForm()
128 form = madweb.forms.RegisterForm()
129 return render(request, 'madweb/register.html', {'form': form, 'home_active': 'class="active"',
129 return render(request, 'madweb/register.html', {'form': form, 'home_active': 'class="active"',
130 'site_name': siteName, 'site_list': siteList,
130 'site_name': siteName, 'site_list': siteList,
131 'redirect': redirect})
131 'redirect': redirect})
132
132
133
133
134
134
135
135
136
136
137
137
138 def view_single(request):
138 def view_single(request):
139 """view_single is the single experiment view. It is supplemented by ajax views to speed performamnce,
139 """view_single is the single experiment view. It is supplemented by ajax views to speed performamnce,
140 but this view can also create the entire page given a complete query string
140 but this view can also create the entire page given a complete query string
141 """
141 """
142 responseDict = {'single_active': 'class="active"'}
142 responseDict = {'single_active': 'class="active"'}
143 cookieDict = request.COOKIES
143 cookieDict = request.COOKIES
144 user_email = cookieDict['user_email']
144 user_email = cookieDict['user_email']
145 queryDict = request.GET.copy()
145 queryDict = request.GET.copy()
146 queryDict['user_email'] = user_email
146 queryDict['user_email'] = user_email
147 madDB = madrigal.metadata.MadrigalDB()
147 madDB = madrigal.metadata.MadrigalDB()
148 bg_color = madDB.getBackgroundColor()
148 bg_color = madDB.getBackgroundColor()
149 madWeb = madrigal.ui.web.MadrigalWeb(madDB)
149 madWeb = madrigal.ui.web.MadrigalWeb(madDB)
150 siteName, siteList = madWeb.getSiteInfo()
150 siteName, siteList = madWeb.getSiteInfo()
151 form = madweb.forms.SingleExpDefaultForm(queryDict)
151 form = madweb.forms.SingleExpDefaultForm(queryDict)
152 if not form.is_valid():
152 if not form.is_valid():
153 # new page
153 # new page
154 form = madweb.forms.SingleExpDefaultForm()
154 form = madweb.forms.SingleExpDefaultForm()
155 responseDict['form'] = form
155 responseDict['form'] = form
156 responseDict['site_name'] = siteName
156 responseDict['site_name'] = siteName
157 responseDict['site_list'] = siteList
157 responseDict['site_list'] = siteList
158 responseDict['redirect_list'] = madWeb.getSingleRedirectList()
158 responseDict['redirect_list'] = madWeb.getSingleRedirectList()
159 if 'instruments' in request.GET:
159 if 'instruments' in request.GET:
160 responseDict['instruments'] = request.GET['instruments']
160 responseDict['instruments'] = request.GET['instruments']
161 if 'years' in request.GET:
161 if 'years' in request.GET:
162 responseDict['years'] = request.GET['years']
162 responseDict['years'] = request.GET['years']
163 if 'months' in request.GET:
163 if 'months' in request.GET:
164 responseDict['months'] = request.GET['months']
164 responseDict['months'] = request.GET['months']
165 try:
165 try:
166 # add extra keys if choosing a file
166 # add extra keys if choosing a file
167 form.fields['file_list']
167 form.fields['file_list']
168 responseDict['loader'] = 'loadSingleForm'
168 responseDict['loader'] = 'loadSingleForm'
169 responseDict['redirect'] = reverse('get_files')
169 responseDict['redirect'] = reverse('get_files')
170 # handle the case with no files
170 # handle the case with no files
171 if len(form.fields['file_list'].choices) < 2:
171 if len(form.fields['file_list'].choices) < 2:
172 form2 = madweb.forms.SingleExpPlotsForm({'experiment_list':form['exp_id'].initial})
172 form2 = madweb.forms.SingleExpPlotsForm({'experiment_list':form['exp_id'].initial})
173 form.fields['plot_list'] = form2.fields['plot_list']
173 form.fields['plot_list'] = form2.fields['plot_list']
174 except:
174 except:
175 pass
175 pass
176 responseDict['bg_color'] = bg_color
176 responseDict['bg_color'] = bg_color
177 return render(request, 'madweb/single.html', responseDict)
177 return render(request, 'madweb/single.html', responseDict)
178
178
179
179
180 def get_categories(request):
180 def get_categories(request):
181 """get_categories is a Ajax call that returns the categories select html to support the
181 """get_categories is a Ajax call that returns the categories select html to support the
182 single experiment UI. Called when a user modifies the isGlobal checkbox.
182 single experiment UI. Called when a user modifies the isGlobal checkbox.
183
183
184 Inputs:
184 Inputs:
185 request
185 request
186 """
186 """
187 form = madweb.forms.SingleExpDefaultForm(request.GET)
187 form = madweb.forms.SingleExpDefaultForm(request.GET)
188
188
189 return render(request, 'madweb/categories.html', {'form': form})
189 return render(request, 'madweb/categories.html', {'form': form})
190
190
191
191
192 def get_instruments(request):
192 def get_instruments(request):
193 """get_instruments is a Ajax call that returns the instruments select html to support the
193 """get_instruments is a Ajax call that returns the instruments select html to support the
194 single experiment UI. Called when a user modifies the categories select field.
194 single experiment UI. Called when a user modifies the categories select field.
195
195
196 Inputs:
196 Inputs:
197 request
197 request
198 """
198 """
199 form = madweb.forms.SingleExpInstForm(request.GET)
199 form = madweb.forms.SingleExpInstForm(request.GET)
200
200
201 return render(request, 'madweb/instruments.html', {'form': form})
201 return render(request, 'madweb/instruments.html', {'form': form})
202
202
203
203
204 def get_years(request):
204 def get_years(request):
205 """get_years is a Ajax call that returns the years select html to support the
205 """get_years is a Ajax call that returns the years select html to support the
206 single experiment UI. Called when a user modifies the instruments select field.
206 single experiment UI. Called when a user modifies the instruments select field.
207
207
208 Inputs:
208 Inputs:
209 request
209 request
210 """
210 """
211 form = madweb.forms.SingleExpYearForm(request.GET)
211 form = madweb.forms.SingleExpYearForm(request.GET)
212
212
213 is_global = madweb.forms.getIsGlobal([], request.GET)
213 is_global = madweb.forms.getIsGlobal([], request.GET)
214
214
215 return render(request, 'madweb/years.html', {'isGlobal': is_global,
215 return render(request, 'madweb/years.html', {'isGlobal': is_global,
216 'form': form})
216 'form': form})
217
217
218
218
219 def get_months(request):
219 def get_months(request):
220 """get_months is a Ajax call that returns the months select html to support the
220 """get_months is a Ajax call that returns the months select html to support the
221 single experiment UI. Called when a user modifies the years select field.
221 single experiment UI. Called when a user modifies the years select field.
222
222
223 Inputs:
223 Inputs:
224 request
224 request
225 """
225 """
226 form = madweb.forms.SingleExpMonthForm(request.GET)
226 form = madweb.forms.SingleExpMonthForm(request.GET)
227
227
228 is_global = madweb.forms.getIsGlobal([], request.GET)
228 is_global = madweb.forms.getIsGlobal([], request.GET)
229 year = int(request.GET['years'])
229 year = int(request.GET['years'])
230 kinst =int(request.GET['instruments'])
230 kinst =int(request.GET['instruments'])
231
231
232 return render(request, 'madweb/months.html', {'isGlobal': is_global,
232 return render(request, 'madweb/months.html', {'isGlobal': is_global,
233 'years': year,
233 'years': year,
234 'form': form})
234 'form': form})
235
235
236
236
237 def get_calendar(request):
237 def get_calendar(request):
238 """get_calendar is a Ajax call that returns the calendar html to support the
238 """get_calendar is a Ajax call that returns the calendar html to support the
239 single experiment UI. Called when a user selects month field.
239 single experiment UI. Called when a user selects month field.
240
240
241 Inputs:
241 Inputs:
242 request
242 request
243 """
243 """
244 is_global = madweb.forms.getIsGlobal([], request.GET)
244 is_global = madweb.forms.getIsGlobal([], request.GET)
245 year = int(request.GET['years'])
245 year = int(request.GET['years'])
246 month = int(request.GET['months'])
246 month = int(request.GET['months'])
247 kinst =int(request.GET['instruments'])
247 kinst =int(request.GET['instruments'])
248
248
249 form = madweb.forms.SingleExpCalendarForm({'years': year,
249 form = madweb.forms.SingleExpCalendarForm({'years': year,
250 'months': month,
250 'months': month,
251 'instruments': kinst})
251 'instruments': kinst})
252
252
253 return render(request, 'madweb/calendar.html', {'isGlobal': is_global,
253 return render(request, 'madweb/calendar.html', {'isGlobal': is_global,
254 'years': year,
254 'years': year,
255 'months': month,
255 'months': month,
256 'instruments': kinst,
256 'instruments': kinst,
257 'form': form})
257 'form': form})
258
258
259
259
260 def populate_calendar_experiment(request):
260 def populate_calendar_experiment(request):
261 """populate_calendar_experiment is a ajax view that returns a json object used by the
261 """populate_calendar_experiment is a ajax view that returns a json object used by the
262 calender widget to populate itself.
262 calender widget to populate itself.
263
263
264 Inputs:
264 Inputs:
265 request
265 request
266 """
266 """
267 is_global = madweb.forms.getIsGlobal([], request.GET)
267 is_global = madweb.forms.getIsGlobal([], request.GET)
268 year = int(request.GET['years'])
268 year = int(request.GET['years'])
269 month = int(request.GET['months'])
269 month = int(request.GET['months'])
270 kinst =int(request.GET['instruments'])
270 kinst =int(request.GET['instruments'])
271 madDB = madrigal.metadata.MadrigalDB()
271 madDB = madrigal.metadata.MadrigalDB()
272 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
272 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
273 madInstObj = madrigal.metadata.MadrigalInstrument(madDB)
273 madInstObj = madrigal.metadata.MadrigalInstrument(madDB)
274 catId = madInstObj.getCategoryId(kinst)
274 catId = madInstObj.getCategoryId(kinst)
275
275
276 expDays = madWebObj.getDays(kinst, year, month)
276 expDays = madWebObj.getDays(kinst, year, month)
277
277
278 if len(expDays) == 0:
278 if len(expDays) == 0:
279 expDays = madWebObj.getDays(kinst, year, month, optimize=False)
279 expDays = madWebObj.getDays(kinst, year, month, optimize=False)
280
280
281 color = "#999"
281 color = "#999"
282 jsonListFinal = []
282 jsonListFinal = []
283 for expDay in expDays:
283 for expDay in expDays:
284 newdate = '%i/%i/%i' % (expDay.day, expDay.month, expDay.year)
284 newdate = '%i/%i/%i' % (expDay.day, expDay.month, expDay.year)
285 urlperDate = reverse('view_single')
285 urlperDate = reverse('view_single')
286 query_str = '?'
286 query_str = '?'
287 if is_global:
287 if is_global:
288 query_str += 'isGlobal=on&'
288 query_str += 'isGlobal=on&'
289 query_str += 'categories=%i&instruments=%i&years=%i&months=%i&days=%i' % (catId, kinst, year,
289 query_str += 'categories=%i&instruments=%i&years=%i&months=%i&days=%i' % (catId, kinst, year,
290 expDay.month, expDay.day)
290 expDay.month, expDay.day)
291 urlperDate += query_str
291 urlperDate += query_str
292 dayList = [newdate, "", urlperDate, color]
292 dayList = [newdate, "", urlperDate, color]
293 jsonListFinal.append(dayList)
293 jsonListFinal.append(dayList)
294
294
295 return HttpResponse(json.dumps(jsonListFinal), content_type='application/json')
295 return HttpResponse(json.dumps(jsonListFinal), content_type='application/json')
296
296
297
297
298 def get_files(request):
298 def get_files(request):
299 """get_files is a Ajax call that returns the files select html to support the
299 """get_files is a Ajax call that returns the files select html to support the
300 single experiment UI. Called when a user modifies the calendar or experiments fields.
300 single experiment UI. Called when a user modifies the calendar or experiments fields.
301
301
302 Inputs:
302 Inputs:
303 request
303 request
304 """
304 """
305 cookieDict = request.COOKIES
305 cookieDict = request.COOKIES
306 user_email = cookieDict['user_email']
306 user_email = cookieDict['user_email']
307 queryDict = request.GET.copy()
307 queryDict = request.GET.copy()
308 queryDict['user_email'] = user_email
308 queryDict['user_email'] = user_email
309 form = madweb.forms.SingleExpFileForm(queryDict)
309 form = madweb.forms.SingleExpFileForm(queryDict)
310
310
311 is_global = madweb.forms.getIsGlobal([], request.GET)
311 is_global = madweb.forms.getIsGlobal([], request.GET)
312
312
313 return render(request, 'madweb/file_list.html', {'isGlobal': is_global,
313 return render(request, 'madweb/file_list.html', {'isGlobal': is_global,
314 'form': form,
314 'form': form,
315 'loader': 'loadSingleForm',
315 'loader': 'loadSingleForm',
316 'redirect': reverse('get_files')})
316 'redirect': reverse('get_files')})
317
317
318
318
319 def change_files(request):
319 def change_files(request):
320 """change_files is a Ajax call that returns the files options html to support the
320 """change_files is a Ajax call that returns the files options html to support the
321 single experiment UI. Called when a user modifies the files select field.
321 single experiment UI. Called when a user modifies the files select field.
322
322
323 Inputs:
323 Inputs:
324 request
324 request
325 """
325 """
326 expID =int(request.GET['experiment_list'])
326 expID =int(request.GET['experiment_list'])
327 basename = request.GET['file_list']
327 basename = request.GET['file_list']
328 madDB = madrigal.metadata.MadrigalDB()
328 madDB = madrigal.metadata.MadrigalDB()
329 form = madweb.forms.SingleExpButtonsForm(request.GET)
329 form = madweb.forms.SingleExpButtonsForm(request.GET)
330
330
331 return render(request, 'madweb/file_buttons.html', {'form': form,
331 return render(request, 'madweb/file_buttons.html', {'form': form,
332 'plot_label': madDB.getPlotButtonLabel()})
332 'plot_label': madDB.getPlotButtonLabel()})
333
333
334
334
335 def show_plots(request):
335 def show_plots(request):
336 """show_plots is a Ajax call that returns the files data html with plots to support the
336 """show_plots is a Ajax call that returns the files data html with plots to support the
337 single experiment UI. Called when a user modifies the files select field.
337 single experiment UI. Called when a user modifies the files select field.
338
338
339 Inputs:
339 Inputs:
340 request
340 request
341 """
341 """
342 madDB = madrigal.metadata.MadrigalDB()
342 madDB = madrigal.metadata.MadrigalDB()
343 madExpObj = madrigal.metadata.MadrigalExperiment(madDB)
343 madExpObj = madrigal.metadata.MadrigalExperiment(madDB)
344 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
344 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
345
345
346 try:
346 try:
347 expID = int(request.GET['experiment_list'])
347 expID = int(request.GET['experiment_list'])
348 except ValueError:
348 except ValueError:
349 # convert expPath to expID
349 # convert expPath to expID
350 expID = madWebObj.getExpIDFromExpPath(request.GET['experiment_list'], True)
350 expID = madWebObj.getExpIDFromExpPath(request.GET['experiment_list'], True)
351 plotList = madExpObj.getExpLinksByExpId(expID)
351 plotList = madExpObj.getExpLinksByExpId(expID)
352 if len(plotList) != 0:
352 if len(plotList) != 0:
353 form = madweb.forms.SingleExpPlotsForm(request.GET)
353 form = madweb.forms.SingleExpPlotsForm(request.GET)
354 template = 'madweb/show_plots.html'
354 template = 'madweb/show_plots.html'
355 context = {'form': form}
355 context = {'form': form}
356 else:
356 else:
357 template = 'madweb/parameter_selection.html'
357 template = 'madweb/parameter_selection.html'
358 form = madweb.forms.SingleExpPlotsSelectionForm(request.GET)
358 form = madweb.forms.SingleExpPlotsSelectionForm(request.GET)
359 context = {'form': form, 'expID': expID}
359 context = {'form': form, 'expID': expID}
360
360
361 return render(request, template, context)
361 return render(request, template, context)
362
362
363
363
364 def view_plot(request):
364 def view_plot(request):
365
365
366 param1d = request.GET.get('param1d', 0)
366 param1d = request.GET.get('param1d', 0)
367 param2d = request.GET.get('param2d', 0)
367 param2d = request.GET.get('param2d', 0)
368
368
369 madDB = madrigal.metadata.MadrigalDB()
369 madDB = madrigal.metadata.MadrigalDB()
370 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
370 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
371 madExpObj = madrigal.metadata.MadrigalExperiment(madDB)
371 madExpObj = madrigal.metadata.MadrigalExperiment(madDB)
372
372
373 expID =int(request.GET['expID'])
373 expID =int(request.GET['expID'])
374 expDir = madExpObj.getExpDirByExpId(expID)
374 expDir = madExpObj.getExpDirByExpId(expID)
375 if expDir is None:
375 if expDir is None:
376 raise ValueError('No expDir found for exp_id %i' % (int(expID)))
376 raise ValueError('No expDir found for exp_id %i' % (int(expID)))
377
377
378 fileList = madWebObj.getFileFromExpID(expID, False)
378 # fileList = madWebObj.getFileFromExpID(expID, False)
379 firsttuple = [a_tuple[0] for a_tuple in fileList]
379 # firsttuple = [a_tuple[0] for a_tuple in fileList]
380 basename = firsttuple[0]
380 basename = request.GET['filename']#firsttuple[0]
381 fullFilename = os.path.join(expDir, basename)
381 fullFilename = os.path.join(expDir, basename)
382
382
383 with h5py.File(fullFilename, "r") as f:
383 with h5py.File(fullFilename, "r") as f:
384
384
385 # Get the data
385 # Get the data
386
386
387 data = f['Data']
387 data = f['Data']
388
388
389 if 'Array Layout' in data:
389 if 'Array Layout' in data:
390 array = data['Array Layout']
390 array = data['Array Layout']
391 datatime = [datetime.datetime.fromtimestamp(t) for t in array['timestamps']]
391 datatime = [datetime.datetime.utcfromtimestamp(t-5*60*60) for t in array['timestamps']]
392 yrange = array['gdalt']
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 if param1d==0:
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 else:
405 else:
397 plot = plot_scatter(datatime, array['1D Parameters'][param1d], param1d)
406 plot = plot_scatter(datatime, array['1D Parameters'][param1d], param1d)
398
407
399 else:
408 else:
400 table = data['Table Layout']
409 table = data['Table Layout']
401 datatime = [datetime.datetime.fromtimestamp(t) for t in table['ut2_unix']]
410 datatime = [datetime.datetime.fromtimestamp(t) for t in table['ut2_unix']]
402 plot = plot_scatter(datatime,table[param1d],param1d)
411 plot = plot_scatter(datatime,table[param1d],param1d)
403
412
404 return HttpResponse(plot)
413 return HttpResponse(plot)
405
414
406 def plot_scatter(datatime,dataparam,paramname):
415 def plot_scatter(datatime,dataparam,paramname, error=[]):
407 if (numpy.isnan(dataparam).all()):
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 else:
419 else:
420 mode = 'markers' if len(error)>0 else 'lines'
411 fig = go.Figure()
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 fig.update_yaxes(title_text=paramname)
423 fig.update_yaxes(title_text=paramname)
424 fig.update_xaxes(title_text='Time [LT]')
414
425
415 delta = datatime[-1] - datatime[1]
426 delta = datatime[-1] - datatime[1]
416
427
417 if (delta>datetime.timedelta(days=30)):
428 if (delta>datetime.timedelta(days=30)):
418 # Add range slider
429 # Add range slider
419 fig.update_layout(
430 fig.update_layout(
420 xaxis=dict(
431 xaxis=dict(
421 rangeselector=dict(
432 rangeselector=dict(
422 buttons=list([
433 buttons=list([
423 dict(count=1,
434 dict(count=1,
424 label="1m",
435 label="1m",
425 step="month",
436 step="month",
426 stepmode="backward"),
437 stepmode="backward"),
427 dict(count=6,
438 dict(count=6,
428 label="6m",
439 label="6m",
429 step="month",
440 step="month",
430 stepmode="backward"),
441 stepmode="backward"),
431 dict(count=1,
442 dict(count=1,
432 label="1y",
443 label="1y",
433 step="year",
444 step="year",
434 stepmode="backward"),
445 stepmode="backward"),
435 dict(step="all")
446 dict(step="all")
436 ])
447 ])
437 ),
448 ),
438 rangeslider=dict(
449 rangeslider=dict(
439 visible=True
450 visible=True
440 ),
451 ),
441 type="date"
452 type="date"
442 )
453 )
443 )
454 )
444
455
445
456
446 plot = py.plot(fig, include_plotlyjs=False, output_type='div')
457 plot = py.plot(fig, include_plotlyjs=False, output_type='div')
447
458
448
459
449 return plot
460 return plot
450
461
451
462
452 def plot_heatmap(datatime,datarange,dataparam,paramname):
463 def plot_heatmap(datatime,datarange,dataparam,paramname):
453 if (numpy.all(numpy.isnan(dataparam))):
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 else:
466 else:
456 fig = go.Figure()
467 fig = go.Figure()
457 fig.add_trace(go.Heatmap(x=datatime,y=datarange,z= dataparam,colorscale='Jet',colorbar={"title":paramname}))
468 fig.add_trace(go.Heatmap(x=datatime,y=datarange,z= dataparam,colorscale='Jet',colorbar={"title":paramname}))
458 fig.update_yaxes(title_text="range")
469 fig.update_yaxes(title_text="range")
470 fig.update_xaxes(title_text="Time [LT]")
459 fig.update_layout(
471 fig.update_layout(
460 updatemenus=[
472 updatemenus=[
461 dict(
473 dict(
462 buttons=list([
474 buttons=list([
463 dict(
475 dict(
464 args=["colorscale", "Jet"],
476 args=["colorscale", "Jet"],
465 label="Jet",
477 label="Jet",
466 method="restyle"
478 method="restyle"
467 ),
479 ),
468 dict(
480 dict(
469 args=["colorscale", "RdBu"],
481 args=["colorscale", "RdBu"],
470 label="Red-Blue",
482 label="Red-Blue",
471 method="restyle"
483 method="restyle"
472 ),
484 ),
473 dict(
485 dict(
474 args=["colorscale", "Viridis"],
486 args=["colorscale", "Viridis"],
475 label="Viridis",
487 label="Viridis",
476 method="restyle"
488 method="restyle"
477 ),
489 ),
478 dict(
490 dict(
479 args=["colorscale", "Cividis"],
491 args=["colorscale", "Cividis"],
480 label="Cividis",
492 label="Cividis",
481 method="restyle"
493 method="restyle"
482 ),
494 ),
483 dict(
495 dict(
484 args=["colorscale", "Greens"],
496 args=["colorscale", "Greens"],
485 label="Greens",
497 label="Greens",
486 method="restyle"
498 method="restyle"
487 ),
499 ),
488 ]),
500 ]),
489 type = "dropdown",
501 type = "dropdown",
490 direction="down",
502 direction="down",
491 pad={"r": 10, "t": -10},
503 pad={"r": 10, "t": -10},
492 showactive=True,
504 showactive=True,
493 x=0.1,
505 x=0.1,
494 xanchor="left",
506 xanchor="left",
495 y=1.05,
507 y=1.05,
496 yanchor="top"
508 yanchor="top"
497 ),
509 ),
498 dict(
510 dict(
499 buttons=list([
511 buttons=list([
500 dict(
512 dict(
501 args=[{"contours.showlines": False, "type": "contour"}],
513 args=[{"contours.showlines": False, "type": "contour"}],
502 label="Hide lines",
514 label="Hide lines",
503 method="restyle"
515 method="restyle"
504 ),
516 ),
505 dict(
517 dict(
506 args=[{"contours.showlines": True, "type": "contour"}],
518 args=[{"contours.showlines": True, "type": "contour"}],
507 label="Show lines",
519 label="Show lines",
508 method="restyle"
520 method="restyle"
509 ),
521 ),
510 ]),
522 ]),
511 direction="down",
523 direction="down",
512 pad={"r": 10, "t": -10},
524 pad={"r": 10, "t": -10},
513 showactive=True,
525 showactive=True,
514 x=0.32,
526 x=0.32,
515 xanchor="left",
527 xanchor="left",
516 y=1.05,
528 y=1.05,
517 yanchor="top"
529 yanchor="top"
518 ),
530 ),
519
531
520 ]
532 ]
521 )
533 )
522
534
523 fig.update_layout(
535 fig.update_layout(
524 annotations=[
536 annotations=[
525 dict(text="Colorscale", showarrow=False,
537 dict(text="Colorscale", showarrow=False,
526 x=0, xref="paper", y=1.05, yref="paper", align="left"),
538 x=0, xref="paper", y=1.05, yref="paper", align="left"),
527 dict(text="Lines", x=0.25, xref="paper", y=1.05, yref="paper",
539 dict(text="Lines", x=0.25, xref="paper", y=1.05, yref="paper",
528 showarrow=False)
540 showarrow=False)
529 ]
541 ]
530 )
542 )
531
543
532
544
533 plot = py.plot(fig, include_plotlyjs=False, output_type='div')
545 plot = py.plot(fig, include_plotlyjs=False, output_type='div')
534
546
535 return plot
547 return plot
536
548
537
549
538 def download_as_is(request):
550 def download_as_is(request):
539 """download_as_is is a Ajax call that returns the download as is html to support the
551 """download_as_is is a Ajax call that returns the download as is html to support the
540 single experiment UI. Called when a user selects download/as is link.
552 single experiment UI. Called when a user selects download/as is link.
541
553
542 Inputs:
554 Inputs:
543 request
555 request
544 """
556 """
545 cookieDict = request.COOKIES
557 cookieDict = request.COOKIES
546 if not 'user_fullname' in cookieDict:
558 if not 'user_fullname' in cookieDict:
547 return(HttpResponse('<p>Cookie with user_fullname required for downloadAsIs</p>'))
559 return(HttpResponse('<p>Cookie with user_fullname required for downloadAsIs</p>'))
548 user_fullname = django.utils.http.urlquote_plus(cookieDict['user_fullname'])
560 user_fullname = django.utils.http.urlquote_plus(cookieDict['user_fullname'])
549 user_email = cookieDict['user_email']
561 user_email = cookieDict['user_email']
550 user_affiliation = django.utils.http.urlquote_plus(cookieDict['user_affiliation'])
562 user_affiliation = django.utils.http.urlquote_plus(cookieDict['user_affiliation'])
551 expID =int(request.GET['experiment_list'])
563 expID =int(request.GET['experiment_list'])
552 file_list = request.GET['file_list']
564 file_list = request.GET['file_list']
553 form = madweb.forms.SingleExpDownloadAsIsForm({'format_select':file_list,
565 form = madweb.forms.SingleExpDownloadAsIsForm({'format_select':file_list,
554 'expID': expID})
566 'expID': expID})
555
567
556 return render(request, 'madweb/download_as_is.html', {'form': form, 'exp_id':expID,
568 return render(request, 'madweb/download_as_is.html', {'form': form, 'exp_id':expID,
557 'user_fullname':user_fullname,
569 'user_fullname':user_fullname,
558 'user_email':user_email,
570 'user_email':user_email,
559 'user_affiliation': user_affiliation})
571 'user_affiliation': user_affiliation})
560
572
561
573
562 def download_file_as_is(request):
574 def download_file_as_is(request):
563 """download_file_as_is is a Ajax call that actually downloads a madrigal file.
575 """download_file_as_is is a Ajax call that actually downloads a madrigal file.
564
576
565 Inputs:
577 Inputs:
566 request
578 request
567 """
579 """
568 madDB = madrigal.metadata.MadrigalDB()
580 madDB = madrigal.metadata.MadrigalDB()
569 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
581 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
570 user_fullname = urllib.parse.unquote_plus(request.GET['user_fullname'])
582 user_fullname = urllib.parse.unquote_plus(request.GET['user_fullname'])
571 user_email = request.GET['user_email']
583 user_email = request.GET['user_email']
572 user_affiliation = urllib.parse.unquote_plus(request.GET['user_affiliation'])
584 user_affiliation = urllib.parse.unquote_plus(request.GET['user_affiliation'])
573 exp_id = request.GET['exp_id']
585 exp_id = request.GET['exp_id']
574 basename = request.GET['basename']
586 basename = request.GET['basename']
575 downloadFile = madWebObj.downloadFileAsIs(exp_id, basename, user_fullname, user_email, user_affiliation)
587 downloadFile = madWebObj.downloadFileAsIs(exp_id, basename, user_fullname, user_email, user_affiliation)
576 f = open(downloadFile, 'rb')
588 f = open(downloadFile, 'rb')
577 filename = os.path.basename(downloadFile)
589 filename = os.path.basename(downloadFile)
578 chunk_size = 8192
590 chunk_size = 8192
579 file_type = mimetypes.guess_type(downloadFile)[0]
591 file_type = mimetypes.guess_type(downloadFile)[0]
580 if file_type is None:
592 if file_type is None:
581 file_type = 'application/octet-stream'
593 file_type = 'application/octet-stream'
582 response = StreamingHttpResponse(FileWrapper(f, chunk_size),
594 response = StreamingHttpResponse(FileWrapper(f, chunk_size),
583 content_type=file_type)
595 content_type=file_type)
584 response['Content-Length'] = os.path.getsize(downloadFile)
596 response['Content-Length'] = os.path.getsize(downloadFile)
585 response['Content-Disposition'] = "attachment; filename=%s" % (filename)
597 response['Content-Disposition'] = "attachment; filename=%s" % (filename)
586 response.set_cookie('fileDownload', 'true', path='/', samesite='Strict')
598 response.set_cookie('fileDownload', 'true', path='/', samesite='Strict')
587 return(response)
599 return(response)
588
600
589
601
590 def print_as_is(request):
602 def print_as_is(request):
591 """print_as_is is a Ajax call that returns the text of the ascii file to support the
603 """print_as_is is a Ajax call that returns the text of the ascii file to support the
592 single experiment UI if request.GET has key "text", or the length of the file to be
604 single experiment UI if request.GET has key "text", or the length of the file to be
593 downloaded if not. Called when a user selects print/as is link.
605 downloaded if not. Called when a user selects print/as is link.
594
606
595 Inputs:
607 Inputs:
596 request
608 request
597 """
609 """
598 madDB = madrigal.metadata.MadrigalDB()
610 madDB = madrigal.metadata.MadrigalDB()
599 madExpObj = madrigal.metadata.MadrigalExperiment(madDB)
611 madExpObj = madrigal.metadata.MadrigalExperiment(madDB)
600 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
612 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
601 madParmObj = madrigal.data.MadrigalParameters(madDB)
613 madParmObj = madrigal.data.MadrigalParameters(madDB)
602
614
603 cookieDict = request.COOKIES
615 cookieDict = request.COOKIES
604 if not 'user_fullname' in cookieDict:
616 if not 'user_fullname' in cookieDict:
605 return(HttpResponse('<p>Cookie with user_fullname required for printAsIs</p>'))
617 return(HttpResponse('<p>Cookie with user_fullname required for printAsIs</p>'))
606 user_fullname = django.utils.http.urlquote_plus(cookieDict['user_fullname'])
618 user_fullname = django.utils.http.urlquote_plus(cookieDict['user_fullname'])
607 user_email = cookieDict['user_email']
619 user_email = cookieDict['user_email']
608 user_affiliation = django.utils.http.urlquote_plus(cookieDict['user_affiliation'])
620 user_affiliation = django.utils.http.urlquote_plus(cookieDict['user_affiliation'])
609 expID =int(request.GET['experiment_list'])
621 expID =int(request.GET['experiment_list'])
610 basename = request.GET['file_list']
622 basename = request.GET['file_list']
611 expDir = madExpObj.getExpDirByExpId(int(expID))
623 expDir = madExpObj.getExpDirByExpId(int(expID))
612 if expDir is None:
624 if expDir is None:
613 raise ValueError('No expDir found for exp_id %i' % (int(expID)))
625 raise ValueError('No expDir found for exp_id %i' % (int(expID)))
614 fullFilename = os.path.join(expDir, basename)
626 fullFilename = os.path.join(expDir, basename)
615
627
616 # determine if we need to return the full file text, or just the size and name
628 # determine if we need to return the full file text, or just the size and name
617 if 'text' in request.GET:
629 if 'text' in request.GET:
618 madFileObj = madrigal.data.MadrigalFile(fullFilename, madDB)
630 madFileObj = madrigal.data.MadrigalFile(fullFilename, madDB)
619 measParms = madFileObj.getMeasuredParmList()
631 measParms = madFileObj.getMeasuredParmList()
620 measParmMnemList = madParmObj.getParmMnemonicList(measParms) + madFileObj.getStandardParms(upper=True)
632 measParmMnemList = madParmObj.getParmMnemonicList(measParms) + madFileObj.getStandardParms(upper=True)
621 measParmDescList = madParmObj.getParmDescriptionList(measParmMnemList)
633 measParmDescList = madParmObj.getParmDescriptionList(measParmMnemList)
622 parmList = list(zip(measParmMnemList, measParmDescList))
634 parmList = list(zip(measParmMnemList, measParmDescList))
623 f = open(request.GET['text'])
635 f = open(request.GET['text'])
624 text = f.read()
636 text = f.read()
625 f.close()
637 f.close()
626
638
627 return render(request, 'madweb/print_as_is.html', {'text': text, 'parmList': parmList})
639 return render(request, 'madweb/print_as_is.html', {'text': text, 'parmList': parmList})
628
640
629 else:
641 else:
630 tmpFilename = madWebObj.printFileAsIs(fullFilename, user_fullname, user_email, user_affiliation)
642 tmpFilename = madWebObj.printFileAsIs(fullFilename, user_fullname, user_email, user_affiliation)
631 filesize = os.path.getsize(tmpFilename)
643 filesize = os.path.getsize(tmpFilename)
632 return(HttpResponse('%s:%s' % (filesize, tmpFilename)))
644 return(HttpResponse('%s:%s' % (filesize, tmpFilename)))
633
645
634
646
635 def list_records(request):
647 def list_records(request):
636 """list_records is a Ajax call that returns the list records text.
648 """list_records is a Ajax call that returns the list records text.
637
649
638 Inputs:
650 Inputs:
639 request
651 request
640 """
652 """
641 madDB = madrigal.metadata.MadrigalDB()
653 madDB = madrigal.metadata.MadrigalDB()
642 madExpObj = madrigal.metadata.MadrigalExperiment(madDB)
654 madExpObj = madrigal.metadata.MadrigalExperiment(madDB)
643 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
655 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
644
656
645 expID =int(request.GET['experiment_list'])
657 expID =int(request.GET['experiment_list'])
646 basename = request.GET['file_list']
658 basename = request.GET['file_list']
647 expDir = madExpObj.getExpDirByExpId(int(expID))
659 expDir = madExpObj.getExpDirByExpId(int(expID))
648 if expDir is None:
660 if expDir is None:
649 raise ValueError('No expDir found for exp_id %i' % (int(expID)))
661 raise ValueError('No expDir found for exp_id %i' % (int(expID)))
650 fullFilename = os.path.join(expDir, basename)
662 fullFilename = os.path.join(expDir, basename)
651
663
652 text = madWebObj.listRecords(fullFilename)
664 text = madWebObj.listRecords(fullFilename)
653
665
654 return render(request, 'madweb/list_records.html', {'expDir': expDir,
666 return render(request, 'madweb/list_records.html', {'expDir': expDir,
655 'basename': basename,
667 'basename': basename,
656 'text': text})
668 'text': text})
657
669
658
670
659 def view_record_plot(request):
671 def view_record_plot(request):
660 """view_record_plot returns the view individual record page.
672 """view_record_plot returns the view individual record page.
661
673
662 Inputs:
674 Inputs:
663 request
675 request
664 """
676 """
665 expDir = request.GET['expDir']
677 expDir = request.GET['expDir']
666 basename = request.GET['basename']
678 basename = request.GET['basename']
667 recno = int(request.GET['recno'])
679 recno = int(request.GET['recno'])
668
680
669 return render(request, 'madweb/view_record_plot.html', {'expDir': expDir,
681 return render(request, 'madweb/view_record_plot.html', {'expDir': expDir,
670 'basename': basename,
682 'basename': basename,
671 'recno': recno})
683 'recno': recno})
672
684
673
685
674 def view_record_image(request):
686 def view_record_image(request):
675 """view_record_plot is a Ajax call that returns the record plot.
687 """view_record_plot is a Ajax call that returns the record plot.
676
688
677 Inputs:
689 Inputs:
678 request
690 request
679 """
691 """
680 expDir = request.GET['expDir']
692 expDir = request.GET['expDir']
681 basename = request.GET['basename']
693 basename = request.GET['basename']
682 recno = int(request.GET['recno'])
694 recno = int(request.GET['recno'])
683 pngFiles = glob.glob(os.path.join(expDir, 'plots', basename, 'records/*%05i*.png' % (recno)))
695 pngFiles = glob.glob(os.path.join(expDir, 'plots', basename, 'records/*%05i*.png' % (recno)))
684
696
685 image_data = open(pngFiles[0], "rb").read()
697 image_data = open(pngFiles[0], "rb").read()
686 return HttpResponse(image_data, content_type="image/png")
698 return HttpResponse(image_data, content_type="image/png")
687
699
688
700
689
701
690
702
691 def show_info(request):
703 def show_info(request):
692 """show_info is a Ajax call that returns the text of the catalog/header text to support the
704 """show_info is a Ajax call that returns the text of the catalog/header text to support the
693 single experiment UI. Called when a user selects show info link.
705 single experiment UI. Called when a user selects show info link.
694
706
695 Inputs:
707 Inputs:
696 request
708 request
697 """
709 """
698 madDB = madrigal.metadata.MadrigalDB()
710 madDB = madrigal.metadata.MadrigalDB()
699 madExpObj = madrigal.metadata.MadrigalExperiment(madDB)
711 madExpObj = madrigal.metadata.MadrigalExperiment(madDB)
700
712
701 expID =int(request.GET['experiment_list'])
713 expID =int(request.GET['experiment_list'])
702 basename = request.GET['file_list']
714 basename = request.GET['file_list']
703 expDir = madExpObj.getExpDirByExpId(int(expID))
715 expDir = madExpObj.getExpDirByExpId(int(expID))
704 if expDir is None:
716 if expDir is None:
705 raise ValueError('No expDir found for exp_id %i' % (int(expID)))
717 raise ValueError('No expDir found for exp_id %i' % (int(expID)))
706 fullFilename = os.path.join(expDir, basename)
718 fullFilename = os.path.join(expDir, basename)
707
719
708 madFileObj = madrigal.data.MadrigalFile(fullFilename, madDB)
720 madFileObj = madrigal.data.MadrigalFile(fullFilename, madDB)
709 text = madFileObj.getCatalogHeaderStr()
721 text = madFileObj.getCatalogHeaderStr()
710
722
711 return render(request, 'madweb/show_info.html', {'text':text})
723 return render(request, 'madweb/show_info.html', {'text':text})
712
724
713
725
714 def show_doi(request):
726 def show_doi(request):
715 """show_doi is a Ajax call that returns the permanent url for references to support the
727 """show_doi is a Ajax call that returns the permanent url for references to support the
716 single experiment UI. Called when a user selects show doi link.
728 single experiment UI. Called when a user selects show doi link.
717
729
718 Inputs:
730 Inputs:
719 request
731 request
720 """
732 """
721 madDB = madrigal.metadata.MadrigalDB()
733 madDB = madrigal.metadata.MadrigalDB()
722 madExpObj = madrigal.metadata.MadrigalExperiment(madDB)
734 madExpObj = madrigal.metadata.MadrigalExperiment(madDB)
723 madInstObj = madrigal.metadata.MadrigalInstrument(madDB)
735 madInstObj = madrigal.metadata.MadrigalInstrument(madDB)
724
736
725 expID =request.GET['experiment_list']
737 expID =request.GET['experiment_list']
726 basename = request.GET['file_list']
738 basename = request.GET['file_list']
727 expDir = madExpObj.getExpDirByExpId(int(expID))
739 expDir = madExpObj.getExpDirByExpId(int(expID))
728 # get experiment PI and institution
740 # get experiment PI and institution
729 PI = madExpObj.getPIByExpId(int(expID))
741 PI = madExpObj.getPIByExpId(int(expID))
730 kinst = madExpObj.getKinstByExpId(int(expID))
742 kinst = madExpObj.getKinstByExpId(int(expID))
731 startDTList = madExpObj.getExpStartDateTimeByExpId(int(expID))
743 startDTList = madExpObj.getExpStartDateTimeByExpId(int(expID))
732 yearStr = str(startDTList[0])
744 yearStr = str(startDTList[0])
733 if PI is None:
745 if PI is None:
734 PI = madInstObj.getContactName(kinst)
746 PI = madInstObj.getContactName(kinst)
735 institution = madInstObj.getContactAddress1(kinst)
747 institution = madInstObj.getContactAddress1(kinst)
736
748
737 try:
749 try:
738 madFileObj = madrigal.metadata.MadrigalMetaFile(madDB, os.path.join(expDir, 'fileTab.txt'))
750 madFileObj = madrigal.metadata.MadrigalMetaFile(madDB, os.path.join(expDir, 'fileTab.txt'))
739 url = madFileObj.getFileDOIUrlByFilename(basename)
751 url = madFileObj.getFileDOIUrlByFilename(basename)
740 except:
752 except:
741 url = 'Unknown - please contact madrigal@haystack.mit.edu'
753 url = 'Unknown - please contact madrigal@haystack.mit.edu'
742
754
743 return render(request, 'madweb/show_doi.html', {'url':url, 'PI': PI, 'year': yearStr,
755 return render(request, 'madweb/show_doi.html', {'url':url, 'PI': PI, 'year': yearStr,
744 'institution': institution})
756 'institution': institution})
745
757
746
758
747 def get_advanced(request):
759 def get_advanced(request):
748 """get_advanced is a view that allows user to download/print files with selected parms
760 """get_advanced is a view that allows user to download/print files with selected parms
749 and filters.
761 and filters.
750
762
751 Inputs:
763 Inputs:
752 request
764 request
753 """
765 """
754 madDB = madrigal.metadata.MadrigalDB()
766 madDB = madrigal.metadata.MadrigalDB()
755 bg_color = madDB.getBackgroundColor()
767 bg_color = madDB.getBackgroundColor()
756 madWeb = madrigal.ui.web.MadrigalWeb(madDB)
768 madWeb = madrigal.ui.web.MadrigalWeb(madDB)
757 siteName, siteList = madWeb.getSiteInfo()
769 siteName, siteList = madWeb.getSiteInfo()
758 madExpObj = madrigal.metadata.MadrigalExperiment(madDB)
770 madExpObj = madrigal.metadata.MadrigalExperiment(madDB)
759 webFormatObj = madrigal.ui.web.MadrigalWebFormat()
771 webFormatObj = madrigal.ui.web.MadrigalWebFormat()
760 madParmObj = madrigal.data.MadrigalParameters(madDB)
772 madParmObj = madrigal.data.MadrigalParameters(madDB)
761 parmList = webFormatObj.getFormat('Comprehensive')
773 parmList = webFormatObj.getFormat('Comprehensive')
762 measParmList = []
774 measParmList = []
763 derivedParmList = []
775 derivedParmList = []
764 allParmList = []
776 allParmList = []
765 sureParmList = []
777 sureParmList = []
766
778
767 if 'experiment_list' in request.GET:
779 if 'experiment_list' in request.GET:
768 expID = int(request.GET['experiment_list'])
780 expID = int(request.GET['experiment_list'])
769 else:
781 else:
770 return(HttpResponse('<p>experiment_list required for getAdvanced</p>'))
782 return(HttpResponse('<p>experiment_list required for getAdvanced</p>'))
771 basename = request.GET['file_list']
783 basename = request.GET['file_list']
772 type = request.GET['type']
784 type = request.GET['type']
773 expDir = madExpObj.getExpDirByExpId(int(expID))
785 expDir = madExpObj.getExpDirByExpId(int(expID))
774 if expDir is None:
786 if expDir is None:
775 raise ValueError('No expDir found for exp_id %i' % (int(expID)))
787 raise ValueError('No expDir found for exp_id %i' % (int(expID)))
776 fullFilename = os.path.join(expDir, basename)
788 fullFilename = os.path.join(expDir, basename)
777 expName, kindatDesc = madWeb.getInfoFromFile(fullFilename)
789 expName, kindatDesc = madWeb.getInfoFromFile(fullFilename)
778 madFileObj = madrigal.data.MadrigalFile(fullFilename, madDB)
790 madFileObj = madrigal.data.MadrigalFile(fullFilename, madDB)
779 earliestTime = madFileObj.getEarliestTime()
791 earliestTime = madFileObj.getEarliestTime()
780 latestTime = madFileObj.getLatestTime()
792 latestTime = madFileObj.getLatestTime()
781 earliestDT = datetime.datetime(*earliestTime)
793 earliestDT = datetime.datetime(*earliestTime)
782 latestDT = datetime.datetime(*latestTime)
794 latestDT = datetime.datetime(*latestTime)
783 madFileObj.getMeasDervBothParmLists(parmList, measParmList, derivedParmList, allParmList, sureParmList)
795 madFileObj.getMeasDervBothParmLists(parmList, measParmList, derivedParmList, allParmList, sureParmList)
784 allParmDescList = madParmObj.getParmDescriptionList(allParmList)
796 allParmDescList = madParmObj.getParmDescriptionList(allParmList)
785
797
786 dataDict = {'type': type,
798 dataDict = {'type': type,
787 'fullFilename': fullFilename,
799 'fullFilename': fullFilename,
788 'madFileObj': madFileObj, 'parameters': [],
800 'madFileObj': madFileObj, 'parameters': [],
789 'measParmList': measParmList, 'derivedParmList': derivedParmList,
801 'measParmList': measParmList, 'derivedParmList': derivedParmList,
790 'allParmList': allParmList, 'allParmDescList': allParmDescList,
802 'allParmList': allParmList, 'allParmDescList': allParmDescList,
791 'madDB': madDB, 'madParmObj': madParmObj}
803 'madDB': madDB, 'madParmObj': madParmObj}
792
804
793 min_alt = madFileObj.getMinValidAltitude()
805 min_alt = madFileObj.getMinValidAltitude()
794 max_alt = madFileObj.getMaxValidAltitude()
806 max_alt = madFileObj.getMaxValidAltitude()
795 try:
807 try:
796 float(min_alt)
808 float(min_alt)
797 float(max_alt)
809 float(max_alt)
798 dataDict['min_alt'] = '%9.2f' % (min_alt)
810 dataDict['min_alt'] = '%9.2f' % (min_alt)
799 dataDict['max_alt'] = '%9.2f' % (max_alt)
811 dataDict['max_alt'] = '%9.2f' % (max_alt)
800 except:
812 except:
801 pass
813 pass
802
814
803 if 'AZM' in allParmList:
815 if 'AZM' in allParmList:
804 dataDict['min_az'] = '-180.0'
816 dataDict['min_az'] = '-180.0'
805 dataDict['max_az'] = '180.0'
817 dataDict['max_az'] = '180.0'
806 dataDict['min_az2'] = '0.0'
818 dataDict['min_az2'] = '0.0'
807 dataDict['max_az2'] = '0.0'
819 dataDict['max_az2'] = '0.0'
808
820
809 if 'ELM' in allParmList:
821 if 'ELM' in allParmList:
810 dataDict['min_el'] = '0.0'
822 dataDict['min_el'] = '0.0'
811 dataDict['max_el'] = '90.0'
823 dataDict['max_el'] = '90.0'
812 dataDict['min_el2'] = '0.0'
824 dataDict['min_el2'] = '0.0'
813 dataDict['max_el2'] = '0.0'
825 dataDict['max_el2'] = '0.0'
814
826
815 if 'PL' in allParmList:
827 if 'PL' in allParmList:
816 min_pl = madFileObj.getMinPulseLength()
828 min_pl = madFileObj.getMinPulseLength()
817 max_pl = madFileObj.getMaxPulseLength()
829 max_pl = madFileObj.getMaxPulseLength()
818 try:
830 try:
819 float(min_pl)
831 float(min_pl)
820 float(max_pl)
832 float(max_pl)
821 dataDict['min_pl'] = '%9.2f' % (min_pl)
833 dataDict['min_pl'] = '%9.2f' % (min_pl)
822 dataDict['max_pl'] = '%9.2f' % (max_pl)
834 dataDict['max_pl'] = '%9.2f' % (max_pl)
823 except:
835 except:
824 pass
836 pass
825
837
826 if type == 'download':
838 if type == 'download':
827 defaultFormat = 'Hdf5'
839 defaultFormat = 'Hdf5'
828 else:
840 else:
829 defaultFormat = 'ascii'
841 defaultFormat = 'ascii'
830 dataDict['formats'] = defaultFormat
842 dataDict['formats'] = defaultFormat
831 dataDict['missing'] = 'NaN'
843 dataDict['missing'] = 'NaN'
832 dataDict['start_date'] = earliestDT
844 dataDict['start_date'] = earliestDT
833 dataDict['end_date'] = latestDT
845 dataDict['end_date'] = latestDT
834
846
835
847
836 isprintForm = madweb.forms.IsprintForm(dataDict)
848 isprintForm = madweb.forms.IsprintForm(dataDict)
837
849
838 return render(request, 'madweb/get_advanced.html', {'form': isprintForm,
850 return render(request, 'madweb/get_advanced.html', {'form': isprintForm,
839 'parmList': isprintForm.parmList,
851 'parmList': isprintForm.parmList,
840 'measParmList': measParmList,
852 'measParmList': measParmList,
841 'site_name': siteName, 'site_list': siteList,
853 'site_name': siteName, 'site_list': siteList,
842 'expName': expName, 'kindatDesc': kindatDesc,
854 'expName': expName, 'kindatDesc': kindatDesc,
843 'basename': os.path.basename(fullFilename),
855 'basename': os.path.basename(fullFilename),
844 'type': type, 'bg_color': bg_color,
856 'type': type, 'bg_color': bg_color,
845 'datetime': True})
857 'datetime': True})
846
858
847 def advanced_download(request):
859 def advanced_download(request):
848 """advanced_download is a view that downloads a file with selected parms
860 """advanced_download is a view that downloads a file with selected parms
849 and filters.
861 and filters.
850
862
851 Inputs:
863 Inputs:
852 request
864 request
853 """
865 """
854 madDB = madrigal.metadata.MadrigalDB()
866 madDB = madrigal.metadata.MadrigalDB()
855 madWeb = madrigal.ui.web.MadrigalWeb(madDB)
867 madWeb = madrigal.ui.web.MadrigalWeb(madDB)
856 webFormatObj = madrigal.ui.web.MadrigalWebFormat()
868 webFormatObj = madrigal.ui.web.MadrigalWebFormat()
857 madParmObj = madrigal.data.MadrigalParameters(madDB)
869 madParmObj = madrigal.data.MadrigalParameters(madDB)
858
870
859 cookieDict = request.COOKIES
871 cookieDict = request.COOKIES
860 if not 'user_fullname' in cookieDict:
872 if not 'user_fullname' in cookieDict:
861 return(HttpResponse('<p>Cookie with user_fullname required for advancedDownload</p>'))
873 return(HttpResponse('<p>Cookie with user_fullname required for advancedDownload</p>'))
862 user_fullname = django.utils.http.urlquote_plus(cookieDict['user_fullname'])
874 user_fullname = django.utils.http.urlquote_plus(cookieDict['user_fullname'])
863 user_email = cookieDict['user_email']
875 user_email = cookieDict['user_email']
864 user_affiliation = django.utils.http.urlquote_plus(cookieDict['user_affiliation'])
876 user_affiliation = django.utils.http.urlquote_plus(cookieDict['user_affiliation'])
865
877
866 parmList = webFormatObj.getFormat('Comprehensive')
878 parmList = webFormatObj.getFormat('Comprehensive')
867 measParmList = []
879 measParmList = []
868 derivedParmList = []
880 derivedParmList = []
869 allParmList = []
881 allParmList = []
870 sureParmList = []
882 sureParmList = []
871 madFileObj = madrigal.data.MadrigalFile(request.GET['fullFilename'], madDB)
883 madFileObj = madrigal.data.MadrigalFile(request.GET['fullFilename'], madDB)
872 madFileObj.getMeasDervBothParmLists(parmList, measParmList, derivedParmList, allParmList, sureParmList)
884 madFileObj.getMeasDervBothParmLists(parmList, measParmList, derivedParmList, allParmList, sureParmList)
873 allParmDescList = madParmObj.getParmDescriptionList(allParmList)
885 allParmDescList = madParmObj.getParmDescriptionList(allParmList)
874
886
875 request.GET._mutable = True
887 request.GET._mutable = True
876 request.GET['madFileObj']=madFileObj
888 request.GET['madFileObj']=madFileObj
877 request.GET['measParmList']=measParmList
889 request.GET['measParmList']=measParmList
878 request.GET['derivedParmList']=derivedParmList
890 request.GET['derivedParmList']=derivedParmList
879 request.GET['allParmList']=allParmList
891 request.GET['allParmList']=allParmList
880 request.GET['allParmDescList']=allParmDescList
892 request.GET['allParmDescList']=allParmDescList
881 request.GET['start_date'] = request.GET['start_date'].strip()
893 request.GET['start_date'] = request.GET['start_date'].strip()
882 request.GET['end_date'] = request.GET['end_date'].strip()
894 request.GET['end_date'] = request.GET['end_date'].strip()
883 # convert dates to datetime
895 # convert dates to datetime
884 request.GET['start_date'] = datetime.datetime.strptime(request.GET['start_date'], '%Y-%m-%dT%H:%M:%S')
896 request.GET['start_date'] = datetime.datetime.strptime(request.GET['start_date'], '%Y-%m-%dT%H:%M:%S')
885 request.GET['end_date'] = datetime.datetime.strptime(request.GET['end_date'], '%Y-%m-%dT%H:%M:%S')
897 request.GET['end_date'] = datetime.datetime.strptime(request.GET['end_date'], '%Y-%m-%dT%H:%M:%S')
886 request.GET['madDB'] = madDB
898 request.GET['madDB'] = madDB
887 request.GET['madParmObj'] = madParmObj
899 request.GET['madParmObj'] = madParmObj
888
900
889
901
890 isprintForm = madweb.forms.IsprintForm(request.GET)
902 isprintForm = madweb.forms.IsprintForm(request.GET)
891
903
892
904
893 if not isprintForm.is_valid():
905 if not isprintForm.is_valid():
894 raise ValueError(str(isprintForm.errors))
906 raise ValueError(str(isprintForm.errors))
895
907
896 downloadFile = madWeb.downloadIsprintFileFromIsprintForm(isprintForm.cleaned_data, user_fullname, user_email, user_affiliation)
908 downloadFile = madWeb.downloadIsprintFileFromIsprintForm(isprintForm.cleaned_data, user_fullname, user_email, user_affiliation)
897
909
898
910
899 f = open(downloadFile, 'rb')
911 f = open(downloadFile, 'rb')
900 filename = os.path.basename(downloadFile)
912 filename = os.path.basename(downloadFile)
901 chunk_size = 8192
913 chunk_size = 8192
902 file_type = mimetypes.guess_type(downloadFile)[0]
914 file_type = mimetypes.guess_type(downloadFile)[0]
903 if file_type is None:
915 if file_type is None:
904 file_type = 'application/octet-stream'
916 file_type = 'application/octet-stream'
905 response = StreamingHttpResponse(FileWrapper(f, chunk_size),
917 response = StreamingHttpResponse(FileWrapper(f, chunk_size),
906 content_type=file_type)
918 content_type=file_type)
907 response['Content-Length'] = os.path.getsize(downloadFile)
919 response['Content-Length'] = os.path.getsize(downloadFile)
908 response['Content-Disposition'] = "attachment; filename=%s" % (filename)
920 response['Content-Disposition'] = "attachment; filename=%s" % (filename)
909 return(response)
921 return(response)
910
922
911
923
912 def advanced_print(request):
924 def advanced_print(request):
913 """advanced_download is a view that print a file with selected parms
925 """advanced_download is a view that print a file with selected parms
914 and filters.
926 and filters.
915
927
916 Inputs:
928 Inputs:
917 request
929 request
918 """
930 """
919 madDB = madrigal.metadata.MadrigalDB()
931 madDB = madrigal.metadata.MadrigalDB()
920 bg_color = madDB.getBackgroundColor()
932 bg_color = madDB.getBackgroundColor()
921 madWeb = madrigal.ui.web.MadrigalWeb(madDB)
933 madWeb = madrigal.ui.web.MadrigalWeb(madDB)
922 webFormatObj = madrigal.ui.web.MadrigalWebFormat()
934 webFormatObj = madrigal.ui.web.MadrigalWebFormat()
923 madParmObj = madrigal.data.MadrigalParameters(madDB)
935 madParmObj = madrigal.data.MadrigalParameters(madDB)
924
936
925 cookieDict = request.COOKIES
937 cookieDict = request.COOKIES
926 if not 'user_fullname' in cookieDict:
938 if not 'user_fullname' in cookieDict:
927 return(HttpResponse('<p>Cookie with user_fullname required for advancedPrint</p>'))
939 return(HttpResponse('<p>Cookie with user_fullname required for advancedPrint</p>'))
928 user_fullname = django.utils.http.urlquote_plus(cookieDict['user_fullname'])
940 user_fullname = django.utils.http.urlquote_plus(cookieDict['user_fullname'])
929 user_email = cookieDict['user_email']
941 user_email = cookieDict['user_email']
930 user_affiliation = django.utils.http.urlquote_plus(cookieDict['user_affiliation'])
942 user_affiliation = django.utils.http.urlquote_plus(cookieDict['user_affiliation'])
931
943
932 parmList = webFormatObj.getFormat('Comprehensive')
944 parmList = webFormatObj.getFormat('Comprehensive')
933 measParmList = []
945 measParmList = []
934 derivedParmList = []
946 derivedParmList = []
935 allParmList = []
947 allParmList = []
936 sureParmList = []
948 sureParmList = []
937 madFileObj = madrigal.data.MadrigalFile(request.GET['fullFilename'], madDB)
949 madFileObj = madrigal.data.MadrigalFile(request.GET['fullFilename'], madDB)
938 madFileObj.getMeasDervBothParmLists(parmList, measParmList, derivedParmList, allParmList, sureParmList)
950 madFileObj.getMeasDervBothParmLists(parmList, measParmList, derivedParmList, allParmList, sureParmList)
939 allParmDescList = madParmObj.getParmDescriptionList(allParmList)
951 allParmDescList = madParmObj.getParmDescriptionList(allParmList)
940 fullFilename = request.GET['fullFilename']
952 fullFilename = request.GET['fullFilename']
941 expName, kindatDesc = madWeb.getInfoFromFile(fullFilename)
953 expName, kindatDesc = madWeb.getInfoFromFile(fullFilename)
942
954
943 request.GET._mutable = True
955 request.GET._mutable = True
944 request.GET['madFileObj']=madFileObj
956 request.GET['madFileObj']=madFileObj
945 request.GET['measParmList']=measParmList
957 request.GET['measParmList']=measParmList
946 request.GET['derivedParmList']=derivedParmList
958 request.GET['derivedParmList']=derivedParmList
947 request.GET['allParmList']=allParmList
959 request.GET['allParmList']=allParmList
948 request.GET['allParmDescList']=allParmDescList
960 request.GET['allParmDescList']=allParmDescList
949 request.GET['start_date'] = request.GET['start_date'].strip()
961 request.GET['start_date'] = request.GET['start_date'].strip()
950 request.GET['end_date'] = request.GET['end_date'].strip()
962 request.GET['end_date'] = request.GET['end_date'].strip()
951 # convert dates to datetime
963 # convert dates to datetime
952 request.GET['start_date'] = datetime.datetime.strptime(request.GET['start_date'], '%Y-%m-%dT%H:%M:%S')
964 request.GET['start_date'] = datetime.datetime.strptime(request.GET['start_date'], '%Y-%m-%dT%H:%M:%S')
953 request.GET['end_date'] = datetime.datetime.strptime(request.GET['end_date'], '%Y-%m-%dT%H:%M:%S')
965 request.GET['end_date'] = datetime.datetime.strptime(request.GET['end_date'], '%Y-%m-%dT%H:%M:%S')
954 request.GET['madDB'] = madDB
966 request.GET['madDB'] = madDB
955 request.GET['madParmObj'] = madParmObj
967 request.GET['madParmObj'] = madParmObj
956
968
957 isprintForm = madweb.forms.IsprintForm(request.GET)
969 isprintForm = madweb.forms.IsprintForm(request.GET)
958
970
959
971
960 if not isprintForm.is_valid():
972 if not isprintForm.is_valid():
961 raise ValueError(str(isprintForm.errors))
973 raise ValueError(str(isprintForm.errors))
962
974
963 downloadFile = madWeb.downloadIsprintFileFromIsprintForm(isprintForm.cleaned_data, user_fullname, user_email, user_affiliation)
975 downloadFile = madWeb.downloadIsprintFileFromIsprintForm(isprintForm.cleaned_data, user_fullname, user_email, user_affiliation)
964
976
965 f = open(downloadFile, 'r')
977 f = open(downloadFile, 'r')
966 file_text = f.read()
978 file_text = f.read()
967 f.close()
979 f.close()
968 os.remove(downloadFile)
980 os.remove(downloadFile)
969 return render(request, 'madweb/advanced_print.html', {'expName': expName, 'kindatDesc': kindatDesc,
981 return render(request, 'madweb/advanced_print.html', {'expName': expName, 'kindatDesc': kindatDesc,
970 'basename': os.path.basename(fullFilename),
982 'basename': os.path.basename(fullFilename),
971 'file_text': file_text, 'bg_color': bg_color})
983 'file_text': file_text, 'bg_color': bg_color})
972
984
973
985
974 def view_list(request):
986 def view_list(request):
975 """view_list is the list experiment view.
987 """view_list is the list experiment view.
976 """
988 """
977 madDB = madrigal.metadata.MadrigalDB()
989 madDB = madrigal.metadata.MadrigalDB()
978 bg_color = madDB.getBackgroundColor()
990 bg_color = madDB.getBackgroundColor()
979 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
991 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
980 siteName, siteList = madWebObj.getSiteInfo()
992 siteName, siteList = madWebObj.getSiteInfo()
981 responseDict = {'list_active': 'class="active"'}
993 responseDict = {'list_active': 'class="active"'}
982 form = madweb.forms.ListExpForm()
994 form = madweb.forms.ListExpForm()
983 responseDict['form'] = form
995 responseDict['form'] = form
984 responseDict['categoryList'] = form.categories
996 responseDict['categoryList'] = form.categories
985 responseDict['instrumentList'] = form.instruments
997 responseDict['instrumentList'] = form.instruments
986 responseDict['site_name'] = siteName
998 responseDict['site_name'] = siteName
987 responseDict['site_list'] = siteList
999 responseDict['site_list'] = siteList
988 responseDict['datetime'] = True
1000 responseDict['datetime'] = True
989 responseDict['bg_color'] = bg_color
1001 responseDict['bg_color'] = bg_color
990
1002
991 return render(request, 'madweb/list.html', responseDict)
1003 return render(request, 'madweb/list.html', responseDict)
992
1004
993
1005
994 def list_experiments(request):
1006 def list_experiments(request):
995 """list_experiments is a view that lists all selected experiments.
1007 """list_experiments is a view that lists all selected experiments.
996
1008
997 Inputs:
1009 Inputs:
998 request
1010 request
999 """
1011 """
1000 madDB = madrigal.metadata.MadrigalDB()
1012 madDB = madrigal.metadata.MadrigalDB()
1001 bg_color = madDB.getBackgroundColor()
1013 bg_color = madDB.getBackgroundColor()
1002 madWeb = madrigal.ui.web.MadrigalWeb(madDB)
1014 madWeb = madrigal.ui.web.MadrigalWeb(madDB)
1003 siteName, siteList = madWeb.getSiteInfo()
1015 siteName, siteList = madWeb.getSiteInfo()
1004
1016
1005 listForm = madweb.forms.ListExpForm(request.GET)
1017 listForm = madweb.forms.ListExpForm(request.GET)
1006 try:
1018 try:
1007 if not listForm.is_valid():
1019 if not listForm.is_valid():
1008 return(HttpResponse(str(listForm.errors)))
1020 return(HttpResponse(str(listForm.errors)))
1009 except KeyError:
1021 except KeyError:
1010 return(HttpResponse('<p>Missing arguments in list_experiments</p>'))
1022 return(HttpResponse('<p>Missing arguments in list_experiments</p>'))
1011
1023
1012 kinstList = [int(kinst) for kinst in listForm.cleaned_data['instruments']]
1024 kinstList = [int(kinst) for kinst in listForm.cleaned_data['instruments']]
1013 startDate = listForm.cleaned_data['start_date']
1025 startDate = listForm.cleaned_data['start_date']
1014 startDT = datetime.datetime(startDate.year, startDate.month, startDate.day, 0, 0, 0)
1026 startDT = datetime.datetime(startDate.year, startDate.month, startDate.day, 0, 0, 0)
1015 endDate = listForm.cleaned_data['end_date']
1027 endDate = listForm.cleaned_data['end_date']
1016 endDT = datetime.datetime(endDate.year, endDate.month, endDate.day, 23, 59, 59)
1028 endDT = datetime.datetime(endDate.year, endDate.month, endDate.day, 23, 59, 59)
1017 localOnly = not listForm.cleaned_data['isGlobal']
1029 localOnly = not listForm.cleaned_data['isGlobal']
1018 expList = madWeb.getExperimentList(kinstList, startDT, endDT, localOnly)
1030 expList = madWeb.getExperimentList(kinstList, startDT, endDT, localOnly)
1019
1031
1020 return render(request, 'madweb/list_experiments.html', {'expList':expList, 'localOnly':localOnly,
1032 return render(request, 'madweb/list_experiments.html', {'expList':expList, 'localOnly':localOnly,
1021 'list_active': 'class="active"', 'site_name': siteName,
1033 'list_active': 'class="active"', 'site_name': siteName,
1022 'site_list': siteList, 'bg_color': bg_color})
1034 'site_list': siteList, 'bg_color': bg_color})
1023
1035
1024
1036
1025 def show_experiment(request):
1037 def show_experiment(request):
1026 """show_experiment call that returns the experiment page to support the list experiments UI.
1038 """show_experiment call that returns the experiment page to support the list experiments UI.
1027
1039
1028 Inputs:
1040 Inputs:
1029 request
1041 request
1030 """
1042 """
1031 madDB = madrigal.metadata.MadrigalDB()
1043 madDB = madrigal.metadata.MadrigalDB()
1032 bg_color = madDB.getBackgroundColor()
1044 bg_color = madDB.getBackgroundColor()
1033 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1045 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1034 siteName, siteList = madWebObj.getSiteInfo()
1046 siteName, siteList = madWebObj.getSiteInfo()
1035 cookieDict = request.COOKIES
1047 cookieDict = request.COOKIES
1036 user_email = cookieDict['user_email']
1048 user_email = cookieDict['user_email']
1037 queryDict = request.GET.copy()
1049 queryDict = request.GET.copy()
1038 queryDict['user_email'] = user_email
1050 queryDict['user_email'] = user_email
1039 if 'show_plots' in queryDict:
1051 if 'show_plots' in queryDict:
1040 plotsForm = madweb.forms.SingleExpPlotsForm(queryDict)
1052 plotsForm = madweb.forms.SingleExpPlotsForm(queryDict)
1041 form = madweb.forms.SingleExpFileForm(queryDict)
1053 form = madweb.forms.SingleExpFileForm(queryDict)
1042 if 'show_plots' in queryDict:
1054 if 'show_plots' in queryDict:
1043 form.fields['plot_list'] = plotsForm.fields['plot_list']
1055 form.fields['plot_list'] = plotsForm.fields['plot_list']
1044 if len(form.fields['file_list'].choices) > 1:
1056 if len(form.fields['file_list'].choices) > 1:
1045 # this experiment has data files
1057 # this experiment has data files
1046 return render(request, 'madweb/show_experiment.html', {'list_active': 'class="active"',
1058 return render(request, 'madweb/show_experiment.html', {'list_active': 'class="active"',
1047 'form': form, 'site_name': siteName,
1059 'form': form, 'site_name': siteName,
1048 'site_list': siteList,
1060 'site_list': siteList,
1049 'loader': 'loadPage',
1061 'loader': 'loadPage',
1050 'bg_color': bg_color,
1062 'bg_color': bg_color,
1051 'redirect': reverse('show_experiment')})
1063 'redirect': reverse('show_experiment')})
1052
1064
1053 else:
1065 else:
1054 # this experiment has no data files
1066 # this experiment has no data files
1055 form2 = madweb.forms.SingleExpPlotsForm(request.GET)
1067 form2 = madweb.forms.SingleExpPlotsForm(request.GET)
1056 exp_desc = form.fields['exp_desc'].label
1068 exp_desc = form.fields['exp_desc'].label
1057 return render(request, 'madweb/show_exp_no_files.html', {'list_active': 'class="active"',
1069 return render(request, 'madweb/show_exp_no_files.html', {'list_active': 'class="active"',
1058 'form': form2, 'exp_desc': exp_desc,
1070 'form': form2, 'exp_desc': exp_desc,
1059 'site_name': siteName,
1071 'site_name': siteName,
1060 'site_list': siteList,
1072 'site_list': siteList,
1061 'loader': 'loadPage',
1073 'loader': 'loadPage',
1062 'bg_color': bg_color,
1074 'bg_color': bg_color,
1063 'redirect': reverse('show_experiment')})
1075 'redirect': reverse('show_experiment')})
1064
1076
1065
1077
1066 def show_experiment_v2(request):
1078 def show_experiment_v2(request):
1067 """show_experiment_v2 is a slight variant of show_experiment to accept old form
1079 """show_experiment_v2 is a slight variant of show_experiment to accept old form
1068 calls from Madrigal2 sites.
1080 calls from Madrigal2 sites.
1069
1081
1070 Inputs:
1082 Inputs:
1071 request
1083 request
1072 """
1084 """
1073 madDB = madrigal.metadata.MadrigalDB()
1085 madDB = madrigal.metadata.MadrigalDB()
1074 bg_color = madDB.getBackgroundColor()
1086 bg_color = madDB.getBackgroundColor()
1075 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1087 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1076 siteName, siteList = madWebObj.getSiteInfo()
1088 siteName, siteList = madWebObj.getSiteInfo()
1077 cookieDict = request.COOKIES
1089 cookieDict = request.COOKIES
1078 user_email = cookieDict['user_email']
1090 user_email = cookieDict['user_email']
1079 queryDict = request.GET.copy()
1091 queryDict = request.GET.copy()
1080 queryDict['user_email'] = user_email
1092 queryDict['user_email'] = user_email
1081 queryDict['experiment_list'] = queryDict['exp']
1093 queryDict['experiment_list'] = queryDict['exp']
1082 form = madweb.forms.SingleExpFileForm(queryDict)
1094 form = madweb.forms.SingleExpFileForm(queryDict)
1083
1095
1084 return render(request, 'madweb/show_experiment.html', {'list_active': 'class="active"',
1096 return render(request, 'madweb/show_experiment.html', {'list_active': 'class="active"',
1085 'form': form, 'site_name': siteName,
1097 'form': form, 'site_name': siteName,
1086 'site_list': siteList,
1098 'site_list': siteList,
1087 'loader': 'loadPage',
1099 'loader': 'loadPage',
1088 'bg_color': bg_color,
1100 'bg_color': bg_color,
1089 'redirect': reverse('show_experiment')})
1101 'redirect': reverse('show_experiment')})
1090
1102
1091
1103
1092 def choose_script(request):
1104 def choose_script(request):
1093 """choose_script that returns the choose script page.
1105 """choose_script that returns the choose script page.
1094
1106
1095 Inputs:
1107 Inputs:
1096 request
1108 request
1097 """
1109 """
1098 madDB = madrigal.metadata.MadrigalDB()
1110 madDB = madrigal.metadata.MadrigalDB()
1099 bg_color = madDB.getBackgroundColor()
1111 bg_color = madDB.getBackgroundColor()
1100 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1112 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1101 siteName, siteList = madWebObj.getSiteInfo()
1113 siteName, siteList = madWebObj.getSiteInfo()
1102 return render(request, 'madweb/choose_script.html', {'script_active': 'class="active"', 'site_name': siteName,
1114 return render(request, 'madweb/choose_script.html', {'script_active': 'class="active"', 'site_name': siteName,
1103 'site_list': siteList, 'bg_color': bg_color})
1115 'site_list': siteList, 'bg_color': bg_color})
1104
1116
1105
1117
1106 def download_as_is_script(request):
1118 def download_as_is_script(request):
1107 """download_as_is_script that returns the download_as_is_script script page.
1119 """download_as_is_script that returns the download_as_is_script script page.
1108
1120
1109 Inputs:
1121 Inputs:
1110 request
1122 request
1111 """
1123 """
1112 madDB = madrigal.metadata.MadrigalDB()
1124 madDB = madrigal.metadata.MadrigalDB()
1113 bg_color = madDB.getBackgroundColor()
1125 bg_color = madDB.getBackgroundColor()
1114 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1126 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1115 siteName, siteList = madWebObj.getSiteInfo()
1127 siteName, siteList = madWebObj.getSiteInfo()
1116 responseDict = {'script_active': 'class="active"'}
1128 responseDict = {'script_active': 'class="active"'}
1117 form = madweb.forms.DownloadAsIsScriptForm()
1129 form = madweb.forms.DownloadAsIsScriptForm()
1118 responseDict['form'] = form
1130 responseDict['form'] = form
1119 responseDict['categoryList'] = form.categories
1131 responseDict['categoryList'] = form.categories
1120 responseDict['instrumentList'] = form.instruments
1132 responseDict['instrumentList'] = form.instruments
1121 responseDict['kindatList'] = form.kindats
1133 responseDict['kindatList'] = form.kindats
1122 responseDict['site_name'] = siteName
1134 responseDict['site_name'] = siteName
1123 responseDict['site_list'] = siteList
1135 responseDict['site_list'] = siteList
1124 responseDict['datetime'] = True
1136 responseDict['datetime'] = True
1125 responseDict['bg_color'] = bg_color
1137 responseDict['bg_color'] = bg_color
1126
1138
1127 return render(request, 'madweb/download_as_is_script.html', responseDict)
1139 return render(request, 'madweb/download_as_is_script.html', responseDict)
1128
1140
1129
1141
1130 def generate_download_files_script(request):
1142 def generate_download_files_script(request):
1131 """generate_download_files_script is a Ajax call that returns the generated file download script.
1143 """generate_download_files_script is a Ajax call that returns the generated file download script.
1132
1144
1133 Inputs:
1145 Inputs:
1134 request
1146 request
1135 """
1147 """
1136 form = madweb.forms.DownloadAsIsScriptForm(request.GET)
1148 form = madweb.forms.DownloadAsIsScriptForm(request.GET)
1137 if not form.is_valid():
1149 if not form.is_valid():
1138 raise ValueError('Form error: %s' % (form.errors))
1150 raise ValueError('Form error: %s' % (form.errors))
1139 cookieDict = request.COOKIES
1151 cookieDict = request.COOKIES
1140 if not 'user_fullname' in cookieDict:
1152 if not 'user_fullname' in cookieDict:
1141 return(HttpResponse('<p>Cookie with user_fullname required for generateDownloadFilesScript</p>'))
1153 return(HttpResponse('<p>Cookie with user_fullname required for generateDownloadFilesScript</p>'))
1142 user_fullname = django.utils.http.urlquote_plus(cookieDict['user_fullname'])
1154 user_fullname = django.utils.http.urlquote_plus(cookieDict['user_fullname'])
1143 user_email = cookieDict['user_email']
1155 user_email = cookieDict['user_email']
1144 user_affiliation = django.utils.http.urlquote_plus(cookieDict['user_affiliation'])
1156 user_affiliation = django.utils.http.urlquote_plus(cookieDict['user_affiliation'])
1145 madWebObj = madrigal.ui.web.MadrigalWeb()
1157 madWebObj = madrigal.ui.web.MadrigalWeb()
1146 script_text = madWebObj.generateDownloadFileScriptFromForm(form.cleaned_data, user_fullname,
1158 script_text = madWebObj.generateDownloadFileScriptFromForm(form.cleaned_data, user_fullname,
1147 user_email, user_affiliation)
1159 user_email, user_affiliation)
1148 return render(request, 'madweb/download_files_script.html', {'script_text': script_text})
1160 return render(request, 'madweb/download_files_script.html', {'script_text': script_text})
1149
1161
1150
1162
1151 def download_advanced_script(request):
1163 def download_advanced_script(request):
1152 """download_advanced_script that returns the download_advanced_script script page.
1164 """download_advanced_script that returns the download_advanced_script script page.
1153
1165
1154 Inputs:
1166 Inputs:
1155 request
1167 request
1156 """
1168 """
1157 madDB = madrigal.metadata.MadrigalDB()
1169 madDB = madrigal.metadata.MadrigalDB()
1158 bg_color = madDB.getBackgroundColor()
1170 bg_color = madDB.getBackgroundColor()
1159 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1171 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1160 siteName, siteList = madWebObj.getSiteInfo()
1172 siteName, siteList = madWebObj.getSiteInfo()
1161 responseDict = {'script_active': 'class="active"'}
1173 responseDict = {'script_active': 'class="active"'}
1162 form = madweb.forms.DownloadAdvancedScriptForm()
1174 form = madweb.forms.DownloadAdvancedScriptForm()
1163 responseDict['form'] = form
1175 responseDict['form'] = form
1164 responseDict['categoryList'] = form.categories
1176 responseDict['categoryList'] = form.categories
1165 responseDict['instrumentList'] = form.instruments
1177 responseDict['instrumentList'] = form.instruments
1166 responseDict['kindatList'] = form.kindats
1178 responseDict['kindatList'] = form.kindats
1167 responseDict['site_name'] = siteName
1179 responseDict['site_name'] = siteName
1168 responseDict['site_list'] = siteList
1180 responseDict['site_list'] = siteList
1169 responseDict['datetime'] = True
1181 responseDict['datetime'] = True
1170 responseDict['bg_color'] = bg_color
1182 responseDict['bg_color'] = bg_color
1171
1183
1172 return render(request, 'madweb/download_advanced_script.html', responseDict)
1184 return render(request, 'madweb/download_advanced_script.html', responseDict)
1173
1185
1174
1186
1175 def generate_download_advanced_script(request):
1187 def generate_download_advanced_script(request):
1176 """generate_download_advanced_script is a Ajax call that returns the generated advanced download script.
1188 """generate_download_advanced_script is a Ajax call that returns the generated advanced download script.
1177
1189
1178 Inputs:
1190 Inputs:
1179 request
1191 request
1180 """
1192 """
1181 form1 = madweb.forms.DownloadAdvancedScriptForm(request.GET)
1193 form1 = madweb.forms.DownloadAdvancedScriptForm(request.GET)
1182 if not form1.is_valid():
1194 if not form1.is_valid():
1183 raise ValueError('Form error: %s' % (form1.errors))
1195 raise ValueError('Form error: %s' % (form1.errors))
1184 form2 = madweb.forms.AdvScriptParmsForm(request.GET)
1196 form2 = madweb.forms.AdvScriptParmsForm(request.GET)
1185 if not form2.is_valid():
1197 if not form2.is_valid():
1186 raise ValueError('Form error: %s' % (form2.errors))
1198 raise ValueError('Form error: %s' % (form2.errors))
1187 form3 = madweb.forms.AdvScriptParmsFiltersForm(request.GET)
1199 form3 = madweb.forms.AdvScriptParmsFiltersForm(request.GET)
1188 if not form3.is_valid():
1200 if not form3.is_valid():
1189 raise ValueError('Form error: %s' % (form3.errors))
1201 raise ValueError('Form error: %s' % (form3.errors))
1190 cookieDict = request.COOKIES
1202 cookieDict = request.COOKIES
1191 if not 'user_fullname' in cookieDict:
1203 if not 'user_fullname' in cookieDict:
1192 return(HttpResponse('<p>Cookie with user_fullname required for generateAdvancedDownloadScript</p>'))
1204 return(HttpResponse('<p>Cookie with user_fullname required for generateAdvancedDownloadScript</p>'))
1193 user_fullname = django.utils.http.urlquote_plus(cookieDict['user_fullname'])
1205 user_fullname = django.utils.http.urlquote_plus(cookieDict['user_fullname'])
1194 user_email = cookieDict['user_email']
1206 user_email = cookieDict['user_email']
1195 user_affiliation = django.utils.http.urlquote_plus(cookieDict['user_affiliation'])
1207 user_affiliation = django.utils.http.urlquote_plus(cookieDict['user_affiliation'])
1196 madWebObj = madrigal.ui.web.MadrigalWeb()
1208 madWebObj = madrigal.ui.web.MadrigalWeb()
1197 script_text = madWebObj.generateGlobalIsprintScriptFromForm(form1.cleaned_data, form2.cleaned_data,
1209 script_text = madWebObj.generateGlobalIsprintScriptFromForm(form1.cleaned_data, form2.cleaned_data,
1198 form3.cleaned_data, user_fullname,
1210 form3.cleaned_data, user_fullname,
1199 user_email, user_affiliation)
1211 user_email, user_affiliation)
1200 return render(request, 'madweb/download_files_script.html', {'script_text': script_text})
1212 return render(request, 'madweb/download_files_script.html', {'script_text': script_text})
1201
1213
1202
1214
1203 def generate_parms_script(request):
1215 def generate_parms_script(request):
1204 """generate_parms_script is a Ajax call that returns the generated parameter script.
1216 """generate_parms_script is a Ajax call that returns the generated parameter script.
1205
1217
1206 Inputs:
1218 Inputs:
1207 request
1219 request
1208 """
1220 """
1209 form = madweb.forms.AdvScriptParmsForm(request.GET)
1221 form = madweb.forms.AdvScriptParmsForm(request.GET)
1210 return render(request, 'madweb/download_adv_parms_script.html', {'form': form,
1222 return render(request, 'madweb/download_adv_parms_script.html', {'form': form,
1211 'parmList': form.parmList})
1223 'parmList': form.parmList})
1212
1224
1213
1225
1214 def generate_parms_filters_script(request):
1226 def generate_parms_filters_script(request):
1215 """generate_parms_filters_script is a Ajax call that returns the generated parameter filters script.
1227 """generate_parms_filters_script is a Ajax call that returns the generated parameter filters script.
1216
1228
1217 Inputs:
1229 Inputs:
1218 request
1230 request
1219 """
1231 """
1220 form = madweb.forms.AdvScriptParmsFiltersForm(request.GET)
1232 form = madweb.forms.AdvScriptParmsFiltersForm(request.GET)
1221 return render(request, 'madweb/download_adv_parms_filters_script.html', {'form': form})
1233 return render(request, 'madweb/download_adv_parms_filters_script.html', {'form': form})
1222
1234
1223
1235
1224 def ftp(request):
1236 def ftp(request):
1225 """ftp creates the first ftp page listing instruments
1237 """ftp creates the first ftp page listing instruments
1226 """
1238 """
1227 madDB = madrigal.metadata.MadrigalDB()
1239 madDB = madrigal.metadata.MadrigalDB()
1228 bg_color = madDB.getBackgroundColor()
1240 bg_color = madDB.getBackgroundColor()
1229 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1241 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1230 siteName, siteList = madWebObj.getSiteInfo()
1242 siteName, siteList = madWebObj.getSiteInfo()
1231 cookieDict = request.COOKIES
1243 cookieDict = request.COOKIES
1232 if not 'user_fullname' in cookieDict:
1244 if not 'user_fullname' in cookieDict:
1233 return(HttpResponse('<p>Cookie with user_fullname required for ftp</p>'))
1245 return(HttpResponse('<p>Cookie with user_fullname required for ftp</p>'))
1234 fullname = django.utils.http.urlquote_plus(cookieDict['user_fullname'])
1246 fullname = django.utils.http.urlquote_plus(cookieDict['user_fullname'])
1235 email = cookieDict['user_email']
1247 email = cookieDict['user_email']
1236 affiliation = django.utils.http.urlquote_plus(cookieDict['user_affiliation'])
1248 affiliation = django.utils.http.urlquote_plus(cookieDict['user_affiliation'])
1237 # create instrument with data list with tuple (instrument_name, kinst)
1249 # create instrument with data list with tuple (instrument_name, kinst)
1238 madInstDataObj = madrigal.metadata.MadrigalInstrumentData(madDB)
1250 madInstDataObj = madrigal.metadata.MadrigalInstrumentData(madDB)
1239 madInstList = [(instrument_name, kinst) for kinst, instrument_name, site_id in madInstDataObj.getInstruments(local=True)]
1251 madInstList = [(instrument_name, kinst) for kinst, instrument_name, site_id in madInstDataObj.getInstruments(local=True)]
1240 return render(request, 'madweb/ftp_instruments.html', {'madInstList': madInstList, 'fullname': fullname,
1252 return render(request, 'madweb/ftp_instruments.html', {'madInstList': madInstList, 'fullname': fullname,
1241 'email': email, 'affiliation':affiliation, 'site_name': siteName,
1253 'email': email, 'affiliation':affiliation, 'site_name': siteName,
1242 'site_list': siteList, 'bg_color': bg_color})
1254 'site_list': siteList, 'bg_color': bg_color})
1243
1255
1244
1256
1245 def ftp_instrument(request, fullname, email, affiliation, kinst):
1257 def ftp_instrument(request, fullname, email, affiliation, kinst):
1246 """ftp_instrument creates the first ftp instrument page listing years
1258 """ftp_instrument creates the first ftp instrument page listing years
1247 Inputs: kinst selected
1259 Inputs: kinst selected
1248 """
1260 """
1249 kinst = int(kinst)
1261 kinst = int(kinst)
1250 madDB = madrigal.metadata.MadrigalDB()
1262 madDB = madrigal.metadata.MadrigalDB()
1251 bg_color = madDB.getBackgroundColor()
1263 bg_color = madDB.getBackgroundColor()
1252 madInstDataObj = madrigal.metadata.MadrigalInstrumentData(madDB)
1264 madInstDataObj = madrigal.metadata.MadrigalInstrumentData(madDB)
1253 madInstObj = madrigal.metadata.MadrigalInstrument(madDB)
1265 madInstObj = madrigal.metadata.MadrigalInstrument(madDB)
1254 inst_name = madInstObj.getInstrumentName(kinst)
1266 inst_name = madInstObj.getInstrumentName(kinst)
1255 yearList = madInstDataObj.getInstrumentYears(kinst)
1267 yearList = madInstDataObj.getInstrumentYears(kinst)
1256 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1268 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1257 siteName, siteList = madWebObj.getSiteInfo()
1269 siteName, siteList = madWebObj.getSiteInfo()
1258 return render(request, 'madweb/ftp_years.html',{'yearList':yearList, 'kinst':kinst,
1270 return render(request, 'madweb/ftp_years.html',{'yearList':yearList, 'kinst':kinst,
1259 'inst_name':inst_name, 'fullname': fullname,
1271 'inst_name':inst_name, 'fullname': fullname,
1260 'email': email, 'affiliation':affiliation,
1272 'email': email, 'affiliation':affiliation,
1261 'site_name': siteName, 'site_list': siteList,
1273 'site_name': siteName, 'site_list': siteList,
1262 'bg_color': bg_color })
1274 'bg_color': bg_color })
1263
1275
1264
1276
1265 def ftp_year(request, fullname, email, affiliation, kinst, year):
1277 def ftp_year(request, fullname, email, affiliation, kinst, year):
1266 """ftp_year creates the first ftp year page listing kindats
1278 """ftp_year creates the first ftp year page listing kindats
1267 Inputs: kinst selected, year selected
1279 Inputs: kinst selected, year selected
1268 """
1280 """
1269 kinst = int(kinst)
1281 kinst = int(kinst)
1270 year = int(year)
1282 year = int(year)
1271 madDB = madrigal.metadata.MadrigalDB()
1283 madDB = madrigal.metadata.MadrigalDB()
1272 bg_color = madDB.getBackgroundColor()
1284 bg_color = madDB.getBackgroundColor()
1273 madInstObj = madrigal.metadata.MadrigalInstrument(madDB)
1285 madInstObj = madrigal.metadata.MadrigalInstrument(madDB)
1274 inst_name = madInstObj.getInstrumentName(kinst)
1286 inst_name = madInstObj.getInstrumentName(kinst)
1275 madInstKindatObj = madrigal.metadata.MadrigalInstrumentKindats(madDB)
1287 madInstKindatObj = madrigal.metadata.MadrigalInstrumentKindats(madDB)
1276 kindatList = madInstKindatObj.getKindatListForInstrumentYear(kinst, year)
1288 kindatList = madInstKindatObj.getKindatListForInstrumentYear(kinst, year)
1277 madKindatObj = madrigal.metadata.MadrigalKindat(madDB)
1289 madKindatObj = madrigal.metadata.MadrigalKindat(madDB)
1278 # create kindatDescList, a list of tuples of (kindat_desc, kindat) for that kinst, year
1290 # create kindatDescList, a list of tuples of (kindat_desc, kindat) for that kinst, year
1279 kindatDescList = []
1291 kindatDescList = []
1280 for kindat in kindatList:
1292 for kindat in kindatList:
1281 kindatDescList.append((madKindatObj.getKindatDescription(kindat, kinst), kindat))
1293 kindatDescList.append((madKindatObj.getKindatDescription(kindat, kinst), kindat))
1282 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1294 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1283 siteName, siteList = madWebObj.getSiteInfo()
1295 siteName, siteList = madWebObj.getSiteInfo()
1284 return render(request, 'madweb/ftp_kindats.html', {'kindatDescList': kindatDescList, 'year': year,
1296 return render(request, 'madweb/ftp_kindats.html', {'kindatDescList': kindatDescList, 'year': year,
1285 'kinst': kinst, 'inst_name':inst_name, 'fullname': fullname,
1297 'kinst': kinst, 'inst_name':inst_name, 'fullname': fullname,
1286 'email': email, 'affiliation':affiliation,
1298 'email': email, 'affiliation':affiliation,
1287 'site_name': siteName, 'site_list': siteList,
1299 'site_name': siteName, 'site_list': siteList,
1288 'bg_color': bg_color })
1300 'bg_color': bg_color })
1289
1301
1290
1302
1291 def ftp_kindat(request, fullname, email, affiliation, kinst, year, kindat):
1303 def ftp_kindat(request, fullname, email, affiliation, kinst, year, kindat):
1292 """ftp_kindat creates the first ftp format page listing formats to choose from
1304 """ftp_kindat creates the first ftp format page listing formats to choose from
1293 Inputs: kinst selected, year selected, kindat selected
1305 Inputs: kinst selected, year selected, kindat selected
1294 """
1306 """
1295 kinst = int(kinst)
1307 kinst = int(kinst)
1296 kindat = int(kindat)
1308 kindat = int(kindat)
1297 madDB = madrigal.metadata.MadrigalDB()
1309 madDB = madrigal.metadata.MadrigalDB()
1298 bg_color = madDB.getBackgroundColor()
1310 bg_color = madDB.getBackgroundColor()
1299 madKindatObj = madrigal.metadata.MadrigalKindat(madDB)
1311 madKindatObj = madrigal.metadata.MadrigalKindat(madDB)
1300 kindat_desc = madKindatObj.getKindatDescription(kindat, kinst)
1312 kindat_desc = madKindatObj.getKindatDescription(kindat, kinst)
1301 madInstObj = madrigal.metadata.MadrigalInstrument(madDB)
1313 madInstObj = madrigal.metadata.MadrigalInstrument(madDB)
1302 inst_name = madInstObj.getInstrumentName(kinst)
1314 inst_name = madInstObj.getInstrumentName(kinst)
1303 formatDescList = [(formatDict[key], key) for key in list(formatDict.keys())]
1315 formatDescList = [(formatDict[key], key) for key in list(formatDict.keys())]
1304 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1316 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1305 siteName, siteList = madWebObj.getSiteInfo()
1317 siteName, siteList = madWebObj.getSiteInfo()
1306 return render(request, 'madweb/ftp_formats.html', {'formatDescList': formatDescList, 'year': year,
1318 return render(request, 'madweb/ftp_formats.html', {'formatDescList': formatDescList, 'year': year,
1307 'kinst': kinst, 'inst_name': inst_name, 'kindat': kindat,
1319 'kinst': kinst, 'inst_name': inst_name, 'kindat': kindat,
1308 'kindat_desc': kindat_desc, 'fullname': fullname,
1320 'kindat_desc': kindat_desc, 'fullname': fullname,
1309 'email': email, 'affiliation': affiliation,
1321 'email': email, 'affiliation': affiliation,
1310 'site_name': siteName, 'site_list': siteList,
1322 'site_name': siteName, 'site_list': siteList,
1311 'bg_color': bg_color } )
1323 'bg_color': bg_color } )
1312
1324
1313
1325
1314 def ftp_files(request, fullname, email, affiliation, kinst, year, kindat, format):
1326 def ftp_files(request, fullname, email, affiliation, kinst, year, kindat, format):
1315 """ftp_files creates the ftp files page listing individual files
1327 """ftp_files creates the ftp files page listing individual files
1316 Inputs: kinst selected, year selected, kindat selected
1328 Inputs: kinst selected, year selected, kindat selected
1317 """
1329 """
1318 kinst = int(kinst)
1330 kinst = int(kinst)
1319 year = int(year)
1331 year = int(year)
1320 dt = datetime.datetime(year,1,1) # speed up search
1332 dt = datetime.datetime(year,1,1) # speed up search
1321 kindat = int(kindat)
1333 kindat = int(kindat)
1322 if format not in ('hdf5', 'netCDF4', 'ascii'):
1334 if format not in ('hdf5', 'netCDF4', 'ascii'):
1323 raise ValueError('Unknown format %s' % (format))
1335 raise ValueError('Unknown format %s' % (format))
1324 if format == 'netCDF4':
1336 if format == 'netCDF4':
1325 thisExt = '.nc'
1337 thisExt = '.nc'
1326 elif format == 'ascii':
1338 elif format == 'ascii':
1327 thisExt = '.txt'
1339 thisExt = '.txt'
1328 format_desc = formatDict[format]
1340 format_desc = formatDict[format]
1329 # create a list of full names, where each item is a tuple of
1341 # create a list of full names, where each item is a tuple of
1330 # (fullFilename in Madrigal, output basename with correct extension, date string)
1342 # (fullFilename in Madrigal, output basename with correct extension, date string)
1331 fileList = []
1343 fileList = []
1332 madDB = madrigal.metadata.MadrigalDB()
1344 madDB = madrigal.metadata.MadrigalDB()
1333 bg_color = madDB.getBackgroundColor()
1345 bg_color = madDB.getBackgroundColor()
1334 madKindatObj = madrigal.metadata.MadrigalKindat(madDB)
1346 madKindatObj = madrigal.metadata.MadrigalKindat(madDB)
1335 kindat_desc = madKindatObj.getKindatDescription(kindat, kinst)
1347 kindat_desc = madKindatObj.getKindatDescription(kindat, kinst)
1336 madInstObj = madrigal.metadata.MadrigalInstrument(madDB)
1348 madInstObj = madrigal.metadata.MadrigalInstrument(madDB)
1337 inst_name = madInstObj.getInstrumentName(kinst)
1349 inst_name = madInstObj.getInstrumentName(kinst)
1338 pi = madInstObj.getContactName(kinst)
1350 pi = madInstObj.getContactName(kinst)
1339 pi_email = madInstObj.getContactEmail(kinst)
1351 pi_email = madInstObj.getContactEmail(kinst)
1340 madExpObj = madrigal.metadata.MadrigalExperiment(madDB)
1352 madExpObj = madrigal.metadata.MadrigalExperiment(madDB)
1341 startIndex = madExpObj.getStartPosition(dt) + 1
1353 startIndex = madExpObj.getStartPosition(dt) + 1
1342 for loop in (0,1):
1354 for loop in (0,1):
1343 # we normally only loop once, but sometimes multi-year experiments require a slow full search
1355 # we normally only loop once, but sometimes multi-year experiments require a slow full search
1344 if loop == 0:
1356 if loop == 0:
1345 thisStartIndex = startIndex
1357 thisStartIndex = startIndex
1346 else:
1358 else:
1347 thisStartIndex = 0 # should only get to this case for rare multi-year experiments
1359 thisStartIndex = 0 # should only get to this case for rare multi-year experiments
1348 for i in range(thisStartIndex, madExpObj.getExpCount()):
1360 for i in range(thisStartIndex, madExpObj.getExpCount()):
1349 if kinst != madExpObj.getKinstByPosition(i):
1361 if kinst != madExpObj.getKinstByPosition(i):
1350 continue
1362 continue
1351 stTuple = madExpObj.getExpStartDateTimeByPosition(i)[0:6]
1363 stTuple = madExpObj.getExpStartDateTimeByPosition(i)[0:6]
1352 etTuple = madExpObj.getExpEndDateTimeByPosition(i)[0:6]
1364 etTuple = madExpObj.getExpEndDateTimeByPosition(i)[0:6]
1353 expTitle = madExpObj.getExpNameByPosition(i)
1365 expTitle = madExpObj.getExpNameByPosition(i)
1354 sDT = datetime.datetime(*stTuple)
1366 sDT = datetime.datetime(*stTuple)
1355 eDT = datetime.datetime(*etTuple)
1367 eDT = datetime.datetime(*etTuple)
1356 if sDT.year > year:
1368 if sDT.year > year:
1357 break
1369 break
1358 if eDT.year < year:
1370 if eDT.year < year:
1359 continue
1371 continue
1360 dateStr = ' From %s to %s: %s' % (sDT.strftime('%Y-%m-%d %H:%M:%S'), eDT.strftime('%Y-%m-%d %H:%M:%S'), str(expTitle))
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 expDir = madExpObj.getExpDirByPosition(i)
1373 expDir = madExpObj.getExpDirByPosition(i)
1362 # look at this exp for the right kindat
1374 # look at this exp for the right kindat
1363 try:
1375 try:
1364 madFileObj = madrigal.metadata.MadrigalMetaFile(madDB, os.path.join(expDir, 'fileTab.txt'))
1376 madFileObj = madrigal.metadata.MadrigalMetaFile(madDB, os.path.join(expDir, 'fileTab.txt'))
1365 except:
1377 except:
1366 pass
1378 pass
1367 for j in range(madFileObj.getFileCount()):
1379 for j in range(madFileObj.getFileCount()):
1368 if madFileObj.getCategoryByPosition(j) not in (0,1):
1380 if madFileObj.getCategoryByPosition(j) not in (0,1):
1369 # skip history and alternate files
1381 # skip history and alternate files
1370 continue
1382 continue
1371 if madFileObj.getKindatByPosition(j) != kindat:
1383 if madFileObj.getKindatByPosition(j) != kindat:
1372 continue
1384 continue
1373 statusStr = ' : %s' % (str(madFileObj.getStatusByPosition(j)))
1385 statusStr = ' : %s' % (str(madFileObj.getStatusByPosition(j)))
1374 fullFilename = os.path.join(expDir, madFileObj.getFilenameByPosition(j))
1386 fullFilename = os.path.join(expDir, madFileObj.getFilenameByPosition(j))
1375 fullBasename = os.path.basename(fullFilename)
1387 fullBasename = os.path.basename(fullFilename)
1376 if format != 'hdf5':
1388 if format != 'hdf5':
1377 base, file_extension = os.path.splitext(fullFilename)
1389 base, file_extension = os.path.splitext(fullFilename)
1378 basename = os.path.basename(base + thisExt)
1390 basename = os.path.basename(base + thisExt)
1379 else:
1391 else:
1380 basename = os.path.basename(fullFilename)
1392 basename = os.path.basename(fullFilename)
1381 # make sure this file isn't too big to create a cache
1393 # make sure this file isn't too big to create a cache
1382 file_size = os.path.getsize(fullFilename)
1394 file_size = os.path.getsize(fullFilename)
1383 if file_size > maxSize and format != 'hdf5':
1395 if file_size > maxSize and format != 'hdf5':
1384 # make sure cached file exists before adding
1396 # make sure cached file exists before adding
1385 if format == 'netCDF4':
1397 if format == 'netCDF4':
1386 cachedFile = os.path.join(expDir, 'overview', fullBasename + thisExt)
1398 cachedFile = os.path.join(expDir, 'overview', fullBasename + thisExt)
1387 else:
1399 else:
1388 cachedFile = os.path.join(expDir, 'overview', fullBasename + thisExt + '.gz')
1400 cachedFile = os.path.join(expDir, 'overview', fullBasename + thisExt + '.gz')
1389 if not os.path.exists(cachedFile):
1401 if not os.path.exists(cachedFile):
1390 continue
1402 continue
1391 fileList.append((urllib.parse.quote_plus(fullFilename), basename, dateStr + statusStr))
1403 fileList.append((urllib.parse.quote_plus(fullFilename), basename, dateStr + statusStr))
1392
1404
1393 if len(fileList) > 0:
1405 if len(fileList) > 0:
1394 break # usually we avoid the slow full loop
1406 break # usually we avoid the slow full loop
1395
1407
1396
1408
1397 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1409 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1398 siteName, siteList = madWebObj.getSiteInfo()
1410 siteName, siteList = madWebObj.getSiteInfo()
1399
1411
1400 return render(request, 'madweb/ftp_files.html', {'fullFilenames': fileList, 'year': year, 'kindat_desc': kindat_desc,
1412 return render(request, 'madweb/ftp_files.html', {'fullFilenames': fileList, 'year': year, 'kindat_desc': kindat_desc,
1401 'kinst': kinst, 'inst_name':inst_name, 'fullname': fullname,
1413 'kinst': kinst, 'inst_name':inst_name, 'fullname': fullname,
1402 'kindat': kindat, 'format': format, 'format_desc': format_desc,
1414 'kindat': kindat, 'format': format, 'format_desc': format_desc,
1403 'email': email, 'affiliation':affiliation,
1415 'email': email, 'affiliation':affiliation,
1404 'site_name': siteName, 'site_list': siteList,
1416 'site_name': siteName, 'site_list': siteList,
1405 'pi_email': pi_email, 'pi_name': pi,
1417 'pi_email': pi_email, 'pi_name': pi,
1406 'bg_color': bg_color})
1418 'bg_color': bg_color})
1407
1419
1408
1420
1409 def ftp_download(request, user_fullname, user_email, user_affiliation, kinst, year, kindat, format, fullHdf5Filename):
1421 def ftp_download(request, user_fullname, user_email, user_affiliation, kinst, year, kindat, format, fullHdf5Filename):
1410 """ftp_download creates the first ftp kindat page listing individual files
1422 """ftp_download creates the first ftp kindat page listing individual files
1411 Inputs: kinst selected, year selected, kindat selected
1423 Inputs: kinst selected, year selected, kindat selected
1412 """
1424 """
1413 madDB = madrigal.metadata.MadrigalDB()
1425 madDB = madrigal.metadata.MadrigalDB()
1414 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1426 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1415 user_fullname = urllib.parse.unquote_plus(user_fullname)
1427 user_fullname = urllib.parse.unquote_plus(user_fullname)
1416 user_affiliation = urllib.parse.unquote_plus(user_affiliation)
1428 user_affiliation = urllib.parse.unquote_plus(user_affiliation)
1417 fullHdf5Filename = urllib.parse.unquote_plus(fullHdf5Filename)
1429 fullHdf5Filename = urllib.parse.unquote_plus(fullHdf5Filename)
1418 fullFilename = madWebObj.downloadFullFileAsIs(fullHdf5Filename, format, user_fullname, user_email, user_affiliation)
1430 fullFilename = madWebObj.downloadFullFileAsIs(fullHdf5Filename, format, user_fullname, user_email, user_affiliation)
1419
1431
1420 f = open(fullFilename, 'rb')
1432 f = open(fullFilename, 'rb')
1421 filename = os.path.basename(fullFilename)
1433 filename = os.path.basename(fullFilename)
1422 chunk_size = 8192
1434 chunk_size = 8192
1423 file_type = mimetypes.guess_type(fullFilename)[0]
1435 file_type = mimetypes.guess_type(fullFilename)[0]
1424 if file_type is None:
1436 if file_type is None:
1425 file_type = 'application/octet-stream'
1437 file_type = 'application/octet-stream'
1426 response = StreamingHttpResponse(FileWrapper(f, chunk_size),
1438 response = StreamingHttpResponse(FileWrapper(f, chunk_size),
1427 content_type=file_type)
1439 content_type=file_type)
1428 response['Content-Length'] = os.path.getsize(fullFilename)
1440 response['Content-Length'] = os.path.getsize(fullFilename)
1429 response['Content-Disposition'] = "attachment; filename=%s" % (filename)
1441 response['Content-Disposition'] = "attachment; filename=%s" % (filename)
1430 return(response)
1442 return(response)
1431
1443
1432
1444
1433 @csrf_exempt
1445 @csrf_exempt
1434 def ftp_multiple_download(request):
1446 def ftp_multiple_download(request):
1435 """ftp_download creates the first ftp kindat page listing individual files
1447 """ftp_download creates the first ftp kindat page listing individual files
1436 Inputs: kinst selected, year selected, kindat selected
1448 Inputs: kinst selected, year selected, kindat selected
1437 """
1449 """
1438 if request.method == 'POST':
1450 if request.method == 'POST':
1439 reqDict = request.POST
1451 reqDict = request.POST
1440 else:
1452 else:
1441 reqDict = request.GET
1453 reqDict = request.GET
1442 madDB = madrigal.metadata.MadrigalDB()
1454 madDB = madrigal.metadata.MadrigalDB()
1443 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1455 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1444 user_fullname = urllib.parse.unquote_plus(reqDict.get('user_fullname'))
1456 user_fullname = urllib.parse.unquote_plus(reqDict.get('user_fullname'))
1445 user_email = reqDict.get('user_email')
1457 user_email = reqDict.get('user_email')
1446 user_affiliation = urllib.parse.unquote_plus(reqDict.get('user_affiliation'))
1458 user_affiliation = urllib.parse.unquote_plus(reqDict.get('user_affiliation'))
1447 format = reqDict.get('format')
1459 format = reqDict.get('format')
1448 fileList = reqDict.getlist('fullFilename')
1460 fileList = reqDict.getlist('fullFilename')
1449 fileList = [urllib.parse.unquote_plus(filename) for filename in fileList]
1461 fileList = [urllib.parse.unquote_plus(filename) for filename in fileList]
1450 if len(fileList) > 10:
1462 if len(fileList) > 10:
1451 # send user an email with warning
1463 # send user an email with warning
1452 tmpDir = os.path.join(madDB.getMadroot(), 'experiments/stage')
1464 tmpDir = os.path.join(madDB.getMadroot(), 'experiments/stage')
1453 fullFilename = os.path.join(tmpDir, 'result_error_%06i.txt' % (random.randint(0,999999)))
1465 fullFilename = os.path.join(tmpDir, 'result_error_%06i.txt' % (random.randint(0,999999)))
1454 f = open(fullFilename, 'w')
1466 f = open(fullFilename, 'w')
1455 f.write('Error - you requested %i files, maximum is 10\n' % (len(fileList)))
1467 f.write('Error - you requested %i files, maximum is 10\n' % (len(fileList)))
1456 f.close()
1468 f.close()
1457 else:
1469 else:
1458 fullFilename = madWebObj.downloadMultipleFiles(fileList, format, user_fullname, user_email, user_affiliation)
1470 fullFilename = madWebObj.downloadMultipleFiles(fileList, format, user_fullname, user_email, user_affiliation)
1459
1471
1460 f = open(fullFilename, 'rb')
1472 f = open(fullFilename, 'rb')
1461 filename = os.path.basename(fullFilename)
1473 filename = os.path.basename(fullFilename)
1462 chunk_size = 8192
1474 chunk_size = 8192
1463 file_type = mimetypes.guess_type(fullFilename)[0]
1475 file_type = mimetypes.guess_type(fullFilename)[0]
1464 if file_type is None:
1476 if file_type is None:
1465 file_type = 'application/octet-stream'
1477 file_type = 'application/octet-stream'
1466 response = StreamingHttpResponse(FileWrapper(f, chunk_size),
1478 response = StreamingHttpResponse(FileWrapper(f, chunk_size),
1467 content_type=file_type)
1479 content_type=file_type)
1468 response['Content-Length'] = os.path.getsize(fullFilename)
1480 response['Content-Length'] = os.path.getsize(fullFilename)
1469 response['Content-Disposition'] = "attachment; filename=%s" % (filename)
1481 response['Content-Disposition'] = "attachment; filename=%s" % (filename)
1470 return(response)
1482 return(response)
1471
1483
1472
1484
1473 def instrument_metadata(request):
1485 def instrument_metadata(request):
1474 """instrument_metadata returns the instrument_metadata page.
1486 """instrument_metadata returns the instrument_metadata page.
1475
1487
1476 Inputs:
1488 Inputs:
1477 request
1489 request
1478 """
1490 """
1479 # create a list of tuples of (kinst, name, category, latitude, longitude, altitude, pi, pi_email, mnemonic)
1491 # create a list of tuples of (kinst, name, category, latitude, longitude, altitude, pi, pi_email, mnemonic)
1480 madDB = madrigal.metadata.MadrigalDB()
1492 madDB = madrigal.metadata.MadrigalDB()
1481 bg_color = madDB.getBackgroundColor()
1493 bg_color = madDB.getBackgroundColor()
1482 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1494 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1483 siteName, siteList = madWebObj.getSiteInfo()
1495 siteName, siteList = madWebObj.getSiteInfo()
1484 madInstObj = madrigal.metadata.MadrigalInstrument(madDB)
1496 madInstObj = madrigal.metadata.MadrigalInstrument(madDB)
1485 instList = []
1497 instList = []
1486 for name, mnemonic, kinst, category, catID in madInstObj.getOrderedInstrumentList():
1498 for name, mnemonic, kinst, category, catID in madInstObj.getOrderedInstrumentList():
1487 latitude = madInstObj.getLatitude(kinst)
1499 latitude = madInstObj.getLatitude(kinst)
1488 longitude = madInstObj.getLongitude(kinst)
1500 longitude = madInstObj.getLongitude(kinst)
1489 altitude = madInstObj.getAltitude(kinst)
1501 altitude = madInstObj.getAltitude(kinst)
1490 pi = madInstObj.getContactName(kinst)
1502 pi = madInstObj.getContactName(kinst)
1491 pi_email = madInstObj.getContactEmail(kinst)
1503 pi_email = madInstObj.getContactEmail(kinst)
1492 instList.append((kinst, name, category, latitude, longitude, altitude, pi, pi_email, mnemonic))
1504 instList.append((kinst, name, category, latitude, longitude, altitude, pi, pi_email, mnemonic))
1493
1505
1494 responseDict = {'inst_active': 'class="active"', 'instList': instList,
1506 responseDict = {'inst_active': 'class="active"', 'instList': instList,
1495 'site_name': siteName, 'site_list': siteList, 'bg_color': bg_color}
1507 'site_name': siteName, 'site_list': siteList, 'bg_color': bg_color}
1496 return render(request, 'madweb/instrument_metadata.html', responseDict)
1508 return render(request, 'madweb/instrument_metadata.html', responseDict)
1497
1509
1498
1510
1499 def site_metadata(request):
1511 def site_metadata(request):
1500 """site_metadata returns the site_metadata page.
1512 """site_metadata returns the site_metadata page.
1501
1513
1502 Inputs:
1514 Inputs:
1503 request
1515 request
1504 """
1516 """
1505 # create a list of tuples of (siteId, name, url, contact, contact email, version)
1517 # create a list of tuples of (siteId, name, url, contact, contact email, version)
1506 madDB = madrigal.metadata.MadrigalDB()
1518 madDB = madrigal.metadata.MadrigalDB()
1507 bg_color = madDB.getBackgroundColor()
1519 bg_color = madDB.getBackgroundColor()
1508 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1520 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1509 siteName, otherSiteList = madWebObj.getSiteInfo()
1521 siteName, otherSiteList = madWebObj.getSiteInfo()
1510 madSiteObj = madrigal.metadata.MadrigalSite(madDB)
1522 madSiteObj = madrigal.metadata.MadrigalSite(madDB)
1511 siteList = []
1523 siteList = []
1512 for siteId, siteName in madSiteObj.getSiteList():
1524 for siteId, siteName in madSiteObj.getSiteList():
1513 if madSiteObj.getSiteServer(siteId).find('http') == -1:
1525 if madSiteObj.getSiteServer(siteId).find('http') == -1:
1514 url = 'http://' + os.path.join(madSiteObj.getSiteServer(siteId),
1526 url = 'http://' + os.path.join(madSiteObj.getSiteServer(siteId),
1515 madSiteObj.getSiteDocRoot(siteId))
1527 madSiteObj.getSiteDocRoot(siteId))
1516 else:
1528 else:
1517 url = os.path.join(madSiteObj.getSiteServer(siteId),
1529 url = os.path.join(madSiteObj.getSiteServer(siteId),
1518 madSiteObj.getSiteDocRoot(siteId))
1530 madSiteObj.getSiteDocRoot(siteId))
1519 contact = madSiteObj.getSiteContactName(siteId)
1531 contact = madSiteObj.getSiteContactName(siteId)
1520 contact_email = madSiteObj.getSiteEmail(siteId)
1532 contact_email = madSiteObj.getSiteEmail(siteId)
1521 version = madSiteObj.getSiteVersion(siteId)
1533 version = madSiteObj.getSiteVersion(siteId)
1522 siteList.append((siteId, siteName, url, contact, contact_email, version))
1534 siteList.append((siteId, siteName, url, contact, contact_email, version))
1523
1535
1524 responseDict = {'site_active': 'class="active"', 'siteList': siteList,
1536 responseDict = {'site_active': 'class="active"', 'siteList': siteList,
1525 'site_name': siteName, 'site_list': otherSiteList, 'bg_color': bg_color}
1537 'site_name': siteName, 'site_list': otherSiteList, 'bg_color': bg_color}
1526 return render(request, 'madweb/site_metadata.html', responseDict)
1538 return render(request, 'madweb/site_metadata.html', responseDict)
1527
1539
1528
1540
1529 def parameter_metadata(request):
1541 def parameter_metadata(request):
1530 """parameter_metadata returns the site_metadata page.
1542 """parameter_metadata returns the site_metadata page.
1531
1543
1532 Inputs:
1544 Inputs:
1533 request
1545 request
1534 """
1546 """
1535 madDB = madrigal.metadata.MadrigalDB()
1547 madDB = madrigal.metadata.MadrigalDB()
1536 bg_color = madDB.getBackgroundColor()
1548 bg_color = madDB.getBackgroundColor()
1537 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1549 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1538 siteName, siteList = madWebObj.getSiteInfo()
1550 siteName, siteList = madWebObj.getSiteInfo()
1539 madParmObj = madrigal.data.MadrigalParameters(madDB)
1551 madParmObj = madrigal.data.MadrigalParameters(madDB)
1540 madParmCatObj = madrigal.metadata.MadrigalParmCategory(madDB)
1552 madParmCatObj = madrigal.metadata.MadrigalParmCategory(madDB)
1541 parmDict = {} # key is category string, value is list of category tuples (mnemonic, description, units, code)
1553 parmDict = {} # key is category string, value is list of category tuples (mnemonic, description, units, code)
1542 parmList = [] # list of tuples, each tuple either a single category, or (mnemonic, description, units, code)
1554 parmList = [] # list of tuples, each tuple either a single category, or (mnemonic, description, units, code)
1543 categoryList = []
1555 categoryList = []
1544 categoryUrlList = []
1556 categoryUrlList = []
1545 for mnemonic in madParmObj.getSortedMnemonicList():
1557 for mnemonic in madParmObj.getSortedMnemonicList():
1546 description = madParmObj.getSimpleParmDescription(mnemonic)
1558 description = madParmObj.getSimpleParmDescription(mnemonic)
1547 units = madParmObj.getParmUnits(mnemonic)
1559 units = madParmObj.getParmUnits(mnemonic)
1548 code = madParmObj.getParmCodeFromMnemonic(mnemonic)
1560 code = madParmObj.getParmCodeFromMnemonic(mnemonic)
1549 category = madParmObj.getParmCategory(mnemonic)
1561 category = madParmObj.getParmCategory(mnemonic)
1550 if category is None:
1562 if category is None:
1551 # deprecated prolog parm
1563 # deprecated prolog parm
1552 continue
1564 continue
1553 if category in list(parmDict.keys()):
1565 if category in list(parmDict.keys()):
1554 parmDict[category].append((mnemonic, description, units, code))
1566 parmDict[category].append((mnemonic, description, units, code))
1555 else:
1567 else:
1556 parmDict[category] = [(mnemonic, description, units, code)]
1568 parmDict[category] = [(mnemonic, description, units, code)]
1557
1569
1558 # now loop through all categories
1570 # now loop through all categories
1559 for thisCategory, catId in madParmCatObj.getCategoryList():
1571 for thisCategory, catId in madParmCatObj.getCategoryList():
1560 parmList.append((thisCategory,))
1572 parmList.append((thisCategory,))
1561 categoryList.append(thisCategory)
1573 categoryList.append(thisCategory)
1562 categoryAnchor = thisCategory.replace(' ','_')
1574 categoryAnchor = thisCategory.replace(' ','_')
1563 categoryUrlList.append('<a href="#%s">%s</a>' % (categoryAnchor, thisCategory))
1575 categoryUrlList.append('<a href="#%s">%s</a>' % (categoryAnchor, thisCategory))
1564 for values in parmDict[thisCategory]:
1576 for values in parmDict[thisCategory]:
1565 parmList.append(values)
1577 parmList.append(values)
1566
1578
1567 responseDict = {'parm_active': 'class="active"', 'parmList': parmList,
1579 responseDict = {'parm_active': 'class="active"', 'parmList': parmList,
1568 'categoryUrlList':categoryUrlList,
1580 'categoryUrlList':categoryUrlList,
1569 'site_name': siteName, 'site_list': siteList, 'bg_color': bg_color}
1581 'site_name': siteName, 'site_list': siteList, 'bg_color': bg_color}
1570 return render(request, 'madweb/parameter_metadata.html', responseDict)
1582 return render(request, 'madweb/parameter_metadata.html', responseDict)
1571
1583
1572
1584
1573 def kindat_metadata(request):
1585 def kindat_metadata(request):
1574 """kindat_metadata returns the kindat_metadata page.
1586 """kindat_metadata returns the kindat_metadata page.
1575
1587
1576 Inputs:
1588 Inputs:
1577 request
1589 request
1578 """
1590 """
1579 # create a list of tuples of (kindat, description, kinst, instrument_name)
1591 # create a list of tuples of (kindat, description, kinst, instrument_name)
1580 madDB = madrigal.metadata.MadrigalDB()
1592 madDB = madrigal.metadata.MadrigalDB()
1581 bg_color = madDB.getBackgroundColor()
1593 bg_color = madDB.getBackgroundColor()
1582 madKindatObj = madrigal.metadata.MadrigalKindat(madDB)
1594 madKindatObj = madrigal.metadata.MadrigalKindat(madDB)
1583 madInstObj = madrigal.metadata.MadrigalInstrument(madDB)
1595 madInstObj = madrigal.metadata.MadrigalInstrument(madDB)
1584 madInstKindatObj = madrigal.metadata.MadrigalInstrumentKindats(madDB)
1596 madInstKindatObj = madrigal.metadata.MadrigalInstrumentKindats(madDB)
1585 # create a dict of key = kindat code, value list of associated instruments
1597 # create a dict of key = kindat code, value list of associated instruments
1586 kindatDict = {}
1598 kindatDict = {}
1587 for name, mnem, kinst in madInstObj.getInstrumentList():
1599 for name, mnem, kinst in madInstObj.getInstrumentList():
1588 thisKindatList = madInstKindatObj.getKindatListForInstruments(kinst)
1600 thisKindatList = madInstKindatObj.getKindatListForInstruments(kinst)
1589 for kindat in thisKindatList:
1601 for kindat in thisKindatList:
1590 if kindat not in kindatDict:
1602 if kindat not in kindatDict:
1591 kindatDict[kindat] = [kinst]
1603 kindatDict[kindat] = [kinst]
1592 else:
1604 else:
1593 kindatDict[kindat].append(kinst)
1605 kindatDict[kindat].append(kinst)
1594
1606
1595 kindatList = []
1607 kindatList = []
1596 for description, code_str in madKindatObj.getKindatList():
1608 for description, code_str in madKindatObj.getKindatList():
1597 try:
1609 try:
1598 kinst, kindat = code_str.split('_')
1610 kinst, kindat = code_str.split('_')
1599 instName = madInstObj.getInstrumentName(int(kinst))
1611 instName = madInstObj.getInstrumentName(int(kinst))
1600 except:
1612 except:
1601 kindat = code_str
1613 kindat = code_str
1602 try:
1614 try:
1603 kinst = str(kindatDict[int(kindat)][0])
1615 kinst = str(kindatDict[int(kindat)][0])
1604 instName = madInstObj.getInstrumentName(int(kinst))
1616 instName = madInstObj.getInstrumentName(int(kinst))
1605 except KeyError:
1617 except KeyError:
1606 kinst = '-'
1618 kinst = '-'
1607 instName = 'Unspecified'
1619 instName = 'Unspecified'
1608 kindatList.append((kindat, description, kinst, instName))
1620 kindatList.append((kindat, description, kinst, instName))
1609 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1621 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1610 siteName, siteList = madWebObj.getSiteInfo()
1622 siteName, siteList = madWebObj.getSiteInfo()
1611
1623
1612 responseDict = {'kindat_active': 'class="active"', 'kindatList': kindatList,
1624 responseDict = {'kindat_active': 'class="active"', 'kindatList': kindatList,
1613 'site_name': siteName, 'site_list': siteList, 'bg_color': bg_color}
1625 'site_name': siteName, 'site_list': siteList, 'bg_color': bg_color}
1614 return render(request, 'madweb/kindat_metadata.html', responseDict)
1626 return render(request, 'madweb/kindat_metadata.html', responseDict)
1615
1627
1616
1628
1617 def madrigal_calculator(request):
1629 def madrigal_calculator(request):
1618 """madrigal_calculator returns the Madrigal Calculator page.
1630 """madrigal_calculator returns the Madrigal Calculator page.
1619
1631
1620 Inputs:
1632 Inputs:
1621 request
1633 request
1622 """
1634 """
1623 madDB = madrigal.metadata.MadrigalDB()
1635 madDB = madrigal.metadata.MadrigalDB()
1624 bg_color = madDB.getBackgroundColor()
1636 bg_color = madDB.getBackgroundColor()
1625 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1637 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1626 siteName, siteList = madWebObj.getSiteInfo()
1638 siteName, siteList = madWebObj.getSiteInfo()
1627 # original blank form
1639 # original blank form
1628 madCalculatorForm = madweb.forms.MadCalculatorForm()
1640 madCalculatorForm = madweb.forms.MadCalculatorForm()
1629 parmList = [(parm, madCalculatorForm.parmDescDict[parm]) for parm in list(madCalculatorForm.parmDescDict.keys())]
1641 parmList = [(parm, madCalculatorForm.parmDescDict[parm]) for parm in list(madCalculatorForm.parmDescDict.keys())]
1630 return render(request, 'madweb/madrigal_calculator.html', {'madCalculator_active': 'class="active"',
1642 return render(request, 'madweb/madrigal_calculator.html', {'madCalculator_active': 'class="active"',
1631 'form': madCalculatorForm,
1643 'form': madCalculatorForm,
1632 'parmList': parmList,
1644 'parmList': parmList,
1633 'site_name': siteName, 'site_list': siteList,
1645 'site_name': siteName, 'site_list': siteList,
1634 'bg_color': bg_color, 'datetime': True})
1646 'bg_color': bg_color, 'datetime': True})
1635
1647
1636 def madrigal_calculator_output(request):
1648 def madrigal_calculator_output(request):
1637 """madrigal_calculator returns the output from the Madrigal Calculator page.
1649 """madrigal_calculator returns the output from the Madrigal Calculator page.
1638
1650
1639 Inputs:
1651 Inputs:
1640 request
1652 request
1641 """
1653 """
1642 madDB = madrigal.metadata.MadrigalDB()
1654 madDB = madrigal.metadata.MadrigalDB()
1643 bg_color = madDB.getBackgroundColor()
1655 bg_color = madDB.getBackgroundColor()
1644 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1656 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1645 siteName, siteList = madWebObj.getSiteInfo()
1657 siteName, siteList = madWebObj.getSiteInfo()
1646
1658
1647 madCalculatorForm = madweb.forms.MadCalculatorForm(request.GET)
1659 madCalculatorForm = madweb.forms.MadCalculatorForm(request.GET)
1648
1660
1649 try:
1661 try:
1650 if not madCalculatorForm.is_valid():
1662 if not madCalculatorForm.is_valid():
1651 return(HttpResponse(str(madCalculatorForm.errors)))
1663 return(HttpResponse(str(madCalculatorForm.errors)))
1652 except KeyError:
1664 except KeyError:
1653 return(HttpResponse('<p>Missing arguments in madCalculatorOutput</p>'))
1665 return(HttpResponse('<p>Missing arguments in madCalculatorOutput</p>'))
1654
1666
1655 text = madWebObj.runMadrigalCalculatorFromForm(madCalculatorForm.cleaned_data)
1667 text = madWebObj.runMadrigalCalculatorFromForm(madCalculatorForm.cleaned_data)
1656
1668
1657 return render(request, 'madweb/madrigal_calculator_output.html', {'madCalculator_active': 'class="active"',
1669 return render(request, 'madweb/madrigal_calculator_output.html', {'madCalculator_active': 'class="active"',
1658 'text': text,
1670 'text': text,
1659 'site_name': siteName, 'site_list': siteList,
1671 'site_name': siteName, 'site_list': siteList,
1660 'bg_color': bg_color})
1672 'bg_color': bg_color})
1661
1673
1662
1674
1663 def get_metadata(request):
1675 def get_metadata(request):
1664 """get_metadata allows local metadata files to be downloaded.
1676 """get_metadata allows local metadata files to be downloaded.
1665
1677
1666 Inputs:
1678 Inputs:
1667 request
1679 request
1668 """
1680 """
1669 fileDict = {'0':'expTab.txt',
1681 fileDict = {'0':'expTab.txt',
1670 '1': 'fileTab.txt',
1682 '1': 'fileTab.txt',
1671 '3': 'instTab.txt',
1683 '3': 'instTab.txt',
1672 '4': 'parmCodes.txt',
1684 '4': 'parmCodes.txt',
1673 '5': 'siteTab.txt',
1685 '5': 'siteTab.txt',
1674 '6': 'typeTab.txt',
1686 '6': 'typeTab.txt',
1675 '7': 'instKindatTab.txt',
1687 '7': 'instKindatTab.txt',
1676 '8': 'instParmTab.txt',
1688 '8': 'instParmTab.txt',
1677 '9': 'madCatTab.txt',
1689 '9': 'madCatTab.txt',
1678 '10': 'instType.txt'}
1690 '10': 'instType.txt'}
1679 form = madweb.forms.GetMetadataForm(request.GET)
1691 form = madweb.forms.GetMetadataForm(request.GET)
1680 if form.is_valid():
1692 if form.is_valid():
1681 madDB = madrigal.metadata.MadrigalDB()
1693 madDB = madrigal.metadata.MadrigalDB()
1682 downloadFile = os.path.join(madDB.getMetadataDir(),
1694 downloadFile = os.path.join(madDB.getMetadataDir(),
1683 fileDict[form.cleaned_data['fileType']])
1695 fileDict[form.cleaned_data['fileType']])
1684
1696
1685
1697
1686 f = open(downloadFile, 'rb')
1698 f = open(downloadFile, 'rb')
1687 filename = os.path.basename(downloadFile)
1699 filename = os.path.basename(downloadFile)
1688 chunk_size = 8192
1700 chunk_size = 8192
1689 response = StreamingHttpResponse(FileWrapper(f, chunk_size),
1701 response = StreamingHttpResponse(FileWrapper(f, chunk_size),
1690 content_type=mimetypes.guess_type(downloadFile)[0])
1702 content_type=mimetypes.guess_type(downloadFile)[0])
1691 response['Content-Length'] = os.path.getsize(downloadFile)
1703 response['Content-Length'] = os.path.getsize(downloadFile)
1692 response['Content-Disposition'] = "attachment; filename=%s" % (filename)
1704 response['Content-Disposition'] = "attachment; filename=%s" % (filename)
1693 return(response)
1705 return(response)
1694
1706
1695 else:
1707 else:
1696 madDB = madrigal.metadata.MadrigalDB()
1708 madDB = madrigal.metadata.MadrigalDB()
1697 bg_color = madDB.getBackgroundColor()
1709 bg_color = madDB.getBackgroundColor()
1698 form = madweb.forms.GetMetadataForm()
1710 form = madweb.forms.GetMetadataForm()
1699 return render(request, 'madweb/get_metadata.html', {'form': form, 'bg_color': bg_color})
1711 return render(request, 'madweb/get_metadata.html', {'form': form, 'bg_color': bg_color})
1700
1712
1701
1713
1702 def looker_main(request):
1714 def looker_main(request):
1703 """looker_main loads the main looker selection form.
1715 """looker_main loads the main looker selection form.
1704
1716
1705 Inputs:
1717 Inputs:
1706 request
1718 request
1707 """
1719 """
1708 madDB = madrigal.metadata.MadrigalDB()
1720 madDB = madrigal.metadata.MadrigalDB()
1709 bg_color = madDB.getBackgroundColor()
1721 bg_color = madDB.getBackgroundColor()
1710 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1722 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1711 siteName, siteList = madWebObj.getSiteInfo()
1723 siteName, siteList = madWebObj.getSiteInfo()
1712 lookerSelectForm = madweb.forms.LookerSelectForm()
1724 lookerSelectForm = madweb.forms.LookerSelectForm()
1713 return render(request, 'madweb/looker_main.html', {'looker_active': 'class="active"',
1725 return render(request, 'madweb/looker_main.html', {'looker_active': 'class="active"',
1714 'form': lookerSelectForm,
1726 'form': lookerSelectForm,
1715 'site_name': siteName, 'site_list': siteList,
1727 'site_name': siteName, 'site_list': siteList,
1716 'bg_color': bg_color})
1728 'bg_color': bg_color})
1717
1729
1718
1730
1719 def looker_form(request):
1731 def looker_form(request):
1720 """looker_form loads the appropriate looker form.
1732 """looker_form loads the appropriate looker form.
1721
1733
1722 Inputs:
1734 Inputs:
1723 request
1735 request
1724 """
1736 """
1725 madDB = madrigal.metadata.MadrigalDB()
1737 madDB = madrigal.metadata.MadrigalDB()
1726 bg_color = madDB.getBackgroundColor()
1738 bg_color = madDB.getBackgroundColor()
1727 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1739 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1728 siteName, siteList = madWebObj.getSiteInfo()
1740 siteName, siteList = madWebObj.getSiteInfo()
1729 if not 'looker_options' in request.GET:
1741 if not 'looker_options' in request.GET:
1730 return(HttpResponse('<p>looker form requires looker_options</p>'))
1742 return(HttpResponse('<p>looker form requires looker_options</p>'))
1731 form = madweb.forms.LookerSelectForm(request.GET)
1743 form = madweb.forms.LookerSelectForm(request.GET)
1732 if form.is_valid():
1744 if form.is_valid():
1733 option = form.cleaned_data['looker_options']
1745 option = form.cleaned_data['looker_options']
1734 if option == '1':
1746 if option == '1':
1735 form = madweb.forms.LookerGeodeticRadar()
1747 form = madweb.forms.LookerGeodeticRadar()
1736 return render(request, 'madweb/looker_geodetic_to_radar.html', {'looker_active': 'class="active"',
1748 return render(request, 'madweb/looker_geodetic_to_radar.html', {'looker_active': 'class="active"',
1737 'form': form,
1749 'form': form,
1738 'site_name': siteName, 'site_list': siteList,
1750 'site_name': siteName, 'site_list': siteList,
1739 'bg_color': bg_color})
1751 'bg_color': bg_color})
1740 elif option == '2':
1752 elif option == '2':
1741 form = madweb.forms.LookerGeomagRadar()
1753 form = madweb.forms.LookerGeomagRadar()
1742 return render(request, 'madweb/looker_geomagnetic_to_radar.html', {'looker_active': 'class="active"',
1754 return render(request, 'madweb/looker_geomagnetic_to_radar.html', {'looker_active': 'class="active"',
1743 'form': form,
1755 'form': form,
1744 'site_name': siteName, 'site_list': siteList,
1756 'site_name': siteName, 'site_list': siteList,
1745 'bg_color': bg_color})
1757 'bg_color': bg_color})
1746 elif option == '3':
1758 elif option == '3':
1747 form = madweb.forms.LookerGeomagFromGeodetic()
1759 form = madweb.forms.LookerGeomagFromGeodetic()
1748 return render(request, 'madweb/looker_geomagnetic_from_geodetic.html', {'looker_active': 'class="active"',
1760 return render(request, 'madweb/looker_geomagnetic_from_geodetic.html', {'looker_active': 'class="active"',
1749 'form': form,
1761 'form': form,
1750 'site_name': siteName, 'site_list': siteList,
1762 'site_name': siteName, 'site_list': siteList,
1751 'bg_color': bg_color})
1763 'bg_color': bg_color})
1752 elif option == '4':
1764 elif option == '4':
1753 form = madweb.forms.LookerGeomagFromRadar()
1765 form = madweb.forms.LookerGeomagFromRadar()
1754 return render(request, 'madweb/looker_geomagnetic_from_radar.html', {'looker_active': 'class="active"',
1766 return render(request, 'madweb/looker_geomagnetic_from_radar.html', {'looker_active': 'class="active"',
1755 'form': form,
1767 'form': form,
1756 'site_name': siteName, 'site_list': siteList,
1768 'site_name': siteName, 'site_list': siteList,
1757 'bg_color': bg_color})
1769 'bg_color': bg_color})
1758 elif option == '5':
1770 elif option == '5':
1759 form = madweb.forms.LookerFieldLineFromRadar()
1771 form = madweb.forms.LookerFieldLineFromRadar()
1760 return render(request, 'madweb/looker_field_line_from_radar.html', {'looker_active': 'class="active"',
1772 return render(request, 'madweb/looker_field_line_from_radar.html', {'looker_active': 'class="active"',
1761 'form': form,
1773 'form': form,
1762 'site_name': siteName, 'site_list': siteList,
1774 'site_name': siteName, 'site_list': siteList,
1763 'bg_color': bg_color})
1775 'bg_color': bg_color})
1764 elif option == '6':
1776 elif option == '6':
1765 form = madweb.forms.LookerFieldLineFromGeodetic()
1777 form = madweb.forms.LookerFieldLineFromGeodetic()
1766 return render(request, 'madweb/looker_field_line_from_geodetic.html', {'looker_active': 'class="active"',
1778 return render(request, 'madweb/looker_field_line_from_geodetic.html', {'looker_active': 'class="active"',
1767 'form': form,
1779 'form': form,
1768 'site_name': siteName, 'site_list': siteList,
1780 'site_name': siteName, 'site_list': siteList,
1769 'bg_color': bg_color})
1781 'bg_color': bg_color})
1770 elif option == '7':
1782 elif option == '7':
1771 form = madweb.forms.LookerFieldLineFromApex()
1783 form = madweb.forms.LookerFieldLineFromApex()
1772 return render(request, 'madweb/looker_field_line_from_apex.html', {'looker_active': 'class="active"',
1784 return render(request, 'madweb/looker_field_line_from_apex.html', {'looker_active': 'class="active"',
1773 'form': form,
1785 'form': form,
1774 'site_name': siteName, 'site_list': siteList,
1786 'site_name': siteName, 'site_list': siteList,
1775 'bg_color': bg_color})
1787 'bg_color': bg_color})
1776 elif option == '8':
1788 elif option == '8':
1777 form = madweb.forms.LookerConjugateFromGeodetic()
1789 form = madweb.forms.LookerConjugateFromGeodetic()
1778 return render(request, 'madweb/looker_conjugate_from_geodetic.html', {'looker_active': 'class="active"',
1790 return render(request, 'madweb/looker_conjugate_from_geodetic.html', {'looker_active': 'class="active"',
1779 'form': form,
1791 'form': form,
1780 'site_name': siteName, 'site_list': siteList,
1792 'site_name': siteName, 'site_list': siteList,
1781 'bg_color': bg_color,
1793 'bg_color': bg_color,
1782 'datetime': True})
1794 'datetime': True})
1783 else:
1795 else:
1784 raise ValueError(str(form.errors))
1796 raise ValueError(str(form.errors))
1785
1797
1786
1798
1787 def looker_output(request):
1799 def looker_output(request):
1788 """looker_output loads the appropriate looker output.
1800 """looker_output loads the appropriate looker output.
1789
1801
1790 Inputs:
1802 Inputs:
1791 request
1803 request
1792 """
1804 """
1793 madDB = madrigal.metadata.MadrigalDB()
1805 madDB = madrigal.metadata.MadrigalDB()
1794 bg_color = madDB.getBackgroundColor()
1806 bg_color = madDB.getBackgroundColor()
1795 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1807 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
1796 siteName, siteList = madWebObj.getSiteInfo()
1808 siteName, siteList = madWebObj.getSiteInfo()
1797
1809
1798 if not 'looker_options' in request.GET:
1810 if not 'looker_options' in request.GET:
1799 return(HttpResponse('<p>looker missing arguments</p>'))
1811 return(HttpResponse('<p>looker missing arguments</p>'))
1800
1812
1801 if request.GET['looker_options'] == "1":
1813 if request.GET['looker_options'] == "1":
1802 form = madweb.forms.LookerGeodeticRadar(request.GET)
1814 form = madweb.forms.LookerGeodeticRadar(request.GET)
1803 if form.is_valid():
1815 if form.is_valid():
1804 text = madWebObj.runLookerFromForm(form.cleaned_data)
1816 text = madWebObj.runLookerFromForm(form.cleaned_data)
1805 return render(request, 'madweb/looker_output.html', {'looker_active': 'class="active"',
1817 return render(request, 'madweb/looker_output.html', {'looker_active': 'class="active"',
1806 'type': 'Az, El, Range to Geodetic points',
1818 'type': 'Az, El, Range to Geodetic points',
1807 'text': text,
1819 'text': text,
1808 'site_name': siteName, 'site_list': siteList,
1820 'site_name': siteName, 'site_list': siteList,
1809 'bg_color': bg_color})
1821 'bg_color': bg_color})
1810 else:
1822 else:
1811 raise ValueError(str(form.errors))
1823 raise ValueError(str(form.errors))
1812 elif request.GET['looker_options'] == "2":
1824 elif request.GET['looker_options'] == "2":
1813 form = madweb.forms.LookerGeomagRadar(request.GET)
1825 form = madweb.forms.LookerGeomagRadar(request.GET)
1814 if form.is_valid():
1826 if form.is_valid():
1815 text = madWebObj.runLookerFromForm(form.cleaned_data)
1827 text = madWebObj.runLookerFromForm(form.cleaned_data)
1816 return render(request, 'madweb/looker_output.html', {'looker_active': 'class="active"',
1828 return render(request, 'madweb/looker_output.html', {'looker_active': 'class="active"',
1817 'type': 'Az, El, Range to Geomagnetic (apex) points',
1829 'type': 'Az, El, Range to Geomagnetic (apex) points',
1818 'text': text,
1830 'text': text,
1819 'site_name': siteName, 'site_list': siteList,
1831 'site_name': siteName, 'site_list': siteList,
1820 'bg_color': bg_color})
1832 'bg_color': bg_color})
1821 else:
1833 else:
1822 raise ValueError(str(form.errors))
1834 raise ValueError(str(form.errors))
1823 elif request.GET['looker_options'] == "3":
1835 elif request.GET['looker_options'] == "3":
1824 form = madweb.forms.LookerGeomagFromGeodetic(request.GET)
1836 form = madweb.forms.LookerGeomagFromGeodetic(request.GET)
1825 if form.is_valid():
1837 if form.is_valid():
1826 text = madWebObj.runLookerFromForm(form.cleaned_data)
1838 text = madWebObj.runLookerFromForm(form.cleaned_data)
1827 return render(request, 'madweb/looker_output.html', {'looker_active': 'class="active"',
1839 return render(request, 'madweb/looker_output.html', {'looker_active': 'class="active"',
1828 'type': 'Apex Geomagnetic coordinates from Geodetic grid',
1840 'type': 'Apex Geomagnetic coordinates from Geodetic grid',
1829 'text': text,
1841 'text': text,
1830 'site_name': siteName, 'site_list': siteList,
1842 'site_name': siteName, 'site_list': siteList,
1831 'bg_color': bg_color})
1843 'bg_color': bg_color})
1832 else:
1844 else:
1833 raise ValueError(str(form.errors))
1845 raise ValueError(str(form.errors))
1834 elif request.GET['looker_options'] == "4":
1846 elif request.GET['looker_options'] == "4":
1835 form = madweb.forms.LookerGeomagFromRadar(request.GET)
1847 form = madweb.forms.LookerGeomagFromRadar(request.GET)
1836 if form.is_valid():
1848 if form.is_valid():
1837 text = madWebObj.runLookerFromForm(form.cleaned_data)
1849 text = madWebObj.runLookerFromForm(form.cleaned_data)
1838 return render(request, 'madweb/looker_output.html', {'looker_active': 'class="active"',
1850 return render(request, 'madweb/looker_output.html', {'looker_active': 'class="active"',
1839 'type': 'Apex Geomagnetic and geodetic coordinates and aspect angle from a grid of azimuth, elevation, and range',
1851 'type': 'Apex Geomagnetic and geodetic coordinates and aspect angle from a grid of azimuth, elevation, and range',
1840 'text': text,
1852 'text': text,
1841 'site_name': siteName, 'site_list': siteList,
1853 'site_name': siteName, 'site_list': siteList,
1842 'bg_color': bg_color})
1854 'bg_color': bg_color})
1843 else:
1855 else:
1844 raise ValueError(str(form.errors))
1856 raise ValueError(str(form.errors))
1845 elif request.GET['looker_options'] == "5":
1857 elif request.GET['looker_options'] == "5":
1846 form = madweb.forms.LookerFieldLineFromRadar(request.GET)
1858 form = madweb.forms.LookerFieldLineFromRadar(request.GET)
1847 if form.is_valid():
1859 if form.is_valid():
1848 text = madWebObj.runLookerFromForm(form.cleaned_data)
1860 text = madWebObj.runLookerFromForm(form.cleaned_data)
1849 return render(request, 'madweb/looker_output.html', {'looker_active': 'class="active"',
1861 return render(request, 'madweb/looker_output.html', {'looker_active': 'class="active"',
1850 'type': 'Field line coordinates for a field line set by radar parameters',
1862 'type': 'Field line coordinates for a field line set by radar parameters',
1851 'text': text,
1863 'text': text,
1852 'site_name': siteName, 'site_list': siteList,
1864 'site_name': siteName, 'site_list': siteList,
1853 'bg_color': bg_color})
1865 'bg_color': bg_color})
1854 else:
1866 else:
1855 raise ValueError(str(form.errors))
1867 raise ValueError(str(form.errors))
1856 elif request.GET['looker_options'] == "6":
1868 elif request.GET['looker_options'] == "6":
1857 form = madweb.forms.LookerFieldLineFromGeodetic(request.GET)
1869 form = madweb.forms.LookerFieldLineFromGeodetic(request.GET)
1858 if form.is_valid():
1870 if form.is_valid():
1859 text = madWebObj.runLookerFromForm(form.cleaned_data)
1871 text = madWebObj.runLookerFromForm(form.cleaned_data)
1860 return render(request, 'madweb/looker_output.html', {'looker_active': 'class="active"',
1872 return render(request, 'madweb/looker_output.html', {'looker_active': 'class="active"',
1861 'type': 'Field line coordinates and radar look parameters for given field line',
1873 'type': 'Field line coordinates and radar look parameters for given field line',
1862 'text': text,
1874 'text': text,
1863 'site_name': siteName, 'site_list': siteList,
1875 'site_name': siteName, 'site_list': siteList,
1864 'bg_color': bg_color})
1876 'bg_color': bg_color})
1865 else:
1877 else:
1866 raise ValueError(str(form.errors))
1878 raise ValueError(str(form.errors))
1867 elif request.GET['looker_options'] == "7":
1879 elif request.GET['looker_options'] == "7":
1868 form = madweb.forms.LookerFieldLineFromApex(request.GET)
1880 form = madweb.forms.LookerFieldLineFromApex(request.GET)
1869 if form.is_valid():
1881 if form.is_valid():
1870 text = madWebObj.runLookerFromForm(form.cleaned_data)
1882 text = madWebObj.runLookerFromForm(form.cleaned_data)
1871 return render(request, 'madweb/looker_output.html', {'looker_active': 'class="active"',
1883 return render(request, 'madweb/looker_output.html', {'looker_active': 'class="active"',
1872 'type': 'Field line coordinates and radar look parameters for given field line',
1884 'type': 'Field line coordinates and radar look parameters for given field line',
1873 'text': text,
1885 'text': text,
1874 'site_name': siteName, 'site_list': siteList,
1886 'site_name': siteName, 'site_list': siteList,
1875 'bg_color': bg_color})
1887 'bg_color': bg_color})
1876 else:
1888 else:
1877 raise ValueError(str(form.errors))
1889 raise ValueError(str(form.errors))
1878 elif request.GET['looker_options'] == "8":
1890 elif request.GET['looker_options'] == "8":
1879 form = madweb.forms.LookerConjugateFromGeodetic(request.GET)
1891 form = madweb.forms.LookerConjugateFromGeodetic(request.GET)
1880 if form.is_valid():
1892 if form.is_valid():
1881 text = madWebObj.runLookerFromForm(form.cleaned_data)
1893 text = madWebObj.runLookerFromForm(form.cleaned_data)
1882 return render(request, 'madweb/looker_output.html', {'looker_active': 'class="active"',
1894 return render(request, 'madweb/looker_output.html', {'looker_active': 'class="active"',
1883 'type': 'Point/Magnetic Conjugate Point vs Latitude, Longitude, Altitude',
1895 'type': 'Point/Magnetic Conjugate Point vs Latitude, Longitude, Altitude',
1884 'datetime': form.cleaned_data['datetime'],
1896 'datetime': form.cleaned_data['datetime'],
1885 'text': text,
1897 'text': text,
1886 'site_name': siteName, 'site_list': siteList,
1898 'site_name': siteName, 'site_list': siteList,
1887 'bg_color': bg_color})
1899 'bg_color': bg_color})
1888 else:
1900 else:
1889 raise ValueError(str(form.errors))
1901 raise ValueError(str(form.errors))
1890
1902
1891 else:
1903 else:
1892 raise ValueError('Unknown looker_option <%s>' % (str(request.GET['looker_options'])))
1904 raise ValueError('Unknown looker_option <%s>' % (str(request.GET['looker_options'])))
1893
1905
1894
1906
1895
1907
1896 def get_version_service(request):
1908 def get_version_service(request):
1897 """get_version_service runs the getVersionService.py service.
1909 """get_version_service runs the getVersionService.py service.
1898
1910
1899 Inputs:
1911 Inputs:
1900 request (ignored)
1912 request (ignored)
1901
1913
1902 Returns a single line of text, with the version in the form <major_version_int>.<minor_version_int>[.<sub_version_int>]
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 madDB = madrigal.metadata.MadrigalDB()
1916 madDB = madrigal.metadata.MadrigalDB()
1905 siteID = madDB.getSiteID()
1917 siteID = madDB.getSiteID()
1906 madSiteObj = madrigal.metadata.MadrigalSite(madDB)
1918 madSiteObj = madrigal.metadata.MadrigalSite(madDB)
1907 return(HttpResponse(madSiteObj.getSiteVersion(siteID)))
1919 return(HttpResponse(madSiteObj.getSiteVersion(siteID)))
1908
1920
1909
1921
1910
1922
1911 def get_instruments_service(request):
1923 def get_instruments_service(request):
1912 """get_instruments_service runs the getInstrumentsService.py service.
1924 """get_instruments_service runs the getInstrumentsService.py service.
1913
1925
1914 Inputs:
1926 Inputs:
1915 request (ignored)
1927 request (ignored)
1916
1928
1917 Returns comma-delimited data, one line for each experiment, with the following fields:
1929 Returns comma-delimited data, one line for each experiment, with the following fields:
1918
1930
1919 1. instrument.name Example: 'Millstone Hill Incoherent Scatter Radar'
1931 1. instrument.name Example: 'Millstone Hill Incoherent Scatter Radar'
1920
1932
1921 2. instrument.code Example: 30
1933 2. instrument.code Example: 30
1922
1934
1923 3. instrument.mnemonic (3 char string) Example: 'mlh'
1935 3. instrument.mnemonic (3 char string) Example: 'mlh'
1924
1936
1925 4. instrument.latitude Example: 45.0
1937 4. instrument.latitude Example: 45.0
1926
1938
1927 5. instrument.longitude Example: 110.0
1939 5. instrument.longitude Example: 110.0
1928
1940
1929 6. instrument.altitude Example: 0.015 (km)
1941 6. instrument.altitude Example: 0.015 (km)
1930
1942
1931 7. instrument.category Example: 'Incoherent Scatter Radars'
1943 7. instrument.category Example: 'Incoherent Scatter Radars'
1932
1944
1933 8. contact name
1945 8. contact name
1934
1946
1935 9. contact email
1947 9. contact email
1936 """
1948 """
1937 # create MadrigalDB obj
1949 # create MadrigalDB obj
1938 madDBObj = madrigal.metadata.MadrigalDB()
1950 madDBObj = madrigal.metadata.MadrigalDB()
1939
1951
1940 # create MadrigalInstument object
1952 # create MadrigalInstument object
1941 madInst = madrigal.metadata.MadrigalInstrument(madDBObj)
1953 madInst = madrigal.metadata.MadrigalInstrument(madDBObj)
1942
1954
1943 # get instrument list
1955 # get instrument list
1944 instList = madInst.getInstrumentList()
1956 instList = madInst.getInstrumentList()
1945
1957
1946 # loop through each instrument
1958 # loop through each instrument
1947 instStr = ''
1959 instStr = ''
1948 for inst in instList:
1960 for inst in instList:
1949 name = inst[0]
1961 name = inst[0]
1950 code = inst[2]
1962 code = inst[2]
1951 mnemonic = inst[1]
1963 mnemonic = inst[1]
1952 latitude = madInst.getLatitude(code)
1964 latitude = madInst.getLatitude(code)
1953 if latitude == None:
1965 if latitude == None:
1954 latitude = 0.0
1966 latitude = 0.0
1955 longitude = madInst.getLongitude(code)
1967 longitude = madInst.getLongitude(code)
1956 if longitude == None:
1968 if longitude == None:
1957 longitude = 0.0
1969 longitude = 0.0
1958 altitude = madInst.getAltitude(code)
1970 altitude = madInst.getAltitude(code)
1959 if altitude == None:
1971 if altitude == None:
1960 altitude = 0.0
1972 altitude = 0.0
1961 category = madInst.getCategory(code)
1973 category = madInst.getCategory(code)
1962 if category == None:
1974 if category == None:
1963 category = ''
1975 category = ''
1964 # print data
1976 # print data
1965 contactName = madInst.getContactName(code)
1977 contactName = madInst.getContactName(code)
1966 contactEmail = madInst.getContactEmail(code)
1978 contactEmail = madInst.getContactEmail(code)
1967 instStr += '%s,%i,%s,%f,%f,%f,%s,%s,%s\n' % (name,
1979 instStr += '%s,%i,%s,%f,%f,%f,%s,%s,%s\n' % (name,
1968 code,
1980 code,
1969 mnemonic,
1981 mnemonic,
1970 latitude,
1982 latitude,
1971 longitude,
1983 longitude,
1972 altitude,
1984 altitude,
1973 category,
1985 category,
1974 str(contactName),
1986 str(contactName),
1975 str(contactEmail))
1987 str(contactEmail))
1976
1988
1977 return render(request, 'madweb/service.html', {'text': instStr})
1989 return render(request, 'madweb/service.html', {'text': instStr})
1978
1990
1979
1991
1980 def get_experiments_service(request):
1992 def get_experiments_service(request):
1981 """get_experiments_service runs the getExperimentsService.py service.
1993 """get_experiments_service runs the getExperimentsService.py service.
1982
1994
1983 Inputs:
1995 Inputs:
1984 request/url - contains arguments:
1996 request/url - contains arguments:
1985
1997
1986 code - one or more kindat values
1998 code - one or more kindat values
1987
1999
1988 startyear, startmonth, startday, starthour, startmin, startsec
2000 startyear, startmonth, startday, starthour, startmin, startsec
1989
2001
1990 endyear, endmonth, endday, endhour, endmin, endsec
2002 endyear, endmonth, endday, endhour, endmin, endsec
1991
2003
1992 local (defaults to True)
2004 local (defaults to True)
1993
2005
1994 Returns comma-delimited data, one line for each experiment, with the following fields:
2006 Returns comma-delimited data, one line for each experiment, with the following fields:
1995
2007
1996 1. experiment.id (int) Example: 10000111
2008 1. experiment.id (int) Example: 10000111
1997
2009
1998 2. experiment.url (string) Example: 'http://www.haystack.mit.edu/cgi-bin/madtoc/1997/mlh/03dec97'
2010 2. experiment.url (string) Example: 'http://www.haystack.mit.edu/cgi-bin/madtoc/1997/mlh/03dec97'
1999
2011
2000 3. experiment.name (string) Example: 'Wide Latitude Substorm Study'
2012 3. experiment.name (string) Example: 'Wide Latitude Substorm Study'
2001
2013
2002 4. experiment.siteid (int) Example: 1
2014 4. experiment.siteid (int) Example: 1
2003
2015
2004 5. experiment.sitename (string) Example: 'Millstone Hill Observatory'
2016 5. experiment.sitename (string) Example: 'Millstone Hill Observatory'
2005
2017
2006 6. experiment.instcode (int) Code of instrument. Example: 30
2018 6. experiment.instcode (int) Code of instrument. Example: 30
2007
2019
2008 7. experiment.instname (string) Instrument name. Example: 'Millstone Hill Incoherent Scatter Radar'
2020 7. experiment.instname (string) Instrument name. Example: 'Millstone Hill Incoherent Scatter Radar'
2009
2021
2010 8. experiment.start year (int) year of experiment start
2022 8. experiment.start year (int) year of experiment start
2011
2023
2012 9. experiment.start month (int) month of experiment start
2024 9. experiment.start month (int) month of experiment start
2013
2025
2014 10. experiment.start day (int) day of experiment start
2026 10. experiment.start day (int) day of experiment start
2015
2027
2016 11. experiment.start hour (int) hour of experiment start
2028 11. experiment.start hour (int) hour of experiment start
2017
2029
2018 12. experiment.start minute (int) min of experiment start
2030 12. experiment.start minute (int) min of experiment start
2019
2031
2020 13. experiment.start second (int) sec of experiment start
2032 13. experiment.start second (int) sec of experiment start
2021
2033
2022 14. experiment.end year (int) year of experiment end
2034 14. experiment.end year (int) year of experiment end
2023
2035
2024 15. experiment.end month (int) month of experiment end
2036 15. experiment.end month (int) month of experiment end
2025
2037
2026 16. experiment.end day (int) day of experiment end
2038 16. experiment.end day (int) day of experiment end
2027
2039
2028 17. experiment.end hour (int) hour of experiment end
2040 17. experiment.end hour (int) hour of experiment end
2029
2041
2030 18. experiment.end minute (int) min of experiment end
2042 18. experiment.end minute (int) min of experiment end
2031
2043
2032 19. experiment.end second (int) sec of experiment end
2044 19. experiment.end second (int) sec of experiment end
2033
2045
2034 20. experiment.isLocal (int) 1 if local, 0 if not
2046 20. experiment.isLocal (int) 1 if local, 0 if not
2035
2047
2036 21.experiment.PI (string) Experiment PI name Example: 'Phil Erickson'
2048 21.experiment.PI (string) Experiment PI name Example: 'Phil Erickson'
2037
2049
2038 22. experiment.PIEmail (string) Experiment PI email Example: 'perickson@haystack.mit.edu'
2050 22. experiment.PIEmail (string) Experiment PI email Example: 'perickson@haystack.mit.edu'
2039
2051
2040 23. utc timestamp of last update to experiment
2052 23. utc timestamp of last update to experiment
2041
2053
2042 24. security value
2054 24. security value
2043
2055
2044 """
2056 """
2045 codeList = request.GET.getlist('code')
2057 codeList = request.GET.getlist('code')
2046 codeList = [int(code) for code in codeList]
2058 codeList = [int(code) for code in codeList]
2047 startyear = int(request.GET['startyear'])
2059 startyear = int(request.GET['startyear'])
2048 startmonth = int(request.GET['startmonth'])
2060 startmonth = int(request.GET['startmonth'])
2049 startday = int(request.GET['startday'])
2061 startday = int(request.GET['startday'])
2050 starthour = int(request.GET['starthour'])
2062 starthour = int(request.GET['starthour'])
2051 startmin = int(request.GET['startmin'])
2063 startmin = int(request.GET['startmin'])
2052 startsec = int(request.GET['startsec'])
2064 startsec = int(request.GET['startsec'])
2053 endyear = int(request.GET['endyear'])
2065 endyear = int(request.GET['endyear'])
2054 endmonth = int(request.GET['endmonth'])
2066 endmonth = int(request.GET['endmonth'])
2055 endday = int(request.GET['endday'])
2067 endday = int(request.GET['endday'])
2056 endhour = int(request.GET['endhour'])
2068 endhour = int(request.GET['endhour'])
2057 endmin = int(request.GET['endmin'])
2069 endmin = int(request.GET['endmin'])
2058 endsec = int(request.GET['endsec'])
2070 endsec = int(request.GET['endsec'])
2059 try:
2071 try:
2060 local = int(request.GET['local'])
2072 local = int(request.GET['local'])
2061 except:
2073 except:
2062 local = 1
2074 local = 1
2063
2075
2064
2076
2065 # if startsec or endsec in (60, 61), handle correctly
2077 # if startsec or endsec in (60, 61), handle correctly
2066 if startsec in (60, 61):
2078 if startsec in (60, 61):
2067 tmpTime = datetime.datetime(startyear,
2079 tmpTime = datetime.datetime(startyear,
2068 startmonth,
2080 startmonth,
2069 startday,
2081 startday,
2070 starthour,
2082 starthour,
2071 startmin,
2083 startmin,
2072 59)
2084 59)
2073 tmpTime += datetime.timedelta(0, startsec - 59)
2085 tmpTime += datetime.timedelta(0, startsec - 59)
2074 startyear = tmpTime.year
2086 startyear = tmpTime.year
2075 startmonth = tmpTime.month
2087 startmonth = tmpTime.month
2076 startday = tmpTime.day
2088 startday = tmpTime.day
2077 starthour = tmpTime.hour
2089 starthour = tmpTime.hour
2078 startmin = tmpTime.minute
2090 startmin = tmpTime.minute
2079 startsec = tmpTime.second
2091 startsec = tmpTime.second
2080
2092
2081 if endsec in (60, 61):
2093 if endsec in (60, 61):
2082 tmpTime = datetime.datetime(endyear,
2094 tmpTime = datetime.datetime(endyear,
2083 endmonth,
2095 endmonth,
2084 endday,
2096 endday,
2085 endhour,
2097 endhour,
2086 endmin,
2098 endmin,
2087 59)
2099 59)
2088 tmpTime += datetime.timedelta(0, endsec - 59)
2100 tmpTime += datetime.timedelta(0, endsec - 59)
2089 endyear = tmpTime.year
2101 endyear = tmpTime.year
2090 endmonth = tmpTime.month
2102 endmonth = tmpTime.month
2091 endday = tmpTime.day
2103 endday = tmpTime.day
2092 endhour = tmpTime.hour
2104 endhour = tmpTime.hour
2093 endmin = tmpTime.minute
2105 endmin = tmpTime.minute
2094 endsec = tmpTime.second
2106 endsec = tmpTime.second
2095
2107
2096 # if codeList is empty or contains 0, change it to only contain 0
2108 # if codeList is empty or contains 0, change it to only contain 0
2097 if len(codeList) == 0 or 0 in codeList:
2109 if len(codeList) == 0 or 0 in codeList:
2098 codeList = [0]
2110 codeList = [0]
2099
2111
2100 retStr = ''
2112 retStr = ''
2101
2113
2102 # create MadrigalDB obj
2114 # create MadrigalDB obj
2103 madDBObj = madrigal.metadata.MadrigalDB()
2115 madDBObj = madrigal.metadata.MadrigalDB()
2104
2116
2105 # get the local site id
2117 # get the local site id
2106 localSiteId = madDBObj.getSiteID()
2118 localSiteId = madDBObj.getSiteID()
2107
2119
2108 # create MadrigalInstrument obj to convert kinst to instrument names
2120 # create MadrigalInstrument obj to convert kinst to instrument names
2109 madInstObj = madrigal.metadata.MadrigalInstrument(madDBObj)
2121 madInstObj = madrigal.metadata.MadrigalInstrument(madDBObj)
2110
2122
2111 # create MadrigalSite obj to convert site id to site name
2123 # create MadrigalSite obj to convert site id to site name
2112 madSiteObj = madrigal.metadata.MadrigalSite(madDBObj)
2124 madSiteObj = madrigal.metadata.MadrigalSite(madDBObj)
2113
2125
2114 madWebObj = madrigal.ui.web.MadrigalWeb(madDBObj)
2126 madWebObj = madrigal.ui.web.MadrigalWeb(madDBObj)
2115 trusted = madWebObj.isTrusted()
2127 trusted = madWebObj.isTrusted()
2116
2128
2117 # create starttime for filter, if possible
2129 # create starttime for filter, if possible
2118 if startyear != None:
2130 if startyear != None:
2119 startTimeFilter = datetime.datetime(startyear,
2131 startTimeFilter = datetime.datetime(startyear,
2120 startmonth,
2132 startmonth,
2121 startday,
2133 startday,
2122 starthour,
2134 starthour,
2123 startmin,
2135 startmin,
2124 startsec)
2136 startsec)
2125 else:
2137 else:
2126 startTimeFilter = None
2138 startTimeFilter = None
2127
2139
2128 # create endtime for filter, if possible
2140 # create endtime for filter, if possible
2129 if endyear != None:
2141 if endyear != None:
2130 endTimeFilter = datetime.datetime(endyear,
2142 endTimeFilter = datetime.datetime(endyear,
2131 endmonth,
2143 endmonth,
2132 endday,
2144 endday,
2133 endhour,
2145 endhour,
2134 endmin,
2146 endmin,
2135 endsec)
2147 endsec)
2136 else:
2148 else:
2137 endTimeFilter = None
2149 endTimeFilter = None
2138
2150
2139 # create MadrigalExperiments for local or all files
2151 # create MadrigalExperiments for local or all files
2140 if local == 1:
2152 if local == 1:
2141 madExpObj = madrigal.metadata.MadrigalExperiment(madDBObj)
2153 madExpObj = madrigal.metadata.MadrigalExperiment(madDBObj)
2142 else:
2154 else:
2143 # use file expTabAll.txt to get all experiments
2155 # use file expTabAll.txt to get all experiments
2144 filename = madDBObj.getMadroot()
2156 filename = madDBObj.getMadroot()
2145 if filename[-1] != '/':
2157 if filename[-1] != '/':
2146 filename += '/'
2158 filename += '/'
2147 filename += 'metadata/expTabAll.txt'
2159 filename += 'metadata/expTabAll.txt'
2148 madExpObj = madrigal.metadata.MadrigalExperiment(madDBObj, filename)
2160 madExpObj = madrigal.metadata.MadrigalExperiment(madDBObj, filename)
2149
2161
2150 madExpObj.sortByDateSite()
2162 madExpObj.sortByDateSite()
2151
2163
2152
2164
2153 # loop through the data
2165 # loop through the data
2154 if not startTimeFilter is None:
2166 if not startTimeFilter is None:
2155 position = madExpObj.getStartPosition(startTimeFilter)
2167 position = madExpObj.getStartPosition(startTimeFilter)
2156 else:
2168 else:
2157 position = 0
2169 position = 0
2158 while(True):
2170 while(True):
2159 thisId = madExpObj.getExpIdByPosition(position)
2171 thisId = madExpObj.getExpIdByPosition(position)
2160 # check for end
2172 # check for end
2161 if thisId == None:
2173 if thisId == None:
2162 break
2174 break
2163 thisUrl = madExpObj.getExpUrlByPosition(position)
2175 thisUrl = madExpObj.getExpUrlByPosition(position)
2164 thisName = madExpObj.getExpNameByPosition(position)
2176 thisName = madExpObj.getExpNameByPosition(position)
2165 thisSiteId = madExpObj.getExpSiteIdByPosition(position)
2177 thisSiteId = madExpObj.getExpSiteIdByPosition(position)
2166 thisSiteName = madSiteObj.getSiteName(thisSiteId)
2178 thisSiteName = madSiteObj.getSiteName(thisSiteId)
2167 thisInstCode = madExpObj.getKinstByPosition(position)
2179 thisInstCode = madExpObj.getKinstByPosition(position)
2168 thisInstName =madInstObj.getInstrumentName(thisInstCode)
2180 thisInstName =madInstObj.getInstrumentName(thisInstCode)
2169 thisStart = madExpObj.getExpStartDateTimeByPosition(position)
2181 thisStart = madExpObj.getExpStartDateTimeByPosition(position)
2170 thisEnd = madExpObj.getExpEndDateTimeByPosition(position)
2182 thisEnd = madExpObj.getExpEndDateTimeByPosition(position)
2171 thisSecurity = madExpObj.getSecurityByPosition(position)
2183 thisSecurity = madExpObj.getSecurityByPosition(position)
2172 if thisSiteId == localSiteId:
2184 if thisSiteId == localSiteId:
2173 thisLocal = 1
2185 thisLocal = 1
2174 else:
2186 else:
2175 thisLocal = 0
2187 thisLocal = 0
2176 thisPI = madExpObj.getPIByPosition(position)
2188 thisPI = madExpObj.getPIByPosition(position)
2177 if thisPI in (None, ''):
2189 if thisPI in (None, ''):
2178 thisPI = madInstObj.getContactName(thisInstCode)
2190 thisPI = madInstObj.getContactName(thisInstCode)
2179 thisPIEmail = madExpObj.getPIEmailByPosition(position)
2191 thisPIEmail = madExpObj.getPIEmailByPosition(position)
2180 if thisPIEmail in (None, ''):
2192 if thisPIEmail in (None, ''):
2181 thisPIEmail = madInstObj.getContactEmail(thisInstCode)
2193 thisPIEmail = madInstObj.getContactEmail(thisInstCode)
2182 expDir = madExpObj.getExpDirByPosition(position)
2194 expDir = madExpObj.getExpDirByPosition(position)
2183
2195
2184 position += 1
2196 position += 1
2185
2197
2186 # some experiments set the end of the day to 24:00:00 - not
2198 # some experiments set the end of the day to 24:00:00 - not
2187 # technically correct - reset to 23:59:59
2199 # technically correct - reset to 23:59:59
2188
2200
2189 if (thisStart[3] == 24 and thisStart[4] == 0 and thisStart[5] == 0):
2201 if (thisStart[3] == 24 and thisStart[4] == 0 and thisStart[5] == 0):
2190 thisStart[3] = 23
2202 thisStart[3] = 23
2191 thisStart[4] = 59
2203 thisStart[4] = 59
2192 thisStart[5] = 59
2204 thisStart[5] = 59
2193
2205
2194 if (thisEnd[3] == 24 and thisEnd[4] == 0 and thisEnd[5] == 0):
2206 if (thisEnd[3] == 24 and thisEnd[4] == 0 and thisEnd[5] == 0):
2195 thisEnd[3] = 23
2207 thisEnd[3] = 23
2196 thisEnd[4] = 59
2208 thisEnd[4] = 59
2197 thisEnd[5] = 59
2209 thisEnd[5] = 59
2198
2210
2199 # apply filters
2211 # apply filters
2200
2212
2201 # first apply instrument code filter
2213 # first apply instrument code filter
2202 if codeList[0] != 0:
2214 if codeList[0] != 0:
2203 if thisInstCode not in codeList:
2215 if thisInstCode not in codeList:
2204 continue
2216 continue
2205
2217
2206 # apply starttime and endtime filters
2218 # apply starttime and endtime filters
2207 thisStartTime = datetime.datetime(thisStart[0],
2219 thisStartTime = datetime.datetime(thisStart[0],
2208 thisStart[1],
2220 thisStart[1],
2209 thisStart[2],
2221 thisStart[2],
2210 thisStart[3],
2222 thisStart[3],
2211 thisStart[4],
2223 thisStart[4],
2212 thisStart[5])
2224 thisStart[5])
2213
2225
2214 thisEndTime = datetime.datetime(thisEnd[0],
2226 thisEndTime = datetime.datetime(thisEnd[0],
2215 thisEnd[1],
2227 thisEnd[1],
2216 thisEnd[2],
2228 thisEnd[2],
2217 thisEnd[3],
2229 thisEnd[3],
2218 thisEnd[4],
2230 thisEnd[4],
2219 thisEnd[5])
2231 thisEnd[5])
2220
2232
2221 if startTimeFilter != None:
2233 if startTimeFilter != None:
2222 if thisEndTime < startTimeFilter:
2234 if thisEndTime < startTimeFilter:
2223 continue
2235 continue
2224
2236
2225 if endTimeFilter != None:
2237 if endTimeFilter != None:
2226 if thisStartTime > endTimeFilter:
2238 if thisStartTime > endTimeFilter:
2227 continue
2239 continue
2228
2240
2229 # apply local filer
2241 # apply local filer
2230 if local == 1 and thisLocal == 0:
2242 if local == 1 and thisLocal == 0:
2231 continue
2243 continue
2232
2244
2233 # apply security filter
2245 # apply security filter
2234 if trusted == 0 and thisSecurity not in (0,2):
2246 if trusted == 0 and thisSecurity not in (0,2):
2235 continue
2247 continue
2236
2248
2237 # create exp timestamp
2249 # create exp timestamp
2238 if local == 1:
2250 if local == 1:
2239 thisUTTimestamp = int(os.stat(expDir).st_mtime + time.timezone)
2251 thisUTTimestamp = int(os.stat(expDir).st_mtime + time.timezone)
2240 else:
2252 else:
2241 thisUTTimestamp = 0
2253 thisUTTimestamp = 0
2242
2254
2243 # add this experiment
2255 # add this experiment
2244 retStr += '%i,%s,%s,%i,%s,%i,%s,%i,%i,%i,%i,%i,%i,%i,%i,%i,%i,%i,%i,%i,%s,%s,%i,%i\n' % \
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 (thisId,
2257 (thisId,
2246 thisUrl,
2258 thisUrl,
2247 thisName,
2259 thisName,
2248 thisSiteId,
2260 thisSiteId,
2249 thisSiteName,
2261 thisSiteName,
2250 thisInstCode,
2262 thisInstCode,
2251 thisInstName,
2263 thisInstName,
2252 thisStart[0],
2264 thisStart[0],
2253 thisStart[1],
2265 thisStart[1],
2254 thisStart[2],
2266 thisStart[2],
2255 thisStart[3],
2267 thisStart[3],
2256 thisStart[4],
2268 thisStart[4],
2257 thisStart[5],
2269 thisStart[5],
2258 thisEnd[0],
2270 thisEnd[0],
2259 thisEnd[1],
2271 thisEnd[1],
2260 thisEnd[2],
2272 thisEnd[2],
2261 thisEnd[3],
2273 thisEnd[3],
2262 thisEnd[4],
2274 thisEnd[4],
2263 thisEnd[5],
2275 thisEnd[5],
2264 thisLocal,
2276 thisLocal,
2265 str(thisPI),
2277 str(thisPI),
2266 str(thisPIEmail),
2278 str(thisPIEmail),
2267 thisUTTimestamp,
2279 thisUTTimestamp,
2268 thisSecurity)
2280 thisSecurity)
2269
2281
2270 return render(request, 'madweb/service.html', {'text': retStr})
2282 return render(request, 'madweb/service.html', {'text': retStr})
2271
2283
2272
2284
2273 def get_experiment_files_service(request):
2285 def get_experiment_files_service(request):
2274 """get_experiment_files_service runs the getExperimentFilesService.py service.
2286 """get_experiment_files_service runs the getExperimentFilesService.py service.
2275
2287
2276 Inputs:
2288 Inputs:
2277 request/url - contains arguments:
2289 request/url - contains arguments:
2278
2290
2279 id - local experiment id
2291 id - local experiment id
2280
2292
2281 Returns comma-delimited data, one line for each experiment file, with the following fields:
2293 Returns comma-delimited data, one line for each experiment file, with the following fields:
2282
2294
2283 1. file.name (string) Example '/opt/mdarigal/blah/mlh980120g.001'
2295 1. file.name (string) Example '/opt/mdarigal/blah/mlh980120g.001'
2284
2296
2285 2. file.kindat (int) Kindat code. Example: 3001
2297 2. file.kindat (int) Kindat code. Example: 3001
2286
2298
2287 3. file.kindat desc (string) Kindat description: Example 'Basic Derived Parameters'
2299 3. file.kindat desc (string) Kindat description: Example 'Basic Derived Parameters'
2288
2300
2289 4. file.category (int) (1=default, 2=variant, 3=history, 4=real-time)
2301 4. file.category (int) (1=default, 2=variant, 3=history, 4=real-time)
2290
2302
2291 5. file.status (string)('preliminary', 'final', or any other description)
2303 5. file.status (string)('preliminary', 'final', or any other description)
2292
2304
2293 6. file.permission (int) 0 for public, 1 for private. For now will not return private files.
2305 6. file.permission (int) 0 for public, 1 for private. For now will not return private files.
2294
2306
2295 7. file DOI (string) - citable url to file
2307 7. file DOI (string) - citable url to file
2296
2308
2297 Returns empty string if experiment id not found. Skips files that are not Hdf5
2309 Returns empty string if experiment id not found. Skips files that are not Hdf5
2298 """
2310 """
2299 id = int(request.GET['id'])
2311 id = int(request.GET['id'])
2300
2312
2301 # create MadrigalDB obj
2313 # create MadrigalDB obj
2302 madDBObj = madrigal.metadata.MadrigalDB()
2314 madDBObj = madrigal.metadata.MadrigalDB()
2303
2315
2304 # create MadrigalExperiments object to get full file name
2316 # create MadrigalExperiments object to get full file name
2305 madExpObj = madrigal.metadata.MadrigalExperiment(madDBObj)
2317 madExpObj = madrigal.metadata.MadrigalExperiment(madDBObj)
2306
2318
2307 # create Madrigal Kindat to get Kindat descriptions
2319 # create Madrigal Kindat to get Kindat descriptions
2308 madKindatObj = madrigal.metadata.MadrigalKindat(madDBObj)
2320 madKindatObj = madrigal.metadata.MadrigalKindat(madDBObj)
2309
2321
2310 madWebObj = madrigal.ui.web.MadrigalWeb(madDBObj)
2322 madWebObj = madrigal.ui.web.MadrigalWeb(madDBObj)
2311 trusted = madWebObj.isTrusted()
2323 trusted = madWebObj.isTrusted()
2312
2324
2313
2325
2314 retStr = ''
2326 retStr = ''
2315 thisUrl = madExpObj.getExpUrlByExpId(id)
2327 thisUrl = madExpObj.getExpUrlByExpId(id)
2316 if thisUrl is None:
2328 if thisUrl is None:
2317 raise IOError('No such id: %i' % (id))
2329 raise IOError('No such id: %i' % (id))
2318 expPath = madExpObj.getExpDirByExpId(id)
2330 expPath = madExpObj.getExpDirByExpId(id)
2319 kinst = madExpObj.getKinstByExpId(id)
2331 kinst = madExpObj.getKinstByExpId(id)
2320 if os.access(os.path.join(expPath, 'fileTab.txt'), os.R_OK):
2332 if os.access(os.path.join(expPath, 'fileTab.txt'), os.R_OK):
2321 madFileObj = madrigal.metadata.MadrigalMetaFile(madDBObj, os.path.join(expPath, 'fileTab.txt'))
2333 madFileObj = madrigal.metadata.MadrigalMetaFile(madDBObj, os.path.join(expPath, 'fileTab.txt'))
2322 for i in range(madFileObj.getFileCount()):
2334 for i in range(madFileObj.getFileCount()):
2323 basename = madFileObj.getFilenameByPosition(i)
2335 basename = madFileObj.getFilenameByPosition(i)
2324 name = os.path.join(expPath, basename)
2336 name = os.path.join(expPath, basename)
2325 base_filename, file_extension = os.path.splitext(name)
2337 base_filename, file_extension = os.path.splitext(name)
2326 if file_extension not in ('.hdf5', '.hdf', '.h5'):
2338 if file_extension not in ('.hdf5', '.hdf', '.h5'):
2327 continue
2339 continue
2328 kindat = madFileObj.getKindatByPosition(i)
2340 kindat = madFileObj.getKindatByPosition(i)
2329 kindatdesc = madKindatObj.getKindatDescription(kindat, kinst)
2341 kindatdesc = madKindatObj.getKindatDescription(kindat, kinst)
2330 category = madFileObj.getCategoryByPosition(i)
2342 category = madFileObj.getCategoryByPosition(i)
2331 status = madFileObj.getStatusByPosition(i)
2343 status = madFileObj.getStatusByPosition(i)
2332 permission = madFileObj.getAccessByPosition(i)
2344 permission = madFileObj.getAccessByPosition(i)
2333 doi = madFileObj.getFileDOIUrlByPosition(i)
2345 doi = madFileObj.getFileDOIUrlByPosition(i)
2334
2346
2335 # skip private files if not trusted
2347 # skip private files if not trusted
2336 if trusted == 0 and int(permission) != 0:
2348 if trusted == 0 and int(permission) != 0:
2337 continue
2349 continue
2338
2350
2339 retStr += '%s,%i,%s,%i,%s,%i,%s\n' % \
2351 retStr += '%s,%i,%s,%i,%s,%i,%s\n' % \
2340 (name,
2352 (name,
2341 kindat,
2353 kindat,
2342 kindatdesc,
2354 kindatdesc,
2343 category,
2355 category,
2344 status,
2356 status,
2345 permission,
2357 permission,
2346 doi)
2358 doi)
2347
2359
2348
2360
2349
2361
2350 return render(request, 'madweb/service.html', {'text': django.utils.safestring.mark_safe(retStr)})
2362 return render(request, 'madweb/service.html', {'text': django.utils.safestring.mark_safe(retStr)})
2351
2363
2352
2364
2353 def get_parameters_service(request):
2365 def get_parameters_service(request):
2354 """get_parameters_service runs the getParametersService.py service.
2366 """get_parameters_service runs the getParametersService.py service.
2355
2367
2356 Inputs:
2368 Inputs:
2357 request/url - contains arguments:
2369 request/url - contains arguments:
2358
2370
2359 filename=<full path to data file>
2371 filename=<full path to data file>
2360
2372
2361 Returns backslash-delimited data, one for each parameter either measured or derivable, with the following fields:
2373 Returns backslash-delimited data, one for each parameter either measured or derivable, with the following fields:
2362
2374
2363 1. parameter.mnemonic (string) Example 'dti'
2375 1. parameter.mnemonic (string) Example 'dti'
2364
2376
2365 2. parameter.description (string) Example:
2377 2. parameter.description (string) Example:
2366 "F10.7 Multiday average observed (Ott)"
2378 "F10.7 Multiday average observed (Ott)"
2367
2379
2368 3. parameter.isError (int) 1 if error parameter, 0 if not
2380 3. parameter.isError (int) 1 if error parameter, 0 if not
2369
2381
2370 4. parameter.units (string) Example "W/m2/Hz"
2382 4. parameter.units (string) Example "W/m2/Hz"
2371
2383
2372 5. parameter.isMeasured (int) 1 if measured, 0 if derivable
2384 5. parameter.isMeasured (int) 1 if measured, 0 if derivable
2373
2385
2374 6. parameter.category (string) Example: "Time Related Parameter"
2386 6. parameter.category (string) Example: "Time Related Parameter"
2375
2387
2376 7. parameter.isSure (int) - 1 if parameter can be found for every record, 0 if can only be found for some.
2388 7. parameter.isSure (int) - 1 if parameter can be found for every record, 0 if can only be found for some.
2377 Not relevant to Madrigal 3, where always 1
2389 Not relevant to Madrigal 3, where always 1
2378
2390
2379 8. parameter.isAddIncrement - 1 if additional increment, 0 if normal (Added in Madrigal 2.5)
2391 8. parameter.isAddIncrement - 1 if additional increment, 0 if normal (Added in Madrigal 2.5)
2380 Not relevant to Madrigal 3, where always -1
2392 Not relevant to Madrigal 3, where always -1
2381 """
2393 """
2382 filename = request.GET['filename']
2394 filename = request.GET['filename']
2383
2395
2384 # create MadrigalDB obj
2396 # create MadrigalDB obj
2385 madDBObj = madrigal.metadata.MadrigalDB()
2397 madDBObj = madrigal.metadata.MadrigalDB()
2386
2398
2387 # create Madrigal File object
2399 # create Madrigal File object
2388 madFileObj = madrigal.data.MadrigalFile(filename, madDBObj)
2400 madFileObj = madrigal.data.MadrigalFile(filename, madDBObj)
2389
2401
2390 # create Madrigal Parameter object
2402 # create Madrigal Parameter object
2391 madParmObj = madrigal.data.MadrigalParameters(madDBObj)
2403 madParmObj = madrigal.data.MadrigalParameters(madDBObj)
2392
2404
2393 # create Madrigal web object
2405 # create Madrigal web object
2394 madWebObj = madrigal.ui.web.MadrigalWebFormat()
2406 madWebObj = madrigal.ui.web.MadrigalWebFormat()
2395
2407
2396
2408
2397 # create lists of parameters
2409 # create lists of parameters
2398 measParmList = []
2410 measParmList = []
2399 derivedParmList = []
2411 derivedParmList = []
2400 allParmList = []
2412 allParmList = []
2401 sureParmList = []
2413 sureParmList = []
2402
2414
2403 # use the comprehensive list of parameters to check if derivable
2415 # use the comprehensive list of parameters to check if derivable
2404 parmList = madWebObj.getFormat('Comprehensive')
2416 parmList = madWebObj.getFormat('Comprehensive')
2405
2417
2406 # populate lists
2418 # populate lists
2407 madFileObj.getMeasDervBothParmLists(parmList,
2419 madFileObj.getMeasDervBothParmLists(parmList,
2408 measParmList,
2420 measParmList,
2409 derivedParmList,
2421 derivedParmList,
2410 allParmList,
2422 allParmList,
2411 sureParmList)
2423 sureParmList)
2412
2424
2413 retStr = ''
2425 retStr = ''
2414
2426
2415 # loop through allParmList and output results
2427 # loop through allParmList and output results
2416 for parm in allParmList:
2428 for parm in allParmList:
2417 description = madParmObj.getSimpleParmDescription(parm)
2429 description = madParmObj.getSimpleParmDescription(parm)
2418 isNorm = madParmObj.getParmType(parm)
2430 isNorm = madParmObj.getParmType(parm)
2419 if isNorm == 1:
2431 if isNorm == 1:
2420 isError = 0
2432 isError = 0
2421 else:
2433 else:
2422 isError = 1
2434 isError = 1
2423 units = madParmObj.getParmUnits(parm)
2435 units = madParmObj.getParmUnits(parm)
2424 if parm in measParmList:
2436 if parm in measParmList:
2425 isMeasured = 1
2437 isMeasured = 1
2426 else:
2438 else:
2427 isMeasured = 0
2439 isMeasured = 0
2428 if parm in sureParmList:
2440 if parm in sureParmList:
2429 isSure = 1
2441 isSure = 1
2430 else:
2442 else:
2431 isSure = 0
2443 isSure = 0
2432 category = madParmObj.getParmCategory(parm)
2444 category = madParmObj.getParmCategory(parm)
2433 try:
2445 try:
2434 if madParmObj.isAddIncrement(parm):
2446 if madParmObj.isAddIncrement(parm):
2435 isAddIncrement = 1
2447 isAddIncrement = 1
2436 else:
2448 else:
2437 isAddIncrement = 0
2449 isAddIncrement = 0
2438 except:
2450 except:
2439 isAddIncrement = -1
2451 isAddIncrement = -1
2440 # print out this parm
2452 # print out this parm
2441 retStr += '%s\\%s\\%i\\%s\\%i\\%s\\%i\\%i\n' % (parm,
2453 retStr += '%s\\%s\\%i\\%s\\%i\\%s\\%i\\%i\n' % (parm,
2442 description,
2454 description,
2443 isError,
2455 isError,
2444 units,
2456 units,
2445 isMeasured,
2457 isMeasured,
2446 category,
2458 category,
2447 isSure,
2459 isSure,
2448 isAddIncrement)
2460 isAddIncrement)
2449
2461
2450 return render(request, 'madweb/service.html', {'text': retStr})
2462 return render(request, 'madweb/service.html', {'text': retStr})
2451
2463
2452
2464
2453
2465
2454 def isprint_service(request):
2466 def isprint_service(request):
2455 """isprint_service runs the isprintService.py service.
2467 """isprint_service runs the isprintService.py service.
2456
2468
2457 Inputs:
2469 Inputs:
2458 request/url - contains arguments:
2470 request/url - contains arguments:
2459
2471
2460 'file': The full path to the file to be analyzed by isprint. If over 50 MB, returns error message.
2472 'file': The full path to the file to be analyzed by isprint. If over 50 MB, returns error message.
2461
2473
2462 'parms': Multiple requested parameters, space (+) separated.
2474 'parms': Multiple requested parameters, space (+) separated.
2463
2475
2464 'filters': Multiple of filters desired, as in isprint command
2476 'filters': Multiple of filters desired, as in isprint command
2465
2477
2466 'user_fullname' user name
2478 'user_fullname' user name
2467
2479
2468 'user_email' user email
2480 'user_email' user email
2469
2481
2470 'user_affiliation' user affiliation
2482 'user_affiliation' user affiliation
2471
2483
2472 'output' - option argument specifying output file basename. Will be Hdf5 format if extension in
2484 'output' - option argument specifying output file basename. Will be Hdf5 format if extension in
2473 ('hdf5', 'h5', 'hdf'). Will be netCDF4 is extension is '.nc'. Otherwise ascii. If not
2485 ('hdf5', 'h5', 'hdf'). Will be netCDF4 is extension is '.nc'. Otherwise ascii. If not
2474 given, output is ascii.
2486 given, output is ascii.
2475
2487
2476 'header': t for headers, f for no header. Defaults to no header. Ignored if not ascii output
2488 'header': t for headers, f for no header. Defaults to no header. Ignored if not ascii output
2477
2489
2478 Returns data as either column delimited ascii, Hdf5, or netCDF4.
2490 Returns data as either column delimited ascii, Hdf5, or netCDF4.
2479 """
2491 """
2480 madDB = madrigal.metadata.MadrigalDB()
2492 madDB = madrigal.metadata.MadrigalDB()
2481 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
2493 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
2482
2494
2483 # get required arguments
2495 # get required arguments
2484 thisFile = request.GET['file']
2496 thisFile = request.GET['file']
2485 parms = request.GET.getlist('parms')
2497 parms = request.GET.getlist('parms')
2486 filters = request.GET.getlist('filters')
2498 filters = request.GET.getlist('filters')
2487 user_fullname = request.GET['user_fullname']
2499 user_fullname = request.GET['user_fullname']
2488 user_email = request.GET['user_email']
2500 user_email = request.GET['user_email']
2489 user_affiliation = request.GET['user_affiliation']
2501 user_affiliation = request.GET['user_affiliation']
2490
2502
2491 # get optional arguments
2503 # get optional arguments
2492 try:
2504 try:
2493 output = os.path.basename(request.GET['output'])
2505 output = os.path.basename(request.GET['output'])
2494 filename, file_extension = os.path.splitext(output)
2506 filename, file_extension = os.path.splitext(output)
2495 if file_extension in ('.hdf5', '.h5', '.hdf'):
2507 if file_extension in ('.hdf5', '.h5', '.hdf'):
2496 format = 'Hdf5'
2508 format = 'Hdf5'
2497 elif file_extension in ('.nc',):
2509 elif file_extension in ('.nc',):
2498 format = 'netCDF4'
2510 format = 'netCDF4'
2499 else:
2511 else:
2500 format = 'ascii'
2512 format = 'ascii'
2501 except:
2513 except:
2502 format = 'ascii'
2514 format = 'ascii'
2503 output = None
2515 output = None
2504
2516
2505 # verify thisFile exists, not too big
2517 # verify thisFile exists, not too big
2506 errorMessage = None
2518 errorMessage = None
2507 if not os.access(thisFile, os.R_OK):
2519 if not os.access(thisFile, os.R_OK):
2508 errorMessage = 'File %s not found' % (thisFile)
2520 errorMessage = 'File %s not found' % (thisFile)
2509 elif os.path.getsize(thisFile) > 200.0E6:
2521 elif os.path.getsize(thisFile) > 200.0E6:
2510 errorMessage = 'File %s greater than 200 MB in size - running dynamic file creation not possible. Please use -- download as is -- instead.' % (thisFile)
2522 errorMessage = 'File %s greater than 200 MB in size - running dynamic file creation not possible. Please use -- download as is -- instead.' % (thisFile)
2511 if not errorMessage is None:
2523 if not errorMessage is None:
2512 return render(request, 'madweb/service.html', {'text': errorMessage})
2524 return render(request, 'madweb/service.html', {'text': errorMessage})
2513
2525
2514 if not output is None:
2526 if not output is None:
2515 # we need to write to a download file
2527 # we need to write to a download file
2516 downloadFile = os.path.join(tempfile.gettempdir(), output)
2528 downloadFile = os.path.join(tempfile.gettempdir(), output)
2517 if os.access(downloadFile, os.R_OK):
2529 if os.access(downloadFile, os.R_OK):
2518 try:
2530 try:
2519 os.remove(downloadFile)
2531 os.remove(downloadFile)
2520 except:
2532 except:
2521 pass
2533 pass
2522 try:
2534 try:
2523 header = request.GET['header']
2535 header = request.GET['header']
2524 if header not in ('t', 'f'):
2536 if header not in ('t', 'f'):
2525 raise ValueError('Unknown header value <%s>' % (header))
2537 raise ValueError('Unknown header value <%s>' % (header))
2526 except:
2538 except:
2527 header = 'f'
2539 header = 'f'
2528
2540
2529 # log data access
2541 # log data access
2530 madWebObj.logDataAccess(thisFile, user_fullname, user_email, user_affiliation)
2542 madWebObj.logDataAccess(thisFile, user_fullname, user_email, user_affiliation)
2531
2543
2532 # run isprint command
2544 # run isprint command
2533 cmd = '%s/bin/isprint file=%s ' % (madDB.getMadroot(), thisFile)
2545 cmd = '%s/bin/isprint file=%s ' % (madDB.getMadroot(), thisFile)
2534 if not output is None:
2546 if not output is None:
2535 cmd += 'output=%s ' % (downloadFile)
2547 cmd += 'output=%s ' % (downloadFile)
2536 delimiter = ' '
2548 delimiter = ' '
2537 cmd += delimiter.join(parms) + ' '
2549 cmd += delimiter.join(parms) + ' '
2538 filterStr = delimiter.join(filters)
2550 filterStr = delimiter.join(filters)
2539 cmd += filterStr + ' '
2551 cmd += filterStr + ' '
2540 if format == 'ascii':
2552 if format == 'ascii':
2541 cmd += 'summary=f '
2553 cmd += 'summary=f '
2542 cmd += 'header=%s ' % (header)
2554 cmd += 'header=%s ' % (header)
2543
2555
2544 if output is None:
2556 if output is None:
2545 # text response
2557 # text response
2546 #result = subprocess.check_output(cmd.split())
2558 #result = subprocess.check_output(cmd.split())
2547 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
2559 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
2548 result,errtext = p.communicate()
2560 result,errtext = p.communicate()
2549 if p.returncode != 0:
2561 if p.returncode != 0:
2550 result = errtext
2562 result = errtext
2551 if type(result) in (bytes, numpy.bytes_):
2563 if type(result) in (bytes, numpy.bytes_):
2552 result = result.decode('utf-8')
2564 result = result.decode('utf-8')
2553 if header == 'f':
2565 if header == 'f':
2554 index = result.find('\n')
2566 index = result.find('\n')
2555 result = result[index+1:]
2567 result = result[index+1:]
2556 return render(request, 'madweb/service.html', {'text': result})
2568 return render(request, 'madweb/service.html', {'text': result})
2557 else:
2569 else:
2558 # file download response
2570 # file download response
2559 #subprocess.check_call(cmd.split())
2571 #subprocess.check_call(cmd.split())
2560 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
2572 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
2561 result,errtext = p.communicate()
2573 result,errtext = p.communicate()
2562 if p.returncode != 0:
2574 if p.returncode != 0:
2563 # write the error to result file
2575 # write the error to result file
2564 f = open(downloadFile, 'w')
2576 f = open(downloadFile, 'w')
2565 if type(errtext) in (bytes, numpy.bytes_):
2577 if type(errtext) in (bytes, numpy.bytes_):
2566 errtext = errtext.decode('utf-8')
2578 errtext = errtext.decode('utf-8')
2567 f.write(errtext)
2579 f.write(errtext)
2568 f.close()
2580 f.close()
2569
2581
2570 f = open(downloadFile, 'rb')
2582 f = open(downloadFile, 'rb')
2571 filename = os.path.basename(downloadFile)
2583 filename = os.path.basename(downloadFile)
2572 chunk_size = 8192
2584 chunk_size = 8192
2573 file_type = mimetypes.guess_type(downloadFile)[0]
2585 file_type = mimetypes.guess_type(downloadFile)[0]
2574 if file_type is None:
2586 if file_type is None:
2575 file_type = 'application/octet-stream'
2587 file_type = 'application/octet-stream'
2576 response = StreamingHttpResponse(FileWrapper(f, chunk_size),
2588 response = StreamingHttpResponse(FileWrapper(f, chunk_size),
2577 content_type=file_type)
2589 content_type=file_type)
2578 response['Content-Length'] = os.path.getsize(downloadFile)
2590 response['Content-Length'] = os.path.getsize(downloadFile)
2579 response['Content-Disposition'] = "attachment; filename=%s" % (filename)
2591 response['Content-Disposition'] = "attachment; filename=%s" % (filename)
2580 os.remove(downloadFile)
2592 os.remove(downloadFile)
2581 return(response)
2593 return(response)
2582
2594
2583
2595
2584 def get_madfile_service(request):
2596 def get_madfile_service(request):
2585 """get_madfile_service runs the getMadfile.cgi service.
2597 """get_madfile_service runs the getMadfile.cgi service.
2586
2598
2587 Inputs:
2599 Inputs:
2588 request/url - contains arguments:
2600 request/url - contains arguments:
2589
2601
2590 'fileName': The full path to the file to be downloaded as.
2602 'fileName': The full path to the file to be downloaded as.
2591
2603
2592 'fileType': -1 for ascii, -2 for Hdf5, -3 for netCDF4. No other values supported
2604 'fileType': -1 for ascii, -2 for Hdf5, -3 for netCDF4. No other values supported
2593
2605
2594 'user_fullname' user name
2606 'user_fullname' user name
2595
2607
2596 'user_email' user email
2608 'user_email' user email
2597
2609
2598 'user_affiliation' user affiliation
2610 'user_affiliation' user affiliation
2599
2611
2600 Returns file as either column delimited ascii, Hdf5, or netCDF4.
2612 Returns file as either column delimited ascii, Hdf5, or netCDF4.
2601 """
2613 """
2602 madDB = madrigal.metadata.MadrigalDB()
2614 madDB = madrigal.metadata.MadrigalDB()
2603 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
2615 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
2604
2616
2605 # get required arguments
2617 # get required arguments
2606 fileName = request.GET['fileName']
2618 fileName = request.GET['fileName']
2607 fileType = int(request.GET['fileType'])
2619 fileType = int(request.GET['fileType'])
2608 user_fullname = request.GET['user_fullname']
2620 user_fullname = request.GET['user_fullname']
2609 user_email = request.GET['user_email']
2621 user_email = request.GET['user_email']
2610 user_affiliation = request.GET['user_affiliation']
2622 user_affiliation = request.GET['user_affiliation']
2611
2623
2612 if fileType not in (-1, -2, -3):
2624 if fileType not in (-1, -2, -3):
2613 return(HttpResponse('<p>fileType %i not allowed: -1 for ascii, -2 for Hdf5, -3 for netCDF4</p>' % (fileType)))
2625 return(HttpResponse('<p>fileType %i not allowed: -1 for ascii, -2 for Hdf5, -3 for netCDF4</p>' % (fileType)))
2614
2626
2615 # log data access
2627 # log data access
2616 madWebObj.logDataAccess(fileName, user_fullname, user_email, user_affiliation)
2628 madWebObj.logDataAccess(fileName, user_fullname, user_email, user_affiliation)
2617
2629
2618 if fileType in (-1, -3):
2630 if fileType in (-1, -3):
2619 # may need to create temp file
2631 # may need to create temp file
2620 filepath, file_extension = os.path.splitext(fileName)
2632 filepath, file_extension = os.path.splitext(fileName)
2621 basename = os.path.basename(filepath)
2633 basename = os.path.basename(filepath)
2622 dirname = os.path.dirname(fileName)
2634 dirname = os.path.dirname(fileName)
2623 if fileType == -1:
2635 if fileType == -1:
2624 cachedTxtFile = os.path.join(dirname, 'overview', os.path.basename(fileName) + '.txt.gz')
2636 cachedTxtFile = os.path.join(dirname, 'overview', os.path.basename(fileName) + '.txt.gz')
2625 tmpFile = os.path.join(tempfile.gettempdir(), basename + '.txt.gz')
2637 tmpFile = os.path.join(tempfile.gettempdir(), basename + '.txt.gz')
2626 if os.access(cachedTxtFile, os.R_OK):
2638 if os.access(cachedTxtFile, os.R_OK):
2627 shutil.copy(cachedTxtFile, tmpFile)
2639 shutil.copy(cachedTxtFile, tmpFile)
2628 else:
2640 else:
2629 tmpFile = os.path.join(tempfile.gettempdir(), basename + '.txt')
2641 tmpFile = os.path.join(tempfile.gettempdir(), basename + '.txt')
2630 madrigal.cedar.convertToText(fileName, tmpFile)
2642 madrigal.cedar.convertToText(fileName, tmpFile)
2631 else:
2643 else:
2632 cachedNCFile = os.path.join(dirname, 'overview', os.path.basename(fileName) + '.nc')
2644 cachedNCFile = os.path.join(dirname, 'overview', os.path.basename(fileName) + '.nc')
2633 tmpFile = os.path.join(tempfile.gettempdir(), basename + '.nc')
2645 tmpFile = os.path.join(tempfile.gettempdir(), basename + '.nc')
2634 if os.access(cachedNCFile, os.R_OK):
2646 if os.access(cachedNCFile, os.R_OK):
2635 shutil.copy(cachedNCFile, tmpFile)
2647 shutil.copy(cachedNCFile, tmpFile)
2636 else:
2648 else:
2637 try:
2649 try:
2638 madrigal.cedar.convertToNetCDF4(fileName, tmpFile)
2650 madrigal.cedar.convertToNetCDF4(fileName, tmpFile)
2639 except IOError:
2651 except IOError:
2640 cedarObj = madrigal.cedar.MadrigalCedarFile(fileName)
2652 cedarObj = madrigal.cedar.MadrigalCedarFile(fileName)
2641 cedarObj.write('netCDF4', tmpFile)
2653 cedarObj.write('netCDF4', tmpFile)
2642
2654
2643 else:
2655 else:
2644 tmpFile = fileName
2656 tmpFile = fileName
2645
2657
2646 f = open(tmpFile, 'rb')
2658 f = open(tmpFile, 'rb')
2647 filename = os.path.basename(tmpFile)
2659 filename = os.path.basename(tmpFile)
2648 chunk_size = 8192
2660 chunk_size = 8192
2649 file_type = mimetypes.guess_type(tmpFile)[0]
2661 file_type = mimetypes.guess_type(tmpFile)[0]
2650 if file_type is None:
2662 if file_type is None:
2651 file_type = 'application/octet-stream'
2663 file_type = 'application/octet-stream'
2652 response = StreamingHttpResponse(FileWrapper(f, chunk_size),
2664 response = StreamingHttpResponse(FileWrapper(f, chunk_size),
2653 content_type=file_type)
2665 content_type=file_type)
2654 response['Content-Length'] = os.path.getsize(tmpFile)
2666 response['Content-Length'] = os.path.getsize(tmpFile)
2655 response['Content-Disposition'] = "attachment; filename=%s" % (filename)
2667 response['Content-Disposition'] = "attachment; filename=%s" % (filename)
2656 if fileType in (-1, -3):
2668 if fileType in (-1, -3):
2657 os.remove(tmpFile)
2669 os.remove(tmpFile)
2658 return(response)
2670 return(response)
2659
2671
2660
2672
2661 def mad_calculator_service(request):
2673 def mad_calculator_service(request):
2662 """mad_calculator_service runs the madCalculator service.
2674 """mad_calculator_service runs the madCalculator service.
2663
2675
2664 Inputs:
2676 Inputs:
2665 request/url - contains arguments:
2677 request/url - contains arguments:
2666
2678
2667 year, month, day, hour, min, sec
2679 year, month, day, hour, min, sec
2668
2680
2669 startLat - Starting geodetic latitude, -90 to 90 (float)
2681 startLat - Starting geodetic latitude, -90 to 90 (float)
2670
2682
2671 endLat - Ending geodetic latitude, -90 to 90 (float)
2683 endLat - Ending geodetic latitude, -90 to 90 (float)
2672
2684
2673 stepLat - Latitude step (0.1 to 90) (float)
2685 stepLat - Latitude step (0.1 to 90) (float)
2674
2686
2675 startLong - Starting geodetic longitude, -180 to 180 (float)
2687 startLong - Starting geodetic longitude, -180 to 180 (float)
2676
2688
2677 endLong - Ending geodetic longitude, -180 to 180 (float)
2689 endLong - Ending geodetic longitude, -180 to 180 (float)
2678
2690
2679 stepLong - Longitude step (0.1 to 180) (float)
2691 stepLong - Longitude step (0.1 to 180) (float)
2680
2692
2681 startAlt - Starting geodetic altitude, >= 0 (float)
2693 startAlt - Starting geodetic altitude, >= 0 (float)
2682
2694
2683 endAlt - Ending geodetic altitude, > 0 (float)
2695 endAlt - Ending geodetic altitude, > 0 (float)
2684
2696
2685 stepAlt - Altitude step (>= 0.1) (float)
2697 stepAlt - Altitude step (>= 0.1) (float)
2686
2698
2687 parms - comma delimited string of Madrigal parameters desired
2699 parms - comma delimited string of Madrigal parameters desired
2688
2700
2689 oneD - zero or more mnemonics,float values to set input 1D values
2701 oneD - zero or more mnemonics,float values to set input 1D values
2690
2702
2691 Returns comma-delimited data, one line for each combination of lat, long, and alt,
2703 Returns comma-delimited data, one line for each combination of lat, long, and alt,
2692 with the following fields:
2704 with the following fields:
2693
2705
2694 1. latitude
2706 1. latitude
2695
2707
2696 2. longitude
2708 2. longitude
2697
2709
2698 3. altitude
2710 3. altitude
2699
2711
2700 4. Values for each Madrigal parameter listed in argument parms, separated by whitespace
2712 4. Values for each Madrigal parameter listed in argument parms, separated by whitespace
2701 """
2713 """
2702 year = int(request.GET['year'])
2714 year = int(request.GET['year'])
2703 month = int(request.GET['month'])
2715 month = int(request.GET['month'])
2704 day = int(request.GET['day'])
2716 day = int(request.GET['day'])
2705 hour = int(request.GET['hour'])
2717 hour = int(request.GET['hour'])
2706 minute = int(request.GET['min'])
2718 minute = int(request.GET['min'])
2707 second = int(request.GET['sec'])
2719 second = int(request.GET['sec'])
2708 try:
2720 try:
2709 dt = datetime.datetime(year, month, day, hour, minute, second)
2721 dt = datetime.datetime(year, month, day, hour, minute, second)
2710 except:
2722 except:
2711 return(HttpResponse('Illegal time: year %i, month %i, day %i, hour %i, minute %i, second %i' % (year, month, day, hour, minute, second)))
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 startLat = float(request.GET['startLat'])
2725 startLat = float(request.GET['startLat'])
2714 endLat = float(request.GET['endLat'])
2726 endLat = float(request.GET['endLat'])
2715 if startLat == endLat:
2727 if startLat == endLat:
2716 endLat += 0.001
2728 endLat += 0.001
2717 elif startLat > endLat:
2729 elif startLat > endLat:
2718 return(HttpResponse('startLat %s cannot be greater than endLat %s' % (str(startLat), str(endLat))))
2730 return(HttpResponse('startLat %s cannot be greater than endLat %s' % (str(startLat), str(endLat))))
2719 stepLat = float(request.GET['stepLat'])
2731 stepLat = float(request.GET['stepLat'])
2720 if stepLat < 0.0:
2732 if stepLat < 0.0:
2721 return(HttpResponse('stepLat %s cannot be less than zero' % (str(stepLat))))
2733 return(HttpResponse('stepLat %s cannot be less than zero' % (str(stepLat))))
2722 elif stepLat == 0.0:
2734 elif stepLat == 0.0:
2723 stepLat = 0.001
2735 stepLat = 0.001
2724 latList = list(numpy.arange(startLat, endLat, stepLat))
2736 latList = list(numpy.arange(startLat, endLat, stepLat))
2725
2737
2726 startLong = float(request.GET['startLong'])
2738 startLong = float(request.GET['startLong'])
2727 endLong = float(request.GET['endLong'])
2739 endLong = float(request.GET['endLong'])
2728 if startLong == endLong:
2740 if startLong == endLong:
2729 endLong += 0.001
2741 endLong += 0.001
2730 elif startLong > endLong:
2742 elif startLong > endLong:
2731 return(HttpResponse('startLong %s cannot be greater than endLong %s' % (str(startLong), str(endLong))))
2743 return(HttpResponse('startLong %s cannot be greater than endLong %s' % (str(startLong), str(endLong))))
2732 stepLong = float(request.GET['stepLong'])
2744 stepLong = float(request.GET['stepLong'])
2733 if stepLong < 0.0:
2745 if stepLong < 0.0:
2734 return(HttpResponse('stepLong %s cannot be less than zero' % (str(stepLong))))
2746 return(HttpResponse('stepLong %s cannot be less than zero' % (str(stepLong))))
2735 elif stepLong == 0.0:
2747 elif stepLong == 0.0:
2736 stepLong = 0.001
2748 stepLong = 0.001
2737 lonList = list(numpy.arange(startLong, endLong, stepLong))
2749 lonList = list(numpy.arange(startLong, endLong, stepLong))
2738
2750
2739 startAlt = float(request.GET['startAlt'])
2751 startAlt = float(request.GET['startAlt'])
2740 endAlt = float(request.GET['endAlt'])
2752 endAlt = float(request.GET['endAlt'])
2741 if startAlt == endAlt:
2753 if startAlt == endAlt:
2742 endAlt += 0.001
2754 endAlt += 0.001
2743 elif startAlt > endAlt:
2755 elif startAlt > endAlt:
2744 return(HttpResponse('startAlt %s cannot be greater than endAlt %s' % (str(startAlt), str(endAlt))))
2756 return(HttpResponse('startAlt %s cannot be greater than endAlt %s' % (str(startAlt), str(endAlt))))
2745 stepAlt = float(request.GET['stepAlt'])
2757 stepAlt = float(request.GET['stepAlt'])
2746 if stepAlt < 0.0:
2758 if stepAlt < 0.0:
2747 return(HttpResponse('stepAlt %s cannot be less than zero' % (str(stepAlt))))
2759 return(HttpResponse('stepAlt %s cannot be less than zero' % (str(stepAlt))))
2748 elif stepAlt == 0.0:
2760 elif stepAlt == 0.0:
2749 stepAlt = 0.01
2761 stepAlt = 0.01
2750 altList = list(numpy.arange(startAlt, endAlt, stepAlt))
2762 altList = list(numpy.arange(startAlt, endAlt, stepAlt))
2751
2763
2752 # limit total calculations to 1E5
2764 # limit total calculations to 1E5
2753 total = len(latList) * len(lonList) * len(altList)
2765 total = len(latList) * len(lonList) * len(altList)
2754 if total > 1.0E5:
2766 if total > 1.0E5:
2755 return(HttpResponse('Too many points for madCalculatorService: %i' % (total)))
2767 return(HttpResponse('Too many points for madCalculatorService: %i' % (total)))
2756
2768
2757 parms = request.GET['parms']
2769 parms = request.GET['parms']
2758 desiredParmList = [item.strip() for item in ['gdlat','glon','gdalt'] + parms.split(',')]
2770 desiredParmList = [item.strip() for item in ['gdlat','glon','gdalt'] + parms.split(',')]
2759
2771
2760 oneDList = request.GET.getlist('oneD')
2772 oneDList = request.GET.getlist('oneD')
2761 oneDParmDict = {}
2773 oneDParmDict = {}
2762 for oneDStr in oneDList:
2774 for oneDStr in oneDList:
2763 mnem, strValue = oneDStr.split(',')
2775 mnem, strValue = oneDStr.split(',')
2764 oneDParmDict[mnem] = [float(strValue)]
2776 oneDParmDict[mnem] = [float(strValue)]
2765
2777
2766 # capture stdout
2778 # capture stdout
2767 old_stdout = sys.stdout
2779 old_stdout = sys.stdout
2768 sys.stdout = mystdout = io.StringIO()
2780 sys.stdout = mystdout = io.StringIO()
2769 madrigal.isprint.MadCalculatorGrid(None, desiredParmList, [dt], latList, lonList, altList,
2781 madrigal.isprint.MadCalculatorGrid(None, desiredParmList, [dt], latList, lonList, altList,
2770 oneDParmDict, summary=None)
2782 oneDParmDict, summary=None)
2771 text = mystdout.getvalue()
2783 text = mystdout.getvalue()
2772 sys.stdout = old_stdout
2784 sys.stdout = old_stdout
2773
2785
2774 return render(request, 'madweb/service.html', {'text': text})
2786 return render(request, 'madweb/service.html', {'text': text})
2775
2787
2776
2788
2777 def mad_time_calculator_service(request):
2789 def mad_time_calculator_service(request):
2778 """mad_time_calculator_service runs the madTimeCalculator service. Input parameters must not be location dependent
2790 """mad_time_calculator_service runs the madTimeCalculator service. Input parameters must not be location dependent
2779
2791
2780 Inputs:
2792 Inputs:
2781 request/url - contains arguments:
2793 request/url - contains arguments:
2782
2794
2783 1. startyear - int
2795 1. startyear - int
2784
2796
2785 2. startmonth - int
2797 2. startmonth - int
2786
2798
2787 3. startday - int
2799 3. startday - int
2788
2800
2789 4. starthour - int
2801 4. starthour - int
2790
2802
2791 5. startmin - int
2803 5. startmin - int
2792
2804
2793 6. startsec - int
2805 6. startsec - int
2794
2806
2795 7. endyear - int
2807 7. endyear - int
2796
2808
2797 8. endmonth - int
2809 8. endmonth - int
2798
2810
2799 9. endday - int
2811 9. endday - int
2800
2812
2801 10. endhour - int
2813 10. endhour - int
2802
2814
2803 11. endmin - int
2815 11. endmin - int
2804
2816
2805 12. endsec - int
2817 12. endsec - int
2806
2818
2807 13. stephours - float - number of hours per time step
2819 13. stephours - float - number of hours per time step
2808
2820
2809 14. parms - comma delimited string of Madrigal parameters desired (must not depend on location)
2821 14. parms - comma delimited string of Madrigal parameters desired (must not depend on location)
2810
2822
2811 Returns comma-delimited data, one line for each year, month, day, hour, minute, and second,
2823 Returns comma-delimited data, one line for each year, month, day, hour, minute, and second,
2812 with the following fields:
2824 with the following fields:
2813
2825
2814 1-6: year, month, day, hour, minute, and second
2826 1-6: year, month, day, hour, minute, and second
2815
2827
2816 2. requested parm fields
2828 2. requested parm fields
2817 """
2829 """
2818 startyear = int(request.GET['startyear'])
2830 startyear = int(request.GET['startyear'])
2819 startmonth = int(request.GET['startmonth'])
2831 startmonth = int(request.GET['startmonth'])
2820 startday = int(request.GET['startday'])
2832 startday = int(request.GET['startday'])
2821 starthour = int(request.GET['starthour'])
2833 starthour = int(request.GET['starthour'])
2822 startminute = int(request.GET['startmin'])
2834 startminute = int(request.GET['startmin'])
2823 startsecond = int(request.GET['startsec'])
2835 startsecond = int(request.GET['startsec'])
2824 endyear = int(request.GET['endyear'])
2836 endyear = int(request.GET['endyear'])
2825 endmonth = int(request.GET['endmonth'])
2837 endmonth = int(request.GET['endmonth'])
2826 endday = int(request.GET['endday'])
2838 endday = int(request.GET['endday'])
2827 endhour = int(request.GET['endhour'])
2839 endhour = int(request.GET['endhour'])
2828 endminute = int(request.GET['endmin'])
2840 endminute = int(request.GET['endmin'])
2829 endsecond = int(request.GET['endsec'])
2841 endsecond = int(request.GET['endsec'])
2830 dt1 = datetime.datetime(startyear, startmonth, startday, starthour, startminute, startsecond)
2842 dt1 = datetime.datetime(startyear, startmonth, startday, starthour, startminute, startsecond)
2831 dt2 = datetime.datetime(endyear, endmonth, endday, endhour, endminute, endsecond)
2843 dt2 = datetime.datetime(endyear, endmonth, endday, endhour, endminute, endsecond)
2832 if dt1 > dt2:
2844 if dt1 > dt2:
2833 return(HttpResponse('End Datetime %s cannot be before start datetime %s' % (str(dt2), str(dt1))))
2845 return(HttpResponse('End Datetime %s cannot be before start datetime %s' % (str(dt2), str(dt1))))
2834
2846
2835 stephours = float(request.GET['stephours'])
2847 stephours = float(request.GET['stephours'])
2836 if stephours <= 0.0:
2848 if stephours <= 0.0:
2837 return(HttpResponse('stephours cannot be non-positive: %f' % (stephours)))
2849 return(HttpResponse('stephours cannot be non-positive: %f' % (stephours)))
2838
2850
2839 dtList = []
2851 dtList = []
2840 while dt1 <= dt2:
2852 while dt1 <= dt2:
2841 dtList.append(dt1)
2853 dtList.append(dt1)
2842 dt1 += datetime.timedelta(hours=stephours)
2854 dt1 += datetime.timedelta(hours=stephours)
2843
2855
2844 parms = request.GET['parms']
2856 parms = request.GET['parms']
2845 desiredParmList = [item.strip() for item in ['year','month','day','hour','min','sec'] + parms.split(',')]
2857 desiredParmList = [item.strip() for item in ['year','month','day','hour','min','sec'] + parms.split(',')]
2846
2858
2847 # no spatial data
2859 # no spatial data
2848 latList = lonList = altList = []
2860 latList = lonList = altList = []
2849 # capture stdout
2861 # capture stdout
2850 old_stdout = sys.stdout
2862 old_stdout = sys.stdout
2851 sys.stdout = mystdout = io.StringIO()
2863 sys.stdout = mystdout = io.StringIO()
2852 madrigal.isprint.MadCalculatorGrid(None, desiredParmList, dtList, latList, lonList, altList,
2864 madrigal.isprint.MadCalculatorGrid(None, desiredParmList, dtList, latList, lonList, altList,
2853 summary=None)
2865 summary=None)
2854 text = mystdout.getvalue()
2866 text = mystdout.getvalue()
2855 sys.stdout = old_stdout
2867 sys.stdout = old_stdout
2856
2868
2857 return render(request, 'madweb/service.html', {'text': text})
2869 return render(request, 'madweb/service.html', {'text': text})
2858
2870
2859
2871
2860
2872
2861 @csrf_exempt
2873 @csrf_exempt
2862 def mad_calculator2_service(request):
2874 def mad_calculator2_service(request):
2863 """mad_calculator2_service runs the madCalculator2 service.
2875 """mad_calculator2_service runs the madCalculator2 service.
2864
2876
2865 Differs from madCalulator in that positions are a list rather than a grid.
2877 Differs from madCalulator in that positions are a list rather than a grid.
2866
2878
2867 Inputs:
2879 Inputs:
2868 request/url - contains arguments:
2880 request/url - contains arguments:
2869
2881
2870 year, month, day, hour, min, sec
2882 year, month, day, hour, min, sec
2871
2883
2872 lats - comma separated list of latitudes to analyze
2884 lats - comma separated list of latitudes to analyze
2873
2885
2874 longs - comma separated list of longitudes to analyze. Len must == len(lats)
2886 longs - comma separated list of longitudes to analyze. Len must == len(lats)
2875
2887
2876 alts - comma separated list of altitudes to analyze. Len must == len(lats)
2888 alts - comma separated list of altitudes to analyze. Len must == len(lats)
2877
2889
2878 parms - comma delimited string of Madrigal parameters desired
2890 parms - comma delimited string of Madrigal parameters desired
2879
2891
2880 oneD - zero or more mnemonics,float values to set input 1D values
2892 oneD - zero or more mnemonics,float values to set input 1D values
2881 Example: &oneD=kinst,31.0&oneD=elm,45.0
2893 Example: &oneD=kinst,31.0&oneD=elm,45.0
2882
2894
2883 twoD - zero or more mnemonics,comma-separate float list of len(lats) to set input 2D values
2895 twoD - zero or more mnemonics,comma-separate float list of len(lats) to set input 2D values
2884 Example: twoD=te,1000,1100,1200 twoD=ti,1000,1000,1000
2896 Example: twoD=te,1000,1100,1200 twoD=ti,1000,1000,1000
2885 where there are 3 lats
2897 where there are 3 lats
2886
2898
2887 Returns comma-delimited data, one line for each lat value,
2899 Returns comma-delimited data, one line for each lat value,
2888 with the following fields:
2900 with the following fields:
2889
2901
2890 1. latitude
2902 1. latitude
2891
2903
2892 2. longitude
2904 2. longitude
2893
2905
2894 3. altitude
2906 3. altitude
2895
2907
2896 4. Values for each Madrigal parameter listed in argument parms, separated by whitespace
2908 4. Values for each Madrigal parameter listed in argument parms, separated by whitespace
2897 """
2909 """
2898 if request.method == 'POST':
2910 if request.method == 'POST':
2899 reqDict = request.POST
2911 reqDict = request.POST
2900 else:
2912 else:
2901 reqDict = request.GET
2913 reqDict = request.GET
2902 try:
2914 try:
2903 year = int(reqDict.get('year'))
2915 year = int(reqDict.get('year'))
2904 except TypeError:
2916 except TypeError:
2905 return(HttpResponse('<p>madCalculator2Service requires year</p>'))
2917 return(HttpResponse('<p>madCalculator2Service requires year</p>'))
2906 month = int(reqDict['month'])
2918 month = int(reqDict['month'])
2907 day = int(reqDict['day'])
2919 day = int(reqDict['day'])
2908 hour = int(reqDict['hour'])
2920 hour = int(reqDict['hour'])
2909 minute = int(reqDict['min'])
2921 minute = int(reqDict['min'])
2910 second = int(reqDict['sec'])
2922 second = int(reqDict['sec'])
2911 dt = datetime.datetime(year, month, day, hour, minute, second)
2923 dt = datetime.datetime(year, month, day, hour, minute, second)
2912
2924
2913 latsStr = reqDict['lats']
2925 latsStr = reqDict['lats']
2914 lats = [float(item) for item in latsStr.split(',')]
2926 lats = [float(item) for item in latsStr.split(',')]
2915 longsStr = reqDict['longs']
2927 longsStr = reqDict['longs']
2916 longs = [float(item) for item in longsStr.split(',')]
2928 longs = [float(item) for item in longsStr.split(',')]
2917 altsStr = reqDict['alts']
2929 altsStr = reqDict['alts']
2918 alts = [float(item) for item in altsStr.split(',')]
2930 alts = [float(item) for item in altsStr.split(',')]
2919
2931
2920 parms = reqDict['parms']
2932 parms = reqDict['parms']
2921 desiredParmList = [item.strip() for item in ['gdlat','glon','gdalt'] + parms.split(',')]
2933 desiredParmList = [item.strip() for item in ['gdlat','glon','gdalt'] + parms.split(',')]
2922
2934
2923 oneDList = reqDict.getlist('oneD')
2935 oneDList = reqDict.getlist('oneD')
2924 oneDParmDict = {}
2936 oneDParmDict = {}
2925 for oneDStr in oneDList:
2937 for oneDStr in oneDList:
2926 mnem, strValue = oneDStr.split(',')
2938 mnem, strValue = oneDStr.split(',')
2927 oneDParmDict[mnem] = [float(strValue)]
2939 oneDParmDict[mnem] = [float(strValue)]
2928
2940
2929 twoDList = reqDict.getlist('twoD')
2941 twoDList = reqDict.getlist('twoD')
2930
2942
2931 twoDParmDict = {}
2943 twoDParmDict = {}
2932 for twoDStr in twoDList:
2944 for twoDStr in twoDList:
2933 items = twoDStr.split(',')
2945 items = twoDStr.split(',')
2934 if len(items) != 1 + len(lats):
2946 if len(items) != 1 + len(lats):
2935 raise ValueError('twoDstr %s not correct number of points' % (str(twoDStr)))
2947 raise ValueError('twoDstr %s not correct number of points' % (str(twoDStr)))
2936 mnem = items[0]
2948 mnem = items[0]
2937 floatValues = [float(item) for item in items[1:]]
2949 floatValues = [float(item) for item in items[1:]]
2938 # now we need to expand these values to be two dimensional 1 x len(lats)
2950 # now we need to expand these values to be two dimensional 1 x len(lats)
2939 values = numpy.zeros((1,len(lats)), dtype=numpy.float)
2951 values = numpy.zeros((1,len(lats)), dtype=numpy.float)
2940 values[0][:] = floatValues
2952 values[0][:] = floatValues
2941 twoDParmDict[mnem] = values
2953 twoDParmDict[mnem] = values
2942
2954
2943 # capture stdout
2955 # capture stdout
2944 old_stdout = sys.stdout
2956 old_stdout = sys.stdout
2945 sys.stdout = mystdout = io.StringIO()
2957 sys.stdout = mystdout = io.StringIO()
2946 madrigal.isprint.MadCalculatorList(None, desiredParmList, [dt], lats, longs, alts,
2958 madrigal.isprint.MadCalculatorList(None, desiredParmList, [dt], lats, longs, alts,
2947 oneDParmDict, twoDParmDict, summary=None)
2959 oneDParmDict, twoDParmDict, summary=None)
2948 text = mystdout.getvalue()
2960 text = mystdout.getvalue()
2949 sys.stdout = old_stdout
2961 sys.stdout = old_stdout
2950
2962
2951 return render(request, 'madweb/service.html', {'text': text})
2963 return render(request, 'madweb/service.html', {'text': text})
2952
2964
2953
2965
2954
2966
2955
2967
2956 @csrf_exempt
2968 @csrf_exempt
2957 def mad_calculator3_service(request):
2969 def mad_calculator3_service(request):
2958 """mad_calculator3_service runs the madCalculator3 service.
2970 """mad_calculator3_service runs the madCalculator3 service.
2959
2971
2960 Differs from madCalulator in that multiple times, each with a unique list of positions, can be passed in.
2972 Differs from madCalulator in that multiple times, each with a unique list of positions, can be passed in.
2961
2973
2962 Inputs:
2974 Inputs:
2963 request/url - contains arguments:
2975 request/url - contains arguments:
2964
2976
2965 year - a comma-separated list of years - (required)
2977 year - a comma-separated list of years - (required)
2966
2978
2967 month - a comma-separated list of months - (required)
2979 month - a comma-separated list of months - (required)
2968
2980
2969 day - a comma-separated list of days - (required)
2981 day - a comma-separated list of days - (required)
2970
2982
2971 hour - a comma-separated list of hours - (required)
2983 hour - a comma-separated list of hours - (required)
2972
2984
2973 min - a comma-separated list of minutes - (required)
2985 min - a comma-separated list of minutes - (required)
2974
2986
2975 sec - a comma-separated list of seconds - (required)
2987 sec - a comma-separated list of seconds - (required)
2976
2988
2977 numPos - a comma-sepatated list of the number of positions for each time - (required)
2989 numPos - a comma-sepatated list of the number of positions for each time - (required)
2978
2990
2979 lats - a comma-separated list of geodetic latitudes, -90 to 90 (required). Listed
2991 lats - a comma-separated list of geodetic latitudes, -90 to 90 (required). Listed
2980 for first time, then second, etc. Total must be equal to the sum
2992 for first time, then second, etc. Total must be equal to the sum
2981 of numPos.
2993 of numPos.
2982
2994
2983 longs - a comma-separated list of longitudes (required) Listed
2995 longs - a comma-separated list of longitudes (required) Listed
2984 for first time, then second, etc. Total must be equal to the sum
2996 for first time, then second, etc. Total must be equal to the sum
2985 of numPos.
2997 of numPos.
2986
2998
2987 alts - a comma-separated list of geodetic altitudes in km (required) Listed
2999 alts - a comma-separated list of geodetic altitudes in km (required) Listed
2988 for first time, then second, etc. Total must be equal to the sum
3000 for first time, then second, etc. Total must be equal to the sum
2989 of numPos.
3001 of numPos.
2990
3002
2991 parms - comma delimited string of Madrigal parameters desired (required)
3003 parms - comma delimited string of Madrigal parameters desired (required)
2992
3004
2993 oneD - string in form <parm>,<comma-separated values> This argument allows the user to
3005 oneD - string in form <parm>,<comma-separated values> This argument allows the user to
2994 set any number of one-D parameters to be used in the calculation.
3006 set any number of one-D parameters to be used in the calculation.
2995 Value must be parameter name, comma, list of values as double,
3007 Value must be parameter name, comma, list of values as double,
2996 where length of list is equal to number of times.
3008 where length of list is equal to number of times.
2997 Example: &oneD=kinst,31.0,31.0&oneD=elm,45.0,50
3009 Example: &oneD=kinst,31.0,31.0&oneD=elm,45.0,50
2998 (optional - 0 or more allowed)
3010 (optional - 0 or more allowed)
2999
3011
3000 twoD=<parm>,<values> (optional - 0 or more allowed) This argument allows the user to
3012 twoD=<parm>,<values> (optional - 0 or more allowed) This argument allows the user to
3001 set any number of two-D parameters to be used in the calculation.
3013 set any number of two-D parameters to be used in the calculation.
3002 Value must be parameter name, comma, comma-separated values.
3014 Value must be parameter name, comma, comma-separated values.
3003 Number of values must equal the sum of numPos. Order is
3015 Number of values must equal the sum of numPos. Order is
3004 first time values first, then second time values, etc
3016 first time values first, then second time values, etc
3005 Example: twoD=te,1000,1100,1200,1000,1100,1200 &twoD=ti,1000,1000,1000,1000,1000,1000
3017 Example: twoD=te,1000,1100,1200,1000,1100,1200 &twoD=ti,1000,1000,1000,1000,1000,1000
3006 where numPos=3,3
3018 where numPos=3,3
3007
3019
3008 Returns comma-delimited data, one line for each location. Separate times are delimited by line
3020 Returns comma-delimited data, one line for each location. Separate times are delimited by line
3009
3021
3010 TIME MM/DD/YYYY HH:MM:SS
3022 TIME MM/DD/YYYY HH:MM:SS
3011
3023
3012 Data lines have the following fields:
3024 Data lines have the following fields:
3013
3025
3014 1. latitude
3026 1. latitude
3015
3027
3016 2. longitude
3028 2. longitude
3017
3029
3018 3. altitude
3030 3. altitude
3019
3031
3020 4. Values for each Madrigal parameter listed in argument parms, separated by whitespace
3032 4. Values for each Madrigal parameter listed in argument parms, separated by whitespace
3021 """
3033 """
3022 if request.method == 'POST':
3034 if request.method == 'POST':
3023 reqDict = request.POST
3035 reqDict = request.POST
3024 else:
3036 else:
3025 reqDict = request.GET
3037 reqDict = request.GET
3026 try:
3038 try:
3027 yearList = [int(item) for item in reqDict.get('year').split(',')]
3039 yearList = [int(item) for item in reqDict.get('year').split(',')]
3028 except AttributeError:
3040 except AttributeError:
3029 return(HttpResponse('<p>madCalculator3Service requires year</p>'))
3041 return(HttpResponse('<p>madCalculator3Service requires year</p>'))
3030 monthList = [int(item) for item in reqDict.get('month').split(',')]
3042 monthList = [int(item) for item in reqDict.get('month').split(',')]
3031 dayList = [int(item) for item in reqDict.get('day').split(',')]
3043 dayList = [int(item) for item in reqDict.get('day').split(',')]
3032 hourList = [int(item) for item in reqDict.get('hour').split(',')]
3044 hourList = [int(item) for item in reqDict.get('hour').split(',')]
3033 minList = [int(item) for item in reqDict.get('min').split(',')]
3045 minList = [int(item) for item in reqDict.get('min').split(',')]
3034 secList = [int(item) for item in reqDict.get('sec').split(',')]
3046 secList = [int(item) for item in reqDict.get('sec').split(',')]
3035 dtList = [datetime.datetime(yearList[i], monthList[i], dayList[i],
3047 dtList = [datetime.datetime(yearList[i], monthList[i], dayList[i],
3036 hourList[i], minList[i], secList[i]) for i in range(len(yearList))]
3048 hourList[i], minList[i], secList[i]) for i in range(len(yearList))]
3037 numPosStr = reqDict['numPos']
3049 numPosStr = reqDict['numPos']
3038 numPosList = [int(item) for item in numPosStr.split(',')]
3050 numPosList = [int(item) for item in numPosStr.split(',')]
3039 totalPos = 0
3051 totalPos = 0
3040 for numPos in numPosList:
3052 for numPos in numPosList:
3041 totalPos += numPos
3053 totalPos += numPos
3042 latsStr = reqDict['lats']
3054 latsStr = reqDict['lats']
3043 lats = [float(item) for item in latsStr.split(',')]
3055 lats = [float(item) for item in latsStr.split(',')]
3044 if len(lats) != totalPos:
3056 if len(lats) != totalPos:
3045 return(HttpResponse('wrong number of lats, expected %i' % (totalPos)))
3057 return(HttpResponse('wrong number of lats, expected %i' % (totalPos)))
3046 longsStr = reqDict['longs']
3058 longsStr = reqDict['longs']
3047 longs = [float(item) for item in longsStr.split(',')]
3059 longs = [float(item) for item in longsStr.split(',')]
3048 if len(longs) != totalPos:
3060 if len(longs) != totalPos:
3049 return(HttpResponse('wrong number of longs, expected %i' % (totalPos)))
3061 return(HttpResponse('wrong number of longs, expected %i' % (totalPos)))
3050 altsStr = reqDict['alts']
3062 altsStr = reqDict['alts']
3051 alts = [float(item) for item in altsStr.split(',')]
3063 alts = [float(item) for item in altsStr.split(',')]
3052 if len(alts) != totalPos:
3064 if len(alts) != totalPos:
3053 return(HttpResponse('wrong number of alts, expected %i' % (totalPos)))
3065 return(HttpResponse('wrong number of alts, expected %i' % (totalPos)))
3054
3066
3055 parms = reqDict['parms']
3067 parms = reqDict['parms']
3056 desiredParmList = [item.strip() for item in ['gdlat','glon','gdalt'] + parms.split(',')]
3068 desiredParmList = [item.strip() for item in ['gdlat','glon','gdalt'] + parms.split(',')]
3057
3069
3058 oneDList = reqDict.getlist('oneD')
3070 oneDList = reqDict.getlist('oneD')
3059 twoDList = reqDict.getlist('twoD')
3071 twoDList = reqDict.getlist('twoD')
3060
3072
3061 # since the positions can change with each call, we need to call madrigal.isprint.MadCalculatorGrid once for each time
3073 # since the positions can change with each call, we need to call madrigal.isprint.MadCalculatorGrid once for each time
3062 startIndex = 0
3074 startIndex = 0
3063 endIndex = 0
3075 endIndex = 0
3064 fullText = ''
3076 fullText = ''
3065 for timeIndex, numPos in enumerate(numPosList):
3077 for timeIndex, numPos in enumerate(numPosList):
3066 startIndex = endIndex
3078 startIndex = endIndex
3067 endIndex += numPos
3079 endIndex += numPos
3068 thisLats = lats[startIndex:endIndex]
3080 thisLats = lats[startIndex:endIndex]
3069 thisLongs = longs[startIndex:endIndex]
3081 thisLongs = longs[startIndex:endIndex]
3070 thisAlts = alts[startIndex:endIndex]
3082 thisAlts = alts[startIndex:endIndex]
3071
3083
3072 oneDParmDict = {}
3084 oneDParmDict = {}
3073 for oneDStr in oneDList:
3085 for oneDStr in oneDList:
3074 values = oneDStr.split(',')
3086 values = oneDStr.split(',')
3075 if len(values) != 1+len(dtList):
3087 if len(values) != 1+len(dtList):
3076 return(HttpResponse('wrong number of values given for 1D parm %s' % (values[0])))
3088 return(HttpResponse('wrong number of values given for 1D parm %s' % (values[0])))
3077 oneDParmDict[values[0]] = [float(values[timeIndex+1])]
3089 oneDParmDict[values[0]] = [float(values[timeIndex+1])]
3078
3090
3079 twoDParmDict = {}
3091 twoDParmDict = {}
3080
3092
3081 for twoDStr in twoDList:
3093 for twoDStr in twoDList:
3082 values = twoDStr.split(',')
3094 values = twoDStr.split(',')
3083 if len(values) != 1 + totalPos:
3095 if len(values) != 1 + totalPos:
3084 return(HttpResponse('twoDstr %s not correct number of points' % (str(twoDStr))))
3096 return(HttpResponse('twoDstr %s not correct number of points' % (str(twoDStr))))
3085 mnem = values[0]
3097 mnem = values[0]
3086 floatValues = [float(item) for item in values[1+startIndex:1+endIndex]]
3098 floatValues = [float(item) for item in values[1+startIndex:1+endIndex]]
3087 # now we need to expand these values to be two dimensional - 1,len(thisLats)
3099 # now we need to expand these values to be two dimensional - 1,len(thisLats)
3088 values2D = numpy.zeros((1,len(thisLats)), dtype=numpy.float)
3100 values2D = numpy.zeros((1,len(thisLats)), dtype=numpy.float)
3089 values2D[0][:] = floatValues
3101 values2D[0][:] = floatValues
3090 twoDParmDict[mnem] = values2D
3102 twoDParmDict[mnem] = values2D
3091
3103
3092
3104
3093
3105
3094 # capture stdout
3106 # capture stdout
3095 old_stdout = sys.stdout
3107 old_stdout = sys.stdout
3096 sys.stdout = mystdout = io.StringIO()
3108 sys.stdout = mystdout = io.StringIO()
3097 madrigal.isprint.MadCalculatorList(None, desiredParmList, [dtList[timeIndex]], thisLats,
3109 madrigal.isprint.MadCalculatorList(None, desiredParmList, [dtList[timeIndex]], thisLats,
3098 thisLongs, thisAlts,
3110 thisLongs, thisAlts,
3099 oneDParmDict, twoDParmDict, summary=None)
3111 oneDParmDict, twoDParmDict, summary=None)
3100 text = mystdout.getvalue()
3112 text = mystdout.getvalue()
3101 sys.stdout = old_stdout
3113 sys.stdout = old_stdout
3102
3114
3103 fullText += 'TIME %s\n' % (dtList[timeIndex].strftime('%m/%d/%Y %H:%M:%S'))
3115 fullText += 'TIME %s\n' % (dtList[timeIndex].strftime('%m/%d/%Y %H:%M:%S'))
3104 fullText += text
3116 fullText += text
3105
3117
3106 return render(request, 'madweb/service.html', {'text': fullText})
3118 return render(request, 'madweb/service.html', {'text': fullText})
3107
3119
3108
3120
3109
3121
3110 def geodetic_to_radar_service(request):
3122 def geodetic_to_radar_service(request):
3111 """geodetic_to_radar_service runs the geodeticToRadar service.
3123 """geodetic_to_radar_service runs the geodeticToRadar service.
3112
3124
3113 Inputs:
3125 Inputs:
3114 request/url - contains arguments:
3126 request/url - contains arguments:
3115
3127
3116 slatgd - radar geodetic latitude
3128 slatgd - radar geodetic latitude
3117
3129
3118 slon - radar longitude
3130 slon - radar longitude
3119
3131
3120 saltgd - radar geodetic altitude
3132 saltgd - radar geodetic altitude
3121
3133
3122 gdlat - a comma-separated list of geodetic latitude of point
3134 gdlat - a comma-separated list of geodetic latitude of point
3123
3135
3124 glon - a comma-separated list of longitude of point. Len must be same as gdlat
3136 glon - a comma-separated list of longitude of point. Len must be same as gdlat
3125
3137
3126 gdalt - a comma-separated list of geodetic altitude of point. Len must be same as gdlat
3138 gdalt - a comma-separated list of geodetic altitude of point. Len must be same as gdlat
3127
3139
3128
3140
3129 Returns comma-delimited data, one line for point in lists (points treated as individual combinations, not grids):
3141 Returns comma-delimited data, one line for point in lists (points treated as individual combinations, not grids):
3130
3142
3131 1. radar azimuth in degrees (0 = north)
3143 1. radar azimuth in degrees (0 = north)
3132
3144
3133 2. radar elevation in degrees
3145 2. radar elevation in degrees
3134
3146
3135 3. radar range in km
3147 3. radar range in km
3136 """
3148 """
3137 slatgd = float(request.GET['slatgd'])
3149 slatgd = float(request.GET['slatgd'])
3138 slon = float(request.GET['slon'])
3150 slon = float(request.GET['slon'])
3139 saltgd = float(request.GET['saltgd'])
3151 saltgd = float(request.GET['saltgd'])
3140 oneDParmDict = {'GDLATR': [slatgd],
3152 oneDParmDict = {'GDLATR': [slatgd],
3141 'GDLONR': [slon],
3153 'GDLONR': [slon],
3142 'GALTR': [saltgd]}
3154 'GALTR': [saltgd]}
3143 gdlatStr = request.GET['gdlat']
3155 gdlatStr = request.GET['gdlat']
3144 gdlatList = [float(item) for item in gdlatStr.split(',')]
3156 gdlatList = [float(item) for item in gdlatStr.split(',')]
3145 glonStr = request.GET['glon']
3157 glonStr = request.GET['glon']
3146 glonList = [float(item) for item in glonStr.split(',')]
3158 glonList = [float(item) for item in glonStr.split(',')]
3147 gdaltStr = request.GET['gdalt']
3159 gdaltStr = request.GET['gdalt']
3148 gdaltList = [float(item) for item in gdaltStr.split(',')]
3160 gdaltList = [float(item) for item in gdaltStr.split(',')]
3149 desiredParmList = ['azm', 'elm', 'range']
3161 desiredParmList = ['azm', 'elm', 'range']
3150 dtList = [datetime.datetime(2001,1,1)] # not relevant
3162 dtList = [datetime.datetime(2001,1,1)] # not relevant
3151 if len(gdlatList) != len(glonList) or len(gdlatList) != len(gdaltList):
3163 if len(gdlatList) != len(glonList) or len(gdlatList) != len(gdaltList):
3152 return(HttpResponse('all point list lengths must be equal'))
3164 return(HttpResponse('all point list lengths must be equal'))
3153
3165
3154 fullText = ''
3166 fullText = ''
3155
3167
3156 delimiter = ','
3168 delimiter = ','
3157 for i in range(len(gdlatList)):
3169 for i in range(len(gdlatList)):
3158 # capture stdout
3170 # capture stdout
3159 old_stdout = sys.stdout
3171 old_stdout = sys.stdout
3160 sys.stdout = mystdout = io.StringIO()
3172 sys.stdout = mystdout = io.StringIO()
3161 madrigal.isprint.MadCalculatorGrid(None, desiredParmList, dtList, [gdlatList[i]],
3173 madrigal.isprint.MadCalculatorGrid(None, desiredParmList, dtList, [gdlatList[i]],
3162 [glonList[i]], [gdaltList[i]], summary=None,
3174 [glonList[i]], [gdaltList[i]], summary=None,
3163 oneDParmDict=oneDParmDict)
3175 oneDParmDict=oneDParmDict)
3164 text = mystdout.getvalue()
3176 text = mystdout.getvalue()
3165 sys.stdout = old_stdout
3177 sys.stdout = old_stdout
3166 for line in text.split('\n'):
3178 for line in text.split('\n'):
3167 items = line.split()
3179 items = line.split()
3168 fullText += delimiter.join(items) + '\n'
3180 fullText += delimiter.join(items) + '\n'
3169
3181
3170 return render(request, 'madweb/service.html', {'text': fullText})
3182 return render(request, 'madweb/service.html', {'text': fullText})
3171
3183
3172
3184
3173 def radar_to_geodetic_service(request):
3185 def radar_to_geodetic_service(request):
3174 """radar_to_geodetic_service runs the radarToGeodetic service.
3186 """radar_to_geodetic_service runs the radarToGeodetic service.
3175
3187
3176 Inputs:
3188 Inputs:
3177 request/url - contains arguments:
3189 request/url - contains arguments:
3178
3190
3179 slatgd - radar geodetic latitude
3191 slatgd - radar geodetic latitude
3180
3192
3181 slon - radar longitude
3193 slon - radar longitude
3182
3194
3183 saltgd - radar geodetic altitude
3195 saltgd - radar geodetic altitude
3184
3196
3185 azs - a comma-separated list of azimuths of point
3197 azs - a comma-separated list of azimuths of point
3186
3198
3187 els - a comma-separated list of elevations of point. Len must be same as azs
3199 els - a comma-separated list of elevations of point. Len must be same as azs
3188
3200
3189 ranges - a comma-separated list of ranges to point. Len must be same as azs
3201 ranges - a comma-separated list of ranges to point. Len must be same as azs
3190
3202
3191
3203
3192 Returns comma-delimited data, one line for point in lists (points treated as individual combinations, not grids):
3204 Returns comma-delimited data, one line for point in lists (points treated as individual combinations, not grids):
3193
3205
3194 1. geodetic latitude
3206 1. geodetic latitude
3195
3207
3196 2. longitude (-180 to 180)
3208 2. longitude (-180 to 180)
3197
3209
3198 3. geodetic altitude in km
3210 3. geodetic altitude in km
3199 """
3211 """
3200 slatgd = float(request.GET['slatgd'])
3212 slatgd = float(request.GET['slatgd'])
3201 slon = float(request.GET['slon'])
3213 slon = float(request.GET['slon'])
3202 saltgd = float(request.GET['saltgd'])
3214 saltgd = float(request.GET['saltgd'])
3203 azStr = request.GET['az']
3215 azStr = request.GET['az']
3204 azList = [float(item) for item in azStr.split(',')]
3216 azList = [float(item) for item in azStr.split(',')]
3205 elStr = request.GET['el']
3217 elStr = request.GET['el']
3206 elList = [float(item) for item in elStr.split(',')]
3218 elList = [float(item) for item in elStr.split(',')]
3207 rangeStr = request.GET['range']
3219 rangeStr = request.GET['range']
3208 rangeList = [float(item) for item in rangeStr.split(',')]
3220 rangeList = [float(item) for item in rangeStr.split(',')]
3209 if len(azList) != len(elList) or len(azList) != len(rangeList):
3221 if len(azList) != len(elList) or len(azList) != len(rangeList):
3210 return(HttpResponse('all point list lengths must be equal'))
3222 return(HttpResponse('all point list lengths must be equal'))
3211
3223
3212 fullText = ''
3224 fullText = ''
3213
3225
3214 for i in range(len(azList)):
3226 for i in range(len(azList)):
3215 gdlat,glon,gdalt = madrigal._derive.radarToGeodetic(slatgd, slon, saltgd,
3227 gdlat,glon,gdalt = madrigal._derive.radarToGeodetic(slatgd, slon, saltgd,
3216 azList[i], elList[i], rangeList[i])
3228 azList[i], elList[i], rangeList[i])
3217 fullText += '%f,%f,%f\n' % (gdlat,glon,gdalt)
3229 fullText += '%f,%f,%f\n' % (gdlat,glon,gdalt)
3218
3230
3219 return render(request, 'madweb/service.html', {'text': fullText})
3231 return render(request, 'madweb/service.html', {'text': fullText})
3220
3232
3221
3233
3222
3234
3223 def list_file_times_service(request):
3235 def list_file_times_service(request):
3224 """list_file_times_service runs the listFileTimes service.
3236 """list_file_times_service runs the listFileTimes service.
3225
3237
3226 Inputs:
3238 Inputs:
3227 request/url - contains arguments:
3239 request/url - contains arguments:
3228
3240
3229 Optional: expDir - experiment directory to list. Can be absolute or relative to
3241 Optional: expDir - experiment directory to list. Can be absolute or relative to
3230 experiments[0-9]*. Default is all files in $MADROOT/experiments*
3242 experiments[0-9]*. Default is all files in $MADROOT/experiments*
3231
3243
3232 Returns comma-delimited data, one for each file:
3244 Returns comma-delimited data, one for each file:
3233
3245
3234 1. Full path of file
3246 1. Full path of file
3235
3247
3236 2. File modification time in form YYYY-MM-DD HH:MM:SS (UT time)
3248 2. File modification time in form YYYY-MM-DD HH:MM:SS (UT time)
3237 """
3249 """
3238 expDir = None
3250 expDir = None
3239 try:
3251 try:
3240 expDir = request.GET['expDir']
3252 expDir = request.GET['expDir']
3241 except:
3253 except:
3242 pass
3254 pass
3243 madDB = madrigal.metadata.MadrigalDB()
3255 madDB = madrigal.metadata.MadrigalDB()
3244 fileList = madDB.listFileTimes(expDir)
3256 fileList = madDB.listFileTimes(expDir)
3245 fullText = '\n\n'
3257 fullText = '\n\n'
3246 for filename, filetime in fileList:
3258 for filename, filetime in fileList:
3247 fullText += "\'%s\', %s\n" % (filename, filetime.strftime('%Y-%m-%d %H:%M:%S'))
3259 fullText += "\'%s\', %s\n" % (filename, filetime.strftime('%Y-%m-%d %H:%M:%S'))
3248
3260
3249 return render(request, 'madweb/service.html', {'text': django.utils.safestring.mark_safe(fullText)})
3261 return render(request, 'madweb/service.html', {'text': django.utils.safestring.mark_safe(fullText)})
3250
3262
3251
3263
3252 def download_web_file_service(request):
3264 def download_web_file_service(request):
3253 """download_web_file_service runs the downloadWebFile service.
3265 """download_web_file_service runs the downloadWebFile service.
3254
3266
3255 Inputs:
3267 Inputs:
3256 request/url - contains arguments:
3268 request/url - contains arguments:
3257
3269
3258 expPath - path to file starting at experiments*
3270 expPath - path to file starting at experiments*
3259
3271
3260 Returns comma-delimited data, one for each file:
3272 Returns comma-delimited data, one for each file:
3261
3273
3262 1. Full path of file
3274 1. Full path of file
3263
3275
3264 2. File modification time in form YYYY-MM-DD HH:MM:SS (UT time)
3276 2. File modification time in form YYYY-MM-DD HH:MM:SS (UT time)
3265 """
3277 """
3266 expPath = request.GET['expPath']
3278 expPath = request.GET['expPath']
3267 madDB = madrigal.metadata.MadrigalDB()
3279 madDB = madrigal.metadata.MadrigalDB()
3268 downloadFile = os.path.join(madDB.getMadroot(), expPath)
3280 downloadFile = os.path.join(madDB.getMadroot(), expPath)
3269 f = open(downloadFile, 'rb')
3281 f = open(downloadFile, 'rb')
3270 thisFile = django.core.files.File(f)
3282 thisFile = django.core.files.File(f)
3271 response = HttpResponse(thisFile, content_type='application/x-octet-stream')
3283 response = HttpResponse(thisFile, content_type='application/x-octet-stream')
3272 response['Content-Disposition'] = 'attachment; filename="' + os.path.basename(downloadFile) + '"'
3284 response['Content-Disposition'] = 'attachment; filename="' + os.path.basename(downloadFile) + '"'
3273 response['Content-Length'] = os.path.getsize(downloadFile)
3285 response['Content-Length'] = os.path.getsize(downloadFile)
3274 return(response)
3286 return(response)
3275
3287
3276
3288
3277 def trace_magnetic_field_service(request):
3289 def trace_magnetic_field_service(request):
3278 """trace_magnetic_field_service runs the traceMagneticField service.
3290 """trace_magnetic_field_service runs the traceMagneticField service.
3279
3291
3280 Inputs:
3292 Inputs:
3281 request/url - contains arguments:
3293 request/url - contains arguments:
3282
3294
3283 year, month, day, hour, min, sec
3295 year, month, day, hour, min, sec
3284
3296
3285 inputType (0 for geodetic, 1 for GSM)
3297 inputType (0 for geodetic, 1 for GSM)
3286
3298
3287 outputType (0 for geodetic, 1 for GSM)
3299 outputType (0 for geodetic, 1 for GSM)
3288
3300
3289 The following parameter depend on inputType:
3301 The following parameter depend on inputType:
3290
3302
3291 in1 - a comma-separated list of geodetic altitudes or ZGSMs of starting point
3303 in1 - a comma-separated list of geodetic altitudes or ZGSMs of starting point
3292
3304
3293 in2 - a comma-separated list of geodetic latitudes or XGSMs of starting point
3305 in2 - a comma-separated list of geodetic latitudes or XGSMs of starting point
3294
3306
3295 in3 - a comma-separated list of longitude or YGSM of starting point
3307 in3 - a comma-separated list of longitude or YGSM of starting point
3296
3308
3297 Length of all three lists must be the same
3309 Length of all three lists must be the same
3298
3310
3299 model - 0 for Tsyganenko, 1 for IGRF
3311 model - 0 for Tsyganenko, 1 for IGRF
3300
3312
3301 qualifier - 0 for conjugate, 1 for north_alt, 2 for south_alt, 3 for apex, 4 for GSM XY plane
3313 qualifier - 0 for conjugate, 1 for north_alt, 2 for south_alt, 3 for apex, 4 for GSM XY plane
3302
3314
3303 stopAlt - altitude in km to stop trace at, if qualifier is north_alt or south_alt.
3315 stopAlt - altitude in km to stop trace at, if qualifier is north_alt or south_alt.
3304
3316
3305 If other qualifier, this parameter is not required.
3317 If other qualifier, this parameter is not required.
3306
3318
3307 Returns comma-delimited data, one line for point in in lists:
3319 Returns comma-delimited data, one line for point in in lists:
3308
3320
3309 1. geodetic altitude or ZGSM of ending point
3321 1. geodetic altitude or ZGSM of ending point
3310
3322
3311 2. geodetic latitude or XGSM of ending point
3323 2. geodetic latitude or XGSM of ending point
3312
3324
3313 3. longitude or YGSM of ending point
3325 3. longitude or YGSM of ending point
3314 """
3326 """
3315 year = int(request.GET['year'])
3327 year = int(request.GET['year'])
3316 month = int(request.GET['month'])
3328 month = int(request.GET['month'])
3317 day = int(request.GET['day'])
3329 day = int(request.GET['day'])
3318 hour = int(request.GET['hour'])
3330 hour = int(request.GET['hour'])
3319 minute = int(request.GET['min'])
3331 minute = int(request.GET['min'])
3320 second = int(request.GET['sec'])
3332 second = int(request.GET['sec'])
3321 dt = datetime.datetime(year, month, day, hour, minute, second)
3333 dt = datetime.datetime(year, month, day, hour, minute, second)
3322 inputType = int(request.GET['inputType'])
3334 inputType = int(request.GET['inputType'])
3323 if inputType not in (0,1):
3335 if inputType not in (0,1):
3324 return(HttpResponse('inputType must be 0 or 1, not %i' % (inputType)))
3336 return(HttpResponse('inputType must be 0 or 1, not %i' % (inputType)))
3325 outputType = int(request.GET['outputType'])
3337 outputType = int(request.GET['outputType'])
3326 if outputType not in (0,1):
3338 if outputType not in (0,1):
3327 return(HttpResponse('outputType must be 0 or 1, not %i' % (outputType)))
3339 return(HttpResponse('outputType must be 0 or 1, not %i' % (outputType)))
3328 in1Str = request.GET['in1']
3340 in1Str = request.GET['in1']
3329 in1List = [float(item) for item in in1Str.split(',')]
3341 in1List = [float(item) for item in in1Str.split(',')]
3330 in2Str = request.GET['in2']
3342 in2Str = request.GET['in2']
3331 in2List = [float(item) for item in in2Str.split(',')]
3343 in2List = [float(item) for item in in2Str.split(',')]
3332 in3Str = request.GET['in3']
3344 in3Str = request.GET['in3']
3333 in3List = [float(item) for item in in3Str.split(',')]
3345 in3List = [float(item) for item in in3Str.split(',')]
3334 if len(in1List) != len(in2List) or len(in1List) != len(in3List):
3346 if len(in1List) != len(in2List) or len(in1List) != len(in3List):
3335 return(HttpResponse('All three in* lists must have same length'))
3347 return(HttpResponse('All three in* lists must have same length'))
3336 model = int(request.GET['model'])
3348 model = int(request.GET['model'])
3337 if model not in (0,1):
3349 if model not in (0,1):
3338 return(HttpResponse('model must be 0 or 1, not %i' % (model)))
3350 return(HttpResponse('model must be 0 or 1, not %i' % (model)))
3339 qualifier = int(request.GET['qualifier'])
3351 qualifier = int(request.GET['qualifier'])
3340 if qualifier not in (0,1,2,3,4):
3352 if qualifier not in (0,1,2,3,4):
3341 return(HttpResponse('model must be in 0,1,2,3,4 not %i' % (model)))
3353 return(HttpResponse('model must be in 0,1,2,3,4 not %i' % (model)))
3342 try:
3354 try:
3343 stopAlt = float(request.GET['stopAlt'])
3355 stopAlt = float(request.GET['stopAlt'])
3344 except:
3356 except:
3345 stopAlt = 0.0
3357 stopAlt = 0.0
3346
3358
3347 fullText = ''
3359 fullText = ''
3348 resultArr = numpy.zeros((3,), dtype='f8')
3360 resultArr = numpy.zeros((3,), dtype='f8')
3349 madDB = madrigal.metadata.MadrigalDB()
3361 madDB = madrigal.metadata.MadrigalDB()
3350 madDeriveObj = madrigal.derivation.MadrigalDerivationMethods(madDB.getMadroot())
3362 madDeriveObj = madrigal.derivation.MadrigalDerivationMethods(madDB.getMadroot())
3351 for i in range(len(in1List)):
3363 for i in range(len(in1List)):
3352 madDeriveObj.traceMagneticField(year, month, day, hour, minute, second,
3364 madDeriveObj.traceMagneticField(year, month, day, hour, minute, second,
3353 inputType, outputType, in1List[i], in2List[i], in3List[i],
3365 inputType, outputType, in1List[i], in2List[i], in3List[i],
3354 model, qualifier, stopAlt, resultArr)
3366 model, qualifier, stopAlt, resultArr)
3355 fullText += '%f,%f,%f\n' % (resultArr[0], resultArr[1], resultArr[2])
3367 fullText += '%f,%f,%f\n' % (resultArr[0], resultArr[1], resultArr[2])
3356
3368
3357 return render(request, 'madweb/service.html', {'text': fullText})
3369 return render(request, 'madweb/service.html', {'text': fullText})
3358
3370
3359
3371
3360 def global_file_search_service(request):
3372 def global_file_search_service(request):
3361 """global_file_search_service returns a list of full paths to files or citable urls based on search arguments
3373 """global_file_search_service returns a list of full paths to files or citable urls based on search arguments
3362
3374
3363 Inputs:
3375 Inputs:
3364 request/url - contains arguments:
3376 request/url - contains arguments:
3365
3377
3366 startDate: start date in form YYYY-MM-DD to filter experiments before
3378 startDate: start date in form YYYY-MM-DD to filter experiments before
3367 endDate: end date in form YYYY-MM-DD to filter experiments after
3379 endDate: end date in form YYYY-MM-DD to filter experiments after
3368 inst: (optional, multiple allowed) an instrument code or name. For names,
3380 inst: (optional, multiple allowed) an instrument code or name. For names,
3369 fnmatch will be used. If not set, all instruments used.
3381 fnmatch will be used. If not set, all instruments used.
3370 kindat: (optional, multiple allowed) a kind of data codes or name. For names,
3382 kindat: (optional, multiple allowed) a kind of data codes or name. For names,
3371 fnmatch will be used. If not set, all kinds of data used.
3383 fnmatch will be used. If not set, all kinds of data used.
3372 seasonalStartDate: (optional) in form MM/DD, rejects all days earlier in year. If not set
3384 seasonalStartDate: (optional) in form MM/DD, rejects all days earlier in year. If not set
3373 implies 01/01
3385 implies 01/01
3374 seasonalEndDate: (optional) in form MM/DD, rejects all days later in year. If not set
3386 seasonalEndDate: (optional) in form MM/DD, rejects all days later in year. If not set
3375 implies 12/31
3387 implies 12/31
3376 includeNonDefault: (optional) if "True", include realtime files when there are no default.
3388 includeNonDefault: (optional) if "True", include realtime files when there are no default.
3377 If not set, only default files.
3389 If not set, only default files.
3378 expName: (optional) - filter experiments by the experiment name. fnmatch rules
3390 expName: (optional) - filter experiments by the experiment name. fnmatch rules
3379 If not set, no filtering by experiment name.
3391 If not set, no filtering by experiment name.
3380 excludeExpName: (optional) - exclude experiments by the experiment name. fnmatch rules
3392 excludeExpName: (optional) - exclude experiments by the experiment name. fnmatch rules
3381 If not set, no excluding experiments by experiment name.
3393 If not set, no excluding experiments by experiment name.
3382 fileDesc: (optional) filter files using input file Description string via fnmatch.
3394 fileDesc: (optional) filter files using input file Description string via fnmatch.
3383 If not set, in no filtering by file name
3395 If not set, in no filtering by file name
3384 returnCitation: (optional) if True, return a list of file citations. If not set, return
3396 returnCitation: (optional) if True, return a list of file citations. If not set, return
3385 a list of full paths to the files selected
3397 a list of full paths to the files selected
3386
3398
3387 """
3399 """
3388 madDB = madrigal.metadata.MadrigalDB()
3400 madDB = madrigal.metadata.MadrigalDB()
3389 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
3401 madWebObj = madrigal.ui.web.MadrigalWeb(madDB)
3390
3402
3391 # get required arguments
3403 # get required arguments
3392 startDate = request.GET['startDate']
3404 startDate = request.GET['startDate']
3393 endDate = request.GET['endDate']
3405 endDate = request.GET['endDate']
3394 startDate = datetime.datetime.strptime(startDate, '%Y-%m-%d')
3406 startDate = datetime.datetime.strptime(startDate, '%Y-%m-%d')
3395 endDate = datetime.datetime.strptime(endDate, '%Y-%m-%d')
3407 endDate = datetime.datetime.strptime(endDate, '%Y-%m-%d')
3396
3408
3397 # get optional arguments
3409 # get optional arguments
3398 inst = request.GET.getlist('inst')
3410 inst = request.GET.getlist('inst')
3399 if inst == []:
3411 if inst == []:
3400 inst = None
3412 inst = None
3401 kindat = request.GET.getlist('kindat')
3413 kindat = request.GET.getlist('kindat')
3402 if kindat == []:
3414 if kindat == []:
3403 kindat = None
3415 kindat = None
3404 seasonalStartDate = request.GET.get('seasonalStartDate', default = None)
3416 seasonalStartDate = request.GET.get('seasonalStartDate', default = None)
3405 seasonalEndDate = request.GET.get('seasonalEndDate', default = None)
3417 seasonalEndDate = request.GET.get('seasonalEndDate', default = None)
3406 includeNonDefault = bool(request.GET.get('includeNonDefault', default = False))
3418 includeNonDefault = bool(request.GET.get('includeNonDefault', default = False))
3407 expName = request.GET.get('expName', default = None)
3419 expName = request.GET.get('expName', default = None)
3408 excludeExpName = request.GET.get('excludeExpName', default = None)
3420 excludeExpName = request.GET.get('excludeExpName', default = None)
3409 fileDesc = request.GET.get('fileDesc', default = None)
3421 fileDesc = request.GET.get('fileDesc', default = None)
3410 returnCitation = bool(request.GET.get('returnCitation', default = False))
3422 returnCitation = bool(request.GET.get('returnCitation', default = False))
3411
3423
3412 result = madWebObj.global_file_search(startDate, endDate, inst, kindat,
3424 result = madWebObj.global_file_search(startDate, endDate, inst, kindat,
3413 seasonalStartDate, seasonalEndDate,
3425 seasonalStartDate, seasonalEndDate,
3414 includeNonDefault, expName, excludeExpName,
3426 includeNonDefault, expName, excludeExpName,
3415 fileDesc, returnCitation)
3427 fileDesc, returnCitation)
3416
3428
3417 fullText = ''
3429 fullText = ''
3418 for item in result:
3430 for item in result:
3419 fullText += '%s\n' % (item)
3431 fullText += '%s\n' % (item)
3420
3432
3421 return render(request, 'madweb/service.html', {'text': django.utils.safestring.mark_safe(fullText)})
3433 return render(request, 'madweb/service.html', {'text': django.utils.safestring.mark_safe(fullText)})
3422
3434
3423
3435
3424
3436
3425
3437
3426 def get_url_list_from_group_id_service(request):
3438 def get_url_list_from_group_id_service(request):
3427 """get_url_list_from_group_id_service returns a list of citable urls associated with group id.
3439 """get_url_list_from_group_id_service returns a list of citable urls associated with group id.
3428
3440
3429 Inputs:
3441 Inputs:
3430 request/url - contains arguments:
3442 request/url - contains arguments:
3431
3443
3432 id - group id
3444 id - group id
3433
3445
3434 Returns one line for each citable url
3446 Returns one line for each citable url
3435
3447
3436 Returns empty string if experiment id not found. Skips files that are not Hdf5
3448 Returns empty string if experiment id not found. Skips files that are not Hdf5
3437 """
3449 """
3438 id = int(request.GET['id'])
3450 id = int(request.GET['id'])
3439
3451
3440 # create MadrigalDB obj
3452 # create MadrigalDB obj
3441 madDBObj = madrigal.metadata.MadrigalDB()
3453 madDBObj = madrigal.metadata.MadrigalDB()
3442
3454
3443 urlList = madDBObj.getListFromGroupId(id)
3455 urlList = madDBObj.getListFromGroupId(id)
3444
3456
3445 retStr = ''
3457 retStr = ''
3446 for url in urlList:
3458 for url in urlList:
3447 retStr += '%s\n' % (url)
3459 retStr += '%s\n' % (url)
3448
3460
3449 return render(request, 'madweb/service.html', {'text': django.utils.safestring.mark_safe(retStr)})
3461 return render(request, 'madweb/service.html', {'text': django.utils.safestring.mark_safe(retStr)})
3450
3462
3451
3463
3452 def set_group_id_from_url_list_service(request):
3464 def set_group_id_from_url_list_service(request):
3453 """set_group_id_from_url_list sets a list of citable urls to a group id .
3465 """set_group_id_from_url_list sets a list of citable urls to a group id .
3454
3466
3455 Inputs:
3467 Inputs:
3456 request/url - contains arguments:
3468 request/url - contains arguments:
3457
3469
3458 'user_fullname' user name
3470 'user_fullname' user name
3459
3471
3460 'user_email' user email
3472 'user_email' user email
3461
3473
3462 'user_affiliation' user affiliation
3474 'user_affiliation' user affiliation
3463
3475
3464 'url' - citable url. Multiple arguments allowed
3476 'url' - citable url. Multiple arguments allowed
3465
3477
3466 Returns group id (integer) set
3478 Returns group id (integer) set
3467 """
3479 """
3468 madDB = madrigal.metadata.MadrigalDB()
3480 madDB = madrigal.metadata.MadrigalDB()
3469
3481
3470 print(request.GET)
3482 print(request.GET)
3471
3483
3472 # get required arguments
3484 # get required arguments
3473 urls = request.GET.getlist('url')
3485 urls = request.GET.getlist('url')
3474 user_fullname = request.GET['user_fullname']
3486 user_fullname = request.GET['user_fullname']
3475 user_email = request.GET['user_email']
3487 user_email = request.GET['user_email']
3476 user_affiliation = request.GET['user_affiliation']
3488 user_affiliation = request.GET['user_affiliation']
3477
3489
3478 id = madDB.createGroupIdWithList(user_fullname, user_email, user_affiliation, urls)
3490 id = madDB.createGroupIdWithList(user_fullname, user_email, user_affiliation, urls)
3479
3491
3480 return render(request, 'madweb/service.html', {'text': str(id)})
3492 return render(request, 'madweb/service.html', {'text': str(id)})
3481
3493
3482
3494
3483 ### doc pages ###
3495 ### doc pages ###
3484
3496
3485 def docs(request, name):
3497 def docs(request, name):
3486 madDB = madrigal.metadata.MadrigalDB()
3498 madDB = madrigal.metadata.MadrigalDB()
3487 openMadObj = madrigal.openmadrigal.OpenMadrigal(madDB)
3499 openMadObj = madrigal.openmadrigal.OpenMadrigal(madDB)
3488 bg_color = madDB.getBackgroundColor()
3500 bg_color = madDB.getBackgroundColor()
3489 if name.find('..') != -1:
3501 if name.find('..') != -1:
3490 # no trying to look elsewhere
3502 # no trying to look elsewhere
3491 return(HttpResponse('Illegal name passed to docs: <%s>' % (name)))
3503 return(HttpResponse('Illegal name passed to docs: <%s>' % (name)))
3492 # check if siteSpecitic.html
3504 # check if siteSpecitic.html
3493 siteSpecificPath = os.path.join(madDB.getMadroot(), 'source/madpy/djangoMad/madweb/templates/madweb/siteSpecific.html')
3505 siteSpecificPath = os.path.join(madDB.getMadroot(), 'source/madpy/djangoMad/madweb/templates/madweb/siteSpecific.html')
3494 if os.access(siteSpecificPath, os.R_OK):
3506 if os.access(siteSpecificPath, os.R_OK):
3495 siteSpecific = reverse('docs', args=['siteSpecific.html'])
3507 siteSpecific = reverse('docs', args=['siteSpecific.html'])
3496 else:
3508 else:
3497 siteSpecific = '#'
3509 siteSpecific = '#'
3498 openmadrigal = openMadObj.getOpenMadrigalUrl()
3510 openmadrigal = openMadObj.getOpenMadrigalUrl()
3499 # since google insists filenames are case insensitive, convert to right name if there is no direct match if possible
3511 # since google insists filenames are case insensitive, convert to right name if there is no direct match if possible
3500 this_file = os.path.join(madDB.getMadroot(), 'source/madpy/djangoMad/madweb/templates/madweb', name)
3512 this_file = os.path.join(madDB.getMadroot(), 'source/madpy/djangoMad/madweb/templates/madweb', name)
3501 if not os.access(this_file, os.R_OK):
3513 if not os.access(this_file, os.R_OK):
3502 found = False
3514 found = False
3503 existing_files = glob.glob(os.path.join(madDB.getMadroot(), 'source/madpy/djangoMad/madweb/templates/madweb/*.html'))
3515 existing_files = glob.glob(os.path.join(madDB.getMadroot(), 'source/madpy/djangoMad/madweb/templates/madweb/*.html'))
3504 for existing_file in existing_files:
3516 for existing_file in existing_files:
3505 if name.lower() == os.path.basename(existing_file).lower():
3517 if name.lower() == os.path.basename(existing_file).lower():
3506 name = os.path.basename(existing_file)
3518 name = os.path.basename(existing_file)
3507 found = True
3519 found = True
3508 break # correct name found and name modified
3520 break # correct name found and name modified
3509 if not found:
3521 if not found:
3510 return(HttpResponse('<p>Cannot find %s</p>' % (str(name))))
3522 return(HttpResponse('<p>Cannot find %s</p>' % (str(name))))
3511
3523
3512 if os.path.isdir(this_file):
3524 if os.path.isdir(this_file):
3513 return(HttpResponse('<p>%s is a directory</p>' % (str(name))))
3525 return(HttpResponse('<p>%s is a directory</p>' % (str(name))))
3514
3526
3515 return render(request, 'madweb/%s' % (name), {'bg_color': bg_color, 'siteSpecific': siteSpecific,
3527 return render(request, 'madweb/%s' % (name), {'bg_color': bg_color, 'siteSpecific': siteSpecific,
3516 'openmadrigal': openmadrigal})
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