@@ -467,8 +467,61 @@ def _curvature_matrix_func_list_and_mapper(self) -> np.ndarray:
467467
468468 return curvature_matrix
469469
470+ def _mapped_reconstructed_data_dict_from (
471+ self ,
472+ * ,
473+ use_operated_for_linear_func : bool ,
474+ ) -> Dict ["LinearObj" , "Array2D" ]:
475+ """
476+ Shared implementation for mapping a reconstruction to image-plane arrays for each linear object.
477+
478+ - AbstractMapper: uses unique mappings (w-tilde compatible) + PSF convolution.
479+ - Linear-func: uses either operated or unoperated mapping matrix dict.
480+ """
481+ mapped_dict : Dict ["LinearObj" , "Array2D" ] = {}
482+
483+ reconstruction_dict = self .source_quantity_dict_from (
484+ source_quantity = self .reconstruction
485+ )
486+
487+ for linear_obj in self .linear_obj_list :
488+ reconstruction = reconstruction_dict [linear_obj ]
489+
490+ if isinstance (linear_obj , AbstractMapper ):
491+
492+ mapped = inversion_imaging_numba_util .mapped_reconstructed_data_via_image_to_pix_unique_from (
493+ data_to_pix_unique = linear_obj .unique_mappings .data_to_pix_unique ,
494+ data_weights = linear_obj .unique_mappings .data_weights ,
495+ pix_lengths = linear_obj .unique_mappings .pix_lengths ,
496+ reconstruction = np .array (reconstruction ),
497+ )
498+
499+ mapped = Array2D (values = mapped , mask = self .mask )
500+
501+ if use_operated_for_linear_func :
502+ mapped = self .psf .convolved_image_from (
503+ image = mapped ,
504+ blurring_image = None ,
505+ ).array
506+
507+ mapped = Array2D (values = mapped , mask = self .mask )
508+
509+ else :
510+
511+ if use_operated_for_linear_func :
512+ mapping_matrix = self .linear_func_operated_mapping_matrix_dict [linear_obj ]
513+ else :
514+ mapping_matrix = self .linear_func_mapping_matrix_dict [linear_obj ]
515+
516+ mapped = np .sum (reconstruction * mapping_matrix , axis = 1 )
517+ mapped = Array2D (values = mapped , mask = self .mask )
518+
519+ mapped_dict [linear_obj ] = mapped
520+
521+ return mapped_dict
522+
470523 @property
471- def mapped_reconstructed_operated_data_dict (self ) -> Dict [LinearObj , Array2D ]:
524+ def mapped_reconstructed_data_dict (self ) -> Dict [LinearObj , Array2D ]:
472525 """
473526 When constructing the simultaneous linear equations (via vectors and matrices) the quantities of each individual
474527 linear object (e.g. their `mapping_matrix`) are combined into single ndarrays via stacking. This does not track
@@ -482,6 +535,9 @@ def mapped_reconstructed_operated_data_dict(self) -> Dict[LinearObj, Array2D]:
482535 This function converts an ndarray of a `reconstruction` to a dictionary of ndarrays containing each linear
483536 object's reconstructed data values, where the keys are the instances of each mapper in the inversion.
484537
538+ The images are the unconvolved reconstructed data values, meaning they are the solved for reconstruction
539+ with PSF operations removed.
540+
485541 The w-tilde formalism bypasses the calculation of the `mapping_matrix` and it therefore cannot be used to map
486542 the reconstruction's values to the image-plane. Instead, the unique data-to-pixelization mappings are used,
487543 including the 2D convolution operation after mapping is complete.
@@ -492,52 +548,40 @@ def mapped_reconstructed_operated_data_dict(self) -> Dict[LinearObj, Array2D]:
492548 The reconstruction (in the source frame) whose values are mapped to a dictionary of values for each
493549 individual mapper (in the image-plane).
494550 """
495-
496- mapped_reconstructed_operated_data_dict = {}
497-
498- reconstruction_dict = self .source_quantity_dict_from (
499- source_quantity = self .reconstruction
551+ return self ._mapped_reconstructed_data_dict_from (
552+ use_operated_for_linear_func = False
500553 )
501554
502- for linear_obj in self .linear_obj_list :
503- reconstruction = reconstruction_dict [linear_obj ]
504-
505- if isinstance (linear_obj , AbstractMapper ):
506-
507- mapped_reconstructed_image = inversion_imaging_numba_util .mapped_reconstructed_data_via_image_to_pix_unique_from (
508- data_to_pix_unique = linear_obj .unique_mappings .data_to_pix_unique ,
509- data_weights = linear_obj .unique_mappings .data_weights ,
510- pix_lengths = linear_obj .unique_mappings .pix_lengths ,
511- reconstruction = np .array (reconstruction ),
512- )
513-
514- mapped_reconstructed_image = Array2D (
515- values = mapped_reconstructed_image , mask = self .mask
516- )
517-
518- mapped_reconstructed_image = self .psf .convolved_image_from (
519- image = mapped_reconstructed_image ,
520- blurring_image = None ,
521- ).array
555+ @property
556+ def mapped_reconstructed_operated_data_dict (self ) -> Dict [LinearObj , Array2D ]:
557+ """
558+ When constructing the simultaneous linear equations (via vectors and matrices) the quantities of each individual
559+ linear object (e.g. their `mapping_matrix`) are combined into single ndarrays via stacking. This does not track
560+ which quantities belong to which linear objects, therefore the linear equation's solutions (which are returned
561+ as ndarrays) do not contain information on which linear object(s) they correspond to.
522562
523- mapped_reconstructed_image = Array2D (
524- values = mapped_reconstructed_image , mask = self . mask
525- )
563+ For example, consider if two `Mapper` objects with 50 and 100 source pixels are used in an `Inversion`.
564+ The `reconstruction` (which contains the solved for source pixels values) is an ndarray of shape [150], but
565+ the ndarray itself does not track which values belong to which `Mapper`.
526566
527- else :
567+ This function converts an ndarray of a `reconstruction` to a dictionary of ndarrays containing each linear
568+ object's reconstructed data values, where the keys are the instances of each mapper in the inversion.
528569
529- operated_mapping_matrix = self .linear_func_operated_mapping_matrix_dict [
530- linear_obj
531- ]
570+ The images are the convolved reconstructed data values, meaning they are the solved for reconstruction with PSF
571+ operations included.
532572
533- mapped_reconstructed_image = np . sum (
534- reconstruction * operated_mapping_matrix , axis = 1
535- )
573+ The w-tilde formalism bypasses the calculation of the `mapping_matrix` and it therefore cannot be used to map
574+ the reconstruction's values to the image-plane. Instead, the unique data-to-pixelization mappings are used,
575+ including the 2D convolution operation after mapping is complete.
536576
537- mapped_reconstructed_image = Array2D (
538- values = mapped_reconstructed_image , mask = self .mask
539- )
577+ Parameters
578+ ----------
579+ reconstruction
580+ The reconstruction (in the source frame) whose values are mapped to a dictionary of values for each
581+ individual mapper (in the image-plane).
582+ """
583+ return self ._mapped_reconstructed_data_dict_from (
584+ use_operated_for_linear_func = True
585+ )
540586
541- mapped_reconstructed_operated_data_dict [linear_obj ] = mapped_reconstructed_image
542587
543- return mapped_reconstructed_operated_data_dict
0 commit comments