Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Here's one comparison of an example analysis in three different frameworks:

  • myana (online C++ framework),

...

  • using ROOT histogramming package
  • psana (offline

...

  • C++ framework)

...

  • , using ROOT histogramming package
  • pyana (offline python framework)
    • using ROOT histogramming package
    • alternative without ROOT, using NumPy to store arrays and MatPlotLib to plot those arrays/

C++ framework). They all make histograms/plots of AMO ITof wavefunctions, in 20 energy bins (energy measured by FEE Gas Detector). All make histograms using ROOT, the plotting of histograms done in a separate macro. Additionally, another example using pyana, where MatPlotLib is used instead of ROOT to produce the histogram. MatPlotLib does the plotting directly from NumPy arrays, and for comparison purposes, this code snippet stores numpy arrays to hdf5 files.

Composition Setup
cloak.memory.duration = 0
cloak.toggle.type = default
Deck of Cards
idCode Snippets
Card
labelmyana with ROOT
Code Block
title"myana_esort.cc"
#include <TROOT.h>
#include <TH1F.h>
#include <TProfile.h>
#include <time.h>

#include "myana.hh"
#include "main.hh"

static int                  numChannelsITof;
static int                  numSamplesITof;
static double               sampleIntervalITof;

static const int            maxITofBin = 50;
static TProfile*            profWf[maxITofBin];
static TProfile*            profWfAll;
static TH1F*                histEnrg;
static TH1I*                histBin;

static unsigned int         shotCountITof = 0;

float  e1,e2;
int nenergy;
static int bin;
//double* weights;

clock_t start_time;
clock_t finish_time;

const char* ParameterFileName = "ParameterFileName";

FILE *LaserParamOut;
FILE *ShotsOut;
char ShotsName[200];

using namespace Pds;

// This function is called once at the beginning of the analysis job,
// You can ask for detector "configuration" information here.

void beginjob() {

  // get ITof parameters from myana.inp
  const char inpname[20]="myana.inp";
  FILE *inpfile;
  inpfile=fopen(inpname,"r");
  fscanf(inpfile,"%d\n",&nenergy); // nbins of histogram
  fscanf(inpfile,"%f\n",&e1); // xmin of histogram
  fscanf(inpfile,"%f\n",&e2); // xmax of histogram
  printf("%d %e %e\n",nenergy,e1,e2);
  fclose(inpfile);

  printf("calling beginjob()\n"); fflush(stdout);

  int i;
  int fail = 0;


  /*
   * Processing ITof Config Data
   */
  fail = getAcqConfig( AmoITof, numChannelsITof, numSamplesITof, sampleIntervalITof);

//   // this is needed for TProfile::FillN routine
//   double weightsarray[numSamplesITof];
//   for (int i=0;i<numSamplesITof;i++){
//     weightsarray[i] = 1.000000;
//   }
//   weights = &weightsarray[0];

  // create an "averaging" histogram (called "profile")
  profWfAll = new TProfile("profWfAll","Average Waveform;Seconds;Volts"
                           , numSamplesITof
                           , 0.0,sampleIntervalITof,"");
  char name[32];
  char title[232];
  for (i=0;i<nenergy;i=i+1) {
    sprintf(name,"profWf%d",i);
    sprintf(title,"Average Waveform in Energy bin %d",i);
    profWf[i] = new TProfile(name,title,numSamplesITof,
                             0.0,sampleIntervalITof,"");
    profWf[i]->SetYTitle("Volts");    //optional
    profWf[i]->SetXTitle("Seconds");  //optional
  }

  // create a histogram to display the energy bins
  histEnrg = new TH1F("histEnrg","Energy bins;Energy; Event Count",nenergy,e1,e2);
  histBin = new TH1I("histBin","Energy bins;Bin; Event Count",nenergy,0.0,nenergy);
  histEnrg->SetMarkerStyle(4); histEnrg->SetMarkerColor(4); // blue circles
  histBin->SetMarkerStyle(4);  histBin->SetMarkerColor(4); // blue circles
}

// This function is called once for each run.  You should check to see
// if detector configuration information has changed.

void beginrun()
{
  printf("beginrun is done, starting timer...");
  start_time = clock();
}

void begincalib()
{
}

// This is called once every shot.  You can ask for
// the individual detector shot data here.

void event()
{
  int fail;
  /*
   * Processing FeeGasDet Value
   */
  double shotEnergy[4];
  fail = getFeeGasDet( shotEnergy );
  double energy = (shotEnergy[2]+shotEnergy[3])/2;
  if ( energy < e1 ) {
    histEnrg->Fill(e1);
  } else if ( energy > e2 ) {
    histEnrg->Fill(e2);
  } else {
    histEnrg->Fill(energy);
  }

  /*
   * Processing ITof waveform
   */
  double* timeITof;
  double* voltageITof;
  int channel = 0;
  fail = getAcqValue( AmoITof, channel, timeITof, voltageITof);
  if ( fail != 0 )
    printf( "event(): getAcqValue() failed, code = %d\n", fail );
  else
  {
    bin = int(( (energy-e1)/(e2-e1) )*nenergy+0.5);
    if (bin<1) bin=0;
    if (bin>nenergy-1) bin=int(nenergy-1);
    for (int i=0;i<numSamplesITof;i=i+1)
      {
        double t = timeITof[i];
        double v = voltageITof[i];
        profWf[bin]->Fill(t,v);

        profWfAll->Fill(t,v);
      }
    //profWfAllhistBin->FillN( int(numSamplesITof), timeITof, voltageITof, weights, 1);
    histBin->Fill(bin);
    shotCountITof>Fill(bin);
    shotCountITof++;
  }

}

void endcalib()
{
}


void endrun()
{
  printf("User analysis endrun() routine called.\n");
}

void endjob()
{
  printf("User analysis endjob() routine called.\n");
  finish_time = clock();
  double duration = (finish_time - start_time)/CLOCKS_PER_SEC;
  printf("Time elapsed: %.2f s \n",(duration));
  printf("Number of events processed: %d \n", shotCountITof);

  printf("%d \n",profWfAll->GetNbinsX());
  for (int bin=20;bin<40;bin++){
    printf("%.10f +- %.10f \n",profWfAll->GetBinContent(bin+1),profWfAll->GetBinError(bin+1));
  }
}
Card
labelpyana psana with ROOT
Code Block
title"pyanapsana_esort_hmgr.pycpp"
import sys
import logging
import time

