##// END OF EJS Templates
Update cr models.py to show used memory in plot_pulses view
jrojas -
r409:ff996bcda7e9
parent child
Show More
@@ -1,1027 +1,1079
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.urls 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 #print(data)
161 # self.name = data['name']
162 # self.name = data['name']
162 self.ipp = data['ipp']
163 self.ipp = data['ipp']
163 self.ntx = data['ntx']
164 self.ntx = data['ntx']
164 self.clock_in = data['clock_in']
165 self.clock_in = data['clock_in']
165 self.clock_divider = data['clock_divider']
166 self.clock_divider = data['clock_divider']
166 self.clock = data['clock']
167 self.clock = data['clock']
167 self.time_before = data['time_before']
168 self.time_before = data['time_before']
168 self.time_after = data['time_after']
169 self.time_after = data['time_after']
169 self.sync = data['sync']
170 self.sync = data['sync']
170 self.sampling_reference = data['sampling_reference']
171 self.sampling_reference = data['sampling_reference']
171 self.total_units = self.ipp*self.ntx*self.km2unit
172 self.total_units = self.ipp*self.ntx*self.km2unit
172 self.save()
173 self.save()
173 self.clean_lines()
174 self.clean_lines()
174
175
176 #print(params)
177
175 positions = {'tx':0, 'tr':0}
178 positions = {'tx':0, 'tr':0}
176 for i, id in enumerate(data['lines']):
179 for i, id in enumerate(data['lines']):
177 line_data = params['lines']['byId'][id]
180 line_data = params['lines']['byId'][id]
178 line_type = RCLineType.objects.get(name=line_data['line_type'])
181 line_type = RCLineType.objects.get(name=line_data['line_type'])
179 if line_type.name == 'codes':
182 if line_type.name == 'codes':
180 code = RCLineCode.objects.get(name=line_data['params']['code'])
183 code = RCLineCode.objects.get(name=line_data['params']['code'])
181 line_data['params']['code'] = code.pk
184 line_data['params']['code'] = code.pk
182 if line_type.name == 'tx':
185 if line_type.name == 'tx':
183 position = positions['tx']
186 position = positions['tx']
184 positions['tx'] += 1
187 positions['tx'] += 1
185 elif line_type.name == 'tr':
188 elif line_type.name == 'tr':
186 position = positions['tr']
189 position = positions['tr']
187 positions['tr'] += 1
190 positions['tr'] += 1
188 else:
191 else:
189 position = 0
192 position = 0
190 line, dum = RCLine.objects.update_or_create(
193 line, dum = RCLine.objects.update_or_create(
191 rc_configuration=self,
194 rc_configuration=self,
192 channel=i,
195 channel=i,
193 position=position,
196 position=position,
194 defaults={
197 defaults={
195 'line_type': line_type,
198 'line_type': line_type,
196 'params': json.dumps(line_data['params'])
199 'params': json.dumps(line_data['params'])
197 }
200 }
198 )
201 )
199
202
200 for i, line in enumerate(self.get_lines()):
203 for i, line in enumerate(self.get_lines()):
201 line_params = json.loads(line.params)
204 line_params = json.loads(line.params)
202 if 'TX_ref' in line_params:
205 if 'TX_ref' in line_params:
203 if line_params['TX_ref'] in (0, '0'):
206 if line_params['TX_ref'] in (0, '0'):
204 line_params['TX_ref'] = '0'
207 line_params['TX_ref'] = '0'
205 else:
208 else:
206 ref_id = '{}'.format(line_params['TX_ref'])
209 ref_id = '{}'.format(line_params['TX_ref'])
207 ref_line = params['lines']['byId'][ref_id]
210 ref_line = params['lines']['byId'][ref_id]
208 line_params['TX_ref'] = RCLine.objects.get(
211 line_params['TX_ref'] = RCLine.objects.get(
209 rc_configuration=self,
212 rc_configuration=self,
210 params=json.dumps(ref_line['params'])
213 params=json.dumps(ref_line['params'])
211 ).pk
214 ).pk
212 line.params = json.dumps(line_params)
215 line.params = json.dumps(line_params)
216 print(line.params)
213 line.save()
217 line.save()
214
218 print("Fin de dict to param")
215
219
216 def get_delays(self):
220 def get_delays(self):
217
221
218 pulses = [line.pulses_as_points() for line in self.get_lines()]
222 pulses = [line.pulses_as_points() for line in self.get_lines()]
219 points = [tup for tups in pulses for tup in tups]
223 points = [tup for tups in pulses for tup in tups]
220 points = set([x for tup in points for x in tup])
224 points = set([x for tup in points for x in tup])
221 points = list(points)
225 points = list(points)
222 points.sort()
226 points.sort()
223
227
224 if points[0]!=0:
228 if points[0]!=0:
225 points.insert(0, 0)
229 points.insert(0, 0)
226
230
227 return [points[i+1]-points[i] for i in range(len(points)-1)]
231 return [points[i+1]-points[i] for i in range(len(points)-1)]
228
232
229
230 def get_pulses(self, binary=True):
233 def get_pulses(self, binary=True):
231
234
232 pulses = [line.pulses_as_points() for line in self.get_lines()]
235 pulses = [line.pulses_as_points() for line in self.get_lines()]
233 tuples = [tup for tups in pulses for tup in tups]
236 tuples = [tup for tups in pulses for tup in tups]
234 points = set([x for tup in tuples for x in tup])
237 points = set([x for tup in tuples for x in tup])
235 points = list(points)
238 points = list(points)
236 points.sort()
239 points.sort()
237 states = []
240 states = []
238 last = [0 for x in pulses]
241 last = [0 for x in pulses]
242 n_pulses = len(pulses)
243 print('len_pulses', n_pulses)
244 print('len_points', len(points))
245 ups_arr = [[] for _ in range(n_pulses)]
246 dws_arr = [[] for _ in range(n_pulses)]
247
248 for i, tups in enumerate(pulses):
249 ups_arr[i] = [tup[0] for tup in tups if tup!=(0,0)]
250 dws_arr[i] = [tup[1] for tup in tups if tup!=(0,0)]
251 print('len_points*n_pulses',len(points)*n_pulses)
252 #print('ups_arr', ups_arr)
253 #print('dws_arr', dws_arr)
239
254
240 for x in points:
255 for x in points:
241 dum = []
256 dum = []
242 for i, tups in enumerate(pulses):
257 print('loading', x*100/max(points))
243 ups = [tup[0] for tup in tups if tup!=(0,0)]
258
244 dws = [tup[1] for tup in tups if tup!=(0,0)]
259 for i in range(n_pulses):
245 if x in ups:
260 if x in ups_arr[i]:
246 dum.append(1)
261 dum.append(1)
247 elif x in dws:
262 elif x in dws_arr[i]:
248 dum.append(0)
263 dum.append(0)
249 else:
264 else:
250 dum.append(last[i])
265 dum.append(last[i])
251 states.append(dum)
266 #print(dum)
267 states.append(dum)
252 last = dum
268 last = dum
253
269
254 if binary:
270 if binary:
255 ret = []
271 ret = []
256 for flips in states:
272 for flips in states:
257 flips.reverse()
273 flips.reverse()
258 ret.append(int(''.join([str(x) for x in flips]), 2))
274 ret.append(int(''.join([str(x) for x in flips]), 2))
259 states = ret
275 states = ret
276 #print(states[:-1])
277 #print('len_states',len(states[:-1]))
260
278
261 return states[:-1]
279 return states[:-1]
262
280
263 def add_cmd(self, cmd):
281 def add_cmd(self, cmd):
264
282
265 if cmd in DAT_CMDS:
283 if cmd in DAT_CMDS:
266 return (255, DAT_CMDS[cmd])
284 return (255, DAT_CMDS[cmd])
267
285
268 def add_data(self, value):
286 def add_data(self, value):
269
287
270 return (254, value-1)
288 return (254, value-1)
271
289
272 def parms_to_binary(self, dat=True):
290 def parms_to_binary(self, dat=True):
273 '''
291 '''
274 Create "dat" stream to be send to CR
292 Create "dat" stream to be send to CR
275 '''
293 '''
276
294
277 data = bytearray()
295 data = bytearray()
278 # create header
296 # create header
279 data.extend(self.add_cmd('DISABLE'))
297 data.extend(self.add_cmd('DISABLE'))
280 data.extend(self.add_cmd('CONTINUE'))
298 data.extend(self.add_cmd('CONTINUE'))
281 data.extend(self.add_cmd('RESTART'))
299 data.extend(self.add_cmd('RESTART'))
282
300
283 if self.control_sw:
301 if self.control_sw:
284 data.extend(self.add_cmd('SW_ONE'))
302 data.extend(self.add_cmd('SW_ONE'))
285 else:
303 else:
286 data.extend(self.add_cmd('SW_ZERO'))
304 data.extend(self.add_cmd('SW_ZERO'))
287
305
288 if self.control_tx:
306 if self.control_tx:
289 data.extend(self.add_cmd('TX_ONE'))
307 data.extend(self.add_cmd('TX_ONE'))
290 else:
308 else:
291 data.extend(self.add_cmd('TX_ZERO'))
309 data.extend(self.add_cmd('TX_ZERO'))
292
310
293 # write divider
311 # write divider
294 data.extend(self.add_cmd('CLOCK_DIVIDER'))
312 data.extend(self.add_cmd('CLOCK_DIVIDER'))
295 data.extend(self.add_data(self.clock_divider))
313 data.extend(self.add_data(self.clock_divider))
296
314
297 # write delays
315 # write delays
298 data.extend(self.add_cmd('DELAY_START'))
316 data.extend(self.add_cmd('DELAY_START'))
299 # first delay is always zero
317 # first delay is always zero
300 data.extend(self.add_data(1))
318 data.extend(self.add_data(1))
301
319
302 delays = self.get_delays()
320 delays = self.get_delays()
303
321
304 for delay in delays:
322 for delay in delays:
305 while delay>252:
323 while delay>252:
306 data.extend(self.add_data(253))
324 data.extend(self.add_data(253))
307 delay -= 253
325 delay -= 253
308 data.extend(self.add_data(int(delay)))
326 data.extend(self.add_data(int(delay)))
309
327
310 # write flips
328 # write flips
311 data.extend(self.add_cmd('FLIP_START'))
329 data.extend(self.add_cmd('FLIP_START'))
312
330
313 states = self.get_pulses(binary=True)
331 states = self.get_pulses(binary=True)
314
332
315
333
316 last = 0
334 last = 0
317 for flip, delay in zip(states, delays):
335 for flip, delay in zip(states, delays):
318 data.extend(self.add_data((flip^last)+1))
336 data.extend(self.add_data((flip^last)+1))
319 last = flip
337 last = flip
320 while delay>252:
338 while delay>252:
321 data.extend(self.add_data(1))
339 data.extend(self.add_data(1))
322 delay -= 253
340 delay -= 253
323
341
324 # write sampling period
342 # write sampling period
325 data.extend(self.add_cmd('SAMPLING_PERIOD'))
343 data.extend(self.add_cmd('SAMPLING_PERIOD'))
326 wins = self.get_lines(line_type__name='windows')
344 wins = self.get_lines(line_type__name='windows')
327 if wins:
345 if wins:
328 win_params = json.loads(wins[0].params)['params']
346 win_params = json.loads(wins[0].params)['params']
329 if win_params:
347 if win_params:
330 dh = int(win_params[0]['resolution']*self.km2unit)
348 dh = int(win_params[0]['resolution']*self.km2unit)
331 else:
349 else:
332 dh = 1
350 dh = 1
333 else:
351 else:
334 dh = 1
352 dh = 1
335 data.extend(self.add_data(dh))
353 data.extend(self.add_data(dh))
336
354
337 # write enable
355 # write enable
338 data.extend(self.add_cmd('ENABLE'))
356 data.extend(self.add_cmd('ENABLE'))
339
357
340 if not dat:
358 if not dat:
341 return data
359 return data
342
360
343 return '\n'.join(['{}'.format(x) for x in data])
361 return '\n'.join(['{}'.format(x) for x in data])
344
362
345 def update_pulses(self):
363 def update_pulses(self):
346
364 contador = 0
347 for line in self.get_lines():
365 for line in self.get_lines():
366 contador=contador+1
367 print(contador)
348 line.update_pulses()
368 line.update_pulses()
349
369
350 def plot_pulses2(self, km=False):
370 def plot_pulses2(self, km=False):
351
371
352 import matplotlib
372 import matplotlib
353 matplotlib.use('Agg')
373 matplotlib.use('Agg')
354 import matplotlib.pyplot as plt
374 import matplotlib.pyplot as plt
355 from bokeh.resources import CDN
375 from bokeh.resources import CDN
356 from bokeh.embed import components
376 from bokeh.embed import components
357 from bokeh.mpl import to_bokeh
377 from bokeh.mpl import to_bokeh
358 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, HoverTool, SaveTool
378 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, HoverTool, SaveTool
359
379
360 lines = self.get_lines()
380 lines = self.get_lines()
361
381
362 N = len(lines)
382 N = len(lines)
363 npoints = self.total_units/self.km2unit if km else self.total_units
383 npoints = self.total_units/self.km2unit if km else self.total_units
364 fig = plt.figure(figsize=(12, 2+N*0.5))
384 fig = plt.figure(figsize=(12, 2+N*0.5))
365 ax = fig.add_subplot(111)
385 ax = fig.add_subplot(111)
366 labels = ['IPP']
386 labels = ['IPP']
367
387
368 for i, line in enumerate(lines):
388 for i, line in enumerate(lines):
369 labels.append(line.get_name(channel=True))
389 labels.append(line.get_name(channel=True))
370 l = ax.plot((0, npoints),(N-i-1, N-i-1))
390 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)]
391 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),
392 ax.broken_barh(points, (N-i-1, 0.5),
373 edgecolor=l[0].get_color(), facecolor='none')
393 edgecolor=l[0].get_color(), facecolor='none')
374
394
375 n = 0
395 n = 0
376 f = ((self.ntx+50)/100)*5 if ((self.ntx+50)/100)*10>0 else 2
396 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):
397 for x in np.arange(0, npoints, self.ipp if km else self.ipp*self.km2unit):
378 if n%f==0:
398 if n%f==0:
379 ax.text(x, N, '%s' % n, size=10)
399 ax.text(x, N, '%s' % n, size=10)
380 n += 1
400 n += 1
381
401
382 labels.reverse()
402 labels.reverse()
383 ax.set_yticks(range(len(labels)))
403 ax.set_yticks(range(len(labels)))
384 ax.set_yticklabels(labels)
404 ax.set_yticklabels(labels)
385 ax.set_xlabel = 'Units'
405 ax.set_xlabel = 'Units'
386 plot = to_bokeh(fig, use_pandas=False)
406 plot = to_bokeh(fig, use_pandas=False)
387 plot.tools = [PanTool(dimensions=['width']), WheelZoomTool(dimensions=['width']), ResetTool(), SaveTool()]
407 plot.tools = [PanTool(dimensions="width"), WheelZoomTool(dimensions="width"), ResetTool(), SaveTool()]
388 plot.toolbar_location="above"
408 plot.toolbar_location="above"
389
409
390 return components(plot, CDN)
410 return components(plot, CDN)
391
411
392 def plot_pulses(self, km=False):
412 def plot_pulses(self, km=False):
393
413
394 from bokeh.plotting import figure
414 from bokeh.plotting import figure
395 from bokeh.resources import CDN
415 from bokeh.resources import CDN
396 from bokeh.embed import components
416 from bokeh.embed import components
397 from bokeh.models import FixedTicker, PrintfTickFormatter
417 from bokeh.models import FixedTicker, PrintfTickFormatter, Label
398 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, HoverTool, SaveTool
418 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, HoverTool, SaveTool
399 from bokeh.models.sources import ColumnDataSource
419 from bokeh.models.sources import ColumnDataSource
400
420
401 lines = self.get_lines().reverse()
421 lines = self.get_lines().reverse()
402
422
403 N = len(lines)
423 N = len(lines)
404 npoints = self.total_units/self.km2unit if km else self.total_units
424 npoints = self.total_units/self.km2unit if km else self.total_units
405 ipp = self.ipp if km else self.ipp*self.km2unit
425 ipp = self.ipp if km else self.ipp*self.km2unit
406
426
407 hover = HoverTool(tooltips=[("Line", "@name"),
427 hover = HoverTool(tooltips=[("Line", "@name"),
408 ("IPP", "@ipp"),
428 ("IPP", "@ipp"),
409 ("X", "@left")])
429 ("X", "@left")])
410
430
411 tools = [PanTool(dimensions=['width']),
431 tools = [PanTool(dimensions="width"),
412 WheelZoomTool(dimensions=['width']),
432 WheelZoomTool(dimensions="width"),
413 hover, SaveTool()]
433 hover, SaveTool()]
414
434
415 plot = figure(width=1000,
435 plot = figure(width=1000,
416 height=40+N*50,
436 height=40+N*50,
417 y_range = (0, N),
437 y_range = (0, N),
418 tools=tools,
438 tools=tools,
419 toolbar_location='above',
439 toolbar_location='above',
420 toolbar_sticky=False,)
440 toolbar_sticky=False,)
421
441
442 pulses = [line.pulses_as_points() for line in self.get_lines()]
443 tuples = [tup for tups in pulses for tup in tups]
444 points = set([x for tup in tuples for x in tup])
445 capacity_bytes = round((8*(len(points)-1)+12)/2) # se divide entre 2 porque la mitad era solo para direcciones
446 capacity_percent = (capacity_bytes/2097152)*100
447 # Add the used memory message
448 x_label_memory = Label(x=900, y=-1.5, text='Used memory of '+str(capacity_bytes)+'/2097152 bytes ('+'%.3f'%capacity_percent+'%)', text_align="right", x_units='screen', text_font_size='14pt')
449 plot.add_layout(x_label_memory, 'below')
450
422 plot.xaxis.axis_label = 'Km' if km else 'Units'
451 plot.xaxis.axis_label = 'Km' if km else 'Units'
423 plot.xaxis[0].formatter = PrintfTickFormatter(format='%d')
452 plot.xaxis[0].formatter = PrintfTickFormatter(format='%d')
424 plot.yaxis.axis_label = 'Pulses'
453 plot.yaxis.axis_label = 'Pulses'
425 plot.yaxis[0].ticker=FixedTicker(ticks=list(range(N)))
454 plot.yaxis[0].ticker=FixedTicker(ticks=list(range(N)))
426 plot.yaxis[0].formatter = PrintfTickFormatter(format='Line %d')
455 plot.yaxis[0].formatter = PrintfTickFormatter(format='Line %d')
427
456
428 for i, line in enumerate(lines):
457 for i, line in enumerate(lines):
429
458
430 points = [tup for tup in line.pulses_as_points(km=km) if tup!=(0,0)]
459 points = [tup for tup in line.pulses_as_points(km=km) if tup!=(0,0)]
431
460
432 source = ColumnDataSource(data = dict(
461 source = ColumnDataSource(data = dict(
433 bottom = [i for tup in points],
462 bottom = [i for tup in points],
434 top = [i+0.5 for tup in points],
463 top = [i+0.5 for tup in points],
435 left = [tup[0] for tup in points],
464 left = [tup[0] for tup in points],
436 right = [tup[1] for tup in points],
465 right = [tup[1] for tup in points],
437 ipp = [int(tup[0]/ipp) for tup in points],
466 ipp = [int(tup[0]/ipp) for tup in points],
438 name = [line.get_name() for tup in points]
467 name = [line.get_name() for tup in points]
439 ))
468 ))
440
469
441 plot.quad(
470 plot.quad(
442 bottom = 'bottom',
471 bottom = 'bottom',
443 top = 'top',
472 top = 'top',
444 left = 'left',
473 left = 'left',
445 right = 'right',
474 right = 'right',
446 source = source,
475 source = source,
447 fill_alpha = 0,
476 fill_alpha = 0,
448 #line_color = 'blue',
477 #line_color = 'blue',
449 )
478 )
450
479
451 plot.line([0, npoints], [i, i])#, color='blue')
480 plot.line([0, npoints], [i, i])#, color='blue')
452
481
453 return components(plot, CDN)
482 return components(plot, CDN)
454
483
455 def request(self, cmd, method='get', **kwargs):
484 def request(self, cmd, method='get', **kwargs):
456
485
457 req = getattr(requests, method)(self.device.url(cmd), **kwargs)
486 req = getattr(requests, method)(self.device.url(cmd), **kwargs)
458 payload = req.json()
487 payload = req.json()
459
488
460 return payload
489 return payload
461
490
462 def status_device(self):
491 def status_device(self):
463
492
464 try:
493 try:
465 self.device.status = 0
494 self.device.status = 0
466 payload = self.request('status')
495 payload = self.request('status')
467 if payload['status']=='enable':
496 if payload['status']=='enable':
468 self.device.status = 3
497 self.device.status = 3
469 elif payload['status']=='disable':
498 elif payload['status']=='disable':
470 self.device.status = 2
499 self.device.status = 2
471 else:
500 else:
472 self.device.status = 1
501 self.device.status = 1
473 self.device.save()
502 self.device.save()
474 self.message = 'RC status: {}'.format(payload['status'])
503 self.message = 'RC status: {}'.format(payload['status'])
475 return False
504 return False
476 except Exception as e:
505 except Exception as e:
477 if 'No route to host' not in str(e):
506 if 'No route to host' not in str(e):
478 self.device.status = 4
507 self.device.status = 4
479 self.device.save()
508 self.device.save()
480 self.message = 'RC status: {}'.format(str(e))
509 self.message = 'RC status: {}'.format(str(e))
481 return False
510 return False
482
511
483 self.device.save()
512 self.device.save()
484 return True
513 return True
485
514
486 def reset_device(self):
515 def reset_device(self):
487
516
488 try:
517 try:
489 payload = self.request('reset', 'post')
518 payload = self.request('reset', 'post')
490 if payload['reset']=='ok':
519 if payload['reset']=='ok':
491 self.message = 'RC restarted OK'
520 self.message = 'RC restarted OK'
492 self.device.status = 2
521 self.device.status = 2
493 self.device.save()
522 self.device.save()
494 else:
523 else:
495 self.message = 'RC restart fail'
524 self.message = 'RC restart fail'
496 self.device.status = 4
525 self.device.status = 4
497 self.device.save()
526 self.device.save()
498 except Exception as e:
527 except Exception as e:
499 self.message = 'RC reset: {}'.format(str(e))
528 self.message = 'RC reset: {}'.format(str(e))
500 return False
529 return False
501
530
502 return True
531 return True
503
532
504 def stop_device(self):
533 def stop_device(self):
505
534
506 try:
535 try:
507 payload = self.request('stop', 'post')
536 payload = self.request('stop', 'post')
508 self.message = 'RC stop: {}'.format(payload['stop'])
537 self.message = 'RC stop: {}'.format(payload['stop'])
509 if payload['stop']=='ok':
538 if payload['stop']=='ok':
510 self.device.status = 2
539 self.device.status = 2
511 self.device.save()
540 self.device.save()
512 else:
541 else:
513 self.device.status = 4
542 self.device.status = 4
514 self.device.save()
543 self.device.save()
515 return False
544 return False
516 except Exception as e:
545 except Exception as e:
517 if 'No route to host' not in str(e):
546 if 'No route to host' not in str(e):
518 self.device.status = 4
547 self.device.status = 4
519 else:
548 else:
520 self.device.status = 0
549 self.device.status = 0
521 self.message = 'RC stop: {}'.format(str(e))
550 self.message = 'RC stop: {}'.format(str(e))
522 self.device.save()
551 self.device.save()
523 return False
552 return False
524
553
525 return True
554 return True
526
555
527 def start_device(self):
556 def start_device(self):
528
557
529 try:
558 try:
530 payload = self.request('start', 'post')
559 payload = self.request('start', 'post')
531 self.message = 'RC start: {}'.format(payload['start'])
560 self.message = 'RC start: {}'.format(payload['start'])
532 if payload['start']=='ok':
561 if payload['start']=='ok':
533 self.device.status = 3
562 self.device.status = 3
534 self.device.save()
563 self.device.save()
535 else:
564 else:
536 return False
565 return False
537 except Exception as e:
566 except Exception as e:
538 if 'No route to host' not in str(e):
567 if 'No route to host' not in str(e):
539 self.device.status = 4
568 self.device.status = 4
540 else:
569 else:
541 self.device.status = 0
570 self.device.status = 0
542 self.message = 'RC start: {}'.format(str(e))
571 self.message = 'RC start: {}'.format(str(e))
543 self.device.save()
572 self.device.save()
544 return False
573 return False
545
574
546 return True
575 return True
547
576
548 def write_device(self, raw=False):
577 def write_device(self, raw=False):
578 print("write device")
549
579
550 if not raw:
580 if not raw:
551 clock = RCClock.objects.get(rc_configuration=self)
581 clock = RCClock.objects.get(rc_configuration=self)
552 if clock.mode:
582 if clock.mode:
553 data = {'default': clock.frequency}
583 data = {'default': clock.frequency}
554 else:
584 else:
555 data = {'manual': [clock.multiplier, clock.divisor, clock.reference]}
585 data = {'manual': [clock.multiplier, clock.divisor, clock.reference]}
556 payload = self.request('setfreq', 'post', data=json.dumps(data))
586 payload = self.request('setfreq', 'post', data=json.dumps(data))
557 if payload['command'] <> 'ok':
587 #if payload['setfreq'] != 'ok':
588 if payload['command'] != 'ok':
589 #self.message = 'RC write: {}'.format(payload['setfreq'])
558 self.message = 'RC write: {}'.format(payload['command'])
590 self.message = 'RC write: {}'.format(payload['command'])
559 else:
591 else:
592 #self.message = payload['setfreq']
560 self.message = payload['programming']
593 self.message = payload['programming']
594 #if payload['setfreq'] == 'fail':
561 if payload['programming'] == 'fail':
595 if payload['programming'] == 'fail':
562 self.message = 'RC write: error programming CGS chip'
596 self.message = 'RC write: error programming CGS chip'
563
597
564 values = []
598 values = []
599 print('wait delay values...')
565 for pulse, delay in zip(self.get_pulses(), self.get_delays()):
600 for pulse, delay in zip(self.get_pulses(), self.get_delays()):
566 while delay>65536:
601 #print('wait zip...')
602 while delay > 65536:
567 values.append((pulse, 65535))
603 values.append((pulse, 65535))
568 delay -= 65536
604 delay -= 65536
569 values.append((pulse, delay-1))
605 values.append((pulse, delay-1))
570 data = bytearray()
606 data = bytearray()
571 #reset
607 #reset
572 data.extend((128, 0))
608 data.extend((128, 0))
573 #disable
609 #disable
574 data.extend((129, 0))
610 data.extend((129, 0))
575 #SW switch
611 #SW switch
576 if self.control_sw:
612 if self.control_sw:
577 data.extend((130, 2))
613 data.extend((130, 2))
578 else:
614 else:
579 data.extend((130, 0))
615 data.extend((130, 0))
580 #divider
616 #divider
581 data.extend((131, self.clock_divider-1))
617 data.extend((131, self.clock_divider-1))
582 #enable writing
618 #enable writing
583 data.extend((139, 62))
619 data.extend((139, 62))
584
620
585 last = 0
621 last = 0
622 print('wait data...')
586 for tup in values:
623 for tup in values:
587 vals = pack('<HH', last^tup[0], tup[1])
624 vals = pack('<HH', last^tup[0], tup[1])
588 last = tup[0]
625 last = tup[0]
589 data.extend((133, vals[1], 132, vals[0], 133, vals[3], 132, vals[2]))
626 data.extend((133, vals[1], 132, vals[0], 133, vals[3], 132, vals[2]))
590
627
591 #enable
628 #enable
592 data.extend((129, 1))
629 data.extend((129, 1))
630 print('len',len(data))
593
631
594 if raw:
632 if raw:
595 return b64encode(data)
633 return b64encode(data)
596
634
597 try:
635 #try:
598 payload = self.request('stop', 'post')
636 print('requests')
599 payload = self.request('reset', 'post')
637 payload = self.request('stop', 'post')
600 #payload = self.request('divider', 'post', data={'divider': self.clock_divider-1})
638 payload = self.request('reset', 'post')
601 #payload = self.request('write', 'post', data=b64encode(bytearray((139, 62))), timeout=20)
639 #payload = self.request('divider', 'post', data={'divider': self.clock_divider-1})
602 n = len(data)
640 #payload = self.request('write', 'post', data=b64encode(bytearray((139, 62))), timeout=20)
603 x = 0
641 n = len(data)
604 #while x < n:
642 print('len: ',n)
605 payload = self.request('write', 'post', data=b64encode(data))
643 x = 0
606 # x += 1024
644 cnt = 0
607
645 while x < n:
608 if payload['write']=='ok':
646 print('writing...', cnt)
609 self.device.status = 3
647 payload = self.request('write', 'post', data=b64encode(data[x:x+3072]))#(data))#
610 self.device.save()
648 x += 3072
611 self.message = 'RC configured and started'
649 cnt += 1#time.sleep(1)
612 else:
650 print('writing...', x*100/n)
613 self.device.status = 1
651
614 self.device.save()
652 if payload['write']=='ok':
615 self.message = 'RC write: {}'.format(payload['write'])
653 self.device.status = 3
616 return False
654 self.device.save()
655 self.message = 'RC configured and started'
656 else:
657 self.device.status = 1
658 self.device.save()
659 self.message = 'RC write: {}'.format(payload['write'])
660 return False
617
661
618 #payload = self.request('start', 'post')
662 #payload = self.request('start', 'post')
619
663
620 except Exception as e:
664 #except Exception as e:
621 if 'No route to host' not in str(e):
665 # if 'No route to host' not in str(e):
622 self.device.status = 4
666 # self.device.status = 4
623 else:
667 # else:
624 self.device.status = 0
668 # self.device.status = 0
625 self.message = 'RC write: {}'.format(str(e))
669 # self.message = 'RC write: {}'.format(str(e))
626 self.device.save()
670 # self.device.save()
627 return False
671 # return False
628
672
629 return True
673 return True
630
674
631
675
632 def get_absolute_url_import(self):
676 def get_absolute_url_import(self):
633 return reverse('url_import_rc_conf', args=[str(self.id)])
677 return reverse('url_import_rc_conf', args=[str(self.id)])
634
678
635
679
636 class RCLineCode(models.Model):
680 class RCLineCode(models.Model):
637
681
638 name = models.CharField(max_length=40)
682 name = models.CharField(max_length=40)
639 bits_per_code = models.PositiveIntegerField(default=0)
683 bits_per_code = models.PositiveIntegerField(default=0)
640 number_of_codes = models.PositiveIntegerField(default=0)
684 number_of_codes = models.PositiveIntegerField(default=0)
641 codes = models.TextField(blank=True, null=True)
685 codes = models.TextField(blank=True, null=True)
642
686
643 class Meta:
687 class Meta:
644 db_table = 'rc_line_codes'
688 db_table = 'rc_line_codes'
645 ordering = ('name',)
689 ordering = ('name',)
646
690
647 def __str__(self):
691 def __str__(self):
648 return u'%s' % self.name
692 return u'%s' % self.name
649
693
650
694
651 class RCLineType(models.Model):
695 class RCLineType(models.Model):
652
696
653 name = models.CharField(choices=LINE_TYPES, max_length=40)
697 name = models.CharField(choices=LINE_TYPES, max_length=40)
654 description = models.TextField(blank=True, null=True)
698 description = models.TextField(blank=True, null=True)
655 params = models.TextField(default='[]')
699 params = models.TextField(default='[]')
656
700
657 class Meta:
701 class Meta:
658 db_table = 'rc_line_types'
702 db_table = 'rc_line_types'
659
703
660 def __str__(self):
704 def __str__(self):
661 return u'%s - %s' % (self.name.upper(), self.get_name_display())
705 return u'%s - %s' % (self.name.upper(), self.get_name_display())
662
706
663
707
664 class RCLine(models.Model):
708 class RCLine(models.Model):
665
709
666 rc_configuration = models.ForeignKey(RCConfiguration, on_delete=models.CASCADE)
710 rc_configuration = models.ForeignKey('RCConfiguration', on_delete=models.CASCADE)
667 line_type = models.ForeignKey(RCLineType)
711 line_type = models.ForeignKey('RCLineType',on_delete=models.CASCADE)
668 channel = models.PositiveIntegerField(default=0)
712 channel = models.PositiveIntegerField(default=0)
669 position = models.PositiveIntegerField(default=0)
713 position = models.PositiveIntegerField(default=0)
670 params = models.TextField(default='{}')
714 params = models.TextField(default='{}')
671 pulses = models.TextField(default='')
715 pulses = models.TextField(default='')
672
716
673 class Meta:
717 class Meta:
674 db_table = 'rc_lines'
718 db_table = 'rc_lines'
675 ordering = ['channel']
719 ordering = ['channel']
676
720
677 def __str__(self):
721 def __str__(self):
678 if self.rc_configuration:
722 if self.rc_configuration:
679 return u'{}|{} - {}'.format(self.pk, self.get_name(), self.rc_configuration.name)
723 return u'{}|{} - {}'.format(self.pk, self.get_name(), self.rc_configuration.name)
680
724
681 def jsonify(self):
725 def jsonify(self):
682
726
683 data = {}
727 data = {}
684 data['params'] = json.loads(self.params)
728 data['params'] = json.loads(self.params)
685 data['id'] = '{}'.format(self.pk)
729 data['id'] = '{}'.format(self.pk)
686 data['line_type'] = self.line_type.name
730 data['line_type'] = self.line_type.name
687 data['name'] = self.get_name()
731 data['name'] = self.get_name()
688 if data['line_type']=='codes':
732 if data['line_type']=='codes':
689 data['params']['code'] = RCLineCode.objects.get(pk=data['params']['code']).name
733 data['params']['code'] = RCLineCode.objects.get(pk=data['params']['code']).name
690
734
691 return data
735 return data
692
736
693
737
694 def clone(self, **kwargs):
738 def clone(self, **kwargs):
695
739
696 self.pk = None
740 self.pk = None
697 self.id = None
741 self.id = None
698
742
699 for attr, value in kwargs.items():
743 for attr, value in kwargs.items():
700 setattr(self, attr, value)
744 setattr(self, attr, value)
701
745
702 self.save()
746 self.save()
703
747
704 return self
748 return self
705
749
706 def get_name(self, channel=False):
750 def get_name(self, channel=False):
707
751
708 chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
752 chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
709 s = ''
753 s = ''
710
754
711 if self.line_type.name in ('tx',):
755 if self.line_type.name in ('tx',):
712 s = chars[self.position]
756 s = chars[self.position]
713 elif self.line_type.name in ('codes', 'windows', 'tr'):
757 elif self.line_type.name in ('codes', 'windows', 'tr'):
714 if 'TX_ref' in json.loads(self.params):
758 if 'TX_ref' in json.loads(self.params):
715 pk = json.loads(self.params)['TX_ref']
759 pk = json.loads(self.params)['TX_ref']
716 if pk in (0, '0'):
760 if pk in (0, '0'):
717 s = ','.join(chars[l.position] for l in self.rc_configuration.get_lines(line_type__name='tx'))
761 s = ','.join(chars[l.position] for l in self.rc_configuration.get_lines(line_type__name='tx'))
718 else:
762 else:
719 ref = RCLine.objects.get(pk=pk)
763 ref = RCLine.objects.get(pk=pk)
720 s = chars[ref.position]
764 s = chars[ref.position]
721 s = '({})'.format(s)
765 s = '({})'.format(s)
722
766
723 s = '{}{}'.format(self.line_type.name.upper(), s)
767 s = '{}{}'.format(self.line_type.name.upper(), s)
724
768
725 if channel:
769 if channel:
726 return '{} {}'.format(s, self.channel)
770 return '{} {}'.format(s, self.channel)
727 else:
771 else:
728 return s
772 return s
729
773
730 def get_lines(self, **kwargs):
774 def get_lines(self, **kwargs):
731
775
732 return RCLine.objects.filter(rc_configuration=self.rc_configuration, **kwargs)
776 return RCLine.objects.filter(rc_configuration=self.rc_configuration, **kwargs)
733
777
734 def pulses_as_array(self):
778 def pulses_as_array(self):
735
779
736 y = np.zeros(self.rc_configuration.total_units)
780 y = np.zeros(self.rc_configuration.total_units)
737
781
738 for tup in ast.literal_eval(self.pulses):
782 for tup in ast.literal_eval(self.pulses):
739 y[tup[0]:tup[1]] = 1
783 y[tup[0]:tup[1]] = 1
740
784
741 return y.astype(np.int8)
785 return y.astype(np.int8)
742
786
743 def pulses_as_points(self, km=False):
787 def pulses_as_points(self, km=False):
744
788
745 if km:
789 if km:
746 unit2km = 1/self.rc_configuration.km2unit
790 unit2km = 1/self.rc_configuration.km2unit
747 return [(tup[0]*unit2km, tup[1]*unit2km) for tup in ast.literal_eval(self.pulses)]
791 return [(tup[0]*unit2km, tup[1]*unit2km) for tup in ast.literal_eval(self.pulses)]
748 else:
792 else:
749 return ast.literal_eval(self.pulses)
793 return ast.literal_eval(self.pulses)
750
794
751 def get_win_ref(self, params, tx_id, km2unit):
795 def get_win_ref(self, params, tx_id, km2unit):
752
796
753 ref = self.rc_configuration.sampling_reference
797 ref = self.rc_configuration.sampling_reference
754 codes = [line for line in self.get_lines(line_type__name='codes') if int(json.loads(line.params)['TX_ref'])==int(tx_id)]
798 codes = [line for line in self.get_lines(line_type__name='codes') if int(json.loads(line.params)['TX_ref'])==int(tx_id)]
755
799
756 if codes:
800 if codes:
757 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit/len(json.loads(codes[0].params)['codes'][0])
801 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit/len(json.loads(codes[0].params)['codes'][0])
758 else:
802 else:
759 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit
803 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit
760
804
761 if ref=='first_baud':
805 if ref=='first_baud':
762 return int(1 + round((tx_width + 1)/2 + params['first_height']*km2unit - params['resolution']*km2unit))
806 return int(1 + round((tx_width + 1)/2 + params['first_height']*km2unit - params['resolution']*km2unit))
763 elif ref=='sub_baud':
807 elif ref=='sub_baud':
764 return np.ceil(1 + params['first_height']*km2unit - params['resolution']*km2unit/2)
808 return np.ceil(1 + params['first_height']*km2unit - params['resolution']*km2unit/2)
765 else:
809 else:
766 return 0
810 return 0
767
811
768 def update_pulses(self):
812 def update_pulses(self):
769 '''
813 '''
770 Update pulses field
814 Update pulses field
771 '''
815 '''
772
816
773 km2unit = self.rc_configuration.km2unit
817 km2unit = self.rc_configuration.km2unit
774 us2unit = self.rc_configuration.us2unit
818 us2unit = self.rc_configuration.us2unit
775 ipp = self.rc_configuration.ipp
819 ipp = self.rc_configuration.ipp
776 ntx = int(self.rc_configuration.ntx)
820 ntx = int(self.rc_configuration.ntx)
777 ipp_u = int(ipp*km2unit)
821 ipp_u = int(ipp*km2unit)
778 total = ipp_u*ntx if self.rc_configuration.total_units==0 else self.rc_configuration.total_units
822 total = ipp_u*ntx if self.rc_configuration.total_units==0 else self.rc_configuration.total_units
779 y = []
823 y = []
780
824
781 if self.line_type.name=='tr':
825 if self.line_type.name=='tr':
782 tr_params = json.loads(self.params)
826 tr_params = json.loads(self.params)
783
827 #print(tr_params)
828 #print(tr_params['TX_ref'])
784 if tr_params['TX_ref'] in ('0', 0):
829 if tr_params['TX_ref'] in ('0', 0):
785 txs = self.get_lines(line_type__name='tx')
830 txs = self.get_lines(line_type__name='tx')
786 else:
831 else:
787 txs = RCLine.objects.filter(pk=tr_params['TX_ref'])
832 txs = RCLine.objects.filter(pk=tr_params['TX_ref'])
788
833
789 for tx in txs:
834 for tx in txs:
790 params = json.loads(tx.params)
835 params = json.loads(tx.params)
791
836
792 if float(params['pulse_width'])==0:
837 if float(params['pulse_width'])==0:
793 continue
838 continue
794 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
839 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
795 width = float(params['pulse_width'])*km2unit+int(self.rc_configuration.time_before*us2unit)
840 width = float(params['pulse_width'])*km2unit+int(self.rc_configuration.time_before*us2unit)
796 before = 0
841 before = 0
797 after = int(self.rc_configuration.time_after*us2unit)
842 after = int(self.rc_configuration.time_after*us2unit)
798
843
799 y_tx = self.points(ntx, ipp_u, width,
844 y_tx = self.points(ntx, ipp_u, width,
800 delay=delays,
845 delay=delays,
801 before=before,
846 before=before,
802 after=after,
847 after=after,
803 sync=self.rc_configuration.sync)
848 sync=self.rc_configuration.sync)
804
849
805 ranges = params['range'].split(',')
850 ranges = params['range'].split(',')
806
851
807 if len(ranges)>0 and ranges[0]!='0':
852 if len(ranges)>0 and ranges[0]!='0':
808 y_tx = self.mask_ranges(y_tx, ranges)
853 y_tx = self.mask_ranges(y_tx, ranges)
809
854
810 tr_ranges = tr_params['range'].split(',')
855 tr_ranges = tr_params['range'].split(',')
811
856
812 if len(tr_ranges)>0 and tr_ranges[0]!='0':
857 if len(tr_ranges)>0 and tr_ranges[0]!='0':
813 y_tx = self.mask_ranges(y_tx, tr_ranges)
858 y_tx = self.mask_ranges(y_tx, tr_ranges)
814
859
815 y.extend(y_tx)
860 y.extend(y_tx)
816
861
817 self.pulses = str(y)
862 self.pulses = str(y)
818 y = self.array_to_points(self.pulses_as_array())
863 y = self.array_to_points(self.pulses_as_array())
819
864
820 elif self.line_type.name=='tx':
865 elif self.line_type.name=='tx':
821 params = json.loads(self.params)
866 params = json.loads(self.params)
822 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
867 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
823 width = float(params['pulse_width'])*km2unit
868 width = float(params['pulse_width'])*km2unit
824
869
825 if width>0:
870 if width>0:
826 before = int(self.rc_configuration.time_before*us2unit)
871 before = int(self.rc_configuration.time_before*us2unit)
827 after = 0
872 after = 0
828
873
829 y = self.points(ntx, ipp_u, width,
874 y = self.points(ntx, ipp_u, width,
830 delay=delays,
875 delay=delays,
831 before=before,
876 before=before,
832 after=after,
877 after=after,
833 sync=self.rc_configuration.sync)
878 sync=self.rc_configuration.sync)
834
879
835 ranges = params['range'].split(',')
880 ranges = params['range'].split(',')
836
881
837 if len(ranges)>0 and ranges[0]!='0':
882 if len(ranges)>0 and ranges[0]!='0':
838 y = self.mask_ranges(y, ranges)
883 y = self.mask_ranges(y, ranges)
839
884
840 elif self.line_type.name=='flip':
885 elif self.line_type.name=='flip':
841 n = float(json.loads(self.params)['number_of_flips'])
886 n = float(json.loads(self.params)['number_of_flips'])
842 width = n*ipp*km2unit
887 width = n*ipp*km2unit
843 y = self.points(int((ntx+1)/(2*n)), ipp_u*n*2, width)
888 y = self.points(int((ntx+1)/(2*n)), ipp_u*n*2, width)
844
889
845 elif self.line_type.name=='codes':
890 elif self.line_type.name=='codes':
846 params = json.loads(self.params)
891 params = json.loads(self.params)
847 tx = RCLine.objects.get(pk=params['TX_ref'])
892 tx = RCLine.objects.get(pk=params['TX_ref'])
848 tx_params = json.loads(tx.params)
893 tx_params = json.loads(tx.params)
849 delays = [float(d)*km2unit for d in tx_params['delays'].split(',') if d]
894 delays = [float(d)*km2unit for d in tx_params['delays'].split(',') if d]
850 f = int(float(tx_params['pulse_width'])*km2unit/len(params['codes'][0]))
895 f = int(float(tx_params['pulse_width'])*km2unit/len(params['codes'][0]))
851 codes = [(np.fromstring(''.join([s*f for s in code]), dtype=np.uint8)-48).astype(np.int8) for code in params['codes']]
896 codes = [(np.fromstring(''.join([s*f for s in code]), dtype=np.uint8)-48).astype(np.int8) for code in params['codes']]
852 codes = [self.array_to_points(code) for code in codes]
897 codes = [self.array_to_points(code) for code in codes]
853 n = len(codes)
898 n = len(codes)
854
899
855 ranges = tx_params['range'].split(',')
900 ranges = tx_params['range'].split(',')
856 if len(ranges)>0 and ranges[0]!='0':
901 if len(ranges)>0 and ranges[0]!='0':
857 dum = self.mask_ranges(tx.pulses_as_points(), ranges)
902 dum = self.mask_ranges(tx.pulses_as_points(), ranges)
858 else:
903 else:
859 dum = tx.pulses_as_points()
904 dum = tx.pulses_as_points()
860
905
861 for i, tup in enumerate(dum):
906 for i, tup in enumerate(dum):
862 if tup==(0,0): continue
907 if tup==(0,0): continue
863 code = codes[i%n]
908 code = codes[i%n]
864 y.extend([(c[0]+tup[0], c[1]+tup[0]) for c in code])
909 y.extend([(c[0]+tup[0], c[1]+tup[0]) for c in code])
865
910
866 elif self.line_type.name=='sync':
911 elif self.line_type.name=='sync':
867 params = json.loads(self.params)
912 params = json.loads(self.params)
868 n = ipp_u*ntx
913 n = ipp_u*ntx
869 if params['invert'] in ('1', 1):
914 if params['invert'] in ('1', 1):
870 y = [(n-1, n)]
915 y = [(n-1, n)]
871 else:
916 else:
872 y = [(0, 1)]
917 y = [(0, 1)]
873
918
874 elif self.line_type.name=='prog_pulses':
919 elif self.line_type.name=='prog_pulses':
875 params = json.loads(self.params)
920 params = json.loads(self.params)
876 if int(params['periodic'])==0:
921 if int(params['periodic'])==0:
877 nntx = 1
922 nntx = 1
878 nipp = ipp_u*ntx
923 nipp = ipp_u*ntx
879 else:
924 else:
880 nntx = ntx
925 nntx = ntx
881 nipp = ipp_u
926 nipp = ipp_u
882
927
883 if 'params' in params and len(params['params'])>0:
928 if 'params' in params and len(params['params'])>0:
884 for p in params['params']:
929 for p in params['params']:
885 y_pp = self.points(nntx, nipp,
930 y_pp = self.points(nntx, nipp,
886 p['end']-p['begin'],
931 p['end']-p['begin'],
887 before=p['begin'])
932 before=p['begin'])
888
933
889 y.extend(y_pp)
934 y.extend(y_pp)
890
935
891 elif self.line_type.name=='windows':
936 elif self.line_type.name=='windows':
892 params = json.loads(self.params)
937 params = json.loads(self.params)
893 if 'params' in params and len(params['params'])>0:
938 if 'params' in params and len(params['params'])>0:
894 tx = RCLine.objects.get(pk=params['TX_ref'])
939 tx = RCLine.objects.get(pk=params['TX_ref'])
895 tx_params = json.loads(tx.params)
940 tx_params = json.loads(tx.params)
896 ranges = tx_params['range'].split(',')
941 ranges = tx_params['range'].split(',')
897 for p in params['params']:
942 for p in params['params']:
898 y_win = self.points(ntx, ipp_u,
943 y_win = self.points(ntx, ipp_u,
899 p['resolution']*p['number_of_samples']*km2unit,
944 p['resolution']*p['number_of_samples']*km2unit,
900 before=int(self.rc_configuration.time_before*us2unit)+p['first_height']*km2unit,
945 before=int(self.rc_configuration.time_before*us2unit)+p['first_height']*km2unit,
901 sync=self.rc_configuration.sync+self.get_win_ref(p, params['TX_ref'], km2unit))
946 sync=self.rc_configuration.sync+self.get_win_ref(p, params['TX_ref'], km2unit))
902
947
903
948
904 if len(ranges)>0 and ranges[0]!='0':
949 if len(ranges)>0 and ranges[0]!='0':
905 y_win = self.mask_ranges(y_win, ranges)
950 y_win = self.mask_ranges(y_win, ranges)
906
951
907 y.extend(y_win)
952 y.extend(y_win)
908
953
909 elif self.line_type.name=='mix':
954 elif self.line_type.name=='mix':
910 values = self.rc_configuration.parameters.split('-')
955 values = self.rc_configuration.parameters.split('-')
911 confs = [RCConfiguration.objects.get(pk=value.split('|')[0]) for value in values]
956 confs = [RCConfiguration.objects.get(pk=value.split('|')[0]) for value in values]
912 modes = [value.split('|')[1] for value in values]
957 modes = [value.split('|')[1] for value in values]
913 ops = [value.split('|')[2] for value in values]
958 ops = [value.split('|')[2] for value in values]
914 delays = [value.split('|')[3] for value in values]
959 delays = [value.split('|')[3] for value in values]
915 masks = [value.split('|')[4] for value in values]
960 masks = [value.split('|')[4] for value in values]
961 print("masks")
962 print(masks)
963 print('{:8b}'.format(int(masks[0])))
916 mask = list('{:8b}'.format(int(masks[0])))
964 mask = list('{:8b}'.format(int(masks[0])))
965 print("mask")
966 print(mask)
917 mask.reverse()
967 mask.reverse()
968 print("mask reverse")
969 print(mask)
918 if mask[self.channel] in ('0', '', ' '):
970 if mask[self.channel] in ('0', '', ' '):
919 y = np.zeros(confs[0].total_units, dtype=np.int8)
971 y = np.zeros(confs[0].total_units, dtype=np.int8)
920 else:
972 else:
921 y = confs[0].get_lines(channel=self.channel)[0].pulses_as_array()
973 y = confs[0].get_lines(channel=self.channel)[0].pulses_as_array()
922
974
923 for i in range(1, len(values)):
975 for i in range(1, len(values)):
924 mask = list('{:8b}'.format(int(masks[i])))
976 mask = list('{:8b}'.format(int(masks[i])))
925 mask.reverse()
977 mask.reverse()
926
978
927 if mask[self.channel] in ('0', '', ' '):
979 if mask[self.channel] in ('0', '', ' '):
928 continue
980 continue
929 Y = confs[i].get_lines(channel=self.channel)[0].pulses_as_array()
981 Y = confs[i].get_lines(channel=self.channel)[0].pulses_as_array()
930 delay = float(delays[i])*km2unit
982 delay = float(delays[i])*km2unit
931
983
932 if modes[i]=='P':
984 if modes[i]=='P':
933 if delay>0:
985 if delay>0:
934 if delay<self.rc_configuration.ipp*km2unit and len(Y)==len(y):
986 if delay<self.rc_configuration.ipp*km2unit and len(Y)==len(y):
935 y_temp = np.empty_like(Y)
987 y_temp = np.empty_like(Y)
936 y_temp[:delay] = 0
988 y_temp[:delay] = 0
937 y_temp[delay:] = Y[:-delay]
989 y_temp[delay:] = Y[:-delay]
938 elif delay+len(Y)>len(y):
990 elif delay+len(Y)>len(y):
939 y_new = np.zeros(delay+len(Y), dtype=np.int8)
991 y_new = np.zeros(delay+len(Y), dtype=np.int8)
940 y_new[:len(y)] = y
992 y_new[:len(y)] = y
941 y = y_new
993 y = y_new
942 y_temp = np.zeros(delay+len(Y), dtype=np.int8)
994 y_temp = np.zeros(delay+len(Y), dtype=np.int8)
943 y_temp[-len(Y):] = Y
995 y_temp[-len(Y):] = Y
944 elif delay+len(Y)==len(y):
996 elif delay+len(Y)==len(y):
945 y_temp = np.zeros(delay+len(Y))
997 y_temp = np.zeros(delay+len(Y))
946 y_temp[-len(Y):] = Y
998 y_temp[-len(Y):] = Y
947 elif delay+len(Y)<len(y):
999 elif delay+len(Y)<len(y):
948 y_temp = np.zeros(len(y), dtype=np.int8)
1000 y_temp = np.zeros(len(y), dtype=np.int8)
949 y_temp[delay:delay+len(Y)] = Y
1001 y_temp[delay:delay+len(Y)] = Y
950 else:
1002 else:
951 y_temp = Y.copy()
1003 y_temp = Y.copy()
952
1004
953 if ops[i]=='OR':
1005 if ops[i]=='OR':
954 y = y | y_temp
1006 y = y | y_temp
955 elif ops[i]=='XOR':
1007 elif ops[i]=='XOR':
956 y = y ^ y_temp
1008 y = y ^ y_temp
957 elif ops[i]=='AND':
1009 elif ops[i]=='AND':
958 y = y & y_temp
1010 y = y & y_temp
959 elif ops[i]=='NAND':
1011 elif ops[i]=='NAND':
960 y = y & ~y_temp
1012 y = y & ~y_temp
961 else:
1013 else:
962 y = np.concatenate([y, Y])
1014 y = np.concatenate([y, Y])
963
1015
964 total = len(y)
1016 total = len(y)
965 y = self.array_to_points(y)
1017 y = self.array_to_points(y)
966
1018
967 else:
1019 else:
968 y = []
1020 y = []
969
1021
970 if self.rc_configuration.total_units != total:
1022 if self.rc_configuration.total_units != total:
971 self.rc_configuration.total_units = total
1023 self.rc_configuration.total_units = total
972 self.rc_configuration.save()
1024 self.rc_configuration.save()
973
1025
974 self.pulses = str(y)
1026 self.pulses = str(y)
975 self.save()
1027 self.save()
976
1028
977 @staticmethod
1029 @staticmethod
978 def array_to_points(X):
1030 def array_to_points(X):
979
1031
980 if X.size==0:
1032 if X.size==0:
981 return []
1033 return []
982
1034
983 d = X[1:]-X[:-1]
1035 d = X[1:]-X[:-1]
984
1036
985 up = np.where(d==1)[0]
1037 up = np.where(d==1)[0]
986 if X[0]==1:
1038 if X[0]==1:
987 up = np.concatenate((np.array([-1]), up))
1039 up = np.concatenate((np.array([-1]), up))
988 up += 1
1040 up += 1
989
1041
990 dw = np.where(d==-1)[0]
1042 dw = np.where(d==-1)[0]
991 if X[-1]==1:
1043 if X[-1]==1:
992 dw = np.concatenate((dw, np.array([len(X)-1])))
1044 dw = np.concatenate((dw, np.array([len(X)-1])))
993 dw += 1
1045 dw += 1
994
1046
995 return [(tup[0], tup[1]) for tup in zip(up, dw)]
1047 return [(tup[0], tup[1]) for tup in zip(up, dw)]
996
1048
997 @staticmethod
1049 @staticmethod
998 def mask_ranges(Y, ranges):
1050 def mask_ranges(Y, ranges):
999
1051
1000 y = [(0, 0) for __ in Y]
1052 y = [(0, 0) for __ in Y]
1001
1053
1002 for index in ranges:
1054 for index in ranges:
1003 if '-' in index:
1055 if '-' in index:
1004 args = [int(a) for a in index.split('-')]
1056 args = [int(a) for a in index.split('-')]
1005 y[args[0]-1:args[1]] = Y[args[0]-1:args[1]]
1057 y[args[0]-1:args[1]] = Y[args[0]-1:args[1]]
1006 else:
1058 else:
1007 y[int(index)-1] = Y[int(index)-1]
1059 y[int(index)-1] = Y[int(index)-1]
1008
1060
1009 return y
1061 return y
1010
1062
1011 @staticmethod
1063 @staticmethod
1012 def points(ntx, ipp, width, delay=[0], before=0, after=0, sync=0):
1064 def points(ntx, ipp, width, delay=[0], before=0, after=0, sync=0):
1013
1065
1014 delays = len(delay)
1066 delays = len(delay)
1015
1067
1016 Y = [(int(ipp*x+before+delay[x%delays]+sync), int(ipp*x+width+before+delay[x%delays]+after+sync)) for x in range(ntx)]
1068 Y = [(int(ipp*x+before+delay[x%delays]+sync), int(ipp*x+width+before+delay[x%delays]+after+sync)) for x in range(ntx)]
1017
1069
1018 return Y
1070 return Y
1019
1071
1020 class RCClock(models.Model):
1072 class RCClock(models.Model):
1021
1073
1022 rc_configuration = models.ForeignKey(RCConfiguration, on_delete=models.CASCADE)
1074 rc_configuration = models.ForeignKey('RCConfiguration', on_delete=models.CASCADE)
1023 mode = models.BooleanField(default=True, choices=((True, 'Auto'), (False, 'Manual')))
1075 mode = models.BooleanField(default=True, choices=((True, 'Auto'), (False, 'Manual')))
1024 multiplier = models.PositiveIntegerField(default=60)
1076 multiplier = models.PositiveIntegerField(default=60)
1025 divisor = models.PositiveIntegerField(default=10)
1077 divisor = models.PositiveIntegerField(default=10)
1026 reference = models.PositiveSmallIntegerField(default=1, choices=((0, 'Internal (25MHz)'), (1, 'External (10MHz)')))
1078 reference = models.PositiveSmallIntegerField(default=1, choices=((0, 'Internal (25MHz)'), (1, 'External (10MHz)')))
1027 frequency = models.FloatField(default=60.0) No newline at end of file
1079 frequency = models.FloatField(default=60.0)
General Comments 0
You need to be logged in to leave comments. Login now