def test_convert_variable_unknown_type(self):
     """
     Test output variable type are unchanged if the target type is unrecognised
     """
     self.assertIsInstance(vu.convert_variable_to_type('value', 'unknown'),
                           str)
     self.assertIsInstance(vu.convert_variable_to_type(1, 'unknown'), int)
    def test_copy_variable(self):
        """
        Test: A Variable object can is copied
        When: copy_variable function is called
        """
        expected = self.valid_variable
        expected.pk = None

        actual = vu.copy_variable(vu.copy_variable(self.valid_inst_var))
        self.assertIsInstance(actual, self.var_model.InstrumentVariable)
        self.assertEqual(actual.name, expected.name)
 def test_convert_variable_to_type_list_types(self):
     """
     Test database variables types are successfully recognised and converted into python
     for list types
     """
     str_list = vu.convert_variable_to_type('[\'s\',\'t\'', 'list_text')
     self.assertIsInstance(str_list, list)
     self.assertIsInstance(str_list[0], str)
     int_list = vu.convert_variable_to_type('1,2', 'list_number')
     self.assertIsInstance(int_list, list)
     self.assertIsInstance(int_list[0], int)
     float_list = vu.convert_variable_to_type('1.0,2.0', 'list_number')
     self.assertIsInstance(float_list, list)
     self.assertIsInstance(float_list[0], float)
 def test_convert_variable_to_type(self):
     """
     Test: database variables types are successfully recognised and converted into python
     single variable types
     When: calling convert_variable_to_type with valid arguments
     """
     self.assertIsInstance(vu.convert_variable_to_type('text', 'text'), str)
     self.assertIsInstance(vu.convert_variable_to_type('1', 'number'), int)
     self.assertIsInstance(vu.convert_variable_to_type('1.0', 'number'),
                           float)
     self.assertIsInstance(vu.convert_variable_to_type('True', 'boolean'),
                           bool)
     self.assertIsInstance(vu.convert_variable_to_type('False', 'boolean'),
                           bool)
Exemplo n.º 5
0
    def show_variables_for_run(self, instrument_name, run_number=None):
        """
        Look for the applicable variables for the given run number. If none are set, return an empty
        list (or QuerySet) anyway.
        """
        instrument = db.get_instrument(instrument_name)
        variable_run_number = 0

        # If we haven't been given a run number, we should try to find it.
        model = db.start_database().variable_model
        if not run_number:
            applicable_variables = model.InstrumentVariable.objects \
                .filter(instrument_id=instrument.id) \
                .order_by('-start_run')
            if applicable_variables:
                variable_run_number = applicable_variables[0].start_run
        else:
            variable_run_number = run_number

        # Find variable records associated with instrument variables
        variables = self.find_var_records_for_inst_vars(
            instrument.id, variable_run_number)

        # If we have found some variables then we want to use them by first making copies of them
        # and sending them back to be used. This means we don't alter the previous set of variables.
        # If we haven't found any variables, just return an empty list.
        if variables:
            self._update_variables(variables)
            new_variables = []
            for variable in variables:
                new_variables.append(VariableUtils().copy_variable(variable))
            return new_variables
        return []
Exemplo n.º 6
0
    def get_script_and_arguments(reduction_run):
        """
        Fetch the reduction script from the given run and return it as a string, along with a
        dictionary of arguments.
        """
        model = access.start_database().variable_model
        run_variable_records = model.RunVariable.objects \
            .filter(reduction_run_id=reduction_run.id)

        standard_vars, advanced_vars = {}, {}
        for run_variable in run_variable_records:
            variable = model.Variable.objects.filter(
                id=run_variable.variable_ptr_id).first()
            value = VariableUtils().convert_variable_to_type(
                variable.value, variable.type)
            if variable.is_advanced:
                advanced_vars[variable.name] = value
            else:
                standard_vars[variable.name] = value

        arguments = {
            'standard_vars': standard_vars,
            'advanced_vars': advanced_vars
        }

        return reduction_run.script, arguments