#------//-----------------------
#// ImportsThis for other modulesClass's Header --
#//-----------------------------
import numpy as np
import matplotlib.pyplot as plt

#-
#include "speed/psana_esort.h"

//--------------------
#  Class definition// C/C++ Headers --
#//-----------------
#include <time.h>

//---------------
class pyana_esort_hmgr (object) :
    """Class whose instance will be used as a user analysis module. """
    #----------------
// Collaborating Class  #Headers  Constructor --
    #//-------------------------------
    def __init__ ( self, nenergy, e1, e2, source = "AmoITof-0|Acqiris-0"):
        """Class constructor. The parameters to the constructor are passed
        from pyana configuration file. If parameters do not have default
        values  here then the must be defined in pyana.cfg. All parameters
        are passed as strings, convert to correct type before use.
        """
        self.source = source
        self.nebins = int(nenergy)
#include "MsgLogger/MsgLogger.h"

//--------------------------------------------------
// to work with detector data include corresponding
// header from psddl_psana package
//--------------------------------------------------
#include "psddl_psana/acqiris.ddl.h"
#include "psddl_psana/bld.ddl.h"

//-----------------------------------------------------------------------
// Local Macros, Typedefs, Structures, Unions and Forward Declarations --
//-----------------------------------------------------------------------

// This declares this class as psana module
using namespace speed;
PSANA_MODULE_FACTORY(psana_esort)

//              ----------------------------------------
//        self.emin = float(e1)
    -- Public Function Member self.emax = float(e2)

Definitions --
//        self.nev = 0

    #-------------------
    #  Public methods --
    #-------------------

namespace    def beginjob( self, evt, env ) :
        """This method is called once at the beginning of the job.
        It will also be called in any Xtc Configure transition, if
        configurations have changed since last it was run.

        @param evt    event data object
        @param env    environment object
        """

        # Preferred way to log information is via logging package
        logging.info( "pyana_esort_hmgr.beginjob() called " )

        cfg = env.getAcqConfig(self.source)
        #numChannels = cfg.nbrChannels()
        self.numSamplesITof = cfg.horiz().nbrSamples()
        sampleIntervalITof = cfg.horiz().sampInterval()
        print self.numSamplesITof
        print sampleIntervalITof

