Jammy2211 / PyAutoGalaxy

PyAutoGalaxy: Open-Source Multiwavelength Galaxy Structure & Morphology
https://pyautogalaxy.readthedocs.io/
MIT License
27 stars 13 forks source link

Dont edit state when mapping linear light profiles #101

Closed Jammy2211 closed 1 year ago

Jammy2211 commented 1 year ago

The following code makes the cardinal sin of editing state of an object:

https://github.com/Jammy2211/PyAutoGalaxy/blob/feature/linear_light_visuals_fix/autogalaxy/abstract_fit.py

    @property
    def model_obj_linear_light_profiles_to_light_profiles(self):
        """
        The model object may contain linear light profiles, which solve for the `intensity` during the `Inversion`.

        This means they are difficult to visualize, because they do not have a valid `intensity` parameter.

        To address this, this property creates a new `model_obj` where all linear light profiles are converted to
        ordinary light profiles whose `intensity` parameters are set to the results of the Inversion.

        Returns
        -------
        A `model_obj` (E.g. `Plane` or `Tracer`) where the light profile intensity values are set to the results
        of those inferred via the `Inversion`.
        """

        if self.linear_light_profile_intensity_dict is None:
            return self.model_obj

        model_obj = copy.copy(self.model_obj)

        for galaxy in model_obj.galaxies:
            for key, obj in galaxy.__dict__.items():
                if isinstance(obj, LightProfileLinear) or isinstance(obj, Basis):
                    galaxy.__dict__[key] = obj.lp_instance_from(
                        linear_light_profile_intensity_dict=self.linear_light_profile_intensity_dict
                    )

        return model_obj

This is causing horrible bugs (foturnely, visualization only), downstream in the code.

Could you rewirte the function to not edit state? I am struggling to figure out how to do this myself.

The function effectively takes a Plane or Tracer object (which is what self.model_obj is) and creates a new one, where all LightProfileLinear and Basis objects are mapped such that any linear light profiles become ordinary light profiles.

This is required for performing visualization.

You may need to implement the solution separately in the following functions:

    @property
    def plane_linear_light_profiles_to_light_profiles(self) -> Plane:
        """
        The `Plane` where all linear light profiles have been converted to ordinary light profiles, where their
        `intensity` values are set to the values inferred by this fit.

        This is typically used for visualization, because linear light profiles cannot be used in `LightProfilePlotter`
        or `GalaxyPlotter` objects.
        """
        return self.model_obj_linear_light_profiles_to_light_profiles
    @property
    def tracer_linear_light_profiles_to_light_profiles(self) -> Tracer:
        """
        The `Tracer` where all linear light profiles have been converted to ordinary light profiles, where their
        `intensity` values are set to the values inferred by this fit.

        This is typically used for visualization, because linear light profiles cannot be used in `LightProfilePlotter`
        or `GalaxyPlotter` objects.
        """
        return self.model_obj_linear_light_profiles_to_light_profiles
Jammy2211 commented 1 year ago

Note that both projects are on the following branch for this issue:

https://github.com/Jammy2211/PyAutoGalaxy/tree/feature/linear_light_visuals_fix https://github.com/Jammy2211/PyAutoLens/tree/feature/linear_light_visuals_fix