Coverage for python/lsst/sims/photUtils/CosmologyObject.py : 15%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""
231 October 2014
4The class CosmologyObject provides an interface for the methods in astropy.cosmology that
5we anticipate using the most.
7The methods in astropy.cosmology are accessed by instantiating a cosmology object and calling
8methods that belong to that object. CosmologyObject interfaces with this by declaring a member
9variable self.activeCosmology. Methods provided by CosmologyObject call the equivalent
10astropy.cosmology methods on self.activeCosmology. activeCosmology is set by calling
11CosmologyObject.initializeCosmology(args...) with the appropriate cosmological paramters.
12Passing in no parametrs loads the Millennium Simulation cosmology (Springel et al 2005, Nature 435, 629
13or arXiv:astro-ph/0504097).
15The difficulty with all of this that, between the version of astropy shipped with anaconda (v0.2.5) and
16the most modern version (v0.4), the API for astropy.cosmology has changed in two ways.
18One difference is that methods like comoving_distance have gone from returning floats to returning
19astropy.Quantity's which come with both a value and units. To deal with this, CosmologyObject
20checks dir(cosmology.comoving_distance()) etc. If 'units' is defined, CosmologyObject sets
21member variables such as self.distanceUnits, self.hUnits, and self.modulusUnits defining the units
22in which we want to return those quantities. When you call the wrapper for comoving_distance,
23CosmologyObject will make sure that the output is returned in the units we expect (Mpc).
24The expected units are set in CosmologyObject.setUnits()
26The other API difference is in how 'default_cosmology' is stored. astropy.cosmology allows
27the user to set a default cosmology that the system stores so that the user does not have to
28constantly redeclare the same cosmology object at different points in the code. Unfortunately,
29the naming conventions for the methods to set and retrieve this default cosmology have changed
30between recent versions of astropy. CosmologyObject deals with this change in API using
31CosmologyObject.setCurrent() (called automatically by CosmologyObject's __init__)
32and CosmologyObject.getCurrent(), which returns a cosmology object containing the activeCosmology
33contained in CosmologyObject.
35A user who wants to interact with the naked
36astropy.cosmology methods can run something like
38uu = CosmologyObject() #which sets activeCosmology to the Millennium Simulation cosmology
39myUniverse = uu.getCurrent()
41myUniverse now contains a cosmology object which is equivalent to the activeCosmology. Direct
42calls to the astropy.cosmology methods of the form
44dd = myUniverse.comoving_distance(1.0) #comoving distance to redshift z=1
46will now work.
49The methods in CosmologyObject have been tested on astropy v0.2.5 and v0.4.2
50"""
52from builtins import object
53import numpy
54import astropy.cosmology as cosmology
55import astropy.units as units
57flatnessthresh = 1.0e-12
59__all__ = ["CosmologyObject"]
61class CosmologyObject(object):
63 def __init__(self, H0=73.0, Om0=0.25, Ok0=None, w0=None, wa=None):
64 """
65 Initialize the cosmology wrapper with the parameters specified
66 (e.g. does not account for massive neutrinos)
68 param [in] H0 is the Hubble parameter at the present epoch in km/s/Mpc
70 param [in] Om0 is the current matter density paramter (fraction of critical density)
72 param [in] Ok0 is the current curvature density parameter
74 param [in] w0 is the current dark energy equation of state w0 paramter
76 param[in] wa is the current dark energy equation of state wa paramter
78 The total dark energy equation of state as a function of z is
79 w = w0 + wa z/(1+z)
81 Currently, this wrapper class expects you to specify either a LambdaCDM (flat or non-flat) cosmology
82 or a w0, wa (flat or non-flat) cosmology.
84 The default cosmology is taken as the cosmology used
85 in the Millennium Simulation (Springel et al 2005, Nature 435, 629 or
86 arXiv:astro-ph/0504097)
88 Om0 = 0.25
89 Ob0 = 0.045 (baryons; not currently used in this code)
90 H0 = 73.0
91 Ok0 = 0.0, (implying Ode0 approx 0.75)
92 w0 = -1.0
93 wa = 0.0
95 where
96 Om0 + Ok0 + Ode0 + Ogamma0 + Onu0 = 1.0
98 sigma_8 = 0.9 (rms mass flucutation in an 8 h^-1 Mpc sphere;
99 not currently used in this code)
101 ns = 1 (index of the initial spectrum of linear mas perturbations;
102 not currently used in this code)
104 """
106 self.activeCosmology = None
108 if w0 is not None and wa is None:
109 wa = 0.0
111 isCosmologicalConstant = False
112 if (w0 is None and wa is None) or (w0==-1.0 and wa==0.0):
113 isCosmologicalConstant = True
115 isFlat = False
116 if Ok0 is None or (numpy.abs(Ok0) < flatnessthresh):
117 isFlat = True
119 if isCosmologicalConstant and isFlat:
120 universe = cosmology.FlatLambdaCDM(H0=H0, Om0=Om0)
121 elif isCosmologicalConstant:
122 tmpmodel = cosmology.FlatLambdaCDM(H0=H0, Om0=Om0)
123 Ode0 = 1.0 - Om0 - tmpmodel.Ogamma0 - tmpmodel.Onu0 - Ok0
124 universe = cosmology.LambdaCDM(H0=H0, Om0=Om0, Ode0=Ode0)
125 elif isFlat:
126 universe = cosmology.Flatw0waCDM(H0=H0, Om0=Om0, w0=w0, wa=wa)
127 else:
128 tmpmodel = cosmology.Flatw0waCDM(H0=H0, Om0=Om0, w0=w0, wa=wa)
129 Ode0 = 1.0 - Om0 - tmpmodel.Ogamma0 - tmpmodel.Onu0 - Ok0
131 universe = cosmology.w0waCDM(H0=H0, Om0=Om0, Ode0=Ode0,
132 w0=w0, wa=wa)
134 self.setCurrent(universe)
136 def setCurrent(self, universe):
137 """
138 Take the cosmology indicated by 'universe' and set it as the current/default
139 cosmology (depending on the API of the version of astropy being run)
141 universe is also assigned to self.activeCosmology, which is the cosmology that
142 this wrapper's methods use for calculations.
143 """
145 if 'default_cosmology' in dir(cosmology):
146 cosmology.default_cosmology.set(universe)
147 elif 'set_current' in dir(cosmology):
148 cosmology.set_current(universe)
149 else:
150 raise RuntimeError("CosmologyObject.setCurrent does not know how to handle this version of astropy")
152 self.activeCosmology = universe
153 self.setUnits()
155 def setUnits(self):
156 """
157 This method specifies the units in which various outputs from the wrapper are expected
158 (this is because the latest version of astropy.cosmology outputs quantities such as
159 the Hubble parameter and luminosity distance with units attached; the version of
160 astropy.cosmology that comes within anaconda does not do this as of 30 October 2014)
161 """
163 H = self.activeCosmology.H(0.0)
164 if 'unit' in dir(H):
165 self.hUnits = units.Unit("km / (Mpc s)")
166 else:
167 self.hUnits = None
169 dd = self.activeCosmology.comoving_distance(0.0)
170 if 'unit' in dir(dd):
171 self.distanceUnits = units.Mpc
172 else:
173 self.distanceUnits = None
175 mm = self.activeCosmology.distmod(1.0)
176 if 'unit' in dir(mm):
177 self.modulusUnits = units.mag
178 else:
179 self.modulusUnits = None
181 def getCurrent(self):
182 """
183 Return the cosmology currently stored as the current cosmology
185 This is for users who want direct access to all of astropy.cosmology's methods,
186 not just those wrapped by this class.
188 documentation for astropy.cosmology can be found at the URL below (be sure to check which version of
189 astropy you are running; as of 30 October 2014, the anaconda distributed with the stack
190 comes with version 0.2.5)
192 https://astropy.readthedocs.org/en/v0.2.5/cosmology/index.html
193 """
195 return self.activeCosmology
197 def H(self, redshift=0.0):
198 """
199 return the Hubble paramter in km/s/Mpc at the specified redshift
201 effectively wrapps astropy.cosmology.FLRW.H()
202 """
204 H = self.activeCosmology.H(redshift)
206 if 'value' in dir(H):
207 if H.unit == self.hUnits:
208 return H.value
209 else:
210 return H.to(self.hUnits).value
211 else:
212 return H
214 def OmegaMatter(self, redshift=0.0):
215 """
216 return the matter density paramter (fraction of critical density) at the specified redshift
218 effectively wraps astropy.cosmology.FLRW.Om()
219 """
221 return self.activeCosmology.Om(redshift)
223 def OmegaDarkEnergy(self, redshift=0.0):
224 """
225 return the dark energy density paramter (fraction of critical density) at the specified redshift
227 effectively wraps astropy.cosmology.FLRW.Ode()
228 """
230 return self.activeCosmology.Ode(redshift)
232 def OmegaPhotons(self, redshift=0.0):
233 """
234 return the photon density paramter (fraction of critical density) at the specified redshift
236 effectively wraps astropy.cosmology.FLRW.Ogamma()
237 """
239 return self.activeCosmology.Ogamma(redshift)
241 def OmegaNeutrinos(self, redshift=0.0):
242 """
243 return the neutrino density paramter (fraction of critical density) at the specified redshift
245 assumes neutrinos are massless
247 effectively wraps astropy.cosmology.FLRW.Onu()
248 """
250 return self.activeCosmology.Onu(redshift)
252 def OmegaCurvature(self, redshift=0.0):
253 """
254 return the effective curvature density paramter (fraction of critical density) at the
255 specified redshift.
257 Positive means the universe is open.
259 Negative means teh universe is closed.
261 Zero means the universe is flat.
263 effectively wraps astropy.cosmology.FLRW.Ok()
264 """
266 return self.activeCosmology.Ok(redshift)
268 def w(self, redshift=0.0):
269 """
270 return the dark energy equation of state at the specified redshift
272 effecitvely wraps astropy.cosmology.FLRW.w()
273 """
275 return self.activeCosmology.w(redshift)
277 def comovingDistance(self, redshift=0.0):
278 """
279 return the comoving distance to the specified redshift in Mpc
281 note, this comoving distance is X in the FRW metric
283 ds^2 = -c^2 dt^2 + a^2 dX^2 + a^2 sin^2(X) dOmega^2
285 i.e. the curvature of the universe is folded into the sin()/sinh() function.
286 This distande just integrates dX = c dt/a
288 effectively wraps astropy.cosmology.FLRW.comoving_distance()
289 """
290 dd = self.activeCosmology.comoving_distance(redshift)
292 if 'value' in dir(dd):
293 if dd.unit == self.distanceUnits:
294 return dd.value
295 else:
296 return dd.to(self.distanceUnits).value
297 else:
298 return dd
300 def luminosityDistance(self, redshift=0.0):
301 """
302 the luminosity distance to the specified redshift in Mpc
304 accounts for spatial curvature
306 effectively wraps astropy.cosmology.FLRW.luminosity_distance()
307 """
309 dd = self.activeCosmology.luminosity_distance(redshift)
311 if 'value' in dir(dd):
312 if dd.unit == self.distanceUnits:
313 return dd.value
314 else:
315 return dd.to(self.distanceUnits).value
316 else:
317 return dd
319 def angularDiameterDistance(self, redshift=0.0):
320 """
321 angular diameter distance to the specified redshift in Mpc
323 effectively wraps astropy.cosmology.FLRW.angular_diameter_distance()
324 """
326 dd = self.activeCosmology.angular_diameter_distance(redshift)
328 if 'value' in dir(dd):
329 if dd.unit == self.distanceUnits:
330 return dd.value
331 else:
332 return dd.to(self.distanceUnits).value
333 else:
334 return dd
336 def distanceModulus(self, redshift=0.0):
337 """
338 distance modulus to the specified redshift
340 effectively wraps astropy.cosmology.FLRW.distmod()
341 """
343 mm = self.activeCosmology.distmod(redshift)
344 if 'unit' in dir(mm):
345 if mm.unit == self.modulusUnits:
346 mod = mm.value
347 else:
348 mod = mm.to(self.modulusUnits).value
349 else:
350 mod = mm
352 #The astropy.cosmology.distmod() method has no problem returning a negative
353 #distance modulus (or -inf if redshift==0.0)
354 #Given that this makes no sense, the code below forces all distance moduli
355 #to be greater than zero.
356 #
357 #a Runtime Warning will be raised (because distmod will try to take the
358 #logarithm of luminosityDistance = 0, but the code will still run
359 if isinstance(mod, float):
360 if mod < 0.0:
361 return 0.0
362 else:
363 return mod
364 else:
365 return numpy.where(mod>0.0, mod, 0.0)