Before thinking about the reader implementation, lets start by imagining the kind of API we would like to provide to users.
with logger.Reader(basename) as f: # Create a logger.ParticleSet of the particles we want to track. # This function loops over all the index files and get all the particles # contain cache for the particle set (for later) particle_set = f.get_particles(type="Gas", cache=True) particle_set -= f.get_particles(ids=[...]) # remove the use of the cache particle_set.cache_enabled(False) # Read some fields for some particles. This generates a new ParticleSet that # contains the particles from `particle_set` that exist at time `time`, and # populates their position and velocities. particles_at_time_t = f.get_particle_data( particles=particle_set, fields=["Coordinates", "Velocities"], time=time, interpolation="linear") # Extract the particle positions as an Nx3 matrix. positions = particles_at_time_t["Coordinates"] # Move a set of particles forward in time. # here we should be fast thanks to the cache. particles_at_time_t_plus_one = f.get_particle_data( particles=particles_at_time_t, fields=["Coordinates"], time=time + 1) # here we close the logfile and cleanup everything
The main class here is
logger.Reader, which manages the log and index files in the directory
logger.ParticleSet is an abstraction for a set of particles from a
Reader. Like regular sets, we can add, subtract, and intersect
Reader.get_particle_data extracts data for a set of particles at a given time.