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