===========
Simulations
===========

The `pymad8.Sim` module provides various simulation utilities

Simulation features
-------------------

* Particle tracking using Mad8 rmat files

Tracking
--------

There is two tracking related classes in this module : `Track_Collection` and `Tracking`.
These classes features are the following :

* Set the different particles we want to track
* Write the track collection as Mad8 or Bdsim inputs
* Set the different sampler at which we want to observe the particles
* Run the tracking using Rmatrices generated by Mad8
* Plot various results such as trajectory, phase space ...
* Load tracking data generated by BDSIM and compare with pymad8 trajectory

Building tracking classes
*************************

A collection of tracks can by setup by constructing a Track_Collection instance for a given reference energy in GeV : ::

  track_collection = pymad8.Sim.Track_Collection(E_0)

At first there is no tracks in the collection. We can add each individual track by giving the starting position, angle, and energy difference with respect to the reference : ::

  track_collection.AddTrack(x, xp, y, yp, z, DE)

The Tracking instance is generated from Mad8 twiss and rmat files : ::

  tracking = pymad8.Sim.Tracking('twiss_tape', 'rmat_tape')

Then we can add the samplers at which we want to observe the particles.
Multiples samplers can be added at once and we can either find them by index, name or type: ::

  tracking.AddSampler(10)                       # Add element with index 10 as sampler
  tracking.AddSampler('INITIAL', select='name') # Add element named 'INITIAL' as sampler
  tracking.AddSampler('QUAD', select='type')    # Add all quadrupoles as samplers

Write track collection
**********************

In order to run other tracking codes with the same initial particles, we can write the track collection into text files that can be input for Mad8 or for Bdsim : ::

  track_collection.WriteMad8Track(mad8outputfile)
  track_collection.WriteBdsimTrack(bdsimoutputfile)
  
Run tracking
************

Now that we have both Track_Collection and Tracking instances we can run the pymad8 tracking : ::

  tracking.RunPymad8Tracking(track_collection)

In case we have a circulare maching and we want the tracking data after a certain number of turn one can do : ::

  tracking.RunPymad8Tracking(track_collection, turns=nb_turns)

The calculated data is then shaped as a pandas DataFrame and stored in **pymad8_df**

Plotting
********

After runing the tracking function. One can use the plotting function avaliable to show the trajectory, phase space, correlation and profile histograms : ::

  tracking.PlotTrajectory(5, 'X')                     # Trajectory of the 5th particle in X
  tracking.PlotPhaseSpace(50, 'X')                    # Phase space in X at 50m 
  tracking.PlotCorrelation(50, 'X', ref_sampler='IP') # Correlation in X at 50m w.r.t sampler named 'IP'
  tracking.PlotHist(50, 'X')                          # Beam profile in X at 50m

Loading external tracking data
******************************

One can use the Tracking instance to load a BDSIM root file and store the tracking data in a similar way as **pymad8_df** : ::

  tracking.LoadBdsimTrack(rootfile)

The data is then stored in **bdsim_df** and can then be use to plot trajectory comparison between pymad8 and BDSIM.

.. note:: Make sure to use the same initial particles using the `WriteBdsimTrack` function
