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