diff --git a/validphys2/src/validphys/commondataparser.py b/validphys2/src/validphys/commondataparser.py index 7e56bb5b1e..eefbbb780d 100644 --- a/validphys2/src/validphys/commondataparser.py +++ b/validphys2/src/validphys/commondataparser.py @@ -53,6 +53,7 @@ from validphys.coredata import KIN_NAMES, CommonData from validphys.datafiles import new_to_legacy_map, path_commondata from validphys.plotoptions.plottingoptions import PlottingOptions, labeler_functions +from validphys.process_options import ValidProcess from validphys.utils import parse_yaml_inp try: @@ -138,6 +139,7 @@ def _get_ported_kinlabel(process_type): In principle there is a one to one correspondance between the process label in the kinematic and ``KINLABEL_LATEX``, however, there were some special cases that need to be taken into account """ + process_type = str(process_type) if process_type in KINLABEL_LATEX: return KINLABEL_LATEX[process_type] # special case in which the process in DIS- or DYP-like @@ -152,6 +154,12 @@ def _get_process_description(process_type): """Get the process description string for a given process type Similarly to kinlabel, some special cases are taken into account. """ + try: + return process_type.description + except AttributeError: + # This process needs to be updated + pass + if process_type in PROCESS_DESCRIPTION_LABEL: return PROCESS_DESCRIPTION_LABEL[process_type] # If not, is this a DYP- or DIS-like dataset? @@ -375,7 +383,7 @@ class ObservableMetaData: ndata: int # Plotting options plotting: PlottingOptions - process_type: str + process_type: ValidProcess kinematic_coverage: list[str] # Data itself @@ -414,8 +422,6 @@ def __post_init__(self): nkincov = self.kinematic_coverage + [f"extra_{i}" for i in range(diff_to_3)] object.__setattr__(self, 'kinematic_coverage', nkincov) - object.__setattr__(self, 'process_type', self.process_type.upper()) - def __hash__(self): """ObservableMetaData is defined by: - the setname diff --git a/validphys2/src/validphys/coredata.py b/validphys2/src/validphys/coredata.py index d2f3a7dadc..b0fb1b145b 100644 --- a/validphys2/src/validphys/coredata.py +++ b/validphys2/src/validphys/coredata.py @@ -264,6 +264,8 @@ def __post_init__(self): ) if self.legacy_name is None: self.legacy_name = self.setname + # TODO: set for now commondataproc as a string as well + self.commondataproc = str(self.commondataproc) def with_cuts(self, cuts): """A method to return a CommonData object where diff --git a/validphys2/src/validphys/filters.py b/validphys2/src/validphys/filters.py index aa7b05dc68..bf877a0dec 100644 --- a/validphys2/src/validphys/filters.py +++ b/validphys2/src/validphys/filters.py @@ -50,6 +50,7 @@ def _get_kinlabel_process_type(process_type): to the process type This requires some extra digestion for DIS """ + process_type = str(process_type) if process_type[:3] == "DIS": return KIN_LABEL["DIS"] return KIN_LABEL[process_type] @@ -484,10 +485,8 @@ def __init__(self, initial_data: dict, *, defaults: dict, theory_parameters: dic else: self.variables = cd.metadata.kinematic_coverage else: - if self.process_type[:3] == "DIS": - self.variables = KIN_LABEL["DIS"] - else: - self.variables = KIN_LABEL[self.process_type] + self.variables = _get_kinlabel_process_type(self.process_type) + # TODO: for now this will be a string within this class if hasattr(self, "local_variables"): if not isinstance(self.local_variables, Mapping): @@ -535,6 +534,10 @@ def __init__(self, initial_data: dict, *, defaults: dict, theory_parameters: dic f"Could not process rule {self.rule_string!r}: Unknown name {name!r}" ) + # Before returning, set the process type as a string for the rest of the filter + if self.process_type is not None: + self.process_type = str(self.process_type) + @property def _properties(self): """Attributes of the Rule class that are defining. Two diff --git a/validphys2/src/validphys/plotoptions/core.py b/validphys2/src/validphys/plotoptions/core.py index a89b5bf57d..96ec755337 100644 --- a/validphys2/src/validphys/plotoptions/core.py +++ b/validphys2/src/validphys/plotoptions/core.py @@ -103,7 +103,8 @@ def __init__( self.y_scale = y_scale self.dataset_label = dataset_label self.process_description = process_description - self.ds_metadata = ds_metadata # For new commondata format + # Metadata of the dataset + self.ds_metadata = ds_metadata def name_to_label(self, name): if name in labeler_functions: @@ -115,6 +116,10 @@ def name_to_label(self, name): return name return self.kinlabels[ix] + @property + def process_type(self): + return self.ds_metadata.process_type + @property def xlabel(self): if self._x_label is not None: @@ -186,6 +191,7 @@ def from_commondata(cls, commondata, cuts=None, normalize=False): plot_params = plot_params.new_child(pcd.normalize) kinlabels = plot_params['kinematics_override'].new_labels(*kinlabels) + plot_params["process_type"] = commondata.metadata.process_type if "extra_labels" in plot_params and cuts is not None: cut_extra_labels = { @@ -255,6 +261,7 @@ def kitable(data, info, *, cuts=None): if isinstance(data, CommonData) and cuts is not None: table = table.loc[cuts.load()] table.index.name = default_labels[0] + if info.kinematics_override: transform = apply_to_all_columns(table, info.kinematics_override) table = pd.DataFrame(np.array(transform).T, columns=table.columns, index=table.index) @@ -296,6 +303,11 @@ def transform_result(cv, error, kintable, info): def get_xq2map(kintable, info): """Return a tuple of (x,Q²) from the kinematic values defined in kitable - (usually obtained by calling ``kitable``) using machinery specified in - ``info``""" - return apply_to_all_columns(kintable, info.kinematics_override.xq2map) + (usually obtained by calling ``kitable``) using the process type if available + + Otherwise it will fallback to the legacy mode, i.e., "using machinery specified in``info`` + """ + try: + return info.process_type.xq2map(kintable, info.ds_metadata) + except AttributeError: + return apply_to_all_columns(kintable, info.kinematics_override.xq2map) diff --git a/validphys2/src/validphys/process_options.py b/validphys2/src/validphys/process_options.py index 2b243082f1..2f2aa048af 100644 --- a/validphys2/src/validphys/process_options.py +++ b/validphys2/src/validphys/process_options.py @@ -7,10 +7,13 @@ from enum import Enum from typing import Callable, Optional, Tuple +from validobj.custom import Parser + class _Vars(Enum): x = "x" Q2 = "Q2" + Q = "Q" y = "y" @@ -24,32 +27,49 @@ class _Process: def __hash__(self): return hash(self.name) - def xq2map(self, kin_df): + def xq2map(self, kin_df, metadata): """Transform the kinematics dataframe into a x q dataframe For double hadronic processes the number of output point will be 2x ninput + These functions should have access to both the kinematic dataframe and the + metadata of the commondata """ if self.xq2map_function is None: raise NotImplementedError(f"xq2map is not implemented for {self.name}") # check that all variables in the dataframe are accepted by this process - return self.xq2map(kin_df) + return self.xq2map_function(kin_df, metadata) + + def __str__(self): + return self.name + +def _dis_xq2map(kin_df, metadata): + """In the old style commondata, the variables in the dataframe were ``x, Q2, y`` + but due to the transformations that happen inside validphys they become ``x, Q, y`` + """ + if all(kin_df.columns == ["k1", "k2", "k3"]): + # old style format: (x, Q, y) + x, q, _ = kin_df.values.T + return x, q * q -def _dis_xq2map(kin_df): - if all(kin_df.columns == ["kin1", "kin2", "kin3"]): - # old style format: (x, Q2, y) - return kin_df.drop("kin3", axis=1) raise NotImplementedError("No new style DIS dataset implemented anyway") DIS = _Process( "DIS", "Deep Inelastic Scattering", - accepted_variables=(_Vars.x, _Vars.Q, _Vars.y), + accepted_variables=(_Vars.x, _Vars.Q2, _Vars.y, _Vars.Q), xq2map_function=_dis_xq2map, ) -class Processes: - dis = DIS - dis_nc = dataclasses.replace(DIS, name="DIS NC") - dis_cc = dataclasses.replace(DIS, name="DIS CC") +PROCESSES = { + "DIS": DIS, + "DIS_NC": dataclasses.replace(DIS, name="DIS_NC"), + "DIS_CC": dataclasses.replace(DIS, name="DIS_CC"), + "DIS_NCE": dataclasses.replace(DIS, name="DIS_NCE"), +} + + +@Parser +def ValidProcess(process_name) -> _Process: + return PROCESSES.get(process_name.upper(), process_name.upper())