##// END OF EJS Templates
Fix windows line ranges in RC model
jespinoza -
r303:d316309a4704
parent child
Show More
@@ -1,1002 +1,999
1
1
2
2
3 import ast
3 import ast
4 import json
4 import json
5 import requests
5 import requests
6 import numpy as np
6 import numpy as np
7 from base64 import b64encode
7 from base64 import b64encode
8 from struct import pack
8 from struct import pack
9
9
10 from django.db import models
10 from django.db import models
11 from django.core.urlresolvers import reverse
11 from django.core.urlresolvers import reverse
12 from django.core.validators import MinValueValidator, MaxValueValidator
12 from django.core.validators import MinValueValidator, MaxValueValidator
13
13
14 from apps.main.models import Configuration
14 from apps.main.models import Configuration
15 from apps.main.utils import Params
15 from apps.main.utils import Params
16 from devices.rc import api
16 from devices.rc import api
17 from apps.rc.utils import RCFile
17 from apps.rc.utils import RCFile
18
18
19
19
20 LINE_TYPES = (
20 LINE_TYPES = (
21 ('none', 'Not used'),
21 ('none', 'Not used'),
22 ('tr', 'Transmission/reception selector signal'),
22 ('tr', 'Transmission/reception selector signal'),
23 ('tx', 'A modulating signal (Transmission pulse)'),
23 ('tx', 'A modulating signal (Transmission pulse)'),
24 ('codes', 'BPSK modulating signal'),
24 ('codes', 'BPSK modulating signal'),
25 ('windows', 'Sample window signal'),
25 ('windows', 'Sample window signal'),
26 ('sync', 'Synchronizing signal'),
26 ('sync', 'Synchronizing signal'),
27 ('flip', 'IPP related periodic signal'),
27 ('flip', 'IPP related periodic signal'),
28 ('prog_pulses', 'Programmable pulse'),
28 ('prog_pulses', 'Programmable pulse'),
29 ('mix', 'Mixed line'),
29 ('mix', 'Mixed line'),
30 )
30 )
31
31
32
32
33 SAMPLING_REFS = (
33 SAMPLING_REFS = (
34 ('none', 'No Reference'),
34 ('none', 'No Reference'),
35 ('begin_baud', 'Begin of the first baud'),
35 ('begin_baud', 'Begin of the first baud'),
36 ('first_baud', 'Middle of the first baud'),
36 ('first_baud', 'Middle of the first baud'),
37 ('sub_baud', 'Middle of the sub-baud')
37 ('sub_baud', 'Middle of the sub-baud')
38 )
38 )
39
39
40 DAT_CMDS = {
40 DAT_CMDS = {
41 # Pulse Design commands
41 # Pulse Design commands
42 'DISABLE' : 0, # Disables pulse generation
42 'DISABLE' : 0, # Disables pulse generation
43 'ENABLE' : 24, # Enables pulse generation
43 'ENABLE' : 24, # Enables pulse generation
44 'DELAY_START' : 40, # Write delay status to memory
44 'DELAY_START' : 40, # Write delay status to memory
45 'FLIP_START' : 48, # Write flip status to memory
45 'FLIP_START' : 48, # Write flip status to memory
46 'SAMPLING_PERIOD' : 64, # Establish Sampling Period
46 'SAMPLING_PERIOD' : 64, # Establish Sampling Period
47 'TX_ONE' : 72, # Output '0' in line TX
47 'TX_ONE' : 72, # Output '0' in line TX
48 'TX_ZERO' : 88, # Output '0' in line TX
48 'TX_ZERO' : 88, # Output '0' in line TX
49 'SW_ONE' : 104, # Output '0' in line SW
49 'SW_ONE' : 104, # Output '0' in line SW
50 'SW_ZERO' : 112, # Output '1' in line SW
50 'SW_ZERO' : 112, # Output '1' in line SW
51 'RESTART': 120, # Restarts CR8 Firmware
51 'RESTART': 120, # Restarts CR8 Firmware
52 'CONTINUE' : 253, # Function Unknown
52 'CONTINUE' : 253, # Function Unknown
53 # Commands available to new controllers
53 # Commands available to new controllers
54 # 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.
54 # 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.
55 'CLOCK_DIVISOR_INIT' : 12, # Specifies Clock Divisor. Legacy command, ignored in the actual .dat conversion
55 'CLOCK_DIVISOR_INIT' : 12, # Specifies Clock Divisor. Legacy command, ignored in the actual .dat conversion
56 'CLOCK_DIVISOR_LAST' : 22, # Specifies Clock Divisor (default 60 if not included) syntax: 255,22 254,N-1.
56 'CLOCK_DIVISOR_LAST' : 22, # Specifies Clock Divisor (default 60 if not included) syntax: 255,22 254,N-1.
57 'CLOCK_DIVIDER' : 8,
57 'CLOCK_DIVIDER' : 8,
58 }
58 }
59
59
60 MAX_BITS = 8
60 MAX_BITS = 8
61
61
62 # Rotate left: 0b1001 --> 0b0011
62 # Rotate left: 0b1001 --> 0b0011
63 rol = lambda val, r_bits: \
63 rol = lambda val, r_bits: \
64 (val << r_bits%MAX_BITS) & (2**MAX_BITS-1) | \
64 (val << r_bits%MAX_BITS) & (2**MAX_BITS-1) | \
65 ((val & (2**MAX_BITS-1)) >> (MAX_BITS-(r_bits%MAX_BITS)))
65 ((val & (2**MAX_BITS-1)) >> (MAX_BITS-(r_bits%MAX_BITS)))
66
66
67 # Rotate right: 0b1001 --> 0b1100
67 # Rotate right: 0b1001 --> 0b1100
68 ror = lambda val, r_bits: \
68 ror = lambda val, r_bits: \
69 ((val & (2**MAX_BITS-1)) >> r_bits%MAX_BITS) | \
69 ((val & (2**MAX_BITS-1)) >> r_bits%MAX_BITS) | \
70 (val << (MAX_BITS-(r_bits%MAX_BITS)) & (2**MAX_BITS-1))
70 (val << (MAX_BITS-(r_bits%MAX_BITS)) & (2**MAX_BITS-1))
71
71
72
72
73 class RCConfiguration(Configuration):
73 class RCConfiguration(Configuration):
74
74
75 ipp = models.FloatField(verbose_name='IPP [Km]', validators=[MinValueValidator(1)], default=300)
75 ipp = models.FloatField(verbose_name='IPP [Km]', validators=[MinValueValidator(1)], default=300)
76 ntx = models.PositiveIntegerField(verbose_name='Number of TX', validators=[MinValueValidator(1)], default=1)
76 ntx = models.PositiveIntegerField(verbose_name='Number of TX', validators=[MinValueValidator(1)], default=1)
77 clock_in = models.FloatField(verbose_name='Clock in [MHz]', validators=[MinValueValidator(1), MaxValueValidator(80)], default=1)
77 clock_in = models.FloatField(verbose_name='Clock in [MHz]', validators=[MinValueValidator(1), MaxValueValidator(80)], default=1)
78 clock_divider = models.PositiveIntegerField(verbose_name='Clock divider', validators=[MinValueValidator(1), MaxValueValidator(256)], default=1)
78 clock_divider = models.PositiveIntegerField(verbose_name='Clock divider', validators=[MinValueValidator(1), MaxValueValidator(256)], default=1)
79 clock = models.FloatField(verbose_name='Clock Master [MHz]', blank=True, default=1)
79 clock = models.FloatField(verbose_name='Clock Master [MHz]', blank=True, default=1)
80 time_before = models.PositiveIntegerField(verbose_name='Time before [&mu;S]', default=12)
80 time_before = models.PositiveIntegerField(verbose_name='Time before [&mu;S]', default=12)
81 time_after = models.PositiveIntegerField(verbose_name='Time after [&mu;S]', default=1)
81 time_after = models.PositiveIntegerField(verbose_name='Time after [&mu;S]', default=1)
82 sync = models.PositiveIntegerField(verbose_name='Synchro delay', default=0)
82 sync = models.PositiveIntegerField(verbose_name='Synchro delay', default=0)
83 sampling_reference = models.CharField(verbose_name='Sampling Reference', choices=SAMPLING_REFS, default='none', max_length=40)
83 sampling_reference = models.CharField(verbose_name='Sampling Reference', choices=SAMPLING_REFS, default='none', max_length=40)
84 control_tx = models.BooleanField(verbose_name='Control Switch TX', default=False)
84 control_tx = models.BooleanField(verbose_name='Control Switch TX', default=False)
85 control_sw = models.BooleanField(verbose_name='Control Switch SW', default=False)
85 control_sw = models.BooleanField(verbose_name='Control Switch SW', default=False)
86 total_units = models.PositiveIntegerField(default=0)
86 total_units = models.PositiveIntegerField(default=0)
87 mix = models.BooleanField(default=False)
87 mix = models.BooleanField(default=False)
88
88
89 class Meta:
89 class Meta:
90 db_table = 'rc_configurations'
90 db_table = 'rc_configurations'
91
91
92 def get_absolute_url_plot(self):
92 def get_absolute_url_plot(self):
93 return reverse('url_plot_rc_pulses', args=[str(self.id)])
93 return reverse('url_plot_rc_pulses', args=[str(self.id)])
94
94
95 @property
95 @property
96 def ipp_unit(self):
96 def ipp_unit(self):
97
97
98 return '{} ({})'.format(self.ipp, int(self.ipp*self.km2unit))
98 return '{} ({})'.format(self.ipp, int(self.ipp*self.km2unit))
99
99
100 @property
100 @property
101 def us2unit(self):
101 def us2unit(self):
102
102
103 return self.clock_in/self.clock_divider
103 return self.clock_in/self.clock_divider
104
104
105 @property
105 @property
106 def km2unit(self):
106 def km2unit(self):
107
107
108 return 20./3*(self.clock_in/self.clock_divider)
108 return 20./3*(self.clock_in/self.clock_divider)
109
109
110 def clone(self, **kwargs):
110 def clone(self, **kwargs):
111
111
112 lines = self.get_lines()
112 lines = self.get_lines()
113 self.pk = None
113 self.pk = None
114 self.id = None
114 self.id = None
115 for attr, value in kwargs.items():
115 for attr, value in kwargs.items():
116 setattr(self, attr, value)
116 setattr(self, attr, value)
117 self.save()
117 self.save()
118
118
119 for line in lines:
119 for line in lines:
120 line.clone(rc_configuration=self)
120 line.clone(rc_configuration=self)
121
121
122 new_lines = self.get_lines()
122 new_lines = self.get_lines()
123 for line in new_lines:
123 for line in new_lines:
124 line_params = json.loads(line.params)
124 line_params = json.loads(line.params)
125 if 'TX_ref' in line_params and (line_params['TX_ref'] != '0'):
125 if 'TX_ref' in line_params and (line_params['TX_ref'] != '0'):
126 ref_line = RCLine.objects.get(pk=line_params['TX_ref'])
126 ref_line = RCLine.objects.get(pk=line_params['TX_ref'])
127 line_params['TX_ref'] = ['{}'.format(l.pk) for l in new_lines if l.get_name()==ref_line.get_name()][0]
127 line_params['TX_ref'] = ['{}'.format(l.pk) for l in new_lines if l.get_name()==ref_line.get_name()][0]
128 line.params = json.dumps(line_params)
128 line.params = json.dumps(line_params)
129 line.save()
129 line.save()
130
130
131 return self
131 return self
132
132
133 def get_lines(self, **kwargs):
133 def get_lines(self, **kwargs):
134 '''
134 '''
135 Retrieve configuration lines
135 Retrieve configuration lines
136 '''
136 '''
137
137
138 return RCLine.objects.filter(rc_configuration=self.pk, **kwargs)
138 return RCLine.objects.filter(rc_configuration=self.pk, **kwargs)
139
139
140
140
141 def clean_lines(self):
141 def clean_lines(self):
142 '''
142 '''
143 '''
143 '''
144
144
145 empty_line = RCLineType.objects.get(name='none')
145 empty_line = RCLineType.objects.get(name='none')
146
146
147 for line in self.get_lines():
147 for line in self.get_lines():
148 line.line_type = empty_line
148 line.line_type = empty_line
149 line.params = '{}'
149 line.params = '{}'
150 line.save()
150 line.save()
151
151
152 def dict_to_parms(self, params, id=None):
152 def dict_to_parms(self, params, id=None):
153 '''
153 '''
154 '''
154 '''
155
155
156 if id:
156 if id:
157 data = Params(params).get_conf(id_conf=id)
157 data = Params(params).get_conf(id_conf=id)
158 else:
158 else:
159 data = Params(params).get_conf(dtype='rc')
159 data = Params(params).get_conf(dtype='rc')
160
160
161 self.name = data['name']
161 self.name = data['name']
162 self.ipp = data['ipp']
162 self.ipp = data['ipp']
163 self.ntx = data['ntx']
163 self.ntx = data['ntx']
164 self.clock_in = data['clock_in']
164 self.clock_in = data['clock_in']
165 self.clock_divider = data['clock_divider']
165 self.clock_divider = data['clock_divider']
166 self.clock = data['clock']
166 self.clock = data['clock']
167 self.time_before = data['time_before']
167 self.time_before = data['time_before']
168 self.time_after = data['time_after']
168 self.time_after = data['time_after']
169 self.sync = data['sync']
169 self.sync = data['sync']
170 self.sampling_reference = data['sampling_reference']
170 self.sampling_reference = data['sampling_reference']
171 self.total_units = self.ipp*self.ntx*self.km2unit
171 self.total_units = self.ipp*self.ntx*self.km2unit
172 self.save()
172 self.save()
173 self.clean_lines()
173 self.clean_lines()
174
174
175 positions = {'tx':0, 'tr':0}
175 positions = {'tx':0, 'tr':0}
176 for i, id in enumerate(data['lines']):
176 for i, id in enumerate(data['lines']):
177 line_data = params['lines']['byId'][id]
177 line_data = params['lines']['byId'][id]
178 line_type = RCLineType.objects.get(name=line_data['line_type'])
178 line_type = RCLineType.objects.get(name=line_data['line_type'])
179 if line_type.name == 'codes':
179 if line_type.name == 'codes':
180 code = RCLineCode.objects.get(name=line_data['params']['code'])
180 code = RCLineCode.objects.get(name=line_data['params']['code'])
181 line_data['params']['code'] = code.pk
181 line_data['params']['code'] = code.pk
182 if line_type.name == 'tx':
182 if line_type.name == 'tx':
183 position = positions['tx']
183 position = positions['tx']
184 positions['tx'] += 1
184 positions['tx'] += 1
185 elif line_type.name == 'tr':
185 elif line_type.name == 'tr':
186 position = positions['tr']
186 position = positions['tr']
187 positions['tr'] += 1
187 positions['tr'] += 1
188 else:
188 else:
189 position = 0
189 position = 0
190 line, dum = RCLine.objects.update_or_create(
190 line, dum = RCLine.objects.update_or_create(
191 rc_configuration=self,
191 rc_configuration=self,
192 channel=i,
192 channel=i,
193 position=position,
193 position=position,
194 defaults={
194 defaults={
195 'line_type': line_type,
195 'line_type': line_type,
196 'params': json.dumps(line_data['params'])
196 'params': json.dumps(line_data['params'])
197 }
197 }
198 )
198 )
199
199
200 for i, line in enumerate(self.get_lines()):
200 for i, line in enumerate(self.get_lines()):
201 line_params = json.loads(line.params)
201 line_params = json.loads(line.params)
202 if 'TX_ref' in line_params:
202 if 'TX_ref' in line_params:
203 if line_params['TX_ref'] in (0, '0'):
203 if line_params['TX_ref'] in (0, '0'):
204 line_params['TX_ref'] = '0'
204 line_params['TX_ref'] = '0'
205 else:
205 else:
206 ref_id = '{}'.format(line_params['TX_ref'])
206 ref_id = '{}'.format(line_params['TX_ref'])
207 ref_line = params['lines']['byId'][ref_id]
207 ref_line = params['lines']['byId'][ref_id]
208 line_params['TX_ref'] = RCLine.objects.get(
208 line_params['TX_ref'] = RCLine.objects.get(
209 rc_configuration=self,
209 rc_configuration=self,
210 params=json.dumps(ref_line['params'])
210 params=json.dumps(ref_line['params'])
211 ).pk
211 ).pk
212 line.params = json.dumps(line_params)
212 line.params = json.dumps(line_params)
213 line.save()
213 line.save()
214
214
215
215
216 def get_delays(self):
216 def get_delays(self):
217
217
218 pulses = [line.pulses_as_points() for line in self.get_lines()]
218 pulses = [line.pulses_as_points() for line in self.get_lines()]
219 points = [tup for tups in pulses for tup in tups]
219 points = [tup for tups in pulses for tup in tups]
220 points = set([x for tup in points for x in tup])
220 points = set([x for tup in points for x in tup])
221 points = list(points)
221 points = list(points)
222 points.sort()
222 points.sort()
223
223
224 if points[0]!=0:
224 if points[0]!=0:
225 points.insert(0, 0)
225 points.insert(0, 0)
226
226
227 return [points[i+1]-points[i] for i in range(len(points)-1)]
227 return [points[i+1]-points[i] for i in range(len(points)-1)]
228
228
229
229
230 def get_pulses(self, binary=True):
230 def get_pulses(self, binary=True):
231
231
232 pulses = [line.pulses_as_points() for line in self.get_lines()]
232 pulses = [line.pulses_as_points() for line in self.get_lines()]
233 tuples = [tup for tups in pulses for tup in tups]
233 tuples = [tup for tups in pulses for tup in tups]
234 points = set([x for tup in tuples for x in tup])
234 points = set([x for tup in tuples for x in tup])
235 points = list(points)
235 points = list(points)
236 points.sort()
236 points.sort()
237 states = []
237 states = []
238 last = [0 for x in pulses]
238 last = [0 for x in pulses]
239
239
240 for x in points:
240 for x in points:
241 dum = []
241 dum = []
242 for i, tups in enumerate(pulses):
242 for i, tups in enumerate(pulses):
243 ups = [tup[0] for tup in tups if tup!=(0,0)]
243 ups = [tup[0] for tup in tups if tup!=(0,0)]
244 dws = [tup[1] for tup in tups if tup!=(0,0)]
244 dws = [tup[1] for tup in tups if tup!=(0,0)]
245 if x in ups:
245 if x in ups:
246 dum.append(1)
246 dum.append(1)
247 elif x in dws:
247 elif x in dws:
248 dum.append(0)
248 dum.append(0)
249 else:
249 else:
250 dum.append(last[i])
250 dum.append(last[i])
251 states.append(dum)
251 states.append(dum)
252 last = dum
252 last = dum
253
253
254 if binary:
254 if binary:
255 ret = []
255 ret = []
256 for flips in states:
256 for flips in states:
257 flips.reverse()
257 flips.reverse()
258 ret.append(int(''.join([str(x) for x in flips]), 2))
258 ret.append(int(''.join([str(x) for x in flips]), 2))
259 states = ret
259 states = ret
260
260
261 return states[:-1]
261 return states[:-1]
262
262
263 def add_cmd(self, cmd):
263 def add_cmd(self, cmd):
264
264
265 if cmd in DAT_CMDS:
265 if cmd in DAT_CMDS:
266 return (255, DAT_CMDS[cmd])
266 return (255, DAT_CMDS[cmd])
267
267
268 def add_data(self, value):
268 def add_data(self, value):
269
269
270 return (254, value-1)
270 return (254, value-1)
271
271
272 def parms_to_binary(self, dat=True):
272 def parms_to_binary(self, dat=True):
273 '''
273 '''
274 Create "dat" stream to be send to CR
274 Create "dat" stream to be send to CR
275 '''
275 '''
276
276
277 data = bytearray()
277 data = bytearray()
278 # create header
278 # create header
279 data.extend(self.add_cmd('DISABLE'))
279 data.extend(self.add_cmd('DISABLE'))
280 data.extend(self.add_cmd('CONTINUE'))
280 data.extend(self.add_cmd('CONTINUE'))
281 data.extend(self.add_cmd('RESTART'))
281 data.extend(self.add_cmd('RESTART'))
282
282
283 if self.control_sw:
283 if self.control_sw:
284 data.extend(self.add_cmd('SW_ONE'))
284 data.extend(self.add_cmd('SW_ONE'))
285 else:
285 else:
286 data.extend(self.add_cmd('SW_ZERO'))
286 data.extend(self.add_cmd('SW_ZERO'))
287
287
288 if self.control_tx:
288 if self.control_tx:
289 data.extend(self.add_cmd('TX_ONE'))
289 data.extend(self.add_cmd('TX_ONE'))
290 else:
290 else:
291 data.extend(self.add_cmd('TX_ZERO'))
291 data.extend(self.add_cmd('TX_ZERO'))
292
292
293 # write divider
293 # write divider
294 data.extend(self.add_cmd('CLOCK_DIVIDER'))
294 data.extend(self.add_cmd('CLOCK_DIVIDER'))
295 data.extend(self.add_data(self.clock_divider))
295 data.extend(self.add_data(self.clock_divider))
296
296
297 # write delays
297 # write delays
298 data.extend(self.add_cmd('DELAY_START'))
298 data.extend(self.add_cmd('DELAY_START'))
299 # first delay is always zero
299 # first delay is always zero
300 data.extend(self.add_data(1))
300 data.extend(self.add_data(1))
301
301
302 delays = self.get_delays()
302 delays = self.get_delays()
303
303
304 for delay in delays:
304 for delay in delays:
305 while delay>252:
305 while delay>252:
306 data.extend(self.add_data(253))
306 data.extend(self.add_data(253))
307 delay -= 253
307 delay -= 253
308 data.extend(self.add_data(int(delay)))
308 data.extend(self.add_data(int(delay)))
309
309
310 # write flips
310 # write flips
311 data.extend(self.add_cmd('FLIP_START'))
311 data.extend(self.add_cmd('FLIP_START'))
312
312
313 states = self.get_pulses(binary=True)
313 states = self.get_pulses(binary=True)
314
314
315
315
316 last = 0
316 last = 0
317 for flip, delay in zip(states, delays):
317 for flip, delay in zip(states, delays):
318 data.extend(self.add_data((flip^last)+1))
318 data.extend(self.add_data((flip^last)+1))
319 last = flip
319 last = flip
320 while delay>252:
320 while delay>252:
321 data.extend(self.add_data(1))
321 data.extend(self.add_data(1))
322 delay -= 253
322 delay -= 253
323
323
324 # write sampling period
324 # write sampling period
325 data.extend(self.add_cmd('SAMPLING_PERIOD'))
325 data.extend(self.add_cmd('SAMPLING_PERIOD'))
326 wins = self.get_lines(line_type__name='windows')
326 wins = self.get_lines(line_type__name='windows')
327 if wins:
327 if wins:
328 win_params = json.loads(wins[0].params)['params']
328 win_params = json.loads(wins[0].params)['params']
329 if win_params:
329 if win_params:
330 dh = int(win_params[0]['resolution']*self.km2unit)
330 dh = int(win_params[0]['resolution']*self.km2unit)
331 else:
331 else:
332 dh = 1
332 dh = 1
333 else:
333 else:
334 dh = 1
334 dh = 1
335 data.extend(self.add_data(dh))
335 data.extend(self.add_data(dh))
336
336
337 # write enable
337 # write enable
338 data.extend(self.add_cmd('ENABLE'))
338 data.extend(self.add_cmd('ENABLE'))
339
339
340 if not dat:
340 if not dat:
341 return data
341 return data
342
342
343 return '\n'.join(['{}'.format(x) for x in data])
343 return '\n'.join(['{}'.format(x) for x in data])
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_pulses2(self, km=False):
350 def plot_pulses2(self, km=False):
351
351
352 import matplotlib
352 import matplotlib
353 matplotlib.use('Agg')
353 matplotlib.use('Agg')
354 import matplotlib.pyplot as plt
354 import matplotlib.pyplot as plt
355 from bokeh.resources import CDN
355 from bokeh.resources import CDN
356 from bokeh.embed import components
356 from bokeh.embed import components
357 from bokeh.mpl import to_bokeh
357 from bokeh.mpl import to_bokeh
358 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, HoverTool, SaveTool
358 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, HoverTool, SaveTool
359
359
360 lines = self.get_lines()
360 lines = self.get_lines()
361
361
362 N = len(lines)
362 N = len(lines)
363 npoints = self.total_units/self.km2unit if km else self.total_units
363 npoints = self.total_units/self.km2unit if km else self.total_units
364 fig = plt.figure(figsize=(12, 2+N*0.5))
364 fig = plt.figure(figsize=(12, 2+N*0.5))
365 ax = fig.add_subplot(111)
365 ax = fig.add_subplot(111)
366 labels = ['IPP']
366 labels = ['IPP']
367
367
368 for i, line in enumerate(lines):
368 for i, line in enumerate(lines):
369 labels.append(line.get_name(channel=True))
369 labels.append(line.get_name(channel=True))
370 l = ax.plot((0, npoints),(N-i-1, N-i-1))
370 l = ax.plot((0, npoints),(N-i-1, N-i-1))
371 points = [(tup[0], tup[1]-tup[0]) for tup in line.pulses_as_points(km=km) if tup!=(0,0)]
371 points = [(tup[0], tup[1]-tup[0]) for tup in line.pulses_as_points(km=km) if tup!=(0,0)]
372 ax.broken_barh(points, (N-i-1, 0.5),
372 ax.broken_barh(points, (N-i-1, 0.5),
373 edgecolor=l[0].get_color(), facecolor='none')
373 edgecolor=l[0].get_color(), facecolor='none')
374
374
375 n = 0
375 n = 0
376 f = ((self.ntx+50)/100)*5 if ((self.ntx+50)/100)*10>0 else 2
376 f = ((self.ntx+50)/100)*5 if ((self.ntx+50)/100)*10>0 else 2
377 for x in np.arange(0, npoints, self.ipp if km else self.ipp*self.km2unit):
377 for x in np.arange(0, npoints, self.ipp if km else self.ipp*self.km2unit):
378 if n%f==0:
378 if n%f==0:
379 ax.text(x, N, '%s' % n, size=10)
379 ax.text(x, N, '%s' % n, size=10)
380 n += 1
380 n += 1
381
381
382 labels.reverse()
382 labels.reverse()
383 ax.set_yticks(range(len(labels)))
383 ax.set_yticks(range(len(labels)))
384 ax.set_yticklabels(labels)
384 ax.set_yticklabels(labels)
385 ax.set_xlabel = 'Units'
385 ax.set_xlabel = 'Units'
386 plot = to_bokeh(fig, use_pandas=False)
386 plot = to_bokeh(fig, use_pandas=False)
387 plot.tools = [PanTool(dimensions=['width']), WheelZoomTool(dimensions=['width']), ResetTool(), SaveTool()]
387 plot.tools = [PanTool(dimensions=['width']), WheelZoomTool(dimensions=['width']), ResetTool(), SaveTool()]
388 plot.toolbar_location="above"
388 plot.toolbar_location="above"
389
389
390 return components(plot, CDN)
390 return components(plot, CDN)
391
391
392 def plot_pulses(self, km=False):
392 def plot_pulses(self, km=False):
393
393
394 from bokeh.plotting import figure
394 from bokeh.plotting import figure
395 from bokeh.resources import CDN
395 from bokeh.resources import CDN
396 from bokeh.embed import components
396 from bokeh.embed import components
397 from bokeh.models import FixedTicker, PrintfTickFormatter
397 from bokeh.models import FixedTicker, PrintfTickFormatter
398 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, HoverTool, SaveTool
398 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, HoverTool, SaveTool
399 from bokeh.models.sources import ColumnDataSource
399 from bokeh.models.sources import ColumnDataSource
400
400
401 lines = self.get_lines().reverse()
401 lines = self.get_lines().reverse()
402
402
403 N = len(lines)
403 N = len(lines)
404 npoints = self.total_units/self.km2unit if km else self.total_units
404 npoints = self.total_units/self.km2unit if km else self.total_units
405 ipp = self.ipp if km else self.ipp*self.km2unit
405 ipp = self.ipp if km else self.ipp*self.km2unit
406
406
407 hover = HoverTool(tooltips=[("Line", "@name"),
407 hover = HoverTool(tooltips=[("Line", "@name"),
408 ("IPP", "@ipp"),
408 ("IPP", "@ipp"),
409 ("X", "@left")])
409 ("X", "@left")])
410
410
411 tools = [PanTool(dimensions=['width']),
411 tools = [PanTool(dimensions=['width']),
412 WheelZoomTool(dimensions=['width']),
412 WheelZoomTool(dimensions=['width']),
413 hover, SaveTool()]
413 hover, SaveTool()]
414
414
415 plot = figure(width=1000,
415 plot = figure(width=1000,
416 height=40+N*50,
416 height=40+N*50,
417 y_range = (0, N),
417 y_range = (0, N),
418 tools=tools,
418 tools=tools,
419 toolbar_location='above',
419 toolbar_location='above',
420 toolbar_sticky=False,)
420 toolbar_sticky=False,)
421
421
422 plot.xaxis.axis_label = 'Km' if km else 'Units'
422 plot.xaxis.axis_label = 'Km' if km else 'Units'
423 plot.xaxis[0].formatter = PrintfTickFormatter(format='%d')
423 plot.xaxis[0].formatter = PrintfTickFormatter(format='%d')
424 plot.yaxis.axis_label = 'Pulses'
424 plot.yaxis.axis_label = 'Pulses'
425 plot.yaxis[0].ticker=FixedTicker(ticks=list(range(N)))
425 plot.yaxis[0].ticker=FixedTicker(ticks=list(range(N)))
426 plot.yaxis[0].formatter = PrintfTickFormatter(format='Line %d')
426 plot.yaxis[0].formatter = PrintfTickFormatter(format='Line %d')
427
427
428 for i, line in enumerate(lines):
428 for i, line in enumerate(lines):
429
429
430 points = [tup for tup in line.pulses_as_points(km=km) if tup!=(0,0)]
430 points = [tup for tup in line.pulses_as_points(km=km) if tup!=(0,0)]
431
431
432 source = ColumnDataSource(data = dict(
432 source = ColumnDataSource(data = dict(
433 bottom = [i for tup in points],
433 bottom = [i for tup in points],
434 top = [i+0.5 for tup in points],
434 top = [i+0.5 for tup in points],
435 left = [tup[0] for tup in points],
435 left = [tup[0] for tup in points],
436 right = [tup[1] for tup in points],
436 right = [tup[1] for tup in points],
437 ipp = [int(tup[0]/ipp) for tup in points],
437 ipp = [int(tup[0]/ipp) for tup in points],
438 name = [line.get_name() for tup in points]
438 name = [line.get_name() for tup in points]
439 ))
439 ))
440
440
441 plot.quad(
441 plot.quad(
442 bottom = 'bottom',
442 bottom = 'bottom',
443 top = 'top',
443 top = 'top',
444 left = 'left',
444 left = 'left',
445 right = 'right',
445 right = 'right',
446 source = source,
446 source = source,
447 fill_alpha = 0,
447 fill_alpha = 0,
448 #line_color = 'blue',
448 #line_color = 'blue',
449 )
449 )
450
450
451 plot.line([0, npoints], [i, i])#, color='blue')
451 plot.line([0, npoints], [i, i])#, color='blue')
452
452
453 return components(plot, CDN)
453 return components(plot, CDN)
454
454
455 def request(self, cmd, method='get', **kwargs):
455 def request(self, cmd, method='get', **kwargs):
456
456
457 req = getattr(requests, method)(self.device.url(cmd), **kwargs)
457 req = getattr(requests, method)(self.device.url(cmd), **kwargs)
458 payload = req.json()
458 payload = req.json()
459
459
460 return payload
460 return payload
461
461
462 def status_device(self):
462 def status_device(self):
463
463
464 try:
464 try:
465 self.device.status = 0
465 self.device.status = 0
466 payload = self.request('status')
466 payload = self.request('status')
467 if payload['status']=='enable':
467 if payload['status']=='enable':
468 self.device.status = 3
468 self.device.status = 3
469 elif payload['status']=='disable':
469 elif payload['status']=='disable':
470 self.device.status = 2
470 self.device.status = 2
471 else:
471 else:
472 self.device.status = 1
472 self.device.status = 1
473 self.device.save()
473 self.device.save()
474 self.message = 'RC status: {}'.format(payload['status'])
474 self.message = 'RC status: {}'.format(payload['status'])
475 return False
475 return False
476 except Exception as e:
476 except Exception as e:
477 if 'No route to host' not in str(e):
477 if 'No route to host' not in str(e):
478 self.device.status = 4
478 self.device.status = 4
479 self.device.save()
479 self.device.save()
480 self.message = 'RC status: {}'.format(str(e))
480 self.message = 'RC status: {}'.format(str(e))
481 return False
481 return False
482
482
483 self.device.save()
483 self.device.save()
484 return True
484 return True
485
485
486 def reset_device(self):
486 def reset_device(self):
487
487
488 try:
488 try:
489 payload = self.request('reset', 'post')
489 payload = self.request('reset', 'post')
490 if payload['reset']=='ok':
490 if payload['reset']=='ok':
491 self.message = 'RC restarted OK'
491 self.message = 'RC restarted OK'
492 self.device.status = 2
492 self.device.status = 2
493 self.device.save()
493 self.device.save()
494 else:
494 else:
495 self.message = 'RC restart fail'
495 self.message = 'RC restart fail'
496 self.device.status = 4
496 self.device.status = 4
497 self.device.save()
497 self.device.save()
498 except Exception as e:
498 except Exception as e:
499 self.message = 'RC reset: {}'.format(str(e))
499 self.message = 'RC reset: {}'.format(str(e))
500 return False
500 return False
501
501
502 return True
502 return True
503
503
504 def stop_device(self):
504 def stop_device(self):
505
505
506 try:
506 try:
507 payload = self.request('stop', 'post')
507 payload = self.request('stop', 'post')
508 self.message = 'RC stop: {}'.format(payload['stop'])
508 self.message = 'RC stop: {}'.format(payload['stop'])
509 if payload['stop']=='ok':
509 if payload['stop']=='ok':
510 self.device.status = 2
510 self.device.status = 2
511 self.device.save()
511 self.device.save()
512 else:
512 else:
513 self.device.status = 4
513 self.device.status = 4
514 self.device.save()
514 self.device.save()
515 return False
515 return False
516 except Exception as e:
516 except Exception as e:
517 if 'No route to host' not in str(e):
517 if 'No route to host' not in str(e):
518 self.device.status = 4
518 self.device.status = 4
519 else:
519 else:
520 self.device.status = 0
520 self.device.status = 0
521 self.message = 'RC stop: {}'.format(str(e))
521 self.message = 'RC stop: {}'.format(str(e))
522 self.device.save()
522 self.device.save()
523 return False
523 return False
524
524
525 return True
525 return True
526
526
527 def start_device(self):
527 def start_device(self):
528
528
529 try:
529 try:
530 payload = self.request('start', 'post')
530 payload = self.request('start', 'post')
531 self.message = 'RC start: {}'.format(payload['start'])
531 self.message = 'RC start: {}'.format(payload['start'])
532 if payload['start']=='ok':
532 if payload['start']=='ok':
533 self.device.status = 3
533 self.device.status = 3
534 self.device.save()
534 self.device.save()
535 else:
535 else:
536 return False
536 return False
537 except Exception as e:
537 except Exception as e:
538 if 'No route to host' not in str(e):
538 if 'No route to host' not in str(e):
539 self.device.status = 4
539 self.device.status = 4
540 else:
540 else:
541 self.device.status = 0
541 self.device.status = 0
542 self.message = 'RC start: {}'.format(str(e))
542 self.message = 'RC start: {}'.format(str(e))
543 self.device.save()
543 self.device.save()
544 return False
544 return False
545
545
546 return True
546 return True
547
547
548 def write_device(self):
548 def write_device(self):
549
549
550 #values = zip(self.get_pulses(), [x-1 for x in self.get_delays()])
550 #values = zip(self.get_pulses(), [x-1 for x in self.get_delays()])
551
551
552 values = []
552 values = []
553 for pulse, delay in zip(self.get_pulses(), self.get_delays()):
553 for pulse, delay in zip(self.get_pulses(), self.get_delays()):
554 while delay>65536:
554 while delay>65536:
555 values.append((pulse, 65535))
555 values.append((pulse, 65535))
556 delay -= 65536
556 delay -= 65536
557 values.append((pulse, delay-1))
557 values.append((pulse, delay-1))
558
558
559 data = bytearray()
559 data = bytearray()
560 #reset
560 #reset
561 data.extend((128, 0))
561 data.extend((128, 0))
562 #disable
562 #disable
563 data.extend((129, 0))
563 data.extend((129, 0))
564 #divider
564 #divider
565 data.extend((131, self.clock_divider-1))
565 data.extend((131, self.clock_divider-1))
566 #enable writing
566 #enable writing
567 data.extend((139, 62))
567 data.extend((139, 62))
568
568
569 last = 0
569 last = 0
570 for tup in values:
570 for tup in values:
571 vals = pack('<HH', last^tup[0], tup[1])
571 vals = pack('<HH', last^tup[0], tup[1])
572 last = tup[0]
572 last = tup[0]
573 data.extend((133, vals[1], 132, vals[0], 133, vals[3], 132, vals[2]))
573 data.extend((133, vals[1], 132, vals[0], 133, vals[3], 132, vals[2]))
574
574
575 #enable
575 #enable
576 data.extend((129, 1))
576 data.extend((129, 1))
577
577
578 try:
578 try:
579 payload = self.request('stop', 'post')
579 payload = self.request('stop', 'post')
580 payload = self.request('reset', 'post')
580 payload = self.request('reset', 'post')
581 #payload = self.request('divider', 'post', data={'divider': self.clock_divider-1})
581 #payload = self.request('divider', 'post', data={'divider': self.clock_divider-1})
582 #payload = self.request('write', 'post', data=b64encode(bytearray((139, 62))), timeout=20)
582 #payload = self.request('write', 'post', data=b64encode(bytearray((139, 62))), timeout=20)
583 n = len(data)
583 n = len(data)
584 x = 0
584 x = 0
585 #while x < n:
585 #while x < n:
586 payload = self.request('write', 'post', data=b64encode(data))
586 payload = self.request('write', 'post', data=b64encode(data))
587 # x += 1024
587 # x += 1024
588
588
589 if payload['write']=='ok':
589 if payload['write']=='ok':
590 self.device.status = 3
590 self.device.status = 3
591 self.device.save()
591 self.device.save()
592 self.message = 'RC configured and started'
592 self.message = 'RC configured and started'
593 else:
593 else:
594 self.device.status = 1
594 self.device.status = 1
595 self.device.save()
595 self.device.save()
596 self.message = 'RC write: {}'.format(payload['write'])
596 self.message = 'RC write: {}'.format(payload['write'])
597 return False
597 return False
598
598
599 #payload = self.request('start', 'post')
599 #payload = self.request('start', 'post')
600
600
601 except Exception as e:
601 except Exception as e:
602 if 'No route to host' not in str(e):
602 if 'No route to host' not in str(e):
603 self.device.status = 4
603 self.device.status = 4
604 else:
604 else:
605 self.device.status = 0
605 self.device.status = 0
606 self.message = 'RC write: {}'.format(str(e))
606 self.message = 'RC write: {}'.format(str(e))
607 self.device.save()
607 self.device.save()
608 return False
608 return False
609
609
610 return True
610 return True
611
611
612
612
613 def get_absolute_url_import(self):
613 def get_absolute_url_import(self):
614 return reverse('url_import_rc_conf', args=[str(self.id)])
614 return reverse('url_import_rc_conf', args=[str(self.id)])
615
615
616
616
617 class RCLineCode(models.Model):
617 class RCLineCode(models.Model):
618
618
619 name = models.CharField(max_length=40)
619 name = models.CharField(max_length=40)
620 bits_per_code = models.PositiveIntegerField(default=0)
620 bits_per_code = models.PositiveIntegerField(default=0)
621 number_of_codes = models.PositiveIntegerField(default=0)
621 number_of_codes = models.PositiveIntegerField(default=0)
622 codes = models.TextField(blank=True, null=True)
622 codes = models.TextField(blank=True, null=True)
623
623
624 class Meta:
624 class Meta:
625 db_table = 'rc_line_codes'
625 db_table = 'rc_line_codes'
626 ordering = ('name',)
626 ordering = ('name',)
627
627
628 def __str__(self):
628 def __str__(self):
629 return u'%s' % self.name
629 return u'%s' % self.name
630
630
631
631
632 class RCLineType(models.Model):
632 class RCLineType(models.Model):
633
633
634 name = models.CharField(choices=LINE_TYPES, max_length=40)
634 name = models.CharField(choices=LINE_TYPES, max_length=40)
635 description = models.TextField(blank=True, null=True)
635 description = models.TextField(blank=True, null=True)
636 params = models.TextField(default='[]')
636 params = models.TextField(default='[]')
637
637
638 class Meta:
638 class Meta:
639 db_table = 'rc_line_types'
639 db_table = 'rc_line_types'
640
640
641 def __str__(self):
641 def __str__(self):
642 return u'%s - %s' % (self.name.upper(), self.get_name_display())
642 return u'%s - %s' % (self.name.upper(), self.get_name_display())
643
643
644
644
645 class RCLine(models.Model):
645 class RCLine(models.Model):
646
646
647 rc_configuration = models.ForeignKey(RCConfiguration, on_delete=models.CASCADE)
647 rc_configuration = models.ForeignKey(RCConfiguration, on_delete=models.CASCADE)
648 line_type = models.ForeignKey(RCLineType)
648 line_type = models.ForeignKey(RCLineType)
649 channel = models.PositiveIntegerField(default=0)
649 channel = models.PositiveIntegerField(default=0)
650 position = models.PositiveIntegerField(default=0)
650 position = models.PositiveIntegerField(default=0)
651 params = models.TextField(default='{}')
651 params = models.TextField(default='{}')
652 pulses = models.TextField(default='')
652 pulses = models.TextField(default='')
653
653
654 class Meta:
654 class Meta:
655 db_table = 'rc_lines'
655 db_table = 'rc_lines'
656 ordering = ['channel']
656 ordering = ['channel']
657
657
658 def __str__(self):
658 def __str__(self):
659 if self.rc_configuration:
659 if self.rc_configuration:
660 return u'{}|{} - {}'.format(self.pk, self.get_name(), self.rc_configuration.name)
660 return u'{}|{} - {}'.format(self.pk, self.get_name(), self.rc_configuration.name)
661
661
662 def jsonify(self):
662 def jsonify(self):
663
663
664 data = {}
664 data = {}
665 data['params'] = json.loads(self.params)
665 data['params'] = json.loads(self.params)
666 data['id'] = '{}'.format(self.pk)
666 data['id'] = '{}'.format(self.pk)
667 data['line_type'] = self.line_type.name
667 data['line_type'] = self.line_type.name
668 data['name'] = self.get_name()
668 data['name'] = self.get_name()
669 if data['line_type']=='codes':
669 if data['line_type']=='codes':
670 data['params']['code'] = RCLineCode.objects.get(pk=data['params']['code']).name
670 data['params']['code'] = RCLineCode.objects.get(pk=data['params']['code']).name
671
671
672 return data
672 return data
673
673
674
674
675 def clone(self, **kwargs):
675 def clone(self, **kwargs):
676
676
677 self.pk = None
677 self.pk = None
678 self.id = None
678 self.id = None
679
679
680 for attr, value in kwargs.items():
680 for attr, value in kwargs.items():
681 setattr(self, attr, value)
681 setattr(self, attr, value)
682
682
683 self.save()
683 self.save()
684
684
685 return self
685 return self
686
686
687 def get_name(self, channel=False):
687 def get_name(self, channel=False):
688
688
689 chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
689 chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
690 s = ''
690 s = ''
691
691
692 if self.line_type.name in ('tx',):
692 if self.line_type.name in ('tx',):
693 s = chars[self.position]
693 s = chars[self.position]
694 elif self.line_type.name in ('codes', 'windows', 'tr'):
694 elif self.line_type.name in ('codes', 'windows', 'tr'):
695 if 'TX_ref' in json.loads(self.params):
695 if 'TX_ref' in json.loads(self.params):
696 pk = json.loads(self.params)['TX_ref']
696 pk = json.loads(self.params)['TX_ref']
697 if pk in (0, '0'):
697 if pk in (0, '0'):
698 s = ','.join(chars[l.position] for l in self.rc_configuration.get_lines(line_type__name='tx'))
698 s = ','.join(chars[l.position] for l in self.rc_configuration.get_lines(line_type__name='tx'))
699 else:
699 else:
700 ref = RCLine.objects.get(pk=pk)
700 ref = RCLine.objects.get(pk=pk)
701 s = chars[ref.position]
701 s = chars[ref.position]
702 s = '({})'.format(s)
702 s = '({})'.format(s)
703
703
704 s = '{}{}'.format(self.line_type.name.upper(), s)
704 s = '{}{}'.format(self.line_type.name.upper(), s)
705
705
706 if channel:
706 if channel:
707 return '{} {}'.format(s, self.channel)
707 return '{} {}'.format(s, self.channel)
708 else:
708 else:
709 return s
709 return s
710
710
711 def get_lines(self, **kwargs):
711 def get_lines(self, **kwargs):
712
712
713 return RCLine.objects.filter(rc_configuration=self.rc_configuration, **kwargs)
713 return RCLine.objects.filter(rc_configuration=self.rc_configuration, **kwargs)
714
714
715 def pulses_as_array(self):
715 def pulses_as_array(self):
716
716
717 y = np.zeros(self.rc_configuration.total_units)
717 y = np.zeros(self.rc_configuration.total_units)
718
718
719 for tup in ast.literal_eval(self.pulses):
719 for tup in ast.literal_eval(self.pulses):
720 y[tup[0]:tup[1]] = 1
720 y[tup[0]:tup[1]] = 1
721
721
722 return y.astype(np.int8)
722 return y.astype(np.int8)
723
723
724 def pulses_as_points(self, km=False):
724 def pulses_as_points(self, km=False):
725
725
726 if km:
726 if km:
727 unit2km = 1/self.rc_configuration.km2unit
727 unit2km = 1/self.rc_configuration.km2unit
728 return [(tup[0]*unit2km, tup[1]*unit2km) for tup in ast.literal_eval(self.pulses)]
728 return [(tup[0]*unit2km, tup[1]*unit2km) for tup in ast.literal_eval(self.pulses)]
729 else:
729 else:
730 return ast.literal_eval(self.pulses)
730 return ast.literal_eval(self.pulses)
731
731
732 def get_win_ref(self, params, tx_id, km2unit):
732 def get_win_ref(self, params, tx_id, km2unit):
733
733
734 ref = self.rc_configuration.sampling_reference
734 ref = self.rc_configuration.sampling_reference
735 codes = [line for line in self.get_lines(line_type__name='codes') if int(json.loads(line.params)['TX_ref'])==int(tx_id)]
735 codes = [line for line in self.get_lines(line_type__name='codes') if int(json.loads(line.params)['TX_ref'])==int(tx_id)]
736
736
737 if codes:
737 if codes:
738 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit/len(json.loads(codes[0].params)['codes'][0])
738 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit/len(json.loads(codes[0].params)['codes'][0])
739 else:
739 else:
740 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit
740 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit
741
741
742 if ref=='first_baud':
742 if ref=='first_baud':
743 return int(1 + round((tx_width + 1)/2 + params['first_height']*km2unit - params['resolution']*km2unit))
743 return int(1 + round((tx_width + 1)/2 + params['first_height']*km2unit - params['resolution']*km2unit))
744 elif ref=='sub_baud':
744 elif ref=='sub_baud':
745 return np.ceil(1 + params['first_height']*km2unit - params['resolution']*km2unit/2)
745 return np.ceil(1 + params['first_height']*km2unit - params['resolution']*km2unit/2)
746 else:
746 else:
747 return 0
747 return 0
748
748
749 def update_pulses(self):
749 def update_pulses(self):
750 '''
750 '''
751 Update pulses field
751 Update pulses field
752 '''
752 '''
753
753
754 km2unit = self.rc_configuration.km2unit
754 km2unit = self.rc_configuration.km2unit
755 us2unit = self.rc_configuration.us2unit
755 us2unit = self.rc_configuration.us2unit
756 ipp = self.rc_configuration.ipp
756 ipp = self.rc_configuration.ipp
757 ntx = int(self.rc_configuration.ntx)
757 ntx = int(self.rc_configuration.ntx)
758 ipp_u = int(ipp*km2unit)
758 ipp_u = int(ipp*km2unit)
759 total = ipp_u*ntx if self.rc_configuration.total_units==0 else self.rc_configuration.total_units
759 total = ipp_u*ntx if self.rc_configuration.total_units==0 else self.rc_configuration.total_units
760 y = []
760 y = []
761
761
762 if self.line_type.name=='tr':
762 if self.line_type.name=='tr':
763 tr_params = json.loads(self.params)
763 tr_params = json.loads(self.params)
764
764
765 if tr_params['TX_ref'] in ('0', 0):
765 if tr_params['TX_ref'] in ('0', 0):
766 txs = self.get_lines(line_type__name='tx')
766 txs = self.get_lines(line_type__name='tx')
767 else:
767 else:
768 txs = RCLine.objects.filter(pk=tr_params['TX_ref'])
768 txs = RCLine.objects.filter(pk=tr_params['TX_ref'])
769
769
770 for tx in txs:
770 for tx in txs:
771 params = json.loads(tx.params)
771 params = json.loads(tx.params)
772
772
773 if float(params['pulse_width'])==0:
773 if float(params['pulse_width'])==0:
774 continue
774 continue
775 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
775 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
776 width = float(params['pulse_width'])*km2unit+int(self.rc_configuration.time_before*us2unit)
776 width = float(params['pulse_width'])*km2unit+int(self.rc_configuration.time_before*us2unit)
777 before = 0
777 before = 0
778 after = int(self.rc_configuration.time_after*us2unit)
778 after = int(self.rc_configuration.time_after*us2unit)
779
779
780 y_tx = self.points(ntx, ipp_u, width,
780 y_tx = self.points(ntx, ipp_u, width,
781 delay=delays,
781 delay=delays,
782 before=before,
782 before=before,
783 after=after,
783 after=after,
784 sync=self.rc_configuration.sync)
784 sync=self.rc_configuration.sync)
785
785
786 ranges = params['range'].split(',')
786 ranges = params['range'].split(',')
787
787
788 if len(ranges)>0 and ranges[0]!='0':
788 if len(ranges)>0 and ranges[0]!='0':
789 y_tx = self.mask_ranges(y_tx, ranges)
789 y_tx = self.mask_ranges(y_tx, ranges)
790
790
791 tr_ranges = tr_params['range'].split(',')
791 tr_ranges = tr_params['range'].split(',')
792
792
793 if len(tr_ranges)>0 and tr_ranges[0]!='0':
793 if len(tr_ranges)>0 and tr_ranges[0]!='0':
794 y_tx = self.mask_ranges(y_tx, tr_ranges)
794 y_tx = self.mask_ranges(y_tx, tr_ranges)
795
795
796 y.extend(y_tx)
796 y.extend(y_tx)
797
797
798 self.pulses = str(y)
798 self.pulses = str(y)
799 y = self.array_to_points(self.pulses_as_array())
799 y = self.array_to_points(self.pulses_as_array())
800
800
801 elif self.line_type.name=='tx':
801 elif self.line_type.name=='tx':
802 params = json.loads(self.params)
802 params = json.loads(self.params)
803 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
803 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
804 width = float(params['pulse_width'])*km2unit
804 width = float(params['pulse_width'])*km2unit
805
805
806 if width>0:
806 if width>0:
807 before = int(self.rc_configuration.time_before*us2unit)
807 before = int(self.rc_configuration.time_before*us2unit)
808 after = 0
808 after = 0
809
809
810 y = self.points(ntx, ipp_u, width,
810 y = self.points(ntx, ipp_u, width,
811 delay=delays,
811 delay=delays,
812 before=before,
812 before=before,
813 after=after,
813 after=after,
814 sync=self.rc_configuration.sync)
814 sync=self.rc_configuration.sync)
815
815
816 ranges = params['range'].split(',')
816 ranges = params['range'].split(',')
817
817
818 if len(ranges)>0 and ranges[0]!='0':
818 if len(ranges)>0 and ranges[0]!='0':
819 y = self.mask_ranges(y, ranges)
819 y = self.mask_ranges(y, ranges)
820
820
821 elif self.line_type.name=='flip':
821 elif self.line_type.name=='flip':
822 n = float(json.loads(self.params)['number_of_flips'])
822 n = float(json.loads(self.params)['number_of_flips'])
823 width = n*ipp*km2unit
823 width = n*ipp*km2unit
824 y = self.points(int((ntx+1)/(2*n)), ipp_u*n*2, width)
824 y = self.points(int((ntx+1)/(2*n)), ipp_u*n*2, width)
825
825
826 elif self.line_type.name=='codes':
826 elif self.line_type.name=='codes':
827 params = json.loads(self.params)
827 params = json.loads(self.params)
828 tx = RCLine.objects.get(pk=params['TX_ref'])
828 tx = RCLine.objects.get(pk=params['TX_ref'])
829 tx_params = json.loads(tx.params)
829 tx_params = json.loads(tx.params)
830 delays = [float(d)*km2unit for d in tx_params['delays'].split(',') if d]
830 delays = [float(d)*km2unit for d in tx_params['delays'].split(',') if d]
831 f = int(float(tx_params['pulse_width'])*km2unit/len(params['codes'][0]))
831 f = int(float(tx_params['pulse_width'])*km2unit/len(params['codes'][0]))
832 codes = [(np.fromstring(''.join([s*f for s in code]), dtype=np.uint8)-48).astype(np.int8) for code in params['codes']]
832 codes = [(np.fromstring(''.join([s*f for s in code]), dtype=np.uint8)-48).astype(np.int8) for code in params['codes']]
833 codes = [self.array_to_points(code) for code in codes]
833 codes = [self.array_to_points(code) for code in codes]
834 n = len(codes)
834 n = len(codes)
835
835
836 ranges = tx_params['range'].split(',')
836 ranges = tx_params['range'].split(',')
837 if len(ranges)>0 and ranges[0]!='0':
837 if len(ranges)>0 and ranges[0]!='0':
838 dum = self.mask_ranges(tx.pulses_as_points(), ranges)
838 dum = self.mask_ranges(tx.pulses_as_points(), ranges)
839 else:
839 else:
840 dum = tx.pulses_as_points()
840 dum = tx.pulses_as_points()
841
841
842 for i, tup in enumerate(dum):
842 for i, tup in enumerate(dum):
843 if tup==(0,0): continue
843 if tup==(0,0): continue
844 code = codes[i%n]
844 code = codes[i%n]
845 y.extend([(c[0]+tup[0], c[1]+tup[0]) for c in code])
845 y.extend([(c[0]+tup[0], c[1]+tup[0]) for c in code])
846
846
847 elif self.line_type.name=='sync':
847 elif self.line_type.name=='sync':
848 params = json.loads(self.params)
848 params = json.loads(self.params)
849 n = ipp_u*ntx
849 n = ipp_u*ntx
850 if params['invert'] in ('1', 1):
850 if params['invert'] in ('1', 1):
851 y = [(n-1, n)]
851 y = [(n-1, n)]
852 else:
852 else:
853 y = [(0, 1)]
853 y = [(0, 1)]
854
854
855 elif self.line_type.name=='prog_pulses':
855 elif self.line_type.name=='prog_pulses':
856 params = json.loads(self.params)
856 params = json.loads(self.params)
857 if int(params['periodic'])==0:
857 if int(params['periodic'])==0:
858 nntx = 1
858 nntx = 1
859 nipp = ipp_u*ntx
859 nipp = ipp_u*ntx
860 else:
860 else:
861 nntx = ntx
861 nntx = ntx
862 nipp = ipp_u
862 nipp = ipp_u
863
863
864 if 'params' in params and len(params['params'])>0:
864 if 'params' in params and len(params['params'])>0:
865 for p in params['params']:
865 for p in params['params']:
866 y_pp = self.points(nntx, nipp,
866 y_pp = self.points(nntx, nipp,
867 p['end']-p['begin'],
867 p['end']-p['begin'],
868 before=p['begin'])
868 before=p['begin'])
869
869
870 y.extend(y_pp)
870 y.extend(y_pp)
871
871
872 elif self.line_type.name=='windows':
872 elif self.line_type.name=='windows':
873 params = json.loads(self.params)
873 params = json.loads(self.params)
874 if 'params' in params and len(params['params'])>0:
874 if 'params' in params and len(params['params'])>0:
875 tr_lines = self.get_lines(line_type__name='tr')
875 tx = RCLine.objects.get(pk=params['TX_ref'])
876 if tr_lines:
876 tx_params = json.loads(tx.params)
877 tr_params = json.loads(self.get_lines(line_type__name='tr')[0].params)
877 ranges = tx_params['range'].split(',')
878 tr_ranges = tr_params['range'].split(',')
879 else:
880 tr_ranges = []
881 for p in params['params']:
878 for p in params['params']:
882 y_win = self.points(ntx, ipp_u,
879 y_win = self.points(ntx, ipp_u,
883 p['resolution']*p['number_of_samples']*km2unit,
880 p['resolution']*p['number_of_samples']*km2unit,
884 before=int(self.rc_configuration.time_before*us2unit)+p['first_height']*km2unit,
881 before=int(self.rc_configuration.time_before*us2unit)+p['first_height']*km2unit,
885 sync=self.rc_configuration.sync+self.get_win_ref(p, params['TX_ref'], km2unit))
882 sync=self.rc_configuration.sync+self.get_win_ref(p, params['TX_ref'], km2unit))
886
883
887
884
888 if len(tr_ranges)>0 and tr_ranges[0]!='0':
885 if len(ranges)>0 and ranges[0]!='0':
889 y_win = self.mask_ranges(y_win, tr_ranges)
886 y_win = self.mask_ranges(y_win, ranges)
890
887
891 y.extend(y_win)
888 y.extend(y_win)
892
889
893 elif self.line_type.name=='mix':
890 elif self.line_type.name=='mix':
894 values = self.rc_configuration.parameters.split('-')
891 values = self.rc_configuration.parameters.split('-')
895 confs = [RCConfiguration.objects.get(pk=value.split('|')[0]) for value in values]
892 confs = [RCConfiguration.objects.get(pk=value.split('|')[0]) for value in values]
896 modes = [value.split('|')[1] for value in values]
893 modes = [value.split('|')[1] for value in values]
897 ops = [value.split('|')[2] for value in values]
894 ops = [value.split('|')[2] for value in values]
898 delays = [value.split('|')[3] for value in values]
895 delays = [value.split('|')[3] for value in values]
899 masks = [value.split('|')[4] for value in values]
896 masks = [value.split('|')[4] for value in values]
900 mask = list('{:8b}'.format(int(masks[0])))
897 mask = list('{:8b}'.format(int(masks[0])))
901 mask.reverse()
898 mask.reverse()
902 if mask[self.channel] in ('0', '', ' '):
899 if mask[self.channel] in ('0', '', ' '):
903 y = np.zeros(confs[0].total_units, dtype=np.int8)
900 y = np.zeros(confs[0].total_units, dtype=np.int8)
904 else:
901 else:
905 y = confs[0].get_lines(channel=self.channel)[0].pulses_as_array()
902 y = confs[0].get_lines(channel=self.channel)[0].pulses_as_array()
906
903
907 for i in range(1, len(values)):
904 for i in range(1, len(values)):
908 mask = list('{:8b}'.format(int(masks[i])))
905 mask = list('{:8b}'.format(int(masks[i])))
909 mask.reverse()
906 mask.reverse()
910
907
911 if mask[self.channel] in ('0', '', ' '):
908 if mask[self.channel] in ('0', '', ' '):
912 continue
909 continue
913 Y = confs[i].get_lines(channel=self.channel)[0].pulses_as_array()
910 Y = confs[i].get_lines(channel=self.channel)[0].pulses_as_array()
914 delay = float(delays[i])*km2unit
911 delay = float(delays[i])*km2unit
915
912
916 if modes[i]=='P':
913 if modes[i]=='P':
917 if delay>0:
914 if delay>0:
918 if delay<self.rc_configuration.ipp*km2unit and len(Y)==len(y):
915 if delay<self.rc_configuration.ipp*km2unit and len(Y)==len(y):
919 y_temp = np.empty_like(Y)
916 y_temp = np.empty_like(Y)
920 y_temp[:delay] = 0
917 y_temp[:delay] = 0
921 y_temp[delay:] = Y[:-delay]
918 y_temp[delay:] = Y[:-delay]
922 elif delay+len(Y)>len(y):
919 elif delay+len(Y)>len(y):
923 y_new = np.zeros(delay+len(Y), dtype=np.int8)
920 y_new = np.zeros(delay+len(Y), dtype=np.int8)
924 y_new[:len(y)] = y
921 y_new[:len(y)] = y
925 y = y_new
922 y = y_new
926 y_temp = np.zeros(delay+len(Y), dtype=np.int8)
923 y_temp = np.zeros(delay+len(Y), dtype=np.int8)
927 y_temp[-len(Y):] = Y
924 y_temp[-len(Y):] = Y
928 elif delay+len(Y)==len(y):
925 elif delay+len(Y)==len(y):
929 y_temp = np.zeros(delay+len(Y))
926 y_temp = np.zeros(delay+len(Y))
930 y_temp[-len(Y):] = Y
927 y_temp[-len(Y):] = Y
931 elif delay+len(Y)<len(y):
928 elif delay+len(Y)<len(y):
932 y_temp = np.zeros(len(y), dtype=np.int8)
929 y_temp = np.zeros(len(y), dtype=np.int8)
933 y_temp[delay:delay+len(Y)] = Y
930 y_temp[delay:delay+len(Y)] = Y
934 else:
931 else:
935 y_temp = Y.copy()
932 y_temp = Y.copy()
936
933
937 if ops[i]=='OR':
934 if ops[i]=='OR':
938 y = y | y_temp
935 y = y | y_temp
939 elif ops[i]=='XOR':
936 elif ops[i]=='XOR':
940 y = y ^ y_temp
937 y = y ^ y_temp
941 elif ops[i]=='AND':
938 elif ops[i]=='AND':
942 y = y & y_temp
939 y = y & y_temp
943 elif ops[i]=='NAND':
940 elif ops[i]=='NAND':
944 y = y & ~y_temp
941 y = y & ~y_temp
945 else:
942 else:
946 y = np.concatenate([y, Y])
943 y = np.concatenate([y, Y])
947
944
948 total = len(y)
945 total = len(y)
949 y = self.array_to_points(y)
946 y = self.array_to_points(y)
950
947
951 else:
948 else:
952 y = []
949 y = []
953
950
954 if self.rc_configuration.total_units != total:
951 if self.rc_configuration.total_units != total:
955 self.rc_configuration.total_units = total
952 self.rc_configuration.total_units = total
956 self.rc_configuration.save()
953 self.rc_configuration.save()
957
954
958 self.pulses = str(y)
955 self.pulses = str(y)
959 self.save()
956 self.save()
960
957
961 @staticmethod
958 @staticmethod
962 def array_to_points(X):
959 def array_to_points(X):
963
960
964 if X.size==0:
961 if X.size==0:
965 return []
962 return []
966
963
967 d = X[1:]-X[:-1]
964 d = X[1:]-X[:-1]
968
965
969 up = np.where(d==1)[0]
966 up = np.where(d==1)[0]
970 if X[0]==1:
967 if X[0]==1:
971 up = np.concatenate((np.array([-1]), up))
968 up = np.concatenate((np.array([-1]), up))
972 up += 1
969 up += 1
973
970
974 dw = np.where(d==-1)[0]
971 dw = np.where(d==-1)[0]
975 if X[-1]==1:
972 if X[-1]==1:
976 dw = np.concatenate((dw, np.array([len(X)-1])))
973 dw = np.concatenate((dw, np.array([len(X)-1])))
977 dw += 1
974 dw += 1
978
975
979 return [(tup[0], tup[1]) for tup in zip(up, dw)]
976 return [(tup[0], tup[1]) for tup in zip(up, dw)]
980
977
981 @staticmethod
978 @staticmethod
982 def mask_ranges(Y, ranges):
979 def mask_ranges(Y, ranges):
983
980
984 y = [(0, 0) for __ in Y]
981 y = [(0, 0) for __ in Y]
985
982
986 for index in ranges:
983 for index in ranges:
987 if '-' in index:
984 if '-' in index:
988 args = [int(a) for a in index.split('-')]
985 args = [int(a) for a in index.split('-')]
989 y[args[0]-1:args[1]] = Y[args[0]-1:args[1]]
986 y[args[0]-1:args[1]] = Y[args[0]-1:args[1]]
990 else:
987 else:
991 y[int(index)-1] = Y[int(index)-1]
988 y[int(index)-1] = Y[int(index)-1]
992
989
993 return y
990 return y
994
991
995 @staticmethod
992 @staticmethod
996 def points(ntx, ipp, width, delay=[0], before=0, after=0, sync=0):
993 def points(ntx, ipp, width, delay=[0], before=0, after=0, sync=0):
997
994
998 delays = len(delay)
995 delays = len(delay)
999
996
1000 Y = [(int(ipp*x+before+delay[x%delays]+sync), int(ipp*x+width+before+delay[x%delays]+after+sync)) for x in range(ntx)]
997 Y = [(int(ipp*x+before+delay[x%delays]+sync), int(ipp*x+width+before+delay[x%delays]+after+sync)) for x in range(ntx)]
1001
998
1002 return Y
999 return Y
General Comments 0
You need to be logged in to leave comments. Login now