def test_from_subclass_complete_info(self, instance, format_type): """ Test transforming an instance and parsing from that class, when there's full information available. """ format, objtype = format_type cosmo = getattr(cosmology.realizations, instance) # test to_format obj = cosmo.to_format(format) assert isinstance(obj, objtype) # read with the same class that wrote. got = cosmo.__class__.from_format(obj, format=format) got2 = Cosmology.from_format(obj) # and autodetect assert got2 == got # internal consistency assert got == cosmo # external consistency assert got.meta == cosmo.meta # this should be equivalent to got = Cosmology.from_format(obj, format=format, cosmology=cosmo.__class__) assert got == cosmo assert got.meta == cosmo.meta # and also got = Cosmology.from_format(obj, format=format, cosmology=cosmo.__class__.__qualname__) assert got == cosmo assert got.meta == cosmo.meta
def test_fromformat_subclass_partial_info_mapping(self, cosmo): """ Test writing from an instance and reading from that class. This works with missing information. """ m = cosmo.to_format("mapping") # partial information m.pop("cosmology", None) m.pop("Tcmb0", None) # read with the same class that wrote fills in the missing info with # the default value got = cosmo.__class__.from_format(m, format="mapping") got2 = Cosmology.from_format(m, format="mapping", cosmology=cosmo.__class__) got3 = Cosmology.from_format(m, format="mapping", cosmology=cosmo.__class__.__qualname__) assert (got == got2) and (got2 == got3) # internal consistency # not equal, because Tcmb0 is changed, which also changes m_nu assert got != cosmo assert got.Tcmb0 == cosmo.__class__._init_signature.parameters[ "Tcmb0"].default assert got.clone(name=cosmo.name, Tcmb0=cosmo.Tcmb0, m_nu=cosmo.m_nu) == cosmo # but the metadata is the same assert got.meta == cosmo.meta
def test_fromformat_subclass_complete_info(self, cosmo_cls, cosmo, format, objtype): """ Test transforming an instance and parsing from that class, when there's full information available. Partial information tests are handled in the Mixin super classes. """ # test to_format obj = cosmo.to_format(format) assert isinstance(obj, objtype) # read with the same class that wrote. got = cosmo_cls.from_format(obj, format=format) got2 = Cosmology.from_format(obj) # and autodetect assert got2 == got # internal consistency assert got == cosmo # external consistency assert got.meta == cosmo.meta # this should be equivalent to got = Cosmology.from_format(obj, format=format, cosmology=cosmo_cls) assert got == cosmo assert got.meta == cosmo.meta # and also got = Cosmology.from_format(obj, format=format, cosmology=cosmo_cls.__qualname__) assert got == cosmo assert got.meta == cosmo.meta
def test_tofromformat_complete_info(self, cosmo, format, objtype): """Read tests happen later.""" # test to_format obj = cosmo.to_format(format) assert isinstance(obj, objtype) # test from_format got = Cosmology.from_format(obj, format=format) # and autodetect got2 = Cosmology.from_format(obj) assert got2 == got # internal consistency assert got == cosmo # external consistency assert got.meta == cosmo.meta
def test_fromformat_class_mismatch(self, cosmo, format_type): format, objtype = format_type # test to_format obj = cosmo.to_format(format) assert isinstance(obj, objtype) # class mismatch with pytest.raises(TypeError): w0wzCDM.from_format(obj, format=format) with pytest.raises(TypeError): Cosmology.from_format(obj, format=format, cosmology=w0wzCDM) # when specifying the class with pytest.raises(ValueError, match="`cosmology` must be either"): w0wzCDM.from_format(obj, format=format, cosmology="FlatLambdaCDM")
def test_tofromformat_complete_info(self, cosmo, format, totype, xfail_if_not_registered_with_yaml): """Read tests happen later.""" # test to_format obj = cosmo.to_format(format) assert isinstance(obj, totype) # test from_format got = Cosmology.from_format(obj, format=format) # Test autodetect, if enabled if self.can_autodentify(format): got2 = Cosmology.from_format(obj) assert got2 == got # internal consistency assert got == cosmo # external consistency assert got.meta == cosmo.meta
def test_fromformat_class_mismatch(self, instance, format_type): cosmo = getattr(cosmology.realizations, instance) format, objtype = format_type # test to_format obj = cosmo.to_format(format) assert isinstance(obj, objtype) # class mismatch with pytest.raises(TypeError, match="missing 1 required"): w0wzCDM.from_format(obj, format=format) with pytest.raises(TypeError, match="missing 1 required"): Cosmology.from_format(obj, format=format, cosmology=w0wzCDM) # when specifying the class with pytest.raises(ValueError, match="`cosmology` must be either"): w0wzCDM.from_format(obj, format=format, cosmology="FlatLambdaCDM")
def test_roundtrip_from_astropy(self, expected): # convert to ``mypackage`` mycosmo = expected.to_format("mypackage") # Read back got = Cosmology.from_format(mycosmo, format="mypackage") # test round-tripped as expected assert got == expected # tests immutable parameters, e.g. H0
def read_myformat(filename, **kwargs): if isinstance(filename, (str, bytes, os.PathLike)): with open(filename, "r") as file: data = file.read() else: # file-like : this also handles errors in dumping data = filename.read() mapping = {} ... # process `data`, adding to `mapping` return Cosmology.from_format(mapping, **kwargs)
def test_roundtrip_from_mypackage(self, expected): # convert to Astropy acosmo = Cosmology.from_format(expected, format="mypackage") # convert back to ``mypackage``` got = acosmo.to_format("mypackage") # test round-tripped as expected assert isinstance(got, MyCosmology) assert got == expected # assuming ``MyCosmology`` has an __eq__ method ... # more equality tests
def read_json(filename, **kwargs): with open(filename, "r") as file: data = file.read() mapping = json.loads(data) # parse json mappable to dict # deserialize Quantity for k, v in mapping.items(): if isinstance(v, dict) and "value" in v and "unit" in v: mapping[k] = u.Quantity(v["value"], v["unit"]) for k, v in mapping.get("meta", {}).items(): # also the metadata if isinstance(v, dict) and "value" in v and "unit" in v: mapping["meta"][k] = u.Quantity(v["value"], v["unit"]) return Cosmology.from_format(mapping, **kwargs)
def from_mypackage(mycosmo): """Load `~astropy.cosmology.Cosmology` from ``mypackage`` object.""" # Cosmology provides a nice method "mapping", so all that needs to # be done here is create a dictionary of the parameters mapping = {} mapping["H0"] = mycosmo.hubble_parameter mapping["Om0"] = mycosmo.Omega_matter_initial ... # keep building mapping return Cosmology.from_format( mapping, format="mapping", move_to_meta=True ) # extra info -> meta
def test_from_subclass_partial_info(self, instance): """ Test writing from an instance and reading from that class. This requires partial information. .. todo:: generalize over all formats for this test. """ format, objtype = ("mapping", dict) cosmo = getattr(cosmology.realizations, instance) # test to_format obj = cosmo.to_format(format) assert isinstance(obj, objtype) # partial information tempobj = copy.deepcopy(obj) del tempobj["cosmology"] del tempobj["Tcmb0"] # read with the same class that wrote fills in the missing info with # the default value got = cosmo.__class__.from_format(tempobj, format=format) got2 = Cosmology.from_format(tempobj, format=format, cosmology=cosmo.__class__) got3 = Cosmology.from_format(tempobj, format=format, cosmology=cosmo.__class__.__qualname__) assert (got == got2) and (got2 == got3) # internal consistency # not equal, because Tcmb0 is changed assert got != cosmo assert got.Tcmb0 == cosmo.__class__._init_signature.parameters[ "Tcmb0"].default assert got.clone(name=cosmo.name, Tcmb0=cosmo.Tcmb0) == cosmo # but the metadata is the same assert got.meta == cosmo.meta
def read_myformat(filename, **kwargs): """Read files in format 'myformat'. Parameters ---------- filename : str **kwargs Keyword arguments into `astropy.cosmology.Cosmology.from_format` with ``format="mypackage"``. Returns ------- `~mypackage.cosmology.MyCosmology` instance """ mycosmo = file_reader(filename) # ← read file ↓ build Cosmology return Cosmology.from_format(mycosmo, format="mypackage", **kwargs)
def test_to_from_mapping_instance(expected): # ------------ # To Mapping params = expected.to_format('mapping') assert isinstance(params, dict) assert params["cosmology"] is expected.__class__ assert params["name"] == expected.name # ------------ # From Mapping params["mismatching"] = "will error" # tests are different if the last argument is a **kwarg if tuple(expected._init_signature.parameters.values())[-1].kind == 4: got = Cosmology.from_format(params, format="mapping") assert got.__class__ == expected.__class__ assert got.name == expected.name assert "mismatching" not in got.meta return # don't continue testing # read with mismatching parameters errors with pytest.raises(TypeError, match="there are unused parameters"): Cosmology.from_format(params, format="mapping") # unless mismatched are moved to meta got = Cosmology.from_format(params, format="mapping", move_to_meta=True) assert got.__class__ == expected.__class__ assert got == expected assert got.meta["mismatching"] == "will error" # it won't error if everything matches up params.pop("mismatching") got = Cosmology.from_format(params, format="mapping") assert got.__class__ == expected.__class__ assert got == expected # and it will also work if the cosmology is a string params["cosmology"] = params["cosmology"].__name__ got = Cosmology.from_format(params, format="mapping") assert got == expected # also it auto-identifies 'format' got = Cosmology.from_format(params) assert got == expected
def from_mypackage(mycosmo): """Load `~astropy.cosmology.Cosmology` from ``mypackage`` object. Parameters ---------- mycosmo : `~mypackage.cosmology.MyCosmology` Returns ------- `~astropy.cosmology.Cosmology` """ m = dict(mycosmo) m["name"] = mycosmo.name # ---------------- # remap Parameters m["H0"] = m.pop("hubble_parameter") * (u.km / u.s / u.Mpc) m["Om0"] = m.pop("initial_matter_density") m["Tcmb0"] = m.pop("initial_temperature") * u.K # m["Neff"] = m.pop("Neff") # skip b/c unchanged m["m_nu"] = m.pop("neutrino_masses") * u.eV m["Ob0"] = m.pop("initial_baryon_density") # ---------------- # remap metadata m["t0"] = m.pop("current_age") * u.Gyr # optional if "reionization_redshift" in m: m["z_reion"] = m.pop("reionization_redshift") # ... # keep building `m` # ---------------- # Detect which type of Astropy cosmology to build. # TODO! CUSTOMIZE FOR DETECTION # Here we just force FlatLambdaCDM, but if your package allows for # non-flat cosmologies... m["cosmology"] = FlatLambdaCDM # build cosmology return Cosmology.from_format(m, format="mapping", move_to_meta=True)