##// END OF EJS Templates
ver_3Julio :: new changes
jespinoza -
r400:fea82e8575d1
parent child
Show More
@@ -1,1007 +1,1007
1 1 from django.db import models
2 2 from apps.main.models import Configuration , User
3 3 from django.urls import reverse
4 4 from celery.execute import send_task
5 5 from datetime import datetime
6 6 import ast
7 7 import socket
8 8 import json
9 9 import requests
10 10 import struct
11 11 import os, sys, time
12 12
13 13 antenna_default = json.dumps({
14 14 "antenna_up": [[0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
15 15 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
16 16 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
17 17 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
18 18 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0],
19 19 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0],
20 20 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0],
21 21 [0.5,0.5,0.5,0.5,1.0,1.0,1.0,1.0]
22 22 ]
23 23 ,
24 24 "antenna_down": [[0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
25 25 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
26 26 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
27 27 [0.0,0.0,0.0,0.0,0.5,0.5,0.5,0.5],
28 28 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0],
29 29 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0],
30 30 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0],
31 31 [0.5,0.5,0.5,0.5,3.0,3.0,3.0,3.0]],
32 32 })
33 33
34 34
35 35 tx_default = json.dumps({
36 36 "up": [[1,1,1,1,0,0,0,0],
37 37 [1,1,1,1,0,0,0,0],
38 38 [1,1,1,1,0,0,0,0],
39 39 [1,1,1,1,0,0,0,0],
40 40 [0,0,0,0,1,1,1,1],
41 41 [0,0,0,0,1,1,1,1],
42 42 [0,0,0,0,1,1,1,1],
43 43 [0,0,0,0,1,1,1,1]],
44 44
45 45 "down": [[1,1,1,1,0,0,0,0],
46 46 [1,1,1,1,0,0,0,0],
47 47 [1,1,1,1,0,0,0,0],
48 48 [1,1,1,1,0,0,0,0],
49 49 [0,0,0,0,1,1,1,1],
50 50 [0,0,0,0,1,1,1,1],
51 51 [0,0,0,0,1,1,1,1],
52 52 [0,0,0,0,1,1,1,1]],
53 53 })
54 54
55 55 rx_default = json.dumps({
56 56 "up": [[1,1,1,1,0,0,0,0],
57 57 [1,1,1,1,0,0,0,0],
58 58 [1,1,1,1,0,0,0,0],
59 59 [1,1,1,1,0,0,0,0],
60 60 [0,0,0,0,1,1,1,1],
61 61 [0,0,0,0,1,1,1,1],
62 62 [0,0,0,0,1,1,1,1],
63 63 [0,0,0,0,1,1,1,1]],
64 64
65 65 "down": [[1,1,1,1,0,0,0,0],
66 66 [1,1,1,1,0,0,0,0],
67 67 [1,1,1,1,0,0,0,0],
68 68 [1,1,1,1,0,0,0,0],
69 69 [0,0,0,0,1,1,1,1],
70 70 [0,0,0,0,1,1,1,1],
71 71 [0,0,0,0,1,1,1,1],
72 72 [0,0,0,0,1,1,1,1]],
73 73 })
74 74
75 75 status_default = '0000000000000000000000000000000000000000000000000000000000000000'
76 76 default_messages = {}
77 77
78 78 for i in range(1,65):
79 79 default_messages[str(i)] = "Module "+str(i)
80 80
81 81
82 82 ues_default = json.dumps({
83 83 "up": [0.533333,0.00000,1.06667,0.00000],
84 84 "down": [0.533333,0.00000,1.06667,0.00000]
85 85 })
86 86
87 87 onlyrx_default = json.dumps({
88 88 "up": False,
89 89 "down": False
90 90 })
91 91
92 92 def up_convertion(cadena):
93 93 valores = []
94 94 for c in cadena:
95 95 if c == 1.0: valores=valores+['000']
96 96 if c == 2.0: valores=valores+['001']
97 97 if c == 3.0: valores=valores+['010']
98 98 if c == 0.0: valores=valores+['011']
99 99 if c == 0.5: valores=valores+['100']
100 100 if c == 1.5: valores=valores+['101']
101 101 if c == 2.5: valores=valores+['110']
102 102 if c == 3.5: valores=valores+['111']
103 103
104 104 return valores
105 105
106 106 def up_conv_bits(value):
107 107
108 108 if value == 1.0: bits="000"
109 109 if value == 2.0: bits="001"
110 110 if value == 3.0: bits="010"
111 111 if value == 0.0: bits="011"
112 112 if value == 0.5: bits="100"
113 113 if value == 1.5: bits="101"
114 114 if value == 2.5: bits="110"
115 115 if value == 3.5: bits="111"
116 116
117 117 return bits
118 118
119 119 def down_convertion(cadena):
120 120 valores = []
121 121 for c in cadena:
122 122 if c == 1.0: valores=valores+['000']
123 123 if c == 2.0: valores=valores+['001']
124 124 if c == 3.0: valores=valores+['010']
125 125 if c == 0.0: valores=valores+['011']
126 126 if c == 0.5: valores=valores+['100']
127 127 if c == 1.5: valores=valores+['101']
128 128 if c == 2.5: valores=valores+['110']
129 129 if c == 3.5: valores=valores+['111']
130 130
131 131 return valores
132 132
133 133 def down_conv_bits(value):
134 134
135 135 if value == 1.0: bits="000"
136 136 if value == 2.0: bits="001"
137 137 if value == 3.0: bits="010"
138 138 if value == 0.0: bits="011"
139 139 if value == 0.5: bits="100"
140 140 if value == 1.5: bits="101"
141 141 if value == 2.5: bits="110"
142 142 if value == 3.5: bits="111"
143 143
144 144 return bits
145 145
146 146 def up_conv_value(bits):
147 147
148 148 if bits == "000": value=1.0
149 149 if bits == "001": value=2.0
150 150 if bits == "010": value=3.0
151 151 if bits == "011": value=0.0
152 152 if bits == "100": value=0.5
153 153 if bits == "101": value=1.5
154 154 if bits == "110": value=2.5
155 155 if bits == "111": value=3.5
156 156
157 157 return value
158 158
159 159 def down_conv_value(bits):
160 160
161 161 if bits == "000": value=1.0
162 162 if bits == "001": value=2.0
163 163 if bits == "010": value=3.0
164 164 if bits == "011": value=0.0
165 165 if bits == "100": value=0.5
166 166 if bits == "101": value=1.5
167 167 if bits == "110": value=2.5
168 168 if bits == "111": value=3.5
169 169
170 170 return value
171 171
172 172 def ip2position(module_number):
173 173 j=0
174 174 i=0
175 175 for x in range(0,module_number-1):
176 176 j=j+1
177 177 if j==8:
178 178 i=i+1
179 179 j=0
180 180
181 181 pos = [i,j]
182 182 return pos
183 183
184 184
185 185 def fromBinary2Char(binary_string):
186 186 number = int(binary_string, 2)
187 187 #Plus 33 to avoid more than 1 characters values such as: '\x01'-'\x1f'
188 188 number = number + 33
189 189 char = chr(number)
190 190 return char
191 191
192 192 def fromChar2Binary(char):
193 193 number = ord(char) - 33
194 194 #Minus 33 to get the real value
195 195 bits = bin(number)[2:]
196 196 #To ensure we have a string with 6bits
197 197 if len(bits) < 6:
198 198 bits = bits.zfill(6)
199 199 return bits
200 200
201 201 OPERATION_MODES = (
202 202 (0, 'Manual'),
203 203 (1, 'Automatic'),
204 204 )
205 205
206 206 class ABSConfiguration(Configuration):
207 207 active_beam = models.PositiveSmallIntegerField(verbose_name='Active Beam', default=0)
208 208 module_status = models.CharField(verbose_name='Module Status', max_length=10000, default=status_default)
209 209 operation_mode = models.PositiveSmallIntegerField(verbose_name='Operation Mode', choices=OPERATION_MODES, default = 0)
210 210 operation_value = models.FloatField(verbose_name='Periodic (seconds)', default="10", null=True, blank=True)
211 211 module_messages = models.CharField(verbose_name='Modules Messages', max_length=10000, default=json.dumps(default_messages))
212 212
213 213 class Meta:
214 214 db_table = 'abs_configurations'
215 215
216 216 def get_absolute_url_plot(self):
217 217 return reverse('url_plot_abs_patterns', args=[str(self.id)])
218 218
219 219
220 220 def parms_to_dict(self):
221 221
222 222 parameters = {}
223 223
224 224 parameters['device_id'] = self.device.id
225 225 parameters['label'] = self.label
226 226 parameters['device_type'] = self.device.device_type.name
227 227 parameters['beams'] = {}
228 228
229 229 beams = ABSBeam.objects.filter(abs_conf=self)
230 230 b=1
231 231 for beam in beams:
232 232 #absbeam = ABSBeam.objects.get(pk=beams[beam])
233 233 parameters['beams']['beam'+str(b)] = beam.parms_to_dict()#absbeam.parms_to_dict()
234 234 b+=1
235 235
236 236 return parameters
237 237
238 238
239 239 def dict_to_parms(self, parameters):
240 240
241 241 self.label = parameters['label']
242 242
243 243 absbeams = ABSBeam.objects.filter(abs_conf=self)
244 244 beams = parameters['beams']
245 245
246 246 if absbeams:
247 247 beams_number = len(beams)
248 248 absbeams_number = len(absbeams)
249 249 if beams_number==absbeams_number:
250 250 i = 1
251 251 for absbeam in absbeams:
252 252 absbeam.dict_to_parms(beams['beam'+str(i)])
253 253 i = i+1
254 254 elif beams_number > absbeams_number:
255 255 i = 1
256 256 for absbeam in absbeams:
257 257 absbeam.dict_to_parms(beams['beam'+str(i)])
258 258 i=i+1
259 259 for x in range(i,beams_number+1):
260 260 new_beam = ABSBeam(
261 261 name =beams['beam'+str(i)]['name'],
262 262 antenna =json.dumps(beams['beam'+str(i)]['antenna']),
263 263 abs_conf = self,
264 264 tx =json.dumps(beams['beam'+str(i)]['tx']),
265 265 rx =json.dumps(beams['beam'+str(i)]['rx']),
266 266 ues =json.dumps(beams['beam'+str(i)]['ues']),
267 267 only_rx =json.dumps(beams['beam'+str(i)]['only_rx'])
268 268 )
269 269 new_beam.save()
270 270 i=i+1
271 271 else: #beams_number < absbeams_number:
272 272 i = 1
273 273 for absbeam in absbeams:
274 274 if i <= beams_number:
275 275 absbeam.dict_to_parms(beams['beam'+str(i)])
276 276 i=i+1
277 277 else:
278 278 absbeam.delete()
279 279 else:
280 280 for beam in beams:
281 281 new_beam = ABSBeam(
282 282 name =beams[beam]['name'],
283 283 antenna =json.dumps(beams[beam]['antenna']),
284 284 abs_conf = self,
285 285 tx =json.dumps(beams[beam]['tx']),
286 286 rx =json.dumps(beams[beam]['rx']),
287 287 ues =json.dumps(beams[beam]['ues']),
288 288 only_rx =json.dumps(beams[beam]['only_rx'])
289 289 )
290 290 new_beam.save()
291 291
292 292
293 293
294 294 def update_from_file(self, parameters):
295 295
296 296 self.dict_to_parms(parameters)
297 297 self.save()
298 298
299 299
300 300 def get_beams(self, **kwargs):
301 301 '''
302 302 This function returns ABS Configuration beams
303 303 '''
304 304 return ABSBeam.objects.filter(abs_conf=self.pk, **kwargs)
305 305
306 306 def clone(self, **kwargs):
307 307
308 308 beams = self.get_beams()
309 309 self.pk = None
310 310 self.id = None
311 311 for attr, value in kwargs.items():
312 312 setattr(self, attr, value)
313 313 self.save()
314 314
315 315 for beam in beams:
316 316 beam.clone(abs_conf=self)
317 317
318 318 #-----For Active Beam-----
319 319 new_beams = ABSBeam.objects.filter(abs_conf=self)
320 320 self.active_beam = new_beams[0].id
321 321 self.save()
322 322 #-----For Active Beam-----
323 323 #-----For Device Status---
324 324 self.device.status = 3
325 325 self.device.save()
326 326 #-----For Device Status---
327 327
328 328 return self
329 329
330 330
331 331 def start_device(self):
332 332
333 333 if self.device.status == 3:
334 334
335 335 try:
336 336 #self.write_device()
337 337 send_task('task_change_beam', [self.id],)
338 338 self.message = 'ABS running'
339 339
340 340 except Exception as e:
341 341 self.message = str(e)
342 342 return False
343 343
344 344 return True
345 345
346 346 else:
347 347 self.message = 'Please, select Write ABS Device first.'
348 348 return False
349 349
350 350
351 351 def stop_device(self):
352 352
353 353 self.device.status = 2
354 354 self.device.save()
355 355 self.message = 'ABS has been stopped.'
356 356 self.save()
357 357
358 358 return True
359 359
360 360
361 361 def write_device(self):
362 362
363 363 """
364 364 This function sends the beams list to every abs module.
365 365 It needs 'module_conf' function
366 366 """
367 367 print("Write")
368 368 beams = ABSBeam.objects.filter(abs_conf=self)
369 369 nbeams = len(beams)
370 370
371 371 # Se manda a cero RC para poder realizar cambio de beam
372 372 if self.experiment is None:
373 373 confs = []
374 374 else:
375 375 confs = Configuration.objects.filter(experiment = self.experiment).filter(type=0)
376 376 confdds = ''
377 377 confjars = ''
378 378 confrc = ''
379 379 #TO STOP DEVICES: DDS-JARS-RC
380 380 for i in range(0,len(confs)):
381 381 if i==0:
382 382 for conf in confs:
383 383 if conf.device.device_type.name == 'dds':
384 384 confdds = conf
385 385 confdds.stop_device()
386 386 break
387 387 if i==1:
388 388 for conf in confs:
389 389 if conf.device.device_type.name == 'jars':
390 390 confjars = conf
391 391 confjars.stop_device()
392 392 break
393 393 if i==2:
394 394 for conf in confs:
395 395 if conf.device.device_type.name == 'rc':
396 396 confrc = conf
397 397 confrc.stop_device()
398 398 break
399 399
400 400 '''
401 401 if self.connected_modules() == 0 :
402 402 print("No encuentra modulos")
403 403 self.message = "No ABS Module detected."
404 404 return False
405 405 '''
406 406 #-------------Write each abs module-----------
407 407
408 408 if beams:
409 409 block_id = 0
410 410 message = 'SNDF{:03d}{:02d}{:02d}'.format(nbeams, nbeams, block_id)
411 411 for i, status in enumerate(self.module_status):
412 412 message += ''.join([fromBinary2Char(beam.module_6bits(i)) for beam in beams])
413 413 status = ['0'] * 64
414 414 n = 0
415 415 print("Llega una antes entrar a multicast")
416 416 sock = self.send_multicast(message)
417 417
418 418 while True:
419 419 #for i in range(32):
420 420 try:
421 421 data, address = sock.recvfrom(1024)
422 422 print (address, data)
423 423 data = data.decode("utf-8")
424 424 if data == '1':
425 425 status[int(address[0][10:])-1] = '3'
426 426 #print (int(address[0][10:])-1)
427 427 elif data == '0':
428 428 status[int(address[0][10:])-1] = '1'
429 429 except socket.timeout:
430 430 print('Timeout')
431 431 break
432 432 except Exception as e:
433 433 print ('Error {}'.format(e))
434 434 n += 1
435 435 sock.close()
436 436 else:
437 437 self.message = "ABS Configuration does not have beams"
438 438 print('No beams')
439 439 #Start DDS-RC-JARS
440 440 if confdds:
441 441 confdds.start_device()
442 442 if confrc:
443 443 #print confrc
444 444 confrc.start_device()
445 445 if confjars:
446 446 confjars.start_device()
447 447 return False
448 448
449 449 if n == 64:
450 450 self.message = "Could not write ABS Modules"
451 451 self.device.status = 0
452 452 self.module_status = ''.join(status)
453 453 self.save()
454 454 print('Could not write ABS')
455 455 #Start DDS-RC-JARS
456 456 if confdds:
457 457 confdds.start_device()
458 458 if confrc:
459 459 #print confrc
460 460 confrc.start_device()
461 461 if confjars:
462 462 confjars.start_device()
463 463 return False
464 464 else:
465 465 self.message = "ABS Beams List have been sent to ABS Modules"
466 466 print('ABS beams list sent')
467 467 self.active_beam = beams[0].pk
468 468
469 469 #Start DDS-RC-JARS
470 470 if confdds:
471 471 confdds.start_device()
472 472 if confrc:
473 473 #print confrc
474 474 confrc.start_device()
475 475 if confjars:
476 476 confjars.start_device()
477 477
478 478 print('Inicia intento de salvar device.status')
479 479 self.device.status = 3
480 480 self.module_status = ''.join(status)
481 481 #print(status)
482 482 self.save()
483 483 print('Estatus salvado')
484 484 conf_active, __ = ABSActive.objects.get_or_create(pk=1)
485 485 conf_active.conf = self
486 486 conf_active.save()
487 487 return True
488 488
489 489
490 490 def read_module(self, module):
491 491
492 492 """
493 493 Read out-bits (up-down) of 1 abs module NOT for Configuration
494 494 """
495 495
496 496 ip_address = self.device.ip_address
497 497 ip_address = ip_address.split('.')
498 498 module_seq = (ip_address[0],ip_address[1],ip_address[2])
499 499 dot = '.'
500 500 module_ip = dot.join(module_seq)+'.'+str(module)
501 501 module_port = self.device.port_address
502 502 read_route = 'http://'+module_ip+':'+str(module_port)+'/read'
503 503
504 504 module_status = json.loads(self.module_status)
505 505 print(read_route)
506 506
507 507 module_bits = ''
508 508
509 509 try:
510 510 r_read = requests.get(read_route, timeout=0.5)
511 511 answer = r_read.json()
512 512 module_bits = answer['allbits']
513 513 except:
514 514 return {}
515 515
516 516 return module_bits
517 517
518 518 def read_device(self):
519 519
520 520 parms = {}
521 521 # Reads active modules.
522 522 module_status = json.loads(self.module_status)
523 523 total = 0
524 524 for status in module_status:
525 525 if module_status[status] != 0:
526 526 module_bits = self.read_module(int(status))
527 527 bits={}
528 528 if module_bits:
529 529 bits = (str(module_bits['um2']) + str(module_bits['um1']) + str(module_bits['um0']) +
530 530 str(module_bits['dm2']) + str(module_bits['dm1']) + str(module_bits['dm0']) )
531 531 parms[str(status)] = bits
532 532
533 533 total +=1
534 534
535 535 if total==0:
536 536 self.message = "No ABS Module detected. Please select 'Status'."
537 537 return False
538 538
539 539
540 540
541 541 self.message = "ABS Modules have been read"
542 542 #monitoreo_tx = JROABSClnt_01CeCnMod000000MNTR10
543 543 return parms
544 544
545 545
546 546 def connected_modules(self):
547 547 """
548 548 This function returns the number of connected abs-modules without updating.
549 549 """
550 550 num = 0
551 551 print(self.module_status)
552 552 for i, status in enumerate(self.module_status):
553 553 if status != '0':
554 554 num += 1
555 555 #print('status {}:{}'.format(i+1, status))
556 556 return num
557 557
558 558 def send_multicast(self, message):
559 559 #print("Send multicast")
560 560 multicast_group = ('224.3.29.71', 10000)
561 561 # Create the datagram socket
562 562 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
563 563 sock.settimeout(1)
564 local_ip = os.environ.get('LOCAL_IP', '192.168.2.128')
564 local_ip = os.environ.get('LOCAL_IP', '192.168.1.128')
565 565 sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, socket.inet_aton(local_ip))
566 566 sock.sendto(message.encode(), multicast_group)
567 567 print('Sending ' + message)
568 568 return sock
569 569
570 570 def status_device(self):
571 571 """
572 572 This function returns the status of all abs-modules as one.
573 573 If at least one module is connected, its answer is "1"
574 574 """
575 575 print ('Status device')
576 576 print (self.active_beam)
577 577 beams = ABSBeam.objects.filter(abs_conf=self)
578 578 #print beams[self.active_beam-1].module_6bits(0)
579 579 active = ABSActive.objects.get(pk=1)
580 580 if active.conf != self:
581 581 self.message = 'La configuracion actual es la del siguiente enlace %s.' % active.conf.get_absolute_url()
582 582 self.message += "\n"
583 583 self.message += 'Se debe realizar un write en esta configuracion para luego obtener un status valido.'
584 584
585 585 return False
586 586
587 587 sock = self.send_multicast('MNTR')
588 588
589 589 n = 0
590 590 status = ['0'] * 64
591 591
592 592 while True:
593 593 #for i in range(32):
594 594 #if True:
595 595 try:
596 596 print("Recibiendo")
597 597 address = None
598 598 data, address = sock.recvfrom(2)
599 599 print (address, data)
600 600 print("!!!!")
601 601 data = data.decode()
602 602 aux_mon = "1"
603 603 aux_expected = aux_mon
604 604 if(len(data)==2):
605 605 print ("data[1]: ")
606 606 print (data[1])
607 607 aux_mon = fromChar2Binary(data[1])
608 608 print (aux_mon)
609 609 aux_i = (str(address[0]).split('.'))[3]
610 610 print (aux_i)
611 611 print ('Active beam')
612 612 beam_active = ABSBeam.objects.get(pk=self.active_beam)
613 613 print (beam_active)
614 614 aux_expected = beam_active.module_6bits(int(aux_i)-1)
615 615 print (aux_expected)
616 616
617 617 print ("data[0]: ")
618 618 print (data[0])
619 619
620 620 if data[0] == '1':
621 621 status[int(address[0][10:])-1] = '3'
622 622 if aux_mon == aux_expected:
623 623 print ('Es igual')
624 624 else:
625 625 print ('Es diferente')
626 626 status[int(address[0][10:])-1] = '2'
627 627
628 628 elif data[0] == '0':
629 629 status[int(address[0][10:])-1] = '1'
630 630 n += 1
631 631 print('Module: {} connected'.format(address))
632 632 except socket.timeout:
633 633 print('Timeout')
634 634 break
635 635 except:
636 636 print('Module: {} error'.format(address))
637 637 pass
638 638
639 639 sock.close()
640 640
641 641 if n > 0:
642 642 self.message = 'ABS modules Status have been updated.'
643 643 self.device.status = 1
644 644 else:
645 645 self.device.status = 0
646 646 self.message = 'No ABS module is connected.'
647 647 self.module_status = ''.join(status)
648 648 self.save()
649 649
650 650 return self.device.status
651 651
652 652
653 653 def send_beam(self, beam_pos):
654 654 """
655 655 This function connects to a multicast group and sends the beam number
656 656 to all abs modules.
657 657 """
658 658 print ('Send beam')
659 659 print (self.active_beam)
660 660 beams = ABSBeam.objects.filter(abs_conf=self)
661 661 #print beams[self.active_beam-1].module_6bits(0)
662 662 active = ABSActive.objects.get(pk=1)
663 663 if active.conf != self:
664 664 self.message = 'La configuracion actual es la del siguiente enlace %s.' % active.conf.get_absolute_url()
665 665 self.message += "\n"
666 666 self.message += 'Se debe realizar un write en esta configuracion para luego obtener un status valido.'
667 667
668 668 return False
669 669
670 670 # Se manda a cero RC para poder realizar cambio de beam
671 671 if self.experiment is None:
672 672 confs = []
673 673 else:
674 674 confs = Configuration.objects.filter(experiment = self.experiment).filter(type=0)
675 675 confdds = ''
676 676 confjars = ''
677 677 confrc = ''
678 678 #TO STOP DEVICES: DDS-JARS-RC
679 679 for i in range(0,len(confs)):
680 680 if i==0:
681 681 for conf in confs:
682 682 if conf.device.device_type.name == 'dds':
683 683 confdds = conf
684 684 confdds.stop_device()
685 685 break
686 686 if i==1:
687 687 for conf in confs:
688 688 if conf.device.device_type.name == 'jars':
689 689 confjars = conf
690 690 confjars.stop_device()
691 691 break
692 692 if i==2:
693 693 for conf in confs:
694 694 if conf.device.device_type.name == 'rc':
695 695 confrc = conf
696 696 confrc.stop_device()
697 697 break
698 698 if beam_pos > 0:
699 699 beam_pos = beam_pos - 1
700 700 else:
701 701 beam_pos = 0
702 702
703 703 #El indice del apunte debe ser menor que el numero total de apuntes
704 704 #El servidor tcp en el embebido comienza a contar desde 0
705 705 status = ['0'] * 64
706 706 message = 'CHGB{}'.format(beam_pos)
707 707 sock = self.send_multicast(message)
708 708 while True:
709 709 #for i in range(32):
710 710 try:
711 711 data, address = sock.recvfrom(1024)
712 712 print (address, data)
713 713 data = data.decode()
714 714 if data == '1':
715 715 status[int(address[0][10:])-1] = '3'
716 716 elif data == '0':
717 717 status[int(address[0][10:])-1] = '1'
718 718 except socket.timeout:
719 719 print('Timeout')
720 720 break
721 721 except Exception as e:
722 722 print ('Error {}'.format(e))
723 723 pass
724 724
725 725 sock.close()
726 726
727 727 #Start DDS-RC-JARS
728 728 if confdds:
729 729 confdds.start_device()
730 730 if confrc:
731 731 #print confrc
732 732 confrc.start_device()
733 733 if confjars:
734 734 confjars.start_device()
735 735
736 736 self.message = "ABS Beam has been changed"
737 737 self.module_status = ''.join(status)
738 738 self.save()
739 739 return True
740 740
741 741
742 742 def get_absolute_url_import(self):
743 743 return reverse('url_import_abs_conf', args=[str(self.id)])
744 744
745 745 class ABSActive(models.Model):
746 746 conf = models.ForeignKey(ABSConfiguration, null=True, verbose_name='ABS Configuration', on_delete=models.CASCADE)
747 747
748 748 class Meta:
749 749 db_table = 'abs_absactive'
750 750
751 751 class ABSBeam(models.Model):
752 752
753 753 name = models.CharField(max_length=60, default='Beam')
754 754 antenna = models.CharField(verbose_name='Antenna', max_length=1000, default=antenna_default)
755 755 abs_conf = models.ForeignKey('ABSConfiguration', null=True,
756 756 verbose_name='ABS Configuration', on_delete=models.CASCADE)
757 757 tx = models.CharField(verbose_name='Tx', max_length=1000, default=tx_default)
758 758 rx = models.CharField(verbose_name='Rx', max_length=1000, default=rx_default)
759 759 s_time = models.TimeField(verbose_name='Star Time', default='00:00:00')
760 760 e_time = models.TimeField(verbose_name='End Time', default='23:59:59')
761 761 ues = models.CharField(verbose_name='Ues', max_length=100, default=ues_default)
762 762 only_rx = models.CharField(verbose_name='Only RX', max_length=40, default=onlyrx_default)
763 763
764 764 class Meta:
765 765 db_table = 'abs_beams'
766 766
767 767 def __unicode__(self):
768 768 return u'%s' % (self.name)
769 769
770 770 def parms_to_dict(self):
771 771
772 772 parameters = {}
773 773 parameters['name'] = self.name
774 774 parameters['antenna'] = ast.literal_eval(self.antenna)
775 775 parameters['abs_conf'] = self.abs_conf.name
776 776 parameters['tx'] = ast.literal_eval(self.tx)
777 777 parameters['rx'] = ast.literal_eval(self.rx)
778 778 parameters['s_time'] = self.s_time.strftime("%H:%M:%S")
779 779 parameters['e_time'] = self.e_time.strftime("%H:%M:%S")
780 780 parameters['ues'] = ast.literal_eval(self.ues)
781 781 parameters['only_rx'] = json.loads(self.only_rx)
782 782
783 783 return parameters
784 784
785 785 def dict_to_parms(self, parameters):
786 786
787 787 self.name = parameters['name']
788 788 self.antenna = json.dumps(parameters['antenna'])
789 789 #self.abs_conf = parameters['abs_conf']
790 790 self.tx = json.dumps(parameters['tx'])
791 791 self.rx = json.dumps(parameters['rx'])
792 792 #self.s_time = parameters['s_time']
793 793 #self.e_time = parameters['e_time']
794 794 self.ues = json.dumps(parameters['ues'])
795 795 self.only_rx = json.dumps(parameters['only_rx'])
796 796 self.save()
797 797
798 798
799 799 def clone(self, **kwargs):
800 800
801 801 self.pk = None
802 802 self.id = None
803 803 for attr, value in kwargs.items():
804 804 setattr(self, attr, value)
805 805
806 806 self.save()
807 807
808 808 return self
809 809
810 810
811 811 def module_6bits(self, module):
812 812 """
813 813 This function reads antenna pattern and choose 6bits (upbits-downbits) for one abs module
814 814 """
815 815 module += 1
816 816 if module > 64:
817 817 beam_bits = ""
818 818 return beam_bits
819 819
820 820 data = ast.literal_eval(self.antenna)
821 821 up_data = data['antenna_up']
822 822 down_data = data['antenna_down']
823 823
824 824 pos = ip2position(module)
825 825 up_value = up_data[pos[0]][pos[1]]
826 826 down_value = down_data[pos[0]][pos[1]]
827 827
828 828 up_bits = up_conv_bits(up_value)
829 829 down_bits = down_conv_bits(down_value)
830 830 beam_bits = up_bits+down_bits
831 831
832 832 return beam_bits
833 833
834 834
835 835 @property
836 836 def get_upvalues(self):
837 837 """
838 838 This function reads antenna pattern and show the up-value of one abs module
839 839 """
840 840
841 841 data = ast.literal_eval(self.antenna)
842 842 up_data = data['antenna_up']
843 843
844 844 up_values = []
845 845 for data in up_data:
846 846 for i in range(0,8):
847 847 up_values.append(data[i])
848 848
849 849 return up_values
850 850
851 851 @property
852 852 def antenna_upvalues(self):
853 853 """
854 854 This function reads antenna pattern and show the up - values of one abs beam
855 855 in a particular order
856 856 """
857 857 data = ast.literal_eval(self.antenna)
858 858 up_data = data['antenna_up']
859 859
860 860 return up_data
861 861
862 862 @property
863 863 def antenna_downvalues(self):
864 864 """
865 865 This function reads antenna pattern and show the down - values of one abs beam
866 866 in a particular order
867 867 """
868 868 data = ast.literal_eval(self.antenna)
869 869 down_data = data['antenna_down']
870 870
871 871 return down_data
872 872
873 873 @property
874 874 def get_downvalues(self):
875 875 """
876 876 This function reads antenna pattern and show the down-value of one abs module
877 877 """
878 878
879 879 data = ast.literal_eval(self.antenna)
880 880 down_data = data['antenna_down']
881 881
882 882 down_values = []
883 883 for data in down_data:
884 884 for i in range(0,8):
885 885 down_values.append(data[i])
886 886
887 887 return down_values
888 888
889 889 @property
890 890 def get_up_ues(self):
891 891 """
892 892 This function shows the up-ues-value of one beam
893 893 """
894 894 data = ast.literal_eval(self.ues)
895 895 up_ues = data['up']
896 896
897 897 return up_ues
898 898
899 899 @property
900 900 def get_down_ues(self):
901 901 """
902 902 This function shows the down-ues-value of one beam
903 903 """
904 904 data = ast.literal_eval(self.ues)
905 905 down_ues = data['down']
906 906
907 907 return down_ues
908 908
909 909 @property
910 910 def get_up_onlyrx(self):
911 911 """
912 912 This function shows the up-onlyrx-value of one beam
913 913 """
914 914 data = json.loads(self.only_rx)
915 915 up_onlyrx = data['up']
916 916
917 917 return up_onlyrx
918 918
919 919 @property
920 920 def get_down_onlyrx(self):
921 921 """
922 922 This function shows the down-onlyrx-value of one beam
923 923 """
924 924 data = json.loads(self.only_rx)
925 925 down_onlyrx = data['down']
926 926
927 927 return down_onlyrx
928 928
929 929 @property
930 930 def get_tx(self):
931 931 """
932 932 This function shows the tx-values of one beam
933 933 """
934 934 data = json.loads(self.tx)
935 935
936 936 return data
937 937
938 938 @property
939 939 def get_uptx(self):
940 940 """
941 941 This function shows the up-tx-values of one beam
942 942 """
943 943 data = json.loads(self.tx)
944 944 up_data = data['up']
945 945
946 946 up_values = []
947 947 for data in up_data:
948 948 for i in range(0,8):
949 949 up_values.append(data[i])
950 950
951 951 return up_values
952 952
953 953 @property
954 954 def get_downtx(self):
955 955 """
956 956 This function shows the down-tx-values of one beam
957 957 """
958 958 data = json.loads(self.tx)
959 959 down_data = data['down']
960 960
961 961 down_values = []
962 962 for data in down_data:
963 963 for i in range(0,8):
964 964 down_values.append(data[i])
965 965
966 966 return down_values
967 967
968 968
969 969
970 970 @property
971 971 def get_rx(self):
972 972 """
973 973 This function shows the rx-values of one beam
974 974 """
975 975 data = json.loads(self.rx)
976 976
977 977 return data
978 978
979 979 @property
980 980 def get_uprx(self):
981 981 """
982 982 This function shows the up-rx-values of one beam
983 983 """
984 984 data = json.loads(self.rx)
985 985 up_data = data['up']
986 986
987 987 up_values = []
988 988 for data in up_data:
989 989 for i in range(0,8):
990 990 up_values.append(data[i])
991 991
992 992 return up_values
993 993
994 994 @property
995 995 def get_downrx(self):
996 996 """
997 997 This function shows the down-rx-values of one beam
998 998 """
999 999 data = json.loads(self.rx)
1000 1000 down_data = data['down']
1001 1001
1002 1002 down_values = []
1003 1003 for data in down_data:
1004 1004 for i in range(0,8):
1005 1005 down_values.append(data[i])
1006 1006
1007 1007 return down_values
@@ -1,18 +1,18
1 1 from django.urls import path
2 2
3 3 from apps.abs import views
4 4
5 5 urlpatterns = (
6 6 path('<int:id_conf>/', views.abs_conf, name='url_abs_conf'),
7 7 path('<int:id_conf>/edit/', views.abs_conf_edit, name='url_edit_abs_conf'),
8 8 path('alert/', views.abs_conf_alert, name='url_alert_abs_conf'),
9 9 path('<int:id_conf>/import/', views.import_file, name='url_import_abs_conf'),
10 10 #url(r'^(?P<id_conf>-?\d+)/status/', views.abs_conf, {'status_request':True},name='url_status_abs_conf'),
11 11 path('<int:id_conf>/change_beam/<int:id_beam>/', views.send_beam, name='url_send_beam'),
12 12 path('<int:id_conf>/plot/', views.plot_patterns, name='url_plot_abs_patterns'),
13 13 path('<int:id_conf>/plot/<int:id_beam>/', views.plot_patterns, name='url_plot_abs_patterns'),
14 path('<int:id_conf>/plot/<int:id_beam>/<int:antenna>/pattern.png', views.plot_pattern, name='url_plot_beam'),
14 path('<int:id_conf>/plot/<int:id_beam>/<slug:antenna>/pattern.png', views.plot_pattern, name='url_plot_beam'),
15 15 path('<int:id_conf>/add_beam/', views.add_beam, name='url_add_abs_beam'),
16 16 path('<int:id_conf>/beam/<int:id_beam>/delete/', views.remove_beam, name='url_remove_abs_beam'),
17 17 path('<int:id_conf>/beam/<int:id_beam>/edit/', views.edit_beam, name='url_edit_abs_beam'),
18 18 )
@@ -1,1775 +1,1775
1 1 #!/usr/bin/python
2 2 import sys, os, os.path
3 3 import traceback
4 4 import cgi
5 5 from http import cookies
6 6
7 7 import time, datetime
8 8 import types
9 9 import numpy
10 10 import numpy.fft
11 11 import scipy.linalg
12 12 import scipy.special
13 13 from io import StringIO
14 14
15 15
16 16 #import Misc_Routines
17 17 from .Misc_Routines import CoFactors
18 18 #import TimeTools
19 19 from .TimeTools import Time , Julian ,Doy2Date
20 20 #import JroAntSetup
21 21 from .JroAntSetup import ReturnSetup
22 22 #import Graphics_OverJro
23 23 from .Graphics_OverJro import AntPatternPlot ,BFieldPlot,CelestialObjectsPlot,PatternCutPlot,SkyNoisePlot
24 24 #import Astro_Coords
25 25 from .Astro_Coords import Geodetic ,AltAz ,CelestialBodies
26 26
27 27 class JroPattern():
28 28 def __init__(self,pattern=0,path=None,filename=None,nptsx=101,nptsy=101,maxphi=5,fftopt=0, \
29 29 getcut=0,dcosx=None,dcosy=None,eomwl=6,airwl=4, **kwargs):
30 30 """
31 31 JroPattern class creates an object to represent the useful parameters for beam mode-
32 32 lling of the Jicamarca VHF radar.
33 33
34 34 Parameters
35 35 ----------
36 36 pattern = An integer (See JroAntSetup to know the available values) to load a prede-
37 37 fined configuration. The default value is 0. To use a user-defined configuration
38 38 pattern must be None.
39 39 path = A string giving the directory that contains the user-configuration file. PATH
40 40 will work if pattern is None.
41 41 filename = A string giving the name of the user-configuration file. FILENAME will
42 42 work if pattern is None.
43 43 nptsx = A scalar to specify the number of points used to define the angular resolu-
44 44 tion in the "x" axis. The default value is 101.
45 45 nptsy = A scalar to specify the number of points used to define the angular resolu-
46 46 tion in the "x" axis. The default value is 101.
47 47 maxphi = A scalar giving the maximum (absolute) angle (in degree) to model the ante-
48 48 nna pattern. The default value is 5 degrees.
49 49 fftopt = Set this input to 1 to model the beam using FFT. To model using antenna
50 50 theory set to 0 (default value).
51 51 getcut = Set to 1 to show an antenna cut instead of a contour plot of itself (set to
52 52 0). The defautl value is 0.
53 53 dcosx = An array giving the directional cosines for the x-axis. DCOSX will work if
54 54 getcut is actived.
55 55 dcosy = An array giving the directional cosines for the y-axis. DCOSY will work if
56 56 getcut is actived.
57 57 eomwl = A scalar giving the radar wavelength. The default value is 6m (50 MHZ).
58 58 airwl = Set this input to float (or intger) to specify the wavelength (in meters) of
59 59 the transmitted EOM wave in the air. The default value is 4m.
60 60
61 61 Modification History
62 62 --------------------
63 63 Converted to Object-oriented Programming by Freddy Galindo, ROJ, 20 September 2009.
64 64 """
65 65
66 66
67 67
68 68 # Getting antenna configuration.
69 69 if filename:
70 70 setup = ReturnSetup(path=path,filename=filename,pattern=pattern)
71 71
72 72 ues = setup["ues"]
73 73 phase = setup["phase"]
74 74 gaintx = setup["gaintx"]
75 75 gainrx = setup["gainrx"]
76 76 justrx = setup["justrx"]
77 77 self.title = setup["title"]
78 78 else:
79 79 ues = kwargs["ues"]
80 80 phase = kwargs["phases"]
81 81 gaintx = kwargs["gain_tx"]
82 82 gainrx = kwargs["gain_rx"]
83 83 justrx = kwargs["just_rx"]
84 84 self.title = kwargs.get("title", "JRO Pattern")
85 85
86 86 # Defining attributes for JroPattern class.
87 87 # Antenna configuration
88 88
89 89 self.uestx = ues
90 90 self.phasetx = phase
91 91 self.gaintx = gaintx
92 92 self.uesrx = ues
93 93 self.phaserx = phase
94 94 self.gainrx = gainrx
95 95 self.justrx = justrx
96 96
97 97 # Pattern resolution & method to model
98 98 self.maxphi = maxphi
99 99 self.nptsx = nptsx
100 100 self.nptsy = nptsy
101 101 self.fftopt = fftopt
102 102
103 103 # To get a cut of the pattern.
104 104 self.getcut = getcut
105 105
106 106 maxdcos = numpy.sin(maxphi*CoFactors.d2r)
107 107 if dcosx==None:dcosx = ((numpy.arange(nptsx,dtype=float)/(nptsx-1))-0.5)*2*maxdcos
108 108 if dcosy==None:dcosy = ((numpy.arange(nptsy,dtype=float)/(nptsy-1))-0.5)*2*maxdcos
109 109 self.dcosx = dcosx
110 110 self.dcosy = dcosy
111 111 self.nx = dcosx.size
112 112 self.ny = dcosy.size*(getcut==0) + (getcut==1)
113 113
114 114 self.eomwl = eomwl
115 115 self.airwl = airwl
116 116
117 117 self.kk = 2.*numpy.pi/eomwl
118 118
119 119 self.pattern = None
120 120 self.meanpos = None
121 121 self.norpattern = None
122 122 self.maxpattern = None
123 123
124 124
125 125
126 126 self.getPattern()
127 127
128 128 def getPattern(self):
129 129 """
130 130 getpattern method returns the modeled total antenna pattern and its mean position.
131 131
132 132 Return
133 133 ------
134 134 pattern = An array giving the Modelled antenna pattern.
135 135 mean_pos = A 2-elements array giving the mean position of the main beam.
136 136
137 137 Examples
138 138 --------
139 139 >> [pattern, mean_pos] = JroPattern(pattern=2).getPattern()
140 140 >> print meanpos
141 141 [ 8.08728085e-14 -4.78193873e-14]
142 142
143 143 Modification history
144 144 --------------------
145 145 Developed by Jorge L. Chau.
146 146 Converted to Python by Freddy R. Galindo, ROJ, 20 September 2009.
147 147 """
148 148
149 149 if (self.fftopt>0) and (self.getcut>0):
150 150 #print "Conflict bewteen fftopt and getcut"
151 151 #print "To get a cut of the antenna pattern uses ffopt=0"
152 152 return None, None
153 153
154 154 if (self.fftopt==0):
155 155 # Getting antenna pattern using the array method
156 156 self.pattern = self.__usingArray(rx=1)
157 157 if (self.justrx==0):self.pattern = self.pattern*self.__usingArray(rx=0)
158 158
159 159 elif (self.fftopt>0):
160 160 # Getting antenna pattern using FFT method
161 161 self.pattern = self.__usingFFT(rx=1)
162 162 if (self.justrx==0):self.pattern = self.pattern*self.__usingFFT(rx=0)
163 163
164 164 self.maxpattern = numpy.nanmax(self.pattern)
165 165 self.norpattern = self.pattern/self.maxpattern
166 166 if self.getcut==0:self.__getBeamPars()
167 167
168 168 def __usingArray(self,rx):
169 169 """
170 170 __usingArray method returns the Jicamarca antenna pattern computed using array model
171 171
172 172 pattern = dipolepattern x modulepattern
173 173
174 174 Parameters
175 175 ----------
176 176 rx = Set to 1 to use the Rx information. Otherwise set to 0 for Tx.
177 177
178 178 Return
179 179 ------
180 180 pattern = An array giving the modelled antenna pattern using the array model.
181 181
182 182 Modification history
183 183 --------------------
184 184 Developed by Jorge L. Chau.
185 185 Converted to Python by Freddy R. Galindo, ROJ, 20 September 2009.
186 186 """
187 187
188 188 if rx==1:
189 189 ues = self.uesrx
190 190 phase = self.phaserx
191 191 gain = self.gainrx
192 192 elif rx==0:
193 193 ues = self.uestx
194 194 phase = self.phasetx
195 195 gain = self.gaintx
196 196
197 197 ues = ues*360./self.airwl
198 198 phase = phase*360./self.airwl
199 199
200 200 for ii in range(4):
201 201 if ii==0:dim = numpy.array([4,0,8,4]) # WEST
202 202 elif ii==1:dim = numpy.array([0,0,4,4]) # NORTH
203 203 elif ii==2:dim = numpy.array([0,4,4,8]) # EAST
204 204 elif ii==3:dim = numpy.array([4,4,8,8]) # SOUTH
205 205 xi = dim[0]; xf = dim[2]; yi = dim[1]; yf = dim[3]
206 206 phase[xi:xf,yi:yf] = phase[xi:xf,yi:yf] + ues[ii]
207 207
208 208 phase = -phase
209 209
210 210 ar = self.eomwl*numpy.array([[0.5,6., 24.5],[0.5,6.,24.5]])
211 211 nr = numpy.array([[12.,4.,2.],[12.,4.,2.]])
212 212 lr = 0.25*self.eomwl*numpy.array([[0,0.,0],[0.,0,0]])
213 213
214 214 # Computing module and dipole patterns.
215 215 pattern = (numpy.abs(self.__dipPattern(ar,nr,lr)*self.__modPattern(phase,gain)))**2
216 216
217 217 return pattern
218 218
219 219 def __usingFFT(self,rx):
220 220 """
221 221 __usingFFT method returns the Jicamarca antenna pattern computed using The Fast Fou-
222 222 rier Transform.
223 223
224 224 pattern = iFFT(FFT(gain*EXP(j*phase)))
225 225
226 226 Parameters
227 227 ----------
228 228 rx = Set to 1 to use the Rx information. Otherwise set to 0 for Tx.
229 229
230 230 Return
231 231 ------
232 232 pattern = An array giving the modelled antenna pattern using the array model.
233 233
234 234 Modification history
235 235 --------------------
236 236 Developed by Jorge L. Chau.
237 237 Converted to Python by Freddy R. Galindo, ROJ, 20 September 2009.
238 238 """
239 239
240 240 if rx==1:
241 241 ues = self.uesrx
242 242 phase = self.phaserx
243 243 gain = self.gainrx
244 244 elif rx==0:
245 245 ues = self.uestx
246 246 phase = self.phasetx
247 247 gain = self.gaintx
248 248
249 249 ues = ues*360./self.airwl
250 250 phase = phase*360./self.airwl
251 251
252 252 for ii in range(4):
253 253 if ii==0:dim = numpy.array([4,0,8,4]) # WEST
254 254 elif ii==1:dim = numpy.array([0,0,4,4]) # NORTH
255 255 elif ii==2:dim = numpy.array([0,4,4,8]) # EAST
256 256 elif ii==3:dim = numpy.array([4,4,8,8]) # SOUTH
257 257 xi = dim[0]; xf = dim[2]; yi = dim[1]; yf = dim[3]
258 258 phase[xi:xf,yi:yf] = phase[xi:xf,yi:yf] + ues[ii]
259 259
260 260 phase = -phase
261 261
262 262 delta_x = self.eomwl/2.
263 263 delta_y = self.eomwl/2.
264 264
265 265 nxfft = 2048
266 266 nyfft = 2048
267 267 dcosx = (numpy.arange(nxfft) - (0.5*nxfft))/(nxfft*delta_x)*self.eomwl
268 268 dcosy = (numpy.arange(nyfft) - (0.5*nyfft))/(nyfft*delta_y)*self.eomwl
269 269
270 270 fft_gain = numpy.zeros((nxfft,nyfft))
271 271 fft_phase = numpy.zeros((nxfft,nyfft))
272 272
273 273 nx = 8
274 274 ny = 8
275 275 ndx =12
276 276 ndy =12
277 277 for iy in numpy.arange(ny):
278 278 for ix in numpy.arange(nx):
279 279 ix1 = nxfft/2-self.nx/2*ndx+ix*ndx
280 280 if ix<(nx/2):ix1 = ix1 - 1
281 281 if ix>=(nx/2):ix1 = ix1 + 1
282 282
283 283 iy1 = nyfft/2-ny/2*ndx+iy*ndy
284 284 if iy<(ny/2):iy1 = iy1 - 1
285 285 if iy>=(ny/2):iy1 = iy1 + 1
286 286
287 287 fft_gain[ix1:ix1+ndx-1,iy1:iy1+ndy-1] = gain[ix,ny-1-iy]
288 288 fft_phase[ix1:ix1+ndx-1,iy1:iy1+ndy-1] = phase[ix,ny-1-iy]
289 289
290 290
291 291 fft_phase = fft_phase*CoFactors.d2r
292 292
293 293 pattern = numpy.abs(numpy.fft.fft2(fft_gain*numpy.exp(numpy.complex(0,1)*fft_phase)))**2
294 294 pattern = numpy.fft.fftshift(pattern)
295 295
296 296 xvals = numpy.where((dcosx>=(numpy.min(self.dcosx))) & (dcosx<=(numpy.max(self.dcosx))))
297 297 yvals = numpy.where((dcosy>=(numpy.min(self.dcosy))) & (dcosy<=(numpy.max(self.dcosy))))
298 298
299 299 pattern = pattern[xvals[0][0]:xvals[0][-1],yvals[0][0]:yvals[0][-1]]
300 300
301 301 return pattern
302 302
303 303 def __readAttenuation(self):
304 304 """
305 305 _readAttenuation reads the attenuations' file and returns an array giving these va-
306 306 lues (dB). The ext file must be in the directory "resource".
307 307
308 308 Return
309 309 ------
310 310 attenuation = An array giving attenuation values read from the text file.
311 311
312 312 Modification history
313 313 --------------------
314 314 Developed by Jorge L. Chau.
315 315 Converted to Python by Freddy R. Galindo, ROJ, 20 September 2009.
316 316 """
317 317
318 318 # attenuation = None
319 319 # # foldr = sys.path[-1] + os.sep + "resource" + os.sep
320 320 # base_path = os.path.dirname(os.path.abspath(__file__))
321 321 # #foldr = './resource'
322 322 # #filen = "attenuation.txt"
323 323 # attenuationFile = os.path.join(base_path,"resource","attenuation.txt")
324 324 # #ff = open(os.path.join(foldr,filen),'r')
325 325 # ff = open(attenuationFile,'r')
326 326 # print(ff.read())
327 327 # exec(ff.read())
328 328 # ff.close()
329 329 attenuation = numpy.array([[[-21.25,-15.25,-9.25,-3.25,03.25,09.25,15.25,21.25],
330 330 [-21.25,-15.25,-9.25,-3.25,03.25,09.25,15.25,21.25],
331 331 [-21.25,-15.25,-9.25,-3.25,03.25,09.25,15.25,21.25],
332 332 [-21.25,-15.25,-9.25,-3.25,03.25,09.25,15.25,21.25],
333 333 [-21.25,-15.25,-9.25,-3.25,03.25,09.25,15.25,21.25],
334 334 [-21.25,-15.25,-9.25,-3.25,03.25,09.25,15.25,21.25],
335 335 [-21.25,-15.25,-9.25,-3.25,03.25,09.25,15.25,21.25],
336 336 [-21.25,-15.25,-9.25,-3.25,03.25,09.25,15.25,21.25]],
337 337 [[21.25,21.25,21.25,21.25,21.25,21.25,21.25,21.25],
338 338 [15.25,15.25,15.25,15.25,15.25,15.25,15.25,15.25],
339 339 [09.25,09.25,09.25,09.25,09.25,09.25,09.25,09.25],
340 340 [03.25,03.25,03.25,03.25,03.25,03.25,03.25,03.25],
341 341 [-03.25,-03.25,-03.25,-03.25,-03.25,-03.25,-03.25,-03.25],
342 342 [-09.25,-09.25,-09.25,-09.25,-09.25,-09.25,-09.25,-09.25],
343 343 [-15.25,-15.25,-15.25,-15.25,-15.25,-15.25,-15.25,-15.25],
344 344 [-21.25,-21.25,-21.25,-21.25,-21.25,-21.25,-21.25,-21.25]]])
345 345
346 346 return attenuation
347 347
348 348 def __dipPattern(self,ar,nr,lr):
349 349 """
350 350 _dipPattern function computes the dipole's pattern to the Jicamarca radar. The next
351 351 equation defines the pattern as a function of the mainlobe direction:
352 352
353 353 sincx = SIN(k/2*n0x*(a0x*SIN(phi)*COS(alpha)))/SIN(k/2*(a0x*SIN(phi)*COS(alpha)))
354 354 sincy = SIN(k/2*n0y*(a0y*SIN(phi)*SIN(alpha)))/SIN(k/2*(a0y*SIN(phi)*SIN(alpha)))
355 355 A0(phi,alpha) = sincx*sincy
356 356 Parameters
357 357 ----------
358 358 ar = ?
359 359 nr = ?
360 360 lr = ?
361 361
362 362 Return
363 363 ------
364 364 dipole = An array giving antenna pattern from the dipole point of view..
365 365
366 366 Modification history
367 367 --------------------
368 368 Developed by Jorge L. Chau.
369 369 Converted to Python by Freddy R. Galindo, ROJ, 20 September 2009.
370 370 """
371 371
372 372 dipole = numpy.zeros((self.nx,self.ny),dtype=complex)
373 373 for iy in range(self.ny):
374 374 for ix in range(self.nx):
375 375 yindex = iy*(self.getcut==0) + ix*(self.getcut==1)
376 376
377 377 argx = ar[0,0]*self.dcosx[ix] - lr[0,0]
378 378 if argx == 0.0:
379 379 junkx = nr[0,0]
380 380 else:
381 381 junkx = numpy.sin(0.5*self.kk*nr[0,0]*argx)/numpy.sin(0.5*self.kk*argx)
382 382
383 383
384 384 argy = ar[1,0]*self.dcosy[yindex] - lr[1,0]
385 385 if argy == 0.0:
386 386 junky = nr[1,0]
387 387 else:
388 388 junky = numpy.sin(0.5*self.kk*nr[1,0]*argy)/numpy.sin(0.5*self.kk*argy)
389 389
390 390
391 391 dipole[ix,iy] = junkx*junky
392 392
393 393 return dipole
394 394
395 395 def __modPattern(self,phase,gain):
396 396 """
397 397 ModPattern computes the module's pattern to the Jicamarca radar. The next equation
398 398 defines the pattern as a function mainlobe direction:
399 399
400 400 phasex = pos(x)*SIN(phi)*COS(alpha)
401 401 phasey = pos(y)*SIN(phi)*SIN(alpha)
402 402
403 403 A1(phi,alpha) = TOTAL(gain*EXP(COMPLEX(0,k*(phasex+phasey)+phase)))
404 404
405 405 Parameters
406 406 ----------
407 407 phase = Bidimensional array (8x8) giving the phase (in meters) of each module.
408 408 gain = Bidimensional array (8x8) giving to define modules will be active (ones)
409 409 and which will not (zeros).
410 410
411 411 Return
412 412 ------
413 413 module = An array giving antenna pattern from the module point of view..
414 414
415 415 Modification history
416 416 --------------------
417 417 Developed by Jorge L. Chau.
418 418 Converted to Python by Freddy R. Galindo, ROJ, 20 September 2009.
419 419 """
420 420
421 421 pos = self.eomwl*self.__readAttenuation()
422 422 posx = pos[0,:,:]
423 423 posy = pos[1,:,:]
424 424
425 425 phase = phase*CoFactors.d2r
426 426 module = numpy.zeros((self.nx,self.ny),dtype=complex)
427 427 for iy in range(self.ny):
428 428 for ix in range(self.nx):
429 429 yindex = iy*(self.getcut==0) + ix*(self.getcut==1)
430 430 phasex = posx*self.dcosx[ix]
431 431 phasey = posy*self.dcosy[yindex]
432 432 tmp = gain*numpy.exp(numpy.complex(0,1.)*(self.kk*(phasex+phasey)+phase))
433 433 module[ix,iy] = tmp.sum()
434 434
435 435 return module
436 436
437 437 def __getBeamPars(self):
438 438 """
439 439 _getBeamPars computes the main-beam parameters of the antenna.
440 440
441 441 Modification history
442 442 --------------------
443 443 Developed by Jorge L. Chau.
444 444 Converted to Python by Freddy R. Galindo, ROJ, 20 September 2009.
445 445 """
446 446
447 447 dx = self.dcosx[1] - self.dcosx[0]
448 448 dy = self.dcosy[1] - self.dcosy[0]
449 449
450 450 amp = self.norpattern
451 451
452 452 xx = numpy.resize(self.dcosx,(self.nx,self.nx)).transpose()
453 453 yy = numpy.resize(self.dcosy,(self.ny,self.ny))
454 454
455 455 mm0 = amp[numpy.where(amp > 0.5)]
456 456 xx0 = xx[numpy.where(amp > 0.5)]
457 457 yy0 = yy[numpy.where(amp > 0.5)]
458 458
459 459 xc = numpy.sum(mm0*xx0)/numpy.sum(mm0)
460 460 yc = numpy.sum(mm0*yy0)/numpy.sum(mm0)
461 461 rc = numpy.sqrt(mm0.size*dx*dy/numpy.pi)
462 462
463 463 nnx = numpy.where(numpy.abs(self.dcosx - xc) < rc)
464 464 nny = numpy.where(numpy.abs(self.dcosy - yc) < rc)
465 465
466 466 mm1 = amp[numpy.min(nnx):numpy.max(nnx)+1,numpy.min(nny):numpy.max(nny)+1]
467 467 xx1 = self.dcosx[numpy.min(nnx):numpy.max(nnx)+1]
468 468 yy1 = self.dcosy[numpy.min(nny):numpy.max(nny)+1]
469 469
470 470 # fitting data into the main beam.
471 import gaussfit
472 params = gaussfit.fitgaussian(mm1)
471 from .gaussfit import fitgaussian
472 params = fitgaussian(mm1)
473 473
474 474 # Tranforming from indexes to axis' values
475 475 xcenter = xx1[0] + (((xx1[xx1.size-1] - xx1[0])/(xx1.size -1))*(params[1]))
476 476 ycenter = yy1[0] + (((yy1[yy1.size-1] - yy1[0])/(yy1.size -1))*(params[2]))
477 477 xwidth = ((xx1[xx1.size-1] - xx1[0])/(xx1.size-1))*(params[3])*(1/CoFactors.d2r)
478 478 ywidth = ((yy1[yy1.size-1] - yy1[0])/(yy1.size-1))*(params[4])*(1/CoFactors.d2r)
479 479 meanwx = (xwidth*ywidth)
480 480 meanpos = numpy.array([xcenter,ycenter])
481 481
482 482 #print 'Position: %f %f' %(xcenter,ycenter)
483 483 #print 'Widths: %f %f' %(xwidth, ywidth)
484 484 #print 'BWHP: %f' %(2*numpy.sqrt(2*meanwx)*numpy.sqrt(-numpy.log(0.5)))
485 485
486 486 self.meanpos = meanpos
487 487
488 488
489 489 class BField():
490 490 def __init__(self,year=None,doy=None,site=1,heights=None,alpha_i=90):
491 491 """
492 492 BField class creates an object to get the Magnetic field for a specific date and
493 493 height(s).
494 494
495 495 Parameters
496 496 ----------
497 497 year = A scalar giving the desired year. If the value is None (default value) then
498 498 the current year will be used.
499 499 doy = A scalar giving the desired day of the year. If the value is None (default va-
500 500 lue) then the current doy will be used.
501 501 site = An integer to choose the geographic coordinates of the place where the magne-
502 502 tic field will be computed. The default value is over Jicamarca (site=1)
503 503 heights = An array giving the heights (km) where the magnetic field will be modeled By default the magnetic field will be computed at 100, 500 and 1000km.
504 504 alpha_i = Angle to interpolate the magnetic field.
505 505
506 506 Modification History
507 507 --------------------
508 508 Converted to Object-oriented Programming by Freddy Galindo, ROJ, 07 October 2009.
509 509 """
510 510
511 511 tmp = time.localtime()
512 512 if year==None: year = tmp[0]
513 513 if doy==None: doy = tmp[7]
514 514 self.year = year
515 515 self.doy = doy
516 516 self.site = site
517 517 if heights==None:heights = numpy.array([100,500,1000])
518 518 self.heights = heights
519 519 self.alpha_i = alpha_i
520 520
521 521 def getBField(self,maglimits=numpy.array([-7,-7,7,7])):
522 522 """
523 523 getBField models the magnetic field for a different heights in a specific date.
524 524
525 525 Parameters
526 526 ----------
527 527 maglimits = An 4-elements array giving ..... The default value is [-7,-7,7,7].
528 528
529 529 Return
530 530 ------
531 531 dcos = An 4-dimensional array giving the directional cosines of the magnetic field
532 532 over the desired place.
533 533 alpha = An 3-dimensional array giving the angle of the magnetic field over the desi-
534 534 red place.
535 535
536 536 Modification History
537 537 --------------------
538 538 Converted to Python by Freddy R. Galindo, ROJ, 07 October 2009.
539 539 """
540 540
541 541 x_ant = numpy.array([1,0,0])
542 542 y_ant = numpy.array([0,1,0])
543 543 z_ant = numpy.array([0,0,1])
544 544
545 545 if self.site==0:
546 546 title_site = "Magnetic equator"
547 547 coord_site = numpy.array([-76+52./60.,-11+57/60.,0.5])
548 548 elif self.site==1:
549 549 title_site = 'Jicamarca'
550 550 coord_site = [-76-52./60.,-11-57/60.,0.5]
551 551 theta = (45+5.35)*numpy.pi/180. # (50.35 and 1.46 from Fleish Thesis)
552 552 delta = -1.46*numpy.pi/180
553 553
554 554 x_ant1 = numpy.roll(self.rotvector(self.rotvector(x_ant,1,delta),3,theta),1)
555 555 y_ant1 = numpy.roll(self.rotvector(self.rotvector(y_ant,1,delta),3,theta),1)
556 556 z_ant1 = numpy.roll(self.rotvector(self.rotvector(z_ant,1,delta),3,theta),1)
557 557
558 558 ang0 = -1*coord_site[0]*numpy.pi/180.
559 559 ang1 = coord_site[1]*numpy.pi/180.
560 560 x_ant = self.rotvector(self.rotvector(x_ant1,2,ang1),3,ang0)
561 561 y_ant = self.rotvector(self.rotvector(y_ant1,2,ang1),3,ang0)
562 562 z_ant = self.rotvector(self.rotvector(z_ant1,2,ang1),3,ang0)
563 563 else:
564 564 # print "No defined Site. Skip..."
565 565 return None
566 566
567 567 nhei = self.heights.size
568 568 pt_intercep = numpy.zeros((nhei,2))
569 569 nfields = 1
570 570
571 571 grid_res = 0.5
572 572 nlon = int(numpy.int(maglimits[2] - maglimits[0])/grid_res + 1)
573 573 nlat = int(numpy.int(maglimits[3] - maglimits[1])/grid_res + 1)
574 574
575 575 location = numpy.zeros((nlon,nlat,2))
576 576 mlon = numpy.atleast_2d(numpy.arange(nlon)*grid_res + maglimits[0])
577 577 mrep = numpy.atleast_2d(numpy.zeros(nlat) + 1)
578 578 location0 = numpy.dot(mlon.transpose(),mrep)
579 579
580 580 mlat = numpy.atleast_2d(numpy.arange(nlat)*grid_res + maglimits[1])
581 581 mrep = numpy.atleast_2d(numpy.zeros(nlon) + 1)
582 582 location1 = numpy.dot(mrep.transpose(),mlat)
583 583
584 584 location[:,:,0] = location0
585 585 location[:,:,1] = location1
586 586
587 587 alpha = numpy.zeros((nlon,nlat,nhei))
588 588 rr = numpy.zeros((nlon,nlat,nhei,3))
589 589 dcos = numpy.zeros((nlon,nlat,nhei,2))
590 590
591 591 global first_time
592 592
593 593 first_time = None
594 594 for ilon in numpy.arange(nlon):
595 595 for ilat in numpy.arange(nlat):
596 596 outs = self.__bdotk(self.heights,
597 597 self.year + self.doy/366.,
598 598 coord_site[1],
599 599 coord_site[0],
600 600 coord_site[2],
601 601 coord_site[1]+location[ilon,ilat,1],
602 602 location[ilon,ilat,0]*720./180.)
603 603
604 604 alpha[ilon, ilat,:] = outs[1]
605 605 rr[ilon, ilat,:,:] = outs[3]
606 606
607 607 mrep = numpy.atleast_2d((numpy.zeros(nhei)+1)).transpose()
608 608 tmp = outs[3]*numpy.dot(mrep,numpy.atleast_2d(x_ant))
609 609 tmp = tmp.sum(axis=1)
610 610 dcos[ilon,ilat,:,0] = tmp/numpy.sqrt((outs[3]**2).sum(axis=1))
611 611
612 612 mrep = numpy.atleast_2d((numpy.zeros(nhei)+1)).transpose()
613 613 tmp = outs[3]*numpy.dot(mrep,numpy.atleast_2d(y_ant))
614 614 tmp = tmp.sum(axis=1)
615 615 dcos[ilon,ilat,:,1] = tmp/numpy.sqrt((outs[3]**2).sum(axis=1))
616 616
617 617 return dcos, alpha, nlon, nlat
618 618
619 619
620 620 def __bdotk(self,heights,tm,gdlat=-11.95,gdlon=-76.8667,gdalt=0.0,decd=-12.88, ham=-4.61666667):
621 621
622 622 global first_time
623 623 # Mean Earth radius in Km WGS 84
624 624 a_igrf = 6371.2
625 625
626 626 bk = numpy.zeros(heights.size)
627 627 alpha = numpy.zeros(heights.size)
628 628 bfm = numpy.zeros(heights.size)
629 629 rr = numpy.zeros((heights.size,3))
630 630 rgc = numpy.zeros((heights.size,3))
631 631
632 ObjGeodetic = Astro_Coords.Geodetic(gdlat,gdalt)
632 ObjGeodetic = Geodetic(gdlat,gdalt)
633 633 [gclat,gcalt] = ObjGeodetic.change2geocentric()
634 634
635 635 gclat = gclat*numpy.pi/180.
636 636 gclon = gdlon*numpy.pi/180.
637 637
638 638 # Antenna position from center of Earth
639 639 ca_vector = [numpy.cos(gclat)*numpy.cos(gclon),numpy.cos(gclat)*numpy.sin(gclon),numpy.sin(gclat)]
640 640 ca_vector = gcalt*numpy.array(ca_vector)
641 641
642 642 dec = decd*numpy.pi/180.
643 643
644 644 # K vector respect to the center of earth.
645 645 klon = gclon + ham*numpy.pi/720.
646 646 k_vector = [numpy.cos(dec)*numpy.cos(klon),numpy.cos(dec)*numpy.sin(klon),numpy.sin(dec)]
647 647 k_vector = numpy.array(k_vector)
648 648
649 649 for ih in numpy.arange(heights.size):
650 650 # Vector from Earth's center to volume of interest
651 651 rr[ih,:] = k_vector*heights[ih]
652 652 cv_vector = numpy.squeeze(ca_vector) + rr[ih,:]
653 653
654 654 cv_gcalt = numpy.sqrt(numpy.sum(cv_vector**2.))
655 655 cvxy = numpy.sqrt(numpy.sum(cv_vector[0:2]**2.))
656 656
657 657 radial = cv_vector/cv_gcalt
658 658 east = numpy.array([-1*cv_vector[1],cv_vector[0],0])/cvxy
659 659 comp1 = east[1]*radial[2] - radial[1]*east[2]
660 660 comp2 = east[2]*radial[0] - radial[2]*east[0]
661 661 comp3 = east[0]*radial[1] - radial[0]*east[1]
662 662 north = -1*numpy.array([comp1, comp2, comp3])
663 663
664 664 rr_k = cv_vector - numpy.squeeze(ca_vector)
665 665 u_rr = rr_k/numpy.sqrt(numpy.sum(rr_k**2.))
666 666
667 667 cv_gclat = numpy.arctan2(cv_vector[2],cvxy)
668 668 cv_gclon = numpy.arctan2(cv_vector[1],cv_vector[0])
669 669
670 670 bhei = cv_gcalt-a_igrf
671 671 blat = cv_gclat*180./numpy.pi
672 672 blon = cv_gclon*180./numpy.pi
673 673 bfield = self.__igrfkudeki(bhei,tm,blat,blon)
674 674
675 675 B = (bfield[0]*north + bfield[1]*east - bfield[2]*radial)*1.0e-5
676 676
677 677 bfm[ih] = numpy.sqrt(numpy.sum(B**2.)) #module
678 678 bk[ih] = numpy.sum(u_rr*B)
679 679 alpha[ih] = numpy.arccos(bk[ih]/bfm[ih])*180/numpy.pi
680 680 rgc[ih,:] = numpy.array([cv_gclon, cv_gclat, cv_gcalt])
681 681
682 682 return bk, alpha, bfm, rr, rgc
683 683
684 684
685 685 def __igrfkudeki(self,heights,time,latitude,longitude,ae=6371.2):
686 686 """
687 687 __igrfkudeki calculates the International Geomagnetic Reference Field for given in-
688 688 put conditions based on IGRF2005 coefficients.
689 689
690 690 Parameters
691 691 ----------
692 692 heights = Scalar or vector giving the height above the Earth of the point in ques-
693 693 tion in kilometers.
694 694 time = Scalar or vector giving the decimal year of time in question (e.g. 1991.2).
695 695 latitude = Latitude of point in question in decimal degrees. Scalar or vector.
696 696 longitude = Longitude of point in question in decimal degrees. Scalar or vector.
697 697 ae =
698 698 first_time =
699 699
700 700 Return
701 701 ------
702 702 bn =
703 703 be =
704 704 bd =
705 705 bmod =
706 706 balpha =
707 707 first_time =
708 708
709 709 Modification History
710 710 --------------------
711 711 Converted to Python by Freddy R. Galindo, ROJ, 03 October 2009.
712 712 """
713 713
714 714 global first_time
715 715 global gs, hs, nvec, mvec, maxcoef
716 716
717 717 heights = numpy.atleast_1d(heights)
718 718 time = numpy.atleast_1d(time)
719 719 latitude = numpy.atleast_1d(latitude)
720 720 longitude = numpy.atleast_1d(longitude)
721 721
722 722 if numpy.max(latitude)==90:
723 723 # print "Field calculations are not supported at geographic poles"
724 724 pass
725 725
726 726 # output arrays
727 727 bn = numpy.zeros(heights.size)
728 728 be = numpy.zeros(heights.size)
729 729 bd = numpy.zeros(heights.size)
730 730
731 731 if first_time==None:first_time=0
732 732
733 733 time0 = time[0]
734 734 if time!=first_time:
735 735 #print "Getting coefficients for", time0
736 736 [periods,g,h ] = self.__readIGRFcoeff()
737 737 top_year = numpy.max(periods)
738 738 nperiod = (top_year - 1900)/5 + 1
739 739
740 740 maxcoef = 10
741 741 if time0>=2000:maxcoef = 12
742 742
743 743
744 744 # Normalization array for Schmidt fucntions
745 745 multer = numpy.zeros((2+maxcoef,1+maxcoef)) + 1
746 746 for cn in (numpy.arange(maxcoef)+1):
747 747 for rm in (numpy.arange(cn)+1):
748 748 tmp = numpy.arange(2*rm) + cn - rm + 1.
749 749 multer[rm+1,cn] = ((-1.)**rm)*numpy.sqrt(2./tmp.prod())
750 750
751 751 schmidt = multer[1:,1:].transpose()
752 752
753 753 # n and m arrays
754 754 nvec = numpy.atleast_2d(numpy.arange(maxcoef)+2)
755 755 mvec = numpy.atleast_2d(numpy.arange(maxcoef+1)).transpose()
756 756
757 757 # Time adjusted igrf g and h with Schmidt normalization
758 758 # IGRF coefficient arrays: g0(n,m), n=1, maxcoeff,m=0, maxcoeff, ...
759 759 if time0<top_year:
760 760 dtime = (time0 - 1900) % 5
761 761 ntime = (time0 - 1900 - dtime)/5
762 762 else:
763 763 # Estimating coefficients for times > top_year
764 764 dtime = (time0 - top_year) + 5
765 765 ntime = g[:,0,0].size - 2
766 766
767 767 g0 = g[ntime,1:maxcoef+1,:maxcoef+1]
768 768 h0 = h[ntime,1:maxcoef+1,:maxcoef+1]
769 769 gdot = g[ntime+1,1:maxcoef+1,:maxcoef+1]-g[ntime,1:maxcoef+1,:maxcoef+1]
770 770 hdot = h[ntime+1,1:maxcoef+1,:maxcoef+1]-h[ntime,1:maxcoef+1,:maxcoef+1]
771 771 gs = (g0 + dtime*(gdot/5.))*schmidt[:maxcoef,0:maxcoef+1]
772 772 hs = (h0 + dtime*(hdot/5.))*schmidt[:maxcoef,0:maxcoef+1]
773 773
774 774 first_time = time0
775 775
776 776 for ii in numpy.arange(heights.size):
777 777 # Height dependence array rad = (ae/(ae+height))**(n+3)
778 778 rad = numpy.atleast_2d((ae/(ae + heights[ii]))**(nvec+1))
779 779
780 780 # Sin and Cos of m times longitude phi arrays
781 781 mphi = mvec*longitude[ii]*numpy.pi/180.
782 782 cosmphi = numpy.atleast_2d(numpy.cos(mphi))
783 783 sinmphi = numpy.atleast_2d(numpy.sin(mphi))
784 784
785 785 # Cos of colatitude theta
786 786 c = numpy.cos((90 - latitude[ii])*numpy.pi/180.)
787 787
788 788 # Legendre functions p(n,m|c)
789 789 [p,dp]= scipy.special.lpmn(maxcoef+1,maxcoef+1,c)
790 790 p = p[:,:-1].transpose()
791 791 s = numpy.sqrt((1. - c)*(1 + c))
792 792
793 793 # Generate derivative array dpdtheta = -s*dpdc
794 794 dpdtheta = c*p/s
795 795 for m in numpy.arange(maxcoef+2): dpdtheta[:,m] = m*dpdtheta[:,m]
796 796 dpdtheta = dpdtheta + numpy.roll(p,-1,axis=1)
797 797
798 798 # Extracting arrays required for field calculations
799 799 p = p[1:maxcoef+1,:maxcoef+1]
800 800 dpdtheta = dpdtheta[1:maxcoef+1,:maxcoef+1]
801 801
802 802 # Weigh p and dpdtheta with gs and hs coefficients.
803 803 gp = gs*p
804 804 hp = hs*p
805 805 gdpdtheta = gs*dpdtheta
806 806 hdpdtheta = hs*dpdtheta
807 807 # Calcultate field components
808 808 matrix0 = numpy.dot(gdpdtheta,cosmphi)
809 809 matrix1 = numpy.dot(hdpdtheta,sinmphi)
810 810 bn[ii] = numpy.dot(rad,(matrix0 + matrix1))
811 811 matrix0 = numpy.dot(hp,(mvec*cosmphi))
812 812 matrix1 = numpy.dot(gp,(mvec*sinmphi))
813 813 be[ii] = numpy.dot((-1*rad),((matrix0 - matrix1)/s))
814 814 matrix0 = numpy.dot(gp,cosmphi)
815 815 matrix1 = numpy.dot(hp,sinmphi)
816 816 bd[ii] = numpy.dot((-1*nvec*rad),(matrix0 + matrix1))
817 817
818 818 bmod = numpy.sqrt(bn**2. + be**2. + bd**2.)
819 819 btheta = numpy.arctan(bd/numpy.sqrt(be**2. + bn**2.))*180/numpy.pi
820 820 balpha = numpy.arctan(be/bn)*180./numpy.pi
821 821
822 822 #bn : north
823 823 #be : east
824 824 #bn : radial
825 825 #bmod : module
826 826
827 827
828 828 return bn, be, bd, bmod, btheta, balpha
829 829
830 830 def str2num(self, datum):
831 831 try:
832 832 return int(datum)
833 833 except:
834 834 try:
835 835 return float(datum)
836 836 except:
837 837 return datum
838 838
839 839 def __readIGRFfile(self, filename):
840 840 list_years=[]
841 841 for i in range(1,24):
842 842 list_years.append(1895.0 + i*5)
843 843
844 844 epochs=list_years
845 845 epochs.append(epochs[-1]+5)
846 846 nepochs = numpy.shape(epochs)
847 847
848 848 gg = numpy.zeros((13,14,nepochs[0]),dtype=float)
849 849 hh = numpy.zeros((13,14,nepochs[0]),dtype=float)
850 850
851 851 coeffs_file=open(filename)
852 852 lines=coeffs_file.readlines()
853 853
854 854 coeffs_file.close()
855 855
856 856 for line in lines:
857 857 items = line.split()
858 858 g_h = items[0]
859 859 n = self.str2num(items[1])
860 860 m = self.str2num(items[2])
861 861
862 862 coeffs = items[3:]
863 863
864 864 for i in range(len(coeffs)-1):
865 865 coeffs[i] = self.str2num(coeffs[i])
866 866
867 867 #coeffs = numpy.array(coeffs)
868 868 ncoeffs = numpy.shape(coeffs)[0]
869 869
870 870 if g_h == 'g':
871 871 # print n," g ",m
872 872 gg[n-1,m,:]=coeffs
873 873 elif g_h=='h':
874 874 # print n," h ",m
875 875 hh[n-1,m,:]=coeffs
876 876 # else :
877 877 # continue
878 878
879 879 # Ultimo Reordenamiento para almacenar .
880 880 gg[:,:,nepochs[0]-1] = gg[:,:,nepochs[0]-2] + 5*gg[:,:,nepochs[0]-1]
881 881 hh[:,:,nepochs[0]-1] = hh[:,:,nepochs[0]-2] + 5*hh[:,:,nepochs[0]-1]
882 882
883 883 # return numpy.array([gg,hh])
884 884 periods = numpy.array(epochs)
885 885 g = gg
886 886 h = hh
887 887 return periods, g, h
888 888
889 889
890 890 def __readIGRFcoeff(self,filename="igrf10coeffs.dat"):
891 891 """
892 892 __readIGRFcoeff reads the coefficients from a binary file which is located in the
893 893 folder "resource."
894 894
895 895 Parameter
896 896 ---------
897 897 filename = A string to specify the name of the file which contains thec coeffs. The
898 898 default value is "igrf10coeffs.dat"
899 899
900 900 Return
901 901 ------
902 902 periods = A lineal array giving...
903 903 g1 =
904 904 h1 =
905 905
906 906 Modification History
907 907 --------------------
908 908 Converted to Python by Freddy R. Galindo, ROJ, 03 October 2009.
909 909 """
910 910
911 911 # # igrfile = sys.path[-1] + os.sep + "resource" + os.sep + filename
912 912 # igrfile = os.path.join('./resource',filename)
913 913 # f = open(igrfile,'rb')
914 914 # #f = open(os.getcwd() + os.sep + "resource" + os.sep + filename,'rb')
915 915 #
916 916 # # Reading SkyNoise Power (lineal scale)
917 917 # periods = numpy.fromfile(f,numpy.dtype([('var','<f4')]),23)
918 918 # periods = periods['var']
919 919 #
920 920 # g = numpy.fromfile(f,numpy.dtype([('var','<f8')]),23*14*14)
921 921 # g = g['var'].reshape((14,14,23)).transpose()
922 922 #
923 923 # h = numpy.fromfile(f,numpy.dtype([('var','<f8')]),23*14*14)
924 924 # h = h['var'].reshape((14,14,23)).transpose()
925 925 #
926 926 # f.close()
927 927 base_path = os.path.dirname(os.path.abspath(__file__))
928 928 filename = os.path.join(base_path,"resource","igrf11coeffs.txt")
929 929
930 930 period_v, g_v, h_v = self.__readIGRFfile(filename)
931 931 g2 = numpy.zeros((14,14,24))
932 932 h2 = numpy.zeros((14,14,24))
933 933 g2[1:14,:,:] = g_v
934 934 h2[1:14,:,:] = h_v
935 935
936 936 g = numpy.transpose(g2, (2,0,1))
937 937 h = numpy.transpose(h2, (2,0,1))
938 938 periods = period_v.copy()
939 939
940 940 return periods, g, h
941 941
942 942 def rotvector(self,vector,axis=1,ang=0):
943 943 """
944 944 rotvector function returns the new vector generated rotating the rectagular coords.
945 945
946 946 Parameters
947 947 ----------
948 948 vector = A lineal 3-elements array (x,y,z).
949 949 axis = A integer to specify the axis used to rotate the coord systems. The default
950 950 value is 1.
951 951 axis = 1 -> Around "x"
952 952 axis = 2 -> Around "y"
953 953 axis = 3 -> Around "z"
954 954 ang = Angle of rotation (in radians). The default value is zero.
955 955
956 956 Return
957 957 ------
958 958 rotvector = A lineal array of 3 elements giving the new coordinates.
959 959
960 960 Modification History
961 961 --------------------
962 962 Converted to Python by Freddy R. Galindo, ROJ, 01 October 2009.
963 963 """
964 964
965 965 if axis==1:
966 966 t = [[1,0,0],[0,numpy.cos(ang),numpy.sin(ang)],[0,-numpy.sin(ang),numpy.cos(ang)]]
967 967 elif axis==2:
968 968 t = [[numpy.cos(ang),0,-numpy.sin(ang)],[0,1,0],[numpy.sin(ang),0,numpy.cos(ang)]]
969 969 elif axis==3:
970 970 t = [[numpy.cos(ang),numpy.sin(ang),0],[-numpy.sin(ang),numpy.cos(ang),0],[0,0,1]]
971 971
972 972 rotvector = numpy.array(numpy.dot(numpy.array(t),numpy.array(vector)))
973 973
974 974 return rotvector
975 975
976 976
977 977 class overJroShow:
978 978
979 979 # __serverdocspath = '/usr/local/www/htdocs'
980 980 # __tmpDir = 'overJro/tempReports'
981 981 # __serverdocspath = '/Users/dsuarez/Pictures'
982 982 # __tmpDir = 'overjro'
983 983 __serverdocspath = ''
984 984 __tmpDir = ''
985 985
986 986 def __init__(self, title=''):
987 987 self.year = None
988 988 self.month = None
989 989 self.dom = None
990 990 self.pattern = None
991 991 self.maxphi = None
992 992 self.heights = None
993 993 self.filename = None
994 994 self.showType = None
995 995 self.path = None
996 996 self.objects = None
997 997 self.nptsx = 101
998 998 self.nptsy = 101
999 999 self.fftopt = 0
1000 1000 self.site = 1
1001 1001 self.dcosx = 1
1002 1002 self.dcosy = 1
1003 1003 self.dcosxrange = None
1004 1004 self.dcosyrange = None
1005 1005 self.maxha_min= 0.
1006 1006 self.show_object = None
1007 1007 self.dcosx_mag = None
1008 1008 self.dcosy_mag = None
1009 1009 self.ha_mag = None
1010 1010 self.time_mag = None
1011 1011 self.main_dec = None
1012 1012 self.ObjC = None
1013 1013 self.ptitle = title
1014 1014 self.path4plotname = None
1015 1015 self.plotname0 = None
1016 1016 self.plotname1 = None
1017 1017 self.plotname2 = None
1018 1018 self.scriptHeaders = 0
1019 1019 self.glat = -11.95
1020 1020 self.glon = -76.8667
1021 1021 self.UT = 5 #timezone
1022 1022
1023 1023 self.glat = -11.951481
1024 1024 self.glon = -76.874383
1025 1025 # self.outputHead('Show Plot')
1026 1026 # self.printBody()
1027 1027
1028 1028 def setScriptState(self):
1029 1029 self.madForm = cgi.FieldStorage()
1030 1030
1031 1031 if self.madForm.has_key('serverdocspath'):
1032 1032 self.__serverdocspath = self.madForm.getvalue('serverdocspath')#'/usr/local/www/htdocs'
1033 1033
1034 1034 if self.madForm.has_key('tmpdir'):
1035 1035 self.__tmpDir = self.madForm.getvalue('tmpdir')#'overJro/tempReports'
1036 1036
1037 1037 if self.madForm.has_key('showType'):
1038 1038 self.showType = int(self.madForm.getvalue('showType'))
1039 1039
1040 1040 if self.showType == 0 or self.showType == 1:
1041 1041
1042 1042 # if self.madForm.has_key('year') and \
1043 1043 # self.madForm.has_key('month') and \
1044 1044 # self.madForm.has_key('dom') and \
1045 1045 # self.madForm.has_key('pattern') and \
1046 1046 # self.madForm.has_key('maxphi') and \
1047 1047 # self.madForm.has_key('objects') and \
1048 1048 # self.madForm.has_key('heights'):
1049 1049
1050 1050 if self.madForm.has_key('year') and \
1051 1051 self.madForm.has_key('month') and \
1052 1052 self.madForm.has_key('dom') and \
1053 1053 self.madForm.has_key('maxphi') and \
1054 1054 self.madForm.has_key('objects') and \
1055 1055 self.madForm.has_key('heights'):
1056 1056
1057 1057 self.year = int(self.madForm.getvalue('year'))
1058 1058 self.month = int(self.madForm.getvalue('month'))
1059 1059 self.dom = int(self.madForm.getvalue('dom'))
1060 1060 self.maxphi = float(self.madForm.getvalue('maxphi'))
1061 1061
1062 1062 if self.madForm.has_key('pattern'):
1063 1063
1064 1064 tmp_pattern = self.madForm.getvalue('pattern') #pattern es predifinido en listado o definido por el usuario
1065 1065 self.pattern=[]
1066 1066 if tmp_pattern[0] == '[':
1067 1067 tmp_pattern=tmp_pattern[1:]
1068 1068
1069 1069 if tmp_pattern[-1] == ']':
1070 1070 tmp_pattern=tmp_pattern[0:len(tmp_pattern)-1]
1071 1071
1072 1072 for s in tmp_pattern.split(','):
1073 1073 self.pattern.append(float(s))
1074 1074 elif self.madForm.has_key('filename'):
1075 1075 if self.madForm.has_key('filename'):
1076 1076 self.filename = self.madForm.getvalue('filename') # nombre de archivo: patron de radiacion definido por el usuario
1077 1077
1078 1078 if self.madForm.has_key('path'):
1079 1079 self.path = self.madForm.getvalue('path') #path donde se encuentra el archivo: patron de radiacion del usuario
1080 1080
1081 1081 else:
1082 1082 print ("Content-Type: text/html\n")
1083 1083 print ('<h3> This cgi plot script was called without the proper arguments.</h3>')
1084 1084 print ('<p> This is a script used to plot Antenna Cuts over Jicamarca Antenna</p>')
1085 1085 print ('<p> Required arguments:</p>')
1086 1086 print ('<p> pattern - chekbox indicating objects over jicamarca antenna</p>')
1087 1087 print ('<p> or')
1088 1088 print ('<p> filename - The pattern defined by users is a file text')
1089 1089 print ('<p> path - folder with pattern files')
1090 1090 sys.exit(0)
1091 1091
1092 1092
1093 1093 tmp_heights = self.madForm.getvalue('heights')
1094 1094 self.heights=[]
1095 1095 if tmp_heights[0] == '[':
1096 1096 tmp_heights=tmp_heights[1:]
1097 1097
1098 1098 if tmp_heights[-1] == ']':
1099 1099 tmp_heights=tmp_heights[0:len(tmp_heights)-1]
1100 1100
1101 1101 for s in tmp_heights.split(','):
1102 1102 self.heights.append(float(s))
1103 1103 self.heights = numpy.array(self.heights)
1104 1104
1105 1105 tmp_objects = self.madForm.getvalue('objects') #lista con los objetos a graficar en el patron de radiacion
1106 1106 self.objects=[]
1107 1107 if tmp_objects[0] == '[':
1108 1108 tmp_objects=tmp_objects[1:]
1109 1109
1110 1110 if tmp_objects[-1] == ']':
1111 1111 tmp_objects=tmp_objects[0:len(tmp_objects)-1]
1112 1112
1113 1113 for s in tmp_objects.split(','):
1114 1114 self.objects.append(int(s))
1115 1115
1116 1116 if self.showType == 1:
1117 1117 if numpy.sum(self.objects) == 0:
1118 1118 if self.scriptHeaders == 0:
1119 1119 print ("Content-Type: text/html\n")
1120 1120 print ('<h3> This cgi plot script was called without the proper arguments.</h3>')
1121 1121 print ('<p> This is a script used to plot Antenna Cuts over Jicamarca Antenna</p>')
1122 1122 print ('<p> Required arguments:</p>')
1123 1123 print ('<p> objects - chekbox indicating objects over jicamarca antenna</p>')
1124 1124 print ('<p> Please, options in "Select Object" must be checked')
1125 1125 sys.exit(0)
1126 1126
1127 1127 #considerar para futura implementacion
1128 1128 if self.madForm.has_key('filename'):
1129 1129 self.filename = self.madForm.getvalue('filename') # nombre de archivo: patron de radiacion definido por el usuario
1130 1130
1131 1131 if self.madForm.has_key('path'):
1132 1132 self.path = self.madForm.getvalue('path') #path donde se encuentra el archivo: patron de radiacion del usuario
1133 1133
1134 1134
1135 1135 else:
1136 1136 if self.scriptHeaders == 0:
1137 1137 print ("Content-Type: text/html\n")
1138 1138
1139 1139 print ('<h3> This cgi plot script was called without the proper arguments.</h3>')
1140 1140 print ('<p> This is a script used to plot Pattern Field and Celestial Objects over Jicamarca Antenna</p>')
1141 1141 print ('<p> Required arguments:</p>')
1142 1142 print ('<p> year - year of event</p>')
1143 1143 print ('<p> month - month of event</p>')
1144 1144 print ('<p> dom - day of month</p>')
1145 1145 print ('<p> pattern - pattern is defined by "Select an Experiment" list box</p>')
1146 1146 print ('<p> maxphi - maxphi is defined by "Max Angle" text box</p>')
1147 1147 print ('<p> objects - objects is a list defined by checkbox in "Select Object"</p>')
1148 1148 print ('<p> heights - heights is defined by "Heights" text box, for default heights=[100,500,1000]</p>')
1149 1149 print ('<p> showType - showType is a hidden element for show plot of Pattern&Object or Antenna Cuts or Sky Noise</p>')
1150 1150
1151 1151 sys.exit(0)
1152 1152
1153 1153 if self.showType == 2:
1154 1154 if self.madForm.has_key('year') and \
1155 1155 self.madForm.has_key('month') and \
1156 1156 self.madForm.has_key('dom'):
1157 1157
1158 1158 self.year = int(self.madForm.getvalue('year'))
1159 1159 self.month = int(self.madForm.getvalue('month'))
1160 1160 self.dom = int(self.madForm.getvalue('dom'))
1161 1161
1162 1162 else:
1163 1163 if self.scriptHeaders == 0:
1164 1164 print ("Content-Type: text/html\n")
1165 1165 print ('<h3> This cgi plot script was called without the proper arguments.</h3>')
1166 1166 print ('<p> This is a script used to plot Sky Noise over Jicamarca Antenna</p>')
1167 1167 print ('<p> Required arguments:</p>')
1168 1168 print ('<p> year - year of event</p>')
1169 1169 print ('<p> month - month of event</p>')
1170 1170 print ('<p> dom - day of month</p>')
1171 1171
1172 1172 sys.exit(0)
1173 1173
1174 1174
1175 1175 def initParameters1(self):
1176 1176
1177 1177 gui=1
1178 1178 if self.pattern==None:
1179 1179 if gui==1: self.filename = self.filename.split(',')
1180 1180
1181 1181 pattern = numpy.atleast_1d(self.pattern)
1182 1182 filename = numpy.atleast_1d(self.filename)
1183 1183
1184 1184 npatterns = numpy.max(numpy.array([pattern.size,filename.size]))
1185 1185
1186 1186 self.pattern = numpy.resize(pattern,npatterns)
1187 1187 self.filename = numpy.resize(filename,npatterns)
1188 1188
1189 1189 self.doy = datetime.datetime(self.year,self.month,self.dom).timetuple().tm_yday
1190 1190
1191 1191
1192 1192 if self.objects==None:
1193 1193 self.objects=numpy.zeros(5)
1194 1194 else:
1195 1195 tmp = numpy.atleast_1d(self.objects)
1196 1196 self.objects = numpy.zeros(5)
1197 1197 self.objects[0:tmp.size] = tmp
1198 1198
1199 1199 self.show_object = self.objects
1200 1200
1201 1201 self.maxha_min = 4*self.maxphi*numpy.sqrt(2)*1.25
1202 1202
1203 1203
1204 1204 if self.heights==None:
1205 1205 self.heights = numpy.array([100.,500.,1000.])
1206 1206
1207 1207
1208 1208
1209 1209 #ROJ geographic coordinates and time zone
1210 1210 self.glat = -11.95
1211 1211 self.glon = -76.8667
1212 1212 self.UT = 5 #timezone
1213 1213
1214 1214 self.glat = -11.951481
1215 1215 self.glon = -76.874383
1216 1216
1217 1217
1218 1218 self.junkjd = Time(self.year,self.month,self.dom).change2julday()
1219 1219 self.junklst = Julian(self.junkjd).change2lst(longitude=self.glon)
1220 1220
1221 1221 # Finding RA of observatory for a specific date
1222 1222 self.ra_obs = self.junklst*CoFactors.h2d
1223 1223
1224 1224 def initParameters(self):
1225 1225
1226 1226 # Defining plot filenames
1227 1227 self.path4plotname = os.path.join(self.__serverdocspath,self.__tmpDir)
1228 1228 self.plotname0 = 'over_jro_0_%i.png'% (time.time()) #plot pattern & objects
1229 1229 self.plotname1 = 'over_jro_1_%i.png'% (time.time()) #plot antenna cuts
1230 1230 self.plotname2 = 'over_jro_2_%i.png'% (time.time()) #plot sky noise
1231 1231
1232 1232 # Defining antenna axes respect to geographic coordinates (See Ochs report).
1233 1233 # alfa = 1.46*Misc_Routines.CoFactors.d2r
1234 1234 # theta = 51.01*Misc_Routines.CoFactors.d2r
1235 1235
1236 1236 alfa = 1.488312*CoFactors.d2r
1237 1237 th = 6.166710 + 45.0
1238 1238 theta = th*CoFactors.d2r
1239 1239
1240 1240 sina = numpy.sin(alfa)
1241 1241 cosa = numpy.cos(alfa)
1242 1242 MT1 = numpy.array([[1,0,0],[0,cosa,-sina],[0,sina,cosa]])
1243 1243 sinb = numpy.sin(theta)
1244 1244 cosb = numpy.cos(theta)
1245 1245 MT2 = numpy.array([[cosb,sinb,0],[-sinb,cosb,0],[0,0,1]])
1246 1246 self.MT3 = numpy.array(numpy.dot(MT2, MT1)).transpose()
1247 1247
1248 1248 self.xg = numpy.dot(self.MT3.transpose(),numpy.array([1,0,0]))
1249 1249 self.yg = numpy.dot(self.MT3.transpose(),numpy.array([0,1,0]))
1250 1250 self.zg = numpy.dot(self.MT3.transpose(),numpy.array([0,0,1]))
1251 1251
1252 1252 def plotPattern2(self, date, phases, gain_tx, gain_rx, ues, just_rx):
1253 1253 # Plotting Antenna patterns.
1254 1254
1255 1255 self.initParameters()
1256 1256 self.doy = datetime.datetime(date.year,date.month,date.day).timetuple().tm_yday
1257 1257 self.junkjd = Time(self.year,self.month,self.dom).change2julday()
1258 1258 self.junklst = Julian(self.junkjd).change2lst(longitude=self.glon)
1259 1259 self.ra_obs = self.junklst*CoFactors.h2d
1260 1260
1261 1261 date = Time(date.year,date.month,date.day).change2strdate(mode=2)
1262 1262
1263 1263 mesg = 'Over Jicamarca: ' + date[0]
1264 1264
1265 1265 ObjAnt = JroPattern(pattern=0,
1266 1266 filename=None,
1267 1267 path=None,
1268 1268 nptsx=self.nptsx,
1269 1269 nptsy=self.nptsy,
1270 1270 #maxphi=self.maxphi,
1271 1271 fftopt=self.fftopt,
1272 1272 phases=numpy.array(phases),
1273 1273 gain_tx=numpy.array(gain_tx),
1274 1274 gain_rx=numpy.array(gain_rx),
1275 1275 ues=numpy.array(ues),
1276 1276 just_rx=just_rx
1277 1277 )
1278 1278
1279 1279 dum = AntPatternPlot()
1280 1280
1281 1281 dum.contPattern(iplot=0,
1282 1282 gpath=self.path4plotname,
1283 1283 filename=self.plotname0,
1284 1284 mesg=mesg,
1285 1285 amp=ObjAnt.norpattern,
1286 1286 x=ObjAnt.dcosx,
1287 1287 y=ObjAnt.dcosy,
1288 1288 getCut=ObjAnt.getcut,
1289 1289 title=self.ptitle,
1290 1290 save=False)
1291 1291
1292 1292
1293 1293 dum.plotRaDec(gpath=self.path4plotname,
1294 1294 filename=self.plotname0,
1295 1295 jd=self.junkjd,
1296 1296 ra_obs=self.ra_obs,
1297 1297 xg=self.xg,
1298 1298 yg=self.yg,
1299 1299 x=ObjAnt.dcosx,
1300 1300 y=ObjAnt.dcosy,
1301 1301 save=False)
1302 1302
1303 1303 ObjB = BField(self.year,self.doy,1,self.heights)
1304 1304 [dcos, alpha, nlon, nlat] = ObjB.getBField()
1305 1305
1306 1306 dum.plotBField('', '',dcos,alpha,nlon,nlat,
1307 1307 self.dcosxrange,
1308 1308 self.dcosyrange,
1309 1309 ObjB.heights,
1310 1310 ObjB.alpha_i,
1311 1311 save=False)
1312 1312
1313 1313 return dum.fig
1314 1314
1315 1315
1316 1316 def plotPattern(self):
1317 1317 # Plotting Antenna patterns.
1318 1318 npatterns = numpy.size(self.pattern)
1319 1319
1320 1320 if npatterns==1:
1321 1321 if self.pattern[0] == None: npatterns = self.filename.__len__()
1322 1322
1323 1323 date = TimeTools.Time(self.year,self.month,self.dom).change2strdate(mode=2)
1324 1324
1325 1325 mesg = 'Over Jicamarca: ' + date[0]
1326 1326
1327 1327 title = ''
1328 1328
1329 1329 for ii in numpy.arange(npatterns):
1330 1330 ObjAnt = JroPattern(pattern=self.pattern[ii],
1331 1331 filename=self.filename[ii],
1332 1332 path=self.path,
1333 1333 nptsx=self.nptsx,
1334 1334 nptsy=self.nptsy,
1335 1335 maxphi=self.maxphi,
1336 1336 fftopt=self.fftopt)
1337 1337
1338 1338 title += ObjAnt.title
1339 1339 # Plotting Contour Map
1340 1340
1341 1341 self.path4plotname = '/home/jespinoza/workspace/radarsys/trunk/webapp/apps/abs/static/images'
1342 1342 dum = AntPatternPlot()
1343 1343 dum.contPattern(iplot=ii,
1344 1344 gpath=self.path4plotname,
1345 1345 filename=self.plotname0,
1346 1346 mesg=mesg,
1347 1347 amp=ObjAnt.norpattern,
1348 1348 x=ObjAnt.dcosx,
1349 1349 y=ObjAnt.dcosy,
1350 1350 getCut=ObjAnt.getcut,
1351 1351 title=title)
1352 1352 # title=ObjAnt.title)
1353 1353 # self.ptitle = ObjAnt.title
1354 1354
1355 1355 if ii != (npatterns-1):
1356 1356 title += '+'
1357 1357
1358 1358
1359 1359 vect_ant = numpy.array([ObjAnt.meanpos[0],ObjAnt.meanpos[1],numpy.sqrt(1-numpy.sum(ObjAnt.meanpos**2.))])
1360 1360
1361 1361 vect_geo = numpy.dot(scipy.linalg.inv(self.MT3),vect_ant)
1362 1362
1363 1363 vect_polar = Misc_Routines.Vector(numpy.array(vect_geo),direction=1).Polar2Rect()
1364 1364
1365 [ra,dec,ha] = Astro_Coords.AltAz(vect_polar[1],vect_polar[0],self.junkjd).change2equatorial()
1365 [ra,dec,ha] = AltAz(vect_polar[1],vect_polar[0],self.junkjd).change2equatorial()
1366 1366
1367 1367 print('Main beam position (HA(min), DEC(degrees)): %f %f')%(ha*4.,dec)
1368 1368
1369 1369 self.main_dec = dec
1370 1370
1371 1371 self.ptitle = title
1372 1372
1373 1373 AntPatternPlot().plotRaDec(gpath=self.path4plotname,
1374 1374 filename=self.plotname0,
1375 1375 jd=self.junkjd,
1376 1376 ra_obs=self.ra_obs,
1377 1377 xg=self.xg,
1378 1378 yg=self.yg,
1379 1379 x=ObjAnt.dcosx,
1380 1380 y=ObjAnt.dcosy)
1381 1381
1382 1382 self.dcosx = ObjAnt.dcosx
1383 1383
1384 1384 self.dcosy = ObjAnt.dcosy
1385 1385
1386 1386 self.dcosxrange = [numpy.min(self.dcosx),numpy.max(self.dcosx)]
1387 1387
1388 1388 self.dcosyrange = [numpy.min(self.dcosy),numpy.max(self.dcosy)]
1389 1389
1390 1390 def plotBfield(self):
1391 1391
1392 1392 if self.show_object[0]>0:
1393 1393 # Getting B field
1394 1394 ObjB = BField(self.year,self.doy,self.site,self.heights)
1395 1395
1396 1396
1397 1397 [dcos, alpha, nlon, nlat] = ObjB.getBField()
1398 1398
1399 1399 # Plotting B field.
1400 1400 # print "Drawing magnetic field over Observatory"
1401 1401
1402 1402 Obj = BFieldPlot()
1403 1403
1404 1404 Obj.plotBField(self.path4plotname,self.plotname0,dcos,alpha,nlon,nlat,self.dcosxrange,self.dcosyrange,ObjB.heights,ObjB.alpha_i)
1405 1405
1406 1406 if self.show_object[0]>1:
1407 1407
1408 1408 Bhei = 0
1409 1409
1410 1410 dcosx = Obj.alpha_location[:,0,Bhei]
1411 1411
1412 1412 dcosy = Obj.alpha_location[:,1,Bhei]
1413 1413
1414 1414 vect_ant = [dcosx,dcosy,numpy.sqrt(1.-(dcosx**2. + dcosy**2.))]
1415 1415
1416 1416 vect_ant = numpy.array(vect_ant)
1417 1417
1418 1418 vect_geo = numpy.dot(scipy.linalg.inv(self.MT3),vect_ant)
1419 1419
1420 1420 vect_geo = numpy.array(vect_geo).transpose()
1421 1421
1422 1422 vect_polar = Misc_Routines.Vector(vect_geo,direction=1).Polar2Rect()
1423 1423
1424 [ra,dec,ha] = Astro_Coords.AltAz(vect_polar[1,:],vect_polar[0,:],self.junkjd).change2equatorial()
1424 [ra,dec,ha] = AltAz(vect_polar[1,:],vect_polar[0,:],self.junkjd).change2equatorial()
1425 1425
1426 1426 val = numpy.where(ha>=180)
1427 1427
1428 1428 if val[0].size>0:ha[val] = ha[val] -360.
1429 1429
1430 1430 val = numpy.where(numpy.abs(ha)<=self.maxphi)
1431 1431
1432 1432 if val[0].size>2:
1433 1433
1434 1434 self.dcosx_mag = dcosx[val]
1435 1435
1436 1436 self.dcosy_mag = dcosy[val]
1437 1437
1438 1438 self.ha_mag = ha[val]
1439 1439
1440 1440 self.time_mag = 0
1441 1441
1442 1442 def plotCelestial(self):
1443 1443
1444 1444 ntod = 24.*16.
1445 1445
1446 1446 tod = numpy.arange(ntod)/ntod*24.
1447 1447
1448 1448 [month,dom] = Doy2Date(self.year,self.doy).change2date()
1449 1449
1450 1450 jd = Time(self.year,month,dom,tod+self.UT).change2julday()
1451 1451
1452 1452 if numpy.sum(self.show_object[1:]>0)!=0:
1453 1453
1454 1454 self.ObjC = CelestialObjectsPlot(jd,self.main_dec,tod,self.maxha_min,self.show_object)
1455 1455
1456 1456 self.ObjC.drawObject(self.glat,
1457 1457 self.glon,
1458 1458 self.xg,
1459 1459 self.yg,
1460 1460 self.dcosxrange,
1461 1461 self.dcosyrange,
1462 1462 self.path4plotname,
1463 1463 self.plotname0)
1464 1464
1465 1465 def plotAntennaCuts(self):
1466 1466 # print "Drawing antenna cuts"
1467 1467
1468 1468 incha = 0.05 # min
1469 1469 nha = numpy.int32(2*self.maxha_min/incha) + 1.
1470 1470 newha = numpy.arange(nha)/nha*2.*self.maxha_min - self.maxha_min
1471 1471 nha_star = numpy.int32(200./incha)
1472 1472 star_ha = (numpy.arange(nha_star) - (nha_star/2))*nha_star
1473 1473
1474 1474 #Init ObjCut for PatternCutPlot()
1475 1475 view_objects = numpy.where(self.show_object>0)
1476 1476 subplots = len(view_objects[0])
1477 1477 ObjCut = PatternCutPlot(subplots)
1478 1478
1479 1479 for io in (numpy.arange(5)):
1480 1480 if self.show_object[io]==2:
1481 1481 if io==0:
1482 1482 if self.dcosx_mag.size!=0:
1483 1483 dcosx = self.dcosx_mag
1484 1484 dcosy = self.dcosy_mag
1485 1485 dcosz = 1 - numpy.sqrt(dcosx**2. + dcosy**2.)
1486 1486
1487 1487 # Finding rotation of B respec to antenna coords.
1488 1488 [mm,bb] = scipy.polyfit(dcosx,dcosy,1)
1489 1489 alfa = 0.0
1490 1490 theta = -1.*numpy.arctan(mm)
1491 1491 sina = numpy.sin(alfa); cosa = numpy.cos(alfa)
1492 1492 MT1 = [[1,0,0],[0,cosa,-sina],[0,sina,cosa]]
1493 1493 MT1 = numpy.array(MT1)
1494 1494 sinb = numpy.sin(theta); cosb = numpy.cos(theta)
1495 1495 MT2 = [[cosb,sinb,0],[-sinb,cosb,0],[0,0,1]]
1496 1496 MT2 = numpy.array(MT2)
1497 1497 MT3_mag = numpy.dot(MT2, MT1)
1498 1498 MT3_mag = numpy.array(MT3_mag).transpose()
1499 1499 # Getting dcos respec to B coords
1500 1500 vector = numpy.array([dcosx,dcosy,dcosz])
1501 1501 nvector = numpy.dot(MT3_mag,vector)
1502 1502 nvector = numpy.array(nvector).transpose()
1503 1503
1504 1504 ## print 'Rotation (deg) %f'%(theta/Misc_Routines.CoFactors.d2r)
1505 1505
1506 1506 yoffset = numpy.sum(nvector[:,1])/nvector[:,1].size
1507 1507 # print 'Dcosyoffset %f'%(yoffset)
1508 1508
1509 1509 ha = self.ha_mag*4.
1510 1510 time = self.time_mag
1511 1511 width_star = 0.1 # half width in minutes
1512 1512 otitle = 'B Perp. cut'
1513 1513 # else:
1514 1514 # print "No B perp. over Observatory"
1515 1515 #
1516 1516 #
1517 1517 elif io==1:
1518 1518 if self.ObjC.dcosx_sun.size!=0:
1519 1519 dcosx = self.ObjC.dcosx_sun
1520 1520 dcosy = self.ObjC.dcosy_sun
1521 1521 ha = self.ObjC.ha_sun*4.0
1522 1522 time = self.ObjC.time_sun
1523 1523 width_star = 2. # half width in minutes
1524 1524 otitle = 'Sun cut'
1525 1525 # else:
1526 1526 # print "Sun is not passing over Observatory"
1527 1527
1528 1528 elif io==2:
1529 1529 if self.ObjC.dcosx_moon.size!=0:
1530 1530 dcosx = self.ObjC.dcosx_moon
1531 1531 dcosy = self.ObjC.dcosy_moon
1532 1532 ha = self.ObjC.ha_moon*4
1533 1533 time = self.ObjC.time_moon
1534 1534 m_distance = 404114.6 # distance to the Earth in km
1535 1535 m_diameter = 1734.4 # diameter in km.
1536 1536 width_star = numpy.arctan(m_distance/m_diameter)
1537 1537 width_star = width_star/2./CoFactors.d2r*4.
1538 1538 otitle = 'Moon cut'
1539 1539 # else:
1540 1540 # print "Moon is not passing over Observatory"
1541 1541
1542 1542 elif io==3:
1543 1543 if self.ObjC.dcosx_hydra.size!=0:
1544 1544 dcosx = self.ObjC.dcosx_hydra
1545 1545 dcosy = self.ObjC.dcosy_hydra
1546 1546 ha = self.ObjC.ha_hydra*4.
1547 1547 time = self.ObjC.time_hydra
1548 1548 width_star = 0.25 # half width in minutes
1549 1549 otitle = 'Hydra cut'
1550 1550 # else:
1551 1551 # print "Hydra is not passing over Observatory"
1552 1552
1553 1553 elif io==4:
1554 1554 if self.ObjC.dcosx_galaxy.size!=0:
1555 1555 dcosx = self.ObjC.dcosx_galaxy
1556 1556 dcosy = self.ObjC.dcosy_galaxy
1557 1557 ha = self.ObjC.ha_galaxy*4.
1558 1558 time = self.ObjC.time_galaxy
1559 1559 width_star = 25. # half width in minutes
1560 1560 otitle = 'Galaxy cut'
1561 1561 # else:
1562 1562 # print "Galaxy center is not passing over Jicamarca"
1563 1563 #
1564 1564 #
1565 1565 hour = numpy.int32(time)
1566 1566 mins = numpy.int32((time - hour)*60.)
1567 1567 secs = numpy.int32(((time - hour)*60. - mins)*60.)
1568 1568
1569 1569 ObjT = Time(self.year,self.month,self.dom,hour,mins,secs)
1570 1570 subtitle = ObjT.change2strdate()
1571 1571
1572 1572 star_cut = numpy.exp(-(star_ha/width_star)**2./2.)
1573 1573
1574 1574 pol = scipy.polyfit(ha,dcosx,3.)
1575 1575 polx = numpy.poly1d(pol); newdcosx = polx(newha)
1576 1576 pol = scipy.polyfit(ha,dcosy,3.)
1577 1577 poly = numpy.poly1d(pol);newdcosy = poly(newha)
1578 1578
1579 1579 patterns = []
1580 1580 for icut in numpy.arange(self.pattern.size):
1581 1581 # Getting Antenna cut.
1582 1582 Obj = JroPattern(dcosx=newdcosx,
1583 1583 dcosy=newdcosy,
1584 1584 getcut=1,
1585 1585 pattern=self.pattern[icut],
1586 1586 path=self.path,
1587 1587 filename=self.filename[icut])
1588 1588
1589 1589 Obj.getPattern()
1590 1590
1591 1591 patterns.append(Obj.pattern)
1592 1592
1593 1593
1594 1594 ObjCut.drawCut(io,
1595 1595 patterns,
1596 1596 self.pattern.size,
1597 1597 newha,
1598 1598 otitle,
1599 1599 subtitle,
1600 1600 self.ptitle)
1601 1601
1602 1602 ObjCut.saveFig(self.path4plotname,self.plotname1)
1603 1603
1604 1604 def plotSkyNoise(self):
1605 1605 # print 'Creating SkyNoise map over Jicamarca'
1606 1606 dom = self.dom
1607 1607 month = self.month
1608 1608 year = self.year
1609 1609
1610 1610 julian = Time(year,month,dom).change2julday()
1611 1611
1612 [powr,time, lst] = Astro_Coords.CelestialBodies().skyNoise(julian)
1612 [powr,time, lst] = CelestialBodies().skyNoise(julian)
1613 1613
1614 1614 SkyNoisePlot([year,month,dom],powr,time,lst).getPlot(self.path4plotname,self.plotname2)
1615 1615
1616 1616
1617 1617 def outputHead(self,title):
1618 1618 print ("Content-Type: text/html")
1619 1619 print (self).scriptHeaders = 1
1620 1620 print ('<html>')
1621 1621 print ('<head>')
1622 1622 print ('\t<title>' + title + '</title>')
1623 1623 print ('<style type="text/css">')
1624 1624 print ('body')
1625 1625 print ('{')
1626 1626 print ('background-color:#ffffff;')
1627 1627 print ('}')
1628 1628 print ('h1')
1629 1629 print ('{')
1630 1630 print ('color:black;')
1631 1631 print ('font-size:18px;')
1632 1632 print ('text-align:center;')
1633 1633 print ('}')
1634 1634 print ('p')
1635 1635 print ('{')
1636 1636 print ('font-family:"Arial";')
1637 1637 print ('font-size:16px;')
1638 1638 print ('color:black;')
1639 1639 print ('}')
1640 1640 print ('</style>')
1641 1641 # self.printJavaScript()
1642 1642 print ('</head>')
1643 1643
1644 1644 def printJavaScript(self):
1645 1645 print
1646 1646
1647 1647 def printBody(self):
1648 1648 print ('<body>')
1649 1649 # print '<h1>Test Input Parms</h1>'
1650 1650 # for key in self.madForm.keys():
1651 1651 # #print '<p> name=' + str(key)
1652 1652 # if type(self.madForm.getvalue(key)) == types.ListType:
1653 1653 # for value in self.madForm.getvalue(key):
1654 1654 # print '<p> name=' + str(key) + \
1655 1655 # ' value=' + value + ''
1656 1656 # else:
1657 1657 # print '<p> name=' + str(key) + \
1658 1658 # ' value=' + str(cgi.escape(self.madForm.getvalue(key))) + ''
1659 1659
1660 1660 print ('<form name="form1" method="post" target="showFrame">')
1661 1661 print (' <div align="center">')
1662 1662 print (' <table width=98% border="1" cellpadding="1">')
1663 1663 print (' <tr>')
1664 1664 print (' <td colspan="2" align="center">')
1665 1665 if self.showType == 0:
1666 1666 print (' <IMG SRC="%s" BORDER="0" >')%(os.path.join(os.sep + self.__tmpDir,self.plotname0))
1667 1667 if self.showType == 1:
1668 1668 print (' <IMG SRC="%s" BORDER="0" >')%(os.path.join(os.sep + self.__tmpDir,self.plotname1))
1669 1669 if self.showType == 2:
1670 1670 print (' <IMG SRC="%s" BORDER="0" >')%(os.path.join(os.sep + self.__tmpDir,self.plotname2))
1671 1671 print (' </td>')
1672 1672 print (' </tr>')
1673 1673 print (' </table>')
1674 1674 print (' </div>')
1675 1675 print ('</form>')
1676 1676
1677 1677 print ('</body>')
1678 1678 print ('</html>')
1679 1679
1680 1680 #def execute(self, serverdocspath, tmpdir, currentdate, finalpath, showType=0, maxphi=5.0, objects="[1,1]", heights="[150,500,1000]"):
1681 1681 def setInputParameters(self, serverpath, currentdate, finalpath, showType=0, maxphi=5.0, objects="[1,1]", heights="[150,500,1000]"):
1682 1682 self.objects=[]
1683 1683 self.heights=[]
1684 1684 #self.__serverdocspath = serverdocspath
1685 1685 self.__serverdocspath = os.path.split(serverpath)[0]
1686 1686 #self.__tmpDir = tmpdir
1687 1687 self.__tmpDir = os.path.split(serverpath)[1]
1688 1688 self.showType = int(showType)
1689 1689 self.year = int(currentdate.strftime("%Y")) # Get year of currentdate
1690 1690 self.month = int(currentdate.strftime("%m")) # Get month of currentdate
1691 1691 self.dom = int(currentdate.strftime("%d")) # Get day of currentdate
1692 1692 self.filename = os.path.split(finalpath)[1]
1693 1693 self.path = os.path.split(finalpath)[0]
1694 1694 self.maxphi = float(maxphi)
1695 1695
1696 1696 tmp_objects = (objects.replace("[","")).replace("]","")
1697 1697 for s in tmp_objects.split(','):
1698 1698 self.objects.append(int(s))
1699 1699
1700 1700 tmp_heights = (heights.replace("[","")).replace("]","")
1701 1701 for s in tmp_heights.split(','):
1702 1702 self.heights.append(float(s))
1703 1703 self.heights = numpy.array(self.heights)
1704 1704
1705 1705 def setupParameters(self):
1706 1706 self.initParameters()
1707 1707
1708 1708 def initParametersCGI(self):
1709 1709 self.setScriptState()
1710 1710 self.initParameters()
1711 1711
1712 1712 def execute(self):
1713 1713 if self.showType == 0 or self.showType == 1:
1714 1714 self.initParameters1()
1715 1715 self.plotPattern()
1716 1716
1717 1717 if numpy.sum(self.show_object>0) != 0:
1718 1718 self.plotBfield()
1719 1719 self.plotCelestial()
1720 1720
1721 1721 if numpy.sum(self.show_object>1) != 0:
1722 1722 self.plotAntennaCuts()
1723 1723
1724 1724 if self.showType == 2:
1725 1725 self.plotSkyNoise()
1726 1726
1727 1727 def getPlot(self):
1728 1728
1729 1729 return os.path.join(self.__serverdocspath,self.__tmpDir,self.plotname0)
1730 1730
1731 1731
1732 1732 if __name__ == '__main__':
1733 1733
1734 1734 # Script overJroShow.py
1735 1735 # This script only calls the init function of the class overJroShow()
1736 1736 # All work is done by the init function
1737 1737
1738 1738 phases = numpy.array([[2.0,0.0,1.5,1.5,1.0,1.0,1.0,0.5],
1739 1739 [2.0,2.5,2.5,3.5,0.5,1.0,1.0,1.0],
1740 1740 [2.5,2.5,1.0,1.0,0.5,0.5,0.5,0.5],
1741 1741 [1.0,1.0,1.0,1.0,0.5,0.5,0.5,1.0],
1742 1742 [0.5,0.5,0.5,0.5,0.5,0.0,0.0,0.0],
1743 1743 [0.5,0.5,1.0,0.5,0.0,0.0,0.0,0.0],
1744 1744 [0.5,0.5,0.5,1.0,0.0,0.0,0.0,0.0],
1745 1745 [0.5,0.5,0.5,0.5,0.0,0.0,0.0,0.0]])
1746 1746
1747 1747 gain_tx = numpy.array([[0,0,0,0,0,0,0,0],
1748 1748 [0,0,0,0,0,0,0,0],
1749 1749 [0,0,0,0,0,0,0,0],
1750 1750 [0,0,0,0,0,0,0,0],
1751 1751 [0,0,0,0,1,1,1,1],
1752 1752 [0,0,0,0,0,0,0,0],
1753 1753 [0,0,0,0,0,0,0,0],
1754 1754 [0,0,0,0,0,0,0,0]])
1755 1755
1756 1756 gain_rx = numpy.array([[0,0,0,0,0,0,0,0],
1757 1757 [0,0,1,0,0,0,0,0],
1758 1758 [0,0,1,0,0,0,0,0],
1759 1759 [0,0,0,0,0,0,0,0],
1760 1760 [0,0,0,0,0,0,0,0],
1761 1761 [0,0,0,0,0,0,0,0],
1762 1762 [0,0,0,0,0,0,0,0],
1763 1763 [0,0,0,0,0,0,0,0]])
1764 1764
1765 1765 jro = overJroShow()
1766 1766
1767 1767 fig = jro.plotPattern2(datetime.datetime.today(),
1768 1768 phases=phases,
1769 1769 gain_tx=gain_tx,
1770 1770 gain_rx=gain_rx,
1771 1771 ues=numpy.array([0.0,0.0,0.0,0.0]),
1772 1772 just_rx=0)
1773 1773
1774 1774 fig.savefig('./pat.png')
1775 1775
@@ -1,1042 +1,1047
1
2
3 1 import ast
4 2 import json
5 3 import requests
6 4 import numpy as np
5 import time
7 6 from base64 import b64encode
8 7 from struct import pack
9 8
10 9 from django.db import models
11 10 from django.urls import reverse
12 11 from django.core.validators import MinValueValidator, MaxValueValidator
13 12
14 13 from apps.main.models import Configuration
15 14 from apps.main.utils import Params
16 15 from devices.rc import api
17 16 from apps.rc.utils import RCFile
18 17
19 18
20 19 LINE_TYPES = (
21 20 ('none', 'Not used'),
22 21 ('tr', 'Transmission/reception selector signal'),
23 22 ('tx', 'A modulating signal (Transmission pulse)'),
24 23 ('codes', 'BPSK modulating signal'),
25 24 ('windows', 'Sample window signal'),
26 25 ('sync', 'Synchronizing signal'),
27 26 ('flip', 'IPP related periodic signal'),
28 27 ('prog_pulses', 'Programmable pulse'),
29 28 ('mix', 'Mixed line'),
30 29 )
31 30
32 31
33 32 SAMPLING_REFS = (
34 33 ('none', 'No Reference'),
35 34 ('begin_baud', 'Begin of the first baud'),
36 35 ('first_baud', 'Middle of the first baud'),
37 36 ('sub_baud', 'Middle of the sub-baud')
38 37 )
39 38
40 39 DAT_CMDS = {
41 40 # Pulse Design commands
42 41 'DISABLE' : 0, # Disables pulse generation
43 42 'ENABLE' : 24, # Enables pulse generation
44 43 'DELAY_START' : 40, # Write delay status to memory
45 44 'FLIP_START' : 48, # Write flip status to memory
46 45 'SAMPLING_PERIOD' : 64, # Establish Sampling Period
47 46 'TX_ONE' : 72, # Output '0' in line TX
48 47 'TX_ZERO' : 88, # Output '0' in line TX
49 48 'SW_ONE' : 104, # Output '0' in line SW
50 49 'SW_ZERO' : 112, # Output '1' in line SW
51 50 'RESTART': 120, # Restarts CR8 Firmware
52 51 'CONTINUE' : 253, # Function Unknown
53 52 # Commands available to new controllers
54 53 # 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 54 'CLOCK_DIVISOR_INIT' : 12, # Specifies Clock Divisor. Legacy command, ignored in the actual .dat conversion
56 55 'CLOCK_DIVISOR_LAST' : 22, # Specifies Clock Divisor (default 60 if not included) syntax: 255,22 254,N-1.
57 56 'CLOCK_DIVIDER' : 8,
58 57 }
59 58
60 59 MAX_BITS = 8
61 60
62 61 # Rotate left: 0b1001 --> 0b0011
63 62 rol = lambda val, r_bits: \
64 63 (val << r_bits%MAX_BITS) & (2**MAX_BITS-1) | \
65 64 ((val & (2**MAX_BITS-1)) >> (MAX_BITS-(r_bits%MAX_BITS)))
66 65
67 66 # Rotate right: 0b1001 --> 0b1100
68 67 ror = lambda val, r_bits: \
69 68 ((val & (2**MAX_BITS-1)) >> r_bits%MAX_BITS) | \
70 69 (val << (MAX_BITS-(r_bits%MAX_BITS)) & (2**MAX_BITS-1))
71 70
72 71
73 72 class RCConfiguration(Configuration):
74 73
75 74 ipp = models.FloatField(verbose_name='IPP [Km]', validators=[MinValueValidator(1)], default=300)
76 75 ntx = models.PositiveIntegerField(verbose_name='Number of TX', validators=[MinValueValidator(1)], default=1)
77 76 clock_in = models.FloatField(verbose_name='Clock in [MHz]', validators=[MinValueValidator(1), MaxValueValidator(80)], default=1)
78 77 clock_divider = models.PositiveIntegerField(verbose_name='Clock divider', validators=[MinValueValidator(1), MaxValueValidator(256)], default=1)
79 78 clock = models.FloatField(verbose_name='Clock Master [MHz]', blank=True, default=1)
80 79 time_before = models.PositiveIntegerField(verbose_name='Time before [&mu;S]', default=12)
81 80 time_after = models.PositiveIntegerField(verbose_name='Time after [&mu;S]', default=1)
82 81 sync = models.PositiveIntegerField(verbose_name='Synchro delay', default=0)
83 82 sampling_reference = models.CharField(verbose_name='Sampling Reference', choices=SAMPLING_REFS, default='none', max_length=40)
84 83 control_tx = models.BooleanField(verbose_name='Control Switch TX', default=False)
85 84 control_sw = models.BooleanField(verbose_name='Control Switch SW', default=False)
86 85 total_units = models.PositiveIntegerField(default=0)
87 86 mix = models.BooleanField(default=False)
88 87
89 88 class Meta:
90 89 db_table = 'rc_configurations'
91 90
92 91 def get_absolute_url_plot(self):
93 92 return reverse('url_plot_rc_pulses', args=[str(self.id)])
94 93
95 94 @property
96 95 def ipp_unit(self):
97 96
98 97 return '{} ({})'.format(self.ipp, int(self.ipp*self.km2unit))
99 98
100 99 @property
101 100 def us2unit(self):
102 101
103 102 return self.clock_in/self.clock_divider
104 103
105 104 @property
106 105 def km2unit(self):
107 106
108 107 return 20./3*(self.clock_in/self.clock_divider)
109 108
110 109 def clone(self, **kwargs):
111 110
112 111 lines = self.get_lines()
113 112 self.pk = None
114 113 self.id = None
115 114 for attr, value in kwargs.items():
116 115 setattr(self, attr, value)
117 116 self.save()
118 117
119 118 for line in lines:
120 119 line.clone(rc_configuration=self)
121 120
122 121 new_lines = self.get_lines()
123 122 for line in new_lines:
124 123 line_params = json.loads(line.params)
125 124 if 'TX_ref' in line_params and (line_params['TX_ref'] != '0'):
126 125 ref_line = RCLine.objects.get(pk=line_params['TX_ref'])
127 126 line_params['TX_ref'] = ['{}'.format(l.pk) for l in new_lines if l.get_name()==ref_line.get_name()][0]
128 127 line.params = json.dumps(line_params)
129 128 line.save()
130 129
131 130 return self
132 131
133 132 def get_lines(self, **kwargs):
134 133 '''
135 134 Retrieve configuration lines
136 135 '''
137 136
138 137 return RCLine.objects.filter(rc_configuration=self.pk, **kwargs)
139 138
140 139
141 140 def clean_lines(self):
142 141 '''
143 142 '''
144 143
145 144 empty_line = RCLineType.objects.get(name='none')
146 145
147 146 for line in self.get_lines():
148 147 line.line_type = empty_line
149 148 line.params = '{}'
150 149 line.save()
151 150
152 151 def dict_to_parms(self, params, id=None):
153 152 '''
154 153 '''
155 154
156 155 if id:
157 156 data = Params(params).get_conf(id_conf=id)
158 157 else:
159 158 data = Params(params).get_conf(dtype='rc')
160 159
161 160 #print(data)
162 161 # self.name = data['name']
163 162 self.ipp = data['ipp']
164 163 self.ntx = data['ntx']
165 164 self.clock_in = data['clock_in']
166 165 self.clock_divider = data['clock_divider']
167 166 self.clock = data['clock']
168 167 self.time_before = data['time_before']
169 168 self.time_after = data['time_after']
170 169 self.sync = data['sync']
171 170 self.sampling_reference = data['sampling_reference']
172 171 self.total_units = self.ipp*self.ntx*self.km2unit
173 172 self.save()
174 173 self.clean_lines()
175 174
176 175 #print(params)
177 176
178 177 positions = {'tx':0, 'tr':0}
179 178 for i, id in enumerate(data['lines']):
180 179 line_data = params['lines']['byId'][id]
181 180 line_type = RCLineType.objects.get(name=line_data['line_type'])
182 181 if line_type.name == 'codes':
183 182 code = RCLineCode.objects.get(name=line_data['params']['code'])
184 183 line_data['params']['code'] = code.pk
185 184 if line_type.name == 'tx':
186 185 position = positions['tx']
187 186 positions['tx'] += 1
188 187 elif line_type.name == 'tr':
189 188 position = positions['tr']
190 189 positions['tr'] += 1
191 190 else:
192 191 position = 0
193 192 line, dum = RCLine.objects.update_or_create(
194 193 rc_configuration=self,
195 194 channel=i,
196 195 position=position,
197 196 defaults={
198 197 'line_type': line_type,
199 198 'params': json.dumps(line_data['params'])
200 199 }
201 200 )
202 201
203 202 for i, line in enumerate(self.get_lines()):
204 203 line_params = json.loads(line.params)
205 204 if 'TX_ref' in line_params:
206 205 if line_params['TX_ref'] in (0, '0'):
207 206 line_params['TX_ref'] = '0'
208 207 else:
209 208 ref_id = '{}'.format(line_params['TX_ref'])
210 209 ref_line = params['lines']['byId'][ref_id]
211 210 line_params['TX_ref'] = RCLine.objects.get(
212 211 rc_configuration=self,
213 212 params=json.dumps(ref_line['params'])
214 213 ).pk
215 214 line.params = json.dumps(line_params)
216 215 print(line.params)
217 216 line.save()
218 217 print("Fin de dict to param")
219 218
220 219 def get_delays(self):
221 220
222 221 pulses = [line.pulses_as_points() for line in self.get_lines()]
223 222 points = [tup for tups in pulses for tup in tups]
224 223 points = set([x for tup in points for x in tup])
225 224 points = list(points)
226 225 points.sort()
227 226
228 227 if points[0]!=0:
229 228 points.insert(0, 0)
230 229
231 230 return [points[i+1]-points[i] for i in range(len(points)-1)]
232 231
233 232
234 233 def get_pulses(self, binary=True):
235 234
236 235 pulses = [line.pulses_as_points() for line in self.get_lines()]
237 236 tuples = [tup for tups in pulses for tup in tups]
238 237 points = set([x for tup in tuples for x in tup])
239 238 points = list(points)
240 239 points.sort()
241 240 states = []
242 241 last = [0 for x in pulses]
243 242
244 243 for x in points:
245 244 dum = []
246 245 for i, tups in enumerate(pulses):
247 246 ups = [tup[0] for tup in tups if tup!=(0,0)]
248 247 dws = [tup[1] for tup in tups if tup!=(0,0)]
249 248 if x in ups:
250 249 dum.append(1)
251 250 elif x in dws:
252 251 dum.append(0)
253 252 else:
254 253 dum.append(last[i])
255 254 states.append(dum)
256 255 last = dum
257 256
258 257 if binary:
259 258 ret = []
260 259 for flips in states:
261 260 flips.reverse()
262 261 ret.append(int(''.join([str(x) for x in flips]), 2))
263 262 states = ret
264 263
265 264 return states[:-1]
266 265
267 266 def add_cmd(self, cmd):
268 267
269 268 if cmd in DAT_CMDS:
270 269 return (255, DAT_CMDS[cmd])
271 270
272 271 def add_data(self, value):
273 272
274 273 return (254, value-1)
275 274
276 275 def parms_to_binary(self, dat=True):
277 276 '''
278 277 Create "dat" stream to be send to CR
279 278 '''
280 279
281 280 data = bytearray()
282 281 # create header
283 282 data.extend(self.add_cmd('DISABLE'))
284 283 data.extend(self.add_cmd('CONTINUE'))
285 284 data.extend(self.add_cmd('RESTART'))
286 285
287 286 if self.control_sw:
288 287 data.extend(self.add_cmd('SW_ONE'))
289 288 else:
290 289 data.extend(self.add_cmd('SW_ZERO'))
291 290
292 291 if self.control_tx:
293 292 data.extend(self.add_cmd('TX_ONE'))
294 293 else:
295 294 data.extend(self.add_cmd('TX_ZERO'))
296 295
297 296 # write divider
298 297 data.extend(self.add_cmd('CLOCK_DIVIDER'))
299 298 data.extend(self.add_data(self.clock_divider))
300 299
301 300 # write delays
302 301 data.extend(self.add_cmd('DELAY_START'))
303 302 # first delay is always zero
304 303 data.extend(self.add_data(1))
305 304
306 305 delays = self.get_delays()
307 306
308 307 for delay in delays:
309 308 while delay>252:
310 309 data.extend(self.add_data(253))
311 310 delay -= 253
312 311 data.extend(self.add_data(int(delay)))
313 312
314 313 # write flips
315 314 data.extend(self.add_cmd('FLIP_START'))
316 315
317 316 states = self.get_pulses(binary=True)
318 317
319 318
320 319 last = 0
321 320 for flip, delay in zip(states, delays):
322 321 data.extend(self.add_data((flip^last)+1))
323 322 last = flip
324 323 while delay>252:
325 324 data.extend(self.add_data(1))
326 325 delay -= 253
327 326
328 327 # write sampling period
329 328 data.extend(self.add_cmd('SAMPLING_PERIOD'))
330 329 wins = self.get_lines(line_type__name='windows')
331 330 if wins:
332 331 win_params = json.loads(wins[0].params)['params']
333 332 if win_params:
334 333 dh = int(win_params[0]['resolution']*self.km2unit)
335 334 else:
336 335 dh = 1
337 336 else:
338 337 dh = 1
339 338 data.extend(self.add_data(dh))
340 339
341 340 # write enable
342 341 data.extend(self.add_cmd('ENABLE'))
343 342
344 343 if not dat:
345 344 return data
346 345
347 346 return '\n'.join(['{}'.format(x) for x in data])
348 347
349 348 def update_pulses(self):
350 349 contador = 0
351 350 for line in self.get_lines():
352 351 contador=contador+1
353 352 print(contador)
354 353 line.update_pulses()
355 354
356 355 def plot_pulses2(self, km=False):
357 356
358 357 import matplotlib
359 358 matplotlib.use('Agg')
360 359 import matplotlib.pyplot as plt
361 360 from bokeh.resources import CDN
362 361 from bokeh.embed import components
363 362 from bokeh.mpl import to_bokeh
364 363 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, HoverTool, SaveTool
365 364
366 365 lines = self.get_lines()
367 366
368 367 N = len(lines)
369 368 npoints = self.total_units/self.km2unit if km else self.total_units
370 369 fig = plt.figure(figsize=(12, 2+N*0.5))
371 370 ax = fig.add_subplot(111)
372 371 labels = ['IPP']
373 372
374 373 for i, line in enumerate(lines):
375 374 labels.append(line.get_name(channel=True))
376 375 l = ax.plot((0, npoints),(N-i-1, N-i-1))
377 376 points = [(tup[0], tup[1]-tup[0]) for tup in line.pulses_as_points(km=km) if tup!=(0,0)]
378 377 ax.broken_barh(points, (N-i-1, 0.5),
379 378 edgecolor=l[0].get_color(), facecolor='none')
380 379
381 380 n = 0
382 381 f = ((self.ntx+50)/100)*5 if ((self.ntx+50)/100)*10>0 else 2
383 382 for x in np.arange(0, npoints, self.ipp if km else self.ipp*self.km2unit):
384 383 if n%f==0:
385 384 ax.text(x, N, '%s' % n, size=10)
386 385 n += 1
387 386
388 387 labels.reverse()
389 388 ax.set_yticks(range(len(labels)))
390 389 ax.set_yticklabels(labels)
391 390 ax.set_xlabel = 'Units'
392 391 plot = to_bokeh(fig, use_pandas=False)
393 392 plot.tools = [PanTool(dimensions="width"), WheelZoomTool(dimensions="width"), ResetTool(), SaveTool()]
394 393 plot.toolbar_location="above"
395 394
396 395 return components(plot, CDN)
397 396
398 397 def plot_pulses(self, km=False):
399 398
400 399 from bokeh.plotting import figure
401 400 from bokeh.resources import CDN
402 401 from bokeh.embed import components
403 402 from bokeh.models import FixedTicker, PrintfTickFormatter
404 403 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, HoverTool, SaveTool
405 404 from bokeh.models.sources import ColumnDataSource
406 405
407 406 lines = self.get_lines().reverse()
408 407
409 408 N = len(lines)
410 409 npoints = self.total_units/self.km2unit if km else self.total_units
411 410 ipp = self.ipp if km else self.ipp*self.km2unit
412 411
413 412 hover = HoverTool(tooltips=[("Line", "@name"),
414 413 ("IPP", "@ipp"),
415 414 ("X", "@left")])
416 415
417 416 tools = [PanTool(dimensions="width"),
418 417 WheelZoomTool(dimensions="width"),
419 418 hover, SaveTool()]
420 419
421 420 plot = figure(width=1000,
422 421 height=40+N*50,
423 422 y_range = (0, N),
424 423 tools=tools,
425 424 toolbar_location='above',
426 425 toolbar_sticky=False,)
427 426
428 427 plot.xaxis.axis_label = 'Km' if km else 'Units'
429 428 plot.xaxis[0].formatter = PrintfTickFormatter(format='%d')
430 429 plot.yaxis.axis_label = 'Pulses'
431 430 plot.yaxis[0].ticker=FixedTicker(ticks=list(range(N)))
432 431 plot.yaxis[0].formatter = PrintfTickFormatter(format='Line %d')
433 432
434 433 for i, line in enumerate(lines):
435 434
436 435 points = [tup for tup in line.pulses_as_points(km=km) if tup!=(0,0)]
437 436
438 437 source = ColumnDataSource(data = dict(
439 438 bottom = [i for tup in points],
440 439 top = [i+0.5 for tup in points],
441 440 left = [tup[0] for tup in points],
442 441 right = [tup[1] for tup in points],
443 442 ipp = [int(tup[0]/ipp) for tup in points],
444 443 name = [line.get_name() for tup in points]
445 444 ))
446 445
447 446 plot.quad(
448 447 bottom = 'bottom',
449 448 top = 'top',
450 449 left = 'left',
451 450 right = 'right',
452 451 source = source,
453 452 fill_alpha = 0,
454 453 #line_color = 'blue',
455 454 )
456 455
457 456 plot.line([0, npoints], [i, i])#, color='blue')
458 457
459 458 return components(plot, CDN)
460 459
461 460 def request(self, cmd, method='get', **kwargs):
462 461
463 462 req = getattr(requests, method)(self.device.url(cmd), **kwargs)
464 463 payload = req.json()
465 464
466 465 return payload
467 466
468 467 def status_device(self):
469 468
470 469 try:
471 470 self.device.status = 0
472 471 payload = self.request('status')
473 472 if payload['status']=='enable':
474 473 self.device.status = 3
475 474 elif payload['status']=='disable':
476 475 self.device.status = 2
477 476 else:
478 477 self.device.status = 1
479 478 self.device.save()
480 479 self.message = 'RC status: {}'.format(payload['status'])
481 480 return False
482 481 except Exception as e:
483 482 if 'No route to host' not in str(e):
484 483 self.device.status = 4
485 484 self.device.save()
486 485 self.message = 'RC status: {}'.format(str(e))
487 486 return False
488 487
489 488 self.device.save()
490 489 return True
491 490
492 491 def reset_device(self):
493 492
494 493 try:
495 494 payload = self.request('reset', 'post')
496 495 if payload['reset']=='ok':
497 496 self.message = 'RC restarted OK'
498 497 self.device.status = 2
499 498 self.device.save()
500 499 else:
501 500 self.message = 'RC restart fail'
502 501 self.device.status = 4
503 502 self.device.save()
504 503 except Exception as e:
505 504 self.message = 'RC reset: {}'.format(str(e))
506 505 return False
507 506
508 507 return True
509 508
510 509 def stop_device(self):
511 510
512 511 try:
513 512 payload = self.request('stop', 'post')
514 513 self.message = 'RC stop: {}'.format(payload['stop'])
515 514 if payload['stop']=='ok':
516 515 self.device.status = 2
517 516 self.device.save()
518 517 else:
519 518 self.device.status = 4
520 519 self.device.save()
521 520 return False
522 521 except Exception as e:
523 522 if 'No route to host' not in str(e):
524 523 self.device.status = 4
525 524 else:
526 525 self.device.status = 0
527 526 self.message = 'RC stop: {}'.format(str(e))
528 527 self.device.save()
529 528 return False
530 529
531 530 return True
532 531
533 532 def start_device(self):
534 533
535 534 try:
536 535 payload = self.request('start', 'post')
537 536 self.message = 'RC start: {}'.format(payload['start'])
538 537 if payload['start']=='ok':
539 538 self.device.status = 3
540 539 self.device.save()
541 540 else:
542 541 return False
543 542 except Exception as e:
544 543 if 'No route to host' not in str(e):
545 544 self.device.status = 4
546 545 else:
547 546 self.device.status = 0
548 547 self.message = 'RC start: {}'.format(str(e))
549 548 self.device.save()
550 549 return False
551 550
552 551 return True
553 552
554 553 def write_device(self, raw=False):
555 554 print("write device")
556 555
557 556 if not raw:
557 pass
558 '''
558 559 clock = RCClock.objects.get(rc_configuration=self)
559 560 if clock.mode:
560 561 data = {'default': clock.frequency}
561 562 else:
562 563 data = {'manual': [clock.multiplier, clock.divisor, clock.reference]}
563 564 payload = self.request('setfreq', 'post', data=json.dumps(data))
564 565 if payload['setfreq'] != 'ok':
565 566 self.message = 'RC write: {}'.format(payload['setfreq'])
566 567 else:
567 568 self.message = payload['setfreq']
568 569 if payload['setfreq'] == 'fail':
569 570 self.message = 'RC write: error programming CGS chip'
571 '''
570 572
571 573 values = []
574 print('ok')
572 575 for pulse, delay in zip(self.get_pulses(), self.get_delays()):
573 576 while delay > 65536:
574 577 values.append((pulse, 65535))
575 578 delay -= 65536
576 579 values.append((pulse, delay-1))
577 580 data = bytearray()
578 581 #reset
579 582 data.extend((128, 0))
580 583 #disable
581 584 data.extend((129, 0))
582 585 #SW switch
583 586 if self.control_sw:
584 587 data.extend((130, 2))
585 588 else:
586 589 data.extend((130, 0))
587 590 #divider
588 591 data.extend((131, self.clock_divider-1))
589 592 #enable writing
590 593 data.extend((139, 62))
591 594
592 595 last = 0
593 596 for tup in values:
594 597 vals = pack('<HH', last^tup[0], tup[1])
595 598 last = tup[0]
596 599 data.extend((133, vals[1], 132, vals[0], 133, vals[3], 132, vals[2]))
597 600
598 601 #enable
599 602 data.extend((129, 1))
600 603
601 604 if raw:
602 605 return b64encode(data)
603 606
604 607 #try:
605 608 payload = self.request('stop', 'post')
606 609 payload = self.request('reset', 'post')
607 610 #payload = self.request('divider', 'post', data={'divider': self.clock_divider-1})
608 611 #payload = self.request('write', 'post', data=b64encode(bytearray((139, 62))), timeout=20)
609 612 n = len(data)
610 613 x = 0
611 #while x < n:
612 payload = self.request('write', 'post', data=b64encode(data))
613 # x += 1024
614 while x < n:
615 payload = self.request('write', 'post', data=b64encode(data[x:x+1024]))
616 x += 1024
617 time.sleep(1)
618 print('writing... ', x)
614 619
615 620 if payload['write']=='ok':
616 621 self.device.status = 3
617 622 self.device.save()
618 623 self.message = 'RC configured and started'
619 624 else:
620 625 self.device.status = 1
621 626 self.device.save()
622 627 self.message = 'RC write: {}'.format(payload['write'])
623 628 return False
624 629
625 630 #payload = self.request('start', 'post')
626 631
627 632 #except Exception as e:
628 633 # if 'No route to host' not in str(e):
629 634 # self.device.status = 4
630 635 # else:
631 636 # self.device.status = 0
632 637 # self.message = 'RC write: {}'.format(str(e))
633 638 # self.device.save()
634 639 # return False
635 640
636 641 return True
637 642
638 643
639 644 def get_absolute_url_import(self):
640 645 return reverse('url_import_rc_conf', args=[str(self.id)])
641 646
642 647
643 648 class RCLineCode(models.Model):
644 649
645 650 name = models.CharField(max_length=40)
646 651 bits_per_code = models.PositiveIntegerField(default=0)
647 652 number_of_codes = models.PositiveIntegerField(default=0)
648 653 codes = models.TextField(blank=True, null=True)
649 654
650 655 class Meta:
651 656 db_table = 'rc_line_codes'
652 657 ordering = ('name',)
653 658
654 659 def __str__(self):
655 660 return u'%s' % self.name
656 661
657 662
658 663 class RCLineType(models.Model):
659 664
660 665 name = models.CharField(choices=LINE_TYPES, max_length=40)
661 666 description = models.TextField(blank=True, null=True)
662 667 params = models.TextField(default='[]')
663 668
664 669 class Meta:
665 670 db_table = 'rc_line_types'
666 671
667 672 def __str__(self):
668 673 return u'%s - %s' % (self.name.upper(), self.get_name_display())
669 674
670 675
671 676 class RCLine(models.Model):
672 677
673 678 rc_configuration = models.ForeignKey('RCConfiguration', on_delete=models.CASCADE)
674 679 line_type = models.ForeignKey('RCLineType',on_delete=models.CASCADE)
675 680 channel = models.PositiveIntegerField(default=0)
676 681 position = models.PositiveIntegerField(default=0)
677 682 params = models.TextField(default='{}')
678 683 pulses = models.TextField(default='')
679 684
680 685 class Meta:
681 686 db_table = 'rc_lines'
682 687 ordering = ['channel']
683 688
684 689 def __str__(self):
685 690 if self.rc_configuration:
686 691 return u'{}|{} - {}'.format(self.pk, self.get_name(), self.rc_configuration.name)
687 692
688 693 def jsonify(self):
689 694
690 695 data = {}
691 696 data['params'] = json.loads(self.params)
692 697 data['id'] = '{}'.format(self.pk)
693 698 data['line_type'] = self.line_type.name
694 699 data['name'] = self.get_name()
695 700 if data['line_type']=='codes':
696 701 data['params']['code'] = RCLineCode.objects.get(pk=data['params']['code']).name
697 702
698 703 return data
699 704
700 705
701 706 def clone(self, **kwargs):
702 707
703 708 self.pk = None
704 709 self.id = None
705 710
706 711 for attr, value in kwargs.items():
707 712 setattr(self, attr, value)
708 713
709 714 self.save()
710 715
711 716 return self
712 717
713 718 def get_name(self, channel=False):
714 719
715 720 chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
716 721 s = ''
717 722
718 723 if self.line_type.name in ('tx',):
719 724 s = chars[self.position]
720 725 elif self.line_type.name in ('codes', 'windows', 'tr'):
721 726 if 'TX_ref' in json.loads(self.params):
722 727 pk = json.loads(self.params)['TX_ref']
723 728 if pk in (0, '0'):
724 729 s = ','.join(chars[l.position] for l in self.rc_configuration.get_lines(line_type__name='tx'))
725 730 else:
726 731 ref = RCLine.objects.get(pk=pk)
727 732 s = chars[ref.position]
728 733 s = '({})'.format(s)
729 734
730 735 s = '{}{}'.format(self.line_type.name.upper(), s)
731 736
732 737 if channel:
733 738 return '{} {}'.format(s, self.channel)
734 739 else:
735 740 return s
736 741
737 742 def get_lines(self, **kwargs):
738 743
739 744 return RCLine.objects.filter(rc_configuration=self.rc_configuration, **kwargs)
740 745
741 746 def pulses_as_array(self):
742 747
743 748 y = np.zeros(self.rc_configuration.total_units)
744 749
745 750 for tup in ast.literal_eval(self.pulses):
746 751 y[tup[0]:tup[1]] = 1
747 752
748 753 return y.astype(np.int8)
749 754
750 755 def pulses_as_points(self, km=False):
751 756
752 757 if km:
753 758 unit2km = 1/self.rc_configuration.km2unit
754 759 return [(tup[0]*unit2km, tup[1]*unit2km) for tup in ast.literal_eval(self.pulses)]
755 760 else:
756 761 return ast.literal_eval(self.pulses)
757 762
758 763 def get_win_ref(self, params, tx_id, km2unit):
759 764
760 765 ref = self.rc_configuration.sampling_reference
761 766 codes = [line for line in self.get_lines(line_type__name='codes') if int(json.loads(line.params)['TX_ref'])==int(tx_id)]
762 767
763 768 if codes:
764 769 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit/len(json.loads(codes[0].params)['codes'][0])
765 770 else:
766 771 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit
767 772
768 773 if ref=='first_baud':
769 774 return int(1 + round((tx_width + 1)/2 + params['first_height']*km2unit - params['resolution']*km2unit))
770 775 elif ref=='sub_baud':
771 776 return np.ceil(1 + params['first_height']*km2unit - params['resolution']*km2unit/2)
772 777 else:
773 778 return 0
774 779
775 780 def update_pulses(self):
776 781 '''
777 782 Update pulses field
778 783 '''
779 784
780 785 km2unit = self.rc_configuration.km2unit
781 786 us2unit = self.rc_configuration.us2unit
782 787 ipp = self.rc_configuration.ipp
783 788 ntx = int(self.rc_configuration.ntx)
784 789 ipp_u = int(ipp*km2unit)
785 790 total = ipp_u*ntx if self.rc_configuration.total_units==0 else self.rc_configuration.total_units
786 791 y = []
787 792
788 793 if self.line_type.name=='tr':
789 794 tr_params = json.loads(self.params)
790 795 #print(tr_params)
791 796 #print(tr_params['TX_ref'])
792 797 if tr_params['TX_ref'] in ('0', 0):
793 798 txs = self.get_lines(line_type__name='tx')
794 799 else:
795 800 txs = RCLine.objects.filter(pk=tr_params['TX_ref'])
796 801
797 802 for tx in txs:
798 803 params = json.loads(tx.params)
799 804
800 805 if float(params['pulse_width'])==0:
801 806 continue
802 807 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
803 808 width = float(params['pulse_width'])*km2unit+int(self.rc_configuration.time_before*us2unit)
804 809 before = 0
805 810 after = int(self.rc_configuration.time_after*us2unit)
806 811
807 812 y_tx = self.points(ntx, ipp_u, width,
808 813 delay=delays,
809 814 before=before,
810 815 after=after,
811 816 sync=self.rc_configuration.sync)
812 817
813 818 ranges = params['range'].split(',')
814 819
815 820 if len(ranges)>0 and ranges[0]!='0':
816 821 y_tx = self.mask_ranges(y_tx, ranges)
817 822
818 823 tr_ranges = tr_params['range'].split(',')
819 824
820 825 if len(tr_ranges)>0 and tr_ranges[0]!='0':
821 826 y_tx = self.mask_ranges(y_tx, tr_ranges)
822 827
823 828 y.extend(y_tx)
824 829
825 830 self.pulses = str(y)
826 831 y = self.array_to_points(self.pulses_as_array())
827 832
828 833 elif self.line_type.name=='tx':
829 834 params = json.loads(self.params)
830 835 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
831 836 width = float(params['pulse_width'])*km2unit
832 837
833 838 if width>0:
834 839 before = int(self.rc_configuration.time_before*us2unit)
835 840 after = 0
836 841
837 842 y = self.points(ntx, ipp_u, width,
838 843 delay=delays,
839 844 before=before,
840 845 after=after,
841 846 sync=self.rc_configuration.sync)
842 847
843 848 ranges = params['range'].split(',')
844 849
845 850 if len(ranges)>0 and ranges[0]!='0':
846 851 y = self.mask_ranges(y, ranges)
847 852
848 853 elif self.line_type.name=='flip':
849 854 n = float(json.loads(self.params)['number_of_flips'])
850 855 width = n*ipp*km2unit
851 856 y = self.points(int((ntx+1)/(2*n)), ipp_u*n*2, width)
852 857
853 858 elif self.line_type.name=='codes':
854 859 params = json.loads(self.params)
855 860 tx = RCLine.objects.get(pk=params['TX_ref'])
856 861 tx_params = json.loads(tx.params)
857 862 delays = [float(d)*km2unit for d in tx_params['delays'].split(',') if d]
858 863 f = int(float(tx_params['pulse_width'])*km2unit/len(params['codes'][0]))
859 864 codes = [(np.fromstring(''.join([s*f for s in code]), dtype=np.uint8)-48).astype(np.int8) for code in params['codes']]
860 865 codes = [self.array_to_points(code) for code in codes]
861 866 n = len(codes)
862 867
863 868 ranges = tx_params['range'].split(',')
864 869 if len(ranges)>0 and ranges[0]!='0':
865 870 dum = self.mask_ranges(tx.pulses_as_points(), ranges)
866 871 else:
867 872 dum = tx.pulses_as_points()
868 873
869 874 for i, tup in enumerate(dum):
870 875 if tup==(0,0): continue
871 876 code = codes[i%n]
872 877 y.extend([(c[0]+tup[0], c[1]+tup[0]) for c in code])
873 878
874 879 elif self.line_type.name=='sync':
875 880 params = json.loads(self.params)
876 881 n = ipp_u*ntx
877 882 if params['invert'] in ('1', 1):
878 883 y = [(n-1, n)]
879 884 else:
880 885 y = [(0, 1)]
881 886
882 887 elif self.line_type.name=='prog_pulses':
883 888 params = json.loads(self.params)
884 889 if int(params['periodic'])==0:
885 890 nntx = 1
886 891 nipp = ipp_u*ntx
887 892 else:
888 893 nntx = ntx
889 894 nipp = ipp_u
890 895
891 896 if 'params' in params and len(params['params'])>0:
892 897 for p in params['params']:
893 898 y_pp = self.points(nntx, nipp,
894 899 p['end']-p['begin'],
895 900 before=p['begin'])
896 901
897 902 y.extend(y_pp)
898 903
899 904 elif self.line_type.name=='windows':
900 905 params = json.loads(self.params)
901 906 if 'params' in params and len(params['params'])>0:
902 907 tx = RCLine.objects.get(pk=params['TX_ref'])
903 908 tx_params = json.loads(tx.params)
904 909 ranges = tx_params['range'].split(',')
905 910 for p in params['params']:
906 911 y_win = self.points(ntx, ipp_u,
907 912 p['resolution']*p['number_of_samples']*km2unit,
908 913 before=int(self.rc_configuration.time_before*us2unit)+p['first_height']*km2unit,
909 914 sync=self.rc_configuration.sync+self.get_win_ref(p, params['TX_ref'], km2unit))
910 915
911 916
912 917 if len(ranges)>0 and ranges[0]!='0':
913 918 y_win = self.mask_ranges(y_win, ranges)
914 919
915 920 y.extend(y_win)
916 921
917 922 elif self.line_type.name=='mix':
918 923 values = self.rc_configuration.parameters.split('-')
919 924 confs = [RCConfiguration.objects.get(pk=value.split('|')[0]) for value in values]
920 925 modes = [value.split('|')[1] for value in values]
921 926 ops = [value.split('|')[2] for value in values]
922 927 delays = [value.split('|')[3] for value in values]
923 928 masks = [value.split('|')[4] for value in values]
924 929 print("masks")
925 930 print(masks)
926 931 print('{:8b}'.format(int(masks[0])))
927 932 mask = list('{:8b}'.format(int(masks[0])))
928 933 print("mask")
929 934 print(mask)
930 935 mask.reverse()
931 936 print("mask reverse")
932 937 print(mask)
933 938 if mask[self.channel] in ('0', '', ' '):
934 939 y = np.zeros(confs[0].total_units, dtype=np.int8)
935 940 else:
936 941 y = confs[0].get_lines(channel=self.channel)[0].pulses_as_array()
937 942
938 943 for i in range(1, len(values)):
939 944 mask = list('{:8b}'.format(int(masks[i])))
940 945 mask.reverse()
941 946
942 947 if mask[self.channel] in ('0', '', ' '):
943 948 continue
944 949 Y = confs[i].get_lines(channel=self.channel)[0].pulses_as_array()
945 950 delay = float(delays[i])*km2unit
946 951
947 952 if modes[i]=='P':
948 953 if delay>0:
949 954 if delay<self.rc_configuration.ipp*km2unit and len(Y)==len(y):
950 955 y_temp = np.empty_like(Y)
951 956 y_temp[:delay] = 0
952 957 y_temp[delay:] = Y[:-delay]
953 958 elif delay+len(Y)>len(y):
954 959 y_new = np.zeros(delay+len(Y), dtype=np.int8)
955 960 y_new[:len(y)] = y
956 961 y = y_new
957 962 y_temp = np.zeros(delay+len(Y), dtype=np.int8)
958 963 y_temp[-len(Y):] = Y
959 964 elif delay+len(Y)==len(y):
960 965 y_temp = np.zeros(delay+len(Y))
961 966 y_temp[-len(Y):] = Y
962 967 elif delay+len(Y)<len(y):
963 968 y_temp = np.zeros(len(y), dtype=np.int8)
964 969 y_temp[delay:delay+len(Y)] = Y
965 970 else:
966 971 y_temp = Y.copy()
967 972
968 973 if ops[i]=='OR':
969 974 y = y | y_temp
970 975 elif ops[i]=='XOR':
971 976 y = y ^ y_temp
972 977 elif ops[i]=='AND':
973 978 y = y & y_temp
974 979 elif ops[i]=='NAND':
975 980 y = y & ~y_temp
976 981 else:
977 982 y = np.concatenate([y, Y])
978 983
979 984 total = len(y)
980 985 y = self.array_to_points(y)
981 986
982 987 else:
983 988 y = []
984 989
985 990 if self.rc_configuration.total_units != total:
986 991 self.rc_configuration.total_units = total
987 992 self.rc_configuration.save()
988 993
989 994 self.pulses = str(y)
990 995 self.save()
991 996
992 997 @staticmethod
993 998 def array_to_points(X):
994 999
995 1000 if X.size==0:
996 1001 return []
997 1002
998 1003 d = X[1:]-X[:-1]
999 1004
1000 1005 up = np.where(d==1)[0]
1001 1006 if X[0]==1:
1002 1007 up = np.concatenate((np.array([-1]), up))
1003 1008 up += 1
1004 1009
1005 1010 dw = np.where(d==-1)[0]
1006 1011 if X[-1]==1:
1007 1012 dw = np.concatenate((dw, np.array([len(X)-1])))
1008 1013 dw += 1
1009 1014
1010 1015 return [(tup[0], tup[1]) for tup in zip(up, dw)]
1011 1016
1012 1017 @staticmethod
1013 1018 def mask_ranges(Y, ranges):
1014 1019
1015 1020 y = [(0, 0) for __ in Y]
1016 1021
1017 1022 for index in ranges:
1018 1023 if '-' in index:
1019 1024 args = [int(a) for a in index.split('-')]
1020 1025 y[args[0]-1:args[1]] = Y[args[0]-1:args[1]]
1021 1026 else:
1022 1027 y[int(index)-1] = Y[int(index)-1]
1023 1028
1024 1029 return y
1025 1030
1026 1031 @staticmethod
1027 1032 def points(ntx, ipp, width, delay=[0], before=0, after=0, sync=0):
1028 1033
1029 1034 delays = len(delay)
1030 1035
1031 1036 Y = [(int(ipp*x+before+delay[x%delays]+sync), int(ipp*x+width+before+delay[x%delays]+after+sync)) for x in range(ntx)]
1032 1037
1033 1038 return Y
1034 1039
1035 1040 class RCClock(models.Model):
1036 1041
1037 1042 rc_configuration = models.ForeignKey('RCConfiguration', on_delete=models.CASCADE)
1038 1043 mode = models.BooleanField(default=True, choices=((True, 'Auto'), (False, 'Manual')))
1039 1044 multiplier = models.PositiveIntegerField(default=60)
1040 1045 divisor = models.PositiveIntegerField(default=10)
1041 1046 reference = models.PositiveSmallIntegerField(default=1, choices=((0, 'Internal (25MHz)'), (1, 'External (10MHz)')))
1042 frequency = models.FloatField(default=60.0) No newline at end of file
1047 frequency = models.FloatField(default=60.0)
@@ -1,436 +1,435
1
2 1 import json
3 2
4 3 from django.contrib import messages
5 4 from django.utils.safestring import mark_safe
6 5 from django.shortcuts import render, redirect, get_object_or_404, HttpResponse
7 6 from django.contrib.auth.decorators import login_required
8 7
9 8 from apps.main.models import Experiment, Device
10 9 from apps.main.views import sidebar
11 10
12 11 from .models import RCConfiguration, RCLine, RCLineType, RCLineCode, RCClock
13 12 from .forms import RCConfigurationForm, RCLineForm, RCLineViewForm, RCLineEditForm, RCImportForm, RCLineCodesForm, RCClockForm
14 13
15 14
16 15 def conf(request, conf_id):
17 16
18 17 conf = get_object_or_404(RCConfiguration, pk=conf_id)
19 18
20 19 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
21 20 clk = RCClock.objects.filter(rc_configuration=conf).first()
22 21 if clk is None:
23 22 clk = RCClock(rc_configuration=conf)
24 23 clk.save()
25 24
26 25 for line in lines:
27 26 params = json.loads(line.params)
28 27 line.form = RCLineViewForm(extra_fields=params, line=line)
29 28 if 'params' in params:
30 29 line.subforms = [RCLineViewForm(extra_fields=fields, line=line, subform=True) for fields in params['params']]
31 30
32 31 kwargs = {}
33 32 kwargs['clock'] = clk
34 33 kwargs['dev_conf'] = conf
35 34 kwargs['rc_lines'] = lines
36 35 kwargs['dev_conf_keys'] = ['ipp_unit', 'ntx', 'clock_divider', 'clock',
37 36 'time_before', 'time_after', 'sync', 'sampling_reference',
38 37 'control_tx', 'control_sw']
39 38
40 39 kwargs['title'] = 'Configuration'
41 40 kwargs['suptitle'] = 'Detail'
42 41
43 42 kwargs['button'] = 'Edit Configuration'
44 43 ###### SIDEBAR ######
45 44 kwargs.update(sidebar(conf=conf))
46 45
47 46 return render(request, 'rc_conf.html', kwargs)
48 47
49 48 @login_required
50 49 def conf_edit(request, conf_id):
51 50
52 51 conf = get_object_or_404(RCConfiguration, pk=conf_id)
53 52 clock = RCClock.objects.get(rc_configuration=conf)
54 53 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
55 54
56 55 for line in lines:
57 56 params = json.loads(line.params)
58 57 #print(params)
59 58 line.form = RCLineEditForm(conf=conf, line=line, extra_fields=params)
60 59 line.subform = False
61 60
62 61 if 'params' in params:
63 62 line.subforms = [RCLineEditForm(extra_fields=fields, line=line, subform=i) for i, fields in enumerate(params['params'])]
64 63 line.subform = True
65 64 print(params)
66 65 print("fin de sub carga de params")
67 66 #print("fin de carga de params")
68 67 if request.method=='GET':
69 68 print("GET case")
70 69 form = RCConfigurationForm(instance=conf)
71 70 form_clock = RCClockForm(instance=clock)
72 71
73 72 elif request.method=='POST':
74 73 #print("ingreso a post conf edit")
75 74 line_data = {}
76 75 conf_data = {}
77 76 clock_data = {}
78 77 extras = []
79 78 print("Inicio impresion POST#####")
80 79 print(request.POST.items)
81 80 print("Fin impresion de POST items#####")
82 81 #classified post fields
83 82 for label,value in request.POST.items():
84 83 if label=='csrfmiddlewaretoken':
85 84 continue
86 85
87 86 if label.count('|')==0:
88 87 if label in ('mode', 'multiplier', 'divisor', 'reference', 'frequency'):
89 88 clock_data[label] = value
90 89 else:
91 90 conf_data[label] = value
92 91 continue
93 92
94 93 elif label.split('|')[0]!='-1':
95 94 extras.append(label)
96 95 continue
97 96
98 97 #print(label)
99 98 x, pk, name = label.split('|')
100 99
101 100 if name=='codes':
102 101 value = [s for s in value.split('\r\n') if s]
103 102
104 103 if pk in line_data:
105 104 line_data[pk][name] = value
106 105 else:
107 106 line_data[pk] = {name:value}
108 107 #print(line_data[pk])
109 108 #update conf
110 109
111 110 form_clock = RCClockForm(clock_data, instance=clock)
112 111 form = RCConfigurationForm(conf_data, instance=conf)
113 112
114 113 #print(request.POST.items())
115 114
116 115 if form_clock.is_valid() and form.is_valid():
117 116 form_clock.save()
118 117 form.save()
119 118
120 119 #update lines fields
121 extras.sort()
120 extras.sort(key=lambda x: int(x.split('|')[0]))
122 121 #print("Inicio extras")
123 122 #print(extras)
124 123 #print("Fin extras")
125 124 for label in extras:
126 125 x, pk, name = label.split('|')
127 126 if pk not in line_data:
128 127 line_data[pk] = {}
129 128 if 'params' not in line_data[pk]:
130 129 line_data[pk]['params'] = []
131 130 if len(line_data[pk]['params'])<int(x)+1:
132 131 line_data[pk]['params'].append({})
133 132 line_data[pk]['params'][int(x)][name] = float(request.POST[label])
134 133
135 134 for pk, params in line_data.items():
136 135 line = RCLine.objects.get(pk=pk)
137 136 if line.line_type.name in ('windows', 'prog_pulses'):
138 137 if 'params' not in params:
139 138 params['params'] = []
140 139 line.params = json.dumps(params)
141 140 #print(line.params)
142 141 line.save()
143 142
144 143
145 144 #update pulses field
146 145 conf.update_pulses()
147 146
148 147 messages.success(request, 'RC Configuration successfully updated')
149 148
150 149 return redirect(conf.get_absolute_url())
151 150
152 151 kwargs = {}
153 152 kwargs['dev_conf'] = conf
154 153 kwargs['form'] = form
155 154 kwargs['form_clock'] = form_clock
156 155 kwargs['rc_lines'] = lines
157 156 kwargs['edit'] = True
158 157
159 158 kwargs['title'] = 'RC Configuration'
160 159 kwargs['suptitle'] = 'Edit'
161 160 kwargs['button'] = 'Update'
162 161
163 162 return render(request, 'rc_conf_edit.html', kwargs)
164 163
165 164
166 165 def add_line(request, conf_id, line_type_id=None, code_id=None):
167 166
168 167 conf = get_object_or_404(RCConfiguration, pk=conf_id)
169 168
170 169 if request.method=='GET':
171 170 if line_type_id:
172 171 line_type = get_object_or_404(RCLineType, pk=line_type_id)
173 172
174 173 if code_id:
175 174 form = RCLineForm(initial={'rc_configuration':conf_id, 'line_type': line_type_id, 'code_id': code_id},
176 175 extra_fields=json.loads(line_type.params))
177 176 else:
178 177 form = RCLineForm(initial={'rc_configuration':conf_id, 'line_type': line_type_id},
179 178 extra_fields=json.loads(line_type.params))
180 179 else:
181 180 line_type = {'id':0}
182 181 form = RCLineForm(initial={'rc_configuration':conf_id})
183 182
184 183 if request.method=='POST':
185 184
186 185 line_type = get_object_or_404(RCLineType, pk=line_type_id)
187 186 form = RCLineForm(request.POST,
188 187 extra_fields=json.loads(line_type.params))
189 188
190 189 if form.is_valid():
191 190 form.save()
192 191 form.instance.update_pulses()
193 192 return redirect('url_edit_rc_conf', conf.id)
194 193
195 194 kwargs = {}
196 195 kwargs['form'] = form
197 196 kwargs['title'] = 'RC Configuration'
198 197 kwargs['suptitle'] = 'Add Line'
199 198 kwargs['button'] = 'Add'
200 199 kwargs['previous'] = conf.get_absolute_url_edit()
201 200 kwargs['dev_conf'] = conf
202 201 kwargs['line_type'] = line_type
203 202
204 203 return render(request, 'rc_add_line.html', kwargs)
205 204
206 205 def edit_codes(request, conf_id, line_id, code_id=None):
207 206
208 207 conf = get_object_or_404(RCConfiguration, pk=conf_id)
209 208 line = get_object_or_404(RCLine, pk=line_id)
210 209 params = json.loads(line.params)
211 210
212 211 if request.method=='GET':
213 212 if code_id:
214 213 code = get_object_or_404(RCLineCode, pk=code_id)
215 214 form = RCLineCodesForm(instance=code)
216 215 else:
217 216 initial = {'code': params['code'],
218 217 'codes': params['codes'] if 'codes' in params else [],
219 218 'number_of_codes': len(params['codes']) if 'codes' in params else 0,
220 219 'bits_per_code': len(params['codes'][0]) if 'codes' in params else 0,
221 220 }
222 221 form = RCLineCodesForm(initial=initial)
223 222
224 223 if request.method=='POST':
225 224 form = RCLineCodesForm(request.POST)
226 225 if form.is_valid():
227 226 params['code'] = request.POST['code']
228 227 params['codes'] = [s for s in request.POST['codes'].split('\r\n') if s]
229 228 line.params = json.dumps(params)
230 229 line.save()
231 230 messages.success(request, 'Line: "%s" has been updated.' % line)
232 231 return redirect('url_edit_rc_conf', conf.id)
233 232
234 233 kwargs = {}
235 234 kwargs['form'] = form
236 235 kwargs['title'] = line
237 236 kwargs['suptitle'] = 'Edit'
238 237 kwargs['button'] = 'Update'
239 238 kwargs['dev_conf'] = conf
240 239 kwargs['previous'] = conf.get_absolute_url_edit()
241 240 kwargs['line'] = line
242 241
243 242 return render(request, 'rc_edit_codes.html', kwargs)
244 243
245 244 def add_subline(request, conf_id, line_id):
246 245
247 246 conf = get_object_or_404(RCConfiguration, pk=conf_id)
248 247 line = get_object_or_404(RCLine, pk=line_id)
249 248
250 249 if request.method == 'POST':
251 250 if line:
252 251 params = json.loads(line.params)
253 252 subparams = json.loads(line.line_type.params)
254 253 if 'params' in subparams:
255 254 dum = {}
256 255 for key, value in subparams['params'].items():
257 256 dum[key] = value['value']
258 257 params['params'].append(dum)
259 258 line.params = json.dumps(params)
260 259 line.save()
261 260 return redirect('url_edit_rc_conf', conf.id)
262 261
263 262 kwargs = {}
264 263
265 264 kwargs['title'] = 'Add new'
266 265 kwargs['suptitle'] = '%s to %s' % (line.line_type.name, line)
267 266
268 267 return render(request, 'confirm.html', kwargs)
269 268
270 269 def remove_line(request, conf_id, line_id):
271 270
272 271 conf = get_object_or_404(RCConfiguration, pk=conf_id)
273 272 line = get_object_or_404(RCLine, pk=line_id)
274 273
275 274 if request.method == 'POST':
276 275 if line:
277 276 try:
278 277 channel = line.channel
279 278 line.delete()
280 279 for ch in range(channel+1, RCLine.objects.filter(rc_configuration=conf).count()+1):
281 280 l = RCLine.objects.get(rc_configuration=conf, channel=ch)
282 281 l.channel = l.channel-1
283 282 l.save()
284 283 messages.success(request, 'Line: "%s" has been deleted.' % line)
285 284 except:
286 285 messages.error(request, 'Unable to delete line: "%s".' % line)
287 286
288 287 return redirect('url_edit_rc_conf', conf.id)
289 288
290 289 kwargs = {}
291 290
292 291 kwargs['object'] = line
293 292 kwargs['delete'] = True
294 293 kwargs['title'] = 'Delete'
295 294 kwargs['suptitle'] = 'Line'
296 295 kwargs['previous'] = conf.get_absolute_url_edit()
297 296 return render(request, 'confirm.html', kwargs)
298 297
299 298
300 299 def remove_subline(request, conf_id, line_id, subline_id):
301 300
302 301 conf = get_object_or_404(RCConfiguration, pk=conf_id)
303 302 line = get_object_or_404(RCLine, pk=line_id)
304 303
305 304 if request.method == 'POST':
306 305 if line:
307 306 params = json.loads(line.params)
308 307 params['params'].remove(params['params'][int(subline_id)-1])
309 308 line.params = json.dumps(params)
310 309 line.save()
311 310
312 311 return redirect('url_edit_rc_conf', conf.id)
313 312
314 313 kwargs = {}
315 314
316 315 kwargs['object'] = line
317 316 kwargs['object_name'] = line.line_type.name
318 317 kwargs['delete_view'] = True
319 318 kwargs['title'] = 'Confirm delete'
320 319
321 320 return render(request, 'confirm.html', kwargs)
322 321
323 322
324 323 def update_lines_position(request, conf_id):
325 324
326 325 conf = get_object_or_404(RCConfiguration, pk=conf_id)
327 326 print("ingreso a update_lines_position")
328 327 if request.method=='POST':
329 328 ch = 0
330 329 for item in request.POST['items'].split('&'):
331 330 line = RCLine.objects.get(pk=item.split('=')[-1])
332 331 line.channel = ch
333 332 line.save()
334 333 ch += 1
335 334
336 335 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
337 336
338 337 for line in lines:
339 338
340 339 params = json.loads(line.params)
341 340 print(params)
342 341 print("Fin de impresion_lines_position")
343 342 line.form = RCLineEditForm(conf=conf, line=line, extra_fields=params)
344 343
345 344 if 'params' in params:
346 345 line.subform = True
347 346 line.subforms = [RCLineEditForm(extra_fields=fields, line=line, subform=i) for i, fields in enumerate(params['params'])]
348 347
349 348 html = render(request, 'rc_lines.html', {'dev_conf':conf, 'rc_lines':lines, 'edit':True})
350 349 data = {'html': html.content.decode('utf8')}
351 350
352 351 return HttpResponse(json.dumps(data), content_type="application/json")
353 352 return redirect('url_edit_rc_conf', conf.id)
354 353
355 354
356 355 def import_file(request, conf_id):
357 356
358 357 conf = get_object_or_404(RCConfiguration, pk=conf_id)
359 358 if request.method=='POST':
360 359 form = RCImportForm(request.POST, request.FILES)
361 360 if form.is_valid():
362 361 try:
363 362 data = conf.import_from_file(request.FILES['file_name'])
364 363 conf.dict_to_parms(data)
365 364 conf.update_pulses()
366 365 messages.success(request, 'Configuration "%s" loaded succesfully' % request.FILES['file_name'])
367 366 return redirect(conf.get_absolute_url_edit())
368 367
369 368 except Exception as e:
370 369 messages.error(request, 'Error parsing file: "%s" - %s' % (request.FILES['file_name'], repr(e)))
371 370 else:
372 371 messages.warning(request, 'Your current configuration will be replaced')
373 372 form = RCImportForm()
374 373
375 374 kwargs = {}
376 375 kwargs['form'] = form
377 376 kwargs['title'] = 'RC Configuration'
378 377 kwargs['suptitle'] = 'Import file'
379 378 kwargs['button'] = 'Upload'
380 379 kwargs['previous'] = conf.get_absolute_url()
381 380
382 381 return render(request, 'rc_import.html', kwargs)
383 382
384 383
385 384 def plot_pulses(request, conf_id):
386 385
387 386 conf = get_object_or_404(RCConfiguration, pk=conf_id)
388 387 km = True if 'km' in request.GET else False
389 388
390 389 script, div = conf.plot_pulses(km=km)
391 390
392 391 kwargs = {}
393 392 kwargs['no_sidebar'] = True
394 393 kwargs['title'] = 'RC Pulses'
395 394 kwargs['suptitle'] = conf.name
396 395 kwargs['div'] = mark_safe(div)
397 396 kwargs['script'] = mark_safe(script)
398 397 kwargs['units'] = conf.km2unit
399 398 kwargs['kms'] = 1/conf.km2unit
400 399
401 400 if km:
402 401 kwargs['km_selected'] = True
403 402
404 403 if 'json' in request.GET:
405 404 return HttpResponse(json.dumps({'div':mark_safe(div), 'script':mark_safe(script)}), content_type="application/json")
406 405 else:
407 406 return render(request, 'rc_pulses.html', kwargs)
408 407
409 408 def plot_pulses2(request, conf_id):
410 409
411 410 conf = get_object_or_404(RCConfiguration, pk=conf_id)
412 411 km = True if 'km' in request.GET else False
413 412
414 413 script, div = conf.plot_pulses2(km=km)
415 414
416 415 kwargs = {}
417 416 kwargs['no_sidebar'] = True
418 417 kwargs['title'] = 'RC Pulses'
419 418 kwargs['suptitle'] = conf.name
420 419 kwargs['div'] = mark_safe(div)
421 420 kwargs['script'] = mark_safe(script)
422 421 kwargs['units'] = conf.km2unit
423 422 kwargs['kms'] = 1/conf.km2unit
424 423
425 424 if km:
426 425 kwargs['km_selected'] = True
427 426
428 427 if 'json' in request.GET:
429 428 return HttpResponse(json.dumps({'div':mark_safe(div), 'script':mark_safe(script)}), content_type="application/json")
430 429 else:
431 430 return render(request, 'rc_pulses.html', kwargs)
432 431
433 432 def conf_raw(request, conf_id):
434 433 conf = get_object_or_404(RCConfiguration, pk=conf_id)
435 434 raw = conf.write_device(raw=True)
436 return HttpResponse(raw, content_type='application/json') No newline at end of file
435 return HttpResponse(raw, content_type='application/json')
@@ -1,68 +1,70
1 1 version: '2'
2 2 services:
3 3 # Django app
4 web:
5 container_name: 'radarsys'
6 build: .
7 restart: always
8 image: radarsys
9 command: gunicorn radarsys.wsgi:application -w 2 -b :8000
10 # command: python manage.py runserver 0.0.0.0:8030
11 # ports:
12 # - 8030:8030
13 env_file: .env
4 # web:
5 # container_name: 'radarsys'
6 # build: .
7 # restart: always
8 # image: radarsys
9 # command: gunicorn radarsys.wsgi:application -w 2 -b :8000
10 # # command: python manage.py runserver 0.0.0.0:8030
11 # # ports:
12 # # - 8030:8030
13 # env_file: .env
14 14
15 links:
16 - redis
17 - postgres
18 volumes:
19 - './:/radarsys'
20 - '${DOCKER_DATA}/static:/radarsys/static'
21 depends_on:
22 - redis
23 - postgres
15 # links:
16 # - redis
17 # - postgres
18 # volumes:
19 # - './:/radarsys'
20 # - '${DOCKER_DATA}/static:/radarsys/static'
21 # depends_on:
22 # - redis
23 # - postgres
24 24
25 25 redis:
26 26 container_name: 'radarsys-redis'
27 27 image: 'redis:3.2-alpine'
28 28 volumes:
29 29 - '${DOCKER_DATA}/redis:/data'
30 ports:
31 - 6300:6379
30 32
31 33 celery_worker:
32 34 container_name: 'radarsys-celery'
33 35 image: radarsys
34 36 env_file: .env
35 37 command: celery -A radarsys worker -l info
36 volumes_from:
37 - web
38 depends_on:
39 - web
38 # volumes_from:
39 # - web
40 # depends_on:
41 # - web
40 42
41 43 # PostgreSQL
42 44 postgres:
43 45 container_name: 'radarsys-postgres'
44 46 build: ./postgres/
45 47 volumes:
46 48 - ./postgres/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
47 - pgdata:/var/lib/postgresql/data
48 # ports:
49 # - 5432:5432
49 - /data/dockers/radarsys/postgres:/var/lib/postgresql/data
50 ports:
51 - 5400:5432
50 52 env_file: .env
51 53
52 54 # Web Server
53 nginx:
54 container_name: 'radarsys-nginx'
55 restart: always
56 build: ./nginx/
57 ports:
58 - '8030:8030'
59 volumes_from:
60 - web
61 links:
62 - web:web
63 depends_on:
64 - web
55 # nginx:
56 # container_name: 'radarsys-nginx'
57 # restart: always
58 # build: ./nginx/
59 # ports:
60 # - '8030:8030'
61 # volumes_from:
62 # - web
63 # links:
64 # - web:web
65 # depends_on:
66 # - web
65 67
66 volumes:
67 pgdata:
68 driver: local
68 # volumes:
69 # pgdata:
70 # driver: local
@@ -1,146 +1,140
1 1 """
2 2 Django settings for radarsys project.
3 3
4 4 Generated by 'django-admin startproject' using Django 1.8.6.
5 5
6 6 For more information on this file, see
7 7 https://docs.djangoproject.com/en/1.8/topics/settings/
8 8
9 9 For the full list of settings and their values, see
10 10 https://docs.djangoproject.com/en/1.8/ref/settings/
11 11 """
12 12
13 13 # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
14 14 import os
15 15
16 16 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
17 17
18 18 # Quick-start development settings - unsuitable for production
19 19 # See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/
20 20
21 21 # SECURITY WARNING: keep the secret key used in production secret!
22 22 SECRET_KEY = 'xshb$k5fc-+j16)cvyffj&9u__0q3$l!hieh#+tbzqg)*f^km0'
23 23
24 24 # SECURITY WARNING: don't run with debug turned on in production!
25 25 DEBUG = True
26 26
27 27 ALLOWED_HOSTS = ['*']
28 28
29 29 # Application definition
30 30
31 INSTALLED_APPS = [
31 INSTALLED_APPS = (
32 32 'django.contrib.admin',
33 33 'django.contrib.auth',
34 34 'django.contrib.contenttypes',
35 35 'django.contrib.sessions',
36 36 'django.contrib.messages',
37 37 'django.contrib.staticfiles',
38 38 'bootstrap4',
39 39 'polymorphic',
40 40 'apps.accounts',
41 41 'apps.main',
42 42 'apps.misc',
43 43 'apps.rc',
44 44 'apps.dds',
45 'apps.dds_rest',
45 46 'apps.jars',
46 47 'apps.usrp',
47 48 'apps.abs',
48 49 'apps.cgs',
49 'apps.dds_rest',
50 ]
50 )
51 51
52 52 MIDDLEWARE = [
53 53 'django.middleware.security.SecurityMiddleware',
54 54 'django.contrib.sessions.middleware.SessionMiddleware',
55 55 'django.middleware.common.CommonMiddleware',
56 56 'django.middleware.csrf.CsrfViewMiddleware',
57 57 'django.contrib.auth.middleware.AuthenticationMiddleware',
58 58 'django.contrib.messages.middleware.MessageMiddleware',
59 59 'django.middleware.clickjacking.XFrameOptionsMiddleware',
60 60
61 61 ]
62 62
63 63 ROOT_URLCONF = 'radarsys.urls'
64 64
65 65 TEMPLATES = [
66 66 {
67 67 'BACKEND': 'django.template.backends.django.DjangoTemplates',
68 'DIRS': [os.path.join(BASE_DIR, "templates")],
68 'DIRS': [os.path.join(BASE_DIR, "templates").replace('\\', '/'),],
69 69 'APP_DIRS': True,
70 70 'OPTIONS': {
71 71 'context_processors': [
72 72 'django.template.context_processors.debug',
73 73 'django.template.context_processors.request',
74 74 'django.contrib.auth.context_processors.auth',
75 75 'django.contrib.messages.context_processors.messages',
76 76 'apps.main.processors.radarsys_globals',
77 77 ],
78 78 },
79 79 },
80 80 ]
81 81
82 82 WSGI_APPLICATION = 'radarsys.wsgi.application'
83 83
84 84
85 85 # Database
86 86 # https://docs.djangoproject.com/en/1.8/ref/settings/#databases
87 87
88 88 DATABASES = {
89 89 'default': {
90 90 'ENGINE': 'django.db.backends.sqlite3',
91 91 'NAME': 'radarsys.sqlite',
92 # 'ENGINE': 'django.db.backends.postgresql_psycopg2',
93 # 'NAME': os.environ.get('DB_NAME', 'radarsys'),
94 # 'USER': os.environ.get('DB_USER', 'docker'),
95 # 'PASSWORD': os.environ.get('DB_PASSWORD', 'docker'),
96 # 'HOST': os.environ.get('POSTGRES_PORT_5432_TCP_ADDR', 'localhost'),
97 # 'PORT': os.environ.get('POSTGRES_PORT_5432_TCP_PORT', '5400'),
98 }
92 99 }
93 # 'default': {
94 # 'ENGINE': 'django.db.backends.postgresql_psycopg2',
95 # 'NAME': os.environ.get('DB_NAME', 'radarsys'),
96 # 'USER': os.environ.get('DB_USER', 'docker'),
97 # 'PASSWORD': os.environ.get('DB_PASSWORD', 'docker'),
98 # 'HOST': os.environ.get('POSTGRES_PORT_5432_TCP_ADDR', 'localhost'),
99 # 'PORT': os.environ.get('POSTGRES_PORT_5432_TCP_PORT', '5400'),
100 #}
101 }
102 100
103 101 # Internationalization
104 102 # https://docs.djangoproject.com/en/1.8/topics/i18n/
105 103
106 104 LANGUAGE_CODE = 'en-us'
107 105
108 USE_TZ = False #True
109
110 106 TIME_ZONE = os.environ.get('TZ', 'America/Lima')
111 107
112 108 USE_I18N = True
113 109
114 110 USE_L10N = True
115 111
112 USE_TZ = False
113
116 114 # Static files (CSS, JavaScript, Images)
117 115 # https://docs.djangoproject.com/en/1.8/howto/static-files/
118 116
119 117 MEDIA_URL = '/media/'
120 118 MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
121 119
122 120 STATIC_URL = '/static/'
123 121 STATIC_ROOT = os.path.join(BASE_DIR, 'static')
124 122
125 123 STATICFILES_FINDERS = (
126 124 'django.contrib.staticfiles.finders.FileSystemFinder',
127 125 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
128 126 )
129 127
130 128 # Celery stuff
131
132 REDIS_HOST = os.environ.get('REDIS_HOST', 'localhost')
133 #REDIS_HOST = os.environ.get('REDIS_HOST', '127.0.0.1')
134 REDIS_PORT = os.environ.get('REDIS_PORT', 6379)
129 REDIS_HOST = os.environ.get('REDIS_HOST', '127.0.0.1')
130 REDIS_PORT = os.environ.get('REDIS_PORT', 6300)
135 131
136 132 BROKER_TRANSPORT = 'redis'
137 #BROKER_URL = 'redis://{}:{}/0'.format(REDIS_HOST, REDIS_PORT)
138 BROKER_URL = 'redis://{}:{}'.format(REDIS_HOST, REDIS_PORT)
133 BROKER_URL = 'redis://{}:{}/0'.format(REDIS_HOST, REDIS_PORT)
139 134
140 CELERY_RESULT_BACKEND = 'redis://{}:{}/0'.format(REDIS_HOST, REDIS_PORT)
141 CELERY_BROKER_TRANSPORT = BROKER_URL
142 CELERY_ACCEPT_CONTENT = ['application/json']
143 CELERY_TASK_SERIALIZER = 'json'
135 CELERY_RESULT_BACKEND = 'redis://{}:{}/0'.format(REDIS_HOST, REDIS_PORT)
136 CELERY_BROKER_TRANSPORT = BROKER_URL
137 CELERY_ACCEPT_CONTENT = ['application/json']
138 CELERY_TASK_SERIALIZER = 'json'
144 139 CELERY_RESULT_SERIALIZER = 'json'
145 CELERY_ENABLE_UTC = False
146 CELERY_TIMEZONE = 'America/Lima' No newline at end of file
140 CELERY_ENABLE_UTC = False
General Comments 0
You need to be logged in to leave comments. Login now