1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 |
@@ -0,0 +1,17 | |||||
|
1 | {% extends "base.html" %} | |||
|
2 | ||||
|
3 | {% block title %}Login{% endblock %} | |||
|
4 | ||||
|
5 | {% block content %} | |||
|
6 | <center> | |||
|
7 | <h4>Please login</h4> | |||
|
8 | ||||
|
9 | <div style="margin-top: 30px;"> | |||
|
10 | <form method="POST"> | |||
|
11 | {{ form.as_p }} | |||
|
12 | {% csrf_token %} | |||
|
13 | <button type="submit">Login</button> | |||
|
14 | </form> | |||
|
15 | </div> | |||
|
16 | </center> | |||
|
17 | {% endblock %} |
@@ -0,0 +1,9 | |||||
|
1 | from django.conf.urls import url | |||
|
2 | from . import views | |||
|
3 | ||||
|
4 | urlpatterns = [ | |||
|
5 | url(r'^login/$', views.login_view, name='login'), | |||
|
6 | url(r'^logout/$', views.logout_view, name='logout'), | |||
|
7 | ] | |||
|
8 | ||||
|
9 | app_name = 'login' No newline at end of file |
@@ -0,0 +1,38 | |||||
|
1 | from django.contrib.auth import authenticate | |||
|
2 | from django.contrib.auth import login, logout | |||
|
3 | from django.contrib.auth.forms import AuthenticationForm | |||
|
4 | from django.shortcuts import render, redirect | |||
|
5 | ||||
|
6 | ''' Login to updata app for ROJ staff''' | |||
|
7 | ||||
|
8 | def login_view(request): | |||
|
9 | ||||
|
10 | form = AuthenticationForm() | |||
|
11 | if request.method == "POST": | |||
|
12 | form = AuthenticationForm(data=request.POST) | |||
|
13 | ||||
|
14 | if form.is_valid(): | |||
|
15 | ||||
|
16 | username = form.cleaned_data['username'] | |||
|
17 | password = form.cleaned_data['password'] | |||
|
18 | ||||
|
19 | user = authenticate(username=username, password=password) | |||
|
20 | ||||
|
21 | if user is not None: | |||
|
22 | ||||
|
23 | if user.is_active: | |||
|
24 | login(request, user) | |||
|
25 | ||||
|
26 | return redirect('/updata') | |||
|
27 | else: | |||
|
28 | return render(request, "login/login.html" ) | |||
|
29 | else: | |||
|
30 | context = {'error_login': "error"} | |||
|
31 | return render(request, "login/login.html", context ) | |||
|
32 | ||||
|
33 | return render(request, "login/login.html", {'form': form}) | |||
|
34 | ||||
|
35 | def logout_view(request): | |||
|
36 | ||||
|
37 | logout(request) | |||
|
38 | return redirect('/') No newline at end of file |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 |
@@ -0,0 +1,108 | |||||
|
1 | from django import forms | |||
|
2 | import django.utils.html | |||
|
3 | import django.utils.safestring | |||
|
4 | import django.template.defaulttags | |||
|
5 | ||||
|
6 | # third party imports | |||
|
7 | import numpy | |||
|
8 | ||||
|
9 | # Madrigal imports | |||
|
10 | import madrigal.metadata | |||
|
11 | import madrigal.ui.web | |||
|
12 | ||||
|
13 | # madrigal imports | |||
|
14 | import madrigal._derive | |||
|
15 | import madrigal.metadata | |||
|
16 | import madrigal.ui.web | |||
|
17 | import madrigal.cedar | |||
|
18 | import madrigal.isprint | |||
|
19 | import madweb.forms | |||
|
20 | ||||
|
21 | import datetime, time | |||
|
22 | ||||
|
23 | def getSelection(keyword, args, kwargs): | |||
|
24 | """getSelection returns '0' if keyword not a key in either args[0] or kwargs, | |||
|
25 | otherwise the value | |||
|
26 | ||||
|
27 | args, kwargs - arguments as passed into SingleExpDefaultForm __init__ | |||
|
28 | """ | |||
|
29 | if len(args) == 0 and len(list(kwargs.keys())) == 0: | |||
|
30 | return('0') # default case when no data passed in | |||
|
31 | elif len(args) > 0: | |||
|
32 | # args[0] is data dict argument to bind data | |||
|
33 | if keyword in args[0]: | |||
|
34 | return(args[0][keyword]) | |||
|
35 | else: | |||
|
36 | return('0') | |||
|
37 | elif keyword in kwargs: | |||
|
38 | return(kwargs[keyword]) | |||
|
39 | elif 'data' in kwargs: | |||
|
40 | if keyword in kwargs['data']: | |||
|
41 | return(kwargs['data'][keyword]) | |||
|
42 | else: | |||
|
43 | return('0') | |||
|
44 | else: | |||
|
45 | return('0') | |||
|
46 | ||||
|
47 | def getExperimentList(args, kwargs, madWeb, header='Select experiment: '): | |||
|
48 | ||||
|
49 | instrumentsId= int(getSelection('instruments', args, kwargs)) | |||
|
50 | ||||
|
51 | kinstList = [int(instrumentsId)] | |||
|
52 | startDate = datetime.datetime(1950,1,1) | |||
|
53 | startDT = datetime.datetime(startDate.year, startDate.month, startDate.day, 0, 0, 0) | |||
|
54 | now = datetime.datetime.now() | |||
|
55 | endDate = datetime.datetime(now.year, 12, 31, 23, 59, 59) | |||
|
56 | endDT = datetime.datetime(endDate.year, endDate.month, endDate.day, 23, 59, 59) | |||
|
57 | experiments = madWeb.getExperimentList(kinstList,startDT, endDT, True) | |||
|
58 | expListin = [('0', header),] | |||
|
59 | for exp in experiments: | |||
|
60 | expListin.append((exp[0], exp[2])) | |||
|
61 | ||||
|
62 | # Using set | |||
|
63 | seen = set() | |||
|
64 | ||||
|
65 | # using list comprehension | |||
|
66 | expList = [(a, b) for a, b in expListin | |||
|
67 | if not (b in seen or seen.add(b))] | |||
|
68 | ||||
|
69 | return(expList) | |||
|
70 | ||||
|
71 | class UpdataForm(forms.Form): | |||
|
72 | def __init__(self, *args, **kwargs): | |||
|
73 | super(UpdataForm, self).__init__(*args, **kwargs) | |||
|
74 | madDB = madrigal.metadata.MadrigalDB() | |||
|
75 | madInstData = madrigal.metadata.MadrigalInstrumentData(madDB) | |||
|
76 | instruments = madInstData.getInstruments(0, True) | |||
|
77 | instList = [('0', "Select Instrument"), ] | |||
|
78 | for kinst, instDesc, siteID in instruments: | |||
|
79 | instList.append((str(kinst), instDesc)) | |||
|
80 | ||||
|
81 | instrumentSelection = getSelection('instruments', args, kwargs) | |||
|
82 | self.fields['instruments'] = django.forms.ChoiceField(widget = django.forms.Select(attrs={"onChange":'populateExp(this)'}), | |||
|
83 | choices=instList, | |||
|
84 | initial=instrumentSelection, | |||
|
85 | label='Instrument:') | |||
|
86 | ||||
|
87 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) | |||
|
88 | experimentSelection = getSelection('experiments', args, kwargs) | |||
|
89 | self.fields['experiments'] = django.forms.ChoiceField(choices=getExperimentList(args, kwargs, madWebObj), | |||
|
90 | initial=experimentSelection, | |||
|
91 | required=False, label='Experiment:') | |||
|
92 | ||||
|
93 | description = forms.CharField(widget=forms.Textarea(attrs={'cols': 40,'rows': 3, 'style': 'resize:none'}), label='Description') | |||
|
94 | type = forms.ChoiceField(choices=[('0', 'Public'),('1', 'Private')], initial=0,widget=forms.RadioSelect(attrs={'class': 'custom-radio'})) | |||
|
95 | file = forms.FileField(label='Select Files', widget=forms.ClearableFileInput(attrs={'multiple': True})) | |||
|
96 | ||||
|
97 | class ExpForm(forms.Form): | |||
|
98 | """SingleExpInstForm is a Form class for the instrument select field in the Single Experiment interface. | |||
|
99 | Use this because its faster to create than the full SingleExpDefaultForm | |||
|
100 | """ | |||
|
101 | def __init__(self, *args, **kwargs): | |||
|
102 | super(ExpForm, self).__init__(*args, **kwargs) | |||
|
103 | madDB = madrigal.metadata.MadrigalDB() | |||
|
104 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) | |||
|
105 | experimentSelection = getSelection('experiments', args, kwargs) | |||
|
106 | self.fields['experiments'] = django.forms.ChoiceField(choices=getExperimentList(args, kwargs, madWebObj), | |||
|
107 | initial=experimentSelection, | |||
|
108 | required=False, label='Experiment') |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 |
@@ -0,0 +1,9 | |||||
|
1 | <div class="row"> | |||
|
2 | {{ form.experiments.label }} | |||
|
3 | </div> | |||
|
4 | <!-- Instrument select is its own row in selections column --> | |||
|
5 | <div class="row"> | |||
|
6 | <div class="col-md-12"> | |||
|
7 | {{ form.experiments }} | |||
|
8 | </div> <!-- end span --> | |||
|
9 | </div> <!-- end row --> No newline at end of file |
@@ -0,0 +1,102 | |||||
|
1 | {% extends "base.html" %} | |||
|
2 | {% block title %}Upload Data{% endblock %} | |||
|
3 | ||||
|
4 | {% block extra_head %} | |||
|
5 | <script type="text/javascript"> | |||
|
6 | function populateExp(select) { | |||
|
7 | ||||
|
8 | var kinst = select.options[select.selectedIndex].value; | |||
|
9 | var url = "{% url 'updata:get_experiments' %}" + '?instruments=' + kinst; | |||
|
10 | // first delete all forms that are now out of date | |||
|
11 | divIndex = $(".single_form").index($("#experiments")) | |||
|
12 | $(".single_form").slice(divIndex).empty() | |||
|
13 | // second populate the categories html | |||
|
14 | $(".single_form").slice(divIndex, divIndex + 1).load(url); | |||
|
15 | } | |||
|
16 | ||||
|
17 | </script> | |||
|
18 | ||||
|
19 | <style> | |||
|
20 | .custom-radio { | |||
|
21 | list-style: none; | |||
|
22 | margin: 0; | |||
|
23 | padding: 0; | |||
|
24 | } | |||
|
25 | </style> | |||
|
26 | {% endblock %} | |||
|
27 | ||||
|
28 | {% block content %} | |||
|
29 | ||||
|
30 | <center><h4>Upload Data</h4></center> | |||
|
31 | <form method="post" enctype="multipart/form-data"> | |||
|
32 | ||||
|
33 | {% csrf_token %} | |||
|
34 | ||||
|
35 | {% block description %} | |||
|
36 | <!-- subdivide selection column for instruments to be possibly filled in by ajax - single_form 0 --> | |||
|
37 | <div class="col-md-12 single_form" id="description"> | |||
|
38 | <div class="row"> | |||
|
39 | {{ form.description.label }} | |||
|
40 | </div> | |||
|
41 | <!-- Instrument select is its own row in selections column --> | |||
|
42 | <div class="row"> | |||
|
43 | <div class="col-md-12"> | |||
|
44 | {{ form.description }} | |||
|
45 | </div> <!-- end span --> | |||
|
46 | </div> <!-- end row --> | |||
|
47 | </div> <!-- end subdivide --> | |||
|
48 | ||||
|
49 | {% endblock %} | |||
|
50 | ||||
|
51 | {% block file %} | |||
|
52 | <div class="col-md-12 single_form" style="margin-top: 15px;" id="description"> | |||
|
53 | <div class="row"> | |||
|
54 | {{ form.file.label }} | |||
|
55 | </div> | |||
|
56 | <!-- Instrument select is its own row in selections column --> | |||
|
57 | <div class="row"> | |||
|
58 | <div class="col-md-12"> | |||
|
59 | {{ form.file }} | |||
|
60 | </div> <!-- end span --> | |||
|
61 | </div> <!-- end row --> | |||
|
62 | </div> <!-- end subdivide --> | |||
|
63 | ||||
|
64 | {% endblock %} | |||
|
65 | ||||
|
66 | {% block type %} | |||
|
67 | <div class="col-md-12 single_form" style="margin-top: 15px;" id="description"> | |||
|
68 | <!-- Instrument select is its own row in selections column --> | |||
|
69 | <div class="row"> | |||
|
70 | <div class="col-md-12"> | |||
|
71 | {{ form.type }} | |||
|
72 | </div> <!-- end span --> | |||
|
73 | </div> <!-- end row --> | |||
|
74 | </div> <!-- end subdivide --> | |||
|
75 | ||||
|
76 | {% endblock %} | |||
|
77 | ||||
|
78 | {% block instruments %} | |||
|
79 | <!-- subdivide selection column for instruments to be possibly filled in by ajax - single_form 0 --> | |||
|
80 | <div class="col-md-12 single_form" style="margin-top: 15px;" id="instruments"> | |||
|
81 | ||||
|
82 | {% if form.instruments %} | |||
|
83 | {% include "madweb/instruments.html" %} | |||
|
84 | {% endif %} | |||
|
85 | ||||
|
86 | </div> <!-- end subdivide --> | |||
|
87 | {% endblock %} | |||
|
88 | ||||
|
89 | {% block experiments %} | |||
|
90 | <!-- subdivide selection column for experiments to be possibly filled in by ajax - single_form 0 --> | |||
|
91 | <div class="col-md-12 single_form" style="margin-top: 15px;" id="experiments"> | |||
|
92 | ||||
|
93 | {% if form.experiments %} | |||
|
94 | {% include "updata/experiments.html" %} | |||
|
95 | {% endif %} | |||
|
96 | ||||
|
97 | </div> <!-- end subdivide --> | |||
|
98 | {% endblock %} | |||
|
99 | <button style="margin-top: 15px;" type="submit">Load</button> | |||
|
100 | ||||
|
101 | </form> | |||
|
102 | {% endblock %} No newline at end of file |
@@ -0,0 +1,9 | |||||
|
1 | from django.conf.urls import url | |||
|
2 | from . import views | |||
|
3 | ||||
|
4 | urlpatterns = [ | |||
|
5 | url(r'^$',views.index, name='updata_index'), | |||
|
6 | url(r'^getExperiments/?$', views.get_experiments, name='get_experiments'), | |||
|
7 | ] | |||
|
8 | ||||
|
9 | app_name = 'updata' No newline at end of file |
@@ -0,0 +1,83 | |||||
|
1 | ||||
|
2 | from django.contrib.auth.decorators import login_required | |||
|
3 | from django.shortcuts import render | |||
|
4 | from .forms import UpdataForm, ExpForm | |||
|
5 | from django.core.files.storage import FileSystemStorage | |||
|
6 | from django.contrib import messages | |||
|
7 | ||||
|
8 | import os | |||
|
9 | ||||
|
10 | # madrigal imports | |||
|
11 | import madrigal.metadata | |||
|
12 | import madrigal.ui.web | |||
|
13 | import madrigal.admin | |||
|
14 | ||||
|
15 | @login_required | |||
|
16 | def index(request): | |||
|
17 | ''' | |||
|
18 | Uploading experiments data view. Allows user to upload experiment files | |||
|
19 | ||||
|
20 | ''' | |||
|
21 | dbAdminObj = madrigal.admin.MadrigalDBAdmin() | |||
|
22 | madDB = madrigal.metadata.MadrigalDB() | |||
|
23 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) | |||
|
24 | siteName, siteList = madWebObj.getSiteInfo() | |||
|
25 | ||||
|
26 | if request.method == 'POST': | |||
|
27 | form = UpdataForm(request.POST, request.FILES) | |||
|
28 | files = request.FILES.getlist('file') | |||
|
29 | ||||
|
30 | if form.is_valid(): | |||
|
31 | try: | |||
|
32 | description = form.cleaned_data['description'] | |||
|
33 | instCode = int(form.cleaned_data['instruments']) | |||
|
34 | expId = form.cleaned_data['experiments'] | |||
|
35 | perm = int(form.cleaned_data['type']) | |||
|
36 | ||||
|
37 | #saving file | |||
|
38 | for f in files: | |||
|
39 | fs = FileSystemStorage(location='/tmp') | |||
|
40 | fs.save(f.name, f) | |||
|
41 | madExp = madrigal.metadata.MadrigalExperiment() | |||
|
42 | filepath = os.path.join('/tmp', f.name) | |||
|
43 | expTitle = madExp.getExpNameByExpId(expId) | |||
|
44 | ||||
|
45 | dbAdminObj.createMadrigalExperiment(filepath,expTitle, perm, description, instCode) | |||
|
46 | ||||
|
47 | ||||
|
48 | madInstParams = madrigal.metadata.MadrigalInstrumentParameters() | |||
|
49 | madInstKindats = madrigal.metadata.MadrigalInstrumentKindats() | |||
|
50 | ||||
|
51 | print('*** Updating local metadata ***') | |||
|
52 | dbAdminObj.__updateLocalMetadata__() | |||
|
53 | print('*** Rebuilding instParmTab.txt ***') | |||
|
54 | madInstParams.rebuildInstParmTable() | |||
|
55 | print('*** Rebuilding instKindatTab.txt ***') | |||
|
56 | madInstKindats.rebuildInstKindatTable() | |||
|
57 | messages.success( | |||
|
58 | request, 'Experimento(s) creado(s) exitosamente') | |||
|
59 | form = UpdataForm() | |||
|
60 | ||||
|
61 | except Exception as e: | |||
|
62 | messages.error( | |||
|
63 | request, str(e)) | |||
|
64 | else: | |||
|
65 | form = UpdataForm() | |||
|
66 | ||||
|
67 | return render(request, 'updata/index.html', { | |||
|
68 | 'form': form, | |||
|
69 | 'site_name': siteName, | |||
|
70 | 'site_list': siteList, | |||
|
71 | }) | |||
|
72 | ||||
|
73 | ||||
|
74 | def get_experiments(request): | |||
|
75 | """get_experiments is a Ajax call that returns the experiments select html to support the | |||
|
76 | updata UI. Called when a user modifies the intruments select field. | |||
|
77 | ||||
|
78 | Inputs: | |||
|
79 | request | |||
|
80 | """ | |||
|
81 | form = ExpForm(request.GET) | |||
|
82 | ||||
|
83 | return render(request, 'updata/experiments.html', {'form': form}) |
1 | NO CONTENT: new file 100755, binary diff hidden |
|
NO CONTENT: new file 100755, binary diff hidden |
@@ -0,0 +1,50 | |||||
|
1 | <div class="row" style="margin-bottom: 20px"> | |||
|
2 | Select parameter: <br> | |||
|
3 | {{ form.param_list1d.label }} | |||
|
4 | {{ form.param_list1d }} | |||
|
5 | {% if form.param_list2d %} | |||
|
6 | {{ form.param_list2d.label }} | |||
|
7 | {{ form.param_list2d }} | |||
|
8 | {% endif %} | |||
|
9 | ||||
|
10 | </div> | |||
|
11 | ||||
|
12 | <script> | |||
|
13 | $('#id_param_list2d').bind('change', function (e) { | |||
|
14 | var expID = '{{ expID }}'; | |||
|
15 | var param = $(this).val(); | |||
|
16 | var url = '{% url 'plot' %}' + '?expID=' + expID + '¶m2d=' + param; | |||
|
17 | console.log(url) | |||
|
18 | // first delete all forms that are now out of date | |||
|
19 | divIndex = $(".single_form").index($( "#file_plot" )) | |||
|
20 | $(".single_form").slice(divIndex).empty() | |||
|
21 | // second populate the file_plot html if '0' not selected | |||
|
22 | if (param != '0') { | |||
|
23 | $(".single_form").slice(divIndex,divIndex+1).html("<img src=\"static/loader.gif\" class=\"load_center\"/>").load(url); | |||
|
24 | } | |||
|
25 | }) | |||
|
26 | $('#id_param_list1d').bind('change', function (e) { | |||
|
27 | var expID = '{{ expID }}'; | |||
|
28 | var param = $(this).val(); | |||
|
29 | var url = '{% url 'plot' %}' + '?expID=' + expID + '¶m1d=' + param; | |||
|
30 | console.log(url) | |||
|
31 | // first delete all forms that are now out of date | |||
|
32 | divIndex = $(".single_form").index($( "#file_plot" )) | |||
|
33 | $(".single_form").slice(divIndex).empty() | |||
|
34 | // second populate the file_plot html if '0' not selected | |||
|
35 | if (param != '0') { | |||
|
36 | $(".single_form").slice(divIndex,divIndex+1).html("<img src=\"static/loader.gif\" class =\"load_center\"/>").load(url); | |||
|
37 | } | |||
|
38 | }) | |||
|
39 | </script> | |||
|
40 | <style> | |||
|
41 | .load_center { | |||
|
42 | display: block; | |||
|
43 | margin-left: auto; | |||
|
44 | margin-right: auto; | |||
|
45 | margin-top: 100px; | |||
|
46 | margin-bottom: 100px; | |||
|
47 | width: 4%; | |||
|
48 | align-items: center; | |||
|
49 | } | |||
|
50 | </style> No newline at end of file |
@@ -12,13 +12,11 https://docs.djangoproject.com/en/1.7/ref/settings/ | |||||
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 |
|
||||
16 |
|
||||
17 | # Quick-start development settings - unsuitable for production |
|
15 | # Quick-start development settings - unsuitable for production | |
18 | # See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/ |
|
16 | # See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/ | |
19 |
|
17 | |||
20 | # SECURITY WARNING: keep the secret key used in production secret! |
|
18 | # SECURITY WARNING: keep the secret key used in production secret! | |
21 | SECRET_KEY = '!wa!749ow0!%7t7tr6fr^fvkqyd7yc#mmvpfedr+f2pb!4r)wd' |
|
19 | SECRET_KEY = '^c1l3d35+q28^66d2pc1qlu(k$wmw^*gg3rfitz^s)t=9eu1ui' | |
22 |
|
20 | |||
23 | # SECURITY WARNING: don't run with debug turned on in production! |
|
21 | # SECURITY WARNING: don't run with debug turned on in production! | |
24 | DEBUG = True |
|
22 | DEBUG = True | |
@@ -38,7 +36,7 MANAGERS = (('Bill Rideout', 'brideout@haystack.mit.edu'),) | |||||
38 | # Application definition |
|
36 | # Application definition | |
39 |
|
37 | |||
40 | INSTALLED_APPS = ( |
|
38 | INSTALLED_APPS = ( | |
41 |
|
|
39 | 'django.contrib.admin', | |
42 | 'django.contrib.auth', |
|
40 | 'django.contrib.auth', | |
43 | 'django.contrib.contenttypes', |
|
41 | 'django.contrib.contenttypes', | |
44 | 'django.contrib.sessions', |
|
42 | 'django.contrib.sessions', | |
@@ -46,18 +44,20 INSTALLED_APPS = ( | |||||
46 | 'django.contrib.staticfiles', |
|
44 | 'django.contrib.staticfiles', | |
47 | 'madweb', |
|
45 | 'madweb', | |
48 | 'django_bootstrap_calendar', |
|
46 | 'django_bootstrap_calendar', | |
49 | 'bootstrap3' |
|
47 | 'bootstrap3', | |
|
48 | 'apps.login', | |||
|
49 | 'apps.updata', | |||
50 | ) |
|
50 | ) | |
51 |
|
51 | |||
52 |
MIDDLEWARE |
|
52 | MIDDLEWARE = [ | |
53 |
'django. |
|
53 | 'django.middleware.security.SecurityMiddleware', | |
54 | 'django.contrib.messages.middleware.MessageMiddleware', |
|
|||
55 | 'django.contrib.sessions.middleware.SessionMiddleware', |
|
54 | 'django.contrib.sessions.middleware.SessionMiddleware', | |
56 | 'django.middleware.common.CommonMiddleware', |
|
55 | 'django.middleware.common.CommonMiddleware', | |
57 | 'django.middleware.csrf.CsrfViewMiddleware', |
|
56 | 'django.middleware.csrf.CsrfViewMiddleware', | |
58 |
'django.contrib.auth.middleware. |
|
57 | 'django.contrib.auth.middleware.AuthenticationMiddleware', | |
|
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 | |||
@@ -80,6 +80,7 TEMPLATES = [ | |||||
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 | ], |
|
84 | ], | |
84 | }, |
|
85 | }, | |
85 | }, |
|
86 | }, | |
@@ -90,8 +91,13 TEMPLATES = [ | |||||
90 | # https://docs.djangoproject.com/en/1.7/ref/settings/#databases |
|
91 | # https://docs.djangoproject.com/en/1.7/ref/settings/#databases | |
91 |
|
92 | |||
92 | DATABASES = { |
|
93 | DATABASES = { | |
|
94 | 'default': { | |||
|
95 | 'ENGINE': 'django.db.backends.sqlite3', | |||
|
96 | 'NAME': 'madrigal.sqlite', | |||
|
97 | } | |||
93 | } |
|
98 | } | |
94 |
|
99 | |||
|
100 | ||||
95 | # Internationalization |
|
101 | # Internationalization | |
96 | # https://docs.djangoproject.com/en/1.7/topics/i18n/ |
|
102 | # https://docs.djangoproject.com/en/1.7/topics/i18n/ | |
97 |
|
103 |
@@ -5,4 +5,7 import madweb.views | |||||
5 | urlpatterns = [ |
|
5 | urlpatterns = [ | |
6 | url(r'^', include('madweb.urls')), |
|
6 | url(r'^', 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")), | |||
|
9 | url(r'^accounts/', include('apps.login.urls', namespace="login")), | |||
|
10 | url(r'^admin/', admin.site.urls), | |||
8 | ] |
|
11 | ] |
@@ -12,7 +12,7 import madrigal.metadata | |||||
12 |
|
12 | |||
13 | madDB = madrigal.metadata.MadrigalDB() |
|
13 | madDB = madrigal.metadata.MadrigalDB() | |
14 | os.environ['PYTHON_EGG_CACHE'] = os.path.join(madDB.getMadroot(), 'eggs') |
|
14 | os.environ['PYTHON_EGG_CACHE'] = os.path.join(madDB.getMadroot(), 'eggs') | |
15 |
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djangoMad.settings |
|
15 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djangoMad.settings") | |
16 |
|
16 | |||
17 | from django.core.wsgi import get_wsgi_application |
|
17 | from django.core.wsgi import get_wsgi_application | |
18 | application = get_wsgi_application() |
|
18 | application = get_wsgi_application() |
@@ -16,6 +16,7 import django.template.defaulttags | |||||
16 |
|
16 | |||
17 | # third party imports |
|
17 | # third party imports | |
18 | import numpy |
|
18 | import numpy | |
|
19 | import h5py | |||
19 |
|
20 | |||
20 | # Madrigal imports |
|
21 | # Madrigal imports | |
21 | import madrigal.metadata |
|
22 | import madrigal.metadata | |
@@ -637,6 +638,139 class SingleExpPlotsForm(django.forms.Form): | |||||
637 | choices=plotList, |
|
638 | choices=plotList, | |
638 | required=False) |
|
639 | required=False) | |
639 |
|
|
640 | ||
|
641 | '''get_params2 retrieves a list of 1d and 2d parameters of type 1 hdf5 files''' | |||
|
642 | def get_params1(args, kwargs, madExpObj, madWebObj): | |||
|
643 | ||||
|
644 | expID = getSelection('experiment_list', args, kwargs) | |||
|
645 | expDir = madExpObj.getExpDirByExpId(expID) | |||
|
646 | fileList = madWebObj.getFileFromExpID(expID, False) | |||
|
647 | ||||
|
648 | firsttuple = [a_tuple[0] for a_tuple in fileList] | |||
|
649 | basename = firsttuple[0] | |||
|
650 | fullFilename = os.path.join(expDir, basename) | |||
|
651 | f = h5py.File(fullFilename, "r") | |||
|
652 | data = f[list(f.keys())[0]] | |||
|
653 | array = data[list(data.keys())[0]] | |||
|
654 | ||||
|
655 | param1d = array[list(array.keys())[0]] | |||
|
656 | param2d = array[list(array.keys())[1]] | |||
|
657 | paramch1d = list(param1d.keys()) | |||
|
658 | paramch2d = list(param2d.keys()) | |||
|
659 | ||||
|
660 | dataparameters = param1d[list(param1d.keys())[0]] | |||
|
661 | paramch_mn_bin = list(dataparameters['mnemonic']) | |||
|
662 | paramch_bin = list(dataparameters['description']) | |||
|
663 | paramch_mn = list() | |||
|
664 | paramch = list() | |||
|
665 | ||||
|
666 | for i in range(len(paramch_bin)): | |||
|
667 | paramch_mn.append(paramch_mn_bin[i].decode("utf-8")) | |||
|
668 | paramch.append(paramch_bin[i].decode("utf-8")) | |||
|
669 | ||||
|
670 | choices1d = ['Select parameter'] | |||
|
671 | for ch in paramch1d[1:]: | |||
|
672 | aux = paramch[paramch_mn.index(ch.upper())] | |||
|
673 | choices1d.append(aux) | |||
|
674 | ||||
|
675 | ||||
|
676 | dataparameters = param2d[list(param2d.keys())[0]] | |||
|
677 | paramch_mn_bin = list(dataparameters['mnemonic']) | |||
|
678 | paramch_mn = list() | |||
|
679 | paramch_bin = list(dataparameters['description']) | |||
|
680 | paramch = list() | |||
|
681 | ||||
|
682 | for i in range(len(paramch_bin)): | |||
|
683 | paramch_mn.append(paramch_mn_bin[i].decode("utf-8")) | |||
|
684 | paramch.append(paramch_bin[i].decode("utf-8")) | |||
|
685 | ||||
|
686 | choices2d = ['Select parameter'] | |||
|
687 | for ch in paramch2d[1:]: | |||
|
688 | aux = paramch[paramch_mn.index(ch.upper())] | |||
|
689 | choices2d.append(aux) | |||
|
690 | ||||
|
691 | ||||
|
692 | choices = [choices1d,choices2d] | |||
|
693 | return choices | |||
|
694 | ||||
|
695 | ||||
|
696 | '''get params2 retrieves a list of 1d parameters of type 2 of hdf5 files''' | |||
|
697 | def get_params2(args, kwargs, madExpObj, madWebObj): | |||
|
698 | ||||
|
699 | expID = getSelection('experiment_list', args, kwargs) | |||
|
700 | expDir = madExpObj.getExpDirByExpId(expID) | |||
|
701 | fileList = madWebObj.getFileFromExpID(expID, False) | |||
|
702 | ||||
|
703 | firsttuple = [a_tuple[0] for a_tuple in fileList] | |||
|
704 | basename = firsttuple[0] | |||
|
705 | fullFilename = os.path.join(expDir, basename) | |||
|
706 | f = h5py.File(fullFilename, "r") | |||
|
707 | ||||
|
708 | metadata = f[list(f.keys())[1]] | |||
|
709 | table = metadata[list(metadata.keys())[0]] | |||
|
710 | param_mn_bin = list(table['mnemonic']) | |||
|
711 | param_mn = list() | |||
|
712 | for p in param_mn_bin: | |||
|
713 | param_mn.append(p.decode("utf")) | |||
|
714 | ||||
|
715 | index = param_mn.index('UT2_UNIX') | |||
|
716 | params = list(table['description']) | |||
|
717 | choices = ['Select parameter'] | |||
|
718 | for p in params[index+1:]: | |||
|
719 | choices.append(p.decode("utf-8")) | |||
|
720 | ||||
|
721 | return choices | |||
|
722 | ||||
|
723 | ||||
|
724 | class SingleExpPlotsSelectionForm(django.forms.Form): | |||
|
725 | """SingleExpPlotsSselectionForm is a Form class for the parameters selection for plotting in the Single Experiment interface. | |||
|
726 | Use this because its faster to create than the full SingleExpDefaultForm | |||
|
727 | """ | |||
|
728 | ||||
|
729 | def __init__(self, *args, **kwargs): | |||
|
730 | super(SingleExpPlotsSelectionForm, self).__init__(*args, **kwargs) | |||
|
731 | madDB = madrigal.metadata.MadrigalDB() | |||
|
732 | madExpObj = madrigal.metadata.MadrigalExperiment(madDB) | |||
|
733 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) | |||
|
734 | expID = getSelection('experiment_list', args, kwargs) | |||
|
735 | try: | |||
|
736 | expID = int(expID) | |||
|
737 | except ValueError: | |||
|
738 | # convert expPath to expID | |||
|
739 | expID = madWebObj.getExpIDFromExpPath(expID, True) | |||
|
740 | expDir = madExpObj.getExpDirByExpId(expID) | |||
|
741 | fileList = madWebObj.getFileFromExpID(expID, False) | |||
|
742 | ||||
|
743 | firsttuple = [a_tuple[0] for a_tuple in fileList] | |||
|
744 | basename = firsttuple[0] | |||
|
745 | fullFilename = os.path.join(expDir, basename) | |||
|
746 | f = h5py.File(fullFilename, "r") | |||
|
747 | data = f[list(f.keys())[0]] | |||
|
748 | ||||
|
749 | if 'Array Layout' in list(data.keys()): | |||
|
750 | choices = get_params1(args, kwargs, madExpObj, madWebObj) | |||
|
751 | params1d = choices[0] | |||
|
752 | params2d = choices[1] | |||
|
753 | ||||
|
754 | index = list(range(len(params1d))) | |||
|
755 | paramchoices1d = list(zip(index, params1d)) | |||
|
756 | ||||
|
757 | ||||
|
758 | index = list(range(len(params2d))) | |||
|
759 | paramchoices2d = list(zip(index, params2d)) | |||
|
760 | ||||
|
761 | ||||
|
762 | self.fields['param_list2d'] = django.forms.ChoiceField(widget = django.forms.Select(), choices=paramchoices2d, label="2D Parameters", required=False) | |||
|
763 | ||||
|
764 | else: | |||
|
765 | params1d = get_params2(args, kwargs, madExpObj, madWebObj) | |||
|
766 | #if params1d[0] == 'ut2_unix': | |||
|
767 | # params1d[0] = 'Select parameter' | |||
|
768 | index = list(range(len(params1d))) | |||
|
769 | paramchoices1d = list(zip(index, params1d)) | |||
|
770 | ||||
|
771 | self.fields['param_list1d'] = django.forms.ChoiceField(widget = django.forms.Select(), choices=paramchoices1d, label="1D Parameters", required=False) | |||
|
772 | ||||
|
773 | ||||
640 |
|
774 | |||
641 | class SingleExpDownloadAsIsForm(django.forms.Form): |
|
775 | class SingleExpDownloadAsIsForm(django.forms.Form): | |
642 | """SingleExpDownloadAsIsForm is a Form class for the download as is field in the Single Experiment interface. |
|
776 | """SingleExpDownloadAsIsForm is a Form class for the download as is field in the Single Experiment interface. |
@@ -56,4 +56,12 | |||||
56 | {% include "madweb/show_plots.html" %} |
|
56 | {% include "madweb/show_plots.html" %} | |
57 | {% endif %} |
|
57 | {% endif %} | |
58 | </div> <!-- end subdivide --> |
|
58 | </div> <!-- end subdivide --> | |
59 | {% endblock %} No newline at end of file |
|
59 | ||
|
60 | <!-- file select div --> | |||
|
61 | <div class="col-md-12 single_form" id="file_plot"> | |||
|
62 | {% if form.show_plots %} | |||
|
63 | {% include "madweb/parameter_selection.html" %} | |||
|
64 | {% endif %} | |||
|
65 | </div> <!-- end subdivide --> | |||
|
66 | ||||
|
67 | {% endblock %} No newline at end of file |
@@ -257,3 +257,12 | |||||
257 | </div> <!-- end subdivide --> |
|
257 | </div> <!-- end subdivide --> | |
258 | {% endblock %} |
|
258 | {% endblock %} | |
259 |
|
259 | |||
|
260 | {% block file_plot %} | |||
|
261 | <!-- file select div --> | |||
|
262 | <div class="col-md-12 single_form" id="file_plot"> | |||
|
263 | {% if form.show_plots %} | |||
|
264 | {% include "madweb/parameter_selection.html" %} | |||
|
265 | {% endif %} | |||
|
266 | </div> <!-- end subdivide --> | |||
|
267 | {% endblock %} | |||
|
268 |
@@ -51,6 +51,9 urlpatterns = [ url(r'^$', | |||||
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/?$', | |||
|
55 | views.view_plot, | |||
|
56 | name='plot'), | |||
54 | url(r'^downloadAsIs/?$', |
|
57 | url(r'^downloadAsIs/?$', | |
55 | views.download_as_is, |
|
58 | views.download_as_is, | |
56 | name='download_as_is'), |
|
59 | name='download_as_is'), |
@@ -38,6 +38,9 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 | |||
|
42 | import plotly.graph_objs as go | |||
|
43 | import h5py | |||
41 |
|
44 | |||
42 |
|
45 | |||
43 | # madrigal imports |
|
46 | # madrigal imports | |
@@ -336,16 +339,217 def show_plots(request): | |||||
336 | Inputs: |
|
339 | Inputs: | |
337 | request |
|
340 | request | |
338 | """ |
|
341 | """ | |
|
342 | madDB = madrigal.metadata.MadrigalDB() | |||
|
343 | madExpObj = madrigal.metadata.MadrigalExperiment(madDB) | |||
|
344 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) | |||
|
345 | ||||
339 | try: |
|
346 | try: | |
340 | expID = int(request.GET['experiment_list']) |
|
347 | expID = int(request.GET['experiment_list']) | |
341 | except ValueError: |
|
348 | except ValueError: | |
342 | # convert expPath to expID |
|
349 | # convert expPath to expID | |
343 | madDB = madrigal.metadata.MadrigalDB() |
|
|||
344 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) |
|
|||
345 | expID = madWebObj.getExpIDFromExpPath(request.GET['experiment_list'], True) |
|
350 | expID = madWebObj.getExpIDFromExpPath(request.GET['experiment_list'], True) | |
346 | form = madweb.forms.SingleExpPlotsForm(request.GET) |
|
351 | plotList = madExpObj.getExpLinksByExpId(expID) | |
|
352 | if len(plotList) != 0: | |||
|
353 | form = madweb.forms.SingleExpPlotsForm(request.GET) | |||
|
354 | template = 'madweb/show_plots.html' | |||
|
355 | context = {'form': form} | |||
|
356 | else: | |||
|
357 | template = 'madweb/parameter_selection.html' | |||
|
358 | form = madweb.forms.SingleExpPlotsSelectionForm(request.GET) | |||
|
359 | context = {'form': form, 'expID': expID} | |||
|
360 | ||||
|
361 | return render(request, template, context) | |||
|
362 | ||||
|
363 | ||||
|
364 | def view_plot(request): | |||
|
365 | ||||
|
366 | param1d = int(request.GET.get('param1d','0')) | |||
|
367 | param2d = int(request.GET.get('param2d','0')) | |||
|
368 | ||||
|
369 | madDB = madrigal.metadata.MadrigalDB() | |||
|
370 | madWebObj = madrigal.ui.web.MadrigalWeb(madDB) | |||
|
371 | madExpObj = madrigal.metadata.MadrigalExperiment(madDB) | |||
|
372 | ||||
|
373 | expID =int(request.GET['expID']) | |||
|
374 | expDir = madExpObj.getExpDirByExpId(expID) | |||
|
375 | if expDir is None: | |||
|
376 | raise ValueError('No expDir found for exp_id %i' % (int(expID))) | |||
347 |
|
377 | |||
348 | return render(request, 'madweb/show_plots.html', {'form': form}) |
|
378 | fileList = madWebObj.getFileFromExpID(expID, False) | |
|
379 | firsttuple = [a_tuple[0] for a_tuple in fileList] | |||
|
380 | basename = firsttuple[0] | |||
|
381 | fullFilename = os.path.join(expDir, basename) | |||
|
382 | ||||
|
383 | with h5py.File(fullFilename, "r") as f: | |||
|
384 | ||||
|
385 | # Get the data | |||
|
386 | ||||
|
387 | data = f[list(f.keys())[0]] | |||
|
388 | ||||
|
389 | if 'Array Layout' in list(data.keys()): | |||
|
390 | array = data[list(data.keys())[0]] | |||
|
391 | timestamps = array[list(array.keys())[4]] | |||
|
392 | datatime = [datetime.datetime.fromtimestamp(t) for t in list(timestamps)] | |||
|
393 | ||||
|
394 | range = array[list(array.keys())[3]] | |||
|
395 | datarange = list(range) | |||
|
396 | ||||
|
397 | ||||
|
398 | if param1d==0: | |||
|
399 | parameters_2d = array[list(array.keys())[1]] | |||
|
400 | paramname = list(parameters_2d.keys())[param2d] | |||
|
401 | param = parameters_2d[list(parameters_2d.keys())[param2d]] | |||
|
402 | dataparam = list(param) | |||
|
403 | plot = plot_heatmap(datatime,datarange,dataparam,paramname) | |||
|
404 | ||||
|
405 | else: | |||
|
406 | parameters_1d = array[list(array.keys())[0]] | |||
|
407 | paramname = list(parameters_1d.keys())[param1d] | |||
|
408 | param = parameters_1d[list(parameters_1d.keys())[param1d]] | |||
|
409 | dataparam = list(param) | |||
|
410 | plot = plot_scatter(datatime,dataparam,paramname) | |||
|
411 | ||||
|
412 | else: | |||
|
413 | table = data[list(data.keys())[0]] | |||
|
414 | a = list(table.dtype.fields.keys()) | |||
|
415 | index = a.index('ut2_unix') | |||
|
416 | v = a[index:] | |||
|
417 | paramname = v[param1d] | |||
|
418 | dataparam = list(table[paramname]) | |||
|
419 | datatime = [datetime.datetime.fromtimestamp(t) for t in list(table['ut2_unix'])] | |||
|
420 | plot = plot_scatter(datatime,dataparam,paramname) | |||
|
421 | ||||
|
422 | return HttpResponse(plot) | |||
|
423 | ||||
|
424 | def plot_scatter(datatime,dataparam,paramname): | |||
|
425 | if (numpy.isnan(dataparam).all()): | |||
|
426 | plot = "There is no valid data available for this plot" | |||
|
427 | ||||
|
428 | else: | |||
|
429 | fig = go.Figure() | |||
|
430 | fig.add_trace(go.Scatter(x=datatime, y=dataparam)) | |||
|
431 | fig.update_yaxes(title_text=paramname) | |||
|
432 | ||||
|
433 | delta = datatime[-1] - datatime[1] | |||
|
434 | ||||
|
435 | if (delta>datetime.timedelta(days=30)): | |||
|
436 | # Add range slider | |||
|
437 | fig.update_layout( | |||
|
438 | xaxis=dict( | |||
|
439 | rangeselector=dict( | |||
|
440 | buttons=list([ | |||
|
441 | dict(count=1, | |||
|
442 | label="1m", | |||
|
443 | step="month", | |||
|
444 | stepmode="backward"), | |||
|
445 | dict(count=6, | |||
|
446 | label="6m", | |||
|
447 | step="month", | |||
|
448 | stepmode="backward"), | |||
|
449 | dict(count=1, | |||
|
450 | label="1y", | |||
|
451 | step="year", | |||
|
452 | stepmode="backward"), | |||
|
453 | dict(step="all") | |||
|
454 | ]) | |||
|
455 | ), | |||
|
456 | rangeslider=dict( | |||
|
457 | visible=True | |||
|
458 | ), | |||
|
459 | type="date" | |||
|
460 | ) | |||
|
461 | ) | |||
|
462 | ||||
|
463 | ||||
|
464 | plot = py.plot(fig, include_plotlyjs=False, output_type='div') | |||
|
465 | ||||
|
466 | ||||
|
467 | return plot | |||
|
468 | ||||
|
469 | ||||
|
470 | def plot_heatmap(datatime,datarange,dataparam,paramname): | |||
|
471 | if (numpy.isnan(dataparam).all()): | |||
|
472 | plot = "There is no valid data available for this plot" | |||
|
473 | else: | |||
|
474 | fig = go.Figure() | |||
|
475 | fig.add_trace(go.Heatmap(x=datatime,y=datarange,z= dataparam,colorscale='Jet',colorbar={"title":paramname})) | |||
|
476 | fig.update_yaxes(title_text="range") | |||
|
477 | fig.update_layout( | |||
|
478 | updatemenus=[ | |||
|
479 | dict( | |||
|
480 | buttons=list([ | |||
|
481 | dict( | |||
|
482 | args=["colorscale", "Jet"], | |||
|
483 | label="Jet", | |||
|
484 | method="restyle" | |||
|
485 | ), | |||
|
486 | dict( | |||
|
487 | args=["colorscale", "RdBu"], | |||
|
488 | label="Red-Blue", | |||
|
489 | method="restyle" | |||
|
490 | ), | |||
|
491 | dict( | |||
|
492 | args=["colorscale", "Viridis"], | |||
|
493 | label="Viridis", | |||
|
494 | method="restyle" | |||
|
495 | ), | |||
|
496 | dict( | |||
|
497 | args=["colorscale", "Cividis"], | |||
|
498 | label="Cividis", | |||
|
499 | method="restyle" | |||
|
500 | ), | |||
|
501 | dict( | |||
|
502 | args=["colorscale", "Greens"], | |||
|
503 | label="Greens", | |||
|
504 | method="restyle" | |||
|
505 | ), | |||
|
506 | ]), | |||
|
507 | type = "dropdown", | |||
|
508 | direction="down", | |||
|
509 | pad={"r": 10, "t": 10}, | |||
|
510 | showactive=True, | |||
|
511 | x=0.1, | |||
|
512 | xanchor="left", | |||
|
513 | y=1.05, | |||
|
514 | yanchor="top" | |||
|
515 | ), | |||
|
516 | dict( | |||
|
517 | buttons=list([ | |||
|
518 | dict( | |||
|
519 | args=[{"contours.showlines": False, "type": "contour"}], | |||
|
520 | label="Hide lines", | |||
|
521 | method="restyle" | |||
|
522 | ), | |||
|
523 | dict( | |||
|
524 | args=[{"contours.showlines": True, "type": "contour"}], | |||
|
525 | label="Show lines", | |||
|
526 | method="restyle" | |||
|
527 | ), | |||
|
528 | ]), | |||
|
529 | direction="down", | |||
|
530 | pad={"r": 10, "t": 10}, | |||
|
531 | showactive=True, | |||
|
532 | x=0.32, | |||
|
533 | xanchor="left", | |||
|
534 | y=1.05, | |||
|
535 | yanchor="top" | |||
|
536 | ), | |||
|
537 | ] | |||
|
538 | ) | |||
|
539 | ||||
|
540 | fig.update_layout( | |||
|
541 | annotations=[ | |||
|
542 | dict(text="Colorscale", showarrow=False, | |||
|
543 | x=0, xref="paper", y=1.03, yref="paper", align="left"), | |||
|
544 | dict(text="Lines", x=0.25, xref="paper", y=1.03, yref="paper", | |||
|
545 | showarrow=False) | |||
|
546 | ] | |||
|
547 | ) | |||
|
548 | ||||
|
549 | ||||
|
550 | plot = py.plot(fig, include_plotlyjs=False, output_type='div') | |||
|
551 | ||||
|
552 | return plot | |||
349 |
|
553 | |||
350 |
|
554 | |||
351 | def download_as_is(request): |
|
555 | def download_as_is(request): |
@@ -22,6 +22,7 | |||||
22 | <meta charset="UTF-8"> |
|
22 | <meta charset="UTF-8"> | |
23 | <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
23 | <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
24 | <link rel="shortcut icon" type="image/png" href="/static/favicon.ico"/> |
|
24 | <link rel="shortcut icon" type="image/png" href="/static/favicon.ico"/> | |
|
25 | <script src="https://cdn.plot.ly/plotly-latest.min.js"></script> | |||
25 | <title>{% block title %}Madrigal Database{% endblock %}</title> |
|
26 | <title>{% block title %}Madrigal Database{% endblock %}</title> | |
26 | <style type="text/css"> |
|
27 | <style type="text/css"> | |
27 | html body { |
|
28 | html body { | |
@@ -74,6 +75,7 | |||||
74 | {% block file_select %}{% endblock %} |
|
75 | {% block file_select %}{% endblock %} | |
75 | {% block file_buttons %}{% endblock %} |
|
76 | {% block file_buttons %}{% endblock %} | |
76 | {% block file_data %}{% endblock %} |
|
77 | {% block file_data %}{% endblock %} | |
|
78 | {% block file_plot %}{% endblock %} | |||
77 | </div> |
|
79 | </div> | |
78 |
|
80 | |||
79 | </div> |
|
81 | </div> |
@@ -124,7 +124,8 | |||||
124 | {% endfor %} |
|
124 | {% endfor %} | |
125 | </ul> |
|
125 | </ul> | |
126 | </li> |
|
126 | </li> | |
127 |
<li><a href="http://cedar.openmadrigal.org/openmadrigal" data-toggle="tooltip" data-original-title="Click here to go to OpenMadrigal, where you can download API's in python, Matlab, and IDL to run Madrigal scripts, and access Madrigal's source code." data-placement="bottom">OpenMadrigal</a></li> |
|
127 | <li><a href="http://cedar.openmadrigal.org/openmadrigal" data-toggle="tooltip" data-original-title="Click here to go to OpenMadrigal, where you can download API's in python, Matlab, and IDL to run Madrigal scripts, and access Madrigal's source code." data-placement="bottom">OpenMadrigal</a></li> | |
|
128 | <li><a href="{% url 'updata:updata_index' %}" data-toggle="tooltip" data-original-title="Click here to upload data to Madrigal database." data-placement="bottom">Upload Madrigal Data</a></li> | |||
128 | </ul> |
|
129 | </ul> | |
129 | </div> |
|
130 | </div> | |
130 | </nav> No newline at end of file |
|
131 | </nav> |
General Comments 0
You need to be logged in to leave comments.
Login now