@@ -112,6 +112,33 @@ def _load_labels(
112112 return np .column_stack (columns )
113113
114114
115+ def _read_fparam_from_systems (
116+ systems : list [dpdata .System ],
117+ ) -> dict [str , np .ndarray ] | None :
118+ """Auto-read fparam.npy from each system's ``set.*/`` directories.
119+
120+ Returns a dict mapping ``"fparam_0"``, ``"fparam_1"``, ... to 1-D
121+ arrays of length ``n_frames_total``, suitable for passing as
122+ ``conditions=`` to :meth:`ConditionManager.fit_transform`.
123+
124+ Returns ``None`` when no system has a ``set.*/fparam.npy`` file.
125+ """
126+ all_fparams = []
127+ for system in systems :
128+ source = _get_source (system )
129+ if source is None :
130+ continue
131+ fps = sorted (Path (source ).glob ("set.*/fparam.npy" ))
132+ if not fps :
133+ continue
134+ arrs = [np .load (str (fp )) for fp in fps ]
135+ all_fparams .append (np .concatenate (arrs , axis = 0 ))
136+ if not all_fparams :
137+ return None
138+ combined = np .concatenate (all_fparams , axis = 0 ) # (n_frames, fparam_dim)
139+ return {f"fparam_{ i } " : combined [:, i ] for i in range (combined .shape [1 ])}
140+
141+
115142def _read_data_type_map (system ) -> list [str ]:
116143 """Read element symbols from a dpdata System's ``atom_names``.
117144
@@ -560,10 +587,12 @@ class DPAFineTuner:
560587 loss_function : str
561588 ``"mse"`` or ``"smooth_mae"`` (training paradigms).
562589 fparam_dim : int
563- (frozen_head / finetune / mft only) Dimensionality of per-frame
564- condition inputs (e.g. temperature, pressure). Requires
565- set.*/fparam.npy of shape (n_frames, fparam_dim) in every
566- training system. Default 0 (disabled).
590+ Dimension of per-frame context features (e.g. temperature,
591+ humidity). When > 0, ``set.*/fparam.npy`` of shape
592+ ``(n_frames, fparam_dim)`` is read automatically for all
593+ strategies. For ``frozen_sklearn``, fparam columns are
594+ standardized and concatenated to the descriptor via
595+ ``ConditionManager``. Default 0 (disabled).
567596 output_dir : str
568597 Directory for ``input.json``, checkpoints, and logs.
569598 save_freq, disp_freq : int
@@ -854,7 +883,6 @@ def fit(
854883 target_key = None ,
855884 labels = None ,
856885 fmt = None ,
857- conditions = None ,
858886 aux_data = None ,
859887 ):
860888 """Train the model.
@@ -879,15 +907,13 @@ def fit(
879907 (frozen_sklearn) Pre-computed labels.
880908 fmt : str, optional
881909 Reserved for future format support.
882- conditions : dict[str, np.ndarray], optional
883- (frozen_sklearn) Named condition arrays.
884910 aux_data : str | list[str], optional
885911 (mft only) Auxiliary training system directories. Required when
886912 ``strategy='mft'``; must be absent otherwise.
887913 """
888914 if self .strategy == "frozen_sklearn" :
889915 return self ._fit_sklearn (
890- train_data , type_map , target_key , labels , fmt , conditions
916+ train_data , type_map , target_key , labels , fmt
891917 )
892918
893919 if self .strategy == "mft" :
@@ -951,7 +977,6 @@ def _fit_sklearn(
951977 target_key = None ,
952978 labels = None ,
953979 fmt = None ,
954- conditions = None ,
955980 ):
956981 """Fit the frozen-sklearn pipeline (delegates to ``_FrozenSklearnPipeline``).
957982
@@ -978,10 +1003,12 @@ def _fit_sklearn(
9781003 features = self ._extract_features_cached (systems )
9791004
9801005 self ._condition_manager = None
981- if conditions is not None :
982- self ._condition_manager = ConditionManager ()
983- X_cond = self ._condition_manager .fit_transform (conditions )
984- features = np .concatenate ([features , X_cond ], axis = 1 )
1006+ if self .fparam_dim > 0 :
1007+ conditions = _read_fparam_from_systems (systems )
1008+ if conditions is not None :
1009+ self ._condition_manager = ConditionManager ()
1010+ X_cond = self ._condition_manager .fit_transform (conditions )
1011+ features = np .concatenate ([features , X_cond ], axis = 1 )
9851012
9861013 if labels is not None :
9871014 y = np .asarray (labels )
@@ -1019,19 +1046,19 @@ def _fit_sklearn(
10191046 p ._condition_manager = self ._condition_manager
10201047 p ._fitted = True
10211048
1022- def predict (self , data , fmt = None , conditions = None ) -> DotDict :
1049+ def predict (self , data , fmt = None ) -> DotDict :
10231050 """
10241051 Extract features and run the fitted sklearn predictor.
10251052
1053+ fparam is automatically read from ``set.*/fparam.npy`` when the
1054+ model was fit with ``fparam_dim > 0``.
1055+
10261056 Parameters
10271057 ----------
10281058 data : str | list[str]
10291059 Path(s) to deepmd/npy system directories.
10301060 fmt : str, optional
10311061 Reserved for future format support.
1032- conditions : dict[str, np.ndarray], optional
1033- Named condition arrays. Required when the model was fit with
1034- conditions; must be absent otherwise.
10351062
10361063 Returns
10371064 -------
@@ -1047,20 +1074,20 @@ def predict(self, data, fmt=None, conditions=None) -> DotDict:
10471074 features = self ._extract_features (systems )
10481075
10491076 if self ._condition_manager is not None :
1077+ conditions = _read_fparam_from_systems (systems )
10501078 if conditions is None :
10511079 raise DPAConditionError (
1052- "This model was fit with conditions. Pass conditions= to predict()."
1080+ "This model was fit with fparam but set.*/fparam.npy "
1081+ "was not found in the test data."
10531082 )
10541083 X_cond = self ._condition_manager .transform (conditions )
10551084 features = np .concatenate ([features , X_cond ], axis = 1 )
1056- elif conditions is not None :
1057- raise DPAConditionError ("This model was fit without conditions." )
10581085
10591086 raw = self .predictor .predict (features )
10601087 predictions = np .asarray (raw ).reshape (- 1 , self ._task_dim )
10611088 return DotDict ({"predictions" : predictions })
10621089
1063- def evaluate (self , data , fmt = None , conditions = None ) -> DotDict :
1090+ def evaluate (self , data , fmt = None ) -> DotDict :
10641091 """
10651092 Predict on ``data`` and compute evaluation metrics against stored labels.
10661093
@@ -1070,9 +1097,6 @@ def evaluate(self, data, fmt=None, conditions=None) -> DotDict:
10701097 Path(s) to deepmd/npy system directories with label files.
10711098 fmt : str, optional
10721099 Reserved for future format support.
1073- conditions : dict[str, np.ndarray], optional
1074- Named condition arrays. Required when the model was fit with
1075- conditions; must be absent otherwise.
10761100
10771101 Returns
10781102 -------
@@ -1081,7 +1105,7 @@ def evaluate(self, data, fmt=None, conditions=None) -> DotDict:
10811105 predictions : np.ndarray, shape (n_frames, task_dim)
10821106 labels : np.ndarray, shape (n_frames, task_dim)
10831107 """
1084- result = self .predict (data , fmt = fmt , conditions = conditions )
1108+ result = self .predict (data , fmt = fmt )
10851109 predictions = result .predictions
10861110
10871111 systems = load_data (data , fmt = fmt )
0 commit comments