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)
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)
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)