@@ -7,13 +7,13 from django.utils.safestring import mark_safe | |||||
7 | from apps.main.models import Device |
|
7 | from apps.main.models import Device | |
8 | from apps.main.forms import add_empty_choice |
|
8 | from apps.main.forms import add_empty_choice | |
9 | from .models import RCConfiguration, RCLine, RCLineType, RCLineCode |
|
9 | from .models import RCConfiguration, RCLine, RCLineType, RCLineCode | |
10 | from .widgets import KmUnitWidget, KmUnitHzWidget, KmUnitDcWidget, UnitKmWidget, DefaultWidget, CodesWidget, HiddenWidget |
|
10 | from .widgets import KmUnitWidget, KmUnitHzWidget, KmUnitDcWidget, UnitKmWidget, DefaultWidget, CodesWidget, HiddenWidget, HCheckboxSelectMultiple | |
11 |
|
11 | |||
12 | def create_choices_from_model(model, conf_id, all=False): |
|
12 | def create_choices_from_model(model, conf_id, all=False): | |
13 |
|
13 | |||
14 | if model=='RCLine': |
|
14 | if model=='RCLine': | |
15 | instance = RCConfiguration.objects.get(pk=conf_id) |
|
15 | instance = RCConfiguration.objects.get(pk=conf_id) | |
16 | choices = [(line.pk, line.get_name()) for line in instance.get_lines(type='tx')] |
|
16 | choices = [(line.pk, line.get_name()) for line in instance.get_lines(line_type__name='tx')] | |
17 | choices = add_empty_choice(choices, label='All') |
|
17 | choices = add_empty_choice(choices, label='All') | |
18 | else: |
|
18 | else: | |
19 | instance = globals()[model] |
|
19 | instance = globals()[model] | |
@@ -64,7 +64,7 class RCConfigurationForm(forms.ModelForm): | |||||
64 |
|
64 | |||
65 | devices = Device.objects.filter(device_type__name='rc') |
|
65 | devices = Device.objects.filter(device_type__name='rc') | |
66 | if instance.experiment: |
|
66 | if instance.experiment: | |
67 |
self.fields['experiment'].widget.attrs[' |
|
67 | self.fields['experiment'].widget.attrs['read_only'] = True | |
68 | #self.fields['experiment'].widget.choices = [(instance.experiment.id, instance.experiment)] |
|
68 | #self.fields['experiment'].widget.choices = [(instance.experiment.id, instance.experiment)] | |
69 | self.fields['device'].widget.choices = [(device.id, device) for device in devices] |
|
69 | self.fields['device'].widget.choices = [(device.id, device) for device in devices] | |
70 | self.fields['ipp'].widget = KmUnitHzWidget(attrs={'km2unit':instance.km2unit}) |
|
70 | self.fields['ipp'].widget = KmUnitHzWidget(attrs={'km2unit':instance.km2unit}) | |
@@ -91,7 +91,39 class RCConfigurationForm(forms.ModelForm): | |||||
91 | self.add_error('ipp', 'Invalid IPP units={}'.format(form_data['ipp']*(20./3*(form_data['clock_in']/form_data['clock_divider'])))) |
|
91 | self.add_error('ipp', 'Invalid IPP units={}'.format(form_data['ipp']*(20./3*(form_data['clock_in']/form_data['clock_divider'])))) | |
92 |
|
92 | |||
93 | return form_data |
|
93 | return form_data | |
94 |
|
94 | |||
|
95 | ||||
|
96 | class RCMixConfigurationForm(forms.Form): | |||
|
97 | ||||
|
98 | clock_in = forms.CharField(widget=forms.HiddenInput()) | |||
|
99 | clock_divider = forms.CharField(widget=forms.HiddenInput()) | |||
|
100 | name = forms.CharField() | |||
|
101 | experiment = forms.ChoiceField() | |||
|
102 | operation = forms.ChoiceField(widget=forms.RadioSelect(), | |||
|
103 | choices=[(0, 'OR'), (1, 'XOR'), (2, 'AND'), (3, 'NAND')], | |||
|
104 | initial=1) | |||
|
105 | delay = forms.CharField() | |||
|
106 | mask = forms.MultipleChoiceField(choices=[(0, 'L1'),(1, 'L2'),(2, 'L3'),(3, 'L4'),(4, 'L5'),(5, 'L6'),(6, 'L7'),(7, 'L8')], | |||
|
107 | widget=HCheckboxSelectMultiple()) | |||
|
108 | result = forms.CharField(required=False, | |||
|
109 | widget=forms.Textarea(attrs={'readonly':True, 'rows':5, 'class':'tabuled'})) | |||
|
110 | ||||
|
111 | def __init__(self, *args, **kwargs): | |||
|
112 | confs = kwargs.pop('confs', []) | |||
|
113 | if confs: | |||
|
114 | km2unit = confs[0].km2unit | |||
|
115 | clock_in = confs[0].clock_in | |||
|
116 | clock_divider = confs[0].clock_divider | |||
|
117 | else: | |||
|
118 | km2unit = clock_in = clock_divider = 0 | |||
|
119 | super(RCMixConfigurationForm, self).__init__(*args, **kwargs) | |||
|
120 | self.fields['experiment'].choices = [(conf.pk, '{} | {}'.format(conf.pk, conf.name)) for conf in confs] | |||
|
121 | self.fields['delay'].widget = KmUnitWidget(attrs = {'km2unit':km2unit}) | |||
|
122 | self.fields['clock_in'].initial = clock_in | |||
|
123 | self.fields['clock_divider'].initial = clock_divider | |||
|
124 | ||||
|
125 | ||||
|
126 | ||||
95 | class RCLineForm(forms.ModelForm): |
|
127 | class RCLineForm(forms.ModelForm): | |
96 |
|
128 | |||
97 | def __init__(self, *args, **kwargs): |
|
129 | def __init__(self, *args, **kwargs): |
@@ -10,6 +10,7 from django.core.urlresolvers import reverse | |||||
10 | from django.core.validators import MinValueValidator, MaxValueValidator |
|
10 | 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 .utils import RCFile, pulses, pulses_from_code, create_mask, pulses_to_points |
|
14 | from .utils import RCFile, pulses, pulses_from_code, create_mask, pulses_to_points | |
14 |
|
15 | |||
15 | # Create your models here. |
|
16 | # Create your models here. | |
@@ -23,6 +24,7 LINE_TYPES = ( | |||||
23 | ('sync', 'Synchronizing signal'), |
|
24 | ('sync', 'Synchronizing signal'), | |
24 | ('flip', 'IPP related periodic signal'), |
|
25 | ('flip', 'IPP related periodic signal'), | |
25 | ('prog_pulses', 'Programmable pulse'), |
|
26 | ('prog_pulses', 'Programmable pulse'), | |
|
27 | ('mix', 'Mixed line'), | |||
26 | ) |
|
28 | ) | |
27 |
|
29 | |||
28 |
|
30 | |||
@@ -55,23 +57,30 DAT_CMDS = { | |||||
55 |
|
57 | |||
56 | class RCConfiguration(Configuration): |
|
58 | class RCConfiguration(Configuration): | |
57 |
|
59 | |||
58 |
ipp = models.FloatField(verbose_name='Inter pulse period (Km)', validators=[MinValueValidator(1), MaxValueValidator( |
|
60 | ipp = models.FloatField(verbose_name='Inter pulse period (Km)', validators=[MinValueValidator(1), MaxValueValidator(9000)], default=300) | |
59 |
ntx = models.PositiveIntegerField(verbose_name='Number of TX', validators=[MinValueValidator(1), MaxValueValidator( |
|
61 | ntx = models.PositiveIntegerField(verbose_name='Number of TX', validators=[MinValueValidator(1), MaxValueValidator(300)], default=1) | |
60 | clock_in = models.FloatField(verbose_name='Clock in (MHz)', validators=[MinValueValidator(1), MaxValueValidator(80)], default=1) |
|
62 | clock_in = models.FloatField(verbose_name='Clock in (MHz)', validators=[MinValueValidator(1), MaxValueValidator(80)], default=1) | |
61 | 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) | |
62 | clock = models.FloatField(verbose_name='Clock Master (MHz)', blank=True, default=1) |
|
64 | clock = models.FloatField(verbose_name='Clock Master (MHz)', blank=True, default=1) | |
63 |
time_before = models.PositiveIntegerField(verbose_name='Time before (μS)', default= |
|
65 | time_before = models.PositiveIntegerField(verbose_name='Time before (μS)', default=12) | |
64 |
time_after = models.PositiveIntegerField(verbose_name='Time after (μS)', default= |
|
66 | time_after = models.PositiveIntegerField(verbose_name='Time after (μS)', default=1) | |
65 | sync = models.PositiveIntegerField(verbose_name='Synchro delay', default=0) |
|
67 | sync = models.PositiveIntegerField(verbose_name='Synchro delay', default=0) | |
66 | 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) | |
67 | control_tx = models.BooleanField(verbose_name='Control Switch TX', default=False) |
|
69 | control_tx = models.BooleanField(verbose_name='Control Switch TX', default=False) | |
68 | control_sw = models.BooleanField(verbose_name='Control Switch SW', default=False) |
|
70 | control_sw = models.BooleanField(verbose_name='Control Switch SW', default=False) | |
69 |
|
71 | mix = models.BooleanField(default=False) | ||
70 |
|
72 | |||
71 | class Meta: |
|
73 | class Meta: | |
72 | db_table = 'rc_configurations' |
|
74 | db_table = 'rc_configurations' | |
73 |
|
75 | |||
74 |
|
76 | |||
|
77 | def __unicode__(self): | |||
|
78 | ||||
|
79 | if self.mix: | |||
|
80 | return u'[MIXED]: %s' % self.name | |||
|
81 | else: | |||
|
82 | return u'[%s]: %s' % (self.device.name, self.name) | |||
|
83 | ||||
75 | def get_absolute_url_plot(self): |
|
84 | def get_absolute_url_plot(self): | |
76 | return reverse('url_plot_rc_pulses', args=[str(self.id)]) |
|
85 | return reverse('url_plot_rc_pulses', args=[str(self.id)]) | |
77 |
|
86 | |||
@@ -83,13 +92,11 class RCConfiguration(Configuration): | |||||
83 |
|
92 | |||
84 | return self.clock_in/self.clock_divider |
|
93 | return self.clock_in/self.clock_divider | |
85 |
|
94 | |||
86 |
|
||||
87 | @property |
|
95 | @property | |
88 | def km2unit(self): |
|
96 | def km2unit(self): | |
89 |
|
97 | |||
90 | return 20./3*(self.clock_in/self.clock_divider) |
|
98 | return 20./3*(self.clock_in/self.clock_divider) | |
91 |
|
99 | |||
92 |
|
||||
93 | def clone(self, **kwargs): |
|
100 | def clone(self, **kwargs): | |
94 |
|
101 | |||
95 | lines = self.get_lines() |
|
102 | lines = self.get_lines() | |
@@ -104,15 +111,13 class RCConfiguration(Configuration): | |||||
104 |
|
111 | |||
105 | return self |
|
112 | return self | |
106 |
|
113 | |||
107 |
def get_lines(self, |
|
114 | def get_lines(self, **kwargs): | |
108 | ''' |
|
115 | ''' | |
109 | Retrieve configuration lines |
|
116 | Retrieve configuration lines | |
110 | ''' |
|
117 | ''' | |
111 |
|
118 | |||
112 | if type is not None: |
|
119 | return RCLine.objects.filter(rc_configuration=self.pk, **kwargs) | |
113 | return RCLine.objects.filter(rc_configuration=self.pk, line_type__name=type) |
|
120 | ||
114 | else: |
|
|||
115 | return RCLine.objects.filter(rc_configuration=self.pk) |
|
|||
116 |
|
121 | |||
117 | def clean_lines(self): |
|
122 | def clean_lines(self): | |
118 | ''' |
|
123 | ''' | |
@@ -146,9 +151,67 class RCConfiguration(Configuration): | |||||
146 | line_data['type'] = line.line_type.name |
|
151 | line_data['type'] = line.line_type.name | |
147 | data['lines'].append(line_data) |
|
152 | data['lines'].append(line_data) | |
148 |
|
153 | |||
|
154 | data['delays'] = self.get_delays() | |||
|
155 | data['pulses'] = self.get_pulses() | |||
149 |
|
156 | |||
150 | return data |
|
157 | return data | |
151 |
|
158 | |||
|
159 | def dict_to_parms(self, data): | |||
|
160 | ''' | |||
|
161 | ''' | |||
|
162 | ||||
|
163 | self.name = data['name'] | |||
|
164 | self.ipp = data['ipp'] | |||
|
165 | self.ntx = data['ntx'] | |||
|
166 | self.clock_in = data['clock_in'] | |||
|
167 | self.clock_divider = data['clock_divider'] | |||
|
168 | self.clock = data['clock'] | |||
|
169 | self.time_before = data['time_before'] | |||
|
170 | self.time_after = data['time_after'] | |||
|
171 | self.sync = data['sync'] | |||
|
172 | self.sampling_reference = data['sampling_reference'] | |||
|
173 | self.clean_lines() | |||
|
174 | ||||
|
175 | lines = [] | |||
|
176 | positions = {'tx':0, 'tr':0} | |||
|
177 | ||||
|
178 | for i, line_data in enumerate(data['lines']): | |||
|
179 | line_type = RCLineType.objects.get(name=line_data.pop('type')) | |||
|
180 | if line_type.name=='codes': | |||
|
181 | code = RCLineCode.objects.get(name=line_data['code']) | |||
|
182 | line_data['code'] = code.pk | |||
|
183 | line = RCLine.objects.filter(rc_configuration=self, channel=i) | |||
|
184 | if line: | |||
|
185 | line = line[0] | |||
|
186 | line.line_type = line_type | |||
|
187 | line.params = json.dumps(line_data) | |||
|
188 | else: | |||
|
189 | line = RCLine(rc_configuration=self, line_type=line_type, | |||
|
190 | params=json.dumps(line_data), | |||
|
191 | channel=i) | |||
|
192 | ||||
|
193 | if line_type.name=='tx': | |||
|
194 | line.position = positions['tx'] | |||
|
195 | positions['tx'] += 1 | |||
|
196 | ||||
|
197 | if line_type.name=='tr': | |||
|
198 | line.position = positions['tr'] | |||
|
199 | positions['tr'] += 1 | |||
|
200 | ||||
|
201 | line.save() | |||
|
202 | lines.append(line) | |||
|
203 | ||||
|
204 | for line, line_data in zip(lines, data['lines']): | |||
|
205 | if 'TX_ref' in line_data: | |||
|
206 | params = json.loads(line.params) | |||
|
207 | if line_data['TX_ref'] in (0, '0'): | |||
|
208 | params['TX_ref'] = '0' | |||
|
209 | else: | |||
|
210 | params['TX_ref'] = [l.pk for l in lines if l.line_type.name=='tx' and l.get_name()==line_data['TX_ref']][0] | |||
|
211 | line.params = json.dumps(params) | |||
|
212 | line.save() | |||
|
213 | ||||
|
214 | ||||
152 | def get_delays(self): |
|
215 | def get_delays(self): | |
153 |
|
216 | |||
154 | pulses = [line.get_pulses() for line in self.get_lines()] |
|
217 | pulses = [line.get_pulses() for line in self.get_lines()] | |
@@ -163,14 +226,24 class RCConfiguration(Configuration): | |||||
163 | return [points[i+1]-points[i] for i in range(len(points)-1)] |
|
226 | return [points[i+1]-points[i] for i in range(len(points)-1)] | |
164 |
|
227 | |||
165 |
|
228 | |||
166 |
def get_ |
|
229 | def get_pulses(self, binary=True): | |
|
230 | ||||
|
231 | pulses = [line.get_pulses() for line in self.get_lines()] | |||
|
232 | points = [tup for tups in pulses for tup in tups] | |||
|
233 | points = set([x for tup in points for x in tup]) | |||
|
234 | points = list(points) | |||
|
235 | points.sort() | |||
167 |
|
236 | |||
168 | line_points = [pulses_to_points(line.pulses_as_array()) for line in self.get_lines()] |
|
237 | line_points = [pulses_to_points(line.pulses_as_array()) for line in self.get_lines()] | |
169 | line_points = [[(x, x+y) for x,y in tups] for tups in line_points] |
|
238 | line_points = [[(x, x+y) for x,y in tups] for tups in line_points] | |
170 | line_points = [[t for x in tups for t in x] for tups in line_points] |
|
239 | line_points = [[t for x in tups for t in x] for tups in line_points] | |
171 | states = [[1 if x in tups else 0 for tups in line_points] for x in points] |
|
240 | states = [[1 if x in tups else 0 for tups in line_points] for x in points] | |
172 |
|
241 | |||
173 | return states |
|
242 | if binary: | |
|
243 | states.reverse() | |||
|
244 | states = [int(''.join([str(x) for x in flips]), 2) for flips in states] | |||
|
245 | ||||
|
246 | return states[:-1] | |||
174 |
|
247 | |||
175 | def add_cmd(self, cmd): |
|
248 | def add_cmd(self, cmd): | |
176 |
|
249 | |||
@@ -210,17 +283,8 class RCConfiguration(Configuration): | |||||
210 | data.append(self.add_cmd('DELAY_START')) |
|
283 | data.append(self.add_cmd('DELAY_START')) | |
211 | # first delay is always zero |
|
284 | # first delay is always zero | |
212 | data.append(self.add_data(1)) |
|
285 | data.append(self.add_data(1)) | |
213 | line_points = [pulses_to_points(line.pulses_as_array()) for line in self.get_lines()] |
|
286 | ||
214 | points = [tup for tups in line_points for tup in tups] |
|
287 | delays = self.get_delays() | |
215 | points = [(x, x+y) for x,y in points] |
|
|||
216 | points = set([x for tup in points for x in tup]) |
|
|||
217 | points = list(points) |
|
|||
218 | points.sort() |
|
|||
219 |
|
||||
220 | if points[0]<>0: |
|
|||
221 | points.insert(0, 0) |
|
|||
222 |
|
||||
223 | delays = [points[i+1]-points[i] for i in range(len(points)-1)] |
|
|||
224 |
|
288 | |||
225 | for delay in delays: |
|
289 | for delay in delays: | |
226 | while delay>252: |
|
290 | while delay>252: | |
@@ -230,10 +294,10 class RCConfiguration(Configuration): | |||||
230 |
|
294 | |||
231 | # write flips |
|
295 | # write flips | |
232 | data.append(self.add_cmd('FLIP_START')) |
|
296 | data.append(self.add_cmd('FLIP_START')) | |
233 | line_points = [[(x, x+y) for x,y in tups] for tups in line_points] |
|
297 | ||
234 | line_points = [[t for x in tups for t in x] for tups in line_points] |
|
298 | states = self.get_pulses(binary=False) | |
235 | states = [[1 if x in tups else 0 for tups in line_points] for x in points] |
|
299 | ||
236 |
for flips, delay in zip(states |
|
300 | for flips, delay in zip(states, delays): | |
237 | flips.reverse() |
|
301 | flips.reverse() | |
238 | flip = int(''.join([str(x) for x in flips]), 2) |
|
302 | flip = int(''.join([str(x) for x in flips]), 2) | |
239 | data.append(self.add_data(flip+1)) |
|
303 | data.append(self.add_data(flip+1)) | |
@@ -243,7 +307,7 class RCConfiguration(Configuration): | |||||
243 |
|
307 | |||
244 | # write sampling period |
|
308 | # write sampling period | |
245 | data.append(self.add_cmd('SAMPLING_PERIOD')) |
|
309 | data.append(self.add_cmd('SAMPLING_PERIOD')) | |
246 | wins = self.get_lines(type='windows') |
|
310 | wins = self.get_lines(line_type__name='windows') | |
247 | if wins: |
|
311 | if wins: | |
248 | win_params = json.loads(wins[0].params)['params'] |
|
312 | win_params = json.loads(wins[0].params)['params'] | |
249 | if win_params: |
|
313 | if win_params: | |
@@ -265,63 +329,59 class RCConfiguration(Configuration): | |||||
265 | ''' |
|
329 | ''' | |
266 |
|
330 | |||
267 | f = RCFile(filename) |
|
331 | f = RCFile(filename) | |
268 | data = f.data |
|
332 | self.dict_to_parms(f.data) | |
269 | self.name = data['name'] |
|
333 | ||
270 | self.ipp = data['ipp'] |
|
334 | def update_pulses(self): | |
271 | self.ntx = data['ntx'] |
|
|||
272 | self.clock_in = data['clock_in'] |
|
|||
273 | self.clock_divider = data['clock_divider'] |
|
|||
274 | self.clock = data['clock'] |
|
|||
275 | self.time_before = data['time_before'] |
|
|||
276 | self.time_after = data['time_after'] |
|
|||
277 | self.sync = data['sync'] |
|
|||
278 | self.sampling_reference = data['sampling_reference'] |
|
|||
279 | self.clean_lines() |
|
|||
280 |
|
||||
281 | lines = [] |
|
|||
282 | positions = {'tx':0, 'tr':0} |
|
|||
283 |
|
335 | |||
284 |
for |
|
336 | for line in self.get_lines(): | |
285 | line_type = RCLineType.objects.get(name=line_data.pop('type')) |
|
337 | if line.line_type.name=='tr': | |
286 | if line_type.name=='codes': |
|
338 | continue | |
287 | code = RCLineCode.objects.get(name=line_data['code']) |
|
339 | line.update_pulses() | |
288 | line_data['code'] = code.pk |
|
|||
289 | line = RCLine.objects.filter(rc_configuration=self, channel=i) |
|
|||
290 | if line: |
|
|||
291 | line = line[0] |
|
|||
292 | line.line_type = line_type |
|
|||
293 | line.params = json.dumps(line_data) |
|
|||
294 | else: |
|
|||
295 | line = RCLine(rc_configuration=self, line_type=line_type, |
|
|||
296 | params=json.dumps(line_data), |
|
|||
297 | channel=i) |
|
|||
298 |
|
||||
299 | if line_type.name=='tx': |
|
|||
300 | line.position = positions['tx'] |
|
|||
301 | positions['tx'] += 1 |
|
|||
302 |
|
||||
303 | if line_type.name=='tr': |
|
|||
304 | line.position = positions['tr'] |
|
|||
305 | positions['tr'] += 1 |
|
|||
306 |
|
||||
307 | line.save() |
|
|||
308 | lines.append(line) |
|
|||
309 |
|
||||
310 | for line, line_data in zip(lines, data['lines']): |
|
|||
311 | if 'TX_ref' in line_data: |
|
|||
312 | params = json.loads(line.params) |
|
|||
313 | if line_data['TX_ref'] in (0, '0'): |
|
|||
314 | params['TX_ref'] = '0' |
|
|||
315 | else: |
|
|||
316 | params['TX_ref'] = [l.pk for l in lines if l.line_type.name=='tx' and l.get_name()==line_data['TX_ref']][0] |
|
|||
317 | line.params = json.dumps(params) |
|
|||
318 | line.save() |
|
|||
319 |
|
340 | |||
320 |
|
341 | for tr in self.get_lines(line_type__name='tr'): | ||
|
342 | tr.update_pulses() | |||
|
343 | ||||
321 | def status_device(self): |
|
344 | def status_device(self): | |
322 |
|
345 | |||
323 | return 0 |
|
346 | return 0 | |
324 |
|
347 | |||
|
348 | def stop_device(self): | |||
|
349 | ||||
|
350 | answer = api.disable(ip = self.device.ip_address, | |||
|
351 | port = self.device.port_address) | |||
|
352 | ||||
|
353 | if answer[0] != "1": | |||
|
354 | self.message = answer[0:] | |||
|
355 | return 0 | |||
|
356 | ||||
|
357 | self.message = answer[2:] | |||
|
358 | return 1 | |||
|
359 | ||||
|
360 | def start_device(self): | |||
|
361 | ||||
|
362 | answer = api.enable(ip = self.device.ip_address, | |||
|
363 | port = self.device.port_address) | |||
|
364 | ||||
|
365 | if answer[0] != "1": | |||
|
366 | self.message = answer[0:] | |||
|
367 | return 0 | |||
|
368 | ||||
|
369 | self.message = answer[2:] | |||
|
370 | return 1 | |||
|
371 | ||||
|
372 | def write_device(self): | |||
|
373 | answer = api.write_config(ip = self.device.ip_address, | |||
|
374 | port = self.device.port_address, | |||
|
375 | parms = self.parms_to_dict()) | |||
|
376 | ||||
|
377 | if answer[0] != "1": | |||
|
378 | self.message = answer[0:] | |||
|
379 | return 0 | |||
|
380 | ||||
|
381 | self.message = answer[2:] | |||
|
382 | return 1 | |||
|
383 | ||||
|
384 | ||||
325 | class RCLineCode(models.Model): |
|
385 | class RCLineCode(models.Model): | |
326 |
|
386 | |||
327 | name = models.CharField(max_length=40) |
|
387 | name = models.CharField(max_length=40) | |
@@ -336,6 +396,7 class RCLineCode(models.Model): | |||||
336 | def __unicode__(self): |
|
396 | def __unicode__(self): | |
337 | return u'%s' % self.name |
|
397 | return u'%s' % self.name | |
338 |
|
398 | |||
|
399 | ||||
339 | class RCLineType(models.Model): |
|
400 | class RCLineType(models.Model): | |
340 |
|
401 | |||
341 | name = models.CharField(choices=LINE_TYPES, max_length=40) |
|
402 | name = models.CharField(choices=LINE_TYPES, max_length=40) | |
@@ -388,29 +449,24 class RCLine(models.Model): | |||||
388 | return self.line_type.name.upper() |
|
449 | return self.line_type.name.upper() | |
389 | pk = json.loads(self.params)['TX_ref'] |
|
450 | pk = json.loads(self.params)['TX_ref'] | |
390 | if pk in (0, '0'): |
|
451 | if pk in (0, '0'): | |
391 | refs = ','.join(chars[l.position] for l in self.rc_configuration.get_lines('tx')) |
|
452 | refs = ','.join(chars[l.position] for l in self.rc_configuration.get_lines(line_type__name='tx')) | |
392 | return '%s (%s)' % (self.line_type.name.upper(), refs) |
|
453 | return '%s (%s)' % (self.line_type.name.upper(), refs) | |
393 | else: |
|
454 | else: | |
394 | ref = RCLine.objects.get(pk=pk) |
|
455 | ref = RCLine.objects.get(pk=pk) | |
395 | return '%s (%s)' % (self.line_type.name.upper(), chars[ref.position]) |
|
456 | return '%s (%s)' % (self.line_type.name.upper(), chars[ref.position]) | |
396 | elif self.line_type.name in ('flip', 'prog_pulses', 'sync', 'none'): |
|
457 | elif self.line_type.name in ('flip', 'prog_pulses', 'sync', 'none', 'mix'): | |
397 | return '%s %s' % (self.line_type.name.upper(), self.channel) |
|
458 | return '%s %s' % (self.line_type.name.upper(), self.channel) | |
398 | else: |
|
459 | else: | |
399 | return self.line_type.name.upper() |
|
460 | return self.line_type.name.upper() | |
400 |
|
461 | |||
401 |
def get_lines(self, |
|
462 | def get_lines(self, **kwargs): | |
402 |
|
463 | |||
403 | if type is not None: |
|
464 | return RCLine.objects.filter(rc_configuration=self.rc_configuration, **kwargs) | |
404 | return RCLine.objects.filter(rc_configuration=self.rc_configuration, line_type__name=type) |
|
|||
405 | else: |
|
|||
406 | return RCLine.objects.filter(rc_configuration=self.rc_configuration) |
|
|||
407 |
|
||||
408 |
|
465 | |||
409 | def pulses_as_array(self): |
|
466 | def pulses_as_array(self): | |
410 |
|
467 | |||
411 | return (np.fromstring(self.pulses, dtype=np.uint8)-48).astype(np.int8) |
|
468 | return (np.fromstring(self.pulses, dtype=np.uint8)-48).astype(np.int8) | |
412 |
|
469 | |||
413 |
|
||||
414 | def get_pulses(self): |
|
470 | def get_pulses(self): | |
415 |
|
471 | |||
416 | X = self.pulses_as_array() |
|
472 | X = self.pulses_as_array() | |
@@ -432,12 +488,10 class RCLine(models.Model): | |||||
432 | def get_win_ref(self, params, tx_id, km2unit): |
|
488 | def get_win_ref(self, params, tx_id, km2unit): | |
433 |
|
489 | |||
434 | ref = self.rc_configuration.sampling_reference |
|
490 | ref = self.rc_configuration.sampling_reference | |
435 |
|
491 | codes = [line for line in self.get_lines(line_type__name='codes') if int(json.loads(line.params)['TX_ref'])==int(tx_id)] | ||
436 | codes = [line for line in self.get_lines(type='code') if int(json.loads(line.params)['TX_ref'])==int(tx_id)] |
|
492 | ||
437 |
|
493 | if codes: | ||
438 | if codes: |
|
494 | tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit/len(json.loads(codes[0].params)['codes'][0]) | |
439 | code_line = RCLineCode.objects.get(pk=json.loads(codes[0].params)['code']) |
|
|||
440 | tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit/code_line.bits_per_code |
|
|||
441 | else: |
|
495 | else: | |
442 | tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit |
|
496 | tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit | |
443 |
|
497 | |||
@@ -464,7 +518,7 class RCLine(models.Model): | |||||
464 | if self.line_type.name=='tr': |
|
518 | if self.line_type.name=='tr': | |
465 | params = json.loads(self.params) |
|
519 | params = json.loads(self.params) | |
466 | if params['TX_ref'] in ('0', 0): |
|
520 | if params['TX_ref'] in ('0', 0): | |
467 | txs = [tx.update_pulses(save=False, tr=True) for tx in self.get_lines('tx')] |
|
521 | txs = [tx.update_pulses(save=False, tr=True) for tx in self.get_lines(line_type__name='tx')] | |
468 | else: |
|
522 | else: | |
469 | txs = [tx.update_pulses(save=False, tr=True) for tx in RCLine.objects.filter(pk=params['TX_ref'])] |
|
523 | txs = [tx.update_pulses(save=False, tr=True) for tx in RCLine.objects.filter(pk=params['TX_ref'])] | |
470 | if len(txs)==0 or 0 in [len(tx) for tx in txs]: |
|
524 | if len(txs)==0 or 0 in [len(tx) for tx in txs]: | |
@@ -498,13 +552,12 class RCLine(models.Model): | |||||
498 |
|
552 | |||
499 | elif self.line_type.name=='codes': |
|
553 | elif self.line_type.name=='codes': | |
500 | params = json.loads(self.params) |
|
554 | params = json.loads(self.params) | |
501 | #codes = ast.literal_eval(RCLineCode.objects.get(pk=json.loads(self.params)['code']).codes) |
|
|||
502 | tx = RCLine.objects.get(pk=params['TX_ref']) |
|
555 | tx = RCLine.objects.get(pk=params['TX_ref']) | |
503 | tx_params = json.loads(tx.params) |
|
556 | tx_params = json.loads(tx.params) | |
504 |
|
557 | delays = [float(d)*km2unit for d in tx_params['delays'].split(',') if d] | ||
505 |
y = pulses_from_code( |
|
558 | y = pulses_from_code(tx.pulses_as_array(), | |
506 |
|
|
559 | params['codes'], | |
507 | before=int(self.rc_configuration.time_before*us2unit)+self.rc_configuration.sync) |
|
560 | int(float(tx_params['pulse_width'])*km2unit)) | |
508 |
|
561 | |||
509 | ranges = tx_params['range'].split(',') |
|
562 | ranges = tx_params['range'].split(',') | |
510 | if len(ranges)>0 and ranges[0]<>'0': |
|
563 | if len(ranges)>0 and ranges[0]<>'0': | |
@@ -533,20 +586,53 class RCLine(models.Model): | |||||
533 |
|
586 | |||
534 | elif self.line_type.name=='windows': |
|
587 | elif self.line_type.name=='windows': | |
535 | params = json.loads(self.params) |
|
588 | params = json.loads(self.params) | |
|
589 | ||||
536 | if 'params' in params and len(params['params'])>0: |
|
590 | if 'params' in params and len(params['params'])>0: | |
537 | print 'REFS' |
|
|||
538 | print [self.get_win_ref(pp, params['TX_ref'],km2unit) for pp in params['params']] |
|
|||
539 | y = sum([pulses(x, ipp_u, pp['resolution']*pp['number_of_samples']*km2unit, |
|
591 | y = sum([pulses(x, ipp_u, pp['resolution']*pp['number_of_samples']*km2unit, | |
540 | shift=0, |
|
592 | shift=0, | |
541 | before=int(self.rc_configuration.time_before*us2unit)+self.get_win_ref(pp, params['TX_ref'],km2unit), |
|
593 | before=int(self.rc_configuration.time_before*us2unit)+self.get_win_ref(pp, params['TX_ref'],km2unit), | |
542 | sync=self.rc_configuration.sync) for pp in params['params']]) |
|
594 | sync=self.rc_configuration.sync) for pp in params['params']]) | |
543 | tr = self.get_lines('tr')[0] |
|
595 | tr = self.get_lines(line_type__name='tr')[0] | |
544 | ranges = json.loads(tr.params)['range'].split(',') |
|
596 | ranges = json.loads(tr.params)['range'].split(',') | |
545 | if len(ranges)>0 and ranges[0]<>'0': |
|
597 | if len(ranges)>0 and ranges[0]<>'0': | |
546 | mask = create_mask(ranges, ipp_u, ntx, self.rc_configuration.sync) |
|
598 | mask = create_mask(ranges, ipp_u, ntx, self.rc_configuration.sync) | |
547 | y = y & mask |
|
599 | y = y & mask | |
548 | else: |
|
600 | else: | |
549 | y = np.zeros(ipp_u*ntx) |
|
601 | y = np.zeros(ipp_u*ntx) | |
|
602 | ||||
|
603 | elif self.line_type.name=='mix': | |||
|
604 | values = self.rc_configuration.parameters.split('-') | |||
|
605 | confs = RCConfiguration.objects.filter(pk__in=[value.split('|')[0] for value in values]) | |||
|
606 | modes = [value.split('|')[1] for value in values] | |||
|
607 | delays = [value.split('|')[2] for value in values] | |||
|
608 | masks = [value.split('|')[3] for value in values] | |||
|
609 | ||||
|
610 | y = confs[0].get_lines(channel=self.channel)[0].pulses_as_array() | |||
|
611 | ||||
|
612 | for i in range(1, len(values)): | |||
|
613 | mask = list('{:8b}'.format(int(masks[i]))) | |||
|
614 | mask.reverse() | |||
|
615 | ||||
|
616 | if mask[self.channel] in ('0', '', ' '): | |||
|
617 | continue | |||
|
618 | Y = confs[i].get_lines(channel=self.channel)[0].pulses_as_array() | |||
|
619 | delay = float(delays[i])*km2unit | |||
|
620 | if delay>0: | |||
|
621 | y_temp = np.empty_like(Y) | |||
|
622 | y_temp[:delay] = 0 | |||
|
623 | y_temp[delay:] = Y[:-delay] | |||
|
624 | ||||
|
625 | if modes[i]=='OR': | |||
|
626 | y2 = y | y_temp | |||
|
627 | elif modes[i]=='XOR': | |||
|
628 | y2 = y ^ y_temp | |||
|
629 | elif modes[i]=='AND': | |||
|
630 | y2 = y & y_temp | |||
|
631 | elif modes[i]=='NAND': | |||
|
632 | y2 = y & ~y_temp | |||
|
633 | ||||
|
634 | y = y2 | |||
|
635 | ||||
550 | else: |
|
636 | else: | |
551 | y = np.zeros(ipp_u*ntx) |
|
637 | y = np.zeros(ipp_u*ntx) | |
552 |
|
638 | |||
@@ -555,5 +641,5 class RCLine(models.Model): | |||||
555 | self.save() |
|
641 | self.save() | |
556 | else: |
|
642 | else: | |
557 | return y |
|
643 | return y | |
558 |
|
644 | |||
559 | No newline at end of file |
|
645 |
@@ -223,27 +223,28 def pulses_to_points(X): | |||||
223 | dw += 1 |
|
223 | dw += 1 | |
224 |
|
224 | |||
225 | return [(tup[0], tup[1]-tup[0]) for tup in zip(up, dw)] |
|
225 | return [(tup[0], tup[1]-tup[0]) for tup in zip(up, dw)] | |
226 |
|
||||
227 |
|
226 | |||
228 |
def pulses_from_code( |
|
227 | def pulses_from_code(X, codes, width): | |
229 |
|
228 | |||
230 | if ntx>len(codes): |
|
229 | d = X[1:]-X[:-1] | |
231 | ipp_codes = [c for __ in xrange(ntx) for c in codes][:ntx] |
|
|||
232 | else: |
|
|||
233 | ipp_codes = codes[:ntx] |
|
|||
234 |
|
230 | |||
235 | f = width/len(codes[0]) |
|
231 | up = np.where(d==1)[0] | |
|
232 | if X[0]==1: | |||
|
233 | up = np.concatenate((np.array([-1]), up)) | |||
|
234 | up += 1 | |||
236 |
|
235 | |||
237 | ipp_codes = [''.join([s*f for s in code]) for code in ipp_codes] |
|
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 |
|
238 | |||
239 | if before>0: |
|
239 | y = np.zeros(len(X)) | |
240 | sbefore = '{0:0{1}d}'.format(0, before) |
|
|||
241 | else: |
|
|||
242 | sbefore = '' |
|
|||
243 |
|
240 | |||
244 | temp = ['{0}{1}{2:0{3}d}'.format(sbefore, ipp_codes[i], 0, int(ipp)-len(ipp_codes[i])-before) for i in range(ntx)] |
|
241 | j=0 | |
|
242 | n = len(codes) | |||
|
243 | for i in up: | |||
|
244 | y[i:i+width] = codes[j%n] | |||
|
245 | j += 1 | |||
245 |
|
246 | |||
246 | return (np.fromstring(''.join(temp), dtype=np.uint8)-48).astype(np.int8) |
|
247 | return y | |
247 |
|
248 | |||
248 |
|
249 | |||
249 | def create_mask(ranges, ipp, ntx, sync): |
|
250 | def create_mask(ranges, ipp, ntx, sync): | |
@@ -301,10 +302,10 def plot_pulses(unit, maximun, lines): | |||||
301 | labels = [] |
|
302 | labels = [] | |
302 |
|
303 | |||
303 | for i, line in enumerate(lines): |
|
304 | for i, line in enumerate(lines): | |
304 | print line |
|
|||
305 | labels.append(line.get_name()) |
|
305 | labels.append(line.get_name()) | |
|
306 | l = ax.plot((0, maximun),(N-i-1, N-i-1)) | |||
306 | ax.broken_barh(pulses_to_points(line.pulses_as_array()), (N-i-1, 0.5), |
|
307 | ax.broken_barh(pulses_to_points(line.pulses_as_array()), (N-i-1, 0.5), | |
307 |
edgecolor= |
|
308 | edgecolor=l[0].get_color(), facecolor='none') | |
308 |
|
309 | |||
309 | labels.reverse() |
|
310 | labels.reverse() | |
310 | ax.set_yticklabels(labels) |
|
311 | ax.set_yticklabels(labels) |
@@ -117,13 +117,7 def conf_edit(request, conf_id): | |||||
117 | line.save() |
|
117 | line.save() | |
118 |
|
118 | |||
119 | #update pulses field |
|
119 | #update pulses field | |
120 | for line in conf.get_lines(): |
|
120 | conf.update_pulses() | |
121 | if line.line_type.name=='tr': |
|
|||
122 | continue |
|
|||
123 | line.update_pulses() |
|
|||
124 |
|
||||
125 | for tr in conf.get_lines('tr'): |
|
|||
126 | tr.update_pulses() |
|
|||
127 |
|
121 | |||
128 | messages.success(request, 'RC Configuration successfully updated') |
|
122 | messages.success(request, 'RC Configuration successfully updated') | |
129 |
|
123 | |||
@@ -376,7 +370,7 def view_pulses(request, conf_id): | |||||
376 |
|
370 | |||
377 | unit = (conf.clock/conf.clock_divider)*3./20 |
|
371 | unit = (conf.clock/conf.clock_divider)*3./20 | |
378 |
|
372 | |||
379 |
N = |
|
373 | N = conf.ipp*conf.km2unit*conf.ntx | |
380 |
|
374 | |||
381 | script, div = plot_pulses(unit, N, lines) |
|
375 | script, div = plot_pulses(unit, N, lines) | |
382 |
|
376 |
@@ -1,9 +1,12 | |||||
1 |
|
1 | |||
2 | import ast |
|
2 | import ast | |
3 | import json |
|
3 | import json | |
|
4 | from itertools import chain | |||
4 |
|
5 | |||
5 | from django import forms |
|
6 | from django import forms | |
6 | from django.utils.safestring import mark_safe |
|
7 | from django.utils.safestring import mark_safe | |
|
8 | from django.utils.encoding import force_unicode | |||
|
9 | from django.utils.html import conditional_escape | |||
7 |
|
10 | |||
8 |
|
11 | |||
9 | class KmUnitWidget(forms.widgets.TextInput): |
|
12 | class KmUnitWidget(forms.widgets.TextInput): | |
@@ -26,7 +29,7 class KmUnitWidget(forms.widgets.TextInput): | |||||
26 | if 'line' in attrs: |
|
29 | if 'line' in attrs: | |
27 | label += '_{0}'.format(attrs['line'].pk) |
|
30 | label += '_{0}'.format(attrs['line'].pk) | |
28 |
|
31 | |||
29 | html = '<div class="col-md-12 col-no-padding"><div class="col-md-5 col-no-padding"><input type="text" {0} class="form-control" id="id_{1}" name="{2}" value="{3}"></div><div class="col-md-1 col-no-padding">Km</div><div class="col-md-5 col-no-padding"><input type="text" {4} class="form-control" id="id_{5}_unit" value="{6}"></div><div class="col-md-1 col-no-padding">Units</div></div>'.format(disabled, label, name, value, disabled, label, unit) |
|
32 | html = '<div class="col-md-12 col-no-padding"><div class="col-md-5 col-no-padding"><input type="text" {0} class="form-control" id="id_{1}" name="{2}" value="{3}"></div><div class="col-md-1 col-no-padding">Km</div><div class="col-md-5 col-no-padding"><input type="text" {4} class="form-control" id="id_{5}_unit" value="{6}"></div><div class="col-md-1 col-no-padding">Units</div></div><br>'.format(disabled, label, name, value, disabled, label, unit) | |
30 |
|
33 | |||
31 | script = '''<script type="text/javascript"> |
|
34 | script = '''<script type="text/javascript"> | |
32 | $(document).ready(function () {{ |
|
35 | $(document).ready(function () {{ | |
@@ -162,7 +165,7 class KmUnitDcWidget(forms.widgets.TextInput): | |||||
162 |
|
165 | |||
163 | label += '_{0}'.format(attrs['line'].pk) |
|
166 | label += '_{0}'.format(attrs['line'].pk) | |
164 |
|
167 | |||
165 |
dc = float(json.loads(attrs['line'].params)['pulse_width'])*attrs['line'].rc_configuration.ipp |
|
168 | dc = float(json.loads(attrs['line'].params)['pulse_width'])*100/attrs['line'].rc_configuration.ipp | |
166 |
|
169 | |||
167 | html = '''<div class="col-md-12 col-no-padding"> |
|
170 | html = '''<div class="col-md-12 col-no-padding"> | |
168 | <div class="col-md-3 col-no-padding"><input type="number" {0} class="form-control" id="id_{1}" name="{2}" value="{3}"></div> |
|
171 | <div class="col-md-3 col-no-padding"><input type="number" {0} class="form-control" id="id_{1}" name="{2}" value="{3}"></div> | |
@@ -188,7 +191,7 class KmUnitDcWidget(forms.widgets.TextInput): | |||||
188 | }}); |
|
191 | }}); | |
189 |
|
192 | |||
190 | $("#id_{label}_dc").change(function() {{ |
|
193 | $("#id_{label}_dc").change(function() {{ | |
191 |
$("#id_{label}").val(parseFloat($(this).val())*parseFloat($("#id_ipp").val()) |
|
194 | $("#id_{label}").val(parseFloat($(this).val())*100/parseFloat($("#id_ipp").val())); | |
192 | $("#id_{label}_unit").val(str2unit($("#id_{label}").val())); |
|
195 | $("#id_{label}_unit").val(str2unit($("#id_{label}").val())); | |
193 | }}); |
|
196 | }}); | |
194 | }}); |
|
197 | }}); | |
@@ -242,4 +245,31 class CodesWidget(forms.widgets.Textarea): | |||||
242 | html = '<textarea rows="5" {0} class="form-control" id="id_{1}" name="{2}" style="white-space:nowrap; overflow:scroll;">{3}</textarea>'.format(disabled, label, name, codes) |
|
245 | html = '<textarea rows="5" {0} class="form-control" id="id_{1}" name="{2}" style="white-space:nowrap; overflow:scroll;">{3}</textarea>'.format(disabled, label, name, codes) | |
243 |
|
246 | |||
244 | return mark_safe(html) |
|
247 | return mark_safe(html) | |
|
248 | ||||
|
249 | class HCheckboxSelectMultiple(forms.CheckboxSelectMultiple): | |||
|
250 | ||||
|
251 | def render(self, name, value, attrs=None, choices=()): | |||
|
252 | ||||
|
253 | if value is None: value = [] | |||
|
254 | has_id = attrs and 'id' in attrs | |||
|
255 | final_attrs = self.build_attrs(attrs, name=name) | |||
|
256 | output = [u'<br><ul>'] | |||
|
257 | # Normalize to strings | |||
|
258 | str_values = set([force_unicode(v) for v in value]) | |||
|
259 | for i, (option_value, option_label) in enumerate(chain(self.choices, choices)): | |||
|
260 | # If an ID attribute was given, add a numeric index as a suffix, | |||
|
261 | # so that the checkboxes don't all have the same ID attribute. | |||
|
262 | if has_id: | |||
|
263 | final_attrs = dict(final_attrs, id='%s_%s' % (attrs['id'], i)) | |||
|
264 | label_for = u' for="%s"' % final_attrs['id'] | |||
|
265 | else: | |||
|
266 | label_for = '' | |||
|
267 | ||||
|
268 | cb = forms.CheckboxInput(final_attrs, check_test=lambda value: value in str_values) | |||
|
269 | option_value = force_unicode(option_value) | |||
|
270 | rendered_cb = cb.render(name, option_value) | |||
|
271 | option_label = conditional_escape(force_unicode(option_label)) | |||
|
272 | output.append(u'<span><label%s>%s %s</label></span>' % (label_for, rendered_cb, option_label)) | |||
|
273 | output.append(u'</div><br>') | |||
|
274 | return mark_safe(u'\n'.join(output)) | |||
245 | No newline at end of file |
|
275 |
General Comments 0
You need to be logged in to leave comments.
Login now