##// END OF EJS Templates
RC files have been updated...
Fiorella Quino -
r264:17ec69be4c00
parent child
Show More
@@ -1,382 +1,382
1 import os
1 import os
2 import json
2 import json
3
3
4 from django import forms
4 from django import forms
5 from django.utils.safestring import mark_safe
5 from django.utils.safestring import mark_safe
6 from apps.main.models import Device
6 from apps.main.models import Device
7 from apps.main.forms import add_empty_choice
7 from apps.main.forms import add_empty_choice
8 from .models import RCConfiguration, RCLine, RCLineType, RCLineCode
8 from .models import RCConfiguration, RCLine, RCLineType, RCLineCode
9 from .widgets import KmUnitWidget, KmUnitHzWidget, KmUnitDcWidget, UnitKmWidget, DefaultWidget, CodesWidget, HiddenWidget, HCheckboxSelectMultiple
9 from .widgets import KmUnitWidget, KmUnitHzWidget, KmUnitDcWidget, UnitKmWidget, DefaultWidget, CodesWidget, HiddenWidget, HCheckboxSelectMultiple
10
10
11 def create_choices_from_model(model, conf_id, all_choice=False):
11 def create_choices_from_model(model, conf_id, all_choice=False):
12
12
13 if model=='RCLine':
13 if model=='RCLine':
14 instance = RCConfiguration.objects.get(pk=conf_id)
14 instance = RCConfiguration.objects.get(pk=conf_id)
15 choices = [(line.pk, line.get_name()) for line in instance.get_lines(line_type__name='tx')]
15 choices = [(line.pk, line.get_name()) for line in instance.get_lines(line_type__name='tx')]
16 if all_choice:
16 if all_choice:
17 choices = add_empty_choice(choices, label='All')
17 choices = add_empty_choice(choices, label='All')
18 else:
18 else:
19 instance = globals()[model]
19 instance = globals()[model]
20 choices = instance.objects.all().values_list('pk', 'name')
20 choices = instance.objects.all().values_list('pk', 'name')
21
21
22 return choices
22 return choices
23
23
24
24
25 class ExtFileField(forms.FileField):
25 class ExtFileField(forms.FileField):
26 """
26 """
27 Same as forms.FileField, but you can specify a file extension whitelist.
27 Same as forms.FileField, but you can specify a file extension whitelist.
28
28
29 >>> from django.core.files.uploadedfile import SimpleUploadedFile
29 >>> from django.core.files.uploadedfile import SimpleUploadedFile
30 >>>
30 >>>
31 >>> t = ExtFileField(ext_whitelist=(".pdf", ".txt"))
31 >>> t = ExtFileField(ext_whitelist=(".pdf", ".txt"))
32 >>>
32 >>>
33 >>> t.clean(SimpleUploadedFile('filename.pdf', 'Some File Content'))
33 >>> t.clean(SimpleUploadedFile('filename.pdf', 'Some File Content'))
34 >>> t.clean(SimpleUploadedFile('filename.txt', 'Some File Content'))
34 >>> t.clean(SimpleUploadedFile('filename.txt', 'Some File Content'))
35 >>>
35 >>>
36 >>> t.clean(SimpleUploadedFile('filename.exe', 'Some File Content'))
36 >>> t.clean(SimpleUploadedFile('filename.exe', 'Some File Content'))
37 Traceback (most recent call last):
37 Traceback (most recent call last):
38 ...
38 ...
39 ValidationError: [u'Not allowed filetype!']
39 ValidationError: [u'Not allowed filetype!']
40 """
40 """
41 def __init__(self, *args, **kwargs):
41 def __init__(self, *args, **kwargs):
42 extensions = kwargs.pop("extensions")
42 extensions = kwargs.pop("extensions")
43 self.extensions = [i.lower() for i in extensions]
43 self.extensions = [i.lower() for i in extensions]
44
44
45 super(ExtFileField, self).__init__(*args, **kwargs)
45 super(ExtFileField, self).__init__(*args, **kwargs)
46
46
47 def clean(self, *args, **kwargs):
47 def clean(self, *args, **kwargs):
48 data = super(ExtFileField, self).clean(*args, **kwargs)
48 data = super(ExtFileField, self).clean(*args, **kwargs)
49 filename = data.name
49 filename = data.name
50 ext = os.path.splitext(filename)[1]
50 ext = os.path.splitext(filename)[1]
51 ext = ext.lower()
51 ext = ext.lower()
52 if ext not in self.extensions:
52 if ext not in self.extensions:
53 raise forms.ValidationError('Not allowed file type: %s' % ext)
53 raise forms.ValidationError('Not allowed file type: %s' % ext)
54
54
55
55
56 class RCConfigurationForm(forms.ModelForm):
56 class RCConfigurationForm(forms.ModelForm):
57
57
58 def __init__(self, *args, **kwargs):
58 def __init__(self, *args, **kwargs):
59 super(RCConfigurationForm, self).__init__(*args, **kwargs)
59 super(RCConfigurationForm, self).__init__(*args, **kwargs)
60
60
61 instance = getattr(self, 'instance', None)
61 instance = getattr(self, 'instance', None)
62
62
63 if instance and instance.pk:
63 if instance and instance.pk:
64
64
65 devices = Device.objects.filter(device_type__name='rc')
65 devices = Device.objects.filter(device_type__name='rc')
66 if instance.experiment:
66 if instance.experiment:
67 self.fields['experiment'].widget.attrs['read_only'] = True
67 self.fields['experiment'].widget.attrs['read_only'] = True
68 #self.fields['experiment'].widget.choices = [(instance.experiment.id, instance.experiment)]
68 #self.fields['experiment'].widget.choices = [(instance.experiment.id, instance.experiment)]
69 self.fields['device'].widget.choices = [(device.id, device) for device in devices]
69 self.fields['device'].widget.choices = [(device.id, device) for device in devices]
70 self.fields['ipp'].widget = KmUnitHzWidget(attrs={'km2unit':instance.km2unit})
70 self.fields['ipp'].widget = KmUnitHzWidget(attrs={'km2unit':instance.km2unit})
71 self.fields['clock'].widget.attrs['readonly'] = True
71 self.fields['clock'].widget.attrs['readonly'] = True
72
72
73 self.fields['time_before'].label = mark_safe(self.fields['time_before'].label)
73 self.fields['time_before'].label = mark_safe(self.fields['time_before'].label)
74 self.fields['time_after'].label = mark_safe(self.fields['time_after'].label)
74 self.fields['time_after'].label = mark_safe(self.fields['time_after'].label)
75
75
76 if 'initial' in kwargs and 'experiment' in kwargs['initial'] and kwargs['initial']['experiment'] not in (0, '0'):
76 if 'initial' in kwargs and 'experiment' in kwargs['initial'] and kwargs['initial']['experiment'] not in (0, '0'):
77 self.fields['experiment'].widget.attrs['readonly'] = True
77 self.fields['experiment'].widget.attrs['readonly'] = True
78
78
79 class Meta:
79 class Meta:
80 model = RCConfiguration
80 model = RCConfiguration
81 exclude = ('type', 'parameters', 'status', 'total_units', 'mix')
81 exclude = ('type', 'parameters', 'status', 'total_units', 'mix')
82
82
83 def clean(self):
83 def clean(self):
84 form_data = super(RCConfigurationForm, self).clean()
84 form_data = super(RCConfigurationForm, self).clean()
85
85
86 if 'clock_divider' in form_data:
86 if 'clock_divider' in form_data:
87 if form_data['clock_divider']<1:
87 if form_data['clock_divider']<1:
88 self.add_error('clock_divider', 'Invalid Value')
88 self.add_error('clock_divider', 'Invalid Value')
89 else:
89 #else:
90 if form_data['ipp']*(20./3*(form_data['clock_in']/form_data['clock_divider']))%10!=0:
90 # if form_data['ipp']*(20./3*(form_data['clock_in']/form_data['clock_divider']))%10!=0:
91 self.add_error('ipp', 'Invalid IPP units={}'.format(form_data['ipp']*(20./3*(form_data['clock_in']/form_data['clock_divider']))))
91 # self.add_error('ipp', 'Invalid IPP units={}'.format(form_data['ipp']*(20./3*(form_data['clock_in']/form_data['clock_divider']))))
92
92
93 return form_data
93 return form_data
94
94
95 def save(self):
95 def save(self):
96 conf = super(RCConfigurationForm, self).save()
96 conf = super(RCConfigurationForm, self).save()
97 conf.total_units = conf.ipp*conf.ntx*conf.km2unit
97 conf.total_units = conf.ipp*conf.ntx*conf.km2unit
98 conf.save()
98 conf.save()
99 return conf
99 return conf
100
100
101
101
102 class RCMixConfigurationForm(forms.Form):
102 class RCMixConfigurationForm(forms.Form):
103
103
104 clock_in = forms.CharField(widget=forms.HiddenInput())
104 clock_in = forms.CharField(widget=forms.HiddenInput())
105 clock_divider = forms.CharField(widget=forms.HiddenInput())
105 clock_divider = forms.CharField(widget=forms.HiddenInput())
106 name = forms.CharField()
106 name = forms.CharField()
107 experiment = forms.ChoiceField()
107 experiment = forms.ChoiceField()
108 mode = forms.ChoiceField(widget=forms.RadioSelect(),
108 mode = forms.ChoiceField(widget=forms.RadioSelect(),
109 choices=[(0, 'Parallel'), (1, 'Sequence')],
109 choices=[(0, 'Parallel'), (1, 'Sequence')],
110 initial=0)
110 initial=0)
111 operation = forms.ChoiceField(widget=forms.RadioSelect(),
111 operation = forms.ChoiceField(widget=forms.RadioSelect(),
112 choices=[(0, 'OR'), (1, 'XOR'), (2, 'AND'), (3, 'NAND')],
112 choices=[(0, 'OR'), (1, 'XOR'), (2, 'AND'), (3, 'NAND')],
113 initial=1)
113 initial=1)
114 delay = forms.CharField()
114 delay = forms.CharField()
115 mask = forms.MultipleChoiceField(choices=[(0, 'L1'),(1, 'L2'),(2, 'L3'),(3, 'L4'),(4, 'L5'),(5, 'L6'),(6, 'L7'),(7, 'L8')],
115 mask = forms.MultipleChoiceField(choices=[(0, 'L1'),(1, 'L2'),(2, 'L3'),(3, 'L4'),(4, 'L5'),(5, 'L6'),(6, 'L7'),(7, 'L8')],
116 widget=HCheckboxSelectMultiple())
116 widget=HCheckboxSelectMultiple())
117 result = forms.CharField(required=False,
117 result = forms.CharField(required=False,
118 widget=forms.Textarea(attrs={'readonly':True, 'rows':5, 'class':'tabuled'}))
118 widget=forms.Textarea(attrs={'readonly':True, 'rows':5, 'class':'tabuled'}))
119
119
120 def __init__(self, *args, **kwargs):
120 def __init__(self, *args, **kwargs):
121 confs = kwargs.pop('confs', [])
121 confs = kwargs.pop('confs', [])
122 if confs:
122 if confs:
123 km2unit = confs[0].km2unit
123 km2unit = confs[0].km2unit
124 clock_in = confs[0].clock_in
124 clock_in = confs[0].clock_in
125 clock_divider = confs[0].clock_divider
125 clock_divider = confs[0].clock_divider
126 else:
126 else:
127 km2unit = clock_in = clock_divider = 0
127 km2unit = clock_in = clock_divider = 0
128 super(RCMixConfigurationForm, self).__init__(*args, **kwargs)
128 super(RCMixConfigurationForm, self).__init__(*args, **kwargs)
129 self.fields['experiment'].choices = [(conf.pk, '{} | {}'.format(conf.pk, conf.name)) for conf in confs]
129 self.fields['experiment'].choices = [(conf.pk, '{} | {}'.format(conf.pk, conf.name)) for conf in confs]
130 self.fields['delay'].widget = KmUnitWidget(attrs = {'km2unit':km2unit})
130 self.fields['delay'].widget = KmUnitWidget(attrs = {'km2unit':km2unit})
131 self.fields['clock_in'].initial = clock_in
131 self.fields['clock_in'].initial = clock_in
132 self.fields['clock_divider'].initial = clock_divider
132 self.fields['clock_divider'].initial = clock_divider
133
133
134
134
135 class RCLineForm(forms.ModelForm):
135 class RCLineForm(forms.ModelForm):
136
136
137 def __init__(self, *args, **kwargs):
137 def __init__(self, *args, **kwargs):
138 self.extra_fields = kwargs.pop('extra_fields', [])
138 self.extra_fields = kwargs.pop('extra_fields', [])
139 super(RCLineForm, self).__init__(*args, **kwargs)
139 super(RCLineForm, self).__init__(*args, **kwargs)
140
140
141 if 'initial' in kwargs and 'line_type' in kwargs['initial']:
141 if 'initial' in kwargs and 'line_type' in kwargs['initial']:
142 line_type = RCLineType.objects.get(pk=kwargs['initial']['line_type'])
142 line_type = RCLineType.objects.get(pk=kwargs['initial']['line_type'])
143
143
144 if 'code_id' in kwargs['initial']:
144 if 'code_id' in kwargs['initial']:
145 model_initial = kwargs['initial']['code_id']
145 model_initial = kwargs['initial']['code_id']
146 else:
146 else:
147 model_initial = 0
147 model_initial = 0
148
148
149 params = json.loads(line_type.params)
149 params = json.loads(line_type.params)
150
150
151 for label, value in self.extra_fields.items():
151 for label, value in self.extra_fields.items():
152 if label=='params':
152 if label=='params':
153 continue
153 continue
154
154
155 if 'model' in params[label]:
155 if 'model' in params[label]:
156 self.fields[label] = forms.ChoiceField(choices=create_choices_from_model(params[label]['model'],
156 self.fields[label] = forms.ChoiceField(choices=create_choices_from_model(params[label]['model'],
157 kwargs['initial']['rc_configuration']),
157 kwargs['initial']['rc_configuration']),
158 initial=model_initial)
158 initial=model_initial)
159
159
160
160
161 else:
161 else:
162 if label=='codes' and 'code_id' in kwargs['initial']:
162 if label=='codes' and 'code_id' in kwargs['initial']:
163 self.fields[label] = forms.CharField(initial=RCLineCode.objects.get(pk=kwargs['initial']['code_id']).codes)
163 self.fields[label] = forms.CharField(initial=RCLineCode.objects.get(pk=kwargs['initial']['code_id']).codes)
164 else:
164 else:
165 self.fields[label] = forms.CharField(initial=value['value'])
165 self.fields[label] = forms.CharField(initial=value['value'])
166
166
167 if label=='codes':
167 if label=='codes':
168 self.fields[label].widget = CodesWidget()
168 self.fields[label].widget = CodesWidget()
169
169
170 if self.data:
170 if self.data:
171 line_type = RCLineType.objects.get(pk=self.data['line_type'])
171 line_type = RCLineType.objects.get(pk=self.data['line_type'])
172
172
173 if 'code_id' in self.data:
173 if 'code_id' in self.data:
174 model_initial = self.data['code_id']
174 model_initial = self.data['code_id']
175 else:
175 else:
176 model_initial = 0
176 model_initial = 0
177
177
178 params = json.loads(line_type.params)
178 params = json.loads(line_type.params)
179
179
180 for label, value in self.extra_fields.items():
180 for label, value in self.extra_fields.items():
181 if label=='params':
181 if label=='params':
182 continue
182 continue
183
183
184 if 'model' in params[label]:
184 if 'model' in params[label]:
185 self.fields[label] = forms.ChoiceField(choices=create_choices_from_model(params[label]['model'],
185 self.fields[label] = forms.ChoiceField(choices=create_choices_from_model(params[label]['model'],
186 self.data['rc_configuration']),
186 self.data['rc_configuration']),
187 initial=model_initial)
187 initial=model_initial)
188
188
189
189
190 else:
190 else:
191 if label=='codes' and 'code' in self.data:
191 if label=='codes' and 'code' in self.data:
192 self.fields[label] = forms.CharField(initial=self.data['codes'])
192 self.fields[label] = forms.CharField(initial=self.data['codes'])
193 else:
193 else:
194 self.fields[label] = forms.CharField(initial=self.data[label])
194 self.fields[label] = forms.CharField(initial=self.data[label])
195
195
196 if label=='codes':
196 if label=='codes':
197 self.fields[label].widget = CodesWidget()
197 self.fields[label].widget = CodesWidget()
198
198
199
199
200 class Meta:
200 class Meta:
201 model = RCLine
201 model = RCLine
202 fields = ('rc_configuration', 'line_type', 'channel')
202 fields = ('rc_configuration', 'line_type', 'channel')
203 widgets = {
203 widgets = {
204 'channel': forms.HiddenInput(),
204 'channel': forms.HiddenInput(),
205 }
205 }
206
206
207
207
208 def clean(self):
208 def clean(self):
209
209
210 form_data = self.cleaned_data
210 form_data = self.cleaned_data
211 if 'code' in self.data and self.data['TX_ref']=="0":
211 if 'code' in self.data and self.data['TX_ref']=="0":
212 self.add_error('TX_ref', 'Choose a valid TX reference')
212 self.add_error('TX_ref', 'Choose a valid TX reference')
213
213
214 if RCLineType.objects.get(pk=self.data['line_type']).name=='mix':
214 if RCLineType.objects.get(pk=self.data['line_type']).name=='mix':
215 self.add_error('line_type', 'Invalid Line type')
215 self.add_error('line_type', 'Invalid Line type')
216
216
217 return form_data
217 return form_data
218
218
219
219
220 def save(self):
220 def save(self):
221 line = super(RCLineForm, self).save()
221 line = super(RCLineForm, self).save()
222
222
223 #auto add channel
223 #auto add channel
224 line.channel = RCLine.objects.filter(rc_configuration=line.rc_configuration).count()-1
224 line.channel = RCLine.objects.filter(rc_configuration=line.rc_configuration).count()-1
225
225
226 #auto add position for TX, TR & CODE
226 #auto add position for TX, TR & CODE
227 if line.line_type.name in ('tx', ):
227 if line.line_type.name in ('tx', ):
228 line.position = RCLine.objects.filter(rc_configuration=line.rc_configuration, line_type=line.line_type).count()-1
228 line.position = RCLine.objects.filter(rc_configuration=line.rc_configuration, line_type=line.line_type).count()-1
229
229
230 #save extra fields in params
230 #save extra fields in params
231 params = {}
231 params = {}
232 for label, value in self.extra_fields.items():
232 for label, value in self.extra_fields.items():
233 if label=='params':
233 if label=='params':
234 params['params'] = []
234 params['params'] = []
235 elif label=='codes':
235 elif label=='codes':
236 params[label] = [s for s in self.data[label].split('\r\n') if s]
236 params[label] = [s for s in self.data[label].split('\r\n') if s]
237 else:
237 else:
238 params[label] = self.data[label]
238 params[label] = self.data[label]
239 line.params = json.dumps(params)
239 line.params = json.dumps(params)
240 line.save()
240 line.save()
241 return
241 return
242
242
243
243
244 class RCLineViewForm(forms.Form):
244 class RCLineViewForm(forms.Form):
245
245
246 def __init__(self, *args, **kwargs):
246 def __init__(self, *args, **kwargs):
247
247
248 extra_fields = kwargs.pop('extra_fields')
248 extra_fields = kwargs.pop('extra_fields')
249 line = kwargs.pop('line')
249 line = kwargs.pop('line')
250 subform = kwargs.pop('subform', False)
250 subform = kwargs.pop('subform', False)
251 super(RCLineViewForm, self).__init__(*args, **kwargs)
251 super(RCLineViewForm, self).__init__(*args, **kwargs)
252
252
253 if subform:
253 if subform:
254 params = json.loads(line.line_type.params)['params']
254 params = json.loads(line.line_type.params)['params']
255 else:
255 else:
256 params = json.loads(line.line_type.params)
256 params = json.loads(line.line_type.params)
257
257
258 for label, value in extra_fields.items():
258 for label, value in extra_fields.items():
259
259
260 if label=='params':
260 if label=='params':
261 continue
261 continue
262 if 'ref' in label:
262 if 'ref' in label:
263 if value in (0, '0'):
263 if value in (0, '0'):
264 value = 'All'
264 value = 'All'
265 else:
265 else:
266 value = RCLine.objects.get(pk=value).get_name()
266 value = RCLine.objects.get(pk=value).get_name()
267 elif label=='code':
267 elif label=='code':
268 value = RCLineCode.objects.get(pk=value).name
268 value = RCLineCode.objects.get(pk=value).name
269
269
270 self.fields[label] = forms.CharField(initial=value)
270 self.fields[label] = forms.CharField(initial=value)
271
271
272 if 'widget' in params[label]:
272 if 'widget' in params[label]:
273 km2unit = line.rc_configuration.km2unit
273 km2unit = line.rc_configuration.km2unit
274 if params[label]['widget']=='km':
274 if params[label]['widget']=='km':
275 self.fields[label].widget = KmUnitWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
275 self.fields[label].widget = KmUnitWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
276 elif params[label]['widget']=='unit':
276 elif params[label]['widget']=='unit':
277 self.fields[label].widget = UnitKmWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
277 self.fields[label].widget = UnitKmWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
278 elif params[label]['widget']=='dc':
278 elif params[label]['widget']=='dc':
279 self.fields[label].widget = KmUnitDcWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
279 self.fields[label].widget = KmUnitDcWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
280 elif params[label]['widget']=='codes':
280 elif params[label]['widget']=='codes':
281 self.fields[label].widget = CodesWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
281 self.fields[label].widget = CodesWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
282 else:
282 else:
283 self.fields[label].widget = DefaultWidget(attrs={'disabled':True})
283 self.fields[label].widget = DefaultWidget(attrs={'disabled':True})
284
284
285
285
286 class RCLineEditForm(forms.ModelForm):
286 class RCLineEditForm(forms.ModelForm):
287
287
288 def __init__(self, *args, **kwargs):
288 def __init__(self, *args, **kwargs):
289
289
290 extra_fields = kwargs.pop('extra_fields', [])
290 extra_fields = kwargs.pop('extra_fields', [])
291 conf = kwargs.pop('conf', False)
291 conf = kwargs.pop('conf', False)
292 line = kwargs.pop('line')
292 line = kwargs.pop('line')
293 subform = kwargs.pop('subform', False)
293 subform = kwargs.pop('subform', False)
294
294
295 super(RCLineEditForm, self).__init__(*args, **kwargs)
295 super(RCLineEditForm, self).__init__(*args, **kwargs)
296
296
297 if subform is not False:
297 if subform is not False:
298 params = json.loads(line.line_type.params)['params']
298 params = json.loads(line.line_type.params)['params']
299 count = subform
299 count = subform
300 else:
300 else:
301 params = json.loads(line.line_type.params)
301 params = json.loads(line.line_type.params)
302 count = -1
302 count = -1
303
303
304 for label, value in extra_fields.items():
304 for label, value in extra_fields.items():
305
305
306 if label in ('params',):
306 if label in ('params',):
307 continue
307 continue
308 if 'help' in params[label]:
308 if 'help' in params[label]:
309 help_text = params[label]['help']
309 help_text = params[label]['help']
310 else:
310 else:
311 help_text = ''
311 help_text = ''
312
312
313 if 'model' in params[label]:
313 if 'model' in params[label]:
314 if line.line_type.name=='tr':
314 if line.line_type.name=='tr':
315 all_choice = True
315 all_choice = True
316 else:
316 else:
317 all_choice = False
317 all_choice = False
318 self.fields[label] = forms.ChoiceField(choices=create_choices_from_model(params[label]['model'], conf.id, all_choice=all_choice),
318 self.fields[label] = forms.ChoiceField(choices=create_choices_from_model(params[label]['model'], conf.id, all_choice=all_choice),
319 initial=value,
319 initial=value,
320 widget=forms.Select(attrs={'name':'%s|%s|%s' % (count, line.id, label)}),
320 widget=forms.Select(attrs={'name':'%s|%s|%s' % (count, line.id, label)}),
321 help_text=help_text)
321 help_text=help_text)
322
322
323 else:
323 else:
324 self.fields[label] = forms.CharField(initial=value, help_text=help_text)
324 self.fields[label] = forms.CharField(initial=value, help_text=help_text)
325
325
326 if label in ('code', ):
326 if label in ('code', ):
327 self.fields[label].widget = HiddenWidget(attrs={'name':'%s|%s|%s' % (count, line.id, label)})
327 self.fields[label].widget = HiddenWidget(attrs={'name':'%s|%s|%s' % (count, line.id, label)})
328
328
329 elif 'widget' in params[label]:
329 elif 'widget' in params[label]:
330 km2unit = line.rc_configuration.km2unit
330 km2unit = line.rc_configuration.km2unit
331 if params[label]['widget']=='km':
331 if params[label]['widget']=='km':
332 self.fields[label].widget = KmUnitWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
332 self.fields[label].widget = KmUnitWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
333 elif params[label]['widget']=='unit':
333 elif params[label]['widget']=='unit':
334 self.fields[label].widget = UnitKmWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
334 self.fields[label].widget = UnitKmWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
335 elif params[label]['widget']=='dc':
335 elif params[label]['widget']=='dc':
336 self.fields[label].widget = KmUnitDcWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
336 self.fields[label].widget = KmUnitDcWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
337 elif params[label]['widget']=='codes':
337 elif params[label]['widget']=='codes':
338 self.fields[label].widget = CodesWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
338 self.fields[label].widget = CodesWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
339 else:
339 else:
340 self.fields[label].widget = DefaultWidget(attrs={'line':line, 'name':'%s|%s|%s' % (count, line.id, label)})
340 self.fields[label].widget = DefaultWidget(attrs={'line':line, 'name':'%s|%s|%s' % (count, line.id, label)})
341
341
342
342
343 class Meta:
343 class Meta:
344 model = RCLine
344 model = RCLine
345 exclude = ('rc_configuration', 'line_type', 'channel', 'position', 'params', 'pulses')
345 exclude = ('rc_configuration', 'line_type', 'channel', 'position', 'params', 'pulses')
346
346
347
347
348 class RCSubLineEditForm(forms.Form):
348 class RCSubLineEditForm(forms.Form):
349
349
350 def __init__(self, *args, **kwargs):
350 def __init__(self, *args, **kwargs):
351 extra_fields = kwargs.pop('extra_fields')
351 extra_fields = kwargs.pop('extra_fields')
352 count = kwargs.pop('count')
352 count = kwargs.pop('count')
353 line = kwargs.pop('line')
353 line = kwargs.pop('line')
354 super(RCSubLineEditForm, self).__init__(*args, **kwargs)
354 super(RCSubLineEditForm, self).__init__(*args, **kwargs)
355 for label, value in extra_fields.items():
355 for label, value in extra_fields.items():
356 self.fields[label] = forms.CharField(initial=value,
356 self.fields[label] = forms.CharField(initial=value,
357 widget=forms.TextInput(attrs={'name':'%s|%s|%s' % (count, line, label)}))
357 widget=forms.TextInput(attrs={'name':'%s|%s|%s' % (count, line, label)}))
358
358
359
359
360 class RCImportForm(forms.Form):
360 class RCImportForm(forms.Form):
361
361
362 file_name = ExtFileField(extensions=['.racp', '.json', '.dat'])
362 file_name = ExtFileField(extensions=['.racp', '.json', '.dat'])
363
363
364
364
365 class RCLineCodesForm(forms.ModelForm):
365 class RCLineCodesForm(forms.ModelForm):
366
366
367 def __init__(self, *args, **kwargs):
367 def __init__(self, *args, **kwargs):
368 super(RCLineCodesForm, self).__init__(*args, **kwargs)
368 super(RCLineCodesForm, self).__init__(*args, **kwargs)
369
369
370 if 'initial' in kwargs:
370 if 'initial' in kwargs:
371 self.fields['code'] = forms.ChoiceField(choices=RCLineCode.objects.all().values_list('pk', 'name'),
371 self.fields['code'] = forms.ChoiceField(choices=RCLineCode.objects.all().values_list('pk', 'name'),
372 initial=kwargs['initial']['code'])
372 initial=kwargs['initial']['code'])
373 if 'instance' in kwargs:
373 if 'instance' in kwargs:
374 self.fields['code'] = forms.ChoiceField(choices=RCLineCode.objects.all().values_list('pk', 'name'),
374 self.fields['code'] = forms.ChoiceField(choices=RCLineCode.objects.all().values_list('pk', 'name'),
375 initial=kwargs['instance'].pk)
375 initial=kwargs['instance'].pk)
376
376
377 self.fields['codes'].widget = CodesWidget()
377 self.fields['codes'].widget = CodesWidget()
378
378
379
379
380 class Meta:
380 class Meta:
381 model = RCLineCode
381 model = RCLineCode
382 exclude = ('name',)
382 exclude = ('name',)
@@ -1,978 +1,982
1
1
2
2 import ast
3 import ast
3 import json
4 import json
4 import requests
5 import requests
5 import numpy as np
6 import numpy as np
6 from base64 import b64encode
7 from base64 import b64encode
7 from struct import pack
8 from struct import pack
8
9
9 from django.db import models
10 from django.db import models
10 from django.core.urlresolvers import reverse
11 from django.core.urlresolvers import reverse
11 from django.core.validators import MinValueValidator, MaxValueValidator
12 from django.core.validators import MinValueValidator, MaxValueValidator
12
13
13 from apps.main.models import Configuration
14 from apps.main.models import Configuration
15 from apps.main.utils import Params
14 from devices.rc import api
16 from devices.rc import api
15 from .utils import RCFile
17 from apps.rc.utils import RCFile
16 from django.template.defaultfilters import last
17
18
18 # Create your models here.
19
19
20 LINE_TYPES = (
20 LINE_TYPES = (
21 ('none', 'Not used'),
21 ('none', 'Not used'),
22 ('tr', 'Transmission/reception selector signal'),
22 ('tr', 'Transmission/reception selector signal'),
23 ('tx', 'A modulating signal (Transmission pulse)'),
23 ('tx', 'A modulating signal (Transmission pulse)'),
24 ('codes', 'BPSK modulating signal'),
24 ('codes', 'BPSK modulating signal'),
25 ('windows', 'Sample window signal'),
25 ('windows', 'Sample window signal'),
26 ('sync', 'Synchronizing signal'),
26 ('sync', 'Synchronizing signal'),
27 ('flip', 'IPP related periodic signal'),
27 ('flip', 'IPP related periodic signal'),
28 ('prog_pulses', 'Programmable pulse'),
28 ('prog_pulses', 'Programmable pulse'),
29 ('mix', 'Mixed line'),
29 ('mix', 'Mixed line'),
30 )
30 )
31
31
32
32
33 SAMPLING_REFS = (
33 SAMPLING_REFS = (
34 ('none', 'No Reference'),
34 ('none', 'No Reference'),
35 ('begin_baud', 'Begin of the first baud'),
35 ('begin_baud', 'Begin of the first baud'),
36 ('first_baud', 'Middle of the first baud'),
36 ('first_baud', 'Middle of the first baud'),
37 ('sub_baud', 'Middle of the sub-baud')
37 ('sub_baud', 'Middle of the sub-baud')
38 )
38 )
39
39
40 DAT_CMDS = {
40 DAT_CMDS = {
41 # Pulse Design commands
41 # Pulse Design commands
42 'DISABLE' : 0, # Disables pulse generation
42 'DISABLE' : 0, # Disables pulse generation
43 'ENABLE' : 24, # Enables pulse generation
43 'ENABLE' : 24, # Enables pulse generation
44 'DELAY_START' : 40, # Write delay status to memory
44 'DELAY_START' : 40, # Write delay status to memory
45 'FLIP_START' : 48, # Write flip status to memory
45 'FLIP_START' : 48, # Write flip status to memory
46 'SAMPLING_PERIOD' : 64, # Establish Sampling Period
46 'SAMPLING_PERIOD' : 64, # Establish Sampling Period
47 'TX_ONE' : 72, # Output '0' in line TX
47 'TX_ONE' : 72, # Output '0' in line TX
48 'TX_ZERO' : 88, # Output '0' in line TX
48 'TX_ZERO' : 88, # Output '0' in line TX
49 'SW_ONE' : 104, # Output '0' in line SW
49 'SW_ONE' : 104, # Output '0' in line SW
50 'SW_ZERO' : 112, # Output '1' in line SW
50 'SW_ZERO' : 112, # Output '1' in line SW
51 'RESTART': 120, # Restarts CR8 Firmware
51 'RESTART': 120, # Restarts CR8 Firmware
52 'CONTINUE' : 253, # Function Unknown
52 'CONTINUE' : 253, # Function Unknown
53 # Commands available to new controllers
53 # Commands available to new controllers
54 # 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.
54 # 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.
55 'CLOCK_DIVISOR_INIT' : 12, # Specifies Clock Divisor. Legacy command, ignored in the actual .dat conversion
55 'CLOCK_DIVISOR_INIT' : 12, # Specifies Clock Divisor. Legacy command, ignored in the actual .dat conversion
56 'CLOCK_DIVISOR_LAST' : 22, # Specifies Clock Divisor (default 60 if not included) syntax: 255,22 254,N-1.
56 'CLOCK_DIVISOR_LAST' : 22, # Specifies Clock Divisor (default 60 if not included) syntax: 255,22 254,N-1.
57 'CLOCK_DIVIDER' : 8,
57 'CLOCK_DIVIDER' : 8,
58 }
58 }
59
59
60 MAX_BITS = 8
61
62 # Rotate left: 0b1001 --> 0b0011
63 rol = lambda val, r_bits: \
64 (val << r_bits%MAX_BITS) & (2**MAX_BITS-1) | \
65 ((val & (2**MAX_BITS-1)) >> (MAX_BITS-(r_bits%MAX_BITS)))
66
67 # Rotate right: 0b1001 --> 0b1100
68 ror = lambda val, r_bits: \
69 ((val & (2**MAX_BITS-1)) >> r_bits%MAX_BITS) | \
70 (val << (MAX_BITS-(r_bits%MAX_BITS)) & (2**MAX_BITS-1))
71
60
72
61 class RCConfiguration(Configuration):
73 class RCConfiguration(Configuration):
62
74
63 ipp = models.FloatField(verbose_name='IPP [Km]', validators=[MinValueValidator(1), MaxValueValidator(9000)], default=300)
75 ipp = models.FloatField(verbose_name='IPP [Km]', validators=[MinValueValidator(1), MaxValueValidator(9000)], default=300)
64 ntx = models.PositiveIntegerField(verbose_name='Number of TX', validators=[MinValueValidator(1), MaxValueValidator(400)], default=1)
76 ntx = models.PositiveIntegerField(verbose_name='Number of TX', validators=[MinValueValidator(1), MaxValueValidator(400)], default=1)
65 clock_in = models.FloatField(verbose_name='Clock in [MHz]', validators=[MinValueValidator(1), MaxValueValidator(80)], default=1)
77 clock_in = models.FloatField(verbose_name='Clock in [MHz]', validators=[MinValueValidator(1), MaxValueValidator(80)], default=1)
66 clock_divider = models.PositiveIntegerField(verbose_name='Clock divider', validators=[MinValueValidator(1), MaxValueValidator(256)], default=1)
78 clock_divider = models.PositiveIntegerField(verbose_name='Clock divider', validators=[MinValueValidator(1), MaxValueValidator(256)], default=1)
67 clock = models.FloatField(verbose_name='Clock Master [MHz]', blank=True, default=1)
79 clock = models.FloatField(verbose_name='Clock Master [MHz]', blank=True, default=1)
68 time_before = models.PositiveIntegerField(verbose_name='Time before [&mu;S]', default=12)
80 time_before = models.PositiveIntegerField(verbose_name='Time before [&mu;S]', default=12)
69 time_after = models.PositiveIntegerField(verbose_name='Time after [&mu;S]', default=1)
81 time_after = models.PositiveIntegerField(verbose_name='Time after [&mu;S]', default=1)
70 sync = models.PositiveIntegerField(verbose_name='Synchro delay', default=0)
82 sync = models.PositiveIntegerField(verbose_name='Synchro delay', default=0)
71 sampling_reference = models.CharField(verbose_name='Sampling Reference', choices=SAMPLING_REFS, default='none', max_length=40)
83 sampling_reference = models.CharField(verbose_name='Sampling Reference', choices=SAMPLING_REFS, default='none', max_length=40)
72 control_tx = models.BooleanField(verbose_name='Control Switch TX', default=False)
84 control_tx = models.BooleanField(verbose_name='Control Switch TX', default=False)
73 control_sw = models.BooleanField(verbose_name='Control Switch SW', default=False)
85 control_sw = models.BooleanField(verbose_name='Control Switch SW', default=False)
74 total_units = models.PositiveIntegerField(default=0)
86 total_units = models.PositiveIntegerField(default=0)
75 mix = models.BooleanField(default=False)
87 mix = models.BooleanField(default=False)
76
88
77 class Meta:
89 class Meta:
78 db_table = 'rc_configurations'
90 db_table = 'rc_configurations'
79
91
80 def get_absolute_url_plot(self):
92 def get_absolute_url_plot(self):
81 return reverse('url_plot_rc_pulses', args=[str(self.id)])
93 return reverse('url_plot_rc_pulses', args=[str(self.id)])
82
94
83 def get_absolute_url_import(self):
84 return reverse('url_import_rc_conf', args=[str(self.id)])
85
86 @property
95 @property
87 def ipp_unit(self):
96 def ipp_unit(self):
88
97
89 return '{} ({})'.format(self.ipp, int(self.ipp*self.km2unit))
98 return '{} ({})'.format(self.ipp, int(self.ipp*self.km2unit))
90
99
91 @property
100 @property
92 def us2unit(self):
101 def us2unit(self):
93
102
94 return self.clock_in/self.clock_divider
103 return self.clock_in/self.clock_divider
95
104
96 @property
105 @property
97 def km2unit(self):
106 def km2unit(self):
98
107
99 return 20./3*(self.clock_in/self.clock_divider)
108 return 20./3*(self.clock_in/self.clock_divider)
100
109
101 def clone(self, **kwargs):
110 def clone(self, **kwargs):
102
111
103 lines = self.get_lines()
112 lines = self.get_lines()
113 print 'LINES'
114 print lines
104 self.pk = None
115 self.pk = None
105 self.id = None
116 self.id = None
106 for attr, value in kwargs.items():
117 for attr, value in kwargs.items():
107 setattr(self, attr, value)
118 setattr(self, attr, value)
108 self.save()
119 self.save()
109
120
110 for line in lines:
121 for line in lines:
111 line.clone(rc_configuration=self)
122 line.clone(rc_configuration=self)
112
123
124 new_lines = self.get_lines()
125 for line in new_lines:
126 line_params = json.loads(line.params)
127 if 'TX_ref' in line_params:
128 ref_line = RCLine.objects.get(pk=line_params['TX_ref'])
129 line_params['TX_ref'] = ['{}'.format(l.pk) for l in new_lines if l.get_name()==ref_line.get_name()][0]
130 line.params = json.dumps(line_params)
131 line.save()
132
113 return self
133 return self
114
134
115 def get_lines(self, **kwargs):
135 def get_lines(self, **kwargs):
116 '''
136 '''
117 Retrieve configuration lines
137 Retrieve configuration lines
118 '''
138 '''
119
139
120 return RCLine.objects.filter(rc_configuration=self.pk, **kwargs)
140 return RCLine.objects.filter(rc_configuration=self.pk, **kwargs)
121
141
122
142
123 def clean_lines(self):
143 def clean_lines(self):
124 '''
144 '''
125 '''
145 '''
126
146
127 empty_line = RCLineType.objects.get(name='none')
147 empty_line = RCLineType.objects.get(name='none')
128
148
129 for line in self.get_lines():
149 for line in self.get_lines():
130 line.line_type = empty_line
150 line.line_type = empty_line
131 line.params = '{}'
151 line.params = '{}'
132 line.save()
152 line.save()
133
153
134 def parms_to_dict(self):
154 def dict_to_parms(self, params, id=None):
135 '''
155 '''
136 '''
156 '''
137
157
138 ignored = ('parameters', 'type','polymorphic_ctype', 'configuration_ptr',
158 if id:
139 'created_date', 'programmed_date', 'mix')
159 data = Params(params).get_conf(id_conf=id)
140
160 else:
141 data = {}
161 data = Params(params).get_conf(dtype='rc')
142 for field in self._meta.fields:
143 if field.name in ignored:
144 continue
145 data[field.name] = '{}'.format(field.value_from_object(self))
146
147 data['device_id'] = data.pop('device')
148 data['device_type'] = self.device.device_type.name
149 data['lines'] = []
150 data['mix'] = self.mix
151
152 for line in self.get_lines():
153 line_data = json.loads(line.params)
154 if 'TX_ref' in line_data and line_data['TX_ref'] not in (0, '0'):
155 line_data['TX_ref'] = RCLine.objects.get(pk=line_data['TX_ref']).get_name()
156 if 'code' in line_data:
157 line_data['code'] = RCLineCode.objects.get(pk=line_data['code']).name
158 line_data['type'] = line.line_type.name
159 line_data['name'] = line.get_name()
160 data['lines'].append(line_data)
161
162 data['delays'] = self.get_delays()
163 data['pulses'] = self.get_pulses()
164
165 return data
166
167 def dict_to_parms(self, data):
168 '''
169 '''
170
162
171 self.name = data['name']
163 self.name = data['name']
172 self.ipp = float(data['ipp'])
164 self.ipp = data['ipp']
173 self.ntx = int(data['ntx'])
165 self.ntx = data['ntx']
174 self.clock_in = float(data['clock_in'])
166 self.clock_in = data['clock_in']
175 self.clock_divider = int(data['clock_divider'])
167 self.clock_divider = data['clock_divider']
176 self.clock = float(data['clock'])
168 self.clock = data['clock']
177 self.time_before = data['time_before']
169 self.time_before = data['time_before']
178 self.time_after = data['time_after']
170 self.time_after = data['time_after']
179 self.sync = data['sync']
171 self.sync = data['sync']
180 self.sampling_reference = data['sampling_reference']
172 self.sampling_reference = data['sampling_reference']
181 self.total_units = self.ipp*self.ntx*self.km2unit
173 self.total_units = self.ipp*self.ntx*self.km2unit
182 self.save()
174 self.save()
183 self.clean_lines()
175 self.clean_lines()
184
176
185 lines = []
186 positions = {'tx':0, 'tr':0}
177 positions = {'tx':0, 'tr':0}
187
178 for i, id in enumerate(data['lines']):
188 for i, line_data in enumerate(data['lines']):
179 line_data = params['lines']['byId'][id]
189 name = line_data.pop('name', '')
180 line_type = RCLineType.objects.get(name=line_data['line_type'])
190 line_type = RCLineType.objects.get(name=line_data.pop('type'))
181 if line_type.name == 'codes':
191 if line_type.name=='codes':
182 code = RCLineCode.objects.get(name=line_data['params']['code'])
192 code = RCLineCode.objects.get(name=line_data['code'])
183 line_data['params']['code'] = code.pk
193 line_data['code'] = code.pk
184 if line_type.name == 'tx':
194 line = RCLine.objects.filter(rc_configuration=self, channel=i)
185 position = positions['tx']
195 if line:
196 line = line[0]
197 line.line_type = line_type
198 line.params = json.dumps(line_data)
199 else:
200 line = RCLine(rc_configuration=self, line_type=line_type,
201 params=json.dumps(line_data),
202 channel=i)
203
204 if line_type.name=='tx':
205 line.position = positions['tx']
206 positions['tx'] += 1
186 positions['tx'] += 1
207
187 elif line_type.name == 'tr':
208 if line_type.name=='tr':
188 position = positions['tr']
209 line.position = positions['tr']
210 positions['tr'] += 1
189 positions['tr'] += 1
211
190 else:
212 line.save()
191 position = 0
213 lines.append(line)
192 line, dum = RCLine.objects.update_or_create(
214
193 rc_configuration=self,
215 for line, line_data in zip(lines, data['lines']):
194 channel=i,
216 if 'TX_ref' in line_data:
195 position=position,
217 params = json.loads(line.params)
196 defaults={
218 if line_data['TX_ref'] in (0, '0'):
197 'line_type': line_type,
219 params['TX_ref'] = '0'
198 'params': json.dumps(line_data['params'])
199 }
200 )
201
202 for i, line in enumerate(self.get_lines()):
203 line_params = json.loads(line.params)
204 if 'TX_ref' in line_params:
205 if line_params['TX_ref'] in (0, '0'):
206 line_params['TX_ref'] = '0'
220 else:
207 else:
221 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]
208 ref_id = '{}'.format(line_params['TX_ref'])
222 line.params = json.dumps(params)
209 ref_line = params['lines']['byId'][ref_id]
210 line_params['TX_ref'] = RCLine.objects.get(
211 rc_configuration=self,
212 params=json.dumps(ref_line['params'])
213 ).pk
214 line.params = json.dumps(line_params)
223 line.save()
215 line.save()
224
216
225
217
226 def get_delays(self):
218 def get_delays(self):
227
219
228 pulses = [line.pulses_as_points() for line in self.get_lines()]
220 pulses = [line.pulses_as_points() for line in self.get_lines()]
229 points = [tup for tups in pulses for tup in tups]
221 points = [tup for tups in pulses for tup in tups]
230 points = set([x for tup in points for x in tup])
222 points = set([x for tup in points for x in tup])
231 points = list(points)
223 points = list(points)
232 points.sort()
224 points.sort()
233
225
234 if points[0]!=0:
226 if points[0]!=0:
235 points.insert(0, 0)
227 points.insert(0, 0)
236
228
237 return [points[i+1]-points[i] for i in range(len(points)-1)]
229 return [points[i+1]-points[i] for i in range(len(points)-1)]
238
230
239
231
240 def get_pulses(self, binary=True):
232 def get_pulses(self, binary=True):
241
233
242
243 pulses = [line.pulses_as_points() for line in self.get_lines()]
234 pulses = [line.pulses_as_points() for line in self.get_lines()]
244 tuples = [tup for tups in pulses for tup in tups]
235 tuples = [tup for tups in pulses for tup in tups]
245 points = set([x for tup in tuples for x in tup])
236 points = set([x for tup in tuples for x in tup])
246 points = list(points)
237 points = list(points)
247 points.sort()
238 points.sort()
248 states = []
239 states = []
249 last = [0 for x in pulses]
240 last = [0 for x in pulses]
250
241
251 for x in points:
242 for x in points:
252 dum = []
243 dum = []
253 for i,tups in enumerate(pulses):
244 for i, tups in enumerate(pulses):
254 ups = [tup[0] for tup in tups]
245 ups = [tup[0] for tup in tups]
255 dws = [tup[1] for tup in tups]
246 dws = [tup[1] for tup in tups]
256 if x in ups:
247 if x in ups:
257 dum.append(1)
248 dum.append(1)
258 elif x in dws:
249 elif x in dws:
259 dum.append(0)
250 dum.append(0)
260 else:
251 else:
261 dum.append(last[i])
252 dum.append(last[i])
262 states.append(dum)
253 states.append(dum)
263 last = dum
254 last = dum
264
255
265 if binary:
256 if binary:
266 ret = []
257 ret = []
267 for flips in states:
258 for flips in states:
268 flips.reverse()
259 flips.reverse()
269 ret.append(int(''.join([str(x) for x in flips]), 2))
260 ret.append(int(''.join([str(x) for x in flips]), 2))
270 states = ret
261 states = ret
271
262
272 return states[:-1]
263 return states[:-1]
273
264
274 def add_cmd(self, cmd):
265 def add_cmd(self, cmd):
275
266
276 if cmd in DAT_CMDS:
267 if cmd in DAT_CMDS:
277 return (255, DAT_CMDS[cmd])
268 return (255, DAT_CMDS[cmd])
278
269
279 def add_data(self, value):
270 def add_data(self, value):
280
271
281 return (254, value-1)
272 return (254, value-1)
282
273
283 def parms_to_binary(self, dat=True):
274 def parms_to_binary(self, dat=True):
284 '''
275 '''
285 Create "dat" stream to be send to CR
276 Create "dat" stream to be send to CR
286 '''
277 '''
287
278
288 data = bytearray()
279 data = bytearray()
289 # create header
280 # create header
290 data.extend(self.add_cmd('DISABLE'))
281 data.extend(self.add_cmd('DISABLE'))
291 data.extend(self.add_cmd('CONTINUE'))
282 data.extend(self.add_cmd('CONTINUE'))
292 data.extend(self.add_cmd('RESTART'))
283 data.extend(self.add_cmd('RESTART'))
293
284
294 if self.control_sw:
285 if self.control_sw:
295 data.extend(self.add_cmd('SW_ONE'))
286 data.extend(self.add_cmd('SW_ONE'))
296 else:
287 else:
297 data.extend(self.add_cmd('SW_ZERO'))
288 data.extend(self.add_cmd('SW_ZERO'))
298
289
299 if self.control_tx:
290 if self.control_tx:
300 data.extend(self.add_cmd('TX_ONE'))
291 data.extend(self.add_cmd('TX_ONE'))
301 else:
292 else:
302 data.extend(self.add_cmd('TX_ZERO'))
293 data.extend(self.add_cmd('TX_ZERO'))
303
294
304 # write divider
295 # write divider
305 data.extend(self.add_cmd('CLOCK_DIVIDER'))
296 data.extend(self.add_cmd('CLOCK_DIVIDER'))
306 data.extend(self.add_data(self.clock_divider))
297 data.extend(self.add_data(self.clock_divider))
307
298
308 # write delays
299 # write delays
309 data.extend(self.add_cmd('DELAY_START'))
300 data.extend(self.add_cmd('DELAY_START'))
310 # first delay is always zero
301 # first delay is always zero
311 data.extend(self.add_data(1))
302 data.extend(self.add_data(1))
312
303
313 delays = self.get_delays()
304 delays = self.get_delays()
314
305
315 for delay in delays:
306 for delay in delays:
316 while delay>252:
307 while delay>252:
317 data.extend(self.add_data(253))
308 data.extend(self.add_data(253))
318 delay -= 253
309 delay -= 253
319 data.extend(self.add_data(int(delay)))
310 data.extend(self.add_data(int(delay)))
320
311
321 # write flips
312 # write flips
322 data.extend(self.add_cmd('FLIP_START'))
313 data.extend(self.add_cmd('FLIP_START'))
323
314
324 states = self.get_pulses(binary=True)
315 states = self.get_pulses(binary=True)
325
316
326
317
327 last = 0
318 last = 0
328 for flip, delay in zip(states, delays):
319 for flip, delay in zip(states, delays):
329 data.extend(self.add_data((flip^last)+1))
320 data.extend(self.add_data((flip^last)+1))
330 last = flip
321 last = flip
331 while delay>252:
322 while delay>252:
332 data.extend(self.add_data(1))
323 data.extend(self.add_data(1))
333 delay -= 253
324 delay -= 253
334
325
335 # write sampling period
326 # write sampling period
336 data.extend(self.add_cmd('SAMPLING_PERIOD'))
327 data.extend(self.add_cmd('SAMPLING_PERIOD'))
337 wins = self.get_lines(line_type__name='windows')
328 wins = self.get_lines(line_type__name='windows')
338 if wins:
329 if wins:
339 win_params = json.loads(wins[0].params)['params']
330 win_params = json.loads(wins[0].params)['params']
340 if win_params:
331 if win_params:
341 dh = int(win_params[0]['resolution']*self.km2unit)
332 dh = int(win_params[0]['resolution']*self.km2unit)
342 else:
333 else:
343 dh = 1
334 dh = 1
344 else:
335 else:
345 dh = 1
336 dh = 1
346 data.extend(self.add_data(dh))
337 data.extend(self.add_data(dh))
347
338
348 # write enable
339 # write enable
349 data.extend(self.add_cmd('ENABLE'))
340 data.extend(self.add_cmd('ENABLE'))
350
341
351 if not dat:
342 if not dat:
352 return data
343 return data
353
344
354 return '\n'.join(['{}'.format(x) for x in data])
345 return '\n'.join(['{}'.format(x) for x in data])
355
346
356
357 def update_from_file(self, filename):
358 '''
359 Update instance from file
360 '''
361
362 f = RCFile(filename)
363 self.dict_to_parms(f.data)
364 self.update_pulses()
365
366 def update_pulses(self):
347 def update_pulses(self):
367
348
368 for line in self.get_lines():
349 for line in self.get_lines():
369 line.update_pulses()
350 line.update_pulses()
370
351
371 def plot_pulses2(self, km=False):
352 def plot_pulses2(self, km=False):
372
353
373 import matplotlib.pyplot as plt
354 import matplotlib.pyplot as plt
374 from bokeh.resources import CDN
355 from bokeh.resources import CDN
375 from bokeh.embed import components
356 from bokeh.embed import components
376 from bokeh.mpl import to_bokeh
357 from bokeh.mpl import to_bokeh
377 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, HoverTool, SaveTool
358 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, HoverTool, SaveTool
378
359
379 lines = self.get_lines()
360 lines = self.get_lines()
380
361
381 N = len(lines)
362 N = len(lines)
382 npoints = self.total_units/self.km2unit if km else self.total_units
363 npoints = self.total_units/self.km2unit if km else self.total_units
383 fig = plt.figure(figsize=(12, 2+N*0.5))
364 fig = plt.figure(figsize=(12, 2+N*0.5))
384 ax = fig.add_subplot(111)
365 ax = fig.add_subplot(111)
385 labels = ['IPP']
366 labels = ['IPP']
386
367
387 for i, line in enumerate(lines):
368 for i, line in enumerate(lines):
388 labels.append(line.get_name(channel=True))
369 labels.append(line.get_name(channel=True))
389 l = ax.plot((0, npoints),(N-i-1, N-i-1))
370 l = ax.plot((0, npoints),(N-i-1, N-i-1))
390 points = [(tup[0], tup[1]-tup[0]) for tup in line.pulses_as_points(km=km) if tup!=(0,0)]
371 points = [(tup[0], tup[1]-tup[0]) for tup in line.pulses_as_points(km=km) if tup!=(0,0)]
391 ax.broken_barh(points, (N-i-1, 0.5),
372 ax.broken_barh(points, (N-i-1, 0.5),
392 edgecolor=l[0].get_color(), facecolor='none')
373 edgecolor=l[0].get_color(), facecolor='none')
393
374
394 n = 0
375 n = 0
395 f = ((self.ntx+50)/100)*5 if ((self.ntx+50)/100)*10>0 else 2
376 f = ((self.ntx+50)/100)*5 if ((self.ntx+50)/100)*10>0 else 2
396 for x in np.arange(0, npoints, self.ipp if km else self.ipp*self.km2unit):
377 for x in np.arange(0, npoints, self.ipp if km else self.ipp*self.km2unit):
397 if n%f==0:
378 if n%f==0:
398 ax.text(x, N, '%s' % n, size=10)
379 ax.text(x, N, '%s' % n, size=10)
399 n += 1
380 n += 1
400
381
401
402 labels.reverse()
382 labels.reverse()
403 ax.set_yticks(range(len(labels)))
383 ax.set_yticks(range(len(labels)))
404 ax.set_yticklabels(labels)
384 ax.set_yticklabels(labels)
405 ax.set_xlabel = 'Units'
385 ax.set_xlabel = 'Units'
406 plot = to_bokeh(fig, use_pandas=False)
386 plot = to_bokeh(fig, use_pandas=False)
407 plot.tools = [PanTool(dimensions=['width']), WheelZoomTool(dimensions=['width']), ResetTool(), SaveTool()]
387 plot.tools = [PanTool(dimensions=['width']), WheelZoomTool(dimensions=['width']), ResetTool(), SaveTool()]
408 plot.toolbar_location="above"
388 plot.toolbar_location="above"
409
389
410 return components(plot, CDN)
390 return components(plot, CDN)
411
391
412 def plot_pulses(self, km=False):
392 def plot_pulses(self, km=False):
413
393
414 from bokeh.plotting import figure
394 from bokeh.plotting import figure
415 from bokeh.resources import CDN
395 from bokeh.resources import CDN
416 from bokeh.embed import components
396 from bokeh.embed import components
417 from bokeh.models import FixedTicker, PrintfTickFormatter
397 from bokeh.models import FixedTicker, PrintfTickFormatter
418 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, HoverTool, SaveTool
398 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, HoverTool, SaveTool
419 from bokeh.models.sources import ColumnDataSource
399 from bokeh.models.sources import ColumnDataSource
420
400
421 lines = self.get_lines().reverse()
401 lines = self.get_lines().reverse()
422
402
423 N = len(lines)
403 N = len(lines)
424 npoints = self.total_units/self.km2unit if km else self.total_units
404 npoints = self.total_units/self.km2unit if km else self.total_units
425 ipp = self.ipp if km else self.ipp*self.km2unit
405 ipp = self.ipp if km else self.ipp*self.km2unit
426
406
427 hover = HoverTool(tooltips=[("Line", "@name"),
407 hover = HoverTool(tooltips=[("Line", "@name"),
428 ("IPP", "@ipp"),
408 ("IPP", "@ipp"),
429 ("X", "@left")])
409 ("X", "@left")])
430
410
431 tools = [PanTool(dimensions=['width']),
411 tools = [PanTool(dimensions=['width']),
432 WheelZoomTool(dimensions=['width']),
412 WheelZoomTool(dimensions=['width']),
433 hover, SaveTool()]
413 hover, SaveTool()]
434
414
435 plot = figure(width=1000,
415 plot = figure(width=1000,
436 height=40+N*50,
416 height=40+N*50,
437 y_range = (0, N),
417 y_range = (0, N),
438 tools=tools,
418 tools=tools,
439 toolbar_location='above',
419 toolbar_location='above',
440 toolbar_sticky=False,)
420 toolbar_sticky=False,)
441
421
442 plot.xaxis.axis_label = 'Km' if km else 'Units'
422 plot.xaxis.axis_label = 'Km' if km else 'Units'
443 plot.xaxis[0].formatter = PrintfTickFormatter(format='%d')
423 plot.xaxis[0].formatter = PrintfTickFormatter(format='%d')
444 plot.yaxis.axis_label = 'Pulses'
424 plot.yaxis.axis_label = 'Pulses'
445 plot.yaxis[0].ticker=FixedTicker(ticks=list(range(N)))
425 plot.yaxis[0].ticker=FixedTicker(ticks=list(range(N)))
446 plot.yaxis[0].formatter = PrintfTickFormatter(format='Line %d')
426 plot.yaxis[0].formatter = PrintfTickFormatter(format='Line %d')
447
427
448 for i, line in enumerate(lines):
428 for i, line in enumerate(lines):
449
429
450 points = [tup for tup in line.pulses_as_points(km=km) if tup!=(0,0)]
430 points = [tup for tup in line.pulses_as_points(km=km) if tup!=(0,0)]
451
431
452 source = ColumnDataSource(data = dict(
432 source = ColumnDataSource(data = dict(
453 bottom = [i for tup in points],
433 bottom = [i for tup in points],
454 top = [i+0.5 for tup in points],
434 top = [i+0.5 for tup in points],
455 left = [tup[0] for tup in points],
435 left = [tup[0] for tup in points],
456 right = [tup[1] for tup in points],
436 right = [tup[1] for tup in points],
457 ipp = [int(tup[0]/ipp) for tup in points],
437 ipp = [int(tup[0]/ipp) for tup in points],
458 name = [line.get_name() for tup in points]
438 name = [line.get_name() for tup in points]
459 ))
439 ))
460
440
461 plot.quad(
441 plot.quad(
462 bottom = 'bottom',
442 bottom = 'bottom',
463 top = 'top',
443 top = 'top',
464 left = 'left',
444 left = 'left',
465 right = 'right',
445 right = 'right',
466 source = source,
446 source = source,
467 fill_alpha = 0,
447 fill_alpha = 0,
468 #line_color = 'blue',
448 #line_color = 'blue',
469 )
449 )
470
450
471 plot.line([0, npoints], [i, i])#, color='blue')
451 plot.line([0, npoints], [i, i])#, color='blue')
472
452
473 return components(plot, CDN)
453 return components(plot, CDN)
474
454
455 def request(self, cmd, method='get', **kwargs):
456
457 req = getattr(requests, method)(self.device.url(cmd), **kwargs)
458 payload = req.json()
459
460 return payload
461
475 def status_device(self):
462 def status_device(self):
476
463
477 try:
464 try:
478 self.device.status = 0
465 self.device.status = 0
479 req = requests.get(self.device.url('status'))
466 payload = self.request('status')
480 payload = req.json()
467 if payload['status']=='enable':
481 if payload['status']=='enabled':
482 self.device.status = 3
468 self.device.status = 3
483 elif payload['status']=='disabled':
469 elif payload['status']=='disable':
484 self.device.status = 2
470 self.device.status = 2
485 else:
471 else:
486 self.device.status = 1
472 self.device.status = 1
487 self.device.save()
473 self.device.save()
488 self.message = payload['status']
474 self.message = 'RC status: {}'.format(payload['status'])
489 return False
475 return False
490 except Exception as e:
476 except Exception as e:
491 if 'No route to host' not in str(e):
477 if 'No route to host' not in str(e):
492 self.device.status = 4
478 self.device.status = 4
493 self.device.save()
479 self.device.save()
494 self.message = str(e)
480 self.message = 'RC status: {}'.format(str(e))
495 return False
481 return False
496
482
497 self.device.save()
483 self.device.save()
498 return True
484 return True
499
485
500 def reset_device(self):
486 def reset_device(self):
501
487
502 try:
488 try:
503 req = requests.post(self.device.url('reset'))
489 payload = self.request('reset', 'post')
504 payload = req.json()
505 if payload['reset']=='ok':
490 if payload['reset']=='ok':
506 self.message = 'RC restarted'
491 self.message = 'RC restarted OK'
492 self.device.status = 2
493 self.device.save()
507 else:
494 else:
508 self.message = 'RC restart not ok'
495 self.message = 'RC restart fail'
509 self.device.status = 4
496 self.device.status = 4
510 self.device.save()
497 self.device.save()
511 except Exception as e:
498 except Exception as e:
512 self.message = str(e)
499 self.message = 'RC reset: {}'.format(str(e))
513 return False
500 return False
514
501
515 return True
502 return True
516
503
517 def stop_device(self):
504 def stop_device(self):
518
505
519 try:
506 try:
520 req = requests.post(self.device.url('stop'))
507 payload = self.request('stop', 'post')
521 payload = req.json()
508 self.message = 'RC stop: {}'.format(payload['stop'])
522 if payload['stop']=='ok':
509 if payload['stop']=='ok':
523 self.device.status = 2
510 self.device.status = 2
524 self.device.save()
511 self.device.save()
525 self.message = 'RC stopped'
526 else:
512 else:
527 self.message = 'RC stop not ok'
528 self.device.status = 4
513 self.device.status = 4
529 self.device.save()
514 self.device.save()
530 return False
515 return False
531 except Exception as e:
516 except Exception as e:
532 if 'No route to host' not in str(e):
517 if 'No route to host' not in str(e):
533 self.device.status = 4
518 self.device.status = 4
534 else:
519 else:
535 self.device.status = 0
520 self.device.status = 0
536 self.message = str(e)
521 self.message = 'RC stop: {}'.format(str(e))
537 self.device.save()
522 self.device.save()
538 return False
523 return False
539
524
540 return True
525 return True
541
526
542 def start_device(self):
527 def start_device(self):
543
528
544 try:
529 try:
545 req = requests.post(self.device.url('start'))
530 payload = self.request('start', 'post')
546 payload = req.json()
531 self.message = 'RC start: {}'.format(payload['start'])
547 if payload['start']=='ok':
532 if payload['start']=='ok':
548 self.device.status = 3
533 self.device.status = 3
549 self.device.save()
534 self.device.save()
550 self.message = 'RC running'
551 else:
535 else:
552 self.message = 'RC start not ok'
553 return False
536 return False
554 except Exception as e:
537 except Exception as e:
555 if 'No route to host' not in str(e):
538 if 'No route to host' not in str(e):
556 self.device.status = 4
539 self.device.status = 4
557 else:
540 else:
558 self.device.status = 0
541 self.device.status = 0
559 self.message = str(e)
542 self.message = 'RC start: {}'.format(str(e))
560 self.device.save()
543 self.device.save()
561 return False
544 return False
562
545
563 return True
546 return True
564
547
565 def write_device(self):
548 def write_device(self):
566
549
567 values = zip(self.get_pulses(),
550 values = zip(self.get_pulses(),
568 [x-1 for x in self.get_delays()])
551 [x-1 for x in self.get_delays()])
569
552
570 data = bytearray()
553 data = bytearray()
571 #reset
554 #reset
572 data.extend((128, 0))
555 data.extend((128, 0))
573 #disable
556 #disable
574 data.extend((129, 0))
557 data.extend((129, 0))
575 #divider
558 #divider
576 data.extend((131, self.clock_divider-1))
559 data.extend((131, self.clock_divider-1))
577 #enable writing
560 #enable writing
578 data.extend((139, 62))
561 data.extend((139, 62))
579
562
580 last = 0
563 last = 0
581 for tup in values:
564 for tup in values:
582 vals = pack('<HH', last^tup[0], tup[1])
565 vals = pack('<HH', last^tup[0], tup[1])
583 last = tup[0]
566 last = tup[0]
584 data.extend((133, vals[1], 132, vals[0], 133, vals[3], 132, vals[2]))
567 data.extend((133, vals[1], 132, vals[0], 133, vals[3], 132, vals[2]))
585
568
586 #enable
569 #enable
587 data.extend((129, 1))
570 data.extend((129, 1))
588
571
589 try:
572 try:
590 req = requests.post(self.device.url('write'), data=b64encode(data))
573 payload = self.request('write', 'post', data=b64encode(data))
591 payload = req.json()
574
592 if payload['write']=='ok':
575 if payload['write']=='ok':
593 self.device.status = 2
576 self.device.status = 3
594 self.device.save()
577 self.device.save()
595 self.message = 'RC configured'
578 self.message = 'RC configured and started'
596 else:
579 else:
597 self.device.status = 1
580 self.device.status = 1
598 self.device.save()
581 self.device.save()
599 self.message = 'RC write not ok'
582 self.message = 'RC write: {}'.format(payload['write'])
600 return False
583 return False
601
584
602 except Exception as e:
585 except Exception as e:
603 if 'No route to host' not in str(e):
586 if 'No route to host' not in str(e):
604 self.device.status = 4
587 self.device.status = 4
605 else:
588 else:
606 self.device.status = 0
589 self.device.status = 0
607 self.message = str(e)
590 self.message = 'RC write: {}'.format(str(e))
608 self.device.save()
591 self.device.save()
609 return False
592 return False
610
593
611 return True
594 return True
612
595
613
596
597 def get_absolute_url_import(self):
598 return reverse('url_import_rc_conf', args=[str(self.id)])
599
600
614 class RCLineCode(models.Model):
601 class RCLineCode(models.Model):
615
602
616 name = models.CharField(max_length=40)
603 name = models.CharField(max_length=40)
617 bits_per_code = models.PositiveIntegerField(default=0)
604 bits_per_code = models.PositiveIntegerField(default=0)
618 number_of_codes = models.PositiveIntegerField(default=0)
605 number_of_codes = models.PositiveIntegerField(default=0)
619 codes = models.TextField(blank=True, null=True)
606 codes = models.TextField(blank=True, null=True)
620
607
621 class Meta:
608 class Meta:
622 db_table = 'rc_line_codes'
609 db_table = 'rc_line_codes'
623 ordering = ('name',)
610 ordering = ('name',)
624
611
625 def __str__(self):
612 def __str__(self):
626 return u'%s' % self.name
613 return u'%s' % self.name
627
614
628
615
629 class RCLineType(models.Model):
616 class RCLineType(models.Model):
630
617
631 name = models.CharField(choices=LINE_TYPES, max_length=40)
618 name = models.CharField(choices=LINE_TYPES, max_length=40)
632 description = models.TextField(blank=True, null=True)
619 description = models.TextField(blank=True, null=True)
633 params = models.TextField(default='[]')
620 params = models.TextField(default='[]')
634
621
635 class Meta:
622 class Meta:
636 db_table = 'rc_line_types'
623 db_table = 'rc_line_types'
637
624
638 def __str__(self):
625 def __str__(self):
639 return u'%s - %s' % (self.name.upper(), self.get_name_display())
626 return u'%s - %s' % (self.name.upper(), self.get_name_display())
640
627
641
628
642 class RCLine(models.Model):
629 class RCLine(models.Model):
643
630
644 rc_configuration = models.ForeignKey(RCConfiguration, on_delete=models.CASCADE)
631 rc_configuration = models.ForeignKey(RCConfiguration, on_delete=models.CASCADE)
645 line_type = models.ForeignKey(RCLineType)
632 line_type = models.ForeignKey(RCLineType)
646 channel = models.PositiveIntegerField(default=0)
633 channel = models.PositiveIntegerField(default=0)
647 position = models.PositiveIntegerField(default=0)
634 position = models.PositiveIntegerField(default=0)
648 params = models.TextField(default='{}')
635 params = models.TextField(default='{}')
649 pulses = models.TextField(default='')
636 pulses = models.TextField(default='')
650
637
651 class Meta:
638 class Meta:
652 db_table = 'rc_lines'
639 db_table = 'rc_lines'
653 ordering = ['channel']
640 ordering = ['channel']
654
641
655 def __str__(self):
642 def __str__(self):
656 if self.rc_configuration:
643 if self.rc_configuration:
657 return u'%s - %s' % (self.rc_configuration, self.get_name())
644 return u'%s - %s' % (self.rc_configuration, self.get_name())
658
645
646 def jsonify(self):
647
648 data = {}
649 data['params'] = json.loads(self.params)
650 data['id'] = '{}'.format(self.pk)
651 data['line_type'] = self.line_type.name
652 data['name'] = self.get_name()
653 if data['line_type']=='codes':
654 data['params']['code'] = RCLineCode.objects.get(pk=data['params']['code']).name
655
656 return data
657
658
659 def clone(self, **kwargs):
659 def clone(self, **kwargs):
660
660
661 self.pk = None
661 self.pk = None
662 self.id = None
662
663
663 for attr, value in kwargs.items():
664 for attr, value in kwargs.items():
664 setattr(self, attr, value)
665 setattr(self, attr, value)
665
666
666 self.save()
667 self.save()
667
668
668 return self
669 return self
669
670
670 def get_name(self, channel=False):
671 def get_name(self, channel=False):
671
672
672 chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
673 chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
673 s = ''
674 s = ''
674
675
675 if self.line_type.name in ('tx',):
676 if self.line_type.name in ('tx',):
676 s = chars[self.position]
677 s = chars[self.position]
677 elif self.line_type.name in ('codes', 'windows', 'tr'):
678 elif self.line_type.name in ('codes', 'windows', 'tr'):
678 if 'TX_ref' in json.loads(self.params):
679 if 'TX_ref' in json.loads(self.params):
679 pk = json.loads(self.params)['TX_ref']
680 pk = json.loads(self.params)['TX_ref']
680 if pk in (0, '0'):
681 if pk in (0, '0'):
681 s = ','.join(chars[l.position] for l in self.rc_configuration.get_lines(line_type__name='tx'))
682 s = ','.join(chars[l.position] for l in self.rc_configuration.get_lines(line_type__name='tx'))
682 else:
683 else:
683 ref = RCLine.objects.get(pk=pk)
684 ref = RCLine.objects.get(pk=pk)
684 s = chars[ref.position]
685 s = chars[ref.position]
685 s = '({})'.format(s)
686 s = '({})'.format(s)
686
687
687 s = '{}{}'.format(self.line_type.name.upper(), s)
688 s = '{}{}'.format(self.line_type.name.upper(), s)
688
689
689 if channel:
690 if channel:
690 return '{} {}'.format(s, self.channel)
691 return '{} {}'.format(s, self.channel)
691 else:
692 else:
692 return s
693 return s
693
694
694 def get_lines(self, **kwargs):
695 def get_lines(self, **kwargs):
695
696
696 return RCLine.objects.filter(rc_configuration=self.rc_configuration, **kwargs)
697 return RCLine.objects.filter(rc_configuration=self.rc_configuration, **kwargs)
697
698
698 def pulses_as_array(self):
699 def pulses_as_array(self):
699
700
700 y = np.zeros(self.rc_configuration.total_units)
701 y = np.zeros(self.rc_configuration.total_units)
701
702
702 for tup in ast.literal_eval(self.pulses):
703 for tup in ast.literal_eval(self.pulses):
703 y[tup[0]:tup[1]] = 1
704 y[tup[0]:tup[1]] = 1
704
705
705 return y.astype(np.int8)
706 return y.astype(np.int8)
706
707
707 def pulses_as_points(self, km=False):
708 def pulses_as_points(self, km=False):
708
709
709 if km:
710 if km:
710 unit2km = 1/self.rc_configuration.km2unit
711 unit2km = 1/self.rc_configuration.km2unit
711 return [(tup[0]*unit2km, tup[1]*unit2km) for tup in ast.literal_eval(self.pulses)]
712 return [(tup[0]*unit2km, tup[1]*unit2km) for tup in ast.literal_eval(self.pulses)]
712 else:
713 else:
713 return ast.literal_eval(self.pulses)
714 return ast.literal_eval(self.pulses)
714
715
715 def get_win_ref(self, params, tx_id, km2unit):
716 def get_win_ref(self, params, tx_id, km2unit):
716
717
717 ref = self.rc_configuration.sampling_reference
718 ref = self.rc_configuration.sampling_reference
718 codes = [line for line in self.get_lines(line_type__name='codes') if int(json.loads(line.params)['TX_ref'])==int(tx_id)]
719 codes = [line for line in self.get_lines(line_type__name='codes') if int(json.loads(line.params)['TX_ref'])==int(tx_id)]
719
720
720 if codes:
721 if codes:
721 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit/len(json.loads(codes[0].params)['codes'][0])
722 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit/len(json.loads(codes[0].params)['codes'][0])
722 else:
723 else:
723 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit
724 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit
724
725
725 if ref=='first_baud':
726 if ref=='first_baud':
726 return int(1 + round((tx_width + 1)/2 + params['first_height']*km2unit - params['resolution']*km2unit))
727 return int(1 + round((tx_width + 1)/2 + params['first_height']*km2unit - params['resolution']*km2unit))
727 elif ref=='sub_baud':
728 elif ref=='sub_baud':
728 return np.ceil(1 + params['first_height']*km2unit - params['resolution']*km2unit/2)
729 return np.ceil(1 + params['first_height']*km2unit - params['resolution']*km2unit/2)
729 else:
730 else:
730 return 0
731 return 0
731
732
732 def update_pulses(self):
733 def update_pulses(self):
733 '''
734 '''
734 Update pulses field
735 Update pulses field
735 '''
736 '''
736
737
737 km2unit = self.rc_configuration.km2unit
738 km2unit = self.rc_configuration.km2unit
738 us2unit = self.rc_configuration.us2unit
739 us2unit = self.rc_configuration.us2unit
739 ipp = self.rc_configuration.ipp
740 ipp = self.rc_configuration.ipp
740 ntx = int(self.rc_configuration.ntx)
741 ntx = int(self.rc_configuration.ntx)
741 ipp_u = int(ipp*km2unit)
742 ipp_u = int(ipp*km2unit)
742 total = ipp_u*ntx if self.rc_configuration.total_units==0 else self.rc_configuration.total_units
743 total = ipp_u*ntx if self.rc_configuration.total_units==0 else self.rc_configuration.total_units
743 y = []
744 y = []
744
745
745 if self.line_type.name=='tr':
746 if self.line_type.name=='tr':
746 tr_params = json.loads(self.params)
747 tr_params = json.loads(self.params)
747
748
748 if tr_params['TX_ref'] in ('0', 0):
749 if tr_params['TX_ref'] in ('0', 0):
749 txs = self.get_lines(line_type__name='tx')
750 txs = self.get_lines(line_type__name='tx')
750 else:
751 else:
751 txs = RCLine.objects.filter(pk=tr_params['TX_ref'])
752 txs = RCLine.objects.filter(pk=tr_params['TX_ref'])
752
753
753 for tx in txs:
754 for tx in txs:
754 params = json.loads(tx.params)
755 params = json.loads(tx.params)
755
756
756 if float(params['pulse_width'])==0:
757 if float(params['pulse_width'])==0:
757 continue
758 continue
758 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
759 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
759 width = float(params['pulse_width'])*km2unit+int(self.rc_configuration.time_before*us2unit)
760 width = float(params['pulse_width'])*km2unit+int(self.rc_configuration.time_before*us2unit)
760 before = 0
761 before = 0
761 after = int(self.rc_configuration.time_after*us2unit)
762 after = int(self.rc_configuration.time_after*us2unit)
762
763
763 y_tx = self.points(ntx, ipp_u, width,
764 y_tx = self.points(ntx, ipp_u, width,
764 delay=delays,
765 delay=delays,
765 before=before,
766 before=before,
766 after=after,
767 after=after,
767 sync=self.rc_configuration.sync)
768 sync=self.rc_configuration.sync)
768
769
769 ranges = params['range'].split(',')
770 ranges = params['range'].split(',')
770
771
771 if len(ranges)>0 and ranges[0]!='0':
772 if len(ranges)>0 and ranges[0]!='0':
772 y_tx = self.mask_ranges(y_tx, ranges)
773 y_tx = self.mask_ranges(y_tx, ranges)
773
774
774 tr_ranges = tr_params['range'].split(',')
775 tr_ranges = tr_params['range'].split(',')
775
776
776 if len(tr_ranges)>0 and tr_ranges[0]!='0':
777 if len(tr_ranges)>0 and tr_ranges[0]!='0':
777 y_tx = self.mask_ranges(y_tx, tr_ranges)
778 y_tx = self.mask_ranges(y_tx, tr_ranges)
778
779
779 y.extend(y_tx)
780 y.extend(y_tx)
780
781
781 self.pulses = str(y)
782 self.pulses = str(y)
782 y = self.array_to_points(self.pulses_as_array())
783 y = self.array_to_points(self.pulses_as_array())
783
784
784 elif self.line_type.name=='tx':
785 elif self.line_type.name=='tx':
785 params = json.loads(self.params)
786 params = json.loads(self.params)
786 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
787 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
787 width = float(params['pulse_width'])*km2unit
788 width = float(params['pulse_width'])*km2unit
788
789
789 if width>0:
790 if width>0:
790 before = int(self.rc_configuration.time_before*us2unit)
791 before = int(self.rc_configuration.time_before*us2unit)
791 after = 0
792 after = 0
792
793
793 y = self.points(ntx, ipp_u, width,
794 y = self.points(ntx, ipp_u, width,
794 delay=delays,
795 delay=delays,
795 before=before,
796 before=before,
796 after=after,
797 after=after,
797 sync=self.rc_configuration.sync)
798 sync=self.rc_configuration.sync)
798
799
799 ranges = params['range'].split(',')
800 ranges = params['range'].split(',')
800
801
801 if len(ranges)>0 and ranges[0]!='0':
802 if len(ranges)>0 and ranges[0]!='0':
802 y = self.mask_ranges(y, ranges)
803 y = self.mask_ranges(y, ranges)
803
804
804 elif self.line_type.name=='flip':
805 elif self.line_type.name=='flip':
805 n = float(json.loads(self.params)['number_of_flips'])
806 n = float(json.loads(self.params)['number_of_flips'])
806 width = n*ipp*km2unit
807 width = n*ipp*km2unit
807 y = self.points(int((ntx+1)/(2*n)), ipp_u*n*2, width)
808 y = self.points(int((ntx+1)/(2*n)), ipp_u*n*2, width)
808
809
809 elif self.line_type.name=='codes':
810 elif self.line_type.name=='codes':
810 params = json.loads(self.params)
811 params = json.loads(self.params)
811 tx = RCLine.objects.get(pk=params['TX_ref'])
812 tx = RCLine.objects.get(pk=params['TX_ref'])
812 tx_params = json.loads(tx.params)
813 tx_params = json.loads(tx.params)
813 delays = [float(d)*km2unit for d in tx_params['delays'].split(',') if d]
814 delays = [float(d)*km2unit for d in tx_params['delays'].split(',') if d]
814 f = int(float(tx_params['pulse_width'])*km2unit/len(params['codes'][0]))
815 f = int(float(tx_params['pulse_width'])*km2unit/len(params['codes'][0]))
815 codes = [(np.fromstring(''.join([s*f for s in code]), dtype=np.uint8)-48).astype(np.int8) for code in params['codes']]
816 codes = [(np.fromstring(''.join([s*f for s in code]), dtype=np.uint8)-48).astype(np.int8) for code in params['codes']]
816 codes = [self.array_to_points(code) for code in codes]
817 codes = [self.array_to_points(code) for code in codes]
817 n = len(codes)
818 n = len(codes)
818
819
819 ranges = tx_params['range'].split(',')
820 ranges = tx_params['range'].split(',')
820 if len(ranges)>0 and ranges[0]!='0':
821 if len(ranges)>0 and ranges[0]!='0':
821 dum = self.mask_ranges(tx.pulses_as_points(), ranges)
822 dum = self.mask_ranges(tx.pulses_as_points(), ranges)
822 else:
823 else:
823 dum = tx.pulses_as_points()
824 dum = tx.pulses_as_points()
824
825
825 for i, tup in enumerate(dum):
826 for i, tup in enumerate(dum):
826 if tup==(0,0): continue
827 if tup==(0,0): continue
827 code = codes[i%n]
828 code = codes[i%n]
828 y.extend([(c[0]+tup[0], c[1]+tup[0]) for c in code])
829 y.extend([(c[0]+tup[0], c[1]+tup[0]) for c in code])
829
830
830 elif self.line_type.name=='sync':
831 elif self.line_type.name=='sync':
831 params = json.loads(self.params)
832 params = json.loads(self.params)
832 n = ipp_u*ntx
833 n = ipp_u*ntx
833 if params['invert'] in ('1', 1):
834 if params['invert'] in ('1', 1):
834 y = [(n-1, n)]
835 y = [(n-1, n)]
835 else:
836 else:
836 y = [(0, 1)]
837 y = [(0, 1)]
837
838
838 elif self.line_type.name=='prog_pulses':
839 elif self.line_type.name=='prog_pulses':
839 params = json.loads(self.params)
840 params = json.loads(self.params)
840 if int(params['periodic'])==0:
841 if int(params['periodic'])==0:
841 nntx = 1
842 nntx = 1
842 nipp = ipp_u*ntx
843 nipp = ipp_u*ntx
843 else:
844 else:
844 nntx = ntx
845 nntx = ntx
845 nipp = ipp_u
846 nipp = ipp_u
846
847
847 if 'params' in params and len(params['params'])>0:
848 if 'params' in params and len(params['params'])>0:
848 for p in params['params']:
849 for p in params['params']:
849 y_pp = self.points(nntx, nipp,
850 y_pp = self.points(nntx, nipp,
850 p['end']-p['begin'],
851 p['end']-p['begin'],
851 before=p['begin'])
852 before=p['begin'])
852
853
853 y.extend(y_pp)
854 y.extend(y_pp)
854
855
855 elif self.line_type.name=='windows':
856 elif self.line_type.name=='windows':
856 params = json.loads(self.params)
857 params = json.loads(self.params)
857 if 'params' in params and len(params['params'])>0:
858 if 'params' in params and len(params['params'])>0:
858 tr_params = json.loads(self.get_lines(line_type__name='tr')[0].params)
859 tr_params = json.loads(self.get_lines(line_type__name='tr')[0].params)
859 tr_ranges = tr_params['range'].split(',')
860 tr_ranges = tr_params['range'].split(',')
860 for p in params['params']:
861 for p in params['params']:
861 y_win = self.points(ntx, ipp_u,
862 y_win = self.points(ntx, ipp_u,
862 p['resolution']*p['number_of_samples']*km2unit,
863 p['resolution']*p['number_of_samples']*km2unit,
863 before=int(self.rc_configuration.time_before*us2unit),
864 before=int(self.rc_configuration.time_before*us2unit),
864 sync=self.rc_configuration.sync+self.get_win_ref(p, params['TX_ref'], km2unit))
865 sync=self.rc_configuration.sync+self.get_win_ref(p, params['TX_ref'], km2unit))
865
866
866
867
867 if len(tr_ranges)>0 and tr_ranges[0]!='0':
868 if len(tr_ranges)>0 and tr_ranges[0]!='0':
868 y_win = self.mask_ranges(y_win, tr_ranges)
869 y_win = self.mask_ranges(y_win, tr_ranges)
869
870
870 y.extend(y_win)
871 y.extend(y_win)
871
872
872 elif self.line_type.name=='mix':
873 elif self.line_type.name=='mix':
873 values = self.rc_configuration.parameters.split('-')
874 values = self.rc_configuration.parameters.split('-')
874 confs = [RCConfiguration.objects.get(pk=value.split('|')[0]) for value in values]
875 confs = [RCConfiguration.objects.get(pk=value.split('|')[0]) for value in values]
875 modes = [value.split('|')[1] for value in values]
876 modes = [value.split('|')[1] for value in values]
876 ops = [value.split('|')[2] for value in values]
877 ops = [value.split('|')[2] for value in values]
877 delays = [value.split('|')[3] for value in values]
878 delays = [value.split('|')[3] for value in values]
878 masks = [value.split('|')[4] for value in values]
879 masks = [value.split('|')[4] for value in values]
879 mask = list('{:8b}'.format(int(masks[0])))
880 mask = list('{:8b}'.format(int(masks[0])))
880 mask.reverse()
881 mask.reverse()
881 if mask[self.channel] in ('0', '', ' '):
882 if mask[self.channel] in ('0', '', ' '):
882 y = np.zeros(confs[0].total_units, dtype=np.int8)
883 y = np.zeros(confs[0].total_units, dtype=np.int8)
883 else:
884 else:
884 y = confs[0].get_lines(channel=self.channel)[0].pulses_as_array()
885 y = confs[0].get_lines(channel=self.channel)[0].pulses_as_array()
885
886
886 for i in range(1, len(values)):
887 for i in range(1, len(values)):
887 mask = list('{:8b}'.format(int(masks[i])))
888 mask = list('{:8b}'.format(int(masks[i])))
888 mask.reverse()
889 mask.reverse()
889
890
890 if mask[self.channel] in ('0', '', ' '):
891 if mask[self.channel] in ('0', '', ' '):
891 continue
892 continue
892 Y = confs[i].get_lines(channel=self.channel)[0].pulses_as_array()
893 Y = confs[i].get_lines(channel=self.channel)[0].pulses_as_array()
893 delay = float(delays[i])*km2unit
894 delay = float(delays[i])*km2unit
894
895
895 if modes[i]=='P':
896 if modes[i]=='P':
896 if delay>0:
897 if delay>0:
897 if delay<self.rc_configuration.ipp*km2unit and len(Y)==len(y):
898 if delay<self.rc_configuration.ipp*km2unit and len(Y)==len(y):
898 y_temp = np.empty_like(Y)
899 y_temp = np.empty_like(Y)
899 y_temp[:delay] = 0
900 y_temp[:delay] = 0
900 y_temp[delay:] = Y[:-delay]
901 y_temp[delay:] = Y[:-delay]
901 elif delay+len(Y)>len(y):
902 elif delay+len(Y)>len(y):
902 y_new = np.zeros(delay+len(Y), dtype=np.int8)
903 y_new = np.zeros(delay+len(Y), dtype=np.int8)
903 y_new[:len(y)] = y
904 y_new[:len(y)] = y
904 y = y_new
905 y = y_new
905 y_temp = np.zeros(delay+len(Y), dtype=np.int8)
906 y_temp = np.zeros(delay+len(Y), dtype=np.int8)
906 y_temp[-len(Y):] = Y
907 y_temp[-len(Y):] = Y
907 elif delay+len(Y)==len(y):
908 elif delay+len(Y)==len(y):
908 y_temp = np.zeros(delay+len(Y))
909 y_temp = np.zeros(delay+len(Y))
909 y_temp[-len(Y):] = Y
910 y_temp[-len(Y):] = Y
910 elif delay+len(Y)<len(y):
911 elif delay+len(Y)<len(y):
911 y_temp = np.zeros(len(y), dtype=np.int8)
912 y_temp = np.zeros(len(y), dtype=np.int8)
912 y_temp[delay:delay+len(Y)] = Y
913 y_temp[delay:delay+len(Y)] = Y
913 else:
914 else:
914 y_temp = Y.copy()
915 y_temp = Y.copy()
915
916
916 if ops[i]=='OR':
917 if ops[i]=='OR':
917 y = y | y_temp
918 y = y | y_temp
918 elif ops[i]=='XOR':
919 elif ops[i]=='XOR':
919 y = y ^ y_temp
920 y = y ^ y_temp
920 elif ops[i]=='AND':
921 elif ops[i]=='AND':
921 y = y & y_temp
922 y = y & y_temp
922 elif ops[i]=='NAND':
923 elif ops[i]=='NAND':
923 y = y & ~y_temp
924 y = y & ~y_temp
924 else:
925 else:
925 y = np.concatenate([y, Y])
926 y = np.concatenate([y, Y])
926
927
927 total = len(y)
928 total = len(y)
928 y = self.array_to_points(y)
929 y = self.array_to_points(y)
929
930
930 else:
931 else:
931 y = []
932 y = []
932
933
933 if self.rc_configuration.total_units != total:
934 if self.rc_configuration.total_units != total:
934 self.rc_configuration.total_units = total
935 self.rc_configuration.total_units = total
935 self.rc_configuration.save()
936 self.rc_configuration.save()
936
937
937 self.pulses = str(y)
938 self.pulses = str(y)
938 self.save()
939 self.save()
939
940
940 @staticmethod
941 @staticmethod
941 def array_to_points(X):
942 def array_to_points(X):
942
943
944 if X.size==0:
945 return []
946
943 d = X[1:]-X[:-1]
947 d = X[1:]-X[:-1]
944
948
945 up = np.where(d==1)[0]
949 up = np.where(d==1)[0]
946 if X[0]==1:
950 if X[0]==1:
947 up = np.concatenate((np.array([-1]), up))
951 up = np.concatenate((np.array([-1]), up))
948 up += 1
952 up += 1
949
953
950 dw = np.where(d==-1)[0]
954 dw = np.where(d==-1)[0]
951 if X[-1]==1:
955 if X[-1]==1:
952 dw = np.concatenate((dw, np.array([len(X)-1])))
956 dw = np.concatenate((dw, np.array([len(X)-1])))
953 dw += 1
957 dw += 1
954
958
955 return [(tup[0], tup[1]) for tup in zip(up, dw)]
959 return [(tup[0], tup[1]) for tup in zip(up, dw)]
956
960
957 @staticmethod
961 @staticmethod
958 def mask_ranges(Y, ranges):
962 def mask_ranges(Y, ranges):
959
963
960 y = [(0, 0) for __ in Y]
964 y = [(0, 0) for __ in Y]
961
965
962 for index in ranges:
966 for index in ranges:
963 if '-' in index:
967 if '-' in index:
964 args = [int(a) for a in index.split('-')]
968 args = [int(a) for a in index.split('-')]
965 y[args[0]-1:args[1]] = Y[args[0]-1:args[1]]
969 y[args[0]-1:args[1]] = Y[args[0]-1:args[1]]
966 else:
970 else:
967 y[int(index)-1] = Y[int(index)-1]
971 y[int(index)-1] = Y[int(index)-1]
968
972
969 return y
973 return y
970
974
971 @staticmethod
975 @staticmethod
972 def points(ntx, ipp, width, delay=[0], before=0, after=0, sync=0):
976 def points(ntx, ipp, width, delay=[0], before=0, after=0, sync=0):
973
977
974 delays = len(delay)
978 delays = len(delay)
975
979
976 Y = [(int(ipp*x+before+delay[x%delays]+sync), int(ipp*x+width+before+delay[x%delays]+after+sync)) for x in range(ntx)]
980 Y = [(int(ipp*x+before+delay[x%delays]+sync), int(ipp*x+width+before+delay[x%delays]+after+sync)) for x in range(ntx)]
977
981
978 return Y
982 return Y
@@ -1,401 +1,401
1
1
2 import json
2 import json
3
3
4 from django.contrib import messages
4 from django.contrib import messages
5 from django.utils.safestring import mark_safe
5 from django.utils.safestring import mark_safe
6 from django.shortcuts import render, redirect, get_object_or_404, HttpResponse
6 from django.shortcuts import render, redirect, get_object_or_404, HttpResponse
7
7
8 from apps.main.models import Experiment, Device
8 from apps.main.models import Experiment, Device
9 from apps.main.views import sidebar
9 from apps.main.views import sidebar
10
10
11 from .models import RCConfiguration, RCLine, RCLineType, RCLineCode
11 from .models import RCConfiguration, RCLine, RCLineType, RCLineCode
12 from .forms import RCConfigurationForm, RCLineForm, RCLineViewForm, RCLineEditForm, RCImportForm, RCLineCodesForm
12 from .forms import RCConfigurationForm, RCLineForm, RCLineViewForm, RCLineEditForm, RCImportForm, RCLineCodesForm
13
13
14
14
15 def conf(request, conf_id):
15 def conf(request, conf_id):
16
16
17 conf = get_object_or_404(RCConfiguration, pk=conf_id)
17 conf = get_object_or_404(RCConfiguration, pk=conf_id)
18
18
19 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
19 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
20
20
21 for line in lines:
21 for line in lines:
22 params = json.loads(line.params)
22 params = json.loads(line.params)
23 line.form = RCLineViewForm(extra_fields=params, line=line)
23 line.form = RCLineViewForm(extra_fields=params, line=line)
24 if 'params' in params:
24 if 'params' in params:
25 line.subforms = [RCLineViewForm(extra_fields=fields, line=line, subform=True) for fields in params['params']]
25 line.subforms = [RCLineViewForm(extra_fields=fields, line=line, subform=True) for fields in params['params']]
26
26
27 kwargs = {}
27 kwargs = {}
28 kwargs['dev_conf'] = conf
28 kwargs['dev_conf'] = conf
29 kwargs['rc_lines'] = lines
29 kwargs['rc_lines'] = lines
30 kwargs['dev_conf_keys'] = ['name', 'ipp_unit', 'ntx', 'clock_in', 'clock_divider', 'clock',
30 kwargs['dev_conf_keys'] = ['name', 'ipp_unit', 'ntx', 'clock_in', 'clock_divider', 'clock',
31 'time_before', 'time_after', 'sync', 'sampling_reference', 'control_tx', 'control_sw']
31 'time_before', 'time_after', 'sync', 'sampling_reference', 'control_tx', 'control_sw']
32
32
33 kwargs['title'] = 'RC Configuration'
33 kwargs['title'] = 'RC Configuration'
34 kwargs['suptitle'] = 'Details'
34 kwargs['suptitle'] = 'Details'
35
35
36 kwargs['button'] = 'Edit Configuration'
36 kwargs['button'] = 'Edit Configuration'
37 ###### SIDEBAR ######
37 ###### SIDEBAR ######
38 kwargs.update(sidebar(conf=conf))
38 kwargs.update(sidebar(conf=conf))
39
39
40 return render(request, 'rc_conf.html', kwargs)
40 return render(request, 'rc_conf.html', kwargs)
41
41
42
42
43 def conf_edit(request, conf_id):
43 def conf_edit(request, conf_id):
44
44
45 conf = get_object_or_404(RCConfiguration, pk=conf_id)
45 conf = get_object_or_404(RCConfiguration, pk=conf_id)
46
46
47 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
47 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
48
48
49 for line in lines:
49 for line in lines:
50 params = json.loads(line.params)
50 params = json.loads(line.params)
51 line.form = RCLineEditForm(conf=conf, line=line, extra_fields=params)
51 line.form = RCLineEditForm(conf=conf, line=line, extra_fields=params)
52 line.subform = False
52 line.subform = False
53
53
54 if 'params' in params:
54 if 'params' in params:
55 line.subforms = [RCLineEditForm(extra_fields=fields, line=line, subform=i) for i, fields in enumerate(params['params'])]
55 line.subforms = [RCLineEditForm(extra_fields=fields, line=line, subform=i) for i, fields in enumerate(params['params'])]
56 line.subform = True
56 line.subform = True
57
57
58 if request.method=='GET':
58 if request.method=='GET':
59
59
60 form = RCConfigurationForm(instance=conf)
60 form = RCConfigurationForm(instance=conf)
61
61
62 elif request.method=='POST':
62 elif request.method=='POST':
63
63
64 line_data = {}
64 line_data = {}
65 conf_data = {}
65 conf_data = {}
66 extras = []
66 extras = []
67
67
68 #classified post fields
68 #classified post fields
69 for label,value in request.POST.items():
69 for label,value in request.POST.items():
70 if label=='csrfmiddlewaretoken':
70 if label=='csrfmiddlewaretoken':
71 continue
71 continue
72
72
73 if label.count('|')==0:
73 if label.count('|')==0:
74 conf_data[label] = value
74 conf_data[label] = value
75 continue
75 continue
76
76
77 elif label.split('|')[0]!='-1':
77 elif label.split('|')[0]!='-1':
78 extras.append(label)
78 extras.append(label)
79 continue
79 continue
80
80
81 x, pk, name = label.split('|')
81 x, pk, name = label.split('|')
82
82
83 if name=='codes':
83 if name=='codes':
84 value = [s for s in value.split('\r\n') if s]
84 value = [s for s in value.split('\r\n') if s]
85
85
86 if pk in line_data:
86 if pk in line_data:
87 line_data[pk][name] = value
87 line_data[pk][name] = value
88 else:
88 else:
89 line_data[pk] = {name:value}
89 line_data[pk] = {name:value}
90
90
91 #update conf
91 #update conf
92 form = RCConfigurationForm(conf_data, instance=conf)
92 form = RCConfigurationForm(conf_data, instance=conf)
93
93
94 if form.is_valid():
94 if form.is_valid():
95
95
96 form.save()
96 form.save()
97
97
98 #update lines fields
98 #update lines fields
99 extras.sort()
99 extras.sort()
100 for label in extras:
100 for label in extras:
101 x, pk, name = label.split('|')
101 x, pk, name = label.split('|')
102 if pk not in line_data:
102 if pk not in line_data:
103 line_data[pk] = {}
103 line_data[pk] = {}
104 if 'params' not in line_data[pk]:
104 if 'params' not in line_data[pk]:
105 line_data[pk]['params'] = []
105 line_data[pk]['params'] = []
106 if len(line_data[pk]['params'])<int(x)+1:
106 if len(line_data[pk]['params'])<int(x)+1:
107 line_data[pk]['params'].append({})
107 line_data[pk]['params'].append({})
108 line_data[pk]['params'][int(x)][name] = float(request.POST[label])
108 line_data[pk]['params'][int(x)][name] = float(request.POST[label])
109
109
110 for pk, params in line_data.items():
110 for pk, params in line_data.items():
111 line = RCLine.objects.get(pk=pk)
111 line = RCLine.objects.get(pk=pk)
112 if line.line_type.name in ('windows', 'prog_pulses'):
112 if line.line_type.name in ('windows', 'prog_pulses'):
113 if 'params' not in params:
113 if 'params' not in params:
114 params['params'] = []
114 params['params'] = []
115 line.params = json.dumps(params)
115 line.params = json.dumps(params)
116 line.save()
116 line.save()
117
117
118 #update pulses field
118 #update pulses field
119 conf.update_pulses()
119 conf.update_pulses()
120
120
121 messages.success(request, 'RC Configuration successfully updated')
121 messages.success(request, 'RC Configuration successfully updated')
122
122
123 return redirect(conf.get_absolute_url())
123 return redirect(conf.get_absolute_url())
124
124
125 kwargs = {}
125 kwargs = {}
126 kwargs['dev_conf'] = conf
126 kwargs['dev_conf'] = conf
127 kwargs['form'] = form
127 kwargs['form'] = form
128 kwargs['rc_lines'] = lines
128 kwargs['rc_lines'] = lines
129 kwargs['edit'] = True
129 kwargs['edit'] = True
130
130
131 kwargs['title'] = 'RC Configuration'
131 kwargs['title'] = 'RC Configuration'
132 kwargs['suptitle'] = 'Edit'
132 kwargs['suptitle'] = 'Edit'
133 kwargs['button'] = 'Update'
133 kwargs['button'] = 'Update'
134 kwargs['previous'] = conf.get_absolute_url()
134 kwargs['previous'] = conf.get_absolute_url()
135
135
136 return render(request, 'rc_conf_edit.html', kwargs)
136 return render(request, 'rc_conf_edit.html', kwargs)
137
137
138
138
139 def add_line(request, conf_id, line_type_id=None, code_id=None):
139 def add_line(request, conf_id, line_type_id=None, code_id=None):
140
140
141 conf = get_object_or_404(RCConfiguration, pk=conf_id)
141 conf = get_object_or_404(RCConfiguration, pk=conf_id)
142
142
143 if request.method=='GET':
143 if request.method=='GET':
144 if line_type_id:
144 if line_type_id:
145 line_type = get_object_or_404(RCLineType, pk=line_type_id)
145 line_type = get_object_or_404(RCLineType, pk=line_type_id)
146
146
147 if code_id:
147 if code_id:
148 form = RCLineForm(initial={'rc_configuration':conf_id, 'line_type': line_type_id, 'code_id': code_id},
148 form = RCLineForm(initial={'rc_configuration':conf_id, 'line_type': line_type_id, 'code_id': code_id},
149 extra_fields=json.loads(line_type.params))
149 extra_fields=json.loads(line_type.params))
150 else:
150 else:
151 form = RCLineForm(initial={'rc_configuration':conf_id, 'line_type': line_type_id},
151 form = RCLineForm(initial={'rc_configuration':conf_id, 'line_type': line_type_id},
152 extra_fields=json.loads(line_type.params))
152 extra_fields=json.loads(line_type.params))
153 else:
153 else:
154 line_type = {'id':0}
154 line_type = {'id':0}
155 form = RCLineForm(initial={'rc_configuration':conf_id})
155 form = RCLineForm(initial={'rc_configuration':conf_id})
156
156
157 if request.method=='POST':
157 if request.method=='POST':
158
158
159 line_type = get_object_or_404(RCLineType, pk=line_type_id)
159 line_type = get_object_or_404(RCLineType, pk=line_type_id)
160 form = RCLineForm(request.POST,
160 form = RCLineForm(request.POST,
161 extra_fields=json.loads(line_type.params))
161 extra_fields=json.loads(line_type.params))
162
162
163 if form.is_valid():
163 if form.is_valid():
164 form.save()
164 form.save()
165 form.instance.update_pulses()
165 form.instance.update_pulses()
166 return redirect('url_edit_rc_conf', conf.id)
166 return redirect('url_edit_rc_conf', conf.id)
167
167
168 kwargs = {}
168 kwargs = {}
169 kwargs['form'] = form
169 kwargs['form'] = form
170 kwargs['title'] = 'RC Configuration'
170 kwargs['title'] = 'RC Configuration'
171 kwargs['suptitle'] = 'Add Line'
171 kwargs['suptitle'] = 'Add Line'
172 kwargs['button'] = 'Add'
172 kwargs['button'] = 'Add'
173 kwargs['previous'] = conf.get_absolute_url_edit()
173 kwargs['previous'] = conf.get_absolute_url_edit()
174 kwargs['dev_conf'] = conf
174 kwargs['dev_conf'] = conf
175 kwargs['line_type'] = line_type
175 kwargs['line_type'] = line_type
176
176
177 return render(request, 'rc_add_line.html', kwargs)
177 return render(request, 'rc_add_line.html', kwargs)
178
178
179 def edit_codes(request, conf_id, line_id, code_id=None):
179 def edit_codes(request, conf_id, line_id, code_id=None):
180
180
181 conf = get_object_or_404(RCConfiguration, pk=conf_id)
181 conf = get_object_or_404(RCConfiguration, pk=conf_id)
182 line = get_object_or_404(RCLine, pk=line_id)
182 line = get_object_or_404(RCLine, pk=line_id)
183 params = json.loads(line.params)
183 params = json.loads(line.params)
184
184
185 if request.method=='GET':
185 if request.method=='GET':
186 if code_id:
186 if code_id:
187 code = get_object_or_404(RCLineCode, pk=code_id)
187 code = get_object_or_404(RCLineCode, pk=code_id)
188 form = RCLineCodesForm(instance=code)
188 form = RCLineCodesForm(instance=code)
189 else:
189 else:
190 initial = {'code': params['code'],
190 initial = {'code': params['code'],
191 'codes': params['codes'] if 'codes' in params else [],
191 'codes': params['codes'] if 'codes' in params else [],
192 'number_of_codes': len(params['codes']) if 'codes' in params else 0,
192 'number_of_codes': len(params['codes']) if 'codes' in params else 0,
193 'bits_per_code': len(params['codes'][0]) if 'codes' in params else 0,
193 'bits_per_code': len(params['codes'][0]) if 'codes' in params else 0,
194 }
194 }
195 form = RCLineCodesForm(initial=initial)
195 form = RCLineCodesForm(initial=initial)
196
196
197 if request.method=='POST':
197 if request.method=='POST':
198 form = RCLineCodesForm(request.POST)
198 form = RCLineCodesForm(request.POST)
199 if form.is_valid():
199 if form.is_valid():
200 params['code'] = request.POST['code']
200 params['code'] = request.POST['code']
201 params['codes'] = [s for s in request.POST['codes'].split('\r\n') if s]
201 params['codes'] = [s for s in request.POST['codes'].split('\r\n') if s]
202 line.params = json.dumps(params)
202 line.params = json.dumps(params)
203 line.save()
203 line.save()
204 messages.success(request, 'Line: "%s" has been updated.' % line)
204 messages.success(request, 'Line: "%s" has been updated.' % line)
205 return redirect('url_edit_rc_conf', conf.id)
205 return redirect('url_edit_rc_conf', conf.id)
206
206
207 kwargs = {}
207 kwargs = {}
208 kwargs['form'] = form
208 kwargs['form'] = form
209 kwargs['title'] = line
209 kwargs['title'] = line
210 kwargs['suptitle'] = 'Edit'
210 kwargs['suptitle'] = 'Edit'
211 kwargs['button'] = 'Update'
211 kwargs['button'] = 'Update'
212 kwargs['dev_conf'] = conf
212 kwargs['dev_conf'] = conf
213 kwargs['previous'] = conf.get_absolute_url_edit()
213 kwargs['previous'] = conf.get_absolute_url_edit()
214 kwargs['line'] = line
214 kwargs['line'] = line
215
215
216 return render(request, 'rc_edit_codes.html', kwargs)
216 return render(request, 'rc_edit_codes.html', kwargs)
217
217
218 def add_subline(request, conf_id, line_id):
218 def add_subline(request, conf_id, line_id):
219
219
220 conf = get_object_or_404(RCConfiguration, pk=conf_id)
220 conf = get_object_or_404(RCConfiguration, pk=conf_id)
221 line = get_object_or_404(RCLine, pk=line_id)
221 line = get_object_or_404(RCLine, pk=line_id)
222
222
223 if request.method == 'POST':
223 if request.method == 'POST':
224 if line:
224 if line:
225 params = json.loads(line.params)
225 params = json.loads(line.params)
226 subparams = json.loads(line.line_type.params)
226 subparams = json.loads(line.line_type.params)
227 if 'params' in subparams:
227 if 'params' in subparams:
228 dum = {}
228 dum = {}
229 for key, value in subparams['params'].items():
229 for key, value in subparams['params'].items():
230 dum[key] = value['value']
230 dum[key] = value['value']
231 params['params'].append(dum)
231 params['params'].append(dum)
232 line.params = json.dumps(params)
232 line.params = json.dumps(params)
233 line.save()
233 line.save()
234 return redirect('url_edit_rc_conf', conf.id)
234 return redirect('url_edit_rc_conf', conf.id)
235
235
236 kwargs = {}
236 kwargs = {}
237
237
238 kwargs['title'] = 'Add new'
238 kwargs['title'] = 'Add new'
239 kwargs['suptitle'] = '%s to %s' % (line.line_type.name, line)
239 kwargs['suptitle'] = '%s to %s' % (line.line_type.name, line)
240
240
241 return render(request, 'confirm.html', kwargs)
241 return render(request, 'confirm.html', kwargs)
242
242
243 def remove_line(request, conf_id, line_id):
243 def remove_line(request, conf_id, line_id):
244
244
245 conf = get_object_or_404(RCConfiguration, pk=conf_id)
245 conf = get_object_or_404(RCConfiguration, pk=conf_id)
246 line = get_object_or_404(RCLine, pk=line_id)
246 line = get_object_or_404(RCLine, pk=line_id)
247
247
248 if request.method == 'POST':
248 if request.method == 'POST':
249 if line:
249 if line:
250 try:
250 try:
251 channel = line.channel
251 channel = line.channel
252 line.delete()
252 line.delete()
253 for ch in range(channel+1, RCLine.objects.filter(rc_configuration=conf).count()+1):
253 for ch in range(channel+1, RCLine.objects.filter(rc_configuration=conf).count()+1):
254 l = RCLine.objects.get(rc_configuration=conf, channel=ch)
254 l = RCLine.objects.get(rc_configuration=conf, channel=ch)
255 l.channel = l.channel-1
255 l.channel = l.channel-1
256 l.save()
256 l.save()
257 messages.success(request, 'Line: "%s" has been deleted.' % line)
257 messages.success(request, 'Line: "%s" has been deleted.' % line)
258 except:
258 except:
259 messages.error(request, 'Unable to delete line: "%s".' % line)
259 messages.error(request, 'Unable to delete line: "%s".' % line)
260
260
261 return redirect('url_edit_rc_conf', conf.id)
261 return redirect('url_edit_rc_conf', conf.id)
262
262
263 kwargs = {}
263 kwargs = {}
264
264
265 kwargs['object'] = line
265 kwargs['object'] = line
266 kwargs['delete'] = True
266 kwargs['delete'] = True
267 kwargs['title'] = 'Delete'
267 kwargs['title'] = 'Delete'
268 kwargs['suptitle'] = 'Line'
268 kwargs['suptitle'] = 'Line'
269 kwargs['previous'] = conf.get_absolute_url_edit()
269 kwargs['previous'] = conf.get_absolute_url_edit()
270 return render(request, 'confirm.html', kwargs)
270 return render(request, 'confirm.html', kwargs)
271
271
272
272
273 def remove_subline(request, conf_id, line_id, subline_id):
273 def remove_subline(request, conf_id, line_id, subline_id):
274
274
275 conf = get_object_or_404(RCConfiguration, pk=conf_id)
275 conf = get_object_or_404(RCConfiguration, pk=conf_id)
276 line = get_object_or_404(RCLine, pk=line_id)
276 line = get_object_or_404(RCLine, pk=line_id)
277
277
278 if request.method == 'POST':
278 if request.method == 'POST':
279 if line:
279 if line:
280 params = json.loads(line.params)
280 params = json.loads(line.params)
281 params['params'].remove(params['params'][int(subline_id)-1])
281 params['params'].remove(params['params'][int(subline_id)-1])
282 line.params = json.dumps(params)
282 line.params = json.dumps(params)
283 line.save()
283 line.save()
284
284
285 return redirect('url_edit_rc_conf', conf.id)
285 return redirect('url_edit_rc_conf', conf.id)
286
286
287 kwargs = {}
287 kwargs = {}
288
288
289 kwargs['object'] = line
289 kwargs['object'] = line
290 kwargs['object_name'] = line.line_type.name
290 kwargs['object_name'] = line.line_type.name
291 kwargs['delete_view'] = True
291 kwargs['delete_view'] = True
292 kwargs['title'] = 'Confirm delete'
292 kwargs['title'] = 'Confirm delete'
293
293
294 return render(request, 'confirm.html', kwargs)
294 return render(request, 'confirm.html', kwargs)
295
295
296
296
297 def update_lines_position(request, conf_id):
297 def update_lines_position(request, conf_id):
298
298
299 conf = get_object_or_404(RCConfiguration, pk=conf_id)
299 conf = get_object_or_404(RCConfiguration, pk=conf_id)
300
300
301 if request.method=='POST':
301 if request.method=='POST':
302 ch = 0
302 ch = 0
303 for item in request.POST['items'].split('&'):
303 for item in request.POST['items'].split('&'):
304 line = RCLine.objects.get(pk=item.split('=')[-1])
304 line = RCLine.objects.get(pk=item.split('=')[-1])
305 line.channel = ch
305 line.channel = ch
306 line.save()
306 line.save()
307 ch += 1
307 ch += 1
308
308
309 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
309 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
310
310
311 for line in lines:
311 for line in lines:
312 params = json.loads(line.params)
312 params = json.loads(line.params)
313 line.form = RCLineEditForm(conf=conf, line=line, extra_fields=params)
313 line.form = RCLineEditForm(conf=conf, line=line, extra_fields=params)
314
314
315 if 'params' in params:
315 if 'params' in params:
316 line.subform = True
316 line.subform = True
317 line.subforms = [RCLineEditForm(extra_fields=fields, line=line, subform=i) for i, fields in enumerate(params['params'])]
317 line.subforms = [RCLineEditForm(extra_fields=fields, line=line, subform=i) for i, fields in enumerate(params['params'])]
318
318
319 html = render(request, 'rc_lines.html', {'dev_conf':conf, 'rc_lines':lines, 'edit':True})
319 html = render(request, 'rc_lines.html', {'dev_conf':conf, 'rc_lines':lines, 'edit':True})
320 data = {'html': html.content.decode('utf8')}
320 data = {'html': html.content.decode('utf8')}
321
321
322 return HttpResponse(json.dumps(data), content_type="application/json")
322 return HttpResponse(json.dumps(data), content_type="application/json")
323 return redirect('url_edit_rc_conf', conf.id)
323 return redirect('url_edit_rc_conf', conf.id)
324
324
325
325
326 def import_file(request, conf_id):
326 def import_file(request, conf_id):
327
327
328 conf = get_object_or_404(RCConfiguration, pk=conf_id)
328 conf = get_object_or_404(RCConfiguration, pk=conf_id)
329 if request.method=='POST':
329 if request.method=='POST':
330 form = RCImportForm(request.POST, request.FILES)
330 form = RCImportForm(request.POST, request.FILES)
331 if form.is_valid():
331 if form.is_valid():
332 try:
332 try:
333 #if True:
333 data = conf.import_from_file(request.FILES['file_name'])
334 conf.update_from_file(request.FILES['file_name'])
334 conf.dict_to_parms(data)
335 conf.update_pulses()
335 messages.success(request, 'Configuration "%s" loaded succesfully' % request.FILES['file_name'])
336 messages.success(request, 'Configuration "%s" loaded succesfully' % request.FILES['file_name'])
336 return redirect(conf.get_absolute_url_edit())
337 return redirect(conf.get_absolute_url_edit())
337
338
338 except Exception as e:
339 except Exception as e:
339 messages.error(request, 'Error parsing file: "%s" - %s' % (request.FILES['file_name'], e))
340 messages.error(request, 'Error parsing file: "%s" - %s' % (request.FILES['file_name'], repr(e)))
340
341 else:
341 else:
342 messages.warning(request, 'Your current configuration will be replaced')
342 messages.warning(request, 'Your current configuration will be replaced')
343 form = RCImportForm()
343 form = RCImportForm()
344
344
345 kwargs = {}
345 kwargs = {}
346 kwargs['form'] = form
346 kwargs['form'] = form
347 kwargs['title'] = 'RC Configuration'
347 kwargs['title'] = 'RC Configuration'
348 kwargs['suptitle'] = 'Import file'
348 kwargs['suptitle'] = 'Import file'
349 kwargs['button'] = 'Upload'
349 kwargs['button'] = 'Upload'
350 kwargs['previous'] = conf.get_absolute_url()
350 kwargs['previous'] = conf.get_absolute_url()
351
351
352 return render(request, 'rc_import.html', kwargs)
352 return render(request, 'rc_import.html', kwargs)
353
353
354
354
355 def plot_pulses(request, conf_id):
355 def plot_pulses(request, conf_id):
356
356
357 conf = get_object_or_404(RCConfiguration, pk=conf_id)
357 conf = get_object_or_404(RCConfiguration, pk=conf_id)
358 km = True if 'km' in request.GET else False
358 km = True if 'km' in request.GET else False
359
359
360 script, div = conf.plot_pulses(km=km)
360 script, div = conf.plot_pulses(km=km)
361
361
362 kwargs = {}
362 kwargs = {}
363 kwargs['no_sidebar'] = True
363 kwargs['no_sidebar'] = True
364 kwargs['title'] = 'RC Pulses'
364 kwargs['title'] = 'RC Pulses'
365 kwargs['suptitle'] = conf.name
365 kwargs['suptitle'] = conf.name
366 kwargs['div'] = mark_safe(div)
366 kwargs['div'] = mark_safe(div)
367 kwargs['script'] = mark_safe(script)
367 kwargs['script'] = mark_safe(script)
368 kwargs['units'] = conf.km2unit
368 kwargs['units'] = conf.km2unit
369 kwargs['kms'] = 1/conf.km2unit
369 kwargs['kms'] = 1/conf.km2unit
370
370
371 if km:
371 if km:
372 kwargs['km_selected'] = True
372 kwargs['km_selected'] = True
373
373
374 if 'json' in request.GET:
374 if 'json' in request.GET:
375 return HttpResponse(json.dumps({'div':mark_safe(div), 'script':mark_safe(script)}), content_type="application/json")
375 return HttpResponse(json.dumps({'div':mark_safe(div), 'script':mark_safe(script)}), content_type="application/json")
376 else:
376 else:
377 return render(request, 'rc_pulses.html', kwargs)
377 return render(request, 'rc_pulses.html', kwargs)
378
378
379 def plot_pulses2(request, conf_id):
379 def plot_pulses2(request, conf_id):
380
380
381 conf = get_object_or_404(RCConfiguration, pk=conf_id)
381 conf = get_object_or_404(RCConfiguration, pk=conf_id)
382 km = True if 'km' in request.GET else False
382 km = True if 'km' in request.GET else False
383
383
384 script, div = conf.plot_pulses2(km=km)
384 script, div = conf.plot_pulses2(km=km)
385
385
386 kwargs = {}
386 kwargs = {}
387 kwargs['no_sidebar'] = True
387 kwargs['no_sidebar'] = True
388 kwargs['title'] = 'RC Pulses'
388 kwargs['title'] = 'RC Pulses'
389 kwargs['suptitle'] = conf.name
389 kwargs['suptitle'] = conf.name
390 kwargs['div'] = mark_safe(div)
390 kwargs['div'] = mark_safe(div)
391 kwargs['script'] = mark_safe(script)
391 kwargs['script'] = mark_safe(script)
392 kwargs['units'] = conf.km2unit
392 kwargs['units'] = conf.km2unit
393 kwargs['kms'] = 1/conf.km2unit
393 kwargs['kms'] = 1/conf.km2unit
394
394
395 if km:
395 if km:
396 kwargs['km_selected'] = True
396 kwargs['km_selected'] = True
397
397
398 if 'json' in request.GET:
398 if 'json' in request.GET:
399 return HttpResponse(json.dumps({'div':mark_safe(div), 'script':mark_safe(script)}), content_type="application/json")
399 return HttpResponse(json.dumps({'div':mark_safe(div), 'script':mark_safe(script)}), content_type="application/json")
400 else:
400 else:
401 return render(request, 'rc_pulses.html', kwargs)
401 return render(request, 'rc_pulses.html', kwargs)
@@ -1,315 +1,319
1
1
2 import ast
2 import ast
3 import json
3 import json
4 from itertools import chain
4 from itertools import chain
5
5
6 from django import forms
6 from django import forms
7 from django.utils.safestring import mark_safe
7 from django.utils.safestring import mark_safe
8 from django.utils.encoding import force_text
8 from django.utils.encoding import force_text
9 from django.utils.html import conditional_escape
9 from django.utils.html import conditional_escape
10
10
11 try:
11 try:
12 basestring # attempt to evaluate basestring
12 basestring # attempt to evaluate basestring
13 def isstr(s):
13 def isstr(s):
14 return isinstance(s, basestring)
14 return isinstance(s, basestring)
15 except NameError:
15 except NameError:
16 def isstr(s):
16 def isstr(s):
17 return isinstance(s, str)
17 return isinstance(s, str)
18
18
19 class KmUnitWidget(forms.widgets.TextInput):
19 class KmUnitWidget(forms.widgets.TextInput):
20
20
21 def render(self, label, value, attrs=None):
21 def render(self, label, value, attrs=None):
22
22
23 if isinstance(value, (int, float)):
23 if isinstance(value, (int, float)):
24 unit = int(value*attrs['km2unit'])
24 unit = int(value*attrs['km2unit'])
25 elif isstr(value):
25 elif isstr(value):
26 units = []
26 units = []
27 values = [s for s in value.split(',') if s]
27 values = [s for s in value.split(',') if s]
28 for val in values:
28 for val in values:
29 units.append('{0:.0f}'.format(float(val)*attrs['km2unit']))
29 units.append('{0:.0f}'.format(float(val)*attrs['km2unit']))
30
30
31 unit = ','.join(units)
31 unit = ','.join(units)
32
32
33 disabled = 'disabled' if attrs.get('disabled', False) else ''
33 disabled = 'disabled' if attrs.get('disabled', False) else ''
34 name = attrs.get('name', label)
34 name = attrs.get('name', label)
35 if attrs['id'] in ('id_delays',):
35 if attrs['id'] in ('id_delays',):
36 input_type = 'text'
36 input_type = 'text'
37 else:
37 else:
38 input_type = 'number'
38 input_type = 'number'
39
39
40 if 'line' in attrs:
40 if 'line' in attrs:
41 label += '_{0}_{1}'.format(attrs['line'].pk, name.split('|')[0])
41 label += '_{0}_{1}'.format(attrs['line'].pk, name.split('|')[0])
42
42
43 html = '''<div class="col-md-12 col-no-padding">
43 html = '''<div class="col-md-12 col-no-padding">
44 <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>
44 <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>
45 <div class="col-md-1 col-no-padding">Km</div>
45 <div class="col-md-1 col-no-padding">Km</div>
46 <div class="col-md-5 col-no-padding"><input type="{0}" {1} class="form-control" id="id_{2}_unit" value="{5}"></div>
46 <div class="col-md-5 col-no-padding"><input type="{0}" step="any" {1} class="form-control" id="id_{2}_unit" value="{5}"></div>
47 <div class="col-md-1 col-no-padding">Units</div></div><br>'''.format(input_type, disabled, label, name, value, unit)
47 <div class="col-md-1 col-no-padding">Units</div></div><br>'''.format(input_type, disabled, label, name, value, unit)
48
48
49 script = '''<script type="text/javascript">
49 script = '''<script type="text/javascript">
50 $(document).ready(function () {{
50 $(document).ready(function () {{
51
51
52 km_fields.push("id_{label}");
52 km_fields.push("id_{label}");
53 unit_fields.push("id_{label}_unit");
53 unit_fields.push("id_{label}_unit");
54
54
55 $("#id_{label}").change(function() {{
55 $("#id_{label}").change(function() {{
56 $("#id_{label}_unit").val(str2unit($(this).val()));
56 $("#id_{label}_unit").val(str2unit($(this).val()));
57 $("#id_{label}").val(str2km($("#id_{label}_unit").val()));
57 $("#id_{label}").val(str2km($("#id_{label}_unit").val()));
58 updateWindows("#id_{label}");
58 updateWindows("#id_{label}");
59 }});
59 }});
60 $("#id_{label}_unit").change(function() {{
60 $("#id_{label}_unit").change(function() {{
61 $(this).val(str2int($(this).val()));
61 $(this).val(str2int($(this).val()));
62 $("#id_{label}").val(str2km($(this).val()));
62 $("#id_{label}").val(str2km($(this).val()));
63 updateWindows("#id_{label}");
63 updateWindows("#id_{label}");
64 }});
64 }});
65 }});
65 }});
66 </script>'''.format(label=label)
66 </script>'''.format(label=label)
67
67
68 if disabled:
68 if disabled:
69 return mark_safe(html)
69 return mark_safe(html)
70 else:
70 else:
71 return mark_safe(html+script)
71 return mark_safe(html+script)
72
72
73
73
74 class UnitKmWidget(forms.widgets.TextInput):
74 class UnitKmWidget(forms.widgets.TextInput):
75
75
76 def render(self, label, value, attrs=None):
76 def render(self, label, value, attrs=None):
77
77
78 if isinstance(value, (int, float)):
78 if isinstance(value, (int, float)):
79 km = value/attrs['km2unit']
79 km = value/attrs['km2unit']
80 elif isinstance(value, basestring):
80 elif isinstance(value, basestring):
81 kms = []
81 kms = []
82 values = [s for s in value.split(',') if s]
82 values = [s for s in value.split(',') if s]
83 for val in values:
83 for val in values:
84 kms.append('{0:.0f}'.format(float(val)/attrs['km2unit']))
84 kms.append('{0:.0f}'.format(float(val)/attrs['km2unit']))
85
85
86 km = ','.join(kms)
86 km = ','.join(kms)
87
87
88 disabled = 'disabled' if attrs.get('disabled', False) else ''
88 disabled = 'disabled' if attrs.get('disabled', False) else ''
89 name = attrs.get('name', label)
89 name = attrs.get('name', label)
90
90
91 if 'line' in attrs:
91 if 'line' in attrs:
92 label += '_{0}_{1}'.format(attrs['line'].pk, name.split('|')[0])
92 label += '_{0}_{1}'.format(attrs['line'].pk, name.split('|')[0])
93
93
94 html = '''<div class="col-md-12 col-no-padding">
94 html = '''<div class="col-md-12 col-no-padding">
95 <div class="col-md-5 col-no-padding"><input type="number" {0} class="form-control" id="id_{1}_unit" name="{2}" value="{3}"></div>
95 <div class="col-md-5 col-no-padding"><input type="number" step="any" {0} class="form-control" id="id_{1}_unit" name="{2}" value="{3}"></div>
96 <div class="col-md-1 col-no-padding">Units</div>
96 <div class="col-md-1 col-no-padding">Units</div>
97 <div class="col-md-5 col-no-padding"><input type="number" step="any" {4} class="form-control" id="id_{5}" value="{6}"></div>
97 <div class="col-md-5 col-no-padding"><input type="number" step="any" {4} class="form-control" id="id_{5}" value="{6}"></div>
98 <div class="col-md-1 col-no-padding">Km</div></div>'''.format(disabled, label, name, value, disabled, label, km)
98 <div class="col-md-1 col-no-padding">Km</div></div>'''.format(disabled, label, name, value, disabled, label, km)
99
99
100 script = '''<script type="text/javascript">
100 script = '''<script type="text/javascript">
101 $(document).ready(function () {{
101 $(document).ready(function () {{
102
102
103 km_fields.push("id_{label}");
103 km_fields.push("id_{label}");
104 unit_fields.push("id_{label}_unit");
104 unit_fields.push("id_{label}_unit");
105
105
106 $("#id_{label}").change(function() {{
106 $("#id_{label}").change(function() {{
107 $("#id_{label}_unit").val(str2unit($(this).val()));
107 $("#id_{label}_unit").val(str2unit($(this).val()));
108 }});
108 }});
109 $("#id_{label}_unit").change(function() {{
109 $("#id_{label}_unit").change(function() {{
110 $("#id_{label}").val(str2km($(this).val()));
110 $("#id_{label}").val(str2km($(this).val()));
111 }});
111 }});
112 }});
112 }});
113 </script>'''.format(label=label)
113 </script>'''.format(label=label)
114
114
115 if disabled:
115 if disabled:
116 return mark_safe(html)
116 return mark_safe(html)
117 else:
117 else:
118 return mark_safe(html+script)
118 return mark_safe(html+script)
119
119
120
120
121 class KmUnitHzWidget(forms.widgets.TextInput):
121 class KmUnitHzWidget(forms.widgets.TextInput):
122
122
123 def render(self, label, value, attrs=None):
123 def render(self, label, value, attrs=None):
124
124
125 unit = float(value)*attrs['km2unit']
125 unit = float(value)*attrs['km2unit']
126 if unit%10==0:
126 if unit%10==0:
127 unit = int(unit)
127 unit = int(unit)
128 hz = 150000*float(value)**-1
128 hz = 150000*float(value)**-1
129
129
130 disabled = 'disabled' if attrs.get('disabled', False) else ''
130 disabled = 'disabled' if attrs.get('disabled', False) else ''
131 name = attrs.get('name', label)
131 name = attrs.get('name', label)
132
132
133 if 'line' in attrs:
133 if 'line' in attrs:
134 label += '_{0}'.format(attrs['line'].pk)
134 label += '_{0}'.format(attrs['line'].pk)
135
135
136 html = '''<div class="col-md-12 col-no-padding">
136 html = '''<div class="col-md-12 col-no-padding">
137 <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>
137 <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>
138 <div class="col-md-1 col-no-padding">Km</div>
138 <div class="col-md-1 col-no-padding">Km</div>
139 <div class="col-md-3 col-no-padding"><input type="number" {4} class="form-control" id="id_{1}_unit" value="{5}"></div>
139 <div class="col-md-3 col-no-padding"><input type="number" step="any" {4} class="form-control" id="id_{1}_unit" value="{5}"></div>
140 <div class="col-md-1 col-no-padding">Units</div>
140 <div class="col-md-1 col-no-padding">Units</div>
141 <div class="col-md-3 col-no-padding"><input type="number" step="any" {4} class="form-control" id="id_{1}_hz" value="{6}"></div>
141 <div class="col-md-3 col-no-padding"><input type="number" step="any" {4} class="form-control" id="id_{1}_hz" value="{6}"></div>
142 <div class="col-md-1 col-no-padding">Hz</div>
142 <div class="col-md-1 col-no-padding">Hz</div>
143 </div>'''.format(disabled, label, name, value, disabled, unit, hz)
143 </div>'''.format(disabled, label, name, value, disabled, unit, hz)
144
144
145 script = '''<script type="text/javascript">
145 script = '''<script type="text/javascript">
146 $(document).ready(function () {{
146 $(document).ready(function () {{
147 km_fields.push("id_{label}");
147 km_fields.push("id_{label}");
148 unit_fields.push("id_{label}_unit");
148 unit_fields.push("id_{label}_unit");
149 $("#id_{label}").change(function() {{
149 $("#id_{label}").change(function() {{
150 $("#id_{label}_unit").val(str2unit($(this).val()));
150 $("#id_{label}_unit").val(str2unit($(this).val()));
151 $("#id_{label}").val(str2km($("#id_{label}_unit").val()));
151 $("#id_{label}").val(str2km($("#id_{label}_unit").val()));
152 $("#id_{label}_hz").val(str2hz($(this).val()));
152 $("#id_{label}_hz").val(str2hz($(this).val()));
153 updateDc();
153 updateDc();
154 }});
154 }});
155 $("#id_{label}_unit").change(function() {{
155 $("#id_{label}_unit").change(function() {{
156 $(this).val(Math.round(parseFloat($(this).val())/10)*10);
156 $(this).val(Math.round(parseFloat($(this).val())/10)*10);
157 $("#id_{label}").val(str2km($(this).val()));
157 $("#id_{label}").val(str2km($(this).val()));
158 $("#id_{label}_hz").val(str2hz($("#id_{label}").val()));
158 $("#id_{label}_hz").val(str2hz($("#id_{label}").val()));
159 updateDc();
159 updateDc();
160 }});
160 }});
161 $("#id_{label}_hz").change(function() {{
161 $("#id_{label}_hz").change(function() {{
162 $("#id_{label}").val(str2hz($(this).val()));
162 $("#id_{label}").val(str2hz($(this).val()));
163 $("#id_{label}_unit").val(str2unit($("#id_{label}").val()));
163 $("#id_{label}_unit").val(str2unit($("#id_{label}").val()));
164 updateDc();
164 updateDc();
165 }});
165 }});
166 }});
166 }});
167 </script>'''.format(label=label)
167 </script>'''.format(label=label)
168
168
169 if disabled:
169 if disabled:
170 return mark_safe(html)
170 return mark_safe(html)
171 else:
171 else:
172 return mark_safe(html+script)
172 return mark_safe(html+script)
173
173
174
174
175 class KmUnitDcWidget(forms.widgets.TextInput):
175 class KmUnitDcWidget(forms.widgets.TextInput):
176
176
177 def render(self, label, value, attrs=None):
177 def render(self, label, value, attrs=None):
178
178
179 unit = int(float(value)*attrs['km2unit'])
179 unit = int(float(value)*attrs['km2unit'])
180
180
181 disabled = 'disabled' if attrs.get('disabled', False) else ''
181 disabled = 'disabled' if attrs.get('disabled', False) else ''
182 name = attrs.get('name', label)
182 name = attrs.get('name', label)
183
183
184 label += '_{0}'.format(attrs['line'].pk)
184 label += '_{0}'.format(attrs['line'].pk)
185
185
186 dc = float(json.loads(attrs['line'].params)['pulse_width'])*100/attrs['line'].rc_configuration.ipp
186 dc = float(json.loads(attrs['line'].params)['pulse_width'])*100/attrs['line'].rc_configuration.ipp
187
187
188 html = '''<div class="col-md-12 col-no-padding">
188 html = '''<div class="col-md-12 col-no-padding">
189 <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>
189 <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>
190 <div class="col-md-1 col-no-padding">Km</div>
190 <div class="col-md-1 col-no-padding">Km</div>
191 <div class="col-md-3 col-no-padding"><input type="number" {4} class="form-control" id="id_{1}_unit" value="{5}"></div>
191 <div class="col-md-3 col-no-padding"><input type="number" step="any" {4} class="form-control" id="id_{1}_unit" value="{5}"></div>
192 <div class="col-md-1 col-no-padding">Units</div>
192 <div class="col-md-1 col-no-padding">Units</div>
193 <div class="col-md-3 col-no-padding"><input type="number" step="any" {4} class="form-control" id="id_{1}_dc" value="{6}"></div>
193 <div class="col-md-3 col-no-padding"><input type="number" step="any" {4} class="form-control" id="id_{1}_dc" value="{6}"></div>
194 <div class="col-md-1 col-no-padding">DC[%]</div>
194 <div class="col-md-1 col-no-padding">DC[%]</div>
195 </div>'''.format(disabled, label, name, value, disabled, unit, dc)
195 </div>'''.format(disabled, label, name, value, disabled, unit, dc)
196
196
197 script = '''<script type="text/javascript">
197 script = '''<script type="text/javascript">
198 $(document).ready(function () {{
198 $(document).ready(function () {{
199 km_fields.push("id_{label}");
199 km_fields.push("id_{label}");
200 unit_fields.push("id_{label}_unit");
200 unit_fields.push("id_{label}_unit");
201 dc_fields.push("id_{label}");
201 dc_fields.push("id_{label}");
202 $("#id_{label}").change(function() {{
202 $("#id_{label}").change(function() {{
203 $("#id_{label}_unit").val(str2unit($(this).val()));
203 $("#id_{label}_unit").val(str2unit($(this).val()));
204 $("#id_{label}").val(str2km($("#id_{label}_unit").val()));
204 $("#id_{label}").val(str2km($("#id_{label}_unit").val()));
205 $("#id_{label}_dc").val(str2dc($("#id_{label}").val()));
205 $("#id_{label}_dc").val(str2dc($("#id_{label}").val()));
206 }});
206 }});
207 $("#id_{label}_unit").change(function() {{
207 $("#id_{label}_unit").change(function() {{
208 $("#id_{label}").val(str2km($(this).val()));
208 $("#id_{label}").val(str2km($(this).val()));
209 $("#id_{label}_dc").val(str2dc($("#id_{label}").val()));
209 $("#id_{label}_dc").val(str2dc($("#id_{label}").val()));
210 }});
210 }});
211
211
212 $("#id_{label}_dc").change(function() {{
212 $("#id_{label}_dc").change(function() {{
213 $("#id_{label}").val(parseFloat($(this).val())*100/parseFloat($("#id_ipp").val()));
213 $("#id_{label}").val(parseFloat($(this).val())*100/parseFloat($("#id_ipp").val()));
214 $("#id_{label}_unit").val(str2unit($("#id_{label}").val()));
214 $("#id_{label}_unit").val(str2unit($("#id_{label}").val()));
215 }});
215 }});
216 }});
216 }});
217 </script>'''.format(label=label)
217 </script>'''.format(label=label)
218
218
219 if disabled:
219 if disabled:
220 return mark_safe(html)
220 return mark_safe(html)
221 else:
221 else:
222 return mark_safe(html+script)
222 return mark_safe(html+script)
223
223
224
224
225 class DefaultWidget(forms.widgets.TextInput):
225 class DefaultWidget(forms.widgets.TextInput):
226
226
227 def render(self, label, value, attrs=None):
227 def render(self, label, value, attrs=None):
228
228
229 disabled = 'disabled' if attrs.get('disabled', False) else ''
229 disabled = 'disabled' if attrs.get('disabled', False) else ''
230 itype = 'number' if label in ('number_of_samples', 'last_height') else 'text'
230 itype = 'number' if label in ('number_of_samples', 'last_height') else 'text'
231 name = attrs.get('name', label)
231 name = attrs.get('name', label)
232 if 'line' in attrs:
232 if 'line' in attrs:
233 label += '_{0}_{1}'.format(attrs['line'].pk, name.split('|')[0])
233 label += '_{0}_{1}'.format(attrs['line'].pk, name.split('|')[0])
234 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)
234
235 if itype=='number':
236 html = '<div class="col-md-12 col-no-padding"><div class="col-md-5 col-no-padding"><input {0} type="{1}" step="any" class="form-control" id="id_{2}" name="{3}" value="{4}"></div></div>'.format(disabled, itype, label, name, value)
237 else:
238 html = '<div class="col-md-12 col-no-padding"><div class="col-md-5 col-no-padding"><input {0} type="{1}" step="any" class="form-control" id="id_{2}" name="{3}" value="{4}"></div></div>'.format(disabled, itype, label, name, value)
235
239
236 if 'last_height' in label or 'number_of_samples' in label:
240 if 'last_height' in label or 'number_of_samples' in label:
237 script = '''<script type="text/javascript">
241 script = '''<script type="text/javascript">
238 $(document).ready(function () {{
242 $(document).ready(function () {{
239
243
240 $("#id_{label}").change(function() {{
244 $("#id_{label}").change(function() {{
241 updateWindows("#id_{label}");
245 updateWindows("#id_{label}");
242 }});
246 }});
243
247
244 }});
248 }});
245 </script>'''.format(label=label)
249 </script>'''.format(label=label)
246 else:
250 else:
247 script = ''
251 script = ''
248
252
249 if disabled:
253 if disabled:
250 return mark_safe(html)
254 return mark_safe(html)
251 else:
255 else:
252 return mark_safe(html+script)
256 return mark_safe(html+script)
253
257
254
258
255
259
256 return mark_safe(html)
260 return mark_safe(html)
257
261
258
262
259 class HiddenWidget(forms.widgets.HiddenInput):
263 class HiddenWidget(forms.widgets.HiddenInput):
260
264
261 def render(self, label, value, attrs=None):
265 def render(self, label, value, attrs=None):
262
266
263 disabled = 'disabled' if attrs.get('disabled', False) else ''
267 disabled = 'disabled' if attrs.get('disabled', False) else ''
264 name = self.attrs.get('name', label)
268 name = self.attrs.get('name', label)
265
269
266 html = '<input {0} type="hidden" class="form-control" id="id_{1}" name="{2}" value="{3}">'.format(disabled, label, name, value)
270 html = '<input {0} type="hidden" class="form-control" id="id_{1}" name="{2}" value="{3}">'.format(disabled, label, name, value)
267
271
268 return mark_safe(html)
272 return mark_safe(html)
269
273
270
274
271 class CodesWidget(forms.widgets.Textarea):
275 class CodesWidget(forms.widgets.Textarea):
272
276
273 def render(self, label, value, attrs=None):
277 def render(self, label, value, attrs=None):
274
278
275 disabled = 'disabled' if attrs.get('disabled', False) else ''
279 disabled = 'disabled' if attrs.get('disabled', False) else ''
276 name = attrs.get('name', label)
280 name = attrs.get('name', label)
277
281
278 if '[' in value:
282 if '[' in value:
279 value = ast.literal_eval(value)
283 value = ast.literal_eval(value)
280
284
281 if isinstance(value, list):
285 if isinstance(value, list):
282 codes = '\r\n'.join(value)
286 codes = '\r\n'.join(value)
283 else:
287 else:
284 codes = value
288 codes = value
285
289
286 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)
290 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)
287
291
288 return mark_safe(html)
292 return mark_safe(html)
289
293
290 class HCheckboxSelectMultiple(forms.CheckboxSelectMultiple):
294 class HCheckboxSelectMultiple(forms.CheckboxSelectMultiple):
291
295
292 def render(self, name, value, attrs=None, choices=()):
296 def render(self, name, value, attrs=None, choices=()):
293
297
294 if value is None: value = []
298 if value is None: value = []
295 has_id = attrs and 'id' in attrs
299 has_id = attrs and 'id' in attrs
296 final_attrs = self.build_attrs(attrs, name=name)
300 final_attrs = self.build_attrs(attrs, name=name)
297 output = [u'<br><ul>']
301 output = [u'<br><ul>']
298 # Normalize to strings
302 # Normalize to strings
299 str_values = set([force_text(v) for v in value])
303 str_values = set([force_text(v) for v in value])
300 for i, (option_value, option_label) in enumerate(chain(self.choices, choices)):
304 for i, (option_value, option_label) in enumerate(chain(self.choices, choices)):
301 # If an ID attribute was given, add a numeric index as a suffix,
305 # If an ID attribute was given, add a numeric index as a suffix,
302 # so that the checkboxes don't all have the same ID attribute.
306 # so that the checkboxes don't all have the same ID attribute.
303 if has_id:
307 if has_id:
304 final_attrs = dict(final_attrs, id='%s_%s' % (attrs['id'], i))
308 final_attrs = dict(final_attrs, id='%s_%s' % (attrs['id'], i))
305 label_for = u' for="%s"' % final_attrs['id']
309 label_for = u' for="%s"' % final_attrs['id']
306 else:
310 else:
307 label_for = ''
311 label_for = ''
308
312
309 cb = forms.CheckboxInput(final_attrs, check_test=lambda value: value in str_values)
313 cb = forms.CheckboxInput(final_attrs, check_test=lambda value: value in str_values)
310 option_value = force_text(option_value)
314 option_value = force_text(option_value)
311 rendered_cb = cb.render(name, option_value)
315 rendered_cb = cb.render(name, option_value)
312 option_label = conditional_escape(force_text(option_label))
316 option_label = conditional_escape(force_text(option_label))
313 output.append(u'<span><label%s>%s %s</label></span>' % (label_for, rendered_cb, option_label))
317 output.append(u'<span><label%s>%s %s</label></span>' % (label_for, rendered_cb, option_label))
314 output.append(u'</div><br>')
318 output.append(u'</div><br>')
315 return mark_safe(u'\n'.join(output))
319 return mark_safe(u'\n'.join(output))
General Comments 0
You need to be logged in to leave comments. Login now