##// END OF EJS Templates
sync repo...
Juan C. Espinoza -
r157:82791b88ae92
parent child
Show More
@@ -0,0 +1,1
1 {% extends "dev_conf_edit.html" %}
@@ -0,0 +1,145
1 {% extends "base.html" %}
2 {% load bootstrap3 %}
3 {% load static %}
4 {% load main_tags %}
5 {% block extra-head %}
6 <link href="{% static 'css/bootstrap-datetimepicker.min.css' %}" media="screen" rel="stylesheet">
7 {% endblock %}
8
9 {% block exp-active %}active{% endblock %}
10
11 {% block content-title %}{{title}}{% endblock %}
12 {% block content-suptitle %}{{suptitle}}{% endblock %}
13
14 {% block content %}
15
16 {% block menu-actions %}
17
18 {% endblock %}
19
20
21
22 <table class="table table-bordered" style="text-align:center;">
23 <!--<h4 class="panel-title"> </h4>-->
24 <tr>
25 <th style="text-align:center;">Parameters</th>
26 <th style="text-align:center;">DDS</th>
27 <th style="text-align:center;">RC</th>
28 <th style="text-align:center;">JARS</th>
29 <th style="text-align:center;">=P</th>
30 </tr>
31
32 <tr>
33 <th>Clock In</th>
34 <td id="dds_clock">{{ dds.clock }}</td>
35 <td id="rc_clock">{{ rc.clock_in }}</td>
36 <td id="filter_clock">{{ filter_parms.clock }}</td>
37 <td><input id="suggest_clock"></input></td>
38 </tr>
39
40 <tr>
41 <th>Frequency A (Mhz)</th>
42 <td>{{ dds.frequencyA_Mhz }}</td>
43 <td>x</td>
44 <td>{{ filter_parms.fch }}</td>
45 <td><input></input></td>
46 </tr>
47
48 <tr>
49 <th>Frequency A (Decimal)</th>
50 <td>{{ dds.frequencyA }}</td>
51 <td>x</td>
52 <td>{{ filter_parms.fch_decimal }}</td>
53 <td><input></input></td>
54 </tr>
55
56 <tr>
57 <th>Sampling Frequency (MHz)</th>
58 <td id="dds_sampfreq">{{ dds.frequencyA }}</td>
59 <td id="rc_sampfreq">{{ samp_freq_rc }}</td>
60 <td id="jars_sampfreq">{{ samp_freq_jars }}</td>
61 <td><input id="suggest_sampfreq"></input></td>
62 </tr>
63 </table>
64
65
66
67 <div class="">
68 <h4 class="panel-title"><b> Extra Parameters </b></h4>
69 <br>
70 </div>
71
72 <table class="table table-bordered" >
73 {% for configuration in configurations %}
74 {% if configuration.device.device_type.name == 'jars' %}
75 <tr><th>Rate(MB/h)</th><td>{{ rate }}</td></tr>
76 {% endif %}
77 {% endfor %}
78 </table>
79
80
81 <div class="pull-right">
82 <button type="button" class="btn btn-primary" id="bt_back">Back</button>
83 <button type="button" class="btn btn-primary" id="bt_update">{{ button }}</button>
84 </div>
85
86 {% endblock %}
87
88 {% block sidebar%}
89 {% include "sidebar_devices.html" %}
90 {% endblock %}
91
92 {% block extra-js%}
93 <script type="text/javascript">
94
95 {% if dds_conf %}
96 $(document).ready(function() {
97 $('#dds_clock').click(function(event) {
98 clock = $("#dds_clock").text();
99 $("#suggest_clock").val(clock);
100 });
101 $('#dds_sampfreq').click(function(event) {
102 sampfreq = $("#dds_sampfreq").text();
103 $("#suggest_sampfreq").val(sampfreq);
104 });
105 });
106 {% endif %}
107 {% if rc_conf %}
108 $(document).ready(function() {
109 $('#rc_clock').click(function(event) {
110 clock = $("#rc_clock").text();
111 $("#suggest_clock").val(clock);
112 });
113 $('#rc_sampfreq').click(function(event) {
114 sampfreq = $("#rc_sampfreq").text();
115 $("#suggest_sampfreq").val(sampfreq);
116 });
117 });
118 {% endif %}
119 {% if jars_conf %}
120 $(document).ready(function() {
121 $('#filter_clock').click(function(event) {
122 clock = $("#filter_clock").text();
123 $("#suggest_clock").val(clock);
124 });
125 $('#jars_sampfreq').click(function(event) {
126 sampfreq = $("#jars_sampfreq").text();
127 $("#suggest_sampfreq").val(sampfreq);
128 });
129 });
130 {% endif %}
131
132
133
134
135 $(".clickable-row").click(function() {
136 document.location = $(this).data("href");
137 });
138
139 $("#bt_back").click(function() {
140 document.location = "{% url 'url_experiment' experiment.id%}";
141 });
142
143
144 </script>
145 {% endblock %} No newline at end of file
@@ -1,45 +1,83
1 import os
2
1 3 from django import forms
2 4 from apps.main.models import Device, Experiment
3 5 from .models import JARSConfiguration, JARSfilter
4 6 from .widgets import SpectralWidget
5 7
6 8 class JARSConfigurationForm(forms.ModelForm):
7 9 def __init__(self, *args, **kwargs):
8 10 super(JARSConfigurationForm, self).__init__(*args, **kwargs)
9 11 instance = getattr(self, 'instance', None)
10 12
11 13 if instance and instance.pk:
12 14 devices = Device.objects.filter(device_type__name='jars')
13 15
14 16 if instance.experiment:
15 17 experiments = Experiment.objects.filter(pk=instance.experiment.id)
16 18 self.fields['experiment'].widget.choices = [(experiment.id, experiment) for experiment in experiments]
17 19
18 20 self.fields['device'].widget.choices = [(device.id, device) for device in devices]
19 21 #self.fields['spectral'].widget = SpectralWidget()
20 22 self.fields['spectral_number'].widget.attrs['readonly'] = True
21 23 self.fields['spectral'].widget = SpectralWidget()
22 24
23 25 #-------------JARS Configuration needs an Experiment-----------------
24 26 def clean(self):
25 27 cleaned_data = super(JARSConfigurationForm, self).clean()
26 28 experiment = cleaned_data.get('experiment')
27 29 if experiment == None:
28 30 msg = "Error: Jars Configuration needs an Experiment"
29 31 self.add_error('experiment', msg)
30 32
31 33 class Meta:
32 34 model = JARSConfiguration
33 35 exclude = ('type', 'parameters', 'status', 'filter_parms')
34 36
35 37
36 38 class JARSfilterForm(forms.ModelForm):
37 39 def __init__(self, *args, **kwargs):
38 40 super(JARSfilterForm, self).__init__(*args, **kwargs)
39 41 instance = getattr(self, 'instance', None)
40 42
41 43 self.fields['fch_decimal'].widget.attrs['readonly'] = True
42 44
43 45 class Meta:
44 46 model = JARSfilter
45 exclude = ('type', 'parameters', 'status') No newline at end of file
47 exclude = ('type', 'parameters', 'status')
48
49 class ExtFileField(forms.FileField):
50 """
51 Same as forms.FileField, but you can specify a file extension whitelist.
52
53 >>> from django.core.files.uploadedfile import SimpleUploadedFile
54 >>>
55 >>> t = ExtFileField(ext_whitelist=(".pdf", ".txt"))
56 >>>
57 >>> t.clean(SimpleUploadedFile('filename.pdf', 'Some File Content'))
58 >>> t.clean(SimpleUploadedFile('filename.txt', 'Some File Content'))
59 >>>
60 >>> t.clean(SimpleUploadedFile('filename.exe', 'Some File Content'))
61 Traceback (most recent call last):
62 ...
63 ValidationError: [u'Not allowed filetype!']
64 """
65 def __init__(self, *args, **kwargs):
66 extensions = kwargs.pop("extensions")
67 self.extensions = [i.lower() for i in extensions]
68
69 super(ExtFileField, self).__init__(*args, **kwargs)
70
71 def clean(self, *args, **kwargs):
72 data = super(ExtFileField, self).clean(*args, **kwargs)
73 filename = data.name
74 ext = os.path.splitext(filename)[1]
75 ext = ext.lower()
76 if ext not in self.extensions:
77 raise forms.ValidationError('Not allowed file type: %s' % ext)
78
79
80 class JARSImportForm(forms.Form):
81
82 #file_name = ExtFileField(extensions=['.racp', '.json', '.dat'])
83 file_name = ExtFileField(extensions=['.json']) No newline at end of file
@@ -1,177 +1,268
1 1 from django.db import models
2 2 from apps.main.models import Configuration
3 3 from django.core.validators import MinValueValidator, MaxValueValidator
4 from django.core.urlresolvers import reverse
5 from devices.jars import api
4 6
5 7 from apps.rc.models import RCConfiguration
8
9 import json
6 10 # Create your models here.
7 11
8 12 EXPERIMENT_TYPE = (
9 13 (0, 'RAW_DATA'),
10 14 (1, 'PDATA'),
11 15 )
12 16
13 17 DATA_TYPE = (
14 18 (0, 'SHORT'),
15 19 (1, 'FLOAT'),
16 20 )
17 21
18 22 class JARSfilter(models.Model):
19 23
20 24 JARS_NBITS = 32
21 25
22 26 name = models.CharField(max_length=60, unique=True, default='')
23 27 clock = models.FloatField(verbose_name='Clock In (MHz)',validators=[MinValueValidator(5), MaxValueValidator(75)], null=True, default=60)
24 28 mult = models.PositiveIntegerField(verbose_name='Multiplier',validators=[MinValueValidator(1), MaxValueValidator(20)], default=5)
25 29 fch = models.DecimalField(verbose_name='Frequency (MHz)', validators=[MinValueValidator(0), MaxValueValidator(150)], max_digits=19, decimal_places=16, null=True, default=49.9200)
26 30 fch_decimal = models.BigIntegerField(verbose_name='Frequency (Decimal)',validators=[MinValueValidator(0), MaxValueValidator(2**JARS_NBITS-1)], null=True, default=721554505)
27 31 filter_fir = models.PositiveIntegerField(verbose_name='FIR Filter',validators=[MinValueValidator(1), MaxValueValidator(20)], default = 6)
28 32 filter_2 = models.PositiveIntegerField(verbose_name='Filter 2',validators=[MinValueValidator(1), MaxValueValidator(20)], default = 10)
29 33 filter_5 = models.PositiveIntegerField(verbose_name='Filter 5',validators=[MinValueValidator(1), MaxValueValidator(20)], default = 1)
30 34 speed = models.PositiveIntegerField(verbose_name='Speed',validators=[MinValueValidator(0), MaxValueValidator(100000)], default = 0)
31 35
32 36 class Meta:
33 37 db_table = 'jars_filters'
34 38
35 39 def __unicode__(self):
36 40 return u'%s' % (self.name)
37 41
38 42 def parms_to_dict(self):
39 43
40 44 parameters = {}
41 45
42 46 parameters['name'] = self.name
43 47 parameters['clock'] = float(self.clock)
44 48 parameters['mult'] = int(self.mult)
45 49 parameters['fch'] = float(self.fch)
46 50 parameters['fch_decimal'] = int(self.fch)
47 51 parameters['filter_fir'] = int(self.filter_fir)
48 52 parameters['filter_2'] = int(self.filter_2)
49 53 parameters['filter_5'] = int(self.filter_5)
50 54 parameters['speed'] = int(self.speed)
51 55
52 56 return parameters
53 57
54 58 def dict_to_parms(self, parameters):
55 59
56 60 self.name = parameters['name']
57 61 self.clock = parameters['clock']
58 62 self.mult = parameters['mult']
59 63 self.fch = parameters['fch']
60 64 self.fch_decimal = parameters['fch_decimal']
61 65 self.filter_fir = parameters['filter_fir']
62 66 self.filter_2 = parameters['filter_2']
63 67 self.filter_5 = parameters['filter_5']
64 68 self.speed = parameters['speed']
65 69
66 70
67 71 class JARSConfiguration(Configuration):
68 72
69 73 ADC_RESOLUTION = 8
70 74 PCI_DIO_BUSWIDTH = 32
71 75 HEADER_VERSION = 1103
72 76 BEGIN_ON_START = True
73 77 REFRESH_RATE = 1
74 78
75 79 #rc = models.ForeignKey(RCConfiguration, on_delete=models.CASCADE, null=True)
76 80 exp_type = models.PositiveIntegerField(verbose_name='Experiment Type', choices=EXPERIMENT_TYPE, default=0)
77 81 cards_number = models.PositiveIntegerField(verbose_name='Number of Cards', validators=[MinValueValidator(1), MaxValueValidator(4)], default = 1)
78 82 channels_number = models.PositiveIntegerField(verbose_name='Number of Channels', validators=[MinValueValidator(1), MaxValueValidator(8)], default = 5)
79 83 channels = models.CharField(verbose_name='Channels', max_length=15, default = '1,2,3,4,5')
80 rd_directory = models.CharField(verbose_name='Raw Data Directory', max_length=40, default='', blank=True, null=True)
81 raw_data_blocks = models.PositiveIntegerField(verbose_name='Raw Data Blocks', validators=[MaxValueValidator(5000)], default=120)
84 rd_directory = models.CharField(verbose_name='Raw Data Directory', max_length=200, default='', blank=True, null=True)
85 pd_directory = models.CharField(verbose_name='Process Data Directory', max_length=200, default='', blank=True, null=True)
86 #raw_data_blocks = models.PositiveIntegerField(verbose_name='Raw Data Blocks', validators=[MaxValueValidator(5000)], default=120)
82 87 data_type = models.PositiveIntegerField(verbose_name='Data Type', choices=DATA_TYPE, default=0)
83 88 acq_profiles = models.PositiveIntegerField(verbose_name='Acquired Profiles', validators=[MaxValueValidator(5000)], default=400)
84 89 profiles_block = models.PositiveIntegerField(verbose_name='Profiles Per Block', validators=[MaxValueValidator(5000)], default=400)
90 ftp_interval = models.PositiveIntegerField(verbose_name='FTP Interval', default=60)
85 91 fftpoints = models.PositiveIntegerField(verbose_name='FFT Points',default=16)
92 cohe_integr_str = models.PositiveIntegerField(verbose_name='Coh. Int. Stride',validators=[MinValueValidator(1)], default=30)
86 93 cohe_integr = models.PositiveIntegerField(verbose_name='Coherent Integrations',validators=[MinValueValidator(1)], default=30)
87 94 incohe_integr = models.PositiveIntegerField(verbose_name='Incoherent Integrations',validators=[MinValueValidator(1)], default=30)
88 95 filter = models.ForeignKey(JARSfilter, on_delete=models.CASCADE, null=True)
89 96 spectral_number = models.PositiveIntegerField(verbose_name='# Spectral Combinations',validators=[MinValueValidator(1)], default=1)
90 97 spectral = models.CharField(verbose_name='Combinations', max_length=5000, default = '[0, 0],')
91 98 create_directory = models.BooleanField(verbose_name='Create Directory Per Day', default=True)
92 99 include_expname = models.BooleanField(verbose_name='Experiment Name in Directory', default=True)
93 acq_link = models.BooleanField(verbose_name='Acquisition Link', default=True)
94 view_raw_data = models.BooleanField(verbose_name='View Raw Data', default=True)
100 #acq_link = models.BooleanField(verbose_name='Acquisition Link', default=True)
101 #view_raw_data = models.BooleanField(verbose_name='View Raw Data', default=True)
95 102 save_ch_dc = models.BooleanField(verbose_name='Save Channels DC', default=True)
103 save_data = models.BooleanField(verbose_name='Save Data', default=True)
96 104 filter_parms = models.CharField(max_length=10000, default='{}')
97 105
98 106 class Meta:
99 107 db_table = 'jars_configurations'
100 108
101 109 def parms_to_dict(self):
102 110
103 111 parameters = {}
104 112
113 parameters['device_id'] = self.device.id
105 114 parameters['name'] = self.name
106 115 #parameters['rc'] = self.rc.name
107 116 parameters['exp_type'] = self.exp_type
108 117 parameters['exptype'] = EXPERIMENT_TYPE[self.exp_type][1]
109 118 parameters['cards_number'] = self.cards_number
110 119 parameters['channels_number'] = self.channels_number
111 120 parameters['channels'] = self.channels
112 121 parameters['rd_directory'] = self.rd_directory
113 parameters['raw_data_blocks'] = self.raw_data_blocks
122 #parameters['raw_data_blocks'] = self.raw_data_blocks
114 123 parameters['data_type'] = self.data_type
124 parameters['cohe_integr_str'] = self.cohe_integr_str
115 125 parameters['acq_profiles'] = self.acq_profiles
116 126 parameters['profiles_block'] = self.profiles_block
127 parameters['ftp_interval'] = self.ftp_interval
117 128 parameters['fftpoints'] = self.fftpoints
118 129 parameters['cohe_integr'] = self.cohe_integr
119 130 #parameters['incohe_integr'] = self.incohe_integr
120 131 parameters['filter'] = self.filter.name
132 parameters['filter_parms'] = self.filter_parms
121 133 #parameters['spectral_number'] = self.spectral_number
122 134 #parameters['spectral'] = self.spectral
123 135 parameters['create_directory'] = bool(self.create_directory)
124 136 parameters['include_expname'] = bool(self.include_expname)
125 parameters['acq_link'] = bool(self.acq_link)
126 parameters['view_raw_data'] = bool(self.view_raw_data)
137 #parameters['acq_link'] = bool(self.acq_link)
138 #parameters['view_raw_data'] = bool(self.view_raw_data)
127 139 parameters['save_ch_dc'] = bool(self.save_ch_dc)
140 parameters['save_data'] = bool(self.save_data)
128 141
129 142 if parameters['exptype'] == 'PDATA':
130 143 parameters['incohe_integr'] = self.incohe_integr
131 144 parameters['spectral_number'] = self.spectral_number
132 145 parameters['spectral'] = self.spectral
146 parameters['pd_directory'] = self.pd_directory
133 147
134 148 return parameters
135 149
136 150 def add_parms_to_filter(self):
137 151 self.filter_parms = self.filter.parms_to_dict()
138 152 self.save()
139 153
140 154 def dict_to_parms(self, parameters):
141 155
156 self.name = parameters['name']
157 self.device.id = int(parameters['device_id'])
158
142 159 self.exp_type = int(parameters['exp_type'])
143 160 if parameters['exptype'] == 'PDATA':
144 161 self.incohe_integr = parameters['incohe_integr']
145 162 self.spectral_number = parameters['spectral_number']
146 self.spectral = parameters['spectral']
163 self.spectral = parameters['spectral']
164 self.pd_directory = parameters['pd_directory']
147 165
148 166 self.cards_number = int(parameters['cards_number'])
149 167 self.channels_number = int(parameters['channels_number'])
150 168 self.channels = parameters['channels']
151 169 self.rd_directory = parameters['rd_directory']
152 self.raw_data_blocks = parameters['raw_data_blocks']
170 #self.raw_data_blocks = parameters['raw_data_blocks']
153 171 self.data_type = parameters['data_type']
172 self.cohe_integr_str = parameters['cohe_integr_str']
154 173 self.acq_profiles = parameters['acq_profiles']
155 174 self.profiles_block = parameters['profiles_block']
175 self.ftp_interval = parameters['ftp_interval']
156 176 self.fftpoints = parameters['fftpoints']
157 177 self.cohe_integr = parameters['cohe_integr']
158 178
159 filter_name = parameters['filter']
160 self.filter = JARS.objects.get(name=filter_name)
161 self.save()
179 filter_name = parameters['filter']
180 self.filter = JARSfilter.objects.get(name=filter_name)
162 181 self.add_parms_to_filter()
182 self.filter_parms = parameters['filter_parms']
163 183
164 184 self.create_directory = bool(parameters['create_directory'])
165 185 self.include_expname = bool(parameters['include_expname'])
166 self.acq_link = bool(parameters['acq_link'])
167 self.view_raw_data = bool(parameters['view_raw_data'])
186 #self.acq_link = bool(parameters['acq_link'])
187 #self.view_raw_data = bool(parameters['view_raw_data'])
168 188 self.save_ch_dc = bool(parameters['save_ch_dc'])
189 self.save_data = bool(parameters['save_data'])
169 190
170 191 def status_device(self):
171 return
192
193 answer = api.status(self.device.ip_address,self.device.port_address)
194 self.device.status = int(answer[0])
195 self.message = answer[2:]
196 self.device.save()
197
198 return self.device.status
199
200 def stop_device(self):
201
202 answer = api.stop(self.device.ip_address,self.device.port_address)
203 self.device.status = int(answer[0])
204 self.message = answer[2:]
205 self.device.save()
206
207 return self.device.status
172 208
173 209 def read_device(self):
174 return
210
211 answer = api.read(self.device.ip_address,self.device.port_address)
212 self.device.status = int(answer[0])
213 try:
214 data = json.loads(answer[2:])
215 parms = data['configurations']['jars']
216 except:
217 self.device.status = 0
218 self.device.save()
219 self.message = 'Could not read JARS configuration.'
220 return ''
221
222 #self.dict_to_parms(parms)
223 self.message = 'Current JARS configuration was read successfully.'
224 self.device.save()
225 return parms
226
175 227
176 228 def write_device(self):
177 return No newline at end of file
229
230 data = self.experiment.parms_to_dict()
231 data = json.loads(data)
232 data['configurations']['dds'] =''
233 data['configurations']['cgs'] =''
234 data['configurations']['rc']['pulses']=''
235 data['configurations']['rc']['delays']=''
236 json_data = json.dumps(data)
237
238 answer = api.configure(self.device.ip_address,self.device.port_address,json_data)
239 #print answer
240 self.device.status = int(answer[0])
241 self.message = answer[2:]
242
243 self.device.save()
244
245 return self.device.status
246
247
248 def echo(self):
249
250 answer = api.echo(self.device.ip_address,self.device.port_address,'(=')
251 #print answer
252 self.device.status = int(answer[0])
253 self.message = answer[2:]
254
255 self.device.save()
256
257 return #self.device.status
258
259 def update_from_file(self, parameters):
260
261 self.dict_to_parms(parameters)
262 self.save()
263
264 def get_absolute_url_import(self):
265 return reverse('url_import_jars_conf', args=[str(self.id)])
266
267 def get_absolute_url_read(self):
268 return reverse('url_read_jars_conf', args=[str(self.id)]) No newline at end of file
@@ -1,9 +1,11
1 1 from django.conf.urls import url
2 2
3 3 urlpatterns = (
4 4 url(r'^(?P<id_conf>-?\d+)/$', 'apps.jars.views.jars_conf', name='url_jars_conf'),
5 5 url(r'^(?P<id_conf>-?\d+)/edit/$', 'apps.jars.views.jars_conf_edit', name='url_edit_jars_conf'),
6 6 url(r'^(?P<conf_id>-?\d+)/new_filter/$', 'apps.jars.views.new_filter', name='url_new_jars_filter'),
7 7 url(r'^(?P<conf_id>-?\d+)/view_filter/(?P<filter_id>-?\d+)/$', 'apps.jars.views.view_filter', name='url_jars_filter'),
8 8 url(r'^(?P<conf_id>-?\d+)/view_filter/(?P<filter_id>-?\d+)/edit$', 'apps.jars.views.edit_filter', name='url_edit_jars_filter'),
9 url(r'^(?P<conf_id>-?\d+)/import/$', 'apps.jars.views.import_file', name='url_import_jars_conf'),
10 url(r'^(?P<conf_id>-?\d+)/read/$', 'apps.jars.views.read_conf', name='url_read_jars_conf'),
9 11 )
@@ -1,175 +1,247
1 1 from django.shortcuts import render_to_response
2 2 from django.template import RequestContext
3 3 from django.shortcuts import redirect, render, get_object_or_404
4 4 from django.contrib import messages
5 5
6 6 from apps.main.models import Device
7 7 from apps.main.views import sidebar
8 8
9 9 from .models import JARSConfiguration, JARSfilter
10 from .forms import JARSConfigurationForm, JARSfilterForm
10 from .forms import JARSConfigurationForm, JARSfilterForm, JARSImportForm
11 11 # Create your views here.
12 12
13 13 def jars_conf(request, id_conf):
14 14
15 15 conf = get_object_or_404(JARSConfiguration, pk=id_conf)
16 16
17 17 ip=conf.device.ip_address
18 18 port=conf.device.port_address
19 19
20 20 kwargs = {}
21 21 kwargs['status'] = conf.device.get_status_display()
22 22
23 23
24 24 kwargs['dev_conf'] = conf
25 25 kwargs['dev_conf_keys'] = ['name',
26 26 'cards_number', 'channels_number', 'channels',
27 'rd_directory', 'raw_data_blocks', 'data_type',
28 'acq_profiles', 'profiles_block', 'fftpoints',
27 'rd_directory', 'pd_directory',
28 'data_type',
29 'acq_profiles', 'profiles_block', 'ftp_interval', 'fftpoints',
30 'cohe_integr_str',
29 31 'incohe_integr', 'cohe_integr', 'filter', 'spectral_number',
30 32 'spectral', 'create_directory', 'include_expname',
31 'acq_link', 'view_raw_data', 'save_ch_dc',]
33 'save_ch_dc', 'save_data']
32 34
33 35 kwargs['title'] = 'JARS Configuration'
34 36 kwargs['suptitle'] = 'Details'
35 37
36 38 kwargs['button'] = 'Edit Configuration'
37 39
38 kwargs['no_play'] = True
40 #kwargs['no_play'] = True
41
42 kwargs['only_stop'] = True
39 43
40 44 ###### SIDEBAR ######
41 45 kwargs.update(sidebar(conf=conf))
42 46
43 47 return render(request, 'jars_conf.html', kwargs)
44 48
45 49 def jars_conf_edit(request, id_conf):
46 50
47 51 conf = get_object_or_404(JARSConfiguration, pk=id_conf)
48 52
49 53 if request.method=='GET':
50 54 form = JARSConfigurationForm(instance=conf)
51 55
52 56 if request.method=='POST':
53 57 form = JARSConfigurationForm(request.POST, instance=conf)
54 58
55 59 if form.is_valid():
56 60 conf = form.save(commit=False)
57 61 conf.save()
58 62 return redirect('url_jars_conf', id_conf=conf.id)
59 63
60 64 ##ERRORS
61 65
62 66 kwargs = {}
63 67
64 68 kwargs['filter_id'] = conf.filter.id
65 69 kwargs['id_dev'] = conf.id
66 70 kwargs['form'] = form
67 71 kwargs['title'] = 'Device Configuration'
68 72 kwargs['suptitle'] = 'Edit'
69 73 kwargs['button'] = 'Save'
70 74
71 75 return render(request, 'jars_conf_edit.html', kwargs)
72 76
77 def import_file(request, conf_id):
78
79 conf = get_object_or_404(JARSConfiguration, pk=conf_id)
80 if request.method=='POST':
81 form = JARSImportForm(request.POST, request.FILES)
82 if form.is_valid():
83 try:
84 parms = conf.import_from_file(request.FILES['file_name'])
85
86 if parms:
87 conf.update_from_file(parms)
88 messages.success(request, 'Configuration "%s" loaded succesfully' % request.FILES['file_name'])
89 return redirect(conf.get_absolute_url_edit())
90
91 except Exception as e:
92 messages.error(request, 'Error parsing file: "%s" - %s' % (request.FILES['file_name'], e))
93
94 else:
95 messages.warning(request, 'Your current configuration will be replaced')
96 form = JARSImportForm()
97
98 kwargs = {}
99 kwargs['form'] = form
100 kwargs['title'] = 'JARS Configuration'
101 kwargs['suptitle'] = 'Import file'
102 kwargs['button'] = 'Upload'
103 kwargs['previous'] = conf.get_absolute_url()
104
105 return render(request, 'jars_import.html', kwargs)
106
107 def read_conf(request, conf_id):
108
109 conf = get_object_or_404(JARSConfiguration, pk=conf_id)
110 #filter = get_object_or_404(JARSfilter, pk=filter_id)
111
112 if request.method=='GET':
113
114 parms = conf.read_device()
115 conf.status_device()
116
117 if not parms:
118 messages.error(request, conf.message)
119 return redirect(conf.get_absolute_url())
120
121 form = JARSConfigurationForm(initial=parms, instance=conf)
122
123 if request.method=='POST':
124 form = JARSConfigurationForm(request.POST, instance=conf)
125
126 if form.is_valid():
127 form.save()
128 return redirect(conf.get_absolute_url())
129
130 messages.error(request, "Parameters could not be saved")
131
132 kwargs = {}
133 kwargs['id_dev'] = conf.id
134 kwargs['filter_id'] = conf.filter.id
135 kwargs['form'] = form
136 kwargs['title'] = 'Device Configuration'
137 kwargs['suptitle'] = 'Parameters read from device'
138 kwargs['button'] = 'Save'
139
140 ###### SIDEBAR ######
141 kwargs.update(sidebar(conf=conf))
142
143 return render(request, 'jars_conf_edit.html', kwargs)
144
73 145 def view_filter(request, conf_id, filter_id):
74 146
75 147 conf = get_object_or_404(JARSConfiguration, pk=conf_id)
76 148 filter = get_object_or_404(JARSfilter, pk=filter_id)
77 149
78 150 filter_parms = eval(conf.filter_parms)
79 151 filter.name = filter_parms['name']
80 152 filter.clock = filter_parms['clock']
81 153 filter.mult = filter_parms['mult']
82 154 filter.fch = filter_parms['fch']
83 155 filter.fch_decimal = filter_parms['fch_decimal']
84 156 filter.filter_fir = filter_parms['filter_fir']
85 157 filter.filter_2 = filter_parms['filter_2']
86 158 filter.filter_5 = filter_parms['filter_5']
87 159 filter.speed = filter_parms['speed']
88 160
89 161 kwargs = {}
90 162 kwargs['conf'] = conf
91 163 kwargs['filter'] = filter
92 164 kwargs['dev_conf'] = filter
93 165 kwargs['dev_conf_keys'] = ['name', 'clock',
94 166 'mult', 'fch', 'fch_decimal',
95 167 'filter_fir', 'filter_2',
96 168 'filter_5', 'speed']
97 169
98 170 kwargs['title'] = 'Filter View'
99 171 kwargs['suptitle'] = 'Details'
100 172 kwargs['button'] = 'SI'
101 173 kwargs['edit_button'] = 'Edit Filter'
102 174 kwargs['add_button'] = 'New Filter'
103 175
104 176 return render(request, 'jars_filter.html', kwargs)
105 177
106 178 def edit_filter(request, conf_id, filter_id):
107 179
108 180 conf = get_object_or_404(JARSConfiguration, pk=conf_id)
109 181 filter_parms = eval(conf.filter_parms)
110 182
111 183 if filter_id:
112 184 filter = get_object_or_404(JARSfilter, pk=filter_id)
113 185
114 186 if request.method=='GET':
115 187 form = JARSfilterForm(initial=filter_parms)
116 188
117 189 if request.method=='POST':
118 190 parms = {}
119 191 parms['name'] = request.POST['name']
120 192 parms['clock'] = request.POST['clock']
121 193 parms['mult'] = request.POST['mult']
122 194 parms['fch'] = request.POST['fch']
123 195 parms['fch_decimal'] = request.POST['fch_decimal']
124 196 parms['filter_fir'] = request.POST['filter_fir']
125 197 parms['filter_2'] = request.POST['filter_2']
126 198 parms['filter_5'] = request.POST['filter_5']
127 199 parms['speed'] = request.POST['speed']
128 200
129 201 conf.filter_parms = parms
130 202 conf.save()
131 203
132 204 #form = JARSfilterForm(request.POST)
133 205 #form = JARSfilterForm(request.POST, instance=filter)
134 206 #if form.is_valid():
135 207 #form.save()
136 208 # messages.success(request, 'JARS Filter successfully updated')
137 209 # return redirect('url_jars_filter', conf.id, filter.id)
138 210 return redirect('url_jars_filter', conf.id, filter.id)
139 211
140 212 kwargs = {}
141 213 kwargs['form'] = form
142 214 kwargs['title'] = conf.name
143 215 kwargs['suptitle'] = 'Edit Filter'
144 216 kwargs['button'] = 'Save'
145 217 # kwargs['previous'] = conf.get_absolute_url_edit()
146 218 kwargs['dev_conf'] = conf
147 219
148 220 return render(request, 'jars_filter_edit.html', kwargs)
149 221
150 222 def new_filter(request, conf_id):
151 223
152 224 conf = get_object_or_404(JARSConfiguration, pk=conf_id)
153 225
154 226 if request.method=='GET':
155 227 form = JARSfilterForm()
156 228
157 229 if request.method=='POST':
158 230 form = JARSfilterForm(request.POST)
159 231 if form.is_valid():
160 232 form.save()
161 233 new_filter = get_object_or_404(JARSfilter, name=request.POST['name'])
162 234 conf.filter = new_filter
163 235 conf.add_parms_to_filter()
164 236 messages.success(request, 'New JARS Filter successfully created')
165 237 return redirect('url_edit_jars_conf', id_conf=conf.id)
166 238
167 239 kwargs = {}
168 240 kwargs['form'] = form
169 241 kwargs['title'] = 'New Filter'
170 242 kwargs['suptitle'] = ''
171 243 kwargs['button'] = 'Create'
172 244 # kwargs['previous'] = conf.get_absolute_url_edit()
173 245 kwargs['dev_conf'] = conf
174 246
175 247 return render(request, 'jars_new_filter.html', kwargs) No newline at end of file
@@ -1,602 +1,612
1 1 from django.shortcuts import render, redirect, get_object_or_404, HttpResponse
2 2 from datetime import datetime
3 3
4 4 from django.db import models
5 5 from polymorphic import PolymorphicModel
6 6
7 7 from django.core.urlresolvers import reverse
8 8
9 9
10 10 CONF_STATES = (
11 11 (0, 'Disconnected'),
12 12 (1, 'Connected'),
13 13 (2, 'Running'),
14 14 )
15 15
16 16 EXP_STATES = (
17 17 (0,'Error'), #RED
18 18 (1,'Configured'), #BLUE
19 19 (2,'Running'), #GREEN
20 20 (3,'Waiting'), #YELLOW
21 21 (4,'Not Configured'), #WHITE
22 22 )
23 23
24 24 CONF_TYPES = (
25 25 (0, 'Active'),
26 26 (1, 'Historical'),
27 27 )
28 28
29 29 DEV_STATES = (
30 30 (0, 'No connected'),
31 31 (1, 'Connected'),
32 32 (2, 'Configured'),
33 33 (3, 'Running'),
34 34 )
35 35
36 36 DEV_TYPES = (
37 37 ('', 'Select a device type'),
38 38 ('rc', 'Radar Controller'),
39 39 ('rc_mix', 'Radar Controller (Mix)'),
40 40 ('dds', 'Direct Digital Synthesizer'),
41 41 ('jars', 'Jicamarca Radar Acquisition System'),
42 42 ('usrp', 'Universal Software Radio Peripheral'),
43 43 ('cgs', 'Clock Generator System'),
44 44 ('abs', 'Automatic Beam Switching'),
45 45 )
46 46
47 47 DEV_PORTS = {
48 48 'rc' : 2000,
49 49 'rc_mix': 2000,
50 50 'dds' : 2000,
51 51 'jars' : 2000,
52 52 'usrp' : 2000,
53 53 'cgs' : 8080,
54 54 'abs' : 8080
55 55 }
56 56
57 57 RADAR_STATES = (
58 58 (0, 'No connected'),
59 59 (1, 'Connected'),
60 60 (2, 'Configured'),
61 61 (3, 'Running'),
62 62 (4, 'Scheduled'),
63 63 )
64 64 # Create your models here.
65 65
66 66 class Location(models.Model):
67 67
68 68 name = models.CharField(max_length = 30)
69 69 description = models.TextField(blank=True, null=True)
70 70
71 71 class Meta:
72 72 db_table = 'db_location'
73 73
74 74 def __unicode__(self):
75 75 return u'%s' % self.name
76 76
77 77 def get_absolute_url(self):
78 78 return reverse('url_location', args=[str(self.id)])
79 79
80 80
81 81 class DeviceType(models.Model):
82 82
83 83 name = models.CharField(max_length = 10, choices = DEV_TYPES, default = 'rc')
84 84 description = models.TextField(blank=True, null=True)
85 85
86 86 class Meta:
87 87 db_table = 'db_device_types'
88 88
89 89 def __unicode__(self):
90 90 return u'%s' % self.get_name_display()
91 91
92 92 class Device(models.Model):
93 93
94 94 device_type = models.ForeignKey(DeviceType, on_delete=models.CASCADE)
95 95 location = models.ForeignKey(Location, on_delete=models.CASCADE)
96 96
97 97 name = models.CharField(max_length=40, default='')
98 98 ip_address = models.GenericIPAddressField(protocol='IPv4', default='0.0.0.0')
99 99 port_address = models.PositiveSmallIntegerField(default=2000)
100 100 description = models.TextField(blank=True, null=True)
101 101 status = models.PositiveSmallIntegerField(default=0, choices=DEV_STATES)
102 102
103 103 class Meta:
104 104 db_table = 'db_devices'
105 105
106 106 def __unicode__(self):
107 107 return u'[{}]: {}'.format(self.device_type.name.upper(),
108 108 self.name)
109 109
110 110 def get_status(self):
111 111 return self.status
112 112
113 113 @property
114 114 def status_color(self):
115 115 color = 'muted'
116 116 if self.status == 0:
117 117 color = "danger"
118 118 elif self.status == 1:
119 119 color = "warning"
120 120 elif self.status == 2:
121 121 color = "info"
122 122 elif self.status == 3:
123 123 color = "success"
124 124
125 125 return color
126 126
127 127 def get_absolute_url(self):
128 128 return reverse('url_device', args=[str(self.id)])
129 129
130 130
131 131 class Campaign(models.Model):
132 132
133 133 template = models.BooleanField(default=False)
134 134 name = models.CharField(max_length=60, unique=True)
135 135 start_date = models.DateTimeField(blank=True, null=True)
136 136 end_date = models.DateTimeField(blank=True, null=True)
137 137 tags = models.CharField(max_length=40)
138 138 description = models.TextField(blank=True, null=True)
139 139 experiments = models.ManyToManyField('Experiment', blank=True)
140 140
141 141 class Meta:
142 142 db_table = 'db_campaigns'
143 143 ordering = ('name',)
144 144
145 145 def __unicode__(self):
146 146 if self.template:
147 147 return u'{} (template)'.format(self.name)
148 148 else:
149 149 return u'{}'.format(self.name)
150 150
151 151
152 152 def parms_to_dict(self):
153 153
154 154 import json
155 155
156 156 parameters = {}
157 157 exp_parameters = {}
158 158 experiments = Experiment.objects.filter(campaign = self)
159 159
160 160 i=1
161 161 for experiment in experiments:
162 162 exp_parameters['experiment-'+str(i)] = json.loads(experiment.parms_to_dict())
163 163 i += 1
164 164
165 165
166 166 parameters['experiments'] = exp_parameters
167 167 parameters['end_date'] = self.end_date.strftime("%Y-%m-%d")
168 168 parameters['start_date'] = self.start_date.strftime("%Y-%m-%d")
169 169 parameters['campaign'] = self.__unicode__()
170 170 parameters['tags'] =self.tags
171 171
172 172 parameters = json.dumps(parameters, indent=2, sort_keys=False)
173 173
174 174 return parameters
175 175
176 176 def import_from_file(self, fp):
177 177
178 178 import os, json
179 179
180 180 parms = {}
181 181
182 182 path, ext = os.path.splitext(fp.name)
183 183
184 184 if ext == '.json':
185 185 parms = json.load(fp)
186 186
187 187 return parms
188 188
189 189 def dict_to_parms(self, parms, CONF_MODELS):
190 190
191 191 experiments = Experiment.objects.filter(campaign = self)
192 192 configurations = Configuration.objects.filter(experiment = experiments)
193 193
194 194 if configurations:
195 195 for configuration in configurations:
196 196 configuration.delete()
197 197
198 198 if experiments:
199 199 for experiment in experiments:
200 200 experiment.delete()
201 201
202 202 for parms_exp in parms['experiments']:
203 203 location = Location.objects.get(name = parms['experiments'][parms_exp]['radar'])
204 204 new_exp = Experiment(
205 205 name = parms['experiments'][parms_exp]['experiment'],
206 206 location = location,
207 207 start_time = parms['experiments'][parms_exp]['start_time'],
208 208 end_time = parms['experiments'][parms_exp]['end_time'],
209 209 )
210 210 new_exp.save()
211 211 new_exp.dict_to_parms(parms['experiments'][parms_exp],CONF_MODELS)
212 212 new_exp.save()
213 213
214 214 self.name = parms['campaign']
215 215 self.start_date = parms['start_date']
216 216 self.end_date = parms['end_date']
217 217 self.tags = parms['tags']
218 218 self.experiments.add(new_exp)
219 219 self.save()
220 220
221 221 return self
222 222
223 223 def get_absolute_url(self):
224 224 return reverse('url_campaign', args=[str(self.id)])
225 225
226 226 def get_absolute_url_edit(self):
227 227 return reverse('url_edit_campaign', args=[str(self.id)])
228 228
229 229 def get_absolute_url_export(self):
230 230 return reverse('url_export_campaign', args=[str(self.id)])
231 231
232 232 def get_absolute_url_import(self):
233 233 return reverse('url_import_campaign', args=[str(self.id)])
234 234
235 235
236 236
237 237 class RunningExperiment(models.Model):
238 238 radar = models.OneToOneField('Location', on_delete=models.CASCADE)
239 239 running_experiment = models.ManyToManyField('Experiment', blank = True)
240 240 status = models.PositiveSmallIntegerField(default=0, choices=RADAR_STATES)
241 241
242 242
243 243 class Experiment(models.Model):
244 244
245 245 template = models.BooleanField(default=False)
246 246 name = models.CharField(max_length=40, default='', unique=True)
247 247 location = models.ForeignKey('Location', null=True, blank=True, on_delete=models.CASCADE)
248 248 start_time = models.TimeField(default='00:00:00')
249 249 end_time = models.TimeField(default='23:59:59')
250 250 status = models.PositiveSmallIntegerField(default=0, choices=EXP_STATES)
251 251
252 252 class Meta:
253 253 db_table = 'db_experiments'
254 254 ordering = ('template', 'name')
255 255
256 256 def __unicode__(self):
257 257 if self.template:
258 258 return u'%s (template)' % (self.name)
259 259 else:
260 260 return u'%s' % (self.name)
261 261
262 262 @property
263 263 def radar_system(self):
264 264 return self.location
265 265
266 266 def clone(self, **kwargs):
267 267
268 268 confs = Configuration.objects.filter(experiment=self, type=0)
269 269 self.pk = None
270 270 self.name = '{} [{:%Y/%m/%d}]'.format(self.name, datetime.now())
271 271 for attr, value in kwargs.items():
272 272 setattr(self, attr, value)
273 273
274 274 self.save()
275 275
276 276 for conf in confs:
277 277 conf.clone(experiment=self, template=False)
278 278
279 279 return self
280 280
281 281 def get_status(self):
282 282 configurations = Configuration.objects.filter(experiment=self)
283 283 exp_status=[]
284 284 for conf in configurations:
285 285 print conf.status_device()
286 286 exp_status.append(conf.status_device())
287 287
288 288 if not exp_status: #No Configuration
289 289 self.status = 4
290 290 self.save()
291 291 return
292 292
293 293 total = 1
294 294 for e_s in exp_status:
295 295 total = total*e_s
296 296
297 297 if total == 0: #Error
298 298 status = 0
299 299 elif total == (3**len(exp_status)): #Running
300 300 status = 2
301 301 else:
302 302 status = 1 #Configurated
303 303
304 304 self.status = status
305 305 self.save()
306 306
307 307 def status_color(self):
308 308 color = 'muted'
309 309 if self.status == 0:
310 310 color = "danger"
311 311 elif self.status == 1:
312 312 color = "info"
313 313 elif self.status == 2:
314 314 color = "success"
315 315 elif self.status == 3:
316 316 color = "warning"
317 317
318 318 return color
319 319
320 320 def get_absolute_url(self):
321 321 return reverse('url_experiment', args=[str(self.id)])
322 322
323 323 def parms_to_dict(self):
324 324
325 325 import json
326 326
327 327 configurations = Configuration.objects.filter(experiment=self)
328 328 conf_parameters = {}
329 329 parameters={}
330 330
331 331 for configuration in configurations:
332 332 if 'cgs' in configuration.device.device_type.name:
333 333 conf_parameters['cgs'] = configuration.parms_to_dict()
334 334 if 'dds' in configuration.device.device_type.name:
335 335 conf_parameters['dds'] = configuration.parms_to_dict()
336 336 if 'rc' in configuration.device.device_type.name:
337 337 conf_parameters['rc'] = configuration.parms_to_dict()
338 338 if 'jars' in configuration.device.device_type.name:
339 339 conf_parameters['jars'] = configuration.parms_to_dict()
340 340 if 'usrp' in configuration.device.device_type.name:
341 341 conf_parameters['usrp'] = configuration.parms_to_dict()
342 342 if 'abs' in configuration.device.device_type.name:
343 343 conf_parameters['abs'] = configuration.parms_to_dict()
344 344
345 345 parameters['configurations'] = conf_parameters
346 346 parameters['end_time'] = self.end_time.strftime("%H:%M:%S")
347 347 parameters['start_time'] = self.start_time.strftime("%H:%M:%S")
348 348 parameters['radar'] = self.radar_system.name
349 349 parameters['experiment'] = self.name
350 350 parameters = json.dumps(parameters, indent=2)
351 351
352 352 return parameters
353 353
354 354 def import_from_file(self, fp):
355 355
356 356 import os, json
357 357
358 358 parms = {}
359 359
360 360 path, ext = os.path.splitext(fp.name)
361 361
362 362 if ext == '.json':
363 363 parms = json.load(fp)
364 364
365 365 return parms
366 366
367 367 def dict_to_parms(self, parms, CONF_MODELS):
368 368
369 369 configurations = Configuration.objects.filter(experiment=self)
370 370
371 371 if configurations:
372 372 for configuration in configurations:
373 373 configuration.delete()
374 374
375 375 for conf_type in parms['configurations']:
376 376 #--For ABS Device:
377 377 #--For USRP Device:
378 378 #--For JARS Device:
379 if conf_type == 'jars':
380 device = get_object_or_404(Device, pk=parms['configurations']['jars']['device_id'])
381 DevConfModel = CONF_MODELS[conf_type]
382 confjars_form = DevConfModel(
383 experiment = self,
384 name = 'JARS',
385 device=device,
386 )
387 confjars_form.dict_to_parms(parms['configurations']['jars'])
388 confjars_form.save()
379 389 #--For RC Device:
380 390 if conf_type == 'rc':
381 391 device = get_object_or_404(Device, pk=parms['configurations']['rc']['device_id'])
382 392 DevConfModel = CONF_MODELS[conf_type]
383 393 confrc_form = DevConfModel(
384 394 experiment = self,
385 395 name = 'RC',
386 396 device=device,
387 397 )
388 398 confrc_form.dict_to_parms(parms['configurations']['rc'])
389 399 confrc_form.save()
390 400 #--For DDS Device:
391 401 if conf_type == 'dds':
392 402 device = get_object_or_404(Device, pk=parms['configurations']['dds']['device_id'])
393 403 DevConfModel = CONF_MODELS[conf_type]
394 404 confdds_form = DevConfModel(
395 405 experiment = self,
396 406 name = 'DDS',
397 407 device=device,
398 408 )
399 409 confdds_form.dict_to_parms(parms['configurations']['dds'])
400 410 confdds_form.save()
401 411 #--For CGS Device:
402 412 if conf_type == 'cgs':
403 413 device = get_object_or_404(Device, pk=parms['configurations']['cgs']['device_id'])
404 414 DevConfModel = CONF_MODELS[conf_type]
405 415 confcgs_form = DevConfModel(
406 416 experiment = self,
407 417 name = 'CGS',
408 418 device=device,
409 419 )
410 420 confcgs_form.dict_to_parms(parms['configurations']['cgs'])
411 421 confcgs_form.save()
412 422
413 423 location = Location.objects.get(name = parms['radar'])
414 424 self.name = parms['experiment']
415 425 self.location = location
416 426 self.start_time = parms['start_time']
417 427 self.end_time = parms['end_time']
418 428 self.save()
419 429
420 430 return self
421 431
422 432 def get_absolute_url_edit(self):
423 433 return reverse('url_edit_experiment', args=[str(self.id)])
424 434
425 435 def get_absolute_url_import(self):
426 436 return reverse('url_import_experiment', args=[str(self.id)])
427 437
428 438 def get_absolute_url_export(self):
429 439 return reverse('url_export_experiment', args=[str(self.id)])
430 440
431 441
432 442 class Configuration(PolymorphicModel):
433 443
434 444 template = models.BooleanField(default=False)
435 445
436 446 name = models.CharField(verbose_name="Configuration Name", max_length=40, default='')
437 447
438 448 experiment = models.ForeignKey('Experiment', verbose_name='Experiment', null=True, blank=True, on_delete=models.CASCADE)
439 449 device = models.ForeignKey('Device', verbose_name='Device', null=True, on_delete=models.CASCADE)
440 450
441 451 type = models.PositiveSmallIntegerField(default=0, choices=CONF_TYPES)
442 452
443 453 created_date = models.DateTimeField(auto_now_add=True)
444 454 programmed_date = models.DateTimeField(auto_now=True)
445 455
446 456 parameters = models.TextField(default='{}')
447 457
448 458 message = ""
449 459
450 460 class Meta:
451 461 db_table = 'db_configurations'
452 462
453 463 def __unicode__(self):
454 464
455 465 device = '{}:'.format(self.device.device_type.name.upper())
456 466
457 467 if 'mix' in self._meta.get_all_field_names():
458 468 if self.mix:
459 469 device = '{} MIXED:'.format(self.device.device_type.name.upper())
460 470
461 471 if self.template:
462 472 return u'{} {} (template)'.format(device, self.name)
463 473 else:
464 474 return u'{} {}'.format(device, self.name)
465 475
466 476 def clone(self, **kwargs):
467 477
468 478 self.pk = None
469 479 self.id = None
470 480 for attr, value in kwargs.items():
471 481 setattr(self, attr, value)
472 482
473 483 self.save()
474 484
475 485 return self
476 486
477 487 def parms_to_dict(self):
478 488
479 489 parameters = {}
480 490
481 491 for key in self.__dict__.keys():
482 492 parameters[key] = getattr(self, key)
483 493
484 494 return parameters
485 495
486 496 def parms_to_text(self):
487 497
488 498 raise NotImplementedError, "This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper()
489 499
490 500 return ''
491 501
492 502 def parms_to_binary(self):
493 503
494 504 raise NotImplementedError, "This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper()
495 505
496 506 return ''
497 507
498 508 def dict_to_parms(self, parameters):
499 509
500 510 if type(parameters) != type({}):
501 511 return
502 512
503 513 for key in parameters.keys():
504 514 setattr(self, key, parameters[key])
505 515
506 516 def export_to_file(self, format="json"):
507 517
508 518 import json
509 519
510 520 content_type = ''
511 521
512 522 if format == 'text':
513 523 content_type = 'text/plain'
514 524 filename = '%s_%s.%s' %(self.device.device_type.name, self.name, self.device.device_type.name)
515 525 content = self.parms_to_text()
516 526
517 527 if format == 'binary':
518 528 content_type = 'application/octet-stream'
519 529 filename = '%s_%s.bin' %(self.device.device_type.name, self.name)
520 530 content = self.parms_to_binary()
521 531
522 532 if not content_type:
523 533 content_type = 'application/json'
524 534 filename = '%s_%s.json' %(self.device.device_type.name, self.name)
525 535 content = json.dumps(self.parms_to_dict(), indent=2)
526 536
527 537 fields = {'content_type':content_type,
528 538 'filename':filename,
529 539 'content':content
530 540 }
531 541
532 542 return fields
533 543
534 544 def import_from_file(self, fp):
535 545
536 546 import os, json
537 547
538 548 parms = {}
539 549
540 550 path, ext = os.path.splitext(fp.name)
541 551
542 552 if ext == '.json':
543 553 parms = json.load(fp)
544 554
545 555 return parms
546 556
547 557 def status_device(self):
548 558
549 559 raise NotImplementedError, "This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper()
550 560
551 561 return None
552 562
553 563 def stop_device(self):
554 564
555 565 raise NotImplementedError, "This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper()
556 566
557 567 return None
558 568
559 569 def start_device(self):
560 570
561 571 raise NotImplementedError, "This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper()
562 572
563 573 return None
564 574
565 575 def write_device(self, parms):
566 576
567 577 raise NotImplementedError, "This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper()
568 578
569 579 return None
570 580
571 581 def read_device(self):
572 582
573 583 raise NotImplementedError, "This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper()
574 584
575 585 return None
576 586
577 587 def get_absolute_url(self):
578 588 return reverse('url_%s_conf' % self.device.device_type.name, args=[str(self.id)])
579 589
580 590 def get_absolute_url_edit(self):
581 591 return reverse('url_edit_%s_conf' % self.device.device_type.name, args=[str(self.id)])
582 592
583 593 def get_absolute_url_import(self):
584 594 return reverse('url_import_dev_conf', args=[str(self.id)])
585 595
586 596 def get_absolute_url_export(self):
587 597 return reverse('url_export_dev_conf', args=[str(self.id)])
588 598
589 599 def get_absolute_url_write(self):
590 600 return reverse('url_write_dev_conf', args=[str(self.id)])
591 601
592 602 def get_absolute_url_read(self):
593 603 return reverse('url_read_dev_conf', args=[str(self.id)])
594 604
595 605 def get_absolute_url_start(self):
596 606 return reverse('url_start_dev_conf', args=[str(self.id)])
597 607
598 608 def get_absolute_url_stop(self):
599 609 return reverse('url_stop_dev_conf', args=[str(self.id)])
600 610
601 611 def get_absolute_url_status(self):
602 612 return reverse('url_status_dev_conf', args=[str(self.id)]) No newline at end of file
@@ -1,82 +1,84
1 1 {% extends "base.html" %}
2 2 {% load bootstrap3 %}
3 3 {% load static %}
4 4 {% load main_tags %}
5 5
6 6 {% block search-active %}active{% endblock %}
7 7
8 8 {% block content-title %}{{title}}{% endblock %}
9 9 {% block content-suptitle %}{{suptitle}}{% endblock %}
10 10
11 11 {% block content %}
12 12
13 13 {% block menu-actions %}
14 14 <span class=" dropdown pull-right">
15 15 <a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-menu-hamburger gi-2x" aria-hidden="true"></span></a>
16 16 <ul class="dropdown-menu" role="menu">
17 17 <li><a href="{{ dev_conf.get_absolute_url_edit }}"><span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Edit</a></li>
18 18 <li><a href="{% url 'url_delete_dev_conf' dev_conf.id %}"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span> Delete</a></li>
19 19 <li><a href="{{ dev_conf.get_absolute_url_import }}"><span class="glyphicon glyphicon-import" aria-hidden="true"></span> Import </a></li>
20 20 <li><a href="{{ dev_conf.get_absolute_url_export }}"><span class="glyphicon glyphicon-export" aria-hidden="true"></span> Export </a></li>
21 21 {% block extra-menu-actions %}
22 22 {% endblock %}
23 23 <li><a>----------------</a></li>
24 24 <li><a href="{{ dev_conf.get_absolute_url_status }}"><span class="glyphicon glyphicon-refresh" aria-hidden="true"></span> Status</a></li>
25 25 {% if not no_play %}
26 <li><a href="{{ dev_conf.get_absolute_url_start}}"><span class="glyphicon glyphicon-play" aria-hidden="true"></span> Start</a></li>
26 {% if not only_stop %}
27 <li><a href="{{ dev_conf.get_absolute_url_start}}"><span class="glyphicon glyphicon-play" aria-hidden="true"></span> Start</a></li>
28 {% endif %}
27 29 <li><a href="{{ dev_conf.get_absolute_url_stop }}"><span class="glyphicon glyphicon-stop" aria-hidden="true"></span> Stop</a></li>
28 30 {% endif %}
29 31 <li><a href="{{ dev_conf.get_absolute_url_write }}"><span class="glyphicon glyphicon-download" aria-hidden="true"></span> Write</a></li>
30 32 <li><a href="{{ dev_conf.get_absolute_url_read }}"><span class="glyphicon glyphicon-upload" aria-hidden="true"></span> Read</a></li>
31 33 </ul>
32 34 </span>
33 35 {% endblock %}
34 36
35 37 <table class="table table-bordered">
36 38 <tr>
37 39 <th>Status</th>
38 40 <td>{%if status != "No connected" %} <span class="glyphicon glyphicon-ok-circle text-success" aria-hidden="true"></span> {{status}} {% else %} <span class="glyphicon glyphicon-remove-circle text-danger" aria-hidden="true"></span> {{status}} {% endif %}</td>
39 41 </tr>
40 42
41 43 {% for key in dev_conf_keys %}
42 44 <tr>
43 45 <th>{% get_verbose_field_name dev_conf key %}</th>
44 46 <td>{{dev_conf|attr:key}}</td>
45 47 </tr>
46 48 {% endfor %}
47 49 </table>
48 50
49 51 {% block extra-content %}
50 52 {% endblock %}
51 53
52 54 {% endblock %}
53 55
54 56 {% block sidebar%}
55 57 {% include "sidebar_devices.html" %}
56 58 {% endblock %}
57 59
58 60 {% block extra-js%}
59 61 <script type="text/javascript">
60 62
61 63 $("#bt_edit").click(function() {
62 64 document.location = "{{ dev_conf.get_absolute_url_edit }}";
63 65 });
64 66
65 67 $("#bt_read").click(function() {
66 68 document.location = "{{ dev_conf.get_absolute_url_read }}";
67 69 });
68 70
69 71 $("#bt_write").click(function() {
70 72 document.location = "{{ dev_conf.get_absolute_url_write }}";
71 73 });
72 74
73 75 $("#bt_import").click(function() {
74 76 document.location = "{{ dev_conf.get_absolute_url_import }}";
75 77 });
76 78
77 79 $("#bt_export").click(function() {
78 80 document.location = "{{ dev_conf.get_absolute_url_export }}";
79 81 });
80 82
81 83 </script>
82 84 {% endblock %} No newline at end of file
@@ -1,125 +1,139
1 1 {% extends "base.html" %}
2 2 {% load bootstrap3 %}
3 3 {% load static %}
4 4 {% load main_tags %}
5 5 {% block extra-head %}
6 6 <link href="{% static 'css/bootstrap-datetimepicker.min.css' %}" media="screen" rel="stylesheet">
7 7 {% endblock %}
8 8
9 9 {% block exp-active %}active{% endblock %}
10 10
11 11 {% block content-title %}{{title}}{% endblock %}
12 12 {% block content-suptitle %}{{suptitle}}{% endblock %}
13 13
14 14 {% block content %}
15 15
16 16 {% block menu-actions %}
17 17 <!-- <span class=" dropdown pull-right">
18 18 <a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-menu-hamburger gi-2x" aria-hidden="true"></span></a>
19 19 <ul class="dropdown-menu" role="menu">
20 20 <li><a href="{% url 'url_edit_experiment' experiment.id %}"><span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Edit</a></li>
21 21 <li><a href="{% url 'url_delete_experiment' experiment.id %}"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span> Delete</a></li>
22 22 <li><a href="{{ experiment.get_absolute_url_import }}"><span class="glyphicon glyphicon-import" aria-hidden="true"></span> Import </a></li>
23 23 <li><a href="{{ experiment.get_absolute_url_export }}"><span class="glyphicon glyphicon-export" aria-hidden="true"></span> Export </a></li>
24 24 {% block extra-menu-actions %}
25 25 {% endblock %}
26 26 <li><a>----------------</a></li>
27 27 <li><a href="{% url 'url_mix_experiment' experiment.id %}"><span class="glyphicon glyphicon-random" aria-hidden="true"></span> Mix RC Configurations </a></li>
28 28 <li><a href="{% url 'url_add_dev_conf' experiment.id %}"><span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span> Add Configuration</a></li>
29 29 <li><a href=#><span class="glyphicon glyphicon-check" aria-hidden="true"></span> Verify Parameters</a></li>
30 30
31 31 </ul>
32 32 </span> -->
33 33 {% endblock %}
34 34
35 35 <table class="table table-bordered">
36 36 {% for key in experiment_keys %}
37 37 <tr><th>{{key|title}}</th><td>{{experiment|attr:key}}</td></tr>
38 38 {% endfor %}
39 39 </table>
40 40
41 <div class="">
42 <h4 class="panel-title"><b> Parameters </b></h4>
43 <br>
44 </div>
45 41
46 <table class="table table-bordered">
47 42 {% for configuration in configurations %}
43
48 44 {% if configuration.device.device_type.name == 'dds' %}
49 <!--<h4 class="panel-title"> </h4>-->
50 <tr><th>dds</th><td>(=</td></tr>
45 <div class="">
46 <h4 class="panel-title"><b> DDS </b></h4>
47 <br>
48 </div>
49
50 <table class="table table-bordered">
51 <!--<h4 class="panel-title"> </h4>-->
52 <tr><th>dds</th><td>(=</td></tr>
53 </table>
51 54 {% endif %}
52 55
53 56 {% if configuration.device.device_type.name == 'rc' %}
54 <!--<h4 class="panel-title"> </h4>-->
55 <tr><th>IPP(km)</th><td>{{experiment_data.configurations.rc.ipp}}</td></tr>
56 <tr><th>NTX</th><td>{{experiment_data.configurations.rc.ntx}}</td></tr>
57 <tr><th>TX</th><td>{{tx}}</td></tr>
58 <tr><th>Code</th><td>{{code}}</td></tr>
59 <tr><th>Sampling Window</th><td>{{window|linebreaks}}</td></tr>
60 {% endif %}
57 <div class="">
58 <h4 class="panel-title"><b> CR </b></h4>
59 <br>
60 </div>
61 61
62 {% if configuration.device.device_type.name == 'rc_mix' %}
63 <!--<h4 class="panel-title"> </h4>-->
64 <tr><th>rc_mix</th><td>(=</td></tr>
62 <table class="table table-bordered">
63 <!--<h4 class="panel-title"> </h4>-->
64 <tr><th>IPP(km)</th><td>{{experiment_data.configurations.rc.ipp}}</td></tr>
65 <tr><th>NTX</th><td>{{experiment_data.configurations.rc.ntx}}</td></tr>
66 <tr><th>TX</th><td>{{tx}}</td></tr>
67 <tr><th>Code</th><td>{{code}}</td></tr>
68 <tr><th>Sampling Window</th><td>{{window|linebreaks}}</td></tr>
69 </table>
65 70 {% endif %}
66 71
67 72 {% if configuration.device.device_type.name == 'jars' %}
68 <!--<h4 class="panel-title"> JARS </h4>-->
69 <tr><th>Data Type</th><td>{{exp_type}}</td></tr>
70 <tr><th># Channels</th><td>{{configuration.channels_number}}</td></tr>
71 <tr><th>Coh Int</th><td>{{configuration.cohe_integr}}</td></tr>
72 <tr><th>FFT Points</th><td>{{configuration.fftpoints}}</td></tr>
73 {% if exp_type == 'PDATA'%}
74 <tr><th>Inc Int</th><td>{{configuration.incohe_integr}}</td></tr>
75 <tr><th>Spec. Comb.</th><td>{{configuration.spectral}}</td></tr>
76 {% endif %}
77 <tr><th>Acq Prof</th><td>{{configuration.acq_profiles}}</td></tr>
78 <tr><th>Prof x Block</th><td>{{configuration.profiles_block}}</td></tr>
79 <tr><th>Block x File</th><td>(=</td></tr>
80 {% endif %}
81
82 {% if configuration.device.device_type.name == 'usrp' %}
83 <!--<h4 class="panel-title"> </h4>-->
84 <tr><th>usrp</th><td>(=</td></tr>
85 {% endif %}
86
87 {% if configuration.device.device_type.name == 'cgs' %}
88 <!--<h4 class="panel-title"> CGS </h4>-->
89 <!--<tr><th>Frequency 0</th><td>{{configuration.freq0}}</td></tr>-->
90 <!--<tr><th>Frequency 1</th><td>{{configuration.freq1}}</td></tr>-->
91 <!--<tr><th>Frequency 2</th><td>{{configuration.freq2}}</td></tr>-->
92 <!--<tr><th>Frequency 3</th><td>{{configuration.freq3}}</td></tr>-->
93 {% endif %}
73 <div class="">
74 <h4 class="panel-title"><b> JARS </b></h4>
75 <br>
76 </div>
94 77
95 {% if configuration.device.device_type.name == 'abs' %}
96 <!--<h4 class="panel-title"> </h4>-->
97 <tr><th>abs</th><td>(=</td></tr>
78 <table class="table table-bordered">
79 <!--<h4 class="panel-title"> JARS </h4>-->
80 <tr><th>Data Type</th><td>{{exp_type}}</td></tr>
81 <tr><th># Channels</th><td>{{configuration.channels_number}}</td></tr>
82 <tr><th>Coh Int</th><td>{{configuration.cohe_integr}}</td></tr>
83 <tr><th>FFT Points</th><td>{{configuration.fftpoints}}</td></tr>
84 {% if exp_type == 'PDATA'%}
85 <tr><th>Inc Int</th><td>{{configuration.incohe_integr}}</td></tr>
86 <tr><th>Spec. Comb.</th><td>{{configuration.spectral}}</td></tr>
87 {% endif %}
88 <tr><th>Acq Prof</th><td>{{configuration.acq_profiles}}</td></tr>
89 <tr><th>Prof x Block</th><td>{{configuration.profiles_block}}</td></tr>
90 <tr><th>Block x File</th><td>{{ configuration.raw_data_blocks }}</td></tr>
91 </table>
98 92 {% endif %}
93
99 94 {% endfor %}
95
96
97 <div class="">
98 <h4 class="panel-title"><b> Extra Parameters </b></h4>
99 <br>
100 </div>
101
102 <table class="table table-bordered">
103 {% if jars_conf %}
104 <tr><th>Rate (MB/h)</th><td>{{ rate }}</td></tr>
105 {% endif %}
106 {% if dds_conf %}
107 <tr><th>Vmax (m/s)</th><td>{{ rate }}</td></tr>
108 {% endif %}
100 109 </table>
101 110
111
102 112 <div class="pull-right">
103 113 <button type="button" class="btn btn-primary" id="bt_back">Back</button>
104 114 <button type="button" class="btn btn-primary" id="bt_verify">Verify Parameters</button>
105 115 </div>
106 116
107 117 {% endblock %}
108 118
109 119 {% block sidebar%}
110 120 {% include "sidebar_devices.html" %}
111 121 {% endblock %}
112 122
113 123 {% block extra-js%}
114 124 <script type="text/javascript">
115 125
116 126 $(".clickable-row").click(function() {
117 127 document.location = $(this).data("href");
118 128 });
119 129
120 130 $("#bt_back").click(function() {
121 131 document.location = "{% url 'url_experiment' experiment.id%}";
122 132 });
123 133
134 $("#bt_verify").click(function() {
135 document.location = "{% url 'url_verify_experiment' experiment.id%}";
136 });
137
124 138 </script>
125 139 {% endblock %} No newline at end of file
@@ -1,58 +1,59
1 1 from django.conf.urls import url
2 2
3 3 urlpatterns = (
4 4 url(r'^location/new/$', 'apps.main.views.location_new', name='url_add_location'),
5 5 url(r'^location/$', 'apps.main.views.locations', name='url_locations'),
6 6 url(r'^location/(?P<id_loc>-?\d+)/$', 'apps.main.views.location', name='url_location'),
7 7 url(r'^location/(?P<id_loc>-?\d+)/edit/$', 'apps.main.views.location_edit', name='url_edit_location'),
8 8 url(r'^location/(?P<id_loc>-?\d+)/delete/$', 'apps.main.views.location_delete', name='url_delete_location'),
9 9
10 10 url(r'^device/new/$', 'apps.main.views.device_new', name='url_add_device'),
11 11 url(r'^device/$', 'apps.main.views.devices', name='url_devices'),
12 12 url(r'^device/(?P<id_dev>-?\d+)/$', 'apps.main.views.device', name='url_device'),
13 13 url(r'^device/(?P<id_dev>-?\d+)/edit/$', 'apps.main.views.device_edit', name='url_edit_device'),
14 14 url(r'^device/(?P<id_dev>-?\d+)/delete/$', 'apps.main.views.device_delete', name='url_delete_device'),
15 15
16 16 url(r'^campaign/new/$', 'apps.main.views.campaign_new', name='url_add_campaign'),
17 17 url(r'^campaign/$', 'apps.main.views.campaigns', name='url_campaigns'),
18 18 url(r'^campaign/(?P<id_camp>-?\d+)/$', 'apps.main.views.campaign', name='url_campaign'),
19 19 url(r'^campaign/(?P<id_camp>-?\d+)/edit/$', 'apps.main.views.campaign_edit', name='url_edit_campaign'),
20 20 url(r'^campaign/(?P<id_camp>-?\d+)/delete/$', 'apps.main.views.campaign_delete', name='url_delete_campaign'),
21 21 url(r'^campaign/(?P<id_camp>-?\d+)/export/$', 'apps.main.views.campaign_export', name='url_export_campaign'),
22 22 url(r'^campaign/(?P<id_camp>-?\d+)/import/$', 'apps.main.views.campaign_import', name='url_import_campaign'),
23 23
24 24 url(r'^experiment/new/$', 'apps.main.views.experiment_new', name='url_add_experiment'),
25 25 url(r'^experiment/$', 'apps.main.views.experiments', name='url_experiments'),
26 26 url(r'^experiment/(?P<id_exp>-?\d+)/$', 'apps.main.views.experiment', name='url_experiment'),
27 27 url(r'^experiment/(?P<id_exp>-?\d+)/edit/$', 'apps.main.views.experiment_edit', name='url_edit_experiment'),
28 28 url(r'^experiment/(?P<id_exp>-?\d+)/delete/$', 'apps.main.views.experiment_delete', name='url_delete_experiment'),
29 29 url(r'^experiment/(?P<id_exp>-?\d+)/export/$', 'apps.main.views.experiment_export', name='url_export_experiment'),
30 30 url(r'^experiment/(?P<id_exp>-?\d+)/import/$', 'apps.main.views.experiment_import', name='url_import_experiment'),
31 31 url(r'^experiment/(?P<id_exp>-?\d+)/mix/$', 'apps.main.views.experiment_mix', name='url_mix_experiment'),
32 32 url(r'^experiment/(?P<id_exp>-?\d+)/mix/delete/$', 'apps.main.views.experiment_mix_delete', name='url_delete_mix_experiment'),
33 33 url(r'^experiment/(?P<id_exp>-?\d+)/summary/$', 'apps.main.views.experiment_summary', name='url_sum_experiment'),
34 url(r'^experiment/(?P<id_exp>-?\d+)/verify/$', 'apps.main.views.experiment_verify', name='url_verify_experiment'),
34 35
35 36 url(r'^experiment/(?P<id_exp>-?\d+)/new_dev_conf/$', 'apps.main.views.dev_conf_new', name='url_add_dev_conf'),
36 37 url(r'^experiment/(?P<id_exp>-?\d+)/new_dev_conf/(?P<id_dev>-?\d+)/$', 'apps.main.views.dev_conf_new', name='url_add_dev_conf'),
37 38 url(r'^dev_conf/$', 'apps.main.views.dev_confs', name='url_dev_confs'),
38 39 url(r'^dev_conf/(?P<id_conf>-?\d+)/$', 'apps.main.views.dev_conf', name='url_dev_conf'),
39 40 url(r'^dev_conf/(?P<id_conf>-?\d+)/edit/$', 'apps.main.views.dev_conf_edit', name='url_edit_dev_conf'),
40 41 url(r'^dev_conf/(?P<id_conf>-?\d+)/delete/$', 'apps.main.views.dev_conf_delete', name='url_delete_dev_conf'),
41 42
42 43 url(r'^dev_conf/(?P<id_conf>-?\d+)/write/$', 'apps.main.views.dev_conf_write', name='url_write_dev_conf'),
43 44 url(r'^dev_conf/(?P<id_conf>-?\d+)/read/$', 'apps.main.views.dev_conf_read', name='url_read_dev_conf'),
44 45 url(r'^dev_conf/(?P<id_conf>-?\d+)/import/$', 'apps.main.views.dev_conf_import', name='url_import_dev_conf'),
45 46 url(r'^dev_conf/(?P<id_conf>-?\d+)/export/$', 'apps.main.views.dev_conf_export', name='url_export_dev_conf'),
46 47 url(r'^dev_conf/(?P<id_conf>-?\d+)/start/$', 'apps.main.views.dev_conf_start', name='url_start_dev_conf'),
47 48 url(r'^dev_conf/(?P<id_conf>-?\d+)/stop/$', 'apps.main.views.dev_conf_stop', name='url_stop_dev_conf'),
48 49 url(r'^dev_conf/(?P<id_conf>-?\d+)/status/$', 'apps.main.views.dev_conf_status', name='url_status_dev_conf'),
49 50
50 51 url(r'^operation/$', 'apps.main.views.operation', name='url_operation'),
51 52 url(r'^operation/(?P<id_camp>-?\d+)/$', 'apps.main.views.operation', name='url_operation'),
52 53 url(r'^operation/search/$', 'apps.main.views.operation_search', name='url_operation_search'),
53 54 url(r'^operation/search/(?P<id_camp>-?\d+)/$', 'apps.main.views.operation_search', name='url_operation_search'),
54 55 url(r'^operation/(?P<id_camp>-?\d+)/radar/(?P<id_radar>-?\d+)/play/$', 'apps.main.views.radar_play', name='url_radar_play'),
55 56 url(r'^operation/(?P<id_camp>-?\d+)/radar/(?P<id_radar>-?\d+)/stop/$', 'apps.main.views.radar_stop', name='url_radar_stop'),
56 57 url(r'^operation/(?P<id_camp>-?\d+)/radar/(?P<id_radar>-?\d+)/refresh/$', 'apps.main.views.radar_refresh', name='url_radar_refresh'),
57 58
58 59 )
@@ -1,1487 +1,1629
1 1 from django.shortcuts import render, redirect, get_object_or_404, HttpResponse
2 2 from django.utils.safestring import mark_safe
3 3 from django.http import HttpResponseRedirect
4 4 from django.core.urlresolvers import reverse
5 5 from django.db.models import Q
6 6 from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
7 7 from django.contrib import messages
8 8 from datetime import datetime
9 9 import urllib
10 10
11 11 from .forms import CampaignForm, ExperimentForm, DeviceForm, ConfigurationForm, LocationForm, UploadFileForm, DownloadFileForm, OperationForm, NewForm
12 12 from .forms import OperationSearchForm, FilterForm
13 13 from apps.cgs.forms import CGSConfigurationForm
14 14 from apps.jars.forms import JARSConfigurationForm
15 15 from apps.usrp.forms import USRPConfigurationForm
16 16 from apps.abs.forms import ABSConfigurationForm
17 17 from apps.rc.forms import RCConfigurationForm, RCMixConfigurationForm
18 18 from apps.dds.forms import DDSConfigurationForm
19 19
20 20 from .models import Campaign, Experiment, Device, Configuration, Location, RunningExperiment
21 21 from apps.cgs.models import CGSConfiguration
22 22 from apps.jars.models import JARSConfiguration, EXPERIMENT_TYPE
23 23 from apps.usrp.models import USRPConfiguration
24 24 from apps.abs.models import ABSConfiguration
25 25 from apps.rc.models import RCConfiguration, RCLine, RCLineType
26 26 from apps.dds.models import DDSConfiguration
27 27 from django.http.request import QueryDict
28 #from __builtin__ import False
28 29
29 30 # Create your views here.
30 31
31 32 CONF_FORMS = {
32 33 'rc': RCConfigurationForm,
33 34 'dds': DDSConfigurationForm,
34 35 'jars': JARSConfigurationForm,
35 36 'cgs': CGSConfigurationForm,
36 37 'abs': ABSConfigurationForm,
37 38 'usrp': USRPConfigurationForm,
38 39 }
39 40
40 41 CONF_MODELS = {
41 42 'rc': RCConfiguration,
42 43 'dds': DDSConfiguration,
43 44 'jars': JARSConfiguration,
44 45 'cgs': CGSConfiguration,
45 46 'abs': ABSConfiguration,
46 47 'usrp': USRPConfiguration,
47 48 }
48 49
49 50 MIX_MODES = {
50 51 '0': 'P',
51 52 '1': 'S',
52 53 }
53 54
54 55 MIX_OPERATIONS = {
55 56 '0': 'OR',
56 57 '1': 'XOR',
57 58 '2': 'AND',
58 59 '3': 'NAND',
59 60 }
60 61
61 62
62 63 def index(request):
63 64 kwargs = {}
64 65
65 66 return render(request, 'index.html', kwargs)
66 67
67 68
68 69 def locations(request):
69 70
70 71 page = request.GET.get('page')
71 72 order = ('name',)
72 73
73 74 kwargs = get_paginator(Location, page, order)
74 75
75 76 kwargs['keys'] = ['name', 'description']
76 77 kwargs['title'] = 'Radar System'
77 78 kwargs['suptitle'] = 'List'
78 79
79 80 return render(request, 'base_list.html', kwargs)
80 81
81 82
82 83 def location(request, id_loc):
83 84
84 85 location = get_object_or_404(Location, pk=id_loc)
85 86
86 87 kwargs = {}
87 88 kwargs['location'] = location
88 89 kwargs['location_keys'] = ['name', 'description']
89 90
90 91 kwargs['title'] = 'Location'
91 92 kwargs['suptitle'] = 'Details'
92 93
93 94 return render(request, 'location.html', kwargs)
94 95
95 96
96 97 def location_new(request):
97 98
98 99 if request.method == 'GET':
99 100 form = LocationForm()
100 101
101 102 if request.method == 'POST':
102 103 form = LocationForm(request.POST)
103 104
104 105 if form.is_valid():
105 106 form.save()
106 107 return redirect('url_locations')
107 108
108 109 kwargs = {}
109 110 kwargs['form'] = form
110 111 kwargs['title'] = 'Radar System'
111 112 kwargs['suptitle'] = 'New'
112 113 kwargs['button'] = 'Create'
113 114
114 115 return render(request, 'base_edit.html', kwargs)
115 116
116 117
117 118 def location_edit(request, id_loc):
118 119
119 120 location = get_object_or_404(Location, pk=id_loc)
120 121
121 122 if request.method=='GET':
122 123 form = LocationForm(instance=location)
123 124
124 125 if request.method=='POST':
125 126 form = LocationForm(request.POST, instance=location)
126 127
127 128 if form.is_valid():
128 129 form.save()
129 130 return redirect('url_locations')
130 131
131 132 kwargs = {}
132 133 kwargs['form'] = form
133 134 kwargs['title'] = 'Location'
134 135 kwargs['suptitle'] = 'Edit'
135 136 kwargs['button'] = 'Update'
136 137
137 138 return render(request, 'base_edit.html', kwargs)
138 139
139 140
140 141 def location_delete(request, id_loc):
141 142
142 143 location = get_object_or_404(Location, pk=id_loc)
143 144
144 145 if request.method=='POST':
145 146
146 147 if request.user.is_staff:
147 148 location.delete()
148 149 return redirect('url_locations')
149 150
150 151 messages.error(request, 'Not enough permission to delete this object')
151 152 return redirect(location.get_absolute_url())
152 153
153 154 kwargs = {
154 155 'title': 'Delete',
155 156 'suptitle': 'Location',
156 157 'object': location,
157 158 'previous': location.get_absolute_url(),
158 159 'delete': True
159 160 }
160 161
161 162 return render(request, 'confirm.html', kwargs)
162 163
163 164
164 165 def devices(request):
165 166
166 167 page = request.GET.get('page')
167 168 order = ('device_type', 'name')
168 169
169 170 kwargs = get_paginator(Device, page, order)
170 171 kwargs['keys'] = ['name', 'ip_address', 'port_address', 'device_type']
171 172 kwargs['title'] = 'Device'
172 173 kwargs['suptitle'] = 'List'
173 174
174 175 return render(request, 'base_list.html', kwargs)
175 176
176 177
177 178 def device(request, id_dev):
178 179
179 180 device = get_object_or_404(Device, pk=id_dev)
180 181
181 182 kwargs = {}
182 183 kwargs['device'] = device
183 184 kwargs['device_keys'] = ['device_type', 'name', 'ip_address', 'port_address', 'description']
184 185
185 186 kwargs['title'] = 'Device'
186 187 kwargs['suptitle'] = 'Details'
187 188
188 189 return render(request, 'device.html', kwargs)
189 190
190 191
191 192 def device_new(request):
192 193
193 194 if request.method == 'GET':
194 195 form = DeviceForm()
195 196
196 197 if request.method == 'POST':
197 198 form = DeviceForm(request.POST)
198 199
199 200 if form.is_valid():
200 201 form.save()
201 202 return redirect('url_devices')
202 203
203 204 kwargs = {}
204 205 kwargs['form'] = form
205 206 kwargs['title'] = 'Device'
206 207 kwargs['suptitle'] = 'New'
207 208 kwargs['button'] = 'Create'
208 209
209 210 return render(request, 'base_edit.html', kwargs)
210 211
211 212
212 213 def device_edit(request, id_dev):
213 214
214 215 device = get_object_or_404(Device, pk=id_dev)
215 216
216 217 if request.method=='GET':
217 218 form = DeviceForm(instance=device)
218 219
219 220 if request.method=='POST':
220 221 form = DeviceForm(request.POST, instance=device)
221 222
222 223 if form.is_valid():
223 224 form.save()
224 225 return redirect(device.get_absolute_url())
225 226
226 227 kwargs = {}
227 228 kwargs['form'] = form
228 229 kwargs['title'] = 'Device'
229 230 kwargs['suptitle'] = 'Edit'
230 231 kwargs['button'] = 'Update'
231 232
232 233 return render(request, 'base_edit.html', kwargs)
233 234
234 235
235 236 def device_delete(request, id_dev):
236 237
237 238 device = get_object_or_404(Device, pk=id_dev)
238 239
239 240 if request.method=='POST':
240 241
241 242 if request.user.is_staff:
242 243 device.delete()
243 244 return redirect('url_devices')
244 245
245 246 messages.error(request, 'Not enough permission to delete this object')
246 247 return redirect(device.get_absolute_url())
247 248
248 249 kwargs = {
249 250 'title': 'Delete',
250 251 'suptitle': 'Device',
251 252 'object': device,
252 253 'previous': device.get_absolute_url(),
253 254 'delete': True
254 255 }
255 256
256 257 return render(request, 'confirm.html', kwargs)
257 258
258 259
259 260 def campaigns(request):
260 261
261 262 page = request.GET.get('page')
262 263 order = ('start_date',)
263 264 filters = request.GET.copy()
264 265
265 266 kwargs = get_paginator(Campaign, page, order, filters)
266 267
267 268 form = FilterForm(initial=request.GET, extra_fields=['range_date', 'tags','template'])
268 269 kwargs['keys'] = ['name', 'start_date', 'end_date']
269 270 kwargs['title'] = 'Campaign'
270 271 kwargs['suptitle'] = 'List'
271 272 kwargs['form'] = form
272 273 filters.pop('page', None)
273 274 kwargs['q'] = urllib.urlencode(filters)
274 275
275 276 return render(request, 'base_list.html', kwargs)
276 277
277 278
278 279 def campaign(request, id_camp):
279 280
280 281 campaign = get_object_or_404(Campaign, pk=id_camp)
281 282 experiments = Experiment.objects.filter(campaign=campaign)
282 283
283 284 form = CampaignForm(instance=campaign)
284 285
285 286 kwargs = {}
286 287 kwargs['campaign'] = campaign
287 288 kwargs['campaign_keys'] = ['template', 'name', 'start_date', 'end_date', 'tags', 'description']
288 289
289 290 kwargs['experiments'] = experiments
290 291 kwargs['experiment_keys'] = ['name', 'radar_system', 'start_time', 'end_time']
291 292
292 293 kwargs['title'] = 'Campaign'
293 294 kwargs['suptitle'] = 'Details'
294 295
295 296 kwargs['form'] = form
296 297 kwargs['button'] = 'Add Experiment'
297 298
298 299 return render(request, 'campaign.html', kwargs)
299 300
300 301
301 302 def campaign_new(request):
302 303
303 304 kwargs = {}
304 305
305 306 if request.method == 'GET':
306 307
307 308 if 'template' in request.GET:
308 309 if request.GET['template']=='0':
309 310 form = NewForm(initial={'create_from':2},
310 311 template_choices=Campaign.objects.filter(template=True).values_list('id', 'name'))
311 312 else:
312 313 kwargs['button'] = 'Create'
313 314 kwargs['experiments'] = Configuration.objects.filter(experiment=request.GET['template'])
314 315 kwargs['experiment_keys'] = ['name', 'start_time', 'end_time']
315 316 camp = Campaign.objects.get(pk=request.GET['template'])
316 317 form = CampaignForm(instance=camp,
317 318 initial={'name':'{} [{:%Y/%m/%d}]'.format(camp.name, datetime.now()),
318 319 'template':False})
319 320 elif 'blank' in request.GET:
320 321 kwargs['button'] = 'Create'
321 322 form = CampaignForm()
322 323 else:
323 324 form = NewForm()
324 325
325 326 if request.method == 'POST':
326 327 kwargs['button'] = 'Create'
327 328 post = request.POST.copy()
328 329 experiments = []
329 330
330 331 for id_exp in post.getlist('experiments'):
331 332 exp = Experiment.objects.get(pk=id_exp)
332 333 new_exp = exp.clone(template=False)
333 334 experiments.append(new_exp)
334 335
335 336 post.setlist('experiments', [])
336 337
337 338 form = CampaignForm(post)
338 339
339 340 if form.is_valid():
340 341 campaign = form.save()
341 342 for exp in experiments:
342 343 campaign.experiments.add(exp)
343 344 campaign.save()
344 345 return redirect('url_campaign', id_camp=campaign.id)
345 346
346 347 kwargs['form'] = form
347 348 kwargs['title'] = 'Campaign'
348 349 kwargs['suptitle'] = 'New'
349 350
350 351 return render(request, 'campaign_edit.html', kwargs)
351 352
352 353
353 354 def campaign_edit(request, id_camp):
354 355
355 356 campaign = get_object_or_404(Campaign, pk=id_camp)
356 357
357 358 if request.method=='GET':
358 359 form = CampaignForm(instance=campaign)
359 360
360 361 if request.method=='POST':
361 362 exps = campaign.experiments.all().values_list('pk', flat=True)
362 363 post = request.POST.copy()
363 364 new_exps = post.getlist('experiments')
364 365 post.setlist('experiments', [])
365 366 form = CampaignForm(post, instance=campaign)
366 367
367 368 if form.is_valid():
368 369 camp = form.save()
369 370 for id_exp in new_exps:
370 371 if int(id_exp) in exps:
371 372 exps.pop(id_exp)
372 373 else:
373 374 exp = Experiment.objects.get(pk=id_exp)
374 375 if exp.template:
375 376 camp.experiments.add(exp.clone(template=False))
376 377 else:
377 378 camp.experiments.add(exp)
378 379
379 380 for id_exp in exps:
380 381 camp.experiments.remove(Experiment.objects.get(pk=id_exp))
381 382
382 383 return redirect('url_campaign', id_camp=id_camp)
383 384
384 385 kwargs = {}
385 386 kwargs['form'] = form
386 387 kwargs['title'] = 'Campaign'
387 388 kwargs['suptitle'] = 'Edit'
388 389 kwargs['button'] = 'Update'
389 390
390 391 return render(request, 'campaign_edit.html', kwargs)
391 392
392 393
393 394 def campaign_delete(request, id_camp):
394 395
395 396 campaign = get_object_or_404(Campaign, pk=id_camp)
396 397
397 398 if request.method=='POST':
398 399 if request.user.is_staff:
399 400
400 401 for exp in campaign.experiments.all():
401 402 for conf in Configuration.objects.filter(experiment=exp):
402 403 conf.delete()
403 404 exp.delete()
404 405 campaign.delete()
405 406
406 407 return redirect('url_campaigns')
407 408
408 409 messages.error(request, 'Not enough permission to delete this object')
409 410 return redirect(campaign.get_absolute_url())
410 411
411 412 kwargs = {
412 413 'title': 'Delete',
413 414 'suptitle': 'Campaign',
414 415 'object': campaign,
415 416 'previous': campaign.get_absolute_url(),
416 417 'delete': True
417 418 }
418 419
419 420 return render(request, 'confirm.html', kwargs)
420 421
421 422 def campaign_export(request, id_camp):
422 423
423 424 campaign = get_object_or_404(Campaign, pk=id_camp)
424 425 content = campaign.parms_to_dict()
425 426 content_type = 'application/json'
426 427 filename = '%s_%s.json' %(campaign.name, campaign.id)
427 428
428 429 response = HttpResponse(content_type=content_type)
429 430 response['Content-Disposition'] = 'attachment; filename="%s"' %filename
430 431 response.write(content)
431 432
432 433 return response
433 434
434 435
435 436 def campaign_import(request, id_camp):
436 437
437 438 campaign = get_object_or_404(Campaign, pk=id_camp)
438 439
439 440 if request.method == 'GET':
440 441 file_form = UploadFileForm()
441 442
442 443 if request.method == 'POST':
443 444 file_form = UploadFileForm(request.POST, request.FILES)
444 445
445 446 if file_form.is_valid():
446 447
447 448 parms = campaign.import_from_file(request.FILES['file'])
448 449
449 450 if parms:
450 451 parms['name'] = parms['campaign']
451 452
452 453 new_camp = campaign.dict_to_parms(parms, CONF_MODELS)
453 454
454 455 messages.success(request, "Parameters imported from: '%s'." %request.FILES['file'].name)
455 456
456 457 return redirect(new_camp.get_absolute_url_edit())
457 458
458 459 messages.error(request, "Could not import parameters from file")
459 460
460 461 kwargs = {}
461 462 kwargs['title'] = 'Campaign'
462 463 kwargs['form'] = file_form
463 464 kwargs['suptitle'] = 'Importing file'
464 465 kwargs['button'] = 'Import'
465 466
466 467 return render(request, 'campaign_import.html', kwargs)
467 468
468 469
469 470 def experiments(request):
470 471
471 472 page = request.GET.get('page')
472 473 order = ('location',)
473 474 filters = request.GET.copy()
474 475
475 476 kwargs = get_paginator(Experiment, page, order, filters)
476 477
477 478 form = FilterForm(initial=request.GET, extra_fields=['tags','template'])
478 479
479 480 kwargs['keys'] = ['name', 'radar_system', 'start_time', 'end_time']
480 481 kwargs['title'] = 'Experiment'
481 482 kwargs['suptitle'] = 'List'
482 483 kwargs['form'] = form
483 484 filters.pop('page', None)
484 485 kwargs['q'] = urllib.urlencode(filters)
485 486
486 487 return render(request, 'base_list.html', kwargs)
487 488
488 489
489 490 def experiment(request, id_exp):
490 491
491 492 experiment = get_object_or_404(Experiment, pk=id_exp)
492 493
493 494 configurations = Configuration.objects.filter(experiment=experiment, type=0)
494 495
495 496 kwargs = {}
496 497
497 498 kwargs['experiment_keys'] = ['template', 'radar_system', 'name', 'start_time', 'end_time']
498 499 kwargs['experiment'] = experiment
499 500
500 501 kwargs['configuration_keys'] = ['name', 'device__ip_address', 'device__port_address', 'device__status']
501 502 kwargs['configurations'] = configurations
502 503
503 504 kwargs['title'] = 'Experiment'
504 505 kwargs['suptitle'] = 'Details'
505 506
506 507 kwargs['button'] = 'Add Configuration'
507 508
508 509 ###### SIDEBAR ######
509 510 kwargs.update(sidebar(experiment=experiment))
510 511
511 512 return render(request, 'experiment.html', kwargs)
512 513
513 514
514 515 def experiment_new(request, id_camp=None):
515 516
516 517 kwargs = {}
517 518
518 519 if request.method == 'GET':
519 520 if 'template' in request.GET:
520 521 if request.GET['template']=='0':
521 522 form = NewForm(initial={'create_from':2},
522 523 template_choices=Experiment.objects.filter(template=True).values_list('id', 'name'))
523 524 else:
524 525 kwargs['button'] = 'Create'
525 526 kwargs['configurations'] = Configuration.objects.filter(experiment=request.GET['template'])
526 527 kwargs['configuration_keys'] = ['name', 'device__name', 'device__ip_address', 'device__port_address']
527 528 exp=Experiment.objects.get(pk=request.GET['template'])
528 529 form = ExperimentForm(instance=exp,
529 530 initial={'name': '{} [{:%Y/%m/%d}]'.format(exp.name, datetime.now()),
530 531 'template': False})
531 532 elif 'blank' in request.GET:
532 533 kwargs['button'] = 'Create'
533 534 form = ExperimentForm()
534 535 else:
535 536 form = NewForm()
536 537
537 538 if request.method == 'POST':
538 539 form = ExperimentForm(request.POST)
539 540 print form.data
540 541 if form.is_valid():
541 542 experiment = form.save()
542 543
543 544 if 'template' in request.GET:
544 545 configurations = Configuration.objects.filter(experiment=request.GET['template'], type=0)
545 546 for conf in configurations:
546 547 conf.clone(experiment=experiment, template=False)
547 548
548 549 return redirect('url_experiment', id_exp=experiment.id)
549 550
550 551 kwargs['form'] = form
551 552 kwargs['title'] = 'Experiment'
552 553 kwargs['suptitle'] = 'New'
553 554
554 555 return render(request, 'experiment_edit.html', kwargs)
555 556
556 557
557 558 def experiment_edit(request, id_exp):
558 559
559 560 experiment = get_object_or_404(Experiment, pk=id_exp)
560 561
561 562 if request.method == 'GET':
562 563 form = ExperimentForm(instance=experiment)
563 564
564 565 if request.method=='POST':
565 566 form = ExperimentForm(request.POST, instance=experiment)
566 567
567 568 if form.is_valid():
568 569 experiment = form.save()
569 570 return redirect('url_experiment', id_exp=experiment.id)
570 571
571 572 kwargs = {}
572 573 kwargs['form'] = form
573 574 kwargs['title'] = 'Experiment'
574 575 kwargs['suptitle'] = 'Edit'
575 576 kwargs['button'] = 'Update'
576 577
577 578 return render(request, 'experiment_edit.html', kwargs)
578 579
579 580
580 581 def experiment_delete(request, id_exp):
581 582
582 583 experiment = get_object_or_404(Experiment, pk=id_exp)
583 584
584 585 if request.method=='POST':
585 586 if request.user.is_staff:
586 587 for conf in Configuration.objects.filter(experiment=experiment):
587 588 conf.delete()
588 589 experiment.delete()
589 590 return redirect('url_experiments')
590 591
591 592 messages.error(request, 'Not enough permission to delete this object')
592 593 return redirect(experiment.get_absolute_url())
593 594
594 595 kwargs = {
595 596 'title': 'Delete',
596 597 'suptitle': 'Experiment',
597 598 'object': experiment,
598 599 'previous': experiment.get_absolute_url(),
599 600 'delete': True
600 601 }
601 602
602 603 return render(request, 'confirm.html', kwargs)
603 604
604 605
605 606 def experiment_export(request, id_exp):
606 607
607 608 experiment = get_object_or_404(Experiment, pk=id_exp)
608 609 content = experiment.parms_to_dict()
609 610 content_type = 'application/json'
610 611 filename = '%s_%s.json' %(experiment.name, experiment.id)
611 612
612 613 response = HttpResponse(content_type=content_type)
613 614 response['Content-Disposition'] = 'attachment; filename="%s"' %filename
614 615 response.write(content)
615 616
616 617 return response
617 618
618 619 def experiment_import(request, id_exp):
619 620
620 621 experiment = get_object_or_404(Experiment, pk=id_exp)
621 622 configurations = Configuration.objects.filter(experiment=experiment)
622 623
623 624 if request.method == 'GET':
624 625 file_form = UploadFileForm()
625 626
626 627 if request.method == 'POST':
627 628 file_form = UploadFileForm(request.POST, request.FILES)
628 629
629 630 if file_form.is_valid():
630 631
631 632 parms = experiment.import_from_file(request.FILES['file'])
632 633
633 634 if parms:
634 635
635 636 new_exp = experiment.dict_to_parms(parms, CONF_MODELS)
636 637
637 638 messages.success(request, "Parameters imported from: '%s'." %request.FILES['file'].name)
638 639
639 640 return redirect(new_exp.get_absolute_url_edit())
640 641
641 642 messages.error(request, "Could not import parameters from file")
642 643
643 644 kwargs = {}
644 645 kwargs['title'] = 'Experiment'
645 646 kwargs['form'] = file_form
646 647 kwargs['suptitle'] = 'Importing file'
647 648 kwargs['button'] = 'Import'
648 649
649 650 kwargs.update(sidebar(experiment=experiment))
650 651
651 652 return render(request, 'experiment_import.html', kwargs)
652 653
653 654 def experiment_mix(request, id_exp):
654 655
655 656 experiment = get_object_or_404(Experiment, pk=id_exp)
656 657 rc_confs = [conf for conf in RCConfiguration.objects.filter(experiment=id_exp,
657 658 mix=False)]
658 659
659 660 if len(rc_confs)<2:
660 661 messages.warning(request, 'You need at least two RC Configurations to make a mix')
661 662 return redirect(experiment.get_absolute_url())
662 663
663 664 mix_confs = RCConfiguration.objects.filter(experiment=id_exp, mix=True)
664 665
665 666 if mix_confs:
666 667 mix = mix_confs[0]
667 668 else:
668 669 mix = RCConfiguration(experiment=experiment,
669 670 device=rc_confs[0].device,
670 671 ipp=rc_confs[0].ipp,
671 672 clock_in=rc_confs[0].clock_in,
672 673 clock_divider=rc_confs[0].clock_divider,
673 674 mix=True,
674 675 parameters='')
675 676 mix.save()
676 677
677 678 line_type = RCLineType.objects.get(name='mix')
678 679 for i in range(len(rc_confs[0].get_lines())):
679 680 line = RCLine(rc_configuration=mix, line_type=line_type, channel=i)
680 681 line.save()
681 682
682 683 initial = {'name': mix.name,
683 684 'result': parse_mix_result(mix.parameters),
684 685 'delay': 0,
685 686 'mask': [0,1,2,3,4,5,6,7]
686 687 }
687 688
688 689 if request.method=='GET':
689 690 form = RCMixConfigurationForm(confs=rc_confs, initial=initial)
690 691
691 692 if request.method=='POST':
692 693 result = mix.parameters
693 694
694 695 if '{}|'.format(request.POST['experiment']) in result:
695 696 messages.error(request, 'Configuration already added')
696 697 else:
697 698 if 'operation' in request.POST:
698 699 operation = MIX_OPERATIONS[request.POST['operation']]
699 700 else:
700 701 operation = ' '
701 702
702 703 mode = MIX_MODES[request.POST['mode']]
703 704
704 705 if result:
705 706 result = '{}-{}|{}|{}|{}|{}'.format(mix.parameters,
706 707 request.POST['experiment'],
707 708 mode,
708 709 operation,
709 710 float(request.POST['delay']),
710 711 parse_mask(request.POST.getlist('mask'))
711 712 )
712 713 else:
713 714 result = '{}|{}|{}|{}|{}'.format(request.POST['experiment'],
714 715 mode,
715 716 operation,
716 717 float(request.POST['delay']),
717 718 parse_mask(request.POST.getlist('mask'))
718 719 )
719 720
720 721 mix.parameters = result
721 722 mix.name = request.POST['name']
722 723 mix.save()
723 724 mix.update_pulses()
724 725
725 726 initial['result'] = parse_mix_result(result)
726 727 initial['name'] = mix.name
727 728
728 729 form = RCMixConfigurationForm(initial=initial, confs=rc_confs)
729 730
730 731
731 732 kwargs = {
732 733 'title': 'Experiment',
733 734 'suptitle': 'Mix Configurations',
734 735 'form' : form,
735 736 'extra_button': 'Delete',
736 737 'button': 'Add',
737 738 'cancel': 'Back',
738 739 'previous': experiment.get_absolute_url(),
739 740 'id_exp':id_exp,
740 741
741 742 }
742 743
743 744 return render(request, 'experiment_mix.html', kwargs)
744 745
745 746
746 747 def experiment_mix_delete(request, id_exp):
747 748
748 749 conf = RCConfiguration.objects.get(experiment=id_exp, mix=True)
749 750 values = conf.parameters.split('-')
750 751 conf.parameters = '-'.join(values[:-1])
751 752 conf.save()
752 753
753 754 return redirect('url_mix_experiment', id_exp=id_exp)
754 755
755 756
756 757 def experiment_summary(request, id_exp):
757 758
758 759 import json
760 import ast
759 761
760 762 experiment = get_object_or_404(Experiment, pk=id_exp)
761 763 experiment_data = json.loads(experiment.parms_to_dict())
762 764 configurations = Configuration.objects.filter(experiment=experiment, type=0)
763 765
764 766 kwargs = {}
765 767
766 768 kwargs['experiment_keys'] = ['template', 'radar_system', 'name', 'start_time', 'end_time']
767 769 kwargs['experiment'] = experiment
768 770
769 771 kwargs['configuration_keys'] = ['name', 'device__ip_address', 'device__port_address', 'device__status']
770 772 kwargs['configurations'] = configurations
771 773 kwargs['experiment_data'] = experiment_data
772 774
773 775 kwargs['title'] = 'Experiment Summary'
774 776 kwargs['suptitle'] = 'Details'
775 777
776 778 kwargs['button'] = 'Verify Parameters'
777 779
780 jars_conf = False
781 rc_conf = False
782
778 783 for configuration in configurations:
784 #-------------------- JARS -----------------------:
779 785 if configuration.device.device_type.name == 'jars':
780 kwargs['exp_type'] = EXPERIMENT_TYPE[configuration.exp_type][1]
781
786 jars_conf = True
787 kwargs['jars_conf'] = jars_conf
788 kwargs['exp_type'] = EXPERIMENT_TYPE[configuration.exp_type][1]
789 channels_number = configuration.channels_number
790 exp_type = configuration.exp_type
791 fftpoints = configuration.fftpoints
792 filter_parms = configuration.filter_parms
793 filter_parms = ast.literal_eval(filter_parms)
794 spectral_number = configuration.spectral_number
795
796 #--------------------- RC ----------------------:
782 797 if configuration.device.device_type.name == 'rc':
798 rc_conf = True
799 kwargs['rc_conf'] = rc_conf
783 800 rc_lines = experiment_data['configurations']['rc']['lines']
801 ipp = configuration.ipp
784 802 if experiment_data['configurations']['rc']['mix'] == 'True':
785 803 tx = ''
786 804 code = ''
787 805 window = ''
788 806 else:
789 807 code = rc_lines[3]['code']
790 808
791 809 window_data = rc_lines[6]['params'][0]
792 810 h0 = str(window_data['first_height'])
793 811 dh = str(window_data['resolution'])
794 812 nsa = str(window_data['number_of_samples'])
795 813 window = 'Ho='+h0+'km\nDH='+dh+'km\nNSA='+nsa
796 814
797 815 tx = ''
798 816 if float(rc_lines[1]['delays']) == 0:
799 817 tx = rc_lines[2]['pulse_width']
800 818 elif float(rc_lines[2]['delays']) == 0:
801 819 tx = rc_lines[1]['pulse_width']
802 820 else:
803 821 tx = rc_lines[1]['pulse_width']+' | '+rc_lines[2]['pulse_width']
804 822
805 823 kwargs['tx'] = tx
806 824 kwargs['code'] = code
807 825 kwargs['window'] = window
808
826
827 #-------------------- DDS -----------------------:
828 if configuration.device.device_type.name == 'dds':
829 dds_conf = True
830 kwargs['dds_conf'] = dds_conf
831
832 #------ RC & JARS ------:
833 ipp = 937.5 #
834 nsa = 200#
835 dh = 1.5 #
836 channels_number = 5 #
837
838 if rc_conf and jars_conf:
839 if exp_type == 0: #Short
840 bytes = 2
841 b = nsa*2*bytes*channels_number
842 else: #Float
843 bytes = 4
844 channels = channels_number + spectral_number
845 b = nsa*2*bytes*fftpoints*channels
846
847 ipps = (ipp*pow(10,-6))/0.15
848 GB = 1048576.0*1024.0
849 Hour = 3600
850 rate = b/ipps
851 rate = rate *(1/GB)*(Hour)
852 kwargs['rate'] = str(rate)+" GB/h"
853 else:
854 kwargs['rate'] = ''
855
809 856 ###### SIDEBAR ######
810 857 kwargs.update(sidebar(experiment=experiment))
811 858
812 859 return render(request, 'experiment_summary.html', kwargs)
813 860
861 def experiment_verify(request, id_exp):
862
863 import json
864 import ast
865
866 experiment = get_object_or_404(Experiment, pk=id_exp)
867 experiment_data = json.loads(experiment.parms_to_dict())
868 configurations = Configuration.objects.filter(experiment=experiment, type=0)
869
870 kwargs = {}
871
872 kwargs['experiment_keys'] = ['template', 'radar_system', 'name', 'start_time', 'end_time']
873 kwargs['experiment'] = experiment
874
875 kwargs['configuration_keys'] = ['name', 'device__ip_address', 'device__port_address', 'device__status']
876 kwargs['configurations'] = configurations
877 kwargs['experiment_data'] = experiment_data
878
879 kwargs['title'] = 'Verify Experiment'
880 kwargs['suptitle'] = 'Parameters'
881
882 kwargs['button'] = 'Update'
883
884 jars_conf = False
885 rc_conf = False
886 dds_conf = False
887
888 for configuration in configurations:
889 #-------------------- JARS -----------------------:
890 if configuration.device.device_type.name == 'jars':
891 jars_conf = True
892 kwargs['jars_conf'] = jars_conf
893 filter_parms = configuration.filter_parms
894 filter_parms = ast.literal_eval(filter_parms)
895 kwargs['filter_parms'] = filter_parms
896 #--Sampling Frequency
897 clock = filter_parms['clock']
898 filter_2 = filter_parms['filter_2']
899 filter_5 = filter_parms['filter_5']
900 filter_fir = filter_parms['filter_fir']
901 samp_freq_jars = clock/filter_2/filter_5/filter_fir
902
903 kwargs['samp_freq_jars'] = samp_freq_jars
904 kwargs['jars'] = configuration
905
906 #--------------------- RC ----------------------:
907 if configuration.device.device_type.name == 'rc':
908 rc_conf = True
909 rc_parms = configuration.parms_to_dict()
910 if rc_parms['mix'] == 'True':
911 pass
912 else:
913 rc_lines = rc_parms['lines']
914 dh = rc_lines[6]['params'][0]['resolution']
915 #--Sampling Frequency
916 samp_freq_rc = 0.15/dh
917 kwargs['samp_freq_rc'] = samp_freq_rc
918
919 kwargs['rc_conf'] = rc_conf
920 kwargs['rc'] = configuration
921
922 #-------------------- DDS ----------------------:
923 if configuration.device.device_type.name == 'dds':
924 dds_conf = True
925 dds_parms = configuration.parms_to_dict()
926
927 kwargs['dds_conf'] = dds_conf
928 kwargs['dds'] = configuration
929
930
931 #------------Validation------------:
932 #Clock
933 if dds_conf and rc_conf and jars_conf:
934 if filter_parms['clock'] != rc_parms['clock_in'] and rc_parms['clock_in'] != dds_parms['clock']:
935 messages.warning(request, "Devices don't have the same clock.")
936 elif rc_conf and jars_conf:
937 if filter_parms['clock'] != rc_parms['clock_in']:
938 messages.warning(request, "Devices don't have the same clock.")
939 elif rc_conf and dds_conf:
940 if rc_parms['clock_in'] != dds_parms['clock']:
941 messages.warning(request, "Devices don't have the same clock.")
942 if float(samp_freq_rc) != float(dds_parms['frequencyA']):
943 messages.warning(request, "Devices don't have the same Frequency A.")
944
945
946
947 ###### SIDEBAR ######
948 kwargs.update(sidebar(experiment=experiment))
949
950
951
952
953
954 return render(request, 'experiment_verify.html', kwargs)
955
814 956
815 957 def parse_mix_result(s):
816 958
817 959 values = s.split('-')
818 960 html = 'EXP MOD OPE DELAY MASK\r\n'
819 961
820 962 if not values or values[0] in ('', ' '):
821 963 return mark_safe(html)
822 964
823 965 for i, value in enumerate(values):
824 966 if not value:
825 967 continue
826 968 pk, mode, operation, delay, mask = value.split('|')
827 969 conf = RCConfiguration.objects.get(pk=pk)
828 970 if i==0:
829 971 html += '{:20.18}{:3}{:4}{:9}km{:>6}\r\n'.format(
830 972 conf.name,
831 973 mode,
832 974 ' ',
833 975 delay,
834 976 mask)
835 977 else:
836 978 html += '{:20.18}{:3}{:4}{:9}km{:>6}\r\n'.format(
837 979 conf.name,
838 980 mode,
839 981 operation,
840 982 delay,
841 983 mask)
842 984
843 985 return mark_safe(html)
844 986
845 987 def parse_mask(l):
846 988
847 989 values = []
848 990
849 991 for x in range(8):
850 992 if '{}'.format(x) in l:
851 993 values.append(1)
852 994 else:
853 995 values.append(0)
854 996
855 997 values.reverse()
856 998
857 999 return int(''.join([str(x) for x in values]), 2)
858 1000
859 1001
860 1002 def dev_confs(request):
861 1003
862 1004
863 1005 page = request.GET.get('page')
864 1006 order = ('type', 'device__device_type', 'experiment')
865 1007 filters = request.GET.copy()
866 1008
867 1009 kwargs = get_paginator(Configuration, page, order, filters)
868 1010
869 1011 form = FilterForm(initial=request.GET, extra_fields=['tags','template'])
870 1012 kwargs['keys'] = ['name', 'experiment', 'type', 'programmed_date']
871 1013 kwargs['title'] = 'Configuration'
872 1014 kwargs['suptitle'] = 'List'
873 1015 kwargs['form'] = form
874 1016 filters.pop('page', None)
875 1017 kwargs['q'] = urllib.urlencode(filters)
876 1018
877 1019 return render(request, 'base_list.html', kwargs)
878 1020
879 1021
880 1022 def dev_conf(request, id_conf):
881 1023
882 1024 conf = get_object_or_404(Configuration, pk=id_conf)
883 1025
884 1026 return redirect(conf.get_absolute_url())
885 1027
886 1028
887 1029 def dev_conf_new(request, id_exp=0, id_dev=0):
888 1030
889 1031 initial = {}
890 1032 kwargs = {}
891 1033
892 1034 if id_exp<>0:
893 1035 initial['experiment'] = id_exp
894 1036
895 1037 if id_dev<>0:
896 1038 initial['device'] = id_dev
897 1039
898 1040 if request.method == 'GET':
899 1041
900 1042 if id_dev:
901 1043 kwargs['button'] = 'Create'
902 1044 device = Device.objects.get(pk=id_dev)
903 1045 DevConfForm = CONF_FORMS[device.device_type.name]
904 1046 initial['name'] = request.GET['name']
905 1047 form = DevConfForm(initial=initial)
906 1048 else:
907 1049 if 'template' in request.GET:
908 1050 if request.GET['template']=='0':
909 1051 choices = [(conf.pk, '{}'.format(conf)) for conf in Configuration.objects.filter(template=True)]
910 1052 form = NewForm(initial={'create_from':2},
911 1053 template_choices=choices)
912 1054 else:
913 1055 kwargs['button'] = 'Create'
914 1056 conf = Configuration.objects.get(pk=request.GET['template'])
915 1057 id_dev = conf.device.pk
916 1058 DevConfForm = CONF_FORMS[conf.device.device_type.name]
917 1059 form = DevConfForm(instance=conf,
918 1060 initial={'name': '{} [{:%Y/%m/%d}]'.format(conf.name, datetime.now()),
919 1061 'template': False,
920 1062 'experiment':id_exp})
921 1063 elif 'blank' in request.GET:
922 1064 kwargs['button'] = 'Create'
923 1065 form = ConfigurationForm(initial=initial)
924 1066 else:
925 1067 form = NewForm()
926 1068
927 1069 if request.method == 'POST':
928 1070
929 1071 device = Device.objects.get(pk=request.POST['device'])
930 1072 DevConfForm = CONF_FORMS[device.device_type.name]
931 1073
932 1074 form = DevConfForm(request.POST)
933 1075 kwargs['button'] = 'Create'
934 1076 if form.is_valid():
935 1077 conf = form.save()
936 1078
937 1079 if 'template' in request.GET and conf.device.device_type.name=='rc':
938 1080 lines = RCLine.objects.filter(rc_configuration=request.GET['template'])
939 1081 for line in lines:
940 1082 line.clone(rc_configuration=conf)
941 1083
942 1084 if conf.device.device_type.name=='jars':
943 1085 conf.add_parms_to_filter()
944 1086
945 1087 return redirect('url_dev_conf', id_conf=conf.pk)
946 1088
947 1089 kwargs['id_exp'] = id_exp
948 1090 kwargs['form'] = form
949 1091 kwargs['title'] = 'Configuration'
950 1092 kwargs['suptitle'] = 'New'
951 1093
952 1094
953 1095 if id_dev != 0:
954 1096 device = Device.objects.get(pk=id_dev)
955 1097 kwargs['device'] = device.device_type.name
956 1098
957 1099 return render(request, 'dev_conf_edit.html', kwargs)
958 1100
959 1101
960 1102 def dev_conf_edit(request, id_conf):
961 1103
962 1104 conf = get_object_or_404(Configuration, pk=id_conf)
963 1105
964 1106 DevConfModel = CONF_MODELS[conf.device.device_type.name]
965 1107 DevConfForm = CONF_FORMS[conf.device.device_type.name]
966 1108
967 1109 dev_conf = DevConfModel.objects.get(pk=id_conf)
968 1110
969 1111 if request.method=='GET':
970 1112 form = DevConfForm(instance=dev_conf)
971 1113
972 1114 if request.method=='POST':
973 1115 form = DevConfForm(request.POST, instance=dev_conf)
974 1116
975 1117 if form.is_valid():
976 1118 form.save()
977 1119 return redirect('url_dev_conf', id_conf=id_conf)
978 1120
979 1121 kwargs = {}
980 1122 kwargs['form'] = form
981 1123 kwargs['title'] = 'Device Configuration'
982 1124 kwargs['suptitle'] = 'Edit'
983 1125 kwargs['button'] = 'Update'
984 1126
985 1127 ###### SIDEBAR ######
986 1128 kwargs.update(sidebar(conf=conf))
987 1129
988 1130 return render(request, '%s_conf_edit.html' % conf.device.device_type.name, kwargs)
989 1131
990 1132
991 1133 def dev_conf_start(request, id_conf):
992 1134
993 1135 conf = get_object_or_404(Configuration, pk=id_conf)
994 1136
995 1137 DevConfModel = CONF_MODELS[conf.device.device_type.name]
996 1138
997 1139 conf = DevConfModel.objects.get(pk=id_conf)
998 1140
999 1141 if conf.start_device():
1000 1142 messages.success(request, conf.message)
1001 1143 else:
1002 1144 messages.error(request, conf.message)
1003 1145
1004 1146 conf.status_device()
1005 1147
1006 1148 return redirect(conf.get_absolute_url())
1007 1149
1008 1150
1009 1151 def dev_conf_stop(request, id_conf):
1010 1152
1011 1153 conf = get_object_or_404(Configuration, pk=id_conf)
1012 1154
1013 1155 DevConfModel = CONF_MODELS[conf.device.device_type.name]
1014 1156
1015 1157 conf = DevConfModel.objects.get(pk=id_conf)
1016 1158
1017 1159 if conf.stop_device():
1018 1160 messages.success(request, conf.message)
1019 1161 else:
1020 1162 messages.error(request, conf.message)
1021 1163
1022 1164 conf.status_device()
1023 1165
1024 1166 return redirect(conf.get_absolute_url())
1025 1167
1026 1168
1027 1169 def dev_conf_status(request, id_conf):
1028 1170
1029 1171 conf = get_object_or_404(Configuration, pk=id_conf)
1030 1172
1031 1173 DevConfModel = CONF_MODELS[conf.device.device_type.name]
1032 1174
1033 1175 conf = DevConfModel.objects.get(pk=id_conf)
1034 1176
1035 1177 if conf.status_device():
1036 1178 messages.success(request, conf.message)
1037 1179 else:
1038 1180 messages.error(request, conf.message)
1039 1181
1040 1182 return redirect(conf.get_absolute_url())
1041 1183
1042 1184
1043 1185 def dev_conf_write(request, id_conf):
1044 1186
1045 1187 conf = get_object_or_404(Configuration, pk=id_conf)
1046 1188
1047 1189 DevConfModel = CONF_MODELS[conf.device.device_type.name]
1048 1190
1049 1191 conf = DevConfModel.objects.get(pk=id_conf)
1050 1192
1051 1193 answer = conf.write_device()
1052 1194 conf.status_device()
1053 1195
1054 1196 if answer:
1055 1197 messages.success(request, conf.message)
1056 1198
1057 1199 #Creating a historical configuration
1058 conf.clone(type=0, template=False)
1200 conf.clone(type=1, template=False)
1059 1201
1060 1202 #Original configuration
1061 1203 conf = DevConfModel.objects.get(pk=id_conf)
1062 1204 else:
1063 1205 messages.error(request, conf.message)
1064 1206
1065 1207 return redirect(conf.get_absolute_url())
1066 1208
1067 1209
1068 1210 def dev_conf_read(request, id_conf):
1069 1211
1070 1212 conf = get_object_or_404(Configuration, pk=id_conf)
1071 1213
1072 1214 DevConfModel = CONF_MODELS[conf.device.device_type.name]
1073 1215 DevConfForm = CONF_FORMS[conf.device.device_type.name]
1074 1216
1075 1217 conf = DevConfModel.objects.get(pk=id_conf)
1076 1218
1077 1219 if request.method=='GET':
1078 1220
1079 1221 parms = conf.read_device()
1080 1222 conf.status_device()
1081 1223
1082 1224 if not parms:
1083 1225 messages.error(request, conf.message)
1084 1226 return redirect(conf.get_absolute_url())
1085 1227
1086 1228 form = DevConfForm(initial=parms, instance=conf)
1087 1229
1088 1230 if request.method=='POST':
1089 1231 form = DevConfForm(request.POST, instance=conf)
1090 1232
1091 1233 if form.is_valid():
1092 1234 form.save()
1093 1235 return redirect(conf.get_absolute_url())
1094 1236
1095 1237 messages.error(request, "Parameters could not be saved")
1096 1238
1097 1239 kwargs = {}
1098 1240 kwargs['id_dev'] = conf.id
1099 1241 kwargs['form'] = form
1100 1242 kwargs['title'] = 'Device Configuration'
1101 1243 kwargs['suptitle'] = 'Parameters read from device'
1102 1244 kwargs['button'] = 'Save'
1103 1245
1104 1246 ###### SIDEBAR ######
1105 1247 kwargs.update(sidebar(conf=conf))
1106 1248
1107 1249 return render(request, '%s_conf_edit.html' %conf.device.device_type.name, kwargs)
1108 1250
1109 1251
1110 1252 def dev_conf_import(request, id_conf):
1111 1253
1112 1254 conf = get_object_or_404(Configuration, pk=id_conf)
1113 1255
1114 1256 DevConfModel = CONF_MODELS[conf.device.device_type.name]
1115 1257 DevConfForm = CONF_FORMS[conf.device.device_type.name]
1116 1258 conf = DevConfModel.objects.get(pk=id_conf)
1117 1259
1118 1260 if request.method == 'GET':
1119 1261 file_form = UploadFileForm()
1120 1262
1121 1263 if request.method == 'POST':
1122 1264 file_form = UploadFileForm(request.POST, request.FILES)
1123 1265
1124 1266 if file_form.is_valid():
1125 1267
1126 1268 parms = conf.import_from_file(request.FILES['file'])
1127 1269
1128 1270 if parms:
1129 1271 messages.success(request, "Parameters imported from: '%s'." %request.FILES['file'].name)
1130 1272 form = DevConfForm(initial=parms, instance=conf)
1131 1273
1132 1274 kwargs = {}
1133 1275 kwargs['id_dev'] = conf.id
1134 1276 kwargs['form'] = form
1135 1277 kwargs['title'] = 'Device Configuration'
1136 1278 kwargs['suptitle'] = 'Parameters imported'
1137 1279 kwargs['button'] = 'Save'
1138 1280 kwargs['action'] = conf.get_absolute_url_edit()
1139 1281 kwargs['previous'] = conf.get_absolute_url()
1140 1282
1141 1283 ###### SIDEBAR ######
1142 1284 kwargs.update(sidebar(conf=conf))
1143 1285
1144 1286 return render(request, '%s_conf_edit.html' % conf.device.device_type.name, kwargs)
1145 1287
1146 1288 messages.error(request, "Could not import parameters from file")
1147 1289
1148 1290 kwargs = {}
1149 1291 kwargs['id_dev'] = conf.id
1150 1292 kwargs['title'] = 'Device Configuration'
1151 1293 kwargs['form'] = file_form
1152 1294 kwargs['suptitle'] = 'Importing file'
1153 1295 kwargs['button'] = 'Import'
1154 1296
1155 1297 kwargs.update(sidebar(conf=conf))
1156 1298
1157 1299 return render(request, 'dev_conf_import.html', kwargs)
1158 1300
1159 1301
1160 1302 def dev_conf_export(request, id_conf):
1161 1303
1162 1304 conf = get_object_or_404(Configuration, pk=id_conf)
1163 1305
1164 1306 DevConfModel = CONF_MODELS[conf.device.device_type.name]
1165 1307
1166 1308 conf = DevConfModel.objects.get(pk=id_conf)
1167 1309
1168 1310 if request.method == 'GET':
1169 1311 file_form = DownloadFileForm(conf.device.device_type.name)
1170 1312
1171 1313 if request.method == 'POST':
1172 1314 file_form = DownloadFileForm(conf.device.device_type.name, request.POST)
1173 1315
1174 1316 if file_form.is_valid():
1175 1317 fields = conf.export_to_file(format = file_form.cleaned_data['format'])
1176 1318
1177 1319 response = HttpResponse(content_type=fields['content_type'])
1178 1320 response['Content-Disposition'] = 'attachment; filename="%s"' %fields['filename']
1179 1321 response.write(fields['content'])
1180 1322
1181 1323 return response
1182 1324
1183 1325 messages.error(request, "Could not export parameters")
1184 1326
1185 1327 kwargs = {}
1186 1328 kwargs['id_dev'] = conf.id
1187 1329 kwargs['title'] = 'Device Configuration'
1188 1330 kwargs['form'] = file_form
1189 1331 kwargs['suptitle'] = 'Exporting file'
1190 1332 kwargs['button'] = 'Export'
1191 1333
1192 1334 return render(request, 'dev_conf_export.html', kwargs)
1193 1335
1194 1336
1195 1337 def dev_conf_delete(request, id_conf):
1196 1338
1197 1339 conf = get_object_or_404(Configuration, pk=id_conf)
1198 1340
1199 1341 if request.method=='POST':
1200 1342 if request.user.is_staff:
1201 1343 conf.delete()
1202 1344 return redirect('url_dev_confs')
1203 1345
1204 1346 messages.error(request, 'Not enough permission to delete this object')
1205 1347 return redirect(conf.get_absolute_url())
1206 1348
1207 1349 kwargs = {
1208 1350 'title': 'Delete',
1209 1351 'suptitle': 'Experiment',
1210 1352 'object': conf,
1211 1353 'previous': conf.get_absolute_url(),
1212 1354 'delete': True
1213 1355 }
1214 1356
1215 1357 return render(request, 'confirm.html', kwargs)
1216 1358
1217 1359
1218 1360 def sidebar(**kwargs):
1219 1361
1220 1362 side_data = {}
1221 1363
1222 1364 conf = kwargs.get('conf', None)
1223 1365 experiment = kwargs.get('experiment', None)
1224 1366
1225 1367 if not experiment:
1226 1368 experiment = conf.experiment
1227 1369
1228 1370 if experiment:
1229 1371 side_data['experiment'] = experiment
1230 1372 campaign = experiment.campaign_set.all()
1231 1373 if campaign:
1232 1374 side_data['campaign'] = campaign[0]
1233 1375 experiments = campaign[0].experiments.all()
1234 1376 else:
1235 1377 experiments = [experiment]
1236 1378 configurations = experiment.configuration_set.filter(type=0)
1237 1379 side_data['side_experiments'] = experiments
1238 1380 side_data['side_configurations'] = configurations
1239 1381
1240 1382 return side_data
1241 1383
1242 1384 def get_paginator(model, page, order, filters={}, n=10):
1243 1385
1244 1386 kwargs = {}
1245 1387 query = Q()
1246 1388 if isinstance(filters, QueryDict):
1247 1389 filters = filters.dict()
1248 1390 [filters.pop(key) for key in filters.keys() if filters[key] in ('', ' ')]
1249 1391 filters.pop('page', None)
1250 1392
1251 1393 if 'start_date' in filters:
1252 1394 filters['start_date__gte'] = filters.pop('start_date')
1253 1395 if 'end_date' in filters:
1254 1396 filters['start_date__lte'] = filters.pop('end_date')
1255 1397 if 'tags' in filters:
1256 1398 tags = filters.pop('tags')
1257 1399 if 'tags' in model._meta.get_all_field_names():
1258 1400 query = query | Q(tags__icontains=tags)
1259 1401 if 'name' in model._meta.get_all_field_names():
1260 1402 query = query | Q(name__icontains=tags)
1261 1403 if 'location' in model._meta.get_all_field_names():
1262 1404 query = query | Q(location__name__icontains=tags)
1263 1405 if 'device' in model._meta.get_all_field_names():
1264 1406 query = query | Q(device__name__icontains=tags)
1265 1407
1266 1408 object_list = model.objects.filter(query, **filters).order_by(*order)
1267 1409 paginator = Paginator(object_list, n)
1268 1410
1269 1411 try:
1270 1412 objects = paginator.page(page)
1271 1413 except PageNotAnInteger:
1272 1414 objects = paginator.page(1)
1273 1415 except EmptyPage:
1274 1416 objects = paginator.page(paginator.num_pages)
1275 1417
1276 1418 kwargs['objects'] = objects
1277 1419 kwargs['offset'] = (int(page)-1)*n if page else 0
1278 1420
1279 1421 return kwargs
1280 1422
1281 1423 def operation(request, id_camp=None):
1282 1424
1283 1425 if not id_camp:
1284 1426 campaigns = Campaign.objects.all().order_by('-start_date')
1285 1427
1286 1428 if not campaigns:
1287 1429 kwargs = {}
1288 1430 kwargs['title'] = 'No Campaigns'
1289 1431 kwargs['suptitle'] = 'Empty'
1290 1432 return render(request, 'operation.html', kwargs)
1291 1433
1292 1434 id_camp = campaigns[0].id
1293 1435
1294 1436 campaign = get_object_or_404(Campaign, pk = id_camp)
1295 1437
1296 1438 if request.method=='GET':
1297 1439 form = OperationForm(initial={'campaign': campaign.id}, length = 5)
1298 1440
1299 1441 if request.method=='POST':
1300 1442 form = OperationForm(request.POST, initial={'campaign':campaign.id}, length = 5)
1301 1443
1302 1444 if form.is_valid():
1303 1445 return redirect('url_operation', id_camp=campaign.id)
1304 1446 #locations = Location.objects.filter(experiment__campaign__pk = campaign.id).distinct()
1305 1447 experiments = Experiment.objects.filter(campaign__pk=campaign.id)
1306 1448 #for exs in experiments:
1307 1449 # exs.get_status()
1308 1450 locations= Location.objects.filter(experiment=experiments).distinct()
1309 1451 #experiments = [Experiment.objects.filter(location__pk=location.id).filter(campaign__pk=campaign.id) for location in locations]
1310 1452 kwargs = {}
1311 1453 #---Campaign
1312 1454 kwargs['campaign'] = campaign
1313 1455 kwargs['campaign_keys'] = ['name', 'start_date', 'end_date', 'tags', 'description']
1314 1456 #---Experiment
1315 1457 keys = ['id', 'name', 'start_time', 'end_time', 'status']
1316 1458 kwargs['experiment_keys'] = keys[1:]
1317 1459 kwargs['experiments'] = experiments
1318 1460 #---Radar
1319 1461 kwargs['locations'] = locations
1320 1462 #---Else
1321 1463 kwargs['title'] = 'Campaign'
1322 1464 kwargs['suptitle'] = campaign.name
1323 1465 kwargs['form'] = form
1324 1466 kwargs['button'] = 'Search'
1325 1467 kwargs['details'] = True
1326 1468 kwargs['search_button'] = True
1327 1469
1328 1470 return render(request, 'operation.html', kwargs)
1329 1471
1330 1472
1331 1473 def operation_search(request, id_camp=None):
1332 1474
1333 1475
1334 1476 if not id_camp:
1335 1477 campaigns = Campaign.objects.all().order_by('-start_date')
1336 1478
1337 1479 if not campaigns:
1338 1480 return render(request, 'operation.html', {})
1339 1481
1340 1482 id_camp = campaigns[0].id
1341 1483 campaign = get_object_or_404(Campaign, pk = id_camp)
1342 1484
1343 1485 if request.method=='GET':
1344 1486 form = OperationSearchForm(initial={'campaign': campaign.id})
1345 1487
1346 1488 if request.method=='POST':
1347 1489 form = OperationSearchForm(request.POST, initial={'campaign':campaign.id})
1348 1490
1349 1491 if form.is_valid():
1350 1492 return redirect('url_operation', id_camp=campaign.id)
1351 1493
1352 1494 #locations = Location.objects.filter(experiment__campaign__pk = campaign.id).distinct()
1353 1495 experiments = Experiment.objects.filter(campaign__pk=campaign.id)
1354 1496 #for exs in experiments:
1355 1497 # exs.get_status()
1356 1498 locations= Location.objects.filter(experiment=experiments).distinct()
1357 1499 form = OperationSearchForm(initial={'campaign': campaign.id})
1358 1500
1359 1501 kwargs = {}
1360 1502 #---Campaign
1361 1503 kwargs['campaign'] = campaign
1362 1504 kwargs['campaign_keys'] = ['name', 'start_date', 'end_date', 'tags', 'description']
1363 1505 #---Experiment
1364 1506 keys = ['id', 'name', 'start_time', 'end_time', 'status']
1365 1507 kwargs['experiment_keys'] = keys[1:]
1366 1508 kwargs['experiments'] = experiments
1367 1509 #---Radar
1368 1510 kwargs['locations'] = locations
1369 1511 #---Else
1370 1512 kwargs['title'] = 'Campaign'
1371 1513 kwargs['suptitle'] = campaign.name
1372 1514 kwargs['form'] = form
1373 1515 kwargs['button'] = 'Select'
1374 1516 kwargs['details'] = True
1375 1517 kwargs['search_button'] = False
1376 1518
1377 1519 return render(request, 'operation.html', kwargs)
1378 1520
1379 1521
1380 1522 def radar_play(request, id_camp, id_radar):
1381 1523 campaign = get_object_or_404(Campaign, pk = id_camp)
1382 1524 radar = get_object_or_404(Location, pk = id_radar)
1383 1525 today = datetime.today()
1384 1526 now = today.time()
1385 1527
1386 1528 #--Clear Old Experiments From RunningExperiment Object
1387 1529 running_experiment = RunningExperiment.objects.filter(radar=radar)
1388 1530 if running_experiment:
1389 1531 running_experiment = running_experiment[0]
1390 1532 running_experiment.running_experiment.clear()
1391 1533 running_experiment.save()
1392 1534
1393 1535 #--If campaign datetime is ok:
1394 1536 if today >= campaign.start_date and today <= campaign.end_date:
1395 1537 experiments = Experiment.objects.filter(campaign=campaign).filter(location=radar)
1396 1538 for exp in experiments:
1397 1539 #--If experiment time is ok:
1398 1540 if now >= exp.start_time and now <= exp.end_time:
1399 1541 configurations = Configuration.objects.filter(experiment = exp)
1400 1542 for conf in configurations:
1401 1543 if 'cgs' in conf.device.device_type.name:
1402 1544 conf.status_device()
1403 1545 else:
1404 1546 answer = conf.start_device()
1405 1547 conf.status_device()
1406 1548 #--Running Experiment
1407 1549 old_running_experiment = RunningExperiment.objects.filter(radar=radar)
1408 1550 #--If RunningExperiment element exists
1409 1551 if old_running_experiment:
1410 1552 old_running_experiment = old_running_experiment[0]
1411 1553 old_running_experiment.running_experiment.add(exp)
1412 1554 old_running_experiment.status = 3
1413 1555 old_running_experiment.save()
1414 1556 #--Create a new Running_Experiment Object
1415 1557 else:
1416 1558 new_running_experiment = RunningExperiment(
1417 1559 radar = radar,
1418 1560 status = 3,
1419 1561 )
1420 1562 new_running_experiment.save()
1421 1563 new_running_experiment.running_experiment.add(exp)
1422 1564 new_running_experiment.save()
1423 1565
1424 1566 if answer:
1425 1567 messages.success(request, conf.message)
1426 1568 exp.status=2
1427 1569 exp.save()
1428 1570 else:
1429 1571 messages.error(request, conf.message)
1430 1572 else:
1431 1573 if exp.status == 1 or exp.status == 3:
1432 1574 exp.status=3
1433 1575 exp.save()
1434 1576
1435 1577
1436 1578 route = request.META['HTTP_REFERER']
1437 1579 route = str(route)
1438 1580 if 'search' in route:
1439 1581 return HttpResponseRedirect(reverse('url_operation_search', args=[id_camp]))
1440 1582 else:
1441 1583 return HttpResponseRedirect(reverse('url_operation', args=[id_camp]))
1442 1584
1443 1585
1444 1586 def radar_stop(request, id_camp, id_radar):
1445 1587 campaign = get_object_or_404(Campaign, pk = id_camp)
1446 1588 radar = get_object_or_404(Location, pk = id_radar)
1447 1589 experiments = Experiment.objects.filter(campaign=campaign).filter(location=radar)
1448 1590
1449 1591 for exp in experiments:
1450 1592 configurations = Configuration.objects.filter(experiment = exp)
1451 1593 for conf in configurations:
1452 1594 if 'cgs' in conf.device.device_type.name:
1453 1595 conf.status_device()
1454 1596 else:
1455 1597 answer = conf.stop_device()
1456 1598 conf.status_device()
1457 1599
1458 1600 if answer:
1459 1601 messages.success(request, conf.message)
1460 1602 exp.status=1
1461 1603 exp.save()
1462 1604 else:
1463 1605 messages.error(request, conf.message)
1464 1606
1465 1607
1466 1608 route = request.META['HTTP_REFERER']
1467 1609 route = str(route)
1468 1610 if 'search' in route:
1469 1611 return HttpResponseRedirect(reverse('url_operation_search', args=[id_camp]))
1470 1612 else:
1471 1613 return HttpResponseRedirect(reverse('url_operation', args=[id_camp]))
1472 1614
1473 1615
1474 1616 def radar_refresh(request, id_camp, id_radar):
1475 1617
1476 1618 campaign = get_object_or_404(Campaign, pk = id_camp)
1477 1619 radar = get_object_or_404(Location, pk = id_radar)
1478 1620 experiments = Experiment.objects.filter(campaign=campaign).filter(location=radar)
1479 1621 for exs in experiments:
1480 1622 exs.get_status()
1481 1623
1482 1624 route = request.META['HTTP_REFERER']
1483 1625 route = str(route)
1484 1626 if 'search' in route:
1485 1627 return HttpResponseRedirect(reverse('url_operation_search', args=[id_camp]))
1486 1628 else:
1487 1629 return HttpResponseRedirect(reverse('url_operation', args=[id_camp]))
@@ -1,28 +1,28
1 1 [{"fields": {"number_of_codes": 0, "codes": "[]", "name": "None", "bits_per_code": 0}, "model": "rc.rclinecode", "pk": 1},
2 2 {"fields": {"number_of_codes": 2, "codes": "[u'11101101', u'11100010']", "name": "COMPLEMENTARY_CODE_8", "bits_per_code": 8}, "model": "rc.rclinecode", "pk": 2},
3 3 {"fields": {"number_of_codes": 1, "codes": "[u'1101101001000100010001111000']", "name": "BINARY_CODE_28", "bits_per_code": 28}, "model": "rc.rclinecode", "pk": 3},
4 4 {"fields": {"number_of_codes": 2, "codes": "[u'11', u'10']", "name": "COMPLEMENTARY_CODE_2", "bits_per_code": 2}, "model": "rc.rclinecode", "pk": 4},
5 5 {"fields": {"number_of_codes": 2, "codes": "[u'1110110111100010111011010001110111101101111000100001001011100010', u'1110110111100010111011010001110100010010000111011110110100011101']", "name": "COMPLEMENTARY_CODE_64", "bits_per_code": 64}, "model": "rc.rclinecode", "pk": 5},
6 6 {"fields": {"number_of_codes": 1, "codes": "[u'11100010010']", "name": "BARKER11", "bits_per_code": 11}, "model": "rc.rclinecode", "pk": 6},
7 7 {"fields": {"number_of_codes": 2, "codes": "[u'1111100110101' ]", "name": "BARKER13", "bits_per_code": 13}, "model": "rc.rclinecode", "pk": 7},
8 8 {"fields": {"number_of_codes": 2, "codes": "[u'1101101001000100010001111000', u'0010010110111011101110000111']", "name": "BINARY_CODE_28_FLIP", "bits_per_code": 28}, "model": "rc.rclinecode", "pk": 8},
9 9 {"fields": {"number_of_codes": 2, "codes": "[u'11101101111000101110110100011101', u'11101101111000100001001011100010']", "name": "COMPLEMENTARY_CODE_32", "bits_per_code": 32}, "model": "rc.rclinecode", "pk": 9},
10 10 {"fields": {"number_of_codes": 128, "codes": "[u'1111000100100101', u'1011001010010111', u'1101001000100000', u'1001000110010010', u'1110001001111011', u'1010000111001001', u'1100000101111110', u'1000001011001100', u'1111101001010110', u'1011100111100100', u'1101100101010011', u'1001101011100001', u'1110100100001000', u'1010101010111010', u'1100101000001101', u'1000100110111111', u'1111010010011100', u'1011011100101110', u'1101011110011001', u'1001010000101011', u'1110011111000010', u'1010010001110000', u'1100010011000111', u'1000011101110101', u'1111111111101111', u'1011110001011101', u'1101110011101010', u'1001111101011000', u'1110110010110001', u'1010111100000011', u'1100111110110100', u'1000110000000110', u'0011111000000011', u'0111110110110001', u'0001110100000110', u'0101111010110100', u'0010110101011101', u'0110111011101111', u'0000111001011000', u'0100110111101010', u'0011010101110000', u'0111011011000010', u'0001011001110101', u'0101010111000111', u'0010011000101110', u'0110010110011100', u'0000010100101011', u'0100011010011001', u'0011101110111010', u'0111100000001000', u'0001100010111111', u'0101101100001101', u'0010100011100100', u'0110101101010110', u'0000101111100001', u'0100100001010011', u'0011000011001001', u'0111001101111011', u'0001001111001100', u'0101000001111110', u'0010001110010111', u'0110000000100101', u'0000000010010010', u'0100001100100000', u'1010110011001110', u'1110111101111100', u'1000111111001011', u'1100110001111001', u'1011111110010000', u'1111110000100010', u'1001110010010101', u'1101111100100111', u'1010011110111101', u'1110010000001111', u'1000010010111000', u'1100011100001010', u'1011010011100011', u'1111011101010001', u'1001011111100110', u'1101010001010100', u'1010100101110111', u'1110101011000101', u'1000101001110010', u'1100100111000000', u'1011101000101001', u'1111100110011011', u'1001100100101100', u'1101101010011110', u'1010001000000100', u'1110000110110110', u'1000000100000001', u'1100001010110011', u'1011000101011010', u'1111001011101000', u'1001001001011111', u'1101000111101101', u'1100100111000110', u'1000101001110100', u'1110101011000011', u'1010100101110001', u'1101101010011000', u'1001100100101010', u'1111100110011101', u'1011101000101111', u'1100001010110101', u'1000000100000111', u'1110000110110000', u'1010001000000010', u'1101000111101011', u'1001001001011001', u'1111001011101110', u'1011000101011100', u'1100110001111111', u'1000111111001101', u'1110111101111010', u'1010110011001000', u'1101111100100001', u'1001110010010011', u'1111110000100100', u'1011111110010110', u'1100011100001100', u'1000010010111110', u'1110010000001001', u'1010011110111011', u'1101010001010010', u'1001011111100000', u'1111011101010111', u'1011010011100101']", "name": "AC128", "bits_per_code": 16}, "model": "rc.rclinecode", "pk": 10},
11 11 {"fields": {"number_of_codes": 2, "codes": "[u'11101101111000101110110100011101111011011110001000010010111000101110110111100010111011010001110100010010000111011110110100011101', u'11101101111000101110110100011101111011011110001000010010111000100001001000011101000100101110001011101101111000100001001011100010']", "name": "COMPLEMENTARY_CODE_128", "bits_per_code": 128}, "model": "rc.rclinecode", "pk": 11},
12 12 {"fields": {"number_of_codes": 2, "codes": "[u'1110110111100010', u'1110110100011101']", "name": "COMPLEMENTARY_CODE_16", "bits_per_code": 16}, "model": "rc.rclinecode", "pk": 12},
13 13 {"fields": {"number_of_codes": 1, "codes": "[u'11']", "name": "BARKER2", "bits_per_code": 2}, "model": "rc.rclinecode", "pk": 13},
14 14 {"fields": {"number_of_codes": 1, "codes": "[u'110']", "name": "BARKER3", "bits_per_code": 3}, "model": "rc.rclinecode", "pk": 14},
15 15 {"fields": {"number_of_codes": 2, "codes": "[u'1110', u'1101']", "name": "COMPLEMENTARY_CODE_4", "bits_per_code": 4}, "model": "rc.rclinecode", "pk": 15},
16 16 {"fields": {"number_of_codes": 1, "codes": "[u'1110010']", "name": "BARKER7", "bits_per_code": 7}, "model": "rc.rclinecode", "pk": 16},
17 17 {"fields": {"number_of_codes": 1, "codes": "[u'1101']", "name": "BARKER4", "bits_per_code": 4}, "model": "rc.rclinecode", "pk": 17},
18 18 {"fields": {"number_of_codes": 1, "codes": "[u'11101']", "name": "BARKER5", "bits_per_code": 5}, "model": "rc.rclinecode", "pk": 18},
19 19 {"fields": {"number_of_codes": 0, "codes": "[]", "name": "USERDEFINE", "bits_per_code": 0}, "model": "rc.rclinecode", "pk": 19},
20 20 {"fields": {"params": "{\"TX_ref\": {\"model\": \"RCLine\", \"value\": \"\"}, \"range\": { \"value\": 0, \"help\": \"Frame numbers or frame ranges separated by commas, use 0 for all frames eg: 1,2,10-15\"}}", "name": "tr", "description": ""}, "model": "rc.rclinetype", "pk": 1},
21 21 {"fields": {"params": "{\"pulse_width\":{\"value\": 0, \"widget\":\"dc\"},\r\n \"delays\":{\"value\": \"\", \"widget\":\"km\", \"help\": \"Delay entries separated by commas (TAUs)\"},\r\n \"range\":{\"value\": 0, \"help\": \"Frame numbers or frame ranges separated by commas, use 0 for all frames eg: 1,2,10-15\"}}", "name": "tx", "description": ""}, "model": "rc.rclinetype", "pk": 2},
22 22 {"fields": {"params": "{\"TX_ref\": {\"model\": \"RCLine\", \"value\": \"\"}, \"code\": {\"model\":\"RCLineCode\",\"value\": \"\"}, \"codes\":{\"value\":\"\", \"widget\":\"codes\"}}", "name": "codes", "description": ""}, "model": "rc.rclinetype", "pk": 3},
23 {"fields": {"params": "{ \"TX_ref\":{\"model\": \"RCLine\", \"value\": \"\"}, \"params\": {\"first_height\":{ \"value\": 0, \"widget\":\"km\"},\"resolution\": {\"value\": 0, \"widget\":\"km\"}, \"number_of_samples\": { \"value\": 0, \"help\":\"number of samples (NSA)\"}}}", "name": "windows", "description": ""}, "model": "rc.rclinetype", "pk": 4},
23 {"fields": {"params": "{ \"TX_ref\":{\"model\": \"RCLine\", \"value\": \"\"}, \"params\": {\"first_height\":{ \"value\": 0, \"widget\":\"km\"},\"resolution\": {\"value\": 0, \"widget\":\"km\"}, \"number_of_samples\": { \"value\": 0, \"help\":\"number of samples (NSA)\"}, \"last_height\": { \"value\": 0}}}", "name": "windows", "description": ""}, "model": "rc.rclinetype", "pk": 4},
24 24 {"fields": {"params": "{\"invert\":{\"value\": 0, \"help\": \"Set to 1 for synchro pulse at the end\"}}", "name": "sync", "description": ""}, "model": "rc.rclinetype", "pk": 5},
25 25 {"fields": {"params": "{ \"periodic\": { \"value\": 0, \"help\": \"Set to 1 for IPP periodic\"}, \"params\": {\"begin\": { \"value\": 0, \"widget\":\"unit\"}, \"end\": {\"value\": 0, \"widget\":\"unit\"}}}", "name": "prog_pulses", "description": ""}, "model": "rc.rclinetype", "pk": 6},
26 26 {"fields": {"params": "{\"number_of_flips\": {\"value\": 0}}", "name": "flip", "description": ""}, "model": "rc.rclinetype", "pk": 7},
27 27 {"fields": {"params": "{}", "name": "none", "description": ""}, "model": "rc.rclinetype", "pk": 8},
28 28 {"fields": {"params": "{}", "name": "mix", "description": ""}, "model": "rc.rclinetype", "pk": 9}] No newline at end of file
@@ -1,767 +1,786
1 1
2 2 import ast
3 3 import json
4 4 import numpy as np
5 5
6 6 from polymorphic import PolymorphicModel
7 7
8 8 from django.db import models
9 9 from django.core.urlresolvers import reverse
10 10 from django.core.validators import MinValueValidator, MaxValueValidator
11 11
12 12 from apps.main.models import Configuration
13 13 from devices.rc import api
14 14 from .utils import RCFile
15 15
16 16 # Create your models here.
17 17
18 18 LINE_TYPES = (
19 19 ('none', 'Not used'),
20 20 ('tr', 'Transmission/reception selector signal'),
21 21 ('tx', 'A modulating signal (Transmission pulse)'),
22 22 ('codes', 'BPSK modulating signal'),
23 23 ('windows', 'Sample window signal'),
24 24 ('sync', 'Synchronizing signal'),
25 25 ('flip', 'IPP related periodic signal'),
26 26 ('prog_pulses', 'Programmable pulse'),
27 27 ('mix', 'Mixed line'),
28 28 )
29 29
30 30
31 31 SAMPLING_REFS = (
32 32 ('none', 'No Reference'),
33 ('begin_baud', 'Begin of the first baud'),
33 34 ('first_baud', 'Middle of the first baud'),
34 35 ('sub_baud', 'Middle of the sub-baud')
35 36 )
36 37
37 38 DAT_CMDS = {
38 39 # Pulse Design commands
39 40 'DISABLE' : 0, # Disables pulse generation
40 41 'ENABLE' : 24, # Enables pulse generation
41 42 'DELAY_START' : 40, # Write delay status to memory
42 43 'FLIP_START' : 48, # Write flip status to memory
43 44 'SAMPLING_PERIOD' : 64, # Establish Sampling Period
44 45 'TX_ONE' : 72, # Output '0' in line TX
45 46 'TX_ZERO' : 88, # Output '0' in line TX
46 47 'SW_ONE' : 104, # Output '0' in line SW
47 48 'SW_ZERO' : 112, # Output '1' in line SW
48 49 'RESTART': 120, # Restarts CR8 Firmware
49 50 'CONTINUE' : 253, # Function Unknown
50 51 # Commands available to new controllers
51 52 # In Pulse Design Executable, the clock divisor code is written as 12 at the start, but it should be written as code 22(below) just before the final enable.
52 53 'CLOCK_DIVISOR_INIT' : 12, # Specifies Clock Divisor. Legacy command, ignored in the actual .dat conversion
53 54 'CLOCK_DIVISOR_LAST' : 22, # Specifies Clock Divisor (default 60 if not included) syntax: 255,22 254,N-1.
54 55 'CLOCK_DIVIDER' : 8,
55 56 }
56 57
57 58
58 59 class RCConfiguration(Configuration):
59 60
60 61 ipp = models.FloatField(verbose_name='IPP [Km]', validators=[MinValueValidator(1), MaxValueValidator(9000)], default=300)
61 62 ntx = models.PositiveIntegerField(verbose_name='Number of TX', validators=[MinValueValidator(1), MaxValueValidator(400)], default=1)
62 63 clock_in = models.FloatField(verbose_name='Clock in [MHz]', validators=[MinValueValidator(1), MaxValueValidator(80)], default=1)
63 64 clock_divider = models.PositiveIntegerField(verbose_name='Clock divider', validators=[MinValueValidator(1), MaxValueValidator(256)], default=1)
64 65 clock = models.FloatField(verbose_name='Clock Master [MHz]', blank=True, default=1)
65 66 time_before = models.PositiveIntegerField(verbose_name='Time before [&mu;S]', default=12)
66 67 time_after = models.PositiveIntegerField(verbose_name='Time after [&mu;S]', default=1)
67 68 sync = models.PositiveIntegerField(verbose_name='Synchro delay', default=0)
68 69 sampling_reference = models.CharField(verbose_name='Sampling Reference', choices=SAMPLING_REFS, default='none', max_length=40)
69 70 control_tx = models.BooleanField(verbose_name='Control Switch TX', default=False)
70 71 control_sw = models.BooleanField(verbose_name='Control Switch SW', default=False)
71 72 total_units = models.PositiveIntegerField(default=0)
72 73 mix = models.BooleanField(default=False)
73 74
74 75 class Meta:
75 76 db_table = 'rc_configurations'
76 77
77 78 def get_absolute_url_plot(self):
78 79 return reverse('url_plot_rc_pulses', args=[str(self.id)])
79 80
80 81 def get_absolute_url_import(self):
81 82 return reverse('url_import_rc_conf', args=[str(self.id)])
82 83
83 84 @property
84 85 def ipp_unit(self):
85 86
86 87 return '{} ({})'.format(self.ipp, int(self.ipp*self.km2unit))
87 88
88 89 @property
89 90 def us2unit(self):
90 91
91 92 return self.clock_in/self.clock_divider
92 93
93 94 @property
94 95 def km2unit(self):
95 96
96 97 return 20./3*(self.clock_in/self.clock_divider)
97 98
98 99 def clone(self, **kwargs):
99 100
100 101 lines = self.get_lines()
101 102 self.pk = None
102 103 self.id = None
103 104 for attr, value in kwargs.items():
104 105 setattr(self, attr, value)
105 106 self.save()
106 107
107 108 for line in lines:
108 109 line.clone(rc_configuration=self)
109 110
110 111 return self
111 112
112 113 def get_lines(self, **kwargs):
113 114 '''
114 115 Retrieve configuration lines
115 116 '''
116 117
117 118 return RCLine.objects.filter(rc_configuration=self.pk, **kwargs)
118 119
119 120
120 121 def clean_lines(self):
121 122 '''
122 123 '''
123 124
124 125 empty_line = RCLineType.objects.get(name='none')
125 126
126 127 for line in self.get_lines():
127 128 line.line_type = empty_line
128 129 line.params = '{}'
129 130 line.save()
130 131
131 132 def parms_to_dict(self):
132 133 '''
133 134 '''
134 135
135 136 ignored = ('parameters', 'type', 'polymorphic_ctype', 'configuration_ptr',
136 137 'created_date', 'programmed_date')
137 138
138 139 data = {}
139 140 for field in self._meta.fields:
140 141 if field.name in ignored:
141 142 continue
142 143 data[field.name] = '{}'.format(field.value_from_object(self))
143 144
144 145 data['device_id'] = data.pop('device')
145 146 data['lines'] = []
146 147
147 148 for line in self.get_lines():
148 line_data = json.loads(line.params)
149 line_data = json.loads(line.params)
149 150 if 'TX_ref' in line_data and line_data['TX_ref'] not in (0, '0'):
150 line_data['TX_ref'] = RCLine.objects.get(pk=line_data['TX_ref']).get_name()
151 line_data['TX_ref'] = line.get_name()
151 152 if 'code' in line_data:
152 153 line_data['code'] = RCLineCode.objects.get(pk=line_data['code']).name
153 154 line_data['type'] = line.line_type.name
155 line_data['name'] = line.get_name()
154 156 data['lines'].append(line_data)
155 157
156 158 data['delays'] = self.get_delays()
157 159 data['pulses'] = self.get_pulses()
158 160
159 161 return data
160 162
161 163 def dict_to_parms(self, data):
162 164 '''
163 165 '''
164 166
165 167 self.name = data['name']
166 168 self.ipp = float(data['ipp'])
167 169 self.ntx = int(data['ntx'])
168 170 self.clock_in = float(data['clock_in'])
169 171 self.clock_divider = int(data['clock_divider'])
170 172 self.clock = float(data['clock'])
171 173 self.time_before = data['time_before']
172 174 self.time_after = data['time_after']
173 175 self.sync = data['sync']
174 176 self.sampling_reference = data['sampling_reference']
175 177 self.total_units = self.ipp*self.ntx*self.km2unit
176 178 self.save()
177 179 self.clean_lines()
178 180
179 181 lines = []
180 182 positions = {'tx':0, 'tr':0}
181 183
182 184 for i, line_data in enumerate(data['lines']):
183 185 line_type = RCLineType.objects.get(name=line_data.pop('type'))
184 186 if line_type.name=='codes':
185 187 code = RCLineCode.objects.get(name=line_data['code'])
186 188 line_data['code'] = code.pk
187 189 line = RCLine.objects.filter(rc_configuration=self, channel=i)
188 190 if line:
189 191 line = line[0]
190 192 line.line_type = line_type
191 193 line.params = json.dumps(line_data)
192 194 else:
193 195 line = RCLine(rc_configuration=self, line_type=line_type,
194 196 params=json.dumps(line_data),
195 197 channel=i)
196 198
197 199 if line_type.name=='tx':
198 200 line.position = positions['tx']
199 201 positions['tx'] += 1
200 202
201 203 if line_type.name=='tr':
202 204 line.position = positions['tr']
203 205 positions['tr'] += 1
204 206
205 207 line.save()
206 208 lines.append(line)
207 209
208 210 for line, line_data in zip(lines, data['lines']):
209 211 if 'TX_ref' in line_data:
210 212 params = json.loads(line.params)
211 213 if line_data['TX_ref'] in (0, '0'):
212 214 params['TX_ref'] = '0'
213 215 else:
214 216 params['TX_ref'] = [l.pk for l in lines if l.line_type.name=='tx' and line_data['TX_ref'] in l.get_name()][0]
215 217 line.params = json.dumps(params)
216 218 line.save()
217 219
218 220
219 221 def get_delays(self):
220 222
221 223 pulses = [line.pulses_as_points() for line in self.get_lines()]
222 224 points = [tup for tups in pulses for tup in tups]
223 225 points = set([x for tup in points for x in tup])
224 226 points = list(points)
225 227 points.sort()
226 228
227 229 if points[0]<>0:
228 230 points.insert(0, 0)
229 231
230 232 return [points[i+1]-points[i] for i in range(len(points)-1)]
231 233
232 234
233 235 def get_pulses(self, binary=True):
234 236
235 237 pulses = [line.pulses_as_points() for line in self.get_lines()]
236 238 points = [tup for tups in pulses for tup in tups]
237 239 points = set([x for tup in points for x in tup])
238 240 points = list(points)
239 241 points.sort()
240 242
241 243 line_points = [line.pulses_as_points() for line in self.get_lines()]
242 244 line_points = [[(x, x+y) for x,y in tups] for tups in line_points]
243 245 line_points = [[t for x in tups for t in x] for tups in line_points]
244 246 states = [[1 if x in tups else 0 for tups in line_points] for x in points]
245 247
246 248 if binary:
247 249 states.reverse()
248 250 states = [int(''.join([str(x) for x in flips]), 2) for flips in states]
249 251
250 252 return states[:-1]
251 253
252 254 def add_cmd(self, cmd):
253 255
254 256 if cmd in DAT_CMDS:
255 257 return (255, DAT_CMDS[cmd])
256 258
257 259 def add_data(self, value):
258 260
259 261 return (254, value-1)
260 262
261 263 def parms_to_binary(self):
262 264 '''
263 265 Create "dat" stream to be send to CR
264 266 '''
265 267
266 268 data = []
267 269 # create header
268 270 data.append(self.add_cmd('DISABLE'))
269 271 data.append(self.add_cmd('CONTINUE'))
270 272 data.append(self.add_cmd('RESTART'))
271 273
272 274 if self.control_sw:
273 275 data.append(self.add_cmd('SW_ONE'))
274 276 else:
275 277 data.append(self.add_cmd('SW_ZERO'))
276 278
277 279 if self.control_tx:
278 280 data.append(self.add_cmd('TX_ONE'))
279 281 else:
280 282 data.append(self.add_cmd('TX_ZERO'))
281 283
282 284 # write divider
283 285 data.append(self.add_cmd('CLOCK_DIVIDER'))
284 286 data.append(self.add_data(self.clock_divider))
285 287
286 288 # write delays
287 289 data.append(self.add_cmd('DELAY_START'))
288 290 # first delay is always zero
289 291 data.append(self.add_data(1))
290 292
291 293 delays = self.get_delays()
292 294
293 295 for delay in delays:
294 296 while delay>252:
295 297 data.append(self.add_data(253))
296 298 delay -= 253
297 299 data.append(self.add_data(delay))
298 300
299 301 # write flips
300 302 data.append(self.add_cmd('FLIP_START'))
301 303
302 304 states = self.get_pulses(binary=False)
303 305
304 306 for flips, delay in zip(states, delays):
305 307 flips.reverse()
306 308 flip = int(''.join([str(x) for x in flips]), 2)
307 309 data.append(self.add_data(flip+1))
308 310 while delay>252:
309 311 data.append(self.add_data(1))
310 312 delay -= 253
311 313
312 314 # write sampling period
313 315 data.append(self.add_cmd('SAMPLING_PERIOD'))
314 316 wins = self.get_lines(line_type__name='windows')
315 317 if wins:
316 318 win_params = json.loads(wins[0].params)['params']
317 319 if win_params:
318 320 dh = int(win_params[0]['resolution']*self.km2unit)
319 321 else:
320 322 dh = 1
321 323 else:
322 324 dh = 1
323 325 data.append(self.add_data(dh))
324 326
325 327 # write enable
326 328 data.append(self.add_cmd('ENABLE'))
327 329
328 330 return '\n'.join(['{}'.format(x) for tup in data for x in tup])
329 331
330 332 def update_from_file(self, filename):
331 333 '''
332 334 Update instance from file
333 335 '''
334 336
335 337 f = RCFile(filename)
336 338 self.dict_to_parms(f.data)
337 339 self.update_pulses()
338 340
339 341 def update_pulses(self):
340 342
341 343 for line in self.get_lines():
342 344 line.update_pulses()
343 345
344 def plot_pulses(self):
346 def plot_pulses(self, km=False):
345 347
346 348 import matplotlib.pyplot as plt
347 349 from bokeh.resources import CDN
348 350 from bokeh.embed import components
349 351 from bokeh.mpl import to_bokeh
350 352 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, PreviewSaveTool
351 353
352 354 lines = self.get_lines()
353 355
354 356 N = len(lines)
357 npoints = self.total_units/self.km2unit if km else self.total_units
355 358 fig = plt.figure(figsize=(10, 2+N*0.5))
356 359 ax = fig.add_subplot(111)
357 labels = []
360 labels = ['IPP']
358 361
359 362 for i, line in enumerate(lines):
360 labels.append(line.get_name())
361 l = ax.plot((0, self.total_units),(N-i-1, N-i-1))
362 points = [(tup[0], tup[1]-tup[0]) for tup in line.pulses_as_points() if tup<>(0,0)]
363 labels.append(line.get_name(channel=True))
364 l = ax.plot((0, npoints),(N-i-1, N-i-1))
365 points = [(tup[0], tup[1]-tup[0]) for tup in line.pulses_as_points(km=km) if tup<>(0,0)]
363 366 ax.broken_barh(points, (N-i-1, 0.5),
364 367 edgecolor=l[0].get_color(), facecolor='none')
365 368
369 n = 0
370 f = ((self.ntx+50)/100)*5 if ((self.ntx+50)/100)*10>0 else 2
371 for x in np.arange(0, npoints, self.ipp if km else self.ipp*self.km2unit):
372 if n%f==0:
373 ax.text(x, N, '%s' % n, size=10)
374 n += 1
375
376
366 377 labels.reverse()
367 378 ax.set_yticklabels(labels)
379
368 380 ax.set_xlabel = 'Units'
369 381 plot = to_bokeh(fig, use_pandas=False)
370 382 plot.tools = [PanTool(dimensions=['width']), WheelZoomTool(dimensions=['width']), ResetTool(), PreviewSaveTool()]
371 383
372 384 return components(plot, CDN)
373 385
374 386 def status_device(self):
375 387
376 388 return 0
377 389
378 390 def stop_device(self):
379 391
380 392 answer = api.disable(ip = self.device.ip_address,
381 393 port = self.device.port_address)
382 394
383 395 if answer[0] != "1":
384 396 self.message = answer[0:]
385 397 return 0
386 398
387 399 self.message = answer[2:]
388 400 return 1
389 401
390 402 def start_device(self):
391 403
392 404 answer = api.enable(ip = self.device.ip_address,
393 405 port = self.device.port_address)
394 406
395 407 if answer[0] != "1":
396 408 self.message = answer[0:]
397 409 return 0
398 410
399 411 self.message = answer[2:]
400 412 return 1
401 413
402 414 def write_device(self):
403 415 answer = api.write_config(ip = self.device.ip_address,
404 416 port = self.device.port_address,
405 417 parms = self.parms_to_dict())
406 418
407 419 if answer[0] != "1":
408 420 self.message = answer[0:]
409 421 return 0
410 422
411 423 self.message = answer[2:]
412 424 return 1
413 425
414 426
415 427 class RCLineCode(models.Model):
416 428
417 429 name = models.CharField(max_length=40)
418 430 bits_per_code = models.PositiveIntegerField(default=0)
419 431 number_of_codes = models.PositiveIntegerField(default=0)
420 432 codes = models.TextField(blank=True, null=True)
421 433
422 434 class Meta:
423 435 db_table = 'rc_line_codes'
424 436 ordering = ('name',)
425 437
426 438 def __unicode__(self):
427 439 return u'%s' % self.name
428 440
429 441
430 442 class RCLineType(models.Model):
431 443
432 444 name = models.CharField(choices=LINE_TYPES, max_length=40)
433 445 description = models.TextField(blank=True, null=True)
434 446 params = models.TextField(default='[]')
435 447
436 448 class Meta:
437 449 db_table = 'rc_line_types'
438 450
439 451 def __unicode__(self):
440 452 return u'%s - %s' % (self.name.upper(), self.get_name_display())
441 453
442 454
443 455 class RCLine(models.Model):
444 456
445 457 rc_configuration = models.ForeignKey(RCConfiguration, on_delete=models.CASCADE)
446 458 line_type = models.ForeignKey(RCLineType)
447 459 channel = models.PositiveIntegerField(default=0)
448 460 position = models.PositiveIntegerField(default=0)
449 461 params = models.TextField(default='{}')
450 462 pulses = models.TextField(default='')
451 463
452 464 class Meta:
453 465 db_table = 'rc_lines'
454 466 ordering = ['channel']
455 467
456 468 def __unicode__(self):
457 469 if self.rc_configuration:
458 470 return u'%s - %s' % (self.rc_configuration, self.get_name())
459 471
460 472 def clone(self, **kwargs):
461 473
462 474 self.pk = None
463 475
464 476 for attr, value in kwargs.items():
465 477 setattr(self, attr, value)
466 478
467 479 self.save()
468 480
469 481 return self
470 482
471 def get_name(self):
483 def get_name(self, channel=False):
472 484
473 485 chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
474 486 s = ''
475 487
476 488 if self.line_type.name in ('tx',):
477 489 s = chars[self.position]
478 490 elif self.line_type.name in ('codes', 'windows', 'tr'):
479 491 if 'TX_ref' in json.loads(self.params):
480 492 pk = json.loads(self.params)['TX_ref']
481 493 if pk in (0, '0'):
482 494 s = ','.join(chars[l.position] for l in self.rc_configuration.get_lines(line_type__name='tx'))
483 495 else:
484 496 ref = RCLine.objects.get(pk=pk)
485 497 s = chars[ref.position]
486 498 s = '({})'.format(s)
487 if s:
488 return '{}{} {}'.format(self.line_type.name.upper(), s, self.channel)
499
500 s = '{}{}'.format(self.line_type.name.upper(), s)
501
502 if channel:
503 return '{} {}'.format(s, self.channel)
489 504 else:
490 return '{} {}'.format(self.line_type.name.upper(), self.channel)
505 return s
491 506
492 507 def get_lines(self, **kwargs):
493 508
494 509 return RCLine.objects.filter(rc_configuration=self.rc_configuration, **kwargs)
495 510
496 511 def pulses_as_array(self):
497 512
498 513 y = np.zeros(self.rc_configuration.total_units)
499 514
500 515 for tup in ast.literal_eval(self.pulses):
501 516 y[tup[0]:tup[1]] = 1
502 517
503 518 return y.astype(np.int8)
504 519
505 def pulses_as_points(self):
520 def pulses_as_points(self, km=False):
506 521
507 return ast.literal_eval(self.pulses)
522 if km:
523 unit2km = 1/self.rc_configuration.km2unit
524 return [(tup[0]*unit2km, tup[1]*unit2km) for tup in ast.literal_eval(self.pulses)]
525 else:
526 return ast.literal_eval(self.pulses)
508 527
509 528 def get_win_ref(self, params, tx_id, km2unit):
510 529
511 530 ref = self.rc_configuration.sampling_reference
512 531 codes = [line for line in self.get_lines(line_type__name='codes') if int(json.loads(line.params)['TX_ref'])==int(tx_id)]
513 532
514 533 if codes:
515 534 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit/len(json.loads(codes[0].params)['codes'][0])
516 535 else:
517 536 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit
518 537
519 538 if ref=='first_baud':
520 539 return int(1 + (tx_width + 1)/2 + params['first_height']*km2unit - params['resolution']*km2unit)
521 540 elif ref=='sub_baud':
522 541 return int(1 + params['first_height']*km2unit - params['resolution']*km2unit/2)
523 542 else:
524 543 return 0
525 544
526 545 def update_pulses(self):
527 546 '''
528 547 Update pulses field
529 548 '''
530 549
531 550 km2unit = self.rc_configuration.km2unit
532 551 us2unit = self.rc_configuration.us2unit
533 552 ipp = self.rc_configuration.ipp
534 553 ntx = self.rc_configuration.ntx
535 554 ipp_u = int(ipp*km2unit)
536 555 total = ipp_u*ntx if self.rc_configuration.total_units==0 else self.rc_configuration.total_units
537 556 y = []
538 557
539 558 if self.line_type.name=='tr':
540 559 tr_params = json.loads(self.params)
541 560
542 561 if tr_params['TX_ref'] in ('0', 0):
543 562 txs = self.get_lines(line_type__name='tx')
544 563 else:
545 564 txs = RCLine.objects.filter(pk=tr_params['TX_ref'])
546 565
547 566 for tx in txs:
548 567 params = json.loads(tx.params)
549 568
550 569 if float(params['pulse_width'])==0:
551 570 continue
552 571 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
553 572 width = float(params['pulse_width'])*km2unit+int(self.rc_configuration.time_before*us2unit)
554 573 before = 0
555 574 after = int(self.rc_configuration.time_after*us2unit)
556 575
557 576 y_tx = self.points(ntx, ipp_u, width,
558 577 delay=delays,
559 578 before=before,
560 579 after=after,
561 580 sync=self.rc_configuration.sync)
562 581
563 582 ranges = params['range'].split(',')
564 583
565 584 if len(ranges)>0 and ranges[0]<>'0':
566 585 y_tx = self.mask_ranges(y_tx, ranges)
567 586
568 587 tr_ranges = tr_params['range'].split(',')
569 588
570 589 if len(tr_ranges)>0 and tr_ranges[0]<>'0':
571 590 y_tx = self.mask_ranges(y_tx, tr_ranges)
572 591
573 592 y.extend(y_tx)
574 593
575 594 self.pulses = unicode(y)
576 595 y = self.array_to_points(self.pulses_as_array())
577 596
578 597 elif self.line_type.name=='tx':
579 598 params = json.loads(self.params)
580 599 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
581 600 width = float(params['pulse_width'])*km2unit
582 601
583 602 if width>0:
584 603 before = int(self.rc_configuration.time_before*us2unit)
585 604 after = 0
586 605
587 606 y = self.points(ntx, ipp_u, width,
588 607 delay=delays,
589 608 before=before,
590 609 after=after,
591 610 sync=self.rc_configuration.sync)
592 611
593 612 ranges = params['range'].split(',')
594 613
595 614 if len(ranges)>0 and ranges[0]<>'0':
596 615 y = self.mask_ranges(y, ranges)
597 616
598 617 elif self.line_type.name=='flip':
599 618 n = float(json.loads(self.params)['number_of_flips'])
600 619 width = n*ipp*km2unit
601 620 y = self.points(int((ntx+1)/(2*n)), ipp_u*n*2, width)
602 621
603 622 elif self.line_type.name=='codes':
604 623 params = json.loads(self.params)
605 624 tx = RCLine.objects.get(pk=params['TX_ref'])
606 625 tx_params = json.loads(tx.params)
607 626 delays = [float(d)*km2unit for d in tx_params['delays'].split(',') if d]
608 627 f = int(float(tx_params['pulse_width'])*km2unit)/len(params['codes'][0])
609 628 codes = [(np.fromstring(''.join([s*f for s in code]), dtype=np.uint8)-48).astype(np.int8) for code in params['codes']]
610 629 codes = [self.array_to_points(code) for code in codes]
611 630 n = len(codes)
612 631
613 632 for i, tup in enumerate(tx.pulses_as_points()):
614 633 code = codes[i%n]
615 634 y.extend([(c[0]+tup[0], c[1]+tup[0]) for c in code])
616 635
617 636 ranges = tx_params['range'].split(',')
618 637 if len(ranges)>0 and ranges[0]<>'0':
619 638 y = self.mask_ranges(y, ranges)
620 639
621 640 elif self.line_type.name=='sync':
622 641 params = json.loads(self.params)
623 642 n = ipp_u*ntx
624 643 if params['invert'] in ('1', 1):
625 644 y = [(n-1, n)]
626 645 else:
627 646 y = [(0, 1)]
628 647
629 648 elif self.line_type.name=='prog_pulses':
630 649 params = json.loads(self.params)
631 650 if int(params['periodic'])==0:
632 651 nntx = 1
633 652 nipp = ipp_u*ntx
634 653 else:
635 654 nntx = ntx
636 655 nipp = ipp_u
637 656
638 657 if 'params' in params and len(params['params'])>0:
639 658 for p in params['params']:
640 659 y_pp = self.points(nntx, nipp,
641 660 p['end']-p['begin'],
642 661 before=p['begin'])
643 662
644 663 y.extend(y_pp)
645 664
646 665 elif self.line_type.name=='windows':
647 666 params = json.loads(self.params)
648 667
649 668 if 'params' in params and len(params['params'])>0:
650 669 tr_params = json.loads(self.get_lines(line_type__name='tr')[0].params)
651 670 tr_ranges = tr_params['range'].split(',')
652 671 for p in params['params']:
653 672 y_win = self.points(ntx, ipp_u,
654 673 p['resolution']*p['number_of_samples']*km2unit,
655 674 before=int(self.rc_configuration.time_before*us2unit)+self.get_win_ref(p, params['TX_ref'], km2unit),
656 675 sync=self.rc_configuration.sync)
657 676
658 677 if len(tr_ranges)>0 and tr_ranges[0]<>'0':
659 678 y_win = self.mask_ranges(y_win, tr_ranges)
660 679
661 680 y.extend(y_win)
662 681
663 682 elif self.line_type.name=='mix':
664 683 values = self.rc_configuration.parameters.split('-')
665 684 confs = [RCConfiguration.objects.get(pk=value.split('|')[0]) for value in values]
666 685 modes = [value.split('|')[1] for value in values]
667 686 ops = [value.split('|')[2] for value in values]
668 687 delays = [value.split('|')[3] for value in values]
669 688 masks = [value.split('|')[4] for value in values]
670 689 mask = list('{:8b}'.format(int(masks[0])))
671 690 mask.reverse()
672 691 if mask[self.channel] in ('0', '', ' '):
673 692 y = np.zeros(confs[0].total_units, dtype=np.int8)
674 693 else:
675 694 y = confs[0].get_lines(channel=self.channel)[0].pulses_as_array()
676 695
677 696 for i in range(1, len(values)):
678 697 mask = list('{:8b}'.format(int(masks[i])))
679 698 mask.reverse()
680 699
681 700 if mask[self.channel] in ('0', '', ' '):
682 701 continue
683 702 Y = confs[i].get_lines(channel=self.channel)[0].pulses_as_array()
684 703 delay = float(delays[i])*km2unit
685 704
686 705 if modes[i]=='P':
687 706 if delay>0:
688 707 if delay<self.rc_configuration.ipp*km2unit and len(Y)==len(y):
689 708 y_temp = np.empty_like(Y)
690 709 y_temp[:delay] = 0
691 710 y_temp[delay:] = Y[:-delay]
692 711 elif delay+len(Y)>len(y):
693 712 y_new = np.zeros(delay+len(Y), dtype=np.int8)
694 713 y_new[:len(y)] = y
695 714 y = y_new
696 715 y_temp = np.zeros(delay+len(Y), dtype=np.int8)
697 716 y_temp[-len(Y):] = Y
698 717 elif delay+len(Y)==len(y):
699 718 y_temp = np.zeros(delay+len(Y))
700 719 y_temp[-len(Y):] = Y
701 720 elif delay+len(Y)<len(y):
702 721 y_temp = np.zeros(len(y), dtype=np.int8)
703 722 y_temp[delay:delay+len(Y)] = Y
704 723
705 724 if ops[i]=='OR':
706 725 y = y | y_temp
707 726 elif ops[i]=='XOR':
708 727 y = y ^ y_temp
709 728 elif ops[i]=='AND':
710 729 y = y & y_temp
711 730 elif ops[i]=='NAND':
712 731 y = y & ~y_temp
713 732 else:
714 733 y = np.concatenate([y, Y])
715 734
716 735 total = len(y)
717 736 y = self.array_to_points(y)
718 737
719 738 else:
720 739 y = []
721 740
722 741 if self.rc_configuration.total_units <> total:
723 742 self.rc_configuration.total_units = total
724 743 self.rc_configuration.save()
725 744
726 745 self.pulses = unicode(y)
727 746 self.save()
728 747
729 748 @staticmethod
730 749 def array_to_points(X):
731 750
732 751 d = X[1:]-X[:-1]
733 752
734 753 up = np.where(d==1)[0]
735 754 if X[0]==1:
736 755 up = np.concatenate((np.array([-1]), up))
737 756 up += 1
738 757
739 758 dw = np.where(d==-1)[0]
740 759 if X[-1]==1:
741 760 dw = np.concatenate((dw, np.array([len(X)-1])))
742 761 dw += 1
743 762
744 763 return [(tup[0], tup[1]) for tup in zip(up, dw)]
745 764
746 765 @staticmethod
747 766 def mask_ranges(Y, ranges):
748 767
749 768 y = [(0, 0) for __ in Y]
750 769
751 770 for index in ranges:
752 771 if '-' in index:
753 772 args = [int(a) for a in index.split('-')]
754 773 y[args[0]-1:args[1]] = Y[args[0]-1:args[1]]
755 774 else:
756 775 y[int(index-1)] = Y[int(index-1)]
757 776
758 777 return y
759 778
760 779 @staticmethod
761 780 def points(ntx, ipp, width, delay=[0], before=0, after=0, sync=0):
762 781
763 782 delays = len(delay)
764 783
765 784 Y = [(ipp*x+before+delay[x%delays], ipp*x+width+before+delay[x%delays]+after) for x in range(ntx)]
766 785
767 786 return Y No newline at end of file
@@ -1,71 +1,120
1 1 var km_fields = [];
2 2 var unit_fields = [];
3 3 var dc_fields = [];
4 4
5 5
6 6 function str2hz(s){
7 7
8 8 return 150000*Math.pow(parseFloat(s), -1);
9 9 }
10 10
11 11
12 12 function str2unit(s){
13 13 var km2unit = (20/3)*(parseFloat($('#id_clock_in').val())/parseFloat($('#id_clock_divider').val()));
14 14 var ret = "";
15 15 values = s.split(",");
16 16 for (i=0; i<values.length; i++) {
17 ret += Math.round(parseFloat(values[i]))*km2unit;
17 ret += Math.round(parseFloat(values[i])*km2unit);
18 ret += ",";
19 }
20 return ret.substring(0, ret.length-1);
21 }
22
23
24 function str2int(s){
25 var ret = "";
26 values = s.split(",");
27 for (i=0; i<values.length; i++) {
28 ret += Math.round(parseFloat(values[i]));
18 29 ret += ",";
19 30 }
20 31 return ret.substring(0, ret.length-1);
21 32 }
22 33
23 34
24 35 function str2km(s){
25 36 var km2unit = (20/3)*(parseFloat($('#id_clock_in').val())/parseFloat($('#id_clock_divider').val()));
26 37 var ret = "";
27 38 values = s.split(",");
28 39 for (i=0; i<values.length; i++) {
29 40 ret += parseFloat(values[i])/km2unit;
30 41 ret += ",";
31 42 }
32 43 return ret.substring(0, ret.length-1);
33 44 }
34 45
35 46 function str2dc(s){
36 47
37 48 return parseFloat(s)*100/parseFloat($('#id_ipp').val())
38 49 }
39 50
40 51
41 52 function updateUnits() {
42 53
43 54 for (j=0; j<km_fields.length; j++){
44 55 label_unit = "#"+km_fields[j]+"_unit";
45 56 label = "#"+km_fields[j];
46 57 $(label_unit).val(str2unit($(label).val()));
47 58 }
48 59 }
49 60
50 61
51 62 function updateDc() {
52 63
53 64 for (j=0; j<dc_fields.length; j++){
54 65 label_dc = "#"+dc_fields[j]+"_dc";
55 66 label = "#"+dc_fields[j];
56 67 $(label_dc).val(str2dc($(label).val()));
57 68 }
58 69 }
59 70
60 71
72 function updateWindows(label) {
73
74 if (label.indexOf("first_height")>0){
75 llabel = label.replace("first_height", "last_height");
76 rlabel = label.replace("first_height", "resolution");
77 nlabel = label.replace("first_height", "number_of_samples");
78 value = parseFloat($(label).val())+parseFloat($(rlabel).val())*(parseInt($(nlabel).val())-1);
79 $(llabel).val(value);
80 }
81
82 if (label.indexOf("resolution")>0){
83 llabel = label.replace("resolution", "last_height");
84 flabel = label.replace("resolution", "first_height");
85 nlabel = label.replace("resolution", "number_of_samples");
86 value = parseFloat($(flabel).val())+parseFloat($(label).val())*(parseInt($(nlabel).val())-1);
87 $(llabel).val(value);
88 }
89
90 if (label.indexOf("number_of_samples")>0){
91 llabel = label.replace("number_of_samples", "last_height");
92 rlabel = label.replace("number_of_samples", "resolution");
93 flabel = label.replace("number_of_samples", "first_height");
94 value = parseFloat($(flabel).val())+parseFloat($(rlabel).val())*(parseInt($(label).val())-1);
95 $(llabel).val(value);
96 }
97
98 if (label.indexOf("last_height")>0){
99 flabel = label.replace("last_height", "first_height");
100 rlabel = label.replace("last_height", "resolution");
101 nlabel = label.replace("last_height", "number_of_samples");
102
103 nvalue = Math.round((parseFloat($(label).val())-parseFloat($(flabel).val()))/parseFloat($(rlabel).val()))+1;
104 $(nlabel).val(nvalue);
105 value = parseFloat($(flabel).val())+parseFloat($(rlabel).val())*(nvalue-1);
106 $(label).val(value);
107 }
108
109 }
61 110
62 111 $("#id_clock_in").change(function() {
63 112 $("#id_clock").val(parseFloat($('#id_clock_in').val())/parseFloat($('#id_clock_divider').val()));
64 113 updateUnits();
65 114 });
66 115
67 116 $("#id_clock_divider").change(function() {
68 117 $("#id_clock").val(parseFloat($('#id_clock_in').val())/parseFloat($('#id_clock_divider').val()));
69 118 updateUnits();
70 119 });
71 120
@@ -1,18 +1,27
1 1 {% extends "dev_conf.html" %}
2 2 {% load static %}
3 3 {% load bootstrap3 %}
4 4 {% load main_tags %}
5 5
6 6 {% block extra-menu-actions %}
7 7 <li><a href="{{ dev_conf.get_absolute_url_plot }}" target="_blank"><span class="glyphicon glyphicon-picture" aria-hidden="true"></span> View Pulses </a></li>
8 8 {% endblock %}
9 9
10 10 {% block extra-content %}
11 11
12 12 <div class="clearfix"></div>
13 <h2>RC Lines</h2><hr>
13 <h2>RC Lines</h2>
14 <hr>
14 15 <div class="panel-group" id="div_lines" role="tablist" aria-multiselectable="true">
15 16 {% include "rc_lines.html" %}
16 17 </div>
17 18
18 19 {% endblock extra-content%}
20
21 {% block extra-js%}
22 <script type="text/javascript">
23 $("#bt_toggle").click(function() {
24 $(".panel-collapse").collapse('toggle')
25 });
26 </script>
27 {% endblock %} No newline at end of file
@@ -1,73 +1,77
1 1 {% extends "dev_conf_edit.html" %}
2 2 {% load bootstrap3 %}
3 3 {% load static %}
4 4
5 5 {% block extra-head %}
6 6 <style type="text/css">
7 7 /* show the move cursor as the user moves the mouse over the panel header.*/
8 8 .panel-default { cursor: move; }
9 9 </style>
10 10 <script src="{% static 'js/jquery-ui.min.js' %}"></script>
11 11
12 12 {% endblock %}
13 13
14 14 {% block content %}
15 15 <form class="form" method="post">
16 16 {% csrf_token %}
17 17 {% bootstrap_form form layout='horizontal' size='medium' %}
18 18 <div style="clear: both;"></div>
19 19 <h2>RC Lines</h2><hr>
20 20 <div class="panel-group" id="div_lines" role="tablist" aria-multiselectable="true">
21 21 {% include "rc_lines.html" %}
22 22 </div>
23 23 <div style="clear: both;"></div>
24 24 <br>
25 25 <div class="pull-right">
26 26 <button type="button" class="btn btn-primary" onclick="{% if previous %}window.location.replace('{{ previous }}');{% else %}history.go(-1);{% endif %}">Cancel</button>
27 27 <button type="button" class="btn btn-primary" id="bt_add_line">Add Line</button>
28 28 <button type="submit" class="btn btn-primary">{{button}}</button>
29 29 </div>
30 30 </form>
31 31 {% endblock %}
32 32
33 33 {% block extra-js%}
34 34
35 35 <script src="{% static 'js/cr.js' %}"></script>
36 36
37 37 <script type="text/javascript">
38 38
39 39 $("#div_lines").on("click", "button[name=bt_remove_line]", function(){
40 40 document.location = "/rc/{{dev_conf.id}}/line/"+$(this).val()+"/delete/";
41 41 });
42 42
43 43 $("#div_lines").on("click", "button[name=bt_remove_subline]", function(){
44 44 document.location = $(this).data('url');
45 45 });
46 46
47 47 $("#div_lines").on("click", "button[name=bt_add_subline]", function(){
48 48 document.location = "/rc/{{dev_conf.id}}/line/"+$(this).val()+"/add_subline/";
49 49 });
50 50
51 51 $("#div_lines").on("click", "button[name=bt_edit_codes]", function(){
52 52 document.location = "/rc/{{dev_conf.id}}/line/"+$(this).val()+"/codes/";
53 53 });
54 54
55 55 $("#bt_add_line").click(function() {
56 56 document.location = "{% url 'url_add_rc_line' dev_conf.id%}";
57 57 });
58 58
59 59 $(".panel-group").sortable({
60 60 //placeholder: "ui-state-highlight",
61 61 update: function( event, ui ) {
62 62 var sorted = $( ".panel-group" ).sortable( "serialize", { key: "item" } );
63 63 var url = "{% url 'url_update_rc_lines_position' dev_conf.id %}";
64 64 var csrf_token = "{{csrf_token}}";
65 65 $.post( url, { 'items': sorted, 'csrfmiddlewaretoken': csrf_token }, function(data){
66 66 $("#div_lines").html(data.html);
67 67 });
68 68 }
69 69 });
70 70
71 $("#bt_toggle").click(function() {
72 $(".panel-collapse").collapse('toggle')
73 });
74
71 75 </script>
72 76 {% endblock %}
73 77 No newline at end of file
@@ -1,41 +1,43
1 1 {% load bootstrap3 %}
2
2 <div class="pull-right"><button id="bt_toggle" type="button" class="btn btn-default btn-sm" >
3 Expand/Collapse
4 </button></div><br><br>
3 5 {% for line in rc_lines %}
4 6 <div class="panel panel-default" id="panel-{{line.id}}">
5 7 <div class="panel-heading" role="tab" id="heading{{line.id}}">
6 8 <h4 class="panel-title">
7 9 <a role="button" data-toggle="collapse" data-parent="#div_lines" href="#collapse{{line.id}}" aria-expanded="true" aria-controls="collapse{{line.id}}">
8 10 CH{{line.channel}} - {{line.get_name}}
9 11 </a>
10 12 {% if edit %}
11 13 <button type="button" class="btn-xs btn-default pull-right" name="bt_remove_line" value="{{line.pk}}"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button>
12 14 {% endif %}
13 15 </h4>
14 16 </div>
15 17 <div id="collapse{{line.id}}" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading{{line.id}}">
16 18 <div class="panel-body">
17 19 {% bootstrap_form line.form layout='horizontal' size='small' %}
18 20 <br><br>
19 21 {% for f in line.subforms %}
20 22 <div class="form-group form-group-sm">
21 23 <label class="col-md-3 control-label">{{line.line_type.name}}-{{ forloop.counter }}</label>
22 24 <div class="col-md-9">{% if edit %}<button type='button' name="bt_remove_subline" class="btn-xs btn-default" data-url="{% url 'url_remove_rc_subline' dev_conf.id line.id forloop.counter %}"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button>{% endif %}</div>
23 25 </div><div class="clearfix"></div>
24 26 {% bootstrap_form f layout='horizontal' size='small' %}
25 27 <div class="clearfix"></div>
26 28 {% endfor %}
27 29
28 30 {% if edit and line.subform %}
29 31 <br>
30 32 <button type="button" class="btn btn-sm btn-default" style="margin-left: 10px" name="bt_add_subline" value="{{line.pk}}">Add {{line.line_type.name}}</button>
31 33 {% endif %}
32 34
33 35 {% if edit and line.line_type.name == 'codes' %}
34 36 <br>
35 37 <button type="button" class="btn btn-sm btn-default" style="margin-left: 10px" name="bt_edit_codes" value="{{line.pk}}">Edit</button>
36 38 {% endif %}
37 39
38 40 </div>
39 41 </div>
40 42 </div>
41 43 {% endfor%}
@@ -1,24 +1,62
1 1 {% extends "dev_conf.html" %}
2 2 {% load static %}
3 3 {% load bootstrap3 %}
4 4 {% load main_tags %}
5 5
6 6 {% block extra-head %}
7 7 <link href="http://cdn.pydata.org/bokeh/release/bokeh-0.11.1.min.css" rel="stylesheet" type="text/css">
8 8 {% endblock %}
9 9
10 10 {% block content %}
11
11 12 <div id="div_plot">{{div}}</div>
12 13 <br>
13 <div class="col-md-2">1 Km =</div><div class="col-md-3">{{units}} Units</div>
14 <br>
15 <div class="col-md-2">1 Unit=</div><div class="col-md-3">{{kms}} Km</div>
14
15 <form class="form-horizontal">
16 <div class="form-group">
17 <label class="col-sm-2 control-label">Axis</label>
18 <div class="col-sm-4">
19 <select class="form-control" id='id_axis'>
20 <option value=0>Units</option>
21 {%if km_selected %}
22 <option value=1 selected>Km</option>
23 {%else%}
24 <option value=1>Km</option>
25 {%endif%}
26 </select>
27 </div>
28 </div>
29 <div class="form-group">
30 <label class="col-sm-2 control-label">1 Km</label>
31 <div class="col-sm-4">
32 <p class="form-control-static">{{units}} Units</p>
33 </div>
34 </div>
35 <div class="form-group">
36 <label class="col-sm-2 control-label">1 Unit</label>
37 <div class="col-sm-4">
38 <p class="form-control-static">{{kms}} Km</p>
39 </div>
40 </div>
41 </form>
42
16 43 {% endblock %}
17 44
18 45 {% block extra-js%}
19 46
20 47 <script src="{% static 'js/bokeh-0.11.1.min.js' %}"></script>
21
48
49 <script type="text/javascript">
50
51 $("#id_axis").change(function() {
52 if($(this).val()=='0'){
53 document.location = '?unit';
54 }else{
55 document.location = '?km'
56 }
57 });
58
59 </script>
22 60 {{script}}
23 61
24 62 {% endblock %} No newline at end of file
@@ -1,206 +1,209
1 1
2 2 import json
3 3
4 4 class RCFile(object):
5 5 '''
6 6 Class to handle Radar controller configuration files
7 7 '''
8 8
9 9 def __init__(self, f=None):
10 10
11 11 self.data = {}
12 12 if isinstance(f, str):
13 13 self.f = open(f)
14 14 self.name = f.split('/')[-1]
15 15 elif hasattr(f, 'read'):
16 16 self.f = f
17 17 self.name = f.name.split('/')[-1]
18 18 else:
19 19 self.f = f
20 20 self.name = None
21 21
22 22 if self.f:
23 23 if 'racp' in self.name:
24 24 self.parse_racp()
25 25 elif 'dat' in self.name:
26 26 self.parse_dat()
27 27 elif 'json' in self.name:
28 28 self.data = json.load(self.f)
29 29
30 30 self.f.close()
31 31
32 32 def get_line_parameters(self, data, line):
33 33
34 34 line_params = {}
35 35 for label in data:
36 36 if 'L%d' % line in label or '(Line %d)' % line in label or 'Line%d' % line in label:
37 37 line_params[label] = data[label]
38 38 return line_params
39 39
40 40 def parse_racp(self):
41 41
42 42 data = {}
43 43 raw_data = [s.strip() for s in self.f.readlines()]
44 44
45 45 for line in raw_data:
46 46 if line and '=' in line:
47 47 label, value = line.strip().split('=')
48 48 data[label] = value
49 49
50 50 self.data['experiment_type'] = data['EXPERIMENT TYPE']
51 51 self.data['header_version'] = data['HEADER VERSION']
52 52 self.data['name'] = data['EXPERIMENT NAME']
53 53 self.data['ipp'] = float(data['IPP'])
54 54 self.data['ntx'] = int(data['NTX'])
55 55
56 56 if 'CLOCK DIVIDER' in data:
57 57 self.data['clock_divider'] = int(data['CLOCK DIVIDER'])
58 58 else:
59 59 self.data['clock_divider'] = 1
60 60 self.data['clock_in'] = float(data['RELOJ'])*self.data['clock_divider']
61 61 self.data['clock'] = float(data['RELOJ'])
62 62 self.data['time_before'] = int(data['TR_BEFORE'])
63 63 self.data['time_after'] = int(data['TR_AFTER'])
64 64
65 65 if 'SYNCHRO DELAY' in data:
66 66 self.data['sync'] = int(data['SYNCHRO DELAY'])
67 67 else:
68 68 self.data['sync'] = 0
69 69 self.data['lines'] = []
70 70
71 71 if 'SAMPLING REFERENCE' in data:
72 72 if data['SAMPLING REFERENCE']=='MIDDLE OF FIRST BAUD':
73 73 self.data['sampling_reference'] = 'first_baud'
74 74 elif data['SAMPLING REFERENCE']=='MIDDLE OF FIRST SUB-BAUD':
75 75 self.data['sampling_reference'] = 'sub_baud'
76 76 else:
77 77 self.data['sampling_reference'] = 'none'
78 78
79 79 #Add TR line
80 80 if 'Pulse selection_TR' in data:
81 81 if 'A,' in data['Pulse selection_TR']:
82 82 rng = data['Pulse selection_TR'].replace('A,', '')
83 83 ref = 'TXA'
84 84 elif 'A' in data['Pulse selection_TR']:
85 85 rng = data['Pulse selection_TR'].replace('A', '')
86 86 ref = 'TXA'
87 87 elif 'B,' in data['Pulse selection_TR']:
88 88 rng = data['Pulse selection_TR'].replace('B,', '')
89 89 ref = 'TXB'
90 90 elif 'B' in data['Pulse selection_TR']:
91 91 rng = data['Pulse selection_TR'].replace('B', '')
92 92 ref = 'TXB'
93 93 else:
94 94 rng = data['Pulse selection_TR']
95 95 ref = '0'
96 96 line = {'type':'tr', 'range': rng if rng else '0', 'TX_ref':ref}
97 97 else:
98 98 line = {'type': 'tr', 'range': '0', 'TX_ref': '0'}
99 99
100 100 self.data['lines'].append(line)
101 101
102 102 #Add TX's lines
103 103 if 'TXA' in data:
104 104 line = {'type':'tx', 'pulse_width':data['TXA'], 'delays':'0'}
105 105 if 'Pulse selection_TXA' in data:
106 106 line['range'] = data['Pulse selection_TXA']
107 107 else:
108 108 line['range'] = '0'
109 109 self.data['lines'].append(line)
110 110 else:
111 111 self.data['lines'].append({'type':'tx', 'pulse_width':'0', 'delays':'0', 'range':'0'})
112 112
113 113 if 'TXB' in data:
114 114 line = {'type':'tx', 'pulse_width':data['TXB'], 'delays':'0'}
115 115 if 'Pulse selection_TXB' in data:
116 116 line['range'] = data['Pulse selection_TXB']
117 117 else:
118 118 line['range'] = '0'
119 119
120 120 if 'Number of Taus' in data:
121 121 delays = [data['TAU({0})'.format(i)] for i in range(int(data['Number of Taus']))]
122 122 line['delays'] = ','.join(delays)
123 123
124 124 self.data['lines'].append(line)
125 125 else:
126 126 self.data['lines'].append({'type':'tx', 'pulse_width':'0', 'delays':'0', 'range':'0'})
127 127
128 128 #Add Other lines (4-6)
129 129 for n in range(4, 7):
130 130 params = self.get_line_parameters(data, n)
131 131 labels = params.keys()
132 132
133 133 if 'L%d_FLIP' % n in labels:
134 134 line = {'type':'flip', 'number_of_flips':data['L%d_FLIP' % n]}
135 135 elif 'Code Type' in data and n==4:
136 136 line = {'type':'codes', 'code':data['Code Type'], 'TX_ref':data['L%d_REFERENCE' % n]}
137 137 if 'Number of Codes' in data:
138 138 line['codes'] = [data['COD({})'.format(x)] for x in range(int(data['Number of Codes']))]
139 139 elif 'Code Type (Line %d)' % n in labels:
140 140 line = {'type':'codes', 'code':data['Code Type (Line %d)' % n], 'TX_ref':data['L%d_REFERENCE' % n]}
141 141 if 'Number of Codes (Line %d)' % n in data:
142 142 line['codes'] = [data['L{}_COD({})'.format(n, x)] for x in range(int(data['Number of Codes (Line %d)' % n]))]
143 143 elif 'Sampling Windows (Line %d)' % n in data:
144 144 line = {'type':'windows', 'TX_ref':data['L%d_REFERENCE' % n]}
145 145 windows = []
146 146 for w in range(int(data['Sampling Windows (Line %d)' % n])):
147 147 windows.append({'first_height':float(data['L%d_H0(%d)' % (n, w)]),
148 'resolution':float(data['L%d_DH(%d)' % (n, w)]),
148 149 'number_of_samples':int(data['L%d_NSA(%d)' % (n, w)]),
149 'resolution':float(data['L%d_DH(%d)' % (n, w)])}
150 'last_height':float(data['L%d_DH(%d)' % (n, w)])*(int(data['L%d_NSA(%d)' % (n, w)])-1)+float(data['L%d_H0(%d)' % (n, w)])
151 }
150 152 )
151 153 line['params'] = windows
152 154 elif 'Line%d' % n in labels and data['Line%d' % n]=='Synchro':
153 155 line = {'type':'sync', 'invert':0}
154 156 elif 'L%d Number Of Portions' % n in labels:
155 157 line = {'type':'prog_pulses'}
156 158 if 'L%s Portions IPP Periodic' % n in data:
157 159 line['periodic'] = 1 if data['L%s Portions IPP Periodic' % n]=='YES' else 0
158 160 portions = []
159 161 x = raw_data.index('L%d Number Of Portions=%s' % (n, data['L%d Number Of Portions' % n]))
160 162 for w in range(int(data['L%d Number Of Portions' % n])):
161 163 begin = raw_data[x+1+2*w].split('=')[-1]
162 164 end = raw_data[x+2+2*w].split('=')[-1]
163 165 portions.append({'begin':int(begin),
164 166 'end':int(end)}
165 167 )
166 168 line['params'] = portions
167 169 elif 'FLIP1' in data and n==5:
168 170 line = {'type':'flip', 'number_of_flips':data['FLIP1']}
169 171 elif 'FLIP2' in data and n==6:
170 172 line = {'type':'flip', 'number_of_flips':data['FLIP2']}
171 173 else:
172 174 line = {'type':'none'}
173 175
174 176 self.data['lines'].append(line)
175 177
176 178 #Add line 7 (windows)
177 179 if 'Sampling Windows' in data:
178 180 line = {'type':'windows', 'TX_ref':data['L7_REFERENCE']}
179 181 windows = []
180 182 x = raw_data.index('Sampling Windows=%s' % data['Sampling Windows'])
181 183 for w in range(int(data['Sampling Windows'])):
182 184 h0 = raw_data[x+1+3*w].split('=')[-1]
183 185 nsa = raw_data[x+2+3*w].split('=')[-1]
184 186 dh = raw_data[x+3+3*w].split('=')[-1]
185 187 windows.append({'first_height':float(h0),
186 188 'number_of_samples':int(nsa),
187 'resolution':float(dh)}
189 'resolution':float(dh),
190 'last_height':float(h0)+float(dh)*(int(nsa)-1)}
188 191 )
189 192 line['params'] = windows
190 193 self.data['lines'].append(line)
191 194 else:
192 195 self.data['lines'].append({'type':'none'})
193 196
194 197 #Add line 8 (synchro inverted)
195 198 self.data['lines'].append({'type':'sync', 'invert':1})
196 199
197 200 return
198 201
199 202 def parse_dat(self):
200 203 pass
201 204
202 205
203 206 def get_json(self, indent=None):
204 207 return json.dumps(self.data, indent=indent)
205 208
206 209
@@ -1,373 +1,378
1 1
2 2 import json
3 3
4 4 from django.contrib import messages
5 5 from django.utils.safestring import mark_safe
6 6 from django.shortcuts import render, redirect, get_object_or_404, HttpResponse
7 7
8 8 from apps.main.models import Configuration, Experiment, Device
9 9 from apps.main.views import sidebar
10 10
11 11 from .models import RCConfiguration, RCLine, RCLineType, RCLineCode
12 12 from .forms import RCConfigurationForm, RCLineForm, RCLineViewForm, RCLineEditForm, RCImportForm, RCLineCodesForm
13 13
14 14
15 15 def conf(request, conf_id):
16 16
17 17 conf = get_object_or_404(RCConfiguration, pk=conf_id)
18 18
19 19 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
20 20
21 21 for line in lines:
22 22 params = json.loads(line.params)
23 23 line.form = RCLineViewForm(extra_fields=params, line=line)
24 24 if 'params' in params:
25 25 line.subforms = [RCLineViewForm(extra_fields=fields, line=line, subform=True) for fields in params['params']]
26 26
27 27 kwargs = {}
28 28 kwargs['dev_conf'] = conf
29 29 kwargs['rc_lines'] = lines
30 30 kwargs['dev_conf_keys'] = ['name', 'ipp_unit', 'ntx', 'clock_in', 'clock_divider', 'clock',
31 31 'time_before', 'time_after', 'sync', 'sampling_reference', 'control_tx', 'control_sw']
32 32
33 33 kwargs['title'] = 'RC Configuration'
34 34 kwargs['suptitle'] = 'Details'
35 35
36 36 kwargs['button'] = 'Edit Configuration'
37 37 ###### SIDEBAR ######
38 38 kwargs.update(sidebar(conf=conf))
39 39
40 40 return render(request, 'rc_conf.html', kwargs)
41 41
42 42
43 43 def conf_edit(request, conf_id):
44 44
45 45 conf = get_object_or_404(RCConfiguration, pk=conf_id)
46 46
47 47 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
48 48
49 49 for line in lines:
50 50 params = json.loads(line.params)
51 51 line.form = RCLineEditForm(conf=conf, line=line, extra_fields=params)
52 52 line.subform = False
53 53
54 54 if 'params' in params:
55 55 line.subforms = [RCLineEditForm(extra_fields=fields, line=line, subform=i) for i, fields in enumerate(params['params'])]
56 56 line.subform = True
57 57
58 58 if request.method=='GET':
59 59
60 60 form = RCConfigurationForm(instance=conf)
61 61
62 62 elif request.method=='POST':
63 63
64 64 line_data = {}
65 65 conf_data = {}
66 66 extras = []
67 67
68 68 #classified post fields
69 69 for label,value in request.POST.items():
70 70 if label=='csrfmiddlewaretoken':
71 71 continue
72 72
73 73 if label.count('|')==0:
74 74 conf_data[label] = value
75 75 continue
76 76
77 77 elif label.split('|')[0]<>'-1':
78 78 extras.append(label)
79 79 continue
80 80
81 81 x, pk, name = label.split('|')
82 82
83 83 if name=='codes':
84 84 value = [s for s in value.split('\r\n') if s]
85 85
86 86 if pk in line_data:
87 87 line_data[pk][name] = value
88 88 else:
89 89 line_data[pk] = {name:value}
90 90
91 91 #update conf
92 92 form = RCConfigurationForm(conf_data, instance=conf)
93 93
94 94 if form.is_valid():
95 95
96 96 form.save()
97 97
98 98 #update lines fields
99 99 extras.sort()
100 100 for label in extras:
101 101 x, pk, name = label.split('|')
102 102 if pk not in line_data:
103 103 line_data[pk] = {}
104 104 if 'params' not in line_data[pk]:
105 105 line_data[pk]['params'] = []
106 106 if len(line_data[pk]['params'])<int(x)+1:
107 107 line_data[pk]['params'].append({})
108 108 line_data[pk]['params'][int(x)][name] = float(request.POST[label])
109 109
110 110 for pk, params in line_data.items():
111 111 line = RCLine.objects.get(pk=pk)
112 112 if line.line_type.name in ('windows', 'prog_pulses'):
113 113 if 'params' not in params:
114 114 params['params'] = []
115 115 line.params = json.dumps(params)
116 116 line.save()
117 117
118 118 #update pulses field
119 119 conf.update_pulses()
120 120
121 121 messages.success(request, 'RC Configuration successfully updated')
122 122
123 123 return redirect(conf.get_absolute_url())
124 124
125 125 kwargs = {}
126 126 kwargs['dev_conf'] = conf
127 127 kwargs['form'] = form
128 128 kwargs['rc_lines'] = lines
129 129 kwargs['edit'] = True
130 130
131 131 kwargs['title'] = 'RC Configuration'
132 132 kwargs['suptitle'] = 'Edit'
133 133 kwargs['button'] = 'Update'
134 134 kwargs['previous'] = conf.get_absolute_url()
135 135
136 136 return render(request, 'rc_conf_edit.html', kwargs)
137 137
138 138
139 139 def add_line(request, conf_id, line_type_id=None, code_id=None):
140 140
141 141 conf = get_object_or_404(RCConfiguration, pk=conf_id)
142 142
143 143 if request.method=='GET':
144 144 if line_type_id:
145 145 line_type = get_object_or_404(RCLineType, pk=line_type_id)
146 146
147 147 if code_id:
148 148 form = RCLineForm(initial={'rc_configuration':conf_id, 'line_type': line_type_id, 'code_id': code_id},
149 149 extra_fields=json.loads(line_type.params))
150 150 else:
151 151 form = RCLineForm(initial={'rc_configuration':conf_id, 'line_type': line_type_id},
152 152 extra_fields=json.loads(line_type.params))
153 153 else:
154 154 line_type = {'id':0}
155 155 form = RCLineForm(initial={'rc_configuration':conf_id})
156 156
157 157 if request.method=='POST':
158 158
159 159 line_type = get_object_or_404(RCLineType, pk=line_type_id)
160 160 form = RCLineForm(request.POST,
161 161 extra_fields=json.loads(line_type.params))
162 162
163 163 if form.is_valid():
164 164 form.save()
165 165 form.instance.update_pulses()
166 166 return redirect('url_edit_rc_conf', conf.id)
167 167
168 168 kwargs = {}
169 169 kwargs['form'] = form
170 170 kwargs['title'] = 'RC Configuration'
171 171 kwargs['suptitle'] = 'Add Line'
172 172 kwargs['button'] = 'Add'
173 173 kwargs['previous'] = conf.get_absolute_url_edit()
174 174 kwargs['dev_conf'] = conf
175 175 kwargs['line_type'] = line_type
176 176
177 177 return render(request, 'rc_add_line.html', kwargs)
178 178
179 179 def edit_codes(request, conf_id, line_id, code_id=None):
180 180
181 181 conf = get_object_or_404(RCConfiguration, pk=conf_id)
182 182 line = get_object_or_404(RCLine, pk=line_id)
183 183 params = json.loads(line.params)
184 184
185 185 if request.method=='GET':
186 186 if code_id:
187 187 code = get_object_or_404(RCLineCode, pk=code_id)
188 188 form = RCLineCodesForm(instance=code)
189 189 else:
190 190 initial = {'code': params['code'],
191 191 'codes': params['codes'] if 'codes' in params else [],
192 192 'number_of_codes': len(params['codes']) if 'codes' in params else 0,
193 193 'bits_per_code': len(params['codes'][0]) if 'codes' in params else 0,
194 194 }
195 195 form = RCLineCodesForm(initial=initial)
196 196
197 197 if request.method=='POST':
198 198 form = RCLineCodesForm(request.POST)
199 199 if form.is_valid():
200 200 params['code'] = request.POST['code']
201 201 params['codes'] = [s for s in request.POST['codes'].split('\r\n') if s]
202 202 line.params = json.dumps(params)
203 203 line.save()
204 204 messages.success(request, 'Line: "%s" has been updated.' % line)
205 205 return redirect('url_edit_rc_conf', conf.id)
206 206
207 207 kwargs = {}
208 208 kwargs['form'] = form
209 209 kwargs['title'] = line
210 210 kwargs['suptitle'] = 'Edit'
211 211 kwargs['button'] = 'Update'
212 212 kwargs['dev_conf'] = conf
213 213 kwargs['previous'] = conf.get_absolute_url_edit()
214 214 kwargs['line'] = line
215 215
216 216 return render(request, 'rc_edit_codes.html', kwargs)
217 217
218 218 def add_subline(request, conf_id, line_id):
219 219
220 220 conf = get_object_or_404(RCConfiguration, pk=conf_id)
221 221 line = get_object_or_404(RCLine, pk=line_id)
222 222
223 223 if request.method == 'POST':
224 224 if line:
225 225 params = json.loads(line.params)
226 226 subparams = json.loads(line.line_type.params)
227 227 if 'params' in subparams:
228 228 dum = {}
229 229 for key, value in subparams['params'].items():
230 230 dum[key] = value['value']
231 231 params['params'].append(dum)
232 232 line.params = json.dumps(params)
233 233 line.save()
234 234 return redirect('url_edit_rc_conf', conf.id)
235 235
236 236 kwargs = {}
237 237
238 238 kwargs['title'] = 'Add new'
239 239 kwargs['suptitle'] = '%s to %s' % (line.line_type.name, line)
240 240
241 241 return render(request, 'confirm.html', kwargs)
242 242
243 243 def remove_line(request, conf_id, line_id):
244 244
245 245 conf = get_object_or_404(RCConfiguration, pk=conf_id)
246 246 line = get_object_or_404(RCLine, pk=line_id)
247 247
248 248 if request.method == 'POST':
249 249 if line:
250 250 try:
251 251 channel = line.channel
252 252 line.delete()
253 253 for ch in range(channel+1, RCLine.objects.filter(rc_configuration=conf).count()+1):
254 254 l = RCLine.objects.get(rc_configuration=conf, channel=ch)
255 255 l.channel = l.channel-1
256 256 l.save()
257 257 messages.success(request, 'Line: "%s" has been deleted.' % line)
258 258 except:
259 259 messages.error(request, 'Unable to delete line: "%s".' % line)
260 260
261 261 return redirect('url_edit_rc_conf', conf.id)
262 262
263 263 kwargs = {}
264 264
265 265 kwargs['object'] = line
266 266 kwargs['delete'] = True
267 267 kwargs['title'] = 'Delete'
268 268 kwargs['suptitle'] = 'Line'
269 269 kwargs['previous'] = conf.get_absolute_url_edit()
270 270 return render(request, 'confirm.html', kwargs)
271 271
272 272
273 273 def remove_subline(request, conf_id, line_id, subline_id):
274 274
275 275 conf = get_object_or_404(RCConfiguration, pk=conf_id)
276 276 line = get_object_or_404(RCLine, pk=line_id)
277 277
278 278 if request.method == 'POST':
279 279 if line:
280 280 params = json.loads(line.params)
281 281 params['params'].remove(params['params'][int(subline_id)-1])
282 282 line.params = json.dumps(params)
283 283 line.save()
284 284
285 285 return redirect('url_edit_rc_conf', conf.id)
286 286
287 287 kwargs = {}
288 288
289 289 kwargs['object'] = line
290 290 kwargs['object_name'] = line.line_type.name
291 291 kwargs['delete_view'] = True
292 292 kwargs['title'] = 'Confirm delete'
293 293
294 294 return render(request, 'confirm.html', kwargs)
295 295
296 296
297 297 def update_lines_position(request, conf_id):
298 298
299 299 conf = get_object_or_404(RCConfiguration, pk=conf_id)
300 300
301 301 if request.method=='POST':
302 302 ch = 0
303 303 for item in request.POST['items'].split('&'):
304 304 line = RCLine.objects.get(pk=item.split('=')[-1])
305 305 line.channel = ch
306 306 line.save()
307 307 ch += 1
308 308
309 309 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
310 310
311 311 for line in lines:
312 312 params = json.loads(line.params)
313 313 line.form = RCLineEditForm(conf=conf, line=line, extra_fields=params)
314 314
315 315 if 'params' in params:
316 316 line.subform = True
317 317 line.subforms = [RCLineEditForm(extra_fields=fields, line=line, subform=i) for i, fields in enumerate(params['params'])]
318 318
319 319 html = render(request, 'rc_lines.html', {'dev_conf':conf, 'rc_lines':lines, 'edit':True})
320 320 data = {'html': html.content}
321 321
322 322 return HttpResponse(json.dumps(data), content_type="application/json")
323 323 return redirect('url_edit_rc_conf', conf.id)
324 324
325 325
326 326 def import_file(request, conf_id):
327 327
328 328 conf = get_object_or_404(RCConfiguration, pk=conf_id)
329 329 if request.method=='POST':
330 330 form = RCImportForm(request.POST, request.FILES)
331 331 if form.is_valid():
332 332 try:
333 #if True:
333 334 conf.update_from_file(request.FILES['file_name'])
334 335 messages.success(request, 'Configuration "%s" loaded succesfully' % request.FILES['file_name'])
335 336 return redirect(conf.get_absolute_url_edit())
336 337
337 338 except Exception as e:
338 339 messages.error(request, 'Error parsing file: "%s" - %s' % (request.FILES['file_name'], e))
339 340
340 341 else:
341 342 messages.warning(request, 'Your current configuration will be replaced')
342 343 form = RCImportForm()
343 344
344 345 kwargs = {}
345 346 kwargs['form'] = form
346 347 kwargs['title'] = 'RC Configuration'
347 348 kwargs['suptitle'] = 'Import file'
348 349 kwargs['button'] = 'Upload'
349 350 kwargs['previous'] = conf.get_absolute_url()
350 351
351 352 return render(request, 'rc_import.html', kwargs)
352 353
353 354
354 355 def plot_pulses(request, conf_id):
355 356
356 357 conf = get_object_or_404(RCConfiguration, pk=conf_id)
357
358 script, div = conf.plot_pulses()
358 km = True if 'km' in request.GET else False
359
360 script, div = conf.plot_pulses(km=km)
359 361
360 362 kwargs = {}
361 363
362 364 kwargs['title'] = 'RC Pulses'
363 kwargs['suptitle'] = conf.name
365 kwargs['suptitle'] = conf.name
364 366 kwargs['div'] = mark_safe(div)
365 367 kwargs['script'] = mark_safe(script)
366 368 kwargs['units'] = conf.km2unit
367 369 kwargs['kms'] = 1/conf.km2unit
368 370
371 if km:
372 kwargs['km_selected'] = True
373
369 374 if 'json' in request.GET:
370 375 return HttpResponse(json.dumps({'div':mark_safe(div), 'script':mark_safe(script)}), content_type="application/json")
371 376 else:
372 377 return render(request, 'rc_pulses.html', kwargs)
373 378
@@ -1,283 +1,309
1 1
2 2 import ast
3 3 import json
4 4 from itertools import chain
5 5
6 6 from django import forms
7 7 from django.utils.safestring import mark_safe
8 8 from django.utils.encoding import force_unicode
9 9 from django.utils.html import conditional_escape
10 10
11 11
12 12 class KmUnitWidget(forms.widgets.TextInput):
13 13
14 14 def render(self, label, value, attrs=None):
15 15
16 16 if isinstance(value, (int, float)):
17 17 unit = int(value*attrs['km2unit'])
18 18 elif isinstance(value, basestring):
19 19 units = []
20 20 values = [s for s in value.split(',') if s]
21 21 for val in values:
22 22 units.append('{0:.0f}'.format(float(val)*attrs['km2unit']))
23 23
24 24 unit = ','.join(units)
25 25
26 26 disabled = 'disabled' if attrs.get('disabled', False) else ''
27 27 name = attrs.get('name', label)
28 28 if attrs['id'] in ('id_delays',):
29 29 input_type = 'text'
30 30 else:
31 31 input_type = 'number'
32 32
33 33 if 'line' in attrs:
34 label += '_{0}'.format(attrs['line'].pk)
34 label += '_{0}_{1}'.format(attrs['line'].pk, name.split('|')[0])
35 35
36 36 html = '''<div class="col-md-12 col-no-padding">
37 37 <div class="col-md-5 col-no-padding"><input type="{0}" step="any" {1} class="form-control" id="id_{2}" name="{3}" value="{4}"></div>
38 38 <div class="col-md-1 col-no-padding">Km</div>
39 39 <div class="col-md-5 col-no-padding"><input type="{0}" {1} class="form-control" id="id_{2}_unit" value="{5}"></div>
40 40 <div class="col-md-1 col-no-padding">Units</div></div><br>'''.format(input_type, disabled, label, name, value, unit)
41 41
42 42 script = '''<script type="text/javascript">
43 43 $(document).ready(function () {{
44 44
45 45 km_fields.push("id_{label}");
46 46 unit_fields.push("id_{label}_unit");
47 47
48 48 $("#id_{label}").change(function() {{
49 49 $("#id_{label}_unit").val(str2unit($(this).val()));
50 50 $("#id_{label}").val(str2km($("#id_{label}_unit").val()));
51 updateWindows("#id_{label}");
51 52 }});
52 53 $("#id_{label}_unit").change(function() {{
53 $(this).val(parseFloat($(this).val()));
54 $(this).val(str2int($(this).val()));
54 55 $("#id_{label}").val(str2km($(this).val()));
56 updateWindows("#id_{label}");
55 57 }});
56 58 }});
57 </script>'''.format(label=label)
59 </script>'''.format(label=label)
58 60
59 61 if disabled:
60 62 return mark_safe(html)
61 63 else:
62 64 return mark_safe(html+script)
63 65
64 66
65 67 class UnitKmWidget(forms.widgets.TextInput):
66 68
67 69 def render(self, label, value, attrs=None):
68 70
69 71 if isinstance(value, (int, float)):
70 72 km = value/attrs['km2unit']
71 73 elif isinstance(value, basestring):
72 74 kms = []
73 75 values = [s for s in value.split(',') if s]
74 76 for val in values:
75 77 kms.append('{0:.0f}'.format(float(val)/attrs['km2unit']))
76 78
77 79 km = ','.join(kms)
78 80
79 81 disabled = 'disabled' if attrs.get('disabled', False) else ''
80 82 name = attrs.get('name', label)
81 83
82 84 if 'line' in attrs:
83 label += '_{0}'.format(attrs['line'].pk)
85 label += '_{0}_{1}'.format(attrs['line'].pk, name.split('|')[0])
84 86
85 87 html = '''<div class="col-md-12 col-no-padding">
86 88 <div class="col-md-5 col-no-padding"><input type="number" {0} class="form-control" id="id_{1}_unit" name="{2}" value="{3}"></div>
87 89 <div class="col-md-1 col-no-padding">Units</div>
88 90 <div class="col-md-5 col-no-padding"><input type="number" step="any" {4} class="form-control" id="id_{5}" value="{6}"></div>
89 91 <div class="col-md-1 col-no-padding">Km</div></div>'''.format(disabled, label, name, value, disabled, label, km)
90 92
91 93 script = '''<script type="text/javascript">
92 94 $(document).ready(function () {{
93 95
94 96 km_fields.push("id_{label}");
95 97 unit_fields.push("id_{label}_unit");
96 98
97 99 $("#id_{label}").change(function() {{
98 100 $("#id_{label}_unit").val(str2unit($(this).val()));
99 101 }});
100 102 $("#id_{label}_unit").change(function() {{
101 103 $("#id_{label}").val(str2km($(this).val()));
102 104 }});
103 105 }});
104 106 </script>'''.format(label=label)
105 107
106 108 if disabled:
107 109 return mark_safe(html)
108 110 else:
109 111 return mark_safe(html+script)
110 112
111 113
112 114 class KmUnitHzWidget(forms.widgets.TextInput):
113 115
114 116 def render(self, label, value, attrs=None):
115 117
116 118 unit = float(value)*attrs['km2unit']
117 119 if unit%10==0:
118 120 unit = int(unit)
119 121 hz = 150000*float(value)**-1
120 122
121 123 disabled = 'disabled' if attrs.get('disabled', False) else ''
122 124 name = attrs.get('name', label)
123 125
124 126 if 'line' in attrs:
125 127 label += '_{0}'.format(attrs['line'].pk)
126 128
127 129 html = '''<div class="col-md-12 col-no-padding">
128 130 <div class="col-md-3 col-no-padding"><input type="number" step="any" {0} class="form-control" id="id_{1}" name="{2}" value="{3}"></div>
129 131 <div class="col-md-1 col-no-padding">Km</div>
130 132 <div class="col-md-3 col-no-padding"><input type="number" {4} class="form-control" id="id_{1}_unit" value="{5}"></div>
131 133 <div class="col-md-1 col-no-padding">Units</div>
132 134 <div class="col-md-3 col-no-padding"><input type="number" step="any" {4} class="form-control" id="id_{1}_hz" value="{6}"></div>
133 135 <div class="col-md-1 col-no-padding">Hz</div>
134 136 </div>'''.format(disabled, label, name, value, disabled, unit, hz)
135 137
136 138 script = '''<script type="text/javascript">
137 139 $(document).ready(function () {{
138 140 km_fields.push("id_{label}");
139 141 unit_fields.push("id_{label}_unit");
140 142 $("#id_{label}").change(function() {{
141 143 $("#id_{label}_unit").val(str2unit($(this).val()));
144 $("#id_{label}").val(str2km($("#id_{label}_unit").val()));
142 145 $("#id_{label}_hz").val(str2hz($(this).val()));
143 146 updateDc();
144 147 }});
145 148 $("#id_{label}_unit").change(function() {{
146 149 $(this).val(Math.round(parseFloat($(this).val())/10)*10);
147 150 $("#id_{label}").val(str2km($(this).val()));
148 151 $("#id_{label}_hz").val(str2hz($("#id_{label}").val()));
149 152 updateDc();
150 153 }});
151 154 $("#id_{label}_hz").change(function() {{
152 155 $("#id_{label}").val(str2hz($(this).val()));
153 156 $("#id_{label}_unit").val(str2unit($("#id_{label}").val()));
154 157 updateDc();
155 158 }});
156 159 }});
157 160 </script>'''.format(label=label)
158 161
159 162 if disabled:
160 163 return mark_safe(html)
161 164 else:
162 165 return mark_safe(html+script)
163 166
164 167
165 168 class KmUnitDcWidget(forms.widgets.TextInput):
166 169
167 170 def render(self, label, value, attrs=None):
168 171
169 172 unit = int(float(value)*attrs['km2unit'])
170 173
171 174 disabled = 'disabled' if attrs.get('disabled', False) else ''
172 175 name = attrs.get('name', label)
173 176
174 177 label += '_{0}'.format(attrs['line'].pk)
175 178
176 179 dc = float(json.loads(attrs['line'].params)['pulse_width'])*100/attrs['line'].rc_configuration.ipp
177 180
178 181 html = '''<div class="col-md-12 col-no-padding">
179 182 <div class="col-md-3 col-no-padding"><input type="number" step="any" {0} class="form-control" id="id_{1}" name="{2}" value="{3}"></div>
180 183 <div class="col-md-1 col-no-padding">Km</div>
181 184 <div class="col-md-3 col-no-padding"><input type="number" {4} class="form-control" id="id_{1}_unit" value="{5}"></div>
182 185 <div class="col-md-1 col-no-padding">Units</div>
183 186 <div class="col-md-3 col-no-padding"><input type="number" step="any" {4} class="form-control" id="id_{1}_dc" value="{6}"></div>
184 187 <div class="col-md-1 col-no-padding">DC[%]</div>
185 188 </div>'''.format(disabled, label, name, value, disabled, unit, dc)
186 189
187 190 script = '''<script type="text/javascript">
188 191 $(document).ready(function () {{
189 192 km_fields.push("id_{label}");
190 193 unit_fields.push("id_{label}_unit");
191 194 dc_fields.push("id_{label}");
192 195 $("#id_{label}").change(function() {{
193 196 $("#id_{label}_unit").val(str2unit($(this).val()));
197 $("#id_{label}").val(str2km($("#id_{label}_unit").val()));
194 198 $("#id_{label}_dc").val(str2dc($("#id_{label}").val()));
195 199 }});
196 200 $("#id_{label}_unit").change(function() {{
197 201 $("#id_{label}").val(str2km($(this).val()));
198 202 $("#id_{label}_dc").val(str2dc($("#id_{label}").val()));
199 203 }});
200 204
201 205 $("#id_{label}_dc").change(function() {{
202 206 $("#id_{label}").val(parseFloat($(this).val())*100/parseFloat($("#id_ipp").val()));
203 207 $("#id_{label}_unit").val(str2unit($("#id_{label}").val()));
204 208 }});
205 209 }});
206 210 </script>'''.format(label=label)
207 211
208 212 if disabled:
209 213 return mark_safe(html)
210 214 else:
211 215 return mark_safe(html+script)
212 216
213 217
214 218 class DefaultWidget(forms.widgets.TextInput):
215 219
216 220 def render(self, label, value, attrs=None):
217 221
218 222 disabled = 'disabled' if attrs.get('disabled', False) else ''
223 itype = 'number' if label in ('number_of_samples', 'last_height') else 'text'
219 224 name = attrs.get('name', label)
225 if 'line' in attrs:
226 label += '_{0}_{1}'.format(attrs['line'].pk, name.split('|')[0])
227 html = '<div class="col-md-12 col-no-padding"><div class="col-md-5 col-no-padding"><input {0} type="{1}" class="form-control" id="id_{2}" name="{3}" value="{4}"></div></div>'.format(disabled, itype, label, name, value)
228
229 if 'last_height' in label or 'number_of_samples' in label:
230 script = '''<script type="text/javascript">
231 $(document).ready(function () {{
232
233 $("#id_{label}").change(function() {{
234 updateWindows("#id_{label}");
235 }});
236
237 }});
238 </script>'''.format(label=label)
239 else:
240 script = ''
241
242 if disabled:
243 return mark_safe(html)
244 else:
245 return mark_safe(html+script)
246
220 247
221 html = '<div class="col-md-12 col-no-padding"><div class="col-md-5 col-no-padding"><input {0} type="text" class="form-control" id="id_{1}" name="{2}" value="{3}"></div></div>'.format(disabled, label, name, value)
222 248
223 249 return mark_safe(html)
224 250
225 251
226 252 class HiddenWidget(forms.widgets.HiddenInput):
227 253
228 254 def render(self, label, value, attrs=None):
229 255
230 256 disabled = 'disabled' if attrs.get('disabled', False) else ''
231 257 name = self.attrs.get('name', label)
232 258
233 259 html = '<input {0} type="hidden" class="form-control" id="id_{1}" name="{2}" value="{3}">'.format(disabled, label, name, value)
234 260
235 261 return mark_safe(html)
236 262
237 263
238 264 class CodesWidget(forms.widgets.Textarea):
239 265
240 266 def render(self, label, value, attrs=None):
241 267
242 268 disabled = 'disabled' if attrs.get('disabled', False) else ''
243 269 name = attrs.get('name', label)
244 270
245 271 if '[' in value:
246 272 value = ast.literal_eval(value)
247 273
248 274 if isinstance(value, list):
249 275 codes = '\r\n'.join(value)
250 276 else:
251 277 codes = value
252 278
253 279 html = '<textarea rows="5" {0} class="form-control" id="id_{1}" name="{2}" style="white-space:nowrap; overflow:scroll;">{3}</textarea>'.format(disabled, label, name, codes)
254 280
255 281 return mark_safe(html)
256 282
257 283 class HCheckboxSelectMultiple(forms.CheckboxSelectMultiple):
258 284
259 285 def render(self, name, value, attrs=None, choices=()):
260 286
261 287 if value is None: value = []
262 288 has_id = attrs and 'id' in attrs
263 289 final_attrs = self.build_attrs(attrs, name=name)
264 290 output = [u'<br><ul>']
265 291 # Normalize to strings
266 292 str_values = set([force_unicode(v) for v in value])
267 293 for i, (option_value, option_label) in enumerate(chain(self.choices, choices)):
268 294 # If an ID attribute was given, add a numeric index as a suffix,
269 295 # so that the checkboxes don't all have the same ID attribute.
270 296 if has_id:
271 297 final_attrs = dict(final_attrs, id='%s_%s' % (attrs['id'], i))
272 298 label_for = u' for="%s"' % final_attrs['id']
273 299 else:
274 300 label_for = ''
275 301
276 302 cb = forms.CheckboxInput(final_attrs, check_test=lambda value: value in str_values)
277 303 option_value = force_unicode(option_value)
278 304 rendered_cb = cb.render(name, option_value)
279 305 option_label = conditional_escape(force_unicode(option_label))
280 306 output.append(u'<span><label%s>%s %s</label></span>' % (label_for, rendered_cb, option_label))
281 307 output.append(u'</div><br>')
282 308 return mark_safe(u'\n'.join(output))
283 309 No newline at end of file
@@ -1,135 +1,153
1 1 '''
2 2 Created on Dec 2, 2014
3 3
4 4 @author: Miguel Urco
5 5
6 6 eth_device decorator is used to implement an api to ethernet devices.
7 7 When eth_device decorator is used it adds two parameters to any function (ip and port)
8 8
9 9 #Definition
10 10
11 11 @eth_device
12 12 def enable_rf()
13 13 cmd = "xxxxx"
14 14 payload = "xxxxxx"
15 15
16 16 return cmd, payload
17 17
18 18 #How to call this function:
19 19 answer = enable_rf(ip, port)
20 20
21 21 '''
22 22 import data
23 23
24 24 from devices.jro_device import eth_device, IdClass
25 25
26 26 ID_CLASS = IdClass["rc"]
27 27
28 28 CMD_RESET =0X01
29 29 CMD_ENABLE =0X02
30 30 CMD_CHANGEIP =0X03
31 31 CMD_STATUS =0X04
32 32 CMD_DISABLE =0X02
33 33 CMD_ECHO =0XFE
34 34
35 35 RC_CMD_RESET =0X10
36 36 RC_CMD_WRITE =0x50
37 37 RC_CMD_READ =0x8000
38 RC_CMD_ENABLE =0X24
39 RC_CMD_DISABLE =0X00
38 40
39 41 @eth_device(ID_CLASS)
40 42 def reset():
41 43
42 44 cmd = CMD_RESET
43 45 payload = ""
44 46
45 47 return cmd, payload
46 48
47 49 @eth_device(ID_CLASS)
48 50 def change_ip(ip, mask="255.255.255.0", gateway="0.0.0.0"):
49 51
50 52 cmd = CMD_CHANGEIP
51 53 payload = ip + '/' + mask + '/' + gateway
52 54
53 55 return cmd, payload
54 56
55 57 @eth_device(ID_CLASS)
56 58 def status():
57 59
58 60 cmd = CMD_STATUS
59 61 payload = ""
60 62
61 63 return cmd, payload
62 64
63 65 @eth_device(ID_CLASS)
64 66 def echo():
65 67
66 68 cmd = CMD_ECHO
67 69 payload = ""
68 70
69 71 return cmd, payload
70 72
71 73 @eth_device(ID_CLASS)
74 def enable():
75
76 cmd = RC_CMD_ENABLE
77 payload = chr(0x01)
78
79 return cmd, payload
80
81 @eth_device(ID_CLASS)
82 def disable():
83
84 cmd = RC_CMD_DISABLE
85 payload = chr(0x00)
86
87 return cmd, payload
88
89 @eth_device(ID_CLASS)
72 90 def read_all_device():
73 91
74 92 payload = ""
75 93
76 return CR_CMD_READ, payload
94 return RC_CMD_READ, payload
77 95
78 96 @eth_device(ID_CLASS)
79 97 def write_all_device(payload):
80 98
81 return CR_CMD_WRITE, payload
99 return RC_CMD_WRITE, payload
82 100
83 101 def read_config(ip, port):
84 102 """
85 103 Output:
86 104 parms : Dictionary with keys
87 105
88 106 """
89 107 payload = read_all_device(ip, port)
90 108
91 109 return data.rc_str_to_dict(payload)
92 110
93 111 def write_config(ip, port, parms):
94 112 """
95 113 Input:
96 114 ip :
97 115 port :
98 116 parms : Dictionary with keys
99 117
100 118 """
101 119
102 payload = data.dict_to_rc_str(parms)
120 payload = write_ram_memory(parms['pulses'], parms['delays'])
103 121
104 122 answer = write_all_device(ip, port, payload)
105 123
106 124 return answer
107 125
108 126 def __get_low_byte(valor):
109 127
110 return ord(valor & 0x00FF)
128 return ord(valor & 0x00FF)
111 129
112 130 def __get_high_byte(valor):
113 131
114 return ord((valor & 0xFF00) >> 8)
132 return ord((valor & 0xFF00) >> 8)
133
115 134
116 @eth_device(ID_CLASS)
117 135 def write_ram_memory(vector_valores, vector_tiempos):
118 136
119 137 l1 = len(vector_valores)
120 138 l2 = len(vector_tiempos)
121 139
122 140 cad = ""
123 141
124 142 for i in range(l1):
125 cad += ord(84) + __get_low_byte(vector_valores[i]) + ord(85) + __get_high_byte(vector_valores[i]) + \
143 cad += ord(84) + __get_low_byte(vector_valores[i]) + ord(85) + __get_high_byte(vector_valores[i]) + \
126 144 ord(84) + __get_low_byte(vector_tiempos[i]) + ord(85) + __get_high_byte(vector_tiempos[i])
127 145
128 return RC_CMD_WRITE, cad
146 return cad
129 147
130 148 if __name__ == '__main__':
131 149 ip = "10.10.20.150"
132 150 port = 2000
133 151
134 152 print status(ip, port)
135 153 print read_config(ip, port) No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now