Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
yt-project
GitHub Repository: yt-project/yt
Path: blob/main/doc/helper_scripts/show_fields.py
928 views
1
import inspect
2
3
import numpy as np
4
5
import yt.frontends as frontends_module
6
from yt.config import ytcfg
7
from yt.fields.derived_field import NullFunc
8
from yt.frontends.api import _frontends
9
from yt.frontends.stream.fields import StreamFieldInfo
10
from yt.funcs import obj_length
11
from yt.testing import fake_random_ds
12
from yt.units import dimensions
13
from yt.units.yt_array import Unit
14
from yt.utilities.cosmology import Cosmology
15
16
fields, units = [], []
17
18
for fname, (code_units, _aliases, _dn) in StreamFieldInfo.known_other_fields:
19
fields.append(("gas", fname))
20
units.append(code_units)
21
base_ds = fake_random_ds(4, fields=fields, units=units)
22
base_ds.index
23
base_ds.cosmological_simulation = 1
24
base_ds.cosmology = Cosmology()
25
26
27
ytcfg["yt", "internals", "within_testing"] = True
28
np.seterr(all="ignore")
29
30
31
def _strip_ftype(field):
32
if not isinstance(field, tuple):
33
return field
34
elif field[0] == "all":
35
return field
36
return field[1]
37
38
39
np.random.seed(int(0x4D3D3D3))
40
units = [base_ds._get_field_info(f).units for f in fields]
41
fields = [_strip_ftype(f) for f in fields]
42
ds = fake_random_ds(16, fields=fields, units=units, particles=1)
43
ds.parameters["HydroMethod"] = "streaming"
44
ds.parameters["EOSType"] = 1.0
45
ds.parameters["EOSSoundSpeed"] = 1.0
46
ds.conversion_factors["Time"] = 1.0
47
ds.conversion_factors.update({f: 1.0 for f in fields})
48
ds.gamma = 5.0 / 3.0
49
ds.current_redshift = 0.0001
50
ds.cosmological_simulation = 1
51
ds.hubble_constant = 0.7
52
ds.omega_matter = 0.27
53
ds.omega_lambda = 0.73
54
ds.cosmology = Cosmology(
55
hubble_constant=ds.hubble_constant,
56
omega_matter=ds.omega_matter,
57
omega_lambda=ds.omega_lambda,
58
unit_registry=ds.unit_registry,
59
)
60
for my_unit in ["m", "pc", "AU", "au"]:
61
new_unit = f"{my_unit}cm"
62
my_u = Unit(my_unit, registry=ds.unit_registry)
63
ds.unit_registry.add(
64
new_unit,
65
my_u.base_value,
66
dimensions.length,
67
"\\rm{%s}/(1+z)" % my_unit,
68
prefixable=True,
69
)
70
71
72
header = r"""
73
.. _field-list:
74
75
Field List
76
==========
77
78
This is a list of many of the fields available in yt. We have attempted to
79
include most of the fields that are accessible through the plugin system, as
80
well as the fields that are known by the frontends, however it is possible to
81
generate many more permutations, particularly through vector operations. For
82
more information about the fields framework, see :ref:`fields`.
83
84
Some fields are recognized by specific frontends only. These are typically
85
fields like density and temperature that have their own names and units in
86
the different frontend datasets. Often, these fields are aliased to their
87
yt-named counterpart fields (typically 'gas' fieldtypes). For example, in
88
the ``FLASH`` frontend, the ``dens`` field (i.e. ``(flash, dens)``) is aliased
89
to the gas field density (i.e. ``(gas, density)``), similarly ``(flash, velx)``
90
is aliased to ``(gas, velocity_x)``, and so on. In what follows, if a field
91
is aliased it will be noted.
92
93
Try using the ``ds.field_list`` and ``ds.derived_field_list`` to view the
94
native and derived fields available for your dataset respectively. For example
95
to display the native fields in alphabetical order:
96
97
.. notebook-cell::
98
99
import yt
100
ds = yt.load("Enzo_64/DD0043/data0043")
101
for i in sorted(ds.field_list):
102
print(i)
103
104
To figure out out what all of the field types here mean, see
105
:ref:`known-field-types`.
106
107
.. contents:: Table of Contents
108
:depth: 1
109
:local:
110
:backlinks: none
111
112
.. _yt-fields:
113
114
Universal Fields
115
----------------
116
"""
117
118
footer = """
119
120
Index of Fields
121
---------------
122
123
.. contents::
124
:depth: 3
125
:backlinks: none
126
127
"""
128
print(header)
129
130
seen = []
131
132
133
def fix_units(units, in_cgs=False):
134
unit_object = Unit(units, registry=ds.unit_registry)
135
if in_cgs:
136
unit_object = unit_object.get_cgs_equivalent()
137
latex = unit_object.latex_representation()
138
return latex.replace(r"\ ", "~")
139
140
141
def print_all_fields(fl):
142
for fn in sorted(fl):
143
df = fl[fn]
144
f = df._function
145
s = f"{df.name}"
146
print(s)
147
print("^" * len(s))
148
print()
149
if obj_length(df.units) > 0:
150
# Most universal fields are in CGS except for these special fields
151
if df.name[1] in [
152
"particle_position",
153
"particle_position_x",
154
"particle_position_y",
155
"particle_position_z",
156
"entropy",
157
"kT",
158
"metallicity",
159
"dx",
160
"dy",
161
"dz",
162
"cell_volume",
163
"x",
164
"y",
165
"z",
166
]:
167
print(f" * Units: :math:`{fix_units(df.units)}`")
168
else:
169
print(f" * Units: :math:`{fix_units(df.units, in_cgs=True)}`")
170
print(f" * Sampling Method: {df.sampling_type}")
171
print()
172
print("**Field Source**")
173
print()
174
if f == NullFunc:
175
print("No source available.")
176
print()
177
continue
178
else:
179
print(".. code-block:: python")
180
print()
181
for line in inspect.getsource(f).split("\n"):
182
print(" " + line)
183
print()
184
185
186
ds.index
187
print_all_fields(ds.field_info)
188
189
190
class FieldInfo:
191
"""a simple container to hold the information about fields"""
192
193
def __init__(self, ftype, field, ptype):
194
name = field[0]
195
self.units = ""
196
u = field[1][0]
197
if len(u) > 0:
198
self.units = r":math:`\mathrm{%s}`" % fix_units(u)
199
a = [f"``{f}``" for f in field[1][1] if f]
200
self.aliases = " ".join(a)
201
self.dname = ""
202
if field[1][2] is not None:
203
self.dname = f":math:`{field[1][2]}`"
204
205
if ftype != "particle_type":
206
ftype = f"'{ftype}'"
207
self.name = f"({ftype}, '{name}')"
208
self.ptype = ptype
209
210
211
current_frontends = [f for f in _frontends if f not in ["stream"]]
212
213
for frontend in current_frontends:
214
this_f = getattr(frontends_module, frontend)
215
field_info_names = [fi for fi in dir(this_f) if "FieldInfo" in fi]
216
dataset_names = [dset for dset in dir(this_f) if "Dataset" in dset]
217
218
if frontend == "gadget":
219
# Drop duplicate entry for GadgetHDF5, add special case for FieldInfo
220
# entry
221
dataset_names = ["GadgetDataset"]
222
field_info_names = ["GadgetFieldInfo"]
223
elif frontend == "boxlib":
224
field_info_names = []
225
for d in dataset_names:
226
if "Maestro" in d:
227
field_info_names.append("MaestroFieldInfo")
228
elif "Castro" in d:
229
field_info_names.append("CastroFieldInfo")
230
else:
231
field_info_names.append("BoxlibFieldInfo")
232
elif frontend == "chombo":
233
# remove low dimensional field info containers for ChomboPIC
234
field_info_names = [
235
f for f in field_info_names if "1D" not in f and "2D" not in f
236
]
237
238
for dset_name, fi_name in zip(dataset_names, field_info_names):
239
fi = getattr(this_f, fi_name)
240
nfields = 0
241
if hasattr(fi, "known_other_fields"):
242
known_other_fields = fi.known_other_fields
243
nfields += len(known_other_fields)
244
else:
245
known_other_fields = []
246
if hasattr(fi, "known_particle_fields"):
247
known_particle_fields = fi.known_particle_fields
248
if "Tipsy" in fi_name:
249
known_particle_fields += tuple(fi.aux_particle_fields.values())
250
nfields += len(known_particle_fields)
251
else:
252
known_particle_fields = []
253
if nfields > 0:
254
print(f".. _{dset_name.replace('Dataset', '')}_specific_fields:\n")
255
h = f"{dset_name.replace('Dataset', '')}-Specific Fields"
256
print(h)
257
print("-" * len(h) + "\n")
258
259
field_stuff = []
260
for field in known_other_fields:
261
field_stuff.append(FieldInfo(frontend, field, False))
262
for field in known_particle_fields:
263
if frontend in ["sph", "halo_catalogs", "sdf"]:
264
field_stuff.append(FieldInfo("particle_type", field, True))
265
else:
266
field_stuff.append(FieldInfo("io", field, True))
267
268
# output
269
len_name = 10
270
len_units = 5
271
len_aliases = 7
272
len_part = 9
273
len_disp = 12
274
for f in field_stuff:
275
len_name = max(len_name, len(f.name))
276
len_aliases = max(len_aliases, len(f.aliases))
277
len_units = max(len_units, len(f.units))
278
len_disp = max(len_disp, len(f.dname))
279
280
fstr = "{nm:{nw}} {un:{uw}} {al:{aw}} {pt:{pw}} {dp:{dw}}"
281
header = fstr.format(
282
nm="field name",
283
nw=len_name,
284
un="units",
285
uw=len_units,
286
al="aliases",
287
aw=len_aliases,
288
pt="particle?",
289
pw=len_part,
290
dp="display name",
291
dw=len_disp,
292
)
293
294
div = fstr.format(
295
nm="=" * len_name,
296
nw=len_name,
297
un="=" * len_units,
298
uw=len_units,
299
al="=" * len_aliases,
300
aw=len_aliases,
301
pt="=" * len_part,
302
pw=len_part,
303
dp="=" * len_disp,
304
dw=len_disp,
305
)
306
print(div)
307
print(header)
308
print(div)
309
310
for f in field_stuff:
311
print(
312
fstr.format(
313
nm=f.name,
314
nw=len_name,
315
un=f.units,
316
uw=len_units,
317
al=f.aliases,
318
aw=len_aliases,
319
pt=f.ptype,
320
pw=len_part,
321
dp=f.dname,
322
dw=len_disp,
323
)
324
)
325
326
print(div)
327
print("")
328
329
print(footer)
330
331