[docs]@define(frozen=True,slots=False)classNumericalDiscreteParameter(DiscreteParameter):"""Class for discrete numerical parameters (a.k.a. setpoints)."""# class variablesis_numerical:ClassVar[bool]=True# See base class.# object variables# NOTE: The parameter values are assumed to be sorted by the tolerance validator._values:tuple[float,...]=field(alias="values",# FIXME[typing]: https://github.com/python-attrs/cattrs/issues/111converter=lambdax:sorted(cattrs.structure(x,tuple[float,...])),# type: ignore# FIXME[typing]: https://github.com/python-attrs/attrs/issues/1197validator=[min_len(2),validate_unique_values,# type: ignorevalidate_is_finite,],)"""The values the parameter can take."""tolerance:float=field(default=0.0)"""The absolute tolerance used for deciding whether a value is in range. A tolerance larger than half the minimum distance between parameter values is not allowed because that could cause ambiguity when inputting data points later."""@tolerance.validatordef_validate_tolerance(# noqa: DOC101, DOC103self,_:Any,tolerance:float)->None:"""Validate that the given tolerance is safe. The tolerance is the allowed experimental uncertainty when reading in measured values. A tolerance larger than half the minimum distance between parameter values is not allowed because that could cause ambiguity when inputting data points later. Raises: ValueError: If the tolerance is not safe. """# For zero tolerance, the only left requirement is that all parameter values# are distinct, which is already ensured by the corresponding validator.iftolerance==0.0:returnmin_dist=np.diff(self._values).min()ifmin_dist==(eps:=np.nextafter(0,1)):raiseNumericalUnderflowError(f"The distance between any two parameter values must be at least "f"twice the size of the used floating point resolution of {eps}.")iftolerance>=(max_tol:=min_dist/2.0):raiseValueError(f"Parameter '{self.name}' is initialized with tolerance {tolerance} "f"but due to the given parameter values {self.values}, the specified "f"tolerance must be smaller than {max_tol} to avoid ambiguity.")@override@propertydefvalues(self)->tuple:returntuple(DTypeFloatNumpy(itm)foritminself._values)@override@cached_propertydefcomp_df(self)->pd.DataFrame:comp_df=pd.DataFrame({self.name:self.values},index=self.values,dtype=DTypeFloatNumpy)returncomp_df
[docs]@define(frozen=True,slots=False)classNumericalContinuousParameter(ContinuousParameter):"""Class for continuous numerical parameters."""is_numerical:ClassVar[bool]=True# See base class.# TODO[typing]: https://github.com/python-attrs/attrs/issues/1435bounds:Interval=field(default=None,converter=Interval.create)# type: ignore[misc]"""The bounds of the parameter."""@bounds.validatordef_validate_bounds(self,_:Any,value:Interval)->None:# noqa: DOC101, DOC103"""Validate bounds. Raises: InfiniteIntervalError: If the provided interval is not finite. """ifnotvalue.is_bounded:raiseInfiniteIntervalError(f"You are trying to initialize a parameter with an infinite range "f"of {value.to_tuple()}. Infinite intervals for parameters are "f"currently not supported.")ifvalue.is_degenerate:raiseValueError("The interval specified by the parameter bounds cannot be degenerate.")
@define(frozen=True,slots=False)class_FixedNumericalContinuousParameter(ContinuousParameter):"""Parameter class for fixed numerical parameters."""is_numeric:ClassVar[bool]=True# See base class.value:float=field(converter=float)"""The fixed value of the parameter."""@propertydefbounds(self)->Interval:"""The value of the parameter as a degenerate interval."""returnInterval(self.value,self.value)@overridedefis_in_range(self,item:float)->bool:returnInterval(self.value,self.value).contains(item)@override@propertydefcomp_rep_columns(self)->tuple[str]:return(self.name,)@overridedefsummary(self)->dict:returndict(Name=self.name,Type=self.__class__.__name__,Value=self.value,)# Collect leftover original slotted classes processed by `attrs.define`gc.collect()