##// END OF EJS Templates
- Improve display name for Devices & Configurations...
Juan C. Espinoza -
r121:3cd1b9c58c02
parent child
Show More
@@ -1,593 +1,592
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 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 __unicode__(self):
75 75 return u'%s' % self.name
76 76
77 77 def get_absolute_url(self):
78 78 return reverse('url_device', 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 __unicode__(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 __unicode__(self):
107 return u'%s | %s' % (self.name, self.ip_address)
107 return u'[{}]: {}'.format(self.device_type.name.upper(),
108 self.name)
108 109
109 110 def get_status(self):
110 111 return self.status
111 112
112 113 @property
113 114 def status_color(self):
114 115 color = 'muted'
115 116 if self.status == 0:
116 117 color = "danger"
117 118 elif self.status == 1:
118 119 color = "warning"
119 120 elif self.status == 2:
120 121 color = "info"
121 122 elif self.status == 3:
122 123 color = "success"
123 124
124 125 return color
125 126
126 127 def get_absolute_url(self):
127 128 return reverse('url_device', args=[str(self.id)])
128 129
129 130
130 131 class Campaign(models.Model):
131 132
132 133 template = models.BooleanField(default=False)
133 134 name = models.CharField(max_length=60, unique=True)
134 135 start_date = models.DateTimeField(blank=True, null=True)
135 136 end_date = models.DateTimeField(blank=True, null=True)
136 137 tags = models.CharField(max_length=40)
137 138 description = models.TextField(blank=True, null=True)
138 139 experiments = models.ManyToManyField('Experiment', blank=True)
139 140
140 141 class Meta:
141 142 db_table = 'db_campaigns'
142 143 ordering = ('name',)
143 144
144 145 def __unicode__(self):
145 146 return u'%s' % (self.name)
146 147
147 148 def get_absolute_url(self):
148 149 return reverse('url_campaign', args=[str(self.id)])
149 150
150 151 def parms_to_dict(self):
151 152
152 153 import json
153 154
154 155 parameters = {}
155 156 exp_parameters = {}
156 157 experiments = Experiment.objects.filter(campaign = self)
157 158
158 159 i=1
159 160 for experiment in experiments:
160 161 exp_parameters['experiment-'+str(i)] = json.loads(experiment.parms_to_dict())
161 162 i += 1
162 163
163 164
164 165 parameters['experiments'] = exp_parameters
165 166 parameters['end_date'] = self.end_date.strftime("%Y-%m-%d")
166 167 parameters['start_date'] = self.start_date.strftime("%Y-%m-%d")
167 168 parameters['campaign'] = self.__unicode__()
168 169 parameters['tags'] =self.tags
169 170
170 171 parameters = json.dumps(parameters, indent=2, sort_keys=False)
171 172
172 173 return parameters
173 174
174 175 def import_from_file(self, fp):
175 176
176 177 import os, json
177 178
178 179 parms = {}
179 180
180 181 path, ext = os.path.splitext(fp.name)
181 182
182 183 if ext == '.json':
183 184 parms = json.load(fp)
184 185
185 186 return parms
186 187
187 188 def dict_to_parms(self, parms, CONF_MODELS):
188 189
189 190 experiments = Experiment.objects.filter(campaign = self)
190 191 configurations = Configuration.objects.filter(experiment = experiments)
191 192
192 193 if configurations:
193 194 for configuration in configurations:
194 195 configuration.delete()
195 196
196 197 if experiments:
197 198 for experiment in experiments:
198 199 experiment.delete()
199 200
200 201 for parms_exp in parms['experiments']:
201 202 location = Location.objects.get(name = parms['experiments'][parms_exp]['radar'])
202 203 new_exp = Experiment(
203 204 name = parms['experiments'][parms_exp]['experiment'],
204 205 location = location,
205 206 start_time = parms['experiments'][parms_exp]['start_time'],
206 207 end_time = parms['experiments'][parms_exp]['end_time'],
207 208 )
208 209 new_exp.save()
209 210 new_exp.dict_to_parms(parms['experiments'][parms_exp],CONF_MODELS)
210 211 new_exp.save()
211 212
212 213 self.name = parms['campaign']
213 214 self.start_date = parms['start_date']
214 215 self.end_date = parms['end_date']
215 216 self.tags = parms['tags']
216 217 self.experiments.add(new_exp)
217 218 self.save()
218 219
219 220 return self
220 221
221 222 def get_absolute_url(self):
222 223 return reverse('url_campaign', args=[str(self.id)])
223 224
224 225 def get_absolute_url_edit(self):
225 226 return reverse('url_edit_campaign', args=[str(self.id)])
226 227
227 228 def get_absolute_url_export(self):
228 229 return reverse('url_export_campaign', args=[str(self.id)])
229 230
230 231 def get_absolute_url_import(self):
231 232 return reverse('url_import_campaign', args=[str(self.id)])
232 233
233 234
234 235
235 236 class RunningExperiment(models.Model):
236 237 radar = models.OneToOneField('Location', on_delete=models.CASCADE)
237 238 running_experiment = models.ManyToManyField('Experiment', blank = True)
238 239 status = models.PositiveSmallIntegerField(default=0, choices=RADAR_STATES)
239 240
240 241
241 242 class Experiment(models.Model):
242 243
243 244 template = models.BooleanField(default=False)
244 245 name = models.CharField(max_length=40, default='', unique=True)
245 246 location = models.ForeignKey('Location', null=True, blank=True, on_delete=models.CASCADE)
246 247 start_time = models.TimeField(default='00:00:00')
247 248 end_time = models.TimeField(default='23:59:59')
248 249 status = models.PositiveSmallIntegerField(default=0, choices=EXP_STATES)
249 250
250 251 class Meta:
251 252 db_table = 'db_experiments'
252 253 ordering = ('template', 'name')
253 254
254 255 def __unicode__(self):
255 256 if self.template:
256 257 return u'%s (template)' % (self.name)
257 258 else:
258 259 return u'%s' % (self.name)
259 260
260 261 @property
261 262 def radar(self):
262 263 return self.location
263 264
264 265 def clone(self, **kwargs):
265 266
266 267 confs = Configuration.objects.filter(experiment=self, type=0)
267 268 self.pk = None
268 269 self.name = '{} [{:%Y/%m/%d}]'.format(self.name, datetime.now())
269 270 for attr, value in kwargs.items():
270 271 setattr(self, attr, value)
271 272
272 273 self.save()
273 274
274 275 for conf in confs:
275 276 conf.clone(experiment=self, template=False)
276 277
277 278 return self
278 279
279 280 def get_status(self):
280 281 configurations = Configuration.objects.filter(experiment=self)
281 282 exp_status=[]
282 283 for conf in configurations:
283 284 print conf.status_device()
284 285 exp_status.append(conf.status_device())
285 286
286 287 if not exp_status: #No Configuration
287 288 self.status = 4
288 289 self.save()
289 290 return
290 291
291 292 total = 1
292 293 for e_s in exp_status:
293 294 total = total*e_s
294 295
295 296 if total == 0: #Error
296 297 status = 0
297 298 elif total == (3**len(exp_status)): #Running
298 299 status = 2
299 300 else:
300 301 status = 1 #Configurated
301 302
302 303 self.status = status
303 304 self.save()
304 305
305 306 def status_color(self):
306 color = 'danger'
307 color = 'muted'
307 308 if self.status == 0:
308 309 color = "danger"
309 310 elif self.status == 1:
310 311 color = "info"
311 312 elif self.status == 2:
312 313 color = "success"
313 314 elif self.status == 3:
314 315 color = "warning"
315 else:
316 color = "muted"
317 316
318 317 return color
319 318
320 319 def get_absolute_url(self):
321 320 return reverse('url_experiment', args=[str(self.id)])
322 321
323 322 def parms_to_dict(self):
324 323
325 324 import json
326 325
327 326 configurations = Configuration.objects.filter(experiment=self)
328 327 conf_parameters = {}
329 328 parameters={}
330 329
331 330 for configuration in configurations:
332 331 if 'cgs' in configuration.device.device_type.name:
333 332 conf_parameters['cgs'] = configuration.parms_to_dict()
334 333 if 'dds' in configuration.device.device_type.name:
335 334 conf_parameters['dds'] = configuration.parms_to_dict()
336 335 if 'rc' in configuration.device.device_type.name:
337 336 conf_parameters['rc'] = configuration.parms_to_dict()
338 337 if 'jars' in configuration.device.device_type.name:
339 338 conf_parameters['jars'] = configuration.parms_to_dict()
340 339 if 'usrp' in configuration.device.device_type.name:
341 340 conf_parameters['usrp'] = configuration.parms_to_dict()
342 341 if 'abs' in configuration.device.device_type.name:
343 342 conf_parameters['abs'] = configuration.parms_to_dict()
344 343
345 344 parameters['configurations'] = conf_parameters
346 345 parameters['end_time'] = self.end_time.strftime("%H:%M:%S")
347 346 parameters['start_time'] = self.start_time.strftime("%H:%M:%S")
348 347 parameters['radar'] = self.radar.name
349 348 parameters['experiment'] = self.name
350 349 parameters = json.dumps(parameters, indent=2)
351 350
352 351 return parameters
353 352
354 353 def import_from_file(self, fp):
355 354
356 355 import os, json
357 356
358 357 parms = {}
359 358
360 359 path, ext = os.path.splitext(fp.name)
361 360
362 361 if ext == '.json':
363 362 parms = json.load(fp)
364 363
365 364 return parms
366 365
367 366 def dict_to_parms(self, parms, CONF_MODELS):
368 367
369 368 configurations = Configuration.objects.filter(experiment=self)
370 369
371 370 if configurations:
372 371 for configuration in configurations:
373 372 configuration.delete()
374 373
375 374 for conf_type in parms['configurations']:
376 375 #--For ABS Device:
377 376 #--For USRP Device:
378 377 #--For JARS Device:
379 378 #--For RC Device:
380 379 if conf_type == 'rc':
381 380 device = get_object_or_404(Device, pk=parms['configurations']['rc']['device_id'])
382 381 DevConfModel = CONF_MODELS[conf_type]
383 382 confrc_form = DevConfModel(
384 383 experiment = self,
385 384 name = 'RC',
386 385 device=device,
387 386 )
388 387 confrc_form.dict_to_parms(parms['configurations']['rc'])
389 388 confrc_form.save()
390 389 #--For DDS Device:
391 390 if conf_type == 'dds':
392 391 device = get_object_or_404(Device, pk=parms['configurations']['dds']['device_id'])
393 392 DevConfModel = CONF_MODELS[conf_type]
394 393 confdds_form = DevConfModel(
395 394 experiment = self,
396 395 name = 'DDS',
397 396 device=device,
398 397 )
399 398 confdds_form.dict_to_parms(parms['configurations']['dds'])
400 399 confdds_form.save()
401 400 #--For CGS Device:
402 401 if conf_type == 'cgs':
403 402 device = get_object_or_404(Device, pk=parms['configurations']['cgs']['device_id'])
404 403 DevConfModel = CONF_MODELS[conf_type]
405 404 confcgs_form = DevConfModel(
406 405 experiment = self,
407 406 name = 'CGS',
408 407 device=device,
409 408 )
410 409 confcgs_form.dict_to_parms(parms['configurations']['cgs'])
411 410 confcgs_form.save()
412 411
413 412 location = Location.objects.get(name = parms['radar'])
414 413 self.name = parms['experiment']
415 414 self.location = location
416 415 self.start_time = parms['start_time']
417 416 self.end_time = parms['end_time']
418 417 self.save()
419 418
420 419 return self
421 420
422 421 def get_absolute_url_edit(self):
423 422 return reverse('url_edit_experiment', args=[str(self.id)])
424 423
425 424 def get_absolute_url_import(self):
426 425 return reverse('url_import_experiment', args=[str(self.id)])
427 426
428 427 def get_absolute_url_export(self):
429 428 return reverse('url_export_experiment', args=[str(self.id)])
430 429
431 430
432 431 class Configuration(PolymorphicModel):
433 432
434 433 template = models.BooleanField(default=False)
435 434
436 435 name = models.CharField(verbose_name="Configuration Name", max_length=40, default='')
437 436
438 437 experiment = models.ForeignKey('Experiment', null=True, blank=True, on_delete=models.CASCADE)
439 438 device = models.ForeignKey(Device, null=True, on_delete=models.CASCADE)
440 439
441 440 type = models.PositiveSmallIntegerField(default=0, choices=CONF_TYPES)
442 441
443 442 created_date = models.DateTimeField(auto_now_add=True)
444 443 programmed_date = models.DateTimeField(auto_now=True)
445 444
446 445 parameters = models.TextField(default='{}')
447 446
448 447 message = ""
449 448
450 449 class Meta:
451 450 db_table = 'db_configurations'
452 451
453 452 def __unicode__(self):
454 453
455 return u'[%s]: %s' % (self.device.name, self.name)
454 return u'[{}]: {}'.format(self.device.device_type.name.upper(), self.name)
456 455
457 456 def clone(self, **kwargs):
458 457
459 458 self.pk = None
460 459 self.id = None
461 460 for attr, value in kwargs.items():
462 461 setattr(self, attr, value)
463 462
464 463 self.save()
465 464
466 465 return self
467 466
468 467 def parms_to_dict(self):
469 468
470 469 parameters = {}
471 470
472 471 for key in self.__dict__.keys():
473 472 parameters[key] = getattr(self, key)
474 473
475 474 return parameters
476 475
477 476 def parms_to_text(self):
478 477
479 478 raise NotImplementedError, "This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper()
480 479
481 480 return ''
482 481
483 482 def parms_to_binary(self):
484 483
485 484 raise NotImplementedError, "This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper()
486 485
487 486 return ''
488 487
489 488 def dict_to_parms(self, parameters):
490 489
491 490 if type(parameters) != type({}):
492 491 return
493 492
494 493 for key in parameters.keys():
495 494 setattr(self, key, parameters[key])
496 495
497 496 def export_to_file(self, format="json"):
498 497
499 498 import json
500 499
501 500 content_type = ''
502 501
503 502 if format == 'text':
504 503 content_type = 'text/plain'
505 504 filename = '%s_%s.%s' %(self.device.device_type.name, self.name, self.device.device_type.name)
506 505 content = self.parms_to_text()
507 506
508 507 if format == 'binary':
509 508 content_type = 'application/octet-stream'
510 509 filename = '%s_%s.bin' %(self.device.device_type.name, self.name)
511 510 content = self.parms_to_binary()
512 511
513 512 if not content_type:
514 513 content_type = 'application/json'
515 514 filename = '%s_%s.json' %(self.device.device_type.name, self.name)
516 515 content = json.dumps(self.parms_to_dict(), indent=2)
517 516
518 517 fields = {'content_type':content_type,
519 518 'filename':filename,
520 519 'content':content
521 520 }
522 521
523 522 return fields
524 523
525 524 def import_from_file(self, fp):
526 525
527 526 import os, json
528 527
529 528 parms = {}
530 529
531 530 path, ext = os.path.splitext(fp.name)
532 531
533 532 if ext == '.json':
534 533 parms = json.load(fp)
535 534
536 535 return parms
537 536
538 537 def status_device(self):
539 538
540 539 raise NotImplementedError, "This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper()
541 540
542 541 return None
543 542
544 543 def stop_device(self):
545 544
546 545 raise NotImplementedError, "This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper()
547 546
548 547 return None
549 548
550 549 def start_device(self):
551 550
552 551 raise NotImplementedError, "This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper()
553 552
554 553 return None
555 554
556 555 def write_device(self, parms):
557 556
558 557 raise NotImplementedError, "This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper()
559 558
560 559 return None
561 560
562 561 def read_device(self):
563 562
564 563 raise NotImplementedError, "This method should be implemented in %s Configuration model" %str(self.device.device_type.name).upper()
565 564
566 565 return None
567 566
568 567 def get_absolute_url(self):
569 568 return reverse('url_%s_conf' % self.device.device_type.name, args=[str(self.id)])
570 569
571 570 def get_absolute_url_edit(self):
572 571 return reverse('url_edit_%s_conf' % self.device.device_type.name, args=[str(self.id)])
573 572
574 573 def get_absolute_url_import(self):
575 574 return reverse('url_import_dev_conf', args=[str(self.id)])
576 575
577 576 def get_absolute_url_export(self):
578 577 return reverse('url_export_dev_conf', args=[str(self.id)])
579 578
580 579 def get_absolute_url_write(self):
581 580 return reverse('url_write_dev_conf', args=[str(self.id)])
582 581
583 582 def get_absolute_url_read(self):
584 583 return reverse('url_read_dev_conf', args=[str(self.id)])
585 584
586 585 def get_absolute_url_start(self):
587 586 return reverse('url_start_dev_conf', args=[str(self.id)])
588 587
589 588 def get_absolute_url_stop(self):
590 589 return reverse('url_stop_dev_conf', args=[str(self.id)])
591 590
592 591 def get_absolute_url_status(self):
593 592 return reverse('url_status_dev_conf', args=[str(self.id)]) No newline at end of file
@@ -1,1380 +1,1380
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.contrib import messages
6 6 from datetime import datetime
7 7
8 8 from .forms import CampaignForm, ExperimentForm, DeviceForm, ConfigurationForm, LocationForm, UploadFileForm, DownloadFileForm, OperationForm, NewForm
9 9 from .forms import OperationSearchForm
10 10 from apps.cgs.forms import CGSConfigurationForm
11 11 from apps.jars.forms import JARSConfigurationForm
12 12 from apps.usrp.forms import USRPConfigurationForm
13 13 from apps.abs.forms import ABSConfigurationForm
14 14 from apps.rc.forms import RCConfigurationForm, RCMixConfigurationForm
15 15 from apps.dds.forms import DDSConfigurationForm
16 16
17 17 from .models import Campaign, Experiment, Device, Configuration, Location, RunningExperiment
18 18 from apps.cgs.models import CGSConfiguration
19 19 from apps.jars.models import JARSConfiguration
20 20 from apps.usrp.models import USRPConfiguration
21 21 from apps.abs.models import ABSConfiguration
22 22 from apps.rc.models import RCConfiguration, RCLine, RCLineType
23 23 from apps.dds.models import DDSConfiguration
24 24
25 25 # Create your views here.
26 26
27 27 CONF_FORMS = {
28 28 'rc': RCConfigurationForm,
29 'rc_mix': RCMixConfigurationForm,
30 29 'dds': DDSConfigurationForm,
31 30 'jars': JARSConfigurationForm,
32 31 'cgs': CGSConfigurationForm,
33 32 'abs': ABSConfigurationForm,
34 33 'usrp': USRPConfigurationForm,
35 34 }
36 35
37 36 CONF_MODELS = {
38 37 'rc': RCConfiguration,
39 38 'dds': DDSConfiguration,
40 39 'jars': JARSConfiguration,
41 40 'cgs': CGSConfiguration,
42 41 'abs': ABSConfiguration,
43 42 'usrp': USRPConfiguration,
44 43 }
45 44
46 45 MIX_MODES = {
47 46 '0': 'P',
48 47 '1': 'S',
49 48 }
50 49
51 50 MIX_OPERATIONS = {
52 51 '0': 'OR',
53 52 '1': 'XOR',
54 53 '2': 'AND',
55 54 '3': 'NAND',
56 55 }
57 56
58 57
59 58 def index(request):
60 59 kwargs = {}
61 60
62 61 return render(request, 'index.html', kwargs)
63 62
64 63
65 64 def locations(request):
66 65
67 66 locations = Location.objects.all().order_by('name')
68 67
69 68 keys = ['id', 'name', 'description']
70 69
71 70 kwargs = {}
72 71 kwargs['location_keys'] = keys[1:]
73 72 kwargs['locations'] = locations
74 73 kwargs['title'] = 'Location'
75 74 kwargs['suptitle'] = 'List'
76 75 kwargs['button'] = 'New Location'
77 76
78 77 return render(request, 'locations.html', kwargs)
79 78
80 79
81 80 def location(request, id_loc):
82 81
83 82 location = get_object_or_404(Location, pk=id_loc)
84 83
85 84 kwargs = {}
86 85 kwargs['location'] = location
87 86 kwargs['location_keys'] = ['name', 'description']
88 87
89 88 kwargs['title'] = 'Location'
90 89 kwargs['suptitle'] = 'Details'
91 90
92 91 return render(request, 'location.html', kwargs)
93 92
94 93
95 94 def location_new(request):
96 95
97 96 if request.method == 'GET':
98 97 form = LocationForm()
99 98
100 99 if request.method == 'POST':
101 100 form = LocationForm(request.POST)
102 101
103 102 if form.is_valid():
104 103 form.save()
105 104 return redirect('url_locations')
106 105
107 106 kwargs = {}
108 107 kwargs['form'] = form
109 108 kwargs['title'] = 'Location'
110 109 kwargs['suptitle'] = 'New'
111 110 kwargs['button'] = 'Create'
112 111
113 112 return render(request, 'location_edit.html', kwargs)
114 113
115 114
116 115 def location_edit(request, id_loc):
117 116
118 117 location = get_object_or_404(Location, pk=id_loc)
119 118
120 119 if request.method=='GET':
121 120 form = LocationForm(instance=location)
122 121
123 122 if request.method=='POST':
124 123 form = LocationForm(request.POST, instance=location)
125 124
126 125 if form.is_valid():
127 126 form.save()
128 127 return redirect('url_locations')
129 128
130 129 kwargs = {}
131 130 kwargs['form'] = form
132 131 kwargs['title'] = 'Location'
133 132 kwargs['suptitle'] = 'Edit'
134 133 kwargs['button'] = 'Update'
135 134
136 135 return render(request, 'location_edit.html', kwargs)
137 136
138 137
139 138 def location_delete(request, id_loc):
140 139
141 140 location = get_object_or_404(Location, pk=id_loc)
142 141
143 142 if request.method=='POST':
144 143
145 144 if request.user.is_staff:
146 145 location.delete()
147 146 return redirect('url_locations')
148 147
149 148 messages.error(request, 'Not enough permission to delete this object')
150 149 return redirect(location.get_absolute_url())
151 150
152 151 kwargs = {
153 152 'title': 'Delete',
154 153 'suptitle': 'Location',
155 154 'object': location,
156 155 'previous': location.get_absolute_url(),
157 156 'delete': True
158 157 }
159 158
160 159 return render(request, 'confirm.html', kwargs)
161 160
162 161
163 162 def devices(request):
164 163
165 164 devices = Device.objects.all().order_by('device_type__name')
166 165
167 166 # keys = ['id', 'device_type__name', 'name', 'ip_address']
168 167 keys = ['id', 'name', 'ip_address', 'port_address', 'device_type']
169 168
170 169 kwargs = {}
171 170 kwargs['device_keys'] = keys[1:]
172 171 kwargs['devices'] = devices#.values(*keys)
173 172 kwargs['title'] = 'Device'
174 173 kwargs['suptitle'] = 'List'
175 174 kwargs['button'] = 'New Device'
176 175
177 176 return render(request, 'devices.html', kwargs)
178 177
179 178
180 179 def device(request, id_dev):
181 180
182 181 device = get_object_or_404(Device, pk=id_dev)
183 182
184 183 kwargs = {}
185 184 kwargs['device'] = device
186 185 kwargs['device_keys'] = ['device_type', 'name', 'ip_address', 'port_address', 'description']
187 186
188 187 kwargs['title'] = 'Device'
189 188 kwargs['suptitle'] = 'Details'
190 189
191 190 return render(request, 'device.html', kwargs)
192 191
193 192
194 193 def device_new(request):
195 194
196 195 if request.method == 'GET':
197 196 form = DeviceForm()
198 197
199 198 if request.method == 'POST':
200 199 form = DeviceForm(request.POST)
201 200
202 201 if form.is_valid():
203 202 form.save()
204 203 return redirect('url_devices')
205 204
206 205 kwargs = {}
207 206 kwargs['form'] = form
208 207 kwargs['title'] = 'Device'
209 208 kwargs['suptitle'] = 'New'
210 209 kwargs['button'] = 'Create'
211 210
212 211 return render(request, 'device_edit.html', kwargs)
213 212
214 213
215 214 def device_edit(request, id_dev):
216 215
217 216 device = get_object_or_404(Device, pk=id_dev)
218 217
219 218 if request.method=='GET':
220 219 form = DeviceForm(instance=device)
221 220
222 221 if request.method=='POST':
223 222 form = DeviceForm(request.POST, instance=device)
224 223
225 224 if form.is_valid():
226 225 form.save()
227 226 return redirect(device.get_absolute_url())
228 227
229 228 kwargs = {}
230 229 kwargs['form'] = form
231 230 kwargs['title'] = 'Device'
232 231 kwargs['suptitle'] = 'Edit'
233 232 kwargs['button'] = 'Update'
234 233
235 234 return render(request, 'device_edit.html', kwargs)
236 235
237 236
238 237 def device_delete(request, id_dev):
239 238
240 239 device = get_object_or_404(Device, pk=id_dev)
241 240
242 241 if request.method=='POST':
243 242
244 243 if request.user.is_staff:
245 244 device.delete()
246 245 return redirect('url_devices')
247 246
248 247 messages.error(request, 'Not enough permission to delete this object')
249 248 return redirect(device.get_absolute_url())
250 249
251 250 kwargs = {
252 251 'title': 'Delete',
253 252 'suptitle': 'Device',
254 253 'object': device,
255 254 'previous': device.get_absolute_url(),
256 255 'delete': True
257 256 }
258 257
259 258 return render(request, 'confirm.html', kwargs)
260 259
261 260
262 261 def campaigns(request):
263 262
264 263 campaigns = Campaign.objects.all().order_by('start_date')
265 264
266 265 keys = ['id', 'name', 'start_date', 'end_date']
267 266
268 267 kwargs = {}
269 268 kwargs['campaign_keys'] = keys[1:]
270 269 kwargs['campaigns'] = campaigns#.values(*keys)
271 270 kwargs['title'] = 'Campaign'
272 271 kwargs['suptitle'] = 'List'
273 272 kwargs['button'] = 'New Campaign'
274 273
275 274 return render(request, 'campaigns.html', kwargs)
276 275
277 276
278 277 def campaign(request, id_camp):
279 278
280 279 campaign = get_object_or_404(Campaign, pk=id_camp)
281 280 experiments = Experiment.objects.filter(campaign=campaign)
282 281
283 282 form = CampaignForm(instance=campaign)
284 283
285 284 kwargs = {}
286 285 kwargs['campaign'] = campaign
287 286 kwargs['campaign_keys'] = ['template', 'name', 'start_date', 'end_date', 'tags', 'description']
288 287
289 288 kwargs['experiments'] = experiments
290 289 kwargs['experiment_keys'] = ['name', 'radar', 'start_time', 'end_time']
291 290
292 291 kwargs['title'] = 'Campaign'
293 292 kwargs['suptitle'] = 'Details'
294 293
295 294 kwargs['form'] = form
296 295 kwargs['button'] = 'Add Experiment'
297 296
298 297 return render(request, 'campaign.html', kwargs)
299 298
300 299
301 300 def campaign_new(request):
302 301
303 302 kwargs = {}
304 303
305 304 if request.method == 'GET':
306 305
307 306 if 'template' in request.GET:
308 307 if request.GET['template']=='0':
309 308 form = NewForm(initial={'create_from':2},
310 309 template_choices=Campaign.objects.filter(template=True).values_list('id', 'name'))
311 310 else:
312 311 kwargs['button'] = 'Create'
313 312 kwargs['experiments'] = Configuration.objects.filter(experiment=request.GET['template'])
314 313 kwargs['experiment_keys'] = ['name', 'start_time', 'end_time']
315 314 camp = Campaign.objects.get(pk=request.GET['template'])
316 315 form = CampaignForm(instance=camp,
317 316 initial={'name':'{} [{:%Y/%m/%d}]'.format(camp.name, datetime.now()),
318 317 'template':False})
319 318 elif 'blank' in request.GET:
320 319 kwargs['button'] = 'Create'
321 320 form = CampaignForm()
322 321 else:
323 322 form = NewForm()
324 323
325 324 if request.method == 'POST':
326 325 kwargs['button'] = 'Create'
327 326 post = request.POST.copy()
328 327 experiments = []
329 328
330 329 for id_exp in post.getlist('experiments'):
331 330 exp = Experiment.objects.get(pk=id_exp)
332 331 new_exp = exp.clone(template=False)
333 332 experiments.append(new_exp)
334 333
335 334 post.setlist('experiments', [])
336 335
337 336 form = CampaignForm(post)
338 337
339 338 if form.is_valid():
340 339 campaign = form.save()
341 340 for exp in experiments:
342 341 campaign.experiments.add(exp)
343 342 campaign.save()
344 343 return redirect('url_campaign', id_camp=campaign.id)
345 344
346 345 kwargs['form'] = form
347 346 kwargs['title'] = 'Campaign'
348 347 kwargs['suptitle'] = 'New'
349 348
350 349 return render(request, 'campaign_edit.html', kwargs)
351 350
352 351
353 352 def campaign_edit(request, id_camp):
354 353
355 354 campaign = get_object_or_404(Campaign, pk=id_camp)
356 355
357 356 if request.method=='GET':
358 357 form = CampaignForm(instance=campaign)
359 358
360 359 if request.method=='POST':
361 360 exps = campaign.experiments.all().values_list('pk', flat=True)
362 361 post = request.POST.copy()
363 362 new_exps = post.getlist('experiments')
364 363 post.setlist('experiments', [])
365 364 form = CampaignForm(post, instance=campaign)
366 365
367 366 if form.is_valid():
368 367 camp = form.save()
369 368 for id_exp in new_exps:
370 369 if int(id_exp) in exps:
371 370 exps.pop(id_exp)
372 371 else:
373 372 exp = Experiment.objects.get(pk=id_exp)
374 373 if exp.template:
375 374 camp.experiments.add(exp.clone(template=False))
376 375 else:
377 376 camp.experiments.add(exp)
378 377
379 378 for id_exp in exps:
380 379 camp.experiments.remove(Experiment.objects.get(pk=id_exp))
381 380
382 381 return redirect('url_campaign', id_camp=id_camp)
383 382
384 383 kwargs = {}
385 384 kwargs['form'] = form
386 385 kwargs['title'] = 'Campaign'
387 386 kwargs['suptitle'] = 'Edit'
388 387 kwargs['button'] = 'Update'
389 388
390 389 return render(request, 'campaign_edit.html', kwargs)
391 390
392 391
393 392 def campaign_delete(request, id_camp):
394 393
395 394 campaign = get_object_or_404(Campaign, pk=id_camp)
396 395
397 396 if request.method=='POST':
398 397 if request.user.is_staff:
399 398
400 399 for exp in campaign.experiments.all():
401 400 for conf in Configuration.objects.filter(experiment=exp):
402 401 conf.delete()
403 402 exp.delete()
404 403 campaign.delete()
405 404
406 405 return redirect('url_campaigns')
407 406
408 407 messages.error(request, 'Not enough permission to delete this object')
409 408 return redirect(campaign.get_absolute_url())
410 409
411 410 kwargs = {
412 411 'title': 'Delete',
413 412 'suptitle': 'Campaign',
414 413 'object': campaign,
415 414 'previous': campaign.get_absolute_url(),
416 415 'delete': True
417 416 }
418 417
419 418 return render(request, 'confirm.html', kwargs)
420 419
421 420 def campaign_export(request, id_camp):
422 421
423 422 campaign = get_object_or_404(Campaign, pk=id_camp)
424 423 content = campaign.parms_to_dict()
425 424 content_type = 'application/json'
426 425 filename = '%s_%s.json' %(campaign.name, campaign.id)
427 426
428 427 response = HttpResponse(content_type=content_type)
429 428 response['Content-Disposition'] = 'attachment; filename="%s"' %filename
430 429 response.write(content)
431 430
432 431 return response
433 432
434 433
435 434 def campaign_import(request, id_camp):
436 435
437 436 campaign = get_object_or_404(Campaign, pk=id_camp)
438 437
439 438 if request.method == 'GET':
440 439 file_form = UploadFileForm()
441 440
442 441 if request.method == 'POST':
443 442 file_form = UploadFileForm(request.POST, request.FILES)
444 443
445 444 if file_form.is_valid():
446 445
447 446 parms = campaign.import_from_file(request.FILES['file'])
448 447
449 448 if parms:
450 449 parms['name'] = parms['campaign']
451 450
452 451 new_camp = campaign.dict_to_parms(parms, CONF_MODELS)
453 452
454 453 messages.success(request, "Parameters imported from: '%s'." %request.FILES['file'].name)
455 454
456 455 return redirect(new_camp.get_absolute_url_edit())
457 456
458 457 messages.error(request, "Could not import parameters from file")
459 458
460 459 kwargs = {}
461 460 kwargs['title'] = 'Campaign'
462 461 kwargs['form'] = file_form
463 462 kwargs['suptitle'] = 'Importing file'
464 463 kwargs['button'] = 'Import'
465 464
466 465 return render(request, 'campaign_import.html', kwargs)
467 466
468 467
469 468 def experiments(request):
470 469
471 470 experiment_list = Experiment.objects.all()
472 471
473 472 keys = ['id', 'name', 'start_time', 'end_time']
474 473
475 474 kwargs = {}
476 475
477 476 kwargs['experiment_keys'] = keys[1:]
478 477 kwargs['experiments'] = experiment_list
479 478
480 479 kwargs['title'] = 'Experiment'
481 480 kwargs['suptitle'] = 'List'
482 481 kwargs['button'] = 'New Experiment'
483 482
484 483 return render(request, 'experiments.html', kwargs)
485 484
486 485
487 486 def experiment(request, id_exp):
488 487
489 488 experiment = get_object_or_404(Experiment, pk=id_exp)
490 489
491 490 configurations = Configuration.objects.filter(experiment=experiment, type=0)
492 491
493 492 kwargs = {}
494 493
495 494 kwargs['experiment_keys'] = ['template', 'radar', 'name', 'start_time', 'end_time']
496 495 kwargs['experiment'] = experiment
497 496
498 kwargs['configuration_keys'] = ['name', 'device__device_type', 'device__ip_address', 'device__port_address', 'device__status']
497 kwargs['configuration_keys'] = ['name', 'device__ip_address', 'device__port_address', 'device__status']
499 498 kwargs['configurations'] = configurations
500 499
501 500 kwargs['title'] = 'Experiment'
502 501 kwargs['suptitle'] = 'Details'
503 502
504 503 kwargs['button'] = 'Add Configuration'
505 504
506 505 ###### SIDEBAR ######
507 506 kwargs.update(sidebar(experiment=experiment))
508 507
509 508 return render(request, 'experiment.html', kwargs)
510 509
511 510
512 511 def experiment_new(request, id_camp=None):
513 512
514 513 kwargs = {}
515 514
516 515 if request.method == 'GET':
517 516 if 'template' in request.GET:
518 517 if request.GET['template']=='0':
519 518 form = NewForm(initial={'create_from':2},
520 519 template_choices=Experiment.objects.filter(template=True).values_list('id', 'name'))
521 520 else:
522 521 kwargs['button'] = 'Create'
523 522 kwargs['configurations'] = Configuration.objects.filter(experiment=request.GET['template'])
524 523 kwargs['configuration_keys'] = ['name', 'device__name', 'device__ip_address', 'device__port_address']
525 524 exp=Experiment.objects.get(pk=request.GET['template'])
526 525 form = ExperimentForm(instance=exp,
527 526 initial={'name': '{} [{:%Y/%m/%d}]'.format(exp.name, datetime.now()),
528 527 'template': False})
529 528 elif 'blank' in request.GET:
530 529 kwargs['button'] = 'Create'
531 530 form = ExperimentForm()
532 531 else:
533 532 form = NewForm()
534 533
535 534 if request.method == 'POST':
536 535 form = ExperimentForm(request.POST)
537 536 if form.is_valid():
538 537 experiment = form.save()
539 538
540 539 if 'template' in request.GET:
541 540 configurations = Configuration.objects.filter(experiment=request.GET['template'], type=0)
542 541 for conf in configurations:
543 542 conf.clone(experiment=experiment, template=False)
544 543
545 544 return redirect('url_experiment', id_exp=experiment.id)
546 545
547 546 kwargs['form'] = form
548 547 kwargs['title'] = 'Experiment'
549 548 kwargs['suptitle'] = 'New'
550 549
551 550 return render(request, 'experiment_edit.html', kwargs)
552 551
553 552
554 553 def experiment_edit(request, id_exp):
555 554
556 555 experiment = get_object_or_404(Experiment, pk=id_exp)
557 556
558 557 if request.method == 'GET':
559 558 form = ExperimentForm(instance=experiment)
560 559
561 560 if request.method=='POST':
562 561 form = ExperimentForm(request.POST, instance=experiment)
563 562
564 563 if form.is_valid():
565 564 experiment = form.save()
566 565 return redirect('url_experiment', id_exp=experiment.id)
567 566
568 567 kwargs = {}
569 568 kwargs['form'] = form
570 569 kwargs['title'] = 'Experiment'
571 570 kwargs['suptitle'] = 'Edit'
572 571 kwargs['button'] = 'Update'
573 572
574 573 return render(request, 'experiment_edit.html', kwargs)
575 574
576 575
577 576 def experiment_delete(request, id_exp):
578 577
579 578 experiment = get_object_or_404(Experiment, pk=id_exp)
580 579
581 580 if request.method=='POST':
582 581 if request.user.is_staff:
583 582 for conf in Configuration.objects.filter(experiment=experiment):
584 583 conf.delete()
585 584 experiment.delete()
586 585 return redirect('url_experiments')
587 586
588 587 messages.error(request, 'Not enough permission to delete this object')
589 588 return redirect(experiment.get_absolute_url())
590 589
591 590 kwargs = {
592 591 'title': 'Delete',
593 592 'suptitle': 'Experiment',
594 593 'object': experiment,
595 594 'previous': experiment.get_absolute_url(),
596 595 'delete': True
597 596 }
598 597
599 598 return render(request, 'confirm.html', kwargs)
600 599
601 600
602 601 def experiment_export(request, id_exp):
603 602
604 603 experiment = get_object_or_404(Experiment, pk=id_exp)
605 604 content = experiment.parms_to_dict()
606 605 content_type = 'application/json'
607 606 filename = '%s_%s.json' %(experiment.name, experiment.id)
608 607
609 608 response = HttpResponse(content_type=content_type)
610 609 response['Content-Disposition'] = 'attachment; filename="%s"' %filename
611 610 response.write(content)
612 611
613 612 return response
614 613
615 614 def experiment_import(request, id_exp):
616 615
617 616 experiment = get_object_or_404(Experiment, pk=id_exp)
618 617 configurations = Configuration.objects.filter(experiment=experiment)
619 618
620 619 if request.method == 'GET':
621 620 file_form = UploadFileForm()
622 621
623 622 if request.method == 'POST':
624 623 file_form = UploadFileForm(request.POST, request.FILES)
625 624
626 625 if file_form.is_valid():
627 626
628 627 parms = experiment.import_from_file(request.FILES['file'])
629 628
630 629 if parms:
631 630
632 631 new_exp = experiment.dict_to_parms(parms, CONF_MODELS)
633 632
634 633 messages.success(request, "Parameters imported from: '%s'." %request.FILES['file'].name)
635 634
636 635 return redirect(new_exp.get_absolute_url_edit())
637 636
638 637 messages.error(request, "Could not import parameters from file")
639 638
640 639 kwargs = {}
641 640 kwargs['title'] = 'Experiment'
642 641 kwargs['form'] = file_form
643 642 kwargs['suptitle'] = 'Importing file'
644 643 kwargs['button'] = 'Import'
645 644
646 645 kwargs.update(sidebar(experiment=experiment))
647 646
648 647 return render(request, 'experiment_import.html', kwargs)
649 648
650 649 def experiment_mix(request, id_exp):
651 650
652 651 experiment = get_object_or_404(Experiment, pk=id_exp)
653 652 rc_confs = [conf for conf in RCConfiguration.objects.filter(experiment=id_exp,
654 653 mix=False)]
655 654
656 655 if len(rc_confs)<2:
657 656 messages.warning(request, 'You need at least two RC Configurations to make a mix')
658 657 return redirect(experiment.get_absolute_url())
659 658
660 659 mix_confs = RCConfiguration.objects.filter(experiment=id_exp, mix=True)
661 660
662 661 if mix_confs:
663 662 mix = mix_confs[0]
664 663 else:
665 664 mix = RCConfiguration(experiment=experiment,
666 665 device=rc_confs[0].device,
667 666 ipp=rc_confs[0].ipp,
668 667 clock_in=rc_confs[0].clock_in,
669 668 clock_divider=rc_confs[0].clock_divider,
670 669 mix=True,
671 670 parameters='')
672 671 mix.save()
673 672
674 673 line_type = RCLineType.objects.get(name='mix')
675 674 for i in range(len(rc_confs[0].get_lines())):
676 675 line = RCLine(rc_configuration=mix, line_type=line_type, channel=i)
677 676 line.save()
678 677
679 678 initial = {'name': mix.name,
680 679 'result': parse_mix_result(mix.parameters),
681 680 'delay': 0,
682 681 'mask': [0,1,2,3,4,5,6,7]
683 682 }
684 683
685 684 if request.method=='GET':
686 685 form = RCMixConfigurationForm(confs=rc_confs, initial=initial)
687 686
688 687 if request.method=='POST':
689 688 result = mix.parameters
690 689
691 690 if '{}|'.format(request.POST['experiment']) in result:
692 691 messages.error(request, 'Configuration already added')
693 692 else:
694 693 if 'operation' in request.POST:
695 694 operation = MIX_OPERATIONS[request.POST['operation']]
696 695 else:
697 696 operation = ' '
698 697
699 698 mode = MIX_MODES[request.POST['mode']]
700 699
701 700 if result:
702 701 result = '{}-{}|{}|{}|{}|{}'.format(mix.parameters,
703 702 request.POST['experiment'],
704 703 mode,
705 704 operation,
706 705 float(request.POST['delay']),
707 706 parse_mask(request.POST.getlist('mask'))
708 707 )
709 708 else:
710 709 result = '{}|{}|{}|{}|{}'.format(request.POST['experiment'],
711 710 mode,
712 711 operation,
713 712 float(request.POST['delay']),
714 713 parse_mask(request.POST.getlist('mask'))
715 714 )
716 715
717 716 mix.parameters = result
718 717 mix.name = request.POST['name']
719 718 mix.save()
720 719 mix.update_pulses()
721 720
722 721 initial['result'] = parse_mix_result(result)
723 722 initial['name'] = mix.name
724 723
725 724 form = RCMixConfigurationForm(initial=initial, confs=rc_confs)
726 725
727 726
728 727 kwargs = {
729 728 'title': 'Experiment',
730 729 'suptitle': 'Mix Configurations',
731 730 'form' : form,
732 731 'extra_button': 'Delete',
733 732 'button': 'Add',
734 733 'cancel': 'Back',
735 734 'previous': experiment.get_absolute_url(),
736 735 'id_exp':id_exp,
737 736
738 737 }
739 738
740 739 return render(request, 'experiment_mix.html', kwargs)
741 740
742 741
743 742 def experiment_mix_delete(request, id_exp):
744 743
745 744 conf = RCConfiguration.objects.get(experiment=id_exp, mix=True)
746 745 values = conf.parameters.split('-')
747 746 conf.parameters = '-'.join(values[:-1])
748 747 conf.save()
749 748
750 749 return redirect('url_mix_experiment', id_exp=id_exp)
751 750
752 751
753 752 def parse_mix_result(s):
754 753
755 754 values = s.split('-')
756 755 html = 'EXP MOD OPE DELAY MASK\r\n'
757 756
758 757 if not values or values[0] in ('', ' '):
759 758 return mark_safe(html)
760 759
761 760 for i, value in enumerate(values):
762 761 if not value:
763 762 continue
764 763 pk, mode, operation, delay, mask = value.split('|')
765 764 conf = RCConfiguration.objects.get(pk=pk)
766 765 if i==0:
767 766 html += '{:20.18}{:3}{:4}{:9}km{:>6}\r\n'.format(
768 767 conf.name,
769 768 mode,
770 769 ' ',
771 770 delay,
772 771 mask)
773 772 else:
774 773 html += '{:20.18}{:3}{:4}{:9}km{:>6}\r\n'.format(
775 774 conf.name,
776 775 mode,
777 776 operation,
778 777 delay,
779 778 mask)
780 779
781 780 return mark_safe(html)
782 781
783 782 def parse_mask(l):
784 783
785 784 values = []
786 785
787 786 for x in range(8):
788 787 if '{}'.format(x) in l:
789 788 values.append(1)
790 789 else:
791 790 values.append(0)
792 791
793 792 values.reverse()
794 793
795 794 return int(''.join([str(x) for x in values]), 2)
796 795
797 796
798 797 def dev_confs(request):
799 798
800 799 configurations = Configuration.objects.all().order_by('type', 'device__device_type', 'experiment')
801 800
802 801 kwargs = {}
803 802
804 803 kwargs['configuration_keys'] = ['device', 'name', 'experiment', 'type', 'programmed_date']
805 804 kwargs['configurations'] = configurations
806 805
807 806 kwargs['title'] = 'Configuration'
808 807 kwargs['suptitle'] = 'List'
809 808
810 809 return render(request, 'dev_confs.html', kwargs)
811 810
812 811
813 812 def dev_conf(request, id_conf):
814 813
815 814 conf = get_object_or_404(Configuration, pk=id_conf)
816 815
817 816 return redirect(conf.get_absolute_url())
818 817
819 818
820 819 def dev_conf_new(request, id_exp=0, id_dev=0):
821 820
822 821 initial = {}
823 822 kwargs = {}
824 823
825 824 if id_exp<>0:
826 825 initial['experiment'] = id_exp
827 826
828 827 if id_dev<>0:
829 828 initial['device'] = id_dev
830 829
831 830 if request.method == 'GET':
832 831
833 832 if id_dev:
834 833 kwargs['button'] = 'Create'
835 834 device = Device.objects.get(pk=id_dev)
836 835 DevConfForm = CONF_FORMS[device.device_type.name]
837 836 initial['name'] = request.GET['name']
838 form = DevConfForm(initial=initial)
837 form = DevConfForm(initial=initial)
839 838 else:
840 839 if 'template' in request.GET:
841 840 if request.GET['template']=='0':
841 choices = [(conf.pk, '{}'.format(conf)) for conf in Configuration.objects.filter(template=True)]
842 842 form = NewForm(initial={'create_from':2},
843 template_choices=Configuration.objects.filter(template=True).values_list('id', 'name'))
843 template_choices=choices)
844 844 else:
845 845 kwargs['button'] = 'Create'
846 846 conf = Configuration.objects.get(pk=request.GET['template'])
847 847 id_dev = conf.device.pk
848 848 DevConfForm = CONF_FORMS[conf.device.device_type.name]
849 849 form = DevConfForm(instance=conf,
850 850 initial={'name': '{} [{:%Y/%m/%d}]'.format(conf.name, datetime.now()),
851 851 'template': False,
852 852 'experiment':id_exp})
853 853 elif 'blank' in request.GET:
854 kwargs['button'] = 'Create'
854 kwargs['button'] = 'Create'
855 855 form = ConfigurationForm(initial=initial)
856 856 else:
857 857 form = NewForm()
858 858
859 859 if request.method == 'POST':
860 860
861 861 device = Device.objects.get(pk=request.POST['device'])
862 862 DevConfForm = CONF_FORMS[device.device_type.name]
863 863
864 864 form = DevConfForm(request.POST)
865 865
866 866 if form.is_valid():
867 867 conf = form.save()
868 868
869 869 if 'template' in request.GET and conf.device.device_type.name=='rc':
870 870 lines = RCLine.objects.filter(rc_configuration=request.GET['template'])
871 871 for line in lines:
872 872 line.clone(rc_configuration=conf)
873 873
874 874 return redirect('url_dev_conf', id_conf=conf.pk)
875 875
876 876
877 877 kwargs['id_exp'] = id_exp
878 878 kwargs['form'] = form
879 879 kwargs['title'] = 'Configuration'
880 880 kwargs['suptitle'] = 'New'
881 881
882 882
883 883 if id_dev != 0:
884 884 device = Device.objects.get(pk=id_dev)
885 885 kwargs['device'] = device.device_type.name
886 886
887 887 return render(request, 'dev_conf_edit.html', kwargs)
888 888
889 889
890 890 def dev_conf_edit(request, id_conf):
891 891
892 892 conf = get_object_or_404(Configuration, pk=id_conf)
893 893
894 894 DevConfModel = CONF_MODELS[conf.device.device_type.name]
895 895 DevConfForm = CONF_FORMS[conf.device.device_type.name]
896 896
897 897 dev_conf = DevConfModel.objects.get(pk=id_conf)
898 898
899 899 if request.method=='GET':
900 900 form = DevConfForm(instance=dev_conf)
901 901
902 902 if request.method=='POST':
903 903 form = DevConfForm(request.POST, instance=dev_conf)
904 904
905 905 if form.is_valid():
906 906 form.save()
907 907 return redirect('url_dev_conf', id_conf=id_conf)
908 908
909 909 kwargs = {}
910 910 kwargs['form'] = form
911 911 kwargs['title'] = 'Device Configuration'
912 912 kwargs['suptitle'] = 'Edit'
913 913 kwargs['button'] = 'Update'
914 914
915 915 ###### SIDEBAR ######
916 916 kwargs.update(sidebar(conf=conf))
917 917
918 918 return render(request, '%s_conf_edit.html' % conf.device.device_type.name, kwargs)
919 919
920 920
921 921 def dev_conf_start(request, id_conf):
922 922
923 923 conf = get_object_or_404(Configuration, pk=id_conf)
924 924
925 925 DevConfModel = CONF_MODELS[conf.device.device_type.name]
926 926
927 927 conf = DevConfModel.objects.get(pk=id_conf)
928 928
929 929 if conf.start_device():
930 930 messages.success(request, conf.message)
931 931 else:
932 932 messages.error(request, conf.message)
933 933
934 934 conf.status_device()
935 935
936 936 return redirect(conf.get_absolute_url())
937 937
938 938
939 939 def dev_conf_stop(request, id_conf):
940 940
941 941 conf = get_object_or_404(Configuration, pk=id_conf)
942 942
943 943 DevConfModel = CONF_MODELS[conf.device.device_type.name]
944 944
945 945 conf = DevConfModel.objects.get(pk=id_conf)
946 946
947 947 if conf.stop_device():
948 948 messages.success(request, conf.message)
949 949 else:
950 950 messages.error(request, conf.message)
951 951
952 952 conf.status_device()
953 953
954 954 return redirect(conf.get_absolute_url())
955 955
956 956
957 957 def dev_conf_status(request, id_conf):
958 958
959 959 conf = get_object_or_404(Configuration, pk=id_conf)
960 960
961 961 DevConfModel = CONF_MODELS[conf.device.device_type.name]
962 962
963 963 conf = DevConfModel.objects.get(pk=id_conf)
964 964
965 965 if conf.status_device():
966 966 messages.success(request, conf.message)
967 967 else:
968 968 messages.error(request, conf.message)
969 969
970 970 return redirect(conf.get_absolute_url())
971 971
972 972
973 973 def dev_conf_write(request, id_conf):
974 974
975 975 conf = get_object_or_404(Configuration, pk=id_conf)
976 976
977 977 DevConfModel = CONF_MODELS[conf.device.device_type.name]
978 978
979 979 conf = DevConfModel.objects.get(pk=id_conf)
980 980
981 981 answer = conf.write_device()
982 982 conf.status_device()
983 983
984 984 if answer:
985 985 messages.success(request, conf.message)
986 986
987 987 #Creating a historical configuration
988 988 conf.clone(type=0, template=False)
989 989
990 990 #Original configuration
991 991 conf = DevConfModel.objects.get(pk=id_conf)
992 992 else:
993 993 messages.error(request, conf.message)
994 994
995 995 return redirect(conf.get_absolute_url())
996 996
997 997
998 998 def dev_conf_read(request, id_conf):
999 999
1000 1000 conf = get_object_or_404(Configuration, pk=id_conf)
1001 1001
1002 1002 DevConfModel = CONF_MODELS[conf.device.device_type.name]
1003 1003 DevConfForm = CONF_FORMS[conf.device.device_type.name]
1004 1004
1005 1005 conf = DevConfModel.objects.get(pk=id_conf)
1006 1006
1007 1007 if request.method=='GET':
1008 1008
1009 1009 parms = conf.read_device()
1010 1010 conf.status_device()
1011 1011
1012 1012 if not parms:
1013 1013 messages.error(request, conf.message)
1014 1014 return redirect(conf.get_absolute_url())
1015 1015
1016 1016 form = DevConfForm(initial=parms, instance=conf)
1017 1017
1018 1018 if request.method=='POST':
1019 1019 form = DevConfForm(request.POST, instance=conf)
1020 1020
1021 1021 if form.is_valid():
1022 1022 form.save()
1023 1023 return redirect(conf.get_absolute_url())
1024 1024
1025 1025 messages.error(request, "Parameters could not be saved")
1026 1026
1027 1027 kwargs = {}
1028 1028 kwargs['id_dev'] = conf.id
1029 1029 kwargs['form'] = form
1030 1030 kwargs['title'] = 'Device Configuration'
1031 1031 kwargs['suptitle'] = 'Parameters read from device'
1032 1032 kwargs['button'] = 'Save'
1033 1033
1034 1034 ###### SIDEBAR ######
1035 1035 kwargs.update(sidebar(conf=conf))
1036 1036
1037 1037 return render(request, '%s_conf_edit.html' %conf.device.device_type.name, kwargs)
1038 1038
1039 1039
1040 1040 def dev_conf_import(request, id_conf):
1041 1041
1042 1042 conf = get_object_or_404(Configuration, pk=id_conf)
1043 1043
1044 1044 DevConfModel = CONF_MODELS[conf.device.device_type.name]
1045 1045 DevConfForm = CONF_FORMS[conf.device.device_type.name]
1046 1046 conf = DevConfModel.objects.get(pk=id_conf)
1047 1047
1048 1048 if request.method == 'GET':
1049 1049 file_form = UploadFileForm()
1050 1050
1051 1051 if request.method == 'POST':
1052 1052 file_form = UploadFileForm(request.POST, request.FILES)
1053 1053
1054 1054 if file_form.is_valid():
1055 1055
1056 1056 parms = conf.import_from_file(request.FILES['file'])
1057 1057
1058 1058 if parms:
1059 1059 messages.success(request, "Parameters imported from: '%s'." %request.FILES['file'].name)
1060 1060 form = DevConfForm(initial=parms, instance=conf)
1061 1061
1062 1062 kwargs = {}
1063 1063 kwargs['id_dev'] = conf.id
1064 1064 kwargs['form'] = form
1065 1065 kwargs['title'] = 'Device Configuration'
1066 1066 kwargs['suptitle'] = 'Parameters imported'
1067 1067 kwargs['button'] = 'Save'
1068 1068 kwargs['action'] = conf.get_absolute_url_edit()
1069 1069 kwargs['previous'] = conf.get_absolute_url()
1070 1070
1071 1071 ###### SIDEBAR ######
1072 1072 kwargs.update(sidebar(conf=conf))
1073 1073
1074 1074 return render(request, '%s_conf_edit.html' % conf.device.device_type.name, kwargs)
1075 1075
1076 1076 messages.error(request, "Could not import parameters from file")
1077 1077
1078 1078 kwargs = {}
1079 1079 kwargs['id_dev'] = conf.id
1080 1080 kwargs['title'] = 'Device Configuration'
1081 1081 kwargs['form'] = file_form
1082 1082 kwargs['suptitle'] = 'Importing file'
1083 1083 kwargs['button'] = 'Import'
1084 1084
1085 1085 kwargs.update(sidebar(conf=conf))
1086 1086
1087 1087 return render(request, 'dev_conf_import.html', kwargs)
1088 1088
1089 1089
1090 1090 def dev_conf_export(request, id_conf):
1091 1091
1092 1092 conf = get_object_or_404(Configuration, pk=id_conf)
1093 1093
1094 1094 DevConfModel = CONF_MODELS[conf.device.device_type.name]
1095 1095
1096 1096 conf = DevConfModel.objects.get(pk=id_conf)
1097 1097
1098 1098 if request.method == 'GET':
1099 1099 file_form = DownloadFileForm(conf.device.device_type.name)
1100 1100
1101 1101 if request.method == 'POST':
1102 1102 file_form = DownloadFileForm(conf.device.device_type.name, request.POST)
1103 1103
1104 1104 if file_form.is_valid():
1105 1105 fields = conf.export_to_file(format = file_form.cleaned_data['format'])
1106 1106
1107 1107 response = HttpResponse(content_type=fields['content_type'])
1108 1108 response['Content-Disposition'] = 'attachment; filename="%s"' %fields['filename']
1109 1109 response.write(fields['content'])
1110 1110
1111 1111 return response
1112 1112
1113 1113 messages.error(request, "Could not export parameters")
1114 1114
1115 1115 kwargs = {}
1116 1116 kwargs['id_dev'] = conf.id
1117 1117 kwargs['title'] = 'Device Configuration'
1118 1118 kwargs['form'] = file_form
1119 1119 kwargs['suptitle'] = 'Exporting file'
1120 1120 kwargs['button'] = 'Export'
1121 1121
1122 1122 return render(request, 'dev_conf_export.html', kwargs)
1123 1123
1124 1124
1125 1125 def dev_conf_delete(request, id_conf):
1126 1126
1127 1127 conf = get_object_or_404(Configuration, pk=id_conf)
1128 1128
1129 1129 if request.method=='POST':
1130 1130 if request.user.is_staff:
1131 1131 conf.delete()
1132 1132 return redirect('url_dev_confs')
1133 1133
1134 1134 messages.error(request, 'Not enough permission to delete this object')
1135 1135 return redirect(conf.get_absolute_url())
1136 1136
1137 1137 kwargs = {
1138 1138 'title': 'Delete',
1139 1139 'suptitle': 'Experiment',
1140 1140 'object': conf,
1141 1141 'previous': conf.get_absolute_url(),
1142 1142 'delete': True
1143 1143 }
1144 1144
1145 1145 return render(request, 'confirm.html', kwargs)
1146 1146
1147 1147
1148 1148 def sidebar(**kwargs):
1149 1149
1150 1150 side_data = {}
1151 1151
1152 1152 conf = kwargs.get('conf', None)
1153 1153 experiment = kwargs.get('experiment', None)
1154 1154
1155 1155 if not experiment:
1156 1156 experiment = conf.experiment
1157 1157
1158 1158 if experiment:
1159 1159 side_data['experiment'] = experiment
1160 1160 campaign = experiment.campaign_set.all()
1161 1161 if campaign:
1162 1162 side_data['campaign'] = campaign[0]
1163 1163 experiments = campaign[0].experiments.all()
1164 1164 else:
1165 1165 experiments = [experiment]
1166 1166 configurations = experiment.configuration_set.filter(type=0)
1167 1167 side_data['side_experiments'] = experiments
1168 1168 side_data['side_configurations'] = configurations
1169 1169
1170 1170 return side_data
1171 1171
1172 1172
1173 1173 def operation(request, id_camp=None):
1174 1174
1175 1175 if not id_camp:
1176 1176 campaigns = Campaign.objects.all().order_by('-start_date')
1177 1177
1178 1178 if not campaigns:
1179 1179 kwargs = {}
1180 1180 kwargs['title'] = 'No Campaigns'
1181 1181 kwargs['suptitle'] = 'Empty'
1182 1182 return render(request, 'operation.html', kwargs)
1183 1183
1184 1184 id_camp = campaigns[0].id
1185 1185
1186 1186 campaign = get_object_or_404(Campaign, pk = id_camp)
1187 1187
1188 1188 if request.method=='GET':
1189 1189 form = OperationForm(initial={'campaign': campaign.id}, length = 5)
1190 1190
1191 1191 if request.method=='POST':
1192 1192 form = OperationForm(request.POST, initial={'campaign':campaign.id}, length = 5)
1193 1193
1194 1194 if form.is_valid():
1195 1195 return redirect('url_operation', id_camp=campaign.id)
1196 1196 #locations = Location.objects.filter(experiment__campaign__pk = campaign.id).distinct()
1197 1197 experiments = Experiment.objects.filter(campaign__pk=campaign.id)
1198 1198 #for exs in experiments:
1199 1199 # exs.get_status()
1200 1200 locations= Location.objects.filter(experiment=experiments).distinct()
1201 1201 #experiments = [Experiment.objects.filter(location__pk=location.id).filter(campaign__pk=campaign.id) for location in locations]
1202 1202 kwargs = {}
1203 1203 #---Campaign
1204 1204 kwargs['campaign'] = campaign
1205 1205 kwargs['campaign_keys'] = ['name', 'start_date', 'end_date', 'tags', 'description']
1206 1206 #---Experiment
1207 1207 keys = ['id', 'name', 'start_time', 'end_time', 'status']
1208 1208 kwargs['experiment_keys'] = keys[1:]
1209 1209 kwargs['experiments'] = experiments
1210 1210 #---Radar
1211 1211 kwargs['locations'] = locations
1212 1212 #---Else
1213 1213 kwargs['title'] = 'Campaign'
1214 1214 kwargs['suptitle'] = campaign.name
1215 1215 kwargs['form'] = form
1216 1216 kwargs['button'] = 'Search'
1217 1217 kwargs['details'] = True
1218 1218 kwargs['search_button'] = True
1219 1219
1220 1220 return render(request, 'operation.html', kwargs)
1221 1221
1222 1222
1223 1223 def operation_search(request, id_camp=None):
1224 1224
1225 1225
1226 1226 if not id_camp:
1227 1227 campaigns = Campaign.objects.all().order_by('-start_date')
1228 1228
1229 1229 if not campaigns:
1230 1230 return render(request, 'operation.html', {})
1231 1231
1232 1232 id_camp = campaigns[0].id
1233 1233 campaign = get_object_or_404(Campaign, pk = id_camp)
1234 1234
1235 1235 if request.method=='GET':
1236 1236 form = OperationSearchForm(initial={'campaign': campaign.id})
1237 1237
1238 1238 if request.method=='POST':
1239 1239 form = OperationSearchForm(request.POST, initial={'campaign':campaign.id})
1240 1240
1241 1241 if form.is_valid():
1242 1242 return redirect('url_operation', id_camp=campaign.id)
1243 1243
1244 1244 #locations = Location.objects.filter(experiment__campaign__pk = campaign.id).distinct()
1245 1245 experiments = Experiment.objects.filter(campaign__pk=campaign.id)
1246 1246 #for exs in experiments:
1247 1247 # exs.get_status()
1248 1248 locations= Location.objects.filter(experiment=experiments).distinct()
1249 1249 form = OperationSearchForm(initial={'campaign': campaign.id})
1250 1250
1251 1251 kwargs = {}
1252 1252 #---Campaign
1253 1253 kwargs['campaign'] = campaign
1254 1254 kwargs['campaign_keys'] = ['name', 'start_date', 'end_date', 'tags', 'description']
1255 1255 #---Experiment
1256 1256 keys = ['id', 'name', 'start_time', 'end_time', 'status']
1257 1257 kwargs['experiment_keys'] = keys[1:]
1258 1258 kwargs['experiments'] = experiments
1259 1259 #---Radar
1260 1260 kwargs['locations'] = locations
1261 1261 #---Else
1262 1262 kwargs['title'] = 'Campaign'
1263 1263 kwargs['suptitle'] = campaign.name
1264 1264 kwargs['form'] = form
1265 1265 kwargs['button'] = 'Select'
1266 1266 kwargs['details'] = True
1267 1267 kwargs['search_button'] = False
1268 1268
1269 1269 return render(request, 'operation.html', kwargs)
1270 1270
1271 1271
1272 1272 def radar_play(request, id_camp, id_radar):
1273 1273 campaign = get_object_or_404(Campaign, pk = id_camp)
1274 1274 radar = get_object_or_404(Location, pk = id_radar)
1275 1275 today = datetime.today()
1276 1276 now = today.time()
1277 1277
1278 1278 #--Clear Old Experiments From RunningExperiment Object
1279 1279 running_experiment = RunningExperiment.objects.filter(radar=radar)
1280 1280 if running_experiment:
1281 1281 running_experiment = running_experiment[0]
1282 1282 running_experiment.running_experiment.clear()
1283 1283 running_experiment.save()
1284 1284
1285 1285 #--If campaign datetime is ok:
1286 1286 if today >= campaign.start_date and today <= campaign.end_date:
1287 1287 experiments = Experiment.objects.filter(campaign=campaign).filter(location=radar)
1288 1288 for exp in experiments:
1289 1289 #--If experiment time is ok:
1290 1290 if now >= exp.start_time and now <= exp.end_time:
1291 1291 configurations = Configuration.objects.filter(experiment = exp)
1292 1292 for conf in configurations:
1293 1293 if 'cgs' in conf.device.device_type.name:
1294 1294 conf.status_device()
1295 1295 else:
1296 1296 answer = conf.start_device()
1297 1297 conf.status_device()
1298 1298 #--Running Experiment
1299 1299 old_running_experiment = RunningExperiment.objects.filter(radar=radar)
1300 1300 #--If RunningExperiment element exists
1301 1301 if old_running_experiment:
1302 1302 old_running_experiment = old_running_experiment[0]
1303 1303 old_running_experiment.running_experiment.add(exp)
1304 1304 old_running_experiment.status = 3
1305 1305 old_running_experiment.save()
1306 1306 #--Create a new Running_Experiment Object
1307 1307 else:
1308 1308 new_running_experiment = RunningExperiment(
1309 1309 radar = radar,
1310 1310 status = 3,
1311 1311 )
1312 1312 new_running_experiment.save()
1313 1313 new_running_experiment.running_experiment.add(exp)
1314 1314 new_running_experiment.save()
1315 1315
1316 1316 if answer:
1317 1317 messages.success(request, conf.message)
1318 1318 exp.status=2
1319 1319 exp.save()
1320 1320 else:
1321 1321 messages.error(request, conf.message)
1322 1322 else:
1323 1323 if exp.status == 1 or exp.status == 3:
1324 1324 exp.status=3
1325 1325 exp.save()
1326 1326
1327 1327
1328 1328 route = request.META['HTTP_REFERER']
1329 1329 route = str(route)
1330 1330 if 'search' in route:
1331 1331 return HttpResponseRedirect(reverse('url_operation_search', args=[id_camp]))
1332 1332 else:
1333 1333 return HttpResponseRedirect(reverse('url_operation', args=[id_camp]))
1334 1334
1335 1335
1336 1336 def radar_stop(request, id_camp, id_radar):
1337 1337 campaign = get_object_or_404(Campaign, pk = id_camp)
1338 1338 radar = get_object_or_404(Location, pk = id_radar)
1339 1339 experiments = Experiment.objects.filter(campaign=campaign).filter(location=radar)
1340 1340
1341 1341 for exp in experiments:
1342 1342 configurations = Configuration.objects.filter(experiment = exp)
1343 1343 for conf in configurations:
1344 1344 if 'cgs' in conf.device.device_type.name:
1345 1345 conf.status_device()
1346 1346 else:
1347 1347 answer = conf.stop_device()
1348 1348 conf.status_device()
1349 1349
1350 1350 if answer:
1351 1351 messages.success(request, conf.message)
1352 1352 exp.status=1
1353 1353 exp.save()
1354 1354 else:
1355 1355 messages.error(request, conf.message)
1356 1356
1357 1357
1358 1358 route = request.META['HTTP_REFERER']
1359 1359 route = str(route)
1360 1360 if 'search' in route:
1361 1361 return HttpResponseRedirect(reverse('url_operation_search', args=[id_camp]))
1362 1362 else:
1363 1363 return HttpResponseRedirect(reverse('url_operation', args=[id_camp]))
1364 1364
1365 1365
1366 1366 def radar_refresh(request, id_camp, id_radar):
1367 1367
1368 1368 campaign = get_object_or_404(Campaign, pk = id_camp)
1369 1369 radar = get_object_or_404(Location, pk = id_radar)
1370 1370 experiments = Experiment.objects.filter(campaign=campaign).filter(location=radar)
1371 1371 for exs in experiments:
1372 1372 exs.get_status()
1373 1373
1374 1374 route = request.META['HTTP_REFERER']
1375 1375 route = str(route)
1376 1376 if 'search' in route:
1377 1377 return HttpResponseRedirect(reverse('url_operation_search', args=[id_camp]))
1378 1378 else:
1379 1379 return HttpResponseRedirect(reverse('url_operation', args=[id_camp]))
1380 1380
@@ -1,774 +1,774
1 1
2 2 import ast
3 3 import json
4 4 import numpy as np
5 5
6 6 from polymorphic import PolymorphicModel
7 7
8 8 from django.db import models
9 9 from django.core.urlresolvers import reverse
10 10 from django.core.validators import MinValueValidator, MaxValueValidator
11 11
12 12 from apps.main.models import Configuration
13 13 from devices.rc import api
14 14 from .utils import RCFile
15 15
16 16 # Create your models here.
17 17
18 18 LINE_TYPES = (
19 19 ('none', 'Not used'),
20 20 ('tr', 'Transmission/reception selector signal'),
21 21 ('tx', 'A modulating signal (Transmission pulse)'),
22 22 ('codes', 'BPSK modulating signal'),
23 23 ('windows', 'Sample window signal'),
24 24 ('sync', 'Synchronizing signal'),
25 25 ('flip', 'IPP related periodic signal'),
26 26 ('prog_pulses', 'Programmable pulse'),
27 27 ('mix', 'Mixed line'),
28 28 )
29 29
30 30
31 31 SAMPLING_REFS = (
32 32 ('none', 'No Reference'),
33 33 ('first_baud', 'Middle of the first baud'),
34 34 ('sub_baud', 'Middle of the sub-baud')
35 35 )
36 36
37 37 DAT_CMDS = {
38 38 # Pulse Design commands
39 39 'DISABLE' : 0, # Disables pulse generation
40 40 'ENABLE' : 24, # Enables pulse generation
41 41 'DELAY_START' : 40, # Write delay status to memory
42 42 'FLIP_START' : 48, # Write flip status to memory
43 43 'SAMPLING_PERIOD' : 64, # Establish Sampling Period
44 44 'TX_ONE' : 72, # Output '0' in line TX
45 45 'TX_ZERO' : 88, # Output '0' in line TX
46 46 'SW_ONE' : 104, # Output '0' in line SW
47 47 'SW_ZERO' : 112, # Output '1' in line SW
48 48 'RESTART': 120, # Restarts CR8 Firmware
49 49 'CONTINUE' : 253, # Function Unknown
50 50 # Commands available to new controllers
51 51 # 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.
52 52 'CLOCK_DIVISOR_INIT' : 12, # Specifies Clock Divisor. Legacy command, ignored in the actual .dat conversion
53 53 'CLOCK_DIVISOR_LAST' : 22, # Specifies Clock Divisor (default 60 if not included) syntax: 255,22 254,N-1.
54 54 'CLOCK_DIVIDER' : 8,
55 55 }
56 56
57 57
58 58 class RCConfiguration(Configuration):
59 59
60 60 ipp = models.FloatField(verbose_name='Inter pulse period [Km]', validators=[MinValueValidator(1), MaxValueValidator(9000)], default=300)
61 61 ntx = models.PositiveIntegerField(verbose_name='Number of TX', validators=[MinValueValidator(1), MaxValueValidator(300)], default=1)
62 62 clock_in = models.FloatField(verbose_name='Clock in [MHz]', validators=[MinValueValidator(1), MaxValueValidator(80)], default=1)
63 63 clock_divider = models.PositiveIntegerField(verbose_name='Clock divider', validators=[MinValueValidator(1), MaxValueValidator(256)], default=1)
64 64 clock = models.FloatField(verbose_name='Clock Master [MHz]', blank=True, default=1)
65 65 time_before = models.PositiveIntegerField(verbose_name='Time before [&mu;S]', default=12)
66 66 time_after = models.PositiveIntegerField(verbose_name='Time after [&mu;S]', default=1)
67 67 sync = models.PositiveIntegerField(verbose_name='Synchro delay', default=0)
68 68 sampling_reference = models.CharField(verbose_name='Sampling Reference', choices=SAMPLING_REFS, default='none', max_length=40)
69 69 control_tx = models.BooleanField(verbose_name='Control Switch TX', default=False)
70 70 control_sw = models.BooleanField(verbose_name='Control Switch SW', default=False)
71 71 total_units = models.PositiveIntegerField(default=0)
72 72 mix = models.BooleanField(default=False)
73 73
74 74 class Meta:
75 75 db_table = 'rc_configurations'
76 76
77 77
78 78 def __unicode__(self):
79 79
80 80 if self.mix:
81 return u'[MIXED]: %s' % self.name
81 return u'[RC MIXED]: {}'.format(self.name)
82 82 else:
83 return u'[%s]: %s' % (self.device.name, self.name)
83 return u'[RC]: {}'.format(self.name)
84 84
85 85 def get_absolute_url_plot(self):
86 86 return reverse('url_plot_rc_pulses', args=[str(self.id)])
87 87
88 88 def get_absolute_url_import(self):
89 89 return reverse('url_import_rc_conf', args=[str(self.id)])
90 90
91 91 @property
92 92 def ipp_unit(self):
93 93
94 94 return '{} ({})'.format(self.ipp, int(self.ipp*self.km2unit))
95 95
96 96 @property
97 97 def us2unit(self):
98 98
99 99 return self.clock_in/self.clock_divider
100 100
101 101 @property
102 102 def km2unit(self):
103 103
104 104 return 20./3*(self.clock_in/self.clock_divider)
105 105
106 106 def clone(self, **kwargs):
107 107
108 108 lines = self.get_lines()
109 109 self.pk = None
110 110 self.id = None
111 111 for attr, value in kwargs.items():
112 112 setattr(self, attr, value)
113 113 self.save()
114 114
115 115 for line in lines:
116 116 line.clone(rc_configuration=self)
117 117
118 118 return self
119 119
120 120 def get_lines(self, **kwargs):
121 121 '''
122 122 Retrieve configuration lines
123 123 '''
124 124
125 125 return RCLine.objects.filter(rc_configuration=self.pk, **kwargs)
126 126
127 127
128 128 def clean_lines(self):
129 129 '''
130 130 '''
131 131
132 132 empty_line = RCLineType.objects.get(name='none')
133 133
134 134 for line in self.get_lines():
135 135 line.line_type = empty_line
136 136 line.params = '{}'
137 137 line.save()
138 138
139 139 def parms_to_dict(self):
140 140 '''
141 141 '''
142 142
143 143 ignored = ('parameters', 'type', 'polymorphic_ctype', 'configuration_ptr',
144 144 'created_date', 'programmed_date')
145 145
146 146 data = {}
147 147 for field in self._meta.fields:
148 148 if field.name in ignored:
149 149 continue
150 150 data[field.name] = '{}'.format(field.value_from_object(self))
151 151
152 152 data['lines'] = []
153 153
154 154 for line in self.get_lines():
155 155 line_data = json.loads(line.params)
156 156 if 'TX_ref' in line_data and line_data['TX_ref'] not in (0, '0'):
157 157 line_data['TX_ref'] = RCLine.objects.get(pk=line_data['TX_ref']).get_name()
158 158 if 'code' in line_data:
159 159 line_data['code'] = RCLineCode.objects.get(pk=line_data['code']).name
160 160 line_data['type'] = line.line_type.name
161 161 data['lines'].append(line_data)
162 162
163 163 data['delays'] = self.get_delays()
164 164 data['pulses'] = self.get_pulses()
165 165
166 166 return data
167 167
168 168 def dict_to_parms(self, data):
169 169 '''
170 170 '''
171 171
172 172 self.name = data['name']
173 173 self.ipp = data['ipp']
174 174 self.ntx = data['ntx']
175 175 self.clock_in = data['clock_in']
176 176 self.clock_divider = data['clock_divider']
177 177 self.clock = data['clock']
178 178 self.time_before = data['time_before']
179 179 self.time_after = data['time_after']
180 180 self.sync = data['sync']
181 181 self.sampling_reference = data['sampling_reference']
182 182 self.total_units = self.ipp*self.ntx*self.km2unit
183 183 self.save()
184 184 self.clean_lines()
185 185
186 186 lines = []
187 187 positions = {'tx':0, 'tr':0}
188 188
189 189 for i, line_data in enumerate(data['lines']):
190 190 line_type = RCLineType.objects.get(name=line_data.pop('type'))
191 191 if line_type.name=='codes':
192 192 code = RCLineCode.objects.get(name=line_data['code'])
193 193 line_data['code'] = code.pk
194 194 line = RCLine.objects.filter(rc_configuration=self, channel=i)
195 195 if line:
196 196 line = line[0]
197 197 line.line_type = line_type
198 198 line.params = json.dumps(line_data)
199 199 else:
200 200 line = RCLine(rc_configuration=self, line_type=line_type,
201 201 params=json.dumps(line_data),
202 202 channel=i)
203 203
204 204 if line_type.name=='tx':
205 205 line.position = positions['tx']
206 206 positions['tx'] += 1
207 207
208 208 if line_type.name=='tr':
209 209 line.position = positions['tr']
210 210 positions['tr'] += 1
211 211
212 212 line.save()
213 213 lines.append(line)
214 214
215 215 for line, line_data in zip(lines, data['lines']):
216 216 if 'TX_ref' in line_data:
217 217 params = json.loads(line.params)
218 218 if line_data['TX_ref'] in (0, '0'):
219 219 params['TX_ref'] = '0'
220 220 else:
221 221 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]
222 222 line.params = json.dumps(params)
223 223 line.save()
224 224
225 225
226 226 def get_delays(self):
227 227
228 228 pulses = [line.pulses_as_points() for line in self.get_lines()]
229 229 points = [tup for tups in pulses for tup in tups]
230 230 points = set([x for tup in points for x in tup])
231 231 points = list(points)
232 232 points.sort()
233 233
234 234 if points[0]<>0:
235 235 points.insert(0, 0)
236 236
237 237 return [points[i+1]-points[i] for i in range(len(points)-1)]
238 238
239 239
240 240 def get_pulses(self, binary=True):
241 241
242 242 pulses = [line.pulses_as_points() for line in self.get_lines()]
243 243 points = [tup for tups in pulses for tup in tups]
244 244 points = set([x for tup in points for x in tup])
245 245 points = list(points)
246 246 points.sort()
247 247
248 248 line_points = [line.pulses_as_points() for line in self.get_lines()]
249 249 line_points = [[(x, x+y) for x,y in tups] for tups in line_points]
250 250 line_points = [[t for x in tups for t in x] for tups in line_points]
251 251 states = [[1 if x in tups else 0 for tups in line_points] for x in points]
252 252
253 253 if binary:
254 254 states.reverse()
255 255 states = [int(''.join([str(x) for x in flips]), 2) for flips in states]
256 256
257 257 return states[:-1]
258 258
259 259 def add_cmd(self, cmd):
260 260
261 261 if cmd in DAT_CMDS:
262 262 return (255, DAT_CMDS[cmd])
263 263
264 264 def add_data(self, value):
265 265
266 266 return (254, value-1)
267 267
268 268 def parms_to_binary(self):
269 269 '''
270 270 Create "dat" stream to be send to CR
271 271 '''
272 272
273 273 data = []
274 274 # create header
275 275 data.append(self.add_cmd('DISABLE'))
276 276 data.append(self.add_cmd('CONTINUE'))
277 277 data.append(self.add_cmd('RESTART'))
278 278
279 279 if self.control_sw:
280 280 data.append(self.add_cmd('SW_ONE'))
281 281 else:
282 282 data.append(self.add_cmd('SW_ZERO'))
283 283
284 284 if self.control_tx:
285 285 data.append(self.add_cmd('TX_ONE'))
286 286 else:
287 287 data.append(self.add_cmd('TX_ZERO'))
288 288
289 289 # write divider
290 290 data.append(self.add_cmd('CLOCK_DIVIDER'))
291 291 data.append(self.add_data(self.clock_divider))
292 292
293 293 # write delays
294 294 data.append(self.add_cmd('DELAY_START'))
295 295 # first delay is always zero
296 296 data.append(self.add_data(1))
297 297
298 298 delays = self.get_delays()
299 299
300 300 for delay in delays:
301 301 while delay>252:
302 302 data.append(self.add_data(253))
303 303 delay -= 253
304 304 data.append(self.add_data(delay))
305 305
306 306 # write flips
307 307 data.append(self.add_cmd('FLIP_START'))
308 308
309 309 states = self.get_pulses(binary=False)
310 310
311 311 for flips, delay in zip(states, delays):
312 312 flips.reverse()
313 313 flip = int(''.join([str(x) for x in flips]), 2)
314 314 data.append(self.add_data(flip+1))
315 315 while delay>252:
316 316 data.append(self.add_data(1))
317 317 delay -= 253
318 318
319 319 # write sampling period
320 320 data.append(self.add_cmd('SAMPLING_PERIOD'))
321 321 wins = self.get_lines(line_type__name='windows')
322 322 if wins:
323 323 win_params = json.loads(wins[0].params)['params']
324 324 if win_params:
325 325 dh = int(win_params[0]['resolution']*self.km2unit)
326 326 else:
327 327 dh = 1
328 328 else:
329 329 dh = 1
330 330 data.append(self.add_data(dh))
331 331
332 332 # write enable
333 333 data.append(self.add_cmd('ENABLE'))
334 334
335 335 return '\n'.join(['{}'.format(x) for tup in data for x in tup])
336 336
337 337 def update_from_file(self, filename):
338 338 '''
339 339 Update instance from file
340 340 '''
341 341
342 342 f = RCFile(filename)
343 343 self.dict_to_parms(f.data)
344 344 self.update_pulses()
345 345
346 346 def update_pulses(self):
347 347
348 348 for line in self.get_lines():
349 349 line.update_pulses()
350 350
351 351 def plot_pulses(self):
352 352
353 353 import matplotlib.pyplot as plt
354 354 from bokeh.resources import CDN
355 355 from bokeh.embed import components
356 356 from bokeh.mpl import to_bokeh
357 357 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, PreviewSaveTool
358 358
359 359 lines = self.get_lines()
360 360
361 361 N = len(lines)
362 362 fig = plt.figure(figsize=(10, 2+N*0.5))
363 363 ax = fig.add_subplot(111)
364 364 labels = []
365 365
366 366 for i, line in enumerate(lines):
367 367 labels.append(line.get_name())
368 368 l = ax.plot((0, self.total_units),(N-i-1, N-i-1))
369 369 points = [(tup[0], tup[1]-tup[0]) for tup in line.pulses_as_points() if tup<>(0,0)]
370 370 ax.broken_barh(points, (N-i-1, 0.5),
371 371 edgecolor=l[0].get_color(), facecolor='none')
372 372
373 373 labels.reverse()
374 374 ax.set_yticklabels(labels)
375 375 ax.set_xlabel = 'Units'
376 376 plot = to_bokeh(fig, use_pandas=False)
377 377 plot.tools = [PanTool(dimensions=['width']), WheelZoomTool(dimensions=['width']), ResetTool(), PreviewSaveTool()]
378 378
379 379 return components(plot, CDN)
380 380
381 381 def status_device(self):
382 382
383 383 return 0
384 384
385 385 def stop_device(self):
386 386
387 387 answer = api.disable(ip = self.device.ip_address,
388 388 port = self.device.port_address)
389 389
390 390 if answer[0] != "1":
391 391 self.message = answer[0:]
392 392 return 0
393 393
394 394 self.message = answer[2:]
395 395 return 1
396 396
397 397 def start_device(self):
398 398
399 399 answer = api.enable(ip = self.device.ip_address,
400 400 port = self.device.port_address)
401 401
402 402 if answer[0] != "1":
403 403 self.message = answer[0:]
404 404 return 0
405 405
406 406 self.message = answer[2:]
407 407 return 1
408 408
409 409 def write_device(self):
410 410 answer = api.write_config(ip = self.device.ip_address,
411 411 port = self.device.port_address,
412 412 parms = self.parms_to_dict())
413 413
414 414 if answer[0] != "1":
415 415 self.message = answer[0:]
416 416 return 0
417 417
418 418 self.message = answer[2:]
419 419 return 1
420 420
421 421
422 422 class RCLineCode(models.Model):
423 423
424 424 name = models.CharField(max_length=40)
425 425 bits_per_code = models.PositiveIntegerField(default=0)
426 426 number_of_codes = models.PositiveIntegerField(default=0)
427 427 codes = models.TextField(blank=True, null=True)
428 428
429 429 class Meta:
430 430 db_table = 'rc_line_codes'
431 431 ordering = ('name',)
432 432
433 433 def __unicode__(self):
434 434 return u'%s' % self.name
435 435
436 436
437 437 class RCLineType(models.Model):
438 438
439 439 name = models.CharField(choices=LINE_TYPES, max_length=40)
440 440 description = models.TextField(blank=True, null=True)
441 441 params = models.TextField(default='[]')
442 442
443 443 class Meta:
444 444 db_table = 'rc_line_types'
445 445
446 446 def __unicode__(self):
447 447 return u'%s - %s' % (self.name.upper(), self.get_name_display())
448 448
449 449
450 450 class RCLine(models.Model):
451 451
452 452 rc_configuration = models.ForeignKey(RCConfiguration, on_delete=models.CASCADE)
453 453 line_type = models.ForeignKey(RCLineType)
454 454 channel = models.PositiveIntegerField(default=0)
455 455 position = models.PositiveIntegerField(default=0)
456 456 params = models.TextField(default='{}')
457 457 pulses = models.TextField(default='')
458 458
459 459 class Meta:
460 460 db_table = 'rc_lines'
461 461 ordering = ['channel']
462 462
463 463 def __unicode__(self):
464 464 if self.rc_configuration:
465 465 return u'%s - %s' % (self.rc_configuration, self.get_name())
466 466
467 467 def clone(self, **kwargs):
468 468
469 469 self.pk = None
470 470
471 471 for attr, value in kwargs.items():
472 472 setattr(self, attr, value)
473 473
474 474 self.save()
475 475
476 476 return self
477 477
478 478 def get_name(self):
479 479
480 480 chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
481 481 s = ''
482 482
483 483 if self.line_type.name in ('tx',):
484 484 s = chars[self.position]
485 485 elif self.line_type.name in ('codes', 'windows', 'tr'):
486 486 if 'TX_ref' in json.loads(self.params):
487 487 pk = json.loads(self.params)['TX_ref']
488 488 if pk in (0, '0'):
489 489 s = ','.join(chars[l.position] for l in self.rc_configuration.get_lines(line_type__name='tx'))
490 490 else:
491 491 ref = RCLine.objects.get(pk=pk)
492 492 s = chars[ref.position]
493 493 s = '({})'.format(s)
494 494 if s:
495 495 return '{}{} {}'.format(self.line_type.name.upper(), s, self.channel)
496 496 else:
497 497 return '{} {}'.format(self.line_type.name.upper(), self.channel)
498 498
499 499 def get_lines(self, **kwargs):
500 500
501 501 return RCLine.objects.filter(rc_configuration=self.rc_configuration, **kwargs)
502 502
503 503 def pulses_as_array(self):
504 504
505 505 y = np.zeros(self.rc_configuration.total_units)
506 506
507 507 for tup in ast.literal_eval(self.pulses):
508 508 y[tup[0]:tup[1]] = 1
509 509
510 510 return y.astype(np.int8)
511 511
512 512 def pulses_as_points(self):
513 513
514 514 return ast.literal_eval(self.pulses)
515 515
516 516 def get_win_ref(self, params, tx_id, km2unit):
517 517
518 518 ref = self.rc_configuration.sampling_reference
519 519 codes = [line for line in self.get_lines(line_type__name='codes') if int(json.loads(line.params)['TX_ref'])==int(tx_id)]
520 520
521 521 if codes:
522 522 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit/len(json.loads(codes[0].params)['codes'][0])
523 523 else:
524 524 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit
525 525
526 526 if ref=='first_baud':
527 527 return int(1 + (tx_width + 1)/2 + params['first_height']*km2unit - params['resolution']*km2unit)
528 528 elif ref=='sub_baud':
529 529 return int(1 + params['first_height']*km2unit - params['resolution']*km2unit/2)
530 530 else:
531 531 return 0
532 532
533 533 def update_pulses(self):
534 534 '''
535 535 Update pulses field
536 536 '''
537 537
538 538 km2unit = self.rc_configuration.km2unit
539 539 us2unit = self.rc_configuration.us2unit
540 540 ipp = self.rc_configuration.ipp
541 541 ntx = self.rc_configuration.ntx
542 542 ipp_u = int(ipp*km2unit)
543 543 total = ipp_u*ntx if self.rc_configuration.total_units==0 else self.rc_configuration.total_units
544 544 y = []
545 545
546 546 if self.line_type.name=='tr':
547 547 tr_params = json.loads(self.params)
548 548
549 549 if tr_params['TX_ref'] in ('0', 0):
550 550 txs = self.get_lines(line_type__name='tx')
551 551 else:
552 552 txs = RCLine.objects.filter(pk=tr_params['TX_ref'])
553 553
554 554 for tx in txs:
555 555 params = json.loads(tx.params)
556 556
557 557 if float(params['pulse_width'])==0:
558 558 continue
559 559 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
560 560 width = float(params['pulse_width'])*km2unit+int(self.rc_configuration.time_before*us2unit)
561 561 before = 0
562 562 after = int(self.rc_configuration.time_after*us2unit)
563 563
564 564 y_tx = self.points(ntx, ipp_u, width,
565 565 delay=delays,
566 566 before=before,
567 567 after=after,
568 568 sync=self.rc_configuration.sync)
569 569
570 570 ranges = params['range'].split(',')
571 571
572 572 if len(ranges)>0 and ranges[0]<>'0':
573 573 y_tx = self.mask_ranges(y_tx, ranges)
574 574
575 575 tr_ranges = tr_params['range'].split(',')
576 576
577 577 if len(tr_ranges)>0 and tr_ranges[0]<>'0':
578 578 y_tx = self.mask_ranges(y_tx, tr_ranges)
579 579
580 580 y.extend(y_tx)
581 581
582 582 self.pulses = unicode(y)
583 583 y = self.array_to_points(self.pulses_as_array())
584 584
585 585 elif self.line_type.name=='tx':
586 586 params = json.loads(self.params)
587 587 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
588 588 width = float(params['pulse_width'])*km2unit
589 589
590 590 if width>0:
591 591 before = int(self.rc_configuration.time_before*us2unit)
592 592 after = 0
593 593
594 594 y = self.points(ntx, ipp_u, width,
595 595 delay=delays,
596 596 before=before,
597 597 after=after,
598 598 sync=self.rc_configuration.sync)
599 599
600 600 ranges = params['range'].split(',')
601 601
602 602 if len(ranges)>0 and ranges[0]<>'0':
603 603 y = self.mask_ranges(y, ranges)
604 604
605 605 elif self.line_type.name=='flip':
606 606 n = float(json.loads(self.params)['number_of_flips'])
607 607 width = n*ipp*km2unit
608 608 y = self.points(int((ntx+1)/(2*n)), ipp_u*n*2, width)
609 609
610 610 elif self.line_type.name=='codes':
611 611 params = json.loads(self.params)
612 612 tx = RCLine.objects.get(pk=params['TX_ref'])
613 613 tx_params = json.loads(tx.params)
614 614 delays = [float(d)*km2unit for d in tx_params['delays'].split(',') if d]
615 615 f = int(float(tx_params['pulse_width'])*km2unit)/len(params['codes'][0])
616 616 codes = [(np.fromstring(''.join([s*f for s in code]), dtype=np.uint8)-48).astype(np.int8) for code in params['codes']]
617 617 codes = [self.array_to_points(code) for code in codes]
618 618 n = len(codes)
619 619
620 620 for i, tup in enumerate(tx.pulses_as_points()):
621 621 code = codes[i%n]
622 622 y.extend([(c[0]+tup[0], c[1]+tup[0]) for c in code])
623 623
624 624 ranges = tx_params['range'].split(',')
625 625 if len(ranges)>0 and ranges[0]<>'0':
626 626 y = self.mask_ranges(y, ranges)
627 627
628 628 elif self.line_type.name=='sync':
629 629 params = json.loads(self.params)
630 630 n = ipp_u*ntx
631 631 if params['invert'] in ('1', 1):
632 632 y = [(n-1, n)]
633 633 else:
634 634 y = [(0, 1)]
635 635
636 636 elif self.line_type.name=='prog_pulses':
637 637 params = json.loads(self.params)
638 638 if int(params['periodic'])==0:
639 639 nntx = 1
640 640 nipp = ipp_u*ntx
641 641 else:
642 642 nntx = ntx
643 643 nipp = ipp_u
644 644
645 645 if 'params' in params and len(params['params'])>0:
646 646 for p in params['params']:
647 647 y_pp = self.points(nntx, nipp,
648 648 p['end']-p['begin'],
649 649 before=p['begin'])
650 650
651 651 y.extend(y_pp)
652 652
653 653 elif self.line_type.name=='windows':
654 654 params = json.loads(self.params)
655 655
656 656 if 'params' in params and len(params['params'])>0:
657 657 tr_params = json.loads(self.get_lines(line_type__name='tr')[0].params)
658 658 tr_ranges = tr_params['range'].split(',')
659 659 for p in params['params']:
660 660 y_win = self.points(ntx, ipp_u,
661 661 p['resolution']*p['number_of_samples']*km2unit,
662 662 before=int(self.rc_configuration.time_before*us2unit)+self.get_win_ref(p, params['TX_ref'], km2unit),
663 663 sync=self.rc_configuration.sync)
664 664
665 665 if len(tr_ranges)>0 and tr_ranges[0]<>'0':
666 666 y_win = self.mask_ranges(y_win, tr_ranges)
667 667
668 668 y.extend(y_win)
669 669
670 670 elif self.line_type.name=='mix':
671 671 values = self.rc_configuration.parameters.split('-')
672 672 confs = [RCConfiguration.objects.get(pk=value.split('|')[0]) for value in values]
673 673 modes = [value.split('|')[1] for value in values]
674 674 ops = [value.split('|')[2] for value in values]
675 675 delays = [value.split('|')[3] for value in values]
676 676 masks = [value.split('|')[4] for value in values]
677 677 mask = list('{:8b}'.format(int(masks[0])))
678 678 mask.reverse()
679 679 if mask[self.channel] in ('0', '', ' '):
680 680 y = np.zeros(confs[0].total_units, dtype=np.int8)
681 681 else:
682 682 y = confs[0].get_lines(channel=self.channel)[0].pulses_as_array()
683 683
684 684 for i in range(1, len(values)):
685 685 mask = list('{:8b}'.format(int(masks[i])))
686 686 mask.reverse()
687 687
688 688 if mask[self.channel] in ('0', '', ' '):
689 689 continue
690 690 Y = confs[i].get_lines(channel=self.channel)[0].pulses_as_array()
691 691 delay = float(delays[i])*km2unit
692 692
693 693 if modes[i]=='P':
694 694 if delay>0:
695 695 if delay<self.rc_configuration.ipp*km2unit and len(Y)==len(y):
696 696 y_temp = np.empty_like(Y)
697 697 y_temp[:delay] = 0
698 698 y_temp[delay:] = Y[:-delay]
699 699 elif delay+len(Y)>len(y):
700 700 y_new = np.zeros(delay+len(Y), dtype=np.int8)
701 701 y_new[:len(y)] = y
702 702 y = y_new
703 703 y_temp = np.zeros(delay+len(Y), dtype=np.int8)
704 704 y_temp[-len(Y):] = Y
705 705 elif delay+len(Y)==len(y):
706 706 y_temp = np.zeros(delay+len(Y))
707 707 y_temp[-len(Y):] = Y
708 708 elif delay+len(Y)<len(y):
709 709 y_temp = np.zeros(len(y), dtype=np.int8)
710 710 y_temp[delay:delay+len(Y)] = Y
711 711
712 712 if ops[i]=='OR':
713 713 y = y | y_temp
714 714 elif ops[i]=='XOR':
715 715 y = y ^ y_temp
716 716 elif ops[i]=='AND':
717 717 y = y & y_temp
718 718 elif ops[i]=='NAND':
719 719 y = y & ~y_temp
720 720 else:
721 721 y = np.concatenate([y, Y])
722 722
723 723 total = len(y)
724 724 y = self.array_to_points(y)
725 725
726 726 else:
727 727 y = []
728 728
729 729 if self.rc_configuration.total_units <> total:
730 730 self.rc_configuration.total_units = total
731 731 self.rc_configuration.save()
732 732
733 733 self.pulses = unicode(y)
734 734 self.save()
735 735
736 736 @staticmethod
737 737 def array_to_points(X):
738 738
739 739 d = X[1:]-X[:-1]
740 740
741 741 up = np.where(d==1)[0]
742 742 if X[0]==1:
743 743 up = np.concatenate((np.array([-1]), up))
744 744 up += 1
745 745
746 746 dw = np.where(d==-1)[0]
747 747 if X[-1]==1:
748 748 dw = np.concatenate((dw, np.array([len(X)-1])))
749 749 dw += 1
750 750
751 751 return [(tup[0], tup[1]) for tup in zip(up, dw)]
752 752
753 753 @staticmethod
754 754 def mask_ranges(Y, ranges):
755 755
756 756 y = [(0, 0) for __ in Y]
757 757
758 758 for index in ranges:
759 759 if '-' in index:
760 760 args = [int(a) for a in index.split('-')]
761 761 y[args[0]-1:args[1]] = Y[args[0]-1:args[1]]
762 762 else:
763 763 y[int(index-1)] = Y[int(index-1)]
764 764
765 765 return y
766 766
767 767 @staticmethod
768 768 def points(ntx, ipp, width, delay=[0], before=0, after=0, sync=0):
769 769
770 770 delays = len(delay)
771 771
772 772 Y = [(ipp*x+before+delay[x%delays], ipp*x+width+before+delay[x%delays]+after) for x in range(ntx)]
773 773
774 774 return Y No newline at end of file
@@ -1,373 +1,372
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 Configuration, 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_view'] = True
267 267 kwargs['title'] = 'Confirm delete'
268 268 kwargs['previous'] = conf.get_absolute_url_edit()
269 269 return render(request, 'confirm.html', kwargs)
270 270
271 271
272 272 def remove_subline(request, conf_id, line_id, subline_id):
273 273
274 274 conf = get_object_or_404(RCConfiguration, pk=conf_id)
275 275 line = get_object_or_404(RCLine, pk=line_id)
276 276
277 277 if request.method == 'POST':
278 278 if line:
279 279 params = json.loads(line.params)
280 280 params['params'].remove(params['params'][int(subline_id)-1])
281 281 line.params = json.dumps(params)
282 282 line.save()
283 283
284 284 return redirect('url_edit_rc_conf', conf.id)
285 285
286 286 kwargs = {}
287 287
288 288 kwargs['object'] = line
289 289 kwargs['object_name'] = line.line_type.name
290 290 kwargs['delete_view'] = True
291 291 kwargs['title'] = 'Confirm delete'
292 292
293 293 return render(request, 'confirm.html', kwargs)
294 294
295 295
296 296 def update_lines_position(request, conf_id):
297 297
298 298 conf = get_object_or_404(RCConfiguration, pk=conf_id)
299 299
300 300 if request.method=='POST':
301 301 ch = 0
302 302 for item in request.POST['items'].split('&'):
303 303 line = RCLine.objects.get(pk=item.split('=')[-1])
304 304 line.channel = ch
305 305 line.save()
306 306 ch += 1
307 307
308 308 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
309 309
310 310 for line in lines:
311 311 params = json.loads(line.params)
312 312 line.form = RCLineEditForm(conf=conf, line=line, extra_fields=params)
313 313
314 314 if 'params' in params:
315 315 line.subform = True
316 316 line.subforms = [RCLineEditForm(extra_fields=fields, line=line, subform=i) for i, fields in enumerate(params['params'])]
317 317
318 318 html = render(request, 'rc_lines.html', {'dev_conf':conf, 'rc_lines':lines, 'edit':True})
319 319 data = {'html': html.content}
320 320
321 321 return HttpResponse(json.dumps(data), content_type="application/json")
322 322 return redirect('url_edit_rc_conf', conf.id)
323 323
324 324
325 325 def import_file(request, conf_id):
326 326
327 327 conf = get_object_or_404(RCConfiguration, pk=conf_id)
328 328 if request.method=='POST':
329 329 form = RCImportForm(request.POST, request.FILES)
330 330 if form.is_valid():
331 if True:
332 #try:
331 try:
333 332 conf.update_from_file(request.FILES['file_name'])
334 333 messages.success(request, 'Configuration "%s" loaded succesfully' % request.FILES['file_name'])
335 334 return redirect(conf.get_absolute_url_edit())
336 335
337 #except Exception as e:
338 # messages.error(request, 'Error parsing file: "%s" - %s' % (request.FILES['file_name'], e))
336 except Exception as e:
337 messages.error(request, 'Error parsing file: "%s" - %s' % (request.FILES['file_name'], e))
339 338
340 339 else:
341 340 messages.warning(request, 'Your current configuration will be replaced')
342 341 form = RCImportForm()
343 342
344 343 kwargs = {}
345 344 kwargs['form'] = form
346 345 kwargs['title'] = 'RC Configuration'
347 346 kwargs['suptitle'] = 'Import file'
348 347 kwargs['button'] = 'Upload'
349 348 kwargs['previous'] = conf.get_absolute_url()
350 349
351 350 return render(request, 'rc_import.html', kwargs)
352 351
353 352
354 353 def plot_pulses(request, conf_id):
355 354
356 355 conf = get_object_or_404(RCConfiguration, pk=conf_id)
357 356
358 357 script, div = conf.plot_pulses()
359 358
360 359 kwargs = {}
361 360
362 361 kwargs['title'] = 'RC Pulses'
363 362 kwargs['suptitle'] = conf.name
364 363 kwargs['div'] = mark_safe(div)
365 364 kwargs['script'] = mark_safe(script)
366 365 kwargs['units'] = conf.km2unit
367 366 kwargs['kms'] = 1/conf.km2unit
368 367
369 368 if 'json' in request.GET:
370 369 return HttpResponse(json.dumps({'div':mark_safe(div), 'script':mark_safe(script)}), content_type="application/json")
371 370 else:
372 371 return render(request, 'rc_pulses.html', kwargs)
373 372
General Comments 0
You need to be logged in to leave comments. Login now