I checked myself and just wanted to quickly confirm, is there a 90 percent radius of any sort within IllustrisTNG? 90 percent mass or 90 percent light would work.
Dylan Nelson
13 Apr '21
That is correct, you would need to compute other radii like r10 or r90 yourself (from the particle data).
Julian Goddy
13 Apr '22
Hi Dylan, how would I calculate r90 from the particle data? Is there a formula for this? Also, is there a 50 percent light radius within IllustrisTNG?
Thanks,
Julian
Dylan Nelson
13 Apr '22
Following the definition, you want the radius enclosing 90% of the "total" mass, for example. You should be careful to define "total".
You can compute the distance of every particle from the center of a galaxy, then compute the cumulative cum of mass as a function of enclosed distance, then find the radius as above.
• I can get it to give gas particles instead of stellar particles by changing “stars” with “gas” in the params (line 8) and then changing to “PartType0” in lines 20-23. I can’t get dark particles (changing to “dm” or “total” doesn’t work). But I don’t think it matters for this application as I would rather have r50 and r90 as light radii than mass radii. Is there a way to get these measures in IllustrisTNG?
• The total stellar/gas mass for the subhalo matches the one given in the link above but it slightly off. Why?
• The r50 value is extremely far off and I don’t know why. Do you have any ideas?
Ideally, I would do this with the API version as I don’t really want to download all the h5py files but will do so if necessary.
Thanks,
Julian
CODE:
import h5py
import numpy as np
id = 447698 #eventually I will loop over many subhalos
params = {'stars':'Coordinates,Masses'}
url = "http://www.tng-project.org/api/TNG100-1/snapshots/z=0" + "/subhalos/" + str(id)
sub = get(url) # get json response of subhalo properties
saved_filename = get(url + "/cutout.hdf5", params) # get and save HDF5 cutout file
rr100=0
with h5py.File(saved_filename) as g:
dx100 = g['PartType4']['Coordinates'][:,0] - sub['pos_x']
dy100 = g['PartType4']['Coordinates'][:,1] - sub['pos_y']
dz100 = g['PartType4']['Coordinates'][:,2] - sub['pos_z']
mass100 = g['PartType4']['Masses'][:]
rr100 = np.sqrt(dx100**2 + dy100**2 + dz100**2)
cum_mass=0
radius=0
mass100_sorted_gas = np.sort(mass100_gas)
rr100_sorted_gas = np.sort(rr100_gas)
for i in range(len(rr100)):
if cum_mass <= sub['massinhalfrad_stars']: #alternatively, this is np.sum(mass100):
radius = rr100_sorted_gas[i]
cum_mass += mass100_sorted_gas[i]
print("radius:", radius)
print("mass:", cum_mass)
Dylan Nelson
18 Apr '22
You are sorting the masses and radii separately, which will give the wrong answer.
You should use np.argsort() instead, and also I would suggest np.cumsum().
In general you need to handle the periodic boundary conditions, if the subhalo position is near the box edges.
Hi Dylan,
Thanks for the suggestions. I had forgotten about those functions but they definitely help. I was able to reproduce many of the mass and radii values, but I still can't get r50 for gas. What is the problem? Also, I attempted to handle the periodic boundary conditions; did I do that correctly (I am using IllustrisTNG-100, which I think I read has a box size of 110.7 Mpc, which I set as the box size for the boundary conditions)?
More importantly, how do I get r50 and r90 as light radii instead of mass radii?
My code is below:
Thanks,
Julian
import h5py
import numpy as np
id = 447698
params = {'gas':'Coordinates,Masses', 'stars':'Coordinates,Masses' }
url = "http://www.tng-project.org/api/TNG100-1/snapshots/z=0" + "/subhalos/" + str(id)
sub = get(url) # get json response of subhalo properties
saved_filename = get(url + "/cutout.hdf5", params) # get and save HDF5 cutout file
rr100_gas=0
rr100_stars=0
####### gas is PartType0
####### stars is PartType4
####### boxsize=110.7 Mpc ?
####### scale_factor=1 at z=0, so I want boxsize* 1000/0.704 for Mpc -> kpc/h
boxsize = 110.7 \* 0.704 \* 1000
x_pos=sub['pos_x']
y_pos=sub['pos_y']
z_pos=sub['pos_z']
with h5py.File(saved_filename) as g:
dx100_gas = g['PartType0']['Coordinates'][:,0] - x_pos
dy100_gas = g['PartType0']['Coordinates'][:,1] - y_pos
dz100_gas = g['PartType0']['Coordinates'][:,2] - z_pos
mass100_gas = g['PartType0']['Masses'][:]
dx100_stars = g['PartType4']['Coordinates'][:,0] - x_pos
dy100_stars = g['PartType4']['Coordinates'][:,1] - y_pos
dz100_stars = g['PartType4']['Coordinates'][:,2] - z_pos
mass100_stars = g['PartType4']['Masses'][:]
for i in range(len(dx100_stars)):
if (dx100_stars[i] < -boxsize * 0.5): dx100_stars[i] = dx100_stars[i] + boxsize
if (dx100_stars[i] >= boxsize * 0.5): dx100_stars[i] = dx100_stars[i] - boxsize
if (dy100_stars[i] < -boxsize * 0.5): dy100_stars[i] = dy100_stars[i] + boxsize
if (dy100_stars[i] >= boxsize * 0.5): dy100_stars[i] = dy100_stars[i] - boxsize
if (dz100_stars[i] < -boxsize * 0.5): dz100_stars[i] = dz100_stars[i] + boxsize
if (dz100_stars[i] >= boxsize * 0.5): dz100_stars[i] = dz100_stars[i] - boxsize
for i in range(len(dx100_gas)):
if (dx100_gas[i] < -boxsize * 0.5): dx100_gas[i] = dx100_gas[i] + boxsize
if (dx100_gas[i] >= boxsize * 0.5): dx100_gas[i] = dx100_gas[i] - boxsize
if (dy100_gas[i] < -boxsize * 0.5): dy100_gas[i] = dy100_gas[i] + boxsize
if (dy100_gas[i] >= boxsize * 0.5): dy100_gas[i] = dy100_gas[i] - boxsize
if (dz100_gas[i] < -boxsize * 0.5): dz100_gas[i] = dz100_gas[i] + boxsize
if (dz100_gas[i] >= boxsize * 0.5): dz100_gas[i] = dz100_gas[i] - boxsize
rr100_gas = np.sqrt(dx100_gas**2 + dy100_gas**2 + dz100_gas**2)
rr100_stars = np.sqrt(dx100_stars**2 + dy100_stars**2 + dz100_stars**2)
####### print("done!")
sorted_along_radius_stars=rr100_stars.argsort()
mass100_sorted_stars = mass100_stars[sorted_along_radius_stars]
rr100_sorted_stars = rr100_stars[sorted_along_radius_stars]
sorted_along_radius_gas=rr100_gas.argsort()
mass100_sorted_gas = mass100_gas[sorted_along_radius_gas]
rr100_sorted_gas = rr100_gas[sorted_along_radius_gas]
print("stellar half mass radius", rr100_sorted_stars[np.where(np.cumsum(mass100_sorted_stars) <= sub['massinhalfrad_stars'] )][-1])
print("gas half mass radius", rr100_sorted_gas[ np.where(np.cumsum( mass100_sorted_gas) <= sub['massinhalfrad_gas'] )][-1])
print("***")
print("gas mass in stellar half mass radius:", np.cumsum(mass100_sorted_gas)[np.where(rr100_sorted_gas <= sub['halfmassrad_stars'])] [-1])
print("gas mass in twice half stellar mass radius:", np.cumsum(mass100_sorted_gas)[np.where(rr100_sorted_gas <= 2*sub['halfmassrad_stars'])] [-1])
print("***")
print("stellar mass in half stellar mass radius:", np.cumsum(mass100_sorted_stars)[np.where(rr100_sorted_stars <= sub['halfmassrad_stars'])] [-1])
print("stellar in twice half stellar mass radius:", np.cumsum(mass100_sorted_stars)[np.where(rr100_sorted_stars <= 2*sub['halfmassrad_stars'])] [-1])
print("***")
print("stellar mass in vmax radius:", np.cumsum(mass100_sorted_stars)[np.where(rr100_sorted_stars <= sub['vmaxrad'] )] [-1])
print("gas mass in vmax radius:", np.cumsum(mass100_sorted_gas)[np.where(rr100_sorted_gas <= sub['vmaxrad'] )] [-1])
Dylan Nelson
20 Apr '22
The periodic BC seems ok, but you can use BoxSize = 75000.0 exactly (in "code units" of ckpc/h). Note you can use np.where() instead of any loops to do the periodic BC (faster).
I don't see any problem with the gas, perhaps there is an issue in how you treat wind particles. Wind particles are PartType4 but have negative ages (please see documentation). They are more correctly called gas, and not stars, and so the half mass radii in the catalogs likely
If you want half-light radii, you need to replace the mass arrays by some estimate of "light". For stars you could use one of the bands in GFM_StellarPhotometrics. For gas, you need to use some model to estimate its emission in whatever band/wavelength/line you are thinking of.
Julian Goddy
28 Apr '22
Hi Dylan,
I'm sorry for the very late reply but thanks so much; that helps a lot!
I checked myself and just wanted to quickly confirm, is there a 90 percent radius of any sort within IllustrisTNG? 90 percent mass or 90 percent light would work.
That is correct, you would need to compute other radii like r10 or r90 yourself (from the particle data).
Hi Dylan, how would I calculate r90 from the particle data? Is there a formula for this? Also, is there a 50 percent light radius within IllustrisTNG?
Thanks,
Julian
Following the definition, you want the radius enclosing 90% of the "total" mass, for example. You should be careful to define "total".
You can compute the distance of every particle from the center of a galaxy, then compute the cumulative cum of mass as a function of enclosed distance, then find the radius as above.
Hi Dylan,
Thanks for the comment.
I have made some progress following the procedure you describe and task #6 in the API docs (https://www.tng-project.org/data/docs/api/#reference). My code is below. I am testing my code by seeing if it can reproduce r50 in the subhalo data: (https://www.tng-project.org/api/TNG100-1/snapshots/99/subhalos/447698/). However, there are several problems with it, which I list in no particular order:
• I can get it to give gas particles instead of stellar particles by changing “stars” with “gas” in the params (line 8) and then changing to “PartType0” in lines 20-23. I can’t get dark particles (changing to “dm” or “total” doesn’t work). But I don’t think it matters for this application as I would rather have r50 and r90 as light radii than mass radii. Is there a way to get these measures in IllustrisTNG?
• The total stellar/gas mass for the subhalo matches the one given in the link above but it slightly off. Why?
• The r50 value is extremely far off and I don’t know why. Do you have any ideas?
Ideally, I would do this with the API version as I don’t really want to download all the h5py files but will do so if necessary.
Thanks,
Julian
CODE:
You are sorting the masses and radii separately, which will give the wrong answer.
You should use
np.argsort()
instead, and also I would suggestnp.cumsum()
.In general you need to handle the periodic boundary conditions, if the subhalo position is near the box edges.
Hi Dylan,
Thanks for the suggestions. I had forgotten about those functions but they definitely help. I was able to reproduce many of the mass and radii values, but I still can't get r50 for gas. What is the problem? Also, I attempted to handle the periodic boundary conditions; did I do that correctly (I am using IllustrisTNG-100, which I think I read has a box size of 110.7 Mpc, which I set as the box size for the boundary conditions)?
More importantly, how do I get r50 and r90 as light radii instead of mass radii?
My code is below:
Thanks,
Julian
The periodic BC seems ok, but you can use BoxSize = 75000.0 exactly (in "code units" of ckpc/h). Note you can use
np.where()
instead of any loops to do the periodic BC (faster).I don't see any problem with the gas, perhaps there is an issue in how you treat wind particles. Wind particles are PartType4 but have negative ages (please see documentation). They are more correctly called gas, and not stars, and so the half mass radii in the catalogs likely
If you want half-light radii, you need to replace the mass arrays by some estimate of "light". For stars you could use one of the bands in
GFM_StellarPhotometrics
. For gas, you need to use some model to estimate its emission in whatever band/wavelength/line you are thinking of.Hi Dylan,
I'm sorry for the very late reply but thanks so much; that helps a lot!
Julian