11"""Calibration data models"""
22
3+ from enum import Enum
34from typing import List , Literal , Optional
45
5- from aind_data_schema_models .units import UNITS , PowerUnit , TimeUnit , VolumeUnit
6+ from aind_data_schema_models .units import UNITS , PowerUnit , TimeUnit , VolumeUnit , VoltageUnit
7+ from pydantic import model_validator
68
7- from aind_data_schema .base import AwareDatetimeWithDefault , Discriminated , Field
9+ from aind_data_schema .base import AwareDatetimeWithDefault , DataModel , Discriminated , Field , GenericModel
810from aind_data_schema .components .configs import DeviceConfig
911from aind_data_schema .components .reagent import Reagent
1012
1113
14+ class FitType (Enum ):
15+ """Type of fit for calibration data"""
16+
17+ LINEAR_INTERPOLATION = "linear_interpolation"
18+ LINEAR = "linear"
19+ OTHER = "other"
20+
21+
22+ class CalibrationFit (DataModel ):
23+ """Fit equation for calibration data"""
24+
25+ fit_type : FitType = Field (
26+ ...,
27+ title = "Fit type" ,
28+ )
29+ fit_parameters : Optional [GenericModel ] = Field (
30+ default = None ,
31+ title = "Fit parameters" ,
32+ description = "Parameters of the fit equation, e.g. slope and intercept for linear fit" ,
33+ )
34+
35+ @model_validator (mode = "before" )
36+ def validate_fit_type (cls , values ):
37+ """Ensure that parameters are provided for linear and other fits"""
38+ fit_type = values .get ("fit_type" )
39+ fit_parameters = values .get ("fit_parameters" )
40+
41+ if fit_type in {FitType .LINEAR , FitType .OTHER } and not fit_parameters :
42+ raise ValueError (f"Fit parameters must be provided for { fit_type .value } fit type" )
43+
44+ if fit_type == FitType .LINEAR_INTERPOLATION and fit_parameters is not None :
45+ raise ValueError ("Fit parameters should not be provided for linear interpolation fit type" )
46+
47+ return values
48+
49+
1250class Calibration (DeviceConfig ):
1351 """Generic calibration class"""
1452
@@ -25,17 +63,21 @@ class Calibration(DeviceConfig):
2563 ..., description = "Calibration output (provide the average if repeated)" , title = "Outputs"
2664 )
2765 output_unit : UNITS = Field (..., title = "Output unit" )
66+ fit : Optional [CalibrationFit ] = Field (
67+ default = None ,
68+ title = "Fit" ,
69+ description = "Fit equation for the calibration data used during data acquisition" ,
70+ )
2871 notes : Optional [str ] = Field (
2972 default = None ,
3073 title = "Notes" ,
31- description = "Fit equation, etc" ,
3274 )
3375
3476
3577class VolumeCalibration (Calibration ):
36- """Calibration of a liquid delivery device"""
78+ """Calibration of a liquid delivery device based on solenoid/valve opening times """
3779
38- input : List [float ] = Field (..., title = "Input times" , description = "Length of time solenoid is open" )
80+ input : List [float ] = Field (..., title = "Input times" , description = "Length of time solenoid/valve is open" )
3981 input_unit : TimeUnit = Field (..., title = "Input unit" )
4082 repeats : Optional [int ] = Field (
4183 default = None ,
@@ -51,10 +93,10 @@ class VolumeCalibration(Calibration):
5193
5294
5395class PowerCalibration (Calibration ):
54- """Calibration of a laser device"""
96+ """Calibration of a device that outputs power based on input strength """
5597
56- input : List [float ] = Field (..., title = "Input" , description = "Power or percentage input strength" )
57- input_unit : PowerUnit = Field (..., title = "Input unit" )
98+ input : List [float ] = Field (..., title = "Input" , description = "Power, voltage, or percentage input strength" )
99+ input_unit : PowerUnit | VoltageUnit = Field (..., title = "Input unit" )
58100 output : List [float ] = Field (..., title = "Output" , description = "Power output (provide the average if repeated)" )
59101 output_unit : PowerUnit = Field (..., title = "Output unit" )
60102
0 commit comments