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