speed {

//----------------
// Constructors --
//----------------
psana_esort::psana_esort (const std::string& name)
  : Module(name)
  , m_acqSrc()
  , m_feeSrc()
  , m_maxEvents()
  , m_filter()
  , m_nenergy()
  , m_e1()
  , m_e2()
{
  // get the values from configuration or use defaults
  m_acqSrc = configStr("acqSource", "DetInfo(:Acqiris)");
  m_feeSrc = configStr("feeSource", "BldInfo(FEEGasDetEnergy)");
  m_maxEvents = config("events", 32U);
  m_filter = config("filter", false);
  m_nenergy = config("nenergy",20);
  m_e1 = config("e1",0.0);
  m_e2 = config("e2",4.0);
}

//--------------
// Destructor --
//--------------
psana_esort::~psana_esort ()
{
}

/// Method which is called once at the beginning of the job
void
psana_esort::beginJob(Env& env)
{
  m_count = 0;

  RootHistoManager::RootHMgr& rhmgr = env.rhmgr();

  shared_ptr<Psana::Acqiris::ConfigV1> acqConfig = env.configStore().get(m_acqSrc);
  if (acqConfig.get()) {
    int channel = 0;
    m_nSamples       = acqConfig->horiz().nbrSamples();
    m_sampleInterval = acqConfig->horiz().sampInterval();
    m_slope         hmgr = env.hmgracqConfig->vert(channel).slope()

;
    m_offset        self.histEnrg = hmgr.h1f("histEnrg",";Energy",self.nebins,self.emin,self.emax)acqConfig->vert(channel).offset();

    m_timevector =   self.histBin = hmgr.h1i("histBin",";Bin",self.nebins,0.0, self.nebins)new double[m_nSamples];
    m_wfvector =   self.histEnrg.SetMarkerStyle(4)new double[m_nSamples];
    m_wgvector =   self.histEnrg.SetMarkerColor(4)new double[m_nSamples];
    for    self.histBin.SetMarkerStyle(4)(int i(0);i<m_nSamples;i++){
      m_timevector[i]=  self.histBin.SetMarkerColor(4)

   i * m_sampleInterval;
      m_wfvector[i]=0.0;
     name = "profWfAll"m_wgvector[i]=1.0;
    }

    titlem_profWfAll = rhmgr.profile("profWfAll","Average Waveform;time [s];voltage [V]",
        self.prof_wfAll = hmgr.prof(name,title,self.numSamplesITof,
                            AxisDef(0.0, m_nSamples*m_sampleInterval,m_nSamples)
        0.0,
                        );

    char name[32];
    char title[232];
  self.numSamplesITof*sampleIntervalITof,
  for (int i=0; i<m_nenergy;i++){
      sprintf(name,"profWf%d",i);
      sprintf(title,"Average Waveform in Energy bin %d; time [s]; voltage [V]",i);
      m_profWf[i] = rhmgr.profile(name,  "")
title,
         self.prof_wf = []
        for bin in range (0,self.nebins):
            name = "profWf%d"%binAxisDef(0.0,m_nSamples*m_sampleInterval,m_nSamples)
            title = "Average Waveform in Energy Bin %d;time [s];voltage [V]" % bin
            self.prof_wf.append( hmgr.prof(name,title,self.numSamplesITof,);
    }
  }
  // create a histogram to display the energy bins
  m_histEnrg                         0.0,
                                           self.numSamplesITof*sampleIntervalITof,
                                           ""))


        # prof.FillN requires a weight array...
        self.wg = np.ones(self.numSamplesITof,dtype=float)
        self.ts = None

    def beginrun( self, evt, env ) :
        """This optional method is called if present at the beginning
        of the new run.

        @param evt    event data object
        @param env    environment object
        """
        logging.info( "pyana_esort_hmgr.beginrun() called ")

        print "beginrun is done, starting timer..."
        self.start = time.clock()

    def begincalibcycle( self, evt, env ) :
        """This optional method is called if present at the beginning
        of the new calibration cycle.= rhmgr.h1f("histEnrg","Energy bins;Energy; Event Count",AxisDef(m_e1,m_e2,m_nenergy));
  m_histBin = rhmgr.h1i("histBin","Energy bins;Bin; Event count",AxisDef(0.0,m_nenergy,m_nenergy));
  m_histEnrg->SetMarkerStyle(4); m_histEnrg->SetMarkerColor(4); // blue circles
  m_histBin->SetMarkerStyle(4);  m_histBin->SetMarkerColor(4); // blue circles

}


/// Method which is called at the beginning of the run
void
psana_esort::beginRun(Env& env)
{
  printf("beginRun is done, starting timer...");
  m_start_time = clock();
}

/// Method which is called at the beginning of the calibration cycle
void
psana_esort::beginCalibCycle(Env& env)
{
}

/// Method which is called with event data, this is the only required
/// method, all other methods are optional
void
psana_esort::event(Event& evt, Env& env)
{
  //MsgLog(name(),info,"Event:" << m_count);

  /*
   * Processing FeeGasDet Value
   */
  shared_ptr<Psana::Bld::BldDataFEEGasDetEnergy> fee = evt.get(m_feeSrc);
  double shotEnergy[4] = {0.,0.,0.,0.};
  if (fee.get()) {
    shotEnergy[0] = fee->f_11_ENRC();
    shotEnergy[1] = fee->f_12_ENRC();
    shotEnergy[2] = fee->f_21_ENRC();
    shotEnergy[3] = fee->f_22_ENRC();
  }
  double energy = (shotEnergy[2]+shotEnergy[3])/2;
  if ( energy < m_e1 ) {
    m_histEnrg->Fill(m_e1);
  } else if ( energy > m_e2 ) {
    m_histEnrg->Fill(m_e2);
  } else {
    m_histEnrg->Fill(energy);
  }

  /*
   * Processing ITof waveform
   */
  shared_ptr<Psana::Acqiris::DataDescV1> acqData = evt.get(m_acqSrc);
  if (acqData.get()) {

    m_count++;

    int channel = 0;
    const Psana::Acqiris::DataDescV1Elem& data = acqData->data(channel);

    // copy myana main.cc getAcqValue()
    const int16_t* wfdata = data.waveforms();
    wfdata += data.indexFirstPoint();

    shared_ptr<Psana::Acqiris::ConfigV1> acqConfig = env.configStore().get(m_acqSrc);
    if (acqConfig.get()) {

      for  @param evt(int j=0;j<m_nSamples;j++){
     event data object
        @param env m_wfvector[j] = wfdata[j] * m_slope - m_offset;
     environment object
        """}


      int numSamples logging.info( "pyana_esort_hmgr.begincalibcycle= data.nbrSegments() called ")



* data.nbrSamplesInSeg();
    def event( self, evt, env ) :
        """This method is called for every L1Accept transition.if (numSamples != m_nSamples) std::cout << "nSamples mismatch" << std::endl;

      int bin @param= evt    event data objectint(( (energy-m_e1)/(m_e2-m_e1) )*m_nenergy+0.5);
      if  @param env(bin<1) bin=0;
     environment object
  if (bin>m_nenergy-1) bin=int(m_nenergy-1);


      """m_histBin->Fill(bin);
        logging.info( "pyana_esort_hmgr.event() called ")m_profWf[bin]->FillN(numSamples,m_timevector,m_wfvector,m_wgvector,1);
        self.nev+=1

m_profWfAll->FillN(numSamples,m_timevector,m_wfvector,m_wgvector,1);
    }
  }
}

/// Method shotEnergywhich is called at the end of the calibration cycle
void
psana_esort::endCalibCycle(Env& env)
{
  delete[] m_timevector;
}

/// Method which is called at the end of the run
void
psana_esort::endRun(Env& env)
{
}

/// Method which is called once at the end of the job
void
psana_esort::endJob(Env& env)
{

  clock_t finish_time = clock();
  double duration = (finish_time - m_start_time)/CLOCKS_PER_SEC;
  printf("Time elapsed: %.2f s \n",(duration));
  printf("Number of events processed: %d \n", m_count);

  std::cout << m_profWfAll->GetNbinsX() << std::endl;
  for (int bin = 20; bin<40; bin++) {
    std::cout << m_profWfAll->GetBinContent(bin+1) << " +- " << m_profWfAll->GetBinError(bin+1) << std::endl;
  }
}

} // namespace speed

Card
labelpyana with ROOT
Code Block
title"pyana_esort_hmgr.py"

import sys
import logging
import time

#-----------------------------
# Imports for other modules --
#-----------------------------
import numpy as np
import matplotlib.pyplot as plt

#---------------------
#  Class definition --
#---------------------
class pyana_esort_hmgr (object) :
    """Class whose instance will be used as a user analysis module. """
    #----------------
    #  Constructor --
    #----------------
    def __init__ ( self, nenergy, e1, e2, source = "AmoITof-0|Acqiris-0"):= evt.getFeeGasDet()
        energy = 0.0
        bin = 0
        if shotEnergy is None :
            print "No Gas Detector"
        else :
            energy = (shotEnergy[2]+shotEnergy[3])/2
            self.histEnrg.Fill(energy);

        acqData = evt.getAcqValue(self.source, 0, env)
        if acqData :
            wf = acqData.waveform()

            if self.ts is None :
                self.ts = acqData.timestamps()

            self.prof_wfAll.FillN(self.numSamplesITof,self.ts,wf,self.wg,1)

            bin = int( ((energy-self.emin)/(self.emax-self.emin))*self.nebins+0.5)
            if bin < 1 : bin = 0
        """Class constructor. The parameters ifto binthe >constructor self.nebins : bin = self.nebins-1
are passed
        from pyana configuration file. If parameters  self.histBin.Fill(bin)
  do not have default
          self.prof_wf[bin].FillN(self.numSamplesITof,self.ts,wf,self.wg,1)


    def endcalibcycle( self, env ) :values  here then the must be defined in pyana.cfg. All parameters
        """This optional method is called if present at the end of theare passed as strings, convert to correct type before use.
        calibration cycle.
