##// END OF EJS Templates
Update RC app (add support for mix configurations, bug plotting window line, )...
Juan C. Espinoza -
r107:9a3b62311f15
parent child
Show More
@@ -1,338 +1,370
1 import os
1 import os
2 import ast
2 import ast
3 import json
3 import json
4
4
5 from django import forms
5 from django import forms
6 from django.utils.safestring import mark_safe
6 from django.utils.safestring import mark_safe
7 from apps.main.models import Device
7 from apps.main.models import Device
8 from apps.main.forms import add_empty_choice
8 from apps.main.forms import add_empty_choice
9 from .models import RCConfiguration, RCLine, RCLineType, RCLineCode
9 from .models import RCConfiguration, RCLine, RCLineType, RCLineCode
10 from .widgets import KmUnitWidget, KmUnitHzWidget, KmUnitDcWidget, UnitKmWidget, DefaultWidget, CodesWidget, HiddenWidget
10 from .widgets import KmUnitWidget, KmUnitHzWidget, KmUnitDcWidget, UnitKmWidget, DefaultWidget, CodesWidget, HiddenWidget, HCheckboxSelectMultiple
11
11
12 def create_choices_from_model(model, conf_id, all=False):
12 def create_choices_from_model(model, conf_id, all=False):
13
13
14 if model=='RCLine':
14 if model=='RCLine':
15 instance = RCConfiguration.objects.get(pk=conf_id)
15 instance = RCConfiguration.objects.get(pk=conf_id)
16 choices = [(line.pk, line.get_name()) for line in instance.get_lines(type='tx')]
16 choices = [(line.pk, line.get_name()) for line in instance.get_lines(line_type__name='tx')]
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['disabled'] = 'disabled'
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['disabled'] = 'disabled'
77 self.fields['experiment'].widget.attrs['disabled'] = 'disabled'
78
78
79 class Meta:
79 class Meta:
80 model = RCConfiguration
80 model = RCConfiguration
81 exclude = ('type', 'parameters', 'status')
81 exclude = ('type', 'parameters', 'status')
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
96 class RCMixConfigurationForm(forms.Form):
97
98 clock_in = forms.CharField(widget=forms.HiddenInput())
99 clock_divider = forms.CharField(widget=forms.HiddenInput())
100 name = forms.CharField()
101 experiment = forms.ChoiceField()
102 operation = forms.ChoiceField(widget=forms.RadioSelect(),
103 choices=[(0, 'OR'), (1, 'XOR'), (2, 'AND'), (3, 'NAND')],
104 initial=1)
105 delay = forms.CharField()
106 mask = forms.MultipleChoiceField(choices=[(0, 'L1'),(1, 'L2'),(2, 'L3'),(3, 'L4'),(4, 'L5'),(5, 'L6'),(6, 'L7'),(7, 'L8')],
107 widget=HCheckboxSelectMultiple())
108 result = forms.CharField(required=False,
109 widget=forms.Textarea(attrs={'readonly':True, 'rows':5, 'class':'tabuled'}))
110
111 def __init__(self, *args, **kwargs):
112 confs = kwargs.pop('confs', [])
113 if confs:
114 km2unit = confs[0].km2unit
115 clock_in = confs[0].clock_in
116 clock_divider = confs[0].clock_divider
117 else:
118 km2unit = clock_in = clock_divider = 0
119 super(RCMixConfigurationForm, self).__init__(*args, **kwargs)
120 self.fields['experiment'].choices = [(conf.pk, '{} | {}'.format(conf.pk, conf.name)) for conf in confs]
121 self.fields['delay'].widget = KmUnitWidget(attrs = {'km2unit':km2unit})
122 self.fields['clock_in'].initial = clock_in
123 self.fields['clock_divider'].initial = clock_divider
124
125
126
95 class RCLineForm(forms.ModelForm):
127 class RCLineForm(forms.ModelForm):
96
128
97 def __init__(self, *args, **kwargs):
129 def __init__(self, *args, **kwargs):
98 self.extra_fields = kwargs.pop('extra_fields', [])
130 self.extra_fields = kwargs.pop('extra_fields', [])
99 super(RCLineForm, self).__init__(*args, **kwargs)
131 super(RCLineForm, self).__init__(*args, **kwargs)
100
132
101 if 'initial' in kwargs and 'line_type' in kwargs['initial']:
133 if 'initial' in kwargs and 'line_type' in kwargs['initial']:
102 line_type = RCLineType.objects.get(pk=kwargs['initial']['line_type'])
134 line_type = RCLineType.objects.get(pk=kwargs['initial']['line_type'])
103
135
104 if 'code_id' in kwargs['initial']:
136 if 'code_id' in kwargs['initial']:
105 model_initial = kwargs['initial']['code_id']
137 model_initial = kwargs['initial']['code_id']
106 else:
138 else:
107 model_initial = 0
139 model_initial = 0
108
140
109 params = json.loads(line_type.params)
141 params = json.loads(line_type.params)
110
142
111 for label, value in self.extra_fields.items():
143 for label, value in self.extra_fields.items():
112 if label=='params':
144 if label=='params':
113 continue
145 continue
114
146
115 if 'model' in params[label]:
147 if 'model' in params[label]:
116 self.fields[label] = forms.ChoiceField(choices=create_choices_from_model(params[label]['model'],
148 self.fields[label] = forms.ChoiceField(choices=create_choices_from_model(params[label]['model'],
117 kwargs['initial']['rc_configuration']),
149 kwargs['initial']['rc_configuration']),
118 initial=model_initial)
150 initial=model_initial)
119
151
120
152
121 else:
153 else:
122 if label=='codes' and 'code_id' in kwargs['initial']:
154 if label=='codes' and 'code_id' in kwargs['initial']:
123 self.fields[label] = forms.CharField(initial=RCLineCode.objects.get(pk=kwargs['initial']['code_id']).codes)
155 self.fields[label] = forms.CharField(initial=RCLineCode.objects.get(pk=kwargs['initial']['code_id']).codes)
124 else:
156 else:
125 self.fields[label] = forms.CharField(initial=value['value'])
157 self.fields[label] = forms.CharField(initial=value['value'])
126
158
127 if label=='codes':
159 if label=='codes':
128 self.fields[label].widget = CodesWidget()
160 self.fields[label].widget = CodesWidget()
129
161
130 if self.data:
162 if self.data:
131 line_type = RCLineType.objects.get(pk=self.data['line_type'])
163 line_type = RCLineType.objects.get(pk=self.data['line_type'])
132
164
133 if 'code_id' in self.data:
165 if 'code_id' in self.data:
134 model_initial = self.data['code_id']
166 model_initial = self.data['code_id']
135 else:
167 else:
136 model_initial = 0
168 model_initial = 0
137
169
138 params = json.loads(line_type.params)
170 params = json.loads(line_type.params)
139
171
140 for label, value in self.extra_fields.items():
172 for label, value in self.extra_fields.items():
141 if label=='params':
173 if label=='params':
142 continue
174 continue
143
175
144 if 'model' in params[label]:
176 if 'model' in params[label]:
145 self.fields[label] = forms.ChoiceField(choices=create_choices_from_model(params[label]['model'],
177 self.fields[label] = forms.ChoiceField(choices=create_choices_from_model(params[label]['model'],
146 self.data['rc_configuration']),
178 self.data['rc_configuration']),
147 initial=model_initial)
179 initial=model_initial)
148
180
149
181
150 else:
182 else:
151 if label=='codes' and 'code' in self.data:
183 if label=='codes' and 'code' in self.data:
152 self.fields[label] = forms.CharField(initial=self.data['codes'])
184 self.fields[label] = forms.CharField(initial=self.data['codes'])
153 else:
185 else:
154 self.fields[label] = forms.CharField(initial=self.data[label])
186 self.fields[label] = forms.CharField(initial=self.data[label])
155
187
156 if label=='codes':
188 if label=='codes':
157 self.fields[label].widget = CodesWidget()
189 self.fields[label].widget = CodesWidget()
158
190
159
191
160 class Meta:
192 class Meta:
161 model = RCLine
193 model = RCLine
162 fields = ('rc_configuration', 'line_type', 'channel')
194 fields = ('rc_configuration', 'line_type', 'channel')
163 widgets = {
195 widgets = {
164 'channel': forms.HiddenInput(),
196 'channel': forms.HiddenInput(),
165 }
197 }
166
198
167
199
168 def clean(self):
200 def clean(self):
169
201
170 form_data = self.cleaned_data
202 form_data = self.cleaned_data
171 if 'code' in self.data and self.data['TX_ref']=="0":
203 if 'code' in self.data and self.data['TX_ref']=="0":
172 self.add_error('TX_ref', 'Choose a valid TX reference')
204 self.add_error('TX_ref', 'Choose a valid TX reference')
173
205
174 return form_data
206 return form_data
175
207
176
208
177 def save(self):
209 def save(self):
178 line = super(RCLineForm, self).save()
210 line = super(RCLineForm, self).save()
179
211
180 #auto add channel
212 #auto add channel
181 line.channel = RCLine.objects.filter(rc_configuration=line.rc_configuration).count()-1
213 line.channel = RCLine.objects.filter(rc_configuration=line.rc_configuration).count()-1
182
214
183 #auto add position for TX, TR & CODE
215 #auto add position for TX, TR & CODE
184 if line.line_type.name in ('tx', ):
216 if line.line_type.name in ('tx', ):
185 line.position = RCLine.objects.filter(rc_configuration=line.rc_configuration, line_type=line.line_type).count()-1
217 line.position = RCLine.objects.filter(rc_configuration=line.rc_configuration, line_type=line.line_type).count()-1
186
218
187 #save extra fields in params
219 #save extra fields in params
188 params = {}
220 params = {}
189 for label, value in self.extra_fields.items():
221 for label, value in self.extra_fields.items():
190 if label=='params':
222 if label=='params':
191 params['params'] = []
223 params['params'] = []
192 elif label=='codes':
224 elif label=='codes':
193 params[label] = [s for s in self.data[label].split('\r\n') if s]
225 params[label] = [s for s in self.data[label].split('\r\n') if s]
194 else:
226 else:
195 params[label] = self.data[label]
227 params[label] = self.data[label]
196 line.params = json.dumps(params)
228 line.params = json.dumps(params)
197 line.save()
229 line.save()
198 return
230 return
199
231
200
232
201 class RCLineViewForm(forms.Form):
233 class RCLineViewForm(forms.Form):
202
234
203 def __init__(self, *args, **kwargs):
235 def __init__(self, *args, **kwargs):
204
236
205 extra_fields = kwargs.pop('extra_fields')
237 extra_fields = kwargs.pop('extra_fields')
206 line = kwargs.pop('line')
238 line = kwargs.pop('line')
207 subform = kwargs.pop('subform', False)
239 subform = kwargs.pop('subform', False)
208 super(RCLineViewForm, self).__init__(*args, **kwargs)
240 super(RCLineViewForm, self).__init__(*args, **kwargs)
209
241
210 if subform:
242 if subform:
211 params = json.loads(line.line_type.params)['params']
243 params = json.loads(line.line_type.params)['params']
212 else:
244 else:
213 params = json.loads(line.line_type.params)
245 params = json.loads(line.line_type.params)
214
246
215 for label, value in extra_fields.items():
247 for label, value in extra_fields.items():
216
248
217 if label=='params':
249 if label=='params':
218 continue
250 continue
219 if 'ref' in label:
251 if 'ref' in label:
220 if value in (0, '0'):
252 if value in (0, '0'):
221 value = 'All'
253 value = 'All'
222 else:
254 else:
223 value = RCLine.objects.get(pk=value).get_name()
255 value = RCLine.objects.get(pk=value).get_name()
224 elif label=='code':
256 elif label=='code':
225 value = RCLineCode.objects.get(pk=value).name
257 value = RCLineCode.objects.get(pk=value).name
226
258
227 self.fields[label] = forms.CharField(initial=value)
259 self.fields[label] = forms.CharField(initial=value)
228
260
229 if 'widget' in params[label]:
261 if 'widget' in params[label]:
230 km2unit = line.rc_configuration.km2unit
262 km2unit = line.rc_configuration.km2unit
231 if params[label]['widget']=='km':
263 if params[label]['widget']=='km':
232 self.fields[label].widget = KmUnitWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
264 self.fields[label].widget = KmUnitWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
233 elif params[label]['widget']=='unit':
265 elif params[label]['widget']=='unit':
234 self.fields[label].widget = UnitKmWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
266 self.fields[label].widget = UnitKmWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
235 elif params[label]['widget']=='dc':
267 elif params[label]['widget']=='dc':
236 self.fields[label].widget = KmUnitDcWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
268 self.fields[label].widget = KmUnitDcWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
237 elif params[label]['widget']=='codes':
269 elif params[label]['widget']=='codes':
238 self.fields[label].widget = CodesWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
270 self.fields[label].widget = CodesWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
239 else:
271 else:
240 self.fields[label].widget = DefaultWidget(attrs={'disabled':True})
272 self.fields[label].widget = DefaultWidget(attrs={'disabled':True})
241
273
242
274
243 class RCLineEditForm(forms.ModelForm):
275 class RCLineEditForm(forms.ModelForm):
244
276
245 def __init__(self, *args, **kwargs):
277 def __init__(self, *args, **kwargs):
246
278
247 extra_fields = kwargs.pop('extra_fields', [])
279 extra_fields = kwargs.pop('extra_fields', [])
248 conf = kwargs.pop('conf', False)
280 conf = kwargs.pop('conf', False)
249 line = kwargs.pop('line')
281 line = kwargs.pop('line')
250 subform = kwargs.pop('subform', False)
282 subform = kwargs.pop('subform', False)
251
283
252 super(RCLineEditForm, self).__init__(*args, **kwargs)
284 super(RCLineEditForm, self).__init__(*args, **kwargs)
253
285
254 if subform is not False:
286 if subform is not False:
255 params = json.loads(line.line_type.params)['params']
287 params = json.loads(line.line_type.params)['params']
256 count = subform
288 count = subform
257 else:
289 else:
258 params = json.loads(line.line_type.params)
290 params = json.loads(line.line_type.params)
259 count = -1
291 count = -1
260
292
261 for label, value in extra_fields.items():
293 for label, value in extra_fields.items():
262
294
263 if label in ('params',):
295 if label in ('params',):
264 continue
296 continue
265 if 'help' in params[label]:
297 if 'help' in params[label]:
266 help_text = params[label]['help']
298 help_text = params[label]['help']
267 else:
299 else:
268 help_text = ''
300 help_text = ''
269
301
270 if 'model' in params[label]:
302 if 'model' in params[label]:
271 self.fields[label] = forms.ChoiceField(choices=create_choices_from_model(params[label]['model'], conf.id),
303 self.fields[label] = forms.ChoiceField(choices=create_choices_from_model(params[label]['model'], conf.id),
272 initial=value,
304 initial=value,
273 widget=forms.Select(attrs={'name':'%s|%s|%s' % (count, line.id, label)}),
305 widget=forms.Select(attrs={'name':'%s|%s|%s' % (count, line.id, label)}),
274 help_text=help_text)
306 help_text=help_text)
275
307
276 else:
308 else:
277
309
278 self.fields[label] = forms.CharField(initial=value, help_text=help_text)
310 self.fields[label] = forms.CharField(initial=value, help_text=help_text)
279
311
280 if label in ('code', ):
312 if label in ('code', ):
281 self.fields[label].widget = HiddenWidget(attrs={'name':'%s|%s|%s' % (count, line.id, label)})
313 self.fields[label].widget = HiddenWidget(attrs={'name':'%s|%s|%s' % (count, line.id, label)})
282
314
283 elif 'widget' in params[label]:
315 elif 'widget' in params[label]:
284 km2unit = line.rc_configuration.km2unit
316 km2unit = line.rc_configuration.km2unit
285 if params[label]['widget']=='km':
317 if params[label]['widget']=='km':
286 self.fields[label].widget = KmUnitWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
318 self.fields[label].widget = KmUnitWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
287 elif params[label]['widget']=='unit':
319 elif params[label]['widget']=='unit':
288 self.fields[label].widget = UnitKmWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
320 self.fields[label].widget = UnitKmWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
289 elif params[label]['widget']=='dc':
321 elif params[label]['widget']=='dc':
290 self.fields[label].widget = KmUnitDcWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
322 self.fields[label].widget = KmUnitDcWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
291 elif params[label]['widget']=='codes':
323 elif params[label]['widget']=='codes':
292 self.fields[label].widget = CodesWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
324 self.fields[label].widget = CodesWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
293 else:
325 else:
294 self.fields[label].widget = DefaultWidget(attrs={'name':'%s|%s|%s' % (count, line.id, label)})
326 self.fields[label].widget = DefaultWidget(attrs={'name':'%s|%s|%s' % (count, line.id, label)})
295
327
296
328
297 class Meta:
329 class Meta:
298 model = RCLine
330 model = RCLine
299 exclude = ('rc_configuration', 'line_type', 'channel', 'position', 'params', 'pulses')
331 exclude = ('rc_configuration', 'line_type', 'channel', 'position', 'params', 'pulses')
300
332
301
333
302 class RCSubLineEditForm(forms.Form):
334 class RCSubLineEditForm(forms.Form):
303
335
304 def __init__(self, *args, **kwargs):
336 def __init__(self, *args, **kwargs):
305 extra_fields = kwargs.pop('extra_fields')
337 extra_fields = kwargs.pop('extra_fields')
306 count = kwargs.pop('count')
338 count = kwargs.pop('count')
307 line = kwargs.pop('line')
339 line = kwargs.pop('line')
308 super(RCSubLineEditForm, self).__init__(*args, **kwargs)
340 super(RCSubLineEditForm, self).__init__(*args, **kwargs)
309 for label, value in extra_fields.items():
341 for label, value in extra_fields.items():
310 self.fields[label] = forms.CharField(initial=value,
342 self.fields[label] = forms.CharField(initial=value,
311 widget=forms.TextInput(attrs={'name':'%s|%s|%s' % (count, line, label)}))
343 widget=forms.TextInput(attrs={'name':'%s|%s|%s' % (count, line, label)}))
312
344
313
345
314 class RCImportForm(forms.Form):
346 class RCImportForm(forms.Form):
315
347
316 file_name = ExtFileField(extensions=['.racp', '.json', '.dat'])
348 file_name = ExtFileField(extensions=['.racp', '.json', '.dat'])
317
349
318
350
319 class RCLineCodesForm(forms.ModelForm):
351 class RCLineCodesForm(forms.ModelForm):
320
352
321 def __init__(self, *args, **kwargs):
353 def __init__(self, *args, **kwargs):
322 super(RCLineCodesForm, self).__init__(*args, **kwargs)
354 super(RCLineCodesForm, self).__init__(*args, **kwargs)
323
355
324 if 'initial' in kwargs:
356 if 'initial' in kwargs:
325 self.fields['code'] = forms.ChoiceField(choices=RCLineCode.objects.all().values_list('pk', 'name'),
357 self.fields['code'] = forms.ChoiceField(choices=RCLineCode.objects.all().values_list('pk', 'name'),
326 initial=kwargs['initial']['code'])
358 initial=kwargs['initial']['code'])
327 if 'instance' in kwargs:
359 if 'instance' in kwargs:
328 self.fields['code'] = forms.ChoiceField(choices=RCLineCode.objects.all().values_list('pk', 'name'),
360 self.fields['code'] = forms.ChoiceField(choices=RCLineCode.objects.all().values_list('pk', 'name'),
329 initial=kwargs['instance'].pk)
361 initial=kwargs['instance'].pk)
330
362
331 self.fields['codes'].widget = CodesWidget()
363 self.fields['codes'].widget = CodesWidget()
332
364
333
365
334 class Meta:
366 class Meta:
335 model = RCLineCode
367 model = RCLineCode
336 exclude = ('name',)
368 exclude = ('name',)
337
369
338 No newline at end of file
370
@@ -1,559 +1,645
1
1
2 import ast
2 import ast
3 import json
3 import json
4 import numpy as np
4 import numpy as np
5
5
6 from polymorphic import PolymorphicModel
6 from polymorphic import PolymorphicModel
7
7
8 from django.db import models
8 from django.db import models
9 from django.core.urlresolvers import reverse
9 from django.core.urlresolvers import reverse
10 from django.core.validators import MinValueValidator, MaxValueValidator
10 from django.core.validators import MinValueValidator, MaxValueValidator
11
11
12 from apps.main.models import Configuration
12 from apps.main.models import Configuration
13 from devices.rc import api
13 from .utils import RCFile, pulses, pulses_from_code, create_mask, pulses_to_points
14 from .utils import RCFile, pulses, pulses_from_code, create_mask, pulses_to_points
14
15
15 # Create your models here.
16 # Create your models here.
16
17
17 LINE_TYPES = (
18 LINE_TYPES = (
18 ('none', 'Not used'),
19 ('none', 'Not used'),
19 ('tr', 'Transmission/reception selector signal'),
20 ('tr', 'Transmission/reception selector signal'),
20 ('tx', 'A modulating signal (Transmission pulse)'),
21 ('tx', 'A modulating signal (Transmission pulse)'),
21 ('codes', 'BPSK modulating signal'),
22 ('codes', 'BPSK modulating signal'),
22 ('windows', 'Sample window signal'),
23 ('windows', 'Sample window signal'),
23 ('sync', 'Synchronizing signal'),
24 ('sync', 'Synchronizing signal'),
24 ('flip', 'IPP related periodic signal'),
25 ('flip', 'IPP related periodic signal'),
25 ('prog_pulses', 'Programmable pulse'),
26 ('prog_pulses', 'Programmable pulse'),
27 ('mix', 'Mixed line'),
26 )
28 )
27
29
28
30
29 SAMPLING_REFS = (
31 SAMPLING_REFS = (
30 ('none', 'No Reference'),
32 ('none', 'No Reference'),
31 ('first_baud', 'Middle of the first baud'),
33 ('first_baud', 'Middle of the first baud'),
32 ('sub_baud', 'Middle of the sub-baud')
34 ('sub_baud', 'Middle of the sub-baud')
33 )
35 )
34
36
35 DAT_CMDS = {
37 DAT_CMDS = {
36 # Pulse Design commands
38 # Pulse Design commands
37 'DISABLE' : 0, # Disables pulse generation
39 'DISABLE' : 0, # Disables pulse generation
38 'ENABLE' : 24, # Enables pulse generation
40 'ENABLE' : 24, # Enables pulse generation
39 'DELAY_START' : 40, # Write delay status to memory
41 'DELAY_START' : 40, # Write delay status to memory
40 'FLIP_START' : 48, # Write flip status to memory
42 'FLIP_START' : 48, # Write flip status to memory
41 'SAMPLING_PERIOD' : 64, # Establish Sampling Period
43 'SAMPLING_PERIOD' : 64, # Establish Sampling Period
42 'TX_ONE' : 72, # Output '0' in line TX
44 'TX_ONE' : 72, # Output '0' in line TX
43 'TX_ZERO' : 88, # Output '0' in line TX
45 'TX_ZERO' : 88, # Output '0' in line TX
44 'SW_ONE' : 104, # Output '0' in line SW
46 'SW_ONE' : 104, # Output '0' in line SW
45 'SW_ZERO' : 112, # Output '1' in line SW
47 'SW_ZERO' : 112, # Output '1' in line SW
46 'RESTART': 120, # Restarts CR8 Firmware
48 'RESTART': 120, # Restarts CR8 Firmware
47 'CONTINUE' : 253, # Function Unknown
49 'CONTINUE' : 253, # Function Unknown
48 # Commands available to new controllers
50 # Commands available to new controllers
49 # 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.
51 # 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.
50 'CLOCK_DIVISOR_INIT' : 12, # Specifies Clock Divisor. Legacy command, ignored in the actual .dat conversion
52 'CLOCK_DIVISOR_INIT' : 12, # Specifies Clock Divisor. Legacy command, ignored in the actual .dat conversion
51 'CLOCK_DIVISOR_LAST' : 22, # Specifies Clock Divisor (default 60 if not included) syntax: 255,22 254,N-1.
53 'CLOCK_DIVISOR_LAST' : 22, # Specifies Clock Divisor (default 60 if not included) syntax: 255,22 254,N-1.
52 'CLOCK_DIVIDER' : 8,
54 'CLOCK_DIVIDER' : 8,
53 }
55 }
54
56
55
57
56 class RCConfiguration(Configuration):
58 class RCConfiguration(Configuration):
57
59
58 ipp = models.FloatField(verbose_name='Inter pulse period (Km)', validators=[MinValueValidator(1), MaxValueValidator(1000)], default=10)
60 ipp = models.FloatField(verbose_name='Inter pulse period (Km)', validators=[MinValueValidator(1), MaxValueValidator(9000)], default=300)
59 ntx = models.PositiveIntegerField(verbose_name='Number of TX', validators=[MinValueValidator(1), MaxValueValidator(256)], default=1)
61 ntx = models.PositiveIntegerField(verbose_name='Number of TX', validators=[MinValueValidator(1), MaxValueValidator(300)], default=1)
60 clock_in = models.FloatField(verbose_name='Clock in (MHz)', validators=[MinValueValidator(1), MaxValueValidator(80)], default=1)
62 clock_in = models.FloatField(verbose_name='Clock in (MHz)', validators=[MinValueValidator(1), MaxValueValidator(80)], default=1)
61 clock_divider = models.PositiveIntegerField(verbose_name='Clock divider', validators=[MinValueValidator(1), MaxValueValidator(256)], default=1)
63 clock_divider = models.PositiveIntegerField(verbose_name='Clock divider', validators=[MinValueValidator(1), MaxValueValidator(256)], default=1)
62 clock = models.FloatField(verbose_name='Clock Master (MHz)', blank=True, default=1)
64 clock = models.FloatField(verbose_name='Clock Master (MHz)', blank=True, default=1)
63 time_before = models.PositiveIntegerField(verbose_name='Time before (&mu;S)', default=0)
65 time_before = models.PositiveIntegerField(verbose_name='Time before (&mu;S)', default=12)
64 time_after = models.PositiveIntegerField(verbose_name='Time after (&mu;S)', default=0)
66 time_after = models.PositiveIntegerField(verbose_name='Time after (&mu;S)', default=1)
65 sync = models.PositiveIntegerField(verbose_name='Synchro delay', default=0)
67 sync = models.PositiveIntegerField(verbose_name='Synchro delay', default=0)
66 sampling_reference = models.CharField(verbose_name='Sampling Reference', choices=SAMPLING_REFS, default='none', max_length=40)
68 sampling_reference = models.CharField(verbose_name='Sampling Reference', choices=SAMPLING_REFS, default='none', max_length=40)
67 control_tx = models.BooleanField(verbose_name='Control Switch TX', default=False)
69 control_tx = models.BooleanField(verbose_name='Control Switch TX', default=False)
68 control_sw = models.BooleanField(verbose_name='Control Switch SW', default=False)
70 control_sw = models.BooleanField(verbose_name='Control Switch SW', default=False)
69
71 mix = models.BooleanField(default=False)
70
72
71 class Meta:
73 class Meta:
72 db_table = 'rc_configurations'
74 db_table = 'rc_configurations'
73
75
74
76
77 def __unicode__(self):
78
79 if self.mix:
80 return u'[MIXED]: %s' % self.name
81 else:
82 return u'[%s]: %s' % (self.device.name, self.name)
83
75 def get_absolute_url_plot(self):
84 def get_absolute_url_plot(self):
76 return reverse('url_plot_rc_pulses', args=[str(self.id)])
85 return reverse('url_plot_rc_pulses', args=[str(self.id)])
77
86
78 def get_absolute_url_import(self):
87 def get_absolute_url_import(self):
79 return reverse('url_import_rc_conf', args=[str(self.id)])
88 return reverse('url_import_rc_conf', args=[str(self.id)])
80
89
81 @property
90 @property
82 def us2unit(self):
91 def us2unit(self):
83
92
84 return self.clock_in/self.clock_divider
93 return self.clock_in/self.clock_divider
85
94
86
87 @property
95 @property
88 def km2unit(self):
96 def km2unit(self):
89
97
90 return 20./3*(self.clock_in/self.clock_divider)
98 return 20./3*(self.clock_in/self.clock_divider)
91
99
92
93 def clone(self, **kwargs):
100 def clone(self, **kwargs):
94
101
95 lines = self.get_lines()
102 lines = self.get_lines()
96 self.pk = None
103 self.pk = None
97 self.id = None
104 self.id = None
98 for attr, value in kwargs.items():
105 for attr, value in kwargs.items():
99 setattr(self, attr, value)
106 setattr(self, attr, value)
100 self.save()
107 self.save()
101
108
102 for line in lines:
109 for line in lines:
103 line.clone(rc_configuration=self)
110 line.clone(rc_configuration=self)
104
111
105 return self
112 return self
106
113
107 def get_lines(self, type=None):
114 def get_lines(self, **kwargs):
108 '''
115 '''
109 Retrieve configuration lines
116 Retrieve configuration lines
110 '''
117 '''
111
118
112 if type is not None:
119 return RCLine.objects.filter(rc_configuration=self.pk, **kwargs)
113 return RCLine.objects.filter(rc_configuration=self.pk, line_type__name=type)
120
114 else:
115 return RCLine.objects.filter(rc_configuration=self.pk)
116
121
117 def clean_lines(self):
122 def clean_lines(self):
118 '''
123 '''
119 '''
124 '''
120
125
121 empty_line = RCLineType.objects.get(pk=8)
126 empty_line = RCLineType.objects.get(pk=8)
122
127
123 for line in self.get_lines():
128 for line in self.get_lines():
124 line.line_type = empty_line
129 line.line_type = empty_line
125 line.params = '{}'
130 line.params = '{}'
126 line.save()
131 line.save()
127
132
128 def parms_to_dict(self):
133 def parms_to_dict(self):
129 '''
134 '''
130 '''
135 '''
131
136
132 data = {}
137 data = {}
133 for field in self._meta.fields:
138 for field in self._meta.fields:
134
139
135 data[field.name] = '{}'.format(field.value_from_object(self))
140 data[field.name] = '{}'.format(field.value_from_object(self))
136
141
137 data.pop('parameters')
142 data.pop('parameters')
138 data['lines'] = []
143 data['lines'] = []
139
144
140 for line in self.get_lines():
145 for line in self.get_lines():
141 line_data = json.loads(line.params)
146 line_data = json.loads(line.params)
142 if 'TX_ref' in line_data and line_data['TX_ref'] not in (0, '0'):
147 if 'TX_ref' in line_data and line_data['TX_ref'] not in (0, '0'):
143 line_data['TX_ref'] = RCLine.objects.get(pk=line_data['TX_ref']).get_name()
148 line_data['TX_ref'] = RCLine.objects.get(pk=line_data['TX_ref']).get_name()
144 if 'code' in line_data:
149 if 'code' in line_data:
145 line_data['code'] = RCLineCode.objects.get(pk=line_data['code']).name
150 line_data['code'] = RCLineCode.objects.get(pk=line_data['code']).name
146 line_data['type'] = line.line_type.name
151 line_data['type'] = line.line_type.name
147 data['lines'].append(line_data)
152 data['lines'].append(line_data)
148
153
154 data['delays'] = self.get_delays()
155 data['pulses'] = self.get_pulses()
149
156
150 return data
157 return data
151
158
159 def dict_to_parms(self, data):
160 '''
161 '''
162
163 self.name = data['name']
164 self.ipp = data['ipp']
165 self.ntx = data['ntx']
166 self.clock_in = data['clock_in']
167 self.clock_divider = data['clock_divider']
168 self.clock = data['clock']
169 self.time_before = data['time_before']
170 self.time_after = data['time_after']
171 self.sync = data['sync']
172 self.sampling_reference = data['sampling_reference']
173 self.clean_lines()
174
175 lines = []
176 positions = {'tx':0, 'tr':0}
177
178 for i, line_data in enumerate(data['lines']):
179 line_type = RCLineType.objects.get(name=line_data.pop('type'))
180 if line_type.name=='codes':
181 code = RCLineCode.objects.get(name=line_data['code'])
182 line_data['code'] = code.pk
183 line = RCLine.objects.filter(rc_configuration=self, channel=i)
184 if line:
185 line = line[0]
186 line.line_type = line_type
187 line.params = json.dumps(line_data)
188 else:
189 line = RCLine(rc_configuration=self, line_type=line_type,
190 params=json.dumps(line_data),
191 channel=i)
192
193 if line_type.name=='tx':
194 line.position = positions['tx']
195 positions['tx'] += 1
196
197 if line_type.name=='tr':
198 line.position = positions['tr']
199 positions['tr'] += 1
200
201 line.save()
202 lines.append(line)
203
204 for line, line_data in zip(lines, data['lines']):
205 if 'TX_ref' in line_data:
206 params = json.loads(line.params)
207 if line_data['TX_ref'] in (0, '0'):
208 params['TX_ref'] = '0'
209 else:
210 params['TX_ref'] = [l.pk for l in lines if l.line_type.name=='tx' and l.get_name()==line_data['TX_ref']][0]
211 line.params = json.dumps(params)
212 line.save()
213
214
152 def get_delays(self):
215 def get_delays(self):
153
216
154 pulses = [line.get_pulses() for line in self.get_lines()]
217 pulses = [line.get_pulses() for line in self.get_lines()]
155 points = [tup for tups in pulses for tup in tups]
218 points = [tup for tups in pulses for tup in tups]
156 points = set([x for tup in points for x in tup])
219 points = set([x for tup in points for x in tup])
157 points = list(points)
220 points = list(points)
158 points.sort()
221 points.sort()
159
222
160 if points[0]<>0:
223 if points[0]<>0:
161 points.insert(0, 0)
224 points.insert(0, 0)
162
225
163 return [points[i+1]-points[i] for i in range(len(points)-1)]
226 return [points[i+1]-points[i] for i in range(len(points)-1)]
164
227
165
228
166 def get_flips(self):
229 def get_pulses(self, binary=True):
230
231 pulses = [line.get_pulses() for line in self.get_lines()]
232 points = [tup for tups in pulses for tup in tups]
233 points = set([x for tup in points for x in tup])
234 points = list(points)
235 points.sort()
167
236
168 line_points = [pulses_to_points(line.pulses_as_array()) for line in self.get_lines()]
237 line_points = [pulses_to_points(line.pulses_as_array()) for line in self.get_lines()]
169 line_points = [[(x, x+y) for x,y in tups] for tups in line_points]
238 line_points = [[(x, x+y) for x,y in tups] for tups in line_points]
170 line_points = [[t for x in tups for t in x] for tups in line_points]
239 line_points = [[t for x in tups for t in x] for tups in line_points]
171 states = [[1 if x in tups else 0 for tups in line_points] for x in points]
240 states = [[1 if x in tups else 0 for tups in line_points] for x in points]
172
241
173 return states
242 if binary:
243 states.reverse()
244 states = [int(''.join([str(x) for x in flips]), 2) for flips in states]
245
246 return states[:-1]
174
247
175 def add_cmd(self, cmd):
248 def add_cmd(self, cmd):
176
249
177 if cmd in DAT_CMDS:
250 if cmd in DAT_CMDS:
178 return (255, DAT_CMDS[cmd])
251 return (255, DAT_CMDS[cmd])
179
252
180 def add_data(self, value):
253 def add_data(self, value):
181
254
182 return (254, value-1)
255 return (254, value-1)
183
256
184 def parms_to_binary(self):
257 def parms_to_binary(self):
185 '''
258 '''
186 Create "dat" stream to be send to CR
259 Create "dat" stream to be send to CR
187 '''
260 '''
188
261
189 data = []
262 data = []
190 # create header
263 # create header
191 data.append(self.add_cmd('DISABLE'))
264 data.append(self.add_cmd('DISABLE'))
192 data.append(self.add_cmd('CONTINUE'))
265 data.append(self.add_cmd('CONTINUE'))
193 data.append(self.add_cmd('RESTART'))
266 data.append(self.add_cmd('RESTART'))
194
267
195 if self.control_sw:
268 if self.control_sw:
196 data.append(self.add_cmd('SW_ONE'))
269 data.append(self.add_cmd('SW_ONE'))
197 else:
270 else:
198 data.append(self.add_cmd('SW_ZERO'))
271 data.append(self.add_cmd('SW_ZERO'))
199
272
200 if self.control_tx:
273 if self.control_tx:
201 data.append(self.add_cmd('TX_ONE'))
274 data.append(self.add_cmd('TX_ONE'))
202 else:
275 else:
203 data.append(self.add_cmd('TX_ZERO'))
276 data.append(self.add_cmd('TX_ZERO'))
204
277
205 # write divider
278 # write divider
206 data.append(self.add_cmd('CLOCK_DIVIDER'))
279 data.append(self.add_cmd('CLOCK_DIVIDER'))
207 data.append(self.add_data(self.clock_divider))
280 data.append(self.add_data(self.clock_divider))
208
281
209 # write delays
282 # write delays
210 data.append(self.add_cmd('DELAY_START'))
283 data.append(self.add_cmd('DELAY_START'))
211 # first delay is always zero
284 # first delay is always zero
212 data.append(self.add_data(1))
285 data.append(self.add_data(1))
213 line_points = [pulses_to_points(line.pulses_as_array()) for line in self.get_lines()]
214 points = [tup for tups in line_points for tup in tups]
215 points = [(x, x+y) for x,y in points]
216 points = set([x for tup in points for x in tup])
217 points = list(points)
218 points.sort()
219
286
220 if points[0]<>0:
287 delays = self.get_delays()
221 points.insert(0, 0)
222
223 delays = [points[i+1]-points[i] for i in range(len(points)-1)]
224
288
225 for delay in delays:
289 for delay in delays:
226 while delay>252:
290 while delay>252:
227 data.append(self.add_data(253))
291 data.append(self.add_data(253))
228 delay -= 253
292 delay -= 253
229 data.append(self.add_data(delay))
293 data.append(self.add_data(delay))
230
294
231 # write flips
295 # write flips
232 data.append(self.add_cmd('FLIP_START'))
296 data.append(self.add_cmd('FLIP_START'))
233 line_points = [[(x, x+y) for x,y in tups] for tups in line_points]
297
234 line_points = [[t for x in tups for t in x] for tups in line_points]
298 states = self.get_pulses(binary=False)
235 states = [[1 if x in tups else 0 for tups in line_points] for x in points]
299
236 for flips, delay in zip(states[:-1], delays):
300 for flips, delay in zip(states, delays):
237 flips.reverse()
301 flips.reverse()
238 flip = int(''.join([str(x) for x in flips]), 2)
302 flip = int(''.join([str(x) for x in flips]), 2)
239 data.append(self.add_data(flip+1))
303 data.append(self.add_data(flip+1))
240 while delay>252:
304 while delay>252:
241 data.append(self.add_data(1))
305 data.append(self.add_data(1))
242 delay -= 253
306 delay -= 253
243
307
244 # write sampling period
308 # write sampling period
245 data.append(self.add_cmd('SAMPLING_PERIOD'))
309 data.append(self.add_cmd('SAMPLING_PERIOD'))
246 wins = self.get_lines(type='windows')
310 wins = self.get_lines(line_type__name='windows')
247 if wins:
311 if wins:
248 win_params = json.loads(wins[0].params)['params']
312 win_params = json.loads(wins[0].params)['params']
249 if win_params:
313 if win_params:
250 dh = int(win_params[0]['resolution']*self.km2unit)
314 dh = int(win_params[0]['resolution']*self.km2unit)
251 else:
315 else:
252 dh = 1
316 dh = 1
253 else:
317 else:
254 dh = 1
318 dh = 1
255 data.append(self.add_data(dh))
319 data.append(self.add_data(dh))
256
320
257 # write enable
321 # write enable
258 data.append(self.add_cmd('ENABLE'))
322 data.append(self.add_cmd('ENABLE'))
259
323
260 return '\n'.join(['{}'.format(x) for tup in data for x in tup])
324 return '\n'.join(['{}'.format(x) for tup in data for x in tup])
261
325
262 def update_from_file(self, filename):
326 def update_from_file(self, filename):
263 '''
327 '''
264 Update instance from file
328 Update instance from file
265 '''
329 '''
266
330
267 f = RCFile(filename)
331 f = RCFile(filename)
268 data = f.data
332 self.dict_to_parms(f.data)
269 self.name = data['name']
270 self.ipp = data['ipp']
271 self.ntx = data['ntx']
272 self.clock_in = data['clock_in']
273 self.clock_divider = data['clock_divider']
274 self.clock = data['clock']
275 self.time_before = data['time_before']
276 self.time_after = data['time_after']
277 self.sync = data['sync']
278 self.sampling_reference = data['sampling_reference']
279 self.clean_lines()
280
333
281 lines = []
334 def update_pulses(self):
282 positions = {'tx':0, 'tr':0}
283
335
284 for i, line_data in enumerate(data['lines']):
336 for line in self.get_lines():
285 line_type = RCLineType.objects.get(name=line_data.pop('type'))
337 if line.line_type.name=='tr':
286 if line_type.name=='codes':
338 continue
287 code = RCLineCode.objects.get(name=line_data['code'])
339 line.update_pulses()
288 line_data['code'] = code.pk
289 line = RCLine.objects.filter(rc_configuration=self, channel=i)
290 if line:
291 line = line[0]
292 line.line_type = line_type
293 line.params = json.dumps(line_data)
294 else:
295 line = RCLine(rc_configuration=self, line_type=line_type,
296 params=json.dumps(line_data),
297 channel=i)
298
340
299 if line_type.name=='tx':
341 for tr in self.get_lines(line_type__name='tr'):
300 line.position = positions['tx']
342 tr.update_pulses()
301 positions['tx'] += 1
302
343
303 if line_type.name=='tr':
344 def status_device(self):
304 line.position = positions['tr']
305 positions['tr'] += 1
306
345
307 line.save()
346 return 0
308 lines.append(line)
309
347
310 for line, line_data in zip(lines, data['lines']):
348 def stop_device(self):
311 if 'TX_ref' in line_data:
312 params = json.loads(line.params)
313 if line_data['TX_ref'] in (0, '0'):
314 params['TX_ref'] = '0'
315 else:
316 params['TX_ref'] = [l.pk for l in lines if l.line_type.name=='tx' and l.get_name()==line_data['TX_ref']][0]
317 line.params = json.dumps(params)
318 line.save()
319
349
350 answer = api.disable(ip = self.device.ip_address,
351 port = self.device.port_address)
320
352
321 def status_device(self):
353 if answer[0] != "1":
354 self.message = answer[0:]
355 return 0
322
356
357 self.message = answer[2:]
358 return 1
359
360 def start_device(self):
361
362 answer = api.enable(ip = self.device.ip_address,
363 port = self.device.port_address)
364
365 if answer[0] != "1":
366 self.message = answer[0:]
323 return 0
367 return 0
324
368
369 self.message = answer[2:]
370 return 1
371
372 def write_device(self):
373 answer = api.write_config(ip = self.device.ip_address,
374 port = self.device.port_address,
375 parms = self.parms_to_dict())
376
377 if answer[0] != "1":
378 self.message = answer[0:]
379 return 0
380
381 self.message = answer[2:]
382 return 1
383
384
325 class RCLineCode(models.Model):
385 class RCLineCode(models.Model):
326
386
327 name = models.CharField(max_length=40)
387 name = models.CharField(max_length=40)
328 bits_per_code = models.PositiveIntegerField(default=0)
388 bits_per_code = models.PositiveIntegerField(default=0)
329 number_of_codes = models.PositiveIntegerField(default=0)
389 number_of_codes = models.PositiveIntegerField(default=0)
330 codes = models.TextField(blank=True, null=True)
390 codes = models.TextField(blank=True, null=True)
331
391
332 class Meta:
392 class Meta:
333 db_table = 'rc_line_codes'
393 db_table = 'rc_line_codes'
334 ordering = ('name',)
394 ordering = ('name',)
335
395
336 def __unicode__(self):
396 def __unicode__(self):
337 return u'%s' % self.name
397 return u'%s' % self.name
338
398
399
339 class RCLineType(models.Model):
400 class RCLineType(models.Model):
340
401
341 name = models.CharField(choices=LINE_TYPES, max_length=40)
402 name = models.CharField(choices=LINE_TYPES, max_length=40)
342 description = models.TextField(blank=True, null=True)
403 description = models.TextField(blank=True, null=True)
343 params = models.TextField(default='[]')
404 params = models.TextField(default='[]')
344
405
345 class Meta:
406 class Meta:
346 db_table = 'rc_line_types'
407 db_table = 'rc_line_types'
347
408
348 def __unicode__(self):
409 def __unicode__(self):
349 return u'%s - %s' % (self.name.upper(), self.get_name_display())
410 return u'%s - %s' % (self.name.upper(), self.get_name_display())
350
411
351
412
352 class RCLine(models.Model):
413 class RCLine(models.Model):
353
414
354 rc_configuration = models.ForeignKey(RCConfiguration, on_delete=models.CASCADE)
415 rc_configuration = models.ForeignKey(RCConfiguration, on_delete=models.CASCADE)
355 line_type = models.ForeignKey(RCLineType)
416 line_type = models.ForeignKey(RCLineType)
356 channel = models.PositiveIntegerField(default=0)
417 channel = models.PositiveIntegerField(default=0)
357 position = models.PositiveIntegerField(default=0)
418 position = models.PositiveIntegerField(default=0)
358 params = models.TextField(default='{}')
419 params = models.TextField(default='{}')
359 pulses = models.TextField(default='')
420 pulses = models.TextField(default='')
360
421
361 class Meta:
422 class Meta:
362 db_table = 'rc_lines'
423 db_table = 'rc_lines'
363 ordering = ['channel']
424 ordering = ['channel']
364
425
365 def __unicode__(self):
426 def __unicode__(self):
366 if self.rc_configuration:
427 if self.rc_configuration:
367 return u'%s - %s' % (self.rc_configuration, self.get_name())
428 return u'%s - %s' % (self.rc_configuration, self.get_name())
368
429
369 def clone(self, **kwargs):
430 def clone(self, **kwargs):
370
431
371 self.pk = None
432 self.pk = None
372
433
373 for attr, value in kwargs.items():
434 for attr, value in kwargs.items():
374 setattr(self, attr, value)
435 setattr(self, attr, value)
375
436
376 self.save()
437 self.save()
377
438
378 return self
439 return self
379
440
380 def get_name(self):
441 def get_name(self):
381
442
382 chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
443 chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
383
444
384 if self.line_type.name in ('tx',):
445 if self.line_type.name in ('tx',):
385 return '%s%s' % (self.line_type.name.upper(), chars[self.position])
446 return '%s%s' % (self.line_type.name.upper(), chars[self.position])
386 elif self.line_type.name in ('codes', 'windows', 'tr'):
447 elif self.line_type.name in ('codes', 'windows', 'tr'):
387 if 'TX_ref' not in json.loads(self.params):
448 if 'TX_ref' not in json.loads(self.params):
388 return self.line_type.name.upper()
449 return self.line_type.name.upper()
389 pk = json.loads(self.params)['TX_ref']
450 pk = json.loads(self.params)['TX_ref']
390 if pk in (0, '0'):
451 if pk in (0, '0'):
391 refs = ','.join(chars[l.position] for l in self.rc_configuration.get_lines('tx'))
452 refs = ','.join(chars[l.position] for l in self.rc_configuration.get_lines(line_type__name='tx'))
392 return '%s (%s)' % (self.line_type.name.upper(), refs)
453 return '%s (%s)' % (self.line_type.name.upper(), refs)
393 else:
454 else:
394 ref = RCLine.objects.get(pk=pk)
455 ref = RCLine.objects.get(pk=pk)
395 return '%s (%s)' % (self.line_type.name.upper(), chars[ref.position])
456 return '%s (%s)' % (self.line_type.name.upper(), chars[ref.position])
396 elif self.line_type.name in ('flip', 'prog_pulses', 'sync', 'none'):
457 elif self.line_type.name in ('flip', 'prog_pulses', 'sync', 'none', 'mix'):
397 return '%s %s' % (self.line_type.name.upper(), self.channel)
458 return '%s %s' % (self.line_type.name.upper(), self.channel)
398 else:
459 else:
399 return self.line_type.name.upper()
460 return self.line_type.name.upper()
400
461
401 def get_lines(self, type=None):
462 def get_lines(self, **kwargs):
402
403 if type is not None:
404 return RCLine.objects.filter(rc_configuration=self.rc_configuration, line_type__name=type)
405 else:
406 return RCLine.objects.filter(rc_configuration=self.rc_configuration)
407
463
464 return RCLine.objects.filter(rc_configuration=self.rc_configuration, **kwargs)
408
465
409 def pulses_as_array(self):
466 def pulses_as_array(self):
410
467
411 return (np.fromstring(self.pulses, dtype=np.uint8)-48).astype(np.int8)
468 return (np.fromstring(self.pulses, dtype=np.uint8)-48).astype(np.int8)
412
469
413
414 def get_pulses(self):
470 def get_pulses(self):
415
471
416 X = self.pulses_as_array()
472 X = self.pulses_as_array()
417
473
418 d = X[1:]-X[:-1]
474 d = X[1:]-X[:-1]
419
475
420 up = np.where(d==1)[0]
476 up = np.where(d==1)[0]
421 if X[0]==1:
477 if X[0]==1:
422 up = np.concatenate((np.array([-1]), up))
478 up = np.concatenate((np.array([-1]), up))
423 up += 1
479 up += 1
424
480
425 dw = np.where(d==-1)[0]
481 dw = np.where(d==-1)[0]
426 if X[-1]==1:
482 if X[-1]==1:
427 dw = np.concatenate((dw, np.array([len(X)-1])))
483 dw = np.concatenate((dw, np.array([len(X)-1])))
428 dw += 1
484 dw += 1
429
485
430 return [(tup[0], tup[1]) for tup in zip(up, dw)]
486 return [(tup[0], tup[1]) for tup in zip(up, dw)]
431
487
432 def get_win_ref(self, params, tx_id, km2unit):
488 def get_win_ref(self, params, tx_id, km2unit):
433
489
434 ref = self.rc_configuration.sampling_reference
490 ref = self.rc_configuration.sampling_reference
435
491 codes = [line for line in self.get_lines(line_type__name='codes') if int(json.loads(line.params)['TX_ref'])==int(tx_id)]
436 codes = [line for line in self.get_lines(type='code') if int(json.loads(line.params)['TX_ref'])==int(tx_id)]
437
492
438 if codes:
493 if codes:
439 code_line = RCLineCode.objects.get(pk=json.loads(codes[0].params)['code'])
494 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit/len(json.loads(codes[0].params)['codes'][0])
440 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit/code_line.bits_per_code
441 else:
495 else:
442 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit
496 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit
443
497
444 if ref=='first_baud':
498 if ref=='first_baud':
445 return int(1 + (tx_width + 1)/2 + params['first_height']*km2unit - params['resolution']*km2unit)
499 return int(1 + (tx_width + 1)/2 + params['first_height']*km2unit - params['resolution']*km2unit)
446 elif ref=='sub_baud':
500 elif ref=='sub_baud':
447 return int(1 + params['first_height']*km2unit - params['resolution']*km2unit/2)
501 return int(1 + params['first_height']*km2unit - params['resolution']*km2unit/2)
448 else:
502 else:
449 return 0
503 return 0
450
504
451 def update_pulses(self, save=True, tr=False):
505 def update_pulses(self, save=True, tr=False):
452 '''
506 '''
453 Update pulses field
507 Update pulses field
454 '''
508 '''
455
509
456 km2unit = self.rc_configuration.km2unit
510 km2unit = self.rc_configuration.km2unit
457 us2unit = self.rc_configuration.us2unit
511 us2unit = self.rc_configuration.us2unit
458 ipp = self.rc_configuration.ipp
512 ipp = self.rc_configuration.ipp
459 ntx = self.rc_configuration.ntx
513 ntx = self.rc_configuration.ntx
460 ipp_u = int(ipp*km2unit)
514 ipp_u = int(ipp*km2unit)
461
515
462 x = np.arange(0, ipp_u*ntx)
516 x = np.arange(0, ipp_u*ntx)
463
517
464 if self.line_type.name=='tr':
518 if self.line_type.name=='tr':
465 params = json.loads(self.params)
519 params = json.loads(self.params)
466 if params['TX_ref'] in ('0', 0):
520 if params['TX_ref'] in ('0', 0):
467 txs = [tx.update_pulses(save=False, tr=True) for tx in self.get_lines('tx')]
521 txs = [tx.update_pulses(save=False, tr=True) for tx in self.get_lines(line_type__name='tx')]
468 else:
522 else:
469 txs = [tx.update_pulses(save=False, tr=True) for tx in RCLine.objects.filter(pk=params['TX_ref'])]
523 txs = [tx.update_pulses(save=False, tr=True) for tx in RCLine.objects.filter(pk=params['TX_ref'])]
470 if len(txs)==0 or 0 in [len(tx) for tx in txs]:
524 if len(txs)==0 or 0 in [len(tx) for tx in txs]:
471 return
525 return
472
526
473 y = np.any(txs, axis=0, out=np.ones(ipp_u*ntx))
527 y = np.any(txs, axis=0, out=np.ones(ipp_u*ntx))
474
528
475 ranges = params['range'].split(',')
529 ranges = params['range'].split(',')
476 if len(ranges)>0 and ranges[0]<>'0':
530 if len(ranges)>0 and ranges[0]<>'0':
477 mask = create_mask(ranges, ipp_u, ntx, self.rc_configuration.sync)
531 mask = create_mask(ranges, ipp_u, ntx, self.rc_configuration.sync)
478 y = y.astype(np.int8) & mask
532 y = y.astype(np.int8) & mask
479
533
480 elif self.line_type.name=='tx':
534 elif self.line_type.name=='tx':
481 params = json.loads(self.params)
535 params = json.loads(self.params)
482 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
536 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
483 y = pulses(x, ipp_u, float(params['pulse_width'])*km2unit,
537 y = pulses(x, ipp_u, float(params['pulse_width'])*km2unit,
484 delay=delays,
538 delay=delays,
485 before=int(self.rc_configuration.time_before*us2unit),
539 before=int(self.rc_configuration.time_before*us2unit),
486 after=int(self.rc_configuration.time_after*us2unit) if tr else 0,
540 after=int(self.rc_configuration.time_after*us2unit) if tr else 0,
487 sync=self.rc_configuration.sync)
541 sync=self.rc_configuration.sync)
488
542
489 ranges = params['range'].split(',')
543 ranges = params['range'].split(',')
490
544
491 if len(ranges)>0 and ranges[0]<>'0':
545 if len(ranges)>0 and ranges[0]<>'0':
492 mask = create_mask(ranges, ipp_u, ntx, self.rc_configuration.sync)
546 mask = create_mask(ranges, ipp_u, ntx, self.rc_configuration.sync)
493 y = y & mask
547 y = y & mask
494
548
495 elif self.line_type.name=='flip':
549 elif self.line_type.name=='flip':
496 width = float(json.loads(self.params)['number_of_flips'])*ipp*km2unit
550 width = float(json.loads(self.params)['number_of_flips'])*ipp*km2unit
497 y = pulses(x, 2*width, width)
551 y = pulses(x, 2*width, width)
498
552
499 elif self.line_type.name=='codes':
553 elif self.line_type.name=='codes':
500 params = json.loads(self.params)
554 params = json.loads(self.params)
501 #codes = ast.literal_eval(RCLineCode.objects.get(pk=json.loads(self.params)['code']).codes)
502 tx = RCLine.objects.get(pk=params['TX_ref'])
555 tx = RCLine.objects.get(pk=params['TX_ref'])
503 tx_params = json.loads(tx.params)
556 tx_params = json.loads(tx.params)
504
557 delays = [float(d)*km2unit for d in tx_params['delays'].split(',') if d]
505 y = pulses_from_code(ipp_u, ntx, params['codes'],
558 y = pulses_from_code(tx.pulses_as_array(),
506 int(float(tx_params['pulse_width'])*km2unit),
559 params['codes'],
507 before=int(self.rc_configuration.time_before*us2unit)+self.rc_configuration.sync)
560 int(float(tx_params['pulse_width'])*km2unit))
508
561
509 ranges = tx_params['range'].split(',')
562 ranges = tx_params['range'].split(',')
510 if len(ranges)>0 and ranges[0]<>'0':
563 if len(ranges)>0 and ranges[0]<>'0':
511 mask = create_mask(ranges, ipp_u, ntx, self.rc_configuration.sync)
564 mask = create_mask(ranges, ipp_u, ntx, self.rc_configuration.sync)
512 y = y.astype(np.int8) & mask
565 y = y.astype(np.int8) & mask
513
566
514 elif self.line_type.name=='sync':
567 elif self.line_type.name=='sync':
515 params = json.loads(self.params)
568 params = json.loads(self.params)
516 y = np.zeros(ipp_u*ntx)
569 y = np.zeros(ipp_u*ntx)
517 if params['invert'] in ('1', 1):
570 if params['invert'] in ('1', 1):
518 y[-1] = 1
571 y[-1] = 1
519 else:
572 else:
520 y[0] = 1
573 y[0] = 1
521
574
522 elif self.line_type.name=='prog_pulses':
575 elif self.line_type.name=='prog_pulses':
523 params = json.loads(self.params)
576 params = json.loads(self.params)
524 if int(params['periodic'])==0:
577 if int(params['periodic'])==0:
525 nntx = ntx
578 nntx = ntx
526 else:
579 else:
527 nntx = 1
580 nntx = 1
528
581
529 if 'params' in params and len(params['params'])>0:
582 if 'params' in params and len(params['params'])>0:
530 y = sum([pulses(x, ipp_u*nntx, (pp['end']-pp['begin']), shift=pp['begin']) for pp in params['params']])
583 y = sum([pulses(x, ipp_u*nntx, (pp['end']-pp['begin']), shift=pp['begin']) for pp in params['params']])
531 else:
584 else:
532 y = np.zeros(ipp_u*ntx)
585 y = np.zeros(ipp_u*ntx)
533
586
534 elif self.line_type.name=='windows':
587 elif self.line_type.name=='windows':
535 params = json.loads(self.params)
588 params = json.loads(self.params)
589
536 if 'params' in params and len(params['params'])>0:
590 if 'params' in params and len(params['params'])>0:
537 print 'REFS'
538 print [self.get_win_ref(pp, params['TX_ref'],km2unit) for pp in params['params']]
539 y = sum([pulses(x, ipp_u, pp['resolution']*pp['number_of_samples']*km2unit,
591 y = sum([pulses(x, ipp_u, pp['resolution']*pp['number_of_samples']*km2unit,
540 shift=0,
592 shift=0,
541 before=int(self.rc_configuration.time_before*us2unit)+self.get_win_ref(pp, params['TX_ref'],km2unit),
593 before=int(self.rc_configuration.time_before*us2unit)+self.get_win_ref(pp, params['TX_ref'],km2unit),
542 sync=self.rc_configuration.sync) for pp in params['params']])
594 sync=self.rc_configuration.sync) for pp in params['params']])
543 tr = self.get_lines('tr')[0]
595 tr = self.get_lines(line_type__name='tr')[0]
544 ranges = json.loads(tr.params)['range'].split(',')
596 ranges = json.loads(tr.params)['range'].split(',')
545 if len(ranges)>0 and ranges[0]<>'0':
597 if len(ranges)>0 and ranges[0]<>'0':
546 mask = create_mask(ranges, ipp_u, ntx, self.rc_configuration.sync)
598 mask = create_mask(ranges, ipp_u, ntx, self.rc_configuration.sync)
547 y = y & mask
599 y = y & mask
548 else:
600 else:
549 y = np.zeros(ipp_u*ntx)
601 y = np.zeros(ipp_u*ntx)
602
603 elif self.line_type.name=='mix':
604 values = self.rc_configuration.parameters.split('-')
605 confs = RCConfiguration.objects.filter(pk__in=[value.split('|')[0] for value in values])
606 modes = [value.split('|')[1] for value in values]
607 delays = [value.split('|')[2] for value in values]
608 masks = [value.split('|')[3] for value in values]
609
610 y = confs[0].get_lines(channel=self.channel)[0].pulses_as_array()
611
612 for i in range(1, len(values)):
613 mask = list('{:8b}'.format(int(masks[i])))
614 mask.reverse()
615
616 if mask[self.channel] in ('0', '', ' '):
617 continue
618 Y = confs[i].get_lines(channel=self.channel)[0].pulses_as_array()
619 delay = float(delays[i])*km2unit
620 if delay>0:
621 y_temp = np.empty_like(Y)
622 y_temp[:delay] = 0
623 y_temp[delay:] = Y[:-delay]
624
625 if modes[i]=='OR':
626 y2 = y | y_temp
627 elif modes[i]=='XOR':
628 y2 = y ^ y_temp
629 elif modes[i]=='AND':
630 y2 = y & y_temp
631 elif modes[i]=='NAND':
632 y2 = y & ~y_temp
633
634 y = y2
635
550 else:
636 else:
551 y = np.zeros(ipp_u*ntx)
637 y = np.zeros(ipp_u*ntx)
552
638
553 if save:
639 if save:
554 self.pulses = (y+48).astype(np.uint8).tostring()
640 self.pulses = (y+48).astype(np.uint8).tostring()
555 self.save()
641 self.save()
556 else:
642 else:
557 return y
643 return y
558
644
559 No newline at end of file
645
@@ -1,314 +1,315
1
1
2 import json
2 import json
3 import numpy as np
3 import numpy as np
4 import matplotlib.pyplot as plt
4 import matplotlib.pyplot as plt
5
5
6
6
7 class RCFile(object):
7 class RCFile(object):
8 '''
8 '''
9 Class to handle Radar controller configuration files
9 Class to handle Radar controller configuration files
10 '''
10 '''
11
11
12 def __init__(self, f=None):
12 def __init__(self, f=None):
13
13
14 self.data = {}
14 self.data = {}
15 if isinstance(f, str):
15 if isinstance(f, str):
16 self.f = open(f)
16 self.f = open(f)
17 self.name = f.split('/')[-1]
17 self.name = f.split('/')[-1]
18 elif hasattr(f, 'read'):
18 elif hasattr(f, 'read'):
19 self.f = f
19 self.f = f
20 self.name = f.name.split('/')[-1]
20 self.name = f.name.split('/')[-1]
21 else:
21 else:
22 self.f = f
22 self.f = f
23 self.name = None
23 self.name = None
24
24
25 if self.f:
25 if self.f:
26 if 'racp' in self.name:
26 if 'racp' in self.name:
27 self.parse_racp()
27 self.parse_racp()
28 elif 'dat' in self.name:
28 elif 'dat' in self.name:
29 self.parse_dat()
29 self.parse_dat()
30 elif 'json' in self.name:
30 elif 'json' in self.name:
31 self.data = json.load(self.f)
31 self.data = json.load(self.f)
32
32
33 self.f.close()
33 self.f.close()
34
34
35 def get_line_parameters(self, data, line):
35 def get_line_parameters(self, data, line):
36
36
37 line_params = {}
37 line_params = {}
38 for label in data:
38 for label in data:
39 if 'L%d' % line in label or '(Line %d)' % line in label or 'Line%d' % line in label:
39 if 'L%d' % line in label or '(Line %d)' % line in label or 'Line%d' % line in label:
40 line_params[label] = data[label]
40 line_params[label] = data[label]
41 return line_params
41 return line_params
42
42
43 def parse_racp(self):
43 def parse_racp(self):
44
44
45 data = {}
45 data = {}
46 raw_data = [s.strip() for s in self.f.readlines()]
46 raw_data = [s.strip() for s in self.f.readlines()]
47
47
48 for line in raw_data:
48 for line in raw_data:
49 if line and '=' in line:
49 if line and '=' in line:
50 label, value = line.strip().split('=')
50 label, value = line.strip().split('=')
51 data[label] = value
51 data[label] = value
52
52
53 self.data['experiment_type'] = data['EXPERIMENT TYPE']
53 self.data['experiment_type'] = data['EXPERIMENT TYPE']
54 self.data['header_version'] = data['HEADER VERSION']
54 self.data['header_version'] = data['HEADER VERSION']
55 self.data['name'] = data['EXPERIMENT NAME']
55 self.data['name'] = data['EXPERIMENT NAME']
56 self.data['ipp'] = float(data['IPP'])
56 self.data['ipp'] = float(data['IPP'])
57 self.data['ntx'] = int(data['NTX'])
57 self.data['ntx'] = int(data['NTX'])
58
58
59 if 'CLOCK DIVIDER' in data:
59 if 'CLOCK DIVIDER' in data:
60 self.data['clock_divider'] = int(data['CLOCK DIVIDER'])
60 self.data['clock_divider'] = int(data['CLOCK DIVIDER'])
61 else:
61 else:
62 self.data['clock_divider'] = 1
62 self.data['clock_divider'] = 1
63 self.data['clock_in'] = float(data['RELOJ'])*self.data['clock_divider']
63 self.data['clock_in'] = float(data['RELOJ'])*self.data['clock_divider']
64 self.data['clock'] = float(data['RELOJ'])
64 self.data['clock'] = float(data['RELOJ'])
65 self.data['time_before'] = int(data['TR_BEFORE'])
65 self.data['time_before'] = int(data['TR_BEFORE'])
66 self.data['time_after'] = int(data['TR_AFTER'])
66 self.data['time_after'] = int(data['TR_AFTER'])
67
67
68 if 'SYNCHRO DELAY' in data:
68 if 'SYNCHRO DELAY' in data:
69 self.data['sync'] = int(data['SYNCHRO DELAY'])
69 self.data['sync'] = int(data['SYNCHRO DELAY'])
70 else:
70 else:
71 self.data['sync'] = 0
71 self.data['sync'] = 0
72 self.data['lines'] = []
72 self.data['lines'] = []
73
73
74 if 'SAMPLING REFERENCE' in data:
74 if 'SAMPLING REFERENCE' in data:
75 if data['SAMPLING REFERENCE']=='MIDDLE OF FIRST BAUD':
75 if data['SAMPLING REFERENCE']=='MIDDLE OF FIRST BAUD':
76 self.data['sampling_reference'] = 'first_baud'
76 self.data['sampling_reference'] = 'first_baud'
77 elif data['SAMPLING REFERENCE']=='MIDDLE OF FIRST SUB-BAUD':
77 elif data['SAMPLING REFERENCE']=='MIDDLE OF FIRST SUB-BAUD':
78 self.data['sampling_reference'] = 'sub_baud'
78 self.data['sampling_reference'] = 'sub_baud'
79 else:
79 else:
80 self.data['sampling_reference'] = 'none'
80 self.data['sampling_reference'] = 'none'
81
81
82 #Add TR line
82 #Add TR line
83 if 'Pulse selection_TR' in data:
83 if 'Pulse selection_TR' in data:
84 if 'A,' in data['Pulse selection_TR']:
84 if 'A,' in data['Pulse selection_TR']:
85 rng = data['Pulse selection_TR'].replace('A,', '')
85 rng = data['Pulse selection_TR'].replace('A,', '')
86 ref = 'TXA'
86 ref = 'TXA'
87 elif 'A' in data['Pulse selection_TR']:
87 elif 'A' in data['Pulse selection_TR']:
88 rng = data['Pulse selection_TR'].replace('A', '')
88 rng = data['Pulse selection_TR'].replace('A', '')
89 ref = 'TXA'
89 ref = 'TXA'
90 elif 'B,' in data['Pulse selection_TR']:
90 elif 'B,' in data['Pulse selection_TR']:
91 rng = data['Pulse selection_TR'].replace('B,', '')
91 rng = data['Pulse selection_TR'].replace('B,', '')
92 ref = 'TXB'
92 ref = 'TXB'
93 elif 'B' in data['Pulse selection_TR']:
93 elif 'B' in data['Pulse selection_TR']:
94 rng = data['Pulse selection_TR'].replace('B', '')
94 rng = data['Pulse selection_TR'].replace('B', '')
95 ref = 'TXB'
95 ref = 'TXB'
96 else:
96 else:
97 rng = data['Pulse selection_TR']
97 rng = data['Pulse selection_TR']
98 ref = '0'
98 ref = '0'
99 line = {'type':'tr', 'range': rng if rng else '0', 'TX_ref':ref}
99 line = {'type':'tr', 'range': rng if rng else '0', 'TX_ref':ref}
100 else:
100 else:
101 line = {'type': 'tr', 'range': '0', 'TX_ref': '0'}
101 line = {'type': 'tr', 'range': '0', 'TX_ref': '0'}
102
102
103 self.data['lines'].append(line)
103 self.data['lines'].append(line)
104
104
105 #Add TX's lines
105 #Add TX's lines
106 if 'TXA' in data:
106 if 'TXA' in data:
107 line = {'type':'tx', 'pulse_width':data['TXA'], 'delays':'0'}
107 line = {'type':'tx', 'pulse_width':data['TXA'], 'delays':'0'}
108 if 'Pulse selection_TXA' in data:
108 if 'Pulse selection_TXA' in data:
109 line['range'] = data['Pulse selection_TXA']
109 line['range'] = data['Pulse selection_TXA']
110 else:
110 else:
111 line['range'] = '0'
111 line['range'] = '0'
112 self.data['lines'].append(line)
112 self.data['lines'].append(line)
113 else:
113 else:
114 self.data['lines'].append({'type':'tx', 'pulse_width':'0', 'delays':'0', 'range':'0'})
114 self.data['lines'].append({'type':'tx', 'pulse_width':'0', 'delays':'0', 'range':'0'})
115
115
116 if 'TXB' in data:
116 if 'TXB' in data:
117 line = {'type':'tx', 'pulse_width':data['TXB'], 'delays':'0'}
117 line = {'type':'tx', 'pulse_width':data['TXB'], 'delays':'0'}
118 if 'Pulse selection_TXB' in data:
118 if 'Pulse selection_TXB' in data:
119 line['range'] = data['Pulse selection_TXB']
119 line['range'] = data['Pulse selection_TXB']
120 else:
120 else:
121 line['range'] = '0'
121 line['range'] = '0'
122
122
123 if 'Number of Taus' in data:
123 if 'Number of Taus' in data:
124 delays = [data['TAU({0})'.format(i)] for i in range(int(data['Number of Taus']))]
124 delays = [data['TAU({0})'.format(i)] for i in range(int(data['Number of Taus']))]
125 line['delays'] = ','.join(delays)
125 line['delays'] = ','.join(delays)
126
126
127 self.data['lines'].append(line)
127 self.data['lines'].append(line)
128 else:
128 else:
129 self.data['lines'].append({'type':'tx', 'pulse_width':'0', 'delays':'0', 'range':'0'})
129 self.data['lines'].append({'type':'tx', 'pulse_width':'0', 'delays':'0', 'range':'0'})
130
130
131 #Add Other lines (4-6)
131 #Add Other lines (4-6)
132 for n in range(4, 7):
132 for n in range(4, 7):
133 params = self.get_line_parameters(data, n)
133 params = self.get_line_parameters(data, n)
134 labels = params.keys()
134 labels = params.keys()
135
135
136 if 'L%d_FLIP' % n in labels:
136 if 'L%d_FLIP' % n in labels:
137 line = {'type':'flip', 'number_of_flips':data['L%d_FLIP' % n]}
137 line = {'type':'flip', 'number_of_flips':data['L%d_FLIP' % n]}
138 elif 'Code Type' in data and n==4:
138 elif 'Code Type' in data and n==4:
139 line = {'type':'codes', 'code':data['Code Type'], 'TX_ref':data['L%d_REFERENCE' % n]}
139 line = {'type':'codes', 'code':data['Code Type'], 'TX_ref':data['L%d_REFERENCE' % n]}
140 if 'Number of Codes' in data:
140 if 'Number of Codes' in data:
141 line['codes'] = [data['COD({})'.format(x)] for x in range(int(data['Number of Codes']))]
141 line['codes'] = [data['COD({})'.format(x)] for x in range(int(data['Number of Codes']))]
142 elif 'Code Type (Line %d)' % n in labels:
142 elif 'Code Type (Line %d)' % n in labels:
143 line = {'type':'codes', 'code':data['Code Type (Line %d)' % n], 'TX_ref':data['L%d_REFERENCE' % n]}
143 line = {'type':'codes', 'code':data['Code Type (Line %d)' % n], 'TX_ref':data['L%d_REFERENCE' % n]}
144 if 'Number of Codes (Line %d)' % n in data:
144 if 'Number of Codes (Line %d)' % n in data:
145 line['codes'] = [data['L{}_COD({})'.format(n, x)] for x in range(int(data['Number of Codes (Line %d)' % n]))]
145 line['codes'] = [data['L{}_COD({})'.format(n, x)] for x in range(int(data['Number of Codes (Line %d)' % n]))]
146 elif 'Sampling Windows (Line %d)' % n in data:
146 elif 'Sampling Windows (Line %d)' % n in data:
147 line = {'type':'windows', 'TX_ref':data['L%d_REFERENCE' % n]}
147 line = {'type':'windows', 'TX_ref':data['L%d_REFERENCE' % n]}
148 windows = []
148 windows = []
149 for w in range(int(data['Sampling Windows (Line %d)' % n])):
149 for w in range(int(data['Sampling Windows (Line %d)' % n])):
150 windows.append({'first_height':float(data['L%d_H0(%d)' % (n, w)]),
150 windows.append({'first_height':float(data['L%d_H0(%d)' % (n, w)]),
151 'number_of_samples':int(data['L%d_NSA(%d)' % (n, w)]),
151 'number_of_samples':int(data['L%d_NSA(%d)' % (n, w)]),
152 'resolution':float(data['L%d_DH(%d)' % (n, w)])}
152 'resolution':float(data['L%d_DH(%d)' % (n, w)])}
153 )
153 )
154 line['params'] = windows
154 line['params'] = windows
155 elif 'Line%d' % n in labels and data['Line%d' % n]=='Synchro':
155 elif 'Line%d' % n in labels and data['Line%d' % n]=='Synchro':
156 line = {'type':'sync', 'invert':0}
156 line = {'type':'sync', 'invert':0}
157 elif 'L%d Number Of Portions' % n in labels:
157 elif 'L%d Number Of Portions' % n in labels:
158 line = {'type':'prog_pulses'}
158 line = {'type':'prog_pulses'}
159 if 'L%s Portions IPP Periodic' % n in data:
159 if 'L%s Portions IPP Periodic' % n in data:
160 line['periodic'] = 1 if data['L%s Portions IPP Periodic' % n]=='YES' else 0
160 line['periodic'] = 1 if data['L%s Portions IPP Periodic' % n]=='YES' else 0
161 portions = []
161 portions = []
162 x = raw_data.index('L%d Number Of Portions=%s' % (n, data['L%d Number Of Portions' % n]))
162 x = raw_data.index('L%d Number Of Portions=%s' % (n, data['L%d Number Of Portions' % n]))
163 for w in range(int(data['L%d Number Of Portions' % n])):
163 for w in range(int(data['L%d Number Of Portions' % n])):
164 begin = raw_data[x+1+2*w].split('=')[-1]
164 begin = raw_data[x+1+2*w].split('=')[-1]
165 end = raw_data[x+2+2*w].split('=')[-1]
165 end = raw_data[x+2+2*w].split('=')[-1]
166 portions.append({'begin':int(begin),
166 portions.append({'begin':int(begin),
167 'end':int(end)}
167 'end':int(end)}
168 )
168 )
169 line['params'] = portions
169 line['params'] = portions
170 elif 'FLIP1' in data and n==5:
170 elif 'FLIP1' in data and n==5:
171 line = {'type':'flip', 'number_of_flips':data['FLIP1']}
171 line = {'type':'flip', 'number_of_flips':data['FLIP1']}
172 elif 'FLIP2' in data and n==6:
172 elif 'FLIP2' in data and n==6:
173 line = {'type':'flip', 'number_of_flips':data['FLIP2']}
173 line = {'type':'flip', 'number_of_flips':data['FLIP2']}
174 else:
174 else:
175 line = {'type':'none'}
175 line = {'type':'none'}
176
176
177 self.data['lines'].append(line)
177 self.data['lines'].append(line)
178
178
179 #Add line 7 (windows)
179 #Add line 7 (windows)
180 if 'Sampling Windows' in data:
180 if 'Sampling Windows' in data:
181 line = {'type':'windows', 'TX_ref':data['L7_REFERENCE']}
181 line = {'type':'windows', 'TX_ref':data['L7_REFERENCE']}
182 windows = []
182 windows = []
183 x = raw_data.index('Sampling Windows=%s' % data['Sampling Windows'])
183 x = raw_data.index('Sampling Windows=%s' % data['Sampling Windows'])
184 for w in range(int(data['Sampling Windows'])):
184 for w in range(int(data['Sampling Windows'])):
185 h0 = raw_data[x+1+3*w].split('=')[-1]
185 h0 = raw_data[x+1+3*w].split('=')[-1]
186 nsa = raw_data[x+2+3*w].split('=')[-1]
186 nsa = raw_data[x+2+3*w].split('=')[-1]
187 dh = raw_data[x+3+3*w].split('=')[-1]
187 dh = raw_data[x+3+3*w].split('=')[-1]
188 windows.append({'first_height':float(h0),
188 windows.append({'first_height':float(h0),
189 'number_of_samples':int(nsa),
189 'number_of_samples':int(nsa),
190 'resolution':float(dh)}
190 'resolution':float(dh)}
191 )
191 )
192 line['params'] = windows
192 line['params'] = windows
193 self.data['lines'].append(line)
193 self.data['lines'].append(line)
194 else:
194 else:
195 self.data['lines'].append({'type':'none'})
195 self.data['lines'].append({'type':'none'})
196
196
197 #Add line 8 (synchro inverted)
197 #Add line 8 (synchro inverted)
198 self.data['lines'].append({'type':'sync', 'invert':1})
198 self.data['lines'].append({'type':'sync', 'invert':1})
199
199
200 return
200 return
201
201
202 def parse_dat(self):
202 def parse_dat(self):
203 pass
203 pass
204
204
205
205
206 def get_json(self, indent=None):
206 def get_json(self, indent=None):
207 return json.dumps(self.data, indent=indent)
207 return json.dumps(self.data, indent=indent)
208
208
209
209
210 def pulses_to_points(X):
210 def pulses_to_points(X):
211
211
212
212
213 d = X[1:]-X[:-1]
213 d = X[1:]-X[:-1]
214
214
215 up = np.where(d==1)[0]
215 up = np.where(d==1)[0]
216 if X[0]==1:
216 if X[0]==1:
217 up = np.concatenate((np.array([-1]), up))
217 up = np.concatenate((np.array([-1]), up))
218 up += 1
218 up += 1
219
219
220 dw = np.where(d==-1)[0]
220 dw = np.where(d==-1)[0]
221 if X[-1]==1:
221 if X[-1]==1:
222 dw = np.concatenate((dw, np.array([len(X)-1])))
222 dw = np.concatenate((dw, np.array([len(X)-1])))
223 dw += 1
223 dw += 1
224
224
225 return [(tup[0], tup[1]-tup[0]) for tup in zip(up, dw)]
225 return [(tup[0], tup[1]-tup[0]) for tup in zip(up, dw)]
226
226
227 def pulses_from_code(X, codes, width):
227
228
228 def pulses_from_code(ipp, ntx, codes, width, before=0):
229 d = X[1:]-X[:-1]
229
230
230 if ntx>len(codes):
231 up = np.where(d==1)[0]
231 ipp_codes = [c for __ in xrange(ntx) for c in codes][:ntx]
232 if X[0]==1:
232 else:
233 up = np.concatenate((np.array([-1]), up))
233 ipp_codes = codes[:ntx]
234 up += 1
234
235
235 f = width/len(codes[0])
236 f = width/len(codes[0])
237 codes = [(np.fromstring(''.join([s*f for s in code]), dtype=np.uint8)-48).astype(np.int8) for code in codes]
236
238
237 ipp_codes = [''.join([s*f for s in code]) for code in ipp_codes]
239 y = np.zeros(len(X))
238
239 if before>0:
240 sbefore = '{0:0{1}d}'.format(0, before)
241 else:
242 sbefore = ''
243
240
244 temp = ['{0}{1}{2:0{3}d}'.format(sbefore, ipp_codes[i], 0, int(ipp)-len(ipp_codes[i])-before) for i in range(ntx)]
241 j=0
242 n = len(codes)
243 for i in up:
244 y[i:i+width] = codes[j%n]
245 j += 1
245
246
246 return (np.fromstring(''.join(temp), dtype=np.uint8)-48).astype(np.int8)
247 return y
247
248
248
249
249 def create_mask(ranges, ipp, ntx, sync):
250 def create_mask(ranges, ipp, ntx, sync):
250
251
251 x = np.arange(ipp*ntx)
252 x = np.arange(ipp*ntx)
252 iranges = set()
253 iranges = set()
253
254
254 for index in ranges:
255 for index in ranges:
255 if '-' in index:
256 if '-' in index:
256 args = [int(a) for a in index.split('-')]
257 args = [int(a) for a in index.split('-')]
257 iranges = iranges.union([i for i in range(args[0], args[1]+1)])
258 iranges = iranges.union([i for i in range(args[0], args[1]+1)])
258 else:
259 else:
259 iranges.add(int(index))
260 iranges.add(int(index))
260
261
261 y = np.any([(x>=(idx-1)*ipp+sync) & (x<idx*ipp+sync) for idx in iranges], axis=0).astype(np.int8)
262 y = np.any([(x>=(idx-1)*ipp+sync) & (x<idx*ipp+sync) for idx in iranges], axis=0).astype(np.int8)
262
263
263 return y
264 return y
264
265
265
266
266 def pulses(X, period, width, delay=0, before=0, after=0, sync=0, shift=0):
267 def pulses(X, period, width, delay=0, before=0, after=0, sync=0, shift=0):
267
268
268 delay_array = delay
269 delay_array = delay
269
270
270 if isinstance(delay, (list, tuple)):
271 if isinstance(delay, (list, tuple)):
271 delay_array = np.ones(len(X))
272 delay_array = np.ones(len(X))
272 delays = [d for __ in xrange(len(X)/(period*len(delay))) for d in delay]
273 delays = [d for __ in xrange(len(X)/(period*len(delay))) for d in delay]
273 for i, delay in enumerate(delays):
274 for i, delay in enumerate(delays):
274 delay_array[np.arange(period*i, period*(i+1))] *= delay
275 delay_array[np.arange(period*i, period*(i+1))] *= delay
275
276
276 if after>0:
277 if after>0:
277 width += after+before
278 width += after+before
278 before = 0
279 before = 0
279
280
280 Y = ((X%period<width+delay_array+before+sync) & (X%period>=delay_array+before+sync)).astype(np.int8)
281 Y = ((X%period<width+delay_array+before+sync) & (X%period>=delay_array+before+sync)).astype(np.int8)
281
282
282 if shift>0:
283 if shift>0:
283 y = np.empty_like(Y)
284 y = np.empty_like(Y)
284 y[:shift] = 0
285 y[:shift] = 0
285 y[shift:] = Y[:-shift]
286 y[shift:] = Y[:-shift]
286 return y
287 return y
287 else:
288 else:
288 return Y
289 return Y
289
290
290
291
291 def plot_pulses(unit, maximun, lines):
292 def plot_pulses(unit, maximun, lines):
292
293
293 from bokeh.resources import CDN
294 from bokeh.resources import CDN
294 from bokeh.embed import components
295 from bokeh.embed import components
295 from bokeh.mpl import to_bokeh
296 from bokeh.mpl import to_bokeh
296 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, PreviewSaveTool
297 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, PreviewSaveTool
297
298
298 N = len(lines)
299 N = len(lines)
299 fig = plt.figure(figsize=(10, 2+N*0.5))
300 fig = plt.figure(figsize=(10, 2+N*0.5))
300 ax = fig.add_subplot(111)
301 ax = fig.add_subplot(111)
301 labels = []
302 labels = []
302
303
303 for i, line in enumerate(lines):
304 for i, line in enumerate(lines):
304 print line
305 labels.append(line.get_name())
305 labels.append(line.get_name())
306 l = ax.plot((0, maximun),(N-i-1, N-i-1))
306 ax.broken_barh(pulses_to_points(line.pulses_as_array()), (N-i-1, 0.5),
307 ax.broken_barh(pulses_to_points(line.pulses_as_array()), (N-i-1, 0.5),
307 edgecolor='none', facecolor='#2c3e50')
308 edgecolor=l[0].get_color(), facecolor='none')
308
309
309 labels.reverse()
310 labels.reverse()
310 ax.set_yticklabels(labels)
311 ax.set_yticklabels(labels)
311 plot = to_bokeh(fig, use_pandas=False)
312 plot = to_bokeh(fig, use_pandas=False)
312 plot.tools = [PanTool(dimensions=['width']), WheelZoomTool(dimensions=['width']), ResetTool(), PreviewSaveTool()]
313 plot.tools = [PanTool(dimensions=['width']), WheelZoomTool(dimensions=['width']), ResetTool(), PreviewSaveTool()]
313
314
314 return components(plot, CDN)
315 return components(plot, CDN)
@@ -1,391 +1,385
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 Configuration, Experiment, Device
8 from apps.main.models import Configuration, 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 from .utils import plot_pulses
13 from .utils import plot_pulses
14
14
15
15
16 def conf(request, conf_id):
16 def conf(request, conf_id):
17
17
18 conf = get_object_or_404(RCConfiguration, pk=conf_id)
18 conf = get_object_or_404(RCConfiguration, pk=conf_id)
19
19
20 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
20 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
21
21
22 for line in lines:
22 for line in lines:
23 params = json.loads(line.params)
23 params = json.loads(line.params)
24 line.form = RCLineViewForm(extra_fields=params, line=line)
24 line.form = RCLineViewForm(extra_fields=params, line=line)
25 if 'params' in params:
25 if 'params' in params:
26 line.subforms = [RCLineViewForm(extra_fields=fields, line=line, subform=True) for fields in params['params']]
26 line.subforms = [RCLineViewForm(extra_fields=fields, line=line, subform=True) for fields in params['params']]
27
27
28 kwargs = {}
28 kwargs = {}
29 kwargs['dev_conf'] = conf
29 kwargs['dev_conf'] = conf
30 kwargs['rc_lines'] = lines
30 kwargs['rc_lines'] = lines
31 kwargs['dev_conf_keys'] = ['name', 'ipp', 'ntx', 'clock_in', 'clock_divider', 'clock',
31 kwargs['dev_conf_keys'] = ['name', 'ipp', 'ntx', 'clock_in', 'clock_divider', 'clock',
32 'time_before', 'time_after', 'sync', 'sampling_reference', 'control_tx', 'control_sw']
32 'time_before', 'time_after', 'sync', 'sampling_reference', 'control_tx', 'control_sw']
33
33
34 kwargs['title'] = 'RC Configuration'
34 kwargs['title'] = 'RC Configuration'
35 kwargs['suptitle'] = 'Details'
35 kwargs['suptitle'] = 'Details'
36
36
37 kwargs['button'] = 'Edit Configuration'
37 kwargs['button'] = 'Edit Configuration'
38 ###### SIDEBAR ######
38 ###### SIDEBAR ######
39 kwargs.update(sidebar(conf=conf))
39 kwargs.update(sidebar(conf=conf))
40
40
41 return render(request, 'rc_conf.html', kwargs)
41 return render(request, 'rc_conf.html', kwargs)
42
42
43
43
44 def conf_edit(request, conf_id):
44 def conf_edit(request, conf_id):
45
45
46 conf = get_object_or_404(RCConfiguration, pk=conf_id)
46 conf = get_object_or_404(RCConfiguration, pk=conf_id)
47
47
48 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
48 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
49
49
50 for line in lines:
50 for line in lines:
51 params = json.loads(line.params)
51 params = json.loads(line.params)
52 line.form = RCLineEditForm(conf=conf, line=line, extra_fields=params)
52 line.form = RCLineEditForm(conf=conf, line=line, extra_fields=params)
53 line.subform = False
53 line.subform = False
54
54
55 if 'params' in params:
55 if 'params' in params:
56 line.subforms = [RCLineEditForm(extra_fields=fields, line=line, subform=i) for i, fields in enumerate(params['params'])]
56 line.subforms = [RCLineEditForm(extra_fields=fields, line=line, subform=i) for i, fields in enumerate(params['params'])]
57 line.subform = True
57 line.subform = True
58
58
59 if request.method=='GET':
59 if request.method=='GET':
60
60
61 form = RCConfigurationForm(instance=conf)
61 form = RCConfigurationForm(instance=conf)
62
62
63 elif request.method=='POST':
63 elif request.method=='POST':
64
64
65 line_data = {}
65 line_data = {}
66 conf_data = {}
66 conf_data = {}
67 extras = []
67 extras = []
68
68
69 #classified post fields
69 #classified post fields
70 for label,value in request.POST.items():
70 for label,value in request.POST.items():
71 if label=='csrfmiddlewaretoken':
71 if label=='csrfmiddlewaretoken':
72 continue
72 continue
73
73
74 if label.count('|')==0:
74 if label.count('|')==0:
75 conf_data[label] = value
75 conf_data[label] = value
76 continue
76 continue
77
77
78 elif label.split('|')[0]<>'-1':
78 elif label.split('|')[0]<>'-1':
79 extras.append(label)
79 extras.append(label)
80 continue
80 continue
81
81
82 x, pk, name = label.split('|')
82 x, pk, name = label.split('|')
83
83
84 if name=='codes':
84 if name=='codes':
85 value = [s for s in value.split('\r\n') if s]
85 value = [s for s in value.split('\r\n') if s]
86
86
87 if pk in line_data:
87 if pk in line_data:
88 line_data[pk][name] = value
88 line_data[pk][name] = value
89 else:
89 else:
90 line_data[pk] = {name:value}
90 line_data[pk] = {name:value}
91
91
92 #update conf
92 #update conf
93 form = RCConfigurationForm(conf_data, instance=conf)
93 form = RCConfigurationForm(conf_data, instance=conf)
94
94
95 if form.is_valid():
95 if form.is_valid():
96
96
97 form.save()
97 form.save()
98
98
99 #update lines fields
99 #update lines fields
100 extras.sort()
100 extras.sort()
101 for label in extras:
101 for label in extras:
102 x, pk, name = label.split('|')
102 x, pk, name = label.split('|')
103 if pk not in line_data:
103 if pk not in line_data:
104 line_data[pk] = {}
104 line_data[pk] = {}
105 if 'params' not in line_data[pk]:
105 if 'params' not in line_data[pk]:
106 line_data[pk]['params'] = []
106 line_data[pk]['params'] = []
107 if len(line_data[pk]['params'])<int(x)+1:
107 if len(line_data[pk]['params'])<int(x)+1:
108 line_data[pk]['params'].append({})
108 line_data[pk]['params'].append({})
109 line_data[pk]['params'][int(x)][name] = float(request.POST[label])
109 line_data[pk]['params'][int(x)][name] = float(request.POST[label])
110
110
111 for pk, params in line_data.items():
111 for pk, params in line_data.items():
112 line = RCLine.objects.get(pk=pk)
112 line = RCLine.objects.get(pk=pk)
113 if line.line_type.name in ('windows', 'prog_pulses'):
113 if line.line_type.name in ('windows', 'prog_pulses'):
114 if 'params' not in params:
114 if 'params' not in params:
115 params['params'] = []
115 params['params'] = []
116 line.params = json.dumps(params)
116 line.params = json.dumps(params)
117 line.save()
117 line.save()
118
118
119 #update pulses field
119 #update pulses field
120 for line in conf.get_lines():
120 conf.update_pulses()
121 if line.line_type.name=='tr':
122 continue
123 line.update_pulses()
124
125 for tr in conf.get_lines('tr'):
126 tr.update_pulses()
127
121
128 messages.success(request, 'RC Configuration successfully updated')
122 messages.success(request, 'RC Configuration successfully updated')
129
123
130 return redirect(conf.get_absolute_url())
124 return redirect(conf.get_absolute_url())
131
125
132 kwargs = {}
126 kwargs = {}
133 kwargs['dev_conf'] = conf
127 kwargs['dev_conf'] = conf
134 kwargs['form'] = form
128 kwargs['form'] = form
135 kwargs['rc_lines'] = lines
129 kwargs['rc_lines'] = lines
136 kwargs['edit'] = True
130 kwargs['edit'] = True
137
131
138 kwargs['title'] = 'RC Configuration'
132 kwargs['title'] = 'RC Configuration'
139 kwargs['suptitle'] = 'Edit'
133 kwargs['suptitle'] = 'Edit'
140 kwargs['button'] = 'Update'
134 kwargs['button'] = 'Update'
141 kwargs['previous'] = conf.get_absolute_url()
135 kwargs['previous'] = conf.get_absolute_url()
142
136
143 return render(request, 'rc_conf_edit.html', kwargs)
137 return render(request, 'rc_conf_edit.html', kwargs)
144
138
145
139
146 def add_line(request, conf_id, line_type_id=None, code_id=None):
140 def add_line(request, conf_id, line_type_id=None, code_id=None):
147
141
148 conf = get_object_or_404(RCConfiguration, pk=conf_id)
142 conf = get_object_or_404(RCConfiguration, pk=conf_id)
149
143
150 if request.method=='GET':
144 if request.method=='GET':
151 if line_type_id:
145 if line_type_id:
152 line_type = get_object_or_404(RCLineType, pk=line_type_id)
146 line_type = get_object_or_404(RCLineType, pk=line_type_id)
153
147
154 if code_id:
148 if code_id:
155 form = RCLineForm(initial={'rc_configuration':conf_id, 'line_type': line_type_id, 'code_id': code_id},
149 form = RCLineForm(initial={'rc_configuration':conf_id, 'line_type': line_type_id, 'code_id': code_id},
156 extra_fields=json.loads(line_type.params))
150 extra_fields=json.loads(line_type.params))
157 else:
151 else:
158 form = RCLineForm(initial={'rc_configuration':conf_id, 'line_type': line_type_id},
152 form = RCLineForm(initial={'rc_configuration':conf_id, 'line_type': line_type_id},
159 extra_fields=json.loads(line_type.params))
153 extra_fields=json.loads(line_type.params))
160 else:
154 else:
161 line_type = {'id':0}
155 line_type = {'id':0}
162 form = RCLineForm(initial={'rc_configuration':conf_id})
156 form = RCLineForm(initial={'rc_configuration':conf_id})
163
157
164 if request.method=='POST':
158 if request.method=='POST':
165
159
166 line_type = get_object_or_404(RCLineType, pk=line_type_id)
160 line_type = get_object_or_404(RCLineType, pk=line_type_id)
167 form = RCLineForm(request.POST,
161 form = RCLineForm(request.POST,
168 extra_fields=json.loads(line_type.params))
162 extra_fields=json.loads(line_type.params))
169
163
170 if form.is_valid():
164 if form.is_valid():
171 form.save()
165 form.save()
172 form.instance.update_pulses()
166 form.instance.update_pulses()
173 return redirect('url_edit_rc_conf', conf.id)
167 return redirect('url_edit_rc_conf', conf.id)
174
168
175 kwargs = {}
169 kwargs = {}
176 kwargs['form'] = form
170 kwargs['form'] = form
177 kwargs['title'] = 'RC Configuration'
171 kwargs['title'] = 'RC Configuration'
178 kwargs['suptitle'] = 'Add Line'
172 kwargs['suptitle'] = 'Add Line'
179 kwargs['button'] = 'Add'
173 kwargs['button'] = 'Add'
180 kwargs['previous'] = conf.get_absolute_url_edit()
174 kwargs['previous'] = conf.get_absolute_url_edit()
181 kwargs['dev_conf'] = conf
175 kwargs['dev_conf'] = conf
182 kwargs['line_type'] = line_type
176 kwargs['line_type'] = line_type
183
177
184 return render(request, 'rc_add_line.html', kwargs)
178 return render(request, 'rc_add_line.html', kwargs)
185
179
186 def edit_codes(request, conf_id, line_id, code_id=None):
180 def edit_codes(request, conf_id, line_id, code_id=None):
187
181
188 conf = get_object_or_404(RCConfiguration, pk=conf_id)
182 conf = get_object_or_404(RCConfiguration, pk=conf_id)
189 line = get_object_or_404(RCLine, pk=line_id)
183 line = get_object_or_404(RCLine, pk=line_id)
190 params = json.loads(line.params)
184 params = json.loads(line.params)
191
185
192 if request.method=='GET':
186 if request.method=='GET':
193 if code_id:
187 if code_id:
194 code = get_object_or_404(RCLineCode, pk=code_id)
188 code = get_object_or_404(RCLineCode, pk=code_id)
195 form = RCLineCodesForm(instance=code)
189 form = RCLineCodesForm(instance=code)
196 else:
190 else:
197 initial = {'code': params['code'],
191 initial = {'code': params['code'],
198 'codes': params['codes'] if 'codes' in params else [],
192 'codes': params['codes'] if 'codes' in params else [],
199 'number_of_codes': len(params['codes']) if 'codes' in params else 0,
193 'number_of_codes': len(params['codes']) if 'codes' in params else 0,
200 'bits_per_code': len(params['codes'][0]) if 'codes' in params else 0,
194 'bits_per_code': len(params['codes'][0]) if 'codes' in params else 0,
201 }
195 }
202 form = RCLineCodesForm(initial=initial)
196 form = RCLineCodesForm(initial=initial)
203
197
204 if request.method=='POST':
198 if request.method=='POST':
205 form = RCLineCodesForm(request.POST)
199 form = RCLineCodesForm(request.POST)
206 if form.is_valid():
200 if form.is_valid():
207 params['code'] = request.POST['code']
201 params['code'] = request.POST['code']
208 params['codes'] = [s for s in request.POST['codes'].split('\r\n') if s]
202 params['codes'] = [s for s in request.POST['codes'].split('\r\n') if s]
209 line.params = json.dumps(params)
203 line.params = json.dumps(params)
210 line.save()
204 line.save()
211 messages.success(request, 'Line: "%s" has been updated.' % line)
205 messages.success(request, 'Line: "%s" has been updated.' % line)
212 return redirect('url_edit_rc_conf', conf.id)
206 return redirect('url_edit_rc_conf', conf.id)
213
207
214 kwargs = {}
208 kwargs = {}
215 kwargs['form'] = form
209 kwargs['form'] = form
216 kwargs['title'] = line
210 kwargs['title'] = line
217 kwargs['suptitle'] = 'Edit'
211 kwargs['suptitle'] = 'Edit'
218 kwargs['button'] = 'Update'
212 kwargs['button'] = 'Update'
219 kwargs['dev_conf'] = conf
213 kwargs['dev_conf'] = conf
220 kwargs['previous'] = conf.get_absolute_url_edit()
214 kwargs['previous'] = conf.get_absolute_url_edit()
221 kwargs['line'] = line
215 kwargs['line'] = line
222
216
223 return render(request, 'rc_edit_codes.html', kwargs)
217 return render(request, 'rc_edit_codes.html', kwargs)
224
218
225 def add_subline(request, conf_id, line_id):
219 def add_subline(request, conf_id, line_id):
226
220
227 conf = get_object_or_404(RCConfiguration, pk=conf_id)
221 conf = get_object_or_404(RCConfiguration, pk=conf_id)
228 line = get_object_or_404(RCLine, pk=line_id)
222 line = get_object_or_404(RCLine, pk=line_id)
229
223
230 if request.method == 'POST':
224 if request.method == 'POST':
231 if line:
225 if line:
232 params = json.loads(line.params)
226 params = json.loads(line.params)
233 subparams = json.loads(line.line_type.params)
227 subparams = json.loads(line.line_type.params)
234 if 'params' in subparams:
228 if 'params' in subparams:
235 dum = {}
229 dum = {}
236 for key, value in subparams['params'].items():
230 for key, value in subparams['params'].items():
237 dum[key] = value['value']
231 dum[key] = value['value']
238 params['params'].append(dum)
232 params['params'].append(dum)
239 line.params = json.dumps(params)
233 line.params = json.dumps(params)
240 line.save()
234 line.save()
241 return redirect('url_edit_rc_conf', conf.id)
235 return redirect('url_edit_rc_conf', conf.id)
242
236
243 kwargs = {}
237 kwargs = {}
244
238
245 kwargs['title'] = 'Add new'
239 kwargs['title'] = 'Add new'
246 kwargs['suptitle'] = '%s to %s' % (line.line_type.name, line)
240 kwargs['suptitle'] = '%s to %s' % (line.line_type.name, line)
247
241
248 return render(request, 'confirm.html', kwargs)
242 return render(request, 'confirm.html', kwargs)
249
243
250 def remove_line(request, conf_id, line_id):
244 def remove_line(request, conf_id, line_id):
251
245
252 conf = get_object_or_404(RCConfiguration, pk=conf_id)
246 conf = get_object_or_404(RCConfiguration, pk=conf_id)
253 line = get_object_or_404(RCLine, pk=line_id)
247 line = get_object_or_404(RCLine, pk=line_id)
254
248
255 if request.method == 'POST':
249 if request.method == 'POST':
256 if line:
250 if line:
257 try:
251 try:
258 channel = line.channel
252 channel = line.channel
259 line.delete()
253 line.delete()
260 for ch in range(channel+1, RCLine.objects.filter(rc_configuration=conf).count()+1):
254 for ch in range(channel+1, RCLine.objects.filter(rc_configuration=conf).count()+1):
261 l = RCLine.objects.get(rc_configuration=conf, channel=ch)
255 l = RCLine.objects.get(rc_configuration=conf, channel=ch)
262 l.channel = l.channel-1
256 l.channel = l.channel-1
263 l.save()
257 l.save()
264 messages.success(request, 'Line: "%s" has been deleted.' % line)
258 messages.success(request, 'Line: "%s" has been deleted.' % line)
265 except:
259 except:
266 messages.error(request, 'Unable to delete line: "%s".' % line)
260 messages.error(request, 'Unable to delete line: "%s".' % line)
267
261
268 return redirect('url_edit_rc_conf', conf.id)
262 return redirect('url_edit_rc_conf', conf.id)
269
263
270 kwargs = {}
264 kwargs = {}
271
265
272 kwargs['object'] = line
266 kwargs['object'] = line
273 kwargs['delete_view'] = True
267 kwargs['delete_view'] = True
274 kwargs['title'] = 'Confirm delete'
268 kwargs['title'] = 'Confirm delete'
275 kwargs['previous'] = conf.get_absolute_url_edit()
269 kwargs['previous'] = conf.get_absolute_url_edit()
276 return render(request, 'confirm.html', kwargs)
270 return render(request, 'confirm.html', kwargs)
277
271
278
272
279 def remove_subline(request, conf_id, line_id, subline_id):
273 def remove_subline(request, conf_id, line_id, subline_id):
280
274
281 conf = get_object_or_404(RCConfiguration, pk=conf_id)
275 conf = get_object_or_404(RCConfiguration, pk=conf_id)
282 line = get_object_or_404(RCLine, pk=line_id)
276 line = get_object_or_404(RCLine, pk=line_id)
283
277
284 if request.method == 'POST':
278 if request.method == 'POST':
285 if line:
279 if line:
286 params = json.loads(line.params)
280 params = json.loads(line.params)
287 params['params'].remove(params['params'][int(subline_id)-1])
281 params['params'].remove(params['params'][int(subline_id)-1])
288 line.params = json.dumps(params)
282 line.params = json.dumps(params)
289 line.save()
283 line.save()
290
284
291 return redirect('url_edit_rc_conf', conf.id)
285 return redirect('url_edit_rc_conf', conf.id)
292
286
293 kwargs = {}
287 kwargs = {}
294
288
295 kwargs['object'] = line
289 kwargs['object'] = line
296 kwargs['object_name'] = line.line_type.name
290 kwargs['object_name'] = line.line_type.name
297 kwargs['delete_view'] = True
291 kwargs['delete_view'] = True
298 kwargs['title'] = 'Confirm delete'
292 kwargs['title'] = 'Confirm delete'
299
293
300 return render(request, 'confirm.html', kwargs)
294 return render(request, 'confirm.html', kwargs)
301
295
302
296
303 def update_lines_position(request, conf_id):
297 def update_lines_position(request, conf_id):
304
298
305 conf = get_object_or_404(RCConfiguration, pk=conf_id)
299 conf = get_object_or_404(RCConfiguration, pk=conf_id)
306
300
307 if request.method=='POST':
301 if request.method=='POST':
308 ch = 0
302 ch = 0
309 for item in request.POST['items'].split('&'):
303 for item in request.POST['items'].split('&'):
310 line = RCLine.objects.get(pk=item.split('=')[-1])
304 line = RCLine.objects.get(pk=item.split('=')[-1])
311 line.channel = ch
305 line.channel = ch
312 line.save()
306 line.save()
313 ch += 1
307 ch += 1
314
308
315 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
309 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
316
310
317 for line in lines:
311 for line in lines:
318 params = json.loads(line.params)
312 params = json.loads(line.params)
319 line.form = RCLineEditForm(conf=conf, line=line, extra_fields=params)
313 line.form = RCLineEditForm(conf=conf, line=line, extra_fields=params)
320
314
321 if 'params' in params:
315 if 'params' in params:
322 line.subform = True
316 line.subform = True
323 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'])]
324
318
325 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})
326 data = {'html': html.content}
320 data = {'html': html.content}
327
321
328 return HttpResponse(json.dumps(data), content_type="application/json")
322 return HttpResponse(json.dumps(data), content_type="application/json")
329 return redirect('url_edit_rc_conf', conf.id)
323 return redirect('url_edit_rc_conf', conf.id)
330
324
331
325
332 def import_file(request, conf_id):
326 def import_file(request, conf_id):
333
327
334 conf = get_object_or_404(RCConfiguration, pk=conf_id)
328 conf = get_object_or_404(RCConfiguration, pk=conf_id)
335 if request.method=='POST':
329 if request.method=='POST':
336 form = RCImportForm(request.POST, request.FILES)
330 form = RCImportForm(request.POST, request.FILES)
337 if form.is_valid():
331 if form.is_valid():
338 #try:
332 #try:
339 if True:
333 if True:
340
334
341 conf.update_from_file(request.FILES['file_name'])
335 conf.update_from_file(request.FILES['file_name'])
342 conf.save()
336 conf.save()
343
337
344 for line in conf.get_lines():
338 for line in conf.get_lines():
345 if line.line_type.name=='tr':
339 if line.line_type.name=='tr':
346 continue
340 continue
347 line.update_pulses()
341 line.update_pulses()
348
342
349 for tr in conf.get_lines('tr'):
343 for tr in conf.get_lines('tr'):
350 tr.update_pulses()
344 tr.update_pulses()
351
345
352 messages.success(request, 'Configuration "%s" loaded succesfully' % request.FILES['file_name'])
346 messages.success(request, 'Configuration "%s" loaded succesfully' % request.FILES['file_name'])
353 return redirect(conf.get_absolute_url())
347 return redirect(conf.get_absolute_url())
354
348
355 #except Exception as e:
349 #except Exception as e:
356 # messages.error(request, 'Error parsing file: "%s" - %s' % (request.FILES['file_name'], e))
350 # messages.error(request, 'Error parsing file: "%s" - %s' % (request.FILES['file_name'], e))
357
351
358 else:
352 else:
359 messages.warning(request, 'Your current configuration will be replaced')
353 messages.warning(request, 'Your current configuration will be replaced')
360 form = RCImportForm()
354 form = RCImportForm()
361
355
362 kwargs = {}
356 kwargs = {}
363 kwargs['form'] = form
357 kwargs['form'] = form
364 kwargs['title'] = 'RC Configuration'
358 kwargs['title'] = 'RC Configuration'
365 kwargs['suptitle'] = 'Import file'
359 kwargs['suptitle'] = 'Import file'
366 kwargs['button'] = 'Upload'
360 kwargs['button'] = 'Upload'
367 kwargs['previous'] = conf.get_absolute_url()
361 kwargs['previous'] = conf.get_absolute_url()
368
362
369 return render(request, 'rc_import.html', kwargs)
363 return render(request, 'rc_import.html', kwargs)
370
364
371
365
372 def view_pulses(request, conf_id):
366 def view_pulses(request, conf_id):
373
367
374 conf = get_object_or_404(RCConfiguration, pk=conf_id)
368 conf = get_object_or_404(RCConfiguration, pk=conf_id)
375 lines = RCLine.objects.filter(rc_configuration=conf)
369 lines = RCLine.objects.filter(rc_configuration=conf)
376
370
377 unit = (conf.clock/conf.clock_divider)*3./20
371 unit = (conf.clock/conf.clock_divider)*3./20
378
372
379 N = int(conf.ipp*(conf.clock/conf.clock_divider)*20./3)*conf.ntx
373 N = conf.ipp*conf.km2unit*conf.ntx
380
374
381 script, div = plot_pulses(unit, N, lines)
375 script, div = plot_pulses(unit, N, lines)
382
376
383 kwargs = {}
377 kwargs = {}
384
378
385 kwargs['title'] = 'RC Pulses'
379 kwargs['title'] = 'RC Pulses'
386 kwargs['suptitle'] = conf.name
380 kwargs['suptitle'] = conf.name
387 kwargs['div'] = mark_safe(div)
381 kwargs['div'] = mark_safe(div)
388 kwargs['script'] = mark_safe(script)
382 kwargs['script'] = mark_safe(script)
389
383
390 return render(request, 'rc_pulses.html', kwargs)
384 return render(request, 'rc_pulses.html', kwargs)
391
385
@@ -1,245 +1,275
1
1
2 import ast
2 import ast
3 import json
3 import json
4 from itertools import chain
4
5
5 from django import forms
6 from django import forms
6 from django.utils.safestring import mark_safe
7 from django.utils.safestring import mark_safe
8 from django.utils.encoding import force_unicode
9 from django.utils.html import conditional_escape
7
10
8
11
9 class KmUnitWidget(forms.widgets.TextInput):
12 class KmUnitWidget(forms.widgets.TextInput):
10
13
11 def render(self, label, value, attrs=None):
14 def render(self, label, value, attrs=None):
12
15
13 if isinstance(value, (int, float)):
16 if isinstance(value, (int, float)):
14 unit = int(value*attrs['km2unit'])
17 unit = int(value*attrs['km2unit'])
15 elif isinstance(value, basestring):
18 elif isinstance(value, basestring):
16 units = []
19 units = []
17 values = [s for s in value.split(',') if s]
20 values = [s for s in value.split(',') if s]
18 for val in values:
21 for val in values:
19 units.append('{0:.0f}'.format(float(val)*attrs['km2unit']))
22 units.append('{0:.0f}'.format(float(val)*attrs['km2unit']))
20
23
21 unit = ','.join(units)
24 unit = ','.join(units)
22
25
23 disabled = 'disabled' if attrs.get('disabled', False) else ''
26 disabled = 'disabled' if attrs.get('disabled', False) else ''
24 name = attrs.get('name', label)
27 name = attrs.get('name', label)
25
28
26 if 'line' in attrs:
29 if 'line' in attrs:
27 label += '_{0}'.format(attrs['line'].pk)
30 label += '_{0}'.format(attrs['line'].pk)
28
31
29 html = '<div class="col-md-12 col-no-padding"><div class="col-md-5 col-no-padding"><input type="text" {0} class="form-control" id="id_{1}" name="{2}" value="{3}"></div><div class="col-md-1 col-no-padding">Km</div><div class="col-md-5 col-no-padding"><input type="text" {4} class="form-control" id="id_{5}_unit" value="{6}"></div><div class="col-md-1 col-no-padding">Units</div></div>'.format(disabled, label, name, value, disabled, label, unit)
32 html = '<div class="col-md-12 col-no-padding"><div class="col-md-5 col-no-padding"><input type="text" {0} class="form-control" id="id_{1}" name="{2}" value="{3}"></div><div class="col-md-1 col-no-padding">Km</div><div class="col-md-5 col-no-padding"><input type="text" {4} class="form-control" id="id_{5}_unit" value="{6}"></div><div class="col-md-1 col-no-padding">Units</div></div><br>'.format(disabled, label, name, value, disabled, label, unit)
30
33
31 script = '''<script type="text/javascript">
34 script = '''<script type="text/javascript">
32 $(document).ready(function () {{
35 $(document).ready(function () {{
33
36
34 km_fields.push("id_{label}");
37 km_fields.push("id_{label}");
35 unit_fields.push("id_{label}_unit");
38 unit_fields.push("id_{label}_unit");
36
39
37 $("#id_{label}").change(function() {{
40 $("#id_{label}").change(function() {{
38 $("#id_{label}_unit").val(Math.round(str2unit($(this).val())));
41 $("#id_{label}_unit").val(Math.round(str2unit($(this).val())));
39 $("#id_{label}").val(str2km($("#id_{label}_unit").val()));
42 $("#id_{label}").val(str2km($("#id_{label}_unit").val()));
40 }});
43 }});
41 $("#id_{label}_unit").change(function() {{
44 $("#id_{label}_unit").change(function() {{
42 $(this).val(Math.round(parseFloat($(this).val())));
45 $(this).val(Math.round(parseFloat($(this).val())));
43 $("#id_{label}").val(str2km($(this).val()));
46 $("#id_{label}").val(str2km($(this).val()));
44 }});
47 }});
45 }});
48 }});
46 </script>'''.format(label=label)
49 </script>'''.format(label=label)
47
50
48 if disabled:
51 if disabled:
49 return mark_safe(html)
52 return mark_safe(html)
50 else:
53 else:
51 return mark_safe(html+script)
54 return mark_safe(html+script)
52
55
53
56
54 class UnitKmWidget(forms.widgets.TextInput):
57 class UnitKmWidget(forms.widgets.TextInput):
55
58
56 def render(self, label, value, attrs=None):
59 def render(self, label, value, attrs=None):
57
60
58 if isinstance(value, (int, float)):
61 if isinstance(value, (int, float)):
59 km = value/attrs['km2unit']
62 km = value/attrs['km2unit']
60 elif isinstance(value, basestring):
63 elif isinstance(value, basestring):
61 kms = []
64 kms = []
62 values = [s for s in value.split(',') if s]
65 values = [s for s in value.split(',') if s]
63 for val in values:
66 for val in values:
64 kms.append('{0:.0f}'.format(float(val)/attrs['km2unit']))
67 kms.append('{0:.0f}'.format(float(val)/attrs['km2unit']))
65
68
66 km = ','.join(kms)
69 km = ','.join(kms)
67
70
68 disabled = 'disabled' if attrs.get('disabled', False) else ''
71 disabled = 'disabled' if attrs.get('disabled', False) else ''
69 name = attrs.get('name', label)
72 name = attrs.get('name', label)
70
73
71 if 'line' in attrs:
74 if 'line' in attrs:
72 label += '_{0}'.format(attrs['line'].pk)
75 label += '_{0}'.format(attrs['line'].pk)
73
76
74 html = '''<div class="col-md-12 col-no-padding">
77 html = '''<div class="col-md-12 col-no-padding">
75 <div class="col-md-5 col-no-padding"><input type="number" {0} class="form-control" id="id_{1}_unit" name="{2}" value="{3}"></div>
78 <div class="col-md-5 col-no-padding"><input type="number" {0} class="form-control" id="id_{1}_unit" name="{2}" value="{3}"></div>
76 <div class="col-md-1 col-no-padding">Units</div>
79 <div class="col-md-1 col-no-padding">Units</div>
77 <div class="col-md-5 col-no-padding"><input type="number" {4} class="form-control" id="id_{5}" value="{6}"></div>
80 <div class="col-md-5 col-no-padding"><input type="number" {4} class="form-control" id="id_{5}" value="{6}"></div>
78 <div class="col-md-1 col-no-padding">Km</div></div>'''.format(disabled, label, name, value, disabled, label, km)
81 <div class="col-md-1 col-no-padding">Km</div></div>'''.format(disabled, label, name, value, disabled, label, km)
79
82
80 script = '''<script type="text/javascript">
83 script = '''<script type="text/javascript">
81 $(document).ready(function () {{
84 $(document).ready(function () {{
82
85
83 km_fields.push("id_{label}");
86 km_fields.push("id_{label}");
84 unit_fields.push("id_{label}_unit");
87 unit_fields.push("id_{label}_unit");
85
88
86 $("#id_{label}").change(function() {{
89 $("#id_{label}").change(function() {{
87 $("#id_{label}_unit").val(str2unit($(this).val()));
90 $("#id_{label}_unit").val(str2unit($(this).val()));
88 }});
91 }});
89 $("#id_{label}_unit").change(function() {{
92 $("#id_{label}_unit").change(function() {{
90 $("#id_{label}").val(str2km($(this).val()));
93 $("#id_{label}").val(str2km($(this).val()));
91 }});
94 }});
92 }});
95 }});
93 </script>'''.format(label=label)
96 </script>'''.format(label=label)
94
97
95 if disabled:
98 if disabled:
96 return mark_safe(html)
99 return mark_safe(html)
97 else:
100 else:
98 return mark_safe(html+script)
101 return mark_safe(html+script)
99
102
100
103
101 class KmUnitHzWidget(forms.widgets.TextInput):
104 class KmUnitHzWidget(forms.widgets.TextInput):
102
105
103 def render(self, label, value, attrs=None):
106 def render(self, label, value, attrs=None):
104
107
105 unit = float(value)*attrs['km2unit']
108 unit = float(value)*attrs['km2unit']
106 if unit%10==0:
109 if unit%10==0:
107 unit = int(unit)
110 unit = int(unit)
108 hz = 150000*float(value)**-1
111 hz = 150000*float(value)**-1
109
112
110 disabled = 'disabled' if attrs.get('disabled', False) else ''
113 disabled = 'disabled' if attrs.get('disabled', False) else ''
111 name = attrs.get('name', label)
114 name = attrs.get('name', label)
112
115
113 if 'line' in attrs:
116 if 'line' in attrs:
114 label += '_{0}'.format(attrs['line'].pk)
117 label += '_{0}'.format(attrs['line'].pk)
115
118
116 html = '''<div class="col-md-12 col-no-padding">
119 html = '''<div class="col-md-12 col-no-padding">
117 <div class="col-md-3 col-no-padding"><input type="number" {0} class="form-control" id="id_{1}" name="{2}" value="{3}"></div>
120 <div class="col-md-3 col-no-padding"><input type="number" {0} class="form-control" id="id_{1}" name="{2}" value="{3}"></div>
118 <div class="col-md-1 col-no-padding">Km</div>
121 <div class="col-md-1 col-no-padding">Km</div>
119 <div class="col-md-3 col-no-padding"><input type="number" {4} class="form-control" id="id_{1}_unit" value="{5}"></div>
122 <div class="col-md-3 col-no-padding"><input type="number" {4} class="form-control" id="id_{1}_unit" value="{5}"></div>
120 <div class="col-md-1 col-no-padding">Units</div>
123 <div class="col-md-1 col-no-padding">Units</div>
121 <div class="col-md-3 col-no-padding"><input type="number" {4} class="form-control" id="id_{1}_hz" value="{6}"></div>
124 <div class="col-md-3 col-no-padding"><input type="number" {4} class="form-control" id="id_{1}_hz" value="{6}"></div>
122 <div class="col-md-1 col-no-padding">Hz</div>
125 <div class="col-md-1 col-no-padding">Hz</div>
123 </div>'''.format(disabled, label, name, value, disabled, unit, hz)
126 </div>'''.format(disabled, label, name, value, disabled, unit, hz)
124
127
125 script = '''<script type="text/javascript">
128 script = '''<script type="text/javascript">
126 $(document).ready(function () {{
129 $(document).ready(function () {{
127 km_fields.push("id_{label}");
130 km_fields.push("id_{label}");
128 unit_fields.push("id_{label}_unit");
131 unit_fields.push("id_{label}_unit");
129 $("#id_{label}").change(function() {{
132 $("#id_{label}").change(function() {{
130 $("#id_{label}_unit").val(str2unit($(this).val()));
133 $("#id_{label}_unit").val(str2unit($(this).val()));
131 $("#id_{label}_hz").val(str2hz($(this).val()));
134 $("#id_{label}_hz").val(str2hz($(this).val()));
132 updateDc();
135 updateDc();
133 }});
136 }});
134 $("#id_{label}_unit").change(function() {{
137 $("#id_{label}_unit").change(function() {{
135 $(this).val(Math.round(parseFloat($(this).val())/10)*10);
138 $(this).val(Math.round(parseFloat($(this).val())/10)*10);
136 $("#id_{label}").val(str2km($(this).val()));
139 $("#id_{label}").val(str2km($(this).val()));
137 $("#id_{label}_hz").val(str2hz($("#id_{label}").val()));
140 $("#id_{label}_hz").val(str2hz($("#id_{label}").val()));
138 updateDc();
141 updateDc();
139 }});
142 }});
140 $("#id_{label}_hz").change(function() {{
143 $("#id_{label}_hz").change(function() {{
141 $("#id_{label}").val(str2hz($(this).val()));
144 $("#id_{label}").val(str2hz($(this).val()));
142 $("#id_{label}_unit").val(str2unit($("#id_{label}").val()));
145 $("#id_{label}_unit").val(str2unit($("#id_{label}").val()));
143 updateDc();
146 updateDc();
144 }});
147 }});
145 }});
148 }});
146 </script>'''.format(label=label)
149 </script>'''.format(label=label)
147
150
148 if disabled:
151 if disabled:
149 return mark_safe(html)
152 return mark_safe(html)
150 else:
153 else:
151 return mark_safe(html+script)
154 return mark_safe(html+script)
152
155
153
156
154 class KmUnitDcWidget(forms.widgets.TextInput):
157 class KmUnitDcWidget(forms.widgets.TextInput):
155
158
156 def render(self, label, value, attrs=None):
159 def render(self, label, value, attrs=None):
157
160
158 unit = int(float(value)*attrs['km2unit'])
161 unit = int(float(value)*attrs['km2unit'])
159
162
160 disabled = 'disabled' if attrs.get('disabled', False) else ''
163 disabled = 'disabled' if attrs.get('disabled', False) else ''
161 name = attrs.get('name', label)
164 name = attrs.get('name', label)
162
165
163 label += '_{0}'.format(attrs['line'].pk)
166 label += '_{0}'.format(attrs['line'].pk)
164
167
165 dc = float(json.loads(attrs['line'].params)['pulse_width'])*attrs['line'].rc_configuration.ipp/100
168 dc = float(json.loads(attrs['line'].params)['pulse_width'])*100/attrs['line'].rc_configuration.ipp
166
169
167 html = '''<div class="col-md-12 col-no-padding">
170 html = '''<div class="col-md-12 col-no-padding">
168 <div class="col-md-3 col-no-padding"><input type="number" {0} class="form-control" id="id_{1}" name="{2}" value="{3}"></div>
171 <div class="col-md-3 col-no-padding"><input type="number" {0} class="form-control" id="id_{1}" name="{2}" value="{3}"></div>
169 <div class="col-md-1 col-no-padding">Km</div>
172 <div class="col-md-1 col-no-padding">Km</div>
170 <div class="col-md-3 col-no-padding"><input type="number" {4} class="form-control" id="id_{1}_unit" value="{5}"></div>
173 <div class="col-md-3 col-no-padding"><input type="number" {4} class="form-control" id="id_{1}_unit" value="{5}"></div>
171 <div class="col-md-1 col-no-padding">Units</div>
174 <div class="col-md-1 col-no-padding">Units</div>
172 <div class="col-md-3 col-no-padding"><input type="number" {4} class="form-control" id="id_{1}_dc" value="{6}"></div>
175 <div class="col-md-3 col-no-padding"><input type="number" {4} class="form-control" id="id_{1}_dc" value="{6}"></div>
173 <div class="col-md-1 col-no-padding">DC[%]</div>
176 <div class="col-md-1 col-no-padding">DC[%]</div>
174 </div>'''.format(disabled, label, name, value, disabled, unit, dc)
177 </div>'''.format(disabled, label, name, value, disabled, unit, dc)
175
178
176 script = '''<script type="text/javascript">
179 script = '''<script type="text/javascript">
177 $(document).ready(function () {{
180 $(document).ready(function () {{
178 km_fields.push("id_{label}");
181 km_fields.push("id_{label}");
179 unit_fields.push("id_{label}_unit");
182 unit_fields.push("id_{label}_unit");
180 dc_fields.push("id_{label}");
183 dc_fields.push("id_{label}");
181 $("#id_{label}").change(function() {{
184 $("#id_{label}").change(function() {{
182 $("#id_{label}_unit").val(str2unit($(this).val()));
185 $("#id_{label}_unit").val(str2unit($(this).val()));
183 $("#id_{label}_dc").val(str2dc($("#id_{label}").val()));
186 $("#id_{label}_dc").val(str2dc($("#id_{label}").val()));
184 }});
187 }});
185 $("#id_{label}_unit").change(function() {{
188 $("#id_{label}_unit").change(function() {{
186 $("#id_{label}").val(str2km($(this).val()));
189 $("#id_{label}").val(str2km($(this).val()));
187 $("#id_{label}_dc").val(str2dc($("#id_{label}").val()));
190 $("#id_{label}_dc").val(str2dc($("#id_{label}").val()));
188 }});
191 }});
189
192
190 $("#id_{label}_dc").change(function() {{
193 $("#id_{label}_dc").change(function() {{
191 $("#id_{label}").val(parseFloat($(this).val())*parseFloat($("#id_ipp").val())/100);
194 $("#id_{label}").val(parseFloat($(this).val())*100/parseFloat($("#id_ipp").val()));
192 $("#id_{label}_unit").val(str2unit($("#id_{label}").val()));
195 $("#id_{label}_unit").val(str2unit($("#id_{label}").val()));
193 }});
196 }});
194 }});
197 }});
195 </script>'''.format(label=label)
198 </script>'''.format(label=label)
196
199
197 if disabled:
200 if disabled:
198 return mark_safe(html)
201 return mark_safe(html)
199 else:
202 else:
200 return mark_safe(html+script)
203 return mark_safe(html+script)
201
204
202
205
203 class DefaultWidget(forms.widgets.TextInput):
206 class DefaultWidget(forms.widgets.TextInput):
204
207
205 def render(self, label, value, attrs=None):
208 def render(self, label, value, attrs=None):
206
209
207 disabled = 'disabled' if attrs.get('disabled', False) else ''
210 disabled = 'disabled' if attrs.get('disabled', False) else ''
208 name = attrs.get('name', label)
211 name = attrs.get('name', label)
209
212
210 html = '<div class="col-md-12 col-no-padding"><div class="col-md-5 col-no-padding"><input {0} type="text" class="form-control" id="id_{1}" name="{2}" value="{3}"></div></div>'.format(disabled, label, name, value)
213 html = '<div class="col-md-12 col-no-padding"><div class="col-md-5 col-no-padding"><input {0} type="text" class="form-control" id="id_{1}" name="{2}" value="{3}"></div></div>'.format(disabled, label, name, value)
211
214
212 return mark_safe(html)
215 return mark_safe(html)
213
216
214
217
215 class HiddenWidget(forms.widgets.HiddenInput):
218 class HiddenWidget(forms.widgets.HiddenInput):
216
219
217 def render(self, label, value, attrs=None):
220 def render(self, label, value, attrs=None):
218
221
219 disabled = 'disabled' if attrs.get('disabled', False) else ''
222 disabled = 'disabled' if attrs.get('disabled', False) else ''
220 name = self.attrs.get('name', label)
223 name = self.attrs.get('name', label)
221
224
222 html = '<input {0} type="hidden" class="form-control" id="id_{1}" name="{2}" value="{3}">'.format(disabled, label, name, value)
225 html = '<input {0} type="hidden" class="form-control" id="id_{1}" name="{2}" value="{3}">'.format(disabled, label, name, value)
223
226
224 return mark_safe(html)
227 return mark_safe(html)
225
228
226
229
227 class CodesWidget(forms.widgets.Textarea):
230 class CodesWidget(forms.widgets.Textarea):
228
231
229 def render(self, label, value, attrs=None):
232 def render(self, label, value, attrs=None):
230
233
231 disabled = 'disabled' if attrs.get('disabled', False) else ''
234 disabled = 'disabled' if attrs.get('disabled', False) else ''
232 name = attrs.get('name', label)
235 name = attrs.get('name', label)
233
236
234 if '[' in value:
237 if '[' in value:
235 value = ast.literal_eval(value)
238 value = ast.literal_eval(value)
236
239
237 if isinstance(value, list):
240 if isinstance(value, list):
238 codes = '\r\n'.join(value)
241 codes = '\r\n'.join(value)
239 else:
242 else:
240 codes = value
243 codes = value
241
244
242 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)
245 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)
243
246
244 return mark_safe(html)
247 return mark_safe(html)
245
248
249 class HCheckboxSelectMultiple(forms.CheckboxSelectMultiple):
250
251 def render(self, name, value, attrs=None, choices=()):
252
253 if value is None: value = []
254 has_id = attrs and 'id' in attrs
255 final_attrs = self.build_attrs(attrs, name=name)
256 output = [u'<br><ul>']
257 # Normalize to strings
258 str_values = set([force_unicode(v) for v in value])
259 for i, (option_value, option_label) in enumerate(chain(self.choices, choices)):
260 # If an ID attribute was given, add a numeric index as a suffix,
261 # so that the checkboxes don't all have the same ID attribute.
262 if has_id:
263 final_attrs = dict(final_attrs, id='%s_%s' % (attrs['id'], i))
264 label_for = u' for="%s"' % final_attrs['id']
265 else:
266 label_for = ''
267
268 cb = forms.CheckboxInput(final_attrs, check_test=lambda value: value in str_values)
269 option_value = force_unicode(option_value)
270 rendered_cb = cb.render(name, option_value)
271 option_label = conditional_escape(force_unicode(option_label))
272 output.append(u'<span><label%s>%s %s</label></span>' % (label_for, rendered_cb, option_label))
273 output.append(u'</div><br>')
274 return mark_safe(u'\n'.join(output))
275 No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now