Jammy2211 / PyAutoLens

PyAutoLens: Open Source Strong Gravitational Lensing
https://pyautolens.readthedocs.io/
MIT License
164 stars 32 forks source link

Galaxy.dict() not returning parameters correctly #188

Open samlange04 opened 2 years ago

samlange04 commented 2 years ago

When calling the .dict() instance to extract the parameters of a galaxy, there are a few errors:

  1. The type instance is saved as a string rather than a callable to the function (same for individual mass/light profiles)
  2. If a parameter is drawn from a numpy array (e.g. when randomising and drawing), the dict returns the type rather than the value of the parameter.

See the example below:

lens = al.Galaxy(redshift=1.,
                 light = al.lp.EllSersic(intensity = np.array([0.1])[0]),
                 mass=al.mp.EllIsothermal())
lens.dict()

{'light': {'type': 'autogalaxy.profiles.light_profiles.light_profiles.EllSersic', 'centre': (0.0, 0.0), 'elliptical_comps': (0.0, 0.0), 'intensity': {'type': 'numpy.float64'}, 'effective_radius': 0.6, 'sersic_index': 4.0}, 'mass': {'type': 'autogalaxy.profiles.mass_profiles.total_mass_profiles.EllIsothermal', 'centre': (0.0, 0.0), 'elliptical_comps': (0.0, 0.0), 'einstein_radius': 1.0}, 'type': 'autogalaxy.galaxy.galaxy.Galaxy', 'redshift': 1.0, 'pixelization': None, 'regularization': None, 'hyper_galaxy': None}

Jammy2211 commented 2 years ago

The type instance is saved as a string rather than a callable to the function (same for individual mass/light profiles)

Digging deep into the code, I think this is the intended behavior.

To load a Galaxy (or any Dictable object, e.g. a Plane or Tracer) from a .json file you should be able to do the following:

import json

from autoconf.dictable import Dictable
import autogalaxy as ag

json_file = "galaxy.json"

galaxy = ag.Galaxy(
        redshift=1.0, pixelization=ag.pix.VoronoiMagnification(), regularization=ag.reg.AdaptiveBrightness()
    )

with open(json_file, "w+") as f:
    json.dump(galaxy.dict(), f, indent=4)

with open(json_file, "r+") as f:
    galaxy_dict = json.load(f)

galaxy_from_dict = Dictable.from_dict(galaxy_dict)

print(galaxy_from_dict)

It is a bit odd that doing the following:

galaxy_from_dict = ag.Galaxy.from_dict(galaxy_dict)

Raises the following exception:

<autoarray.inversion.regularization.adaptive_brightness.AdaptiveBrightness object at 0x0000021B2F377BB0>
Traceback (most recent call last):
  File "C:/Users/Jammy/Code/PyAuto/autolens_workspace_test/galaxy_dict.py", line 22, in <module>
    galaxy_from_dict = ag.Galaxy.from_dict(galaxy_dict)
  File "C:\Users\Jammy\Code\PyAuto\PyAutoFit\autofit\mapper\model_object.py", line 80, in from_dict
    type_ = d["type"]
KeyError: 'type'

@rhayes777 I guess this is because it is expecting that the Galaxy was output as a Model object, as opposed to an instance of a Galaxy?

Jammy2211 commented 2 years ago

If a parameter is drawn from a numpy array (e.g. when randomising and drawing), the dict returns the type rather than the value of the parameter.

I didn't clock before that you were inputting parameters as a value of a NumPy array.

I would simply convert these to floats before inputting them, as things like a Galaxy are not inspecting numpy array inputs:

lens = al.Galaxy(redshift=1.,
                 light = al.lp.EllSersic(intensity = float(np.array([0.1])[0])),
                 mass=al.mp.EllIsothermal())
Jammy2211 commented 2 years ago

I have put up the following PR which will allow the following API to work:

https://github.com/rhayes777/PyAutoConf/pull/18

        tracer.output_to_json(file_path=json_file)

        tracer_from_json = al.Tracer.from_json(file_path=json_file)
        galaxy.output_to_json(file_path=json_file)

        galaxy_from_json = al.Galaxy.from_json(file_path=json_file)