Module pyangstrom.fit
Expand source code
import logging
from typing import TypedDict, Protocol, Optional, Type
import abc
from dataclasses import dataclass
from pyangstrom.exp_setup import ExperimentalSetup
from pyangstrom.transform import Margins
from pyangstrom.signal import SignalProperties, SignalResult
logger = logging.getLogger('fit')
Unknowns = dict
@dataclass
class FitterOutput:
"""Contains solutions to unknowns and method-specific metadata."""
unknowns_solutions: Unknowns
@dataclass
class FittingResult:
"""Contains thermal properties and metadata for validating the results."""
unknowns_solutions: Unknowns
theoretical_properties: SignalProperties
class EquationPackage(abc.ABC):
"""Declares methods required by the fitting method to calculate heat model
properties.
"""
@abc.abstractmethod
def __init__(
self,
margins: Margins,
setup: ExperimentalSetup,
**kwargs,
) -> None:
"""EquationPackages are expected to be initialized with only margins,
setup, and any constants relevant to its heat model.
"""
...
@abc.abstractmethod
def solve(self, unknowns: Unknowns) -> SignalResult:
"""Calculates signal properties and metadata based on the given values
for the unknowns.
"""
...
class Fitter(Protocol):
"""Function signature for a valid fitting method."""
def __call__(
self,
unknowns_guesses: Unknowns,
solution: EquationPackage,
observed_properties: SignalProperties,
**kwargs,
) -> FitterOutput: ...
class SolverInformation(TypedDict, total=False):
"""Specifies all heat model details.
Attributes
----------
name
The name of a sample solution. Names can be found on the Sample
Solutions wiki page. Ignored if 'solution' is present.
solution
A reference to an EquationPackage class. Takes precedence over 'name'.
guesses
Initial guess values for the the heat model's unknowns.
parameters
Arguments passed onto the chosen sample solution. Check the Sample
Solutions wiki page for exact details.
References
----------
Sample Solutions:
https://github.com/RuralBrick/Angstrom-Method-Rewrite/wiki/Sample-Solutions
"""
name: str
solution: EquationPackage
guesses: Unknowns
parameters: dict
class FitterInformation(TypedDict, total=False):
"""Specifies how to fit to the signal properties.
Attributes
----------
name
The name of a built-in fitting method. Names can be found on the
Built-in Fitting Methods wiki page. Ignored if 'fitter' is present.
fitter
A reference to a fitter function. Takes precedence over 'name'.
parameters
Arguments passed onto the chosen built-in fitting method. Check the
Build-in Fitting Methods wiki page for exact details.
References
----------
Built-in Fitting Methods:
https://github.com/RuralBrick/Angstrom-Method-Rewrite/wiki/Built%E2%80%90in-Fitting-Methods
"""
name: str
fitter: Fitter
parameters: dict
def extract_solution_class(
solver_information: SolverInformation
) -> Optional[Type[EquationPackage]]:
"""Returns None if 'name' not in solver_information.
Raises
------
ValueError
Named solver not found.
"""
if 'name' not in solver_information:
return None
match solver_information['name']:
case 'lopez-baeza':
from pyangstrom.sample_solutions.lopez_baeza_short import Solution
case 'log_lopez-baeza':
from pyangstrom.sample_solutions.lopez_baeza_short import LogSolution as Solution
case 'kil':
from pyangstrom.sample_solutions.kil_circular_room_temp import Solution
case 'log_kil':
from pyangstrom.sample_solutions.kil_circular_room_temp import LogSolution as Solution
case _:
raise ValueError(f"Solver {solver_information['name']} not found.")
return Solution
def extract_solution(
solver_information: SolverInformation,
signal_result: SignalResult,
setup: ExperimentalSetup,
) -> EquationPackage:
"""
Raises
------
KeyError
Field not found in information.
ValueError
Named solver not found.
"""
if 'solution' in solver_information:
return solver_information['solution']
elif Solution := extract_solution_class(solver_information):
solver_params = (solver_information['parameters']
if 'parameters' in solver_information
else {})
return Solution(signal_result.margins, setup, **solver_params)
else:
raise KeyError(
"Must have either name or solution in solver_information."
)
def extract_fit(fitter_information: FitterInformation) -> Fitter:
"""
Raises
------
KeyError
Field not found in information.
ValueError
Named fitter not found.
"""
if 'fitter' in fitter_information:
return fitter_information['fitter']
elif 'name' in fitter_information:
match fitter_information['name']:
case 'least_squares_regression' | 'lsr':
from pyangstrom.fitting_methods.lsr import fit
case 'nelder-mead':
from pyangstrom.fitting_methods.nelder_mead import fit
case _:
raise ValueError(
f"Fitter {fitter_information['name']} not found."
)
return fit
else:
raise KeyError("Must have either name or fitter in fitter_information.")
def autofit(
signal_result: SignalResult,
solver_information: SolverInformation,
fitter_information: FitterInformation,
setup: ExperimentalSetup,
) -> FittingResult:
"""Fits the specified heat model to the experimental signal properties as
specified by fitter information configuration.
Raises
------
KeyError
Field not found in information.
ValueError
Named solver or fitter not found.
"""
solution = extract_solution(solver_information, signal_result, setup)
fit = extract_fit(fitter_information)
fitter_params = (fitter_information['parameters']
if 'parameters' in fitter_information
else {})
output = fit(
solver_information['guesses'],
solution,
signal_result.signal_properties,
**fitter_params,
)
result = FittingResult(
output.unknowns_solutions,
solution.solve(output.unknowns_solutions),
)
return result
Functions
def autofit(signal_result: SignalResult, solver_information: SolverInformation, fitter_information: FitterInformation, setup: ExperimentalSetup) ‑> FittingResult
-
Fits the specified heat model to the experimental signal properties as specified by fitter information configuration.
Raises
KeyError
- Field not found in information.
ValueError
- Named solver or fitter not found.
Expand source code
def autofit( signal_result: SignalResult, solver_information: SolverInformation, fitter_information: FitterInformation, setup: ExperimentalSetup, ) -> FittingResult: """Fits the specified heat model to the experimental signal properties as specified by fitter information configuration. Raises ------ KeyError Field not found in information. ValueError Named solver or fitter not found. """ solution = extract_solution(solver_information, signal_result, setup) fit = extract_fit(fitter_information) fitter_params = (fitter_information['parameters'] if 'parameters' in fitter_information else {}) output = fit( solver_information['guesses'], solution, signal_result.signal_properties, **fitter_params, ) result = FittingResult( output.unknowns_solutions, solution.solve(output.unknowns_solutions), ) return result
def extract_fit(fitter_information: FitterInformation) ‑> Fitter
-
Raises
KeyError
- Field not found in information.
ValueError
- Named fitter not found.
Expand source code
def extract_fit(fitter_information: FitterInformation) -> Fitter: """ Raises ------ KeyError Field not found in information. ValueError Named fitter not found. """ if 'fitter' in fitter_information: return fitter_information['fitter'] elif 'name' in fitter_information: match fitter_information['name']: case 'least_squares_regression' | 'lsr': from pyangstrom.fitting_methods.lsr import fit case 'nelder-mead': from pyangstrom.fitting_methods.nelder_mead import fit case _: raise ValueError( f"Fitter {fitter_information['name']} not found." ) return fit else: raise KeyError("Must have either name or fitter in fitter_information.")
def extract_solution(solver_information: SolverInformation, signal_result: SignalResult, setup: ExperimentalSetup) ‑> EquationPackage
-
Raises
KeyError
- Field not found in information.
ValueError
- Named solver not found.
Expand source code
def extract_solution( solver_information: SolverInformation, signal_result: SignalResult, setup: ExperimentalSetup, ) -> EquationPackage: """ Raises ------ KeyError Field not found in information. ValueError Named solver not found. """ if 'solution' in solver_information: return solver_information['solution'] elif Solution := extract_solution_class(solver_information): solver_params = (solver_information['parameters'] if 'parameters' in solver_information else {}) return Solution(signal_result.margins, setup, **solver_params) else: raise KeyError( "Must have either name or solution in solver_information." )
def extract_solution_class(solver_information: SolverInformation) ‑> Optional[Type[EquationPackage]]
-
Returns None if 'name' not in solver_information.
Raises
ValueError
- Named solver not found.
Expand source code
def extract_solution_class( solver_information: SolverInformation ) -> Optional[Type[EquationPackage]]: """Returns None if 'name' not in solver_information. Raises ------ ValueError Named solver not found. """ if 'name' not in solver_information: return None match solver_information['name']: case 'lopez-baeza': from pyangstrom.sample_solutions.lopez_baeza_short import Solution case 'log_lopez-baeza': from pyangstrom.sample_solutions.lopez_baeza_short import LogSolution as Solution case 'kil': from pyangstrom.sample_solutions.kil_circular_room_temp import Solution case 'log_kil': from pyangstrom.sample_solutions.kil_circular_room_temp import LogSolution as Solution case _: raise ValueError(f"Solver {solver_information['name']} not found.") return Solution
Classes
class EquationPackage (margins: Margins, setup: ExperimentalSetup, **kwargs)
-
Declares methods required by the fitting method to calculate heat model properties.
EquationPackages are expected to be initialized with only margins, setup, and any constants relevant to its heat model.
Expand source code
class EquationPackage(abc.ABC): """Declares methods required by the fitting method to calculate heat model properties. """ @abc.abstractmethod def __init__( self, margins: Margins, setup: ExperimentalSetup, **kwargs, ) -> None: """EquationPackages are expected to be initialized with only margins, setup, and any constants relevant to its heat model. """ ... @abc.abstractmethod def solve(self, unknowns: Unknowns) -> SignalResult: """Calculates signal properties and metadata based on the given values for the unknowns. """ ...
Ancestors
- abc.ABC
Subclasses
Methods
def solve(self, unknowns: dict) ‑> SignalResult
-
Calculates signal properties and metadata based on the given values for the unknowns.
Expand source code
@abc.abstractmethod def solve(self, unknowns: Unknowns) -> SignalResult: """Calculates signal properties and metadata based on the given values for the unknowns. """ ...
class Fitter (*args, **kwargs)
-
Function signature for a valid fitting method.
Expand source code
class Fitter(Protocol): """Function signature for a valid fitting method.""" def __call__( self, unknowns_guesses: Unknowns, solution: EquationPackage, observed_properties: SignalProperties, **kwargs, ) -> FitterOutput: ...
Ancestors
- typing.Protocol
- typing.Generic
class FitterInformation (*args, **kwargs)
-
Specifies how to fit to the signal properties.
Attributes
name
- The name of a built-in fitting method. Names can be found on the Built-in Fitting Methods wiki page. Ignored if 'fitter' is present.
fitter
- A reference to a fitter function. Takes precedence over 'name'.
parameters
- Arguments passed onto the chosen built-in fitting method. Check the Build-in Fitting Methods wiki page for exact details.
References
Built-in Fitting Methods: https://github.com/RuralBrick/Angstrom-Method-Rewrite/wiki/Built%E2%80%90in-Fitting-Methods
Expand source code
class FitterInformation(TypedDict, total=False): """Specifies how to fit to the signal properties. Attributes ---------- name The name of a built-in fitting method. Names can be found on the Built-in Fitting Methods wiki page. Ignored if 'fitter' is present. fitter A reference to a fitter function. Takes precedence over 'name'. parameters Arguments passed onto the chosen built-in fitting method. Check the Build-in Fitting Methods wiki page for exact details. References ---------- Built-in Fitting Methods: https://github.com/RuralBrick/Angstrom-Method-Rewrite/wiki/Built%E2%80%90in-Fitting-Methods """ name: str fitter: Fitter parameters: dict
Ancestors
- builtins.dict
Class variables
var fitter : Fitter
var name : str
var parameters : dict
class FitterOutput (unknowns_solutions: dict)
-
Contains solutions to unknowns and method-specific metadata.
Expand source code
@dataclass class FitterOutput: """Contains solutions to unknowns and method-specific metadata.""" unknowns_solutions: Unknowns
Class variables
var unknowns_solutions : dict
class FittingResult (unknowns_solutions: dict, theoretical_properties: SignalProperties)
-
Contains thermal properties and metadata for validating the results.
Expand source code
@dataclass class FittingResult: """Contains thermal properties and metadata for validating the results.""" unknowns_solutions: Unknowns theoretical_properties: SignalProperties
Class variables
var theoretical_properties : SignalProperties
var unknowns_solutions : dict
class SolverInformation (*args, **kwargs)
-
Specifies all heat model details.
Attributes
name
- The name of a sample solution. Names can be found on the Sample Solutions wiki page. Ignored if 'solution' is present.
solution
- A reference to an EquationPackage class. Takes precedence over 'name'.
guesses
- Initial guess values for the the heat model's unknowns.
parameters
- Arguments passed onto the chosen sample solution. Check the Sample Solutions wiki page for exact details.
References
Sample Solutions: https://github.com/RuralBrick/Angstrom-Method-Rewrite/wiki/Sample-Solutions
Expand source code
class SolverInformation(TypedDict, total=False): """Specifies all heat model details. Attributes ---------- name The name of a sample solution. Names can be found on the Sample Solutions wiki page. Ignored if 'solution' is present. solution A reference to an EquationPackage class. Takes precedence over 'name'. guesses Initial guess values for the the heat model's unknowns. parameters Arguments passed onto the chosen sample solution. Check the Sample Solutions wiki page for exact details. References ---------- Sample Solutions: https://github.com/RuralBrick/Angstrom-Method-Rewrite/wiki/Sample-Solutions """ name: str solution: EquationPackage guesses: Unknowns parameters: dict
Ancestors
- builtins.dict
Class variables
var guesses : dict
var name : str
var parameters : dict
var solution : EquationPackage