"""
        @paramself.source env= source
   environment object
    self.nebins    """
= int(nenergy)
        logging.info( "pyana_esort_hmgr.endcalibcycle() called" )

self.emin = float(e1)
      def endrun( self,.emax env= float(e2) :

        """This optional method is called if present at the end of the run.self.nev = 0

        @param env    environment object#-------------------
    #  Public methods """--
        logging.info( "pyana_esort_hmgr.endrun() called" )#-------------------

    def endjobbeginjob( self, evt, env ) :
        """This method is called once at the endbeginning of the job.
 It should do      It will also be called in any Xtc Configure transition, if
        configurations finalhave cleanup, e.g. close all open fileschanged since last it was run.

        @param evt    event data object
        @param env    environment object
        """

        # Preferred way to log information is via logging package
        logging.info( "pyana_esort_hmgr.endjobbeginjob() called " )

        durationcfg = timeenv.clockgetAcqConfig() - self.startsource)
        print#numChannels "duration in seconds : ", duration
    = cfg.nbrChannels()
        self.numSamplesITof = cfg.horiz().nbrSamples()
    print "Number of events processed:sampleIntervalITof ", self.nev
= cfg.horiz().sampInterval()
        print self.prof_wfAll.GetNbinsX()numSamplesITof
        for bin in range (20,40):
print sampleIntervalITof

        hmgr = env.hmgr()

       print self.prof_wfAll.GetBinContent(bin+1), " +- ", self.prof_wfAll.GetBinError(bin+1)

Card
labelpyana with MatPlotLib
Code Block
title"pyana_esort_mpl.py"

import sys
import logging
import time

#-----------------------------
# Imports for other modules --
#-----------------------------
import numpy as np
import matplotlib.pyplot as plt
import h5py

#---------------------
#  Class definition --
#---------------------
class pyana_esort_mpl (object) :
    """Class whose instance will be used as a user analysis module. """

    #----------------
    #  Constructor --
    #----------------
    def __init__ ( self, nenergy, e1, e2, source = "AmoITof-0|Acqiris-0"):
histEnrg = hmgr.h1f("histEnrg",";Energy",self.nebins,self.emin,self.emax)
        self.histBin = hmgr.h1i("histBin",";Bin",self.nebins,0.0, self.nebins)
        self.histEnrg.SetMarkerStyle(4)
        self.histEnrg.SetMarkerColor(4)
        self.histBin.SetMarkerStyle(4)
        self.histBin.SetMarkerColor(4)

        name = "profWfAll"
        title = "Average Waveform;time [s];voltage [V]"
        self.prof_wfAll = hmgr.prof(name,title,self.numSamplesITof,
                            """Class constructor. The parameters to the constructor are passed0.0,
        from pyana configuration file. If parameters do not have default
        values  here then the must be defined in pyana.cfg. All parameters self.numSamplesITof*sampleIntervalITof,
        are passed as strings, convert to correct type before use.
        """
        self.source = source
 "")
        self.nebinsprof_wf = int(nenergy)
[]
        for bin self.eminin =range float(e10,self.nebins):
            self.emaxname = float(e2)"profWf%d"%bin
        self.bwidth = (self.emax-self.emin)/self.nebins

  title = "Average Waveform in Energy self.nev = 0

    #-------------------Bin %d;time [s];voltage [V]" % bin
    #  Public methods --
    #-------------------
