##// END OF EJS Templates
Optimize pulses's plot and generation ...
Juan C. Espinoza -
r111:e02ef9acb4e3
parent child
Show More
@@ -1,26 +1,27
1 [{"fields": {"number_of_codes": 0, "codes": "[]", "name": "None", "bits_per_code": 0}, "model": "rc.rclinecode", "pk": 1},
1 [{"fields": {"number_of_codes": 0, "codes": "[]", "name": "None", "bits_per_code": 0}, "model": "rc.rclinecode", "pk": 1},
2 {"fields": {"number_of_codes": 2, "codes": "[u'11101101', u'11100010']", "name": "COMPLEMENTARY_CODE_8", "bits_per_code": 8}, "model": "rc.rclinecode", "pk": 2},
2 {"fields": {"number_of_codes": 2, "codes": "[u'11101101', u'11100010']", "name": "COMPLEMENTARY_CODE_8", "bits_per_code": 8}, "model": "rc.rclinecode", "pk": 2},
3 {"fields": {"number_of_codes": 1, "codes": "[u'1101101001000100010001111000']", "name": "BINARY_CODE_28", "bits_per_code": 28}, "model": "rc.rclinecode", "pk": 3},
3 {"fields": {"number_of_codes": 1, "codes": "[u'1101101001000100010001111000']", "name": "BINARY_CODE_28", "bits_per_code": 28}, "model": "rc.rclinecode", "pk": 3},
4 {"fields": {"number_of_codes": 2, "codes": "[u'11', u'10']", "name": "COMPLEMENTARY_CODE_2", "bits_per_code": 2}, "model": "rc.rclinecode", "pk": 4},
4 {"fields": {"number_of_codes": 2, "codes": "[u'11', u'10']", "name": "COMPLEMENTARY_CODE_2", "bits_per_code": 2}, "model": "rc.rclinecode", "pk": 4},
5 {"fields": {"number_of_codes": 2, "codes": "[u'1110110111100010111011010001110111101101111000100001001011100010', u'1110110111100010111011010001110100010010000111011110110100011101']", "name": "COMPLEMENTARY_CODE_64", "bits_per_code": 64}, "model": "rc.rclinecode", "pk": 5},
5 {"fields": {"number_of_codes": 2, "codes": "[u'1110110111100010111011010001110111101101111000100001001011100010', u'1110110111100010111011010001110100010010000111011110110100011101']", "name": "COMPLEMENTARY_CODE_64", "bits_per_code": 64}, "model": "rc.rclinecode", "pk": 5},
6 {"fields": {"number_of_codes": 1, "codes": "[u'11100010010']", "name": "BARKER11", "bits_per_code": 11}, "model": "rc.rclinecode", "pk": 6},
6 {"fields": {"number_of_codes": 1, "codes": "[u'11100010010']", "name": "BARKER11", "bits_per_code": 11}, "model": "rc.rclinecode", "pk": 6},
7 {"fields": {"number_of_codes": 2, "codes": "[u'1111100110101' ]", "name": "BARKER13", "bits_per_code": 13}, "model": "rc.rclinecode", "pk": 7},
7 {"fields": {"number_of_codes": 2, "codes": "[u'1111100110101' ]", "name": "BARKER13", "bits_per_code": 13}, "model": "rc.rclinecode", "pk": 7},
8 {"fields": {"number_of_codes": 2, "codes": "[u'1101101001000100010001111000', u'0010010110111011101110000111']", "name": "BINARY_CODE_28_FLIP", "bits_per_code": 28}, "model": "rc.rclinecode", "pk": 8},
8 {"fields": {"number_of_codes": 2, "codes": "[u'1101101001000100010001111000', u'0010010110111011101110000111']", "name": "BINARY_CODE_28_FLIP", "bits_per_code": 28}, "model": "rc.rclinecode", "pk": 8},
9 {"fields": {"number_of_codes": 2, "codes": "[u'11101101111000101110110100011101', u'11101101111000100001001011100010']", "name": "COMPLEMENTARY_CODE_32", "bits_per_code": 32}, "model": "rc.rclinecode", "pk": 9},
9 {"fields": {"number_of_codes": 2, "codes": "[u'11101101111000101110110100011101', u'11101101111000100001001011100010']", "name": "COMPLEMENTARY_CODE_32", "bits_per_code": 32}, "model": "rc.rclinecode", "pk": 9},
10 {"fields": {"number_of_codes": 128, "codes": "[u'1111000100100101', u'1011001010010111', u'1101001000100000', u'1001000110010010', u'1110001001111011', u'1010000111001001', u'1100000101111110', u'1000001011001100', u'1111101001010110', u'1011100111100100', u'1101100101010011', u'1001101011100001', u'1110100100001000', u'1010101010111010', u'1100101000001101', u'1000100110111111', u'1111010010011100', u'1011011100101110', u'1101011110011001', u'1001010000101011', u'1110011111000010', u'1010010001110000', u'1100010011000111', u'1000011101110101', u'1111111111101111', u'1011110001011101', u'1101110011101010', u'1001111101011000', u'1110110010110001', u'1010111100000011', u'1100111110110100', u'1000110000000110', u'0011111000000011', u'0111110110110001', u'0001110100000110', u'0101111010110100', u'0010110101011101', u'0110111011101111', u'0000111001011000', u'0100110111101010', u'0011010101110000', u'0111011011000010', u'0001011001110101', u'0101010111000111', u'0010011000101110', u'0110010110011100', u'0000010100101011', u'0100011010011001', u'0011101110111010', u'0111100000001000', u'0001100010111111', u'0101101100001101', u'0010100011100100', u'0110101101010110', u'0000101111100001', u'0100100001010011', u'0011000011001001', u'0111001101111011', u'0001001111001100', u'0101000001111110', u'0010001110010111', u'0110000000100101', u'0000000010010010', u'0100001100100000', u'1010110011001110', u'1110111101111100', u'1000111111001011', u'1100110001111001', u'1011111110010000', u'1111110000100010', u'1001110010010101', u'1101111100100111', u'1010011110111101', u'1110010000001111', u'1000010010111000', u'1100011100001010', u'1011010011100011', u'1111011101010001', u'1001011111100110', u'1101010001010100', u'1010100101110111', u'1110101011000101', u'1000101001110010', u'1100100111000000', u'1011101000101001', u'1111100110011011', u'1001100100101100', u'1101101010011110', u'1010001000000100', u'1110000110110110', u'1000000100000001', u'1100001010110011', u'1011000101011010', u'1111001011101000', u'1001001001011111', u'1101000111101101', u'1100100111000110', u'1000101001110100', u'1110101011000011', u'1010100101110001', u'1101101010011000', u'1001100100101010', u'1111100110011101', u'1011101000101111', u'1100001010110101', u'1000000100000111', u'1110000110110000', u'1010001000000010', u'1101000111101011', u'1001001001011001', u'1111001011101110', u'1011000101011100', u'1100110001111111', u'1000111111001101', u'1110111101111010', u'1010110011001000', u'1101111100100001', u'1001110010010011', u'1111110000100100', u'1011111110010110', u'1100011100001100', u'1000010010111110', u'1110010000001001', u'1010011110111011', u'1101010001010010', u'1001011111100000', u'1111011101010111', u'1011010011100101']", "name": "AC128", "bits_per_code": 16}, "model": "rc.rclinecode", "pk": 10},
10 {"fields": {"number_of_codes": 128, "codes": "[u'1111000100100101', u'1011001010010111', u'1101001000100000', u'1001000110010010', u'1110001001111011', u'1010000111001001', u'1100000101111110', u'1000001011001100', u'1111101001010110', u'1011100111100100', u'1101100101010011', u'1001101011100001', u'1110100100001000', u'1010101010111010', u'1100101000001101', u'1000100110111111', u'1111010010011100', u'1011011100101110', u'1101011110011001', u'1001010000101011', u'1110011111000010', u'1010010001110000', u'1100010011000111', u'1000011101110101', u'1111111111101111', u'1011110001011101', u'1101110011101010', u'1001111101011000', u'1110110010110001', u'1010111100000011', u'1100111110110100', u'1000110000000110', u'0011111000000011', u'0111110110110001', u'0001110100000110', u'0101111010110100', u'0010110101011101', u'0110111011101111', u'0000111001011000', u'0100110111101010', u'0011010101110000', u'0111011011000010', u'0001011001110101', u'0101010111000111', u'0010011000101110', u'0110010110011100', u'0000010100101011', u'0100011010011001', u'0011101110111010', u'0111100000001000', u'0001100010111111', u'0101101100001101', u'0010100011100100', u'0110101101010110', u'0000101111100001', u'0100100001010011', u'0011000011001001', u'0111001101111011', u'0001001111001100', u'0101000001111110', u'0010001110010111', u'0110000000100101', u'0000000010010010', u'0100001100100000', u'1010110011001110', u'1110111101111100', u'1000111111001011', u'1100110001111001', u'1011111110010000', u'1111110000100010', u'1001110010010101', u'1101111100100111', u'1010011110111101', u'1110010000001111', u'1000010010111000', u'1100011100001010', u'1011010011100011', u'1111011101010001', u'1001011111100110', u'1101010001010100', u'1010100101110111', u'1110101011000101', u'1000101001110010', u'1100100111000000', u'1011101000101001', u'1111100110011011', u'1001100100101100', u'1101101010011110', u'1010001000000100', u'1110000110110110', u'1000000100000001', u'1100001010110011', u'1011000101011010', u'1111001011101000', u'1001001001011111', u'1101000111101101', u'1100100111000110', u'1000101001110100', u'1110101011000011', u'1010100101110001', u'1101101010011000', u'1001100100101010', u'1111100110011101', u'1011101000101111', u'1100001010110101', u'1000000100000111', u'1110000110110000', u'1010001000000010', u'1101000111101011', u'1001001001011001', u'1111001011101110', u'1011000101011100', u'1100110001111111', u'1000111111001101', u'1110111101111010', u'1010110011001000', u'1101111100100001', u'1001110010010011', u'1111110000100100', u'1011111110010110', u'1100011100001100', u'1000010010111110', u'1110010000001001', u'1010011110111011', u'1101010001010010', u'1001011111100000', u'1111011101010111', u'1011010011100101']", "name": "AC128", "bits_per_code": 16}, "model": "rc.rclinecode", "pk": 10},
11 {"fields": {"number_of_codes": 2, "codes": "[u'11101101111000101110110100011101111011011110001000010010111000101110110111100010111011010001110100010010000111011110110100011101', u'11101101111000101110110100011101111011011110001000010010111000100001001000011101000100101110001011101101111000100001001011100010']", "name": "COMPLEMENTARY_CODE_128", "bits_per_code": 128}, "model": "rc.rclinecode", "pk": 11},
11 {"fields": {"number_of_codes": 2, "codes": "[u'11101101111000101110110100011101111011011110001000010010111000101110110111100010111011010001110100010010000111011110110100011101', u'11101101111000101110110100011101111011011110001000010010111000100001001000011101000100101110001011101101111000100001001011100010']", "name": "COMPLEMENTARY_CODE_128", "bits_per_code": 128}, "model": "rc.rclinecode", "pk": 11},
12 {"fields": {"number_of_codes": 2, "codes": "[u'1110110111100010', u'1110110100011101']", "name": "COMPLEMENTARY_CODE_16", "bits_per_code": 16}, "model": "rc.rclinecode", "pk": 12},
12 {"fields": {"number_of_codes": 2, "codes": "[u'1110110111100010', u'1110110100011101']", "name": "COMPLEMENTARY_CODE_16", "bits_per_code": 16}, "model": "rc.rclinecode", "pk": 12},
13 {"fields": {"number_of_codes": 1, "codes": "[u'11']", "name": "BARKER2", "bits_per_code": 2}, "model": "rc.rclinecode", "pk": 13},
13 {"fields": {"number_of_codes": 1, "codes": "[u'11']", "name": "BARKER2", "bits_per_code": 2}, "model": "rc.rclinecode", "pk": 13},
14 {"fields": {"number_of_codes": 1, "codes": "[u'110']", "name": "BARKER3", "bits_per_code": 3}, "model": "rc.rclinecode", "pk": 14},
14 {"fields": {"number_of_codes": 1, "codes": "[u'110']", "name": "BARKER3", "bits_per_code": 3}, "model": "rc.rclinecode", "pk": 14},
15 {"fields": {"number_of_codes": 2, "codes": "[u'1110', u'1101']", "name": "COMPLEMENTARY_CODE_4", "bits_per_code": 4}, "model": "rc.rclinecode", "pk": 15},
15 {"fields": {"number_of_codes": 2, "codes": "[u'1110', u'1101']", "name": "COMPLEMENTARY_CODE_4", "bits_per_code": 4}, "model": "rc.rclinecode", "pk": 15},
16 {"fields": {"number_of_codes": 1, "codes": "[u'1110010']", "name": "BARKER7", "bits_per_code": 7}, "model": "rc.rclinecode", "pk": 16},
16 {"fields": {"number_of_codes": 1, "codes": "[u'1110010']", "name": "BARKER7", "bits_per_code": 7}, "model": "rc.rclinecode", "pk": 16},
17 {"fields": {"number_of_codes": 1, "codes": "[u'1101']", "name": "BARKER4", "bits_per_code": 4}, "model": "rc.rclinecode", "pk": 17},
17 {"fields": {"number_of_codes": 1, "codes": "[u'1101']", "name": "BARKER4", "bits_per_code": 4}, "model": "rc.rclinecode", "pk": 17},
18 {"fields": {"number_of_codes": 1, "codes": "[u'11101']", "name": "BARKER5", "bits_per_code": 5}, "model": "rc.rclinecode", "pk": 18},
18 {"fields": {"number_of_codes": 1, "codes": "[u'11101']", "name": "BARKER5", "bits_per_code": 5}, "model": "rc.rclinecode", "pk": 18},
19 {"fields": {"params": "{\"TX_ref\": {\"model\": \"RCLine\", \"value\": \"\"}, \"range\": { \"value\": 0, \"help\": \"Frame numbers or frame ranges separated by commas, use 0 for all frames eg: 1,2,10-15\"}}", "name": "tr", "description": ""}, "model": "rc.rclinetype", "pk": 1},
19 {"fields": {"params": "{\"TX_ref\": {\"model\": \"RCLine\", \"value\": \"\"}, \"range\": { \"value\": 0, \"help\": \"Frame numbers or frame ranges separated by commas, use 0 for all frames eg: 1,2,10-15\"}}", "name": "tr", "description": ""}, "model": "rc.rclinetype", "pk": 1},
20 {"fields": {"params": "{\"pulse_width\":{\"value\": 0, \"widget\":\"dc\"},\r\n \"delays\":{\"value\": \"\", \"widget\":\"km\", \"help\": \"Delay entries separated by commas (TAUs)\"},\r\n \"range\":{\"value\": 0, \"help\": \"Frame numbers or frame ranges separated by commas, use 0 for all frames eg: 1,2,10-15\"}}", "name": "tx", "description": ""}, "model": "rc.rclinetype", "pk": 2},
20 {"fields": {"params": "{\"pulse_width\":{\"value\": 0, \"widget\":\"dc\"},\r\n \"delays\":{\"value\": \"\", \"widget\":\"km\", \"help\": \"Delay entries separated by commas (TAUs)\"},\r\n \"range\":{\"value\": 0, \"help\": \"Frame numbers or frame ranges separated by commas, use 0 for all frames eg: 1,2,10-15\"}}", "name": "tx", "description": ""}, "model": "rc.rclinetype", "pk": 2},
21 {"fields": {"params": "{\"TX_ref\": {\"model\": \"RCLine\", \"value\": \"\"}, \"code\": {\"model\":\"RCLineCode\",\"value\": \"\"}, \"codes\":{\"value\":\"\", \"widget\":\"codes\"}}", "name": "codes", "description": ""}, "model": "rc.rclinetype", "pk": 3},
21 {"fields": {"params": "{\"TX_ref\": {\"model\": \"RCLine\", \"value\": \"\"}, \"code\": {\"model\":\"RCLineCode\",\"value\": \"\"}, \"codes\":{\"value\":\"\", \"widget\":\"codes\"}}", "name": "codes", "description": ""}, "model": "rc.rclinetype", "pk": 3},
22 {"fields": {"params": "{ \"TX_ref\":{\"model\": \"RCLine\", \"value\": \"\"}, \"params\": {\"first_height\":{ \"value\": 0, \"widget\":\"km\"},\"resolution\": {\"value\": 0, \"widget\":\"km\"}, \"number_of_samples\": { \"value\": 0, \"help\":\"number of samples (NSA)\"}}}", "name": "windows", "description": ""}, "model": "rc.rclinetype", "pk": 4},
22 {"fields": {"params": "{ \"TX_ref\":{\"model\": \"RCLine\", \"value\": \"\"}, \"params\": {\"first_height\":{ \"value\": 0, \"widget\":\"km\"},\"resolution\": {\"value\": 0, \"widget\":\"km\"}, \"number_of_samples\": { \"value\": 0, \"help\":\"number of samples (NSA)\"}}}", "name": "windows", "description": ""}, "model": "rc.rclinetype", "pk": 4},
23 {"fields": {"params": "{\"invert\":{\"value\": 0, \"help\": \"Set to 1 for synchro pulse at the end\"}}", "name": "sync", "description": ""}, "model": "rc.rclinetype", "pk": 5},
23 {"fields": {"params": "{\"invert\":{\"value\": 0, \"help\": \"Set to 1 for synchro pulse at the end\"}}", "name": "sync", "description": ""}, "model": "rc.rclinetype", "pk": 5},
24 {"fields": {"params": "{ \"periodic\": { \"value\": 0, \"help\": \"Set to 1 for IPP periodic\"}, \"params\": {\"begin\": { \"value\": 0, \"widget\":\"unit\"}, \"end\": {\"value\": 0, \"widget\":\"unit\"}}}", "name": "prog_pulses", "description": ""}, "model": "rc.rclinetype", "pk": 6},
24 {"fields": {"params": "{ \"periodic\": { \"value\": 0, \"help\": \"Set to 1 for IPP periodic\"}, \"params\": {\"begin\": { \"value\": 0, \"widget\":\"unit\"}, \"end\": {\"value\": 0, \"widget\":\"unit\"}}}", "name": "prog_pulses", "description": ""}, "model": "rc.rclinetype", "pk": 6},
25 {"fields": {"params": "{\"number_of_flips\": {\"value\": 0}}", "name": "flip", "description": ""}, "model": "rc.rclinetype", "pk": 7},
25 {"fields": {"params": "{\"number_of_flips\": {\"value\": 0}}", "name": "flip", "description": ""}, "model": "rc.rclinetype", "pk": 7},
26 {"fields": {"params": "{}", "name": "none", "description": ""}, "model": "rc.rclinetype", "pk": 8}]
26 {"fields": {"params": "{}", "name": "none", "description": ""}, "model": "rc.rclinetype", "pk": 8},
27 {"fields": {"params": "{}", "name": "mix", "description": ""}, "model": "rc.rclinetype", "pk": 9}] No newline at end of file
@@ -1,370 +1,370
1 import os
1 import os
2 import ast
2 import ast
3 import json
3 import json
4
4
5 from django import forms
5 from django import forms
6 from django.utils.safestring import mark_safe
6 from django.utils.safestring import mark_safe
7 from apps.main.models import Device
7 from apps.main.models import Device
8 from apps.main.forms import add_empty_choice
8 from apps.main.forms import add_empty_choice
9 from .models import RCConfiguration, RCLine, RCLineType, RCLineCode
9 from .models import RCConfiguration, RCLine, RCLineType, RCLineCode
10 from .widgets import KmUnitWidget, KmUnitHzWidget, KmUnitDcWidget, UnitKmWidget, DefaultWidget, CodesWidget, HiddenWidget, HCheckboxSelectMultiple
10 from .widgets import KmUnitWidget, KmUnitHzWidget, KmUnitDcWidget, UnitKmWidget, DefaultWidget, CodesWidget, HiddenWidget, HCheckboxSelectMultiple
11
11
12 def create_choices_from_model(model, conf_id, all=False):
12 def create_choices_from_model(model, conf_id, all=False):
13
13
14 if model=='RCLine':
14 if model=='RCLine':
15 instance = RCConfiguration.objects.get(pk=conf_id)
15 instance = RCConfiguration.objects.get(pk=conf_id)
16 choices = [(line.pk, line.get_name()) for line in instance.get_lines(line_type__name='tx')]
16 choices = [(line.pk, line.get_name()) for line in instance.get_lines(line_type__name='tx')]
17 choices = add_empty_choice(choices, label='All')
17 choices = add_empty_choice(choices, label='All')
18 else:
18 else:
19 instance = globals()[model]
19 instance = globals()[model]
20 choices = instance.objects.all().values_list('pk', 'name')
20 choices = instance.objects.all().values_list('pk', 'name')
21
21
22 return choices
22 return choices
23
23
24
24
25 class ExtFileField(forms.FileField):
25 class ExtFileField(forms.FileField):
26 """
26 """
27 Same as forms.FileField, but you can specify a file extension whitelist.
27 Same as forms.FileField, but you can specify a file extension whitelist.
28
28
29 >>> from django.core.files.uploadedfile import SimpleUploadedFile
29 >>> from django.core.files.uploadedfile import SimpleUploadedFile
30 >>>
30 >>>
31 >>> t = ExtFileField(ext_whitelist=(".pdf", ".txt"))
31 >>> t = ExtFileField(ext_whitelist=(".pdf", ".txt"))
32 >>>
32 >>>
33 >>> t.clean(SimpleUploadedFile('filename.pdf', 'Some File Content'))
33 >>> t.clean(SimpleUploadedFile('filename.pdf', 'Some File Content'))
34 >>> t.clean(SimpleUploadedFile('filename.txt', 'Some File Content'))
34 >>> t.clean(SimpleUploadedFile('filename.txt', 'Some File Content'))
35 >>>
35 >>>
36 >>> t.clean(SimpleUploadedFile('filename.exe', 'Some File Content'))
36 >>> t.clean(SimpleUploadedFile('filename.exe', 'Some File Content'))
37 Traceback (most recent call last):
37 Traceback (most recent call last):
38 ...
38 ...
39 ValidationError: [u'Not allowed filetype!']
39 ValidationError: [u'Not allowed filetype!']
40 """
40 """
41 def __init__(self, *args, **kwargs):
41 def __init__(self, *args, **kwargs):
42 extensions = kwargs.pop("extensions")
42 extensions = kwargs.pop("extensions")
43 self.extensions = [i.lower() for i in extensions]
43 self.extensions = [i.lower() for i in extensions]
44
44
45 super(ExtFileField, self).__init__(*args, **kwargs)
45 super(ExtFileField, self).__init__(*args, **kwargs)
46
46
47 def clean(self, *args, **kwargs):
47 def clean(self, *args, **kwargs):
48 data = super(ExtFileField, self).clean(*args, **kwargs)
48 data = super(ExtFileField, self).clean(*args, **kwargs)
49 filename = data.name
49 filename = data.name
50 ext = os.path.splitext(filename)[1]
50 ext = os.path.splitext(filename)[1]
51 ext = ext.lower()
51 ext = ext.lower()
52 if ext not in self.extensions:
52 if ext not in self.extensions:
53 raise forms.ValidationError('Not allowed file type: %s' % ext)
53 raise forms.ValidationError('Not allowed file type: %s' % ext)
54
54
55
55
56 class RCConfigurationForm(forms.ModelForm):
56 class RCConfigurationForm(forms.ModelForm):
57
57
58 def __init__(self, *args, **kwargs):
58 def __init__(self, *args, **kwargs):
59 super(RCConfigurationForm, self).__init__(*args, **kwargs)
59 super(RCConfigurationForm, self).__init__(*args, **kwargs)
60
60
61 instance = getattr(self, 'instance', None)
61 instance = getattr(self, 'instance', None)
62
62
63 if instance and instance.pk:
63 if instance and instance.pk:
64
64
65 devices = Device.objects.filter(device_type__name='rc')
65 devices = Device.objects.filter(device_type__name='rc')
66 if instance.experiment:
66 if instance.experiment:
67 self.fields['experiment'].widget.attrs['read_only'] = True
67 self.fields['experiment'].widget.attrs['read_only'] = True
68 #self.fields['experiment'].widget.choices = [(instance.experiment.id, instance.experiment)]
68 #self.fields['experiment'].widget.choices = [(instance.experiment.id, instance.experiment)]
69 self.fields['device'].widget.choices = [(device.id, device) for device in devices]
69 self.fields['device'].widget.choices = [(device.id, device) for device in devices]
70 self.fields['ipp'].widget = KmUnitHzWidget(attrs={'km2unit':instance.km2unit})
70 self.fields['ipp'].widget = KmUnitHzWidget(attrs={'km2unit':instance.km2unit})
71 self.fields['clock'].widget.attrs['readonly'] = True
71 self.fields['clock'].widget.attrs['readonly'] = True
72
72
73 self.fields['time_before'].label = mark_safe(self.fields['time_before'].label)
73 self.fields['time_before'].label = mark_safe(self.fields['time_before'].label)
74 self.fields['time_after'].label = mark_safe(self.fields['time_after'].label)
74 self.fields['time_after'].label = mark_safe(self.fields['time_after'].label)
75
75
76 if 'initial' in kwargs and 'experiment' in kwargs['initial'] and kwargs['initial']['experiment'] not in (0, '0'):
76 if 'initial' in kwargs and 'experiment' in kwargs['initial'] and kwargs['initial']['experiment'] not in (0, '0'):
77 self.fields['experiment'].widget.attrs['disabled'] = 'disabled'
77 self.fields['experiment'].widget.attrs['disabled'] = 'disabled'
78
78
79 class Meta:
79 class Meta:
80 model = RCConfiguration
80 model = RCConfiguration
81 exclude = ('type', 'parameters', 'status')
81 exclude = ('type', 'parameters', 'status', 'mix')
82
82
83 def clean(self):
83 def clean(self):
84 form_data = super(RCConfigurationForm, self).clean()
84 form_data = super(RCConfigurationForm, self).clean()
85
85
86 if 'clock_divider' in form_data:
86 if 'clock_divider' in form_data:
87 if form_data['clock_divider']<1:
87 if form_data['clock_divider']<1:
88 self.add_error('clock_divider', 'Invalid Value')
88 self.add_error('clock_divider', 'Invalid Value')
89 else:
89 else:
90 if form_data['ipp']*(20./3*(form_data['clock_in']/form_data['clock_divider']))%10<>0:
90 if form_data['ipp']*(20./3*(form_data['clock_in']/form_data['clock_divider']))%10<>0:
91 self.add_error('ipp', 'Invalid IPP units={}'.format(form_data['ipp']*(20./3*(form_data['clock_in']/form_data['clock_divider']))))
91 self.add_error('ipp', 'Invalid IPP units={}'.format(form_data['ipp']*(20./3*(form_data['clock_in']/form_data['clock_divider']))))
92
92
93 return form_data
93 return form_data
94
94
95
95
96 class RCMixConfigurationForm(forms.Form):
96 class RCMixConfigurationForm(forms.Form):
97
97
98 clock_in = forms.CharField(widget=forms.HiddenInput())
98 clock_in = forms.CharField(widget=forms.HiddenInput())
99 clock_divider = forms.CharField(widget=forms.HiddenInput())
99 clock_divider = forms.CharField(widget=forms.HiddenInput())
100 name = forms.CharField()
100 name = forms.CharField()
101 experiment = forms.ChoiceField()
101 experiment = forms.ChoiceField()
102 operation = forms.ChoiceField(widget=forms.RadioSelect(),
102 operation = forms.ChoiceField(widget=forms.RadioSelect(),
103 choices=[(0, 'OR'), (1, 'XOR'), (2, 'AND'), (3, 'NAND')],
103 choices=[(0, 'OR'), (1, 'XOR'), (2, 'AND'), (3, 'NAND')],
104 initial=1)
104 initial=1)
105 delay = forms.CharField()
105 delay = forms.CharField()
106 mask = forms.MultipleChoiceField(choices=[(0, 'L1'),(1, 'L2'),(2, 'L3'),(3, 'L4'),(4, 'L5'),(5, 'L6'),(6, 'L7'),(7, 'L8')],
106 mask = forms.MultipleChoiceField(choices=[(0, 'L1'),(1, 'L2'),(2, 'L3'),(3, 'L4'),(4, 'L5'),(5, 'L6'),(6, 'L7'),(7, 'L8')],
107 widget=HCheckboxSelectMultiple())
107 widget=HCheckboxSelectMultiple())
108 result = forms.CharField(required=False,
108 result = forms.CharField(required=False,
109 widget=forms.Textarea(attrs={'readonly':True, 'rows':5, 'class':'tabuled'}))
109 widget=forms.Textarea(attrs={'readonly':True, 'rows':5, 'class':'tabuled'}))
110
110
111 def __init__(self, *args, **kwargs):
111 def __init__(self, *args, **kwargs):
112 confs = kwargs.pop('confs', [])
112 confs = kwargs.pop('confs', [])
113 if confs:
113 if confs:
114 km2unit = confs[0].km2unit
114 km2unit = confs[0].km2unit
115 clock_in = confs[0].clock_in
115 clock_in = confs[0].clock_in
116 clock_divider = confs[0].clock_divider
116 clock_divider = confs[0].clock_divider
117 else:
117 else:
118 km2unit = clock_in = clock_divider = 0
118 km2unit = clock_in = clock_divider = 0
119 super(RCMixConfigurationForm, self).__init__(*args, **kwargs)
119 super(RCMixConfigurationForm, self).__init__(*args, **kwargs)
120 self.fields['experiment'].choices = [(conf.pk, '{} | {}'.format(conf.pk, conf.name)) for conf in confs]
120 self.fields['experiment'].choices = [(conf.pk, '{} | {}'.format(conf.pk, conf.name)) for conf in confs]
121 self.fields['delay'].widget = KmUnitWidget(attrs = {'km2unit':km2unit})
121 self.fields['delay'].widget = KmUnitWidget(attrs = {'km2unit':km2unit})
122 self.fields['clock_in'].initial = clock_in
122 self.fields['clock_in'].initial = clock_in
123 self.fields['clock_divider'].initial = clock_divider
123 self.fields['clock_divider'].initial = clock_divider
124
124
125
125
126
126
127 class RCLineForm(forms.ModelForm):
127 class RCLineForm(forms.ModelForm):
128
128
129 def __init__(self, *args, **kwargs):
129 def __init__(self, *args, **kwargs):
130 self.extra_fields = kwargs.pop('extra_fields', [])
130 self.extra_fields = kwargs.pop('extra_fields', [])
131 super(RCLineForm, self).__init__(*args, **kwargs)
131 super(RCLineForm, self).__init__(*args, **kwargs)
132
132
133 if 'initial' in kwargs and 'line_type' in kwargs['initial']:
133 if 'initial' in kwargs and 'line_type' in kwargs['initial']:
134 line_type = RCLineType.objects.get(pk=kwargs['initial']['line_type'])
134 line_type = RCLineType.objects.get(pk=kwargs['initial']['line_type'])
135
135
136 if 'code_id' in kwargs['initial']:
136 if 'code_id' in kwargs['initial']:
137 model_initial = kwargs['initial']['code_id']
137 model_initial = kwargs['initial']['code_id']
138 else:
138 else:
139 model_initial = 0
139 model_initial = 0
140
140
141 params = json.loads(line_type.params)
141 params = json.loads(line_type.params)
142
142
143 for label, value in self.extra_fields.items():
143 for label, value in self.extra_fields.items():
144 if label=='params':
144 if label=='params':
145 continue
145 continue
146
146
147 if 'model' in params[label]:
147 if 'model' in params[label]:
148 self.fields[label] = forms.ChoiceField(choices=create_choices_from_model(params[label]['model'],
148 self.fields[label] = forms.ChoiceField(choices=create_choices_from_model(params[label]['model'],
149 kwargs['initial']['rc_configuration']),
149 kwargs['initial']['rc_configuration']),
150 initial=model_initial)
150 initial=model_initial)
151
151
152
152
153 else:
153 else:
154 if label=='codes' and 'code_id' in kwargs['initial']:
154 if label=='codes' and 'code_id' in kwargs['initial']:
155 self.fields[label] = forms.CharField(initial=RCLineCode.objects.get(pk=kwargs['initial']['code_id']).codes)
155 self.fields[label] = forms.CharField(initial=RCLineCode.objects.get(pk=kwargs['initial']['code_id']).codes)
156 else:
156 else:
157 self.fields[label] = forms.CharField(initial=value['value'])
157 self.fields[label] = forms.CharField(initial=value['value'])
158
158
159 if label=='codes':
159 if label=='codes':
160 self.fields[label].widget = CodesWidget()
160 self.fields[label].widget = CodesWidget()
161
161
162 if self.data:
162 if self.data:
163 line_type = RCLineType.objects.get(pk=self.data['line_type'])
163 line_type = RCLineType.objects.get(pk=self.data['line_type'])
164
164
165 if 'code_id' in self.data:
165 if 'code_id' in self.data:
166 model_initial = self.data['code_id']
166 model_initial = self.data['code_id']
167 else:
167 else:
168 model_initial = 0
168 model_initial = 0
169
169
170 params = json.loads(line_type.params)
170 params = json.loads(line_type.params)
171
171
172 for label, value in self.extra_fields.items():
172 for label, value in self.extra_fields.items():
173 if label=='params':
173 if label=='params':
174 continue
174 continue
175
175
176 if 'model' in params[label]:
176 if 'model' in params[label]:
177 self.fields[label] = forms.ChoiceField(choices=create_choices_from_model(params[label]['model'],
177 self.fields[label] = forms.ChoiceField(choices=create_choices_from_model(params[label]['model'],
178 self.data['rc_configuration']),
178 self.data['rc_configuration']),
179 initial=model_initial)
179 initial=model_initial)
180
180
181
181
182 else:
182 else:
183 if label=='codes' and 'code' in self.data:
183 if label=='codes' and 'code' in self.data:
184 self.fields[label] = forms.CharField(initial=self.data['codes'])
184 self.fields[label] = forms.CharField(initial=self.data['codes'])
185 else:
185 else:
186 self.fields[label] = forms.CharField(initial=self.data[label])
186 self.fields[label] = forms.CharField(initial=self.data[label])
187
187
188 if label=='codes':
188 if label=='codes':
189 self.fields[label].widget = CodesWidget()
189 self.fields[label].widget = CodesWidget()
190
190
191
191
192 class Meta:
192 class Meta:
193 model = RCLine
193 model = RCLine
194 fields = ('rc_configuration', 'line_type', 'channel')
194 fields = ('rc_configuration', 'line_type', 'channel')
195 widgets = {
195 widgets = {
196 'channel': forms.HiddenInput(),
196 'channel': forms.HiddenInput(),
197 }
197 }
198
198
199
199
200 def clean(self):
200 def clean(self):
201
201
202 form_data = self.cleaned_data
202 form_data = self.cleaned_data
203 if 'code' in self.data and self.data['TX_ref']=="0":
203 if 'code' in self.data and self.data['TX_ref']=="0":
204 self.add_error('TX_ref', 'Choose a valid TX reference')
204 self.add_error('TX_ref', 'Choose a valid TX reference')
205
205
206 return form_data
206 return form_data
207
207
208
208
209 def save(self):
209 def save(self):
210 line = super(RCLineForm, self).save()
210 line = super(RCLineForm, self).save()
211
211
212 #auto add channel
212 #auto add channel
213 line.channel = RCLine.objects.filter(rc_configuration=line.rc_configuration).count()-1
213 line.channel = RCLine.objects.filter(rc_configuration=line.rc_configuration).count()-1
214
214
215 #auto add position for TX, TR & CODE
215 #auto add position for TX, TR & CODE
216 if line.line_type.name in ('tx', ):
216 if line.line_type.name in ('tx', ):
217 line.position = RCLine.objects.filter(rc_configuration=line.rc_configuration, line_type=line.line_type).count()-1
217 line.position = RCLine.objects.filter(rc_configuration=line.rc_configuration, line_type=line.line_type).count()-1
218
218
219 #save extra fields in params
219 #save extra fields in params
220 params = {}
220 params = {}
221 for label, value in self.extra_fields.items():
221 for label, value in self.extra_fields.items():
222 if label=='params':
222 if label=='params':
223 params['params'] = []
223 params['params'] = []
224 elif label=='codes':
224 elif label=='codes':
225 params[label] = [s for s in self.data[label].split('\r\n') if s]
225 params[label] = [s for s in self.data[label].split('\r\n') if s]
226 else:
226 else:
227 params[label] = self.data[label]
227 params[label] = self.data[label]
228 line.params = json.dumps(params)
228 line.params = json.dumps(params)
229 line.save()
229 line.save()
230 return
230 return
231
231
232
232
233 class RCLineViewForm(forms.Form):
233 class RCLineViewForm(forms.Form):
234
234
235 def __init__(self, *args, **kwargs):
235 def __init__(self, *args, **kwargs):
236
236
237 extra_fields = kwargs.pop('extra_fields')
237 extra_fields = kwargs.pop('extra_fields')
238 line = kwargs.pop('line')
238 line = kwargs.pop('line')
239 subform = kwargs.pop('subform', False)
239 subform = kwargs.pop('subform', False)
240 super(RCLineViewForm, self).__init__(*args, **kwargs)
240 super(RCLineViewForm, self).__init__(*args, **kwargs)
241
241
242 if subform:
242 if subform:
243 params = json.loads(line.line_type.params)['params']
243 params = json.loads(line.line_type.params)['params']
244 else:
244 else:
245 params = json.loads(line.line_type.params)
245 params = json.loads(line.line_type.params)
246
246
247 for label, value in extra_fields.items():
247 for label, value in extra_fields.items():
248
248
249 if label=='params':
249 if label=='params':
250 continue
250 continue
251 if 'ref' in label:
251 if 'ref' in label:
252 if value in (0, '0'):
252 if value in (0, '0'):
253 value = 'All'
253 value = 'All'
254 else:
254 else:
255 value = RCLine.objects.get(pk=value).get_name()
255 value = RCLine.objects.get(pk=value).get_name()
256 elif label=='code':
256 elif label=='code':
257 value = RCLineCode.objects.get(pk=value).name
257 value = RCLineCode.objects.get(pk=value).name
258
258
259 self.fields[label] = forms.CharField(initial=value)
259 self.fields[label] = forms.CharField(initial=value)
260
260
261 if 'widget' in params[label]:
261 if 'widget' in params[label]:
262 km2unit = line.rc_configuration.km2unit
262 km2unit = line.rc_configuration.km2unit
263 if params[label]['widget']=='km':
263 if params[label]['widget']=='km':
264 self.fields[label].widget = KmUnitWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
264 self.fields[label].widget = KmUnitWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
265 elif params[label]['widget']=='unit':
265 elif params[label]['widget']=='unit':
266 self.fields[label].widget = UnitKmWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
266 self.fields[label].widget = UnitKmWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
267 elif params[label]['widget']=='dc':
267 elif params[label]['widget']=='dc':
268 self.fields[label].widget = KmUnitDcWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
268 self.fields[label].widget = KmUnitDcWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
269 elif params[label]['widget']=='codes':
269 elif params[label]['widget']=='codes':
270 self.fields[label].widget = CodesWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
270 self.fields[label].widget = CodesWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True})
271 else:
271 else:
272 self.fields[label].widget = DefaultWidget(attrs={'disabled':True})
272 self.fields[label].widget = DefaultWidget(attrs={'disabled':True})
273
273
274
274
275 class RCLineEditForm(forms.ModelForm):
275 class RCLineEditForm(forms.ModelForm):
276
276
277 def __init__(self, *args, **kwargs):
277 def __init__(self, *args, **kwargs):
278
278
279 extra_fields = kwargs.pop('extra_fields', [])
279 extra_fields = kwargs.pop('extra_fields', [])
280 conf = kwargs.pop('conf', False)
280 conf = kwargs.pop('conf', False)
281 line = kwargs.pop('line')
281 line = kwargs.pop('line')
282 subform = kwargs.pop('subform', False)
282 subform = kwargs.pop('subform', False)
283
283
284 super(RCLineEditForm, self).__init__(*args, **kwargs)
284 super(RCLineEditForm, self).__init__(*args, **kwargs)
285
285
286 if subform is not False:
286 if subform is not False:
287 params = json.loads(line.line_type.params)['params']
287 params = json.loads(line.line_type.params)['params']
288 count = subform
288 count = subform
289 else:
289 else:
290 params = json.loads(line.line_type.params)
290 params = json.loads(line.line_type.params)
291 count = -1
291 count = -1
292
292
293 for label, value in extra_fields.items():
293 for label, value in extra_fields.items():
294
294
295 if label in ('params',):
295 if label in ('params',):
296 continue
296 continue
297 if 'help' in params[label]:
297 if 'help' in params[label]:
298 help_text = params[label]['help']
298 help_text = params[label]['help']
299 else:
299 else:
300 help_text = ''
300 help_text = ''
301
301
302 if 'model' in params[label]:
302 if 'model' in params[label]:
303 self.fields[label] = forms.ChoiceField(choices=create_choices_from_model(params[label]['model'], conf.id),
303 self.fields[label] = forms.ChoiceField(choices=create_choices_from_model(params[label]['model'], conf.id),
304 initial=value,
304 initial=value,
305 widget=forms.Select(attrs={'name':'%s|%s|%s' % (count, line.id, label)}),
305 widget=forms.Select(attrs={'name':'%s|%s|%s' % (count, line.id, label)}),
306 help_text=help_text)
306 help_text=help_text)
307
307
308 else:
308 else:
309
309
310 self.fields[label] = forms.CharField(initial=value, help_text=help_text)
310 self.fields[label] = forms.CharField(initial=value, help_text=help_text)
311
311
312 if label in ('code', ):
312 if label in ('code', ):
313 self.fields[label].widget = HiddenWidget(attrs={'name':'%s|%s|%s' % (count, line.id, label)})
313 self.fields[label].widget = HiddenWidget(attrs={'name':'%s|%s|%s' % (count, line.id, label)})
314
314
315 elif 'widget' in params[label]:
315 elif 'widget' in params[label]:
316 km2unit = line.rc_configuration.km2unit
316 km2unit = line.rc_configuration.km2unit
317 if params[label]['widget']=='km':
317 if params[label]['widget']=='km':
318 self.fields[label].widget = KmUnitWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
318 self.fields[label].widget = KmUnitWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
319 elif params[label]['widget']=='unit':
319 elif params[label]['widget']=='unit':
320 self.fields[label].widget = UnitKmWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
320 self.fields[label].widget = UnitKmWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
321 elif params[label]['widget']=='dc':
321 elif params[label]['widget']=='dc':
322 self.fields[label].widget = KmUnitDcWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
322 self.fields[label].widget = KmUnitDcWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
323 elif params[label]['widget']=='codes':
323 elif params[label]['widget']=='codes':
324 self.fields[label].widget = CodesWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
324 self.fields[label].widget = CodesWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)})
325 else:
325 else:
326 self.fields[label].widget = DefaultWidget(attrs={'name':'%s|%s|%s' % (count, line.id, label)})
326 self.fields[label].widget = DefaultWidget(attrs={'name':'%s|%s|%s' % (count, line.id, label)})
327
327
328
328
329 class Meta:
329 class Meta:
330 model = RCLine
330 model = RCLine
331 exclude = ('rc_configuration', 'line_type', 'channel', 'position', 'params', 'pulses')
331 exclude = ('rc_configuration', 'line_type', 'channel', 'position', 'params', 'pulses')
332
332
333
333
334 class RCSubLineEditForm(forms.Form):
334 class RCSubLineEditForm(forms.Form):
335
335
336 def __init__(self, *args, **kwargs):
336 def __init__(self, *args, **kwargs):
337 extra_fields = kwargs.pop('extra_fields')
337 extra_fields = kwargs.pop('extra_fields')
338 count = kwargs.pop('count')
338 count = kwargs.pop('count')
339 line = kwargs.pop('line')
339 line = kwargs.pop('line')
340 super(RCSubLineEditForm, self).__init__(*args, **kwargs)
340 super(RCSubLineEditForm, self).__init__(*args, **kwargs)
341 for label, value in extra_fields.items():
341 for label, value in extra_fields.items():
342 self.fields[label] = forms.CharField(initial=value,
342 self.fields[label] = forms.CharField(initial=value,
343 widget=forms.TextInput(attrs={'name':'%s|%s|%s' % (count, line, label)}))
343 widget=forms.TextInput(attrs={'name':'%s|%s|%s' % (count, line, label)}))
344
344
345
345
346 class RCImportForm(forms.Form):
346 class RCImportForm(forms.Form):
347
347
348 file_name = ExtFileField(extensions=['.racp', '.json', '.dat'])
348 file_name = ExtFileField(extensions=['.racp', '.json', '.dat'])
349
349
350
350
351 class RCLineCodesForm(forms.ModelForm):
351 class RCLineCodesForm(forms.ModelForm):
352
352
353 def __init__(self, *args, **kwargs):
353 def __init__(self, *args, **kwargs):
354 super(RCLineCodesForm, self).__init__(*args, **kwargs)
354 super(RCLineCodesForm, self).__init__(*args, **kwargs)
355
355
356 if 'initial' in kwargs:
356 if 'initial' in kwargs:
357 self.fields['code'] = forms.ChoiceField(choices=RCLineCode.objects.all().values_list('pk', 'name'),
357 self.fields['code'] = forms.ChoiceField(choices=RCLineCode.objects.all().values_list('pk', 'name'),
358 initial=kwargs['initial']['code'])
358 initial=kwargs['initial']['code'])
359 if 'instance' in kwargs:
359 if 'instance' in kwargs:
360 self.fields['code'] = forms.ChoiceField(choices=RCLineCode.objects.all().values_list('pk', 'name'),
360 self.fields['code'] = forms.ChoiceField(choices=RCLineCode.objects.all().values_list('pk', 'name'),
361 initial=kwargs['instance'].pk)
361 initial=kwargs['instance'].pk)
362
362
363 self.fields['codes'].widget = CodesWidget()
363 self.fields['codes'].widget = CodesWidget()
364
364
365
365
366 class Meta:
366 class Meta:
367 model = RCLineCode
367 model = RCLineCode
368 exclude = ('name',)
368 exclude = ('name',)
369
369
370 No newline at end of file
370
@@ -1,645 +1,737
1
1
2 import ast
2 import ast
3 import json
3 import json
4 import numpy as np
4 import numpy as np
5
5
6 from polymorphic import PolymorphicModel
6 from polymorphic import PolymorphicModel
7
7
8 from django.db import models
8 from django.db import models
9 from django.core.urlresolvers import reverse
9 from django.core.urlresolvers import reverse
10 from django.core.validators import MinValueValidator, MaxValueValidator
10 from django.core.validators import MinValueValidator, MaxValueValidator
11
11
12 from apps.main.models import Configuration
12 from apps.main.models import Configuration
13 from devices.rc import api
13 from devices.rc import api
14 from .utils import RCFile, pulses, pulses_from_code, create_mask, pulses_to_points
14 from .utils import RCFile
15
15
16 # Create your models here.
16 # Create your models here.
17
17
18 LINE_TYPES = (
18 LINE_TYPES = (
19 ('none', 'Not used'),
19 ('none', 'Not used'),
20 ('tr', 'Transmission/reception selector signal'),
20 ('tr', 'Transmission/reception selector signal'),
21 ('tx', 'A modulating signal (Transmission pulse)'),
21 ('tx', 'A modulating signal (Transmission pulse)'),
22 ('codes', 'BPSK modulating signal'),
22 ('codes', 'BPSK modulating signal'),
23 ('windows', 'Sample window signal'),
23 ('windows', 'Sample window signal'),
24 ('sync', 'Synchronizing signal'),
24 ('sync', 'Synchronizing signal'),
25 ('flip', 'IPP related periodic signal'),
25 ('flip', 'IPP related periodic signal'),
26 ('prog_pulses', 'Programmable pulse'),
26 ('prog_pulses', 'Programmable pulse'),
27 ('mix', 'Mixed line'),
27 ('mix', 'Mixed line'),
28 )
28 )
29
29
30
30
31 SAMPLING_REFS = (
31 SAMPLING_REFS = (
32 ('none', 'No Reference'),
32 ('none', 'No Reference'),
33 ('first_baud', 'Middle of the first baud'),
33 ('first_baud', 'Middle of the first baud'),
34 ('sub_baud', 'Middle of the sub-baud')
34 ('sub_baud', 'Middle of the sub-baud')
35 )
35 )
36
36
37 DAT_CMDS = {
37 DAT_CMDS = {
38 # Pulse Design commands
38 # Pulse Design commands
39 'DISABLE' : 0, # Disables pulse generation
39 'DISABLE' : 0, # Disables pulse generation
40 'ENABLE' : 24, # Enables pulse generation
40 'ENABLE' : 24, # Enables pulse generation
41 'DELAY_START' : 40, # Write delay status to memory
41 'DELAY_START' : 40, # Write delay status to memory
42 'FLIP_START' : 48, # Write flip status to memory
42 'FLIP_START' : 48, # Write flip status to memory
43 'SAMPLING_PERIOD' : 64, # Establish Sampling Period
43 'SAMPLING_PERIOD' : 64, # Establish Sampling Period
44 'TX_ONE' : 72, # Output '0' in line TX
44 'TX_ONE' : 72, # Output '0' in line TX
45 'TX_ZERO' : 88, # Output '0' in line TX
45 'TX_ZERO' : 88, # Output '0' in line TX
46 'SW_ONE' : 104, # Output '0' in line SW
46 'SW_ONE' : 104, # Output '0' in line SW
47 'SW_ZERO' : 112, # Output '1' in line SW
47 'SW_ZERO' : 112, # Output '1' in line SW
48 'RESTART': 120, # Restarts CR8 Firmware
48 'RESTART': 120, # Restarts CR8 Firmware
49 'CONTINUE' : 253, # Function Unknown
49 'CONTINUE' : 253, # Function Unknown
50 # Commands available to new controllers
50 # Commands available to new controllers
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.
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 'CLOCK_DIVISOR_INIT' : 12, # Specifies Clock Divisor. Legacy command, ignored in the actual .dat conversion
52 'CLOCK_DIVISOR_INIT' : 12, # Specifies Clock Divisor. Legacy command, ignored in the actual .dat conversion
53 'CLOCK_DIVISOR_LAST' : 22, # Specifies Clock Divisor (default 60 if not included) syntax: 255,22 254,N-1.
53 'CLOCK_DIVISOR_LAST' : 22, # Specifies Clock Divisor (default 60 if not included) syntax: 255,22 254,N-1.
54 'CLOCK_DIVIDER' : 8,
54 'CLOCK_DIVIDER' : 8,
55 }
55 }
56
56
57
57
58 class RCConfiguration(Configuration):
58 class RCConfiguration(Configuration):
59
59
60 ipp = models.FloatField(verbose_name='Inter pulse period (Km)', validators=[MinValueValidator(1), MaxValueValidator(9000)], default=300)
60 ipp = models.FloatField(verbose_name='Inter pulse period (Km)', validators=[MinValueValidator(1), MaxValueValidator(9000)], default=300)
61 ntx = models.PositiveIntegerField(verbose_name='Number of TX', validators=[MinValueValidator(1), MaxValueValidator(300)], default=1)
61 ntx = models.PositiveIntegerField(verbose_name='Number of TX', validators=[MinValueValidator(1), MaxValueValidator(300)], default=1)
62 clock_in = models.FloatField(verbose_name='Clock in (MHz)', validators=[MinValueValidator(1), MaxValueValidator(80)], default=1)
62 clock_in = models.FloatField(verbose_name='Clock in (MHz)', validators=[MinValueValidator(1), MaxValueValidator(80)], default=1)
63 clock_divider = models.PositiveIntegerField(verbose_name='Clock divider', validators=[MinValueValidator(1), MaxValueValidator(256)], default=1)
63 clock_divider = models.PositiveIntegerField(verbose_name='Clock divider', validators=[MinValueValidator(1), MaxValueValidator(256)], default=1)
64 clock = models.FloatField(verbose_name='Clock Master (MHz)', blank=True, default=1)
64 clock = models.FloatField(verbose_name='Clock Master (MHz)', blank=True, default=1)
65 time_before = models.PositiveIntegerField(verbose_name='Time before (&mu;S)', default=12)
65 time_before = models.PositiveIntegerField(verbose_name='Time before (&mu;S)', default=12)
66 time_after = models.PositiveIntegerField(verbose_name='Time after (&mu;S)', default=1)
66 time_after = models.PositiveIntegerField(verbose_name='Time after (&mu;S)', default=1)
67 sync = models.PositiveIntegerField(verbose_name='Synchro delay', default=0)
67 sync = models.PositiveIntegerField(verbose_name='Synchro delay', default=0)
68 sampling_reference = models.CharField(verbose_name='Sampling Reference', choices=SAMPLING_REFS, default='none', max_length=40)
68 sampling_reference = models.CharField(verbose_name='Sampling Reference', choices=SAMPLING_REFS, default='none', max_length=40)
69 control_tx = models.BooleanField(verbose_name='Control Switch TX', default=False)
69 control_tx = models.BooleanField(verbose_name='Control Switch TX', default=False)
70 control_sw = models.BooleanField(verbose_name='Control Switch SW', default=False)
70 control_sw = models.BooleanField(verbose_name='Control Switch SW', default=False)
71 mix = models.BooleanField(default=False)
71 mix = models.BooleanField(default=False)
72
72
73 class Meta:
73 class Meta:
74 db_table = 'rc_configurations'
74 db_table = 'rc_configurations'
75
75
76
76
77 def __unicode__(self):
77 def __unicode__(self):
78
78
79 if self.mix:
79 if self.mix:
80 return u'[MIXED]: %s' % self.name
80 return u'[MIXED]: %s' % self.name
81 else:
81 else:
82 return u'[%s]: %s' % (self.device.name, self.name)
82 return u'[%s]: %s' % (self.device.name, self.name)
83
83
84 def get_absolute_url_plot(self):
84 def get_absolute_url_plot(self):
85 return reverse('url_plot_rc_pulses', args=[str(self.id)])
85 return reverse('url_plot_rc_pulses', args=[str(self.id)])
86
86
87 def get_absolute_url_import(self):
87 def get_absolute_url_import(self):
88 return reverse('url_import_rc_conf', args=[str(self.id)])
88 return reverse('url_import_rc_conf', args=[str(self.id)])
89
89
90 @property
90 @property
91 def us2unit(self):
91 def us2unit(self):
92
92
93 return self.clock_in/self.clock_divider
93 return self.clock_in/self.clock_divider
94
94
95 @property
95 @property
96 def km2unit(self):
96 def km2unit(self):
97
97
98 return 20./3*(self.clock_in/self.clock_divider)
98 return 20./3*(self.clock_in/self.clock_divider)
99
99
100 def clone(self, **kwargs):
100 def clone(self, **kwargs):
101
101
102 lines = self.get_lines()
102 lines = self.get_lines()
103 self.pk = None
103 self.pk = None
104 self.id = None
104 self.id = None
105 for attr, value in kwargs.items():
105 for attr, value in kwargs.items():
106 setattr(self, attr, value)
106 setattr(self, attr, value)
107 self.save()
107 self.save()
108
108
109 for line in lines:
109 for line in lines:
110 line.clone(rc_configuration=self)
110 line.clone(rc_configuration=self)
111
111
112 return self
112 return self
113
113
114 def get_lines(self, **kwargs):
114 def get_lines(self, **kwargs):
115 '''
115 '''
116 Retrieve configuration lines
116 Retrieve configuration lines
117 '''
117 '''
118
118
119 return RCLine.objects.filter(rc_configuration=self.pk, **kwargs)
119 return RCLine.objects.filter(rc_configuration=self.pk, **kwargs)
120
120
121
121
122 def clean_lines(self):
122 def clean_lines(self):
123 '''
123 '''
124 '''
124 '''
125
125
126 empty_line = RCLineType.objects.get(pk=8)
126 empty_line = RCLineType.objects.get(name='none')
127
127
128 for line in self.get_lines():
128 for line in self.get_lines():
129 line.line_type = empty_line
129 line.line_type = empty_line
130 line.params = '{}'
130 line.params = '{}'
131 line.save()
131 line.save()
132
132
133 def parms_to_dict(self):
133 def parms_to_dict(self):
134 '''
134 '''
135 '''
135 '''
136
136
137 ignored = ('parameters', 'type', 'polymorphic_ctype', 'configuration_ptr',
138 'created_date', 'programmed_date')
139
137 data = {}
140 data = {}
138 for field in self._meta.fields:
141 for field in self._meta.fields:
139
142 if field.name in ignored:
143 continue
140 data[field.name] = '{}'.format(field.value_from_object(self))
144 data[field.name] = '{}'.format(field.value_from_object(self))
141
145
142 data.pop('parameters')
143 data['lines'] = []
146 data['lines'] = []
144
147
145 for line in self.get_lines():
148 for line in self.get_lines():
146 line_data = json.loads(line.params)
149 line_data = json.loads(line.params)
147 if 'TX_ref' in line_data and line_data['TX_ref'] not in (0, '0'):
150 if 'TX_ref' in line_data and line_data['TX_ref'] not in (0, '0'):
148 line_data['TX_ref'] = RCLine.objects.get(pk=line_data['TX_ref']).get_name()
151 line_data['TX_ref'] = RCLine.objects.get(pk=line_data['TX_ref']).get_name()
149 if 'code' in line_data:
152 if 'code' in line_data:
150 line_data['code'] = RCLineCode.objects.get(pk=line_data['code']).name
153 line_data['code'] = RCLineCode.objects.get(pk=line_data['code']).name
151 line_data['type'] = line.line_type.name
154 line_data['type'] = line.line_type.name
152 data['lines'].append(line_data)
155 data['lines'].append(line_data)
153
156
154 data['delays'] = self.get_delays()
157 data['delays'] = self.get_delays()
155 data['pulses'] = self.get_pulses()
158 data['pulses'] = self.get_pulses()
156
159
157 return data
160 return data
158
161
159 def dict_to_parms(self, data):
162 def dict_to_parms(self, data):
160 '''
163 '''
161 '''
164 '''
162
165
163 self.name = data['name']
166 self.name = data['name']
164 self.ipp = data['ipp']
167 self.ipp = data['ipp']
165 self.ntx = data['ntx']
168 self.ntx = data['ntx']
166 self.clock_in = data['clock_in']
169 self.clock_in = data['clock_in']
167 self.clock_divider = data['clock_divider']
170 self.clock_divider = data['clock_divider']
168 self.clock = data['clock']
171 self.clock = data['clock']
169 self.time_before = data['time_before']
172 self.time_before = data['time_before']
170 self.time_after = data['time_after']
173 self.time_after = data['time_after']
171 self.sync = data['sync']
174 self.sync = data['sync']
172 self.sampling_reference = data['sampling_reference']
175 self.sampling_reference = data['sampling_reference']
173 self.clean_lines()
176 self.clean_lines()
174
177
175 lines = []
178 lines = []
176 positions = {'tx':0, 'tr':0}
179 positions = {'tx':0, 'tr':0}
177
180
178 for i, line_data in enumerate(data['lines']):
181 for i, line_data in enumerate(data['lines']):
179 line_type = RCLineType.objects.get(name=line_data.pop('type'))
182 line_type = RCLineType.objects.get(name=line_data.pop('type'))
180 if line_type.name=='codes':
183 if line_type.name=='codes':
181 code = RCLineCode.objects.get(name=line_data['code'])
184 code = RCLineCode.objects.get(name=line_data['code'])
182 line_data['code'] = code.pk
185 line_data['code'] = code.pk
183 line = RCLine.objects.filter(rc_configuration=self, channel=i)
186 line = RCLine.objects.filter(rc_configuration=self, channel=i)
184 if line:
187 if line:
185 line = line[0]
188 line = line[0]
186 line.line_type = line_type
189 line.line_type = line_type
187 line.params = json.dumps(line_data)
190 line.params = json.dumps(line_data)
188 else:
191 else:
189 line = RCLine(rc_configuration=self, line_type=line_type,
192 line = RCLine(rc_configuration=self, line_type=line_type,
190 params=json.dumps(line_data),
193 params=json.dumps(line_data),
191 channel=i)
194 channel=i)
192
195
193 if line_type.name=='tx':
196 if line_type.name=='tx':
194 line.position = positions['tx']
197 line.position = positions['tx']
195 positions['tx'] += 1
198 positions['tx'] += 1
196
199
197 if line_type.name=='tr':
200 if line_type.name=='tr':
198 line.position = positions['tr']
201 line.position = positions['tr']
199 positions['tr'] += 1
202 positions['tr'] += 1
200
203
201 line.save()
204 line.save()
202 lines.append(line)
205 lines.append(line)
203
206
204 for line, line_data in zip(lines, data['lines']):
207 for line, line_data in zip(lines, data['lines']):
205 if 'TX_ref' in line_data:
208 if 'TX_ref' in line_data:
206 params = json.loads(line.params)
209 params = json.loads(line.params)
207 if line_data['TX_ref'] in (0, '0'):
210 if line_data['TX_ref'] in (0, '0'):
208 params['TX_ref'] = '0'
211 params['TX_ref'] = '0'
209 else:
212 else:
210 params['TX_ref'] = [l.pk for l in lines if l.line_type.name=='tx' and l.get_name()==line_data['TX_ref']][0]
213 params['TX_ref'] = [l.pk for l in lines if l.line_type.name=='tx' and l.get_name()==line_data['TX_ref']][0]
211 line.params = json.dumps(params)
214 line.params = json.dumps(params)
212 line.save()
215 line.save()
213
216
214
217
215 def get_delays(self):
218 def get_delays(self):
216
219
217 pulses = [line.get_pulses() for line in self.get_lines()]
220 pulses = [line.pulses_as_points() for line in self.get_lines()]
218 points = [tup for tups in pulses for tup in tups]
221 points = [tup for tups in pulses for tup in tups]
219 points = set([x for tup in points for x in tup])
222 points = set([x for tup in points for x in tup])
220 points = list(points)
223 points = list(points)
221 points.sort()
224 points.sort()
222
225
223 if points[0]<>0:
226 if points[0]<>0:
224 points.insert(0, 0)
227 points.insert(0, 0)
225
228
226 return [points[i+1]-points[i] for i in range(len(points)-1)]
229 return [points[i+1]-points[i] for i in range(len(points)-1)]
227
230
228
231
229 def get_pulses(self, binary=True):
232 def get_pulses(self, binary=True):
230
233
231 pulses = [line.get_pulses() for line in self.get_lines()]
234 pulses = [line.pulses_as_points() for line in self.get_lines()]
232 points = [tup for tups in pulses for tup in tups]
235 points = [tup for tups in pulses for tup in tups]
233 points = set([x for tup in points for x in tup])
236 points = set([x for tup in points for x in tup])
234 points = list(points)
237 points = list(points)
235 points.sort()
238 points.sort()
236
239
237 line_points = [pulses_to_points(line.pulses_as_array()) for line in self.get_lines()]
240 line_points = [line.pulses_as_points() for line in self.get_lines()]
238 line_points = [[(x, x+y) for x,y in tups] for tups in line_points]
241 line_points = [[(x, x+y) for x,y in tups] for tups in line_points]
239 line_points = [[t for x in tups for t in x] for tups in line_points]
242 line_points = [[t for x in tups for t in x] for tups in line_points]
240 states = [[1 if x in tups else 0 for tups in line_points] for x in points]
243 states = [[1 if x in tups else 0 for tups in line_points] for x in points]
241
244
242 if binary:
245 if binary:
243 states.reverse()
246 states.reverse()
244 states = [int(''.join([str(x) for x in flips]), 2) for flips in states]
247 states = [int(''.join([str(x) for x in flips]), 2) for flips in states]
245
248
246 return states[:-1]
249 return states[:-1]
247
250
248 def add_cmd(self, cmd):
251 def add_cmd(self, cmd):
249
252
250 if cmd in DAT_CMDS:
253 if cmd in DAT_CMDS:
251 return (255, DAT_CMDS[cmd])
254 return (255, DAT_CMDS[cmd])
252
255
253 def add_data(self, value):
256 def add_data(self, value):
254
257
255 return (254, value-1)
258 return (254, value-1)
256
259
257 def parms_to_binary(self):
260 def parms_to_binary(self):
258 '''
261 '''
259 Create "dat" stream to be send to CR
262 Create "dat" stream to be send to CR
260 '''
263 '''
261
264
262 data = []
265 data = []
263 # create header
266 # create header
264 data.append(self.add_cmd('DISABLE'))
267 data.append(self.add_cmd('DISABLE'))
265 data.append(self.add_cmd('CONTINUE'))
268 data.append(self.add_cmd('CONTINUE'))
266 data.append(self.add_cmd('RESTART'))
269 data.append(self.add_cmd('RESTART'))
267
270
268 if self.control_sw:
271 if self.control_sw:
269 data.append(self.add_cmd('SW_ONE'))
272 data.append(self.add_cmd('SW_ONE'))
270 else:
273 else:
271 data.append(self.add_cmd('SW_ZERO'))
274 data.append(self.add_cmd('SW_ZERO'))
272
275
273 if self.control_tx:
276 if self.control_tx:
274 data.append(self.add_cmd('TX_ONE'))
277 data.append(self.add_cmd('TX_ONE'))
275 else:
278 else:
276 data.append(self.add_cmd('TX_ZERO'))
279 data.append(self.add_cmd('TX_ZERO'))
277
280
278 # write divider
281 # write divider
279 data.append(self.add_cmd('CLOCK_DIVIDER'))
282 data.append(self.add_cmd('CLOCK_DIVIDER'))
280 data.append(self.add_data(self.clock_divider))
283 data.append(self.add_data(self.clock_divider))
281
284
282 # write delays
285 # write delays
283 data.append(self.add_cmd('DELAY_START'))
286 data.append(self.add_cmd('DELAY_START'))
284 # first delay is always zero
287 # first delay is always zero
285 data.append(self.add_data(1))
288 data.append(self.add_data(1))
286
289
287 delays = self.get_delays()
290 delays = self.get_delays()
288
291
289 for delay in delays:
292 for delay in delays:
290 while delay>252:
293 while delay>252:
291 data.append(self.add_data(253))
294 data.append(self.add_data(253))
292 delay -= 253
295 delay -= 253
293 data.append(self.add_data(delay))
296 data.append(self.add_data(delay))
294
297
295 # write flips
298 # write flips
296 data.append(self.add_cmd('FLIP_START'))
299 data.append(self.add_cmd('FLIP_START'))
297
300
298 states = self.get_pulses(binary=False)
301 states = self.get_pulses(binary=False)
299
302
300 for flips, delay in zip(states, delays):
303 for flips, delay in zip(states, delays):
301 flips.reverse()
304 flips.reverse()
302 flip = int(''.join([str(x) for x in flips]), 2)
305 flip = int(''.join([str(x) for x in flips]), 2)
303 data.append(self.add_data(flip+1))
306 data.append(self.add_data(flip+1))
304 while delay>252:
307 while delay>252:
305 data.append(self.add_data(1))
308 data.append(self.add_data(1))
306 delay -= 253
309 delay -= 253
307
310
308 # write sampling period
311 # write sampling period
309 data.append(self.add_cmd('SAMPLING_PERIOD'))
312 data.append(self.add_cmd('SAMPLING_PERIOD'))
310 wins = self.get_lines(line_type__name='windows')
313 wins = self.get_lines(line_type__name='windows')
311 if wins:
314 if wins:
312 win_params = json.loads(wins[0].params)['params']
315 win_params = json.loads(wins[0].params)['params']
313 if win_params:
316 if win_params:
314 dh = int(win_params[0]['resolution']*self.km2unit)
317 dh = int(win_params[0]['resolution']*self.km2unit)
315 else:
318 else:
316 dh = 1
319 dh = 1
317 else:
320 else:
318 dh = 1
321 dh = 1
319 data.append(self.add_data(dh))
322 data.append(self.add_data(dh))
320
323
321 # write enable
324 # write enable
322 data.append(self.add_cmd('ENABLE'))
325 data.append(self.add_cmd('ENABLE'))
323
326
324 return '\n'.join(['{}'.format(x) for tup in data for x in tup])
327 return '\n'.join(['{}'.format(x) for tup in data for x in tup])
325
328
326 def update_from_file(self, filename):
329 def update_from_file(self, filename):
327 '''
330 '''
328 Update instance from file
331 Update instance from file
329 '''
332 '''
330
333
331 f = RCFile(filename)
334 f = RCFile(filename)
332 self.dict_to_parms(f.data)
335 self.dict_to_parms(f.data)
336 self.update_pulses()
337 self.save()
333
338
334 def update_pulses(self):
339 def update_pulses(self):
335
340
336 for line in self.get_lines():
341 for line in self.get_lines():
337 if line.line_type.name=='tr':
338 continue
339 line.update_pulses()
342 line.update_pulses()
340
343
341 for tr in self.get_lines(line_type__name='tr'):
344 def plot_pulses(self):
342 tr.update_pulses()
345
346 import matplotlib.pyplot as plt
347 from bokeh.resources import CDN
348 from bokeh.embed import components
349 from bokeh.mpl import to_bokeh
350 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, PreviewSaveTool
351
352 lines = self.get_lines()
353
354 max_value = self.ipp*self.km2unit*self.ntx
355
356 N = len(lines)
357 fig = plt.figure(figsize=(10, 2+N*0.5))
358 ax = fig.add_subplot(111)
359 labels = []
360
361 for i, line in enumerate(lines):
362 labels.append(line.get_name())
363 l = ax.plot((0, max_value),(N-i-1, N-i-1))
364 points = [(tup[0], tup[1]-tup[0]) for tup in line.pulses_as_points() if tup<>(0,0)]
365 ax.broken_barh(points, (N-i-1, 0.5),
366 edgecolor=l[0].get_color(), facecolor='none')
367
368 labels.reverse()
369 ax.set_yticklabels(labels)
370 plot = to_bokeh(fig, use_pandas=False)
371 plot.tools = [PanTool(dimensions=['width']), WheelZoomTool(dimensions=['width']), ResetTool(), PreviewSaveTool()]
372
373 return components(plot, CDN)
343
374
344 def status_device(self):
375 def status_device(self):
345
376
346 return 0
377 return 0
347
378
348 def stop_device(self):
379 def stop_device(self):
349
380
350 answer = api.disable(ip = self.device.ip_address,
381 answer = api.disable(ip = self.device.ip_address,
351 port = self.device.port_address)
382 port = self.device.port_address)
352
383
353 if answer[0] != "1":
384 if answer[0] != "1":
354 self.message = answer[0:]
385 self.message = answer[0:]
355 return 0
386 return 0
356
387
357 self.message = answer[2:]
388 self.message = answer[2:]
358 return 1
389 return 1
359
390
360 def start_device(self):
391 def start_device(self):
361
392
362 answer = api.enable(ip = self.device.ip_address,
393 answer = api.enable(ip = self.device.ip_address,
363 port = self.device.port_address)
394 port = self.device.port_address)
364
395
365 if answer[0] != "1":
396 if answer[0] != "1":
366 self.message = answer[0:]
397 self.message = answer[0:]
367 return 0
398 return 0
368
399
369 self.message = answer[2:]
400 self.message = answer[2:]
370 return 1
401 return 1
371
402
372 def write_device(self):
403 def write_device(self):
373 answer = api.write_config(ip = self.device.ip_address,
404 answer = api.write_config(ip = self.device.ip_address,
374 port = self.device.port_address,
405 port = self.device.port_address,
375 parms = self.parms_to_dict())
406 parms = self.parms_to_dict())
376
407
377 if answer[0] != "1":
408 if answer[0] != "1":
378 self.message = answer[0:]
409 self.message = answer[0:]
379 return 0
410 return 0
380
411
381 self.message = answer[2:]
412 self.message = answer[2:]
382 return 1
413 return 1
383
414
384
415
385 class RCLineCode(models.Model):
416 class RCLineCode(models.Model):
386
417
387 name = models.CharField(max_length=40)
418 name = models.CharField(max_length=40)
388 bits_per_code = models.PositiveIntegerField(default=0)
419 bits_per_code = models.PositiveIntegerField(default=0)
389 number_of_codes = models.PositiveIntegerField(default=0)
420 number_of_codes = models.PositiveIntegerField(default=0)
390 codes = models.TextField(blank=True, null=True)
421 codes = models.TextField(blank=True, null=True)
391
422
392 class Meta:
423 class Meta:
393 db_table = 'rc_line_codes'
424 db_table = 'rc_line_codes'
394 ordering = ('name',)
425 ordering = ('name',)
395
426
396 def __unicode__(self):
427 def __unicode__(self):
397 return u'%s' % self.name
428 return u'%s' % self.name
398
429
399
430
400 class RCLineType(models.Model):
431 class RCLineType(models.Model):
401
432
402 name = models.CharField(choices=LINE_TYPES, max_length=40)
433 name = models.CharField(choices=LINE_TYPES, max_length=40)
403 description = models.TextField(blank=True, null=True)
434 description = models.TextField(blank=True, null=True)
404 params = models.TextField(default='[]')
435 params = models.TextField(default='[]')
405
436
406 class Meta:
437 class Meta:
407 db_table = 'rc_line_types'
438 db_table = 'rc_line_types'
408
439
409 def __unicode__(self):
440 def __unicode__(self):
410 return u'%s - %s' % (self.name.upper(), self.get_name_display())
441 return u'%s - %s' % (self.name.upper(), self.get_name_display())
411
442
412
443
413 class RCLine(models.Model):
444 class RCLine(models.Model):
414
445
415 rc_configuration = models.ForeignKey(RCConfiguration, on_delete=models.CASCADE)
446 rc_configuration = models.ForeignKey(RCConfiguration, on_delete=models.CASCADE)
416 line_type = models.ForeignKey(RCLineType)
447 line_type = models.ForeignKey(RCLineType)
417 channel = models.PositiveIntegerField(default=0)
448 channel = models.PositiveIntegerField(default=0)
418 position = models.PositiveIntegerField(default=0)
449 position = models.PositiveIntegerField(default=0)
419 params = models.TextField(default='{}')
450 params = models.TextField(default='{}')
420 pulses = models.TextField(default='')
451 pulses = models.TextField(default='')
421
452
422 class Meta:
453 class Meta:
423 db_table = 'rc_lines'
454 db_table = 'rc_lines'
424 ordering = ['channel']
455 ordering = ['channel']
425
456
426 def __unicode__(self):
457 def __unicode__(self):
427 if self.rc_configuration:
458 if self.rc_configuration:
428 return u'%s - %s' % (self.rc_configuration, self.get_name())
459 return u'%s - %s' % (self.rc_configuration, self.get_name())
429
460
430 def clone(self, **kwargs):
461 def clone(self, **kwargs):
431
462
432 self.pk = None
463 self.pk = None
433
464
434 for attr, value in kwargs.items():
465 for attr, value in kwargs.items():
435 setattr(self, attr, value)
466 setattr(self, attr, value)
436
467
437 self.save()
468 self.save()
438
469
439 return self
470 return self
440
471
441 def get_name(self):
472 def get_name(self):
442
473
443 chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
474 chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
475 s = ''
444
476
445 if self.line_type.name in ('tx',):
477 if self.line_type.name in ('tx',):
446 return '%s%s' % (self.line_type.name.upper(), chars[self.position])
478 s = chars[self.position]
447 elif self.line_type.name in ('codes', 'windows', 'tr'):
479 elif self.line_type.name in ('codes', 'windows', 'tr'):
448 if 'TX_ref' not in json.loads(self.params):
480 if 'TX_ref' in json.loads(self.params):
449 return self.line_type.name.upper()
450 pk = json.loads(self.params)['TX_ref']
481 pk = json.loads(self.params)['TX_ref']
451 if pk in (0, '0'):
482 if pk in (0, '0'):
452 refs = ','.join(chars[l.position] for l in self.rc_configuration.get_lines(line_type__name='tx'))
483 s = ','.join(chars[l.position] for l in self.rc_configuration.get_lines(line_type__name='tx'))
453 return '%s (%s)' % (self.line_type.name.upper(), refs)
454 else:
484 else:
455 ref = RCLine.objects.get(pk=pk)
485 ref = RCLine.objects.get(pk=pk)
456 return '%s (%s)' % (self.line_type.name.upper(), chars[ref.position])
486 s = chars[ref.position]
457 elif self.line_type.name in ('flip', 'prog_pulses', 'sync', 'none', 'mix'):
487
458 return '%s %s' % (self.line_type.name.upper(), self.channel)
488 if s:
489 return '{}({}) {}'.format(self.line_type.name.upper(), s, self.channel)
459 else:
490 else:
460 return self.line_type.name.upper()
491 return '{} {}'.format(self.line_type.name.upper(), self.channel)
461
492
462 def get_lines(self, **kwargs):
493 def get_lines(self, **kwargs):
463
494
464 return RCLine.objects.filter(rc_configuration=self.rc_configuration, **kwargs)
495 return RCLine.objects.filter(rc_configuration=self.rc_configuration, **kwargs)
465
496
466 def pulses_as_array(self):
497 def pulses_as_array(self):
467
498
468 return (np.fromstring(self.pulses, dtype=np.uint8)-48).astype(np.int8)
499 y = np.zeros(self.rc_configuration.ntx*self.rc_configuration.ipp*self.rc_configuration.km2unit)
469
470 def get_pulses(self):
471
500
472 X = self.pulses_as_array()
501 for tup in ast.literal_eval(self.pulses):
502 y[tup[0]:tup[1]] = 1
473
503
474 d = X[1:]-X[:-1]
504 return y.astype(np.int8)
475
476 up = np.where(d==1)[0]
477 if X[0]==1:
478 up = np.concatenate((np.array([-1]), up))
479 up += 1
480
505
481 dw = np.where(d==-1)[0]
506 def pulses_as_points(self):
482 if X[-1]==1:
483 dw = np.concatenate((dw, np.array([len(X)-1])))
484 dw += 1
485
507
486 return [(tup[0], tup[1]) for tup in zip(up, dw)]
508 return ast.literal_eval(self.pulses)
487
509
488 def get_win_ref(self, params, tx_id, km2unit):
510 def get_win_ref(self, params, tx_id, km2unit):
489
511
490 ref = self.rc_configuration.sampling_reference
512 ref = self.rc_configuration.sampling_reference
491 codes = [line for line in self.get_lines(line_type__name='codes') if int(json.loads(line.params)['TX_ref'])==int(tx_id)]
513 codes = [line for line in self.get_lines(line_type__name='codes') if int(json.loads(line.params)['TX_ref'])==int(tx_id)]
492
514
493 if codes:
515 if codes:
494 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit/len(json.loads(codes[0].params)['codes'][0])
516 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit/len(json.loads(codes[0].params)['codes'][0])
495 else:
517 else:
496 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit
518 tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit
497
519
498 if ref=='first_baud':
520 if ref=='first_baud':
499 return int(1 + (tx_width + 1)/2 + params['first_height']*km2unit - params['resolution']*km2unit)
521 return int(1 + (tx_width + 1)/2 + params['first_height']*km2unit - params['resolution']*km2unit)
500 elif ref=='sub_baud':
522 elif ref=='sub_baud':
501 return int(1 + params['first_height']*km2unit - params['resolution']*km2unit/2)
523 return int(1 + params['first_height']*km2unit - params['resolution']*km2unit/2)
502 else:
524 else:
503 return 0
525 return 0
504
526
505 def update_pulses(self, save=True, tr=False):
527 def update_pulses(self):
506 '''
528 '''
507 Update pulses field
529 Update pulses field
508 '''
530 '''
509
531
510 km2unit = self.rc_configuration.km2unit
532 km2unit = self.rc_configuration.km2unit
511 us2unit = self.rc_configuration.us2unit
533 us2unit = self.rc_configuration.us2unit
512 ipp = self.rc_configuration.ipp
534 ipp = self.rc_configuration.ipp
513 ntx = self.rc_configuration.ntx
535 ntx = self.rc_configuration.ntx
514 ipp_u = int(ipp*km2unit)
536 ipp_u = int(ipp*km2unit)
515
537
516 x = np.arange(0, ipp_u*ntx)
538 y = []
517
539
518 if self.line_type.name=='tr':
540 if self.line_type.name=='tr':
519 params = json.loads(self.params)
541 tr_params = json.loads(self.params)
520 if params['TX_ref'] in ('0', 0):
542
521 txs = [tx.update_pulses(save=False, tr=True) for tx in self.get_lines(line_type__name='tx')]
543 if tr_params['TX_ref'] in ('0', 0):
544 txs = self.get_lines(line_type__name='tx')
522 else:
545 else:
523 txs = [tx.update_pulses(save=False, tr=True) for tx in RCLine.objects.filter(pk=params['TX_ref'])]
546 txs = [RCLine.objects.filter(pk=tr_params['TX_ref'])]
524 if len(txs)==0 or 0 in [len(tx) for tx in txs]:
525 return
526
547
527 y = np.any(txs, axis=0, out=np.ones(ipp_u*ntx))
548 for tx in txs:
549 params = json.loads(tx.params)
550 if float(params['pulse_width'])==0:
551 continue
552 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
553 width = float(params['pulse_width'])*km2unit+int(self.rc_configuration.time_before*us2unit)
554 before = 0
555 after = int(self.rc_configuration.time_after*us2unit)
556
557 y_tx = self.points(ntx, ipp_u, width,
558 delay=delays,
559 before=before,
560 after=after,
561 sync=self.rc_configuration.sync)
528
562
529 ranges = params['range'].split(',')
563 ranges = params['range'].split(',')
564
530 if len(ranges)>0 and ranges[0]<>'0':
565 if len(ranges)>0 and ranges[0]<>'0':
531 mask = create_mask(ranges, ipp_u, ntx, self.rc_configuration.sync)
566 y_tx = self.mask_ranges(y_tx, ranges)
532 y = y.astype(np.int8) & mask
567
568 tr_ranges = tr_params['range'].split(',')
569
570 if len(tr_ranges)>0 and tr_ranges[0]<>'0':
571 y_tx = self.mask_ranges(y_tx, tr_ranges)
572
573 y.extend(y_tx)
533
574
534 elif self.line_type.name=='tx':
575 elif self.line_type.name=='tx':
535 params = json.loads(self.params)
576 params = json.loads(self.params)
536 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
577 delays = [float(d)*km2unit for d in params['delays'].split(',') if d]
537 y = pulses(x, ipp_u, float(params['pulse_width'])*km2unit,
578 width = float(params['pulse_width'])*km2unit
579
580 if width>0:
581 before = int(self.rc_configuration.time_before*us2unit)
582 after = 0
583
584 y = self.points(ntx, ipp_u, width,
538 delay=delays,
585 delay=delays,
539 before=int(self.rc_configuration.time_before*us2unit),
586 before=before,
540 after=int(self.rc_configuration.time_after*us2unit) if tr else 0,
587 after=after,
541 sync=self.rc_configuration.sync)
588 sync=self.rc_configuration.sync)
542
589
543 ranges = params['range'].split(',')
590 ranges = params['range'].split(',')
544
591
545 if len(ranges)>0 and ranges[0]<>'0':
592 if len(ranges)>0 and ranges[0]<>'0':
546 mask = create_mask(ranges, ipp_u, ntx, self.rc_configuration.sync)
593 y = self.mask_ranges(y, ranges)
547 y = y & mask
548
594
549 elif self.line_type.name=='flip':
595 elif self.line_type.name=='flip':
550 width = float(json.loads(self.params)['number_of_flips'])*ipp*km2unit
596 n = float(json.loads(self.params)['number_of_flips'])
551 y = pulses(x, 2*width, width)
597 width = n*ipp*km2unit
598 y = self.points(int((ntx+1)/(2*n)), ipp_u*n*2, width)
552
599
553 elif self.line_type.name=='codes':
600 elif self.line_type.name=='codes':
554 params = json.loads(self.params)
601 params = json.loads(self.params)
555 tx = RCLine.objects.get(pk=params['TX_ref'])
602 tx = RCLine.objects.get(pk=params['TX_ref'])
556 tx_params = json.loads(tx.params)
603 tx_params = json.loads(tx.params)
557 delays = [float(d)*km2unit for d in tx_params['delays'].split(',') if d]
604 delays = [float(d)*km2unit for d in tx_params['delays'].split(',') if d]
558 y = pulses_from_code(tx.pulses_as_array(),
605 f = int(float(tx_params['pulse_width'])*km2unit)/len(params['codes'][0])
559 params['codes'],
606 codes = [(np.fromstring(''.join([s*f for s in code]), dtype=np.uint8)-48).astype(np.int8) for code in params['codes']]
560 int(float(tx_params['pulse_width'])*km2unit))
607 codes = [self.array_to_points(code) for code in codes]
608 n = len(codes)
609
610 for i, tup in enumerate(tx.pulses_as_points()):
611 code = codes[i%n]
612 y.extend([(c[0]+tup[0], c[1]+tup[0]) for c in code])
561
613
562 ranges = tx_params['range'].split(',')
614 ranges = tx_params['range'].split(',')
563 if len(ranges)>0 and ranges[0]<>'0':
615 if len(ranges)>0 and ranges[0]<>'0':
564 mask = create_mask(ranges, ipp_u, ntx, self.rc_configuration.sync)
616 y = self.mask_ranges(y, ranges)
565 y = y.astype(np.int8) & mask
566
617
567 elif self.line_type.name=='sync':
618 elif self.line_type.name=='sync':
568 params = json.loads(self.params)
619 params = json.loads(self.params)
569 y = np.zeros(ipp_u*ntx)
620 n = ipp_u*ntx
570 if params['invert'] in ('1', 1):
621 if params['invert'] in ('1', 1):
571 y[-1] = 1
622 y = [(n-1, n)]
572 else:
623 else:
573 y[0] = 1
624 y = [(0, 1)]
574
625
575 elif self.line_type.name=='prog_pulses':
626 elif self.line_type.name=='prog_pulses':
576 params = json.loads(self.params)
627 params = json.loads(self.params)
577 if int(params['periodic'])==0:
628 if int(params['periodic'])==0:
578 nntx = ntx
579 else:
580 nntx = 1
629 nntx = 1
630 nipp = ipp_u*ntx
631 else:
632 nntx = ntx
633 nipp = ipp_u
581
634
582 if 'params' in params and len(params['params'])>0:
635 if 'params' in params and len(params['params'])>0:
583 y = sum([pulses(x, ipp_u*nntx, (pp['end']-pp['begin']), shift=pp['begin']) for pp in params['params']])
636 for p in params['params']:
584 else:
637 y_pp = self.points(nntx, nipp,
585 y = np.zeros(ipp_u*ntx)
638 p['end']-p['begin'],
639 before=p['begin'])
640
641 y.extend(y_pp)
586
642
587 elif self.line_type.name=='windows':
643 elif self.line_type.name=='windows':
588 params = json.loads(self.params)
644 params = json.loads(self.params)
589
645
590 if 'params' in params and len(params['params'])>0:
646 if 'params' in params and len(params['params'])>0:
591 y = sum([pulses(x, ipp_u, pp['resolution']*pp['number_of_samples']*km2unit,
647 tr_params = json.loads(self.get_lines(line_type__name='tr')[0].params)
592 shift=0,
648 tr_ranges = tr_params['range'].split(',')
593 before=int(self.rc_configuration.time_before*us2unit)+self.get_win_ref(pp, params['TX_ref'],km2unit),
649 for p in params['params']:
594 sync=self.rc_configuration.sync) for pp in params['params']])
650 y_win = self.points(ntx, ipp_u,
595 tr = self.get_lines(line_type__name='tr')[0]
651 p['resolution']*p['number_of_samples']*km2unit,
596 ranges = json.loads(tr.params)['range'].split(',')
652 before=int(self.rc_configuration.time_before*us2unit)+self.get_win_ref(p, params['TX_ref'], km2unit),
597 if len(ranges)>0 and ranges[0]<>'0':
653 sync=self.rc_configuration.sync)
598 mask = create_mask(ranges, ipp_u, ntx, self.rc_configuration.sync)
654
599 y = y & mask
655 if len(tr_ranges)>0 and tr_ranges[0]<>'0':
600 else:
656 y_win = self.mask_ranges(y_win, tr_ranges)
601 y = np.zeros(ipp_u*ntx)
657
658 y.extend(y_win)
602
659
603 elif self.line_type.name=='mix':
660 elif self.line_type.name=='mix':
604 values = self.rc_configuration.parameters.split('-')
661 values = self.rc_configuration.parameters.split('-')
605 confs = RCConfiguration.objects.filter(pk__in=[value.split('|')[0] for value in values])
662 confs = RCConfiguration.objects.filter(pk__in=[value.split('|')[0] for value in values])
606 modes = [value.split('|')[1] for value in values]
663 modes = [value.split('|')[1] for value in values]
607 delays = [value.split('|')[2] for value in values]
664 delays = [value.split('|')[2] for value in values]
608 masks = [value.split('|')[3] for value in values]
665 masks = [value.split('|')[3] for value in values]
609
666
610 y = confs[0].get_lines(channel=self.channel)[0].pulses_as_array()
667 y = confs[0].get_lines(channel=self.channel)[0].pulses_as_array()
611
668 ysize = len(y)
612 for i in range(1, len(values)):
669 for i in range(1, len(values)):
613 mask = list('{:8b}'.format(int(masks[i])))
670 mask = list('{:8b}'.format(int(masks[i])))
614 mask.reverse()
671 mask.reverse()
615
672
616 if mask[self.channel] in ('0', '', ' '):
673 if mask[self.channel] in ('0', '', ' '):
617 continue
674 continue
618 Y = confs[i].get_lines(channel=self.channel)[0].pulses_as_array()
675 Y = confs[i].get_lines(channel=self.channel)[0].pulses_as_array()
619 delay = float(delays[i])*km2unit
676 delay = float(delays[i])*km2unit
620 if delay>0:
677 if delay>0:
621 y_temp = np.empty_like(Y)
678 y_temp = np.empty_like(Y)
622 y_temp[:delay] = 0
679 y_temp[:delay] = 0
623 y_temp[delay:] = Y[:-delay]
680 y_temp[delay:] = Y[:-delay]
624
681 y_tempsize = len(y_temp)
625 if modes[i]=='OR':
682 if modes[i]=='OR':
626 y2 = y | y_temp
683 y = y | y_temp
627 elif modes[i]=='XOR':
684 elif modes[i]=='XOR':
628 y2 = y ^ y_temp
685 y = y ^ y_temp
629 elif modes[i]=='AND':
686 elif modes[i]=='AND':
630 y2 = y & y_temp
687 y = y & y_temp
631 elif modes[i]=='NAND':
688 elif modes[i]=='NAND':
632 y2 = y & ~y_temp
689 y = y & ~y_temp
633
690
634 y = y2
691 y = self.array_to_points(y)
635
692
636 else:
693 else:
637 y = np.zeros(ipp_u*ntx)
694 y = []
638
695
639 if save:
696 self.pulses = y
640 self.pulses = (y+48).astype(np.uint8).tostring()
641 self.save()
697 self.save()
698
699 @staticmethod
700 def array_to_points(X):
701
702 d = X[1:]-X[:-1]
703
704 up = np.where(d==1)[0]
705 if X[0]==1:
706 up = np.concatenate((np.array([-1]), up))
707 up += 1
708
709 dw = np.where(d==-1)[0]
710 if X[-1]==1:
711 dw = np.concatenate((dw, np.array([len(X)-1])))
712 dw += 1
713
714 return [(tup[0], tup[1]) for tup in zip(up, dw)]
715
716 @staticmethod
717 def mask_ranges(Y, ranges):
718
719 y = [(0, 0) for __ in Y]
720
721 for index in ranges:
722 if '-' in index:
723 args = [int(a) for a in index.split('-')]
724 y[args[0]-1:args[1]] = Y[args[0]-1:args[1]]
642 else:
725 else:
726 y[int(index-1)] = Y[int(index-1)]
727
643 return y
728 return y
644
729
730 @staticmethod
731 def points(ntx, ipp, width, delay=[0], before=0, after=0, sync=0):
732
733 delays = len(delay)
734
735 Y = [(ipp*x+before+delay[x%delays], ipp*x+width+before+delay[x%delays]+after) for x in range(ntx)]
645
736
737 return Y No newline at end of file
@@ -1,20 +1,20
1 from django.conf.urls import url
1 from django.conf.urls import url
2
2
3 urlpatterns = (
3 urlpatterns = (
4 url(r'^(?P<conf_id>-?\d+)/$', 'apps.rc.views.conf', name='url_rc_conf'),
4 url(r'^(?P<conf_id>-?\d+)/$', 'apps.rc.views.conf', name='url_rc_conf'),
5 url(r'^(?P<conf_id>-?\d+)/import/$', 'apps.rc.views.import_file', name='url_import_rc_conf'),
5 url(r'^(?P<conf_id>-?\d+)/import/$', 'apps.rc.views.import_file', name='url_import_rc_conf'),
6 url(r'^(?P<conf_id>-?\d+)/edit/$', 'apps.rc.views.conf_edit', name='url_edit_rc_conf'),
6 url(r'^(?P<conf_id>-?\d+)/edit/$', 'apps.rc.views.conf_edit', name='url_edit_rc_conf'),
7 url(r'^(?P<conf_id>-?\d+)/plot/$', 'apps.rc.views.view_pulses', name='url_plot_rc_pulses'),
7 url(r'^(?P<conf_id>-?\d+)/plot/$', 'apps.rc.views.plot_pulses', name='url_plot_rc_pulses'),
8 url(r'^(?P<id_conf>-?\d+)/write/$', 'apps.main.views.dev_conf_write', name='url_write_rc_conf'),
8 url(r'^(?P<id_conf>-?\d+)/write/$', 'apps.main.views.dev_conf_write', name='url_write_rc_conf'),
9 url(r'^(?P<id_conf>-?\d+)/read/$', 'apps.main.views.dev_conf_read', name='url_read_rc_conf'),
9 url(r'^(?P<id_conf>-?\d+)/read/$', 'apps.main.views.dev_conf_read', name='url_read_rc_conf'),
10
10
11 url(r'^(?P<conf_id>-?\d+)/add_line/$', 'apps.rc.views.add_line', name='url_add_rc_line'),
11 url(r'^(?P<conf_id>-?\d+)/add_line/$', 'apps.rc.views.add_line', name='url_add_rc_line'),
12 url(r'^(?P<conf_id>-?\d+)/add_line/(?P<line_type_id>-?\d+)/$', 'apps.rc.views.add_line', name='url_add_rc_line'),
12 url(r'^(?P<conf_id>-?\d+)/add_line/(?P<line_type_id>-?\d+)/$', 'apps.rc.views.add_line', name='url_add_rc_line'),
13 url(r'^(?P<conf_id>-?\d+)/add_line/(?P<line_type_id>-?\d+)/code/(?P<code_id>-?\d+)/$', 'apps.rc.views.add_line', name='url_add_rc_line_code'),
13 url(r'^(?P<conf_id>-?\d+)/add_line/(?P<line_type_id>-?\d+)/code/(?P<code_id>-?\d+)/$', 'apps.rc.views.add_line', name='url_add_rc_line_code'),
14 url(r'^(?P<conf_id>-?\d+)/update_position/$', 'apps.rc.views.update_lines_position', name='url_update_rc_lines_position'),
14 url(r'^(?P<conf_id>-?\d+)/update_position/$', 'apps.rc.views.update_lines_position', name='url_update_rc_lines_position'),
15 url(r'^(?P<conf_id>-?\d+)/line/(?P<line_id>-?\d+)/delete/$', 'apps.rc.views.remove_line', name='url_remove_rc_line'),
15 url(r'^(?P<conf_id>-?\d+)/line/(?P<line_id>-?\d+)/delete/$', 'apps.rc.views.remove_line', name='url_remove_rc_line'),
16 url(r'^(?P<conf_id>-?\d+)/line/(?P<line_id>-?\d+)/add_subline/$', 'apps.rc.views.add_subline', name='url_add_rc_subline'),
16 url(r'^(?P<conf_id>-?\d+)/line/(?P<line_id>-?\d+)/add_subline/$', 'apps.rc.views.add_subline', name='url_add_rc_subline'),
17 url(r'^(?P<conf_id>-?\d+)/line/(?P<line_id>-?\d+)/codes/$', 'apps.rc.views.edit_codes', name='url_edit_rc_codes'),
17 url(r'^(?P<conf_id>-?\d+)/line/(?P<line_id>-?\d+)/codes/$', 'apps.rc.views.edit_codes', name='url_edit_rc_codes'),
18 url(r'^(?P<conf_id>-?\d+)/line/(?P<line_id>-?\d+)/codes/(?P<code_id>-?\d+)/$', 'apps.rc.views.edit_codes', name='url_edit_rc_codes'),
18 url(r'^(?P<conf_id>-?\d+)/line/(?P<line_id>-?\d+)/codes/(?P<code_id>-?\d+)/$', 'apps.rc.views.edit_codes', name='url_edit_rc_codes'),
19 url(r'^(?P<conf_id>-?\d+)/line/(?P<line_id>-?\d+)/subline/(?P<subline_id>-?\d+)/delete/$', 'apps.rc.views.remove_subline', name='url_remove_rc_subline'),
19 url(r'^(?P<conf_id>-?\d+)/line/(?P<line_id>-?\d+)/subline/(?P<subline_id>-?\d+)/delete/$', 'apps.rc.views.remove_subline', name='url_remove_rc_subline'),
20 )
20 )
@@ -1,315 +1,206
1
1
2 import json
2 import json
3 import numpy as np
4 import matplotlib.pyplot as plt
5
6
3
7 class RCFile(object):
4 class RCFile(object):
8 '''
5 '''
9 Class to handle Radar controller configuration files
6 Class to handle Radar controller configuration files
10 '''
7 '''
11
8
12 def __init__(self, f=None):
9 def __init__(self, f=None):
13
10
14 self.data = {}
11 self.data = {}
15 if isinstance(f, str):
12 if isinstance(f, str):
16 self.f = open(f)
13 self.f = open(f)
17 self.name = f.split('/')[-1]
14 self.name = f.split('/')[-1]
18 elif hasattr(f, 'read'):
15 elif hasattr(f, 'read'):
19 self.f = f
16 self.f = f
20 self.name = f.name.split('/')[-1]
17 self.name = f.name.split('/')[-1]
21 else:
18 else:
22 self.f = f
19 self.f = f
23 self.name = None
20 self.name = None
24
21
25 if self.f:
22 if self.f:
26 if 'racp' in self.name:
23 if 'racp' in self.name:
27 self.parse_racp()
24 self.parse_racp()
28 elif 'dat' in self.name:
25 elif 'dat' in self.name:
29 self.parse_dat()
26 self.parse_dat()
30 elif 'json' in self.name:
27 elif 'json' in self.name:
31 self.data = json.load(self.f)
28 self.data = json.load(self.f)
32
29
33 self.f.close()
30 self.f.close()
34
31
35 def get_line_parameters(self, data, line):
32 def get_line_parameters(self, data, line):
36
33
37 line_params = {}
34 line_params = {}
38 for label in data:
35 for label in data:
39 if 'L%d' % line in label or '(Line %d)' % line in label or 'Line%d' % line in label:
36 if 'L%d' % line in label or '(Line %d)' % line in label or 'Line%d' % line in label:
40 line_params[label] = data[label]
37 line_params[label] = data[label]
41 return line_params
38 return line_params
42
39
43 def parse_racp(self):
40 def parse_racp(self):
44
41
45 data = {}
42 data = {}
46 raw_data = [s.strip() for s in self.f.readlines()]
43 raw_data = [s.strip() for s in self.f.readlines()]
47
44
48 for line in raw_data:
45 for line in raw_data:
49 if line and '=' in line:
46 if line and '=' in line:
50 label, value = line.strip().split('=')
47 label, value = line.strip().split('=')
51 data[label] = value
48 data[label] = value
52
49
53 self.data['experiment_type'] = data['EXPERIMENT TYPE']
50 self.data['experiment_type'] = data['EXPERIMENT TYPE']
54 self.data['header_version'] = data['HEADER VERSION']
51 self.data['header_version'] = data['HEADER VERSION']
55 self.data['name'] = data['EXPERIMENT NAME']
52 self.data['name'] = data['EXPERIMENT NAME']
56 self.data['ipp'] = float(data['IPP'])
53 self.data['ipp'] = float(data['IPP'])
57 self.data['ntx'] = int(data['NTX'])
54 self.data['ntx'] = int(data['NTX'])
58
55
59 if 'CLOCK DIVIDER' in data:
56 if 'CLOCK DIVIDER' in data:
60 self.data['clock_divider'] = int(data['CLOCK DIVIDER'])
57 self.data['clock_divider'] = int(data['CLOCK DIVIDER'])
61 else:
58 else:
62 self.data['clock_divider'] = 1
59 self.data['clock_divider'] = 1
63 self.data['clock_in'] = float(data['RELOJ'])*self.data['clock_divider']
60 self.data['clock_in'] = float(data['RELOJ'])*self.data['clock_divider']
64 self.data['clock'] = float(data['RELOJ'])
61 self.data['clock'] = float(data['RELOJ'])
65 self.data['time_before'] = int(data['TR_BEFORE'])
62 self.data['time_before'] = int(data['TR_BEFORE'])
66 self.data['time_after'] = int(data['TR_AFTER'])
63 self.data['time_after'] = int(data['TR_AFTER'])
67
64
68 if 'SYNCHRO DELAY' in data:
65 if 'SYNCHRO DELAY' in data:
69 self.data['sync'] = int(data['SYNCHRO DELAY'])
66 self.data['sync'] = int(data['SYNCHRO DELAY'])
70 else:
67 else:
71 self.data['sync'] = 0
68 self.data['sync'] = 0
72 self.data['lines'] = []
69 self.data['lines'] = []
73
70
74 if 'SAMPLING REFERENCE' in data:
71 if 'SAMPLING REFERENCE' in data:
75 if data['SAMPLING REFERENCE']=='MIDDLE OF FIRST BAUD':
72 if data['SAMPLING REFERENCE']=='MIDDLE OF FIRST BAUD':
76 self.data['sampling_reference'] = 'first_baud'
73 self.data['sampling_reference'] = 'first_baud'
77 elif data['SAMPLING REFERENCE']=='MIDDLE OF FIRST SUB-BAUD':
74 elif data['SAMPLING REFERENCE']=='MIDDLE OF FIRST SUB-BAUD':
78 self.data['sampling_reference'] = 'sub_baud'
75 self.data['sampling_reference'] = 'sub_baud'
79 else:
76 else:
80 self.data['sampling_reference'] = 'none'
77 self.data['sampling_reference'] = 'none'
81
78
82 #Add TR line
79 #Add TR line
83 if 'Pulse selection_TR' in data:
80 if 'Pulse selection_TR' in data:
84 if 'A,' in data['Pulse selection_TR']:
81 if 'A,' in data['Pulse selection_TR']:
85 rng = data['Pulse selection_TR'].replace('A,', '')
82 rng = data['Pulse selection_TR'].replace('A,', '')
86 ref = 'TXA'
83 ref = 'TXA'
87 elif 'A' in data['Pulse selection_TR']:
84 elif 'A' in data['Pulse selection_TR']:
88 rng = data['Pulse selection_TR'].replace('A', '')
85 rng = data['Pulse selection_TR'].replace('A', '')
89 ref = 'TXA'
86 ref = 'TXA'
90 elif 'B,' in data['Pulse selection_TR']:
87 elif 'B,' in data['Pulse selection_TR']:
91 rng = data['Pulse selection_TR'].replace('B,', '')
88 rng = data['Pulse selection_TR'].replace('B,', '')
92 ref = 'TXB'
89 ref = 'TXB'
93 elif 'B' in data['Pulse selection_TR']:
90 elif 'B' in data['Pulse selection_TR']:
94 rng = data['Pulse selection_TR'].replace('B', '')
91 rng = data['Pulse selection_TR'].replace('B', '')
95 ref = 'TXB'
92 ref = 'TXB'
96 else:
93 else:
97 rng = data['Pulse selection_TR']
94 rng = data['Pulse selection_TR']
98 ref = '0'
95 ref = '0'
99 line = {'type':'tr', 'range': rng if rng else '0', 'TX_ref':ref}
96 line = {'type':'tr', 'range': rng if rng else '0', 'TX_ref':ref}
100 else:
97 else:
101 line = {'type': 'tr', 'range': '0', 'TX_ref': '0'}
98 line = {'type': 'tr', 'range': '0', 'TX_ref': '0'}
102
99
103 self.data['lines'].append(line)
100 self.data['lines'].append(line)
104
101
105 #Add TX's lines
102 #Add TX's lines
106 if 'TXA' in data:
103 if 'TXA' in data:
107 line = {'type':'tx', 'pulse_width':data['TXA'], 'delays':'0'}
104 line = {'type':'tx', 'pulse_width':data['TXA'], 'delays':'0'}
108 if 'Pulse selection_TXA' in data:
105 if 'Pulse selection_TXA' in data:
109 line['range'] = data['Pulse selection_TXA']
106 line['range'] = data['Pulse selection_TXA']
110 else:
107 else:
111 line['range'] = '0'
108 line['range'] = '0'
112 self.data['lines'].append(line)
109 self.data['lines'].append(line)
113 else:
110 else:
114 self.data['lines'].append({'type':'tx', 'pulse_width':'0', 'delays':'0', 'range':'0'})
111 self.data['lines'].append({'type':'tx', 'pulse_width':'0', 'delays':'0', 'range':'0'})
115
112
116 if 'TXB' in data:
113 if 'TXB' in data:
117 line = {'type':'tx', 'pulse_width':data['TXB'], 'delays':'0'}
114 line = {'type':'tx', 'pulse_width':data['TXB'], 'delays':'0'}
118 if 'Pulse selection_TXB' in data:
115 if 'Pulse selection_TXB' in data:
119 line['range'] = data['Pulse selection_TXB']
116 line['range'] = data['Pulse selection_TXB']
120 else:
117 else:
121 line['range'] = '0'
118 line['range'] = '0'
122
119
123 if 'Number of Taus' in data:
120 if 'Number of Taus' in data:
124 delays = [data['TAU({0})'.format(i)] for i in range(int(data['Number of Taus']))]
121 delays = [data['TAU({0})'.format(i)] for i in range(int(data['Number of Taus']))]
125 line['delays'] = ','.join(delays)
122 line['delays'] = ','.join(delays)
126
123
127 self.data['lines'].append(line)
124 self.data['lines'].append(line)
128 else:
125 else:
129 self.data['lines'].append({'type':'tx', 'pulse_width':'0', 'delays':'0', 'range':'0'})
126 self.data['lines'].append({'type':'tx', 'pulse_width':'0', 'delays':'0', 'range':'0'})
130
127
131 #Add Other lines (4-6)
128 #Add Other lines (4-6)
132 for n in range(4, 7):
129 for n in range(4, 7):
133 params = self.get_line_parameters(data, n)
130 params = self.get_line_parameters(data, n)
134 labels = params.keys()
131 labels = params.keys()
135
132
136 if 'L%d_FLIP' % n in labels:
133 if 'L%d_FLIP' % n in labels:
137 line = {'type':'flip', 'number_of_flips':data['L%d_FLIP' % n]}
134 line = {'type':'flip', 'number_of_flips':data['L%d_FLIP' % n]}
138 elif 'Code Type' in data and n==4:
135 elif 'Code Type' in data and n==4:
139 line = {'type':'codes', 'code':data['Code Type'], 'TX_ref':data['L%d_REFERENCE' % n]}
136 line = {'type':'codes', 'code':data['Code Type'], 'TX_ref':data['L%d_REFERENCE' % n]}
140 if 'Number of Codes' in data:
137 if 'Number of Codes' in data:
141 line['codes'] = [data['COD({})'.format(x)] for x in range(int(data['Number of Codes']))]
138 line['codes'] = [data['COD({})'.format(x)] for x in range(int(data['Number of Codes']))]
142 elif 'Code Type (Line %d)' % n in labels:
139 elif 'Code Type (Line %d)' % n in labels:
143 line = {'type':'codes', 'code':data['Code Type (Line %d)' % n], 'TX_ref':data['L%d_REFERENCE' % n]}
140 line = {'type':'codes', 'code':data['Code Type (Line %d)' % n], 'TX_ref':data['L%d_REFERENCE' % n]}
144 if 'Number of Codes (Line %d)' % n in data:
141 if 'Number of Codes (Line %d)' % n in data:
145 line['codes'] = [data['L{}_COD({})'.format(n, x)] for x in range(int(data['Number of Codes (Line %d)' % n]))]
142 line['codes'] = [data['L{}_COD({})'.format(n, x)] for x in range(int(data['Number of Codes (Line %d)' % n]))]
146 elif 'Sampling Windows (Line %d)' % n in data:
143 elif 'Sampling Windows (Line %d)' % n in data:
147 line = {'type':'windows', 'TX_ref':data['L%d_REFERENCE' % n]}
144 line = {'type':'windows', 'TX_ref':data['L%d_REFERENCE' % n]}
148 windows = []
145 windows = []
149 for w in range(int(data['Sampling Windows (Line %d)' % n])):
146 for w in range(int(data['Sampling Windows (Line %d)' % n])):
150 windows.append({'first_height':float(data['L%d_H0(%d)' % (n, w)]),
147 windows.append({'first_height':float(data['L%d_H0(%d)' % (n, w)]),
151 'number_of_samples':int(data['L%d_NSA(%d)' % (n, w)]),
148 'number_of_samples':int(data['L%d_NSA(%d)' % (n, w)]),
152 'resolution':float(data['L%d_DH(%d)' % (n, w)])}
149 'resolution':float(data['L%d_DH(%d)' % (n, w)])}
153 )
150 )
154 line['params'] = windows
151 line['params'] = windows
155 elif 'Line%d' % n in labels and data['Line%d' % n]=='Synchro':
152 elif 'Line%d' % n in labels and data['Line%d' % n]=='Synchro':
156 line = {'type':'sync', 'invert':0}
153 line = {'type':'sync', 'invert':0}
157 elif 'L%d Number Of Portions' % n in labels:
154 elif 'L%d Number Of Portions' % n in labels:
158 line = {'type':'prog_pulses'}
155 line = {'type':'prog_pulses'}
159 if 'L%s Portions IPP Periodic' % n in data:
156 if 'L%s Portions IPP Periodic' % n in data:
160 line['periodic'] = 1 if data['L%s Portions IPP Periodic' % n]=='YES' else 0
157 line['periodic'] = 1 if data['L%s Portions IPP Periodic' % n]=='YES' else 0
161 portions = []
158 portions = []
162 x = raw_data.index('L%d Number Of Portions=%s' % (n, data['L%d Number Of Portions' % n]))
159 x = raw_data.index('L%d Number Of Portions=%s' % (n, data['L%d Number Of Portions' % n]))
163 for w in range(int(data['L%d Number Of Portions' % n])):
160 for w in range(int(data['L%d Number Of Portions' % n])):
164 begin = raw_data[x+1+2*w].split('=')[-1]
161 begin = raw_data[x+1+2*w].split('=')[-1]
165 end = raw_data[x+2+2*w].split('=')[-1]
162 end = raw_data[x+2+2*w].split('=')[-1]
166 portions.append({'begin':int(begin),
163 portions.append({'begin':int(begin),
167 'end':int(end)}
164 'end':int(end)}
168 )
165 )
169 line['params'] = portions
166 line['params'] = portions
170 elif 'FLIP1' in data and n==5:
167 elif 'FLIP1' in data and n==5:
171 line = {'type':'flip', 'number_of_flips':data['FLIP1']}
168 line = {'type':'flip', 'number_of_flips':data['FLIP1']}
172 elif 'FLIP2' in data and n==6:
169 elif 'FLIP2' in data and n==6:
173 line = {'type':'flip', 'number_of_flips':data['FLIP2']}
170 line = {'type':'flip', 'number_of_flips':data['FLIP2']}
174 else:
171 else:
175 line = {'type':'none'}
172 line = {'type':'none'}
176
173
177 self.data['lines'].append(line)
174 self.data['lines'].append(line)
178
175
179 #Add line 7 (windows)
176 #Add line 7 (windows)
180 if 'Sampling Windows' in data:
177 if 'Sampling Windows' in data:
181 line = {'type':'windows', 'TX_ref':data['L7_REFERENCE']}
178 line = {'type':'windows', 'TX_ref':data['L7_REFERENCE']}
182 windows = []
179 windows = []
183 x = raw_data.index('Sampling Windows=%s' % data['Sampling Windows'])
180 x = raw_data.index('Sampling Windows=%s' % data['Sampling Windows'])
184 for w in range(int(data['Sampling Windows'])):
181 for w in range(int(data['Sampling Windows'])):
185 h0 = raw_data[x+1+3*w].split('=')[-1]
182 h0 = raw_data[x+1+3*w].split('=')[-1]
186 nsa = raw_data[x+2+3*w].split('=')[-1]
183 nsa = raw_data[x+2+3*w].split('=')[-1]
187 dh = raw_data[x+3+3*w].split('=')[-1]
184 dh = raw_data[x+3+3*w].split('=')[-1]
188 windows.append({'first_height':float(h0),
185 windows.append({'first_height':float(h0),
189 'number_of_samples':int(nsa),
186 'number_of_samples':int(nsa),
190 'resolution':float(dh)}
187 'resolution':float(dh)}
191 )
188 )
192 line['params'] = windows
189 line['params'] = windows
193 self.data['lines'].append(line)
190 self.data['lines'].append(line)
194 else:
191 else:
195 self.data['lines'].append({'type':'none'})
192 self.data['lines'].append({'type':'none'})
196
193
197 #Add line 8 (synchro inverted)
194 #Add line 8 (synchro inverted)
198 self.data['lines'].append({'type':'sync', 'invert':1})
195 self.data['lines'].append({'type':'sync', 'invert':1})
199
196
200 return
197 return
201
198
202 def parse_dat(self):
199 def parse_dat(self):
203 pass
200 pass
204
201
205
202
206 def get_json(self, indent=None):
203 def get_json(self, indent=None):
207 return json.dumps(self.data, indent=indent)
204 return json.dumps(self.data, indent=indent)
208
205
209
206
210 def pulses_to_points(X):
211
212
213 d = X[1:]-X[:-1]
214
215 up = np.where(d==1)[0]
216 if X[0]==1:
217 up = np.concatenate((np.array([-1]), up))
218 up += 1
219
220 dw = np.where(d==-1)[0]
221 if X[-1]==1:
222 dw = np.concatenate((dw, np.array([len(X)-1])))
223 dw += 1
224
225 return [(tup[0], tup[1]-tup[0]) for tup in zip(up, dw)]
226
227 def pulses_from_code(X, codes, width):
228
229 d = X[1:]-X[:-1]
230
231 up = np.where(d==1)[0]
232 if X[0]==1:
233 up = np.concatenate((np.array([-1]), up))
234 up += 1
235
236 f = width/len(codes[0])
237 codes = [(np.fromstring(''.join([s*f for s in code]), dtype=np.uint8)-48).astype(np.int8) for code in codes]
238
239 y = np.zeros(len(X))
240
241 j=0
242 n = len(codes)
243 for i in up:
244 y[i:i+width] = codes[j%n]
245 j += 1
246
247 return y
248
249
250 def create_mask(ranges, ipp, ntx, sync):
251
252 x = np.arange(ipp*ntx)
253 iranges = set()
254
255 for index in ranges:
256 if '-' in index:
257 args = [int(a) for a in index.split('-')]
258 iranges = iranges.union([i for i in range(args[0], args[1]+1)])
259 else:
260 iranges.add(int(index))
261
262 y = np.any([(x>=(idx-1)*ipp+sync) & (x<idx*ipp+sync) for idx in iranges], axis=0).astype(np.int8)
263
264 return y
265
266
267 def pulses(X, period, width, delay=0, before=0, after=0, sync=0, shift=0):
268
269 delay_array = delay
270
271 if isinstance(delay, (list, tuple)):
272 delay_array = np.ones(len(X))
273 delays = [d for __ in xrange(len(X)/(period*len(delay))) for d in delay]
274 for i, delay in enumerate(delays):
275 delay_array[np.arange(period*i, period*(i+1))] *= delay
276
277 if after>0:
278 width += after+before
279 before = 0
280
281 Y = ((X%period<width+delay_array+before+sync) & (X%period>=delay_array+before+sync)).astype(np.int8)
282
283 if shift>0:
284 y = np.empty_like(Y)
285 y[:shift] = 0
286 y[shift:] = Y[:-shift]
287 return y
288 else:
289 return Y
290
291
292 def plot_pulses(unit, maximun, lines):
293
294 from bokeh.resources import CDN
295 from bokeh.embed import components
296 from bokeh.mpl import to_bokeh
297 from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, PreviewSaveTool
298
299 N = len(lines)
300 fig = plt.figure(figsize=(10, 2+N*0.5))
301 ax = fig.add_subplot(111)
302 labels = []
303
304 for i, line in enumerate(lines):
305 labels.append(line.get_name())
306 l = ax.plot((0, maximun),(N-i-1, N-i-1))
307 ax.broken_barh(pulses_to_points(line.pulses_as_array()), (N-i-1, 0.5),
308 edgecolor=l[0].get_color(), facecolor='none')
309
310 labels.reverse()
311 ax.set_yticklabels(labels)
312 plot = to_bokeh(fig, use_pandas=False)
313 plot.tools = [PanTool(dimensions=['width']), WheelZoomTool(dimensions=['width']), ResetTool(), PreviewSaveTool()]
314
315 return components(plot, CDN)
@@ -1,385 +1,370
1
1
2 import json
2 import json
3
3
4 from django.contrib import messages
4 from django.contrib import messages
5 from django.utils.safestring import mark_safe
5 from django.utils.safestring import mark_safe
6 from django.shortcuts import render, redirect, get_object_or_404, HttpResponse
6 from django.shortcuts import render, redirect, get_object_or_404, HttpResponse
7
7
8 from apps.main.models import Configuration, Experiment, Device
8 from apps.main.models import Configuration, Experiment, Device
9 from apps.main.views import sidebar
9 from apps.main.views import sidebar
10
10
11 from .models import RCConfiguration, RCLine, RCLineType, RCLineCode
11 from .models import RCConfiguration, RCLine, RCLineType, RCLineCode
12 from .forms import RCConfigurationForm, RCLineForm, RCLineViewForm, RCLineEditForm, RCImportForm, RCLineCodesForm
12 from .forms import RCConfigurationForm, RCLineForm, RCLineViewForm, RCLineEditForm, RCImportForm, RCLineCodesForm
13 from .utils import plot_pulses
14
13
15
14
16 def conf(request, conf_id):
15 def conf(request, conf_id):
17
16
18 conf = get_object_or_404(RCConfiguration, pk=conf_id)
17 conf = get_object_or_404(RCConfiguration, pk=conf_id)
19
18
20 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
19 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
21
20
22 for line in lines:
21 for line in lines:
23 params = json.loads(line.params)
22 params = json.loads(line.params)
24 line.form = RCLineViewForm(extra_fields=params, line=line)
23 line.form = RCLineViewForm(extra_fields=params, line=line)
25 if 'params' in params:
24 if 'params' in params:
26 line.subforms = [RCLineViewForm(extra_fields=fields, line=line, subform=True) for fields in params['params']]
25 line.subforms = [RCLineViewForm(extra_fields=fields, line=line, subform=True) for fields in params['params']]
27
26
28 kwargs = {}
27 kwargs = {}
29 kwargs['dev_conf'] = conf
28 kwargs['dev_conf'] = conf
30 kwargs['rc_lines'] = lines
29 kwargs['rc_lines'] = lines
31 kwargs['dev_conf_keys'] = ['name', 'ipp', 'ntx', 'clock_in', 'clock_divider', 'clock',
30 kwargs['dev_conf_keys'] = ['name', 'ipp', 'ntx', 'clock_in', 'clock_divider', 'clock',
32 'time_before', 'time_after', 'sync', 'sampling_reference', 'control_tx', 'control_sw']
31 'time_before', 'time_after', 'sync', 'sampling_reference', 'control_tx', 'control_sw']
33
32
34 kwargs['title'] = 'RC Configuration'
33 kwargs['title'] = 'RC Configuration'
35 kwargs['suptitle'] = 'Details'
34 kwargs['suptitle'] = 'Details'
36
35
37 kwargs['button'] = 'Edit Configuration'
36 kwargs['button'] = 'Edit Configuration'
38 ###### SIDEBAR ######
37 ###### SIDEBAR ######
39 kwargs.update(sidebar(conf=conf))
38 kwargs.update(sidebar(conf=conf))
40
39
41 return render(request, 'rc_conf.html', kwargs)
40 return render(request, 'rc_conf.html', kwargs)
42
41
43
42
44 def conf_edit(request, conf_id):
43 def conf_edit(request, conf_id):
45
44
46 conf = get_object_or_404(RCConfiguration, pk=conf_id)
45 conf = get_object_or_404(RCConfiguration, pk=conf_id)
47
46
48 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
47 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
49
48
50 for line in lines:
49 for line in lines:
51 params = json.loads(line.params)
50 params = json.loads(line.params)
52 line.form = RCLineEditForm(conf=conf, line=line, extra_fields=params)
51 line.form = RCLineEditForm(conf=conf, line=line, extra_fields=params)
53 line.subform = False
52 line.subform = False
54
53
55 if 'params' in params:
54 if 'params' in params:
56 line.subforms = [RCLineEditForm(extra_fields=fields, line=line, subform=i) for i, fields in enumerate(params['params'])]
55 line.subforms = [RCLineEditForm(extra_fields=fields, line=line, subform=i) for i, fields in enumerate(params['params'])]
57 line.subform = True
56 line.subform = True
58
57
59 if request.method=='GET':
58 if request.method=='GET':
60
59
61 form = RCConfigurationForm(instance=conf)
60 form = RCConfigurationForm(instance=conf)
62
61
63 elif request.method=='POST':
62 elif request.method=='POST':
64
63
65 line_data = {}
64 line_data = {}
66 conf_data = {}
65 conf_data = {}
67 extras = []
66 extras = []
68
67
69 #classified post fields
68 #classified post fields
70 for label,value in request.POST.items():
69 for label,value in request.POST.items():
71 if label=='csrfmiddlewaretoken':
70 if label=='csrfmiddlewaretoken':
72 continue
71 continue
73
72
74 if label.count('|')==0:
73 if label.count('|')==0:
75 conf_data[label] = value
74 conf_data[label] = value
76 continue
75 continue
77
76
78 elif label.split('|')[0]<>'-1':
77 elif label.split('|')[0]<>'-1':
79 extras.append(label)
78 extras.append(label)
80 continue
79 continue
81
80
82 x, pk, name = label.split('|')
81 x, pk, name = label.split('|')
83
82
84 if name=='codes':
83 if name=='codes':
85 value = [s for s in value.split('\r\n') if s]
84 value = [s for s in value.split('\r\n') if s]
86
85
87 if pk in line_data:
86 if pk in line_data:
88 line_data[pk][name] = value
87 line_data[pk][name] = value
89 else:
88 else:
90 line_data[pk] = {name:value}
89 line_data[pk] = {name:value}
91
90
92 #update conf
91 #update conf
93 form = RCConfigurationForm(conf_data, instance=conf)
92 form = RCConfigurationForm(conf_data, instance=conf)
94
93
95 if form.is_valid():
94 if form.is_valid():
96
95
97 form.save()
96 form.save()
98
97
99 #update lines fields
98 #update lines fields
100 extras.sort()
99 extras.sort()
101 for label in extras:
100 for label in extras:
102 x, pk, name = label.split('|')
101 x, pk, name = label.split('|')
103 if pk not in line_data:
102 if pk not in line_data:
104 line_data[pk] = {}
103 line_data[pk] = {}
105 if 'params' not in line_data[pk]:
104 if 'params' not in line_data[pk]:
106 line_data[pk]['params'] = []
105 line_data[pk]['params'] = []
107 if len(line_data[pk]['params'])<int(x)+1:
106 if len(line_data[pk]['params'])<int(x)+1:
108 line_data[pk]['params'].append({})
107 line_data[pk]['params'].append({})
109 line_data[pk]['params'][int(x)][name] = float(request.POST[label])
108 line_data[pk]['params'][int(x)][name] = float(request.POST[label])
110
109
111 for pk, params in line_data.items():
110 for pk, params in line_data.items():
112 line = RCLine.objects.get(pk=pk)
111 line = RCLine.objects.get(pk=pk)
113 if line.line_type.name in ('windows', 'prog_pulses'):
112 if line.line_type.name in ('windows', 'prog_pulses'):
114 if 'params' not in params:
113 if 'params' not in params:
115 params['params'] = []
114 params['params'] = []
116 line.params = json.dumps(params)
115 line.params = json.dumps(params)
117 line.save()
116 line.save()
118
117
119 #update pulses field
118 #update pulses field
120 conf.update_pulses()
119 conf.update_pulses()
121
120
122 messages.success(request, 'RC Configuration successfully updated')
121 messages.success(request, 'RC Configuration successfully updated')
123
122
124 return redirect(conf.get_absolute_url())
123 return redirect(conf.get_absolute_url())
125
124
126 kwargs = {}
125 kwargs = {}
127 kwargs['dev_conf'] = conf
126 kwargs['dev_conf'] = conf
128 kwargs['form'] = form
127 kwargs['form'] = form
129 kwargs['rc_lines'] = lines
128 kwargs['rc_lines'] = lines
130 kwargs['edit'] = True
129 kwargs['edit'] = True
131
130
132 kwargs['title'] = 'RC Configuration'
131 kwargs['title'] = 'RC Configuration'
133 kwargs['suptitle'] = 'Edit'
132 kwargs['suptitle'] = 'Edit'
134 kwargs['button'] = 'Update'
133 kwargs['button'] = 'Update'
135 kwargs['previous'] = conf.get_absolute_url()
134 kwargs['previous'] = conf.get_absolute_url()
136
135
137 return render(request, 'rc_conf_edit.html', kwargs)
136 return render(request, 'rc_conf_edit.html', kwargs)
138
137
139
138
140 def add_line(request, conf_id, line_type_id=None, code_id=None):
139 def add_line(request, conf_id, line_type_id=None, code_id=None):
141
140
142 conf = get_object_or_404(RCConfiguration, pk=conf_id)
141 conf = get_object_or_404(RCConfiguration, pk=conf_id)
143
142
144 if request.method=='GET':
143 if request.method=='GET':
145 if line_type_id:
144 if line_type_id:
146 line_type = get_object_or_404(RCLineType, pk=line_type_id)
145 line_type = get_object_or_404(RCLineType, pk=line_type_id)
147
146
148 if code_id:
147 if code_id:
149 form = RCLineForm(initial={'rc_configuration':conf_id, 'line_type': line_type_id, 'code_id': code_id},
148 form = RCLineForm(initial={'rc_configuration':conf_id, 'line_type': line_type_id, 'code_id': code_id},
150 extra_fields=json.loads(line_type.params))
149 extra_fields=json.loads(line_type.params))
151 else:
150 else:
152 form = RCLineForm(initial={'rc_configuration':conf_id, 'line_type': line_type_id},
151 form = RCLineForm(initial={'rc_configuration':conf_id, 'line_type': line_type_id},
153 extra_fields=json.loads(line_type.params))
152 extra_fields=json.loads(line_type.params))
154 else:
153 else:
155 line_type = {'id':0}
154 line_type = {'id':0}
156 form = RCLineForm(initial={'rc_configuration':conf_id})
155 form = RCLineForm(initial={'rc_configuration':conf_id})
157
156
158 if request.method=='POST':
157 if request.method=='POST':
159
158
160 line_type = get_object_or_404(RCLineType, pk=line_type_id)
159 line_type = get_object_or_404(RCLineType, pk=line_type_id)
161 form = RCLineForm(request.POST,
160 form = RCLineForm(request.POST,
162 extra_fields=json.loads(line_type.params))
161 extra_fields=json.loads(line_type.params))
163
162
164 if form.is_valid():
163 if form.is_valid():
165 form.save()
164 form.save()
166 form.instance.update_pulses()
165 form.instance.update_pulses()
167 return redirect('url_edit_rc_conf', conf.id)
166 return redirect('url_edit_rc_conf', conf.id)
168
167
169 kwargs = {}
168 kwargs = {}
170 kwargs['form'] = form
169 kwargs['form'] = form
171 kwargs['title'] = 'RC Configuration'
170 kwargs['title'] = 'RC Configuration'
172 kwargs['suptitle'] = 'Add Line'
171 kwargs['suptitle'] = 'Add Line'
173 kwargs['button'] = 'Add'
172 kwargs['button'] = 'Add'
174 kwargs['previous'] = conf.get_absolute_url_edit()
173 kwargs['previous'] = conf.get_absolute_url_edit()
175 kwargs['dev_conf'] = conf
174 kwargs['dev_conf'] = conf
176 kwargs['line_type'] = line_type
175 kwargs['line_type'] = line_type
177
176
178 return render(request, 'rc_add_line.html', kwargs)
177 return render(request, 'rc_add_line.html', kwargs)
179
178
180 def edit_codes(request, conf_id, line_id, code_id=None):
179 def edit_codes(request, conf_id, line_id, code_id=None):
181
180
182 conf = get_object_or_404(RCConfiguration, pk=conf_id)
181 conf = get_object_or_404(RCConfiguration, pk=conf_id)
183 line = get_object_or_404(RCLine, pk=line_id)
182 line = get_object_or_404(RCLine, pk=line_id)
184 params = json.loads(line.params)
183 params = json.loads(line.params)
185
184
186 if request.method=='GET':
185 if request.method=='GET':
187 if code_id:
186 if code_id:
188 code = get_object_or_404(RCLineCode, pk=code_id)
187 code = get_object_or_404(RCLineCode, pk=code_id)
189 form = RCLineCodesForm(instance=code)
188 form = RCLineCodesForm(instance=code)
190 else:
189 else:
191 initial = {'code': params['code'],
190 initial = {'code': params['code'],
192 'codes': params['codes'] if 'codes' in params else [],
191 'codes': params['codes'] if 'codes' in params else [],
193 'number_of_codes': len(params['codes']) if 'codes' in params else 0,
192 'number_of_codes': len(params['codes']) if 'codes' in params else 0,
194 'bits_per_code': len(params['codes'][0]) if 'codes' in params else 0,
193 'bits_per_code': len(params['codes'][0]) if 'codes' in params else 0,
195 }
194 }
196 form = RCLineCodesForm(initial=initial)
195 form = RCLineCodesForm(initial=initial)
197
196
198 if request.method=='POST':
197 if request.method=='POST':
199 form = RCLineCodesForm(request.POST)
198 form = RCLineCodesForm(request.POST)
200 if form.is_valid():
199 if form.is_valid():
201 params['code'] = request.POST['code']
200 params['code'] = request.POST['code']
202 params['codes'] = [s for s in request.POST['codes'].split('\r\n') if s]
201 params['codes'] = [s for s in request.POST['codes'].split('\r\n') if s]
203 line.params = json.dumps(params)
202 line.params = json.dumps(params)
204 line.save()
203 line.save()
205 messages.success(request, 'Line: "%s" has been updated.' % line)
204 messages.success(request, 'Line: "%s" has been updated.' % line)
206 return redirect('url_edit_rc_conf', conf.id)
205 return redirect('url_edit_rc_conf', conf.id)
207
206
208 kwargs = {}
207 kwargs = {}
209 kwargs['form'] = form
208 kwargs['form'] = form
210 kwargs['title'] = line
209 kwargs['title'] = line
211 kwargs['suptitle'] = 'Edit'
210 kwargs['suptitle'] = 'Edit'
212 kwargs['button'] = 'Update'
211 kwargs['button'] = 'Update'
213 kwargs['dev_conf'] = conf
212 kwargs['dev_conf'] = conf
214 kwargs['previous'] = conf.get_absolute_url_edit()
213 kwargs['previous'] = conf.get_absolute_url_edit()
215 kwargs['line'] = line
214 kwargs['line'] = line
216
215
217 return render(request, 'rc_edit_codes.html', kwargs)
216 return render(request, 'rc_edit_codes.html', kwargs)
218
217
219 def add_subline(request, conf_id, line_id):
218 def add_subline(request, conf_id, line_id):
220
219
221 conf = get_object_or_404(RCConfiguration, pk=conf_id)
220 conf = get_object_or_404(RCConfiguration, pk=conf_id)
222 line = get_object_or_404(RCLine, pk=line_id)
221 line = get_object_or_404(RCLine, pk=line_id)
223
222
224 if request.method == 'POST':
223 if request.method == 'POST':
225 if line:
224 if line:
226 params = json.loads(line.params)
225 params = json.loads(line.params)
227 subparams = json.loads(line.line_type.params)
226 subparams = json.loads(line.line_type.params)
228 if 'params' in subparams:
227 if 'params' in subparams:
229 dum = {}
228 dum = {}
230 for key, value in subparams['params'].items():
229 for key, value in subparams['params'].items():
231 dum[key] = value['value']
230 dum[key] = value['value']
232 params['params'].append(dum)
231 params['params'].append(dum)
233 line.params = json.dumps(params)
232 line.params = json.dumps(params)
234 line.save()
233 line.save()
235 return redirect('url_edit_rc_conf', conf.id)
234 return redirect('url_edit_rc_conf', conf.id)
236
235
237 kwargs = {}
236 kwargs = {}
238
237
239 kwargs['title'] = 'Add new'
238 kwargs['title'] = 'Add new'
240 kwargs['suptitle'] = '%s to %s' % (line.line_type.name, line)
239 kwargs['suptitle'] = '%s to %s' % (line.line_type.name, line)
241
240
242 return render(request, 'confirm.html', kwargs)
241 return render(request, 'confirm.html', kwargs)
243
242
244 def remove_line(request, conf_id, line_id):
243 def remove_line(request, conf_id, line_id):
245
244
246 conf = get_object_or_404(RCConfiguration, pk=conf_id)
245 conf = get_object_or_404(RCConfiguration, pk=conf_id)
247 line = get_object_or_404(RCLine, pk=line_id)
246 line = get_object_or_404(RCLine, pk=line_id)
248
247
249 if request.method == 'POST':
248 if request.method == 'POST':
250 if line:
249 if line:
251 try:
250 try:
252 channel = line.channel
251 channel = line.channel
253 line.delete()
252 line.delete()
254 for ch in range(channel+1, RCLine.objects.filter(rc_configuration=conf).count()+1):
253 for ch in range(channel+1, RCLine.objects.filter(rc_configuration=conf).count()+1):
255 l = RCLine.objects.get(rc_configuration=conf, channel=ch)
254 l = RCLine.objects.get(rc_configuration=conf, channel=ch)
256 l.channel = l.channel-1
255 l.channel = l.channel-1
257 l.save()
256 l.save()
258 messages.success(request, 'Line: "%s" has been deleted.' % line)
257 messages.success(request, 'Line: "%s" has been deleted.' % line)
259 except:
258 except:
260 messages.error(request, 'Unable to delete line: "%s".' % line)
259 messages.error(request, 'Unable to delete line: "%s".' % line)
261
260
262 return redirect('url_edit_rc_conf', conf.id)
261 return redirect('url_edit_rc_conf', conf.id)
263
262
264 kwargs = {}
263 kwargs = {}
265
264
266 kwargs['object'] = line
265 kwargs['object'] = line
267 kwargs['delete_view'] = True
266 kwargs['delete_view'] = True
268 kwargs['title'] = 'Confirm delete'
267 kwargs['title'] = 'Confirm delete'
269 kwargs['previous'] = conf.get_absolute_url_edit()
268 kwargs['previous'] = conf.get_absolute_url_edit()
270 return render(request, 'confirm.html', kwargs)
269 return render(request, 'confirm.html', kwargs)
271
270
272
271
273 def remove_subline(request, conf_id, line_id, subline_id):
272 def remove_subline(request, conf_id, line_id, subline_id):
274
273
275 conf = get_object_or_404(RCConfiguration, pk=conf_id)
274 conf = get_object_or_404(RCConfiguration, pk=conf_id)
276 line = get_object_or_404(RCLine, pk=line_id)
275 line = get_object_or_404(RCLine, pk=line_id)
277
276
278 if request.method == 'POST':
277 if request.method == 'POST':
279 if line:
278 if line:
280 params = json.loads(line.params)
279 params = json.loads(line.params)
281 params['params'].remove(params['params'][int(subline_id)-1])
280 params['params'].remove(params['params'][int(subline_id)-1])
282 line.params = json.dumps(params)
281 line.params = json.dumps(params)
283 line.save()
282 line.save()
284
283
285 return redirect('url_edit_rc_conf', conf.id)
284 return redirect('url_edit_rc_conf', conf.id)
286
285
287 kwargs = {}
286 kwargs = {}
288
287
289 kwargs['object'] = line
288 kwargs['object'] = line
290 kwargs['object_name'] = line.line_type.name
289 kwargs['object_name'] = line.line_type.name
291 kwargs['delete_view'] = True
290 kwargs['delete_view'] = True
292 kwargs['title'] = 'Confirm delete'
291 kwargs['title'] = 'Confirm delete'
293
292
294 return render(request, 'confirm.html', kwargs)
293 return render(request, 'confirm.html', kwargs)
295
294
296
295
297 def update_lines_position(request, conf_id):
296 def update_lines_position(request, conf_id):
298
297
299 conf = get_object_or_404(RCConfiguration, pk=conf_id)
298 conf = get_object_or_404(RCConfiguration, pk=conf_id)
300
299
301 if request.method=='POST':
300 if request.method=='POST':
302 ch = 0
301 ch = 0
303 for item in request.POST['items'].split('&'):
302 for item in request.POST['items'].split('&'):
304 line = RCLine.objects.get(pk=item.split('=')[-1])
303 line = RCLine.objects.get(pk=item.split('=')[-1])
305 line.channel = ch
304 line.channel = ch
306 line.save()
305 line.save()
307 ch += 1
306 ch += 1
308
307
309 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
308 lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel')
310
309
311 for line in lines:
310 for line in lines:
312 params = json.loads(line.params)
311 params = json.loads(line.params)
313 line.form = RCLineEditForm(conf=conf, line=line, extra_fields=params)
312 line.form = RCLineEditForm(conf=conf, line=line, extra_fields=params)
314
313
315 if 'params' in params:
314 if 'params' in params:
316 line.subform = True
315 line.subform = True
317 line.subforms = [RCLineEditForm(extra_fields=fields, line=line, subform=i) for i, fields in enumerate(params['params'])]
316 line.subforms = [RCLineEditForm(extra_fields=fields, line=line, subform=i) for i, fields in enumerate(params['params'])]
318
317
319 html = render(request, 'rc_lines.html', {'dev_conf':conf, 'rc_lines':lines, 'edit':True})
318 html = render(request, 'rc_lines.html', {'dev_conf':conf, 'rc_lines':lines, 'edit':True})
320 data = {'html': html.content}
319 data = {'html': html.content}
321
320
322 return HttpResponse(json.dumps(data), content_type="application/json")
321 return HttpResponse(json.dumps(data), content_type="application/json")
323 return redirect('url_edit_rc_conf', conf.id)
322 return redirect('url_edit_rc_conf', conf.id)
324
323
325
324
326 def import_file(request, conf_id):
325 def import_file(request, conf_id):
327
326
328 conf = get_object_or_404(RCConfiguration, pk=conf_id)
327 conf = get_object_or_404(RCConfiguration, pk=conf_id)
329 if request.method=='POST':
328 if request.method=='POST':
330 form = RCImportForm(request.POST, request.FILES)
329 form = RCImportForm(request.POST, request.FILES)
331 if form.is_valid():
330 if form.is_valid():
332 #try:
331 try:
333 if True:
334
335 conf.update_from_file(request.FILES['file_name'])
332 conf.update_from_file(request.FILES['file_name'])
336 conf.save()
337
338 for line in conf.get_lines():
339 if line.line_type.name=='tr':
340 continue
341 line.update_pulses()
342
343 for tr in conf.get_lines('tr'):
344 tr.update_pulses()
345
346 messages.success(request, 'Configuration "%s" loaded succesfully' % request.FILES['file_name'])
333 messages.success(request, 'Configuration "%s" loaded succesfully' % request.FILES['file_name'])
347 return redirect(conf.get_absolute_url())
334 return redirect(conf.get_absolute_url_edit())
348
335
349 #except Exception as e:
336 except Exception as e:
350 # messages.error(request, 'Error parsing file: "%s" - %s' % (request.FILES['file_name'], e))
337 messages.error(request, 'Error parsing file: "%s" - %s' % (request.FILES['file_name'], e))
351
338
352 else:
339 else:
353 messages.warning(request, 'Your current configuration will be replaced')
340 messages.warning(request, 'Your current configuration will be replaced')
354 form = RCImportForm()
341 form = RCImportForm()
355
342
356 kwargs = {}
343 kwargs = {}
357 kwargs['form'] = form
344 kwargs['form'] = form
358 kwargs['title'] = 'RC Configuration'
345 kwargs['title'] = 'RC Configuration'
359 kwargs['suptitle'] = 'Import file'
346 kwargs['suptitle'] = 'Import file'
360 kwargs['button'] = 'Upload'
347 kwargs['button'] = 'Upload'
361 kwargs['previous'] = conf.get_absolute_url()
348 kwargs['previous'] = conf.get_absolute_url()
362
349
363 return render(request, 'rc_import.html', kwargs)
350 return render(request, 'rc_import.html', kwargs)
364
351
365
352
366 def view_pulses(request, conf_id):
353 def plot_pulses(request, conf_id):
367
354
368 conf = get_object_or_404(RCConfiguration, pk=conf_id)
355 conf = get_object_or_404(RCConfiguration, pk=conf_id)
369 lines = RCLine.objects.filter(rc_configuration=conf)
370
371 unit = (conf.clock/conf.clock_divider)*3./20
372
356
373 N = conf.ipp*conf.km2unit*conf.ntx
357 script, div = conf.plot_pulses()
374
375 script, div = plot_pulses(unit, N, lines)
376
358
377 kwargs = {}
359 kwargs = {}
378
360
379 kwargs['title'] = 'RC Pulses'
361 kwargs['title'] = 'RC Pulses'
380 kwargs['suptitle'] = conf.name
362 kwargs['suptitle'] = conf.name
381 kwargs['div'] = mark_safe(div)
363 kwargs['div'] = mark_safe(div)
382 kwargs['script'] = mark_safe(script)
364 kwargs['script'] = mark_safe(script)
383
365
366 if 'json' in request.GET:
367 return HttpResponse(json.dumps({'div':mark_safe(div), 'script':mark_safe(script)}), content_type="application/json")
368 else:
384 return render(request, 'rc_pulses.html', kwargs)
369 return render(request, 'rc_pulses.html', kwargs)
385
370
General Comments 0
You need to be logged in to leave comments. Login now