##// END OF EJS Templates
fix RCLine.get_name()...
Juan C. Espinoza -
r113:bda9db3004db
parent child
Show More
@@ -1,761 +1,761
1 1
2 2 import ast
3 3 import json
4 4 import numpy as np
5 5
6 6 from polymorphic import PolymorphicModel
7 7
8 8 from django.db import models
9 9 from django.core.urlresolvers import reverse
10 10 from django.core.validators import MinValueValidator, MaxValueValidator
11 11
12 12 from apps.main.models import Configuration
13 13 from devices.rc import api
14 14 from .utils import RCFile
15 15
16 16 # Create your models here.
17 17
18 18 LINE_TYPES = (
19 19 ('none', 'Not used'),
20 20 ('tr', 'Transmission/reception selector signal'),
21 21 ('tx', 'A modulating signal (Transmission pulse)'),
22 22 ('codes', 'BPSK modulating signal'),
23 23 ('windows', 'Sample window signal'),
24 24 ('sync', 'Synchronizing signal'),
25 25 ('flip', 'IPP related periodic signal'),
26 26 ('prog_pulses', 'Programmable pulse'),
27 27 ('mix', 'Mixed line'),
28 28 )
29 29
30 30
31 31 SAMPLING_REFS = (
32 32 ('none', 'No Reference'),
33 33 ('first_baud', 'Middle of the first baud'),
34 34 ('sub_baud', 'Middle of the sub-baud')
35 35 )
36 36
37 37 DAT_CMDS = {
38 38 # Pulse Design commands
39 39 'DISABLE' : 0, # Disables pulse generation
40 40 'ENABLE' : 24, # Enables pulse generation
41 41 'DELAY_START' : 40, # Write delay status to memory
42 42 'FLIP_START' : 48, # Write flip status to memory
43 43 'SAMPLING_PERIOD' : 64, # Establish Sampling Period
44 44 'TX_ONE' : 72, # Output '0' in line TX
45 45 'TX_ZERO' : 88, # Output '0' in line TX
46 46 'SW_ONE' : 104, # Output '0' in line SW
47 47 'SW_ZERO' : 112, # Output '1' in line SW
48 48 'RESTART': 120, # Restarts CR8 Firmware
49 49 'CONTINUE' : 253, # Function Unknown
50 50 # Commands available to new controllers
51 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.
52 52 'CLOCK_DIVISOR_INIT' : 12, # Specifies Clock Divisor. Legacy command, ignored in the actual .dat conversion
53 53 'CLOCK_DIVISOR_LAST' : 22, # Specifies Clock Divisor (default 60 if not included) syntax: 255,22 254,N-1.
54 54 'CLOCK_DIVIDER' : 8,
55 55 }
56 56
57 57
58 58 class RCConfiguration(Configuration):
59 59
60 60 ipp = models.FloatField(verbose_name='Inter pulse period [Km]', validators=[MinValueValidator(1), MaxValueValidator(9000)], default=300)
61 61 ntx = models.PositiveIntegerField(verbose_name='Number of TX', validators=[MinValueValidator(1), MaxValueValidator(300)], default=1)
62 62 clock_in = models.FloatField(verbose_name='Clock in [MHz]', validators=[MinValueValidator(1), MaxValueValidator(80)], default=1)
63 63 clock_divider = models.PositiveIntegerField(verbose_name='Clock divider', validators=[MinValueValidator(1), MaxValueValidator(256)], default=1)
64 64 clock = models.FloatField(verbose_name='Clock Master [MHz]', blank=True, default=1)
65 65 time_before = models.PositiveIntegerField(verbose_name='Time before [μS]', default=12)
66 66 time_after = models.PositiveIntegerField(verbose_name='Time after [μS]', default=1)
67 67 sync = models.PositiveIntegerField(verbose_name='Synchro delay', default=0)
68 68 sampling_reference = models.CharField(verbose_name='Sampling Reference', choices=SAMPLING_REFS, default='none', max_length=40)
69 69 control_tx = models.BooleanField(verbose_name='Control Switch TX', default=False)
70 70 control_sw = models.BooleanField(verbose_name='Control Switch SW', default=False)
71 71 total_units = models.PositiveIntegerField(default=0)
72 72 mix = models.BooleanField(default=False)
73 73
74 74 class Meta:
75 75 db_table = 'rc_configurations'
76 76
77 77
78 78 def __unicode__(self):
79 79
80 80 if self.mix:
81 81 return u'[MIXED]: %s' % self.name
82 82 else:
83 83 return u'[%s]: %s' % (self.device.name, self.name)
84 84
85 85 def get_absolute_url_plot(self):
86 86 return reverse('url_plot_rc_pulses', args=[str(self.id)])
87 87
88 88 def get_absolute_url_import(self):
89 89 return reverse('url_import_rc_conf', args=[str(self.id)])
90 90
91 91 @property
92 92 def ipp_unit(self):
93 93
94 94 return '{} ({})'.format(self.ipp, int(self.ipp*self.km2unit))
95 95
96 96 @property
97 97 def us2unit(self):
98 98
99 99 return self.clock_in/self.clock_divider
100 100
101 101 @property
102 102 def km2unit(self):
103 103
104 104 return 20./3*(self.clock_in/self.clock_divider)
105 105
106 106 def clone(self, **kwargs):
107 107
108 108 lines = self.get_lines()
109 109 self.pk = None
110 110 self.id = None
111 111 for attr, value in kwargs.items():
112 112 setattr(self, attr, value)
113 113 self.save()
114 114
115 115 for line in lines:
116 116 line.clone(rc_configuration=self)
117 117
118 118 return self
119 119
120 120 def get_lines(self, **kwargs):
121 121 '''
122 122 Retrieve configuration lines
123 123 '''
124 124
125 125 return RCLine.objects.filter(rc_configuration=self.pk, **kwargs)
126 126
127 127
128 128 def clean_lines(self):
129 129 '''
130 130 '''
131 131
132 132 empty_line = RCLineType.objects.get(name='none')
133 133
134 134 for line in self.get_lines():
135 135 line.line_type = empty_line
136 136 line.params = '{}'
137 137 line.save()
138 138
139 139 def parms_to_dict(self):
140 140 '''
141 141 '''
142 142
143 143 ignored = ('parameters', 'type', 'polymorphic_ctype', 'configuration_ptr',
144 144 'created_date', 'programmed_date')
145 145
146 146 data = {}
147 147 for field in self._meta.fields:
148 148 if field.name in ignored:
149 149 continue
150 150 data[field.name] = '{}'.format(field.value_from_object(self))
151 151
152 152 data['lines'] = []
153 153
154 154 for line in self.get_lines():
155 155 line_data = json.loads(line.params)
156 156 if 'TX_ref' in line_data and line_data['TX_ref'] not in (0, '0'):
157 157 line_data['TX_ref'] = RCLine.objects.get(pk=line_data['TX_ref']).get_name()
158 158 if 'code' in line_data:
159 159 line_data['code'] = RCLineCode.objects.get(pk=line_data['code']).name
160 160 line_data['type'] = line.line_type.name
161 161 data['lines'].append(line_data)
162 162
163 163 data['delays'] = self.get_delays()
164 164 data['pulses'] = self.get_pulses()
165 165
166 166 return data
167 167
168 168 def dict_to_parms(self, data):
169 169 '''
170 170 '''
171 171
172 172 self.name = data['name']
173 173 self.ipp = data['ipp']
174 174 self.ntx = data['ntx']
175 175 self.clock_in = data['clock_in']
176 176 self.clock_divider = data['clock_divider']
177 177 self.clock = data['clock']
178 178 self.time_before = data['time_before']
179 179 self.time_after = data['time_after']
180 180 self.sync = data['sync']
181 181 self.sampling_reference = data['sampling_reference']
182 182 self.clean_lines()
183 183
184 184 lines = []
185 185 positions = {'tx':0, 'tr':0}
186 186
187 187 for i, line_data in enumerate(data['lines']):
188 188 line_type = RCLineType.objects.get(name=line_data.pop('type'))
189 189 if line_type.name=='codes':
190 190 code = RCLineCode.objects.get(name=line_data['code'])
191 191 line_data['code'] = code.pk
192 192 line = RCLine.objects.filter(rc_configuration=self, channel=i)
193 193 if line:
194 194 line = line[0]
195 195 line.line_type = line_type
196 196 line.params = json.dumps(line_data)
197 197 else:
198 198 line = RCLine(rc_configuration=self, line_type=line_type,
199 199 params=json.dumps(line_data),
200 200 channel=i)
201 201
202 202 if line_type.name=='tx':
203 203 line.position = positions['tx']
204 204 positions['tx'] += 1
205 205
206 206 if line_type.name=='tr':
207 207 line.position = positions['tr']
208 208 positions['tr'] += 1
209 209
210 210 line.save()
211 211 lines.append(line)
212 212
213 213 for line, line_data in zip(lines, data['lines']):
214 214 if 'TX_ref' in line_data:
215 215 params = json.loads(line.params)
216 216 if line_data['TX_ref'] in (0, '0'):
217 217 params['TX_ref'] = '0'
218 218 else:
219 params['TX_ref'] = [l.pk for l in lines if l.line_type.name=='tx' and l.get_name()==line_data['TX_ref']][0]
219 params['TX_ref'] = [l.pk for l in lines if l.line_type.name=='tx' and line_data['TX_ref'] in l.get_name()][0]
220 220 line.params = json.dumps(params)
221 221 line.save()
222 222
223 223
224 224 def get_delays(self):
225 225
226 226 pulses = [line.pulses_as_points() for line in self.get_lines()]
227 227 points = [tup for tups in pulses for tup in tups]
228 228 points = set([x for tup in points for x in tup])
229 229 points = list(points)
230 230 points.sort()
231 231
232 232 if points[0]<>0:
233 233 points.insert(0, 0)
234 234
235 235 return [points[i+1]-points[i] for i in range(len(points)-1)]
236 236
237 237
238 238 def get_pulses(self, binary=True):
239 239
240 240 pulses = [line.pulses_as_points() for line in self.get_lines()]
241 241 points = [tup for tups in pulses for tup in tups]
242 242 points = set([x for tup in points for x in tup])
243 243 points = list(points)
244 244 points.sort()
245 245
246 246 line_points = [line.pulses_as_points() for line in self.get_lines()]
247 247 line_points = [[(x, x+y) for x,y in tups] for tups in line_points]
248 248 line_points = [[t for x in tups for t in x] for tups in line_points]
249 249 states = [[1 if x in tups else 0 for tups in line_points] for x in points]
250 250
251 251 if binary:
252 252 states.reverse()
253 253 states = [int(''.join([str(x) for x in flips]), 2) for flips in states]
254 254
255 255 return states[:-1]
256 256
257 257 def add_cmd(self, cmd):
258 258
259 259 if cmd in DAT_CMDS:
260 260 return (255, DAT_CMDS[cmd])
261 261
262 262 def add_data(self, value):
263 263
264 264 return (254, value-1)
265 265
266 266 def parms_to_binary(self):
267 267 '''
268 268 Create "dat" stream to be send to CR
269 269 '''
270 270
271 271 data = []
272 272 # create header
273 273 data.append(self.add_cmd('DISABLE'))
274 274 data.append(self.add_cmd('CONTINUE'))
275 275 data.append(self.add_cmd('RESTART'))
276 276
277 277 if self.control_sw:
278 278 data.append(self.add_cmd('SW_ONE'))
279 279 else:
280 280 data.append(self.add_cmd('SW_ZERO'))
281 281
282 282 if self.control_tx:
283 283 data.append(self.add_cmd('TX_ONE'))
284 284 else:
285 285 data.append(self.add_cmd('TX_ZERO'))
286 286
287 287 # write divider
288 288 data.append(self.add_cmd('CLOCK_DIVIDER'))
289 289 data.append(self.add_data(self.clock_divider))
290 290
291 291 # write delays
292 292 data.append(self.add_cmd('DELAY_START'))
293 293 # first delay is always zero
294 294 data.append(self.add_data(1))
295 295
296 296 delays = self.get_delays()
297 297
298 298 for delay in delays:
299 299 while delay>252:
300 300 data.append(self.add_data(253))
301 301 delay -= 253
302 302 data.append(self.add_data(delay))
303 303
304 304 # write flips
305 305 data.append(self.add_cmd('FLIP_START'))
306 306
307 307 states = self.get_pulses(binary=False)
308 308
309 309 for flips, delay in zip(states, delays):
310 310 flips.reverse()
311 311 flip = int(''.join([str(x) for x in flips]), 2)
312 312 data.append(self.add_data(flip+1))
313 313 while delay>252:
314 314 data.append(self.add_data(1))
315 315 delay -= 253
316 316
317 317 # write sampling period
318 318 data.append(self.add_cmd('SAMPLING_PERIOD'))
319 319 wins = self.get_lines(line_type__name='windows')
320 320 if wins:
321 321 win_params = json.loads(wins[0].params)['params']
322 322 if win_params:
323 323 dh = int(win_params[0]['resolution']*self.km2unit)
324 324 else:
325 325 dh = 1
326 326 else:
327 327 dh = 1
328 328 data.append(self.add_data(dh))
329 329
330 330 # write enable
331 331 data.append(self.add_cmd('ENABLE'))
332 332
333 333 return '\n'.join(['{}'.format(x) for tup in data for x in tup])
334 334
335 335 def update_from_file(self, filename):
336 336 '''
337 337 Update instance from file
338 338 '''
339 339
340 340 f = RCFile(filename)
341 341 self.dict_to_parms(f.data)
342 342 self.update_pulses()
343 343
344 344 def update_pulses(self):
345 345
346 346 for line in self.get_lines():
347 347 line.update_pulses()
348 348
349 349 def plot_pulses(self):
350 350
351 351 import matplotlib.pyplot as plt
352 352 from bokeh.resources import CDN
353 353 from bokeh.embed import components
354 354 from bokeh.mpl import to_bokeh
355 355 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, PreviewSaveTool
356 356
357 357 lines = self.get_lines()
358 358
359 359 N = len(lines)
360 360 fig = plt.figure(figsize=(10, 2+N*0.5))
361 361 ax = fig.add_subplot(111)
362 362 labels = []
363 363
364 364 for i, line in enumerate(lines):
365 365 labels.append(line.get_name())
366 366 l = ax.plot((0, self.total_units),(N-i-1, N-i-1))
367 367 points = [(tup[0], tup[1]-tup[0]) for tup in line.pulses_as_points() if tup<>(0,0)]
368 368 ax.broken_barh(points, (N-i-1, 0.5),
369 369 edgecolor=l[0].get_color(), facecolor='none')
370 370
371 371 labels.reverse()
372 372 ax.set_yticklabels(labels)
373 373 plot = to_bokeh(fig, use_pandas=False)
374 374 plot.tools = [PanTool(dimensions=['width']), WheelZoomTool(dimensions=['width']), ResetTool(), PreviewSaveTool()]
375 375
376 376 return components(plot, CDN)
377 377
378 378 def status_device(self):
379 379
380 380 return 0
381 381
382 382 def stop_device(self):
383 383
384 384 answer = api.disable(ip = self.device.ip_address,
385 385 port = self.device.port_address)
386 386
387 387 if answer[0] != "1":
388 388 self.message = answer[0:]
389 389 return 0
390 390
391 391 self.message = answer[2:]
392 392 return 1
393 393
394 394 def start_device(self):
395 395
396 396 answer = api.enable(ip = self.device.ip_address,
397 397 port = self.device.port_address)
398 398
399 399 if answer[0] != "1":
400 400 self.message = answer[0:]
401 401 return 0
402 402
403 403 self.message = answer[2:]
404 404 return 1
405 405
406 406 def write_device(self):
407 407 answer = api.write_config(ip = self.device.ip_address,
408 408 port = self.device.port_address,
409 409 parms = self.parms_to_dict())
410 410
411 411 if answer[0] != "1":
412 412 self.message = answer[0:]
413 413 return 0
414 414
415 415 self.message = answer[2:]
416 416 return 1
417 417
418 418
419 419 class RCLineCode(models.Model):
420 420
421 421 name = models.CharField(max_length=40)
422 422 bits_per_code = models.PositiveIntegerField(default=0)
423 423 number_of_codes = models.PositiveIntegerField(default=0)
424 424 codes = models.TextField(blank=True, null=True)
425 425
426 426 class Meta:
427 427 db_table = 'rc_line_codes'
428 428 ordering = ('name',)
429 429
430 430 def __unicode__(self):
431 431 return u'%s' % self.name
432 432
433 433
434 434 class RCLineType(models.Model):
435 435
436 436 name = models.CharField(choices=LINE_TYPES, max_length=40)
437 437 description = models.TextField(blank=True, null=True)
438 438 params = models.TextField(default='[]')
439 439
440 440 class Meta:
441 441 db_table = 'rc_line_types'
442 442
443 443 def __unicode__(self):
444 444 return u'%s - %s' % (self.name.upper(), self.get_name_display())
445 445
446 446
447 447 class RCLine(models.Model):
448 448
449 449 rc_configuration = models.ForeignKey(RCConfiguration, on_delete=models.CASCADE)
450 450 line_type = models.ForeignKey(RCLineType)
451 451 channel = models.PositiveIntegerField(default=0)
452 452 position = models.PositiveIntegerField(default=0)
453 453 params = models.TextField(default='{}')
454 454 pulses = models.TextField(default='')
455 455
456 456 class Meta:
457 457 db_table = 'rc_lines'
458 458 ordering = ['channel']
459 459
460 460 def __unicode__(self):
461 461 if self.rc_configuration:
462 462 return u'%s - %s' % (self.rc_configuration, self.get_name())
463 463
464 464 def clone(self, **kwargs):
465 465
466 466 self.pk = None
467 467
468 468 for attr, value in kwargs.items():
469 469 setattr(self, attr, value)
470 470
471 471 self.save()
472 472
473 473 return self
474 474
475 475 def get_name(self):
476 476
477 477 chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
478 478 s = ''
479 479
480 480 if self.line_type.name in ('tx',):
481 481 s = chars[self.position]
482 482 elif self.line_type.name in ('codes', 'windows', 'tr'):
483 483 if 'TX_ref' in json.loads(self.params):
484 484 pk = json.loads(self.params)['TX_ref']
485 485 if pk in (0, '0'):
486 s = ','.join(chars[l.position] for l in self.rc_configuration.get_lines(line_type__name='tx'))
486 s = ','.join(chars[l.position] for l in self.rc_configuration.get_lines(line_type__name='tx'))
487 487 else:
488 488 ref = RCLine.objects.get(pk=pk)
489 489 s = chars[ref.position]
490
490 s = '({})'.format(s)
491 491 if s:
492 return '{}({}) {}'.format(self.line_type.name.upper(), s, self.channel)
492 return '{}{} {}'.format(self.line_type.name.upper(), s, self.channel)
493 493 else:
494 494 return '{} {}'.format(self.line_type.name.upper(), self.channel)
495 495
496 496 def get_lines(self, **kwargs):
497 497
498 498 return RCLine.objects.filter(rc_configuration=self.rc_configuration, **kwargs)
499 499
500 500 def pulses_as_array(self):
501 501
502 502 y = np.zeros(self.rc_configuration.total_units)
503 503
504 504 for tup in ast.literal_eval(self.pulses):
505 505 y[tup[0]:tup[1]] = 1
506 506
507 507 return y.astype(np.int8)
508 508
509 509 def pulses_as_points(self):
510 510
511 511 return ast.literal_eval(self.pulses)
512 512
513 513 def get_win_ref(self, params, tx_id, km2unit):
514 514
515 515 ref = self.rc_configuration.sampling_reference
516 516 codes = [line for line in self.get_lines(line_type__name='codes') if int(json.loads(line.params)['TX_ref'])==int(tx_id)]
517 517
518 518 if codes:
519 519 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit/len(json.loads(codes[0].params)['codes'][0])
520 520 else:
521 521 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit
522 522
523 523 if ref=='first_baud':
524 524 return int(1 + (tx_width + 1)/2 + params['first_height']*km2unit - params['resolution']*km2unit)
525 525 elif ref=='sub_baud':
526 526 return int(1 + params['first_height']*km2unit - params['resolution']*km2unit/2)
527 527 else:
528 528 return 0
529 529
530 530 def update_pulses(self):
531 531 '''
532 532 Update pulses field
533 533 '''
534 534
535 535 km2unit = self.rc_configuration.km2unit
536 536 us2unit = self.rc_configuration.us2unit
537 537 ipp = self.rc_configuration.ipp
538 538 ntx = self.rc_configuration.ntx
539 539 ipp_u = int(ipp*km2unit)
540 540 total = ipp_u*ntx
541 541 y = []
542 542
543 543 if self.line_type.name=='tr':
544 544 tr_params = json.loads(self.params)
545 545
546 546 if tr_params['TX_ref'] in ('0', 0):
547 547 txs = self.get_lines(line_type__name='tx')
548 548 else:
549 549 txs = [RCLine.objects.filter(pk=tr_params['TX_ref'])]
550 550
551 551 for tx in txs:
552 552 params = json.loads(tx.params)
553 553 if float(params['pulse_width'])==0:
554 554 continue
555 555 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
556 556 width = float(params['pulse_width'])*km2unit+int(self.rc_configuration.time_before*us2unit)
557 557 before = 0
558 558 after = int(self.rc_configuration.time_after*us2unit)
559 559
560 560 y_tx = self.points(ntx, ipp_u, width,
561 561 delay=delays,
562 562 before=before,
563 563 after=after,
564 564 sync=self.rc_configuration.sync)
565 565
566 566 ranges = params['range'].split(',')
567 567
568 568 if len(ranges)>0 and ranges[0]<>'0':
569 569 y_tx = self.mask_ranges(y_tx, ranges)
570 570
571 571 tr_ranges = tr_params['range'].split(',')
572 572
573 573 if len(tr_ranges)>0 and tr_ranges[0]<>'0':
574 574 y_tx = self.mask_ranges(y_tx, tr_ranges)
575 575
576 576 y.extend(y_tx)
577 577
578 578 elif self.line_type.name=='tx':
579 579 params = json.loads(self.params)
580 580 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
581 581 width = float(params['pulse_width'])*km2unit
582 582
583 583 if width>0:
584 584 before = int(self.rc_configuration.time_before*us2unit)
585 585 after = 0
586 586
587 587 y = self.points(ntx, ipp_u, width,
588 588 delay=delays,
589 589 before=before,
590 590 after=after,
591 591 sync=self.rc_configuration.sync)
592 592
593 593 ranges = params['range'].split(',')
594 594
595 595 if len(ranges)>0 and ranges[0]<>'0':
596 596 y = self.mask_ranges(y, ranges)
597 597
598 598 elif self.line_type.name=='flip':
599 599 n = float(json.loads(self.params)['number_of_flips'])
600 600 width = n*ipp*km2unit
601 601 y = self.points(int((ntx+1)/(2*n)), ipp_u*n*2, width)
602 602
603 603 elif self.line_type.name=='codes':
604 604 params = json.loads(self.params)
605 605 tx = RCLine.objects.get(pk=params['TX_ref'])
606 606 tx_params = json.loads(tx.params)
607 607 delays = [float(d)*km2unit for d in tx_params['delays'].split(',') if d]
608 608 f = int(float(tx_params['pulse_width'])*km2unit)/len(params['codes'][0])
609 609 codes = [(np.fromstring(''.join([s*f for s in code]), dtype=np.uint8)-48).astype(np.int8) for code in params['codes']]
610 610 codes = [self.array_to_points(code) for code in codes]
611 611 n = len(codes)
612 612
613 613 for i, tup in enumerate(tx.pulses_as_points()):
614 614 code = codes[i%n]
615 615 y.extend([(c[0]+tup[0], c[1]+tup[0]) for c in code])
616 616
617 617 ranges = tx_params['range'].split(',')
618 618 if len(ranges)>0 and ranges[0]<>'0':
619 619 y = self.mask_ranges(y, ranges)
620 620
621 621 elif self.line_type.name=='sync':
622 622 params = json.loads(self.params)
623 623 n = ipp_u*ntx
624 624 if params['invert'] in ('1', 1):
625 625 y = [(n-1, n)]
626 626 else:
627 627 y = [(0, 1)]
628 628
629 629 elif self.line_type.name=='prog_pulses':
630 630 params = json.loads(self.params)
631 631 if int(params['periodic'])==0:
632 632 nntx = 1
633 633 nipp = ipp_u*ntx
634 634 else:
635 635 nntx = ntx
636 636 nipp = ipp_u
637 637
638 638 if 'params' in params and len(params['params'])>0:
639 639 for p in params['params']:
640 640 y_pp = self.points(nntx, nipp,
641 641 p['end']-p['begin'],
642 642 before=p['begin'])
643 643
644 644 y.extend(y_pp)
645 645
646 646 elif self.line_type.name=='windows':
647 647 params = json.loads(self.params)
648 648
649 649 if 'params' in params and len(params['params'])>0:
650 650 tr_params = json.loads(self.get_lines(line_type__name='tr')[0].params)
651 651 tr_ranges = tr_params['range'].split(',')
652 652 for p in params['params']:
653 653 y_win = self.points(ntx, ipp_u,
654 654 p['resolution']*p['number_of_samples']*km2unit,
655 655 before=int(self.rc_configuration.time_before*us2unit)+self.get_win_ref(p, params['TX_ref'], km2unit),
656 656 sync=self.rc_configuration.sync)
657 657
658 658 if len(tr_ranges)>0 and tr_ranges[0]<>'0':
659 659 y_win = self.mask_ranges(y_win, tr_ranges)
660 660
661 661 y.extend(y_win)
662 662
663 663 elif self.line_type.name=='mix':
664 664 values = self.rc_configuration.parameters.split('-')
665 665 confs = RCConfiguration.objects.filter(pk__in=[value.split('|')[0] for value in values])
666 666 modes = [value.split('|')[1] for value in values]
667 667 ops = [value.split('|')[2] for value in values]
668 668 delays = [value.split('|')[3] for value in values]
669 669 masks = [value.split('|')[4] for value in values]
670 670 mask = list('{:8b}'.format(int(masks[0])))
671 671 mask.reverse()
672 672 if mask[self.channel] in ('0', '', ' '):
673 673 y = np.zeros(total, dtype=np.int8)
674 674 else:
675 675 y = confs[0].get_lines(channel=self.channel)[0].pulses_as_array()
676 676
677 677 for i in range(1, len(values)):
678 678 mask = list('{:8b}'.format(int(masks[i])))
679 679 mask.reverse()
680 680
681 681 if mask[self.channel] in ('0', '', ' '):
682 682 continue
683 683 Y = confs[i].get_lines(channel=self.channel)[0].pulses_as_array()
684 684 delay = float(delays[i])*km2unit
685 685
686 686 if delay>0:
687 687 if delay<self.rc_configuration.ipp*km2unit and len(Y)==len(y):
688 688 y_temp = np.empty_like(Y)
689 689 y_temp[:delay] = 0
690 690 y_temp[delay:] = Y[:-delay]
691 691 elif delay+len(Y)>len(y):
692 692 y_new = np.zeros(delay+len(Y), dtype=np.int8)
693 693 y_new[:len(y)] = y
694 694 y = y_new
695 695 y_temp = np.zeros(delay+len(Y), dtype=np.int8)
696 696 y_temp[-len(Y):] = Y
697 697 elif delay+len(Y)==len(y):
698 698 y_temp = np.zeros(delay+len(Y))
699 699 y_temp[-len(Y):] = Y
700 700
701 701 if ops[i]=='OR':
702 702 y = y | y_temp
703 703 elif ops[i]=='XOR':
704 704 y = y ^ y_temp
705 705 elif ops[i]=='AND':
706 706 y = y & y_temp
707 707 elif ops[i]=='NAND':
708 708 y = y & ~y_temp
709 709
710 710 total = len(y)
711 711 y = self.array_to_points(y)
712 712
713 713 else:
714 714 y = []
715 715
716 716 if self.rc_configuration.total_units <> total:
717 717 self.rc_configuration.total_units = total
718 718 self.rc_configuration.save()
719 719
720 720 self.pulses = y
721 721 self.save()
722 722
723 723 @staticmethod
724 724 def array_to_points(X):
725 725
726 726 d = X[1:]-X[:-1]
727 727
728 728 up = np.where(d==1)[0]
729 729 if X[0]==1:
730 730 up = np.concatenate((np.array([-1]), up))
731 731 up += 1
732 732
733 733 dw = np.where(d==-1)[0]
734 734 if X[-1]==1:
735 735 dw = np.concatenate((dw, np.array([len(X)-1])))
736 736 dw += 1
737 737
738 738 return [(tup[0], tup[1]) for tup in zip(up, dw)]
739 739
740 740 @staticmethod
741 741 def mask_ranges(Y, ranges):
742 742
743 743 y = [(0, 0) for __ in Y]
744 744
745 745 for index in ranges:
746 746 if '-' in index:
747 747 args = [int(a) for a in index.split('-')]
748 748 y[args[0]-1:args[1]] = Y[args[0]-1:args[1]]
749 749 else:
750 750 y[int(index-1)] = Y[int(index-1)]
751 751
752 752 return y
753 753
754 754 @staticmethod
755 755 def points(ntx, ipp, width, delay=[0], before=0, after=0, sync=0):
756 756
757 757 delays = len(delay)
758 758
759 759 Y = [(ipp*x+before+delay[x%delays], ipp*x+width+before+delay[x%delays]+after) for x in range(ntx)]
760 760
761 761 return Y No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now