@@ -118,8 +118,7 @@ def get_pc_type(
118118 )
119119 return ("H2j_ystar" , "H2j_yb" )
120120
121- else :
122- raise RuntimeError (f"{ process_type } has not been implemented." )
121+ raise RuntimeError (f"{ exp_name } : { process_type } has not been implemented." )
123122
124123
125124def _get_dis_pc_type (exp_name : str ) -> PCTypeResult :
@@ -139,23 +138,23 @@ def _get_dis_pc_type(exp_name: str) -> PCTypeResult:
139138 raise ValueError (f"The DIS observable for { exp_name } has not been implemented." )
140139
141140
142- def _get_dijet_pc_type (experiment : str , pc_dict : Optional [dict ] = None ) -> str :
141+ def _get_dijet_pc_type (experiment : str , pc_dict : Optional [dict ] = {} ) -> str :
143142 """Resolve DIJET experiment to PC type key with optional fallback."""
144143 if pc_dict .get ("H2j_ystar" ) and pc_dict .get ("H2j_yb" ):
145144 return ("H2j_ystar" , "H2j_yb" )
145+
146+ if experiment == 'ATLAS' :
147+ specific_key = "H2j_ystar"
148+ elif experiment == 'CMS' :
149+ specific_key = "H2j_ymax"
146150 else :
147- if experiment == 'ATLAS' :
148- specific_key = "H2j_ystar"
149- elif experiment == 'CMS' :
150- specific_key = "H2j_ymax"
151- else :
152- raise ValueError (f"{ experiment } is not implemented for DIJET." )
151+ raise ValueError (f"{ experiment } is not implemented for DIJET." )
153152
154153 return specific_key
155154
156155
157156def linear_bin_function (
158- a : npt .ArrayLike , y_shift : npt .ArrayLike , bin_edges : npt .ArrayLike
157+ a : npt .ArrayLike , y_shift : npt .ArrayLike , nodes : npt .ArrayLike
159158) -> np .ndarray :
160159 """
161160 This function defines the linear bin function used to construct the prior. Specifically,
@@ -168,7 +167,7 @@ def linear_bin_function(
168167 A one-dimensional array of points at which the function is evaluated.
169168 y_shift: ArrayLike of float
170169 A one-dimensional array whose elements represent the y-value of each bin
171- bin_nodes : ArrayLike of float
170+ nodes : ArrayLike of float
172171 A one-dimensional array containing the edges of the bins. The bins are
173172 constructed using pairs of consecutive points.
174173
@@ -177,36 +176,9 @@ def linear_bin_function(
177176 A one-dimensional array containing the function values evaluated at the points
178177 specified in `a`.
179178 """
180- res = np .zeros_like (a )
181- for shift_pos , shift in enumerate (y_shift ):
182- if shift_pos > 0 and shift_pos < len (y_shift ) - 1 :
183- bin_low = bin_edges [shift_pos - 1 ]
184- bin_high = bin_edges [shift_pos + 1 ]
185- bin_mid = bin_edges [shift_pos ]
186- m1 = shift / (bin_mid - bin_low )
187- m2 = shift / (bin_high - bin_mid )
188- elif shift_pos == 0 : # Left-most bin
189- bin_high = bin_edges [shift_pos + 1 ]
190- bin_mid = bin_edges [shift_pos ]
191- bin_low = bin_mid
192- m1 = 0.0
193- m2 = shift / (bin_high - bin_mid )
194- else : # Right-most bin
195- bin_low = bin_edges [shift_pos - 1 ]
196- bin_mid = bin_edges [shift_pos ]
197- bin_high = bin_mid
198- m1 = shift / (bin_mid - bin_low )
199- m2 = 0.0
200- cond_low = np .multiply (
201- a >= bin_low , a < bin_mid if shift_pos != len (y_shift ) - 1 else a <= bin_mid
202- )
203- cond_high = np .multiply (
204- a >= bin_mid , a < bin_high if shift_pos != len (y_shift ) - 1 else a <= bin_high
205- )
206- res = np .add (res , [m1 * (val - bin_low ) if cond else 0.0 for val , cond in zip (a , cond_low )])
207- res = np .add (
208- res , [- m2 * (val - bin_high ) if cond else 0.0 for val , cond in zip (a , cond_high )]
209- )
179+ a = np .asarray (a , dtype = float )
180+ res = np .interp (a , nodes , y_shift )
181+ res [(a < nodes [0 ]) | (a > nodes [- 1 ])] = 0.0
210182 return res
211183
212184
@@ -256,10 +228,10 @@ def jets_pc_func(
256228 One-dimensional array containing the shifts for each bin.
257229 nodes: ArrayLike
258230 One-dimensional array containing the edges of the bins in rapidity.
259- rap: ArrayLike
260- List of rapidity points at which the power correction is evaluated.
261231 pT: ArrayLike
262232 List of pT points at which the power correction is evaluated.
233+ rap: ArrayLike
234+ List of rapidity points at which the power correction is evaluated.
263235
264236 Returns
265237 -------
@@ -442,6 +414,8 @@ def _F(tx, ty):
442414
443415# ---------------------------------------------------------------------------
444416# Power correction callable factories
417+ # If these functions are used to compute c-factors,
418+ # no need to multiply by the observable.
445419# ---------------------------------------------------------------------------
446420def mult_dis_pc (nodes , x , q2 , dataset_sp , pdf , cfactors : bool = False ) -> callable :
447421 """
@@ -526,8 +500,6 @@ def func(y_values_p, y_values_d):
526500 h2d = dis_pc_func (y_values_d , d_nodes , x , q2 )
527501 h2p = dis_pc_func (y_values_p , p_nodes , x , q2 )
528502 if cfactors :
529- # If this function is used to compute c-factors,
530- # no need to multiply by the observable
531503 num = np .sum ([np .ones_like (h2d ), h2d ], axis = 0 )
532504 denom = np .sum ([np .ones_like (h2p ), h2p ], axis = 0 )
533505 return (num , denom )
@@ -583,10 +555,20 @@ def mult_dijet_pc(
583555 fk = fkspec .load_with_cuts (cuts )
584556 th_preds = central_fk_predictions (fk , pdf )
585557
558+ if distrb == '3D' :
559+ if len (ystar ) == 0 or len (yb ) == 0 :
560+ raise ValueError ("For 3D distributions, ystar and yb must be provided." )
561+ elif distrb == "ystar" :
562+ if len (ystar ) == 0 :
563+ raise ValueError ("For ystar distributions, ystar must be provided." )
564+ elif distrb == "ymax" :
565+ if len (ymax ) == 0 :
566+ raise ValueError ("For ymax distributions, ymax must be provided." )
567+ else :
568+ raise ValueError (f"Unknown distrb value: { distrb !r} . Expected '3D', 'ystar', or 'ymax'." )
569+
586570 def func (ystar_shifts , y_b_shifts ):
587571 if distrb == '3D' :
588- if len (ystar ) == 0 or len (yb ) == 0 :
589- raise ValueError ("For 3D distributions, ystar and yb must be provided." )
590572 result = dijet3D_pc_func (
591573 ystar_shifts = ystar_shifts ,
592574 yb_shifts = y_b_shifts ,
@@ -597,8 +579,6 @@ def func(ystar_shifts, y_b_shifts):
597579 m_jj = m_jj ,
598580 )
599581 elif distrb == "ystar" :
600- if len (ystar ) == 0 :
601- raise ValueError ("For ystar distributions, ystar must be provided." )
602582 result = dijet_ystar_pc_func (
603583 ystar_shifts = ystar_shifts ,
604584 yb_shifts = y_b_shifts ,
@@ -608,8 +588,6 @@ def func(ystar_shifts, y_b_shifts):
608588 ystar = ystar ,
609589 )
610590 elif distrb == "ymax" :
611- if len (ymax ) == 0 :
612- raise ValueError ("For ymax distributions, ymax must be provided." )
613591 result = dijet_ymax_pc_func (
614592 ystar_shifts = ystar_shifts ,
615593 yb_shifts = y_b_shifts ,
@@ -618,10 +596,6 @@ def func(ystar_shifts, y_b_shifts):
618596 m_jj = m_jj ,
619597 ymax = ymax ,
620598 )
621- else :
622- raise ValueError (
623- f"Unknown distrb value: { distrb !r} . Expected '3D', 'ystar', or 'ymax'."
624- )
625599
626600 if cfactors :
627601 return np .sum ([np .ones_like (result ), result ], axis = 0 )
@@ -756,9 +730,11 @@ def compute_deltas_pc(
756730 pc_type = get_pc_type (exp_name , process_type , experiment = experiment , pc_dict = pc_dict )
757731
758732 if process_type .startswith ('DIS' ):
759-
760- x = dataset_sp .commondata .metadata .load_kinematics ()['x' ].to_numpy ().reshape (- 1 )[cuts ]
761- q2 = dataset_sp .commondata .metadata .load_kinematics ()['Q2' ].to_numpy ().reshape (- 1 )[cuts ]
733+ try :
734+ x = dataset_sp .commondata .metadata .load_kinematics ()['x' ].to_numpy ().reshape (- 1 )[cuts ]
735+ q2 = dataset_sp .commondata .metadata .load_kinematics ()['Q2' ].to_numpy ().reshape (- 1 )[cuts ]
736+ except KeyError as e :
737+ raise ValueError (f"Required kinematic variable not found: { e } " )
762738
763739 # NMC ratio: special case with two PC types (proton and deuteron)
764740 if isinstance (pc_type , tuple ):
@@ -791,7 +767,6 @@ def compute_deltas_pc(
791767 raise ValueError (f"{ experiment } is not implemented for DIJET." )
792768
793769 kinematics = dataset_sp .commondata .metadata .load_kinematics ()
794- # TODO Excpetion rule for CMS_2JET_7TEV_M12-Y should be removed
795770 rap = kinematics [rap_var ].to_numpy ().reshape (- 1 )[cuts ]
796771 m_jj = kinematics ['m_jj' ].to_numpy ().reshape (- 1 )[cuts ]
797772
@@ -814,6 +789,8 @@ def compute_deltas_pc(
814789 # Both ystar and yb parameters contribute for all 2D distributions
815790 deltas .update (_apply_pars_combs (pars_combs , ["H2j_ystar" , "H2j_yb" ], pc_func ))
816791
792+ # Fallback to the case where power corrections have same structure
793+ # as single-inclusice jets, with pT replaced by m_jj.
817794 else :
818795 nodes = pc_dict [pc_type ]['nodes' ]
819796 pc_func = mult_jet_pc (nodes , m_jj , rap , dataset_sp , pdf , cfactors = cfactors )
0 commit comments