diff --git a/doc/source/pythonmodule.rst b/doc/source/pythonmodule.rst index 2c27e20..58a309e 100644 --- a/doc/source/pythonmodule.rst +++ b/doc/source/pythonmodule.rst @@ -1,6 +1,38 @@ The CosmoToolbox python module ============================== -.. automodule:: cosmotool - :members: loadRamses, loadRamsesAll +.. module:: cosmotool + +Simulation handling +^^^^^^^^^^^^^^^^^^^ + +The simulation data +------------------- + +.. autoclass:: PySimulationBase + :members: + +.. autoclass:: SimulationBare + :members: + +.. autoclass:: Simulation + :members: + +.. autoclass:: PySimulationAdaptor + :members: + +The simulation loaders +---------------------- + +.. autofunction:: loadRamses +.. autofunction:: loadRamsesAll +.. autofunction:: loadGadget +.. autofunction:: loadParallelGadget + +Timing +------ + +.. autofunction:: time_block +.. autofunction:: timeit +.. autofunction:: timeit_quiet diff --git a/python/_cosmotool.pyx b/python/_cosmotool.pyx index 7f26a1d..f6dce91 100644 --- a/python/_cosmotool.pyx +++ b/python/_cosmotool.pyx @@ -49,106 +49,197 @@ cdef extern from "loadRamses.hpp" namespace "CosmoTool": class PySimulationBase(object): + """ + This is the base class to representation Simulation in CosmoTool/python. + """ + def getPositions(self): + """ + getPositions(self) + + Returns: + A list of three arrays holding the positions of the particles. + The i-th element is the i-th coordinate of each particle. + It may be None if the positions were not requested. + """ raise NotImplementedError("getPositions is not implemented") def getVelocities(self): + """ + getVelocities(self) + + Returns: + A list of three arrays holding the velocities of the particles. + The i-th element is the i-th coordinate of each particle. + It may be None if the velocities were not requested. + """ raise NotImplementedError("getVelocities is not implemented") def getIdentifiers(self): + """ + getIdentifiers(self) + + Returns: + Returns an integer array that hold the unique identifiers of + each particle. + It may be None if the identifiers were not requested. + """ raise NotImplementedError("getIdentifiers is not implemented") def getTypes(self): + """ + getTypes(self) + + Returns: + Returns an integer array that hold the type of + each particle. + It may be None if the types were not requested. + """ raise NotImplementedError("getTypes is not implemented") def getOmega_M(self): + """ + getOmega_M(self) + + Returns: + the mean matter density in the simulation, with respect + to the critical density. + """ raise NotImplementedError("getOmega_M is not implemented") def getOmega_Lambda(self): + """ + getOmega_Lambda(self) + + Returns: + the mean dark energy density in the simulation, with respect + to the critical density. + """ raise NotImplementedError("getOmega_Lambda is not implemented") def getTime(self): + """ + getTime(self) + + Returns: + the time the snapshot was taken in the simulation. It can + have various units depending on the file format. + """ raise NotImplementedError("getTime is not implemented") def getHubble(self): + """ + getHubble(self) + + Returns: + the hubble constant in unit of 100 km/s/Mpc + """ raise NotImplementedError("getHubble is not implemented") def getBoxsize(self): + """ + getBoxsize(self) + + Returns: + the size of the simulation box. The length unit is not fixed, + though it is customary to have it in Mpc/h if the loader has + access to the unit normalization. + """ raise NotImplementedError("getBoxsize is not implemented") def getMasses(self): + """ + getMasses(self) + + Returns: + an array with the masses of each particles, in unspecified unit that + depend on the loader. + """ raise NotImplementedError("getMasses is not implemented") cdef class Simulation: + """ + Simulation() + + Class that directly manages internal loaded data obtained from a loader + """ - cdef list positions - cdef list velocities - cdef object identifiers - cdef object types - cdef object masses + cdef list positions + cdef list velocities + cdef object identifiers + cdef object types + cdef object masses - cdef SimuData *data + cdef SimuData *data - property BoxSize: - def __get__(Simulation self): - return self.data.BoxSize + property BoxSize: + def __get__(Simulation self): + return self.data.BoxSize - property time: - def __get__(Simulation self): - return self.data.time + property time: + def __get__(Simulation self): + return self.data.time - property Hubble: - def __get__(Simulation self): - return self.data.Hubble + property Hubble: + def __get__(Simulation self): + return self.data.Hubble - property Omega_M: - def __get__(Simulation self): - return self.data.Omega_M + property Omega_M: + def __get__(Simulation self): + return self.data.Omega_M - property Omega_Lambda: - def __get__(Simulation self): - return self.data.Omega_Lambda + property Omega_Lambda: + def __get__(Simulation self): + return self.data.Omega_Lambda - property positions: - def __get__(Simulation self): - return self.positions + property positions: + def __get__(Simulation self): + return self.positions - property velocities: - def __get__(Simulation self): - return self.velocities + property velocities: + def __get__(Simulation self): + return self.velocities - property identifiers: - def __get__(Simulation self): - return self.identifiers + property identifiers: + def __get__(Simulation self): + return self.identifiers - property types: - def __get__(Simulation self): - return self.types + property types: + def __get__(Simulation self): + return self.types - property masses: - def __get__(Simulation self): - return self.masses + property masses: + def __get__(Simulation self): + return self.masses - property numParticles: - def __get__(Simulation self): - return self.data.NumPart + property numParticles: + def __get__(Simulation self): + return self.data.NumPart - property totalNumParticles: - def __get__(Simulation self): - return self.data.TotalNumPart + property totalNumParticles: + def __get__(Simulation self): + return self.data.TotalNumPart - def __cinit__(Simulation self): - self.data = 0 + def __cinit__(Simulation self): + self.data = 0 - def __dealloc__(Simulation self): - if self.data != 0: - print("Clearing simulation data") - del self.data + def __dealloc__(Simulation self): + if self.data != 0: + print("Clearing simulation data") + del self.data -class _PySimulationAdaptor(PySimulationBase): - +class PySimulationAdaptor(PySimulationBase): + """ + PySimulationAdaptor(PySimulationBase_) + + This class is an adaptor for an internal type to the loader. It defines + all the methods of PySimulationBase. + + Attributes: + simu: a Simulation_ object + """ def __init__(self,sim): self.simu = sim @@ -189,18 +280,13 @@ cdef class ArrayWrapper: cdef set_data(self, np.uint64_t size, int type_array, void* data_ptr): """ Set the data of the array + This cannot be done in the constructor as it must recieve C-level + arguments. -This cannot be done in the constructor as it must recieve C-level -arguments. - -Parameters: ------------ -size: int -Length of the array. -data_ptr: void* -Pointer to the data - - """ + Args: + size (int): Length of the array. + data_ptr (void*): Pointer to the data + """ self.data_ptr = data_ptr self.size = size self.type_array = type_array @@ -275,46 +361,66 @@ cdef object wrap_simudata(SimuData *data, int flags): return simu def loadGadget(str filename, int snapshot_id, bool loadPosition = True, bool loadVelocity = False, bool loadId = False, bool loadType = False, bool loadMass=False): - """loadGadget(filename, cpu_id, loadPosition=True, loadVelocity=False, loadId=False, loadType=False) -It loads a gadget-1 snapshot and return a PySimulationBase object. If cpu_id is negative then the snapshot is considered not to be part of a set of snapshots written by different cpu. Otherwise the filename is modified to reflectt this cpu_id. + """loadGadget(filename, snapshot_id, loadPosition=True, loadVelocity=False, loadId=False, loadType=False) + + This function loads Gadget-1 snapshot format. + + If snapshot_id is negative then the snapshot is considered not to be part of + a set of snapshots written by different cpu. Otherwise the filename is modified + to reflect the indicated snapshot_id. + + Arguments: + filename (str): input filename + snapshot_id (int): identifier of the gadget file if it is a multi-file snapshot + + Keyword arguments: + loadPosition (bool): whether to load positions + loadVelocity (bool): whether to load velocities + loadId (bool): whether to load unique identifiers + loadType (bool): whether to set types to particles + loadMass (bool): whether to set the mass of particles + + Returns: + an PySimulationAdaptor instance. """ - cdef int flags - cdef SimuData *data - cdef Simulation simu + cdef int flags + cdef SimuData *data + cdef Simulation simu - flags = 0 - if loadPosition: - flags |= NEED_POSITION - if loadVelocity: - flags |= NEED_VELOCITY - if loadId: - flags |= NEED_GADGET_ID - if loadType: - flags |= NEED_TYPE - if loadMass: - flags |= NEED_MASS + flags = 0 + if loadPosition: + flags |= NEED_POSITION + if loadVelocity: + flags |= NEED_VELOCITY + if loadId: + flags |= NEED_GADGET_ID + if loadType: + flags |= NEED_TYPE + if loadMass: + flags |= NEED_MASS - data = loadGadgetMulti(filename, snapshot_id, flags) - if data == 0: - return None + data = loadGadgetMulti(filename, snapshot_id, flags) + if data == 0: + return None - return _PySimulationAdaptor(wrap_simudata(data, flags)) + return PySimulationAdaptor(wrap_simudata(data, flags)) def loadParallelGadget(object filename_list, bool loadPosition = True, bool loadVelocity = False, bool loadId = False, bool loadType = False, bool loadMass=False): - """loadGadget(filename list, loadPosition=True, loadVelocity=False, loadId=False, loadType=False) + """loadParallelGadget(filename list, loadPosition=True, loadVelocity=False, loadId=False, loadType=False) Arguments: - - filename list: a list or tuple of filenames to load in parallel + filename (list): a list or tuple of filenames to load in parallel - Keywords: - - loadPosition: indicate to load positions - - loadVelocity: indicate to load velocities - - loadId: indicate to load id - - loadType: indicate to load particle types + Keyword arguments: + loadPosition (bool): indicate to load positions + loadVelocity (bool): indicate to load velocities + loadId (bool): indicate to load id + loadType (bool): indicate to load particle types -It loads a gadget-1 snapshot and return a PySimulationBase object. -""" + Returns: + It loads a gadget-1 snapshot and return a cosmotool.PySimulationBase_ object. + """ cdef int flags, i, num_files cdef list out_arrays cdef SimuData ** data @@ -351,14 +457,22 @@ It loads a gadget-1 snapshot and return a PySimulationBase object. if data[i] == 0: out_arrays.append(None) else: - out_arrays.append(_PySimulationAdaptor(wrap_simudata(data[i], flags))) + out_arrays.append(PySimulationAdaptor(wrap_simudata(data[i], flags))) del_simudata(data) return out_arrays def writeGadget(str filename, object simulation): - + """writeGadget(filename, simulation) + + This function attempts to write the content of the simulation object into + a file named `filename` using a Gadget-1 file format. + + Arguments: + filename (str): output filename + simulation (PySimulationBase): a simulation object + """ cdef SimuData simdata cdef np.ndarray[np.float32_t, ndim=1] pos, vel cdef np.ndarray[np.int64_t, ndim=1] ids @@ -408,7 +522,7 @@ def loadRamses(str basepath, int snapshot_id, int cpu_id, bool doublePrecision = loadVelocity (bool): Whether to load velocities Returns: - An object derived from PySimulationBase. + An object derived from PySimulationBase_. """ cdef int flags cdef SimuData *data @@ -424,5 +538,5 @@ def loadRamses(str basepath, int snapshot_id, int cpu_id, bool doublePrecision = if data == 0: return None - return _PySimulationAdaptor(wrap_simudata(data, flags)) + return PySimulationAdaptor(wrap_simudata(data, flags)) diff --git a/python/cosmotool/timing.py b/python/cosmotool/timing.py index ce56217..c6977f1 100644 --- a/python/cosmotool/timing.py +++ b/python/cosmotool/timing.py @@ -3,35 +3,50 @@ from contextlib import contextmanager @contextmanager def time_block(name): + """ + This generator measure the time taken by a step, and prints the result + in second to the console. + + Arguments: + name (str): prefix to print + """ ts = time.time() yield te = time.time() - print '%s %2.2f sec' % \ - (name, te-ts) + print ('%s %2.2f sec' % (name, te-ts)) def timeit(method): + """This decorator add a timing request for each call to the decorated function. + + Arguments: + method (function): the method to decorate + """ def timed(*args, **kw): ts = time.time() result = method(*args, **kw) te = time.time() - print '%r (%r, %r) %2.2f sec' % \ - (method.__name__, args, kw, te-ts) + print ('%r (%r, %r) %2.2f sec' % (method.__name__, args, kw, te-ts)) return result return timed def timeit_quiet(method): + """This decorator add a timing request for each call to the decorated function. + Same as cosmotool.timeit_ but is quieter by not printing the values of the arguments. + + Arguments: + method (function): the method to decorate + """ def timed(*args, **kw): ts = time.time() result = method(*args, **kw) te = time.time() - print '%r %2.2f sec' % \ - (method.__name__, te-ts) + print ('%r %2.2f sec' % (method.__name__, te-ts)) return result return timed