##// END OF EJS Templates
Improve RC pulses plot and Operation view...
Juan C. Espinoza -
r175:a7fbf14a85a6
parent child
Show More
@@ -1,616 +1,621
1 1 from django.shortcuts import render, redirect, get_object_or_404, HttpResponse
2 2 from datetime import datetime
3 3
4 4 from django.db import models
5 5 from polymorphic.models import PolymorphicModel
6 6
7 7 from django.core.urlresolvers import reverse
8 8
9 9
10 10 CONF_STATES = (
11 11 (0, 'Disconnected'),
12 12 (1, 'Connected'),
13 13 (2, 'Running'),
14 14 )
15 15
16 16 EXP_STATES = (
17 17 (0,'Error'), #RED
18 18 (1,'Configured'), #BLUE
19 19 (2,'Running'), #GREEN
20 20 (3,'Waiting'), #YELLOW
21 21 (4,'Not Configured'), #WHITE
22 22 )
23 23
24 24 CONF_TYPES = (
25 25 (0, 'Active'),
26 26 (1, 'Historical'),
27 27 )
28 28
29 29 DEV_STATES = (
30 30 (0, 'No connected'),
31 31 (1, 'Connected'),
32 32 (2, 'Configured'),
33 33 (3, 'Running'),
34 34 )
35 35
36 36 DEV_TYPES = (
37 37 ('', 'Select a device type'),
38 38 ('rc', 'Radar Controller'),
39 39 ('rc_mix', 'Radar Controller (Mix)'),
40 40 ('dds', 'Direct Digital Synthesizer'),
41 41 ('jars', 'Jicamarca Radar Acquisition System'),
42 42 ('usrp', 'Universal Software Radio Peripheral'),
43 43 ('cgs', 'Clock Generator System'),
44 44 ('abs', 'Automatic Beam Switching'),
45 45 )
46 46
47 47 DEV_PORTS = {
48 48 'rc' : 2000,
49 49 'rc_mix': 2000,
50 50 'dds' : 2000,
51 51 'jars' : 2000,
52 52 'usrp' : 2000,
53 53 'cgs' : 8080,
54 54 'abs' : 8080
55 55 }
56 56
57 57 RADAR_STATES = (
58 58 (0, 'No connected'),
59 59 (1, 'Connected'),
60 60 (2, 'Configured'),
61 61 (3, 'Running'),
62 62 (4, 'Scheduled'),
63 63 )
64 64 # Create your models here.
65 65
66 66 class Location(models.Model):
67 67
68 68 name = models.CharField(max_length = 30)
69 69 description = models.TextField(blank=True, null=True)
70 70
71 71 class Meta:
72 72 db_table = 'db_location'
73 73
74 74 def __str__(self):
75 75 return u'%s' % self.name
76 76
77 77 def get_absolute_url(self):
78 78 return reverse('url_location', args=[str(self.id)])
79 79
80 80
81 81 class DeviceType(models.Model):
82 82
83 83 name = models.CharField(max_length = 10, choices = DEV_TYPES, default = 'rc')
84 84 description = models.TextField(blank=True, null=True)
85 85
86 86 class Meta:
87 87 db_table = 'db_device_types'
88 88
89 89 def __str__(self):
90 90 return u'%s' % self.get_name_display()
91 91
92 92 class Device(models.Model):
93 93
94 94 device_type = models.ForeignKey(DeviceType, on_delete=models.CASCADE)
95 95 location = models.ForeignKey(Location, on_delete=models.CASCADE)
96 96
97 97 name = models.CharField(max_length=40, default='')
98 98 ip_address = models.GenericIPAddressField(protocol='IPv4', default='0.0.0.0')
99 99 port_address = models.PositiveSmallIntegerField(default=2000)
100 100 description = models.TextField(blank=True, null=True)
101 101 status = models.PositiveSmallIntegerField(default=0, choices=DEV_STATES)
102 102
103 103 class Meta:
104 104 db_table = 'db_devices'
105 105
106 106 def __str__(self):
107 107 return u'[{}]: {}'.format(self.device_type.name.upper(),
108 108 self.name)
109 109
110 110 def get_status(self):
111 111 return self.status
112 112
113 113 @property
114 114 def status_color(self):
115 115 color = 'muted'
116 116 if self.status == 0:
117 117 color = "danger"
118 118 elif self.status == 1:
119 119 color = "warning"
120 120 elif self.status == 2:
121 121 color = "info"
122 122 elif self.status == 3:
123 123 color = "success"
124 124
125 125 return color
126 126
127 @property
128 def url(self):
129
130 return 'http://{}:{}/'.format(self.ip_address, self.port_address)
131
127 132 def get_absolute_url(self):
128 133 return reverse('url_device', args=[str(self.id)])
129 134
130 135
131 136 class Campaign(models.Model):
132 137
133 138 template = models.BooleanField(default=False)
134 139 name = models.CharField(max_length=60, unique=True)
135 140 start_date = models.DateTimeField(blank=True, null=True)
136 141 end_date = models.DateTimeField(blank=True, null=True)
137 142 tags = models.CharField(max_length=40)
138 143 description = models.TextField(blank=True, null=True)
139 144 experiments = models.ManyToManyField('Experiment', blank=True)
140 145
141 146 class Meta:
142 147 db_table = 'db_campaigns'
143 148 ordering = ('name',)
144 149
145 150 def __str__(self):
146 151 if self.template:
147 152 return u'{} (template)'.format(self.name)
148 153 else:
149 154 return u'{}'.format(self.name)
150 155
151 156 def parms_to_dict(self):
152 157
153 158 import json
154 159
155 160 parameters = {}
156 161 exp_parameters = {}
157 162 experiments = Experiment.objects.filter(campaign = self)
158 163
159 164 i=1
160 165 for experiment in experiments:
161 166 exp_parameters['experiment-'+str(i)] = json.loads(experiment.parms_to_dict())
162 167 i += 1
163 168
164 169
165 170 parameters['experiments'] = exp_parameters
166 171 parameters['end_date'] = self.end_date.strftime("%Y-%m-%d")
167 172 parameters['start_date'] = self.start_date.strftime("%Y-%m-%d")
168 173 parameters['campaign'] = self.__str__()
169 174 parameters['tags'] =self.tags
170 175
171 176 parameters = json.dumps(parameters, indent=2, sort_keys=False)
172 177
173 178 return parameters
174 179
175 180 def import_from_file(self, fp):
176 181
177 182 import os, json
178 183
179 184 parms = {}
180 185
181 186 path, ext = os.path.splitext(fp.name)
182 187
183 188 if ext == '.json':
184 189 parms = json.loads(fp.read())
185 190
186 191 return parms
187 192
188 193 def dict_to_parms(self, parms, CONF_MODELS):
189 194
190 195 experiments = Experiment.objects.filter(campaign = self)
191 196 configurations = Configuration.objects.filter(experiment = experiments)
192 197
193 198 if configurations:
194 199 for configuration in configurations:
195 200 configuration.delete()
196 201
197 202 if experiments:
198 203 for experiment in experiments:
199 204 experiment.delete()
200 205
201 206 for parms_exp in parms['experiments']:
202 207 location = Location.objects.get(name = parms['experiments'][parms_exp]['radar'])
203 208 new_exp = Experiment(
204 209 name = parms['experiments'][parms_exp]['experiment'],
205 210 location = location,
206 211 start_time = parms['experiments'][parms_exp]['start_time'],
207 212 end_time = parms['experiments'][parms_exp]['end_time'],
208 213 )
209 214 new_exp.save()
210 215 new_exp.dict_to_parms(parms['experiments'][parms_exp],CONF_MODELS)
211 216 new_exp.save()
212 217
213 218 self.name = parms['campaign']
214 219 self.start_date = parms['start_date']
215 220 self.end_date = parms['end_date']
216 221 self.tags = parms['tags']
217 222 self.experiments.add(new_exp)
218 223 self.save()
219 224
220 225 return self
221 226
222 227 def get_experiments_by_location(self):
223 228
224 229 ret = []
225 230 locations = set([e.location for e in self.experiments.all()])
226 231 for loc in locations:
227 232 dum = {}
228 233 dum['name'] = loc.name
229 234 dum['id'] = loc.pk
230 235 dum['experiments'] = [e for e in self.experiments.all() if e.location==loc]
231 236 ret.append(dum)
232 237
233 238 return ret
234 239
235 240 def get_absolute_url(self):
236 241 return reverse('url_campaign', args=[str(self.id)])
237 242
238 243 def get_absolute_url_edit(self):
239 244 return reverse('url_edit_campaign', args=[str(self.id)])
240 245
241 246 def get_absolute_url_export(self):
242 247 return reverse('url_export_campaign', args=[str(self.id)])
243 248
244 249 def get_absolute_url_import(self):
245 250 return reverse('url_import_campaign', args=[str(self.id)])
246 251
247 252
248 253
249 254 class RunningExperiment(models.Model):
250 255 radar = models.OneToOneField('Location', on_delete=models.CASCADE)
251 256 running_experiment = models.ManyToManyField('Experiment', blank = True)
252 257 status = models.PositiveSmallIntegerField(default=0, choices=RADAR_STATES)
253 258
254 259
255 260 class Experiment(models.Model):
256 261
257 262 template = models.BooleanField(default=False)
258 263 name = models.CharField(max_length=40, default='', unique=True)
259 264 location = models.ForeignKey('Location', null=True, blank=True, on_delete=models.CASCADE)
260 265 start_time = models.TimeField(default='00:00:00')
261 266 end_time = models.TimeField(default='23:59:59')
262 267 status = models.PositiveSmallIntegerField(default=0, choices=EXP_STATES)
263 268
264 269 class Meta:
265 270 db_table = 'db_experiments'
266 271 ordering = ('template', 'name')
267 272
268 273 def __str__(self):
269 274 if self.template:
270 275 return u'%s (template)' % (self.name)
271 276 else:
272 277 return u'%s' % (self.name)
273 278
274 279 @property
275 280 def radar_system(self):
276 281 return self.location
277 282
278 283 def clone(self, **kwargs):
279 284
280 285 confs = Configuration.objects.filter(experiment=self, type=0)
281 286 self.pk = None
282 287 self.name = '{} [{:%Y/%m/%d}]'.format(self.name, datetime.now())
283 288 for attr, value in kwargs.items():
284 289 setattr(self, attr, value)
285 290
286 291 self.save()
287 292
288 293 for conf in confs:
289 294 conf.clone(experiment=self, template=False)
290 295
291 296 return self
292 297
293 298 def get_status(self):
294 299 configurations = Configuration.objects.filter(experiment=self)
295 300 exp_status=[]
296 301 for conf in configurations:
297 302 exp_status.append(conf.status_device())
298 303
299 304 if not exp_status: #No Configuration
300 305 self.status = 4
301 306 self.save()
302 307 return
303 308
304 309 total = 1
305 310 for e_s in exp_status:
306 311 total = total*e_s
307 312
308 313 if total == 0: #Error
309 314 status = 0
310 315 elif total == (3**len(exp_status)): #Running
311 316 status = 2
312 317 else:
313 318 status = 1 #Configurated
314 319
315 320 self.status = status
316 321 self.save()
317 322
318 323 def status_color(self):
319 324 color = 'muted'
320 325 if self.status == 0:
321 326 color = "danger"
322 327 elif self.status == 1:
323 328 color = "info"
324 329 elif self.status == 2:
325 330 color = "success"
326 331 elif self.status == 3:
327 332 color = "warning"
328 333
329 334 return color
330 335
331 336 def get_absolute_url(self):
332 337 return reverse('url_experiment', args=[str(self.id)])
333 338
334 339 def parms_to_dict(self):
335 340
336 341 import json
337 342
338 343 configurations = Configuration.objects.filter(experiment=self)
339 344 conf_parameters = {}
340 345 parameters={}
341 346
342 347 for configuration in configurations:
343 348 if 'cgs' in configuration.device.device_type.name:
344 349 conf_parameters['cgs'] = configuration.parms_to_dict()
345 350 if 'dds' in configuration.device.device_type.name:
346 351 conf_parameters['dds'] = configuration.parms_to_dict()
347 352 if 'rc' in configuration.device.device_type.name:
348 353 conf_parameters['rc'] = configuration.parms_to_dict()
349 354 if 'jars' in configuration.device.device_type.name:
350 355 conf_parameters['jars'] = configuration.parms_to_dict()
351 356 if 'usrp' in configuration.device.device_type.name:
352 357 conf_parameters['usrp'] = configuration.parms_to_dict()
353 358 if 'abs' in configuration.device.device_type.name:
354 359 conf_parameters['abs'] = configuration.parms_to_dict()
355 360
356 361 parameters['configurations'] = conf_parameters
357 362 parameters['end_time'] = self.end_time.strftime("%H:%M:%S")
358 363 parameters['start_time'] = self.start_time.strftime("%H:%M:%S")
359 364 parameters['radar'] = self.radar_system.name
360 365 parameters['experiment'] = self.name
361 366 parameters = json.dumps(parameters, indent=2)
362 367
363 368 return parameters
364 369
365 370 def import_from_file(self, fp):
366 371
367 372 import os, json
368 373
369 374 parms = {}
370 375
371 376 path, ext = os.path.splitext(fp.name)
372 377
373 378 if ext == '.json':
374 379 parms = json.loads(fp.read().decode('utf-8'))
375 380
376 381 return parms
377 382
378 383 def dict_to_parms(self, parms, CONF_MODELS):
379 384
380 385 configurations = Configuration.objects.filter(experiment=self)
381 386
382 387 if configurations:
383 388 for configuration in configurations:
384 389 configuration.delete()
385 390
386 391 for conf_type in parms['configurations']:
387 392 #--For ABS Device:
388 393 #--For USRP Device:
389 394 #--For JARS Device:
390 395 if conf_type == 'jars':
391 396 device = get_object_or_404(Device, pk=parms['configurations']['jars']['device_id'])
392 397 DevConfModel = CONF_MODELS[conf_type]
393 398 confjars_form = DevConfModel(
394 399 experiment = self,
395 400 name = 'JARS',
396 401 device=device,
397 402 )
398 403 confjars_form.dict_to_parms(parms['configurations']['jars'])
399 404 confjars_form.save()
400 405 #--For RC Device:
401 406 if conf_type == 'rc':
402 407 device = get_object_or_404(Device, pk=parms['configurations']['rc']['device_id'])
403 408 DevConfModel = CONF_MODELS[conf_type]
404 409 confrc_form = DevConfModel(
405 410 experiment = self,
406 411 name = 'RC',
407 412 device=device,
408 413 )
409 414 confrc_form.dict_to_parms(parms['configurations']['rc'])
410 415 confrc_form.save()
411 416 #--For DDS Device:
412 417 if conf_type == 'dds':
413 418 device = get_object_or_404(Device, pk=parms['configurations']['dds']['device_id'])
414 419 DevConfModel = CONF_MODELS[conf_type]
415 420 confdds_form = DevConfModel(
416 421 experiment = self,
417 422 name = 'DDS',
418 423 device=device,
419 424 )
420 425 confdds_form.dict_to_parms(parms['configurations']['dds'])
421 426 confdds_form.save()
422 427 #--For CGS Device:
423 428 if conf_type == 'cgs':
424 429 device = get_object_or_404(Device, pk=parms['configurations']['cgs']['device_id'])
425 430 DevConfModel = CONF_MODELS[conf_type]
426 431 confcgs_form = DevConfModel(
427 432 experiment = self,
428 433 name = 'CGS',
429 434 device=device,
430 435 )
431 436 confcgs_form.dict_to_parms(parms['configurations']['cgs'])
432 437 confcgs_form.save()
433 438
434 439 location = Location.objects.get(name = parms['radar'])
435 440 self.name = parms['experiment']
436 441 self.location = location
437 442 self.start_time = parms['start_time']
438 443 self.end_time = parms['end_time']
439 444 self.save()
440 445
441 446 return self
442 447
443 448 def get_absolute_url_edit(self):
444 449 return reverse('url_edit_experiment', args=[str(self.id)])
445 450
446 451 def get_absolute_url_import(self):
447 452 return reverse('url_import_experiment', args=[str(self.id)])
448 453
449 454 def get_absolute_url_export(self):
450 455 return reverse('url_export_experiment', args=[str(self.id)])
451 456
452 457
453 458 class Configuration(PolymorphicModel):
454 459
455 460 template = models.BooleanField(default=False)
456 461
457 462 name = models.CharField(verbose_name="Configuration Name", max_length=40, default='')
458 463
459 464 experiment = models.ForeignKey('Experiment', verbose_name='Experiment', null=True, blank=True, on_delete=models.CASCADE)
460 465 device = models.ForeignKey('Device', verbose_name='Device', null=True, on_delete=models.CASCADE)
461 466
462 467 type = models.PositiveSmallIntegerField(default=0, choices=CONF_TYPES)
463 468
464 469 created_date = models.DateTimeField(auto_now_add=True)
465 470 programmed_date = models.DateTimeField(auto_now=True)
466 471
467 472 parameters = models.TextField(default='{}')
468 473
469 474 message = ""
470 475
471 476 class Meta:
472 477 db_table = 'db_configurations'
473 478
474 479 def __str__(self):
475 480
476 481 device = '{}:'.format(self.device.device_type.name.upper())
477 482
478 483 if 'mix' in [f.name for f in self._meta.get_fields()]:
479 484 if self.mix:
480 485 device = '{} MIXED:'.format(self.device.device_type.name.upper())
481 486
482 487 if self.template:
483 488 return u'{} {} (template)'.format(device, self.name)
484 489 else:
485 490 return u'{} {}'.format(device, self.name)
486 491
487 492 def clone(self, **kwargs):
488 493
489 494 self.pk = None
490 495 self.id = None
491 496 for attr, value in kwargs.items():
492 497 setattr(self, attr, value)
493 498
494 499 self.save()
495 500
496 501 return self
497 502
498 503 def parms_to_dict(self):
499 504
500 505 parameters = {}
501 506
502 507 for key in self.__dict__.keys():
503 508 parameters[key] = getattr(self, key)
504 509
505 510 return parameters
506 511
507 512 def parms_to_text(self):
508 513
509 514 raise NotImplementedError("This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper())
510 515
511 516
512 517 def parms_to_binary(self):
513 518
514 519 raise NotImplementedError("This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper())
515 520
516 521
517 522 def dict_to_parms(self, parameters):
518 523
519 524 if type(parameters) != type({}):
520 525 return
521 526
522 527 for key in parameters.keys():
523 528 setattr(self, key, parameters[key])
524 529
525 530 def export_to_file(self, format="json"):
526 531
527 532 import json
528 533
529 534 content_type = ''
530 535
531 536 if format == 'text':
532 537 content_type = 'text/plain'
533 538 filename = '%s_%s.%s' %(self.device.device_type.name, self.name, self.device.device_type.name)
534 539 content = self.parms_to_text()
535 540
536 541 if format == 'binary':
537 542 content_type = 'application/octet-stream'
538 543 filename = '%s_%s.bin' %(self.device.device_type.name, self.name)
539 544 content = self.parms_to_binary()
540 545
541 546 if not content_type:
542 547 content_type = 'application/json'
543 548 filename = '%s_%s.json' %(self.device.device_type.name, self.name)
544 549 content = json.dumps(self.parms_to_dict(), indent=2)
545 550
546 551 fields = {'content_type':content_type,
547 552 'filename':filename,
548 553 'content':content
549 554 }
550 555
551 556 return fields
552 557
553 558 def import_from_file(self, fp):
554 559
555 560 import os, json
556 561
557 562 parms = {}
558 563
559 564 path, ext = os.path.splitext(fp.name)
560 565
561 566 if ext == '.json':
562 567 parms = json.load(fp)
563 568
564 569 return parms
565 570
566 571 def status_device(self):
567 572
568 573 raise NotImplementedError("This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper())
569 574
570 575
571 576 def stop_device(self):
572 577
573 578 raise NotImplementedError("This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper())
574 579
575 580
576 581 def start_device(self):
577 582
578 583 raise NotImplementedError("This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper())
579 584
580 585
581 586 def write_device(self, parms):
582 587
583 588 raise NotImplementedError("This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper())
584 589
585 590
586 591 def read_device(self):
587 592
588 593 raise NotImplementedError("This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper())
589 594
590 595
591 596 def get_absolute_url(self):
592 597 return reverse('url_%s_conf' % self.device.device_type.name, args=[str(self.id)])
593 598
594 599 def get_absolute_url_edit(self):
595 600 return reverse('url_edit_%s_conf' % self.device.device_type.name, args=[str(self.id)])
596 601
597 602 def get_absolute_url_import(self):
598 603 return reverse('url_import_dev_conf', args=[str(self.id)])
599 604
600 605 def get_absolute_url_export(self):
601 606 return reverse('url_export_dev_conf', args=[str(self.id)])
602 607
603 608 def get_absolute_url_write(self):
604 609 return reverse('url_write_dev_conf', args=[str(self.id)])
605 610
606 611 def get_absolute_url_read(self):
607 612 return reverse('url_read_dev_conf', args=[str(self.id)])
608 613
609 614 def get_absolute_url_start(self):
610 615 return reverse('url_start_dev_conf', args=[str(self.id)])
611 616
612 617 def get_absolute_url_stop(self):
613 618 return reverse('url_stop_dev_conf', args=[str(self.id)])
614 619
615 620 def get_absolute_url_status(self):
616 621 return reverse('url_status_dev_conf', args=[str(self.id)])
@@ -1,84 +1,84
1 1 {% extends "base.html" %}
2 2 {% load bootstrap3 %}
3 3 {% load static %}
4 4 {% load main_tags %}
5 5
6 6 {% block search-active %}active{% endblock %}
7 7
8 8 {% block content-title %}{{title}}{% endblock %}
9 9 {% block content-suptitle %}{{suptitle}}{% endblock %}
10 10
11 11 {% block content %}
12 12
13 13 {% block menu-actions %}
14 14 <span class=" dropdown pull-right">
15 15 <a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-menu-hamburger gi-2x" aria-hidden="true"></span></a>
16 16 <ul class="dropdown-menu" role="menu">
17 17 <li><a href="{{ dev_conf.get_absolute_url_edit }}"><span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Edit</a></li>
18 18 <li><a href="{% url 'url_delete_dev_conf' dev_conf.id %}"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span> Delete</a></li>
19 19 <li><a href="{{ dev_conf.get_absolute_url_import }}"><span class="glyphicon glyphicon-import" aria-hidden="true"></span> Import </a></li>
20 20 <li><a href="{{ dev_conf.get_absolute_url_export }}"><span class="glyphicon glyphicon-export" aria-hidden="true"></span> Export </a></li>
21 21 {% block extra-menu-actions %}
22 22 {% endblock %}
23 23 <li><a>----------------</a></li>
24 24 <li><a href="{{ dev_conf.get_absolute_url_status }}"><span class="glyphicon glyphicon-refresh" aria-hidden="true"></span> Status</a></li>
25 25 {% if not no_play %}
26 26 {% if not only_stop %}
27 27 <li><a href="{{ dev_conf.get_absolute_url_start}}"><span class="glyphicon glyphicon-play" aria-hidden="true"></span> Start</a></li>
28 28 {% endif %}
29 29 <li><a href="{{ dev_conf.get_absolute_url_stop }}"><span class="glyphicon glyphicon-stop" aria-hidden="true"></span> Stop</a></li>
30 30 {% endif %}
31 31 <li><a href="{{ dev_conf.get_absolute_url_write }}"><span class="glyphicon glyphicon-download" aria-hidden="true"></span> Write</a></li>
32 32 <li><a href="{{ dev_conf.get_absolute_url_read }}"><span class="glyphicon glyphicon-upload" aria-hidden="true"></span> Read</a></li>
33 33 </ul>
34 34 </span>
35 35 {% endblock %}
36 36
37 37 <table class="table table-bordered">
38 38 <tr>
39 39 <th>Status</th>
40 <td>{%if status != "No connected" %} <span class="glyphicon glyphicon-ok-circle text-success" aria-hidden="true"></span> {{status}} {% else %} <span class="glyphicon glyphicon-remove-circle text-danger" aria-hidden="true"></span> {{status}} {% endif %}</td>
40 <td class="text-{{dev_conf.device.status_color}}"> {{dev_conf.device.get_status_display}} </td>
41 41 </tr>
42 42
43 43 {% for key in dev_conf_keys %}
44 44 <tr>
45 45 <th>{% get_verbose_field_name dev_conf key %}</th>
46 46 <td>{{dev_conf|attr:key}}</td>
47 47 </tr>
48 48 {% endfor %}
49 49 </table>
50 50
51 51 {% block extra-content %}
52 52 {% endblock %}
53 53
54 54 {% endblock %}
55 55
56 56 {% block sidebar%}
57 57 {% include "sidebar_devices.html" %}
58 58 {% endblock %}
59 59
60 60 {% block extra-js%}
61 61 <script type="text/javascript">
62 62
63 63 $("#bt_edit").click(function() {
64 64 document.location = "{{ dev_conf.get_absolute_url_edit }}";
65 65 });
66 66
67 67 $("#bt_read").click(function() {
68 68 document.location = "{{ dev_conf.get_absolute_url_read }}";
69 69 });
70 70
71 71 $("#bt_write").click(function() {
72 72 document.location = "{{ dev_conf.get_absolute_url_write }}";
73 73 });
74 74
75 75 $("#bt_import").click(function() {
76 76 document.location = "{{ dev_conf.get_absolute_url_import }}";
77 77 });
78 78
79 79 $("#bt_export").click(function() {
80 80 document.location = "{{ dev_conf.get_absolute_url_export }}";
81 81 });
82 82
83 83 </script>
84 84 {% endblock %} No newline at end of file
@@ -1,128 +1,129
1 1 {% extends "base.html" %}
2 2 {% load bootstrap3 %}
3 3 {% load static %}
4 4 {% load main_tags %}
5 5 {% block extra-head %}
6 6 <link href="{% static 'css/bootstrap-datetimepicker.min.css' %}" media="screen" rel="stylesheet">
7 7 {% endblock %}
8 8
9 9 {% block operation-active %}active{% endblock %}
10 10
11 11
12 12 {% block content %}
13 13
14 14 {% bootstrap_form form layout='horizontal' size='medium' %}
15 15 <div style="clear: both;"></div>
16 16
17 17 {% if campaign %}
18 18
19 19 <div class="clearfix"></div>
20 20 <h2>Radar Systems</h2>
21 21 <br>
22 22 <div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true" >
23 23
24 24 {% for location in locations %}
25 25
26 26 <div class="panel panel-default">
27 27 <div class="panel-heading" role="tab" id="headingTwo">
28 28 <h4 class="panel-title">
29 29
30 30 <a class="collapsed" role="button" data-toggle="collapse" href="#collapseTwo-{{ location.id }}" aria-expanded="false" aria-controls="collapseTwo">
31 31 {{location.name}}
32 32 <span>
33 33 </span>
34 34 </a>
35 35
36 36 <button type="button" name="bt_play" class="btn btn-primary pull-right btn-xs" data-url="{% url 'url_radar_play' campaign.id location.id %}" style="margin-left: 10px">
37 37 <span class="glyphicon glyphicon-play" aria-hidden="true"></span>
38 38 </button>
39 39 <button type="button" name="bt_stop" class="btn btn-primary pull-right btn-xs" data-url="{% url 'url_radar_stop' campaign.id location.id %}" aria-label="Left Align" style="margin-left: 10px">
40 40 <span class="glyphicon glyphicon-stop" aria-hidden="true"></span>
41 41 </button>
42 42 <button type="button" name="bt_refresh" class="btn btn-primary pull-right btn-xs" data-url="{% url 'url_radar_refresh' campaign.id location.id %}" aria-label="Left Align" style="margin-left: 10px">
43 43 <span class="glyphicon glyphicon-refresh" aria-hidden="true"></span>
44 44 </button>
45 45 </h4>
46 46 </div>
47 47
48 48 <div id="collapseTwo-{{ location.id }}" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingTwo">
49 49 <div class="panel-body">
50 50 <table class="table table-hover">
51 51 <tr>
52 52 <th>#</th>
53 53 {% for header in experiment_keys %}
54 54 <th>{{ header|title }}</th>
55 55 {% endfor%}
56 56 </tr>
57 57
58 58 {% for item in location.experiments %}
59 59 {% if location.name in item.location.name %}
60
61 60 <tr class="clickable-row" data-href="{% url 'url_experiment' item.id %}" >
62 61 <td>{{ forloop.counter }}</td>
63 62 {% for key in experiment_keys %}
64 {% if 'status' in key %}
63 {% if 'name' in key %}
64 <td class="col-md-5">{{ item|value:key }}</td>
65 {% elif 'status' in key %}
65 66 <td class="text-{{item.status_color}}">{{ item|value:key }}</td>
66 67 {% else %}
67 68 <td>{{ item|value:key }}</td>
68 69 {% endif %}
69 70 {% endfor %}
70 71 </tr>
71 72 {% endif %}
72 73 {% endfor %}
73 74 </table>
74 75 </div>
75 76 </div>
76 77 </div>
77 78 {% endfor %}
78 79 </div>
79 80
80 81 {% endif %}
81 82
82 83 {% endblock %}
83 84
84 85
85 86
86 87 {% block extra-js%}
87 88 <script type="text/javascript">
88 89
89 90 //--------For PLAY Button-------
90 91 $("#accordion").on("click", "button[name=bt_play]", function(){
91 92 //alert($(this).data('url'));
92 93 document.location = $(this).data('url');
93 94 });
94 95
95 96 //--------For STOP Button-------
96 97 $("#accordion").on("click", "button[name=bt_stop]", function(){
97 98 //alert($(this).data('url'));
98 99 document.location = $(this).data('url');
99 100 });
100 101
101 102 //--------For REFRESH Button-------
102 103 $("#accordion").on("click", "button[name=bt_refresh]", function(){
103 104 document.location = $(this).data('url');
104 105 });
105 106
106 107 $(".clickable-row").click(function() {
107 108 document.location = $(this).data("href");
108 109 });
109 110
110 111 {% if search_button == True %}
111 112 $(document).ready(function() {
112 113 $("#id_campaign").change(function() {
113 114 var id_camp = document.getElementById("id_campaign").value;
114 115 //alert(id_camp);
115 116 document.location = "{% url 'url_operation'%}"+String(id_camp);
116 117 });
117 118 });
118 119 {% else %}
119 120 $(document).ready(function() {
120 121 $("#id_campaign").change(function() {
121 122 document.location = "{% url 'url_operation'%}"+$(this).val();
122 123 });
123 124 });
124 125 {% endif %}
125 126
126 127
127 128 </script>
128 129 {% endblock %}
@@ -1,1587 +1,1586
1 1 from django.shortcuts import render, redirect, get_object_or_404, HttpResponse
2 2 from django.utils.safestring import mark_safe
3 3 from django.http import HttpResponseRedirect
4 4 from django.core.urlresolvers import reverse
5 5 from django.db.models import Q
6 6 from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
7 7 from django.contrib import messages
8 8 from django.http.request import QueryDict
9 9 from datetime import datetime
10 10
11 11 try:
12 12 from urllib.parse import urlencode
13 13 except ImportError:
14 14 from urllib import urlencode
15 15
16 16 from .forms import CampaignForm, ExperimentForm, DeviceForm, ConfigurationForm, LocationForm, UploadFileForm, DownloadFileForm, OperationForm, NewForm
17 17 from .forms import OperationSearchForm, FilterForm
18 18
19 19 from apps.rc.forms import RCConfigurationForm
20 20 from apps.dds.forms import DDSConfigurationForm
21 21 from apps.jars.forms import JARSConfigurationForm
22 22 from apps.cgs.forms import CGSConfigurationForm
23 23 from apps.abs.forms import ABSConfigurationForm
24 24 from apps.usrp.forms import USRPConfigurationForm
25 25
26 26 from .models import Campaign, Experiment, Device, Configuration, Location, RunningExperiment
27 27 from apps.cgs.models import CGSConfiguration
28 28 from apps.jars.models import JARSConfiguration, EXPERIMENT_TYPE
29 29 from apps.usrp.models import USRPConfiguration
30 30 from apps.abs.models import ABSConfiguration
31 31 from apps.rc.models import RCConfiguration, RCLine, RCLineType
32 32 from apps.dds.models import DDSConfiguration
33 33 from django.http.request import QueryDict
34 34 #from __builtin__ import False
35 35
36 36 # Create your views here.
37 37
38 38 CONF_FORMS = {
39 39 'rc': RCConfigurationForm,
40 40 'dds': DDSConfigurationForm,
41 41 'jars': JARSConfigurationForm,
42 42 'cgs': CGSConfigurationForm,
43 43 'abs': ABSConfigurationForm,
44 44 'usrp': USRPConfigurationForm,
45 45 }
46 46
47 47 CONF_MODELS = {
48 48 'rc': RCConfiguration,
49 49 'dds': DDSConfiguration,
50 50 'jars': JARSConfiguration,
51 51 'cgs': CGSConfiguration,
52 52 'abs': ABSConfiguration,
53 53 'usrp': USRPConfiguration,
54 54 }
55 55
56 56 MIX_MODES = {
57 57 '0': 'P',
58 58 '1': 'S',
59 59 }
60 60
61 61 MIX_OPERATIONS = {
62 62 '0': 'OR',
63 63 '1': 'XOR',
64 64 '2': 'AND',
65 65 '3': 'NAND',
66 66 }
67 67
68 68
69 69 def index(request):
70 70 kwargs = {}
71 71
72 72 return render(request, 'index.html', kwargs)
73 73
74 74
75 75 def locations(request):
76 76
77 77 page = request.GET.get('page')
78 78 order = ('name',)
79 79
80 80 kwargs = get_paginator(Location, page, order)
81 81
82 82 kwargs['keys'] = ['name', 'description']
83 83 kwargs['title'] = 'Radar System'
84 84 kwargs['suptitle'] = 'List'
85 85
86 86 return render(request, 'base_list.html', kwargs)
87 87
88 88
89 89 def location(request, id_loc):
90 90
91 91 location = get_object_or_404(Location, pk=id_loc)
92 92
93 93 kwargs = {}
94 94 kwargs['location'] = location
95 95 kwargs['location_keys'] = ['name', 'description']
96 96
97 97 kwargs['title'] = 'Location'
98 98 kwargs['suptitle'] = 'Details'
99 99
100 100 return render(request, 'location.html', kwargs)
101 101
102 102
103 103 def location_new(request):
104 104
105 105 if request.method == 'GET':
106 106 form = LocationForm()
107 107
108 108 if request.method == 'POST':
109 109 form = LocationForm(request.POST)
110 110
111 111 if form.is_valid():
112 112 form.save()
113 113 return redirect('url_locations')
114 114
115 115 kwargs = {}
116 116 kwargs['form'] = form
117 117 kwargs['title'] = 'Radar System'
118 118 kwargs['suptitle'] = 'New'
119 119 kwargs['button'] = 'Create'
120 120
121 121 return render(request, 'base_edit.html', kwargs)
122 122
123 123
124 124 def location_edit(request, id_loc):
125 125
126 126 location = get_object_or_404(Location, pk=id_loc)
127 127
128 128 if request.method=='GET':
129 129 form = LocationForm(instance=location)
130 130
131 131 if request.method=='POST':
132 132 form = LocationForm(request.POST, instance=location)
133 133
134 134 if form.is_valid():
135 135 form.save()
136 136 return redirect('url_locations')
137 137
138 138 kwargs = {}
139 139 kwargs['form'] = form
140 140 kwargs['title'] = 'Location'
141 141 kwargs['suptitle'] = 'Edit'
142 142 kwargs['button'] = 'Update'
143 143
144 144 return render(request, 'base_edit.html', kwargs)
145 145
146 146
147 147 def location_delete(request, id_loc):
148 148
149 149 location = get_object_or_404(Location, pk=id_loc)
150 150
151 151 if request.method=='POST':
152 152
153 153 if request.user.is_staff:
154 154 location.delete()
155 155 return redirect('url_locations')
156 156
157 157 messages.error(request, 'Not enough permission to delete this object')
158 158 return redirect(location.get_absolute_url())
159 159
160 160 kwargs = {
161 161 'title': 'Delete',
162 162 'suptitle': 'Location',
163 163 'object': location,
164 164 'previous': location.get_absolute_url(),
165 165 'delete': True
166 166 }
167 167
168 168 return render(request, 'confirm.html', kwargs)
169 169
170 170
171 171 def devices(request):
172 172
173 173 page = request.GET.get('page')
174 174 order = ('device_type', 'name')
175 175
176 176 kwargs = get_paginator(Device, page, order)
177 177 kwargs['keys'] = ['name', 'ip_address', 'port_address', 'device_type']
178 178 kwargs['title'] = 'Device'
179 179 kwargs['suptitle'] = 'List'
180 180
181 181 return render(request, 'base_list.html', kwargs)
182 182
183 183
184 184 def device(request, id_dev):
185 185
186 186 device = get_object_or_404(Device, pk=id_dev)
187 187
188 188 kwargs = {}
189 189 kwargs['device'] = device
190 190 kwargs['device_keys'] = ['device_type', 'name', 'ip_address', 'port_address', 'description']
191 191
192 192 kwargs['title'] = 'Device'
193 193 kwargs['suptitle'] = 'Details'
194 194
195 195 return render(request, 'device.html', kwargs)
196 196
197 197
198 198 def device_new(request):
199 199
200 200 if request.method == 'GET':
201 201 form = DeviceForm()
202 202
203 203 if request.method == 'POST':
204 204 form = DeviceForm(request.POST)
205 205
206 206 if form.is_valid():
207 207 form.save()
208 208 return redirect('url_devices')
209 209
210 210 kwargs = {}
211 211 kwargs['form'] = form
212 212 kwargs['title'] = 'Device'
213 213 kwargs['suptitle'] = 'New'
214 214 kwargs['button'] = 'Create'
215 215
216 216 return render(request, 'base_edit.html', kwargs)
217 217
218 218
219 219 def device_edit(request, id_dev):
220 220
221 221 device = get_object_or_404(Device, pk=id_dev)
222 222
223 223 if request.method=='GET':
224 224 form = DeviceForm(instance=device)
225 225
226 226 if request.method=='POST':
227 227 form = DeviceForm(request.POST, instance=device)
228 228
229 229 if form.is_valid():
230 230 form.save()
231 231 return redirect(device.get_absolute_url())
232 232
233 233 kwargs = {}
234 234 kwargs['form'] = form
235 235 kwargs['title'] = 'Device'
236 236 kwargs['suptitle'] = 'Edit'
237 237 kwargs['button'] = 'Update'
238 238
239 239 return render(request, 'base_edit.html', kwargs)
240 240
241 241
242 242 def device_delete(request, id_dev):
243 243
244 244 device = get_object_or_404(Device, pk=id_dev)
245 245
246 246 if request.method=='POST':
247 247
248 248 if request.user.is_staff:
249 249 device.delete()
250 250 return redirect('url_devices')
251 251
252 252 messages.error(request, 'Not enough permission to delete this object')
253 253 return redirect(device.get_absolute_url())
254 254
255 255 kwargs = {
256 256 'title': 'Delete',
257 257 'suptitle': 'Device',
258 258 'object': device,
259 259 'previous': device.get_absolute_url(),
260 260 'delete': True
261 261 }
262 262
263 263 return render(request, 'confirm.html', kwargs)
264 264
265 265
266 266 def campaigns(request):
267 267
268 268 page = request.GET.get('page')
269 269 order = ('start_date',)
270 270 filters = request.GET.copy()
271 271
272 272 kwargs = get_paginator(Campaign, page, order, filters)
273 273
274 274 form = FilterForm(initial=request.GET, extra_fields=['range_date', 'tags','template'])
275 275 kwargs['keys'] = ['name', 'start_date', 'end_date']
276 276 kwargs['title'] = 'Campaign'
277 277 kwargs['suptitle'] = 'List'
278 278 kwargs['form'] = form
279 279 filters.pop('page', None)
280 280 kwargs['q'] = urlencode(filters)
281 281
282 282 return render(request, 'base_list.html', kwargs)
283 283
284 284
285 285 def campaign(request, id_camp):
286 286
287 287 campaign = get_object_or_404(Campaign, pk=id_camp)
288 288 experiments = Experiment.objects.filter(campaign=campaign)
289 289
290 290 form = CampaignForm(instance=campaign)
291 291
292 292 kwargs = {}
293 293 kwargs['campaign'] = campaign
294 294 kwargs['campaign_keys'] = ['template', 'name', 'start_date', 'end_date', 'tags', 'description']
295 295
296 296 kwargs['experiments'] = experiments
297 297 kwargs['experiment_keys'] = ['name', 'radar_system', 'start_time', 'end_time']
298 298
299 299 kwargs['title'] = 'Campaign'
300 300 kwargs['suptitle'] = 'Details'
301 301
302 302 kwargs['form'] = form
303 303 kwargs['button'] = 'Add Experiment'
304 304
305 305 return render(request, 'campaign.html', kwargs)
306 306
307 307
308 308 def campaign_new(request):
309 309
310 310 kwargs = {}
311 311
312 312 if request.method == 'GET':
313 313
314 314 if 'template' in request.GET:
315 315 if request.GET['template']=='0':
316 316 form = NewForm(initial={'create_from':2},
317 317 template_choices=Campaign.objects.filter(template=True).values_list('id', 'name'))
318 318 else:
319 319 kwargs['button'] = 'Create'
320 320 kwargs['experiments'] = Configuration.objects.filter(experiment=request.GET['template'])
321 321 kwargs['experiment_keys'] = ['name', 'start_time', 'end_time']
322 322 camp = Campaign.objects.get(pk=request.GET['template'])
323 323 form = CampaignForm(instance=camp,
324 324 initial={'name':'{} [{:%Y/%m/%d}]'.format(camp.name, datetime.now()),
325 325 'template':False})
326 326 elif 'blank' in request.GET:
327 327 kwargs['button'] = 'Create'
328 328 form = CampaignForm()
329 329 else:
330 330 form = NewForm()
331 331
332 332 if request.method == 'POST':
333 333 kwargs['button'] = 'Create'
334 334 post = request.POST.copy()
335 335 experiments = []
336 336
337 337 for id_exp in post.getlist('experiments'):
338 338 exp = Experiment.objects.get(pk=id_exp)
339 339 new_exp = exp.clone(template=False)
340 340 experiments.append(new_exp)
341 341
342 342 post.setlist('experiments', [])
343 343
344 344 form = CampaignForm(post)
345 345
346 346 if form.is_valid():
347 347 campaign = form.save()
348 348 for exp in experiments:
349 349 campaign.experiments.add(exp)
350 350 campaign.save()
351 351 return redirect('url_campaign', id_camp=campaign.id)
352 352
353 353 kwargs['form'] = form
354 354 kwargs['title'] = 'Campaign'
355 355 kwargs['suptitle'] = 'New'
356 356
357 357 return render(request, 'campaign_edit.html', kwargs)
358 358
359 359
360 360 def campaign_edit(request, id_camp):
361 361
362 362 campaign = get_object_or_404(Campaign, pk=id_camp)
363 363
364 364 if request.method=='GET':
365 365 form = CampaignForm(instance=campaign)
366 366
367 367 if request.method=='POST':
368 368 exps = campaign.experiments.all().values_list('pk', flat=True)
369 369 post = request.POST.copy()
370 370 new_exps = post.getlist('experiments')
371 371 post.setlist('experiments', [])
372 372 form = CampaignForm(post, instance=campaign)
373 373
374 374 if form.is_valid():
375 375 camp = form.save()
376 376 for id_exp in new_exps:
377 377 if int(id_exp) in exps:
378 378 exps.pop(id_exp)
379 379 else:
380 380 exp = Experiment.objects.get(pk=id_exp)
381 381 if exp.template:
382 382 camp.experiments.add(exp.clone(template=False))
383 383 else:
384 384 camp.experiments.add(exp)
385 385
386 386 for id_exp in exps:
387 387 camp.experiments.remove(Experiment.objects.get(pk=id_exp))
388 388
389 389 return redirect('url_campaign', id_camp=id_camp)
390 390
391 391 kwargs = {}
392 392 kwargs['form'] = form
393 393 kwargs['title'] = 'Campaign'
394 394 kwargs['suptitle'] = 'Edit'
395 395 kwargs['button'] = 'Update'
396 396
397 397 return render(request, 'campaign_edit.html', kwargs)
398 398
399 399
400 400 def campaign_delete(request, id_camp):
401 401
402 402 campaign = get_object_or_404(Campaign, pk=id_camp)
403 403
404 404 if request.method=='POST':
405 405 if request.user.is_staff:
406 406
407 407 for exp in campaign.experiments.all():
408 408 for conf in Configuration.objects.filter(experiment=exp):
409 409 conf.delete()
410 410 exp.delete()
411 411 campaign.delete()
412 412
413 413 return redirect('url_campaigns')
414 414
415 415 messages.error(request, 'Not enough permission to delete this object')
416 416 return redirect(campaign.get_absolute_url())
417 417
418 418 kwargs = {
419 419 'title': 'Delete',
420 420 'suptitle': 'Campaign',
421 421 'object': campaign,
422 422 'previous': campaign.get_absolute_url(),
423 423 'delete': True
424 424 }
425 425
426 426 return render(request, 'confirm.html', kwargs)
427 427
428 428 def campaign_export(request, id_camp):
429 429
430 430 campaign = get_object_or_404(Campaign, pk=id_camp)
431 431 content = campaign.parms_to_dict()
432 432 content_type = 'application/json'
433 433 filename = '%s_%s.json' %(campaign.name, campaign.id)
434 434
435 435 response = HttpResponse(content_type=content_type)
436 436 response['Content-Disposition'] = 'attachment; filename="%s"' %filename
437 437 response.write(content)
438 438
439 439 return response
440 440
441 441
442 442 def campaign_import(request, id_camp):
443 443
444 444 campaign = get_object_or_404(Campaign, pk=id_camp)
445 445
446 446 if request.method == 'GET':
447 447 file_form = UploadFileForm()
448 448
449 449 if request.method == 'POST':
450 450 file_form = UploadFileForm(request.POST, request.FILES)
451 451
452 452 if file_form.is_valid():
453 453
454 454 parms = campaign.import_from_file(request.FILES['file'])
455 455
456 456 if parms:
457 457 parms['name'] = parms['campaign']
458 458
459 459 new_camp = campaign.dict_to_parms(parms, CONF_MODELS)
460 460
461 461 messages.success(request, "Parameters imported from: '%s'." %request.FILES['file'].name)
462 462
463 463 return redirect(new_camp.get_absolute_url_edit())
464 464
465 465 messages.error(request, "Could not import parameters from file")
466 466
467 467 kwargs = {}
468 468 kwargs['title'] = 'Campaign'
469 469 kwargs['form'] = file_form
470 470 kwargs['suptitle'] = 'Importing file'
471 471 kwargs['button'] = 'Import'
472 472
473 473 return render(request, 'campaign_import.html', kwargs)
474 474
475 475
476 476 def experiments(request):
477 477
478 478 page = request.GET.get('page')
479 479 order = ('location',)
480 480 filters = request.GET.copy()
481 481
482 482 kwargs = get_paginator(Experiment, page, order, filters)
483 483
484 484 form = FilterForm(initial=request.GET, extra_fields=['tags','template'])
485 485
486 486 kwargs['keys'] = ['name', 'radar_system', 'start_time', 'end_time']
487 487 kwargs['title'] = 'Experiment'
488 488 kwargs['suptitle'] = 'List'
489 489 kwargs['form'] = form
490 490 filters.pop('page', None)
491 491 kwargs['q'] = urlencode(filters)
492 492
493 493 return render(request, 'base_list.html', kwargs)
494 494
495 495
496 496 def experiment(request, id_exp):
497 497
498 498 experiment = get_object_or_404(Experiment, pk=id_exp)
499 499
500 500 configurations = Configuration.objects.filter(experiment=experiment, type=0)
501 501
502 502 kwargs = {}
503 503
504 504 kwargs['experiment_keys'] = ['template', 'radar_system', 'name', 'start_time', 'end_time']
505 505 kwargs['experiment'] = experiment
506 506
507 507 kwargs['configuration_keys'] = ['name', 'device__ip_address', 'device__port_address', 'device__status']
508 508 kwargs['configurations'] = configurations
509 509
510 510 kwargs['title'] = 'Experiment'
511 511 kwargs['suptitle'] = 'Details'
512 512
513 513 kwargs['button'] = 'Add Configuration'
514 514
515 515 ###### SIDEBAR ######
516 516 kwargs.update(sidebar(experiment=experiment))
517 517
518 518 return render(request, 'experiment.html', kwargs)
519 519
520 520
521 521 def experiment_new(request, id_camp=None):
522 522
523 523 kwargs = {}
524 524
525 525 if request.method == 'GET':
526 526 if 'template' in request.GET:
527 527 if request.GET['template']=='0':
528 528 form = NewForm(initial={'create_from':2},
529 529 template_choices=Experiment.objects.filter(template=True).values_list('id', 'name'))
530 530 else:
531 531 kwargs['button'] = 'Create'
532 532 kwargs['configurations'] = Configuration.objects.filter(experiment=request.GET['template'])
533 533 kwargs['configuration_keys'] = ['name', 'device__name', 'device__ip_address', 'device__port_address']
534 534 exp=Experiment.objects.get(pk=request.GET['template'])
535 535 form = ExperimentForm(instance=exp,
536 536 initial={'name': '{} [{:%Y/%m/%d}]'.format(exp.name, datetime.now()),
537 537 'template': False})
538 538 elif 'blank' in request.GET:
539 539 kwargs['button'] = 'Create'
540 540 form = ExperimentForm()
541 541 else:
542 542 form = NewForm()
543 543
544 544 if request.method == 'POST':
545 545 form = ExperimentForm(request.POST)
546 546 if form.is_valid():
547 547 experiment = form.save()
548 548
549 549 if 'template' in request.GET:
550 550 configurations = Configuration.objects.filter(experiment=request.GET['template'], type=0)
551 551 for conf in configurations:
552 552 conf.clone(experiment=experiment, template=False)
553 553
554 554 return redirect('url_experiment', id_exp=experiment.id)
555 555
556 556 kwargs['form'] = form
557 557 kwargs['title'] = 'Experiment'
558 558 kwargs['suptitle'] = 'New'
559 559
560 560 return render(request, 'experiment_edit.html', kwargs)
561 561
562 562
563 563 def experiment_edit(request, id_exp):
564 564
565 565 experiment = get_object_or_404(Experiment, pk=id_exp)
566 566
567 567 if request.method == 'GET':
568 568 form = ExperimentForm(instance=experiment)
569 569
570 570 if request.method=='POST':
571 571 form = ExperimentForm(request.POST, instance=experiment)
572 572
573 573 if form.is_valid():
574 574 experiment = form.save()
575 575 return redirect('url_experiment', id_exp=experiment.id)
576 576
577 577 kwargs = {}
578 578 kwargs['form'] = form
579 579 kwargs['title'] = 'Experiment'
580 580 kwargs['suptitle'] = 'Edit'
581 581 kwargs['button'] = 'Update'
582 582
583 583 return render(request, 'experiment_edit.html', kwargs)
584 584
585 585
586 586 def experiment_delete(request, id_exp):
587 587
588 588 experiment = get_object_or_404(Experiment, pk=id_exp)
589 589
590 590 if request.method=='POST':
591 591 if request.user.is_staff:
592 592 for conf in Configuration.objects.filter(experiment=experiment):
593 593 conf.delete()
594 594 experiment.delete()
595 595 return redirect('url_experiments')
596 596
597 597 messages.error(request, 'Not enough permission to delete this object')
598 598 return redirect(experiment.get_absolute_url())
599 599
600 600 kwargs = {
601 601 'title': 'Delete',
602 602 'suptitle': 'Experiment',
603 603 'object': experiment,
604 604 'previous': experiment.get_absolute_url(),
605 605 'delete': True
606 606 }
607 607
608 608 return render(request, 'confirm.html', kwargs)
609 609
610 610
611 611 def experiment_export(request, id_exp):
612 612
613 613 experiment = get_object_or_404(Experiment, pk=id_exp)
614 614 content = experiment.parms_to_dict()
615 615 content_type = 'application/json'
616 616 filename = '%s_%s.json' %(experiment.name, experiment.id)
617 617
618 618 response = HttpResponse(content_type=content_type)
619 619 response['Content-Disposition'] = 'attachment; filename="%s"' %filename
620 620 response.write(content)
621 621
622 622 return response
623 623
624 624 def experiment_import(request, id_exp):
625 625
626 626 experiment = get_object_or_404(Experiment, pk=id_exp)
627 627 configurations = Configuration.objects.filter(experiment=experiment)
628 628
629 629 if request.method == 'GET':
630 630 file_form = UploadFileForm()
631 631
632 632 if request.method == 'POST':
633 633 file_form = UploadFileForm(request.POST, request.FILES)
634 634
635 635 if file_form.is_valid():
636 636
637 637 parms = experiment.import_from_file(request.FILES['file'])
638 638
639 639 if parms:
640 640
641 641 new_exp = experiment.dict_to_parms(parms, CONF_MODELS)
642 642
643 643 messages.success(request, "Parameters imported from: '%s'." %request.FILES['file'].name)
644 644
645 645 return redirect(new_exp.get_absolute_url_edit())
646 646
647 647 messages.error(request, "Could not import parameters from file")
648 648
649 649 kwargs = {}
650 650 kwargs['title'] = 'Experiment'
651 651 kwargs['form'] = file_form
652 652 kwargs['suptitle'] = 'Importing file'
653 653 kwargs['button'] = 'Import'
654 654
655 655 kwargs.update(sidebar(experiment=experiment))
656 656
657 657 return render(request, 'experiment_import.html', kwargs)
658 658
659 659 def experiment_mix(request, id_exp):
660 660
661 661 experiment = get_object_or_404(Experiment, pk=id_exp)
662 662 rc_confs = [conf for conf in RCConfiguration.objects.filter(experiment=id_exp,
663 663 mix=False)]
664 664
665 665 if len(rc_confs)<2:
666 666 messages.warning(request, 'You need at least two RC Configurations to make a mix')
667 667 return redirect(experiment.get_absolute_url())
668 668
669 669 mix_confs = RCConfiguration.objects.filter(experiment=id_exp, mix=True)
670 670
671 671 if mix_confs:
672 672 mix = mix_confs[0]
673 673 else:
674 674 mix = RCConfiguration(experiment=experiment,
675 675 device=rc_confs[0].device,
676 676 ipp=rc_confs[0].ipp,
677 677 clock_in=rc_confs[0].clock_in,
678 678 clock_divider=rc_confs[0].clock_divider,
679 679 mix=True,
680 680 parameters='')
681 681 mix.save()
682 682
683 683 line_type = RCLineType.objects.get(name='mix')
684 684 for i in range(len(rc_confs[0].get_lines())):
685 685 line = RCLine(rc_configuration=mix, line_type=line_type, channel=i)
686 686 line.save()
687 687
688 688 initial = {'name': mix.name,
689 689 'result': parse_mix_result(mix.parameters),
690 690 'delay': 0,
691 691 'mask': [0,1,2,3,4,5,6,7]
692 692 }
693 693
694 694 if request.method=='GET':
695 695 form = RCMixConfigurationForm(confs=rc_confs, initial=initial)
696 696
697 697 if request.method=='POST':
698 698 result = mix.parameters
699 699
700 700 if '{}|'.format(request.POST['experiment']) in result:
701 701 messages.error(request, 'Configuration already added')
702 702 else:
703 703 if 'operation' in request.POST:
704 704 operation = MIX_OPERATIONS[request.POST['operation']]
705 705 else:
706 706 operation = ' '
707 707
708 708 mode = MIX_MODES[request.POST['mode']]
709 709
710 710 if result:
711 711 result = '{}-{}|{}|{}|{}|{}'.format(mix.parameters,
712 712 request.POST['experiment'],
713 713 mode,
714 714 operation,
715 715 float(request.POST['delay']),
716 716 parse_mask(request.POST.getlist('mask'))
717 717 )
718 718 else:
719 719 result = '{}|{}|{}|{}|{}'.format(request.POST['experiment'],
720 720 mode,
721 721 operation,
722 722 float(request.POST['delay']),
723 723 parse_mask(request.POST.getlist('mask'))
724 724 )
725 725
726 726 mix.parameters = result
727 727 mix.name = request.POST['name']
728 728 mix.save()
729 729 mix.update_pulses()
730 730
731 731 initial['result'] = parse_mix_result(result)
732 732 initial['name'] = mix.name
733 733
734 734 form = RCMixConfigurationForm(initial=initial, confs=rc_confs)
735 735
736 736
737 737 kwargs = {
738 738 'title': 'Experiment',
739 739 'suptitle': 'Mix Configurations',
740 740 'form' : form,
741 741 'extra_button': 'Delete',
742 742 'button': 'Add',
743 743 'cancel': 'Back',
744 744 'previous': experiment.get_absolute_url(),
745 745 'id_exp':id_exp,
746 746
747 747 }
748 748
749 749 return render(request, 'experiment_mix.html', kwargs)
750 750
751 751
752 752 def experiment_mix_delete(request, id_exp):
753 753
754 754 conf = RCConfiguration.objects.get(experiment=id_exp, mix=True)
755 755 values = conf.parameters.split('-')
756 756 conf.parameters = '-'.join(values[:-1])
757 757 conf.save()
758 758
759 759 return redirect('url_mix_experiment', id_exp=id_exp)
760 760
761 761
762 762 def experiment_summary(request, id_exp):
763 763
764 764 import json
765 765 import ast
766 766
767 767 experiment = get_object_or_404(Experiment, pk=id_exp)
768 768 experiment_data = json.loads(experiment.parms_to_dict())
769 769 configurations = Configuration.objects.filter(experiment=experiment, type=0)
770 770
771 771 kwargs = {}
772 772
773 773 kwargs['experiment_keys'] = ['template', 'radar_system', 'name', 'start_time', 'end_time']
774 774 kwargs['experiment'] = experiment
775 775
776 776 kwargs['configuration_keys'] = ['name', 'device__ip_address', 'device__port_address', 'device__status']
777 777 kwargs['configurations'] = configurations
778 778 kwargs['experiment_data'] = experiment_data
779 779
780 780 kwargs['title'] = 'Experiment Summary'
781 781 kwargs['suptitle'] = 'Details'
782 782
783 783 kwargs['button'] = 'Verify Parameters'
784 784
785 785 jars_conf = False
786 786 rc_conf = False
787 787
788 788 for configuration in configurations:
789 789 #-------------------- JARS -----------------------:
790 790 if configuration.device.device_type.name == 'jars':
791 791 jars_conf = True
792 792 kwargs['jars_conf'] = jars_conf
793 793 kwargs['exp_type'] = EXPERIMENT_TYPE[configuration.exp_type][1]
794 794 channels_number = configuration.channels_number
795 795 exp_type = configuration.exp_type
796 796 fftpoints = configuration.fftpoints
797 797 filter_parms = configuration.filter_parms
798 798 filter_parms = ast.literal_eval(filter_parms)
799 799 spectral_number = configuration.spectral_number
800 800
801 801 #--------------------- RC ----------------------:
802 802 if configuration.device.device_type.name == 'rc':
803 803 rc_conf = True
804 804 kwargs['rc_conf'] = rc_conf
805 805 rc_lines = experiment_data['configurations']['rc']['lines']
806 806 ipp = configuration.ipp
807 807 if experiment_data['configurations']['rc']['mix'] == 'True':
808 808 tx = ''
809 809 code = ''
810 810 window = ''
811 811 else:
812 812 code = rc_lines[3]['code']
813 813
814 814 window_data = rc_lines[6]['params'][0]
815 815 h0 = str(window_data['first_height'])
816 816 dh = str(window_data['resolution'])
817 817 nsa = str(window_data['number_of_samples'])
818 818 window = 'Ho='+h0+'km\nDH='+dh+'km\nNSA='+nsa
819 819
820 820 tx = ''
821 821 if float(rc_lines[1]['delays']) == 0:
822 822 tx = rc_lines[2]['pulse_width']
823 823 elif float(rc_lines[2]['delays']) == 0:
824 824 tx = rc_lines[1]['pulse_width']
825 825 else:
826 826 tx = rc_lines[1]['pulse_width']+' | '+rc_lines[2]['pulse_width']
827 827
828 828 kwargs['tx'] = tx
829 829 kwargs['code'] = code
830 830 kwargs['window'] = window
831 831
832 832 #-------------------- DDS -----------------------:
833 833 if configuration.device.device_type.name == 'dds':
834 834 dds_conf = True
835 835 kwargs['dds_conf'] = dds_conf
836 836
837 837 #------ RC & JARS ------:
838 838 ipp = 937.5 #
839 839 nsa = 200#
840 840 dh = 1.5 #
841 841 channels_number = 5 #
842 842
843 843 if rc_conf and jars_conf:
844 844 if exp_type == 0: #Short
845 845 bytes = 2
846 846 b = nsa*2*bytes*channels_number
847 847 else: #Float
848 848 bytes = 4
849 849 channels = channels_number + spectral_number
850 850 b = nsa*2*bytes*fftpoints*channels
851 851
852 852 ipps = (ipp*pow(10,-6))/0.15
853 853 GB = 1048576.0*1024.0
854 854 Hour = 3600
855 855 rate = b/ipps
856 856 rate = rate *(1/GB)*(Hour)
857 857 kwargs['rate'] = str(rate)+" GB/h"
858 858 else:
859 859 kwargs['rate'] = ''
860 860
861 861 ###### SIDEBAR ######
862 862 kwargs.update(sidebar(experiment=experiment))
863 863
864 864 return render(request, 'experiment_summary.html', kwargs)
865 865
866 866 def experiment_verify(request, id_exp):
867 867
868 868 import json
869 869 import ast
870 870
871 871 experiment = get_object_or_404(Experiment, pk=id_exp)
872 872 experiment_data = json.loads(experiment.parms_to_dict())
873 873 configurations = Configuration.objects.filter(experiment=experiment, type=0)
874 874
875 875 kwargs = {}
876 876
877 877 kwargs['experiment_keys'] = ['template', 'radar_system', 'name', 'start_time', 'end_time']
878 878 kwargs['experiment'] = experiment
879 879
880 880 kwargs['configuration_keys'] = ['name', 'device__ip_address', 'device__port_address', 'device__status']
881 881 kwargs['configurations'] = configurations
882 882 kwargs['experiment_data'] = experiment_data
883 883
884 884 kwargs['title'] = 'Verify Experiment'
885 885 kwargs['suptitle'] = 'Parameters'
886 886
887 887 kwargs['button'] = 'Update'
888 888
889 889 jars_conf = False
890 890 rc_conf = False
891 891 dds_conf = False
892 892
893 893 for configuration in configurations:
894 894 #-------------------- JARS -----------------------:
895 895 if configuration.device.device_type.name == 'jars':
896 896 jars_conf = True
897 897 kwargs['jars_conf'] = jars_conf
898 898 filter_parms = configuration.filter_parms
899 899 filter_parms = ast.literal_eval(filter_parms)
900 900 kwargs['filter_parms'] = filter_parms
901 901 #--Sampling Frequency
902 902 clock = filter_parms['clock']
903 903 filter_2 = filter_parms['filter_2']
904 904 filter_5 = filter_parms['filter_5']
905 905 filter_fir = filter_parms['filter_fir']
906 906 samp_freq_jars = clock/filter_2/filter_5/filter_fir
907 907
908 908 kwargs['samp_freq_jars'] = samp_freq_jars
909 909 kwargs['jars'] = configuration
910 910
911 911 #--------------------- RC ----------------------:
912 912 if configuration.device.device_type.name == 'rc':
913 913 rc_conf = True
914 914 rc_parms = configuration.parms_to_dict()
915 915 if rc_parms['mix'] == 'True':
916 916 pass
917 917 else:
918 918 rc_lines = rc_parms['lines']
919 919 dh = rc_lines[6]['params'][0]['resolution']
920 920 #--Sampling Frequency
921 921 samp_freq_rc = 0.15/dh
922 922 kwargs['samp_freq_rc'] = samp_freq_rc
923 923
924 924 kwargs['rc_conf'] = rc_conf
925 925 kwargs['rc'] = configuration
926 926
927 927 #-------------------- DDS ----------------------:
928 928 if configuration.device.device_type.name == 'dds':
929 929 dds_conf = True
930 930 dds_parms = configuration.parms_to_dict()
931 931
932 932 kwargs['dds_conf'] = dds_conf
933 933 kwargs['dds'] = configuration
934 934
935 935
936 936 #------------Validation------------:
937 937 #Clock
938 938 if dds_conf and rc_conf and jars_conf:
939 939 if filter_parms['clock'] != rc_parms['clock_in'] and rc_parms['clock_in'] != dds_parms['clock']:
940 940 messages.warning(request, "Devices don't have the same clock.")
941 941 elif rc_conf and jars_conf:
942 942 if filter_parms['clock'] != rc_parms['clock_in']:
943 943 messages.warning(request, "Devices don't have the same clock.")
944 944 elif rc_conf and dds_conf:
945 945 if rc_parms['clock_in'] != dds_parms['clock']:
946 946 messages.warning(request, "Devices don't have the same clock.")
947 947 if float(samp_freq_rc) != float(dds_parms['frequencyA']):
948 948 messages.warning(request, "Devices don't have the same Frequency A.")
949 949
950 950
951 951
952 952 ###### SIDEBAR ######
953 953 kwargs.update(sidebar(experiment=experiment))
954 954
955 955
956 956
957 957
958 958
959 959 return render(request, 'experiment_verify.html', kwargs)
960 960
961 961
962 962 def parse_mix_result(s):
963 963
964 964 values = s.split('-')
965 965 html = 'EXP MOD OPE DELAY MASK\r\n'
966 966
967 967 if not values or values[0] in ('', ' '):
968 968 return mark_safe(html)
969 969
970 970 for i, value in enumerate(values):
971 971 if not value:
972 972 continue
973 973 pk, mode, operation, delay, mask = value.split('|')
974 974 conf = RCConfiguration.objects.get(pk=pk)
975 975 if i==0:
976 976 html += '{:20.18}{:3}{:4}{:9}km{:>6}\r\n'.format(
977 977 conf.name,
978 978 mode,
979 979 ' ',
980 980 delay,
981 981 mask)
982 982 else:
983 983 html += '{:20.18}{:3}{:4}{:9}km{:>6}\r\n'.format(
984 984 conf.name,
985 985 mode,
986 986 operation,
987 987 delay,
988 988 mask)
989 989
990 990 return mark_safe(html)
991 991
992 992 def parse_mask(l):
993 993
994 994 values = []
995 995
996 996 for x in range(8):
997 997 if '{}'.format(x) in l:
998 998 values.append(1)
999 999 else:
1000 1000 values.append(0)
1001 1001
1002 1002 values.reverse()
1003 1003
1004 1004 return int(''.join([str(x) for x in values]), 2)
1005 1005
1006 1006
1007 1007 def dev_confs(request):
1008 1008
1009 1009
1010 1010 page = request.GET.get('page')
1011 1011 order = ('type', 'device__device_type', 'experiment')
1012 1012 filters = request.GET.copy()
1013 1013
1014 1014 kwargs = get_paginator(Configuration, page, order, filters)
1015 1015
1016 1016 form = FilterForm(initial=request.GET, extra_fields=['tags','template'])
1017 1017 kwargs['keys'] = ['name', 'experiment', 'type', 'programmed_date']
1018 1018 kwargs['title'] = 'Configuration'
1019 1019 kwargs['suptitle'] = 'List'
1020 1020 kwargs['form'] = form
1021 1021 filters.pop('page', None)
1022 1022 kwargs['q'] = urlencode(filters)
1023 1023
1024 1024 return render(request, 'base_list.html', kwargs)
1025 1025
1026 1026
1027 1027 def dev_conf(request, id_conf):
1028 1028
1029 1029 conf = get_object_or_404(Configuration, pk=id_conf)
1030 1030
1031 1031 return redirect(conf.get_absolute_url())
1032 1032
1033 1033
1034 1034 def dev_conf_new(request, id_exp=0, id_dev=0):
1035 1035
1036 1036 initial = {}
1037 1037 kwargs = {}
1038 1038
1039 1039 if id_exp!=0:
1040 1040 initial['experiment'] = id_exp
1041 1041
1042 1042 if id_dev!=0:
1043 1043 initial['device'] = id_dev
1044 1044
1045 1045 if request.method == 'GET':
1046 1046
1047 1047 if id_dev:
1048 1048 kwargs['button'] = 'Create'
1049 1049 device = Device.objects.get(pk=id_dev)
1050 1050 DevConfForm = CONF_FORMS[device.device_type.name]
1051 1051 initial['name'] = request.GET['name']
1052 1052 form = DevConfForm(initial=initial)
1053 1053 else:
1054 1054 if 'template' in request.GET:
1055 1055 if request.GET['template']=='0':
1056 1056 choices = [(conf.pk, '{}'.format(conf)) for conf in Configuration.objects.filter(template=True)]
1057 1057 form = NewForm(initial={'create_from':2},
1058 1058 template_choices=choices)
1059 1059 else:
1060 1060 kwargs['button'] = 'Create'
1061 1061 conf = Configuration.objects.get(pk=request.GET['template'])
1062 1062 id_dev = conf.device.pk
1063 1063 DevConfForm = CONF_FORMS[conf.device.device_type.name]
1064 1064 form = DevConfForm(instance=conf,
1065 1065 initial={'name': '{} [{:%Y/%m/%d}]'.format(conf.name, datetime.now()),
1066 1066 'template': False,
1067 1067 'experiment':id_exp})
1068 1068 elif 'blank' in request.GET:
1069 1069 kwargs['button'] = 'Create'
1070 1070 form = ConfigurationForm(initial=initial)
1071 1071 else:
1072 1072 form = NewForm()
1073 1073
1074 1074 if request.method == 'POST':
1075 1075
1076 1076 device = Device.objects.get(pk=request.POST['device'])
1077 1077 DevConfForm = CONF_FORMS[device.device_type.name]
1078 1078
1079 1079 form = DevConfForm(request.POST)
1080 1080 kwargs['button'] = 'Create'
1081 1081 if form.is_valid():
1082 1082 conf = form.save()
1083 1083
1084 1084 if 'template' in request.GET and conf.device.device_type.name=='rc':
1085 1085 lines = RCLine.objects.filter(rc_configuration=request.GET['template'])
1086 1086 for line in lines:
1087 1087 line.clone(rc_configuration=conf)
1088 1088
1089 1089 if conf.device.device_type.name=='jars':
1090 1090 conf.add_parms_to_filter()
1091 1091
1092 1092 return redirect('url_dev_conf', id_conf=conf.pk)
1093 1093
1094 1094 kwargs['id_exp'] = id_exp
1095 1095 kwargs['form'] = form
1096 1096 kwargs['title'] = 'Configuration'
1097 1097 kwargs['suptitle'] = 'New'
1098 1098
1099 1099
1100 1100 if id_dev != 0:
1101 1101 device = Device.objects.get(pk=id_dev)
1102 1102 kwargs['device'] = device.device_type.name
1103 1103
1104 1104 return render(request, 'dev_conf_edit.html', kwargs)
1105 1105
1106 1106
1107 1107 def dev_conf_edit(request, id_conf):
1108 1108
1109 1109 conf = get_object_or_404(Configuration, pk=id_conf)
1110 1110
1111 1111 DevConfForm = CONF_FORMS[conf.device.device_type.name]
1112 1112
1113 1113 if request.method=='GET':
1114 1114 form = DevConfForm(instance=conf)
1115 1115
1116 1116 if request.method=='POST':
1117 1117 form = DevConfForm(request.POST, instance=conf)
1118 1118
1119 1119 if form.is_valid():
1120 1120 form.save()
1121 1121 return redirect('url_dev_conf', id_conf=id_conf)
1122 1122
1123 1123 kwargs = {}
1124 1124 kwargs['form'] = form
1125 1125 kwargs['title'] = 'Device Configuration'
1126 1126 kwargs['suptitle'] = 'Edit'
1127 1127 kwargs['button'] = 'Update'
1128 1128
1129 1129 ###### SIDEBAR ######
1130 1130 kwargs.update(sidebar(conf=conf))
1131 1131
1132 1132 return render(request, '%s_conf_edit.html' % conf.device.device_type.name, kwargs)
1133 1133
1134 1134
1135 1135 def dev_conf_start(request, id_conf):
1136 1136
1137 1137 conf = get_object_or_404(Configuration, pk=id_conf)
1138 1138
1139 1139 if conf.start_device():
1140 1140 messages.success(request, conf.message)
1141 1141 else:
1142 1142 messages.error(request, conf.message)
1143 1143
1144 1144 conf.status_device()
1145 1145
1146 1146 return redirect(conf.get_absolute_url())
1147 1147
1148 1148
1149 1149 def dev_conf_stop(request, id_conf):
1150 1150
1151 1151 conf = get_object_or_404(Configuration, pk=id_conf)
1152 1152
1153 1153 if conf.stop_device():
1154 1154 messages.success(request, conf.message)
1155 1155 else:
1156 1156 messages.error(request, conf.message)
1157 1157
1158 1158 conf.status_device()
1159 1159
1160 1160 return redirect(conf.get_absolute_url())
1161 1161
1162 1162
1163 1163 def dev_conf_status(request, id_conf):
1164 1164
1165 1165 conf = get_object_or_404(Configuration, pk=id_conf)
1166 1166
1167 1167 if conf.status_device():
1168 1168 messages.success(request, conf.message)
1169 1169 else:
1170 1170 messages.error(request, conf.message)
1171 1171
1172 1172 return redirect(conf.get_absolute_url())
1173 1173
1174 1174
1175 1175 def dev_conf_write(request, id_conf):
1176 1176
1177 1177 conf = get_object_or_404(Configuration, pk=id_conf)
1178 1178
1179 1179 answer = conf.write_device()
1180 1180 conf.status_device()
1181 1181
1182 1182 if answer:
1183 1183 messages.success(request, conf.message)
1184 1184
1185 1185 #Creating a historical configuration
1186 1186 conf.clone(type=1, template=False)
1187 1187
1188 1188 #Original configuration
1189 1189 conf = DevConfModel.objects.get(pk=id_conf)
1190 1190 else:
1191 1191 messages.error(request, conf.message)
1192 1192
1193 1193 return redirect(conf.get_absolute_url())
1194 1194
1195 1195
1196 1196 def dev_conf_read(request, id_conf):
1197 1197
1198 1198 conf = get_object_or_404(Configuration, pk=id_conf)
1199 1199
1200 1200 DevConfForm = CONF_FORMS[conf.device.device_type.name]
1201 1201
1202 1202 if request.method=='GET':
1203 1203
1204 1204 parms = conf.read_device()
1205 1205 conf.status_device()
1206 1206
1207 1207 if not parms:
1208 1208 messages.error(request, conf.message)
1209 1209 return redirect(conf.get_absolute_url())
1210 1210
1211 1211 form = DevConfForm(initial=parms, instance=conf)
1212 1212
1213 1213 if request.method=='POST':
1214 1214 form = DevConfForm(request.POST, instance=conf)
1215 1215
1216 1216 if form.is_valid():
1217 1217 form.save()
1218 1218 return redirect(conf.get_absolute_url())
1219 1219
1220 1220 messages.error(request, "Parameters could not be saved")
1221 1221
1222 1222 kwargs = {}
1223 1223 kwargs['id_dev'] = conf.id
1224 1224 kwargs['form'] = form
1225 1225 kwargs['title'] = 'Device Configuration'
1226 1226 kwargs['suptitle'] = 'Parameters read from device'
1227 1227 kwargs['button'] = 'Save'
1228 1228
1229 1229 ###### SIDEBAR ######
1230 1230 kwargs.update(sidebar(conf=conf))
1231 1231
1232 1232 return render(request, '%s_conf_edit.html' %conf.device.device_type.name, kwargs)
1233 1233
1234 1234
1235 1235 def dev_conf_import(request, id_conf):
1236 1236
1237 1237 conf = get_object_or_404(Configuration, pk=id_conf)
1238 1238 DevConfForm = CONF_FORMS[conf.device.device_type.name]
1239 1239
1240 1240 if request.method == 'GET':
1241 1241 file_form = UploadFileForm()
1242 1242
1243 1243 if request.method == 'POST':
1244 1244 file_form = UploadFileForm(request.POST, request.FILES)
1245 1245
1246 1246 if file_form.is_valid():
1247 1247
1248 1248 parms = conf.import_from_file(request.FILES['file'])
1249 1249
1250 1250 if parms:
1251 1251 messages.success(request, "Parameters imported from: '%s'." %request.FILES['file'].name)
1252 1252 form = DevConfForm(initial=parms, instance=conf)
1253 1253
1254 1254 kwargs = {}
1255 1255 kwargs['id_dev'] = conf.id
1256 1256 kwargs['form'] = form
1257 1257 kwargs['title'] = 'Device Configuration'
1258 1258 kwargs['suptitle'] = 'Parameters imported'
1259 1259 kwargs['button'] = 'Save'
1260 1260 kwargs['action'] = conf.get_absolute_url_edit()
1261 1261 kwargs['previous'] = conf.get_absolute_url()
1262 1262
1263 1263 ###### SIDEBAR ######
1264 1264 kwargs.update(sidebar(conf=conf))
1265 1265
1266 1266 return render(request, '%s_conf_edit.html' % conf.device.device_type.name, kwargs)
1267 1267
1268 1268 messages.error(request, "Could not import parameters from file")
1269 1269
1270 1270 kwargs = {}
1271 1271 kwargs['id_dev'] = conf.id
1272 1272 kwargs['title'] = 'Device Configuration'
1273 1273 kwargs['form'] = file_form
1274 1274 kwargs['suptitle'] = 'Importing file'
1275 1275 kwargs['button'] = 'Import'
1276 1276
1277 1277 kwargs.update(sidebar(conf=conf))
1278 1278
1279 1279 return render(request, 'dev_conf_import.html', kwargs)
1280 1280
1281 1281
1282 1282 def dev_conf_export(request, id_conf):
1283 1283
1284 1284 conf = get_object_or_404(Configuration, pk=id_conf)
1285 1285
1286 1286 if request.method == 'GET':
1287 1287 file_form = DownloadFileForm(conf.device.device_type.name)
1288 1288
1289 1289 if request.method == 'POST':
1290 1290 file_form = DownloadFileForm(conf.device.device_type.name, request.POST)
1291 1291
1292 1292 if file_form.is_valid():
1293 1293 fields = conf.export_to_file(format = file_form.cleaned_data['format'])
1294 1294
1295 1295 response = HttpResponse(content_type=fields['content_type'])
1296 1296 response['Content-Disposition'] = 'attachment; filename="%s"' %fields['filename']
1297 1297 response.write(fields['content'])
1298 1298
1299 1299 return response
1300 1300
1301 1301 messages.error(request, "Could not export parameters")
1302 1302
1303 1303 kwargs = {}
1304 1304 kwargs['id_dev'] = conf.id
1305 1305 kwargs['title'] = 'Device Configuration'
1306 1306 kwargs['form'] = file_form
1307 1307 kwargs['suptitle'] = 'Exporting file'
1308 1308 kwargs['button'] = 'Export'
1309 1309
1310 1310 return render(request, 'dev_conf_export.html', kwargs)
1311 1311
1312 1312
1313 1313 def dev_conf_delete(request, id_conf):
1314 1314
1315 1315 conf = get_object_or_404(Configuration, pk=id_conf)
1316 1316
1317 1317 if request.method=='POST':
1318 1318 if request.user.is_staff:
1319 1319 conf.delete()
1320 1320 return redirect('url_dev_confs')
1321 1321
1322 1322 messages.error(request, 'Not enough permission to delete this object')
1323 1323 return redirect(conf.get_absolute_url())
1324 1324
1325 1325 kwargs = {
1326 1326 'title': 'Delete',
1327 1327 'suptitle': 'Experiment',
1328 1328 'object': conf,
1329 1329 'previous': conf.get_absolute_url(),
1330 1330 'delete': True
1331 1331 }
1332 1332
1333 1333 return render(request, 'confirm.html', kwargs)
1334 1334
1335 1335
1336 1336 def sidebar(**kwargs):
1337 1337
1338 1338 side_data = {}
1339 1339
1340 1340 conf = kwargs.get('conf', None)
1341 1341 experiment = kwargs.get('experiment', None)
1342 1342
1343 1343 if not experiment:
1344 1344 experiment = conf.experiment
1345 1345
1346 1346 if experiment:
1347 1347 side_data['experiment'] = experiment
1348 1348 campaign = experiment.campaign_set.all()
1349 1349 if campaign:
1350 1350 side_data['campaign'] = campaign[0]
1351 1351 experiments = campaign[0].experiments.all()
1352 1352 else:
1353 1353 experiments = [experiment]
1354 1354 configurations = experiment.configuration_set.filter(type=0)
1355 1355 side_data['side_experiments'] = experiments
1356 1356 side_data['side_configurations'] = configurations
1357 1357
1358 1358 return side_data
1359 1359
1360 1360 def get_paginator(model, page, order, filters={}, n=10):
1361 1361
1362 1362 kwargs = {}
1363 1363 query = Q()
1364 1364 if isinstance(filters, QueryDict):
1365 1365 filters = filters.dict()
1366 1366 [filters.pop(key) for key in filters.keys() if filters[key] in ('', ' ')]
1367 1367 filters.pop('page', None)
1368 1368
1369 1369 if 'start_date' in filters:
1370 1370 filters['start_date__gte'] = filters.pop('start_date')
1371 1371 if 'end_date' in filters:
1372 1372 filters['start_date__lte'] = filters.pop('end_date')
1373 1373 if 'tags' in filters:
1374 1374 tags = filters.pop('tags')
1375 1375 if 'tags' in model._meta.get_all_field_names():
1376 1376 query = query | Q(tags__icontains=tags)
1377 1377 if 'name' in model._meta.get_all_field_names():
1378 1378 query = query | Q(name__icontains=tags)
1379 1379 if 'location' in model._meta.get_all_field_names():
1380 1380 query = query | Q(location__name__icontains=tags)
1381 1381 if 'device' in model._meta.get_all_field_names():
1382 1382 query = query | Q(device__name__icontains=tags)
1383 1383
1384 1384 object_list = model.objects.filter(query, **filters).order_by(*order)
1385 1385 paginator = Paginator(object_list, n)
1386 1386
1387 1387 try:
1388 1388 objects = paginator.page(page)
1389 1389 except PageNotAnInteger:
1390 1390 objects = paginator.page(1)
1391 1391 except EmptyPage:
1392 1392 objects = paginator.page(paginator.num_pages)
1393 1393
1394 1394 kwargs['objects'] = objects
1395 1395 kwargs['offset'] = (int(page)-1)*n if page else 0
1396 1396
1397 1397 return kwargs
1398 1398
1399 1399 def operation(request, id_camp=None):
1400 1400
1401 1401 kwargs = {}
1402 kwargs['no_sidebar'] = True
1402 1403 campaigns = Campaign.objects.filter(start_date__lte=datetime.now(),
1403 1404 end_date__gte=datetime.now()).order_by('-start_date')
1404 1405
1405 1406
1406 1407 if id_camp:
1407 1408 campaign = get_object_or_404(Campaign, pk = id_camp)
1408 1409 form = OperationForm(initial={'campaign': campaign.id}, campaigns=campaigns)
1409 1410 kwargs['campaign'] = campaign
1410 1411 else:
1411 1412 form = OperationForm(campaigns=campaigns)
1412 1413 kwargs['form'] = form
1413 1414 return render(request, 'operation.html', kwargs)
1414 1415
1415
1416
1417 1416 #---Experiment
1418 1417 keys = ['id', 'name', 'start_time', 'end_time', 'status']
1419 1418 kwargs['experiment_keys'] = keys[1:]
1420 1419 kwargs['experiments'] = experiments
1421 1420 #---Radar
1422 1421 kwargs['locations'] = campaign.get_experiments_by_location()
1423 1422 #---Else
1424 1423 kwargs['title'] = 'Campaign'
1425 1424 kwargs['suptitle'] = campaign.name
1426 kwargs['form'] = form
1425 kwargs['form'] = form
1427 1426
1428 1427 return render(request, 'operation.html', kwargs)
1429 1428
1430 1429
1431 1430 def operation_search(request, id_camp=None):
1432 1431
1433 1432
1434 1433 if not id_camp:
1435 1434 campaigns = Campaign.objects.all().order_by('-start_date')
1436 1435
1437 1436 if not campaigns:
1438 1437 return render(request, 'operation.html', {})
1439 1438
1440 1439 id_camp = campaigns[0].id
1441 1440 campaign = get_object_or_404(Campaign, pk = id_camp)
1442 1441
1443 1442 if request.method=='GET':
1444 1443 form = OperationSearchForm(initial={'campaign': campaign.id})
1445 1444
1446 1445 if request.method=='POST':
1447 1446 form = OperationSearchForm(request.POST, initial={'campaign':campaign.id})
1448 1447
1449 1448 if form.is_valid():
1450 1449 return redirect('url_operation', id_camp=campaign.id)
1451 1450
1452 1451 #locations = Location.objects.filter(experiment__campaign__pk = campaign.id).distinct()
1453 1452 experiments = Experiment.objects.filter(campaign__pk=campaign.id)
1454 1453 #for exs in experiments:
1455 1454 # exs.get_status()
1456 1455 locations= Location.objects.filter(experiment=experiments).distinct()
1457 1456 form = OperationSearchForm(initial={'campaign': campaign.id})
1458 1457
1459 1458 kwargs = {}
1460 1459 #---Campaign
1461 1460 kwargs['campaign'] = campaign
1462 1461 kwargs['campaign_keys'] = ['name', 'start_date', 'end_date', 'tags', 'description']
1463 1462 #---Experiment
1464 1463 keys = ['id', 'name', 'start_time', 'end_time', 'status']
1465 1464 kwargs['experiment_keys'] = keys[1:]
1466 1465 kwargs['experiments'] = experiments
1467 1466 #---Radar
1468 1467 kwargs['locations'] = locations
1469 1468 #---Else
1470 1469 kwargs['title'] = 'Campaign'
1471 1470 kwargs['suptitle'] = campaign.name
1472 1471 kwargs['form'] = form
1473 1472 kwargs['button'] = 'Select'
1474 1473 kwargs['details'] = True
1475 1474 kwargs['search_button'] = False
1476 1475
1477 1476 return render(request, 'operation.html', kwargs)
1478 1477
1479 1478
1480 1479 def radar_play(request, id_camp, id_radar):
1481 1480 campaign = get_object_or_404(Campaign, pk = id_camp)
1482 1481 radar = get_object_or_404(Location, pk = id_radar)
1483 1482 today = datetime.today()
1484 1483 now = today.time()
1485 1484
1486 1485 #--Clear Old Experiments From RunningExperiment Object
1487 1486 running_experiment = RunningExperiment.objects.filter(radar=radar)
1488 1487 if running_experiment:
1489 1488 running_experiment = running_experiment[0]
1490 1489 running_experiment.running_experiment.clear()
1491 1490 running_experiment.save()
1492 1491
1493 1492 #--If campaign datetime is ok:
1494 1493 if today >= campaign.start_date and today <= campaign.end_date:
1495 1494 experiments = Experiment.objects.filter(campaign=campaign).filter(location=radar)
1496 1495 for exp in experiments:
1497 1496 #--If experiment time is ok:
1498 1497 if now >= exp.start_time and now <= exp.end_time:
1499 1498 configurations = Configuration.objects.filter(experiment = exp)
1500 1499 for conf in configurations:
1501 1500 if 'cgs' in conf.device.device_type.name:
1502 1501 conf.status_device()
1503 1502 else:
1504 1503 answer = conf.start_device()
1505 1504 conf.status_device()
1506 1505 #--Running Experiment
1507 1506 old_running_experiment = RunningExperiment.objects.filter(radar=radar)
1508 1507 #--If RunningExperiment element exists
1509 1508 if old_running_experiment:
1510 1509 old_running_experiment = old_running_experiment[0]
1511 1510 old_running_experiment.running_experiment.add(exp)
1512 1511 old_running_experiment.status = 3
1513 1512 old_running_experiment.save()
1514 1513 #--Create a new Running_Experiment Object
1515 1514 else:
1516 1515 new_running_experiment = RunningExperiment(
1517 1516 radar = radar,
1518 1517 status = 3,
1519 1518 )
1520 1519 new_running_experiment.save()
1521 1520 new_running_experiment.running_experiment.add(exp)
1522 1521 new_running_experiment.save()
1523 1522
1524 1523 if answer:
1525 1524 messages.success(request, conf.message)
1526 1525 exp.status=2
1527 1526 exp.save()
1528 1527 else:
1529 1528 messages.error(request, conf.message)
1530 1529 else:
1531 1530 if exp.status == 1 or exp.status == 3:
1532 1531 exp.status=3
1533 1532 exp.save()
1534 1533
1535 1534
1536 1535 route = request.META['HTTP_REFERER']
1537 1536 route = str(route)
1538 1537 if 'search' in route:
1539 1538 return HttpResponseRedirect(reverse('url_operation_search', args=[id_camp]))
1540 1539 else:
1541 1540 return HttpResponseRedirect(reverse('url_operation', args=[id_camp]))
1542 1541
1543 1542
1544 1543 def radar_stop(request, id_camp, id_radar):
1545 1544 campaign = get_object_or_404(Campaign, pk = id_camp)
1546 1545 radar = get_object_or_404(Location, pk = id_radar)
1547 1546 experiments = Experiment.objects.filter(campaign=campaign).filter(location=radar)
1548 1547
1549 1548 for exp in experiments:
1550 1549 configurations = Configuration.objects.filter(experiment = exp)
1551 1550 for conf in configurations:
1552 1551 if 'cgs' in conf.device.device_type.name:
1553 1552 conf.status_device()
1554 1553 else:
1555 1554 answer = conf.stop_device()
1556 1555 conf.status_device()
1557 1556
1558 1557 if answer:
1559 1558 messages.success(request, conf.message)
1560 1559 exp.status=1
1561 1560 exp.save()
1562 1561 else:
1563 1562 messages.error(request, conf.message)
1564 1563
1565 1564
1566 1565 route = request.META['HTTP_REFERER']
1567 1566 route = str(route)
1568 1567 if 'search' in route:
1569 1568 return HttpResponseRedirect(reverse('url_operation_search', args=[id_camp]))
1570 1569 else:
1571 1570 return HttpResponseRedirect(reverse('url_operation', args=[id_camp]))
1572 1571
1573 1572
1574 1573 def radar_refresh(request, id_camp, id_radar):
1575 1574
1576 1575 campaign = get_object_or_404(Campaign, pk = id_camp)
1577 1576 radar = get_object_or_404(Location, pk = id_radar)
1578 1577 experiments = Experiment.objects.filter(campaign=campaign).filter(location=radar)
1579 1578 for exs in experiments:
1580 1579 exs.get_status()
1581 1580
1582 1581 route = request.META['HTTP_REFERER']
1583 1582 route = str(route)
1584 1583 if 'search' in route:
1585 1584 return HttpResponseRedirect(reverse('url_operation_search', args=[id_camp]))
1586 1585 else:
1587 1586 return HttpResponseRedirect(reverse('url_operation', args=[id_camp]))
@@ -1,786 +1,878
1 1
2 2 import ast
3 3 import json
4 import requests
4 5 import numpy as np
6 from base64 import b64encode
5 7
6 8 from django.db import models
7 9 from django.core.urlresolvers import reverse
8 10 from django.core.validators import MinValueValidator, MaxValueValidator
9 11
10 12 from apps.main.models import Configuration
11 13 from devices.rc import api
12 14 from .utils import RCFile
13 15
14 16 # Create your models here.
15 17
16 18 LINE_TYPES = (
17 19 ('none', 'Not used'),
18 20 ('tr', 'Transmission/reception selector signal'),
19 21 ('tx', 'A modulating signal (Transmission pulse)'),
20 22 ('codes', 'BPSK modulating signal'),
21 23 ('windows', 'Sample window signal'),
22 24 ('sync', 'Synchronizing signal'),
23 25 ('flip', 'IPP related periodic signal'),
24 26 ('prog_pulses', 'Programmable pulse'),
25 27 ('mix', 'Mixed line'),
26 28 )
27 29
28 30
29 31 SAMPLING_REFS = (
30 32 ('none', 'No Reference'),
31 33 ('begin_baud', 'Begin of the first baud'),
32 34 ('first_baud', 'Middle of the first baud'),
33 35 ('sub_baud', 'Middle of the sub-baud')
34 36 )
35 37
36 38 DAT_CMDS = {
37 39 # Pulse Design commands
38 40 'DISABLE' : 0, # Disables pulse generation
39 41 'ENABLE' : 24, # Enables pulse generation
40 42 'DELAY_START' : 40, # Write delay status to memory
41 43 'FLIP_START' : 48, # Write flip status to memory
42 44 'SAMPLING_PERIOD' : 64, # Establish Sampling Period
43 45 'TX_ONE' : 72, # Output '0' in line TX
44 46 'TX_ZERO' : 88, # Output '0' in line TX
45 47 'SW_ONE' : 104, # Output '0' in line SW
46 48 'SW_ZERO' : 112, # Output '1' in line SW
47 49 'RESTART': 120, # Restarts CR8 Firmware
48 50 'CONTINUE' : 253, # Function Unknown
49 51 # Commands available to new controllers
50 52 # In Pulse Design Executable, the clock divisor code is written as 12 at the start, but it should be written as code 22(below) just before the final enable.
51 53 'CLOCK_DIVISOR_INIT' : 12, # Specifies Clock Divisor. Legacy command, ignored in the actual .dat conversion
52 54 'CLOCK_DIVISOR_LAST' : 22, # Specifies Clock Divisor (default 60 if not included) syntax: 255,22 254,N-1.
53 55 'CLOCK_DIVIDER' : 8,
54 56 }
55 57
56 58
57 59 class RCConfiguration(Configuration):
58 60
59 61 ipp = models.FloatField(verbose_name='IPP [Km]', validators=[MinValueValidator(1), MaxValueValidator(9000)], default=300)
60 62 ntx = models.PositiveIntegerField(verbose_name='Number of TX', validators=[MinValueValidator(1), MaxValueValidator(400)], default=1)
61 63 clock_in = models.FloatField(verbose_name='Clock in [MHz]', validators=[MinValueValidator(1), MaxValueValidator(80)], default=1)
62 64 clock_divider = models.PositiveIntegerField(verbose_name='Clock divider', validators=[MinValueValidator(1), MaxValueValidator(256)], default=1)
63 65 clock = models.FloatField(verbose_name='Clock Master [MHz]', blank=True, default=1)
64 66 time_before = models.PositiveIntegerField(verbose_name='Time before [&mu;S]', default=12)
65 67 time_after = models.PositiveIntegerField(verbose_name='Time after [&mu;S]', default=1)
66 68 sync = models.PositiveIntegerField(verbose_name='Synchro delay', default=0)
67 69 sampling_reference = models.CharField(verbose_name='Sampling Reference', choices=SAMPLING_REFS, default='none', max_length=40)
68 70 control_tx = models.BooleanField(verbose_name='Control Switch TX', default=False)
69 71 control_sw = models.BooleanField(verbose_name='Control Switch SW', default=False)
70 72 total_units = models.PositiveIntegerField(default=0)
71 73 mix = models.BooleanField(default=False)
72 74
73 75 class Meta:
74 76 db_table = 'rc_configurations'
75 77
76 78 def get_absolute_url_plot(self):
77 79 return reverse('url_plot_rc_pulses', args=[str(self.id)])
78 80
79 81 def get_absolute_url_import(self):
80 82 return reverse('url_import_rc_conf', args=[str(self.id)])
81 83
82 84 @property
83 85 def ipp_unit(self):
84 86
85 87 return '{} ({})'.format(self.ipp, int(self.ipp*self.km2unit))
86 88
87 89 @property
88 90 def us2unit(self):
89 91
90 92 return self.clock_in/self.clock_divider
91 93
92 94 @property
93 95 def km2unit(self):
94 96
95 97 return 20./3*(self.clock_in/self.clock_divider)
96 98
97 99 def clone(self, **kwargs):
98 100
99 101 lines = self.get_lines()
100 102 self.pk = None
101 103 self.id = None
102 104 for attr, value in kwargs.items():
103 105 setattr(self, attr, value)
104 106 self.save()
105 107
106 108 for line in lines:
107 109 line.clone(rc_configuration=self)
108 110
109 111 return self
110 112
111 113 def get_lines(self, **kwargs):
112 114 '''
113 115 Retrieve configuration lines
114 116 '''
115 117
116 118 return RCLine.objects.filter(rc_configuration=self.pk, **kwargs)
117 119
118 120
119 121 def clean_lines(self):
120 122 '''
121 123 '''
122 124
123 125 empty_line = RCLineType.objects.get(name='none')
124 126
125 127 for line in self.get_lines():
126 128 line.line_type = empty_line
127 129 line.params = '{}'
128 130 line.save()
129 131
130 132 def parms_to_dict(self):
131 133 '''
132 134 '''
133 135
134 136 ignored = ('parameters', 'type', 'polymorphic_ctype', 'configuration_ptr',
135 137 'created_date', 'programmed_date')
136 138
137 139 data = {}
138 140 for field in self._meta.fields:
139 141 if field.name in ignored:
140 142 continue
141 143 data[field.name] = '{}'.format(field.value_from_object(self))
142 144
143 145 data['device_id'] = data.pop('device')
144 146 data['lines'] = []
145 147
146 148 for line in self.get_lines():
147 149 line_data = json.loads(line.params)
148 150 if 'TX_ref' in line_data and line_data['TX_ref'] not in (0, '0'):
149 151 line_data['TX_ref'] = RCLine.objects.get(pk=line_data['TX_ref']).get_name()
150 152 if 'code' in line_data:
151 153 line_data['code'] = RCLineCode.objects.get(pk=line_data['code']).name
152 154 line_data['type'] = line.line_type.name
153 155 line_data['name'] = line.get_name()
154 156 data['lines'].append(line_data)
155 157
156 158 data['delays'] = self.get_delays()
157 159 data['pulses'] = self.get_pulses()
158 160
159 161 return data
160 162
161 163 def dict_to_parms(self, data):
162 164 '''
163 165 '''
164 166
165 167 self.name = data['name']
166 168 self.ipp = float(data['ipp'])
167 169 self.ntx = int(data['ntx'])
168 170 self.clock_in = float(data['clock_in'])
169 171 self.clock_divider = int(data['clock_divider'])
170 172 self.clock = float(data['clock'])
171 173 self.time_before = data['time_before']
172 174 self.time_after = data['time_after']
173 175 self.sync = data['sync']
174 176 self.sampling_reference = data['sampling_reference']
175 177 self.total_units = self.ipp*self.ntx*self.km2unit
176 178 self.save()
177 179 self.clean_lines()
178 180
179 181 lines = []
180 182 positions = {'tx':0, 'tr':0}
181 183
182 184 for i, line_data in enumerate(data['lines']):
183 185 name = line_data.pop('name', '')
184 186 line_type = RCLineType.objects.get(name=line_data.pop('type'))
185 187 if line_type.name=='codes':
186 188 code = RCLineCode.objects.get(name=line_data['code'])
187 189 line_data['code'] = code.pk
188 190 line = RCLine.objects.filter(rc_configuration=self, channel=i)
189 191 if line:
190 192 line = line[0]
191 193 line.line_type = line_type
192 194 line.params = json.dumps(line_data)
193 195 else:
194 196 line = RCLine(rc_configuration=self, line_type=line_type,
195 197 params=json.dumps(line_data),
196 198 channel=i)
197 199
198 200 if line_type.name=='tx':
199 201 line.position = positions['tx']
200 202 positions['tx'] += 1
201 203
202 204 if line_type.name=='tr':
203 205 line.position = positions['tr']
204 206 positions['tr'] += 1
205 207
206 208 line.save()
207 209 lines.append(line)
208 210
209 211 for line, line_data in zip(lines, data['lines']):
210 212 if 'TX_ref' in line_data:
211 213 params = json.loads(line.params)
212 214 if line_data['TX_ref'] in (0, '0'):
213 215 params['TX_ref'] = '0'
214 216 else:
215 217 params['TX_ref'] = [l.pk for l in lines if l.line_type.name=='tx' and line_data['TX_ref'] in l.get_name()][0]
216 218 line.params = json.dumps(params)
217 219 line.save()
218 220
219 221
220 222 def get_delays(self):
221 223
222 224 pulses = [line.pulses_as_points() for line in self.get_lines()]
223 225 points = [tup for tups in pulses for tup in tups]
224 226 points = set([x for tup in points for x in tup])
225 227 points = list(points)
226 228 points.sort()
227 229
228 230 if points[0]!=0:
229 231 points.insert(0, 0)
230 232
231 233 return [points[i+1]-points[i] for i in range(len(points)-1)]
232 234
233 235
234 236 def get_pulses(self, binary=True):
235 237
236 238 pulses = [line.pulses_as_points() for line in self.get_lines()]
237 239 points = [tup for tups in pulses for tup in tups]
238 240 points = set([x for tup in points for x in tup])
239 241 points = list(points)
240 242 points.sort()
241 243
242 244 line_points = [line.pulses_as_points() for line in self.get_lines()]
243 245 line_points = [[(x, x+y) for x,y in tups] for tups in line_points]
244 246 line_points = [[t for x in tups for t in x] for tups in line_points]
245 247 states = [[1 if x in tups else 0 for tups in line_points] for x in points]
246 248
247 249 if binary:
248 250 states.reverse()
249 251 states = [int(''.join([str(x) for x in flips]), 2) for flips in states]
250 252
251 253 return states[:-1]
252 254
253 255 def add_cmd(self, cmd):
254 256
255 257 if cmd in DAT_CMDS:
256 258 return (255, DAT_CMDS[cmd])
257 259
258 260 def add_data(self, value):
259 261
260 262 return (254, value-1)
261
262 def parms_to_binary(self):
263
264 def parms_to_binary(self, dat=True):
263 265 '''
264 266 Create "dat" stream to be send to CR
265 267 '''
266 268
267 data = []
269 data = bytearray()
268 270 # create header
269 data.append(self.add_cmd('DISABLE'))
270 data.append(self.add_cmd('CONTINUE'))
271 data.append(self.add_cmd('RESTART'))
271 data.extend(self.add_cmd('DISABLE'))
272 data.extend(self.add_cmd('CONTINUE'))
273 data.extend(self.add_cmd('RESTART'))
272 274
273 275 if self.control_sw:
274 data.append(self.add_cmd('SW_ONE'))
276 data.extend(self.add_cmd('SW_ONE'))
275 277 else:
276 data.append(self.add_cmd('SW_ZERO'))
278 data.extend(self.add_cmd('SW_ZERO'))
277 279
278 280 if self.control_tx:
279 data.append(self.add_cmd('TX_ONE'))
281 data.extend(self.add_cmd('TX_ONE'))
280 282 else:
281 data.append(self.add_cmd('TX_ZERO'))
283 data.extend(self.add_cmd('TX_ZERO'))
282 284
283 285 # write divider
284 data.append(self.add_cmd('CLOCK_DIVIDER'))
285 data.append(self.add_data(self.clock_divider))
286 data.extend(self.add_cmd('CLOCK_DIVIDER'))
287 data.extend(self.add_data(self.clock_divider))
286 288
287 289 # write delays
288 data.append(self.add_cmd('DELAY_START'))
290 data.extend(self.add_cmd('DELAY_START'))
289 291 # first delay is always zero
290 data.append(self.add_data(1))
292 data.extend(self.add_data(1))
291 293
292 294 delays = self.get_delays()
293 295
294 296 for delay in delays:
295 297 while delay>252:
296 data.append(self.add_data(253))
298 data.extend(self.add_data(253))
297 299 delay -= 253
298 data.append(self.add_data(delay))
300 data.extend(self.add_data(int(delay)))
299 301
300 302 # write flips
301 data.append(self.add_cmd('FLIP_START'))
303 data.extend(self.add_cmd('FLIP_START'))
302 304
303 305 states = self.get_pulses(binary=False)
304 306
305 307 for flips, delay in zip(states, delays):
306 308 flips.reverse()
307 309 flip = int(''.join([str(x) for x in flips]), 2)
308 data.append(self.add_data(flip+1))
310 data.extend(self.add_data(flip+1))
309 311 while delay>252:
310 data.append(self.add_data(1))
312 data.extend(self.add_data(1))
311 313 delay -= 253
312 314
313 315 # write sampling period
314 data.append(self.add_cmd('SAMPLING_PERIOD'))
316 data.extend(self.add_cmd('SAMPLING_PERIOD'))
315 317 wins = self.get_lines(line_type__name='windows')
316 318 if wins:
317 319 win_params = json.loads(wins[0].params)['params']
318 320 if win_params:
319 321 dh = int(win_params[0]['resolution']*self.km2unit)
320 322 else:
321 323 dh = 1
322 324 else:
323 325 dh = 1
324 data.append(self.add_data(dh))
326 data.extend(self.add_data(dh))
325 327
326 328 # write enable
327 data.append(self.add_cmd('ENABLE'))
329 data.extend(self.add_cmd('ENABLE'))
330
331 if not dat:
332 return data
333
334 return '\n'.join(['{}'.format(x) for x in data])
328 335
329 return '\n'.join(['{}'.format(x) for tup in data for x in tup])
330 336
331 337 def update_from_file(self, filename):
332 338 '''
333 339 Update instance from file
334 340 '''
335 341
336 342 f = RCFile(filename)
337 343 self.dict_to_parms(f.data)
338 344 self.update_pulses()
339 345
340 346 def update_pulses(self):
341 347
342 348 for line in self.get_lines():
343 349 line.update_pulses()
344 350
345 def plot_pulses(self, km=False):
351 def plot_pulses2(self, km=False):
346 352
347 353 import matplotlib.pyplot as plt
348 354 from bokeh.resources import CDN
349 355 from bokeh.embed import components
350 356 from bokeh.mpl import to_bokeh
351 357 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, HoverTool, SaveTool
352 358
353 359 lines = self.get_lines()
354 360
355 361 N = len(lines)
356 362 npoints = self.total_units/self.km2unit if km else self.total_units
357 fig = plt.figure(figsize=(10, 2+N*0.5))
363 fig = plt.figure(figsize=(12, 2+N*0.5))
358 364 ax = fig.add_subplot(111)
359 365 labels = ['IPP']
360 366
361 367 for i, line in enumerate(lines):
362 368 labels.append(line.get_name(channel=True))
363 369 l = ax.plot((0, npoints),(N-i-1, N-i-1))
364 370 points = [(tup[0], tup[1]-tup[0]) for tup in line.pulses_as_points(km=km) if tup!=(0,0)]
365 371 ax.broken_barh(points, (N-i-1, 0.5),
366 372 edgecolor=l[0].get_color(), facecolor='none')
367 373
368 374 n = 0
369 375 f = ((self.ntx+50)/100)*5 if ((self.ntx+50)/100)*10>0 else 2
370 376 for x in np.arange(0, npoints, self.ipp if km else self.ipp*self.km2unit):
371 377 if n%f==0:
372 378 ax.text(x, N, '%s' % n, size=10)
373 379 n += 1
374 380
375 381
376 382 labels.reverse()
377 383 ax.set_yticks(range(len(labels)))
378 384 ax.set_yticklabels(labels)
379 385 ax.set_xlabel = 'Units'
380 plot = to_bokeh(fig, use_pandas=False)
386 plot = to_bokeh(fig, use_pandas=False)
381 387 plot.tools = [PanTool(dimensions=['width']), WheelZoomTool(dimensions=['width']), ResetTool(), SaveTool()]
382 388 plot.toolbar_location="above"
383 389
384 390 return components(plot, CDN)
385 391
386 def status_device(self):
392 def plot_pulses(self, km=False):
387 393
388 return 0
394 from bokeh.plotting import figure
395 from bokeh.resources import CDN
396 from bokeh.embed import components
397 from bokeh.models import FixedTicker, PrintfTickFormatter
398 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, HoverTool, SaveTool
399 from bokeh.models.sources import ColumnDataSource
389 400
390 def stop_device(self):
401 lines = self.get_lines().reverse()
402
403 N = len(lines)
404 npoints = self.total_units/self.km2unit if km else self.total_units
405 ipp = self.ipp if km else self.ipp*self.km2unit
406
407 hover = HoverTool(tooltips=[("Line", "@name"),
408 ("IPP", "@ipp"),
409 ("X", "@left")])
410
411 tools = [PanTool(dimensions=['width']),
412 WheelZoomTool(dimensions=['width']),
413 hover, SaveTool()]
414
415 plot = figure(width=1000,
416 height=40+N*50,
417 y_range = (0, N),
418 tools=tools,
419 toolbar_location='above',
420 toolbar_sticky=False,)
421
422 plot.xaxis.axis_label = 'Km' if km else 'Units'
423 plot.xaxis[0].formatter = PrintfTickFormatter(format='%d')
424 plot.yaxis.axis_label = 'Pulses'
425 plot.yaxis[0].ticker=FixedTicker(ticks=list(range(N)))
426 plot.yaxis[0].formatter = PrintfTickFormatter(format='Line %d')
427
428 for i, line in enumerate(lines):
429
430 points = [tup for tup in line.pulses_as_points(km=km) if tup!=(0,0)]
431
432 source = ColumnDataSource(data = dict(
433 bottom = [i for tup in points],
434 top = [i+0.5 for tup in points],
435 left = [tup[0] for tup in points],
436 right = [tup[1] for tup in points],
437 ipp = [int(tup[0]/ipp) for tup in points],
438 name = [line.get_name() for tup in points]
439 ))
440
441 plot.quad(
442 bottom = 'bottom',
443 top = 'top',
444 left = 'left',
445 right = 'right',
446 source = source,
447 fill_alpha = 0,
448 #line_color = 'blue',
449 )
450
451 plot.line([0, npoints], [i, i])#, color='blue')
452
453 return components(plot, CDN)
391 454
392 answer = api.disable(ip = self.device.ip_address,
393 port = self.device.port_address)
455 def status_device(self):
394 456
395 if answer[0] != "1":
396 self.message = answer[0:]
457 try:
458 req = requests.get(self.device.url)
459 payload = req.json()
460 if payload['status']=='ok':
461 self.device.status = 3
462 else:
463 self.device.status = 1
464 except:
465 self.device.status = 0
466
467 self.device.save()
468
469 return self.device.status
470
471
472 def reset_device(self):
473
474 payload = bytearray()
475 payload.extend(self.add_cmd('RESTART'))
476 data = b64encode(payload)
477 req = requests.put(self.device.url, data)
478
479 if data==req.text.encode('utf8'):
480 return 1
481 else:
397 482 return 0
483
484 def stop_device(self):
398 485
399 self.message = answer[2:]
400 return 1
486 payload = bytearray()
487 payload.extend(self.add_cmd('DISABLE'))
488 data = b64encode(payload)
489 req = requests.put(self.device.url, data)
490
491 if data==req.text.encode('utf8'):
492 return 1
493 else:
494 return 0
401 495
402 496 def start_device(self):
403 497
404 answer = api.enable(ip = self.device.ip_address,
405 port = self.device.port_address)
406
407 if answer[0] != "1":
408 self.message = answer[0:]
498 payload = bytearray()
499 payload.extend(self.add_cmd('ENABLE'))
500 data = b64encode(payload)
501 req = requests.put(self.device.url, data)
502
503 if data==req.text.encode('utf8'):
504 return 1
505 else:
409 506 return 0
410 507
411 self.message = answer[2:]
412 return 1
413
414 508 def write_device(self):
415 answer = api.write_config(ip = self.device.ip_address,
416 port = self.device.port_address,
417 parms = self.parms_to_dict())
418
419 if answer[0] != "1":
420 self.message = answer[0:]
509
510 data = b64encode(self.parms_to_binary(dat=False))
511 req = requests.put(self.device.url, data)
512 print(req.text)
513 if data==req.text.encode('utf8'):
514 return 1
515 else:
421 516 return 0
422 517
423 self.message = answer[2:]
424 return 1
425
426 518
427 519 class RCLineCode(models.Model):
428 520
429 521 name = models.CharField(max_length=40)
430 522 bits_per_code = models.PositiveIntegerField(default=0)
431 523 number_of_codes = models.PositiveIntegerField(default=0)
432 524 codes = models.TextField(blank=True, null=True)
433 525
434 526 class Meta:
435 527 db_table = 'rc_line_codes'
436 528 ordering = ('name',)
437 529
438 530 def __str__(self):
439 531 return u'%s' % self.name
440 532
441 533
442 534 class RCLineType(models.Model):
443 535
444 536 name = models.CharField(choices=LINE_TYPES, max_length=40)
445 537 description = models.TextField(blank=True, null=True)
446 538 params = models.TextField(default='[]')
447 539
448 540 class Meta:
449 541 db_table = 'rc_line_types'
450 542
451 543 def __str__(self):
452 544 return u'%s - %s' % (self.name.upper(), self.get_name_display())
453 545
454 546
455 547 class RCLine(models.Model):
456 548
457 549 rc_configuration = models.ForeignKey(RCConfiguration, on_delete=models.CASCADE)
458 550 line_type = models.ForeignKey(RCLineType)
459 551 channel = models.PositiveIntegerField(default=0)
460 552 position = models.PositiveIntegerField(default=0)
461 553 params = models.TextField(default='{}')
462 554 pulses = models.TextField(default='')
463 555
464 556 class Meta:
465 557 db_table = 'rc_lines'
466 558 ordering = ['channel']
467 559
468 560 def __str__(self):
469 561 if self.rc_configuration:
470 562 return u'%s - %s' % (self.rc_configuration, self.get_name())
471 563
472 564 def clone(self, **kwargs):
473 565
474 566 self.pk = None
475 567
476 568 for attr, value in kwargs.items():
477 569 setattr(self, attr, value)
478 570
479 571 self.save()
480 572
481 573 return self
482 574
483 575 def get_name(self, channel=False):
484 576
485 577 chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
486 578 s = ''
487 579
488 580 if self.line_type.name in ('tx',):
489 581 s = chars[self.position]
490 582 elif self.line_type.name in ('codes', 'windows', 'tr'):
491 583 if 'TX_ref' in json.loads(self.params):
492 584 pk = json.loads(self.params)['TX_ref']
493 585 if pk in (0, '0'):
494 586 s = ','.join(chars[l.position] for l in self.rc_configuration.get_lines(line_type__name='tx'))
495 587 else:
496 588 ref = RCLine.objects.get(pk=pk)
497 589 s = chars[ref.position]
498 590 s = '({})'.format(s)
499 591
500 592 s = '{}{}'.format(self.line_type.name.upper(), s)
501 593
502 594 if channel:
503 595 return '{} {}'.format(s, self.channel)
504 596 else:
505 597 return s
506 598
507 599 def get_lines(self, **kwargs):
508 600
509 601 return RCLine.objects.filter(rc_configuration=self.rc_configuration, **kwargs)
510 602
511 603 def pulses_as_array(self):
512 604
513 605 y = np.zeros(self.rc_configuration.total_units)
514 606
515 607 for tup in ast.literal_eval(self.pulses):
516 608 y[tup[0]:tup[1]] = 1
517 609
518 610 return y.astype(np.int8)
519 611
520 612 def pulses_as_points(self, km=False):
521 613
522 614 if km:
523 615 unit2km = 1/self.rc_configuration.km2unit
524 616 return [(tup[0]*unit2km, tup[1]*unit2km) for tup in ast.literal_eval(self.pulses)]
525 617 else:
526 618 return ast.literal_eval(self.pulses)
527 619
528 620 def get_win_ref(self, params, tx_id, km2unit):
529 621
530 622 ref = self.rc_configuration.sampling_reference
531 623 codes = [line for line in self.get_lines(line_type__name='codes') if int(json.loads(line.params)['TX_ref'])==int(tx_id)]
532 624
533 625 if codes:
534 626 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit/len(json.loads(codes[0].params)['codes'][0])
535 627 else:
536 628 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit
537 629
538 630 if ref=='first_baud':
539 631 return int(1 + (tx_width + 1)/2 + params['first_height']*km2unit - params['resolution']*km2unit)
540 632 elif ref=='sub_baud':
541 633 return int(1 + params['first_height']*km2unit - params['resolution']*km2unit/2)
542 634 else:
543 635 return 0
544 636
545 637 def update_pulses(self):
546 638 '''
547 639 Update pulses field
548 640 '''
549 641
550 642 km2unit = self.rc_configuration.km2unit
551 643 us2unit = self.rc_configuration.us2unit
552 644 ipp = self.rc_configuration.ipp
553 ntx = self.rc_configuration.ntx
645 ntx = int(self.rc_configuration.ntx)
554 646 ipp_u = int(ipp*km2unit)
555 647 total = ipp_u*ntx if self.rc_configuration.total_units==0 else self.rc_configuration.total_units
556 648 y = []
557 649
558 650 if self.line_type.name=='tr':
559 651 tr_params = json.loads(self.params)
560 652
561 653 if tr_params['TX_ref'] in ('0', 0):
562 654 txs = self.get_lines(line_type__name='tx')
563 655 else:
564 656 txs = RCLine.objects.filter(pk=tr_params['TX_ref'])
565 657
566 658 for tx in txs:
567 659 params = json.loads(tx.params)
568 660
569 661 if float(params['pulse_width'])==0:
570 662 continue
571 663 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
572 664 width = float(params['pulse_width'])*km2unit+int(self.rc_configuration.time_before*us2unit)
573 665 before = 0
574 666 after = int(self.rc_configuration.time_after*us2unit)
575 667
576 668 y_tx = self.points(ntx, ipp_u, width,
577 669 delay=delays,
578 670 before=before,
579 671 after=after,
580 672 sync=self.rc_configuration.sync)
581 673
582 674 ranges = params['range'].split(',')
583 675
584 676 if len(ranges)>0 and ranges[0]!='0':
585 677 y_tx = self.mask_ranges(y_tx, ranges)
586 678
587 679 tr_ranges = tr_params['range'].split(',')
588 680
589 681 if len(tr_ranges)>0 and tr_ranges[0]!='0':
590 682 y_tx = self.mask_ranges(y_tx, tr_ranges)
591 683
592 684 y.extend(y_tx)
593 685
594 686 self.pulses = str(y)
595 687 y = self.array_to_points(self.pulses_as_array())
596 688
597 689 elif self.line_type.name=='tx':
598 690 params = json.loads(self.params)
599 691 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
600 692 width = float(params['pulse_width'])*km2unit
601 693
602 694 if width>0:
603 695 before = int(self.rc_configuration.time_before*us2unit)
604 696 after = 0
605 697
606 698 y = self.points(ntx, ipp_u, width,
607 699 delay=delays,
608 700 before=before,
609 701 after=after,
610 702 sync=self.rc_configuration.sync)
611 703
612 704 ranges = params['range'].split(',')
613 705
614 706 if len(ranges)>0 and ranges[0]!='0':
615 707 y = self.mask_ranges(y, ranges)
616 708
617 709 elif self.line_type.name=='flip':
618 710 n = float(json.loads(self.params)['number_of_flips'])
619 711 width = n*ipp*km2unit
620 712 y = self.points(int((ntx+1)/(2*n)), ipp_u*n*2, width)
621 713
622 714 elif self.line_type.name=='codes':
623 715 params = json.loads(self.params)
624 716 tx = RCLine.objects.get(pk=params['TX_ref'])
625 717 tx_params = json.loads(tx.params)
626 718 delays = [float(d)*km2unit for d in tx_params['delays'].split(',') if d]
627 719 f = int(float(tx_params['pulse_width'])*km2unit/len(params['codes'][0]))
628 720 codes = [(np.fromstring(''.join([s*f for s in code]), dtype=np.uint8)-48).astype(np.int8) for code in params['codes']]
629 721 codes = [self.array_to_points(code) for code in codes]
630 722 n = len(codes)
631 723
632 724 for i, tup in enumerate(tx.pulses_as_points()):
633 725 code = codes[i%n]
634 726 y.extend([(c[0]+tup[0], c[1]+tup[0]) for c in code])
635 727
636 728 ranges = tx_params['range'].split(',')
637 729 if len(ranges)>0 and ranges[0]!='0':
638 730 y = self.mask_ranges(y, ranges)
639 731
640 732 elif self.line_type.name=='sync':
641 733 params = json.loads(self.params)
642 734 n = ipp_u*ntx
643 735 if params['invert'] in ('1', 1):
644 736 y = [(n-1, n)]
645 737 else:
646 738 y = [(0, 1)]
647 739
648 740 elif self.line_type.name=='prog_pulses':
649 741 params = json.loads(self.params)
650 742 if int(params['periodic'])==0:
651 743 nntx = 1
652 744 nipp = ipp_u*ntx
653 745 else:
654 746 nntx = ntx
655 747 nipp = ipp_u
656 748
657 749 if 'params' in params and len(params['params'])>0:
658 750 for p in params['params']:
659 751 y_pp = self.points(nntx, nipp,
660 752 p['end']-p['begin'],
661 753 before=p['begin'])
662 754
663 755 y.extend(y_pp)
664 756
665 757 elif self.line_type.name=='windows':
666 758 params = json.loads(self.params)
667 759
668 760 if 'params' in params and len(params['params'])>0:
669 761 tr_params = json.loads(self.get_lines(line_type__name='tr')[0].params)
670 762 tr_ranges = tr_params['range'].split(',')
671 763 for p in params['params']:
672 764 y_win = self.points(ntx, ipp_u,
673 765 p['resolution']*p['number_of_samples']*km2unit,
674 766 before=int(self.rc_configuration.time_before*us2unit)+self.get_win_ref(p, params['TX_ref'], km2unit),
675 767 sync=self.rc_configuration.sync)
676 768
677 769 if len(tr_ranges)>0 and tr_ranges[0]!='0':
678 770 y_win = self.mask_ranges(y_win, tr_ranges)
679 771
680 772 y.extend(y_win)
681 773
682 774 elif self.line_type.name=='mix':
683 775 values = self.rc_configuration.parameters.split('-')
684 776 confs = [RCConfiguration.objects.get(pk=value.split('|')[0]) for value in values]
685 777 modes = [value.split('|')[1] for value in values]
686 778 ops = [value.split('|')[2] for value in values]
687 779 delays = [value.split('|')[3] for value in values]
688 780 masks = [value.split('|')[4] for value in values]
689 781 mask = list('{:8b}'.format(int(masks[0])))
690 782 mask.reverse()
691 783 if mask[self.channel] in ('0', '', ' '):
692 784 y = np.zeros(confs[0].total_units, dtype=np.int8)
693 785 else:
694 786 y = confs[0].get_lines(channel=self.channel)[0].pulses_as_array()
695 787
696 788 for i in range(1, len(values)):
697 789 mask = list('{:8b}'.format(int(masks[i])))
698 790 mask.reverse()
699 791
700 792 if mask[self.channel] in ('0', '', ' '):
701 793 continue
702 794 Y = confs[i].get_lines(channel=self.channel)[0].pulses_as_array()
703 795 delay = float(delays[i])*km2unit
704 796
705 797 if modes[i]=='P':
706 798 if delay>0:
707 799 if delay<self.rc_configuration.ipp*km2unit and len(Y)==len(y):
708 800 y_temp = np.empty_like(Y)
709 801 y_temp[:delay] = 0
710 802 y_temp[delay:] = Y[:-delay]
711 803 elif delay+len(Y)>len(y):
712 804 y_new = np.zeros(delay+len(Y), dtype=np.int8)
713 805 y_new[:len(y)] = y
714 806 y = y_new
715 807 y_temp = np.zeros(delay+len(Y), dtype=np.int8)
716 808 y_temp[-len(Y):] = Y
717 809 elif delay+len(Y)==len(y):
718 810 y_temp = np.zeros(delay+len(Y))
719 811 y_temp[-len(Y):] = Y
720 812 elif delay+len(Y)<len(y):
721 813 y_temp = np.zeros(len(y), dtype=np.int8)
722 814 y_temp[delay:delay+len(Y)] = Y
723 815
724 816 if ops[i]=='OR':
725 817 y = y | y_temp
726 818 elif ops[i]=='XOR':
727 819 y = y ^ y_temp
728 820 elif ops[i]=='AND':
729 821 y = y & y_temp
730 822 elif ops[i]=='NAND':
731 823 y = y & ~y_temp
732 824 else:
733 825 y = np.concatenate([y, Y])
734 826
735 827 total = len(y)
736 828 y = self.array_to_points(y)
737 829
738 830 else:
739 831 y = []
740 832
741 833 if self.rc_configuration.total_units != total:
742 834 self.rc_configuration.total_units = total
743 835 self.rc_configuration.save()
744 836
745 837 self.pulses = str(y)
746 838 self.save()
747 839
748 840 @staticmethod
749 841 def array_to_points(X):
750 842
751 843 d = X[1:]-X[:-1]
752 844
753 845 up = np.where(d==1)[0]
754 846 if X[0]==1:
755 847 up = np.concatenate((np.array([-1]), up))
756 848 up += 1
757 849
758 850 dw = np.where(d==-1)[0]
759 851 if X[-1]==1:
760 852 dw = np.concatenate((dw, np.array([len(X)-1])))
761 853 dw += 1
762 854
763 855 return [(tup[0], tup[1]) for tup in zip(up, dw)]
764 856
765 857 @staticmethod
766 858 def mask_ranges(Y, ranges):
767 859
768 860 y = [(0, 0) for __ in Y]
769 861
770 862 for index in ranges:
771 863 if '-' in index:
772 864 args = [int(a) for a in index.split('-')]
773 865 y[args[0]-1:args[1]] = Y[args[0]-1:args[1]]
774 866 else:
775 867 y[int(index-1)] = Y[int(index-1)]
776 868
777 869 return y
778 870
779 871 @staticmethod
780 872 def points(ntx, ipp, width, delay=[0], before=0, after=0, sync=0):
781 873
782 874 delays = len(delay)
783 875
784 876 Y = [(ipp*x+before+delay[x%delays], ipp*x+width+before+delay[x%delays]+after) for x in range(ntx)]
785 877
786 878 return Y
@@ -1,22 +1,23
1 1 from django.conf.urls import url
2 2
3 3 from apps.rc import views
4 4
5 5 urlpatterns = (
6 6 url(r'^(?P<conf_id>-?\d+)/$', views.conf, name='url_rc_conf'),
7 7 url(r'^(?P<conf_id>-?\d+)/import/$', views.import_file, name='url_import_rc_conf'),
8 8 url(r'^(?P<conf_id>-?\d+)/edit/$', views.conf_edit, name='url_edit_rc_conf'),
9 9 url(r'^(?P<conf_id>-?\d+)/plot/$', views.plot_pulses, name='url_plot_rc_pulses'),
10 url(r'^(?P<conf_id>-?\d+)/plot2/$', views.plot_pulses2, name='url_plot_rc_pulses'),
10 11 #url(r'^(?P<id_conf>-?\d+)/write/$', 'apps.main.views.dev_conf_write', name='url_write_rc_conf'),
11 12 #url(r'^(?P<id_conf>-?\d+)/read/$', 'apps.main.views.dev_conf_read', name='url_read_rc_conf'),
12 13
13 14 url(r'^(?P<conf_id>-?\d+)/add_line/$', views.add_line, name='url_add_rc_line'),
14 15 url(r'^(?P<conf_id>-?\d+)/add_line/(?P<line_type_id>-?\d+)/$', views.add_line, name='url_add_rc_line'),
15 16 url(r'^(?P<conf_id>-?\d+)/add_line/(?P<line_type_id>-?\d+)/code/(?P<code_id>-?\d+)/$', views.add_line, name='url_add_rc_line_code'),
16 17 url(r'^(?P<conf_id>-?\d+)/update_position/$', views.update_lines_position, name='url_update_rc_lines_position'),
17 18 url(r'^(?P<conf_id>-?\d+)/line/(?P<line_id>-?\d+)/delete/$', views.remove_line, name='url_remove_rc_line'),
18 19 url(r'^(?P<conf_id>-?\d+)/line/(?P<line_id>-?\d+)/add_subline/$', views.add_subline, name='url_add_rc_subline'),
19 20 url(r'^(?P<conf_id>-?\d+)/line/(?P<line_id>-?\d+)/codes/$', views.edit_codes, name='url_edit_rc_codes'),
20 21 url(r'^(?P<conf_id>-?\d+)/line/(?P<line_id>-?\d+)/codes/(?P<code_id>-?\d+)/$', views.edit_codes, name='url_edit_rc_codes'),
21 22 url(r'^(?P<conf_id>-?\d+)/line/(?P<line_id>-?\d+)/subline/(?P<subline_id>-?\d+)/delete/$', views.remove_subline, name='url_remove_rc_subline'),
22 23 )
@@ -1,377 +1,401
1 1
2 2 import json
3 3
4 4 from django.contrib import messages
5 5 from django.utils.safestring import mark_safe
6 6 from django.shortcuts import render, redirect, get_object_or_404, HttpResponse
7 7
8 8 from apps.main.models import Experiment, Device
9 9 from apps.main.views import sidebar
10 10
11 11 from .models import RCConfiguration, RCLine, RCLineType, RCLineCode
12 12 from .forms import RCConfigurationForm, RCLineForm, RCLineViewForm, RCLineEditForm, RCImportForm, RCLineCodesForm
13 13
14 14
15 15 def conf(request, conf_id):
16 16
17 17 conf = get_object_or_404(RCConfiguration, pk=conf_id)
18 18
19 19 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
20 20
21 21 for line in lines:
22 22 params = json.loads(line.params)
23 23 line.form = RCLineViewForm(extra_fields=params, line=line)
24 24 if 'params' in params:
25 25 line.subforms = [RCLineViewForm(extra_fields=fields, line=line, subform=True) for fields in params['params']]
26 26
27 27 kwargs = {}
28 28 kwargs['dev_conf'] = conf
29 29 kwargs['rc_lines'] = lines
30 30 kwargs['dev_conf_keys'] = ['name', 'ipp_unit', 'ntx', 'clock_in', 'clock_divider', 'clock',
31 31 'time_before', 'time_after', 'sync', 'sampling_reference', 'control_tx', 'control_sw']
32 32
33 33 kwargs['title'] = 'RC Configuration'
34 34 kwargs['suptitle'] = 'Details'
35 35
36 36 kwargs['button'] = 'Edit Configuration'
37 37 ###### SIDEBAR ######
38 38 kwargs.update(sidebar(conf=conf))
39 39
40 40 return render(request, 'rc_conf.html', kwargs)
41 41
42 42
43 43 def conf_edit(request, conf_id):
44 44
45 45 conf = get_object_or_404(RCConfiguration, pk=conf_id)
46 46
47 47 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
48 48
49 49 for line in lines:
50 50 params = json.loads(line.params)
51 51 line.form = RCLineEditForm(conf=conf, line=line, extra_fields=params)
52 52 line.subform = False
53 53
54 54 if 'params' in params:
55 55 line.subforms = [RCLineEditForm(extra_fields=fields, line=line, subform=i) for i, fields in enumerate(params['params'])]
56 56 line.subform = True
57 57
58 58 if request.method=='GET':
59 59
60 60 form = RCConfigurationForm(instance=conf)
61 61
62 62 elif request.method=='POST':
63 63
64 64 line_data = {}
65 65 conf_data = {}
66 66 extras = []
67 67
68 68 #classified post fields
69 69 for label,value in request.POST.items():
70 70 if label=='csrfmiddlewaretoken':
71 71 continue
72 72
73 73 if label.count('|')==0:
74 74 conf_data[label] = value
75 75 continue
76 76
77 77 elif label.split('|')[0]!='-1':
78 78 extras.append(label)
79 79 continue
80 80
81 81 x, pk, name = label.split('|')
82 82
83 83 if name=='codes':
84 84 value = [s for s in value.split('\r\n') if s]
85 85
86 86 if pk in line_data:
87 87 line_data[pk][name] = value
88 88 else:
89 89 line_data[pk] = {name:value}
90 90
91 91 #update conf
92 92 form = RCConfigurationForm(conf_data, instance=conf)
93 93
94 94 if form.is_valid():
95 95
96 96 form.save()
97 97
98 98 #update lines fields
99 99 extras.sort()
100 100 for label in extras:
101 101 x, pk, name = label.split('|')
102 102 if pk not in line_data:
103 103 line_data[pk] = {}
104 104 if 'params' not in line_data[pk]:
105 105 line_data[pk]['params'] = []
106 106 if len(line_data[pk]['params'])<int(x)+1:
107 107 line_data[pk]['params'].append({})
108 108 line_data[pk]['params'][int(x)][name] = float(request.POST[label])
109 109
110 110 for pk, params in line_data.items():
111 111 line = RCLine.objects.get(pk=pk)
112 112 if line.line_type.name in ('windows', 'prog_pulses'):
113 113 if 'params' not in params:
114 114 params['params'] = []
115 115 line.params = json.dumps(params)
116 116 line.save()
117 117
118 118 #update pulses field
119 119 conf.update_pulses()
120 120
121 121 messages.success(request, 'RC Configuration successfully updated')
122 122
123 123 return redirect(conf.get_absolute_url())
124 124
125 125 kwargs = {}
126 126 kwargs['dev_conf'] = conf
127 127 kwargs['form'] = form
128 128 kwargs['rc_lines'] = lines
129 129 kwargs['edit'] = True
130 130
131 131 kwargs['title'] = 'RC Configuration'
132 132 kwargs['suptitle'] = 'Edit'
133 133 kwargs['button'] = 'Update'
134 134 kwargs['previous'] = conf.get_absolute_url()
135 135
136 136 return render(request, 'rc_conf_edit.html', kwargs)
137 137
138 138
139 139 def add_line(request, conf_id, line_type_id=None, code_id=None):
140 140
141 141 conf = get_object_or_404(RCConfiguration, pk=conf_id)
142 142
143 143 if request.method=='GET':
144 144 if line_type_id:
145 145 line_type = get_object_or_404(RCLineType, pk=line_type_id)
146 146
147 147 if code_id:
148 148 form = RCLineForm(initial={'rc_configuration':conf_id, 'line_type': line_type_id, 'code_id': code_id},
149 149 extra_fields=json.loads(line_type.params))
150 150 else:
151 151 form = RCLineForm(initial={'rc_configuration':conf_id, 'line_type': line_type_id},
152 152 extra_fields=json.loads(line_type.params))
153 153 else:
154 154 line_type = {'id':0}
155 155 form = RCLineForm(initial={'rc_configuration':conf_id})
156 156
157 157 if request.method=='POST':
158 158
159 159 line_type = get_object_or_404(RCLineType, pk=line_type_id)
160 160 form = RCLineForm(request.POST,
161 161 extra_fields=json.loads(line_type.params))
162 162
163 163 if form.is_valid():
164 164 form.save()
165 165 form.instance.update_pulses()
166 166 return redirect('url_edit_rc_conf', conf.id)
167 167
168 168 kwargs = {}
169 169 kwargs['form'] = form
170 170 kwargs['title'] = 'RC Configuration'
171 171 kwargs['suptitle'] = 'Add Line'
172 172 kwargs['button'] = 'Add'
173 173 kwargs['previous'] = conf.get_absolute_url_edit()
174 174 kwargs['dev_conf'] = conf
175 175 kwargs['line_type'] = line_type
176 176
177 177 return render(request, 'rc_add_line.html', kwargs)
178 178
179 179 def edit_codes(request, conf_id, line_id, code_id=None):
180 180
181 181 conf = get_object_or_404(RCConfiguration, pk=conf_id)
182 182 line = get_object_or_404(RCLine, pk=line_id)
183 183 params = json.loads(line.params)
184 184
185 185 if request.method=='GET':
186 186 if code_id:
187 187 code = get_object_or_404(RCLineCode, pk=code_id)
188 188 form = RCLineCodesForm(instance=code)
189 189 else:
190 190 initial = {'code': params['code'],
191 191 'codes': params['codes'] if 'codes' in params else [],
192 192 'number_of_codes': len(params['codes']) if 'codes' in params else 0,
193 193 'bits_per_code': len(params['codes'][0]) if 'codes' in params else 0,
194 194 }
195 195 form = RCLineCodesForm(initial=initial)
196 196
197 197 if request.method=='POST':
198 198 form = RCLineCodesForm(request.POST)
199 199 if form.is_valid():
200 200 params['code'] = request.POST['code']
201 201 params['codes'] = [s for s in request.POST['codes'].split('\r\n') if s]
202 202 line.params = json.dumps(params)
203 203 line.save()
204 204 messages.success(request, 'Line: "%s" has been updated.' % line)
205 205 return redirect('url_edit_rc_conf', conf.id)
206 206
207 207 kwargs = {}
208 208 kwargs['form'] = form
209 209 kwargs['title'] = line
210 210 kwargs['suptitle'] = 'Edit'
211 211 kwargs['button'] = 'Update'
212 212 kwargs['dev_conf'] = conf
213 213 kwargs['previous'] = conf.get_absolute_url_edit()
214 214 kwargs['line'] = line
215 215
216 216 return render(request, 'rc_edit_codes.html', kwargs)
217 217
218 218 def add_subline(request, conf_id, line_id):
219 219
220 220 conf = get_object_or_404(RCConfiguration, pk=conf_id)
221 221 line = get_object_or_404(RCLine, pk=line_id)
222 222
223 223 if request.method == 'POST':
224 224 if line:
225 225 params = json.loads(line.params)
226 226 subparams = json.loads(line.line_type.params)
227 227 if 'params' in subparams:
228 228 dum = {}
229 229 for key, value in subparams['params'].items():
230 230 dum[key] = value['value']
231 231 params['params'].append(dum)
232 232 line.params = json.dumps(params)
233 233 line.save()
234 234 return redirect('url_edit_rc_conf', conf.id)
235 235
236 236 kwargs = {}
237 237
238 238 kwargs['title'] = 'Add new'
239 239 kwargs['suptitle'] = '%s to %s' % (line.line_type.name, line)
240 240
241 241 return render(request, 'confirm.html', kwargs)
242 242
243 243 def remove_line(request, conf_id, line_id):
244 244
245 245 conf = get_object_or_404(RCConfiguration, pk=conf_id)
246 246 line = get_object_or_404(RCLine, pk=line_id)
247 247
248 248 if request.method == 'POST':
249 249 if line:
250 250 try:
251 251 channel = line.channel
252 252 line.delete()
253 253 for ch in range(channel+1, RCLine.objects.filter(rc_configuration=conf).count()+1):
254 254 l = RCLine.objects.get(rc_configuration=conf, channel=ch)
255 255 l.channel = l.channel-1
256 256 l.save()
257 257 messages.success(request, 'Line: "%s" has been deleted.' % line)
258 258 except:
259 259 messages.error(request, 'Unable to delete line: "%s".' % line)
260 260
261 261 return redirect('url_edit_rc_conf', conf.id)
262 262
263 263 kwargs = {}
264 264
265 265 kwargs['object'] = line
266 266 kwargs['delete'] = True
267 267 kwargs['title'] = 'Delete'
268 268 kwargs['suptitle'] = 'Line'
269 269 kwargs['previous'] = conf.get_absolute_url_edit()
270 270 return render(request, 'confirm.html', kwargs)
271 271
272 272
273 273 def remove_subline(request, conf_id, line_id, subline_id):
274 274
275 275 conf = get_object_or_404(RCConfiguration, pk=conf_id)
276 276 line = get_object_or_404(RCLine, pk=line_id)
277 277
278 278 if request.method == 'POST':
279 279 if line:
280 280 params = json.loads(line.params)
281 281 params['params'].remove(params['params'][int(subline_id)-1])
282 282 line.params = json.dumps(params)
283 283 line.save()
284 284
285 285 return redirect('url_edit_rc_conf', conf.id)
286 286
287 287 kwargs = {}
288 288
289 289 kwargs['object'] = line
290 290 kwargs['object_name'] = line.line_type.name
291 291 kwargs['delete_view'] = True
292 292 kwargs['title'] = 'Confirm delete'
293 293
294 294 return render(request, 'confirm.html', kwargs)
295 295
296 296
297 297 def update_lines_position(request, conf_id):
298 298
299 299 conf = get_object_or_404(RCConfiguration, pk=conf_id)
300 300
301 301 if request.method=='POST':
302 302 ch = 0
303 303 for item in request.POST['items'].split('&'):
304 304 line = RCLine.objects.get(pk=item.split('=')[-1])
305 305 line.channel = ch
306 306 line.save()
307 307 ch += 1
308 308
309 309 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
310 310
311 311 for line in lines:
312 312 params = json.loads(line.params)
313 313 line.form = RCLineEditForm(conf=conf, line=line, extra_fields=params)
314 314
315 315 if 'params' in params:
316 316 line.subform = True
317 317 line.subforms = [RCLineEditForm(extra_fields=fields, line=line, subform=i) for i, fields in enumerate(params['params'])]
318 318
319 319 html = render(request, 'rc_lines.html', {'dev_conf':conf, 'rc_lines':lines, 'edit':True})
320 320 data = {'html': html.content.decode('utf8')}
321 321
322 322 return HttpResponse(json.dumps(data), content_type="application/json")
323 323 return redirect('url_edit_rc_conf', conf.id)
324 324
325 325
326 326 def import_file(request, conf_id):
327 327
328 328 conf = get_object_or_404(RCConfiguration, pk=conf_id)
329 329 if request.method=='POST':
330 330 form = RCImportForm(request.POST, request.FILES)
331 331 if form.is_valid():
332 332 try:
333 333 #if True:
334 334 conf.update_from_file(request.FILES['file_name'])
335 335 messages.success(request, 'Configuration "%s" loaded succesfully' % request.FILES['file_name'])
336 336 return redirect(conf.get_absolute_url_edit())
337 337
338 338 except Exception as e:
339 339 messages.error(request, 'Error parsing file: "%s" - %s' % (request.FILES['file_name'], e))
340 340
341 341 else:
342 342 messages.warning(request, 'Your current configuration will be replaced')
343 343 form = RCImportForm()
344 344
345 345 kwargs = {}
346 346 kwargs['form'] = form
347 347 kwargs['title'] = 'RC Configuration'
348 348 kwargs['suptitle'] = 'Import file'
349 349 kwargs['button'] = 'Upload'
350 350 kwargs['previous'] = conf.get_absolute_url()
351 351
352 352 return render(request, 'rc_import.html', kwargs)
353 353
354 354
355 355 def plot_pulses(request, conf_id):
356 356
357 357 conf = get_object_or_404(RCConfiguration, pk=conf_id)
358 358 km = True if 'km' in request.GET else False
359 359
360 360 script, div = conf.plot_pulses(km=km)
361 361
362 362 kwargs = {}
363 kwargs['no_sidebar'] = True
364 kwargs['title'] = 'RC Pulses'
365 kwargs['suptitle'] = conf.name
366 kwargs['div'] = mark_safe(div)
367 kwargs['script'] = mark_safe(script)
368 kwargs['units'] = conf.km2unit
369 kwargs['kms'] = 1/conf.km2unit
370
371 if km:
372 kwargs['km_selected'] = True
373
374 if 'json' in request.GET:
375 return HttpResponse(json.dumps({'div':mark_safe(div), 'script':mark_safe(script)}), content_type="application/json")
376 else:
377 return render(request, 'rc_pulses.html', kwargs)
378
379 def plot_pulses2(request, conf_id):
363 380
381 conf = get_object_or_404(RCConfiguration, pk=conf_id)
382 km = True if 'km' in request.GET else False
383
384 script, div = conf.plot_pulses2(km=km)
385
386 kwargs = {}
387 kwargs['no_sidebar'] = True
364 388 kwargs['title'] = 'RC Pulses'
365 389 kwargs['suptitle'] = conf.name
366 390 kwargs['div'] = mark_safe(div)
367 391 kwargs['script'] = mark_safe(script)
368 392 kwargs['units'] = conf.km2unit
369 393 kwargs['kms'] = 1/conf.km2unit
370 394
371 395 if km:
372 396 kwargs['km_selected'] = True
373 397
374 398 if 'json' in request.GET:
375 399 return HttpResponse(json.dumps({'div':mark_safe(div), 'script':mark_safe(script)}), content_type="application/json")
376 400 else:
377 401 return render(request, 'rc_pulses.html', kwargs)
General Comments 0
You need to be logged in to leave comments. Login now