jeans 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
jeans-1.0.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 mgwalkergit
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
jeans-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,45 @@
1
+ Metadata-Version: 2.1
2
+ Name: jeans
3
+ Version: 1.0.0
4
+ Summary: package to compute integrals related to spherical Jeans equation, including various parametric functions to describe halo and tracer components
5
+ Author-email: "Matthew G. Walker" <mgwalker@cmu.edu>
6
+ Project-URL: Homepage, https://github.com/mgwalkergit/jeans
7
+ Project-URL: Issues, https://github.com/mgwalkergit/jeans/issues
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.8
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: numpy
15
+ Requires-Dist: scipy
16
+ Requires-Dist: astropy
17
+ Requires-Dist: matplotlib
18
+
19
+ # jeans
20
+
21
+ A package for ...
22
+
23
+ Author: Matthew G. Walker (2024)
24
+
25
+ # Instructions
26
+
27
+ * Install jeans. You can either pip install the released version or install from github
28
+
29
+ ```
30
+ pip install jeans
31
+ ```
32
+ # Available Models for 2D position
33
+
34
+ xxx
35
+
36
+ In order to ...:
37
+
38
+ ```dmhalo=jeans.dmhalo('nfw',triangle=200,m_triangle=1.e+10,c_triangle=10)```
39
+
40
+ # Examples
41
+
42
+ For examples of ...
43
+
44
+ # Acknowledgement
45
+
jeans-1.0.0/README.md ADDED
@@ -0,0 +1,27 @@
1
+ # jeans
2
+
3
+ A package for ...
4
+
5
+ Author: Matthew G. Walker (2024)
6
+
7
+ # Instructions
8
+
9
+ * Install jeans. You can either pip install the released version or install from github
10
+
11
+ ```
12
+ pip install jeans
13
+ ```
14
+ # Available Models for 2D position
15
+
16
+ xxx
17
+
18
+ In order to ...:
19
+
20
+ ```dmhalo=jeans.dmhalo('nfw',triangle=200,m_triangle=1.e+10,c_triangle=10)```
21
+
22
+ # Examples
23
+
24
+ For examples of ...
25
+
26
+ # Acknowledgement
27
+
@@ -0,0 +1,20 @@
1
+ [project]
2
+ name = "jeans"
3
+ version = "1.0.0"
4
+ authors = [
5
+ { name="Matthew G. Walker", email="mgwalker@cmu.edu" },
6
+ ]
7
+ description = "package to compute integrals related to spherical Jeans equation, including various parametric functions to describe halo and tracer components"
8
+ readme = "README.md"
9
+ requires-python = ">=3.8"
10
+ dependencies = ["numpy","scipy","astropy","matplotlib"
11
+ ]
12
+ classifiers = [
13
+ "Programming Language :: Python :: 3",
14
+ "License :: OSI Approved :: MIT License",
15
+ "Operating System :: OS Independent",
16
+ ]
17
+
18
+ [project.urls]
19
+ Homepage = "https://github.com/mgwalkergit/jeans"
20
+ Issues = "https://github.com/mgwalkergit/jeans/issues"
jeans-1.0.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,2 @@
1
+ from .main import sample_r2d,sample_imf,sample_orbit_2body,add_binaries_physical,add_binaries_func,binary_blend,sample_normal_truncated,sample_inclination
2
+ from .orbit_animation import animation_2body_r,animation_2body_v,animation_2body_spec
@@ -0,0 +1,639 @@
1
+ from xymass import sampler
2
+ import numpy as np
3
+ import scipy
4
+ import scipy.optimize
5
+ import scipy.special
6
+ import warnings
7
+ import matplotlib.pyplot as plt
8
+ import astropy as ap
9
+ import time
10
+
11
+ g=0.004317#newton's G in units of km/s, pc, Msun
12
+
13
+ def get_nfw_gc(c_triangle):
14
+ return 1./(np.log(1.+c_triangle)-c_triangle/(1.+c_triangle))
15
+
16
+ def get_dehnen_core_gc(c_triangle):
17
+ return ((1.+c_triangle)**3)/c_triangle**3
18
+
19
+ def get_dehnen_cusp_gc(c_triangle):
20
+ return ((1.+c_triangle)**2)/c_triangle**2
21
+
22
+ def get_nfw_scale(triangle,h,m_triangle,c_triangle):#r_triangle, scale radius r_s and scale density rho_s, of NFW halo, units of pc and U(m_triangle) / u(r_scale)**3
23
+ gc=get_nfw_gc(c_triangle)
24
+ r_triangle=(2.*g*m_triangle/triangle/((1.e-4*h)**2))**0.3333333333333333#r_triangle in units of pc, where triangle is overdensity factor = [M_triangle / (4*pi*r_triangle**3)] / rho_crit_0, where rho_crit_0 = 3H_0^2/(8*pi*G), H_0 is hubble constant, m_triangle is given in units of Msun
25
+ r_scale=r_triangle/c_triangle#scale radius in same units as r_triangle, where concentration is defined as c_triangle=r_triangle/r_scale
26
+ return r_triangle,r_scale,gc*m_triangle/4./np.pi/r_scale**3
27
+
28
+ def get_dehnen_core_scale(triangle,h,m_triangle,c_triangle):#r_triangle, scale radius r_s and scale density rho_s, of NFW halo, units of pc and U(m_triangle) / u(r_scale)**3
29
+ gc=get_dehnen_core_gc(c_triangle)
30
+ r_triangle=(2.*g*m_triangle/triangle/((1.e-4*h)**2))**0.3333333333333333#r_triangle in units of pc, where triangle is overdensity factor = [M_triangle / (4*pi*r_triangle**3)] / rho_crit_0, where rho_crit_0 = 3H_0^2/(8*pi*G), H_0 is hubble constant, m_triangle is given in units of Msun
31
+ r_scale=r_triangle/c_triangle#scale radius in same units as r_triangle, where concentration is defined as c_triangle=r_triangle/r_scale
32
+ return r_triangle,r_scale,gc*m_triangle/(4./3.)/np.pi/r_scale**3
33
+
34
+ def get_dehnen_cusp_scale(triangle,h,m_triangle,c_triangle):#r_triangle, scale radius r_s and scale density rho_s, of NFW halo, units of pc and U(m_triangle) / u(r_scale)**3
35
+ gc=get_dehnen_cusp_gc(c_triangle)
36
+ r_triangle=(2.*g*m_triangle/triangle/((1.e-4*h)**2))**0.3333333333333333#r_triangle in units of pc, where triangle is overdensity factor = [M_triangle / (4*pi*r_triangle**3)] / rho_crit_0, where rho_crit_0 = 3H_0^2/(8*pi*G), H_0 is hubble constant, m_triangle is given in units of Msun
37
+ r_scale=r_triangle/c_triangle#scale radius in same units as r_triangle, where concentration is defined as c_triangle=r_triangle/r_scale
38
+ return r_triangle,r_scale,gc*m_triangle/(4./2.)/np.pi/r_scale**3
39
+
40
+ def get_abg_triangle_scale(triangle,h,m_triangle,c_triangle,alpha,beta,gamma):#r_triangle, scale radius r_s and scale density, rho_s, of abg halo, given triangle parameters, units of U(m_triangle)/U(r_triangle)**3
41
+ r_triangle=(2.*g*m_triangle/triangle/((1.e-4*h)**2))**0.3333333333333333#r_triangle in units of pc, where triangle is overdensity factor = [M_triangle / (4*pi*r_triangle**3)] / rho_crit_0, where rho_crit_0 = 3H_0^2/(8*pi*G), H_0 is hubble constant, m_triangle is given in units of Msun
42
+ r_scale=r_triangle/c_triangle#scale radius in same units as r_triangle, where concentration is defined as c_triangle=r_triangle/r_scale
43
+
44
+ a=(3.-gamma)/alpha
45
+ b=(beta-gamma)/alpha
46
+ c=(3.-gamma+alpha)/alpha
47
+ z1=-c_triangle**alpha
48
+ hf1=scipy.special.hyp2f1(a,b,c,z1)
49
+ return r_triangle,r_scale,m_triangle*(3.-gamma)/4./np.pi/(r_scale**3)/c_triangle**(3.-gamma)/hf1
50
+
51
+ def nfw_density(x,c_triangle):# returns rho_NFW(x) / rho_scale, where x = r / r_triangle
52
+ cx=c_triangle*x #r / r_scale
53
+ return 1./cx/(1.+cx)**2
54
+
55
+ def dehnen_core_density(x,c_triangle):# returns rho_NFW(x) / rho_scale, where x = r / r_triangle
56
+ cx=c_triangle*x #r / r_scale
57
+ return 1./(1.+cx)**4
58
+
59
+ def dehnen_cusp_density(x,c_triangle):# returns rho_NFW(x) / rho_scale, where x = r / r_triangle
60
+ cx=c_triangle*x #r / r_scale
61
+ return 1./cx/(1.+cx)**3
62
+
63
+ def nfw_mass(x,c_triangle):# returns enclosed mass M(x) / m_triangle, where x = r/r_triangle
64
+ gc=get_nfw_gc(c_triangle)
65
+ cx=c_triangle*x #r / r_scale
66
+ return gc*(np.log(1.+cx)-cx/(1.+cx))
67
+
68
+ def dehnen_core_mass(x,c_triangle):# returns enclosed mass M(x) / m_triangle, where x = r/r_triangle
69
+ gc=get_dehnen_core_gc(c_triangle)
70
+ cx=c_triangle*x #r / r_scale
71
+ return gc*(cx**3)/(1.+cx)**3
72
+
73
+ def dehnen_cusp_mass(x,c_triangle):# returns enclosed mass M(x) / m_triangle, where x = r/r_triangle
74
+ gc=get_dehnen_cusp_gc(c_triangle)
75
+ cx=c_triangle*x #r / r_scale
76
+ return gc*(cx**2)/(1.+cx)**2
77
+
78
+ def fncore(x,r_core,n_core):#returns f^n(x) for coreNFW model (Read, Walker, Pascal 2018), where x=r/r_triangle, r_core=r_core/r_triangle
79
+ return (np.tanh(np.float64(x)/r_core))**n_core
80
+
81
+ def cnfw_density(x,c_triangle,r_core,n_core):#returns rho_coreNFW(x) / rho_s, where x = r/r_triangle and rho_s is scale radius of NFW profile
82
+ ncorem1=n_core-1.
83
+ two=2.
84
+ return fncore(x,r_core,n_core)*nfw_density(x,c_triangle)+n_core*fncore(x,r_core,ncorem1)*(1.-fncore(x,r_core,two))/(x**2)/get_nfw_gc(c_triangle)*nfw_mass(x,c_triangle)/r_core/(c_triangle**3)
85
+
86
+ def cnfw_mass(x,c_triangle,r_core,n_core):# returns M_cNFW(x) / m_triangle, where x=r/r_triangle, x=r/r_triangle, r_core=(core radius)/ r_triangle
87
+ return fncore(x,r_core,n_core)*nfw_mass(x,c_triangle)
88
+
89
+ def cnfwt_density(x,c_triangle,r_core,n_core,r_tide,delta):#returns rho_coreNFWtides(x) / rho_0, where x = r/r_triangle
90
+ if ((type(x) is float)|(type(x) is np.float64)):
91
+ if x<r_tide:
92
+ return cnfw_density(x,c_triangle,r_core,n_core)
93
+ else:
94
+ return cnfw_density(r_tide,c_triangle,r_core,n_core)*((x/r_tide)**(-delta_halo))
95
+ elif ((type(x) is list)|(type(x) is np.ndarray)):
96
+ val=np.zeros(len(x))
97
+ val[x<r_tide]=cnfw_density(x[x<r_tide],c_triangle,r_core,n_core)
98
+ val[x>=r_tide]=cnfw_density(r_tide,c_triangle,r_core,n_core)*((x[x>=r_tide]/r_tide)**(-delta_halo))
99
+ return val
100
+
101
+ def cnfwt_mass(x,c_triangle,r_core,n_core,r_tide,delta):#returns M_cNFWt(x) / m_triangle, where x=r/r_triangle, r_core=(core radius)/r_triangle, r_tide=(tidal radius)/r_triangle
102
+ if ((type(x) is float)|(type(x) is np.float64)):
103
+ if x<r_tide:
104
+ return cnfw_mass(x,c_triangle,r_core,n_core)
105
+ else:
106
+ return cnfw_mass(r_tide,c_triangle,r_core,n_core,r_tide)+cnfw_density(r_tide,c_triangle,r_core,n_core)*get_nfw_gc(c_triangle)/(3.-delta)*((c_triangle*r_tide)**3)*(((x/r_tide)**(3.-delta))-1.)
107
+ elif ((type(x) is list)|(type(x) is np.ndarray)):
108
+ val=np.zeros(len(x))
109
+ val[x<r_tide]=cnfw_mass(x[x<r_tide],c_triangle,r_core,n_core)
110
+ val[x>=r_tide]=cnfw_mass(r_tide,c_triangle,r_core,n_core)+cnfw_density(r_tide,c_triangle,r_core,n_core)*get_nfw_gc(c_triangle)/(3.-delta)*((c_triangle*r_tide)**3)*(((x[x>=r_tide]/r_tide)**(3.-delta))-1.)
111
+ return val
112
+
113
+ def abg_triangle_density(x,c_triangle,alpha,beta,gamma):# returns rho_abg(x) / rho_scale, where x = r / r_triangle
114
+ cx=params['c_triangle']*x #r / r_scale
115
+ return 1./(cx**gamma)/(1.+cx**alpha)**((beta-gamma)/alpha)
116
+
117
+ def abg_triangle_mass(x,c_triangle,alpha,beta,gamma):# returns enclosed mass M_abg(x) / m_triangle, where x = r/r_triangle
118
+ cx=c_triangle*x #r / r_scale
119
+ a=(3.-gamma)/alpha
120
+ b=(beta-gamma)/alpha
121
+ c=(3.-gamma+alpha)/alpha
122
+ z1=-cx**alpha
123
+ z2=-c_triangle**alpha
124
+ hf1=scipy.special.hyp2f1(a,b,c,z1)
125
+ hf2=scipy.special.hyp2f1(a,b,c,z2)
126
+ return ((cx/c_triangle)**(3.-gamma))*hf1/hf2
127
+
128
+ def get_plum_scale(luminosity_tot,r_scale):#nu0, normalization factor for luminosity density profile
129
+ nu0=3.*luminosity_tot/4./np.pi/r_scale**3
130
+ sigma0=luminosity_tot/np.pi/r_scale**2
131
+ return nu0,sigma0
132
+
133
+ def get_exp_scale(luminosity_tot,r_scale):#nu0, normalization factor for luminosity density profile
134
+ nu0=luminosity_tot/2./np.pi**2/r_scale**3
135
+ sigma0=luminosity_tot/2./np.pi/r_scale**2
136
+ return nu0,sigma0
137
+
138
+ def get_a2bg_scale(luminosity_tot,r_scale,beta,gamma):#nu0, normalization factor for luminosity density profile
139
+ alpha=2.
140
+ a=(3.-gamma)/alpha
141
+ b=(beta-gamma)/alpha
142
+ c=beta/2.
143
+ d=(beta-3.)/alpha
144
+ nu0=luminosity_tot/2./np.pi/r_scale**3/scipy.special.gamma(d)/scipy.special.gamma(a)*scipy.special.gamma(b)
145
+ sigma0=luminosity_tot/4./np.sqrt(np.pi)/(r_scale**2)*(beta-3.)*scipy.special.gamma(b)/scipy.special.gamma(a)/scipy.special.gamma(c)
146
+ return nu0,sigma0
147
+
148
+ def get_abg_nu0(luminosity_tot,r_scale,alpha,beta,gamma):#nu0, normalization factor for luminosity density profile
149
+ a=(3.-gamma)/alpha
150
+ b=(beta-gamma)/alpha
151
+ c=beta/2.
152
+ d=(beta-3.)/alpha
153
+ nu0=luminosity_tot/4./np.pi/r_scale**3*alpha*scipy.special.gamma(b)/scipy.special.gamma(d)/scipy.special.gamma(a)
154
+ sigma0=np.nan#haven't yet implemented, probably a numerical integration
155
+ return nu0,sigma0
156
+
157
+ def plum_density(x):#nu(x) / nu0, x=r/r_scale
158
+ return 1./(1.+x**2)**(2.5)
159
+
160
+ def plum_density_2d(x):#Sigma(X) / Sigma0, X=R/r_scale
161
+ return 1./(1.+x**2)**2
162
+
163
+ def exp_density(x):#nu(x) / nu0, x=r/r_scale
164
+ return scipy.special.kn(0,x)
165
+
166
+ def exp_density_2d(x):#Sigma(X) / Sigma0, X=R/r_scale
167
+ return np.exp(-x)
168
+
169
+ def a2bg_density(x,beta,gamma):#nu(x) / nu0, x=r/r_scale
170
+ return 1./(x**gamma)/(1.+x**2)**((beta-gamma)/2.)
171
+
172
+ def a2bg_density_2d(x,beta,gamma):#Sigma(X)/Sigma0, X=R/r_scale
173
+ if x<1.e-50:
174
+ x=1.e-50
175
+ a=(beta-1.)/2.
176
+ b=(beta-gamma)/2.
177
+ c=beta/2.
178
+ z1=-1./x**2
179
+ hf1=scipy.special.hyp2f1(a,b,c,z1)
180
+ return x**(1.-beta)*hf1
181
+
182
+ def abg_density(x,alpha,beta,gamma):#nu(x) / nu0, x=r/r_scale
183
+ return 1./(x**gamma)/(1.+x**alpha)**((beta-gamma)/alpha)
184
+
185
+ def abg_density_2d(x,alpha,beta,gamma):#Sigma(X)/Sigma0, X=R/r_scale
186
+ return np.nan #requires numerical integration, haven't implemented this yet
187
+
188
+ def plum_number(x):#N(x) / N_tot, x=r/r_scale
189
+ return (x**3)/(1.+x**2)**(1.5)
190
+
191
+ def exp_number(x):#N(x) / N_tot, x=r/r_scale
192
+ if x>100:#fudge to overcome numerical error (function below returns nan)
193
+ return 1.
194
+ return 1./(3.*np.pi)*x*(3.*np.pi*scipy.special.kn(2,x)*scipy.special.modstruve(1,x)+scipy.special.kn(1,x)*(3.*np.pi*scipy.special.modstruve(2,x)-4.*x))
195
+
196
+ def a2bg_number(x,beta,gamma):#N(x)/N_tot, x=r/r_scale
197
+ alpha=2.
198
+ a=(3.-gamma)/alpha
199
+ b=(beta-gamma)/alpha
200
+ c=(3.-gamma+alpha)/alpha
201
+ d=(beta-3.)/alpha
202
+ z1=-x**alpha
203
+ z2=-np.inf**alpha
204
+ hf1=scipy.special.hyp2f1(a,b,c,z1)
205
+ hf2=scipy.special.hyp2f1(a,b,c,z2)
206
+ #return abg_number(x,2.,beta,gamma)
207
+ return alpha/(3.-gamma)*(x**(3.-gamma))*hf1*scipy.special.gamma(b)/scipy.special.gamma(d)/scipy.special.gamma(a)
208
+
209
+ def abg_number(x,alpha,beta,gamma):#N(x)/N_tot, x=r/r_scale
210
+ a=(3.-gamma)/alpha
211
+ b=(beta-gamma)/alpha
212
+ c=(3.-gamma+alpha)/alpha
213
+ d=(beta-3.)/alpha
214
+ z1=-x**alpha
215
+ z2=-np.inf**alpha
216
+ hf1=scipy.special.hyp2f1(a,b,c,z1)
217
+ hf2=scipy.special.hyp2f1(a,b,c,z2)
218
+ #return (x**(3.-gamma))*hf1/hf2 #should be equivalent to below
219
+ return alpha/(3.-gamma)*(x**(3.-gamma))*hf1*scipy.special.gamma(b)/scipy.special.gamma(d)/scipy.special.gamma(a)
220
+
221
+ def plum_nscalenorm():#N(r_scale)/(nu0 *r_scale**3)
222
+ return 4.*np.pi/3./(2.**1.5)
223
+
224
+ def exp_nscalenorm():#N(r_scale)/(nu0 *r_scale**3)
225
+ return 2.*np.pi/3.*(3.*np.pi*scipy.special.kn(2,1.)*scipy.special.modstruve(1,1.)+scipy.special.kn(1,1.)*(3.*np.pi*scipy.special.modstruve(2,1.)-4.))
226
+
227
+ def a2bg_nscalenorm(beta,gamma):#N(r_scale)/(nu0 * r_scale**3)
228
+ alpha=2.
229
+ a=(3.-gamma)/alpha
230
+ b=(beta-gamma)/alpha
231
+ c=(3.-gamma+alpha)/alpha
232
+ z2=-1.
233
+ hf2=scipy.special.hyp2f1(a,b,c,z2)
234
+ return 4.*np.pi/(3.-gamma)*hf2
235
+
236
+ def abg_nscalenorm(alpha,beta,gamma):#N(r_scale)/(nu0 * r_scale**3)
237
+ a=(3.-gamma)/alpha
238
+ b=(beta-gamma)/alpha
239
+ c=(3.-gamma+alpha)/alpha
240
+ z2=-1.
241
+ hf2=scipy.special.hyp2f1(a,b,c,z2)
242
+ return 4.*np.pi/(3.-gamma)*hf2
243
+
244
+ def plum_ntotnorm():#N(r=infinity)/(nu0 * r_scale**3)
245
+ return 4.*np.pi/3.
246
+
247
+ def exp_ntotnorm():#N(r=infinity)/(nu0 * r_scale**3)
248
+ return 2.*(np.pi**2)
249
+
250
+ def a2bg_ntotnorm(beta,gamma):#N(r=infinity)/(nu0 * r_scale**3)
251
+ alpha=2.
252
+ a=(3.-gamma)/alpha
253
+ b=(beta-gamma)/alpha
254
+ #c=(3.-gamma+alpha)/alpha
255
+ d=(beta-3.)/alpha
256
+ return 2.*np.pi*scipy.special.gamma(d)*scipy.special.gamma(a)/scipy.special.gamma(b)
257
+
258
+ def abg_ntotnorm(alpha,beta,gamma):#N(r=infinity)/(nu0 * r_scale**3)
259
+ a=(3.-gamma)/alpha
260
+ b=(beta-gamma)/alpha
261
+ #c=(3.-gamma+alpha)/alpha
262
+ d=(beta-3.)/alpha
263
+ return 4.*np.pi/alpha*scipy.special.gamma(d)*scipy.special.gamma(a)/scipy.special.gamma(b)
264
+
265
+
266
+
267
+ def get_dmhalo(model,**params):
268
+
269
+ class dmhalo:
270
+
271
+ def __init__(self,model=None,triangle=None,h=None,m_triangle=None,c_triangle=None,r_triangle=None,r_core=None,n_core=None,r_tide=None,delta=None,alpha=None,beta=None,gamma=None,rho_scale=None,r_scale=None,v_max=None,r_max=None,func_density=None,func_mass=None,func_vcirc=None):
272
+
273
+ self.model=model
274
+ self.triangle=triangle
275
+ self.h=h
276
+ self.m_triangle=m_triangle
277
+ self.c_triangle=c_triangle
278
+ self.r_triangle=r_triangle
279
+ self.r_core=r_core
280
+ self.n_core=n_core
281
+ self.r_tide=r_tide
282
+ self.delta=delta
283
+ self.alpha=alpha
284
+ self.beta=beta
285
+ self.gamma=gamma
286
+ self.rho_scale=rho_scale
287
+ self.r_scale=r_scale
288
+ self.v_max=v_max
289
+ self.r_max=r_max
290
+ self.func_density=func_density
291
+ self.func_mass=func_mass
292
+ self.func_vcirc=func_vcirc
293
+
294
+ if model=='nfw':
295
+
296
+ r_triangle,r_scale,rho_scale=get_nfw_scale(params['triangle'],params['h'],params['m_triangle'],params['c_triangle'])
297
+
298
+ def func_density(x):
299
+ return nfw_density(x,params['c_triangle'])
300
+ def func_mass(x):# returns enclosed mass M(x) / m_triangle, where x = r/r_triangle
301
+ return nfw_mass(x,params['c_triangle'])
302
+
303
+ if model=='dehnen_core':
304
+
305
+ r_triangle,r_scale,rho_scale=get_dehnen_core_scale(params['triangle'],params['h'],params['m_triangle'],params['c_triangle'])
306
+
307
+ def func_density(x):
308
+ return dehnen_core_density(x,params['c_triangle'])
309
+ def func_mass(x):# returns enclosed mass M(x) / m_triangle, where x = r/r_triangle
310
+ return dehnen_core_mass(x,params['c_triangle'])
311
+
312
+ if model=='dehnen_cusp':
313
+
314
+ r_triangle,r_scale,rho_scale=get_dehnen_cusp_scale(params['triangle'],params['h'],params['m_triangle'],params['c_triangle'])
315
+
316
+ def func_density(x):
317
+ return dehnen_cusp_density(x,params['c_triangle'])
318
+ def func_mass(x):# returns enclosed mass M(x) / m_triangle, where x = r/r_triangle
319
+ return dehnen_cusp_mass(x,params['c_triangle'])
320
+
321
+ elif model=='abg_triangle':
322
+
323
+ r_triangle,r_scale,rho_scale=get_abg_triangle_scale(params['triangle'],params['h'],params['m_triangle'],params['c_triangle'],params['alpha'],params['beta'],params['gamma'])
324
+
325
+ def func_density(x):
326
+ return abg_triangle_density(x,params['c_triangle'],params['alpha'],params['beta'],params['gamma'])
327
+ def func_mass(x):
328
+ return abg_triangle_mass(x,params['c_triangle'],params['alpha'],params['beta'],params['gamma'])
329
+
330
+ elif model=='cnfw':
331
+
332
+ r_triangle,r_scale,rho_scale=get_nfw_scale(params['triangle'],params['h'],params['m_triangle'],params['c_triangle'])
333
+
334
+ def func_density(x):
335
+ return cnfw_density(x,params['c_triangle'],params['r_core'],params['n_core'])
336
+ def func_mass(x):# returns enclosed mass M(x) / m_triangle, where x = r/r_triangle
337
+ return cnfw_mass(x,params['c_triangle'],params['r_core'],params['n_core'])
338
+
339
+ elif model=='cnfwt':
340
+
341
+ r_triangle,r_scale,rho_scale=get_nfw_scale(params['triangle'],params['h'],params['m_triangle'],params['c_triangle'])
342
+
343
+ def func_density(x):
344
+ return cnfwt_density(x,params['c_triangle'],params['r_core'],params['n_core'],params['r_tide'],params['delta'])
345
+ def func_mass(x):# returns enclosed mass M(x) / m_triangle, where x = r/r_triangle
346
+ return cnfwt_mass(x,params['c_triangle'],params['r_core'],params['n_core'],params['r_tide'],params['delta'])
347
+
348
+ def func_vcirc(x):# returns circular velocity, km/s
349
+ return np.sqrt(g*func_mass(x)*params['m_triangle']/(x*r_triangle))
350
+
351
+ def neg_vcirc2(x):
352
+ if x<0.:
353
+ return 1.e+30
354
+ return -func_mass(x)/x
355
+
356
+ res=scipy.optimize.minimize(neg_vcirc2,[1.],method='nelder-mead',options={'xatol': 1e-8, 'disp': True})
357
+ r_max=res.x[0]*r_triangle
358
+ v_max=func_vcirc(res.x[0])
359
+
360
+ if model=='nfw':
361
+ return dmhalo(model=model,triangle=params['triangle'],h=params['h'],m_triangle=params['m_triangle'],c_triangle=params['c_triangle'],r_triangle=r_triangle,rho_scale=rho_scale,r_scale=r_scale,v_max=v_max,r_max=r_max,func_density=func_density,func_mass=func_mass,func_vcirc=func_vcirc)
362
+ if model=='dehnen_core':
363
+ return dmhalo(model=model,triangle=params['triangle'],h=params['h'],m_triangle=params['m_triangle'],c_triangle=params['c_triangle'],r_triangle=r_triangle,rho_scale=rho_scale,r_scale=r_scale,v_max=v_max,r_max=r_max,func_density=func_density,func_mass=func_mass,func_vcirc=func_vcirc)
364
+ if model=='dehnen_cusp':
365
+ return dmhalo(model=model,triangle=params['triangle'],h=params['h'],m_triangle=params['m_triangle'],c_triangle=params['c_triangle'],r_triangle=r_triangle,rho_scale=rho_scale,r_scale=r_scale,v_max=v_max,r_max=r_max,func_density=func_density,func_mass=func_mass,func_vcirc=func_vcirc)
366
+ elif model=='abg_triangle':
367
+ return dmhalo(model=model,triangle=params['triangle'],h=params['h'],m_triangle=params['m_triangle'],c_triangle=params['c_triangle'],r_triangle=r_triangle,alpha=params['alpha'],beta=params['beta'],gamma=params['gamma'],rho_scale=rho_scale,r_scale=r_scale,v_max=v_max,r_max=r_max,func_density=func_density,func_mass=func_mass,func_vcirc=func_vcirc)
368
+ elif model=='cnfw':
369
+ return dmhalo(model=model,triangle=params['triangle'],h=params['h'],m_triangle=params['m_triangle'],c_triangle=params['c_triangle'],r_triangle=r_triangle,r_core=params['r_core'],n_core=params['n_core'],rho_scale=rho_scale,r_scale=r_scale,v_max=v_max,r_max=r_max,func_density=func_density,func_mass=func_mass,func_vcirc=func_vcirc)
370
+ elif model=='cnfwt':
371
+ return dmhalo(model=model,triangle=params['triangle'],h=params['h'],m_triangle=params['m_triangle'],c_triangle=params['c_triangle'],r_triangle=r_triangle,r_core=params['r_core'],n_core=params['n_core'],r_tide=params['r_tide'],delta=params['delta'],rho_scale=rho_scale,r_scale=r_scale,v_max=v_max,r_max=r_max,func_density=func_density,func_mass=func_mass,func_vcirc=func_vcirc)
372
+ else:
373
+ raise TypeError('DM halo not properly specified!')
374
+
375
+ def get_tracer(model,**params):
376
+
377
+ class tracer:
378
+
379
+ def __init__(self,model=None,luminosity_tot=None,upsilon=None,r_scale=None,nu0=None,sigma0=None,nscalenorm=None,ntotnorm=None,alpha=None,beta=None,gamma=None,rhalf_2d=None,rhalf_3d=None,func_density=None,func_density_2d=None,func_number=None):
380
+
381
+ self.model=model
382
+ self.luminosity_tot=luminosity_tot
383
+ self.upsilon=upsilon
384
+ self.r_scale=r_scale
385
+ self.nu0=nu0
386
+ self.sigma0=sigma0
387
+ self.nscalenorm=nscalenorm
388
+ self.ntotnorm=ntotnorm
389
+ self.alpha=alpha
390
+ self.beta=beta
391
+ self.gamma=gamma
392
+ self.rhalf_2d=rhalf_2d
393
+ self.rhalf_3d=rhalf_3d
394
+ self.func_density=func_density
395
+ self.func_density_2d=func_density_2d
396
+ self.func_number=func_number
397
+
398
+ if model=='plum':
399
+
400
+ rhalf_2d,rhalf_3d,xxx,yyy=get_rhalf(model,params['r_scale'],bigsigma0=1.,ellipticity=0.)
401
+ nu0,sigma0=get_plum_scale(params['luminosity_tot'],params['r_scale'])
402
+ def func_density(x):
403
+ return plum_density(x)
404
+ def func_density_2d(x):
405
+ return plum_density_2d(x)
406
+ def func_number(x):
407
+ return plum_number(x)
408
+
409
+ return tracer(model=model,luminosity_tot=params['luminosity_tot'],r_scale=params['r_scale'],upsilon=params['upsilon'],nu0=nu0,sigma0=sigma0,nscalenorm=plum_nscalenorm(),ntotnorm=plum_ntotnorm(),rhalf_2d=rhalf_2d,rhalf_3d=rhalf_3d,func_density=func_density,func_density_2d=func_density_2d,func_number=func_number)
410
+
411
+ if model=='exp':
412
+
413
+ rhalf_2d,rhalf_3d,xxx,yyy=get_rhalf(model,params['r_scale'],bigsigma0=1.,ellipticity=0.)
414
+ nu0,sigma0=get_exp_scale(params['luminosity_tot'],params['r_scale'])
415
+ def func_density(x):
416
+ return exp_density(x)
417
+ def func_density_2d(x):
418
+ return exp_density_2d(x)
419
+ def func_number(x):
420
+ return exp_number(x)
421
+
422
+ return tracer(model=model,luminosity_tot=params['luminosity_tot'],r_scale=params['r_scale'],upsilon=params['upsilon'],nu0=nu0,sigma0=sigma0,nscalenorm=exp_nscalenorm(),ntotnorm=exp_ntotnorm(),rhalf_2d=rhalf_2d,rhalf_3d=rhalf_3d,func_density=func_density,func_density_2d=func_density_2d,func_number=func_number)
423
+
424
+ if model=='a2bg':
425
+
426
+ rhalf_2d,rhalf_3d,xxx,yyy=get_rhalf(model,params['r_scale'],bigsigma0=1.,ellipticity=0.,beta=params['beta'],gamma=params['gamma'])
427
+ nu0,sigma0=get_a2bg_scale(params['luminosity_tot'],params['r_scale'],params['beta'],params['gamma'])
428
+ def func_density(x):
429
+ return a2bg_density(x,params['beta'],params['gamma'])
430
+ def func_density_2d(x):
431
+ return a2bg_density_2d(x,params['beta'],params['gamma'])
432
+ def func_number(x):
433
+ return a2bg_number(x,params['beta'],params['gamma'])
434
+
435
+ return tracer(model=model,luminosity_tot=params['luminosity_tot'],r_scale=params['r_scale'],upsilon=params['upsilon'],nu0=nu0,sigma0=sigma0,nscalenorm=a2bg_nscalenorm(params['beta'],params['gamma']),ntotnorm=a2bg_ntotnorm(params['beta'],params['gamma']),beta=params['beta'],gamma=params['gamma'],rhalf_2d=rhalf_2d,rhalf_3d=rhalf_3d,func_density=func_density,func_density_2d=func_density_2d,func_number=func_number)
436
+
437
+ if model=='abg':
438
+
439
+ rhalf_2d,rhalf_3d,xxx,yyy=get_rhalf(model,params['r_scale'],bigsigma0=1.,ellipticity=0.,alpha=params['alpha'],beta=params['beta'],gamma=params['gamma'])
440
+ nu0,sigma0=get_abg_scale(params['luminosity_tot'],params['r_scale'],params['alpha'],params['beta'],params['gamma'])
441
+ def func_density(x):
442
+ return abg_density(x,params['alpha'],params['beta'],params['gamma'])
443
+ def func_density_2d(x):
444
+ return abg_density_2d(x,params['alpha'],params['beta'],params['gamma'])
445
+ def func_number(x):
446
+ return abg_number(x,params['alpha'],params['beta'],params['gamma'])
447
+
448
+ return tracer(model=model,luminosity_tot=params['luminosity_tot'],r_scale=params['r_scale'],upsilon=params['upsilon'],nu0=nu0,sigma0=sigma0,nscalenorm=abg_nscalenorm(params['alpha'],params['beta'],params['gamma']),ntotnorm=abg_ntotnorm(params['alpha'],params['beta'],params['gamma']),alpha=params['alpha'],beta=params['beta'],gamma=params['gamma'],rhalf_2d=rhalf_2d,rhalf_3d=rhalf_3d,func_density=func_density,func_density_2d=func_density_2d,func_number=func_number)
449
+
450
+
451
+ def get_anisotropy(model,**params):
452
+
453
+ class anisotropy:
454
+
455
+ def __init__(self,model=None,beta_0=None,beta_inf=None,r_beta=None,n_beta=None,f_beta=None,beta=None):
456
+
457
+ self.model=model
458
+ self.beta_0=beta_0
459
+ self.beta_inf=beta_inf
460
+ self.r_beta=r_beta
461
+ self.n_beta=n_beta
462
+ self.f_beta=f_beta
463
+ self.beta=beta
464
+
465
+ if model=='read':
466
+
467
+ def beta(x):#x = r / r_beta
468
+ return params['beta_0']+(params['beta_inf']-params['beta_0'])/(1.+x**(-params['n_beta']))
469
+ def f_beta(x):# x = r / r_beta
470
+ return x**(2.*params['beta_inf'])*(1.+x**(-params['n_beta']))**(2.*(params['beta_inf']-params['beta_0'])/params['n_beta'])
471
+
472
+ return anisotropy(model=model,beta_0=params['beta_0'],beta_inf=params['beta_inf'],r_beta=params['r_beta'],n_beta=params['n_beta'],f_beta=f_beta,beta=beta)
473
+
474
+ else:
475
+ raise TypeError('anisotropy model not properly specified!')
476
+
477
+
478
+ def get_rhalf(model,r_scale,**params):
479
+
480
+ if model=='plum':
481
+ rhalf_2d=r_scale
482
+ rhalf_3d=1.30476909*r_scale
483
+ nu0=3*params['bigsigma0']/4/r_scale
484
+ ntot=(1.-params['ellipticity'])*np.pi*r_scale**2*params['bigsigma0']
485
+ elif model=='exp':
486
+ rhalf_2d=1.67835*r_scale
487
+ rhalf_3d=2.22352*r_scale
488
+ nu0=params['bigsigma0']/np.pi/r_scale
489
+ ntot=(1.-params['ellipticity'])*2.*np.pi*r_scale**2*params['bigsigma0']
490
+ elif model=='a2bg':
491
+ def rootfind_2bg_2d(x,beta,gamma):
492
+ return 0.5-np.sqrt(np.pi)*scipy.special.gamma((beta-gamma)/2)/2/scipy.special.gamma(beta/2)/scipy.special.gamma((3-gamma)/2)*x**(3-beta)*scipy.special.hyp2f1((beta-3)/2,(beta-gamma)/2,beta/2,-1/x**2)
493
+ def rootfind_2bg_3d(x,beta,gamma):
494
+ return -0.5+2*scipy.special.gamma((beta-gamma)/2)/scipy.special.gamma((beta-3)/2)/scipy.special.gamma((3-gamma)/2)/(3-gamma)*x**(3-gamma)*scipy.special.hyp2f1((3-gamma)/2,(beta-gamma)/2,(5-gamma)/2,-x**2)
495
+ low0=1.e-20
496
+ high0=1.e+20
497
+ if ((type(r_scale) is float)|(type(r_scale) is np.float64)):
498
+ rhalf_2d=r_scale*scipy.optimize.brentq(rootfind_2bg_2d,low0,high0,args=(params['beta'],params['gamma']),xtol=1.e-12,rtol=1.e-6,maxiter=1000,full_output=False,disp=True)
499
+ rhalf_3d=r_scale*scipy.optimize.brentq(rootfind_2bg_3d,low0,high0,args=(params['beta'],params['gamma']),xtol=1.e-12,rtol=1.e-6,maxiter=100,full_output=False,disp=True)
500
+ else:
501
+ rhalf_2d=[]
502
+ rhalf_3d=[]
503
+ for i in range(0,len(r_scale)):
504
+ rhalf_2d.append(r_scale[i]*scipy.optimize.brentq(rootfind_2bg_2d,low0,high0,args=(params['beta'][i],params['gamma'][i]),xtol=1.e-12,rtol=1.e-6,maxiter=1000,full_output=False,disp=True))
505
+ rhalf_3d.append(r_scale[i]*scipy.optimize.brentq(rootfind_2bg_3d,low0,high0,args=(params['beta'][i],params['gamma'][i]),xtol=1.e-12,rtol=1.e-6,maxiter=100,full_output=False,disp=True))
506
+ rhalf_2d=np.array(rhalf_2d)
507
+ rhalf_3d=np.array(rhalf_3d)
508
+ nu0=params['bigsigma0']*scipy.special.gamma(params['beta']/2)/np.sqrt(np.pi)/r_scale/scipy.special.gamma((params['beta']-1)/2)
509
+ ntot=(1.-params['ellipticity'])*4.*np.sqrt(np.pi)*r_scale**2*params['bigsigma0']/(params['beta']-3)*scipy.special.gamma((3-params['gamma'])/2)*scipy.special.gamma(params['beta']/2)/scipy.special.gamma((params['beta']-params['gamma'])/2)
510
+
511
+ elif model=='abg':
512
+ def rootfind_abg_2d(x,alpha,beta,gamma):
513
+ return np.nan#not computed yet, projection of abg model requires numerical integration
514
+ def rootfind_abg_3d(x,alpha,beta,gamma):
515
+ a=(3.-gamma)/alpha
516
+ b=(beta-gamma)/alpha
517
+ c=(3.-gamma+alpha)/alpha
518
+ d=(beta-3.)/alpha
519
+ z1=-x**alpha
520
+ return -0.5+(x**(3.-gamma))*scipy.special.hyp2f1(a,b,c,z1)*scipy.special.gamma(b)/scipy.special.gamma(d)/scipy.special.gamma(c)
521
+ low0=1.e-20
522
+ high0=1.e+20
523
+ if ((type(r_scale) is float)|(type(r_scale) is np.float64)):
524
+ rhalf_2d=np.nan#not computed yet, projection of abg model requires numerical integration
525
+ rhalf_3d=r_scale*scipy.optimize.brentq(rootfind_abg_3d,low0,high0,args=(params['alpha'],params['beta'],params['gamma']),xtol=1.e-12,rtol=1.e-6,maxiter=100,full_output=False,disp=True)
526
+ else:
527
+ rhalf_2d=[]
528
+ rhalf_3d=[]
529
+ for i in range(0,len(r_scale)):
530
+ rhalf_2d.append(np.nan)#not computed yet, projection of abg model requires numerical integration
531
+ rhalf_3d.append(r_scale[i]*scipy.optimize.brentq(rootfind_abg_3d,low0,high0,args=(params['alpha'],params['beta'][i],params['gamma'][i]),xtol=1.e-12,rtol=1.e-6,maxiter=100,full_output=False,disp=True))
532
+ rhalf_2d=np.array(rhalf_2d)
533
+ rhalf_3d=np.array(rhalf_3d)
534
+ nu0=np.nan#not yet computed
535
+ ntot=np.nan#not yet computed
536
+
537
+ elif model=='captured_truncated':
538
+ return
539
+ else:
540
+ raise ValueError('error in model specification')
541
+ return rhalf_2d,rhalf_3d,nu0,ntot
542
+
543
+ def integrate(bigx,dmhalo,tracer,anisotropy,**params):
544
+ if 'component' not in params:
545
+ params['component']=['los','rad','tan']#default is to calculate all three components
546
+ if not 'upper_limit' in params:#default upper limit is infinity, common alternative is dmhalo.r_triangle
547
+ params['upper_limit']=np.inf
548
+ if not 'epsrel' in params:
549
+ params['epsrel']=1.49e-8
550
+ if not 'epsabs' in params:
551
+ params['epsabs']=1.49e-8
552
+ if not 'limit' in params:
553
+ params['limit']=50
554
+
555
+ def integrand1(x_halo,dmhalo,tracer,anisotropy):
556
+ x_beta=x_halo*dmhalo.r_triangle/tracer.r_scale/anisotropy.r_beta# r / r_beta
557
+ x_tracer=x_halo*dmhalo.r_triangle/tracer.r_scale# r / r_scale
558
+ mass=dmhalo.func_mass(x_halo)+tracer.func_number(x_tracer)*tracer.luminosity_tot*tracer.upsilon/dmhalo.m_triangle
559
+ return mass*tracer.func_density(x_tracer)*anisotropy.f_beta(x_beta)/x_halo**2
560
+
561
+ def integrand_los(x_halo,dmhalo,tracer,anisotropy):
562
+ x_beta=x_halo*dmhalo.r_triangle/tracer.r_scale/anisotropy.r_beta# r / r_beta
563
+ min0=x_halo
564
+ max0=params['upper_limit']
565
+ int1=scipy.integrate.quad(integrand1,min0,max0,args=(dmhalo,tracer,anisotropy),epsrel=params['epsrel'],epsabs=params['epsabs'])
566
+ return (1.-anisotropy.beta(x_beta)*(bigx/x_halo)**2)/np.sqrt(1.-(bigx/x_halo)**2)/anisotropy.f_beta(x_beta)*int1[0]
567
+
568
+ def integrand_rad(x_halo,dmhalo,tracer,anisotropy):
569
+ x_beta=x_halo*dmhalo.r_triangle/tracer.r_scale/anisotropy.r_beta# r / r_beta
570
+ min0=x_halo
571
+ max0=params['upper_limit']
572
+ int1=scipy.integrate.quad(integrand1,min0,max0,args=(dmhalo,tracer,anisotropy),epsrel=params['epsrel'],epsabs=params['epsabs'])
573
+ return (1.-anisotropy.beta(x_beta)+anisotropy.beta(x_beta)*(bigx/x_halo)**2)/np.sqrt(1.-(bigx/x_halo)**2)/anisotropy.f_beta(x_beta)*int1[0]
574
+
575
+ def integrand_tan(x_halo,dmhalo,tracer,anisotropy):
576
+ x_beta=x_halo*dmhalo.r_triangle/tracer.r_scale/anisotropy.r_beta# r / r_beta
577
+ min0=x_halo
578
+ max0=params['upper_limit']
579
+ int1=scipy.integrate.quad(integrand1,min0,max0,args=(dmhalo,tracer,anisotropy),epsrel=params['epsrel'],epsabs=params['epsabs'])
580
+ return (1.-anisotropy.beta(x_beta))/np.sqrt(1.-(bigx/x_halo)**2)/anisotropy.f_beta(x_beta)*int1[0]
581
+
582
+ min0=bigx
583
+ max0=params['upper_limit']
584
+
585
+ if min0==max0:
586
+ bigsigmasigmalos2=0.
587
+ bigsigmasigmarad2=0.
588
+ bigsigmasigmatan2=0.
589
+
590
+ else:
591
+
592
+ if 'los' in params['component']:
593
+ bigsigmasigmalos2=2.*g*dmhalo.m_triangle*scipy.integrate.quad(integrand_los,min0,max0,args=(dmhalo,tracer,anisotropy),epsrel=params['epsrel'],epsabs=params['epsabs'])[0]#sigma^2_los(X) * Sigma(X) / nu0
594
+ if 'rad' in params['component']:
595
+ bigsigmasigmarad2=2.*g*dmhalo.m_triangle*scipy.integrate.quad(integrand_rad,min0,max0,args=(dmhalo,tracer,anisotropy),epsrel=params['epsrel'],epsabs=params['epsabs'])[0]#sigma^2_rad(X) * Sigma(X) / nu0
596
+ if 'tan' in params['component']:
597
+ bigsigmasigmatan2=2.*g*dmhalo.m_triangle*scipy.integrate.quad(integrand_tan,min0,max0,args=(dmhalo,tracer,anisotropy),epsrel=params['epsrel'],epsabs=params['epsabs'])[0]#sigma^2_tan(X) * Sigma(X) / nu0
598
+
599
+ return bigsigmasigmalos2,bigsigmasigmarad2,bigsigmasigmatan2
600
+
601
+ def integrate_isotropic(bigx,dmhalo,tracer,**params):
602
+ if not 'upper_limit' in params:#default upper limit is infinity, common alternative is dmhalo.r_triangle
603
+ params['upper_limit']=np.inf
604
+ if not 'epsrel' in params:
605
+ params['epsrel']=1.49e-8
606
+ if not 'epsabs' in params:
607
+ params['epsabs']=1.49e-8
608
+ if not 'limit' in params:
609
+ params['limit']=50
610
+
611
+ def integrand1(x_halo,dmhalo,tracer):
612
+ x_tracer=x_halo*dmhalo.r_triangle/tracer.r_scale# r / r_scale
613
+ mass=dmhalo.func_mass(x_halo)+tracer.func_number(x_tracer)*tracer.luminosity_tot*tracer.upsilon/dmhalo.m_triangle
614
+ return np.sqrt(1.-(bigx/x_halo)**2)*mass*tracer.func_density(x_tracer)/x_halo
615
+
616
+ min0=bigx
617
+ max0=params['upper_limit']
618
+ return 2.*g*dmhalo.m_triangle*scipy.integrate.quad(integrand1,min0,max0,args=(dmhalo,tracer),epsrel=params['epsrel'],epsabs=params['epsabs'])[0]#sigma^2_LOS(X) * Sigma(X) / nu0
619
+
620
+ def projected_virial(x_halo,dmhalo,tracer):#computes integral for Wlos from Errani etal (2018)
621
+ x_tracer=x_halo*dmhalo.r_triangle/tracer.r_scale
622
+ totalmass=dmhalo.func_mass(x_halo)+tracer.func_number(x_tracer)*tracer.luminosity_tot*tracer.upsilon/dmhalo.m_triangle
623
+ return x_halo*tracer.func_density(x_tracer)*totalmass
624
+
625
+ def get_virial(dmhalo,tracer,**params):
626
+ if not 'epsrel' in params:
627
+ params['epsrel']=1.e-13
628
+ if not 'epsabs' in params:
629
+ params['epsabs']=0.
630
+ if not 'limit' in params:
631
+ params['limit']=500
632
+
633
+ min0=0.
634
+ max0=np.inf
635
+ val1=scipy.integrate.quad(projected_virial,min0,max0,args=(dmhalo,tracer),epsabs=params['epsabs'],epsrel=params['epsrel'],limit=params['limit'])
636
+ vvar=val1[0]*4.*np.pi*g/3.*dmhalo.m_triangle*(dmhalo.r_triangle**2)/tracer.ntotnorm/tracer.r_scale**3
637
+ mu=g*(dmhalo.func_mass(tracer.rhalf_2d/dmhalo.r_triangle)+tracer.func_number(tracer.rhalf_2d/tracer.r_scale)*tracer.luminosity_tot*tracer.upsilon)*dmhalo.m_triangle/tracer.rhalf_2d/vvar
638
+ return vvar,mu
639
+
@@ -0,0 +1,45 @@
1
+ Metadata-Version: 2.1
2
+ Name: jeans
3
+ Version: 1.0.0
4
+ Summary: package to compute integrals related to spherical Jeans equation, including various parametric functions to describe halo and tracer components
5
+ Author-email: "Matthew G. Walker" <mgwalker@cmu.edu>
6
+ Project-URL: Homepage, https://github.com/mgwalkergit/jeans
7
+ Project-URL: Issues, https://github.com/mgwalkergit/jeans/issues
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.8
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: numpy
15
+ Requires-Dist: scipy
16
+ Requires-Dist: astropy
17
+ Requires-Dist: matplotlib
18
+
19
+ # jeans
20
+
21
+ A package for ...
22
+
23
+ Author: Matthew G. Walker (2024)
24
+
25
+ # Instructions
26
+
27
+ * Install jeans. You can either pip install the released version or install from github
28
+
29
+ ```
30
+ pip install jeans
31
+ ```
32
+ # Available Models for 2D position
33
+
34
+ xxx
35
+
36
+ In order to ...:
37
+
38
+ ```dmhalo=jeans.dmhalo('nfw',triangle=200,m_triangle=1.e+10,c_triangle=10)```
39
+
40
+ # Examples
41
+
42
+ For examples of ...
43
+
44
+ # Acknowledgement
45
+
@@ -0,0 +1,10 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ src/jeans/__init__.py
5
+ src/jeans/main.py
6
+ src/jeans.egg-info/PKG-INFO
7
+ src/jeans.egg-info/SOURCES.txt
8
+ src/jeans.egg-info/dependency_links.txt
9
+ src/jeans.egg-info/requires.txt
10
+ src/jeans.egg-info/top_level.txt
@@ -0,0 +1,4 @@
1
+ numpy
2
+ scipy
3
+ astropy
4
+ matplotlib
@@ -0,0 +1 @@
1
+ jeans