Exemplo n.º 7
0
    def _create_variables(self, instrument, script, variable_dict,
                          is_advanced):
        """ Create variables in the database. """
        variables = []
        for key, value in list(variable_dict.items()):
            str_value = str(value).replace('[', '').replace(']', '')
            if len(str_value) > 300:
                raise DataTooLong
            model = db.start_database().variable_model
            help_text = self._get_help_text('standard_vars', key,
                                            instrument.name, script)
            var_type = VariableUtils().get_type_string(value)
            # Please note: As instrument_variable inherits from Variable, the below creates BOTH an
            # an InstrumentVariable and Variable record in the database when saved. As such,
            # both sets of fields are required for initialisation.
            instrument_variable = model.InstrumentVariable(
                name=key,
                value=str_value,
                type=var_type,
                is_advanced=is_advanced,
                help_text=help_text,
                start_run=0,
                instrument_id=instrument.id,
                tracks_script=1)

            db.save_record(instrument_variable)
            variables.append(instrument_variable)
        return variables
Exemplo n.º 8
0
 def show_variables_for_experiment(self, instrument_name,
                                   experiment_reference):
     """
     Look for currently set variables for the experiment.
     If none are set, return an empty list (or QuerySet) anyway.
     """
     instrument = db.get_instrument(instrument_name)
     model = db.start_database().variable_model
     ins_vars = model.InstrumentVariable.objects \
         .filter(instrument_id=instrument.id) \
         .filter(experiment_reference=experiment_reference)
     self._update_variables(ins_vars)
     return [VariableUtils().copy_variable(ins_var) for ins_var in ins_vars]
 def test_derive_run_variable(self):
     """
     Test: A RunVariable record is created
     When: calling the derive_run_variable function with valid input
     """
     expected = self.var_model.RunVariable(
         name=self.valid_variable.name,
         value=self.valid_variable.value,
         is_advanced=self.valid_variable.is_advanced,
         type=self.valid_variable.type,
         help_text=self.valid_variable.help_text,
         reduction_run=self.reduction_run)
     actual = vu.derive_run_variable(self.valid_variable,
                                     self.reduction_run)
     self.assertIsInstance(actual, self.var_model.RunVariable)
     self.assertEqual(actual.name, expected.name)
Exemplo n.º 10
0
 def copy_metadata(new_var):
     """ Copy the source variable's metadata to the new one. """
     source_var = variables[0]
     model = db.start_database().variable_model
     if isinstance(source_var, model.InstrumentVariable):
         map(
             lambda name: setattr(new_var, name,
                                  getattr(source_var, name)),
             ["instrument", "experiment_reference", "start_run"])
     elif isinstance(source_var, model.RunVariable):
         # Create a run variable.
         VariableUtils().derive_run_variable(new_var,
                                             source_var.reduction_run)
     else:
         return
     db.save_record(new_var)
Exemplo n.º 11
0
 def test_get_type_string(self):
     """
     Test: Python types are successfully recognised and converted to database input
     When: Calling get_type_string
     """
     self.assertEqual(vu.get_type_string('a string'), 'text')
     self.assertEqual(vu.get_type_string(1), 'number')
     self.assertEqual(vu.get_type_string(1.0), 'number')
     self.assertEqual(vu.get_type_string(True), 'boolean')
     self.assertEqual(vu.get_type_string([1, 2, 3]), 'list_number')
     self.assertEqual(vu.get_type_string(['s', 't', 'r']), 'list_text')
