import enum from typing import Optional from envipy_additional_information import GroupEnum as G from envipy_additional_information import SubcategoryEnum as S from envipy_additional_information import ( register, register_parser_command, EnviPyModel, # EnviPyModelParser, Interval, UIConfig, IntervalConfig, WidgetType, registry, ) @register(keyname="compoundlabel", groups=[S.MISC, G.SLUDGE, G.SEDIMENT, G.SOIL]) class CompoundLabel(EnviPyModel): label: str class UI: title = "Compound Label" label = UIConfig(widget=WidgetType.TEXT, label="Label", order=1) # TODO Expose EnviPyModelParser in lib and subclass @register_parser_command("compoundlabel") class CompoundLabelParser: @staticmethod def from_string(data: str) -> CompoundLabel: return CompoundLabel(label=data) @register(keyname="studywaterstoragecapacity", groups=[S.MISC, G.SLUDGE, G.SEDIMENT, G.SOIL]) class StudyWaterStorageCapacity(EnviPyModel): capacity: str class UI: title = "Study Water Storage Capacity" capacity = UIConfig(widget=WidgetType.TEXT, label="Study Water Storage Capacity", order=1) # TODO Expose EnviPyModelParser in lib and subclass @register_parser_command("studywst") class StudyWaterStorageCapacityParser: @staticmethod def from_string(data: str) -> StudyWaterStorageCapacity: return StudyWaterStorageCapacity(capacity=data) class ObservationType(enum.Enum): OBSERVED = "observed" APPLIED = "applied" NA = 'NA' @register(keyname="observation", groups=[S.MISC, G.SLUDGE, G.SEDIMENT, G.SOIL]) class Observation(EnviPyModel): type: ObservationType min_value: Optional[float] = None max_value: Optional[float] = None class UI: title = "Observation" type = UIConfig(widget=WidgetType.SELECT, label="Observed or Applied", order=1) min_value = UIConfig(widget=WidgetType.NUMBER, label="Min Value", order=2) max_value = UIConfig(widget=WidgetType.NUMBER, label="Max Value", order=3) # TODO Expose EnviPyModelParser in lib and subclass @register_parser_command("observation") class ObservationParser: @staticmethod def from_string(data: str) -> Observation: parts = data.split(";") observation_type = ObservationType(parts[0]) min_value = None if parts[1]: try: min_value = float(parts[1]) except ValueError: pass max_value = None if parts[2]: try: max_value = float(parts[2]) except ValueError: pass return Observation(type=observation_type, min_value=min_value, max_value=max_value) @register(keyname="kinetics", groups=[S.MISC, G.SLUDGE, G.SEDIMENT, G.SOIL]) class Kinetics(EnviPyModel): dt50: Interval[float] normalized_dt50: bool chi2err: Optional[float] = None t_test: Optional[float] = None swarc: Optional[float] = None visual_fit: Optional[int] = None comment: str source: str kinetic_model: str k1: Optional[float] = None k2: Optional[float] = None g: Optional[float] = None tb: Optional[float] = None alpha: Optional[float] = None beta: Optional[float] = None class UI: title = "Kinetics" # Field config dt50 = IntervalConfig(label="DT50 Range", order=1, unit="d") normalized_dt50 = UIConfig(widget=WidgetType.CHECKBOX, label="Normalized DT50", order=2) chi2err = UIConfig(widget=WidgetType.NUMBER, label="Chi2err", order=3) t_test = UIConfig(widget=WidgetType.NUMBER, label="T-Test", order=4) swarc = UIConfig(widget=WidgetType.NUMBER, label="SWARC", order=5) visual_fit = UIConfig(widget=WidgetType.NUMBER, label="Visual Fit", order=6) comment = UIConfig(widget=WidgetType.TEXTAREA, label="Comments", order=7) source = UIConfig(widget=WidgetType.TEXT, label="Source", order=8) kinetic_model = UIConfig(widget=WidgetType.SELECT, label="Kinetic Model", order=9) k1 = UIConfig(widget=WidgetType.NUMBER, label="K1", order=10) k2 = UIConfig(widget=WidgetType.NUMBER, label="K2", order=11) g = UIConfig(widget=WidgetType.NUMBER, label="G", order=12) tb = UIConfig(widget=WidgetType.NUMBER, label="TB", order=13) alpha = UIConfig(widget=WidgetType.NUMBER, label="Alpha", order=14) beta = UIConfig(widget=WidgetType.NUMBER, label="Beta", order=15) # TODO Expose EnviPyModelParser in lib and subclass @register_parser_command("kineticevaluation") class KinecticsParser: @staticmethod def from_string(data: str) -> Kinetics: parts = data.split(";") dt50 = registry.get_parser("interval").from_string(parts[0]) normalized_dt50 = parts[1] == "true" chi2err = float(parts[2]) if parts[2] else None t_test = float(parts[3]) if parts[3] else None swarc = float(parts[4]) if parts[4] else None visual_fit = int(parts[5]) if parts[5] else None comment = parts[6] source = parts[7] kinetic_model = parts[8] k1 = float(parts[9]) if parts[9] else None k2 = float(parts[10]) if parts[10] else None g = float(parts[11]) if parts[11] else None tb = float(parts[12]) if parts[12] else None alpha = float(parts[13]) if parts[13] else None beta = float(parts[14]) if parts[14] else None return Kinetics( dt50=dt50, normalized_dt50=normalized_dt50, chi2err=chi2err, t_test=t_test, swarc=swarc, visual_fit=visual_fit, comment=comment, source=source, kinetic_model=kinetic_model, k1=k1, k2=k2, g=g, tb=tb, alpha=alpha, beta=beta, ) if __name__ == '__main__': print(KinecticsParser.from_string("187.0 - 187.0;false;;;;;;;AFO;;;;;;"))