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