trident-project/trident

Gadget snapshot is determined to be 'cell-based' not 'particle-based'

Closed this issue · 10 comments

I'm having an issue where trident determines that my gadget is a 'cell based' simulation where it is actually a 'particle-based' simulation. We thing this has a significant affect on the density calculations of our rays.

I have tried running this code to diagnose the problems and force the code to use a sampling type of 'particle' but I get an error of 'ValueError: ('gas', 'smoothing_length') not in derived_field_list'.

How do I get trident to recognize that this is a SPH simulation and not a grid simulation.

Python Version: '3.6.4'
YT version: '3.5.dev0'
Trident Version: '1.1'

import yt
import trident

fn = "/Users/abatten/PhD/data/AURORA/L012N0128/Aurora_L012N0128_FSN1.0_FESC0.5/data/snapshot_060/snap_060.0.hdf5"
ds = yt.load(fn)
trident.add_ion_fields(ds, ions=['H I', 'He I', 'He II'], sampling_type='particle')



yt : [INFO     ] 2018-09-06 11:51:46,130 Parameters: current_time              = 3.035652263793517e+16 s
yt : [INFO     ] 2018-09-06 11:51:46,131 Parameters: domain_dimensions         = [2 2 2]
yt : [INFO     ] 2018-09-06 11:51:46,132 Parameters: domain_left_edge          = [0. 0. 0.]
yt : [INFO     ] 2018-09-06 11:51:46,132 Parameters: domain_right_edge         = [12.5 12.5 12.5]
yt : [INFO     ] 2018-09-06 11:51:46,133 Parameters: cosmological_simulation   = 1
yt : [INFO     ] 2018-09-06 11:51:46,133 Parameters: current_redshift          = 5.9999999999999964
yt : [INFO     ] 2018-09-06 11:51:46,134 Parameters: omega_lambda              = 0.735
yt : [INFO     ] 2018-09-06 11:51:46,135 Parameters: omega_matter              = 0.265
yt : [INFO     ] 2018-09-06 11:51:46,135 Parameters: hubble_constant           = 0.71
yt : [INFO     ] 2018-09-06 11:51:46,152 Allocating for 4.194e+06 particles (index particle type 'all')
yt : [INFO     ] 2018-09-06 11:51:46,594 Identified 2.952e+05 octs

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-3-44efd89e07c2> in <module>()
      5 fn = "/Users/abatten/PhD/data/AURORA/L012N0128/Aurora_L012N0128_FSN1.0_FESC0.5/data/snapshot_060/snap_060.0.hdf5"
      6 ds = yt.load(fn)
----> 7 trident.add_ion_fields(ds, ions=['H I', 'He I', 'He II'], sampling_type='particle')