self.prof_wf.append( hmgr.prof(name,title,self.numSamplesITof,
    def beginjob( self, evt, env ) :
        """This method is called once at the beginning of the job.
        It will also be called in any Xtc Configure transition0.0, if
        configurations have changed since last it was run.

        @param evt    event data object
        @param env    environment objectself.numSamplesITof*sampleIntervalITof,
        """

        # Preferred way to log information is via logging package
        logging.info( "pyana_esort_mpl.beginjob() called " )

      ""))


  cfg = env.getAcqConfig(self.source)
    # prof.FillN requires a #numChannels = cfg.nbrChannels()weight array...
        self.numSamplesITofwg = cfgnp.horizones().nbrSamples(self.numSamplesITof,dtype=float)
        sampleIntervalITofself.ts = cfg.horiz().sampInterval()None

    def beginrun( self, evt, #env for) matplotlib,:
 we store the array till the end instead of a histogram...
        """ energy / bin histogram """
     """This optional method is called if present at the beginning
        of the new run.

     self.axisEnrg = np.arange(self.emin,self.emax,self.bwidth, dtype=float)
  @param evt    event data object
 self.arrayEnrg = np.zeros(self.nebins, dtype=float)
    @param env   """ time wave"""environment object
        self.ts = None

"""
        logging.info( """ voltage wave"""
pyana_esort_hmgr.beginrun() called ")

        print  self.wf = None"beginrun is done, starting timer..."
        self.wf2start = Nonetime.clock()

    def begincalibcycle( self,  """ voltage wave in bins of energyevt, env ) :
        """
This optional method is called if present at self.bwf = []the beginning
        self.bwf2of =the []
new calibration cycle.

      for bin in@param rangeevt (0, self.nebins):
  event data object
        @param env   self.bwf.append( None )
 environment object
        """
      self.bwf2.append( None )  logging.info( "pyana_esort_hmgr.begincalibcycle() called ")




    def beginrunevent( self, evt, env ) :
        """This optional method is called iffor presentevery at the beginning
        of the new runL1Accept transition.

        @param evt    event data object
        @param env    environment object
        """
        logging.info( "pyana_esort_mplhmgr.beginrunevent() called ")

        print "beginrun is done, starting timer..."self.nev+=1

        self.startshotEnergy = timeevt.clockgetFeeGasDet()


     def begincalibcycle( self, evt, env ) :
 energy = 0.0
        bin  """This optional method is called if present at the beginning
   = 0
        if shotEnergy is None :
     of the new calibration cycle.

   print "No Gas Detector"
  @param evt    event dataelse object:
        @param env   energy environment object= (shotEnergy[2]+shotEnergy[3])/2
        """
        logging.info( "pyana_esort_mpl.begincalibcycle() called ")
self.histEnrg.Fill(energy);

    def event( self, evt, envacqData ) :
  = evt.getAcqValue(self.source, 0, env)
      """This method isif called for every L1Accept transition.

acqData :
         @param evt  wf  event data object
= acqData.waveform()

          @param env if self.ts is environmentNone object:
        """
        logging.info( "pyana_esort_mpl.event() called ")

self.ts = acqData.timestamps()

            self.nev+=1

prof_wfAll.FillN(self.numSamplesITof,self.ts,wf,self.wg,1)

         shotEnergy  = evt.getFeeGasDet( bin = int( ((energy-self.emin)/(self.emax-self.emin))*self.nebins+0.5)
        energy = 0.0
  if bin < 1  : bin = 0
            if shotEnergybin is> Noneself.nebins :
 bin = self.nebins-1
         print "No Gas Detector" self.histBin.Fill(bin)
        else :
   self.prof_wf[bin].FillN(self.numSamplesITof,self.ts,wf,self.wg,1)


    def endcalibcycle( self, env  energy = (shotEnergy[2]+shotEnergy[3])/2
) :
        acqData = evt.getAcqValue(self.source, 0, env)
        if acqData :"""This optional method is called if present at the end of the
            awf = acqData.waveform()calibration cycle.

        @param env   if self.ts is None :environment object
        """

        selflogging.ts = acqData.timestamps()info( "pyana_esort_hmgr.endcalibcycle() called" )

    def endrun( self, env ) :
   # average waveform
   """This optional method is called if present at the ifend self.wfof is None:the run.

        @param env       self.wf = awfenvironment object
        """
        selflogging.wf2 = (awf*awf)
  info( "pyana_esort_hmgr.endrun() called" )

    def endjob( self, env   else) :
        """This method is called at the end of self.wf += awfthe job. It should do
        final cleanup, e.g. close all open files.

   self.wf2 += (awf*awf)

   @param env    environment  object
  # binned waveform
    """
        bin = int( ((energy-self.emin)/(self.emax-self.emin))*self.nebins+0.5)logging.info( "pyana_esort_hmgr.endjob() called" )

        duration = time.clock() - self.start
   if bin < 1 : binprint ="duration 0
in seconds : ", duration
        ifprint bin"Number >of self.nebinsevents processed: bin", = self.nebins-1nev

          print  self.arrayEnrg[bin] += 1
self.prof_wfAll.GetNbinsX()
            if self.bwf[bin] is None for bin in range (20,40):
               print self.prof_wfAll.GetBinContent(bin+1), " +- ", self.prof_wfAll.GetBinError(bin+1)

Card
labelpyana with MatPlotLib
Code Block
title"pyana_esort_mpl.py"

import sys
import logging
import time

#-----------------------------
# Imports for other modules --
#-----------------------------
import numpy as np
import matplotlib.pyplot as plt
import h5py

#---------------------
#  Class definition --
#---------------------
class pyana_esort_mpl (object) :
    """Class whose instance will be used as a user analysis module. """

    #----------------
    #  Constructor --
    #----------------
    def __init__ ( self, nenergy, e1, e2, source = "AmoITof-0|Acqiris-0"):
        """Class constructor. The parameters to the constructor are passed
.bwf[bin]=awf
                self.bwf2[bin]=(awf*awf)
            else :
                self.bwf[bin]+=awf
                self.bwf2[bin]+=(awf*awf)

    def endcalibcycle( self, env ) :
        """This optional method is called if present at the end of the
        calibration cycle.

        @param env    environment object
        """

        logging.info(from "pyana_esort_mpl.endcalibcycle() called" )

    def endrun( self, env ) :
        """This optional method is called if present at the end of the run.

        @param env    environment objectpyana configuration file. If parameters do not have default
        values  here then the must be defined in pyana.cfg. All parameters
        are passed as strings, convert to correct type before use.
        """
        logging.info( "pyana_esort_mpl.endrun() called" )

self.source = source
      def endjob( self,.nebins env= int(nenergy) :
        """This method is called at the end of the job. It should doself.emin = float(e1)
        self.emax = float(e2)
        final cleanup, e.g. close all open files.self.bwidth = (self.emax-self.emin)/self.nebins

        @paramself.nev env= 0

   environment object #-------------------
    #  Public methods """--
        logging.info( "pyana_esort_mpl.endjob() called" )#-------------------

    def beginjob( self, evt, #env have) collected:
 the sum so far, but we
  """This method is called once at #the wantbeginning toof display the average

job.
        It will also be called in self.wfany =Xtc self.wf / self.nev
Configure transition, if
         self.wf2 = self.wf2 / self.nevconfigurations have changed since last it was run.

        self.wf_rms = np.sqrt( self.wf2 - self.wf*self.wf ) / np.sqrt(self.nev)
@param evt    event data object
        self.bwf_rms = []
@param env    environment object
    for bin in range (0, self.nebins): """

        # Preferred way to if self.bwf[bin]log information is None:
via logging package
              self.bwf_rms.append(None)
   logging.info( "pyana_esort_mpl.beginjob() called " )

        cfg     continue
= env.getAcqConfig(self.source)
            self.bwf[bin]#numChannels = self.bwf[bin] / self.arrayEnrg[bin]
  cfg.nbrChannels()
          self.bwf2[bin]numSamplesITof = self.bwf2[bin] / self.arrayEnrg[bin]cfg.horiz().nbrSamples()
        sampleIntervalITof =   self.bwf_rms.append(np.sqrt( self.bwf2[bin] \cfg.horiz().sampInterval()

        # for matplotlib, we store the array till the end instead of a histogram...
        """ energy / bin histogram """
        - self.bwf[bin]*self.bwf[bin] ) \self.axisEnrg = np.arange(self.emin,self.emax,self.bwidth, dtype=float)
        self.arrayEnrg = np.zeros(self.nebins, dtype=float)
        """ time wave"""
        self.ts   / np.sqrt(self.arrayEnrg[bin]))= None

        duration = time.clock() - self.start
""" voltage wave"""
        self.wf = None
 print "duration in seconds : ", duration   self.wf2 = None

        print "nevents processed: ", self.nev
    """ voltage wave in bins of energy  """
    duration = time.clock() - self.start
bwf = []
      print "duration inself.bwf2 seconds= :[]
 ", duration
      for bin printin "nevents processed: "range (0, self.nev
nebins):
        # save "histograms" to an hdf5 file self.bwf.append( None )
        ofile   = h5pyself.bwf2.File("outputfile.hdf5", 'w') # open for writing (overwrites existing file)append( None )

    def beginrun( self, evt, env ) :
        group = ofile.create_group("HistogramArrays")
        group.create_dataset("wf_time",data=self.ts)"""This optional method is called if present at the beginning
        group.create_dataset("wf_avg",data=self.wf)of the new run.

        group.create_dataset("wf_avg_rms",data=self.wf_rms)
 @param evt    event data  group.create_dataset("bin_enrg",data=self.arrayEnrg)
object
         group.create_dataset("bin_axis",data=self.axisEnrg)
@param env    environment object
   for bin in range (0, self.nebins):
 """
        logging.info( "pyana_esort_mpl.beginrun() called ")

   if self.bwf[bin] is not None:
 print "beginrun is done, starting timer..."
        self.start = grouptime.create_dataset("wf_bin%d"%bin,data=self.bwf[bin])clock()


    def begincalibcycle( self, evt, env ) :
        group.create_dataset("wf_bin%d_rms"%bin,data=self.bwf_rms[bin])
        ofile.close()


"""This optional method is called if present at the beginning
        durationof = time.clock() - self.startthe new calibration cycle.

        print "duration till after save hdf5, in seconds : ", duration
    @param evt    event data object
        @param env    #environment plotobject
        fig = plt.figure(num=100, figsize=(7.5,5))"""
        ax = fig.add_subplot(111)
  logging.info( "pyana_esort_mpl.begincalibcycle() called ")


    def event( plt.plot(self.axisEnrg, self.arrayEnrgevt, env 'bo') :
        plt.errorbar(self.axisEnrg, self.arrayEnrg, xerr=self.bwidth, yerr=np.sqrt(self.arrayEnrg),fmt=None)
        plt.title("Energy Bins")
"""This method is called for every L1Accept transition.

        @param evt   plt.xlabel("Energy")
    event data object
     plt.ylabel("Event count")
  @param env    environment plt.draw()object
        print "energy histogram plotted"""
        figlogging.savefiginfo( "pyana_esort_mpl_histEnrg.png.event() called ")

        print "energy histogram saved"self.nev+=1


        figshotEnergy = pltevt.figure(num=200, figsize=(7.5,5)getFeeGasDet()
        axenergy = fig.add_subplot(111)0.0
        plt.clf()
bin = 0
         plt.errorbar(self.ts, self.wf,yerr=self.wf_rms, mew=0.0)
if shotEnergy is None :
            print plt.title("Average Waveform")"No Gas Detector"
        plt.xlabel("timeelse :
   [s]")
        plt.ylabel("voltage energy = [V]")
(shotEnergy[2]+shotEnergy[3])/2

        acqData plt= evt.draw(getAcqValue(self.source, 0, env)
        printif "wf avg histogram plotted"
acqData :
            awf = figacqData.savefig("pyana_mpl_profWfAll.png")
waveform()

            print "wf avg histogram saved"

if self.ts is None :
           for bin in range (0, self.nebins):ts = acqData.timestamps()

            if self.bwf[bin] is not None:# average waveform
            if self.wf   # plotis None:
                figself.wf = plt.figure(num=300+bin, figsize=(7.5,5))awf
                axself.wf2 = fig.add_subplot(111(awf*awf)
                plt.clf()else :
                plt.errorbar(self.ts, self.bwf[bin], yerr=self.bwf_rms[bin],mew=0.0)wf += awf
                plt.title("Waveform bin %d (%.2f<E<%.2f)"\self.wf2 += (awf*awf)

            # binned waveform
            bin %= int(bin, ((energy-self.emin+bin*)/(self.bwidth, emax-self.emin+(bin+1))*self.nebins+0.bwidth5))
            if bin < 1 :  plt.xlabel("time bin = 0
   [s]")
         if bin > self.nebins : bin = plt.ylabel("voltageself.nebins-1
            self.arrayEnrg[V]")bin] += 1

            if self.bwf[bin] is None plt.draw():
                print "wf bin %d histogram plotted"%binself.bwf[bin]=awf
                fig.savefig("pyana_mpl_profWf%d.png"%binself.bwf2[bin]=(awf*awf)
            else :
   print "wf bin %d histogram saved"%bin


        duration = time.clock() - self.start
self.bwf[bin]+=awf
          print "duration3 in seconds : ", duration self.bwf2[bin]+=(awf*awf)

    def endcalibcycle( self, env #) test:
        print self.wf.size
        for bin in range (20,40):
"""This optional method is called if present at the end of the
        calibration cycle.

     print self.wf[bin], " +-- ", self.wf_rms[bin]

Card
labelpsana with ROOT
Code Block
title"psana_esort.cpp"

//-----------------------
// This Class's Header --
//-----------------------
#include "speed/psana_esort.h"

//-----------------
// C/C++ Headers --
//-----------------
#include <time.h>

//-------------------------------
// Collaborating Class Headers --
//-------------------------------
#include "MsgLogger/MsgLogger.h"

//--------------------------------------------------
// to work with detector data include corresponding
// header from psddl_psana package
//--------------------------------------------------
#include "psddl_psana/acqiris.ddl.h"
#include "psddl_psana/bld.ddl.h"

//-----------------------------------------------------------------------
// Local Macros, Typedefs, Structures, Unions and Forward Declarations --
//-----------------------------------------------------------------------

// This declares this class as psana module
using namespace speed;
PSANA_MODULE_FACTORY(psana_esort)

//              ----------------------------------------
//              -- Public Function Member Definitions --
// @param env    environment object
        """

        logging.info( "pyana_esort_mpl.endcalibcycle() called" )

    def endrun( self, env ) :
        """This optional method is called if present at the end of the run.

        @param env    environment object
        """
        logging.info( "pyana_esort_mpl.endrun() called" )

    def endjob( self, env ) :
        """This method is called at the end of the job. It should do
        final cleanup, e.g. close all  ----------------------------------------

namespace speed {

//----------------
// Constructors --
//----------------
psana_esort::psana_esort (const std::string& name)
  : Module(name)
  , m_acqSrc()
  , m_feeSrc()
  , m_maxEvents()
  , m_filter()
  , m_nenergy()
  , m_e1()
  , m_e2()
{
  // get the values from configuration or use defaults
  m_acqSrc = configStr("acqSource", "DetInfo(:Acqiris)");
  m_feeSrc = configStr("feeSource", "BldInfo(FEEGasDetEnergy)");
  m_maxEvents = config("events", 32U);
  m_filter = config("filter", false);
  m_nenergy = config("nenergy",20);
  m_e1 = config("e1",0.0);
  m_e2 = config("e2",4.0);
}

//--------------
// Destructor --
//--------------
psana_esort::~psana_esort ()
{
}

/// Method which is called once at the beginning of the job
void
psana_esort::beginJob(Env& env)
{
  m_count = 0;

  RootHistoManager::RootHMgr& rhmgr = env.rhmgr();

  shared_ptr<Psana::Acqiris::ConfigV1> acqConfig = env.configStore().get(m_acqSrc);
  if (acqConfig.get()) {
    int channel = 0;
    m_nSamples       = acqConfig->horiz().nbrSamples();
    m_sampleInterval = acqConfig->horiz().sampInterval();
    m_slopeopen files.

        @param env    environment object
        """
        logging.info( "pyana_esort_mpl.endjob() called" )

        # have collected the sum so far, but we
        # want to display the average

        self.wf = self.wf / self.nev
        self.wf2 = self.wf2 / self.nev
        self.wf_rms = np.sqrt( self.wf2 - self.wf*self.wf ) / np.sqrt(self.nev)

        self.bwf_rms = []
        for bin in range (0, self.nebins):
            if self.bwf[bin] is None:
                self.bwf_rms.append(None)
                continue

            self.bwf[bin] = self.bwf[bin] / self.arrayEnrg[bin]
            self.bwf2[bin] = self.bwf2[bin] / self.arrayEnrg[bin]
            = acqConfig->vert(channel).slope();
self.bwf_rms.append(np.sqrt( self.bwf2[bin] \
      m_offset         = acqConfig->vert(channel).offset();

    m_timevector = new double[m_nSamples];
    m_wfvector = new double[m_nSamples];
    m_wgvector = new double[m_nSamples];
    for (int i(0);i<m_nSamples;i++){- self.bwf[bin]*self.bwf[bin] ) \
      m_timevector[i]= i * m_sampleInterval;
      m_wfvector[i]=0.0;
       m_wgvector[i]=1.0;
    }

    m_profWfAll = rhmgr.profile("profWfAll","Average Waveform;time [s];voltage [V]", / np.sqrt(self.arrayEnrg[bin]))

        duration = time.clock() - self.start
        print "duration in seconds : ", duration
      AxisDef(0.0, m_nSamples*m_sampleInterval,m_nSamples)
      print "nevents processed: ", self.nev
        duration = time.clock() - self.start
        print "duration in seconds : ",  );duration

    char name[32];
   print char title[232];
    for (int i=0; i<m_nenergy;i++){
"nevents processed: ", self.nev

        # save sprintf(name,"profWf%dhistograms",i);
 to an hdf5 file
  sprintf(title,"Average Waveform in Energy bin %d; time [s]; voltage [V]",i);
      m_profWf[i] = rhmgr.profile(name, title,ofile = h5py.File("outputfile.hdf5", 'w') # open for writing (overwrites existing file)
        group = ofile.create_group("HistogramArrays")
        group.create_dataset("wf_time",data=self.ts)
        group.create_dataset("wf_avg",data=self.wf)
        AxisDef(0.0,m_nSamples*m_sampleInterval,m_nSamplesgroup.create_dataset("wf_avg_rms",data=self.wf_rms)
          group.create_dataset("bin_enrg",data=self.arrayEnrg)
        group.create_dataset("bin_axis",data=self.axisEnrg)
        for bin in range     );
    }
  }
  // create a histogram to display the energy bins
  m_histEnrg = rhmgr.h1f("histEnrg","Energy bins;Energy; Event Count",AxisDef(m_e1,m_e2,m_nenergy));
  m_histBin = rhmgr.h1i("histBin","Energy bins;Bin; Event count",AxisDef(0.0,m_nenergy,m_nenergy));
  m_histEnrg->SetMarkerStyle(4); m_histEnrg->SetMarkerColor(4); // blue circles
  m_histBin->SetMarkerStyle(4);  m_histBin->SetMarkerColor(4); // blue circles

  //m_histEnrg = new TH1F("histEnrg",";Energy",m_nenergy,m_e1,m_e2);
  //m_histBin = new TH1I("histBin",";Bin",m_nenergy,0.0,m_nenergy);

}


/// Method which is called at the beginning of the run
void
psana_esort::beginRun(Env& env)
{
  printf("beginRun is done, starting timer...");
  m_start_time = clock();
}

/// Method which is called at the beginning of the calibration cycle
void
psana_esort::beginCalibCycle(Env& env)
{
}

/// Method which is called with event data, this is the only required
/// method, all other methods are optional
void
psana_esort::event(Event& evt, Env& env)
{

//   // this is how to skip event (all downstream modules will not be called)
//   if (m_filter && m_count % 10 == 0) skip();

//   // this is how to gracefully stop analysis job
//   if (m_count >= m_maxEvents) stop();

  //MsgLog(name(),info,"Event:" << m_count);

  /*
   * Processing FeeGasDet Value
   */
  shared_ptr<Psana::Bld::BldDataFEEGasDetEnergy> fee = evt.get(m_feeSrc);
  double shotEnergy[4] = {0.,0.,0.,0.};
  if (fee.get()) {
    shotEnergy[0] = fee->f_11_ENRC();
    shotEnergy[1] = fee->f_12_ENRC();
    shotEnergy[2] = fee->f_21_ENRC();
    shotEnergy[3] = fee->f_22_ENRC();
  }
  double energy = (shotEnergy[2]+shotEnergy[3])/2;
  if ( energy < m_e1 ) {
    m_histEnrg->Fill(m_e1);
  } else if ( energy > m_e2 ) {
    m_histEnrg->Fill(m_e2);
  } else {
    m_histEnrg->Fill(energy);
  }

  /*
   * Processing ITof waveform
   */
  shared_ptr<Psana::Acqiris::DataDescV1> acqData = evt.get(m_acqSrc);
  if (acqData.get()) {

    m_count++;

    int channel = 0;
    const Psana::Acqiris::DataDescV1Elem& data = acqData->data(channel);

    // copy myana main.cc getAcqValue()
    const int16_t* wfdata = data.waveforms();
    wfdata += data.indexFirstPoint();

    shared_ptr<Psana::Acqiris::ConfigV1> acqConfig = env.configStore().get(m_acqSrc);
    if (acqConfig.get()) {

//       const Psana::Acqiris::HorizV1& hcfg = acqConfig->horiz();
//       const Psana::Acqiris::VertV1& vcfg = acqConfig->vert(channel);
//       float slope = vcfg.slope();
//       float offset = vcfg.offset();
//       int nbrSamples = hcfg.nbrSamples();
//       for (int j=0;j<nbrSamples;j++){
//      int16_t swap = (wfdata[j]&0xff<<8) | (wfdata[j]&0xff00>>8);
//      m_wfvector[j] = swap*slope-offset;

      for (int j=0;j<m_nSamples;j++){
        int16_t swap = (wfdata[j]&0xff<<8) | (wfdata[j]&0xff00>>8);
        m_wfvector[j] = swap* m_slope - m_offset;
      }


      int numSamples = data.nbrSegments() * data.nbrSamplesInSeg();
      if (numSamples != m_nSamples) std::cout << "nSamples mismatch" << std::endl;

      int bin = int(( (energy-m_e1)/(m_e2-m_e1) )*m_nenergy+0.5);
      if (bin<1) bin=0;
      if (bin>m_nenergy-1) bin=int(m_nenergy-1);


      m_histBin->Fill(bin);
      m_profWf[bin]->FillN(numSamples,m_timevector,m_wfvector,m_wgvector,1);
      m_profWfAll->FillN(numSamples,m_timevector,m_wfvector,m_wgvector,1);
    }
  }
}

/// Method which is called at the end of the calibration cycle
void
psana_esort::endCalibCycle(Env& env)
{
  delete[] m_timevector;
}

/// Method which is called at the end of the run
void
psana_esort::endRun(Env& env)
{
}

/// Method which is called once at the end of the job
void
psana_esort::endJob(Env& env)
{

  clock_t finish_time = clock();
  double duration = (finish_time - m_start_time)/CLOCKS_PER_SEC;
  printf("Time elapsed: %.2f s \n",(duration));
  printf("Number of events processed: %d \n", m_count);

  std::cout << m_profWfAll->GetNbinsX() << std::endl;
  for (int bin = 20; bin<40; bin++) {
    std::cout << m_profWfAll->GetBinContent(bin+1) << " +- " << m_profWfAll->GetBinError(bin+1) << std::endl;
  }
}

} // namespace speed(0, self.nebins):
            if self.bwf[bin] is not None:
                group.create_dataset("wf_bin%d"%bin,data=self.bwf[bin])
                group.create_dataset("wf_bin%d_rms"%bin,data=self.bwf_rms[bin])
        ofile.close()


        duration = time.clock() - self.start
        print "duration till after save hdf5, in seconds : ", duration
        # plot
        fig = plt.figure(num=100, figsize=(7.5,5))
        ax = fig.add_subplot(111)
        plt.plot(self.axisEnrg, self.arrayEnrg, 'bo')
        plt.errorbar(self.axisEnrg, self.arrayEnrg, xerr=self.bwidth, yerr=np.sqrt(self.arrayEnrg),fmt=None)
        plt.title("Energy Bins")
        plt.xlabel("Energy")
        plt.ylabel("Event count")
        plt.draw()
        print "energy histogram plotted"
        fig.savefig("pyana_mpl_histEnrg.png")
        print "energy histogram saved"


        fig = plt.figure(num=200, figsize=(7.5,5))
        ax = fig.add_subplot(111)
        plt.clf()
        plt.errorbar(self.ts, self.wf,yerr=self.wf_rms, mew=0.0)
        plt.title("Average Waveform")
        plt.xlabel("time   [s]")
        plt.ylabel("voltage   [V]")
        plt.draw()
        print "wf avg histogram plotted"
        fig.savefig("pyana_mpl_profWfAll.png")
        print "wf avg histogram saved"

        for bin in range (0, self.nebins):
            if self.bwf[bin] is not None:
                # plot
                fig = plt.figure(num=300+bin, figsize=(7.5,5))
                ax = fig.add_subplot(111)
                plt.clf()
                plt.errorbar(self.ts, self.bwf[bin], yerr=self.bwf_rms[bin],mew=0.0)
                plt.title("Waveform bin %d (%.2f<E<%.2f)"\
                          % (bin, self.emin+bin*self.bwidth, self.emin+(bin+1)*self.bwidth))
                plt.xlabel("time    [s]")
                plt.ylabel("voltage    [V]")
                plt.draw()
                print "wf bin %d histogram plotted"%bin
                fig.savefig("pyana_mpl_profWf%d.png"%bin)
                print "wf bin %d histogram saved"%bin


        duration = time.clock() - self.start
        print "duration3 in seconds : ", duration

        # test
        print self.wf.size
        for bin in range (20,40):
            print self.wf[bin], " +-- ", self.wf_rms[bin]