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