Exemplo n.º 12
0
    def create_variables_for_run(self, reduction_run):
        """
        Finds the appropriate InstrumentVariables for the given reduction run, and creates
        RunVariables from them. If the run is a re-run, use the previous run's variables.
        If instrument variables set for the run's experiment are found, they're used.
        Otherwise if variables set for the run's run number exist, they'll be used.
        If not, the instrument's default variables will be used.
        """
        instrument_name = reduction_run.instrument.name

        variables = []

        if not variables:
            logger.info('Finding variables from experiment')
            # No previous run versions. Find the instrument variables we want to use.
            variables = self.\
                show_variables_for_experiment(instrument_name,
                                              reduction_run.experiment.reference_number)

        if not variables:
            logger.info('Finding variables from run number')
            # No experiment-specific variables, so let's look for variables set by run number.
            variables = self.show_variables_for_run(instrument_name,
                                                    reduction_run.run_number)

        if not variables:
            logger.info('Using default variables')
            # No variables are set, so we'll use the defaults, and set them them while we're at it.
            variables = self.get_default_variables(instrument_name)
            logger.info('Setting the variables for the run')
            self.set_variables_for_runs(instrument_name, variables,
                                        reduction_run.run_number)

        logger.info('Saving the found variables')
        # Create run variables from these instrument variables, and return them.
        return VariableUtils().save_run_variables(variables, reduction_run)
Exemplo n.º 13
0
 def test_convert_variable_mismatch_type(self):
     """
     Test: number type conversion with non number
     """
     self.assertIsNone(vu.convert_variable_to_type('string', 'number'))
Exemplo n.º 14
0
 def test_get_type_string_unknown_type(self):
     """
     Test: A value of unknown type is output as database type text
     When: Calling get_type_string
     """
     self.assertEqual(vu.get_type_string({'key': 'value'}), 'text')
Exemplo n.º 15
0
    def set_variables_for_runs(self,
                               instrument_name,
                               variables,
                               start_run=0,
                               end_run=None):
        """
        Given a list of variables, we set them to be the variables used for subsequent runs in the
        given run range. If end_run is not supplied, these variables will be ongoing indefinitely.
        If start_run is not supplied, these variables will be set for all run numbers going
        backwards.
        """
        instrument = db.get_instrument(instrument_name)

        # Ensure that the variables we set will be the only ones used for the range given.
        model = db.start_database().variable_model
        applicable_variables = model.InstrumentVariable.objects \
            .filter(instrument_id=instrument.id) \
            .filter(start_run=start_run)

        final_variables = []
        if end_run:
            applicable_variables = applicable_variables.filter(
                start_run__lte=end_run)
            # pylint: disable=no-member
            after_variables = model.InstrumentVariable.objects \
                .filter(instrument_id=instrument.id) \
                .filter(start_run=end_run + 1) \
                .order_by('start_run')

            # pylint: disable=no-member
            previous_variables = model.InstrumentVariable.objects \
                .filter(instrument_id=instrument.id) \
                .filter(start_run__lt=start_run)

            if applicable_variables and not after_variables:
                # The last set of applicable variables extends outside our range.

                # Find the last set.
                final_start = applicable_variables.order_by(
                    '-start_run').first().start_run
                final_variables = list(
                    applicable_variables.filter(start_run=final_start))
                applicable_variables = applicable_variables.exclude(
                    start_run=final_start)  # Don't delete the final set.

            elif not applicable_variables and not after_variables and previous_variables:
                # There is a previous set that applies but doesn't start or end in the range.

                # Find the last set.
                final_start = previous_variables.order_by(
                    '-start_run').first().start_run
                # Set them to apply after our variables.
                # pylint: disable=expression-not-assigned,no-member
                final_variables = list(
                    previous_variables.filter(start_run=final_start))
                [
                    VariableUtils().copy_variable(var).save()
                    for var in final_variables
                ]  # Also copy them to apply before our variables.

            elif not applicable_variables and not after_variables and not previous_variables:
                # There are instrument defaults which apply after our range.
                final_variables = self.get_default_variables(instrument_name)

        # Delete all currently saved variables that apply to the range.
        map(lambda var: var.delete(), applicable_variables)

        # Modify the range of the final set to after the specified range, if there is one.
        for var in final_variables:
            var.start_run = end_run + 1
            db.save_record(var)

        # Then save the new ones.
        for var in variables:
            var.start_run = start_run
            db.save_record(var)