# Baggianalysis

Baggianalysis is a library aimed at simplifying the analysis of particle-based simulations. It makes it easy to parse, convert and analyse trajectories generated by simulation codes in an agnostic way. It is written in C++ and provides Python bindings. It is modular and can be extended from C++ and Python.

## A simple example

The following code imports the `baggianalysis` module, parses a single LAMMPS data file, initialises its topology and perform some computations:

	import baggianalysis as ba
	import numpy as np
	import sys
	
	if len(sys.argv) < 2:
	    print("Usage is %s data_file" % sys.argv[0])
	    exit(1)
	
	# initialise a parser for LAMMPS data files with atom_style "bond"
	parser = ba.LAMMPSDataFileParser("bond")
	# parse the system
	system = parser.make_system(sys.argv[1])
	# initialise the topology from the same file
	topology = ba.Topology.make_topology_from_file(sys.argv[1], ba.parse_LAMMPS_topology)
	# apply the topology to the system
	topology.apply(system)
	
	print("Number of molecules: %d" % len(system.molecules()))
	# compute the centres of mass of all the molecules and store them in a list 
	coms = list(map(lambda mol: mol.com(), system.molecules()))
	# print the centres of mass to the "coms.dat" file
	np.savetxt("coms.dat", coms)
	
The library makes it straightforward to work with whole trajectories. Here is an example where we compute the centre of mass of the first molecule of the system averaged over a whole trajectory:

	import baggianalysis as ba
	import numpy as np
	import sys
	
	if len(sys.argv) < 3:
	    print("Usage is %s topology_file dir" % sys.argv[0])
	    exit(1)
		
	parser = ba.LAMMPSDataFileParser("bond")
	trajectory = ba.FullTrajectory(parser)
	# the first parameter is the directory where the trajectory is stored
	# the second parameter is the pattern that will be used to match the filenames
	# the third parameter is True if we want to sort the files, False otherwise 
	trajectory.initialise_from_folder(sys.argv[2], "no_*", True)
	topology = ba.Topology.make_topology_from_file(sys.argv[1], ba.parse_LAMMPS_topology)
	
	com = np.array([0., 0., 0.])
	for system in trajectory.frames:
	    topology.apply(system)
	    com += system.molecules()[0].com()
	    
	print("The average COM is: %lf %lf %lf" % tuple(com / len(trajectory.frames)))
	
Note that baggianalysis provides a [LazyTrajectory](core/trajectories.html#baggianalysis.core.LazyTrajectory) class that parses files one by one to avoid taking up too much memory. This can be useful when dealing with very large trajectories.

## Main classes

* Simulation snapshots are stored in [System](core/particles.html#baggianalysis.core.System) objects that have several attributes that allow to retrieve the properties of the particles it contains. 
* Each particle is an instance of the [Particle](core/particles.html#baggianalysis.core.Particle) class.
* The [Topology](core/topology.html#baggianalysis.core.Topology) class can be used to manage the topology of a configuration. Topologies can be initialised in two ways:
	* by hand, using the [make_empty_topology()](core/topology.html#baggianalysis.core.Topology.make_empty_topology) static method to create a new topology and then adding bonds one after the other with the [add_bond(p_index, q_index)](core/topology.html#baggianalysis.core.Topology.add_bond) method
	* by using an helper function to parse the topology out of a file through the [make_topology_from_file()](core/topology.html#baggianalysis.core.Topology.make_topology_from_file) static method. Baggianalysis comes with some [ready-made](core/topology.md) functions that can be used to parse topologies.
	
## Library API

```eval_rst
.. toctree::
   :maxdepth: 2
   
   core/core.md
```

## Extending baggianalysis

```eval_rst
.. toctree::
   :maxdepth: 2
   
   extending/parser.md
   extending/topology.md
```
