Field parameters not read
I would like to write a FITS file out of an off-axis projection along some given direction of a field ("i_nu") which I create as a derived field. However, the parameters I set in the main Python program (pl_inu.py) using set_field_parameter() are not passed down to the derived field i_nu. Here is the main macro I am using: """ pl_inu.py """ import numpy as np import yt from yt.utilities.cosmology import Cosmology from yt import derived_field import matplotlib.pyplot as plt from yt.fields.api import ValidateParameter from bckfl_fns import b_p,_e_dens, e_dens, _chi_nu,_kappa, f_kappa, _i_nu, f_chi_nu, los_unit_vector, proj_dist from yt import YTArray, YTQuantity float_formatter = "{:.3f}".format cosmo = Cosmology() LFLY = YTArray(1.0/cosmo.hubble_constant.value,"Mpc").in_cgs() TFLY = (2./3./cosmo.hubble_constant).in_cgs() MFLY = YTArray(5.23e12/cosmo.hubble_constant.value,"Msun").in_cgs() uo = {"length_unit":LFLY, "time_unit":TFLY, "mass_unit":MFLY} fname = 'virgoS12_str_hdf5_plt_cnt_0015' ds=yt.load(fname,units_override=uo) dd=ds.all_data() ds.add_field(("gas", "n_e"), function=_e_dens, units="cm**(-3)", sampling_type='cell', display_name="Electron density", force_override=True) ds.add_field(("gas", "kappa"), function=_kappa, units="kpc**(-1)", sampling_type='cell', display_name="N(E) norm coeff", force_override=True) ds.add_field(("gas", "chi_nu"), function=_chi_nu, units="kpc**(-1)", sampling_type='cell', display_name="synchr. abs. coeff.", force_override=True) ds.add_field(("gas", "i_nu"), function=_i_nu, units="W/(m**2)/Hz", sampling_type='cell', display_name="Synchr. emission", force_override=True, validators=[ValidateParameter(["lmin","l.o.s.","lmin origin","Background I_nu","Magnetic field","Electron p-law index","b(p)","nu (Ghz)"])]) # Output time (in Myr) # co = Cosmology() time = ds.parameters.get('time')*co.t_from_z(0.).in_units("Myr") p = 5./2. E_min = 1.5 E_max = 2.e1 bm4 = 0.01 nu = 1.5 dd.set_field_parameter("Magnetic field", bm4) dd.set_field_parameter("Electron p-law index",p) dd.set_field_parameter("1-p", (1-p)) dd.set_field_parameter("b(p)",b_p(p)) dd.set_field_parameter('E_min', E_min) dd.set_field_parameter('E_max', E_max) dd.set_field_parameter("nu (Ghz)", nu) eul_angles_deg=np.array([4.,22.]) n_dir = los_unit_vector(eul_angles_deg) pos_0 = YTArray([0.,0,-130],'kpc') grid_pos=YTArray([dd['gas','x'],dd['gas','y'],dd['gas','z']]).in_units('kpc') lmin = np.amin(proj_dist(n_dir,grid_pos,pos_0)) i_nu_lmin = YTQuantity(1.e-27,'W/(m**2)/Hz') dd.set_field_parameter('Background I_nu', i_nu_lmin) dd.set_field_parameter("lmin", lmin) dd.set_field_parameter("l.o.s.", n_dir) dd.set_field_parameter('lmin origin', pos_0) dd.set_field_parameter('grid pos', grid_pos) synchr_fits=yt.FITSOffAxisSlice(ds,n_dir,("gas", "i_nu"), width=((50,'kpc'))) fits_name = 'i_nu_r0000_15.fits' synchr_fits.writeto(fits_name, overwrite='True') ==== and this is the collection of functions I use to create the field "i_nu": """ bckfl_fns.py """ import sys import yt import numpy as np import global_vars from yt import derived_field from yt import YTArray, YTQuantity from yt.fields.api import ValidateParameter """ Derived fields in yt-FLASH """ def _kappa(field, data): import math from yt import YTQuantity if data.has_field_parameter("E_min"): E_min = data.get_field_parameter("E_min") else: E_min = 0. if data.has_field_parameter("E_max"): E_max = data.get_field_parameter("E_max") else: E_max = 0. ne_tot = data["gas", "n_e"].v if data.has_field_parameter("Electron p-law index"): p = data.get_field_parameter("Electron p-law index") else: p = 0. if data.has_field_parameter("E_min") and data.has_field_parameter("E_max") \ and data.has_field_parameter("Electron p-law index"): k=YTQuantity(1.0,"kpc**(-1)")*(1-p)*ne_tot/(pow(E_max,(1-p)) - pow(E_min,(1-p))) print("Inside kappa: p-law index is",p, E_min, E_max) else: k=YTQuantity(1.0,"kpc**(-1)") if np.any(k < 0): print("k negative!", k) return k def _chi_nu(field, data): if data.has_field_parameter("Electron p-law index") and \ data.has_field_parameter("b(p)") and \ data.has_field_parameter("Magnetic field") and \ data.has_field_parameter("nu (Ghz)"): p = data.get_field_parameter("Electron p-law index") bp = data.get_field_parameter("b(p)") bm4 = data.get_field_parameter("Magnetic field") nu = data.get_field_parameter("nu (Ghz)") ne_tot = data[("gas","n_e")].v kappa = data[("gas","kappa")] a = 6.445e-6 chi_nu=a*np.power(10,(p/2))*np.power(5.67,p)*kappa*bp*pow(bm4,(0.5*p+1))/np.power(nu,(0.5*p+2)) else: chi_nu=YTQuantity(0.0,"kpc**(-1)") return chi_nu def _i_nu(field, data): from unyt import kpc from yt import YTArray, YTQuantity from yt.units import mass_hydrogen # if data.has_field_parameter("lmin"): lmin = data.get_field_parameter("lmin") print("Inside _i_nu, lmin=",lmin) else: lmin = YTQuantity(0.0,"kpc") if data.has_field_parameter("l.o.s."): los = data.get_field_parameter("l.o.s.") print("Inside _i_nu, l.o.s.=",los) else: los = [0, 0, 0] if data.has_field_parameter("lmin origin"): pos_0 = data.get_field_parameter("lmin origin") print("Inside _i_nu, pos_0=",pos_0) else: pos_0 = data.ds.arr(np.zeros(3), 'kpc') if data.has_field_parameter("Background I_nu"): i_nulmin = data.get_field_parameter("Background I_nu") print("Inside _i_nu, i_nulmin=",i_nulmin) else: i_nu_lmin = 0. if data.has_field_parameter("Magnetic field"): bm4 = data.get_field_parameter("Magnetic field") print("Inside _i_nu, bm4=",bm4) else: bm4 = 1.e-20 ## i_nu_lmin=YTQuantity(i_nulmin,"W/(m**2)/Hz") # i_nu_lmin=YTQuantity(i_nulmin,"W/(m**2)/Hz").in_units("Jansky") if data.has_field_parameter("Electron p-law index"): p = data.get_field_parameter("Electron p-law index") print("Inside _i_nu, p=",p) fact_joc = np.power(10,-p) else: p=0. fact_joc = 0. if data.has_field_parameter("b(p)"): bp = data.get_field_parameter("b(p)") print("Inside _i_nu, b(p)=",bp) else: bp = 0. if data.has_field_parameter("nu (Ghz)"): nu = data.get_field_parameter("nu (Ghz)") print("Inside _i_nu, nu=",nu) else: nu = 0 ne_tot = data["gas","density"].v/mass_hydrogen.v kappa = data["kappa"] a = YTQuantity(4.97766e-17,'W/(m**2)/Hz') chi_nu = f_chi_nu(nu,bm4,p,bp,kappa) j_over_chi = a*fact_joc*(nu**2.5)/np.power(bm4,0.5) grid_pos=YTArray([data['gas','x'],data['gas','y'],data['gas','z']]).in_units('kpc') r = proj_dist(los,grid_pos,pos_0) ad = r-lmin print("Inside _i_nu", i_nulmin, j_over_chi, a) b = np.exp(-chi_nu*(r-lmin)) i_nu = i_nulmin*b + j_over_chi*(1-b) return i_nu """ General purpose functions """ def _e_dens(field, data): """ Computes electron density from gas density.""" from yt.units import mass_hydrogen return data[("gas","density")]/mass_hydrogen def e_dens(dens): """ Computes electron density from gas density.""" from yt.units import mass_hydrogen return dens.v/mass_hydrogen.v def f_kappa(ntot,emin,emax,p): import sys, math fk = (1-p)*ntot/(np.power(emax,(1-p))-np.power(emin,(1-p))) return fk def a_p(p): from scipy import interpolate as int_erp p=[1,1.5,2,2.5,3,3.5,4,4.5,5] bp=[2.056,0.909,0.529,0.359,0.269,0.217,0.186,0.167,0.157] f_interp=int_erp.interp1d(p,bp) return f_interp(p_inp) def b_p(p_inp): from scipy import interpolate as int_erp p=[1,1.5,2,2.5,3,3.5,4,4.5,5] bp=[0.397,0.314,0.269,0.244,0.233,0.230,0.236,0.248,0.268] f_interp=int_erp.interp1d(p,bp) return f_interp(p_inp) def f_chi_nu(nu,B,p,bp,kappa): import sys, math a1 = 5.67**p a2 = pow(10,p/2) c1 = 0.5*p + 1 c2 = 0.5*p + 2 abs_coeff = YTArray([6.445e-6],'kpc**(-1)') return abs_coeff def los_unit_vector(inp_angles): from numpy import radians from math import sin, cos eul_angles_rad=radians(inp_angles) v_dir = np.array([sin(eul_angles_rad[0])*cos(eul_angles_rad[1]),sin(eul_angles_rad[0])*sin(eul_angles_rad[1]),cos(eul_angles_rad[0])]) return v_dir def proj_dist(los,xyz,origin): import numpy as np d = ((xyz.T - origin)*los) dist = np.sqrt(np.sum(d*d, axis=1)) return dist ======= Fr some reasons I do not quite understand, the field parameters I define in the main program are not passed down to the "i_nu" field through the _i_nu function. Here the error message:
python3 pl_synchr_test.py yt : [WARNING ] 2021-10-16 17:45:34,946 Overriding code units: Use this option only if you know that the dataset doesn't define the units correctly or at all. yt : [INFO ] 2021-10-16 17:45:34,946 Overriding length_unit: 4.346024761918768e+24 cm. yt : [INFO ] 2021-10-16 17:45:34,947 Overriding time_unit: 2.897349841279178e+17 s. yt : [INFO ] 2021-10-16 17:45:34,947 Overriding mass_unit: 1.4647063306760563e+46 g. yt : [INFO ] 2021-10-16 17:45:35,024 Parameters: current_time = 0.0016112618581139734 yt : [INFO ] 2021-10-16 17:45:35,024 Parameters: domain_dimensions = [8 8 8] yt : [INFO ] 2021-10-16 17:45:35,024 Parameters: domain_left_edge = [-0.7 -0.7 -0.7] yt : [INFO ] 2021-10-16 17:45:35,024 Parameters: domain_right_edge = [0.7 0.7 0.7] yt : [INFO ] 2021-10-16 17:45:35,024 Parameters: cosmological_simulation = 0 Inside _i_nu, lmin= 0.0 Inside _i_nu, l.o.s.= 0.0 Inside _i_nu, pos_0= 0.0 Inside _i_nu, i_nulmin= 0.0 Inside _i_nu, bm4= 0.0 Inside _i_nu, p= 0.0 Inside _i_nu, b(p)= 0.0 Inside _i_nu, nu= 0.0 /g100/home/userexternal/vantonuc/.local/lib/python3.8/site-packages/unyt/array.py:1778: RuntimeWarning: invalid value encountered in true_divide out_arr = func( Inside _i_nu 0.0 nan W/(Hz*m**2) 4.97766e-17 W/(Hz*m**2) yt : [INFO ] 2021-10-16 17:45:41,439 Making a fixed resolution buffer of (('gas', 'i_nu')) 512 by 512 Traceback (most recent call last): File "pl_synchr_test.py", line 64, in <module> synchr_fits=yt.FITSOffAxisSlice(ds,n_dir,("gas", "i_nu"), width=((50,'kpc'))) File "/g100/home/userexternal/vantonuc/.local/lib/python3.8/site-packages/yt/visualization/fits_image.py", line 1275, in __init__ super().__init__(frb, fields=fields, length_unit=lunit, wcs=w) File "/g100/home/userexternal/vantonuc/.local/lib/python3.8/site-packages/yt/visualization/fits_image.py", line 244, in __init__ this_img = img_data[field] File "/g100/home/userexternal/vantonuc/.local/lib/python3.8/site-packages/yt/visualization/fixed_resolution.py", line 139, in __getitem__ buff = self.ds.coordinates.pixelize( File "/g100/home/userexternal/vantonuc/.local/lib/python3.8/site-packages/yt/geometry/coordinates/cartesian_coordinates.py", line 221, in pixelize return self._oblique_pixelize(data_source, field, bounds, size, antialias) File "/g100/home/userexternal/vantonuc/.local/lib/python3.8/site-packages/yt/geometry/coordinates/cartesian_coordinates.py", line 570, in _oblique_pixelize data_source[field], File "/g100/home/userexternal/vantonuc/.local/lib/python3.8/site-packages/yt/data_objects/data_containers.py", line 258, in __getitem__ self.get_data(f) File "/g100/home/userexternal/vantonuc/.local/lib/python3.8/site-packages/yt/data_objects/selection_objects/data_selection_objects.py", line 169, in get_data finfo.check_available(self) File "/g100/home/userexternal/vantonuc/.local/lib/python3.8/site-packages/yt/fields/derived_field.py", line 244, in check_available validator(data) File "/g100/home/userexternal/vantonuc/.local/lib/python3.8/site-packages/yt/fields/derived_field.py", line 503, in __call__ raise NeedsParameter(doesnt_have) yt.fields.field_exceptions.NeedsParameter: (['lmin', 'l.o.s.', 'lmin origin', 'Background I_nu', 'Magnetic field', 'Electron p-law index', 'b(p)', 'nu (Ghz)']) ========
Many thanks in advance for any help/suggestions.
I have prepared a simpler test code to demonstrate the issue. Here I define one field ("gas, "n_e") through the function _e_dens. I then define a field parameter lmin through a call to set_field_parameter. Inside the function _e_dens I put a simple if..else loop which should print a message when lmin is read. Here is the code: """ pl_test_set_param.py """ import numpy as np import yt from yt.utilities.cosmology import Cosmology from yt import derived_field import matplotlib.pyplot as plt from yt.fields.api import ValidateParameter from yt import YTArray, YTQuantity def _e_dens(field, data): from yt.units import mass_hydrogen if data.has_field_parameter("lmin"): lmin = data.get_field_parameter("lmin") print("From _e_dens lmin=",lmin) else: lmin = YTQuantity(0.,"kpc") print("From _e_dens not read lmin",lmin) return data[("gas","density")]/mass_hydrogen cosmo = Cosmology() LFLY = YTArray(1.0/cosmo.hubble_constant.value,"Mpc").in_cgs() TFLY = (2./3./cosmo.hubble_constant).in_cgs() MFLY = YTArray(5.23e12/cosmo.hubble_constant.value,"Msun").in_cgs() uo = {"length_unit":LFLY, "time_unit":TFLY, "mass_unit":MFLY} dir='/g100_work/INA20_C6T28_0/virgo/v0000/Run0000/' f_root='virgoS12_str_hdf5_plt_cnt_' f_index='0015' fname = dir+f_root+f_index ds=yt.load(fname,units_override=uo) dd=ds.all_data() dd.add_field(("gas", "n_e"), function=_e_dens, units="cm**(-3)", sampling_type='cell', display_name="Electron density", force_override=True) lmin=YTQuantity(3.2,"kpc") dd.set_field_parameter("lmin", lmin) plt_ne = yt.SlicePlot(ds, 'x', 'n_e', width=((120,'kpc'),(200,'kpc'))) plt_ne.annotate_title('Electron density') plt_ne.set_font({'family': 'monospace', 'style': 'normal','size': 36}) """ Electron density limits in cm^-3. """ ne_l = 1.e-6 ne_u = 1.e-1 plt_ne.set_zlim('n_e', ne_l, ne_u) plt_ne.save('n_e_v0000_15_v2.png') #======================== The code correctly creates a slice of n_e. However from the if..else loop inside _e_dens I get the following output: ... From _e_dens not read lmin 0.0 kpc From _e_dens not read lmin 0.0 kpc From _e_dens not read lmin 0.0 kpc ... demonstrating that the field parameter lmin is not read from inside _e_dens, as it should. Again, I would appreciate any fresh insight.
Hi Vincenzo, I think in both cases you need to provide the field parameter to the SlicePlot or the FITSOffAxisSlice as shown here: plt_ne = yt.SlicePlot(ds, 'x', 'n_e', width=((120,'kpc'),(200,'kpc')), field_parameters={"lmin":YTQuantity(3.2,"kpc") }) a similar thing can be done with the FITSOffAxisSlice (I believe). Let us know if not. You added it to the "dd" object but since that is not used in constructing your slice it won’t work. Best, John
On Oct 22, 2021, at 6:16 AM, Vincenzo Antonuccio-Delogu <vincenzo.antonuccio@inaf.it> wrote:
I have prepared a simpler test code to demonstrate the issue. Here I define one field ("gas, "n_e") through the function _e_dens. I then define a field parameter lmin through a call to set_field_parameter. Inside the function _e_dens I put a simple if..else loop which should print a message when lmin is read. Here is the code:
""" pl_test_set_param.py """ import numpy as np import yt from yt.utilities.cosmology import Cosmology from yt import derived_field import matplotlib.pyplot as plt from yt.fields.api import ValidateParameter from yt import YTArray, YTQuantity
def _e_dens(field, data): from yt.units import mass_hydrogen if data.has_field_parameter("lmin"): lmin = data.get_field_parameter("lmin") print("From _e_dens lmin=",lmin) else: lmin = YTQuantity(0.,"kpc") print("From _e_dens not read lmin",lmin)
return data[("gas","density")]/mass_hydrogen
cosmo = Cosmology() LFLY = YTArray(1.0/cosmo.hubble_constant.value,"Mpc").in_cgs() TFLY = (2./3./cosmo.hubble_constant).in_cgs() MFLY = YTArray(5.23e12/cosmo.hubble_constant.value,"Msun").in_cgs() uo = {"length_unit":LFLY, "time_unit":TFLY, "mass_unit":MFLY}
dir='/g100_work/INA20_C6T28_0/virgo/v0000/Run0000/' f_root='virgoS12_str_hdf5_plt_cnt_' f_index='0015' fname = dir+f_root+f_index ds=yt.load(fname,units_override=uo) dd=ds.all_data()
dd.add_field(("gas", "n_e"), function=_e_dens, units="cm**(-3)", sampling_type='cell', display_name="Electron density", force_override=True)
lmin=YTQuantity(3.2,"kpc") dd.set_field_parameter("lmin", lmin)
plt_ne = yt.SlicePlot(ds, 'x', 'n_e', width=((120,'kpc'),(200,'kpc'))) plt_ne.annotate_title('Electron density') plt_ne.set_font({'family': 'monospace', 'style': 'normal','size': 36}) """ Electron density limits in cm^-3. """ ne_l = 1.e-6 ne_u = 1.e-1 plt_ne.set_zlim('n_e', ne_l, ne_u) plt_ne.save('n_e_v0000_15_v2.png') #========================
The code correctly creates a slice of n_e. However from the if..else loop inside _e_dens I get the following output: ... From _e_dens not read lmin 0.0 kpc From _e_dens not read lmin 0.0 kpc From _e_dens not read lmin 0.0 kpc ...
demonstrating that the field parameter lmin is not read from inside _e_dens, as it should. Again, I would appreciate any fresh insight. _______________________________________________ yt-users mailing list -- yt-users@python.org To unsubscribe send an email to yt-users-leave@python.org https://mail.python.org/mailman3/lists/yt-users.python.org/ Member address: jzuhone@gmail.com
participants (2)
-
John ZuHone
-
Vincenzo Antonuccio-Delogu