Setting a format file ********************** .. currentmodule:: pNbody.main In **pNbody**, defining a new format correspond to adding new methods in the main class :class:`NbodyDefault`. This means, writing a new class called ``Nbody_yourformat`` where ``yourformat`` is a string you choos giving the name of your new format. In practice, you need to create a file called:: $HOME/.pNbody/formats/yourformat.py The latter file must describe a new class derived from the main class :class:`NbodyDefault`. Lets look at the first lines of the ``Nbody_default`` class, used when no format is specified. If you have used the:: pNbody_ pNbody_copy-defaultconfig script, you will naturally find this file here:: $HOME/.pNbody/formats/default.py The class is described with the following lines:: class Nbody_default(NbodyDefault): """ This class is usefull to create an empty Nbody object """ The :func:`NbodyDefault.get_read_fcts` and :func:`NbodyDefault.get_write_fcts` methods ====================================================================================== Then you need to redfined important methods. Fist, start with the :func:`NbodyDefault.get_read_fcts` and :func:`NbodyDefault.get_write_fcts` ones. The role of these methods is to return the methods responsible of the reading/writing of your format. Several routines can be used. By default, these two methods return an empty list. Secondly, you need of course to defined these methods. In the ``Nbody_default`` class this is done with the following lines:: def get_read_fcts(self): """ returns the functions needed to read a file. """ return [self.read_particles] def get_write_fcts(self): """ returns the functions needed to write a file. """ return [self.write_particles] The methods ``self.read_particles`` and ``self.write_particles`` will be the core the the io. And you will obviously need to define it. In ``Nbody_default`` class these methods does simply nothing and are defined as follows:: def read_particles(self,f): """ Function that read particles. """ pass def write_particles(self,f): """ Function that write particles. """ pass Note that the methods must have as an argument the pointer ``f`` corresponding to the already opend file. Opening the file is done automatically by **pNbody** and you do not need to do it. A very simple example : an ascii format --------------------------------------- You can easilly read and write ascii files containing the positions, velocities and mass of particles, defining the following methods:: def read_particles(self,f): """ Function that read particles. """ from pNbody import io x,y,z,vx,vy,vz,m=io.read_ascii(f,range(7)) self.pos = transpose(array([x,y,z])).astype(float32) self.vel = transpose(array([vx,vy,vz])).astype(float32) self.mass = m.astype(float32) def write_particles(self,f): """ Function that write particles. """ for i in range(self.nbody): line = "%g %g %g %g %g %g %g \n" %(self.pos[i][0],self.pos[i][1],self.pos[i][2],self.vel[i][0],self.vel[i][1],self.vel[i][2],self.mass[i]) f.write(line) Note that way of doing things works but is not recomanded from a performace point of view. Of course, in this form, the format will not allows parallel io. You will have to work a littre bit more to do it. Let's try to use this new format. We assume here that you are in the ``$HOME/pnbody_examples`` directory. First we convert a ``gadget`` binary file to an ascii ``file``:: >>> from pNbody import * >>> nb = Nbody('gadget.dat',ftype='gadget') >>> nb = nb.set_ftype('ascii') >>> nb.get_ftype() >>> nb.get_ftype() 'Nbody_ascii' >>> nb.get_format_file() '/home/leo/.pNbody/formats/gadget.py' The last lines are simply used to check that everything works fine Now simply rename and save the file:: >>> nb.rename('ascii.dat') >>> nb.write() Out of the python interpreter, you can check the content of the file:: $ head ascii.dat -7.77545 6.07969 0.0733488 0 0 0 6.10352e-05 3.92681 11.4814 0.327888 0 0 0 6.10352e-05 -2.93326 -1.03464 0.221822 0 0 0 6.10352e-05 -3.81556 -0.322033 0.0146847 0 0 0 6.10352e-05 -1.3225 -6.34532 0.586419 0 0 0 6.10352e-05 0.0257911 0.576679 0.595826 0 0 0 6.10352e-05 -1.71236 1.22864 -0.61255 0 0 0 6.10352e-05 -2.6153 -0.21298 0.0526232 0 0 0 6.10352e-05 -2.1161 -2.47928 -0.193715 0 0 0 6.10352e-05 -4.33257 15.8307 0.0778809 0 0 0 6.10352e-05 Now, open it and display to check:: >>> from pNbody import * >>> nb = Nbody('ascii.dat',ftype='ascii') >>> nb.display(size=(30,30)) And you should see an edge-on disk. Some info on our ascii object ============================= When creating an object, it is possible to check the the file that defines it format, using: To list the content of the variables of an object:: >>> nb.get_list_of_vars() ['Density', 'DesNumNgb', 'Hsml', 'MaxNumNgbDeviation', 'Tree', '__doc__', '__module__', '_formatfile', 'byteorder', 'defaultparameters', 'ftype', 'localsystem_of_units', 'log', 'mass_tot', 'nbody', 'nbody_tot', 'npart', 'npart_tot', 'p_name', 'p_name_global', 'parameters', 'pio', 'spec_vars', 'spec_vect', 'status', 'unitsfile', 'unitsparameters'] >>> nb.get_list_of_array() ['mass', 'num', 'pos', 'tpe', 'vel'] >>> nb.get_list_of_method() ['A', 'Accel', 'CombiHisto' ... 'zmodes', 'zprof'] >>> nb.get_default_spec_vars() {} >>> nb.get_default_spec_array() {} 'Density', 'DesNumNgb', 'Hsml', 'MaxNumNgbDeviation', 'Tree' Other important methods ======================= def get_default_spec_vars(self): """ Specific variables to this format """ return {} def get_default_spec_array(self): """ return specific array default values for the class """ return {} Thanks to the magic of the Python interpreted language, creating a new class derived from the main class :class:`NbodyDefault` presents the excellent advantage of letting the opportunity to the user to add new methods (not related to the reading of writing of the format), dedicated to its new and private format, without modifying the **pNbody** source. It is possible to list all know formats:: >>> from pNbody import main >>> main.get_known_formats() >>> main.get_known_formats() ['Nbody_binary', 'Nbody_bnbf', 'Nbody_default', 'Nbody_gadget', 'Nbody_simpleformat', 'Nbody_tipsy', 'Nbody_tipsybig'] The most simple **pNbody** object is created with the:: >>> from pNbody import * >>> nb = Nbody() To check the format:: >>> nb.ftype 'Nbody_default' To give the directory where format files are read:: >>> FORMATSDIR '/home/leo/.pNbody/formats' To get the format file used:: >>> from pNbody import * >>> nb = Nbody() >>> nb.get_format_file() '/home/leo/.pNbody/formats/default.py' To list the