11"""The models module. Contains the pydantic models used by RAT to store project parameters."""
22
33import pathlib
4+ import warnings
45from itertools import count
56from typing import Any
67
@@ -60,7 +61,7 @@ class Background(RATModel):
6061 - if type is 'function', this should be the name of a custom function defined in `Project.custom_files`.
6162 value_1, value_2, ..., value_5 : str
6263 Values required by the background.
63- - if type is 'constant', this should be blank .
64+ - if type is 'constant', all values will be ignored .
6465 - if type is 'data', value_1 may be the parameter name for an optional offset. Other values are ignored.
6566 - if type is 'function', these values may be the names of up to 5 parameters which are passed to the function.
6667
@@ -75,6 +76,26 @@ class Background(RATModel):
7576 value_4 : str = ""
7677 value_5 : str = ""
7778
79+ @model_validator (mode = "after" )
80+ def warn_parameters (self ):
81+ """Raise a warning if the parameters given are not expected for the given type."""
82+ if self .type == TypeOptions .Constant :
83+ expected_empty_fields = ["value_1" , "value_2" , "value_3" , "value_4" , "value_5" ]
84+ elif self .type == TypeOptions .Data :
85+ expected_empty_fields = ["value_2" , "value_3" , "value_4" , "value_5" ]
86+ else :
87+ return self
88+
89+ non_empty_fields = [v for v in expected_empty_fields if getattr (self , v ) != "" ]
90+ if non_empty_fields :
91+ warnings .warn (
92+ "The following values are not recognised by this background type and will be ignored: "
93+ f"{ ', ' .join (non_empty_fields )} " ,
94+ stacklevel = 2 ,
95+ )
96+
97+ return self
98+
7899
79100class Contrast (RATModel ):
80101 """A group of all of the components of a model.
@@ -515,19 +536,20 @@ class Resolution(RATModel):
515536 Parameters
516537 ----------
517538 name : str
518- The name of the background .
539+ The name of the resolution .
519540 type : TypeOptions
520- The type of background ( constant, function or data)
541+ The type of resolution: ' constant', 'data', or (NOT YET IMPLEMENTED) 'function'.
521542 source : str
522- The source data for the background ;
543+ The source data for the resolution ;
523544 - if type is 'constant', this should be the name of a background parameter.
524- - if type is 'data', this should be the name of a dataset defined in `Project.data`.
525- - if type is 'function', this should be the name of a custom function defined in `Project.custom_files`.
545+ - if type is 'data', this should be empty (resolution data is in the contrast data).
546+ - if type is 'function' (NOT YET IMPLEMENTED),
547+ this should be the name of a custom function defined in `Project.custom_files`.
526548 value_1, value_2, ..., value_5 : str
527549 Values required by the background.
528- - if type is 'constant', this should be blank .
529- - if type is 'data', value_1 may be the parameter name for an optional offset. Other values are ignored.
530- - if type is 'function', these values may be the names of up to 5 parameters which are passed to the function.
550+ - if type is 'constant' or 'data', all values will be ignored .
551+ - if type is 'function' (NOT YET IMPLEMENTED),
552+ these values may be the names of up to 5 parameters which are passed to the function.
531553
532554 """
533555
@@ -539,3 +561,34 @@ class Resolution(RATModel):
539561 value_3 : str = ""
540562 value_4 : str = ""
541563 value_5 : str = ""
564+
565+ @field_validator ("type" )
566+ @classmethod
567+ def validate_unimplemented_resolutions (cls , type : TypeOptions ):
568+ """Raise an error if currently unsupported function resolutions are used."""
569+ # when function resolutions are added, fix the commented-out parts of
570+ # test_project.py::test_rename_models
571+ # and test_project.py::test_allowed_resolutions
572+ if type == TypeOptions .Function :
573+ raise NotImplementedError ("Function resolutions are not yet supported." )
574+ return type
575+
576+ @model_validator (mode = "after" )
577+ def warn_parameters (self ):
578+ """Raise a warning if the parameters given are not expected for the given type."""
579+ if self .type == TypeOptions .Constant :
580+ expected_empty_fields = ["value_1" , "value_2" , "value_3" , "value_4" , "value_5" ]
581+ elif self .type == TypeOptions .Data :
582+ expected_empty_fields = ["source" , "value_1" , "value_2" , "value_3" , "value_4" , "value_5" ]
583+ else :
584+ return self
585+
586+ non_empty_fields = [v for v in expected_empty_fields if getattr (self , v ) != "" ]
587+ if non_empty_fields :
588+ warnings .warn (
589+ "The following values are not recognised by this resolution type and will be ignored: "
590+ f"{ ', ' .join (non_empty_fields )} " ,
591+ stacklevel = 2 ,
592+ )
593+
594+ return self
0 commit comments