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