~/anaconda3/lib/python3.6/site-packages/trident/ion_balance.py in add_ion_fields(ds, ions, ftype, ionization_table, field_suffix, line_database, force_override, sampling_type, particle_type)
    328         add_ion_mass_field(atom, ion, ds, ftype, ionization_table,
    329             field_suffix=field_suffix, force_override=force_override,
--> 330             sampling_type=sampling_type)
    331 
    332 def add_ion_fraction_field(atom, ion, ds, ftype="gas",

~/anaconda3/lib/python3.6/site-packages/trident/ion_balance.py in add_ion_mass_field(atom, ion, ds, ftype, ionization_table, field_suffix, force_override, sampling_type, particle_type)
    875                           field_suffix=field_suffix,
    876                           force_override=force_override,
--> 877                           sampling_type=sampling_type)
    878     ds.add_field((ftype, field), function=_ion_mass, units=r"g",
    879                  sampling_type=sampling_type,

~/anaconda3/lib/python3.6/site-packages/trident/ion_balance.py in add_ion_density_field(atom, ion, ds, ftype, ionization_table, field_suffix, force_override, sampling_type, particle_type)
    736                                  field_suffix=field_suffix,
    737                                  force_override=force_override,
--> 738                                  sampling_type=sampling_type)
    739     ds.add_field((ftype, field), function=_ion_density,
    740                  units="g/cm**3", sampling_type=sampling_type,

~/anaconda3/lib/python3.6/site-packages/trident/ion_balance.py in add_ion_number_density_field(atom, ion, ds, ftype, ionization_table, field_suffix, force_override, sampling_type, particle_type)
    598                            field_suffix=field_suffix,
    599                            force_override=force_override,
--> 600                            sampling_type=sampling_type)
    601     ds.add_field((ftype, field),function=_ion_number_density,
    602                  units="cm**-3", sampling_type=sampling_type,

~/anaconda3/lib/python3.6/site-packages/trident/ion_balance.py in add_ion_fraction_field(atom, ion, ds, ftype, ionization_table, field_suffix, force_override, sampling_type, particle_type)
    471     # if ion particle field, add a smoothed deposited version to gas fields
    472     if sampling_type == 'particle':
--> 473         new_field = ds.add_smoothed_particle_field((ftype, field))
    474         if ftype != "gas":
    475             ds.field_info.alias(("gas", field), new_field)

~/anaconda3/lib/python3.6/site-packages/yt/frontends/sph/data_structures.py in add_smoothed_particle_field(self, smooth_field, method, nneighbors, kernel_name)
     71         return super(SPHDataset, self).add_smoothed_particle_field(
     72             smooth_field=smooth_field, method=method, nneighbors=nneighbors,
---> 73             kernel_name=kernel_name
     74         )

~/anaconda3/lib/python3.6/site-packages/yt/data_objects/static_output.py in add_smoothed_particle_field(self, smooth_field, method, nneighbors, kernel_name)
   1347         if (ptype, smoothing_length_name) not in self.derived_field_list:
   1348             raise ValueError("%s not in derived_field_list" %
-> 1349                              ((ptype, smoothing_length_name),))
   1350         density_name = "density"
   1351         registry = self.field_info

ValueError: ('gas', 'smoothing_length') not in derived_field_list

As supplementary, I tried to add the smoothing length of the particles as a field by creating a ray (in the hdf5 file it is SmoothingLength) however I encounter the same error. It also here tells me that there is a mismatch between the SAMPLING_TYPE and FTYPE.

ray = trident.make_simple_ray(fn, start_position=[0.2,0.5, 0],
                              end_position=[0.2, 0.5, 12.5],
                              data_filename="ray.h5",
                              lines=["H", "He"],
                              fields=[('PartType0', 'SmoothingLength'),
                                     ('PartType0', 'Density')]) 


yt : [INFO     ] 2018-09-06 12:01:36,594 Parameters: current_time              = 3.035652263793517e+16 s
yt : [INFO     ] 2018-09-06 12:01:36,597 Parameters: domain_dimensions         = [2 2 2]
yt : [INFO     ] 2018-09-06 12:01:36,599 Parameters: domain_left_edge          = [0. 0. 0.]
yt : [INFO     ] 2018-09-06 12:01:36,600 Parameters: domain_right_edge         = [12.5 12.5 12.5]
yt : [INFO     ] 2018-09-06 12:01:36,603 Parameters: cosmological_simulation   = 1
yt : [INFO     ] 2018-09-06 12:01:36,604 Parameters: current_redshift          = 5.9999999999999964
yt : [INFO     ] 2018-09-06 12:01:36,604 Parameters: omega_lambda              = 0.735
yt : [INFO     ] 2018-09-06 12:01:36,605 Parameters: omega_matter              = 0.265
yt : [INFO     ] 2018-09-06 12:01:36,605 Parameters: hubble_constant           = 0.71
yt : [INFO     ] 2018-09-06 12:01:36,612 Allocating for 4.194e+06 particles (index particle type 'all')
yt : [INFO     ] 2018-09-06 12:01:37,061 Identified 2.952e+05 octs
yt : [WARNING  ] 2018-09-06 12:01:39,780 ===================================================
yt : [WARNING  ] 2018-09-06 12:01:39,781 MISMATCH BETWEEN SAMPLING_TYPE OF FTYPE AND DATASET
yt : [WARNING  ] 2018-09-06 12:01:39,781 sampling_type of (gas, 'density') = cell
yt : [WARNING  ] 2018-09-06 12:01:39,782 sampling_type of dataset = particle
yt : [WARNING  ] 2018-09-06 12:01:39,782 THIS IS PROBABLY UNDESIRED BEHAVIOR.  PLEASE CHOOSE A DIFFERENT FTYPE.
yt : [WARNING  ] 2018-09-06 12:01:39,782 ===================================================

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-82-26d709e94ff5> in <module>()
      4                               lines=["H", "He"],
      5                               fields=[('PartType0', 'SmoothingLength'),
----> 6                                      ('PartType0', 'Density')])

