Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AHF halo ID fix #88

Merged
merged 23 commits into from
Mar 20, 2021
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
0f26bfd
change raw_iter_rows for AHF stat file to return the file position as…
Dec 6, 2018
37e4626
change the implementation of defining halo IDs from their position wi…
Dec 7, 2018
3179077
add test for AHFStatFile class to ensure that the ID numbers are correct
Apr 8, 2019
ee51d3a
Merge branch 'master' into AHF_handler_fix_mjt
mtremmel Apr 8, 2019
c29c405
create separate test halo catalog with ID numbers more like the rando…
Apr 9, 2019
4502ee1
Merge remote-tracking branch 'upstream/master' into AHF_handler_fix_mjt
mtremmel Feb 15, 2021
134b570
create new catalog_id property for halos to save the position within …
mtremmel Feb 15, 2021
5299a33
move counting for catalog_id calculation to iter_rows_raw and apply _…
mtremmel Feb 16, 2021
92fed69
change _catalog_id_offset to _catalog_index_offset to avoid confusion
mtremmel Feb 16, 2021
2f678a9
update stat file tests to incorporate both catalog indices and finder…
mtremmel Feb 16, 2021
317de9d
update load_object function calls and ObjectSpecify constructors to i…
mtremmel Feb 22, 2021
fba582b
propogate changes to halo objects to several test functions, yt and o…
mtremmel Feb 24, 2021
c344e8e
fix inconsistent naming convention for catalog_index column.
mtremmel Feb 26, 2021
ea7c175
-Update stat file importing to include additional output when reading…
mtremmel Feb 26, 2021
1d55bfb
update two tests to expect correct results given changes in the code
mtremmel Feb 26, 2021
c7547fc
Have timestep cache create halo maps for both catalog_index and finde…
mtremmel Mar 1, 2021
c62b698
update the yt halo reader to compare min_halo_particles with the tota…
mtremmel Mar 1, 2021
1030ac3
add comments to explain various halo identifier columns (catalog_inde…
mtremmel Mar 2, 2021
d873acc
remove superfluous checks when loading halo data which were attempting
mtremmel Mar 2, 2021
355e5df
split the timestep cache resolve function into two separate functions…
mtremmel Mar 2, 2021
8ff003a
remove unused get_halo_entry function in GenericLinker class
mtremmel Mar 2, 2021
f8eb973
update docstring for iter_rows
mtremmel Mar 2, 2021
aacf2ee
change the name of the catalog_index halo attribute to finder_offset
mtremmel Mar 17, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 19 additions & 6 deletions tangos/core/halo.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class Halo(Base):
id = Column(Integer, primary_key=True)
halo_number = Column(Integer)
finder_id = Column(Integer)
catalog_index = Column(Integer)
timestep_id = Column(Integer, ForeignKey('timesteps.id'))
timestep = relationship(TimeStep, backref=backref(
'objects', order_by=halo_number, cascade='all', lazy='dynamic'), cascade='save-update, merge')
Expand Down Expand Up @@ -72,10 +73,11 @@ def object_typetag_from_code(typecode):
return c.tag
raise ValueError("Unknown object typecode %d",typecode)

def __init__(self, timestep, halo_number, finder_id, NDM, NStar, NGas, object_typecode=0):
def __init__(self, timestep, halo_number, finder_id, catalog_index, NDM, NStar, NGas, object_typecode=0):
self.timestep = timestep
self.halo_number = int(halo_number)
self.finder_id = int(finder_id)
self.catalog_index = int(catalog_index)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we add comments to these definitions to explain what the three different things are?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, is catalog_index the best name for it? Would finder_offset or something like that be more descriptive?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup I can put in comments. The rationale for catalog_index is that this is the value passed to the input handler's halo catalog reader to extract a halo. In other words, this is the index pointing to this halo within that catalog object. Note that it is not at all a constant offset necessarily from the finder_id. In fact, there is no reason why it is related to the finder_id at all. Rather, h[catalog_index] will return this halo from halo catalog h

Copy link
Member

@apontzen apontzen Mar 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand that yes... but somehow finder_offset sounds right to me, it's the offset in the finder output of this halo from the start? Whereas catalog_index draws attention to finder vs catalog - is that the right thing to contrast? As another alternative, could finder_id become catalog_id? (bad idea, breaks backward compatibility)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

haha I guess we might just have a difference in opinion here? to me your description of "offset" just sounds like an "index" (0 = start, 1 = start +1, etc). I'm ok going with whatever you think is the most descriptive. it shouldn't be very hard to change. Maybe I've been thinking about it too long and find finder_offset confusing.

self.NDM = int(NDM)
self.NStar = int(NStar)
self.NGas = int(NGas)
Expand Down Expand Up @@ -120,12 +122,23 @@ def load(self, mode=None):
handler this can be None or 'partial' (in a normal session) and, when running inside an MPI session,
'server' or 'server-partial'. See https://pynbody.github.io/tangos/mpi.html.
"""
if self.finder_id is None:
halo_number = self.halo_number
if not hasattr(self, "finder_id"):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why has this line changed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This like is basically still there, but my thought was to first check to see if the object even has finder_id and catalog_index columns to begin with for backwards compatibility. Maybe this is all overkill?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've now simplified this. The previous checks were deprecated anyway I think

finder_id = self.halo_number # backward compatibility
else:
finder_id = self.finder_id
if self.finder_id is None:
finder_id = self.halo_number
else:
finder_id = self.finder_id
if not hasattr(self, "catalog_index"):
catalog_index = self.finder_id
else:
if self.catalog_index is None:
catalog_index = finder_id
else:
catalog_index = self.catalog_index
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic is a bit baffling, is it possible to add a comment explaining what is going on?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is really just an attempt at backwards compatibility with a database that does not have these columns already. Maybe this is all too much and it would be better simply provide a tool for the user to update their database accordingly?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think simple is better here. I believe sqlalchemy takes care of adding a column of NULLs (will appear as Nones) when opening an old database. Certainly, I don't think the attribute will ever be missing


return self.handler.load_object(self.timestep.extension, finder_id, object_typetag=self.tag, mode=mode)
return self.handler.load_object(self.timestep.extension, finder_id, catalog_index, object_typetag=self.tag, mode=mode)

def calculate(self, calculation, return_description=False):
"""Use the live-calculation system to calculate a user-specified function of the stored data.
Expand Down Expand Up @@ -390,7 +403,7 @@ class Tracker(Halo):
tag = "tracker"

def __init__(self, timestep, halo_number):
super(Tracker, self).__init__(timestep, halo_number, halo_number, 0,0,0,
super(Tracker, self).__init__(timestep, halo_number, halo_number, halo_number, 0,0,0,
self.__mapper_args__['polymorphic_identity'])

@property
Expand Down Expand Up @@ -449,7 +462,7 @@ class PhantomHalo(Halo):
tag = "phantom"

def __init__(self, timestep, halo_number, finder_id):
super(PhantomHalo, self).__init__(timestep, halo_number, finder_id, 0,0,0,
super(PhantomHalo, self).__init__(timestep, halo_number, finder_id, finder_id, 0,0,0,
self.__mapper_args__['polymorphic_identity'])

TimeStep.phantoms = orm.relationship(Halo, cascade='all', lazy='dynamic',
Expand Down
6 changes: 4 additions & 2 deletions tangos/input_handlers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,12 +134,14 @@ def load_timestep_without_caching(self, ts_extension, mode=None):
"""Creates and returns an object that connects to the data for a timestep on disk"""
raise NotImplementedError

def load_object(self, ts_extension, halo_number, object_typetag='halo', mode=None):
def load_object(self, ts_extension, finder_id, catalog_pos, object_typetag='halo', mode=None):
"""Creates and returns an object that connects to the data for a halo on disk.

:arg ts_extension - the timestep path (relative to the simulation basename)

:arg halo_number - the halo number in the raw halo finder output
:arg finder_id - the halo id in the raw halo finder output

:arg catalog_pos - the position of the raw halo finder output

:arg object_typetag - the type of halo catalogue (normally 'halo' or, for Subfind, might be 'group' to get
the top-level groups)
Expand Down
6 changes: 3 additions & 3 deletions tangos/input_handlers/ahf_trees.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,10 @@ def _load_mtree_file_standard(self):
while i < len(data):
for j in range(data[i][2]):
idx = i+1+j
if data[idx][1]+1 in self._fid: # check if this halo was loaded in case a minimum number of particles different to AHF was used to load halos into DB
if data[idx][1] in self._fid: # check if this halo was loaded in case a minimum number of particles different to AHF was used to load halos into DB
# keep in mind finder id and AHF id have an offset of 1
results['id_desc'] = np.append(results['id_desc'],data[i][0]+1)
results['id_this'] = np.append(results['id_this'],data[idx][1]+1)
results['id_desc'] = np.append(results['id_desc'],data[i][0])
results['id_this'] = np.append(results['id_this'],data[idx][1])
results['f_share'] = np.append(results['f_share'], float(data[idx][0] * data[idx][0]) / (data[i][1] * data[idx][2]) )
i += data[i][2] + 1

Expand Down
75 changes: 52 additions & 23 deletions tangos/input_handlers/halo_stat_files/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@

class HaloStatFile(object):
"""Manages and reads a halo stat file of unspecified format."""
_id_offset = 0
_catalog_index_offset = 0
# _id_from_file_pos = False
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this commented out?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should probably just be deleted. The old version had a flag whether the finder_id was derived from the position within the catalog file, but now finder_id and catalog_index are both saved separately

_column_translations = {}

def __new__(cls, timestep):
Expand Down Expand Up @@ -56,22 +57,29 @@ def all_columns(self):
def iter_rows_raw(self, *args):
"""
Yield the halo ID and requested columns from each line of the stat file, without any emulation.

If _id_from_file_pos is True, the ID is not taken from the stat file, but rather from the order in which
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clarify that _id_from_file_pos is a class attribute, not something passed to the function?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to update this description because this is inaccurate

the halos appear.
:param args: strings for the column names
:return: id, arg1, arg2, arg3 where ID is the halo ID and argN is the value of the Nth named column
"""
with open(self.filename) as f:
header = self._read_column_names(f)
cnt = 0
ids = [0]
for a in args:
try:
ids.append(header.index(a))
except ValueError:
ids.append(None)

for l in f:
if not l.startswith("#"):
yield self._get_values_for_columns(ids, l)
col_data = self._get_values_for_columns(ids, l)
col_data.insert(0, cnt+self._catalog_index_offset)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit confused now - shouldn't something like this be conditional on _id_from_file_pos, if the docstring above is accurate?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's because the docstring is not accurate! I will fix this. Now iter_rows always returns the catalog index (+ any offset set by the class) AND the raw finder ID number read directly from the file, followed by all of the requested quantities.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated the docstring for the iter_rows_raw function. Hopefully it is more clear

#if self._id_from_file_pos:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's this commented-out stuff about?

# col_data[0] = cnt
#col_data[0] += self._id_offset
yield col_data
cnt += 1

def iter_rows(self, *args):
"""
Expand All @@ -90,19 +98,18 @@ def iter_rows(self, *args):
raw_args+=self._column_translations[arg].inputs()
else:
raw_args.append(arg)

for raw_values in self.iter_rows_raw(*raw_args):
values = [raw_values[0]]
values = [raw_values[0], raw_values[1]]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little confused about what is happening here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the returned values are now always catalog_index, finder_id, then all of the asked-for values

for arg in args:
if arg in self._column_translations:
values.append(self._column_translations[arg](raw_args, raw_values[1:]))
values.append(self._column_translations[arg](raw_args, raw_values[2:]))
else:
values.append(raw_values[1:][raw_args.index(arg)])
values.append(raw_values[2:][raw_args.index(arg)])
yield values

def read(self, *args):
"""Read the halo ID and requested columns from the entire file, returning each column as a separate array"""
return_values = [[] for _ in range(len(args)+1)]
return_values = [[] for _ in range(len(args)+2)]
for row in self.iter_rows(*args):
for return_array, value in zip(return_values, row):
return_array.append(value)
Expand All @@ -128,7 +135,7 @@ def _get_values_for_columns(self, columns, line):
this_cast = this_str

results.append(this_cast)
results[0] += self._id_offset
#results[0] += self._id_offset
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove commented-out code if it's definitely not needed

return results

def _read_column_names(self, f):
Expand All @@ -138,14 +145,15 @@ def _read_column_names(self, f):


class AHFStatFile(HaloStatFile):
_id_offset = 1
_catalog_index_offset = 1
# _id_from_file_pos = True
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confused that this is commented out again. Is _id_from_file_pos something that is controllable or not?


_column_translations = {'n_gas': translations.DefaultValue('n_gas', 0),
'n_star': translations.DefaultValue('n_star', 0),
'n_dm': translations.Function(lambda ngas, nstar, npart: npart - (ngas or 0) - (nstar or 0),
'n_gas', 'n_star', 'npart'),
'hostHalo': translations.Function(
lambda id: None if id==-1 else proxy_object.IncompleteProxyObjectFromFinderId(id+AHFStatFile._id_offset, 'halo'),
lambda id: None if id==-1 else proxy_object.IncompleteProxyObjectFromFinderId(id, 'halo'),
'hostHalo')}

def __init__(self, timestep_filename):
Expand All @@ -169,26 +177,24 @@ def filename(cls, timestep_filename):
return "CannotFindAHFHaloFilename"
else:
return file_list[0]
return file

def _calculate_children(self):
# use hostHalo column to calculate virtual childHalo entries
self._children_map = {}
for h_id, host_id_raw in self.iter_rows_raw("hostHalo"):
if host_id_raw!=-1:
host_id = host_id_raw + self._id_offset
cmap = self._children_map.get(host_id, [])
cmap.append(proxy_object.IncompleteProxyObjectFromFinderId(h_id,'halo'))
self._children_map[host_id] = cmap
for c_id, f_id, host_f_id in self.iter_rows_raw("hostHalo"):
if host_f_id!=-1:
cmap = self._children_map.get(host_f_id, [])
cmap.append(proxy_object.IncompleteProxyObjectFromFinderId(f_id,'halo'))
self._children_map[host_f_id] = cmap

def _calculate_children_if_required(self):
if not hasattr(self, "_children_map"):
self._calculate_children()

def _child_halo_entry(self, this_id_raw):
self._calculate_children_if_required()
this_id = this_id_raw + self._id_offset
children = self._children_map.get(this_id, [])
#this_id = this_id_raw + self._id_offset
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove code if it's not needed

children = self._children_map.get(this_id_raw, [])
return children

class RockstarStatFile(HaloStatFile):
Expand All @@ -208,7 +214,7 @@ def filename(cls, timestep_filename):
return "CannotComputeRockstarFilename"

class AmigaIDLStatFile(HaloStatFile):
_id_offset = 0
# _id_offset = 0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove


_column_translations = {'n_dm': translations.Rename('N_dark'),
'n_gas': translations.Rename('N_gas'),
Expand All @@ -220,4 +226,27 @@ class AmigaIDLStatFile(HaloStatFile):
def filename(cls, timestep_filename):
return timestep_filename + '.amiga.stat'


def iter_rows_raw(self, *args):
"""
Yield the halo ID and requested columns from each line of the stat file, without any emulation.
If _id_from_file_pos is True, the ID is not taken from the stat file, but rather from the order in which
the halos appear.
:param args: strings for the column names
:return: id, arg1, arg2, arg3 where ID is the halo ID and argN is the value of the Nth named column
"""
with open(self.filename) as f:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this copy-paste code appear here? Shouldn't it be inherited from the base class?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code expects from the stat file enumerator output of the form catalog_index, finder_id, arg1, arg2, arg3, ... but for this particular stat file catalog_index (the number that the halo catalog associates with a given halo) is always equal to the finder_id. That's why there needs to be a different function here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the docstring incorrect in that case? (I think this is also true for the base class method above)

As for avoiding copy-paste, would something like the following work? (NB I didn't actually try it at all! Just speculating)

def iter_rows_raw(self, *args):
   for row in super(self).iter_rows_raw(*args):
       row[0] = row[1] # sequential catalog index not right in this case; overwrite to match finder id
       yield row

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh yeah I think that's a good solution. I can code that up and see. I'll double check the docstrings

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've implemented this and tested (no "self" in the super call, but otherwise exactly as you have it) and it seems to work. I've pushed this over just now!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also double checked and the iter_rows_raw docstrings were accurate but iter_rows one was not. That has been updated.

header = self._read_column_names(f)
ids = [0]
for a in args:
try:
ids.append(header.index(a))
except ValueError:
ids.append(None)
for l in f:
if not l.startswith("#"):
col_data = self._get_values_for_columns(ids, l)
col_data.insert(0, col_data[0])
#if self._id_from_file_pos:
# col_data[0] = cnt
#col_data[0] += self._id_offset
yield col_data
10 changes: 5 additions & 5 deletions tangos/input_handlers/output_testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def enumerate_objects(self, ts_extension, object_typetag='halo', min_halo_partic
nhalos_string = self._get_ts_property(ts_extension, object_typetag+"s")
nhalos = 0 if nhalos_string is None else int(nhalos_string)
for i in range(nhalos):
yield i+1, 2000-i, 0, 0
yield i+1, i+1, 2000-i, 0, 0

def match_objects(self, ts1, ts2, halo_min, halo_max, dm_only=False, threshold=0.005,
object_typetag='halo', output_handler_for_ts2=None):
Expand Down Expand Up @@ -71,12 +71,12 @@ def load_region(self, ts_extension, region_specification, mode=None):
data.message = data.message[region_specification]
return data

def load_object(self, ts_extension, halo_number, object_typetag='halo', mode=None):
def load_object(self, ts_extension, finder_id, catalog_index, object_typetag='halo', mode=None):
assert object_typetag=='halo'
return DummyTimestepData("Test string - this would contain the data for %s halo %d"%(ts_extension ,halo_number),
return DummyTimestepData("Test string - this would contain the data for %s halo %d"%(ts_extension ,finder_id),
float(self._get_ts_property(ts_extension, 'time')),
int(self._get_ts_property(ts_extension, 'halos')),
halo_number)
catalog_index)

def _get_ts_property(self, ts_extension, property):
ts_filename = self._extension_to_filename(ts_extension)
Expand All @@ -92,4 +92,4 @@ def enumerate_objects(self, ts_extension, object_typetag='halo', min_halo_partic
nhalos_string = self._get_ts_property(ts_extension, object_typetag+"s")
nhalos = 0 if nhalos_string is None else int(nhalos_string)
for i in range(nhalos):
yield i+1, 2000+i, 0, 0
yield i+1, i+1, 2000+i, 0, 0
20 changes: 10 additions & 10 deletions tangos/input_handlers/pynbody.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,28 +103,28 @@ def load_region(self, ts_extension, region_specification, mode=None):
else:
raise NotImplementedError("Load mode %r is not implemented"%mode)

def load_object(self, ts_extension, halo_number, object_typetag='halo', mode=None):
def load_object(self, ts_extension, finder_id, catalog_index, object_typetag='halo', mode=None):
if mode=='partial':
h = self._construct_halo_cat(ts_extension, object_typetag)
h_file = h.load_copy(halo_number)
h_file = h.load_copy(catalog_index)
h_file.physical_units()
return h_file
elif mode=='server':
timestep = self.load_timestep(ts_extension, mode)
from ..parallel_tasks import pynbody_server as ps
return timestep.get_view(ps.ObjectSpecification(halo_number, object_typetag))
return timestep.get_view(ps.ObjectSpecification(finder_id, catalog_index, object_typetag))
elif mode=='server-partial':
timestep = self.load_timestep(ts_extension, mode)
from ..parallel_tasks import pynbody_server as ps
view = timestep.get_view(ps.ObjectSpecification(halo_number, object_typetag))
view = timestep.get_view(ps.ObjectSpecification(finder_id, catalog_index, object_typetag))
load_index = view['remote-index-list']
logger.info("Partial load %r, taking %d particles", ts_extension, len(load_index))
f = pynbody.load(self._extension_to_filename(ts_extension), take=load_index)
f.physical_units()
return f
elif mode is None:
h = self._construct_halo_cat(ts_extension, object_typetag)
return h[halo_number]
return h[catalog_index]
else:
raise NotImplementedError("Load mode %r is not implemented"%mode)

Expand Down Expand Up @@ -236,8 +236,8 @@ def enumerate_objects(self, ts_extension, object_typetag="halo", min_halo_partic
for i in range(istart, len(h)+istart):
try:
hi = h[i]
if len(hi.dm) > min_halo_particles:
yield i, len(hi.dm), len(hi.star), len(hi.gas)
if len(hi.dm)+len(hi.star)+len(hi.gas) > min_halo_particles:
yield i, i, len(hi.dm), len(hi.star), len(hi.gas)
except (ValueError, KeyError) as e:
pass

Expand Down Expand Up @@ -335,12 +335,12 @@ def _is_able_to_load(self, filepath):
except (IOError, RuntimeError):
return False

def load_object(self, ts_extension, halo_number, object_typetag='halo', mode=None):
def load_object(self, ts_extension, finder_id, catalog_index, object_typetag='halo', mode=None):
if mode=='subfind_properties':
h = self._construct_halo_cat(ts_extension, object_typetag)
return h.get_halo_properties(halo_number,with_unit=False)
return h.get_halo_properties(catalog_index,with_unit=False)
else:
return super(GadgetSubfindInputHandler, self).load_object(ts_extension, halo_number, object_typetag, mode)
return super(GadgetSubfindInputHandler, self).load_object(ts_extension, finder_id, catalog_index, object_typetag, mode)

def _construct_group_cat(self, ts_extension):
f = self.load_timestep(ts_extension)
Expand Down
12 changes: 6 additions & 6 deletions tangos/input_handlers/yt.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ def load_timestep_without_caching(self, ts_extension, mode=None):
f = yt.load(self._extension_to_filename(ts_extension))
return f

def load_object(self, ts_extension, object_number, object_typetag='halo', mode=None):
def load_object(self, ts_extension, finder_id, catalog_index, object_typetag='halo', mode=None):
f = self.load_timestep(ts_extension, mode)
cat, cat_dat = self._load_halo_cat(ts_extension, object_typetag)
center = cat_dat["halos","particle_position"][object_number]
center = cat_dat["halos","particle_position"][catalog_index]
center+=f.domain_left_edge-cat.domain_left_edge
radius = cat_dat["halos","virial_radius"][object_number]
radius = cat_dat["halos","virial_radius"][catalog_index]
return f.sphere(center.in_cgs(), radius.in_cgs())


Expand All @@ -60,12 +60,12 @@ def enumerate_objects(self, ts_extension, object_typetag="halo", min_halo_partic
num_objects = len(catalogue_data["halos", "virial_radius"])

for i in range(num_objects):
obj = self.load_object(ts_extension, i, object_typetag)
obj = self.load_object(ts_extension, i, i, object_typetag)
NDM = len(obj["DarkMatter","Mass"])
NGas = len(obj["Gas","Mass"])
NStar = len(obj["Stars","Mass"])
if NDM > min_halo_particles:
yield i, NDM, NStar, NGas
if NDM + NGas + NStar> min_halo_particles:
yield i, i, NDM, NStar, NGas


def _load_halo_cat(self, ts_extension, object_typetag):
Expand Down
Loading