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