##// END OF EJS Templates
Fix bug when import json...
Juan C. Espinoza -
r148:e89cf2aa70f7
parent child
Show More
@@ -1,767 +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 144 data['device_id'] = data.pop('device')
145 145 data['lines'] = []
146 146
147 147 for line in self.get_lines():
148 148 line_data = json.loads(line.params)
149 149 if 'TX_ref' in line_data and line_data['TX_ref'] not in (0, '0'):
150 150 line_data['TX_ref'] = RCLine.objects.get(pk=line_data['TX_ref']).get_name()
151 151 if 'code' in line_data:
152 152 line_data['code'] = RCLineCode.objects.get(pk=line_data['code']).name
153 153 line_data['type'] = line.line_type.name
154 154 data['lines'].append(line_data)
155 155
156 156 data['delays'] = self.get_delays()
157 157 data['pulses'] = self.get_pulses()
158 158
159 159 return data
160 160
161 161 def dict_to_parms(self, data):
162 162 '''
163 163 '''
164 164
165 165 self.name = data['name']
166 self.ipp = data['ipp']
167 self.ntx = data['ntx']
168 self.clock_in = data['clock_in']
169 self.clock_divider = data['clock_divider']
170 self.clock = data['clock']
166 self.ipp = float(data['ipp'])
167 self.ntx = int(data['ntx'])
168 self.clock_in = float(data['clock_in'])
169 self.clock_divider = int(data['clock_divider'])
170 self.clock = float(data['clock'])
171 171 self.time_before = data['time_before']
172 172 self.time_after = data['time_after']
173 173 self.sync = data['sync']
174 174 self.sampling_reference = data['sampling_reference']
175 175 self.total_units = self.ipp*self.ntx*self.km2unit
176 176 self.save()
177 177 self.clean_lines()
178 178
179 179 lines = []
180 180 positions = {'tx':0, 'tr':0}
181 181
182 182 for i, line_data in enumerate(data['lines']):
183 183 line_type = RCLineType.objects.get(name=line_data.pop('type'))
184 184 if line_type.name=='codes':
185 185 code = RCLineCode.objects.get(name=line_data['code'])
186 186 line_data['code'] = code.pk
187 187 line = RCLine.objects.filter(rc_configuration=self, channel=i)
188 188 if line:
189 189 line = line[0]
190 190 line.line_type = line_type
191 191 line.params = json.dumps(line_data)
192 192 else:
193 193 line = RCLine(rc_configuration=self, line_type=line_type,
194 194 params=json.dumps(line_data),
195 195 channel=i)
196 196
197 197 if line_type.name=='tx':
198 198 line.position = positions['tx']
199 199 positions['tx'] += 1
200 200
201 201 if line_type.name=='tr':
202 202 line.position = positions['tr']
203 203 positions['tr'] += 1
204 204
205 205 line.save()
206 206 lines.append(line)
207 207
208 208 for line, line_data in zip(lines, data['lines']):
209 209 if 'TX_ref' in line_data:
210 210 params = json.loads(line.params)
211 211 if line_data['TX_ref'] in (0, '0'):
212 212 params['TX_ref'] = '0'
213 213 else:
214 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]
215 215 line.params = json.dumps(params)
216 216 line.save()
217 217
218 218
219 219 def get_delays(self):
220 220
221 221 pulses = [line.pulses_as_points() for line in self.get_lines()]
222 222 points = [tup for tups in pulses for tup in tups]
223 223 points = set([x for tup in points for x in tup])
224 224 points = list(points)
225 225 points.sort()
226 226
227 227 if points[0]<>0:
228 228 points.insert(0, 0)
229 229
230 230 return [points[i+1]-points[i] for i in range(len(points)-1)]
231 231
232 232
233 233 def get_pulses(self, binary=True):
234 234
235 235 pulses = [line.pulses_as_points() for line in self.get_lines()]
236 236 points = [tup for tups in pulses for tup in tups]
237 237 points = set([x for tup in points for x in tup])
238 238 points = list(points)
239 239 points.sort()
240 240
241 241 line_points = [line.pulses_as_points() for line in self.get_lines()]
242 242 line_points = [[(x, x+y) for x,y in tups] for tups in line_points]
243 243 line_points = [[t for x in tups for t in x] for tups in line_points]
244 244 states = [[1 if x in tups else 0 for tups in line_points] for x in points]
245 245
246 246 if binary:
247 247 states.reverse()
248 248 states = [int(''.join([str(x) for x in flips]), 2) for flips in states]
249 249
250 250 return states[:-1]
251 251
252 252 def add_cmd(self, cmd):
253 253
254 254 if cmd in DAT_CMDS:
255 255 return (255, DAT_CMDS[cmd])
256 256
257 257 def add_data(self, value):
258 258
259 259 return (254, value-1)
260 260
261 261 def parms_to_binary(self):
262 262 '''
263 263 Create "dat" stream to be send to CR
264 264 '''
265 265
266 266 data = []
267 267 # create header
268 268 data.append(self.add_cmd('DISABLE'))
269 269 data.append(self.add_cmd('CONTINUE'))
270 270 data.append(self.add_cmd('RESTART'))
271 271
272 272 if self.control_sw:
273 273 data.append(self.add_cmd('SW_ONE'))
274 274 else:
275 275 data.append(self.add_cmd('SW_ZERO'))
276 276
277 277 if self.control_tx:
278 278 data.append(self.add_cmd('TX_ONE'))
279 279 else:
280 280 data.append(self.add_cmd('TX_ZERO'))
281 281
282 282 # write divider
283 283 data.append(self.add_cmd('CLOCK_DIVIDER'))
284 284 data.append(self.add_data(self.clock_divider))
285 285
286 286 # write delays
287 287 data.append(self.add_cmd('DELAY_START'))
288 288 # first delay is always zero
289 289 data.append(self.add_data(1))
290 290
291 291 delays = self.get_delays()
292 292
293 293 for delay in delays:
294 294 while delay>252:
295 295 data.append(self.add_data(253))
296 296 delay -= 253
297 297 data.append(self.add_data(delay))
298 298
299 299 # write flips
300 300 data.append(self.add_cmd('FLIP_START'))
301 301
302 302 states = self.get_pulses(binary=False)
303 303
304 304 for flips, delay in zip(states, delays):
305 305 flips.reverse()
306 306 flip = int(''.join([str(x) for x in flips]), 2)
307 307 data.append(self.add_data(flip+1))
308 308 while delay>252:
309 309 data.append(self.add_data(1))
310 310 delay -= 253
311 311
312 312 # write sampling period
313 313 data.append(self.add_cmd('SAMPLING_PERIOD'))
314 314 wins = self.get_lines(line_type__name='windows')
315 315 if wins:
316 316 win_params = json.loads(wins[0].params)['params']
317 317 if win_params:
318 318 dh = int(win_params[0]['resolution']*self.km2unit)
319 319 else:
320 320 dh = 1
321 321 else:
322 322 dh = 1
323 323 data.append(self.add_data(dh))
324 324
325 325 # write enable
326 326 data.append(self.add_cmd('ENABLE'))
327 327
328 328 return '\n'.join(['{}'.format(x) for tup in data for x in tup])
329 329
330 330 def update_from_file(self, filename):
331 331 '''
332 332 Update instance from file
333 333 '''
334 334
335 335 f = RCFile(filename)
336 336 self.dict_to_parms(f.data)
337 337 self.update_pulses()
338 338
339 339 def update_pulses(self):
340 340
341 341 for line in self.get_lines():
342 342 line.update_pulses()
343 343
344 344 def plot_pulses(self):
345 345
346 346 import matplotlib.pyplot as plt
347 347 from bokeh.resources import CDN
348 348 from bokeh.embed import components
349 349 from bokeh.mpl import to_bokeh
350 350 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, PreviewSaveTool
351 351
352 352 lines = self.get_lines()
353 353
354 354 N = len(lines)
355 355 fig = plt.figure(figsize=(10, 2+N*0.5))
356 356 ax = fig.add_subplot(111)
357 357 labels = []
358 358
359 359 for i, line in enumerate(lines):
360 360 labels.append(line.get_name())
361 361 l = ax.plot((0, self.total_units),(N-i-1, N-i-1))
362 362 points = [(tup[0], tup[1]-tup[0]) for tup in line.pulses_as_points() if tup<>(0,0)]
363 363 ax.broken_barh(points, (N-i-1, 0.5),
364 364 edgecolor=l[0].get_color(), facecolor='none')
365 365
366 366 labels.reverse()
367 367 ax.set_yticklabels(labels)
368 368 ax.set_xlabel = 'Units'
369 369 plot = to_bokeh(fig, use_pandas=False)
370 370 plot.tools = [PanTool(dimensions=['width']), WheelZoomTool(dimensions=['width']), ResetTool(), PreviewSaveTool()]
371 371
372 372 return components(plot, CDN)
373 373
374 374 def status_device(self):
375 375
376 376 return 0
377 377
378 378 def stop_device(self):
379 379
380 380 answer = api.disable(ip = self.device.ip_address,
381 381 port = self.device.port_address)
382 382
383 383 if answer[0] != "1":
384 384 self.message = answer[0:]
385 385 return 0
386 386
387 387 self.message = answer[2:]
388 388 return 1
389 389
390 390 def start_device(self):
391 391
392 392 answer = api.enable(ip = self.device.ip_address,
393 393 port = self.device.port_address)
394 394
395 395 if answer[0] != "1":
396 396 self.message = answer[0:]
397 397 return 0
398 398
399 399 self.message = answer[2:]
400 400 return 1
401 401
402 402 def write_device(self):
403 403 answer = api.write_config(ip = self.device.ip_address,
404 404 port = self.device.port_address,
405 405 parms = self.parms_to_dict())
406 406
407 407 if answer[0] != "1":
408 408 self.message = answer[0:]
409 409 return 0
410 410
411 411 self.message = answer[2:]
412 412 return 1
413 413
414 414
415 415 class RCLineCode(models.Model):
416 416
417 417 name = models.CharField(max_length=40)
418 418 bits_per_code = models.PositiveIntegerField(default=0)
419 419 number_of_codes = models.PositiveIntegerField(default=0)
420 420 codes = models.TextField(blank=True, null=True)
421 421
422 422 class Meta:
423 423 db_table = 'rc_line_codes'
424 424 ordering = ('name',)
425 425
426 426 def __unicode__(self):
427 427 return u'%s' % self.name
428 428
429 429
430 430 class RCLineType(models.Model):
431 431
432 432 name = models.CharField(choices=LINE_TYPES, max_length=40)
433 433 description = models.TextField(blank=True, null=True)
434 434 params = models.TextField(default='[]')
435 435
436 436 class Meta:
437 437 db_table = 'rc_line_types'
438 438
439 439 def __unicode__(self):
440 440 return u'%s - %s' % (self.name.upper(), self.get_name_display())
441 441
442 442
443 443 class RCLine(models.Model):
444 444
445 445 rc_configuration = models.ForeignKey(RCConfiguration, on_delete=models.CASCADE)
446 446 line_type = models.ForeignKey(RCLineType)
447 447 channel = models.PositiveIntegerField(default=0)
448 448 position = models.PositiveIntegerField(default=0)
449 449 params = models.TextField(default='{}')
450 450 pulses = models.TextField(default='')
451 451
452 452 class Meta:
453 453 db_table = 'rc_lines'
454 454 ordering = ['channel']
455 455
456 456 def __unicode__(self):
457 457 if self.rc_configuration:
458 458 return u'%s - %s' % (self.rc_configuration, self.get_name())
459 459
460 460 def clone(self, **kwargs):
461 461
462 462 self.pk = None
463 463
464 464 for attr, value in kwargs.items():
465 465 setattr(self, attr, value)
466 466
467 467 self.save()
468 468
469 469 return self
470 470
471 471 def get_name(self):
472 472
473 473 chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
474 474 s = ''
475 475
476 476 if self.line_type.name in ('tx',):
477 477 s = chars[self.position]
478 478 elif self.line_type.name in ('codes', 'windows', 'tr'):
479 479 if 'TX_ref' in json.loads(self.params):
480 480 pk = json.loads(self.params)['TX_ref']
481 481 if pk in (0, '0'):
482 482 s = ','.join(chars[l.position] for l in self.rc_configuration.get_lines(line_type__name='tx'))
483 483 else:
484 484 ref = RCLine.objects.get(pk=pk)
485 485 s = chars[ref.position]
486 486 s = '({})'.format(s)
487 487 if s:
488 488 return '{}{} {}'.format(self.line_type.name.upper(), s, self.channel)
489 489 else:
490 490 return '{} {}'.format(self.line_type.name.upper(), self.channel)
491 491
492 492 def get_lines(self, **kwargs):
493 493
494 494 return RCLine.objects.filter(rc_configuration=self.rc_configuration, **kwargs)
495 495
496 496 def pulses_as_array(self):
497 497
498 498 y = np.zeros(self.rc_configuration.total_units)
499 499
500 500 for tup in ast.literal_eval(self.pulses):
501 501 y[tup[0]:tup[1]] = 1
502 502
503 503 return y.astype(np.int8)
504 504
505 505 def pulses_as_points(self):
506 506
507 507 return ast.literal_eval(self.pulses)
508 508
509 509 def get_win_ref(self, params, tx_id, km2unit):
510 510
511 511 ref = self.rc_configuration.sampling_reference
512 512 codes = [line for line in self.get_lines(line_type__name='codes') if int(json.loads(line.params)['TX_ref'])==int(tx_id)]
513 513
514 514 if codes:
515 515 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit/len(json.loads(codes[0].params)['codes'][0])
516 516 else:
517 517 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit
518 518
519 519 if ref=='first_baud':
520 520 return int(1 + (tx_width + 1)/2 + params['first_height']*km2unit - params['resolution']*km2unit)
521 521 elif ref=='sub_baud':
522 522 return int(1 + params['first_height']*km2unit - params['resolution']*km2unit/2)
523 523 else:
524 524 return 0
525 525
526 526 def update_pulses(self):
527 527 '''
528 528 Update pulses field
529 529 '''
530 530
531 531 km2unit = self.rc_configuration.km2unit
532 532 us2unit = self.rc_configuration.us2unit
533 533 ipp = self.rc_configuration.ipp
534 534 ntx = self.rc_configuration.ntx
535 535 ipp_u = int(ipp*km2unit)
536 536 total = ipp_u*ntx if self.rc_configuration.total_units==0 else self.rc_configuration.total_units
537 537 y = []
538 538
539 539 if self.line_type.name=='tr':
540 540 tr_params = json.loads(self.params)
541 541
542 542 if tr_params['TX_ref'] in ('0', 0):
543 543 txs = self.get_lines(line_type__name='tx')
544 544 else:
545 545 txs = RCLine.objects.filter(pk=tr_params['TX_ref'])
546 546
547 547 for tx in txs:
548 548 params = json.loads(tx.params)
549 549
550 550 if float(params['pulse_width'])==0:
551 551 continue
552 552 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
553 553 width = float(params['pulse_width'])*km2unit+int(self.rc_configuration.time_before*us2unit)
554 554 before = 0
555 555 after = int(self.rc_configuration.time_after*us2unit)
556 556
557 557 y_tx = self.points(ntx, ipp_u, width,
558 558 delay=delays,
559 559 before=before,
560 560 after=after,
561 561 sync=self.rc_configuration.sync)
562 562
563 563 ranges = params['range'].split(',')
564 564
565 565 if len(ranges)>0 and ranges[0]<>'0':
566 566 y_tx = self.mask_ranges(y_tx, ranges)
567 567
568 568 tr_ranges = tr_params['range'].split(',')
569 569
570 570 if len(tr_ranges)>0 and tr_ranges[0]<>'0':
571 571 y_tx = self.mask_ranges(y_tx, tr_ranges)
572 572
573 573 y.extend(y_tx)
574 574
575 575 self.pulses = unicode(y)
576 576 y = self.array_to_points(self.pulses_as_array())
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.get(pk=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(confs[0].total_units, 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 modes[i]=='P':
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 elif delay+len(Y)<len(y):
702 702 y_temp = np.zeros(len(y), dtype=np.int8)
703 703 y_temp[delay:delay+len(Y)] = Y
704 704
705 705 if ops[i]=='OR':
706 706 y = y | y_temp
707 707 elif ops[i]=='XOR':
708 708 y = y ^ y_temp
709 709 elif ops[i]=='AND':
710 710 y = y & y_temp
711 711 elif ops[i]=='NAND':
712 712 y = y & ~y_temp
713 713 else:
714 714 y = np.concatenate([y, Y])
715 715
716 716 total = len(y)
717 717 y = self.array_to_points(y)
718 718
719 719 else:
720 720 y = []
721 721
722 722 if self.rc_configuration.total_units <> total:
723 723 self.rc_configuration.total_units = total
724 724 self.rc_configuration.save()
725 725
726 726 self.pulses = unicode(y)
727 727 self.save()
728 728
729 729 @staticmethod
730 730 def array_to_points(X):
731 731
732 732 d = X[1:]-X[:-1]
733 733
734 734 up = np.where(d==1)[0]
735 735 if X[0]==1:
736 736 up = np.concatenate((np.array([-1]), up))
737 737 up += 1
738 738
739 739 dw = np.where(d==-1)[0]
740 740 if X[-1]==1:
741 741 dw = np.concatenate((dw, np.array([len(X)-1])))
742 742 dw += 1
743 743
744 744 return [(tup[0], tup[1]) for tup in zip(up, dw)]
745 745
746 746 @staticmethod
747 747 def mask_ranges(Y, ranges):
748 748
749 749 y = [(0, 0) for __ in Y]
750 750
751 751 for index in ranges:
752 752 if '-' in index:
753 753 args = [int(a) for a in index.split('-')]
754 754 y[args[0]-1:args[1]] = Y[args[0]-1:args[1]]
755 755 else:
756 756 y[int(index-1)] = Y[int(index-1)]
757 757
758 758 return y
759 759
760 760 @staticmethod
761 761 def points(ntx, ipp, width, delay=[0], before=0, after=0, sync=0):
762 762
763 763 delays = len(delay)
764 764
765 765 Y = [(ipp*x+before+delay[x%delays], ipp*x+width+before+delay[x%delays]+after) for x in range(ntx)]
766 766
767 767 return Y No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now