##// END OF EJS Templates
Fix RCLine.update_pulses()...
Juan C. Espinoza -
r115:4ad6aa018602
parent child
Show More
@@ -1,762 +1,762
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.save()
183 183 self.clean_lines()
184 184
185 185 lines = []
186 186 positions = {'tx':0, 'tr':0}
187 187
188 188 for i, line_data in enumerate(data['lines']):
189 189 line_type = RCLineType.objects.get(name=line_data.pop('type'))
190 190 if line_type.name=='codes':
191 191 code = RCLineCode.objects.get(name=line_data['code'])
192 192 line_data['code'] = code.pk
193 193 line = RCLine.objects.filter(rc_configuration=self, channel=i)
194 194 if line:
195 195 line = line[0]
196 196 line.line_type = line_type
197 197 line.params = json.dumps(line_data)
198 198 else:
199 199 line = RCLine(rc_configuration=self, line_type=line_type,
200 200 params=json.dumps(line_data),
201 201 channel=i)
202 202
203 203 if line_type.name=='tx':
204 204 line.position = positions['tx']
205 205 positions['tx'] += 1
206 206
207 207 if line_type.name=='tr':
208 208 line.position = positions['tr']
209 209 positions['tr'] += 1
210 210
211 211 line.save()
212 212 lines.append(line)
213 213
214 214 for line, line_data in zip(lines, data['lines']):
215 215 if 'TX_ref' in line_data:
216 216 params = json.loads(line.params)
217 217 if line_data['TX_ref'] in (0, '0'):
218 218 params['TX_ref'] = '0'
219 219 else:
220 220 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]
221 221 line.params = json.dumps(params)
222 222 line.save()
223 223
224 224
225 225 def get_delays(self):
226 226
227 227 pulses = [line.pulses_as_points() for line in self.get_lines()]
228 228 points = [tup for tups in pulses for tup in tups]
229 229 points = set([x for tup in points for x in tup])
230 230 points = list(points)
231 231 points.sort()
232 232
233 233 if points[0]<>0:
234 234 points.insert(0, 0)
235 235
236 236 return [points[i+1]-points[i] for i in range(len(points)-1)]
237 237
238 238
239 239 def get_pulses(self, binary=True):
240 240
241 241 pulses = [line.pulses_as_points() for line in self.get_lines()]
242 242 points = [tup for tups in pulses for tup in tups]
243 243 points = set([x for tup in points for x in tup])
244 244 points = list(points)
245 245 points.sort()
246 246
247 247 line_points = [line.pulses_as_points() for line in self.get_lines()]
248 248 line_points = [[(x, x+y) for x,y in tups] for tups in line_points]
249 249 line_points = [[t for x in tups for t in x] for tups in line_points]
250 250 states = [[1 if x in tups else 0 for tups in line_points] for x in points]
251 251
252 252 if binary:
253 253 states.reverse()
254 254 states = [int(''.join([str(x) for x in flips]), 2) for flips in states]
255 255
256 256 return states[:-1]
257 257
258 258 def add_cmd(self, cmd):
259 259
260 260 if cmd in DAT_CMDS:
261 261 return (255, DAT_CMDS[cmd])
262 262
263 263 def add_data(self, value):
264 264
265 265 return (254, value-1)
266 266
267 267 def parms_to_binary(self):
268 268 '''
269 269 Create "dat" stream to be send to CR
270 270 '''
271 271
272 272 data = []
273 273 # create header
274 274 data.append(self.add_cmd('DISABLE'))
275 275 data.append(self.add_cmd('CONTINUE'))
276 276 data.append(self.add_cmd('RESTART'))
277 277
278 278 if self.control_sw:
279 279 data.append(self.add_cmd('SW_ONE'))
280 280 else:
281 281 data.append(self.add_cmd('SW_ZERO'))
282 282
283 283 if self.control_tx:
284 284 data.append(self.add_cmd('TX_ONE'))
285 285 else:
286 286 data.append(self.add_cmd('TX_ZERO'))
287 287
288 288 # write divider
289 289 data.append(self.add_cmd('CLOCK_DIVIDER'))
290 290 data.append(self.add_data(self.clock_divider))
291 291
292 292 # write delays
293 293 data.append(self.add_cmd('DELAY_START'))
294 294 # first delay is always zero
295 295 data.append(self.add_data(1))
296 296
297 297 delays = self.get_delays()
298 298
299 299 for delay in delays:
300 300 while delay>252:
301 301 data.append(self.add_data(253))
302 302 delay -= 253
303 303 data.append(self.add_data(delay))
304 304
305 305 # write flips
306 306 data.append(self.add_cmd('FLIP_START'))
307 307
308 308 states = self.get_pulses(binary=False)
309 309
310 310 for flips, delay in zip(states, delays):
311 311 flips.reverse()
312 312 flip = int(''.join([str(x) for x in flips]), 2)
313 313 data.append(self.add_data(flip+1))
314 314 while delay>252:
315 315 data.append(self.add_data(1))
316 316 delay -= 253
317 317
318 318 # write sampling period
319 319 data.append(self.add_cmd('SAMPLING_PERIOD'))
320 320 wins = self.get_lines(line_type__name='windows')
321 321 if wins:
322 322 win_params = json.loads(wins[0].params)['params']
323 323 if win_params:
324 324 dh = int(win_params[0]['resolution']*self.km2unit)
325 325 else:
326 326 dh = 1
327 327 else:
328 328 dh = 1
329 329 data.append(self.add_data(dh))
330 330
331 331 # write enable
332 332 data.append(self.add_cmd('ENABLE'))
333 333
334 334 return '\n'.join(['{}'.format(x) for tup in data for x in tup])
335 335
336 336 def update_from_file(self, filename):
337 337 '''
338 338 Update instance from file
339 339 '''
340 340
341 341 f = RCFile(filename)
342 342 self.dict_to_parms(f.data)
343 343 self.update_pulses()
344 344
345 345 def update_pulses(self):
346 346
347 347 for line in self.get_lines():
348 348 line.update_pulses()
349 349
350 350 def plot_pulses(self):
351 351
352 352 import matplotlib.pyplot as plt
353 353 from bokeh.resources import CDN
354 354 from bokeh.embed import components
355 355 from bokeh.mpl import to_bokeh
356 356 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, PreviewSaveTool
357 357
358 358 lines = self.get_lines()
359 359
360 360 N = len(lines)
361 361 fig = plt.figure(figsize=(10, 2+N*0.5))
362 362 ax = fig.add_subplot(111)
363 363 labels = []
364 364
365 365 for i, line in enumerate(lines):
366 366 labels.append(line.get_name())
367 367 l = ax.plot((0, self.total_units),(N-i-1, N-i-1))
368 368 points = [(tup[0], tup[1]-tup[0]) for tup in line.pulses_as_points() if tup<>(0,0)]
369 369 ax.broken_barh(points, (N-i-1, 0.5),
370 370 edgecolor=l[0].get_color(), facecolor='none')
371 371
372 372 labels.reverse()
373 373 ax.set_yticklabels(labels)
374 374 plot = to_bokeh(fig, use_pandas=False)
375 375 plot.tools = [PanTool(dimensions=['width']), WheelZoomTool(dimensions=['width']), ResetTool(), PreviewSaveTool()]
376 376
377 377 return components(plot, CDN)
378 378
379 379 def status_device(self):
380 380
381 381 return 0
382 382
383 383 def stop_device(self):
384 384
385 385 answer = api.disable(ip = self.device.ip_address,
386 386 port = self.device.port_address)
387 387
388 388 if answer[0] != "1":
389 389 self.message = answer[0:]
390 390 return 0
391 391
392 392 self.message = answer[2:]
393 393 return 1
394 394
395 395 def start_device(self):
396 396
397 397 answer = api.enable(ip = self.device.ip_address,
398 398 port = self.device.port_address)
399 399
400 400 if answer[0] != "1":
401 401 self.message = answer[0:]
402 402 return 0
403 403
404 404 self.message = answer[2:]
405 405 return 1
406 406
407 407 def write_device(self):
408 408 answer = api.write_config(ip = self.device.ip_address,
409 409 port = self.device.port_address,
410 410 parms = self.parms_to_dict())
411 411
412 412 if answer[0] != "1":
413 413 self.message = answer[0:]
414 414 return 0
415 415
416 416 self.message = answer[2:]
417 417 return 1
418 418
419 419
420 420 class RCLineCode(models.Model):
421 421
422 422 name = models.CharField(max_length=40)
423 423 bits_per_code = models.PositiveIntegerField(default=0)
424 424 number_of_codes = models.PositiveIntegerField(default=0)
425 425 codes = models.TextField(blank=True, null=True)
426 426
427 427 class Meta:
428 428 db_table = 'rc_line_codes'
429 429 ordering = ('name',)
430 430
431 431 def __unicode__(self):
432 432 return u'%s' % self.name
433 433
434 434
435 435 class RCLineType(models.Model):
436 436
437 437 name = models.CharField(choices=LINE_TYPES, max_length=40)
438 438 description = models.TextField(blank=True, null=True)
439 439 params = models.TextField(default='[]')
440 440
441 441 class Meta:
442 442 db_table = 'rc_line_types'
443 443
444 444 def __unicode__(self):
445 445 return u'%s - %s' % (self.name.upper(), self.get_name_display())
446 446
447 447
448 448 class RCLine(models.Model):
449 449
450 450 rc_configuration = models.ForeignKey(RCConfiguration, on_delete=models.CASCADE)
451 451 line_type = models.ForeignKey(RCLineType)
452 452 channel = models.PositiveIntegerField(default=0)
453 453 position = models.PositiveIntegerField(default=0)
454 454 params = models.TextField(default='{}')
455 455 pulses = models.TextField(default='')
456 456
457 457 class Meta:
458 458 db_table = 'rc_lines'
459 459 ordering = ['channel']
460 460
461 461 def __unicode__(self):
462 462 if self.rc_configuration:
463 463 return u'%s - %s' % (self.rc_configuration, self.get_name())
464 464
465 465 def clone(self, **kwargs):
466 466
467 467 self.pk = None
468 468
469 469 for attr, value in kwargs.items():
470 470 setattr(self, attr, value)
471 471
472 472 self.save()
473 473
474 474 return self
475 475
476 476 def get_name(self):
477 477
478 478 chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
479 479 s = ''
480 480
481 481 if self.line_type.name in ('tx',):
482 482 s = chars[self.position]
483 483 elif self.line_type.name in ('codes', 'windows', 'tr'):
484 484 if 'TX_ref' in json.loads(self.params):
485 485 pk = json.loads(self.params)['TX_ref']
486 486 if pk in (0, '0'):
487 487 s = ','.join(chars[l.position] for l in self.rc_configuration.get_lines(line_type__name='tx'))
488 488 else:
489 489 ref = RCLine.objects.get(pk=pk)
490 490 s = chars[ref.position]
491 491 s = '({})'.format(s)
492 492 if s:
493 493 return '{}{} {}'.format(self.line_type.name.upper(), s, self.channel)
494 494 else:
495 495 return '{} {}'.format(self.line_type.name.upper(), self.channel)
496 496
497 497 def get_lines(self, **kwargs):
498 498
499 499 return RCLine.objects.filter(rc_configuration=self.rc_configuration, **kwargs)
500 500
501 501 def pulses_as_array(self):
502 502
503 503 y = np.zeros(self.rc_configuration.total_units)
504 504
505 505 for tup in ast.literal_eval(self.pulses):
506 506 y[tup[0]:tup[1]] = 1
507 507
508 508 return y.astype(np.int8)
509 509
510 510 def pulses_as_points(self):
511 511
512 512 return ast.literal_eval(self.pulses)
513 513
514 514 def get_win_ref(self, params, tx_id, km2unit):
515 515
516 516 ref = self.rc_configuration.sampling_reference
517 517 codes = [line for line in self.get_lines(line_type__name='codes') if int(json.loads(line.params)['TX_ref'])==int(tx_id)]
518 518
519 519 if codes:
520 520 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit/len(json.loads(codes[0].params)['codes'][0])
521 521 else:
522 522 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit
523 523
524 524 if ref=='first_baud':
525 525 return int(1 + (tx_width + 1)/2 + params['first_height']*km2unit - params['resolution']*km2unit)
526 526 elif ref=='sub_baud':
527 527 return int(1 + params['first_height']*km2unit - params['resolution']*km2unit/2)
528 528 else:
529 529 return 0
530 530
531 531 def update_pulses(self):
532 532 '''
533 533 Update pulses field
534 534 '''
535 535
536 536 km2unit = self.rc_configuration.km2unit
537 537 us2unit = self.rc_configuration.us2unit
538 538 ipp = self.rc_configuration.ipp
539 539 ntx = self.rc_configuration.ntx
540 540 ipp_u = int(ipp*km2unit)
541 541 total = ipp_u*ntx
542 542 y = []
543 543
544 544 if self.line_type.name=='tr':
545 545 tr_params = json.loads(self.params)
546 546
547 547 if tr_params['TX_ref'] in ('0', 0):
548 548 txs = self.get_lines(line_type__name='tx')
549 549 else:
550 txs = [RCLine.objects.filter(pk=tr_params['TX_ref'])]
550 txs = RCLine.objects.filter(pk=tr_params['TX_ref'])
551 551
552 552 for tx in txs:
553 553 params = json.loads(tx.params)
554 554 if float(params['pulse_width'])==0:
555 555 continue
556 556 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
557 557 width = float(params['pulse_width'])*km2unit+int(self.rc_configuration.time_before*us2unit)
558 558 before = 0
559 559 after = int(self.rc_configuration.time_after*us2unit)
560 560
561 561 y_tx = self.points(ntx, ipp_u, width,
562 562 delay=delays,
563 563 before=before,
564 564 after=after,
565 565 sync=self.rc_configuration.sync)
566 566
567 567 ranges = params['range'].split(',')
568 568
569 569 if len(ranges)>0 and ranges[0]<>'0':
570 570 y_tx = self.mask_ranges(y_tx, ranges)
571 571
572 572 tr_ranges = tr_params['range'].split(',')
573 573
574 574 if len(tr_ranges)>0 and tr_ranges[0]<>'0':
575 575 y_tx = self.mask_ranges(y_tx, tr_ranges)
576 576
577 577 y.extend(y_tx)
578 578
579 579 elif self.line_type.name=='tx':
580 580 params = json.loads(self.params)
581 581 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
582 582 width = float(params['pulse_width'])*km2unit
583 583
584 584 if width>0:
585 585 before = int(self.rc_configuration.time_before*us2unit)
586 586 after = 0
587 587
588 588 y = self.points(ntx, ipp_u, width,
589 589 delay=delays,
590 590 before=before,
591 591 after=after,
592 592 sync=self.rc_configuration.sync)
593 593
594 594 ranges = params['range'].split(',')
595 595
596 596 if len(ranges)>0 and ranges[0]<>'0':
597 597 y = self.mask_ranges(y, ranges)
598 598
599 599 elif self.line_type.name=='flip':
600 600 n = float(json.loads(self.params)['number_of_flips'])
601 601 width = n*ipp*km2unit
602 602 y = self.points(int((ntx+1)/(2*n)), ipp_u*n*2, width)
603 603
604 604 elif self.line_type.name=='codes':
605 605 params = json.loads(self.params)
606 606 tx = RCLine.objects.get(pk=params['TX_ref'])
607 607 tx_params = json.loads(tx.params)
608 608 delays = [float(d)*km2unit for d in tx_params['delays'].split(',') if d]
609 609 f = int(float(tx_params['pulse_width'])*km2unit)/len(params['codes'][0])
610 610 codes = [(np.fromstring(''.join([s*f for s in code]), dtype=np.uint8)-48).astype(np.int8) for code in params['codes']]
611 611 codes = [self.array_to_points(code) for code in codes]
612 612 n = len(codes)
613 613
614 614 for i, tup in enumerate(tx.pulses_as_points()):
615 615 code = codes[i%n]
616 616 y.extend([(c[0]+tup[0], c[1]+tup[0]) for c in code])
617 617
618 618 ranges = tx_params['range'].split(',')
619 619 if len(ranges)>0 and ranges[0]<>'0':
620 620 y = self.mask_ranges(y, ranges)
621 621
622 622 elif self.line_type.name=='sync':
623 623 params = json.loads(self.params)
624 624 n = ipp_u*ntx
625 625 if params['invert'] in ('1', 1):
626 626 y = [(n-1, n)]
627 627 else:
628 628 y = [(0, 1)]
629 629
630 630 elif self.line_type.name=='prog_pulses':
631 631 params = json.loads(self.params)
632 632 if int(params['periodic'])==0:
633 633 nntx = 1
634 634 nipp = ipp_u*ntx
635 635 else:
636 636 nntx = ntx
637 637 nipp = ipp_u
638 638
639 639 if 'params' in params and len(params['params'])>0:
640 640 for p in params['params']:
641 641 y_pp = self.points(nntx, nipp,
642 642 p['end']-p['begin'],
643 643 before=p['begin'])
644 644
645 645 y.extend(y_pp)
646 646
647 647 elif self.line_type.name=='windows':
648 648 params = json.loads(self.params)
649 649
650 650 if 'params' in params and len(params['params'])>0:
651 651 tr_params = json.loads(self.get_lines(line_type__name='tr')[0].params)
652 652 tr_ranges = tr_params['range'].split(',')
653 653 for p in params['params']:
654 654 y_win = self.points(ntx, ipp_u,
655 655 p['resolution']*p['number_of_samples']*km2unit,
656 656 before=int(self.rc_configuration.time_before*us2unit)+self.get_win_ref(p, params['TX_ref'], km2unit),
657 657 sync=self.rc_configuration.sync)
658 658
659 659 if len(tr_ranges)>0 and tr_ranges[0]<>'0':
660 660 y_win = self.mask_ranges(y_win, tr_ranges)
661 661
662 662 y.extend(y_win)
663 663
664 664 elif self.line_type.name=='mix':
665 665 values = self.rc_configuration.parameters.split('-')
666 666 confs = RCConfiguration.objects.filter(pk__in=[value.split('|')[0] for value in values])
667 667 modes = [value.split('|')[1] for value in values]
668 668 ops = [value.split('|')[2] for value in values]
669 669 delays = [value.split('|')[3] for value in values]
670 670 masks = [value.split('|')[4] for value in values]
671 671 mask = list('{:8b}'.format(int(masks[0])))
672 672 mask.reverse()
673 673 if mask[self.channel] in ('0', '', ' '):
674 674 y = np.zeros(total, dtype=np.int8)
675 675 else:
676 676 y = confs[0].get_lines(channel=self.channel)[0].pulses_as_array()
677 677
678 678 for i in range(1, len(values)):
679 679 mask = list('{:8b}'.format(int(masks[i])))
680 680 mask.reverse()
681 681
682 682 if mask[self.channel] in ('0', '', ' '):
683 683 continue
684 684 Y = confs[i].get_lines(channel=self.channel)[0].pulses_as_array()
685 685 delay = float(delays[i])*km2unit
686 686
687 687 if delay>0:
688 688 if delay<self.rc_configuration.ipp*km2unit and len(Y)==len(y):
689 689 y_temp = np.empty_like(Y)
690 690 y_temp[:delay] = 0
691 691 y_temp[delay:] = Y[:-delay]
692 692 elif delay+len(Y)>len(y):
693 693 y_new = np.zeros(delay+len(Y), dtype=np.int8)
694 694 y_new[:len(y)] = y
695 695 y = y_new
696 696 y_temp = np.zeros(delay+len(Y), dtype=np.int8)
697 697 y_temp[-len(Y):] = Y
698 698 elif delay+len(Y)==len(y):
699 699 y_temp = np.zeros(delay+len(Y))
700 700 y_temp[-len(Y):] = Y
701 701
702 702 if ops[i]=='OR':
703 703 y = y | y_temp
704 704 elif ops[i]=='XOR':
705 705 y = y ^ y_temp
706 706 elif ops[i]=='AND':
707 707 y = y & y_temp
708 708 elif ops[i]=='NAND':
709 709 y = y & ~y_temp
710 710
711 711 total = len(y)
712 712 y = self.array_to_points(y)
713 713
714 714 else:
715 715 y = []
716 716
717 717 if self.rc_configuration.total_units <> total:
718 718 self.rc_configuration.total_units = total
719 719 self.rc_configuration.save()
720 720
721 721 self.pulses = y
722 722 self.save()
723 723
724 724 @staticmethod
725 725 def array_to_points(X):
726 726
727 727 d = X[1:]-X[:-1]
728 728
729 729 up = np.where(d==1)[0]
730 730 if X[0]==1:
731 731 up = np.concatenate((np.array([-1]), up))
732 732 up += 1
733 733
734 734 dw = np.where(d==-1)[0]
735 735 if X[-1]==1:
736 736 dw = np.concatenate((dw, np.array([len(X)-1])))
737 737 dw += 1
738 738
739 739 return [(tup[0], tup[1]) for tup in zip(up, dw)]
740 740
741 741 @staticmethod
742 742 def mask_ranges(Y, ranges):
743 743
744 744 y = [(0, 0) for __ in Y]
745 745
746 746 for index in ranges:
747 747 if '-' in index:
748 748 args = [int(a) for a in index.split('-')]
749 749 y[args[0]-1:args[1]] = Y[args[0]-1:args[1]]
750 750 else:
751 751 y[int(index-1)] = Y[int(index-1)]
752 752
753 753 return y
754 754
755 755 @staticmethod
756 756 def points(ntx, ipp, width, delay=[0], before=0, after=0, sync=0):
757 757
758 758 delays = len(delay)
759 759
760 760 Y = [(ipp*x+before+delay[x%delays], ipp*x+width+before+delay[x%delays]+after) for x in range(ntx)]
761 761
762 762 return Y No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now