##// END OF EJS Templates
Add control_sw value in write_device RC
jespinoza -
r304:ef15cc8a2bad
parent child
Show More
@@ -1,999 +1,1001
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()])
551
552 values = []
550 values = []
553 for pulse, delay in zip(self.get_pulses(), self.get_delays()):
551 for pulse, delay in zip(self.get_pulses(), self.get_delays()):
554 while delay>65536:
552 while delay>65536:
555 values.append((pulse, 65535))
553 values.append((pulse, 65535))
556 delay -= 65536
554 delay -= 65536
557 values.append((pulse, delay-1))
555 values.append((pulse, delay-1))
558
559 data = bytearray()
556 data = bytearray()
560 #reset
557 #reset
561 data.extend((128, 0))
558 data.extend((128, 0))
562 #disable
559 #disable
563 data.extend((129, 0))
560 data.extend((129, 0))
561 #SW switch
562 if self.control_sw:
563 data.extend((130, 2))
564 else:
565 data.extend((130, 0))
564 #divider
566 #divider
565 data.extend((131, self.clock_divider-1))
567 data.extend((131, self.clock_divider-1))
566 #enable writing
568 #enable writing
567 data.extend((139, 62))
569 data.extend((139, 62))
568
570
569 last = 0
571 last = 0
570 for tup in values:
572 for tup in values:
571 vals = pack('<HH', last^tup[0], tup[1])
573 vals = pack('<HH', last^tup[0], tup[1])
572 last = tup[0]
574 last = tup[0]
573 data.extend((133, vals[1], 132, vals[0], 133, vals[3], 132, vals[2]))
575 data.extend((133, vals[1], 132, vals[0], 133, vals[3], 132, vals[2]))
574
576
575 #enable
577 #enable
576 data.extend((129, 1))
578 data.extend((129, 1))
577
579
578 try:
580 try:
579 payload = self.request('stop', 'post')
581 payload = self.request('stop', 'post')
580 payload = self.request('reset', 'post')
582 payload = self.request('reset', 'post')
581 #payload = self.request('divider', 'post', data={'divider': self.clock_divider-1})
583 #payload = self.request('divider', 'post', data={'divider': self.clock_divider-1})
582 #payload = self.request('write', 'post', data=b64encode(bytearray((139, 62))), timeout=20)
584 #payload = self.request('write', 'post', data=b64encode(bytearray((139, 62))), timeout=20)
583 n = len(data)
585 n = len(data)
584 x = 0
586 x = 0
585 #while x < n:
587 #while x < n:
586 payload = self.request('write', 'post', data=b64encode(data))
588 payload = self.request('write', 'post', data=b64encode(data))
587 # x += 1024
589 # x += 1024
588
590
589 if payload['write']=='ok':
591 if payload['write']=='ok':
590 self.device.status = 3
592 self.device.status = 3
591 self.device.save()
593 self.device.save()
592 self.message = 'RC configured and started'
594 self.message = 'RC configured and started'
593 else:
595 else:
594 self.device.status = 1
596 self.device.status = 1
595 self.device.save()
597 self.device.save()
596 self.message = 'RC write: {}'.format(payload['write'])
598 self.message = 'RC write: {}'.format(payload['write'])
597 return False
599 return False
598
600
599 #payload = self.request('start', 'post')
601 #payload = self.request('start', 'post')
600
602
601 except Exception as e:
603 except Exception as e:
602 if 'No route to host' not in str(e):
604 if 'No route to host' not in str(e):
603 self.device.status = 4
605 self.device.status = 4
604 else:
606 else:
605 self.device.status = 0
607 self.device.status = 0
606 self.message = 'RC write: {}'.format(str(e))
608 self.message = 'RC write: {}'.format(str(e))
607 self.device.save()
609 self.device.save()
608 return False
610 return False
609
611
610 return True
612 return True
611
613
612
614
613 def get_absolute_url_import(self):
615 def get_absolute_url_import(self):
614 return reverse('url_import_rc_conf', args=[str(self.id)])
616 return reverse('url_import_rc_conf', args=[str(self.id)])
615
617
616
618
617 class RCLineCode(models.Model):
619 class RCLineCode(models.Model):
618
620
619 name = models.CharField(max_length=40)
621 name = models.CharField(max_length=40)
620 bits_per_code = models.PositiveIntegerField(default=0)
622 bits_per_code = models.PositiveIntegerField(default=0)
621 number_of_codes = models.PositiveIntegerField(default=0)
623 number_of_codes = models.PositiveIntegerField(default=0)
622 codes = models.TextField(blank=True, null=True)
624 codes = models.TextField(blank=True, null=True)
623
625
624 class Meta:
626 class Meta:
625 db_table = 'rc_line_codes'
627 db_table = 'rc_line_codes'
626 ordering = ('name',)
628 ordering = ('name',)
627
629
628 def __str__(self):
630 def __str__(self):
629 return u'%s' % self.name
631 return u'%s' % self.name
630
632
631
633
632 class RCLineType(models.Model):
634 class RCLineType(models.Model):
633
635
634 name = models.CharField(choices=LINE_TYPES, max_length=40)
636 name = models.CharField(choices=LINE_TYPES, max_length=40)
635 description = models.TextField(blank=True, null=True)
637 description = models.TextField(blank=True, null=True)
636 params = models.TextField(default='[]')
638 params = models.TextField(default='[]')
637
639
638 class Meta:
640 class Meta:
639 db_table = 'rc_line_types'
641 db_table = 'rc_line_types'
640
642
641 def __str__(self):
643 def __str__(self):
642 return u'%s - %s' % (self.name.upper(), self.get_name_display())
644 return u'%s - %s' % (self.name.upper(), self.get_name_display())
643
645
644
646
645 class RCLine(models.Model):
647 class RCLine(models.Model):
646
648
647 rc_configuration = models.ForeignKey(RCConfiguration, on_delete=models.CASCADE)
649 rc_configuration = models.ForeignKey(RCConfiguration, on_delete=models.CASCADE)
648 line_type = models.ForeignKey(RCLineType)
650 line_type = models.ForeignKey(RCLineType)
649 channel = models.PositiveIntegerField(default=0)
651 channel = models.PositiveIntegerField(default=0)
650 position = models.PositiveIntegerField(default=0)
652 position = models.PositiveIntegerField(default=0)
651 params = models.TextField(default='{}')
653 params = models.TextField(default='{}')
652 pulses = models.TextField(default='')
654 pulses = models.TextField(default='')
653
655
654 class Meta:
656 class Meta:
655 db_table = 'rc_lines'
657 db_table = 'rc_lines'
656 ordering = ['channel']
658 ordering = ['channel']
657
659
658 def __str__(self):
660 def __str__(self):
659 if self.rc_configuration:
661 if self.rc_configuration:
660 return u'{}|{} - {}'.format(self.pk, self.get_name(), self.rc_configuration.name)
662 return u'{}|{} - {}'.format(self.pk, self.get_name(), self.rc_configuration.name)
661
663
662 def jsonify(self):
664 def jsonify(self):
663
665
664 data = {}
666 data = {}
665 data['params'] = json.loads(self.params)
667 data['params'] = json.loads(self.params)
666 data['id'] = '{}'.format(self.pk)
668 data['id'] = '{}'.format(self.pk)
667 data['line_type'] = self.line_type.name
669 data['line_type'] = self.line_type.name
668 data['name'] = self.get_name()
670 data['name'] = self.get_name()
669 if data['line_type']=='codes':
671 if data['line_type']=='codes':
670 data['params']['code'] = RCLineCode.objects.get(pk=data['params']['code']).name
672 data['params']['code'] = RCLineCode.objects.get(pk=data['params']['code']).name
671
673
672 return data
674 return data
673
675
674
676
675 def clone(self, **kwargs):
677 def clone(self, **kwargs):
676
678
677 self.pk = None
679 self.pk = None
678 self.id = None
680 self.id = None
679
681
680 for attr, value in kwargs.items():
682 for attr, value in kwargs.items():
681 setattr(self, attr, value)
683 setattr(self, attr, value)
682
684
683 self.save()
685 self.save()
684
686
685 return self
687 return self
686
688
687 def get_name(self, channel=False):
689 def get_name(self, channel=False):
688
690
689 chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
691 chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
690 s = ''
692 s = ''
691
693
692 if self.line_type.name in ('tx',):
694 if self.line_type.name in ('tx',):
693 s = chars[self.position]
695 s = chars[self.position]
694 elif self.line_type.name in ('codes', 'windows', 'tr'):
696 elif self.line_type.name in ('codes', 'windows', 'tr'):
695 if 'TX_ref' in json.loads(self.params):
697 if 'TX_ref' in json.loads(self.params):
696 pk = json.loads(self.params)['TX_ref']
698 pk = json.loads(self.params)['TX_ref']
697 if pk in (0, '0'):
699 if pk in (0, '0'):
698 s = ','.join(chars[l.position] for l in self.rc_configuration.get_lines(line_type__name='tx'))
700 s = ','.join(chars[l.position] for l in self.rc_configuration.get_lines(line_type__name='tx'))
699 else:
701 else:
700 ref = RCLine.objects.get(pk=pk)
702 ref = RCLine.objects.get(pk=pk)
701 s = chars[ref.position]
703 s = chars[ref.position]
702 s = '({})'.format(s)
704 s = '({})'.format(s)
703
705
704 s = '{}{}'.format(self.line_type.name.upper(), s)
706 s = '{}{}'.format(self.line_type.name.upper(), s)
705
707
706 if channel:
708 if channel:
707 return '{} {}'.format(s, self.channel)
709 return '{} {}'.format(s, self.channel)
708 else:
710 else:
709 return s
711 return s
710
712
711 def get_lines(self, **kwargs):
713 def get_lines(self, **kwargs):
712
714
713 return RCLine.objects.filter(rc_configuration=self.rc_configuration, **kwargs)
715 return RCLine.objects.filter(rc_configuration=self.rc_configuration, **kwargs)
714
716
715 def pulses_as_array(self):
717 def pulses_as_array(self):
716
718
717 y = np.zeros(self.rc_configuration.total_units)
719 y = np.zeros(self.rc_configuration.total_units)
718
720
719 for tup in ast.literal_eval(self.pulses):
721 for tup in ast.literal_eval(self.pulses):
720 y[tup[0]:tup[1]] = 1
722 y[tup[0]:tup[1]] = 1
721
723
722 return y.astype(np.int8)
724 return y.astype(np.int8)
723
725
724 def pulses_as_points(self, km=False):
726 def pulses_as_points(self, km=False):
725
727
726 if km:
728 if km:
727 unit2km = 1/self.rc_configuration.km2unit
729 unit2km = 1/self.rc_configuration.km2unit
728 return [(tup[0]*unit2km, tup[1]*unit2km) for tup in ast.literal_eval(self.pulses)]
730 return [(tup[0]*unit2km, tup[1]*unit2km) for tup in ast.literal_eval(self.pulses)]
729 else:
731 else:
730 return ast.literal_eval(self.pulses)
732 return ast.literal_eval(self.pulses)
731
733
732 def get_win_ref(self, params, tx_id, km2unit):
734 def get_win_ref(self, params, tx_id, km2unit):
733
735
734 ref = self.rc_configuration.sampling_reference
736 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)]
737 codes = [line for line in self.get_lines(line_type__name='codes') if int(json.loads(line.params)['TX_ref'])==int(tx_id)]
736
738
737 if codes:
739 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])
740 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:
741 else:
740 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit
742 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit
741
743
742 if ref=='first_baud':
744 if ref=='first_baud':
743 return int(1 + round((tx_width + 1)/2 + params['first_height']*km2unit - params['resolution']*km2unit))
745 return int(1 + round((tx_width + 1)/2 + params['first_height']*km2unit - params['resolution']*km2unit))
744 elif ref=='sub_baud':
746 elif ref=='sub_baud':
745 return np.ceil(1 + params['first_height']*km2unit - params['resolution']*km2unit/2)
747 return np.ceil(1 + params['first_height']*km2unit - params['resolution']*km2unit/2)
746 else:
748 else:
747 return 0
749 return 0
748
750
749 def update_pulses(self):
751 def update_pulses(self):
750 '''
752 '''
751 Update pulses field
753 Update pulses field
752 '''
754 '''
753
755
754 km2unit = self.rc_configuration.km2unit
756 km2unit = self.rc_configuration.km2unit
755 us2unit = self.rc_configuration.us2unit
757 us2unit = self.rc_configuration.us2unit
756 ipp = self.rc_configuration.ipp
758 ipp = self.rc_configuration.ipp
757 ntx = int(self.rc_configuration.ntx)
759 ntx = int(self.rc_configuration.ntx)
758 ipp_u = int(ipp*km2unit)
760 ipp_u = int(ipp*km2unit)
759 total = ipp_u*ntx if self.rc_configuration.total_units==0 else self.rc_configuration.total_units
761 total = ipp_u*ntx if self.rc_configuration.total_units==0 else self.rc_configuration.total_units
760 y = []
762 y = []
761
763
762 if self.line_type.name=='tr':
764 if self.line_type.name=='tr':
763 tr_params = json.loads(self.params)
765 tr_params = json.loads(self.params)
764
766
765 if tr_params['TX_ref'] in ('0', 0):
767 if tr_params['TX_ref'] in ('0', 0):
766 txs = self.get_lines(line_type__name='tx')
768 txs = self.get_lines(line_type__name='tx')
767 else:
769 else:
768 txs = RCLine.objects.filter(pk=tr_params['TX_ref'])
770 txs = RCLine.objects.filter(pk=tr_params['TX_ref'])
769
771
770 for tx in txs:
772 for tx in txs:
771 params = json.loads(tx.params)
773 params = json.loads(tx.params)
772
774
773 if float(params['pulse_width'])==0:
775 if float(params['pulse_width'])==0:
774 continue
776 continue
775 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
777 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)
778 width = float(params['pulse_width'])*km2unit+int(self.rc_configuration.time_before*us2unit)
777 before = 0
779 before = 0
778 after = int(self.rc_configuration.time_after*us2unit)
780 after = int(self.rc_configuration.time_after*us2unit)
779
781
780 y_tx = self.points(ntx, ipp_u, width,
782 y_tx = self.points(ntx, ipp_u, width,
781 delay=delays,
783 delay=delays,
782 before=before,
784 before=before,
783 after=after,
785 after=after,
784 sync=self.rc_configuration.sync)
786 sync=self.rc_configuration.sync)
785
787
786 ranges = params['range'].split(',')
788 ranges = params['range'].split(',')
787
789
788 if len(ranges)>0 and ranges[0]!='0':
790 if len(ranges)>0 and ranges[0]!='0':
789 y_tx = self.mask_ranges(y_tx, ranges)
791 y_tx = self.mask_ranges(y_tx, ranges)
790
792
791 tr_ranges = tr_params['range'].split(',')
793 tr_ranges = tr_params['range'].split(',')
792
794
793 if len(tr_ranges)>0 and tr_ranges[0]!='0':
795 if len(tr_ranges)>0 and tr_ranges[0]!='0':
794 y_tx = self.mask_ranges(y_tx, tr_ranges)
796 y_tx = self.mask_ranges(y_tx, tr_ranges)
795
797
796 y.extend(y_tx)
798 y.extend(y_tx)
797
799
798 self.pulses = str(y)
800 self.pulses = str(y)
799 y = self.array_to_points(self.pulses_as_array())
801 y = self.array_to_points(self.pulses_as_array())
800
802
801 elif self.line_type.name=='tx':
803 elif self.line_type.name=='tx':
802 params = json.loads(self.params)
804 params = json.loads(self.params)
803 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
805 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
804 width = float(params['pulse_width'])*km2unit
806 width = float(params['pulse_width'])*km2unit
805
807
806 if width>0:
808 if width>0:
807 before = int(self.rc_configuration.time_before*us2unit)
809 before = int(self.rc_configuration.time_before*us2unit)
808 after = 0
810 after = 0
809
811
810 y = self.points(ntx, ipp_u, width,
812 y = self.points(ntx, ipp_u, width,
811 delay=delays,
813 delay=delays,
812 before=before,
814 before=before,
813 after=after,
815 after=after,
814 sync=self.rc_configuration.sync)
816 sync=self.rc_configuration.sync)
815
817
816 ranges = params['range'].split(',')
818 ranges = params['range'].split(',')
817
819
818 if len(ranges)>0 and ranges[0]!='0':
820 if len(ranges)>0 and ranges[0]!='0':
819 y = self.mask_ranges(y, ranges)
821 y = self.mask_ranges(y, ranges)
820
822
821 elif self.line_type.name=='flip':
823 elif self.line_type.name=='flip':
822 n = float(json.loads(self.params)['number_of_flips'])
824 n = float(json.loads(self.params)['number_of_flips'])
823 width = n*ipp*km2unit
825 width = n*ipp*km2unit
824 y = self.points(int((ntx+1)/(2*n)), ipp_u*n*2, width)
826 y = self.points(int((ntx+1)/(2*n)), ipp_u*n*2, width)
825
827
826 elif self.line_type.name=='codes':
828 elif self.line_type.name=='codes':
827 params = json.loads(self.params)
829 params = json.loads(self.params)
828 tx = RCLine.objects.get(pk=params['TX_ref'])
830 tx = RCLine.objects.get(pk=params['TX_ref'])
829 tx_params = json.loads(tx.params)
831 tx_params = json.loads(tx.params)
830 delays = [float(d)*km2unit for d in tx_params['delays'].split(',') if d]
832 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]))
833 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']]
834 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]
835 codes = [self.array_to_points(code) for code in codes]
834 n = len(codes)
836 n = len(codes)
835
837
836 ranges = tx_params['range'].split(',')
838 ranges = tx_params['range'].split(',')
837 if len(ranges)>0 and ranges[0]!='0':
839 if len(ranges)>0 and ranges[0]!='0':
838 dum = self.mask_ranges(tx.pulses_as_points(), ranges)
840 dum = self.mask_ranges(tx.pulses_as_points(), ranges)
839 else:
841 else:
840 dum = tx.pulses_as_points()
842 dum = tx.pulses_as_points()
841
843
842 for i, tup in enumerate(dum):
844 for i, tup in enumerate(dum):
843 if tup==(0,0): continue
845 if tup==(0,0): continue
844 code = codes[i%n]
846 code = codes[i%n]
845 y.extend([(c[0]+tup[0], c[1]+tup[0]) for c in code])
847 y.extend([(c[0]+tup[0], c[1]+tup[0]) for c in code])
846
848
847 elif self.line_type.name=='sync':
849 elif self.line_type.name=='sync':
848 params = json.loads(self.params)
850 params = json.loads(self.params)
849 n = ipp_u*ntx
851 n = ipp_u*ntx
850 if params['invert'] in ('1', 1):
852 if params['invert'] in ('1', 1):
851 y = [(n-1, n)]
853 y = [(n-1, n)]
852 else:
854 else:
853 y = [(0, 1)]
855 y = [(0, 1)]
854
856
855 elif self.line_type.name=='prog_pulses':
857 elif self.line_type.name=='prog_pulses':
856 params = json.loads(self.params)
858 params = json.loads(self.params)
857 if int(params['periodic'])==0:
859 if int(params['periodic'])==0:
858 nntx = 1
860 nntx = 1
859 nipp = ipp_u*ntx
861 nipp = ipp_u*ntx
860 else:
862 else:
861 nntx = ntx
863 nntx = ntx
862 nipp = ipp_u
864 nipp = ipp_u
863
865
864 if 'params' in params and len(params['params'])>0:
866 if 'params' in params and len(params['params'])>0:
865 for p in params['params']:
867 for p in params['params']:
866 y_pp = self.points(nntx, nipp,
868 y_pp = self.points(nntx, nipp,
867 p['end']-p['begin'],
869 p['end']-p['begin'],
868 before=p['begin'])
870 before=p['begin'])
869
871
870 y.extend(y_pp)
872 y.extend(y_pp)
871
873
872 elif self.line_type.name=='windows':
874 elif self.line_type.name=='windows':
873 params = json.loads(self.params)
875 params = json.loads(self.params)
874 if 'params' in params and len(params['params'])>0:
876 if 'params' in params and len(params['params'])>0:
875 tx = RCLine.objects.get(pk=params['TX_ref'])
877 tx = RCLine.objects.get(pk=params['TX_ref'])
876 tx_params = json.loads(tx.params)
878 tx_params = json.loads(tx.params)
877 ranges = tx_params['range'].split(',')
879 ranges = tx_params['range'].split(',')
878 for p in params['params']:
880 for p in params['params']:
879 y_win = self.points(ntx, ipp_u,
881 y_win = self.points(ntx, ipp_u,
880 p['resolution']*p['number_of_samples']*km2unit,
882 p['resolution']*p['number_of_samples']*km2unit,
881 before=int(self.rc_configuration.time_before*us2unit)+p['first_height']*km2unit,
883 before=int(self.rc_configuration.time_before*us2unit)+p['first_height']*km2unit,
882 sync=self.rc_configuration.sync+self.get_win_ref(p, params['TX_ref'], km2unit))
884 sync=self.rc_configuration.sync+self.get_win_ref(p, params['TX_ref'], km2unit))
883
885
884
886
885 if len(ranges)>0 and ranges[0]!='0':
887 if len(ranges)>0 and ranges[0]!='0':
886 y_win = self.mask_ranges(y_win, ranges)
888 y_win = self.mask_ranges(y_win, ranges)
887
889
888 y.extend(y_win)
890 y.extend(y_win)
889
891
890 elif self.line_type.name=='mix':
892 elif self.line_type.name=='mix':
891 values = self.rc_configuration.parameters.split('-')
893 values = self.rc_configuration.parameters.split('-')
892 confs = [RCConfiguration.objects.get(pk=value.split('|')[0]) for value in values]
894 confs = [RCConfiguration.objects.get(pk=value.split('|')[0]) for value in values]
893 modes = [value.split('|')[1] for value in values]
895 modes = [value.split('|')[1] for value in values]
894 ops = [value.split('|')[2] for value in values]
896 ops = [value.split('|')[2] for value in values]
895 delays = [value.split('|')[3] for value in values]
897 delays = [value.split('|')[3] for value in values]
896 masks = [value.split('|')[4] for value in values]
898 masks = [value.split('|')[4] for value in values]
897 mask = list('{:8b}'.format(int(masks[0])))
899 mask = list('{:8b}'.format(int(masks[0])))
898 mask.reverse()
900 mask.reverse()
899 if mask[self.channel] in ('0', '', ' '):
901 if mask[self.channel] in ('0', '', ' '):
900 y = np.zeros(confs[0].total_units, dtype=np.int8)
902 y = np.zeros(confs[0].total_units, dtype=np.int8)
901 else:
903 else:
902 y = confs[0].get_lines(channel=self.channel)[0].pulses_as_array()
904 y = confs[0].get_lines(channel=self.channel)[0].pulses_as_array()
903
905
904 for i in range(1, len(values)):
906 for i in range(1, len(values)):
905 mask = list('{:8b}'.format(int(masks[i])))
907 mask = list('{:8b}'.format(int(masks[i])))
906 mask.reverse()
908 mask.reverse()
907
909
908 if mask[self.channel] in ('0', '', ' '):
910 if mask[self.channel] in ('0', '', ' '):
909 continue
911 continue
910 Y = confs[i].get_lines(channel=self.channel)[0].pulses_as_array()
912 Y = confs[i].get_lines(channel=self.channel)[0].pulses_as_array()
911 delay = float(delays[i])*km2unit
913 delay = float(delays[i])*km2unit
912
914
913 if modes[i]=='P':
915 if modes[i]=='P':
914 if delay>0:
916 if delay>0:
915 if delay<self.rc_configuration.ipp*km2unit and len(Y)==len(y):
917 if delay<self.rc_configuration.ipp*km2unit and len(Y)==len(y):
916 y_temp = np.empty_like(Y)
918 y_temp = np.empty_like(Y)
917 y_temp[:delay] = 0
919 y_temp[:delay] = 0
918 y_temp[delay:] = Y[:-delay]
920 y_temp[delay:] = Y[:-delay]
919 elif delay+len(Y)>len(y):
921 elif delay+len(Y)>len(y):
920 y_new = np.zeros(delay+len(Y), dtype=np.int8)
922 y_new = np.zeros(delay+len(Y), dtype=np.int8)
921 y_new[:len(y)] = y
923 y_new[:len(y)] = y
922 y = y_new
924 y = y_new
923 y_temp = np.zeros(delay+len(Y), dtype=np.int8)
925 y_temp = np.zeros(delay+len(Y), dtype=np.int8)
924 y_temp[-len(Y):] = Y
926 y_temp[-len(Y):] = Y
925 elif delay+len(Y)==len(y):
927 elif delay+len(Y)==len(y):
926 y_temp = np.zeros(delay+len(Y))
928 y_temp = np.zeros(delay+len(Y))
927 y_temp[-len(Y):] = Y
929 y_temp[-len(Y):] = Y
928 elif delay+len(Y)<len(y):
930 elif delay+len(Y)<len(y):
929 y_temp = np.zeros(len(y), dtype=np.int8)
931 y_temp = np.zeros(len(y), dtype=np.int8)
930 y_temp[delay:delay+len(Y)] = Y
932 y_temp[delay:delay+len(Y)] = Y
931 else:
933 else:
932 y_temp = Y.copy()
934 y_temp = Y.copy()
933
935
934 if ops[i]=='OR':
936 if ops[i]=='OR':
935 y = y | y_temp
937 y = y | y_temp
936 elif ops[i]=='XOR':
938 elif ops[i]=='XOR':
937 y = y ^ y_temp
939 y = y ^ y_temp
938 elif ops[i]=='AND':
940 elif ops[i]=='AND':
939 y = y & y_temp
941 y = y & y_temp
940 elif ops[i]=='NAND':
942 elif ops[i]=='NAND':
941 y = y & ~y_temp
943 y = y & ~y_temp
942 else:
944 else:
943 y = np.concatenate([y, Y])
945 y = np.concatenate([y, Y])
944
946
945 total = len(y)
947 total = len(y)
946 y = self.array_to_points(y)
948 y = self.array_to_points(y)
947
949
948 else:
950 else:
949 y = []
951 y = []
950
952
951 if self.rc_configuration.total_units != total:
953 if self.rc_configuration.total_units != total:
952 self.rc_configuration.total_units = total
954 self.rc_configuration.total_units = total
953 self.rc_configuration.save()
955 self.rc_configuration.save()
954
956
955 self.pulses = str(y)
957 self.pulses = str(y)
956 self.save()
958 self.save()
957
959
958 @staticmethod
960 @staticmethod
959 def array_to_points(X):
961 def array_to_points(X):
960
962
961 if X.size==0:
963 if X.size==0:
962 return []
964 return []
963
965
964 d = X[1:]-X[:-1]
966 d = X[1:]-X[:-1]
965
967
966 up = np.where(d==1)[0]
968 up = np.where(d==1)[0]
967 if X[0]==1:
969 if X[0]==1:
968 up = np.concatenate((np.array([-1]), up))
970 up = np.concatenate((np.array([-1]), up))
969 up += 1
971 up += 1
970
972
971 dw = np.where(d==-1)[0]
973 dw = np.where(d==-1)[0]
972 if X[-1]==1:
974 if X[-1]==1:
973 dw = np.concatenate((dw, np.array([len(X)-1])))
975 dw = np.concatenate((dw, np.array([len(X)-1])))
974 dw += 1
976 dw += 1
975
977
976 return [(tup[0], tup[1]) for tup in zip(up, dw)]
978 return [(tup[0], tup[1]) for tup in zip(up, dw)]
977
979
978 @staticmethod
980 @staticmethod
979 def mask_ranges(Y, ranges):
981 def mask_ranges(Y, ranges):
980
982
981 y = [(0, 0) for __ in Y]
983 y = [(0, 0) for __ in Y]
982
984
983 for index in ranges:
985 for index in ranges:
984 if '-' in index:
986 if '-' in index:
985 args = [int(a) for a in index.split('-')]
987 args = [int(a) for a in index.split('-')]
986 y[args[0]-1:args[1]] = Y[args[0]-1:args[1]]
988 y[args[0]-1:args[1]] = Y[args[0]-1:args[1]]
987 else:
989 else:
988 y[int(index)-1] = Y[int(index)-1]
990 y[int(index)-1] = Y[int(index)-1]
989
991
990 return y
992 return y
991
993
992 @staticmethod
994 @staticmethod
993 def points(ntx, ipp, width, delay=[0], before=0, after=0, sync=0):
995 def points(ntx, ipp, width, delay=[0], before=0, after=0, sync=0):
994
996
995 delays = len(delay)
997 delays = len(delay)
996
998
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)]
999 Y = [(int(ipp*x+before+delay[x%delays]+sync), int(ipp*x+width+before+delay[x%delays]+after+sync)) for x in range(ntx)]
998
1000
999 return Y
1001 return Y
General Comments 0
You need to be logged in to leave comments. Login now