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