@@ -18,11 +18,28 @@ def treecorr_to_fits(filename1, filename2):
1818 return xiplus_hdu [1 ], ximinus_hdu [1 ]
1919
2020
21- def tau_to_fits (filename ):
22-
21+ def tau_to_fits (filename , theta = None ):
22+ """
23+ Convert tau statistics to CosmoSIS FITS format.
24+
25+ Parameters:
26+ filename : str
27+ Path to tau statistics FITS file
28+ theta : array-like, optional
29+ Angular separation values to use. If provided, overrides the theta values
30+ from the tau statistics file. This is useful for forcing consistency with
31+ xi correlation function angular separations.
32+ """
2333 tau_stats = fits .getdata (filename )
2434
25- ang = tau_stats ["theta" ]
35+ # Use provided theta if given, otherwise use tau's original theta values
36+ if theta is not None :
37+ ang = theta
38+ print (f"Using provided theta values for tau statistics (forcing consistency)" )
39+ else :
40+ ang = tau_stats ["theta" ]
41+ print (f"Using original tau theta values" )
42+
2643 nbins = len (ang )
2744 lst = np .arange (1 , nbins + 1 )
2845
@@ -162,10 +179,33 @@ def nz_to_fits(filename):
162179 return nz_hdu
163180
164181
165- def rho_to_fits (filename ):
166- rho_stat_hdu = fits .open (filename )
167- rho_stat_hdu [1 ].name = "RHO_STATS"
168- return rho_stat_hdu [1 ]
182+ def rho_to_fits (filename , theta = None ):
183+ """
184+ Convert rho statistics to CosmoSIS FITS format.
185+
186+ Parameters:
187+ filename : str
188+ Path to rho statistics FITS file
189+ theta : array-like, optional
190+ Angular separation values to use. If provided, replaces the theta values
191+ in the rho statistics file. This is useful for forcing consistency with
192+ xi correlation function angular separations.
193+ """
194+ rho_stat_hdul = fits .open (filename )
195+ rho_stat_hdu = rho_stat_hdul [1 ].copy () # Create a copy to avoid modifying the original
196+ rho_stat_hdu .name = "RHO_STATS"
197+
198+ # Force rho to use provided theta if given
199+ if theta is not None :
200+ print (f"Forcing rho statistics to use provided theta values (forcing consistency)" )
201+ # Update the theta column in the data
202+ rho_stat_hdu .data = rho_stat_hdu .data .copy () # Make data writable
203+ rho_stat_hdu .data ['theta' ] = theta
204+ else :
205+ print (f"Using original rho theta values" )
206+
207+ rho_stat_hdul .close () # Close the original file
208+ return rho_stat_hdu
169209
170210
171211if __name__ == "__main__" :
@@ -230,6 +270,10 @@ def rho_to_fits(filename):
230270 f"2pt files not found. Expected files:\n { two_pt_file_xip } \n { two_pt_file_xim } \n Please run cosmo_val.py first to generate these files."
231271 )
232272 xip_hdu , xim_hdu = treecorr_to_fits (str (two_pt_file_xip ), str (two_pt_file_xim ))
273+
274+ # Extract xi meanr for consistency enforcement
275+ xi_theta = xip_hdu .data ['ANG' ] # xi uses 'ANG' column for meanr
276+
233277 if tau_stats_file is None or not tau_stats_file .exists ():
234278 print (f"Tau stats file not found: { tau_stats_file } " )
235279 print (
@@ -238,10 +282,46 @@ def rho_to_fits(filename):
238282 use_tau_stats = False
239283 cov_tau_file = None
240284 if use_tau_stats :
285+ # Load original theta values for validation
286+ tau_stats = fits .getdata (str (tau_stats_file ))
287+ rho_stats = fits .getdata (str (rho_stats_file ))
288+ tau_theta = tau_stats ['theta' ]
289+ rho_theta = rho_stats ['theta' ]
290+
291+ # Validate theta consistency and report differences
292+ print ("=" * 60 )
293+ print ("MEANR CONSISTENCY CHECK" )
294+ print ("=" * 60 )
295+
296+ # Calculate relative differences
297+ tau_diff = np .abs ((tau_theta - xi_theta ) / xi_theta ) * 100
298+ rho_diff = np .abs ((rho_theta - xi_theta ) / xi_theta ) * 100
299+
300+ print (f"Xi theta range: { xi_theta .min ():.6f} - { xi_theta .max ():.6f} arcmin" )
301+ print (f"Tau theta range: { tau_theta .min ():.6f} - { tau_theta .max ():.6f} arcmin" )
302+ print (f"Rho theta range: { rho_theta .min ():.6f} - { rho_theta .max ():.6f} arcmin" )
303+ print ()
304+ print (f"Max tau-xi relative difference: { tau_diff .max ():.3f} %" )
305+ print (f"Mean tau-xi relative difference: { tau_diff .mean ():.3f} %" )
306+ print (f"Max rho-xi relative difference: { rho_diff .max ():.3f} %" )
307+ print (f"Mean rho-xi relative difference: { rho_diff .mean ():.3f} %" )
308+
309+ # Check for excessive differences
310+ max_allowed_diff = 5.0 # 5% threshold
311+ if tau_diff .max () > max_allowed_diff :
312+ raise ValueError (f"Tau-xi meanr difference exceeds { max_allowed_diff } %: { tau_diff .max ():.3f} %" )
313+ if rho_diff .max () > max_allowed_diff :
314+ raise ValueError (f"Rho-xi meanr difference exceeds { max_allowed_diff } %: { rho_diff .max ():.3f} %" )
315+
316+ print (f"✓ All differences below { max_allowed_diff } % threshold" )
317+ print ("✓ Forcing rho and tau to use xi meanr values for consistency" )
318+ print ("=" * 60 )
319+ print ()
320+
241321 print ("Creating rho stats fits extension...\n " )
242- rho_hdu = rho_to_fits (str (rho_stats_file ))
322+ rho_hdu = rho_to_fits (str (rho_stats_file ), theta = xi_theta )
243323 print ("Creating tau fits extensions...\n " )
244- tau_0_p_hdu , tau_2_p_hdu = tau_to_fits (str (tau_stats_file ))
324+ tau_0_p_hdu , tau_2_p_hdu = tau_to_fits (str (tau_stats_file ), theta = xi_theta )
245325 print ("Creating CovMat fits extension...\n " )
246326 cov_hdu = covdat_to_fits (cov_xi_file , str (cov_tau_file ) if cov_tau_file else None )
247327 print ("Creating n(z) fits extension...\n " )
0 commit comments