Beispiel #1
0
    def set_input(self, period, array):
        """
        Set a variable's value (``array``) for a given period (``period``)

        :param array: the input value for the variable
        :param period: the period at which the value is setted

        Example :

        >>> holder.set_input([12, 14], '2018-04')
        >>> holder.get_array('2018-04')
        >>> [12, 14]


        If a ``set_input`` property has been set for the variable, this method may accept inputs for periods not matching the ``definition_period`` of the variable. To read more about this, check the `documentation <https://openfisca.org/doc/coding-the-legislation/35_periods.html#set-input-automatically-process-variable-inputs-defined-for-periods-not-matching-the-definition-period>`_.
        """

        period = periods.period(period)
        if period.unit == periods.ETERNITY and self.variable.definition_period != periods.ETERNITY:
            error_message = os.linesep.join([
                'Unable to set a value for variable {0} for periods.ETERNITY.',
                '{0} is only defined for {1}s. Please adapt your input.',
            ]).format(self.variable.name, self.variable.definition_period)
            raise PeriodMismatchError(self.variable.name, period,
                                      self.variable.definition_period,
                                      error_message)
        if self.variable.is_neutralized:
            warning_message = "You cannot set a value for the variable {}, as it has been neutralized. The value you provided ({}) will be ignored.".format(
                self.variable.name, array)
            return warnings.warn(warning_message, Warning)
        if self.variable.value_type in (float, int) and isinstance(array, str):
            array = tools.eval_expression(array)
        if self.variable.set_input:
            return self.variable.set_input(self, period, array)
        return self._set(period, array)
Beispiel #2
0
    def _set(self, period, value):
        value = self._to_array(value)
        if self.variable.definition_period != periods.ETERNITY:
            if period is None:
                raise ValueError(
                    'A period must be specified to set values, except for variables with periods.ETERNITY as as period_definition.'
                )
            if (self.variable.definition_period != period.unit
                    or period.size > 1):
                name = self.variable.name
                period_size_adj = f'{period.unit}' if (
                    period.size == 1) else f'{period.size}-{period.unit}s'
                error_message = os.linesep.join([
                    f'Unable to set a value for variable "{name}" for {period_size_adj}-long period "{period}".',
                    f'"{name}" can only be set for one {self.variable.definition_period} at a time. Please adapt your input.',
                    f'If you are the maintainer of "{name}", you can consider adding it a set_input attribute to enable automatic period casting.'
                ])

                raise PeriodMismatchError(self.variable.name, period,
                                          self.variable.definition_period,
                                          error_message)

        should_store_on_disk = (
            self._on_disk_storable and self._memory_storage.get(period) is None
            and  # If there is already a value in memory, replace it and don't put a new value in the disk storage
            psutil.virtual_memory().percent >=
            self.simulation.memory_config.max_memory_occupation_pc)

        if should_store_on_disk:
            self._disk_storage.put(value, period)
        else:
            self._memory_storage.put(value, period)
Beispiel #3
0
    def _set(self, period, value, extra_params=None):
        if not isinstance(value, np.ndarray):
            value = np.asarray(value)
        if value.ndim == 0:
            # 0-dim arrays are casted to scalar when they interact with float. We don't want that.
            value = value.reshape(1)
        if len(value) != self.entity.count:
            raise ValueError(
                'Unable to set value "{}" for variable "{}", as its length is {} while there are {} {} in the simulation.'
                .format(value, self.variable.name, len(value),
                        self.entity.count, self.entity.plural))
        if self.variable.value_type == Enum:
            value = self.variable.possible_values.encode(value)
        if value.dtype != self.variable.dtype:
            try:
                value = value.astype(self.variable.dtype)
            except ValueError:
                raise ValueError(
                    'Unable to set value "{}" for variable "{}", as the variable dtype "{}" does not match the value dtype "{}".'
                    .format(value, self.variable.name, self.variable.dtype,
                            value.dtype))

        if self.variable.definition_period != ETERNITY:
            if period is None:
                raise ValueError(
                    'A period must be specified to set values, except for variables with ETERNITY as as period_definition.'
                )
            if ((self.variable.definition_period == MONTH
                 and period.unit != periods.MONTH)
                    or (self.variable.definition_period == YEAR
                        and period.unit != periods.YEAR)):
                error_message = os.linesep.join([
                    'Unable to set a value for variable {0} for {1}-long period {2}.',
                    '{0} is only defined for {3}s. Please adapt your input.',
                    'If you are the maintainer of {0}, you can consider adding it a set_input attribute to enable automatic period casting.'
                ]).format(self.variable.name, period.unit, period,
                          self.variable.definition_period).encode('utf-8')

                raise PeriodMismatchError(self.variable.name, period,
                                          self.variable.definition_period,
                                          error_message)

        should_store_on_disk = (
            self._on_disk_storable
            and self._memory_storage.get(period, extra_params) is None
            and  # If there is already a value in memory, replace it and don't put a new value in the disk storage
            psutil.virtual_memory().percent >=
            self.simulation.memory_config.max_memory_occupation_pc)

        if should_store_on_disk:
            self._disk_storage.put(value, period, extra_params)
        else:
            self._memory_storage.put(value, period, extra_params)