##// END OF EJS Templates
Optimize pulses's plot and generation ...
Juan C. Espinoza -
r111:e02ef9acb4e3
parent child
Show More
@@ -23,4 +23,5
23 {"fields": {"params": "{\"invert\":{\"value\": 0, \"help\": \"Set to 1 for synchro pulse at the end\"}}", "name": "sync", "description": ""}, "model": "rc.rclinetype", "pk": 5},
23 {"fields": {"params": "{\"invert\":{\"value\": 0, \"help\": \"Set to 1 for synchro pulse at the end\"}}", "name": "sync", "description": ""}, "model": "rc.rclinetype", "pk": 5},
24 {"fields": {"params": "{ \"periodic\": { \"value\": 0, \"help\": \"Set to 1 for IPP periodic\"}, \"params\": {\"begin\": { \"value\": 0, \"widget\":\"unit\"}, \"end\": {\"value\": 0, \"widget\":\"unit\"}}}", "name": "prog_pulses", "description": ""}, "model": "rc.rclinetype", "pk": 6},
24 {"fields": {"params": "{ \"periodic\": { \"value\": 0, \"help\": \"Set to 1 for IPP periodic\"}, \"params\": {\"begin\": { \"value\": 0, \"widget\":\"unit\"}, \"end\": {\"value\": 0, \"widget\":\"unit\"}}}", "name": "prog_pulses", "description": ""}, "model": "rc.rclinetype", "pk": 6},
25 {"fields": {"params": "{\"number_of_flips\": {\"value\": 0}}", "name": "flip", "description": ""}, "model": "rc.rclinetype", "pk": 7},
25 {"fields": {"params": "{\"number_of_flips\": {\"value\": 0}}", "name": "flip", "description": ""}, "model": "rc.rclinetype", "pk": 7},
26 {"fields": {"params": "{}", "name": "none", "description": ""}, "model": "rc.rclinetype", "pk": 8}]
26 {"fields": {"params": "{}", "name": "none", "description": ""}, "model": "rc.rclinetype", "pk": 8},
27 {"fields": {"params": "{}", "name": "mix", "description": ""}, "model": "rc.rclinetype", "pk": 9}] No newline at end of file
@@ -78,7 +78,7 class RCConfigurationForm(forms.ModelForm):
78
78
79 class Meta:
79 class Meta:
80 model = RCConfiguration
80 model = RCConfiguration
81 exclude = ('type', 'parameters', 'status')
81 exclude = ('type', 'parameters', 'status', 'mix')
82
82
83 def clean(self):
83 def clean(self):
84 form_data = super(RCConfigurationForm, self).clean()
84 form_data = super(RCConfigurationForm, self).clean()
@@ -11,7 +11,7 from django.core.validators import MinValueValidator, MaxValueValidator
11
11
12 from apps.main.models import Configuration
12 from apps.main.models import Configuration
13 from devices.rc import api
13 from devices.rc import api
14 from .utils import RCFile, pulses, pulses_from_code, create_mask, pulses_to_points
14 from .utils import RCFile
15
15
16 # Create your models here.
16 # Create your models here.
17
17
@@ -123,7 +123,7 class RCConfiguration(Configuration):
123 '''
123 '''
124 '''
124 '''
125
125
126 empty_line = RCLineType.objects.get(pk=8)
126 empty_line = RCLineType.objects.get(name='none')
127
127
128 for line in self.get_lines():
128 for line in self.get_lines():
129 line.line_type = empty_line
129 line.line_type = empty_line
@@ -134,12 +134,15 class RCConfiguration(Configuration):
134 '''
134 '''
135 '''
135 '''
136
136
137 ignored = ('parameters', 'type', 'polymorphic_ctype', 'configuration_ptr',
138 'created_date', 'programmed_date')
139
137 data = {}
140 data = {}
138 for field in self._meta.fields:
141 for field in self._meta.fields:
139
142 if field.name in ignored:
143 continue
140 data[field.name] = '{}'.format(field.value_from_object(self))
144 data[field.name] = '{}'.format(field.value_from_object(self))
141
145
142 data.pop('parameters')
143 data['lines'] = []
146 data['lines'] = []
144
147
145 for line in self.get_lines():
148 for line in self.get_lines():
@@ -214,7 +217,7 class RCConfiguration(Configuration):
214
217
215 def get_delays(self):
218 def get_delays(self):
216
219
217 pulses = [line.get_pulses() for line in self.get_lines()]
220 pulses = [line.pulses_as_points() for line in self.get_lines()]
218 points = [tup for tups in pulses for tup in tups]
221 points = [tup for tups in pulses for tup in tups]
219 points = set([x for tup in points for x in tup])
222 points = set([x for tup in points for x in tup])
220 points = list(points)
223 points = list(points)
@@ -228,13 +231,13 class RCConfiguration(Configuration):
228
231
229 def get_pulses(self, binary=True):
232 def get_pulses(self, binary=True):
230
233
231 pulses = [line.get_pulses() for line in self.get_lines()]
234 pulses = [line.pulses_as_points() for line in self.get_lines()]
232 points = [tup for tups in pulses for tup in tups]
235 points = [tup for tups in pulses for tup in tups]
233 points = set([x for tup in points for x in tup])
236 points = set([x for tup in points for x in tup])
234 points = list(points)
237 points = list(points)
235 points.sort()
238 points.sort()
236
239
237 line_points = [pulses_to_points(line.pulses_as_array()) for line in self.get_lines()]
240 line_points = [line.pulses_as_points() for line in self.get_lines()]
238 line_points = [[(x, x+y) for x,y in tups] for tups in line_points]
241 line_points = [[(x, x+y) for x,y in tups] for tups in line_points]
239 line_points = [[t for x in tups for t in x] for tups in line_points]
242 line_points = [[t for x in tups for t in x] for tups in line_points]
240 states = [[1 if x in tups else 0 for tups in line_points] for x in points]
243 states = [[1 if x in tups else 0 for tups in line_points] for x in points]
@@ -330,16 +333,44 class RCConfiguration(Configuration):
330
333
331 f = RCFile(filename)
334 f = RCFile(filename)
332 self.dict_to_parms(f.data)
335 self.dict_to_parms(f.data)
336 self.update_pulses()
337 self.save()
333
338
334 def update_pulses(self):
339 def update_pulses(self):
335
340
336 for line in self.get_lines():
341 for line in self.get_lines():
337 if line.line_type.name=='tr':
338 continue
339 line.update_pulses()
342 line.update_pulses()
343
344 def plot_pulses(self):
345
346 import matplotlib.pyplot as plt
347 from bokeh.resources import CDN
348 from bokeh.embed import components
349 from bokeh.mpl import to_bokeh
350 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, PreviewSaveTool
351
352 lines = self.get_lines()
340
353
341 for tr in self.get_lines(line_type__name='tr'):
354 max_value = self.ipp*self.km2unit*self.ntx
342 tr.update_pulses()
355
356 N = len(lines)
357 fig = plt.figure(figsize=(10, 2+N*0.5))
358 ax = fig.add_subplot(111)
359 labels = []
360
361 for i, line in enumerate(lines):
362 labels.append(line.get_name())
363 l = ax.plot((0, max_value),(N-i-1, N-i-1))
364 points = [(tup[0], tup[1]-tup[0]) for tup in line.pulses_as_points() if tup<>(0,0)]
365 ax.broken_barh(points, (N-i-1, 0.5),
366 edgecolor=l[0].get_color(), facecolor='none')
367
368 labels.reverse()
369 ax.set_yticklabels(labels)
370 plot = to_bokeh(fig, use_pandas=False)
371 plot.tools = [PanTool(dimensions=['width']), WheelZoomTool(dimensions=['width']), ResetTool(), PreviewSaveTool()]
372
373 return components(plot, CDN)
343
374
344 def status_device(self):
375 def status_device(self):
345
376
@@ -441,23 +472,23 class RCLine(models.Model):
441 def get_name(self):
472 def get_name(self):
442
473
443 chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
474 chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
475 s = ''
444
476
445 if self.line_type.name in ('tx',):
477 if self.line_type.name in ('tx',):
446 return '%s%s' % (self.line_type.name.upper(), chars[self.position])
478 s = chars[self.position]
447 elif self.line_type.name in ('codes', 'windows', 'tr'):
479 elif self.line_type.name in ('codes', 'windows', 'tr'):
448 if 'TX_ref' not in json.loads(self.params):
480 if 'TX_ref' in json.loads(self.params):
449 return self.line_type.name.upper()
481 pk = json.loads(self.params)['TX_ref']
450 pk = json.loads(self.params)['TX_ref']
482 if pk in (0, '0'):
451 if pk in (0, '0'):
483 s = ','.join(chars[l.position] for l in self.rc_configuration.get_lines(line_type__name='tx'))
452 refs = ','.join(chars[l.position] for l in self.rc_configuration.get_lines(line_type__name='tx'))
484 else:
453 return '%s (%s)' % (self.line_type.name.upper(), refs)
485 ref = RCLine.objects.get(pk=pk)
454 else:
486 s = chars[ref.position]
455 ref = RCLine.objects.get(pk=pk)
487
456 return '%s (%s)' % (self.line_type.name.upper(), chars[ref.position])
488 if s:
457 elif self.line_type.name in ('flip', 'prog_pulses', 'sync', 'none', 'mix'):
489 return '{}({}) {}'.format(self.line_type.name.upper(), s, self.channel)
458 return '%s %s' % (self.line_type.name.upper(), self.channel)
459 else:
490 else:
460 return self.line_type.name.upper()
491 return '{} {}'.format(self.line_type.name.upper(), self.channel)
461
492
462 def get_lines(self, **kwargs):
493 def get_lines(self, **kwargs):
463
494
@@ -465,25 +496,16 class RCLine(models.Model):
465
496
466 def pulses_as_array(self):
497 def pulses_as_array(self):
467
498
468 return (np.fromstring(self.pulses, dtype=np.uint8)-48).astype(np.int8)
499 y = np.zeros(self.rc_configuration.ntx*self.rc_configuration.ipp*self.rc_configuration.km2unit)
469
470 def get_pulses(self):
471
472 X = self.pulses_as_array()
473
500
474 d = X[1:]-X[:-1]
501 for tup in ast.literal_eval(self.pulses):
502 y[tup[0]:tup[1]] = 1
503
504 return y.astype(np.int8)
475
505
476 up = np.where(d==1)[0]
506 def pulses_as_points(self):
477 if X[0]==1:
478 up = np.concatenate((np.array([-1]), up))
479 up += 1
480
507
481 dw = np.where(d==-1)[0]
508 return ast.literal_eval(self.pulses)
482 if X[-1]==1:
483 dw = np.concatenate((dw, np.array([len(X)-1])))
484 dw += 1
485
486 return [(tup[0], tup[1]) for tup in zip(up, dw)]
487
509
488 def get_win_ref(self, params, tx_id, km2unit):
510 def get_win_ref(self, params, tx_id, km2unit):
489
511
@@ -502,7 +524,7 class RCLine(models.Model):
502 else:
524 else:
503 return 0
525 return 0
504
526
505 def update_pulses(self, save=True, tr=False):
527 def update_pulses(self):
506 '''
528 '''
507 Update pulses field
529 Update pulses field
508 '''
530 '''
@@ -513,93 +535,128 class RCLine(models.Model):
513 ntx = self.rc_configuration.ntx
535 ntx = self.rc_configuration.ntx
514 ipp_u = int(ipp*km2unit)
536 ipp_u = int(ipp*km2unit)
515
537
516 x = np.arange(0, ipp_u*ntx)
538 y = []
517
539
518 if self.line_type.name=='tr':
540 if self.line_type.name=='tr':
519 params = json.loads(self.params)
541 tr_params = json.loads(self.params)
520 if params['TX_ref'] in ('0', 0):
542
521 txs = [tx.update_pulses(save=False, tr=True) for tx in self.get_lines(line_type__name='tx')]
543 if tr_params['TX_ref'] in ('0', 0):
544 txs = self.get_lines(line_type__name='tx')
522 else:
545 else:
523 txs = [tx.update_pulses(save=False, tr=True) for tx in RCLine.objects.filter(pk=params['TX_ref'])]
546 txs = [RCLine.objects.filter(pk=tr_params['TX_ref'])]
524 if len(txs)==0 or 0 in [len(tx) for tx in txs]:
525 return
526
547
527 y = np.any(txs, axis=0, out=np.ones(ipp_u*ntx))
548 for tx in txs:
528
549 params = json.loads(tx.params)
529 ranges = params['range'].split(',')
550 if float(params['pulse_width'])==0:
530 if len(ranges)>0 and ranges[0]<>'0':
551 continue
531 mask = create_mask(ranges, ipp_u, ntx, self.rc_configuration.sync)
552 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
532 y = y.astype(np.int8) & mask
553 width = float(params['pulse_width'])*km2unit+int(self.rc_configuration.time_before*us2unit)
554 before = 0
555 after = int(self.rc_configuration.time_after*us2unit)
556
557 y_tx = self.points(ntx, ipp_u, width,
558 delay=delays,
559 before=before,
560 after=after,
561 sync=self.rc_configuration.sync)
562
563 ranges = params['range'].split(',')
564
565 if len(ranges)>0 and ranges[0]<>'0':
566 y_tx = self.mask_ranges(y_tx, ranges)
567
568 tr_ranges = tr_params['range'].split(',')
569
570 if len(tr_ranges)>0 and tr_ranges[0]<>'0':
571 y_tx = self.mask_ranges(y_tx, tr_ranges)
572
573 y.extend(y_tx)
533
574
534 elif self.line_type.name=='tx':
575 elif self.line_type.name=='tx':
535 params = json.loads(self.params)
576 params = json.loads(self.params)
536 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
577 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
537 y = pulses(x, ipp_u, float(params['pulse_width'])*km2unit,
578 width = float(params['pulse_width'])*km2unit
538 delay=delays,
539 before=int(self.rc_configuration.time_before*us2unit),
540 after=int(self.rc_configuration.time_after*us2unit) if tr else 0,
541 sync=self.rc_configuration.sync)
542
543 ranges = params['range'].split(',')
544
579
545 if len(ranges)>0 and ranges[0]<>'0':
580 if width>0:
546 mask = create_mask(ranges, ipp_u, ntx, self.rc_configuration.sync)
581 before = int(self.rc_configuration.time_before*us2unit)
547 y = y & mask
582 after = 0
583
584 y = self.points(ntx, ipp_u, width,
585 delay=delays,
586 before=before,
587 after=after,
588 sync=self.rc_configuration.sync)
589
590 ranges = params['range'].split(',')
591
592 if len(ranges)>0 and ranges[0]<>'0':
593 y = self.mask_ranges(y, ranges)
548
594
549 elif self.line_type.name=='flip':
595 elif self.line_type.name=='flip':
550 width = float(json.loads(self.params)['number_of_flips'])*ipp*km2unit
596 n = float(json.loads(self.params)['number_of_flips'])
551 y = pulses(x, 2*width, width)
597 width = n*ipp*km2unit
598 y = self.points(int((ntx+1)/(2*n)), ipp_u*n*2, width)
552
599
553 elif self.line_type.name=='codes':
600 elif self.line_type.name=='codes':
554 params = json.loads(self.params)
601 params = json.loads(self.params)
555 tx = RCLine.objects.get(pk=params['TX_ref'])
602 tx = RCLine.objects.get(pk=params['TX_ref'])
556 tx_params = json.loads(tx.params)
603 tx_params = json.loads(tx.params)
557 delays = [float(d)*km2unit for d in tx_params['delays'].split(',') if d]
604 delays = [float(d)*km2unit for d in tx_params['delays'].split(',') if d]
558 y = pulses_from_code(tx.pulses_as_array(),
605 f = int(float(tx_params['pulse_width'])*km2unit)/len(params['codes'][0])
559 params['codes'],
606 codes = [(np.fromstring(''.join([s*f for s in code]), dtype=np.uint8)-48).astype(np.int8) for code in params['codes']]
560 int(float(tx_params['pulse_width'])*km2unit))
607 codes = [self.array_to_points(code) for code in codes]
608 n = len(codes)
561
609
610 for i, tup in enumerate(tx.pulses_as_points()):
611 code = codes[i%n]
612 y.extend([(c[0]+tup[0], c[1]+tup[0]) for c in code])
613
562 ranges = tx_params['range'].split(',')
614 ranges = tx_params['range'].split(',')
563 if len(ranges)>0 and ranges[0]<>'0':
615 if len(ranges)>0 and ranges[0]<>'0':
564 mask = create_mask(ranges, ipp_u, ntx, self.rc_configuration.sync)
616 y = self.mask_ranges(y, ranges)
565 y = y.astype(np.int8) & mask
566
617
567 elif self.line_type.name=='sync':
618 elif self.line_type.name=='sync':
568 params = json.loads(self.params)
619 params = json.loads(self.params)
569 y = np.zeros(ipp_u*ntx)
620 n = ipp_u*ntx
570 if params['invert'] in ('1', 1):
621 if params['invert'] in ('1', 1):
571 y[-1] = 1
622 y = [(n-1, n)]
572 else:
623 else:
573 y[0] = 1
624 y = [(0, 1)]
574
625
575 elif self.line_type.name=='prog_pulses':
626 elif self.line_type.name=='prog_pulses':
576 params = json.loads(self.params)
627 params = json.loads(self.params)
577 if int(params['periodic'])==0:
628 if int(params['periodic'])==0:
578 nntx = ntx
579 else:
580 nntx = 1
629 nntx = 1
630 nipp = ipp_u*ntx
631 else:
632 nntx = ntx
633 nipp = ipp_u
581
634
582 if 'params' in params and len(params['params'])>0:
635 if 'params' in params and len(params['params'])>0:
583 y = sum([pulses(x, ipp_u*nntx, (pp['end']-pp['begin']), shift=pp['begin']) for pp in params['params']])
636 for p in params['params']:
584 else:
637 y_pp = self.points(nntx, nipp,
585 y = np.zeros(ipp_u*ntx)
638 p['end']-p['begin'],
586
639 before=p['begin'])
640
641 y.extend(y_pp)
642
587 elif self.line_type.name=='windows':
643 elif self.line_type.name=='windows':
588 params = json.loads(self.params)
644 params = json.loads(self.params)
589
645
590 if 'params' in params and len(params['params'])>0:
646 if 'params' in params and len(params['params'])>0:
591 y = sum([pulses(x, ipp_u, pp['resolution']*pp['number_of_samples']*km2unit,
647 tr_params = json.loads(self.get_lines(line_type__name='tr')[0].params)
592 shift=0,
648 tr_ranges = tr_params['range'].split(',')
593 before=int(self.rc_configuration.time_before*us2unit)+self.get_win_ref(pp, params['TX_ref'],km2unit),
649 for p in params['params']:
594 sync=self.rc_configuration.sync) for pp in params['params']])
650 y_win = self.points(ntx, ipp_u,
595 tr = self.get_lines(line_type__name='tr')[0]
651 p['resolution']*p['number_of_samples']*km2unit,
596 ranges = json.loads(tr.params)['range'].split(',')
652 before=int(self.rc_configuration.time_before*us2unit)+self.get_win_ref(p, params['TX_ref'], km2unit),
597 if len(ranges)>0 and ranges[0]<>'0':
653 sync=self.rc_configuration.sync)
598 mask = create_mask(ranges, ipp_u, ntx, self.rc_configuration.sync)
654
599 y = y & mask
655 if len(tr_ranges)>0 and tr_ranges[0]<>'0':
600 else:
656 y_win = self.mask_ranges(y_win, tr_ranges)
601 y = np.zeros(ipp_u*ntx)
657
602
658 y.extend(y_win)
659
603 elif self.line_type.name=='mix':
660 elif self.line_type.name=='mix':
604 values = self.rc_configuration.parameters.split('-')
661 values = self.rc_configuration.parameters.split('-')
605 confs = RCConfiguration.objects.filter(pk__in=[value.split('|')[0] for value in values])
662 confs = RCConfiguration.objects.filter(pk__in=[value.split('|')[0] for value in values])
@@ -608,7 +665,7 class RCLine(models.Model):
608 masks = [value.split('|')[3] for value in values]
665 masks = [value.split('|')[3] for value in values]
609
666
610 y = confs[0].get_lines(channel=self.channel)[0].pulses_as_array()
667 y = confs[0].get_lines(channel=self.channel)[0].pulses_as_array()
611
668 ysize = len(y)
612 for i in range(1, len(values)):
669 for i in range(1, len(values)):
613 mask = list('{:8b}'.format(int(masks[i])))
670 mask = list('{:8b}'.format(int(masks[i])))
614 mask.reverse()
671 mask.reverse()
@@ -621,25 +678,60 class RCLine(models.Model):
621 y_temp = np.empty_like(Y)
678 y_temp = np.empty_like(Y)
622 y_temp[:delay] = 0
679 y_temp[:delay] = 0
623 y_temp[delay:] = Y[:-delay]
680 y_temp[delay:] = Y[:-delay]
624
681 y_tempsize = len(y_temp)
625 if modes[i]=='OR':
682 if modes[i]=='OR':
626 y2 = y | y_temp
683 y = y | y_temp
627 elif modes[i]=='XOR':
684 elif modes[i]=='XOR':
628 y2 = y ^ y_temp
685 y = y ^ y_temp
629 elif modes[i]=='AND':
686 elif modes[i]=='AND':
630 y2 = y & y_temp
687 y = y & y_temp
631 elif modes[i]=='NAND':
688 elif modes[i]=='NAND':
632 y2 = y & ~y_temp
689 y = y & ~y_temp
633
690
634 y = y2
691 y = self.array_to_points(y)
635
692
636 else:
693 else:
637 y = np.zeros(ipp_u*ntx)
694 y = []
638
695
639 if save:
696 self.pulses = y
640 self.pulses = (y+48).astype(np.uint8).tostring()
697 self.save()
641 self.save()
698
642 else:
699 @staticmethod
643 return y
700 def array_to_points(X):
701
702 d = X[1:]-X[:-1]
703
704 up = np.where(d==1)[0]
705 if X[0]==1:
706 up = np.concatenate((np.array([-1]), up))
707 up += 1
708
709 dw = np.where(d==-1)[0]
710 if X[-1]==1:
711 dw = np.concatenate((dw, np.array([len(X)-1])))
712 dw += 1
713
714 return [(tup[0], tup[1]) for tup in zip(up, dw)]
715
716 @staticmethod
717 def mask_ranges(Y, ranges):
718
719 y = [(0, 0) for __ in Y]
720
721 for index in ranges:
722 if '-' in index:
723 args = [int(a) for a in index.split('-')]
724 y[args[0]-1:args[1]] = Y[args[0]-1:args[1]]
725 else:
726 y[int(index-1)] = Y[int(index-1)]
727
728 return y
729
730 @staticmethod
731 def points(ntx, ipp, width, delay=[0], before=0, after=0, sync=0):
732
733 delays = len(delay)
734
735 Y = [(ipp*x+before+delay[x%delays], ipp*x+width+before+delay[x%delays]+after) for x in range(ntx)]
644
736
645 No newline at end of file
737 return Y No newline at end of file
@@ -4,7 +4,7 urlpatterns = (
4 url(r'^(?P<conf_id>-?\d+)/$', 'apps.rc.views.conf', name='url_rc_conf'),
4 url(r'^(?P<conf_id>-?\d+)/$', 'apps.rc.views.conf', name='url_rc_conf'),
5 url(r'^(?P<conf_id>-?\d+)/import/$', 'apps.rc.views.import_file', name='url_import_rc_conf'),
5 url(r'^(?P<conf_id>-?\d+)/import/$', 'apps.rc.views.import_file', name='url_import_rc_conf'),
6 url(r'^(?P<conf_id>-?\d+)/edit/$', 'apps.rc.views.conf_edit', name='url_edit_rc_conf'),
6 url(r'^(?P<conf_id>-?\d+)/edit/$', 'apps.rc.views.conf_edit', name='url_edit_rc_conf'),
7 url(r'^(?P<conf_id>-?\d+)/plot/$', 'apps.rc.views.view_pulses', name='url_plot_rc_pulses'),
7 url(r'^(?P<conf_id>-?\d+)/plot/$', 'apps.rc.views.plot_pulses', name='url_plot_rc_pulses'),
8 url(r'^(?P<id_conf>-?\d+)/write/$', 'apps.main.views.dev_conf_write', name='url_write_rc_conf'),
8 url(r'^(?P<id_conf>-?\d+)/write/$', 'apps.main.views.dev_conf_write', name='url_write_rc_conf'),
9 url(r'^(?P<id_conf>-?\d+)/read/$', 'apps.main.views.dev_conf_read', name='url_read_rc_conf'),
9 url(r'^(?P<id_conf>-?\d+)/read/$', 'apps.main.views.dev_conf_read', name='url_read_rc_conf'),
10
10
@@ -1,8 +1,5
1
1
2 import json
2 import json
3 import numpy as np
4 import matplotlib.pyplot as plt
5
6
3
7 class RCFile(object):
4 class RCFile(object):
8 '''
5 '''
@@ -207,109 +204,3 class RCFile(object):
207 return json.dumps(self.data, indent=indent)
204 return json.dumps(self.data, indent=indent)
208
205
209
206
210 def pulses_to_points(X):
211
212
213 d = X[1:]-X[:-1]
214
215 up = np.where(d==1)[0]
216 if X[0]==1:
217 up = np.concatenate((np.array([-1]), up))
218 up += 1
219
220 dw = np.where(d==-1)[0]
221 if X[-1]==1:
222 dw = np.concatenate((dw, np.array([len(X)-1])))
223 dw += 1
224
225 return [(tup[0], tup[1]-tup[0]) for tup in zip(up, dw)]
226
227 def pulses_from_code(X, codes, width):
228
229 d = X[1:]-X[:-1]
230
231 up = np.where(d==1)[0]
232 if X[0]==1:
233 up = np.concatenate((np.array([-1]), up))
234 up += 1
235
236 f = width/len(codes[0])
237 codes = [(np.fromstring(''.join([s*f for s in code]), dtype=np.uint8)-48).astype(np.int8) for code in codes]
238
239 y = np.zeros(len(X))
240
241 j=0
242 n = len(codes)
243 for i in up:
244 y[i:i+width] = codes[j%n]
245 j += 1
246
247 return y
248
249
250 def create_mask(ranges, ipp, ntx, sync):
251
252 x = np.arange(ipp*ntx)
253 iranges = set()
254
255 for index in ranges:
256 if '-' in index:
257 args = [int(a) for a in index.split('-')]
258 iranges = iranges.union([i for i in range(args[0], args[1]+1)])
259 else:
260 iranges.add(int(index))
261
262 y = np.any([(x>=(idx-1)*ipp+sync) & (x<idx*ipp+sync) for idx in iranges], axis=0).astype(np.int8)
263
264 return y
265
266
267 def pulses(X, period, width, delay=0, before=0, after=0, sync=0, shift=0):
268
269 delay_array = delay
270
271 if isinstance(delay, (list, tuple)):
272 delay_array = np.ones(len(X))
273 delays = [d for __ in xrange(len(X)/(period*len(delay))) for d in delay]
274 for i, delay in enumerate(delays):
275 delay_array[np.arange(period*i, period*(i+1))] *= delay
276
277 if after>0:
278 width += after+before
279 before = 0
280
281 Y = ((X%period<width+delay_array+before+sync) & (X%period>=delay_array+before+sync)).astype(np.int8)
282
283 if shift>0:
284 y = np.empty_like(Y)
285 y[:shift] = 0
286 y[shift:] = Y[:-shift]
287 return y
288 else:
289 return Y
290
291
292 def plot_pulses(unit, maximun, lines):
293
294 from bokeh.resources import CDN
295 from bokeh.embed import components
296 from bokeh.mpl import to_bokeh
297 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, PreviewSaveTool
298
299 N = len(lines)
300 fig = plt.figure(figsize=(10, 2+N*0.5))
301 ax = fig.add_subplot(111)
302 labels = []
303
304 for i, line in enumerate(lines):
305 labels.append(line.get_name())
306 l = ax.plot((0, maximun),(N-i-1, N-i-1))
307 ax.broken_barh(pulses_to_points(line.pulses_as_array()), (N-i-1, 0.5),
308 edgecolor=l[0].get_color(), facecolor='none')
309
310 labels.reverse()
311 ax.set_yticklabels(labels)
312 plot = to_bokeh(fig, use_pandas=False)
313 plot.tools = [PanTool(dimensions=['width']), WheelZoomTool(dimensions=['width']), ResetTool(), PreviewSaveTool()]
314
315 return components(plot, CDN)
@@ -10,7 +10,6 from apps.main.views import sidebar
10
10
11 from .models import RCConfiguration, RCLine, RCLineType, RCLineCode
11 from .models import RCConfiguration, RCLine, RCLineType, RCLineCode
12 from .forms import RCConfigurationForm, RCLineForm, RCLineViewForm, RCLineEditForm, RCImportForm, RCLineCodesForm
12 from .forms import RCConfigurationForm, RCLineForm, RCLineViewForm, RCLineEditForm, RCImportForm, RCLineCodesForm
13 from .utils import plot_pulses
14
13
15
14
16 def conf(request, conf_id):
15 def conf(request, conf_id):
@@ -329,25 +328,13 def import_file(request, conf_id):
329 if request.method=='POST':
328 if request.method=='POST':
330 form = RCImportForm(request.POST, request.FILES)
329 form = RCImportForm(request.POST, request.FILES)
331 if form.is_valid():
330 if form.is_valid():
332 #try:
331 try:
333 if True:
334
335 conf.update_from_file(request.FILES['file_name'])
332 conf.update_from_file(request.FILES['file_name'])
336 conf.save()
337
338 for line in conf.get_lines():
339 if line.line_type.name=='tr':
340 continue
341 line.update_pulses()
342
343 for tr in conf.get_lines('tr'):
344 tr.update_pulses()
345
346 messages.success(request, 'Configuration "%s" loaded succesfully' % request.FILES['file_name'])
333 messages.success(request, 'Configuration "%s" loaded succesfully' % request.FILES['file_name'])
347 return redirect(conf.get_absolute_url())
334 return redirect(conf.get_absolute_url_edit())
348
335
349 #except Exception as e:
336 except Exception as e:
350 # messages.error(request, 'Error parsing file: "%s" - %s' % (request.FILES['file_name'], e))
337 messages.error(request, 'Error parsing file: "%s" - %s' % (request.FILES['file_name'], e))
351
338
352 else:
339 else:
353 messages.warning(request, 'Your current configuration will be replaced')
340 messages.warning(request, 'Your current configuration will be replaced')
@@ -363,16 +350,11 def import_file(request, conf_id):
363 return render(request, 'rc_import.html', kwargs)
350 return render(request, 'rc_import.html', kwargs)
364
351
365
352
366 def view_pulses(request, conf_id):
353 def plot_pulses(request, conf_id):
367
354
368 conf = get_object_or_404(RCConfiguration, pk=conf_id)
355 conf = get_object_or_404(RCConfiguration, pk=conf_id)
369 lines = RCLine.objects.filter(rc_configuration=conf)
370
371 unit = (conf.clock/conf.clock_divider)*3./20
372
373 N = conf.ipp*conf.km2unit*conf.ntx
374
356
375 script, div = plot_pulses(unit, N, lines)
357 script, div = conf.plot_pulses()
376
358
377 kwargs = {}
359 kwargs = {}
378
360
@@ -380,6 +362,9 def view_pulses(request, conf_id):
380 kwargs['suptitle'] = conf.name
362 kwargs['suptitle'] = conf.name
381 kwargs['div'] = mark_safe(div)
363 kwargs['div'] = mark_safe(div)
382 kwargs['script'] = mark_safe(script)
364 kwargs['script'] = mark_safe(script)
383
365
384 return render(request, 'rc_pulses.html', kwargs)
366 if 'json' in request.GET:
367 return HttpResponse(json.dumps({'div':mark_safe(div), 'script':mark_safe(script)}), content_type="application/json")
368 else:
369 return render(request, 'rc_pulses.html', kwargs)
385
370
General Comments 0
You need to be logged in to leave comments. Login now