~/anaconda3/lib/python3.6/site-packages/trident/ray_generator.py in make_simple_ray(dataset_file, start_position, end_position, lines, ftype, fields, solution_filename, data_filename, trajectory, redshift, setup_function, load_kwargs, line_database, ionization_table)
    248                                          ftype=ftype,
    249                                          ionization_table=ionization_table,
--> 250                                          sampling_type=sampling_type)
    251 
    252     # To assure there are no fields that are double specified or that collide

~/anaconda3/lib/python3.6/site-packages/trident/ion_balance.py in add_ion_number_density_field(atom, ion, ds, ftype, ionization_table, field_suffix, force_override, sampling_type, particle_type)
    598                            field_suffix=field_suffix,
    599                            force_override=force_override,
--> 600                            sampling_type=sampling_type)
    601     ds.add_field((ftype, field),function=_ion_number_density,
    602                  units="cm**-3", sampling_type=sampling_type,

~/anaconda3/lib/python3.6/site-packages/trident/ion_balance.py in add_ion_fraction_field(atom, ion, ds, ftype, ionization_table, field_suffix, force_override, sampling_type, particle_type)
    471     # if ion particle field, add a smoothed deposited version to gas fields
    472     if sampling_type == 'particle':
--> 473         new_field = ds.add_smoothed_particle_field((ftype, field))
    474         if ftype != "gas":
    475             ds.field_info.alias(("gas", field), new_field)

~/anaconda3/lib/python3.6/site-packages/yt/frontends/sph/data_structures.py in add_smoothed_particle_field(self, smooth_field, method, nneighbors, kernel_name)
     71         return super(SPHDataset, self).add_smoothed_particle_field(
     72             smooth_field=smooth_field, method=method, nneighbors=nneighbors,
---> 73             kernel_name=kernel_name
     74         )

~/anaconda3/lib/python3.6/site-packages/yt/data_objects/static_output.py in add_smoothed_particle_field(self, smooth_field, method, nneighbors, kernel_name)
   1347         if (ptype, smoothing_length_name) not in self.derived_field_list:
   1348             raise ValueError("%s not in derived_field_list" %
-> 1349                              ((ptype, smoothing_length_name),))
   1350         density_name = "density"
   1351         registry = self.field_info

ValueError: ('gas', 'smoothing_length') not in derived_field_list

Hi @abatten . Thanks for the message and for joining our community!

You probably want to specify the ftype keyword in add_ion_fields() as the field type in your dataset that pertains to the actual gas particles. Probably for Gadget data, this is PartType0. This is mentioned a few times in the docs (in the API docs for add_ion_fields(): https://trident.readthedocs.io/en/latest/generated/trident.add_ion_fields.html#trident.add_ion_fields, and in the docs on adding ion fields: https://trident.readthedocs.io/en/latest/ion_balance.html), but I should probably add an entry to the FAQ about this. But I believe if you set ftype correctly, what you're trying to do should work.

It's also noting that in the current stable release of Trident, particle-based datasets like Gadget are deposited to an octree grid structure and then treated as grid-based datasets for sampling. This is described at length in the method paper, and it can sometimes introduce artifacts in regions of poor resolution. However, there has been substantial work from both the yt and trident communities to treat particle-based datasets natively without depositing to a grid structure called the "demeshening." There are full instructions on installing and using the demeshened versions of yt and trident here (it's linked on our installation page): https://nbviewer.jupyter.org/url/trident-project.org/notebooks/trident_demesh_install.ipynb

I hope this helps with your issue, but please let us know if you continue to have problems.

Hi @chummels .
Thanks for the tip about the demeshed versions of YT and Trident. I was able to download and install them. It seems to be almost working as I would like.

I had a few questions still:

  • What is the difference between 'H_p1_number_density' and 'H_nuclei_density'? When I try to generate a ray with "H" in the line list it only creates 'H_nuclei_number_density' and 'H_number_density' in the output ray.h5, however when I use the example gizmo script on the FIRE data it creates both 'H_nuclei_number_density' and 'H_p1_number_density' with different values.

  • Secondly I'm having problems getting the ray to output 'He_p2_number_density' in the ray. It seems to work on the FIRE data but, for my simulations it doesn't create the the field in my simulations.

    import yt 
    import trident
    
    fn = "/Users/abatten/PhD/data/AURORA/L012N0128/Aurora_L012N0128_FSN1.0_FESC0.5/data/snapshot_060/snap_060.0.hdf5"
    ds = yt.load(fn)
    
    xi, yi, zi = 10, 1.00, 0.0 
    xf, yf, zf = 10, 1.00, 12.5
    ray_start = [xi, yi, zi]
    ray_end = [xf, yf, zf]
    ray = trident.make_simple_ray(fn,
                               start_position=ray_start,
                               end_position=ray_end,
                               lines=['H', 'He', 'H I', 'H II', 'He I', 'He II', 'He III'],
                               ftype='PartType0',
                               data_filename='test_ray.h5')
    
    
    

I have also tried using the following, but this leads to a "RecursionError: maximum recursion depth exceeded while calling a Python object"

trident.add_ion_number_density_field("He", 3, ds, ftype="PartType0", force_override=True)

yt : [WARNING  ] 2018-09-10 16:31:28,313 Field ('gas', 'He_p2_ion_fraction') already exists. To override use force_override=True.

---------------------------------------------------------------------------
RecursionError                            Traceback (most recent call last)
<ipython-input-50-98226b082339> in <module>()
----> 1 trident.add_ion_number_density_field("He", 3, ds, ftype="PartType0", force_override=True)
      2 ray = trident.make_simple_ray(fn, start_position=[0.2,0.5, 0],
      3                               end_position=[0.2, 0.5, 12.5],
      4                               data_filename="ray.h5",
      5                               lines=["H", "He", "C"],

~/Packages/trident/trident/ion_balance.py in add_ion_number_density_field(atom, ion, ds, ftype, ionization_table, field_suffix, force_override, sampling_type, particle_type)
    508 
    509     add_ion_fraction_field(atom, ion, ds, ionization_table,
--> 510                            field_suffix=field_suffix)
    511     ds.add_field(("gas", field),function=_ion_number_density,
    512                  units="cm**-3", sampling_type='local',

~/Packages/trident/trident/ion_balance.py in add_ion_fraction_field(atom, ion, ds, ftype, ionization_table, field_suffix, force_override, sampling_type, particle_type)
    405 
    406     ds.add_field(("gas", field), function=_ion_fraction_field, units="",
--> 407                  sampling_type="local", force_override=force_override)
    408     if ion == 1: # add aliased field too
    409         ds.field_info.alias(("gas", alias_field), ("gas", field))

~/Packages/yt/yt/data_objects/static_output.py in add_field(self, name, function, sampling_type, **kwargs)
   1252         self.field_info.add_field(name, sampling_type, function=function, **kwargs)
   1253         self.field_info._show_field_errors.append(name)
-> 1254         deps, _ = self.field_info.check_derived_fields([name])
   1255         self.field_dependencies.update(deps)
   1256 

~/Packages/yt/yt/fields/field_info_container.py in check_derived_fields(self, fields_to_check)
    377             fi = self[field]
    378             try:
--> 379                 fd = fi.get_dependencies(ds = self.ds)
    380             except Exception as e:
    381                 if field in self._show_field_errors:

~/Packages/yt/yt/fields/derived_field.py in get_dependencies(self, *args, **kwargs)
    216             e.requested.append(self.name)
    217         else:
--> 218             e[self.name]
    219         return e
    220 

~/Packages/yt/yt/fields/field_detector.py in __missing__(self, item)
    106                         vv = finfo(self)
    107                 if not permute_params:
--> 108                     vv = finfo(self)
    109             except NeedsGridType as exc:
    110                 ngz = exc.ghost_zones

~/Packages/yt/yt/fields/derived_field.py in __call__(self, data)
    256                 "for %s" % (self.name,))
    257         with self.unit_registry(data):
--> 258             dd = self._function(self, data)
    259         for field_name in data.keys():
    260             if field_name not in original_fields:

~/Packages/trident/trident/ion_balance.py in _ion_fraction_field(field, data)
    851         raise RuntimeError("This data file format is not supported.")
    852 
--> 853     fraction = np.power(10, interp(data))
    854     fraction[fraction <= fraction_zero_point] = 0.0
    855     if not isinstance(data, FieldDetector) and (fraction > 1.0).any():

~/Packages/yt/yt/utilities/linear_interpolators.py in __call__(self, data_object)
    207 
    208     def __call__(self, data_object):
--> 209         orig_shape = data_object[self.x_name].shape
    210         x_vals = data_object[self.x_name].ravel().astype('float64')
    211         y_vals = data_object[self.y_name].ravel().astype('float64')

~/Packages/yt/yt/fields/field_detector.py in __missing__(self, item)
    106                         vv = finfo(self)
    107                 if not permute_params:
--> 108                     vv = finfo(self)
    109             except NeedsGridType as exc:
    110                 ngz = exc.ghost_zones

~/Packages/yt/yt/fields/derived_field.py in __call__(self, data)
    256                 "for %s" % (self.name,))
    257         with self.unit_registry(data):
--> 258             dd = self._function(self, data)
    259         for field_name in data.keys():
    260             if field_name not in original_fields:

~/Packages/trident/trident/ion_balance.py in _log_nH(field, data)
    101     """
    102     if ("gas", "H_nuclei_density") in data.ds.derived_field_list:
--> 103         log_nH_field = np.log10(data["gas", "H_nuclei_density"])
    104     else:
    105         log_nH_field = np.log10(data["gas", "density"] * to_nH)

~/Packages/yt/yt/fields/field_detector.py in __missing__(self, item)
    106                         vv = finfo(self)
    107                 if not permute_params:
--> 108                     vv = finfo(self)
    109             except NeedsGridType as exc:
    110                 ngz = exc.ghost_zones

~/Packages/yt/yt/fields/derived_field.py in __call__(self, data)
    256                 "for %s" % (self.name,))
    257         with self.unit_registry(data):
--> 258             dd = self._function(self, data)
    259         for field_name in data.keys():
    260             if field_name not in original_fields:

~/Packages/yt/yt/fields/species_fields.py in _nuclei_density(field, data)
    190 
    191     field_data = np.zeros_like(data[ftype, "%s_number_density" %
--> 192                                     data.ds.field_info.species_names[0]])
    193     for species in data.ds.field_info.species_names:
    194         nucleus = species

~/Packages/yt/yt/fields/field_detector.py in __missing__(self, item)
    106                         vv = finfo(self)
    107                 if not permute_params:
--> 108                     vv = finfo(self)
    109             except NeedsGridType as exc:
    110                 ngz = exc.ghost_zones

~/Packages/yt/yt/fields/derived_field.py in __call__(self, data)
    256                 "for %s" % (self.name,))
    257         with self.unit_registry(data):
--> 258             dd = self._function(self, data)
    259         for field_name in data.keys():
    260             if field_name not in original_fields:

~/Packages/trident/trident/ion_balance.py in _ion_number_density(field, data)
    801 
    802     if atom == 'H' or atom == 'He':
--> 803         number_density = solar_abundance[atom] * data[fraction_field_name]
    804     else:
    805         number_density = data.ds.quan(solar_abundance[atom], "1.0/Zsun") * \

... last 13 frames repeated, from the frame below ...

~/Packages/yt/yt/fields/field_detector.py in __missing__(self, item)
    106                         vv = finfo(self)
    107                 if not permute_params:
--> 108                     vv = finfo(self)
    109             except NeedsGridType as exc:
    110                 ngz = exc.ghost_zones

RecursionError: maximum recursion depth exceeded while calling a Python object

Also thirdly, I have a question about the dl,
I created a frequency distribution of the various lengths of dl from 163 rays. We were confused as to why the dl is sharply peaked near zero, as we were expecting something more gaussian like. How is the dl calculated for the demeshed Trident?

We were guessing that the dl is the length piercing the through individual particles (i.e so dl = 2*r_s if the ray goes through the centre of the particle, with r_s being the smoothing length and dl ~ 0, when the ray clips the edge of a particle.) However it would be unlikely for a ray to clip the edge of many particles as opposed to be somewhere in the middle. Which is why we didn't expect a peak near zero for dl.

Finally is the sph kernel integrated for weighting densities when creating rays?

new_dl_kpc_histogram

Hi @abatten . Glad to hear things are almost working for your use case!

To answer your questions, H_p1_number_density refers to the number density of H II. (p1 stands for plus one). H_nuclei_density is the number density of all hydrogen (both neutral and ionized). For reference, H_p0_number_density and H_number_density are both the neutral hydrogen (H I) number density. It's unfortunate, but in the initial implementation in yt, H_number_density was just set up to be neutral hydrogen, not total hydrogen, so in order to retain backwards compatibility it has thus remained as such, and we just alias H_p0_number_density (H plus 0 = H I) to it. Confusing, I know. Maybe in the next full release we'll break backwards compatibility to fix this problem...

Hmm, that's odd about H II fields not being generated for your dataset. Have you just tried explicitly adding them with:

import trident
trident.add_ion_fields(ds, 'H II')

As for your problem with He III, again, this seems odd. Can you again try running the code above but replacing H II with He III and see if it works?

To address your final question about the dl values peaking close to zero for a sightline passing through your SPH volume, I think this makes sense. In a grid-based dataset, the sightline just passes through different cells, and so dl is simply the geometric pathlength over which it intersects those cells. However, in the demeshening version of trident/yt, those path lengths are not simple geometric lengths representing the amount of the SPH particle that has been intersected by the path. It also folds in information about the SPH kernel itself, since that gives the weighting to whatever particle-field you're sampling. So to get the integrated column density of H I along a line of sight, it is still sum(n_HI * dl), but now the dl includes the line integral through the kernel at whatever impact parameter the sightline passes relative to the particle center.

So it's like what you suggest, but weighted with by the smoothing kernel function, which falls off with radius. So I think this will bias sightlines hitting a particle off-center to have smaller and smaller dl values, effectively making it look like a lot of stuff is grazing.

But perhaps @ngoldbaum can speak more to this result, since he was one of the main architects of the demeshening in yt.

Thanks @chummels , that explaination of dl was what we wanted. However I'm still having the issue with HII and HeIII. I tried adding them explicitly with what you suggested, however it gives me erros that the ion fields already exist but doesn't add them to the ray. I also tried adding fields for C I , C II instead of H II and He III which seems to work, just not for H II and HeIII

import yt
import trident

xi, yi, zi = 10, 1.00, 0.0
xf, yf, zf = 10, 1.00, 12.5
ray_start = [xi, yi, zi]
ray_end = [xf, yf, zf]
trident.add_ion_fields(ds, ions=['H II'])
trident.add_ion_fields(ds, ions=['He III'])
sray = trident.make_simple_ray(fn,
                               start_position=ray_start,
                               end_position=ray_end,
                               lines=['H', 'He', 'H I', 'H II', 'He I', 'He II', 'He III'],
                               ftype='PartType0',
                               data_filename='test_ray.h5')

These are the warnings it keeps giving me about the ion fields already existing. And using the force_override=True gives that maximum recursion depth exceeded while calling a Python object error from before.

yt : [WARNING  ] 2018-09-12 15:47:28,145 Field ('gas', 'H_p1_ion_fraction') already exists. To override use force_override=True.
yt : [WARNING  ] 2018-09-12 15:47:28,156 Field ('gas', 'H_p1_number_density') already exists. To override use force_override=True.
yt : [WARNING  ] 2018-09-12 15:47:28,164 Field ('gas', 'H_p1_density') already exists. To override use force_override=True.
yt : [WARNING  ] 2018-09-12 15:47:28,171 Field ('gas', 'H_p1_mass') already exists. To override use force_override=True.
yt : [WARNING  ] 2018-09-12 15:47:28,178 Field ('gas', 'He_p2_ion_fraction') already exists. To override use force_override=True.
yt : [WARNING  ] 2018-09-12 15:47:28,184 Field ('gas', 'He_p2_number_density') already exists. To override use force_override=True.
yt : [WARNING  ] 2018-09-12 15:47:28,191 Field ('gas', 'He_p2_density') already exists. To override use force_override=True.
yt : [WARNING  ] 2018-09-12 15:47:28,201 Field ('gas', 'He_p2_mass') already exists. To override use force_override=True.

It looks like from your example, you're not actually using the dataset, ds, to generate your sray object, since you pass it the filename of the dataset, not the actual dataset that you've processed. Try changing this line from:

sray = trident.make_simple_ray(fn,

to

sray = trident.make_simple_ray(ds,

so trident uses the dataset that you already added the H II and He III lines to. If this doesn't address the problem for you, then I'm not sure how to fix it. I may have to play with your dataset. Alternatively, you could try to reproduce your bug with one of the public datasets, like the FIRE snapshot referenced in the docs. But first let me know if the solution above fixes your issue.

@abatten : Did my suggestions address your problem? If so, can you close this issue? If not, let me know and we can further address things.

Yes I think this worked! Thank you.