@@ -1700,25 +1700,31 @@ def get1DDensityGridData(self, j, paramConfid=None, meanlikes=False, **kwargs):
17001700 return density1D
17011701
17021702 def _setEdgeMask2D (self , parx , pary , prior_mask , winw ):
1703- if parx .has_limits_bot :
1704- prior_mask [:, winw ] /= 2
1703+ # Only apply edge masks on non-periodic axes; periodic axes have no boundaries
1704+ if not parx .periodic :
1705+ if parx .has_limits_bot :
1706+ prior_mask [:, winw ] /= 2
1707+ prior_mask [:, :winw ] = 0
1708+ if parx .has_limits_top :
1709+ prior_mask [:, - (winw + 1 )] /= 2
1710+ prior_mask [:, - winw :] = 0
1711+ if not pary .periodic :
1712+ if pary .has_limits_bot :
1713+ prior_mask [winw , :] /= 2
1714+ prior_mask [:winw :] = 0
1715+ if pary .has_limits_top :
1716+ prior_mask [- (winw + 1 ), :] /= 2
1717+ prior_mask [- winw :, :] = 0
1718+
1719+ def _setAllEdgeMask2D (self , prior_mask , winw , periodic_x = False , periodic_y = False ):
1720+ # Zero out margins only along non-periodic axes
1721+ if not periodic_x :
17051722 prior_mask [:, :winw ] = 0
1706- if parx .has_limits_top :
1707- prior_mask [:, - (winw + 1 )] /= 2
17081723 prior_mask [:, - winw :] = 0
1709- if pary .has_limits_bot :
1710- prior_mask [winw , :] /= 2
1724+ if not periodic_y :
17111725 prior_mask [:winw :] = 0
1712- if pary .has_limits_top :
1713- prior_mask [- (winw + 1 ), :] /= 2
17141726 prior_mask [- winw :, :] = 0
17151727
1716- def _setAllEdgeMask2D (self , prior_mask , winw ):
1717- prior_mask [:, :winw ] = 0
1718- prior_mask [:, - winw :] = 0
1719- prior_mask [:winw :] = 0
1720- prior_mask [- winw :, :] = 0
1721-
17221728 def _getScaleForParam (self , par ):
17231729 # Also ensures that the 1D limits are initialized
17241730 density = self .get1DDensity (par )
@@ -1878,14 +1884,29 @@ def get2DDensityGridData(
18781884 start = time .time ()
18791885 cache = {}
18801886 convolvesize = xsize + 2 * winw + Win .shape [0 ] # larger than needed for selecting fft pixel count
1881- bins2D = convolve2D (histbins , Win , "same" , largest_size = convolvesize , cache = cache )
1887+
1888+ # Determine convolution mode based on parameter periodicity
1889+ if parx .periodic and pary .periodic :
1890+ convolution_mode = "periodic_both"
1891+ elif parx .periodic :
1892+ convolution_mode = "periodic_x"
1893+ elif pary .periodic :
1894+ convolution_mode = "periodic_y"
1895+ else :
1896+ convolution_mode = "same"
1897+
1898+ bins2D = convolve2D (histbins , Win , convolution_mode , largest_size = convolvesize , cache = cache )
18821899
18831900 if meanlikes :
1884- bin2Dlikes = convolve2D (finebinlikes , Win , "same" , largest_size = convolvesize , cache = cache , cache_args = [2 ])
1901+ bin2Dlikes = convolve2D (
1902+ finebinlikes , Win , convolution_mode , largest_size = convolvesize , cache = cache , cache_args = [2 ]
1903+ )
18851904 if mult_bias_correction_order :
18861905 ix = bin2Dlikes > 0
18871906 finebinlikes [ix ] /= bin2Dlikes [ix ]
1888- likes2 = convolve2D (finebinlikes , Win , "same" , largest_size = convolvesize , cache = cache , cache_args = [2 ])
1907+ likes2 = convolve2D (
1908+ finebinlikes , Win , convolution_mode , largest_size = convolvesize , cache = cache , cache_args = [2 ]
1909+ )
18891910 likes2 [ix ] *= bin2Dlikes [ix ]
18901911 bin2Dlikes = likes2
18911912 del finebinlikes
@@ -1896,17 +1917,26 @@ def get2DDensityGridData(
18961917 bin2Dlikes = None
18971918
18981919 bool_mask = None
1920+
18991921 if has_prior and boundary_correction_order >= 0 or mult_bias_correction_order or mask_function :
1922+ # Always pad by winw in both axes so that 'valid' convolution returns (ysize, xsize)
1923+ # Masks are only applied on non-periodic axes; periodic axes remain as ones.
19001924 prior_mask = np .ones ((ysize + 2 * winw , xsize + 2 * winw ))
19011925 if mask_function :
19021926 mask_function (
1903- xbinmin - winw * finewidthx , ybinmin - winw * finewidthy , finewidthx , finewidthy , prior_mask
1927+ xbinmin - winw * finewidthx ,
1928+ ybinmin - winw * finewidthy ,
1929+ finewidthx ,
1930+ finewidthy ,
1931+ prior_mask ,
19041932 )
19051933 bool_mask = prior_mask [winw :- winw , winw :- winw ] < 1e-8
19061934
1907- if has_prior and boundary_correction_order >= 0 :
1908- # Correct for edge effects
1935+ if has_prior and boundary_correction_order >= 0 and not ( parx . periodic and pary . periodic ) :
1936+ # Correct for edge effects; if only one axis is periodic still correct on the other axis
19091937 self ._setEdgeMask2D (parx , pary , prior_mask , winw )
1938+ # Use 'valid' on the padded prior_mask so the result is (ysize, xsize)
1939+ # For periodic axes prior_mask is ones along that axis, so this is consistent
19101940 a00 = convolve2D (prior_mask , Win , "valid" , largest_size = convolvesize , cache = cache )
19111941 ix = a00 * bins2D > np .max (bins2D ) * 1e-8
19121942 a00 = a00 [ix ]
@@ -1933,8 +1963,8 @@ def get2DDensityGridData(
19331963 a11 = convolve2D (
19341964 prior_mask , winy * indexes , "valid" , largest_size = convolvesize , cache = cache , cache_args = [1 ]
19351965 )[ix ]
1936- xP = convolve2D (histbins , winx , "same" , largest_size = convolvesize , cache = cache )[ix ]
1937- yP = convolve2D (histbins , winy , "same" , largest_size = convolvesize , cache = cache )[ix ]
1966+ xP = convolve2D (histbins , winx , convolution_mode , largest_size = convolvesize , cache = cache )[ix ]
1967+ yP = convolve2D (histbins , winy , convolution_mode , largest_size = convolvesize , cache = cache )[ix ]
19381968 denom = a20 * a01 ** 2 + a10 ** 2 * a02 - a00 * a02 * a20 + a11 ** 2 * a00 - 2 * a01 * a10 * a11
19391969 A = a11 ** 2 - a02 * a20
19401970 Ax = a10 * a02 - a01 * a11
@@ -1944,14 +1974,16 @@ def get2DDensityGridData(
19441974 else :
19451975 raise SettingError ("unknown boundary_correction_order (expected 0 or 1)" )
19461976
1947- if mult_bias_correction_order :
1948- self ._setAllEdgeMask2D (prior_mask , winw )
1977+ if mult_bias_correction_order and not (parx .periodic and pary .periodic ):
1978+ # If only one axis is periodic still correct on the non-periodic edges
1979+ self ._setAllEdgeMask2D (prior_mask , winw , periodic_x = parx .periodic , periodic_y = pary .periodic )
1980+ # Use 'valid' on the padded prior_mask so the result is (ysize, xsize)
19491981 a00 = convolve2D (prior_mask , Win , "valid" , largest_size = convolvesize , cache = cache , cache_args = [2 ])
19501982 for _ in range (mult_bias_correction_order ):
19511983 box = histbins .copy ()
19521984 ix2 = bins2D > np .max (bins2D ) * 1e-8
19531985 box [ix2 ] /= bins2D [ix2 ]
1954- bins2D *= convolve2D (box , Win , "same" , largest_size = convolvesize , cache = cache , cache_args = [2 ])
1986+ bins2D *= convolve2D (box , Win , convolution_mode , largest_size = convolvesize , cache = cache , cache_args = [2 ])
19551987 if mask_function :
19561988 bins2D [~ bool_mask ] /= a00 [~ bool_mask ]
19571989 else :
0 commit comments