@@ -651,57 +651,85 @@ def curvature_matrix_off_diags_via_sparse_operator_from(
651651
652652
653653@numba_util .jit ()
654- def curvature_matrix_off_diags_via_data_linear_func_matrix_from (
655- data_linear_func_matrix : np .ndarray ,
654+ def curvature_matrix_off_diags_via_mapper_and_linear_func_curvature_vector_from (
656655 data_to_pix_unique : np .ndarray ,
657656 data_weights : np .ndarray ,
658657 pix_lengths : np .ndarray ,
659658 pix_pixels : int ,
660- ):
659+ curvature_weights : np .ndarray , # shape (n_unmasked, n_funcs)
660+ mask : np .ndarray , # shape (ny, nx), bool
661+ psf_kernel : np .ndarray , # shape (ky, kx)
662+ ) -> np .ndarray :
661663 """
662- Returns the off diagonal terms in the curvature matrix `F` (see Warren & Dye 2003) between a mapper object
663- and a linear func object, using the preloaded `data_linear_func_matrix` of the values of the linear functions.
664-
664+ Returns the off- diagonal terms in the curvature matrix `F` (see Warren & Dye 2003)
665+ between a mapper object and a linear func object, using the unique mappings between
666+ data pixels and pixelization pixels.
665667
666- If a linear function in an inversion is fixed, its values can be evaluated and preloaded beforehand. For every
667- data pixel, the PSF convolution with this preloaded linear function can also be preloaded, in a matrix of
668- shape [data_pixels, 1].
668+ This version applies the PSF directly as a 2D convolution kernel. The curvature
669+ weights of the linear function object (values of the linear function divided by the
670+ noise-map squared) are expanded into the native 2D image grid, convolved with the PSF
671+ kernel, and then remapped back to the 1D slim representation.
669672
670- When mapper objects and linear functions are used simultaneously in an inversion, this preloaded matrix
671- significantly speed up the computation of their off-diagonal terms in the curvature matrix.
672-
673- This function performs this efficient calcluation via the preloaded `data_linear_func_matrix` .
673+ For each unique mapping between a data pixel and a pixelization pixel, the convolved
674+ curvature weights at that data pixel are multiplied by the mapping weights and
675+ accumulated into the off-diagonal block of the curvature matrix. This accounts for
676+ sub-pixel mappings between data pixels and pixelization pixels .
674677
675678 Parameters
676679 ----------
677- data_linear_func_matrix
678- A matrix of shape [data_pixels, total_fixed_linear_functions] that for each data pixel, maps it to the sum of
679- the values of a linear object function convolved with the PSF kernel at the data pixel.
680680 data_to_pix_unique
681- The indexes of all pixels that each data pixel maps to (see the `Mapper` object).
681+ An array that maps every data pixel index (e.g. the masked image pixel indexes in 1D)
682+ to its unique set of pixelization pixel indexes (see `data_slim_to_pixelization_unique_from`).
682683 data_weights
683- The weights of all pixels that each data pixel maps to (see the `Mapper` object).
684+ For every unique mapping between a set of data sub-pixels and a pixelization pixel,
685+ the weight of this mapping based on the number of sub-pixels that map to the pixelization pixel.
684686 pix_lengths
685- The number of pixelization pixels that each data pixel maps to (see the `Mapper` object).
687+ A 1D array describing how many unique pixels each data pixel maps to. Used to iterate over
688+ `data_to_pix_unique` and `data_weights`.
686689 pix_pixels
687- The number of pixelization pixels in the pixelization (see the `Mapper` object).
688- """
689-
690- linear_func_pixels = data_linear_func_matrix .shape [1 ]
691-
692- off_diag = np .zeros ((pix_pixels , linear_func_pixels ))
690+ The total number of pixels in the pixelization that reconstructs the data.
691+ curvature_weights
692+ The operated values of the linear function divided by the noise-map squared, with shape
693+ [n_unmasked_data_pixels, n_linear_func_pixels].
694+ mask
695+ A 2D boolean mask of shape (ny, nx) indicating which pixels are in the data region.
696+ psf_kernel
697+ The PSF kernel in its native 2D form, centered (odd dimensions recommended).
693698
699+ Returns
700+ -------
701+ ndarray
702+ The off-diagonal block of the curvature matrix `F` (see Warren & Dye 2003),
703+ with shape [pix_pixels, n_linear_func_pixels].
704+ """
694705 data_pixels = data_weights .shape [0 ]
695-
706+ n_funcs = curvature_weights .shape [1 ]
707+ ny , nx = mask .shape
708+
709+ # Expand curvature weights into native grid
710+ curvature_native = np .zeros ((ny , nx , n_funcs ))
711+ unmasked_coords = np .argwhere (~ mask )
712+ for i , (y , x ) in enumerate (unmasked_coords ):
713+ for f in range (n_funcs ):
714+ curvature_native [y , x , f ] = curvature_weights [i , f ]
715+
716+ # Convolve in native space
717+ blurred_native = convolve_with_kernel_native (curvature_native , psf_kernel )
718+
719+ # Map back to slim representation
720+ blurred_slim = np .zeros ((data_pixels , n_funcs ))
721+ for i , (y , x ) in enumerate (unmasked_coords ):
722+ for f in range (n_funcs ):
723+ blurred_slim [i , f ] = blurred_native [y , x , f ]
724+
725+ # Accumulate into off_diag
726+ off_diag = np .zeros ((pix_pixels , n_funcs ))
696727 for data_0 in range (data_pixels ):
697728 for pix_0_index in range (pix_lengths [data_0 ]):
698729 data_0_weight = data_weights [data_0 , pix_0_index ]
699730 pix_0 = data_to_pix_unique [data_0 , pix_0_index ]
700-
701- for linear_index in range (linear_func_pixels ):
702- off_diag [pix_0 , linear_index ] += (
703- data_linear_func_matrix [data_0 , linear_index ] * data_0_weight
704- )
731+ for f in range (n_funcs ):
732+ off_diag [pix_0 , f ] += data_0_weight * blurred_slim [data_0 , f ]
705733
706734 return off_diag
707735
0 commit comments