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