diff --git a/apps/main/fixtures/main_initial_data.json b/apps/main/fixtures/main_initial_data.json new file mode 100644 index 0000000..64cc4be --- /dev/null +++ b/apps/main/fixtures/main_initial_data.json @@ -0,0 +1,9 @@ +[ +{"fields": {"name": "JRO", "description": ""}, "model": "main.location", "pk": 1}, +{"fields": {"name": "JASMET", "description": ""}, "model": "main.location", "pk": 2}, +{"fields": {"name": "SOUSY", "description": ""}, "model": "main.location", "pk": 3}, +{"fields": {"name": "rc", "description": ""}, "model": "main.devicetype", "pk": 1}, +{"fields": {"name": "dds", "description": ""}, "model": "main.devicetype", "pk": 2}, +{"fields": {"name": "cgs", "description": ""}, "model": "main.devicetype", "pk": 3}, +{"fields": {"name": "jars", "description": ""}, "model": "main.devicetype", "pk": 4} +] diff --git a/apps/main/forms.py b/apps/main/forms.py index 84e388f..afda942 100644 --- a/apps/main/forms.py +++ b/apps/main/forms.py @@ -14,7 +14,8 @@ DDS_FILE_FORMAT = ( RC_FILE_FORMAT = ( ('json', 'json'), - ('text', 'rc') + ('text', 'racp'), + ('binary', 'dat'), ) def add_empty_choice(choices, pos=0, label='-----'): diff --git a/apps/main/models.py b/apps/main/models.py index de79a0e..a06b565 100644 --- a/apps/main/models.py +++ b/apps/main/models.py @@ -176,9 +176,15 @@ class Configuration(PolymorphicModel): db_table = 'db_configurations' def __unicode__(self): - return u'[%s, %s]: %s' % (self.experiment.name, - self.device.name, - self.name) + + if self.experiment: + return u'[%s, %s]: %s' % (self.experiment.name, + self.device.name, + self.name) + else: + return u'%s' % self.device.name + + def parms_to_dict(self): @@ -228,7 +234,7 @@ class Configuration(PolymorphicModel): if not content_type: content_type = 'application/json' filename = '%s_%s.json' %(self.device.device_type.name, self.name) - content = json.dumps(self.parms_to_dict()) + content = json.dumps(self.parms_to_dict(), indent=2) fields = {'content_type':content_type, 'filename':filename, diff --git a/apps/main/templates/base.html b/apps/main/templates/base.html index 73f6681..1ccdf7e 100644 --- a/apps/main/templates/base.html +++ b/apps/main/templates/base.html @@ -18,6 +18,7 @@ + {% block extra-head %} {% endblock %} @@ -134,7 +135,7 @@ {% endblock %} {# bootstrap_javascript jquery=True #} - + {% block extra-js %} {% endblock%} diff --git a/apps/main/templates/dev_conf.html b/apps/main/templates/dev_conf.html index efb9b15..c48328d 100644 --- a/apps/main/templates/dev_conf.html +++ b/apps/main/templates/dev_conf.html @@ -10,12 +10,15 @@ {% block content %} +{% block menu-actions %} - + - +{% endblock %} + @@ -41,6 +45,9 @@ {% endfor %}
Status
+{% block extra-content %} +{% endblock %} + {% endblock %} {% block sidebar%} diff --git a/apps/main/templates/dev_conf_edit.html b/apps/main/templates/dev_conf_edit.html index 92c73e7..79f1283 100644 --- a/apps/main/templates/dev_conf_edit.html +++ b/apps/main/templates/dev_conf_edit.html @@ -20,6 +20,11 @@ {% bootstrap_form form layout='horizontal' size='medium' %}

+ {% if extra_button %} +
+ +
+ {% endif %}
@@ -32,4 +37,10 @@ {% endblock %} {% block extra-js%} + {% endblock %} \ No newline at end of file diff --git a/apps/main/templates/experiment.html.bkp b/apps/main/templates/experiment.html.bkp deleted file mode 100644 index d22a246..0000000 --- a/apps/main/templates/experiment.html.bkp +++ /dev/null @@ -1,167 +0,0 @@ -{% extends "base.html" %} -{% load bootstrap3 %} -{% load static %} -{% load main_tags %} -{% block extra-head %} - -{% endblock %} - -{% block exp-active %}active{% endblock %} - -{% block content-title %}Experiment{% endblock %} -{% block content-suptitle %}{{suptitle}}{% endblock %} - -{% block content %} -{% if form_new %} -
- {% csrf_token %} - {% bootstrap_form form_new layout='horizontal' size='medium' %} -
-
- -
-{% elif experiment %} - -{% for key in experiment_keys %} - -{% endfor %} -
{{key|title}}{{experiment|attr:key}}
-
- -
-
- -
-
-
- {% csrf_token %} - {% bootstrap_form form layout='horizontal' size='medium' %} -
-
- -
-
-
-
-
- -
-
-
- {% csrf_token %} - {% bootstrap_form subform layout='horizontal' size='medium' %} -
-
- - - - {% for header in keys %} - - {% endfor%} - - {% for item in items %} - - - {% for key in keys %} - - {% endfor %} - - - {% endfor %} -
#{{ header|title }}
{{ forloop.counter }}{{ item|attr:key }} - - -
-
-
-
-
-
-
- -
-
- - - - {% for header in device_keys %} - - {% endfor%} - - {% for item in devices %} - - - {% for key in device_keys %} - - {% endfor %} - - {% endfor %} -
#{{ header|title }}
{{ forloop.counter }}{{ item|attr:key }}
-
-
-
-
-{% else %} - - - - {% for header in keys %} - - {% endfor%} - - {% for item in items %} - - - {% for key in keys %} - - {% endfor %} - - {% endfor %} -
#{{ header|title }}
{{ forloop.counter }}{{ item|attr:key }}
- -{% endif %} - -{% endblock %} - -{% block sidebar%} - {% include "sidebar_devices.html" %} -{% endblock %} - -{% block extra-js%} - - - - -{% endblock %} \ No newline at end of file diff --git a/apps/main/templates/sidebar_devices.html b/apps/main/templates/sidebar_devices.html index ec9b4ce..9975d95 100644 --- a/apps/main/templates/sidebar_devices.html +++ b/apps/main/templates/sidebar_devices.html @@ -61,14 +61,17 @@ {% endif %} {% if dev_conf %} -
-
-

Campaign

-
- -
+ + {% if campaign %} +
+
+

Campaign

+
+ +
+ {% endif %} {% if experiments %}
diff --git a/apps/main/templatetags/main_tags.py b/apps/main/templatetags/main_tags.py index 59a1c88..43f5d6d 100644 --- a/apps/main/templatetags/main_tags.py +++ b/apps/main/templatetags/main_tags.py @@ -1,4 +1,5 @@ from django.template.defaulttags import register +from django.utils.safestring import mark_safe @register.filter def attr(instance, key): @@ -32,4 +33,5 @@ def get_verbose_field_name(instance, field_name): """ Returns verbose_name for a field. """ - return instance._meta.get_field(field_name).verbose_name.title() \ No newline at end of file + + return mark_safe(instance._meta.get_field(field_name).verbose_name) \ No newline at end of file diff --git a/apps/main/urls.py b/apps/main/urls.py index 7944d25..0b7db55 100644 --- a/apps/main/urls.py +++ b/apps/main/urls.py @@ -26,6 +26,7 @@ urlpatterns = ( url(r'^experiment/(?P-?\d+)/delete/$', 'apps.main.views.experiment_delete', name='url_delete_experiment'), url(r'^experiment/(?P-?\d+)/new_dev_conf/$', 'apps.main.views.dev_conf_new', name='url_add_dev_conf'), + url(r'^experiment/(?P-?\d+)/new_dev_conf/(?P-?\d+)/$', 'apps.main.views.dev_conf_new', name='url_add_dev_conf'), url(r'^dev_conf/$', 'apps.main.views.dev_confs', name='url_dev_confs'), url(r'^dev_conf/(?P-?\d+)/$', 'apps.main.views.dev_conf', name='url_dev_conf'), url(r'^dev_conf/(?P-?\d+)/edit/$', 'apps.main.views.dev_conf_edit', name='url_edit_dev_conf'), diff --git a/apps/main/views.py b/apps/main/views.py index cf2e0b7..e0478e2 100644 --- a/apps/main/views.py +++ b/apps/main/views.py @@ -391,7 +391,7 @@ def experiment(request, id_exp): return render(request, 'experiment.html', kwargs) -def experiment_new(request, id_camp=0): +def experiment_new(request, id_camp=None): if request.method == 'GET': form = ExperimentForm(initial={'campaign':id_camp}) @@ -473,42 +473,42 @@ def dev_conf(request, id_conf): conf = get_object_or_404(Configuration, pk=id_conf) - DevConfModel = CONF_MODELS[conf.device.device_type.name] - dev_conf = DevConfModel.objects.get(pk=id_conf) - - kwargs = {} - kwargs['dev_conf'] = dev_conf - kwargs['dev_conf_keys'] = ['name', 'experiment', 'device'] + return redirect(conf.get_absolute_url()) - kwargs['title'] = 'Configuration' - kwargs['suptitle'] = 'Details' + +def dev_conf_new(request, id_exp=0, id_dev=0): - kwargs['button'] = 'Edit Configuration' + initial = {} - ###### SIDEBAR ###### - kwargs.update(sidebar(conf)) + if id_exp==0: + initial['experiment'] = id_exp - return render(request, 'dev_conf.html', kwargs) - -def dev_conf_new(request, id_exp=0): + if id_dev<>0: + initial['device'] = id_dev if request.method == 'GET': - form = ConfigurationForm(initial={'experiment':id_exp}) + if id_dev==0: + form = ConfigurationForm(initial=initial) + else: + device = Device.objects.get(pk=id_dev) + DevConfForm = CONF_FORMS[device.device_type.name] + + form = DevConfForm(initial=initial) if request.method == 'POST': - experiment = Experiment.objects.get(pk=request.POST['experiment']) - device = Device.objects.get(pk=request.POST['device']) + device = Device.objects.get(pk=request.POST['device']) DevConfForm = CONF_FORMS[device.device_type.name] - - form = DevConfForm(request.POST, initial={'experiment':experiment.id}) + + form = DevConfForm(request.POST) if form.is_valid(): dev_conf = form.save() - return redirect('url_experiment', id_exp=experiment.id) + return redirect('url_dev_confs') kwargs = {} + kwargs['id_exp'] = id_exp kwargs['form'] = form kwargs['title'] = 'Configuration' kwargs['suptitle'] = 'New' @@ -701,7 +701,7 @@ def dev_conf_import(request, id_conf): ###### SIDEBAR ###### kwargs.update(sidebar(conf)) - return render(request, '%s_conf_edit.html' %conf.device.device_type.name, kwargs) + return render(request, '%s_conf_edit.html' % conf.device.device_type.name, kwargs) messages.error(request, "Could not import parameters from file") @@ -772,21 +772,17 @@ def dev_conf_delete(request, id_conf): def sidebar(conf): - experiments = Experiment.objects.filter(campaign=conf.experiment.campaign) - configurations = Configuration.objects.filter(experiment=conf.experiment, type=0) - - exp_keys = ['id', 'campaign', 'name', 'start_time', 'end_time'] - conf_keys = ['id', 'device'] - kwargs = {} - kwargs['dev_conf'] = conf - - kwargs['experiment_keys'] = exp_keys[1:] - kwargs['experiments'] = experiments.values(*exp_keys) - - kwargs['configuration_keys'] = conf_keys[1:] - kwargs['configurations'] = configurations #.values(*conf_keys) + if conf.experiment: + experiments = Experiment.objects.filter(campaign=conf.experiment.campaign) + configurations = Configuration.objects.filter(experiment=conf.experiment, type=0) + exp_keys = ['id', 'campaign', 'name', 'start_time', 'end_time'] + kwargs['experiment_keys'] = exp_keys[1:] + kwargs['experiments'] = experiments.values(*exp_keys) + conf_keys = ['id', 'device'] + kwargs['configuration_keys'] = conf_keys[1:] + kwargs['configurations'] = configurations #.values(*conf_keys) return kwargs diff --git a/apps/rc/fixtures/rc_initial_data.json b/apps/rc/fixtures/rc_initial_data.json new file mode 100644 index 0000000..2672e38 --- /dev/null +++ b/apps/rc/fixtures/rc_initial_data.json @@ -0,0 +1,26 @@ +[{"fields": {"number_of_codes": 0, "codes": "[]", "name": "None", "bits_per_code": 0}, "model": "rc.rclinecode", "pk": 1}, + {"fields": {"number_of_codes": 2, "codes": "[u'11101101', u'11100010']", "name": "COMPLEMENTARY_CODE_8", "bits_per_code": 8}, "model": "rc.rclinecode", "pk": 2}, + {"fields": {"number_of_codes": 1, "codes": "[u'1101101001000100010001111000']", "name": "BINARY_CODE_28", "bits_per_code": 28}, "model": "rc.rclinecode", "pk": 3}, + {"fields": {"number_of_codes": 2, "codes": "[u'11', u'10']", "name": "COMPLEMENTARY_CODE_2", "bits_per_code": 2}, "model": "rc.rclinecode", "pk": 4}, + {"fields": {"number_of_codes": 2, "codes": "[u'1110110111100010111011010001110111101101111000100001001011100010', u'1110110111100010111011010001110100010010000111011110110100011101']", "name": "COMPLEMENTARY_CODE_64", "bits_per_code": 64}, "model": "rc.rclinecode", "pk": 5}, + {"fields": {"number_of_codes": 1, "codes": "[u'11100010010']", "name": "BARKER11", "bits_per_code": 11}, "model": "rc.rclinecode", "pk": 6}, + {"fields": {"number_of_codes": 2, "codes": "[u'1111100110101' ]", "name": "BARKER13", "bits_per_code": 13}, "model": "rc.rclinecode", "pk": 7}, + {"fields": {"number_of_codes": 2, "codes": "[u'1101101001000100010001111000', u'0010010110111011101110000111']", "name": "BINARY_CODE_28_FLIP", "bits_per_code": 28}, "model": "rc.rclinecode", "pk": 8}, + {"fields": {"number_of_codes": 2, "codes": "[u'11101101111000101110110100011101', u'11101101111000100001001011100010']", "name": "COMPLEMENTARY_CODE_32", "bits_per_code": 32}, "model": "rc.rclinecode", "pk": 9}, + {"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}, + {"fields": {"number_of_codes": 2, "codes": "[u'11101101111000101110110100011101111011011110001000010010111000101110110111100010111011010001110100010010000111011110110100011101', u'11101101111000101110110100011101111011011110001000010010111000100001001000011101000100101110001011101101111000100001001011100010']", "name": "COMPLEMENTARY_CODE_128", "bits_per_code": 128}, "model": "rc.rclinecode", "pk": 11}, + {"fields": {"number_of_codes": 2, "codes": "[u'1110110111100010', u'1110110100011101']", "name": "COMPLEMENTARY_CODE_16", "bits_per_code": 16}, "model": "rc.rclinecode", "pk": 12}, + {"fields": {"number_of_codes": 1, "codes": "[u'11']", "name": "BARKER2", "bits_per_code": 2}, "model": "rc.rclinecode", "pk": 13}, + {"fields": {"number_of_codes": 1, "codes": "[u'110']", "name": "BARKER3", "bits_per_code": 3}, "model": "rc.rclinecode", "pk": 14}, + {"fields": {"number_of_codes": 2, "codes": "[u'1110', u'1101']", "name": "COMPLEMENTARY_CODE_4", "bits_per_code": 4}, "model": "rc.rclinecode", "pk": 15}, + {"fields": {"number_of_codes": 1, "codes": "[u'1110010']", "name": "BARKER7", "bits_per_code": 7}, "model": "rc.rclinecode", "pk": 16}, + {"fields": {"number_of_codes": 1, "codes": "[u'1101']", "name": "BARKER4", "bits_per_code": 4}, "model": "rc.rclinecode", "pk": 17}, + {"fields": {"number_of_codes": 1, "codes": "[u'11101']", "name": "BARKER5", "bits_per_code": 5}, "model": "rc.rclinecode", "pk": 18}, + {"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}, + {"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}, + {"fields": {"params": "{\"TX_ref\": {\"model\": \"RCLine\", \"value\": \"\"}, \"code\": {\"model\":\"RCLineCode\",\"value\": \"\"}, \"codes\":{\"value\":\"\", \"widget\":\"codes\"}}", "name": "codes", "description": ""}, "model": "rc.rclinetype", "pk": 3}, + {"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}, + {"fields": {"params": "{\"invert\":{\"value\": 0, \"help\": \"Set to 1 for synchro pulse at the end\"}}", "name": "sync", "description": ""}, "model": "rc.rclinetype", "pk": 5}, + {"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}, + {"fields": {"params": "{\"number_of_flips\": {\"value\": 0}}", "name": "flip", "description": ""}, "model": "rc.rclinetype", "pk": 7}, + {"fields": {"params": "{}", "name": "none", "description": ""}, "model": "rc.rclinetype", "pk": 8}] diff --git a/apps/rc/forms.py b/apps/rc/forms.py index b217fd3..3ae13b6 100644 --- a/apps/rc/forms.py +++ b/apps/rc/forms.py @@ -1,4 +1,5 @@ import os +import ast import json from django import forms @@ -6,17 +7,19 @@ from django.utils.safestring import mark_safe from apps.main.models import Device from apps.main.forms import add_empty_choice from .models import RCConfiguration, RCLine, RCLineType, RCLineCode +from .widgets import KmUnitWidget, KmUnitHzWidget, KmUnitDcWidget, UnitKmWidget, DefaultWidget, CodesWidget, HiddenWidget -def create_choices_from_model(model, conf_id): +def create_choices_from_model(model, conf_id, all=False): if model=='RCLine': instance = RCConfiguration.objects.get(pk=conf_id) - choices = instance.get_refs_lines() + choices = [(line.pk, line.get_name()) for line in instance.get_lines(type='tx')] + choices = add_empty_choice(choices, label='All') else: instance = globals()[model] choices = instance.objects.all().values_list('pk', 'name') - return add_empty_choice(choices, label='All') + return choices class ExtFileField(forms.FileField): @@ -47,35 +50,9 @@ class ExtFileField(forms.FileField): ext = os.path.splitext(filename)[1] ext = ext.lower() if ext not in self.extensions: - raise forms.ValidationError('Not allowed filetype: %s' % ext) + raise forms.ValidationError('Not allowed file type: %s' % ext) -class KmUnitWidget(forms.widgets.TextInput): - - def render(self, name, value, attrs=None): - - if isinstance(value, (int, float)): - unit = int(value*attrs['line'].km2unit) - elif isinstance(value, basestring): - units = [] - values = [s for s in value.split(',') if s] - for val in values: - units.append('{0:.0f}'.format(float(val)*attrs['line'].km2unit)) - - unit = ','.join(units) - - html = '
Km
Units
'.format(name, value, unit) - - return mark_safe(html) - -class DefaultWidget(forms.widgets.TextInput): - - def render(self, name, value, attrs=None): - - html = '
'.format(name, value) - - return mark_safe(html) - class RCConfigurationForm(forms.ModelForm): def __init__(self, *args, **kwargs): @@ -86,33 +63,98 @@ class RCConfigurationForm(forms.ModelForm): if instance and instance.pk: devices = Device.objects.filter(device_type__name='rc') - - self.fields['experiment'].widget.attrs['readonly'] = True - self.fields['experiment'].widget.choices = [(instance.experiment.id, instance.experiment)] - + if instance.experiment: + self.fields['experiment'].widget.attrs['readonly'] = True + self.fields['experiment'].widget.choices = [(instance.experiment.id, instance.experiment)] self.fields['device'].widget.choices = [(device.id, device) for device in devices] + self.fields['ipp'].widget = KmUnitHzWidget(attrs={'km2unit':instance.km2unit}) + self.fields['clock'].widget.attrs['readonly'] = True + + self.fields['time_before'].label = mark_safe(self.fields['time_before'].label) + self.fields['time_after'].label = mark_safe(self.fields['time_after'].label) + class Meta: model = RCConfiguration exclude = ('type', 'parameters', 'status') - + def clean(self): + form_data = super(RCConfigurationForm, self).clean() + + if 'clock_divider' in form_data: + if form_data['clock_divider']<1: + self.add_error('clock_divider', 'Invalid Value') + else: + if form_data['ipp']*(20./3*(form_data['clock_in']/form_data['clock_divider']))%10<>0: + self.add_error('ipp', 'Invalid IPP units={}'.format(form_data['ipp']*(20./3*(form_data['clock_in']/form_data['clock_divider'])))) + + return form_data class RCLineForm(forms.ModelForm): def __init__(self, *args, **kwargs): self.extra_fields = kwargs.pop('extra_fields', []) super(RCLineForm, self).__init__(*args, **kwargs) - if 'initial'in kwargs: - for item in self.extra_fields: - if item['name']=='params': + + if 'initial' in kwargs and 'line_type' in kwargs['initial']: + line_type = RCLineType.objects.get(pk=kwargs['initial']['line_type']) + + if 'code_id' in kwargs['initial']: + model_initial = kwargs['initial']['code_id'] + else: + model_initial = 0 + + params = json.loads(line_type.params) + + for label, value in self.extra_fields.items(): + if label=='params': + continue + + if 'model' in params[label]: + self.fields[label] = forms.ChoiceField(choices=create_choices_from_model(params[label]['model'], + kwargs['initial']['rc_configuration']), + initial=model_initial) + + + else: + if label=='codes' and 'code_id' in kwargs['initial']: + self.fields[label] = forms.CharField(initial=RCLineCode.objects.get(pk=kwargs['initial']['code_id']).codes) + else: + self.fields[label] = forms.CharField(initial=value['value']) + + if label=='codes': + self.fields[label].widget = CodesWidget() + + if self.data: + line_type = RCLineType.objects.get(pk=self.data['line_type']) + + if 'code_id' in self.data: + model_initial = self.data['code_id'] + else: + model_initial = 0 + + params = json.loads(line_type.params) + + for label, value in self.extra_fields.items(): + if label=='params': continue - if 'model' in item: - self.fields[item['name']] = forms.ChoiceField(choices=create_choices_from_model(item['model'], - kwargs['initial']['rc_configuration'])) + + if 'model' in params[label]: + self.fields[label] = forms.ChoiceField(choices=create_choices_from_model(params[label]['model'], + self.data['rc_configuration']), + initial=model_initial) + + else: - self.fields[item['name']] = forms.CharField(initial=item['value']) + if label=='codes' and 'code' in self.data: + self.fields[label] = forms.CharField(initial=self.data['codes']) + else: + self.fields[label] = forms.CharField(initial=self.data[label]) + if label=='codes': + self.fields[label].widget = CodesWidget() + + class Meta: model = RCLine fields = ('rc_configuration', 'line_type', 'channel') @@ -120,6 +162,16 @@ class RCLineForm(forms.ModelForm): 'channel': forms.HiddenInput(), } + + def clean(self): + + form_data = self.cleaned_data + if 'code' in self.data and self.data['TX_ref']=="0": + self.add_error('TX_ref', 'Choose a valid TX reference') + + return form_data + + def save(self): line = super(RCLineForm, self).save() @@ -132,11 +184,13 @@ class RCLineForm(forms.ModelForm): #save extra fields in params params = {} - for item in self.extra_fields: - if item['name']=='params': + for label, value in self.extra_fields.items(): + if label=='params': params['params'] = [] + elif label=='codes': + params[label] = [s for s in self.data[label].split('\r\n') if s] else: - params[item['name']] = self.data[item['name']] + params[label] = self.data[label] line.params = json.dumps(params) line.save() return @@ -145,12 +199,19 @@ class RCLineForm(forms.ModelForm): class RCLineViewForm(forms.Form): def __init__(self, *args, **kwargs): + extra_fields = kwargs.pop('extra_fields') line = kwargs.pop('line') subform = kwargs.pop('subform', False) super(RCLineViewForm, self).__init__(*args, **kwargs) - print line + + if subform: + params = json.loads(line.line_type.params)['params'] + else: + params = json.loads(line.line_type.params) + for label, value in extra_fields.items(): + if label=='params': continue if 'ref' in label: @@ -158,48 +219,79 @@ class RCLineViewForm(forms.Form): value = 'All' else: value = RCLine.objects.get(pk=value).get_name() - elif 'code' in label: + elif label=='code': value = RCLineCode.objects.get(pk=value).name - self.fields[label] = forms.CharField(initial=value) - - if subform: - params = json.loads(line.line_type.params)['params'] - else: - params = json.loads(line.line_type.params) + self.fields[label] = forms.CharField(initial=value) if 'widget' in params[label]: + km2unit = line.rc_configuration.km2unit if params[label]['widget']=='km': - self.fields[label].widget = KmUnitWidget(attrs={'line':line}) + self.fields[label].widget = KmUnitWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True}) + elif params[label]['widget']=='unit': + self.fields[label].widget = UnitKmWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True}) + elif params[label]['widget']=='dc': + self.fields[label].widget = KmUnitDcWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True}) + elif params[label]['widget']=='codes': + self.fields[label].widget = CodesWidget(attrs={'line':line, 'km2unit':km2unit, 'disabled':True}) else: - self.fields[label].widget = DefaultWidget() + self.fields[label].widget = DefaultWidget(attrs={'disabled':True}) + class RCLineEditForm(forms.ModelForm): def __init__(self, *args, **kwargs): - self.extra_fields = kwargs.pop('extra_fields', []) + + extra_fields = kwargs.pop('extra_fields', []) + conf = kwargs.pop('conf', False) + line = kwargs.pop('line') + subform = kwargs.pop('subform', False) + super(RCLineEditForm, self).__init__(*args, **kwargs) - if 'initial'in kwargs: - for item, values in self.extra_fields.items(): - if item=='params': - continue - if 'help' in values: - help_text = values['help'] - else: - help_text = '' + + if subform is not False: + params = json.loads(line.line_type.params)['params'] + count = subform + else: + params = json.loads(line.line_type.params) + count = -1 + + for label, value in extra_fields.items(): + + if label in ('params',): + continue + if 'help' in params[label]: + help_text = params[label]['help'] + else: + help_text = '' + + if 'model' in params[label]: + self.fields[label] = forms.ChoiceField(choices=create_choices_from_model(params[label]['model'], conf.id), + initial=value, + widget=forms.Select(attrs={'name':'%s|%s|%s' % (count, line.id, label)}), + help_text=help_text) - if 'model' in values: - self.fields[item] = forms.ChoiceField(choices=create_choices_from_model(values['model'], kwargs['initial']['rc_configuration']), - initial=values['value'], - widget=forms.Select(attrs={'name':'%s|%s' % (kwargs['initial']['line'], item)}), - help_text=help_text) - - else: - self.fields[item] = forms.CharField(initial=values['value'], - widget=forms.TextInput(attrs={'name':'%s|%s' % (kwargs['initial']['line'], item)}), - help_text=help_text) - - + else: + + self.fields[label] = forms.CharField(initial=value, help_text=help_text) + + if label in ('code', ): + self.fields[label].widget = HiddenWidget(attrs={'name':'%s|%s|%s' % (count, line.id, label)}) + + elif 'widget' in params[label]: + km2unit = line.rc_configuration.km2unit + if params[label]['widget']=='km': + self.fields[label].widget = KmUnitWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)}) + elif params[label]['widget']=='unit': + self.fields[label].widget = UnitKmWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)}) + elif params[label]['widget']=='dc': + self.fields[label].widget = KmUnitDcWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)}) + elif params[label]['widget']=='codes': + self.fields[label].widget = CodesWidget(attrs={'line':line, 'km2unit':km2unit, 'name':'%s|%s|%s' % (count, line.id, label)}) + else: + self.fields[label].widget = DefaultWidget(attrs={'name':'%s|%s|%s' % (count, line.id, label)}) + + class Meta: model = RCLine exclude = ('rc_configuration', 'line_type', 'channel', 'position', 'params', 'pulses') @@ -220,4 +312,25 @@ class RCSubLineEditForm(forms.Form): class RCImportForm(forms.Form): file_name = ExtFileField(extensions=['.racp', '.json', '.dat']) + + +class RCLineCodesForm(forms.ModelForm): + + def __init__(self, *args, **kwargs): + super(RCLineCodesForm, self).__init__(*args, **kwargs) + + if 'initial' in kwargs: + self.fields['code'] = forms.ChoiceField(choices=RCLineCode.objects.all().values_list('pk', 'name'), + initial=kwargs['initial']['code']) + if 'instance' in kwargs: + self.fields['code'] = forms.ChoiceField(choices=RCLineCode.objects.all().values_list('pk', 'name'), + initial=kwargs['instance'].pk) + + self.fields['codes'].widget = CodesWidget() + + + class Meta: + model = RCLineCode + exclude = ('name',) + \ No newline at end of file diff --git a/apps/rc/models.py b/apps/rc/models.py index 210f1c4..85b53f0 100644 --- a/apps/rc/models.py +++ b/apps/rc/models.py @@ -6,10 +6,12 @@ import numpy as np from polymorphic import PolymorphicModel from django.db import models +from django.core.urlresolvers import reverse from django.core.validators import MinValueValidator, MaxValueValidator from apps.main.models import Configuration -from .utils import pulses, pulses_from_code, create_mask +from .utils import RCFile, pulses, pulses_from_code, create_mask, pulses_to_points + # Create your models here. LINE_TYPES = ( @@ -24,37 +26,283 @@ LINE_TYPES = ( ) +SAMPLING_REFS = ( + ('none', 'No Reference'), + ('first_baud', 'Middle of the first baud'), + ('sub_baud', 'Middle of the sub-baud') + ) + +DAT_CMDS = { + # Pulse Design commands + 'DISABLE' : 0, # Disables pulse generation + 'ENABLE' : 24, # Enables pulse generation + 'DELAY_START' : 40, # Write delay status to memory + 'FLIP_START' : 48, # Write flip status to memory + 'SAMPLING_PERIOD' : 64, # Establish Sampling Period + 'TX_ONE' : 72, # Output '0' in line TX + 'TX_ZERO' : 88, # Output '0' in line TX + 'SW_ONE' : 104, # Output '0' in line SW + 'SW_ZERO' : 112, # Output '1' in line SW + 'RESTART': 120, # Restarts CR8 Firmware + 'CONTINUE' : 253, # Function Unknown + # Commands available to new controllers + # 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. + 'CLOCK_DIVISOR_INIT' : 12, # Specifies Clock Divisor. Legacy command, ignored in the actual .dat conversion + 'CLOCK_DIVISOR_LAST' : 22, # Specifies Clock Divisor (default 60 if not included) syntax: 255,22 254,N-1. + 'CLOCK_DIVIDER' : 8, + } + + class RCConfiguration(Configuration): ipp = models.FloatField(verbose_name='Inter pulse period (Km)', validators=[MinValueValidator(1), MaxValueValidator(1000)], default=10) - ntx = models.PositiveIntegerField(verbose_name='Number of TX', default=1) - clock = models.FloatField(verbose_name='Clock Master (MHz)', validators=[MinValueValidator(1), MaxValueValidator(80)], default=1) + ntx = models.PositiveIntegerField(verbose_name='Number of TX', validators=[MinValueValidator(1), MaxValueValidator(256)], default=1) + clock_in = models.FloatField(verbose_name='Clock in (MHz)', validators=[MinValueValidator(1), MaxValueValidator(80)], default=1) clock_divider = models.PositiveIntegerField(verbose_name='Clock divider', validators=[MinValueValidator(1), MaxValueValidator(256)], default=1) - time_before = models.PositiveIntegerField(verbose_name='Time before', default=0) - time_after = models.PositiveIntegerField(verbose_name='Time after', default=0) + clock = models.FloatField(verbose_name='Clock Master (MHz)', blank=True, default=1) + time_before = models.PositiveIntegerField(verbose_name='Time before (μS)', default=0) + time_after = models.PositiveIntegerField(verbose_name='Time after (μS)', default=0) sync = models.PositiveIntegerField(verbose_name='Synchro delay', default=0) + sampling_reference = models.CharField(verbose_name='Sampling Reference', choices=SAMPLING_REFS, default='none', max_length=40) + control_tx = models.BooleanField(verbose_name='Control Switch TX', default=False) + control_sw = models.BooleanField(verbose_name='Control Switch SW', default=False) + class Meta: db_table = 'rc_configurations' - - def get_number_position(self): + + + def get_absolute_url_plot(self): + return reverse('url_plot_rc_pulses', args=[str(self.id)]) + + def get_absolute_url_import(self): + return reverse('url_import_rc_conf', args=[str(self.id)]) + + @property + def us2unit(self): - lines = RCLine.objects.filter(rc_configuration=self.rc_configuration) - if lines: - return max([line.position for line in lines]) + return self.clock_in/self.clock_divider + - def get_refs_lines(self): + @property + def km2unit(self): - lines = RCLine.objects.filter(rc_configuration=self.pk, line_type__name='tx') - return [(line.pk, line.get_name()) for line in lines] + return 20./3*(self.clock_in/self.clock_divider) + def get_lines(self, type=None): + ''' + Retrieve configuration lines + ''' if type is not None: return RCLine.objects.filter(rc_configuration=self.pk, line_type__name=type) else: return RCLine.objects.filter(rc_configuration=self.pk) + def clean_lines(self): + ''' + ''' + + empty_line = RCLineType.objects.get(pk=8) + + for line in self.get_lines(): + line.line_type = empty_line + line.params = '{}' + line.save() + + def parms_to_dict(self): + ''' + ''' + + data = {} + for field in self._meta.fields: + + data[field.name] = '{}'.format(field.value_from_object(self)) + + data.pop('parameters') + data['lines'] = [] + + for line in self.get_lines(): + line_data = json.loads(line.params) + if 'TX_ref' in line_data and line_data['TX_ref'] not in (0, '0'): + line_data['TX_ref'] = RCLine.objects.get(pk=line_data['TX_ref']).get_name() + if 'code' in line_data: + line_data['code'] = RCLineCode.objects.get(pk=line_data['code']).name + line_data['type'] = line.line_type.name + data['lines'].append(line_data) + + + return data + + def get_delays(self): + + pulses = [line.get_pulses() for line in self.get_lines()] + points = [tup for tups in pulses for tup in tups] + points = set([x for tup in points for x in tup]) + points = list(points) + points.sort() + + if points[0]<>0: + points.insert(0, 0) + + return [points[i+1]-points[i] for i in range(len(points)-1)] + + + def get_flips(self): + + line_points = [pulses_to_points(line.pulses_as_array()) for line in self.get_lines()] + line_points = [[(x, x+y) for x,y in tups] for tups in line_points] + line_points = [[t for x in tups for t in x] for tups in line_points] + states = [[1 if x in tups else 0 for tups in line_points] for x in points] + + return states + + def add_cmd(self, cmd): + + if cmd in DAT_CMDS: + return (255, DAT_CMDS[cmd]) + + def add_data(self, value): + + return (254, value-1) + + def parms_to_binary(self): + ''' + Create "dat" stream to be send to CR + ''' + + data = [] + # create header + data.append(self.add_cmd('DISABLE')) + data.append(self.add_cmd('CONTINUE')) + data.append(self.add_cmd('RESTART')) + + if self.control_sw: + data.append(self.add_cmd('SW_ONE')) + else: + data.append(self.add_cmd('SW_ZERO')) + + if self.control_tx: + data.append(self.add_cmd('TX_ONE')) + else: + data.append(self.add_cmd('TX_ZERO')) + + # write divider + data.append(self.add_cmd('CLOCK_DIVIDER')) + data.append(self.add_data(self.clock_divider)) + + # write delays + data.append(self.add_cmd('DELAY_START')) + # first delay is always zero + data.append(self.add_data(1)) + line_points = [pulses_to_points(line.pulses_as_array()) for line in self.get_lines()] + points = [tup for tups in line_points for tup in tups] + points = [(x, x+y) for x,y in points] + points = set([x for tup in points for x in tup]) + points = list(points) + points.sort() + + if points[0]<>0: + points.insert(0, 0) + + delays = [points[i+1]-points[i] for i in range(len(points)-1)] + + for delay in delays: + while delay>252: + data.append(self.add_data(253)) + delay -= 253 + data.append(self.add_data(delay)) + + # write flips + data.append(self.add_cmd('FLIP_START')) + line_points = [[(x, x+y) for x,y in tups] for tups in line_points] + line_points = [[t for x in tups for t in x] for tups in line_points] + states = [[1 if x in tups else 0 for tups in line_points] for x in points] + for flips, delay in zip(states[:-1], delays): + flips.reverse() + flip = int(''.join([str(x) for x in flips]), 2) + data.append(self.add_data(flip+1)) + while delay>252: + data.append(self.add_data(1)) + delay -= 253 + + # write sampling period + data.append(self.add_cmd('SAMPLING_PERIOD')) + wins = self.get_lines(type='windows') + if wins: + win_params = json.loads(wins[0].params)['params'] + if win_params: + dh = int(win_params[0]['resolution']*self.km2unit) + else: + dh = 1 + else: + dh = 1 + data.append(self.add_data(dh)) + + # write enable + data.append(self.add_cmd('ENABLE')) + + return '\n'.join(['{}'.format(x) for tup in data for x in tup]) + + def update_from_file(self, filename): + ''' + Update instance from file + ''' + + f = RCFile(filename) + data = f.data + self.name = data['name'] + self.ipp = data['ipp'] + self.ntx = data['ntx'] + self.clock_in = data['clock_in'] + self.clock_divider = data['clock_divider'] + self.clock = data['clock'] + self.time_before = data['time_before'] + self.time_after = data['time_after'] + self.sync = data['sync'] + self.sampling_reference = data['sampling_reference'] + self.clean_lines() + + lines = [] + positions = {'tx':0, 'tr':0} + + for i, line_data in enumerate(data['lines']): + line_type = RCLineType.objects.get(name=line_data.pop('type')) + if line_type.name=='codes': + code = RCLineCode.objects.get(name=line_data['code']) + line_data['code'] = code.pk + line = RCLine.objects.filter(rc_configuration=self, channel=i) + if line: + line = line[0] + line.line_type = line_type + line.params = json.dumps(line_data) + else: + line = RCLine(rc_configuration=self, line_type=line_type, + params=json.dumps(line_data), + channel=i) + + if line_type.name=='tx': + line.position = positions['tx'] + positions['tx'] += 1 + + if line_type.name=='tr': + line.position = positions['tr'] + positions['tr'] += 1 + + line.save() + lines.append(line) + + for line, line_data in zip(lines, data['lines']): + if 'TX_ref' in line_data: + params = json.loads(line.params) + if line_data['TX_ref'] in (0, '0'): + params['TX_ref'] = '0' + else: + params['TX_ref'] = [l.pk for l in lines if l.line_type.name=='tx' and l.get_name()==line_data['TX_ref']][0] + line.params = json.dumps(params) + line.save() + class RCLineCode(models.Model): @@ -97,15 +345,18 @@ class RCLine(models.Model): ordering = ['channel'] def __unicode__(self): - return u'%s - %s' % (self.rc_configuration, self.get_name()) + if self.rc_configuration: + return u'%s - %s' % (self.rc_configuration, self.get_name()) def get_name(self): chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' if self.line_type.name in ('tx',): - return '%s %s' % (self.line_type.name.upper(), chars[self.position]) + return '%s%s' % (self.line_type.name.upper(), chars[self.position]) elif self.line_type.name in ('codes', 'windows', 'tr'): + if 'TX_ref' not in json.loads(self.params): + return self.line_type.name.upper() pk = json.loads(self.params)['TX_ref'] if pk in (0, '0'): refs = ','.join(chars[l.position] for l in self.rc_configuration.get_lines('tx')) @@ -113,7 +364,7 @@ class RCLine(models.Model): else: ref = RCLine.objects.get(pk=pk) return '%s (%s)' % (self.line_type.name.upper(), chars[ref.position]) - elif self.line_type.name in ('flip', 'prog_pulses', 'sync'): + elif self.line_type.name in ('flip', 'prog_pulses', 'sync', 'none'): return '%s %s' % (self.line_type.name.upper(), self.channel) else: return self.line_type.name.upper() @@ -125,21 +376,59 @@ class RCLine(models.Model): else: return RCLine.objects.filter(rc_configuration=self.rc_configuration) + def pulses_as_array(self): return (np.fromstring(self.pulses, dtype=np.uint8)-48).astype(np.int8) - @property - def km2unit(self): + + def get_pulses(self): + + X = self.pulses_as_array() + + d = X[1:]-X[:-1] + + up = np.where(d==1)[0] + if X[0]==1: + up = np.concatenate((np.array([-1]), up)) + up += 1 + + dw = np.where(d==-1)[0] + if X[-1]==1: + dw = np.concatenate((dw, np.array([len(X)-1]))) + dw += 1 + + return [(tup[0], tup[1]) for tup in zip(up, dw)] + + def get_win_ref(self, params, tx_id, km2unit): + + ref = self.rc_configuration.sampling_reference + + codes = [line for line in self.get_lines(type='code') if int(json.loads(line.params)['TX_ref'])==int(tx_id)] + + if codes: + code_line = RCLineCode.objects.get(pk=json.loads(codes[0].params)['code']) + tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit/code_line.bits_per_code + else: + tx_width = float(json.loads(RCLine.objects.get(pk=tx_id).params)['pulse_width'])*km2unit - return 20./3*(self.rc_configuration.clock/self.rc_configuration.clock_divider) + if ref=='first_baud': + return int(1 + (tx_width + 1)/2 + params['first_height']*km2unit - params['resolution']*km2unit) + elif ref=='sub_baud': + return int(1 + params['first_height']*km2unit - params['resolution']*km2unit/2) + else: + return 0 def update_pulses(self, save=True, tr=False): - print self - KM2U = 20./3*(self.rc_configuration.clock/self.rc_configuration.clock_divider) + ''' + Update pulses field + ''' + + km2unit = self.rc_configuration.km2unit + us2unit = self.rc_configuration.us2unit ipp = self.rc_configuration.ipp ntx = self.rc_configuration.ntx - ipp_u = int(ipp*KM2U) + ipp_u = int(ipp*km2unit) x = np.arange(0, ipp_u*ntx) @@ -152,7 +441,7 @@ class RCLine(models.Model): if len(txs)==0 or 0 in [len(tx) for tx in txs]: return - y = np.any(txs, axis=0, out=np.ones(ipp_u*ntx)) + y = np.any(txs, axis=0, out=np.ones(ipp_u*ntx)) ranges = params['range'].split(',') if len(ranges)>0 and ranges[0]<>'0': @@ -161,31 +450,32 @@ class RCLine(models.Model): elif self.line_type.name=='tx': params = json.loads(self.params) - delays = [float(d)*KM2U for d in params['delays'].split(',') if d] - y = pulses(x, ipp_u, float(params['pulse_width'])*KM2U, + delays = [float(d)*km2unit for d in params['delays'].split(',') if d] + y = pulses(x, ipp_u, float(params['pulse_width'])*km2unit, delay=delays, - before=self.rc_configuration.time_before, - after=self.rc_configuration.time_after if tr else 0, + before=int(self.rc_configuration.time_before*us2unit), + after=int(self.rc_configuration.time_after*us2unit) if tr else 0, sync=self.rc_configuration.sync) + ranges = params['range'].split(',') - + if len(ranges)>0 and ranges[0]<>'0': mask = create_mask(ranges, ipp_u, ntx, self.rc_configuration.sync) y = y & mask elif self.line_type.name=='flip': - width = float(json.loads(self.params)['number_of_flips'])*ipp*KM2U + width = float(json.loads(self.params)['number_of_flips'])*ipp*km2unit y = pulses(x, 2*width, width) elif self.line_type.name=='codes': params = json.loads(self.params) - codes = ast.literal_eval(RCLineCode.objects.get(pk=json.loads(self.params)['code']).codes) + #codes = ast.literal_eval(RCLineCode.objects.get(pk=json.loads(self.params)['code']).codes) tx = RCLine.objects.get(pk=params['TX_ref']) tx_params = json.loads(tx.params) - y = pulses_from_code(ipp_u, ntx, codes, - int(float(tx_params['pulse_width'])*KM2U), - before=self.rc_configuration.time_before+self.rc_configuration.sync) + y = pulses_from_code(ipp_u, ntx, params['codes'], + int(float(tx_params['pulse_width'])*km2unit), + before=int(self.rc_configuration.time_before*us2unit)+self.rc_configuration.sync) ranges = tx_params['range'].split(',') if len(ranges)>0 and ranges[0]<>'0': @@ -215,9 +505,12 @@ class RCLine(models.Model): elif self.line_type.name=='windows': params = json.loads(self.params) if 'params' in params and len(params['params'])>0: - y = sum([pulses(x, ipp_u, pp['resolution']*pp['number_of_samples']*KM2U, - delay=(pp['first_height']-pp['resolution'])*KM2U, - before=self.rc_configuration.time_before) for pp in params['params']]) + print 'REFS' + print [self.get_win_ref(pp, params['TX_ref'],km2unit) for pp in params['params']] + y = sum([pulses(x, ipp_u, pp['resolution']*pp['number_of_samples']*km2unit, + shift=0, + before=int(self.rc_configuration.time_before*us2unit)+self.get_win_ref(pp, params['TX_ref'],km2unit), + sync=self.rc_configuration.sync) for pp in params['params']]) tr = self.get_lines('tr')[0] ranges = json.loads(tr.params)['range'].split(',') if len(ranges)>0 and ranges[0]<>'0': @@ -233,4 +526,5 @@ class RCLine(models.Model): self.save() else: return y - \ No newline at end of file + + \ No newline at end of file diff --git a/apps/rc/static/js/cr.js b/apps/rc/static/js/cr.js new file mode 100644 index 0000000..15ae2bc --- /dev/null +++ b/apps/rc/static/js/cr.js @@ -0,0 +1,71 @@ +var km_fields = []; +var unit_fields = []; +var dc_fields = []; + + +function str2hz(s){ + + return 150000*Math.pow(parseFloat(s), -1); +} + + +function str2unit(s){ + var km2unit = (20/3)*(parseFloat($('#id_clock_in').val())/parseFloat($('#id_clock_divider').val())); + var ret = ""; + values = s.split(","); + for (i=0; i {% endblock %} \ No newline at end of file diff --git a/apps/rc/templates/rc_conf.html b/apps/rc/templates/rc_conf.html index 0ce7088..eb4620a 100644 --- a/apps/rc/templates/rc_conf.html +++ b/apps/rc/templates/rc_conf.html @@ -3,24 +3,11 @@ {% load bootstrap3 %} {% load main_tags %} -{% block extra-head %} - +{% block extra-menu-actions %} +
  • View Pulses
  • {% endblock %} -{% block content %} - - - - - - {% for key in dev_conf_keys %} - - - - -{% endfor %} -
    Status{%if connected == True %} Connected {% else %} Disconnected {% endif %}
    {% get_verbose_field_name dev_conf key %}{{dev_conf|attr:key}}
    - +{% block extra-content %}

    RC Lines


    @@ -28,54 +15,4 @@ {% include "rc_lines.html" %}
    -
    - - - - - - - - - - -{% endblock %} - -{% block extra-js%} - - - - - -{% endblock %} \ No newline at end of file +{% endblock extra-content%} diff --git a/apps/rc/templates/rc_conf_edit.html b/apps/rc/templates/rc_conf_edit.html index 848cd0e..59eaea2 100644 --- a/apps/rc/templates/rc_conf_edit.html +++ b/apps/rc/templates/rc_conf_edit.html @@ -7,6 +7,8 @@ /* show the move cursor as the user moves the mouse over the panel header.*/ .panel-default { cursor: move; } + + {% endblock %} {% block content %} @@ -30,7 +32,7 @@ {% block extra-js%} - + +{% endblock %} \ No newline at end of file diff --git a/apps/rc/templates/rc_lines.html b/apps/rc/templates/rc_lines.html index 763bfff..f72b811 100644 --- a/apps/rc/templates/rc_lines.html +++ b/apps/rc/templates/rc_lines.html @@ -15,21 +15,25 @@
    {% bootstrap_form line.form layout='horizontal' size='small' %} -

    +

    + {% for f in line.subforms %} +
    + +
    {% if edit %}{% endif %}
    +
    + {% bootstrap_form f layout='horizontal' size='small' %} +
    + {% endfor %} + + {% if edit and line.subform %} +
    + + {% endif %} - {% for f in line.subforms %} -
    - -
    {% if edit %}{% endif %}
    -
    - {% bootstrap_form f layout='horizontal' size='small' %} -
    - {% endfor %} - - {% if edit and line.subform %} -
    - - {% endif %} + {% if edit and line.line_type.name == 'codes' %} +
    + + {% endif %}
    diff --git a/apps/rc/templates/rc_pulses.html b/apps/rc/templates/rc_pulses.html index 33e6841..0cc6ee4 100644 --- a/apps/rc/templates/rc_pulses.html +++ b/apps/rc/templates/rc_pulses.html @@ -8,18 +8,11 @@ {% endblock %} {% block content %} - - - -
    {{div}}
    - - - +
    {{div}}
    {% endblock %} {% block extra-js%} - {{script}} diff --git a/apps/rc/urls.py b/apps/rc/urls.py index 1c4930b..579b651 100644 --- a/apps/rc/urls.py +++ b/apps/rc/urls.py @@ -7,12 +7,14 @@ urlpatterns = ( url(r'^(?P-?\d+)/plot/$', 'apps.rc.views.view_pulses', name='url_plot_rc_pulses'), url(r'^(?P-?\d+)/write/$', 'apps.main.views.dev_conf_write', name='url_write_rc_conf'), url(r'^(?P-?\d+)/read/$', 'apps.main.views.dev_conf_read', name='url_read_rc_conf'), - url(r'^(?P-?\d+)/export/$', 'apps.main.views.dev_conf_export', name='url_export_rc_conf'), url(r'^(?P-?\d+)/add_line/$', 'apps.rc.views.add_line', name='url_add_rc_line'), url(r'^(?P-?\d+)/add_line/(?P-?\d+)/$', 'apps.rc.views.add_line', name='url_add_rc_line'), + url(r'^(?P-?\d+)/add_line/(?P-?\d+)/code/(?P-?\d+)/$', 'apps.rc.views.add_line', name='url_add_rc_line_code'), url(r'^(?P-?\d+)/update_position/$', 'apps.rc.views.update_lines_position', name='url_update_rc_lines_position'), url(r'^(?P-?\d+)/line/(?P-?\d+)/delete/$', 'apps.rc.views.remove_line', name='url_remove_rc_line'), url(r'^(?P-?\d+)/line/(?P-?\d+)/add_subline/$', 'apps.rc.views.add_subline', name='url_add_rc_subline'), + url(r'^(?P-?\d+)/line/(?P-?\d+)/codes/$', 'apps.rc.views.edit_codes', name='url_edit_rc_codes'), + url(r'^(?P-?\d+)/line/(?P-?\d+)/codes/(?P-?\d+)/$', 'apps.rc.views.edit_codes', name='url_edit_rc_codes'), url(r'^(?P-?\d+)/line/(?P-?\d+)/subline/(?P-?\d+)/delete/$', 'apps.rc.views.remove_subline', name='url_remove_rc_subline'), ) diff --git a/apps/rc/utils.py b/apps/rc/utils.py index 910df06..7ab1af8 100644 --- a/apps/rc/utils.py +++ b/apps/rc/utils.py @@ -1,646 +1,13 @@ -import ast -import json -# import numpy as np -# import matplotlib.pyplot as plt -# from matplotlib import cm - -class Pulse_Design_Racp: - """A class to define the .racp output from Pulse Design """ - def __init__(self): - self.header = {'version': '1103', 'data':[]} - self.radar_param = {'header': '*****Radar Controller Parameters**********', 'data':[]} - self.system_param1 = {'header': '******System Parameters*******************', 'data':[]} - self.system_param2 = {'header': '******System Parameters*******************', 'data':[]} - self.process_param = {'header': '******Process Parameters******************', 'data':[]} - self.xml = None - - self.header_fields = [ - {'name': 'EXPERIMENT TYPE', 'xml': 'Experiment/Process/Signal_pre_processing/Type_of_experiment'}, - {'name': 'EXPERIMENT NAME', 'xml': 'Experiment', 'xml_attr_value':'name'}] - self.radar_param_fields = [ - {'name': 'IPP', 'xml': 'Experiment/Controller/IPP/Width'}, - {'name': 'NTX', 'xml': 'Experiment/Controller/NTX'}, - {'name': 'TXA', 'xml': 'Experiment/Controller/Transmitters/TX', 'xml_attr':'id', 'xml_attr_find':'txa', 'xml_sub_pattern':'Width'}, - {'name': 'TXB', 'xml': 'Experiment/Controller/Transmitters/TX', 'xml_attr':'id', 'xml_attr_find':'txb', 'xml_sub_pattern':'Width'}, - {'name': '***', 'xml':'', 'type':'pulse_enable'}, - {'name': '***', 'xml':'', 'type': 'Line4'}, - {'name': '***', 'xml':'', 'type': 'Line5'}, - {'name': '***', 'xml':'', 'type': 'Line6'}, - {'name': '***', 'xml':'', 'type':'txb_delays_info'}, - {'name': '***', 'xml':'', 'type': 'Line7'}, - {'name': 'SAMPLING REFERENCE', 'xml':'Experiment/Controller/Ctl_Setting/Sampling_reference'}, - {'name': 'RELOJ', 'xml':'Experiment/Controller/Clock/Clock_final'}, - {'name': 'CLOCK DIVIDER', 'xml':'Experiment/Controller/Clock/Clock_div', 'hide':['1']}, - {'name': 'TR_BEFORE', 'xml':'Experiment/Controller/Spc_Setting/Time_before'}, - {'name': 'TR_AFTER', 'xml':'Experiment/Controller/Spc_Setting/Time_after'}, - {'name': 'WINDOW IN LINE 5&6', 'xml':'', 'value':'NO'}, - {'name': 'SYNCHRO DELAY', 'xml':'Experiment/Controller/Spc_Setting/Sync_delay', 'hide':['0']}] - self.system_param1_fields = [ - {'name': 'Number of Cards', 'xml':'Experiment/Process/JARS/Number_of_cards', 'hide':['0']}, - {'name': '***', 'xml':'', 'type':'cards_info'}, - {'name': '***', 'xml':'', 'type':'channels_info'}, - {'name': 'RAW DATA DIRECTORY', 'xml':'Experiment/Process/Data_storage/Directory'}, - {'name': 'CREATE DIRECTORY PER DAY', 'xml':'Experiment/Process/Data_storage/Directory_per_day', 'type':'checkbox_YES_NO'}, - {'name': 'INCLUDE EXPNAME IN DIRECTORY', 'xml':'Experiment/Process/Data_storage/Expname_in_directory', 'type':'checkbox_YES_NO'}] - self.system_param2_fields = [ - {'name': 'ADC Resolution', 'xml':'', 'value':'12'}, # Default is 8, JARS is 12 - {'name': 'PCI DIO BusWidth', 'xml':'', 'value':'32'}, # Default for JARS - {'name': 'RAW DATA BLOCKS', 'xml':'Experiment/Process/Data_arrangement/Data_blocks'}] - self.process_param_fields = [ - {'name': 'DATATYPE', 'xml': 'Experiment/Process/Signal_pre_processing/Type_of_data'}, - {'name': 'DATA ARRANGE', 'xml':'', 'value':'CONTIGUOUS_CH'}, #TODO - {'name': 'COHERENT INTEGRATION STRIDE', 'xml':'Experiment/Process/Signal_pre_processing/Integration_stride'}, - {'name': '------------------', 'xml':'', 'type':'separator'}, - {'name': 'ACQUIRED PROFILES', 'xml':'Experiment/Process/Data_arrangement/Acquired_profiles'}, - {'name': 'PROFILES PER BLOCK', 'xml':'Experiment/Process/Data_arrangement/Profiles_per_block'}, - {'name': '------------------', 'xml':'', 'type':'separator'}, - {'name': 'BEGIN ON START', 'xml':'Experiment/Process/Schedule/Begin_on_Start', 'type': 'checkbox_YES_NO'}, - {'name': 'BEGIN_TIME', 'xml':'Experiment/Process/Schedule/Start', 'hide':['']}, - {'name': 'END_TIME', 'xml':'Experiment/Process/Schedule/End', 'hide':['']}, - {'name': 'VIEW RAW DATA', 'xml':'Experiment/Process/Data_arrangement/View_raw_data', 'type': 'checkbox_YES_NO'}, - {'name': 'REFRESH RATE', 'xml':'', 'value':'1'}, #TODO - {'name': '------------------', 'xml':'', 'type':'separator'}, - {'name': 'SEND STATUS TO FTP', 'xml':'', 'type':'checkbox_YES_NO', 'value':'NO'}, #TODO - {'name': 'FTP SERVER', 'xml':'', 'hide':[None, '']}, #TODO - {'name': 'FTP USER', 'xml':'', 'hide':[None, '']}, #TODO - {'name': 'FTP PASSWD', 'xml':'', 'hide':[None, '']}, #TODO - {'name': 'FTP DIR', 'xml':'', 'hide':[None, '']}, #TODO - {'name': 'FTP FILE', 'xml':'', 'hide':[None, '']}, #TODO - {'name': 'FTP INTERVAL', 'xml':'', 'hide':[None, '']}, #TODO - {'name': 'SAVE STATUS AND BLOCK', 'xml':'', 'type':'checkbox_YES_NO', 'value':'NO'}, #TODO - {'name': 'GENERATE RTI', 'xml':'', 'type':'checkbox_YES_NO', 'value':'NO'}, #TODO - {'name': 'SEND RTI AND BLOCK', 'xml':'Process_acquired_profiles', 'type':'checkbox_YES_NO'}, #TODO - {'name': 'FTP INTERVAL', 'xml':'', 'value':'60'}, #TODO - {'name': '------------------', 'xml':'', 'type':'separator'}, - {'name': 'COMPORT CONFIG', 'xml':'', 'value':'Com1 CBR_9600 TWOSTOPBITS NOPARITY'}, #TODO - {'name': 'JAM CONFIGURE FILE', 'xml':'', 'value':''}, #TODO - {'name': 'ACQUISITION SYSTEM', 'xml':'', 'value':'JARS'}, #TODO - {'name': '******************', 'xml':'', 'type':'acq_system_config_params'}, - {'name': 'SAVE DATA', 'xml':'', 'value':'YES'}, #TODO - {'name': '******************', 'xml':'', 'type':'rc_seq_config_params'}, - {'name': 'RC_STOP_SEQUENCE', 'xml':'', 'value':'255,0,255,8'}, - {'name': 'RC_START_SEQUENCE', 'xml':'', 'value':'255,24'}] - - def get_field_value(self, field, user_value): - if 'type' in field and field['type'] == 'checkbox_YES_NO': # Check for existence of value - if (user_value is None) or (user_value == 'None'): - user_value = 'NO' - elif user_value == 'on': - user_value = 'YES' - if 'value' in field and not(user_value): # Replace by default value - user_value = field['value'] - if 'extra' in field and field['extra'] == 'upper': # Uppercase values - user_value = user_value.upper() - return str(user_value) - - def load_xml(self, xml): - self.xml = xml - for field in self.header_fields: - self.add_line_output(self.header['data'], field) - for field in self.radar_param_fields: - self.add_line_output(self.radar_param['data'], field) - for field in self.system_param1_fields: - self.add_line_output(self.system_param1['data'], field) - for field in self.system_param2_fields: - self.add_line_output(self.system_param2['data'], field) - for field in self.process_param_fields: - self.add_line_output(self.process_param['data'], field) - - - - def add_line_output(self, text_array, param_field): - name = param_field['name'] - xml_l = param_field['xml'] - acq_number_of_cards = int(self.xml.find('Experiment/Process/JARS/Number_of_cards').text) - acq_channels_per_card = int(self.xml.find('Experiment/Process/JARS/Channels_per_card').text) - number_of_acq_channels = acq_number_of_cards * acq_channels_per_card - - if 'xml_attr' in param_field and 'xml_attr_find' in param_field: - sub_pattern = False - if 'xml_sub_pattern' in param_field: - sub_pattern = param_field['xml_sub_pattern'] - element = self.xml.find_by_attribute_value(xml_l, param_field['xml_attr'], param_field['xml_attr_find'],sub_pattern) - else: - element = self.xml.find(xml_l) - - if 'xml_attr_value' in param_field: - value = element.get(param_field['xml_attr_value']) - else: - value = '' - if xml_l == '' and 'value' in param_field: - value = param_field['value'] - elif hasattr(element, 'text'): - value = element.text - - if 'type' in param_field and param_field['type'] == 'separator': # Check for existence of value - text_array.append('------------------------------------------') - return - if 'type' in param_field and param_field['type'] == 'acq_system_config_params': # Get Acquisition System Parameters and add them - text_array.append("************JARS CONFIGURATION PARAMETERS************") - if self.xml.find('Experiment/Process/JARS/Filter').text: - # Notice that we need to use backslashes for the filter path - text_array.append("Jars_Filter="+self.xml.find('Experiment/Process/JARS/Filter_dir').text +'\\'+ self.xml.find('Experiment/Process/JARS/Filter').text) - else: - text_array.append("Jars_Filter=") - text_array.append("JARS_Collection_Mode="+self.xml.find('Experiment/Process/JARS/JARS_Collection_Mode').text) - text_array.append("SAVE_DATA=YES") - text_array.append("*****************************************************") - return - if 'type' in param_field and param_field['type'] == 'rc_seq_config_params': # Get Acquisition System Parameters and add them - text_array.append("****************RC SEQUENCES******************") - return - if 'type' in param_field: - if param_field['type'] == 'pulse_enable': - txa_enable = self.xml.find_by_attribute_value('Experiment/Controller/Transmitters/TX', 'id', 'txa', 'Pulses') - if txa_enable.text is not None: - text_array.append('Pulse selection_TXA='+txa_enable.text) - txb_enable = self.xml.find_by_attribute_value('Experiment/Controller/Transmitters/TX', 'id', 'txb', 'Pulses') - if txb_enable.text is not None: - text_array.append('Pulse selection_TXB='+txb_enable.text) - tr_enable = self.xml.find('Experiment/Controller/IPP/Pulses') - if tr_enable.text is not None: - text_array.append('Pulse selection_TR='+tr_enable.text) - return - elif param_field['type'] == 'Line4' or param_field['type'] == 'Line5' or param_field['type'] == 'Line6' or param_field['type'] == 'Line7': - code_name = 'Code_A' - line_number = '4' - line_parenthesis = '' - line_prepend = '' - - if param_field['type'] == 'Line5': - code_name = 'Code_B' - line_number = '5' - line_parenthesis = ' (Line 5)' - line_prepend = 'L5_' - elif param_field['type'] == 'Line6': - code_name = 'Code_C' - line_number = '6' - line_parenthesis = ' (Line 6)' - line_prepend = 'L6_' - elif param_field['type'] == 'Line7': - code_name = 'Code_D' - line_number = '7' - line_parenthesis = ' (Line 7)' - line_prepend = 'L7_' - - code_channel = self.xml.find_by_attribute_value('Experiment/Controller/Code_channels/Code_channel', 'id', code_name, 'Mode').text - if code_channel == 'FLIP': - value = self.xml.find_by_attribute_value('Experiment/Controller/Code_channels/Code_channel', 'id', code_name, 'Flip').text - flip_name = 'L'+line_number+'_FLIP' + line_parenthesis - if param_field['type'] == 'Line5': - flip_name = 'FLIP1' - elif param_field['type'] == 'Line6': - flip_name = 'FLIP2' - text_array.append(flip_name + '='+value) - elif code_channel == 'CODE': - code_data = self.xml.find_by_attribute_value('Experiment/Controller/Code_channels/Code_channel', 'id', code_name, 'Code') - Code_reference = code_data.find('Code_reference').text - Code_select = code_data.find('Code_select').text - Code_number = code_data.find('Code_number').text - Code_bits = code_data.find('Code_bits').text - custom_codes = get_custom_code_data(Code_select, int(Code_number), int(Code_bits)) - text_array.append('Code Type' + line_parenthesis + '='+Code_select) - text_array.append('Number of Codes' + line_parenthesis + '='+Code_number) - text_array.append('Code Width' + line_parenthesis + '='+Code_bits) - for zero_idx, custom_code in enumerate(custom_codes): - text_array.append(line_prepend+'COD('+str(zero_idx)+')='+custom_code) - # Calculate Codes - text_array.append('L'+line_number+'_REFERENCE='+Code_reference.upper()) - elif code_channel == 'Sampling': - sampling_name = 'Sampling Windows (Line ' + line_number + ')' - prepend = 'L'+line_number+'_' - if param_field['type'] == 'Line7': - sampling_name = 'Sampling Windows' - prepend = '' - sampling_data = self.xml.find_by_attribute_value('Experiment/Controller/Code_channels/Code_channel', 'id', code_name, 'Sampling') - Code_reference = sampling_data.find('Code_reference').text.upper() - samples = sampling_data.find('Samples') - text_array.append(sampling_name+'='+str(len(samples))) - for zero_idx, sample in enumerate(samples): - text_array.append(prepend+'H0('+str(zero_idx)+')='+sample.find('FH').text) - text_array.append(prepend+'NSA('+str(zero_idx)+')='+sample.find('NSA').text) - text_array.append(prepend+'DH('+str(zero_idx)+')='+sample.find('DH').text) - text_array.append('L'+line_number+'_REFERENCE='+Code_reference.upper()) - elif code_channel == 'Synchro': - text_array.append('Line'+line_number+'=Synchro') - elif code_channel == 'Portion_Spec': - portion_data = self.xml.find_by_attribute_value('Experiment/Controller/Code_channels/Code_channel', 'id', code_name, 'PortionSpec') - periodic = portion_data.find('Periodic').text - portions = portion_data.find('Portions') - text_array.append('L'+line_number+' Number Of Portions='+str(len(portions))) - for zero_idx, portion in enumerate(portions): - text_array.append('PORTION_BEGIN('+str(zero_idx)+')='+portion.find('Begin_units').text) - text_array.append('PORTION_END('+str(zero_idx)+')='+portion.find('End_units').text) - if periodic == '1': - text_array.append('L'+line_number+' Portions IPP Periodic=YES') - else: - text_array.append('L'+line_number+' Portions IPP Periodic=NO') - return - elif param_field['type'] == 'txb_delays_info': - txb_delays = self.xml.find_by_attribute_value('Experiment/Controller/Transmitters/TX', 'id', 'txb', 'Delays') - text_array.append("Number of Taus="+str(len(txb_delays))) - for zero_index, txb_delay in enumerate(txb_delays): - text_array.append('TAU('+str(zero_index)+')='+str(txb_delay.text)) - return - elif param_field['type'] == 'cards_info': # Get Cards info - if not(acq_number_of_cards == '0'): - for card in range(acq_number_of_cards): - name = 'Card('+str(card)+')' - text_array.append(name + "=" + str(card)) - return - elif param_field['type'] == 'channels_info': # Get Channel info - text_array.append("Number of Channels="+str(number_of_acq_channels)) - if not(number_of_acq_channels == '0'): - acq_channels = self.xml.find('Experiment/Process/Acq_channel_selection') - enabled_channels = [] - channel_names =[] - for acq_channel in acq_channels: - acq_channel_number = acq_channel.get('id') - acq_channel_name = acq_channel.find('Name').text - enabled = False - if hasattr(acq_channel.find('Enabled'), 'text'): - enabled = acq_channel.find('Enabled').text - if enabled == 'on': - text_array.append("Channel("+acq_channel_number+")=" + str(int(acq_channel_number)+1)) - enabled_channels.append(acq_channel_number) - channel_names.append(acq_channel_name) - text_array.append("Antennas_Names="+str(len(enabled_channels))) - for index, channel in enumerate(enabled_channels): - text_array.append("AntennaName(" + str(int(channel)+1) + ")="+str(channel_names[index])) - return - if 'hide' in param_field and value in param_field['hide']: # Check to see if value should be written - return - text_array.append(name + "=" + self.get_field_value(param_field, value)) - - def convert_to_racp(self): - output = [] - # HEADER - for line in self.header['data']: - output.append(line) - output.append('HEADER VERSION='+self.header['version']) - # RADAR PARAMETERS - output.append(self.radar_param['header']) - for line in self.radar_param['data']: - output.append(line) - # SYSTEM PARAMETERS - output.append(self.system_param1['header']) - for line in self.system_param1['data']: - output.append(line) - output.append(self.system_param2['header']) - for line in self.system_param2['data']: - output.append(line) - # PROCESS PARAMETERS - output.append(self.process_param['header']) - for line in self.process_param['data']: - output.append(line) - - racp_content = "\n".join([str(x) for x in output]) - return racp_content - -def reduce_code_bits(code_bits, bits_per_code): - return code_bits[:bits_per_code] - -def zeropad_code_bits(code_bits, custom_bits_per_code): - return code_bits.ljust(custom_bits_per_code, "0") - - -def get_custom_code_data(codename, number_of_codes, bits_per_code): - import json - import copy - json_data=open('../js/pulse_code_values.json') - PD_pulse_codes = json.load(json_data) - selected_code = copy.copy(PD_pulse_codes[codename]) - - modified_binary_codes = [] - for i in range (number_of_codes): - if (i >= selected_code['number_of_codes']): - # We just repeat the first code. - modified_binary_codes.append(selected_code['binary_codes'][0]) - else: - modified_binary_codes.append(selected_code['binary_codes'][i]) - # Now adjust the width - if (bits_per_code <= selected_code['bits_per_code']): - modified_binary_codes = [reduce_code_bits(x, bits_per_code) for x in modified_binary_codes] - else: # Zero pad to the right - modified_binary_codes = [zeropad_code_bits(x, bits_per_code) for x in modified_binary_codes] - return modified_binary_codes - -class Pulse_Design_Mixed_Racp: - """A class to define the .racp output from Pulse Design """ - def __init__(self, number_of_experiments): - self.header = {'version': '1103'} - self.radar_param = {'header': '*****Radar Controller Parameters**********'} - self.system_param1 = {'header': '******System Parameters*******************'} - self.system_param2 = {'header': '******System Parameters*******************'} - self.process_param = {'header': '******Process Parameters******************'} - self.xml = None - self.number_of_experiments = number_of_experiments - self.header_fields = {} - self.radar_param_fields = {} - self.system_param1_fields = {} - self.system_param2_fields = {} - self.process_param_fields = {} - - for i in range(self.number_of_experiments): - self.header['data_experiment_number_'+str(i)] = [] - self.radar_param['data_experiment_number_'+str(i)] = [] - self.system_param1['data_experiment_number_'+str(i)] = [] - self.system_param2['data_experiment_number_'+str(i)] = [] - self.process_param['data_experiment_number_'+str(i)] = [] - - self.header_fields['indices_experiment_number_'+str(i)] = [] - self.radar_param_fields['indices_experiment_number_'+str(i)] = [] - self.system_param1_fields['indices_experiment_number_'+str(i)] = [] - self.system_param2_fields['indices_experiment_number_'+str(i)] = [] - self.process_param_fields['indices_experiment_number_'+str(i)] = [] - - self.header_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'EXPERIMENT TYPE', 'xml': 'Experiments/List/Experiment['+str(i)+']/XML_contents/Pulse_Design/Experiment/Process/Signal_pre_processing/Type_of_experiment'}) - self.header_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'EXPERIMENT NAME', 'xml': 'Experiments/List/Experiment['+str(i)+']/XML_contents/Pulse_Design/Experiment', 'xml_attr_value':'name'}) - self.radar_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'IPP', 'xml': 'Experiments/List/Experiment['+str(i)+']/XML_contents/Pulse_Design/Experiment/Controller/IPP/Width'}) - self.radar_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'NTX', 'xml': 'Experiments/List/Experiment['+str(i)+']/XML_contents/Pulse_Design/Experiment/Controller/NTX'}) - self.radar_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'TXA', 'xml': 'Experiments/List/Experiment['+str(i)+']/XML_contents/Pulse_Design/Experiment/Controller/Transmitters/TX', 'xml_attr':'id', 'xml_attr_find':'txa', 'xml_sub_pattern':'Width'}) - self.radar_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'TXB', 'xml': 'Experiments/List/Experiment['+str(i)+']/XML_contents/Pulse_Design/Experiment/Controller/Transmitters/TX', 'xml_attr':'id', 'xml_attr_find':'txb', 'xml_sub_pattern':'Width'}) - self.radar_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': '***', 'xml':'', 'type':'pulse_enable'}) - self.radar_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': '***', 'xml':'', 'type': 'Line4'}) - self.radar_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': '***', 'xml':'', 'type': 'Line5'}) - self.radar_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': '***', 'xml':'', 'type': 'Line6'}) - self.radar_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': '***', 'xml':'', 'type':'txb_delays_info'}) - self.radar_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': '***', 'xml':'', 'type': 'Line7'}) - self.radar_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'SAMPLING REFERENCE', 'xml':'Experiments/List/Experiment['+str(i)+']/XML_contents/Pulse_Design/Experiment/Controller/Ctl_Setting/Sampling_reference'}) - self.radar_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'RELOJ', 'xml':'Experiments/List/Experiment['+str(i)+']/XML_contents/Pulse_Design/Experiment/Controller/Clock/Clock_final'}) - self.radar_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'CLOCK DIVIDER', 'xml':'Experiments/List/Experiment['+str(i)+']/XML_contents/Pulse_Design/Experiment/Controller/Clock/Clock_div', 'hide':['1']}) - self.radar_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'TR_BEFORE', 'xml':'Experiments/List/Experiment['+str(i)+']/XML_contents/Pulse_Design/Experiment/Controller/Spc_Setting/Time_before'}) - self.radar_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'TR_AFTER', 'xml':'Experiments/List/Experiment['+str(i)+']/XML_contents/Pulse_Design/Experiment/Controller/Spc_Setting/Time_after'}) - self.radar_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'WINDOW IN LINE 5&6', 'xml':'', 'value':'NO'}) - self.radar_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'SYNCHRO DELAY', 'xml':'Experiments/List/Experiment['+str(i)+']/XML_contents/Pulse_Design/Experiment/Controller/Spc_Setting/Sync_delay', 'hide':['0']}) - self.system_param1_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'Number of Cards', 'xml':'Experiments/List/Experiment['+str(i)+']/XML_contents/Pulse_Design/Experiment/Process/JARS/Number_of_cards', 'hide':['0']}) - self.system_param1_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': '***', 'xml':'', 'type':'cards_info'}) - self.system_param1_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': '***', 'xml':'', 'type':'channels_info'}) - self.system_param1_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'RAW DATA DIRECTORY', 'xml':'Experiments/List/Experiment['+str(i)+']/XML_contents/Pulse_Design/Experiment/Process/Data_storage/Directory'}) - self.system_param1_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'CREATE DIRECTORY PER DAY', 'xml':'Experiments/List/Experiment['+str(i)+']/XML_contents/Pulse_Design/Experiment/Process/Data_storage/Directory_per_day', 'type':'checkbox_YES_NO'}) - self.system_param1_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'INCLUDE EXPNAME IN DIRECTORY', 'xml':'Experiments/List/Experiment['+str(i)+']/XML_contents/Pulse_Design/Experiment/Process/Data_storage/Expname_in_directory', 'type':'checkbox_YES_NO'}) - self.system_param2_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'ADC Resolution', 'xml':'', 'value':'12'})# Default is 8, JARS is 12 - self.system_param2_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'PCI DIO BusWidth', 'xml':'', 'value':'32'}) # Default for JARS - self.system_param2_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'RAW DATA BLOCKS', 'xml':'Experiments/List/Experiment['+str(i)+']/XML_contents/Pulse_Design/Experiment/Process/Data_arrangement/Data_blocks'}) - self.process_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'DATATYPE', 'xml': 'Experiments/List/Experiment['+str(i)+']/XML_contents/Pulse_Design/Experiment/Process/Signal_pre_processing/Type_of_data'}) - self.process_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'DATA ARRANGE', 'xml':'', 'value':'CONTIGUOUS_CH'}) - self.process_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'COHERENT INTEGRATION STRIDE', 'xml':'Experiments/List/Experiment['+str(i)+']/XML_contents/Pulse_Design/Experiment/Process/Signal_pre_processing/Integration_stride'}) - self.process_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': '------------------', 'xml':'', 'type':'separator'}) - self.process_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'ACQUIRED PROFILES', 'xml':'Experiments/List/Experiment['+str(i)+']/XML_contents/Pulse_Design/Experiment/Process/Data_arrangement/Acquired_profiles'}) - self.process_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'PROFILES PER BLOCK', 'xml':'Experiments/List/Experiment['+str(i)+']/XML_contents/Pulse_Design/Experiment/Process/Data_arrangement/Profiles_per_block'}) - self.process_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': '------------------', 'xml':'', 'type':'separator'}) - self.process_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'BEGIN ON START', 'xml':'Experiments/List/Experiment['+str(i)+']/XML_contents/Pulse_Design/Experiment/Process/Schedule/Begin_on_Start', 'type': 'checkbox_YES_NO'}) - self.process_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'BEGIN_TIME', 'xml':'Experiments/List/Experiment['+str(i)+']/XML_contents/Pulse_Design/Experiment/Process/Schedule/Start', 'hide':['']}) - self.process_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'END_TIME', 'xml':'Experiments/List/Experiment['+str(i)+']/XML_contents/Pulse_Design/Experiment/Process/Schedule/End', 'hide':['']}) - self.process_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'VIEW RAW DATA', 'xml':'Experiments/List/Experiment['+str(i)+']/XML_contents/Pulse_Design/Experiment/Process/Data_arrangement/View_raw_data', 'type': 'checkbox_YES_NO'}) - self.process_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'REFRESH RATE', 'xml':'', 'value':'1'}) - self.process_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': '------------------', 'xml':'', 'type':'separator'}) - self.process_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'SEND STATUS TO FTP', 'xml':'', 'type':'checkbox_YES_NO', 'value':'NO'}) - self.process_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'FTP SERVER', 'xml':'', 'hide':[None, '']}) - self.process_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'FTP USER', 'xml':'', 'hide':[None, '']}) - self.process_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'FTP PASSWD', 'xml':'', 'hide':[None, '']}) - self.process_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'FTP DIR', 'xml':'', 'hide':[None, '']}) - self.process_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'FTP FILE', 'xml':'', 'hide':[None, '']}) - self.process_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'FTP INTERVAL', 'xml':'', 'hide':[None, '']}) - self.process_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'SAVE STATUS AND BLOCK', 'xml':'', 'type':'checkbox_YES_NO', 'value':'NO'}) - self.process_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'GENERATE RTI', 'xml':'', 'type':'checkbox_YES_NO', 'value':'NO'}) - self.process_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'SEND RTI AND BLOCK', 'xml':'Process_acquired_profiles', 'type':'checkbox_YES_NO'}) - self.process_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'FTP INTERVAL', 'xml':'', 'value':'60'}) - self.process_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': '------------------', 'xml':'', 'type':'separator'}) - self.process_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'COMPORT CONFIG', 'xml':'', 'value':'Com1 CBR_9600 TWOSTOPBITS NOPARITY'}) - self.process_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'JAM CONFIGURE FILE', 'xml':'', 'value':''}) - self.process_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'ACQUISITION SYSTEM', 'xml':'', 'value':'JARS'}) - self.process_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': '******************', 'xml':'', 'type':'acq_system_config_params'}) - self.process_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'SAVE DATA', 'xml':'', 'value':'YES'}) - self.process_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': '******************', 'xml':'', 'type':'rc_seq_config_params'}) - self.process_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'RC_STOP_SEQUENCE', 'xml':'', 'value':'255,0,255,8'}) - self.process_param_fields['indices_experiment_number_'+str(i)].append({'number_experiment': i,'name': 'RC_START_SEQUENCE', 'xml':'', 'value':'255,24'}) - def get_field_value(self, field, user_value): - if 'type' in field and field['type'] == 'checkbox_YES_NO': # Check for existence of value - if (user_value is None) or (user_value == 'None'): - user_value = 'NO' - elif user_value == 'on': - user_value = 'YES' - if 'value' in field and not(user_value): # Replace by default value - user_value = field['value'] - if 'extra' in field and field['extra'] == 'upper': # Uppercase values - user_value = user_value.upper() - return str(user_value) - - def load_xml(self, xml): - self.xml = xml - for i in range(self.number_of_experiments): - for field in self.header_fields['indices_experiment_number_'+str(i)]: - self.add_line_output(self.header['data_experiment_number_'+str(i)], field) - for field in self.radar_param_fields['indices_experiment_number_'+str(i)]: - self.add_line_output(self.radar_param['data_experiment_number_'+str(i)], field) - for field in self.system_param1_fields['indices_experiment_number_'+str(i)]: - self.add_line_output(self.system_param1['data_experiment_number_'+str(i)], field) - for field in self.system_param2_fields['indices_experiment_number_'+str(i)]: - self.add_line_output(self.system_param2['data_experiment_number_'+str(i)], field) - for field in self.process_param_fields['indices_experiment_number_'+str(i)]: - self.add_line_output(self.process_param['data_experiment_number_'+str(i)], field) - - - - def add_line_output(self, text_array, param_field): - - name = param_field['name'] - xml_l = param_field['xml'] - id = str(param_field['number_experiment']) - acq_number_of_cards = int(self.xml.find('Experiments/List/Experiment['+id+']/XML_contents/Pulse_Design/Experiment/Process/JARS/Number_of_cards').text) - acq_channels_per_card = int(self.xml.find('Experiments/List/Experiment['+id+']/XML_contents/Pulse_Design/Experiment/Process/JARS/Channels_per_card').text) - number_of_acq_channels = acq_number_of_cards * acq_channels_per_card - - - - if 'xml_attr' in param_field and 'xml_attr_find' in param_field: - sub_pattern = False - if 'xml_sub_pattern' in param_field: - sub_pattern = param_field['xml_sub_pattern'] - element = self.xml.find_by_attribute_value(xml_l, param_field['xml_attr'], param_field['xml_attr_find'],sub_pattern) - else: - element = self.xml.find(xml_l) - - if 'xml_attr_value' in param_field: - value = element.get(param_field['xml_attr_value']) - else: - value = '' - if xml_l == '' and 'value' in param_field: - value = param_field['value'] - elif hasattr(element, 'text'): - value = element.text - - if 'type' in param_field and param_field['type'] == 'separator': # Check for existence of value - text_array.append('------------------------------------------') - return - if 'type' in param_field and param_field['type'] == 'acq_system_config_params': # Get Acquisition System Parameters and add them - text_array.append("************JARS CONFIGURATION PARAMETERS************") - if self.xml.find('Experiments/List/Experiment['+id+']/XML_contents/Pulse_Design/Experiment/Process/JARS/Filter').text: - # Notice that we need to use backslashes for the filter path - text_array.append("Jars_Filter="+self.xml.find('Experiments/List/Experiment['+id+']/XML_contents/Pulse_Design/Experiment/Process/JARS/Filter_dir').text +'\\'+ self.xml.find('Experiments/List/Experiment['+id+']/XML_contents/Pulse_Design/Experiment/Process/JARS/Filter').text) - else: - text_array.append("Jars_Filter=") - text_array.append("JARS_Collection_Mode="+self.xml.find('Experiments/List/Experiment['+id+']/XML_contents/Pulse_Design/Experiment/Process/JARS/JARS_Collection_Mode').text) - text_array.append("SAVE_DATA=YES") - text_array.append("*****************************************************") - return - if 'type' in param_field and param_field['type'] == 'rc_seq_config_params': # Get Acquisition System Parameters and add them - text_array.append("****************RC SEQUENCES******************") - return - ##{'name': '***', 'xml':'', 'type':'pulse_enable'}, - if 'type' in param_field: - if param_field['type'] == 'pulse_enable': - txa_enable = self.xml.find_by_attribute_value('Experiments/List/Experiment['+id+']/XML_contents/Pulse_Design/Experiment/Controller/Transmitters/TX', 'id', 'txa', 'Pulses') - if txa_enable.text is not None: - text_array.append('Pulse selection_TXA='+txa_enable.text) - txb_enable = self.xml.find_by_attribute_value('Experiments/List/Experiment['+id+']/XML_contents/Pulse_Design/Experiment/Controller/Transmitters/TX', 'id', 'txb', 'Pulses') - if txb_enable.text is not None: - text_array.append('Pulse selection_TXB='+txb_enable.text) - tr_enable = self.xml.find('Experiments/List/Experiment['+id+']/XML_contents/Pulse_Design/Experiment/Controller/IPP/Pulses') - if tr_enable.text is not None: - text_array.append('Experiments/List/Experiment['+id+']/XML_contents/Pulse_Design/Pulse selection_TR='+tr_enable.text) - return - elif param_field['type'] == 'Line4' or param_field['type'] == 'Line5' or param_field['type'] == 'Line6' or param_field['type'] == 'Line7': - code_name = 'Code_A' - line_number = '4' - line_parenthesis = '' - line_prepend = '' - - if param_field['type'] == 'Line5': - code_name = 'Code_B' - line_number = '5' - line_parenthesis = ' (Line 5)' - line_prepend = 'L5_' - elif param_field['type'] == 'Line6': - code_name = 'Code_C' - line_number = '6' - line_parenthesis = ' (Line 6)' - line_prepend = 'L6_' - elif param_field['type'] == 'Line7': - code_name = 'Code_D' - line_number = '7' - line_parenthesis = ' (Line 7)' - line_prepend = 'L7_' - - code_channel = self.xml.find_by_attribute_value('Experiments/List/Experiment['+id+']/XML_contents/Pulse_Design/Experiment/Controller/Code_channels/Code_channel', 'id', code_name, 'Mode').text - if code_channel == 'FLIP': - value = self.xml.find_by_attribute_value('Experiments/List/Experiment['+id+']/XML_contents/Pulse_Design/Experiment/Controller/Code_channels/Code_channel', 'id', code_name, 'Flip').text - flip_name = 'L'+line_number+'_FLIP' + line_parenthesis - if param_field['type'] == 'Line5': - flip_name = 'FLIP1' - elif param_field['type'] == 'Line6': - flip_name = 'FLIP2' - text_array.append(flip_name + '='+value) - elif code_channel == 'CODE': - code_data = self.xml.find_by_attribute_value('Experiments/List/Experiment['+id+']/XML_contents/Pulse_Design/Experiment/Controller/Code_channels/Code_channel', 'id', code_name, 'Code') - Code_reference = code_data.find('Code_reference').text - Code_select = code_data.find('Code_select').text - Code_number = code_data.find('Code_number').text - Code_bits = code_data.find('Code_bits').text - custom_codes = get_custom_code_data(Code_select, int(Code_number), int(Code_bits)) - text_array.append('Code Type' + line_parenthesis + '='+Code_select) - text_array.append('Number of Codes' + line_parenthesis + '='+Code_number) - text_array.append('Code Width' + line_parenthesis + '='+Code_bits) - for zero_idx, custom_code in enumerate(custom_codes): - text_array.append(line_prepend+'COD('+str(zero_idx)+')='+custom_code) - # Calculate Codes - text_array.append('L'+line_number+'_REFERENCE='+Code_reference.upper()) - elif code_channel == 'Sampling': - sampling_name = 'Sampling Windows (Line ' + line_number + ')' - prepend = 'L'+line_number+'_' - if param_field['type'] == 'Line7': - sampling_name = 'Sampling Windows' - prepend = '' - sampling_data = self.xml.find_by_attribute_value('Experiments/List/Experiment['+id+']/XML_contents/Pulse_Design/Experiment/Controller/Code_channels/Code_channel', 'id', code_name, 'Sampling') - Code_reference = sampling_data.find('Code_reference').text.upper() - samples = sampling_data.find('Samples') - text_array.append(sampling_name+'='+str(len(samples))) - for zero_idx, sample in enumerate(samples): - text_array.append(prepend+'H0('+str(zero_idx)+')='+sample.find('FH').text) - text_array.append(prepend+'NSA('+str(zero_idx)+')='+sample.find('NSA').text) - text_array.append(prepend+'DH('+str(zero_idx)+')='+sample.find('DH').text) - text_array.append('L'+line_number+'_REFERENCE='+Code_reference.upper()) - elif code_channel == 'Synchro': - text_array.append('Line'+line_number+'=Synchro') - elif code_channel == 'Portion_Spec': - portion_data = self.xml.find_by_attribute_value('Experiments/List/Experiment['+id+']/XML_contents/Pulse_Design/Experiment/Controller/Code_channels/Code_channel', 'id', code_name, 'PortionSpec') - periodic = portion_data.find('Periodic').text - portions = portion_data.find('Portions') - text_array.append('L'+line_number+' Number Of Portions='+str(len(portions))) - for zero_idx, portion in enumerate(portions): - text_array.append('PORTION_BEGIN('+str(zero_idx)+')='+portion.find('Begin_units').text) - text_array.append('PORTION_END('+str(zero_idx)+')='+portion.find('End_units').text) - if periodic == '1': - text_array.append('L'+line_number+' Portions IPP Periodic=YES') - else: - text_array.append('L'+line_number+' Portions IPP Periodic=NO') - return - elif param_field['type'] == 'txb_delays_info': - txb_delays = self.xml.find_by_attribute_value('Experiments/List/Experiment['+id+']/XML_contents/Pulse_Design/Experiment/Controller/Transmitters/TX', 'id', 'txb', 'Delays') - text_array.append("Number of Taus="+str(len(txb_delays))) - for zero_index, txb_delay in enumerate(txb_delays): - text_array.append('TAU('+str(zero_index)+')='+str(txb_delay.text)) - return - elif param_field['type'] == 'cards_info': # Get Cards info - if not(acq_number_of_cards == '0'): - for card in range(acq_number_of_cards): - name = 'Card('+str(card)+')' - text_array.append(name + "=" + str(card)) - return - elif param_field['type'] == 'channels_info': # Get Channel info - text_array.append("Number of Channels="+str(number_of_acq_channels)) - if not(number_of_acq_channels == '0'): - acq_channels = self.xml.find('Experiments/List/Experiment['+id+']/XML_contents/Pulse_Design/Experiment/Process/Acq_channel_selection') - enabled_channels = [] - channel_names =[] - for acq_channel in acq_channels: - acq_channel_number = acq_channel.get('id') - acq_channel_name = acq_channel.find('Name').text - enabled = False - if hasattr(acq_channel.find('Enabled'), 'text'): - enabled = acq_channel.find('Enabled').text - if enabled == 'on': - text_array.append("Channel("+acq_channel_number+")=" + str(int(acq_channel_number)+1)) - enabled_channels.append(acq_channel_number) - channel_names.append(acq_channel_name) - text_array.append("Antennas_Names="+str(len(enabled_channels))) - for index, channel in enumerate(enabled_channels): - text_array.append("AntennaName(" + str(int(channel)+1) + ")="+str(channel_names[index])) - return - if 'hide' in param_field and value in param_field['hide']: # Check to see if value should be written - return - text_array.append(name + "=" + self.get_field_value(param_field, value)) - - def convert_to_racp(self): - output = [] - # HEADER - for i in range(self.number_of_experiments): - for line in self.header['data_experiment_number_'+str(i)]: - output.append(line) - output.append('HEADER VERSION='+self.header['version']) - # RADAR PARAMETERS - output.append(self.radar_param['header']) - for line in self.radar_param['data_experiment_number_'+str(i)]: - output.append(line) - # SYSTEM PARAMETERS - output.append(self.system_param1['header']) - for line in self.system_param1['data_experiment_number_'+str(i)]: - output.append(line) - output.append(self.system_param2['header']) - for line in self.system_param2['data_experiment_number_'+str(i)]: - output.append(line) - # PROCESS PARAMETERS - output.append(self.process_param['header']) - for line in self.process_param['data_experiment_number_'+str(i)]: - output.append(line) - output.append("\n") +import json +import numpy as np +import matplotlib.pyplot as plt - racp_content = "\n".join([str(x) for x in output]) - return racp_content class RCFile(object): + ''' + Class to handle Radar controller configuration files + ''' def __init__(self, f=None): @@ -660,6 +27,10 @@ class RCFile(object): self.parse_racp() elif 'dat' in self.name: self.parse_dat() + elif 'json' in self.name: + self.data = json.load(self.f) + + self.f.close() def get_line_parameters(self, data, line): @@ -673,39 +44,61 @@ class RCFile(object): data = {} raw_data = [s.strip() for s in self.f.readlines()] + for line in raw_data: if line and '=' in line: label, value = line.strip().split('=') data[label] = value + self.data['experiment_type'] = data['EXPERIMENT TYPE'] self.data['header_version'] = data['HEADER VERSION'] self.data['name'] = data['EXPERIMENT NAME'] self.data['ipp'] = float(data['IPP']) self.data['ntx'] = int(data['NTX']) + if 'CLOCK DIVIDER' in data: self.data['clock_divider'] = int(data['CLOCK DIVIDER']) else: self.data['clock_divider'] = 1 - self.data['clock'] = float(data['RELOJ'])*self.data['clock_divider'] + self.data['clock_in'] = float(data['RELOJ'])*self.data['clock_divider'] + self.data['clock'] = float(data['RELOJ']) self.data['time_before'] = int(data['TR_BEFORE']) self.data['time_after'] = int(data['TR_AFTER']) + if 'SYNCHRO DELAY' in data: self.data['sync'] = int(data['SYNCHRO DELAY']) else: self.data['sync'] = 0 self.data['lines'] = [] - + + if 'SAMPLING REFERENCE' in data: + if data['SAMPLING REFERENCE']=='MIDDLE OF FIRST BAUD': + self.data['sampling_reference'] = 'first_baud' + elif data['SAMPLING REFERENCE']=='MIDDLE OF FIRST SUB-BAUD': + self.data['sampling_reference'] = 'sub_baud' + else: + self.data['sampling_reference'] = 'none' + #Add TR line if 'Pulse selection_TR' in data: - if 'A' in data['Pulse selection_TR']: + if 'A,' in data['Pulse selection_TR']: + rng = data['Pulse selection_TR'].replace('A,', '') + ref = 'TXA' + elif 'A' in data['Pulse selection_TR']: rng = data['Pulse selection_TR'].replace('A', '') + ref = 'TXA' + elif 'B,' in data['Pulse selection_TR']: + rng = data['Pulse selection_TR'].replace('B,', '') + ref = 'TXB' elif 'B' in data['Pulse selection_TR']: rng = data['Pulse selection_TR'].replace('B', '') + ref = 'TXB' else: rng = data['Pulse selection_TR'] - line = {'type':'tr', 'range': rng, 'TX_ref':'TXA'} + ref = '0' + line = {'type':'tr', 'range': rng if rng else '0', 'TX_ref':ref} else: - line = {'type': 'tr', 'range': 0, 'TX_ref': '0'} + line = {'type': 'tr', 'range': '0', 'TX_ref': '0'} self.data['lines'].append(line) @@ -717,7 +110,9 @@ class RCFile(object): else: line['range'] = '0' self.data['lines'].append(line) - + else: + self.data['lines'].append({'type':'tx', 'pulse_width':'0', 'delays':'0', 'range':'0'}) + if 'TXB' in data: line = {'type':'tx', 'pulse_width':data['TXB'], 'delays':'0'} if 'Pulse selection_TXB' in data: @@ -730,6 +125,8 @@ class RCFile(object): line['delays'] = ','.join(delays) self.data['lines'].append(line) + else: + self.data['lines'].append({'type':'tx', 'pulse_width':'0', 'delays':'0', 'range':'0'}) #Add Other lines (4-6) for n in range(4, 7): @@ -740,8 +137,12 @@ class RCFile(object): line = {'type':'flip', 'number_of_flips':data['L%d_FLIP' % n]} elif 'Code Type' in data and n==4: line = {'type':'codes', 'code':data['Code Type'], 'TX_ref':data['L%d_REFERENCE' % n]} + if 'Number of Codes' in data: + line['codes'] = [data['COD({})'.format(x)] for x in range(int(data['Number of Codes']))] elif 'Code Type (Line %d)' % n in labels: line = {'type':'codes', 'code':data['Code Type (Line %d)' % n], 'TX_ref':data['L%d_REFERENCE' % n]} + if 'Number of Codes (Line %d)' % n in data: + line['codes'] = [data['L{}_COD({})'.format(n, x)] for x in range(int(data['Number of Codes (Line %d)' % n]))] elif 'Sampling Windows (Line %d)' % n in data: line = {'type':'windows', 'TX_ref':data['L%d_REFERENCE' % n]} windows = [] @@ -800,13 +201,13 @@ class RCFile(object): def parse_dat(self): pass - + def get_json(self, indent=None): return json.dumps(self.data, indent=indent) -def pulses_to_bar(X): +def pulses_to_points(X): d = X[1:]-X[:-1] @@ -881,7 +282,7 @@ def pulses(X, period, width, delay=0, before=0, after=0, sync=0, shift=0): if shift>0: y = np.empty_like(Y) y[:shift] = 0 - y[shift:] = Y[:-shift] + y[shift:] = Y[:-shift] return y else: return Y @@ -891,34 +292,21 @@ def plot_pulses(unit, maximun, lines): from bokeh.resources import CDN from bokeh.embed import components - from bokeh.mpl import to_bokeh - from bokeh.plotting import figure + from bokeh.mpl import to_bokeh from bokeh.models.tools import WheelZoomTool, ResetTool, PanTool, PreviewSaveTool - N = len(lines) fig = plt.figure(figsize=(10, 2+N*0.5)) ax = fig.add_subplot(111) labels = [] - data = [] + for i, line in enumerate(lines): print line labels.append(line.get_name()) - ax.broken_barh(pulses_to_bar(line.pulses_as_array()), (N-i-1, 0.5), + ax.broken_barh(pulses_to_points(line.pulses_as_array()), (N-i-1, 0.5), edgecolor='none', facecolor='#2c3e50') - #data.append(line.pulses_as_array()) - - - #labels.append('{:3.2f} Km'.format(unit*100)) - #ax.broken_barh(pulses_to_bar(pulses(np.arange(0, maximun), 200, 100)), (0, 0.5), - # edgecolor='none', facecolor='#ae3910') - - - #ax.pcolor(data, cmap=cm.Blues, vmin=0, vmax=1) - + labels.reverse() - #plot = figure(x_range=[0, maximun], y_range=[0, N]) - #plot.image(image=[np.logical_not(data).astype(np.int8)], x=[0], y=[0], dh=[N], dw=[maximun], palette='Blues9') ax.set_yticklabels(labels) plot = to_bokeh(fig, use_pandas=False) plot.tools = [PanTool(dimensions=['width']), WheelZoomTool(dimensions=['width']), ResetTool(), PreviewSaveTool()] diff --git a/apps/rc/views.py b/apps/rc/views.py index f9b2540..f1b934e 100644 --- a/apps/rc/views.py +++ b/apps/rc/views.py @@ -1,3 +1,4 @@ + import json from django.contrib import messages @@ -8,8 +9,8 @@ from apps.main.models import Configuration, Experiment, Device from apps.main.views import sidebar from .models import RCConfiguration, RCLine, RCLineType, RCLineCode -from .forms import RCConfigurationForm, RCLineForm, RCLineViewForm, RCLineEditForm, RCSubLineEditForm, RCImportForm -from .utils import RCFile, plot_pulses +from .forms import RCConfigurationForm, RCLineForm, RCLineViewForm, RCLineEditForm, RCImportForm, RCLineCodesForm +from .utils import plot_pulses def conf(request, conf_id): @@ -27,8 +28,8 @@ def conf(request, conf_id): kwargs = {} kwargs['dev_conf'] = conf kwargs['rc_lines'] = lines - kwargs['dev_conf_keys'] = ['name', 'ipp', 'ntx', 'clock', 'clock_divider', - 'time_before', 'time_after', 'sync'] + kwargs['dev_conf_keys'] = ['name', 'ipp', 'ntx', 'clock_in', 'clock_divider', 'clock', + 'time_before', 'time_after', 'sync', 'sampling_reference', 'control_tx', 'control_sw'] kwargs['title'] = 'RC Configuration' kwargs['suptitle'] = 'Details' @@ -46,21 +47,14 @@ def conf_edit(request, conf_id): lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel') - for line in lines: - line_type = get_object_or_404(RCLineType, pk=line.line_type.id) - extra_fields = json.loads(line_type.params) - params = json.loads(line.params) - for item, values in extra_fields.items(): - if item=='params': - continue - values['value'] = params[item] - - line.form = RCLineEditForm(initial={'rc_configuration':conf_id, 'line_type': line.line_type.id, 'line': line.id}, - extra_fields=extra_fields) + for line in lines: + params = json.loads(line.params) + line.form = RCLineEditForm(conf=conf, line=line, extra_fields=params) + line.subform = False if 'params' in params: + line.subforms = [RCLineEditForm(extra_fields=fields, line=line, subform=i) for i, fields in enumerate(params['params'])] line.subform = True - line.subforms = [RCSubLineEditForm(extra_fields=fields, line=line.id, count=i) for i, fields in enumerate(params['params'])] if request.method=='GET': @@ -76,22 +70,26 @@ def conf_edit(request, conf_id): for label,value in request.POST.items(): if label=='csrfmiddlewaretoken': continue + if label.count('|')==0: conf_data[label] = value continue - elif label.count('|')==2: + + elif label.split('|')[0]<>'-1': extras.append(label) continue - pk, name = label.split('|') - + x, pk, name = label.split('|') + + if name=='codes': + value = [s for s in value.split('\r\n') if s] + if pk in line_data: line_data[pk][name] = value else: line_data[pk] = {name:value} #update conf - form = RCConfigurationForm(conf_data, instance=conf) if form.is_valid(): @@ -125,7 +123,7 @@ def conf_edit(request, conf_id): line.update_pulses() for tr in conf.get_lines('tr'): - tr.update_pulses() + tr.update_pulses() messages.success(request, 'RC Configuration successfully updated') @@ -147,21 +145,29 @@ def conf_edit(request, conf_id): return render(request, 'rc_conf_edit.html', kwargs) -def add_line(request, conf_id, line_type_id=None): +def add_line(request, conf_id, line_type_id=None, code_id=None): conf = get_object_or_404(RCConfiguration, pk=conf_id) if request.method=='GET': if line_type_id: line_type = get_object_or_404(RCLineType, pk=line_type_id) - form = RCLineForm(initial={'rc_configuration':conf_id, 'line_type': line_type_id}, - extra_fields=json.loads(line_type.params)) + + if code_id: + form = RCLineForm(initial={'rc_configuration':conf_id, 'line_type': line_type_id, 'code_id': code_id}, + extra_fields=json.loads(line_type.params)) + else: + form = RCLineForm(initial={'rc_configuration':conf_id, 'line_type': line_type_id}, + extra_fields=json.loads(line_type.params)) else: + line_type = {'id':0} form = RCLineForm(initial={'rc_configuration':conf_id}) if request.method=='POST': + line_type = get_object_or_404(RCLineType, pk=line_type_id) - form = RCLineForm(request.POST, extra_fields=json.loads(line_type.params)) + form = RCLineForm(request.POST, + extra_fields=json.loads(line_type.params)) if form.is_valid(): form.save() @@ -175,11 +181,51 @@ def add_line(request, conf_id, line_type_id=None): kwargs['button'] = 'Add' kwargs['previous'] = conf.get_absolute_url_edit() kwargs['dev_conf'] = conf + kwargs['line_type'] = line_type kwargs.update(sidebar(conf)) return render(request, 'rc_add_line.html', kwargs) +def edit_codes(request, conf_id, line_id, code_id=None): + + conf = get_object_or_404(RCConfiguration, pk=conf_id) + line = get_object_or_404(RCLine, pk=line_id) + params = json.loads(line.params) + + if request.method=='GET': + if code_id: + code = get_object_or_404(RCLineCode, pk=code_id) + form = RCLineCodesForm(instance=code) + else: + initial = {'code': params['code'], + 'codes': params['codes'] if 'codes' in params else [], + 'number_of_codes': len(params['codes']) if 'codes' in params else 0, + 'bits_per_code': len(params['codes'][0]) if 'codes' in params else 0, + } + form = RCLineCodesForm(initial=initial) + + if request.method=='POST': + form = RCLineCodesForm(request.POST) + if form.is_valid(): + params['code'] = request.POST['code'] + params['codes'] = [s for s in request.POST['codes'].split('\r\n') if s] + line.params = json.dumps(params) + line.save() + messages.success(request, 'Line: "%s" has been updated.' % line) + return redirect('url_edit_rc_conf', conf.id) + + kwargs = {} + kwargs['form'] = form + kwargs['title'] = line + kwargs['suptitle'] = 'Edit' + kwargs['button'] = 'Update' + kwargs['dev_conf'] = conf + kwargs['previous'] = conf.get_absolute_url_edit() + kwargs['line'] = line + + return render(request, 'rc_edit_codes.html', kwargs) + def add_subline(request, conf_id, line_id): conf = get_object_or_404(RCConfiguration, pk=conf_id) @@ -188,13 +234,12 @@ def add_subline(request, conf_id, line_id): if request.method == 'POST': if line: params = json.loads(line.params) - if 'params' in params: - subparams = json.loads(line.line_type.params) - base = [p for p in subparams if p['name']=='params'][0]['form'] - new = {} - for p in base: - new[p['name']] = p['value'] - params['params'].append(new) + subparams = json.loads(line.line_type.params) + if 'params' in subparams: + dum = {} + for key, value in subparams['params'].items(): + dum[key] = value['value'] + params['params'].append(dum) line.params = json.dumps(params) line.save() return redirect('url_edit_rc_conf', conf.id) @@ -234,6 +279,7 @@ def remove_line(request, conf_id, line_id): kwargs['previous'] = conf.get_absolute_url_edit() return render(request, 'confirm.html', kwargs) + def remove_subline(request, conf_id, line_id, subline_id): conf = get_object_or_404(RCConfiguration, pk=conf_id) @@ -273,13 +319,19 @@ def update_lines_position(request, conf_id): lines = RCLine.objects.filter(rc_configuration=conf).order_by('channel') for line in lines: - line.form = RCLineViewForm(extra_fields=json.loads(line.params)) + params = json.loads(line.params) + line.form = RCLineEditForm(conf=conf, line=line, extra_fields=params) + + if 'params' in params: + line.subform = True + line.subforms = [RCLineEditForm(extra_fields=fields, line=line, subform=i) for i, fields in enumerate(params['params'])] - html = render(request, 'rc_lines.html', {'rc_lines':lines, 'edit':True}) + html = render(request, 'rc_lines.html', {'dev_conf':conf, 'rc_lines':lines, 'edit':True}) data = {'html': html.content} return HttpResponse(json.dumps(data), content_type="application/json") return redirect('url_edit_rc_conf', conf.id) + def import_file(request, conf_id): @@ -289,59 +341,17 @@ def import_file(request, conf_id): if form.is_valid(): #try: if True: - f = RCFile(request.FILES['file_name']) - data = f.data - conf.ipp = data['ipp'] - conf.ntx = data['ntx'] - conf.clock = data['clock'] - conf.clock_divider = data['clock_divider'] - conf.time_before = data['time_before'] - conf.time_after = data['time_after'] - conf.sync = data['sync'] - conf.save() - lines = [] - positions = {'tx':0, 'tr':0} - for i, line_data in enumerate(data['lines']): - line_type = RCLineType.objects.get(name=line_data.pop('type')) - if line_type.name=='codes': - code = RCLineCode.objects.get(name=line_data['code']) - line_data['code'] = code.pk - line = RCLine.objects.filter(rc_configuration=conf, channel=i) - if line: - line = line[0] - line.line_type = line_type - line.params = json.dumps(line_data) - else: - line = RCLine(rc_configuration=conf, line_type=line_type, - params=json.dumps(line_data), - channel=i) - - if line_type.name=='tx': - line.position = positions['tx'] - positions['tx'] += 1 - - if line_type.name=='tr': - line.position = positions['tr'] - positions['tr'] += 1 - - line.save() - lines.append(line) - - for line, line_data in zip(lines, data['lines']): - if 'TX_ref' in line_data: - params = json.loads(line.params) - params['TX_ref'] = [l.pk for l in lines if l.line_type.name=='tx' and l.get_name().replace(' ', '')==line_data['TX_ref']][0] - line.params = json.dumps(params) - line.save() - + conf.update_from_file(request.FILES['file_name']) + conf.save() + for line in conf.get_lines(): if line.line_type.name=='tr': continue line.update_pulses() for tr in conf.get_lines('tr'): - tr.update_pulses() + tr.update_pulses() messages.success(request, 'Configuration "%s" loaded succesfully' % request.FILES['file_name']) return redirect(conf.get_absolute_url()) @@ -351,8 +361,7 @@ def import_file(request, conf_id): else: messages.warning(request, 'Your current configuration will be replaced') - form = RCImportForm() - + form = RCImportForm() kwargs = {} kwargs['form'] = form @@ -362,7 +371,7 @@ def import_file(request, conf_id): kwargs['previous'] = conf.get_absolute_url() return render(request, 'rc_import.html', kwargs) - + def view_pulses(request, conf_id): @@ -373,17 +382,14 @@ def view_pulses(request, conf_id): N = int(conf.ipp*(conf.clock/conf.clock_divider)*20./3)*conf.ntx - script, div = plot_pulses(unit, N, lines) - - kwargs = {'div':mark_safe(div), 'script':mark_safe(script)} + script, div = plot_pulses(unit, N, lines) - if 'json' in request.GET: - - return HttpResponse(json.dumps(kwargs), content_type="application/json") - - else: - - + kwargs = {} - return render(request, 'rc_pulses.html', kwargs) + kwargs['title'] = 'RC Pulses' + kwargs['suptitle'] = conf.name + kwargs['div'] = mark_safe(div) + kwargs['script'] = mark_safe(script) + + return render(request, 'rc_pulses.html', kwargs) diff --git a/apps/rc/widgets.py b/apps/rc/widgets.py new file mode 100644 index 0000000..d26ce34 --- /dev/null +++ b/apps/rc/widgets.py @@ -0,0 +1,245 @@ + +import ast +import json + +from django import forms +from django.utils.safestring import mark_safe + + +class KmUnitWidget(forms.widgets.TextInput): + + def render(self, label, value, attrs=None): + + if isinstance(value, (int, float)): + unit = int(value*attrs['km2unit']) + elif isinstance(value, basestring): + units = [] + values = [s for s in value.split(',') if s] + for val in values: + units.append('{0:.0f}'.format(float(val)*attrs['km2unit'])) + + unit = ','.join(units) + + disabled = 'disabled' if attrs.get('disabled', False) else '' + name = attrs.get('name', label) + + if 'line' in attrs: + label += '_{0}'.format(attrs['line'].pk) + + html = '
    Km
    Units
    '.format(disabled, label, name, value, disabled, label, unit) + + script = ''''''.format(label=label) + + if disabled: + return mark_safe(html) + else: + return mark_safe(html+script) + + +class UnitKmWidget(forms.widgets.TextInput): + + def render(self, label, value, attrs=None): + + if isinstance(value, (int, float)): + km = value/attrs['km2unit'] + elif isinstance(value, basestring): + kms = [] + values = [s for s in value.split(',') if s] + for val in values: + kms.append('{0:.0f}'.format(float(val)/attrs['km2unit'])) + + km = ','.join(kms) + + disabled = 'disabled' if attrs.get('disabled', False) else '' + name = attrs.get('name', label) + + if 'line' in attrs: + label += '_{0}'.format(attrs['line'].pk) + + html = '''
    +
    +
    Units
    +
    +
    Km
    '''.format(disabled, label, name, value, disabled, label, km) + + script = ''''''.format(label=label) + + if disabled: + return mark_safe(html) + else: + return mark_safe(html+script) + + +class KmUnitHzWidget(forms.widgets.TextInput): + + def render(self, label, value, attrs=None): + + unit = float(value)*attrs['km2unit'] + if unit%10==0: + unit = int(unit) + hz = 150000*float(value)**-1 + + disabled = 'disabled' if attrs.get('disabled', False) else '' + name = attrs.get('name', label) + + if 'line' in attrs: + label += '_{0}'.format(attrs['line'].pk) + + html = '''
    +
    +
    Km
    +
    +
    Units
    +
    +
    Hz
    +
    '''.format(disabled, label, name, value, disabled, unit, hz) + + script = ''''''.format(label=label) + + if disabled: + return mark_safe(html) + else: + return mark_safe(html+script) + + +class KmUnitDcWidget(forms.widgets.TextInput): + + def render(self, label, value, attrs=None): + + unit = int(float(value)*attrs['km2unit']) + + disabled = 'disabled' if attrs.get('disabled', False) else '' + name = attrs.get('name', label) + + label += '_{0}'.format(attrs['line'].pk) + + dc = float(json.loads(attrs['line'].params)['pulse_width'])*attrs['line'].rc_configuration.ipp/100 + + html = '''
    +
    +
    Km
    +
    +
    Units
    +
    +
    DC[%]
    +
    '''.format(disabled, label, name, value, disabled, unit, dc) + + script = ''''''.format(label=label) + + if disabled: + return mark_safe(html) + else: + return mark_safe(html+script) + + +class DefaultWidget(forms.widgets.TextInput): + + def render(self, label, value, attrs=None): + + disabled = 'disabled' if attrs.get('disabled', False) else '' + name = attrs.get('name', label) + + html = '
    '.format(disabled, label, name, value) + + return mark_safe(html) + + +class HiddenWidget(forms.widgets.HiddenInput): + + def render(self, label, value, attrs=None): + + disabled = 'disabled' if attrs.get('disabled', False) else '' + name = self.attrs.get('name', label) + + html = ''.format(disabled, label, name, value) + + return mark_safe(html) + + +class CodesWidget(forms.widgets.Textarea): + + def render(self, label, value, attrs=None): + + disabled = 'disabled' if attrs.get('disabled', False) else '' + name = attrs.get('name', label) + + if '[' in value: + value = ast.literal_eval(value) + + if isinstance(value, list): + codes = '\r\n'.join(value) + else: + codes = value + + html = ''.format(disabled, label, name, codes) + + return mark_safe(html) + \ No newline at end of file diff --git a/radarsys/settings.py b/radarsys/settings.py index e4157d5..77d7fdc 100644 --- a/radarsys/settings.py +++ b/radarsys/settings.py @@ -121,3 +121,9 @@ STATICFILES_FINDERS = ( 'django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder', ) + +FIXTURE_DIRS = ( + os.path.join(BASE_DIR, 'apps', 'rc', 'fixtures'), + os.path.join(BASE_DIR, 'apps', 'main', 'fixtures'), + +)