@@ -21,6 +21,14 | |||||
21 | document.location = "{% url 'url_delete_mix_experiment' id_exp %}"; |
|
21 | document.location = "{% url 'url_delete_mix_experiment' id_exp %}"; | |
22 | }); |
|
22 | }); | |
23 |
|
23 | |||
|
24 | $('input[type=radio][name=mode]').change(function() { | |||
|
25 | if (this.value == '0') { | |||
|
26 | $('input[type=radio][name=operation]').prop('disabled', false); | |||
|
27 | }else{ | |||
|
28 | $('input[type=radio][name=operation]').prop('disabled', true); | |||
|
29 | } | |||
|
30 | }); | |||
|
31 | ||||
24 | </script> |
|
32 | </script> | |
25 |
|
33 | |||
26 | {% endblock %} No newline at end of file |
|
34 | {% endblock %} |
@@ -34,5 +34,6 def get_verbose_field_name(instance, field_name): | |||||
34 | """ |
|
34 | """ | |
35 | Returns verbose_name for a field. |
|
35 | Returns verbose_name for a field. | |
36 | """ |
|
36 | """ | |
37 |
|
37 | if field_name=='ipp_unit': | ||
|
38 | return 'Inter pulse period [Km(Units)]' | |||
38 | return mark_safe(instance._meta.get_field(field_name).verbose_name) No newline at end of file |
|
39 | return mark_safe(instance._meta.get_field(field_name).verbose_name) |
@@ -44,10 +44,15 CONF_MODELS = { | |||||
44 | } |
|
44 | } | |
45 |
|
45 | |||
46 | MIX_MODES = { |
|
46 | MIX_MODES = { | |
|
47 | '0': 'P', | |||
|
48 | '1': 'S', | |||
|
49 | } | |||
|
50 | ||||
|
51 | MIX_OPERATIONS = { | |||
47 | '0': 'OR', |
|
52 | '0': 'OR', | |
48 | '1': 'XOR', |
|
53 | '1': 'XOR', | |
49 | '2': 'AND', |
|
54 | '2': 'AND', | |
50 | '3': 'NAND' |
|
55 | '3': 'NAND', | |
51 | } |
|
56 | } | |
52 |
|
57 | |||
53 |
|
58 | |||
@@ -680,33 +685,40 def experiment_mix(request, id_exp): | |||||
680 | if request.method=='GET': |
|
685 | if request.method=='GET': | |
681 | form = RCMixConfigurationForm(confs=rc_confs, initial=initial) |
|
686 | form = RCMixConfigurationForm(confs=rc_confs, initial=initial) | |
682 |
|
687 | |||
683 |
if request.method=='POST': |
|
688 | if request.method=='POST': | |
684 |
|
||||
685 | result = mix.parameters |
|
689 | result = mix.parameters | |
686 |
|
690 | |||
687 | if '{}|'.format(request.POST['experiment']) in result: |
|
691 | if '{}|'.format(request.POST['experiment']) in result: | |
688 | messages.error(request, 'Configuration already added') |
|
692 | messages.error(request, 'Configuration already added') | |
689 | else: |
|
693 | else: | |
|
694 | if 'operation' in request.POST: | |||
|
695 | operation = MIX_OPERATIONS[request.POST['operation']] | |||
|
696 | else: | |||
|
697 | operation = '---' | |||
|
698 | ||||
|
699 | mode = MIX_MODES[request.POST['mode']] | |||
|
700 | ||||
690 | if result: |
|
701 | if result: | |
691 | result = '{}-{}|{}|{}|{}'.format(mix.parameters, |
|
702 | result = '{}-{}|{}|{}|{}|{}'.format(mix.parameters, | |
692 |
|
|
703 | request.POST['experiment'], | |
693 |
|
|
704 | mode, | |
694 |
|
|
705 | operation, | |
695 |
|
|
706 | float(request.POST['delay']), | |
696 |
|
|
707 | parse_mask(request.POST.getlist('mask')) | |
|
708 | ) | |||
697 | else: |
|
709 | else: | |
698 | result = '{}|{}|{}|{}'.format(request.POST['experiment'], |
|
710 | result = '{}|{}|{}|{}|{}'.format(request.POST['experiment'], | |
699 |
|
|
711 | mode, | |
700 |
|
|
712 | operation, | |
701 |
|
|
713 | float(request.POST['delay']), | |
702 |
|
|
714 | parse_mask(request.POST.getlist('mask')) | |
|
715 | ) | |||
703 |
|
716 | |||
704 | mix.parameters = result |
|
717 | mix.parameters = result | |
705 | mix.name = request.POST['name'] |
|
718 | mix.name = request.POST['name'] | |
706 | mix.save() |
|
719 | mix.save() | |
707 | mix.update_pulses() |
|
720 | mix.update_pulses() | |
708 |
|
721 | |||
709 |
|
||||
710 | initial['result'] = parse_mix_result(result) |
|
722 | initial['result'] = parse_mix_result(result) | |
711 | initial['name'] = mix.name |
|
723 | initial['name'] = mix.name | |
712 |
|
724 | |||
@@ -741,24 +753,28 def experiment_mix_delete(request, id_exp): | |||||
741 | def parse_mix_result(s): |
|
753 | def parse_mix_result(s): | |
742 |
|
754 | |||
743 | values = s.split('-') |
|
755 | values = s.split('-') | |
744 | html = '' |
|
756 | html = 'EXP MOD OPE DELAY MASK\r\n' | |
745 |
|
757 | |||
|
758 | if not values or values[0] in ('', ' '): | |||
|
759 | return mark_safe(html) | |||
746 |
|
760 | |||
747 | for i, value in enumerate(values): |
|
761 | for i, value in enumerate(values): | |
748 | if not value: |
|
762 | if not value: | |
749 | continue |
|
763 | continue | |
750 | pk, mode, delay, mask = value.split('|') |
|
764 | pk, mode, operation, delay, mask = value.split('|') | |
751 | conf = RCConfiguration.objects.get(pk=pk) |
|
765 | conf = RCConfiguration.objects.get(pk=pk) | |
752 | if i==0: |
|
766 | if i==0: | |
753 | html += '{:20.18}{:4}{:9}km{:>6}\r\n'.format( |
|
767 | html += '{:20.18}{:3}{:4}{:9}km{:>6}\r\n'.format( | |
754 |
conf.name |
|
768 | conf.name, | |
|
769 | mode, | |||
755 | '---', |
|
770 | '---', | |
756 | delay, |
|
771 | delay, | |
757 | mask) |
|
772 | mask) | |
758 | else: |
|
773 | else: | |
759 | html += '{:20.18}{:4}{:9}km{:>6}\r\n'.format( |
|
774 | html += '{:20.18}{:3}{:4}{:9}km{:>6}\r\n'.format( | |
760 |
conf.name |
|
775 | conf.name, | |
761 | mode, |
|
776 | mode, | |
|
777 | operation, | |||
762 | delay, |
|
778 | delay, | |
763 | mask) |
|
779 | mask) | |
764 |
|
780 |
@@ -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', 'mix') |
|
81 | exclude = ('type', 'parameters', 'status', 'total_units', '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() | |
@@ -99,6 +99,9 class RCMixConfigurationForm(forms.Form): | |||||
99 | clock_divider = forms.CharField(widget=forms.HiddenInput()) |
|
99 | clock_divider = forms.CharField(widget=forms.HiddenInput()) | |
100 | name = forms.CharField() |
|
100 | name = forms.CharField() | |
101 | experiment = forms.ChoiceField() |
|
101 | experiment = forms.ChoiceField() | |
|
102 | mode = forms.ChoiceField(widget=forms.RadioSelect(), | |||
|
103 | choices=[(0, 'Parallel'), (1, 'Sequence')], | |||
|
104 | initial=0) | |||
102 | operation = forms.ChoiceField(widget=forms.RadioSelect(), |
|
105 | operation = forms.ChoiceField(widget=forms.RadioSelect(), | |
103 | choices=[(0, 'OR'), (1, 'XOR'), (2, 'AND'), (3, 'NAND')], |
|
106 | choices=[(0, 'OR'), (1, 'XOR'), (2, 'AND'), (3, 'NAND')], | |
104 | initial=1) |
|
107 | initial=1) | |
@@ -121,8 +124,7 class RCMixConfigurationForm(forms.Form): | |||||
121 | self.fields['delay'].widget = KmUnitWidget(attrs = {'km2unit':km2unit}) |
|
124 | self.fields['delay'].widget = KmUnitWidget(attrs = {'km2unit':km2unit}) | |
122 | self.fields['clock_in'].initial = clock_in |
|
125 | self.fields['clock_in'].initial = clock_in | |
123 | self.fields['clock_divider'].initial = clock_divider |
|
126 | self.fields['clock_divider'].initial = clock_divider | |
124 |
|
127 | |||
125 |
|
||||
126 |
|
128 | |||
127 | class RCLineForm(forms.ModelForm): |
|
129 | class RCLineForm(forms.ModelForm): | |
128 |
|
130 |
@@ -57,17 +57,18 DAT_CMDS = { | |||||
57 |
|
57 | |||
58 | class RCConfiguration(Configuration): |
|
58 | class RCConfiguration(Configuration): | |
59 |
|
59 | |||
60 |
ipp = models.FloatField(verbose_name='Inter pulse period |
|
60 | ipp = models.FloatField(verbose_name='Inter pulse period [Km]', validators=[MinValueValidator(1), MaxValueValidator(9000)], default=300) | |
61 | ntx = models.PositiveIntegerField(verbose_name='Number of TX', validators=[MinValueValidator(1), MaxValueValidator(300)], default=1) |
|
61 | ntx = models.PositiveIntegerField(verbose_name='Number of TX', validators=[MinValueValidator(1), MaxValueValidator(300)], default=1) | |
62 |
clock_in = models.FloatField(verbose_name='Clock in |
|
62 | clock_in = models.FloatField(verbose_name='Clock in [MHz]', validators=[MinValueValidator(1), MaxValueValidator(80)], default=1) | |
63 | clock_divider = models.PositiveIntegerField(verbose_name='Clock divider', validators=[MinValueValidator(1), MaxValueValidator(256)], default=1) |
|
63 | clock_divider = models.PositiveIntegerField(verbose_name='Clock divider', validators=[MinValueValidator(1), MaxValueValidator(256)], default=1) | |
64 |
clock = models.FloatField(verbose_name='Clock Master |
|
64 | clock = models.FloatField(verbose_name='Clock Master [MHz]', blank=True, default=1) | |
65 |
time_before = models.PositiveIntegerField(verbose_name='Time before |
|
65 | time_before = models.PositiveIntegerField(verbose_name='Time before [μS]', default=12) | |
66 |
time_after = models.PositiveIntegerField(verbose_name='Time after |
|
66 | time_after = models.PositiveIntegerField(verbose_name='Time after [μS]', default=1) | |
67 | sync = models.PositiveIntegerField(verbose_name='Synchro delay', default=0) |
|
67 | sync = models.PositiveIntegerField(verbose_name='Synchro delay', default=0) | |
68 | sampling_reference = models.CharField(verbose_name='Sampling Reference', choices=SAMPLING_REFS, default='none', max_length=40) |
|
68 | sampling_reference = models.CharField(verbose_name='Sampling Reference', choices=SAMPLING_REFS, default='none', max_length=40) | |
69 | control_tx = models.BooleanField(verbose_name='Control Switch TX', default=False) |
|
69 | control_tx = models.BooleanField(verbose_name='Control Switch TX', default=False) | |
70 | control_sw = models.BooleanField(verbose_name='Control Switch SW', default=False) |
|
70 | control_sw = models.BooleanField(verbose_name='Control Switch SW', default=False) | |
|
71 | total_units = models.PositiveIntegerField(default=0) | |||
71 | mix = models.BooleanField(default=False) |
|
72 | mix = models.BooleanField(default=False) | |
72 |
|
73 | |||
73 | class Meta: |
|
74 | class Meta: | |
@@ -88,6 +89,11 class RCConfiguration(Configuration): | |||||
88 | return reverse('url_import_rc_conf', args=[str(self.id)]) |
|
89 | return reverse('url_import_rc_conf', args=[str(self.id)]) | |
89 |
|
90 | |||
90 | @property |
|
91 | @property | |
|
92 | def ipp_unit(self): | |||
|
93 | ||||
|
94 | return '{} ({})'.format(self.ipp, int(self.ipp*self.km2unit)) | |||
|
95 | ||||
|
96 | @property | |||
91 | def us2unit(self): |
|
97 | def us2unit(self): | |
92 |
|
98 | |||
93 | return self.clock_in/self.clock_divider |
|
99 | return self.clock_in/self.clock_divider | |
@@ -334,12 +340,11 class RCConfiguration(Configuration): | |||||
334 | f = RCFile(filename) |
|
340 | f = RCFile(filename) | |
335 | self.dict_to_parms(f.data) |
|
341 | self.dict_to_parms(f.data) | |
336 | self.update_pulses() |
|
342 | self.update_pulses() | |
337 | self.save() |
|
|||
338 |
|
343 | |||
339 | def update_pulses(self): |
|
344 | def update_pulses(self): | |
340 |
|
345 | |||
341 | for line in self.get_lines(): |
|
346 | for line in self.get_lines(): | |
342 | line.update_pulses() |
|
347 | line.update_pulses() | |
343 |
|
348 | |||
344 | def plot_pulses(self): |
|
349 | def plot_pulses(self): | |
345 |
|
350 | |||
@@ -349,9 +354,7 class RCConfiguration(Configuration): | |||||
349 | from bokeh.mpl import to_bokeh |
|
354 | from bokeh.mpl import to_bokeh | |
350 | from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, PreviewSaveTool |
|
355 | from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, PreviewSaveTool | |
351 |
|
356 | |||
352 | lines = self.get_lines() |
|
357 | lines = self.get_lines() | |
353 |
|
||||
354 | max_value = self.ipp*self.km2unit*self.ntx |
|
|||
355 |
|
358 | |||
356 | N = len(lines) |
|
359 | N = len(lines) | |
357 | fig = plt.figure(figsize=(10, 2+N*0.5)) |
|
360 | fig = plt.figure(figsize=(10, 2+N*0.5)) | |
@@ -360,7 +363,7 class RCConfiguration(Configuration): | |||||
360 |
|
363 | |||
361 | for i, line in enumerate(lines): |
|
364 | for i, line in enumerate(lines): | |
362 | labels.append(line.get_name()) |
|
365 | labels.append(line.get_name()) | |
363 |
l = ax.plot((0, |
|
366 | l = ax.plot((0, self.total_units),(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)] |
|
367 | 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), |
|
368 | ax.broken_barh(points, (N-i-1, 0.5), | |
366 | edgecolor=l[0].get_color(), facecolor='none') |
|
369 | edgecolor=l[0].get_color(), facecolor='none') | |
@@ -496,7 +499,7 class RCLine(models.Model): | |||||
496 |
|
499 | |||
497 | def pulses_as_array(self): |
|
500 | def pulses_as_array(self): | |
498 |
|
501 | |||
499 |
y = np.zeros(self.rc_configuration. |
|
502 | y = np.zeros(self.rc_configuration.total_units) | |
500 |
|
503 | |||
501 | for tup in ast.literal_eval(self.pulses): |
|
504 | for tup in ast.literal_eval(self.pulses): | |
502 | y[tup[0]:tup[1]] = 1 |
|
505 | y[tup[0]:tup[1]] = 1 | |
@@ -534,7 +537,7 class RCLine(models.Model): | |||||
534 | ipp = self.rc_configuration.ipp |
|
537 | ipp = self.rc_configuration.ipp | |
535 | ntx = self.rc_configuration.ntx |
|
538 | ntx = self.rc_configuration.ntx | |
536 | ipp_u = int(ipp*km2unit) |
|
539 | ipp_u = int(ipp*km2unit) | |
537 |
|
540 | total = ipp_u*ntx | ||
538 | y = [] |
|
541 | y = [] | |
539 |
|
542 | |||
540 | if self.line_type.name=='tr': |
|
543 | if self.line_type.name=='tr': | |
@@ -661,38 +664,59 class RCLine(models.Model): | |||||
661 | values = self.rc_configuration.parameters.split('-') |
|
664 | values = self.rc_configuration.parameters.split('-') | |
662 | confs = RCConfiguration.objects.filter(pk__in=[value.split('|')[0] for value in values]) |
|
665 | confs = RCConfiguration.objects.filter(pk__in=[value.split('|')[0] for value in values]) | |
663 | modes = [value.split('|')[1] for value in values] |
|
666 | modes = [value.split('|')[1] for value in values] | |
664 |
|
|
667 | ops = [value.split('|')[2] for value in values] | |
665 |
|
|
668 | delays = [value.split('|')[3] for value in values] | |
|
669 | masks = [value.split('|')[4] for value in values] | |||
|
670 | mask = list('{:8b}'.format(int(masks[0]))) | |||
|
671 | mask.reverse() | |||
|
672 | if mask[self.channel] in ('0', '', ' '): | |||
|
673 | y = np.zeros(total, dtype=np.int8) | |||
|
674 | else: | |||
|
675 | y = confs[0].get_lines(channel=self.channel)[0].pulses_as_array() | |||
666 |
|
676 | |||
667 | y = confs[0].get_lines(channel=self.channel)[0].pulses_as_array() |
|
|||
668 | ysize = len(y) |
|
|||
669 | for i in range(1, len(values)): |
|
677 | for i in range(1, len(values)): | |
670 | mask = list('{:8b}'.format(int(masks[i]))) |
|
678 | mask = list('{:8b}'.format(int(masks[i]))) | |
671 | mask.reverse() |
|
679 | mask.reverse() | |
672 |
|
680 | |||
673 | if mask[self.channel] in ('0', '', ' '): |
|
681 | if mask[self.channel] in ('0', '', ' '): | |
674 | continue |
|
682 | continue | |
675 | Y = confs[i].get_lines(channel=self.channel)[0].pulses_as_array() |
|
683 | Y = confs[i].get_lines(channel=self.channel)[0].pulses_as_array() | |
676 | delay = float(delays[i])*km2unit |
|
684 | delay = float(delays[i])*km2unit | |
677 | if delay>0: |
|
685 | ||
678 | y_temp = np.empty_like(Y) |
|
686 | if delay>0: | |
679 | y_temp[:delay] = 0 |
|
687 | if delay<self.rc_configuration.ipp*km2unit and len(Y)==len(y): | |
680 |
y_temp |
|
688 | y_temp = np.empty_like(Y) | |
681 |
y_temp |
|
689 | y_temp[:delay] = 0 | |
682 | if modes[i]=='OR': |
|
690 | y_temp[delay:] = Y[:-delay] | |
|
691 | elif delay+len(Y)>len(y): | |||
|
692 | y_new = np.zeros(delay+len(Y), dtype=np.int8) | |||
|
693 | y_new[:len(y)] = y | |||
|
694 | y = y_new | |||
|
695 | y_temp = np.zeros(delay+len(Y), dtype=np.int8) | |||
|
696 | y_temp[-len(Y):] = Y | |||
|
697 | elif delay+len(Y)==len(y): | |||
|
698 | y_temp = np.zeros(delay+len(Y)) | |||
|
699 | y_temp[-len(Y):] = Y | |||
|
700 | ||||
|
701 | if ops[i]=='OR': | |||
683 | y = y | y_temp |
|
702 | y = y | y_temp | |
684 |
elif |
|
703 | elif ops[i]=='XOR': | |
685 | y = y ^ y_temp |
|
704 | y = y ^ y_temp | |
686 |
elif |
|
705 | elif ops[i]=='AND': | |
687 | y = y & y_temp |
|
706 | y = y & y_temp | |
688 |
elif |
|
707 | elif ops[i]=='NAND': | |
689 | y = y & ~y_temp |
|
708 | y = y & ~y_temp | |
690 |
|
|
709 | ||
|
710 | total = len(y) | |||
691 | y = self.array_to_points(y) |
|
711 | y = self.array_to_points(y) | |
692 |
|
712 | |||
693 | else: |
|
713 | else: | |
694 | y = [] |
|
714 | y = [] | |
695 |
|
715 | |||
|
716 | if self.rc_configuration.total_units <> total: | |||
|
717 | self.rc_configuration.total_units = total | |||
|
718 | self.rc_configuration.save() | |||
|
719 | ||||
696 | self.pulses = y |
|
720 | self.pulses = y | |
697 | self.save() |
|
721 | self.save() | |
698 |
|
722 |
@@ -27,7 +27,7 def conf(request, conf_id): | |||||
27 | kwargs = {} |
|
27 | kwargs = {} | |
28 | kwargs['dev_conf'] = conf |
|
28 | kwargs['dev_conf'] = conf | |
29 | kwargs['rc_lines'] = lines |
|
29 | kwargs['rc_lines'] = lines | |
30 | kwargs['dev_conf_keys'] = ['name', 'ipp', 'ntx', 'clock_in', 'clock_divider', 'clock', |
|
30 | kwargs['dev_conf_keys'] = ['name', 'ipp_unit', 'ntx', 'clock_in', 'clock_divider', 'clock', | |
31 | 'time_before', 'time_after', 'sync', 'sampling_reference', 'control_tx', 'control_sw'] |
|
31 | 'time_before', 'time_after', 'sync', 'sampling_reference', 'control_tx', 'control_sw'] | |
32 |
|
32 | |||
33 | kwargs['title'] = 'RC Configuration' |
|
33 | kwargs['title'] = 'RC Configuration' | |
@@ -116,7 +116,7 def conf_edit(request, conf_id): | |||||
116 | line.save() |
|
116 | line.save() | |
117 |
|
117 | |||
118 | #update pulses field |
|
118 | #update pulses field | |
119 |
conf.update_pulses() |
|
119 | conf.update_pulses() | |
120 |
|
120 | |||
121 | messages.success(request, 'RC Configuration successfully updated') |
|
121 | messages.success(request, 'RC Configuration successfully updated') | |
122 |
|
122 |
General Comments 0
You need to be logged in to leave comments.
Login now