Index: /trunk/MagicSoft/Mars/msimcamera/MSimCalibrationSignal.cc
===================================================================
--- /trunk/MagicSoft/Mars/msimcamera/MSimCalibrationSignal.cc	(revision 9256)
+++ /trunk/MagicSoft/Mars/msimcamera/MSimCalibrationSignal.cc	(revision 9256)
@@ -0,0 +1,237 @@
+/* ======================================================================== *\
+!
+! *
+! * This file is part of CheObs, the Modular Analysis and Reconstruction
+! * Software. It is distributed to you in the hope that it can be a useful
+! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
+! * It is distributed WITHOUT ANY WARRANTY.
+! *
+! * Permission to use, copy, modify and distribute this software and its
+! * documentation for any purpose is hereby granted without fee,
+! * provided that the above copyright notice appears in all copies and
+! * that both that copyright notice and this permission notice appear
+! * in supporting documentation. It is provided "as is" without express
+! * or implied warranty.
+! *
+!
+!
+!   Author(s): Thomas Bretz,  1/2009 <mailto:tbretz@astro.uni-wuerzburg.de>
+!
+!   Copyright: CheObs Software Development, 2000-2009
+!
+!
+\* ======================================================================== */
+
+//////////////////////////////////////////////////////////////////////////////
+//
+//  MSimCalibrationSignal
+//
+// This task is a MRead task which produces events instead of reading them
+// from a file. To be more precise, calibration events are produced.
+// (Note, that pedestal events are also a kind of calibration events).
+//
+// Whether pedestal or calibration events are produced is defined by
+// the RunType stored in MRawRunheader. The number of pixels which are
+// "enlightened" are determined from a MGeomCam.
+//
+//
+//  Input Containers:
+//   fNameGeomCam [MGeomCam]
+//   MRawRunHeader
+//   IntendedPulsePos [MParameterD]
+//
+//  Output Containers:
+//   [MPhotonEvent]
+//   [TriggerPos [MParameterD]]
+//   MPhotonStatistics
+//   MRawEvtHeader
+//
+//////////////////////////////////////////////////////////////////////////////
+#include "MSimCalibrationSignal.h"
+
+#include <TRandom.h>
+
+#include "MParList.h"
+#include "MTaskList.h"
+
+#include "MLog.h"
+#include "MLogManip.h"
+
+#include "MParameters.h"
+
+#include "MGeomCam.h"
+
+#include "MRawRunHeader.h"
+#include "MRawEvtHeader.h"
+
+#include "MPhotonEvent.h"
+#include "MPhotonData.h"
+
+ClassImp(MSimCalibrationSignal);
+
+using namespace std;
+
+// --------------------------------------------------------------------------
+//
+//  Default Constructor.
+//
+MSimCalibrationSignal::MSimCalibrationSignal(const char* name, const char *title)
+    : fParList(0), fGeom(0), fPulsePos(0), fTrigger(0), fRunHeader(0), fEvtHeader(0),
+    fEvt(0), fStat(0),  fNumEntries(1000)
+{
+    fName  = name  ? name  : "MRead";//"MSimCalibrationSignal";
+    fTitle = title ? title : "Task to create a fake signal (derives from MRead)";
+}
+
+// --------------------------------------------------------------------------
+//
+//  Check for the needed parameter containers.
+//
+Int_t MSimCalibrationSignal::PreProcess(MParList *pList)
+{
+    fGeom = (MGeomCam*)pList->FindObject(fNameGeomCam, "MGeomCam");
+    if (!fGeom)
+    {
+        *fLog << inf << fNameGeomCam << " [MGeomCam] not found..." << endl;
+
+        fGeom = (MGeomCam*)pList->FindCreateObj(fNameGeomCam);
+        if (!fGeom)
+            return kFALSE;
+    }
+
+    fRunHeader = (MRawRunHeader*)pList->FindObject("MRawRunHeader");
+    if (!fRunHeader)
+    {
+        *fLog << err << "MRawRunHeader not found... aborting." << endl;
+        return kFALSE;
+    }
+
+
+    fEvt     = 0;
+    fTrigger = 0;
+
+    if (fRunHeader->IsCalibrationRun())
+    {
+        fEvt = (MPhotonEvent*)pList->FindCreateObj("MPhotonEvent");
+        if (!fEvt)
+            return kFALSE;
+    }
+    else
+    {
+        fTrigger = (MParameterD*)pList->FindCreateObj("MParameterD", "TriggerPos");
+        if (!fTrigger)
+            return kFALSE;
+    }
+
+    fStat = (MPhotonStatistics*)pList->FindCreateObj("MPhotonStatistics");
+    if (!fStat)
+        return kFALSE;
+
+    fEvtHeader = (MRawEvtHeader*)pList->FindCreateObj("MRawEvtHeader");
+    if (!fEvtHeader)
+        return kFALSE;
+
+    fPulsePos = (MParameterD*)pList->FindObject("IntendedPulsePos", "MParameterD");
+    if (!fPulsePos)
+    {
+        *fLog << err << "IntendedPulsePos [MParameterD] not found... aborting." << endl;
+        return kFALSE;
+    }
+
+    //
+    // Search for MTaskList
+    //
+    fParList = pList;
+
+    //
+    // A new file has been opened and new headers have been read.
+    //  --> ReInit tasklist
+    //
+    return kTRUE;
+}
+
+// --------------------------------------------------------------------------
+//
+// ReInit the task-list if this is the first "event from this fake file"
+//
+Bool_t MSimCalibrationSignal::ReInit(MParList *plist)
+{
+    if (plist)
+        return kTRUE;
+
+    if (GetNumExecutions()==0)
+        return kTRUE;
+
+    MTask *fTaskList = (MTask*)fParList->FindObject("MTaskList");
+    if (!fTaskList)
+    {
+        *fLog << err << dbginf << "MTaskList not found... abort." << endl;
+        return kFALSE;
+    }
+
+    if (!fTaskList->ReInit(fParList))
+        return kFALSE;
+
+    return kTRUE;
+}
+
+// --------------------------------------------------------------------------
+//
+// Produce the events.
+//
+Int_t MSimCalibrationSignal::Process()
+{
+    if (GetNumExecutions()==fNumEntries)
+        return kFALSE;
+
+    if (!ReInit())
+        return kERROR;
+
+    Int_t cnt = 0;
+    if (fRunHeader->IsCalibrationRun())
+    {
+        for (UInt_t idx=0; idx<fGeom->GetNumPixels(); idx++)
+        {
+            // FIXME: Where to get this number from?
+            for (int i=0; i<50; i++)
+            {
+                MPhotonData &ph = fEvt->Add(cnt++);
+
+                const Float_t tm = gRandom->Gaus(0, 1);
+
+                ph.SetTag(idx);
+                ph.SetWeight();
+                ph.SetTime(tm);
+            }
+        }
+    }
+
+    fEvt->Shrink(cnt);
+    fEvt->Sort(kTRUE);
+
+    // ------------ FIMXE: Move somewhere else? -------------
+    // -------------------- MSimGeomCam ---------------------
+
+    const Double_t freq = fRunHeader->GetFreqSampling()/1000.;
+
+    // Length (ns), Pulse position (Units ns)
+    const Float_t ns = fRunHeader->GetNumSamplesHiGain()*freq;
+    const Float_t pp = fPulsePos->GetVal();
+
+    const Float_t first = cnt>0 ? fEvt->GetFirst()->GetTime() : 0;
+    const Float_t last  = cnt>0 ? fEvt->GetLast()->GetTime()  : ns;
+
+    fStat->SetTime(first-pp, last+(ns-pp));
+    fStat->SetMaxIndex(fGeom->GetNumPixels()-1);
+    fStat->SetReadyToSave();
+
+    // FIXME: Jitter! (Own class?)
+    fTrigger->SetVal(pp*freq);
+
+    // FIXME: Set from somewhere else? (see also MSimTrigger)
+    fEvtHeader->SetDAQEvtNumber(GetNumExecutions());
+    fEvtHeader->SetReadyToSave();
+
+    return kTRUE;
+
+}
Index: /trunk/MagicSoft/Mars/msimcamera/MSimCalibrationSignal.h
===================================================================
--- /trunk/MagicSoft/Mars/msimcamera/MSimCalibrationSignal.h	(revision 9256)
+++ /trunk/MagicSoft/Mars/msimcamera/MSimCalibrationSignal.h	(revision 9256)
@@ -0,0 +1,51 @@
+#ifndef MARS_MSimCalibrationSignal
+#define MARS_MSimCalibrationSignal
+
+#ifndef MARS_MRead
+#include "MRead.h"
+#endif
+
+class MGeomCam;
+class MParList;
+class MPhotonEvent;
+class MPhotonStatistics;
+class MParameterD;
+class MRawRunHeader;
+class MRawEvtHeader;
+
+class MSimCalibrationSignal : public MRead
+{
+private:
+    MParList          *fParList;    //! Store pointer to MParList for initializing ReInit
+    MGeomCam          *fGeom;       //! Camera geometry to know the number of expected pixels
+    MParameterD       *fPulsePos;   //! Expected position at which the pulse should be
+    MParameterD       *fTrigger;    //! Position in analog channels at which the triggersignal  is raised
+    MRawRunHeader     *fRunHeader;  //! Digitization window and frequency
+
+    MRawEvtHeader     *fEvtHeader;  //! Event header which is filled
+    MPhotonEvent      *fEvt;        //! Photon event into which the new photons are stored
+    MPhotonStatistics *fStat;       //! Photon statistic which is filled
+
+    TString fNameGeomCam;           // Name of the camera geometry
+
+    UInt_t fNumEntries;             // Number of events to produce
+
+    // MTask
+    Int_t  PreProcess(MParList *pList);
+    Int_t  Process();
+    Bool_t ReInit(MParList *plist=0);
+
+    //Int_t ReadRouting(const char *fname, TObjArray &arr);
+public:
+    MSimCalibrationSignal(const char *name=NULL, const char *title=NULL);
+
+    void SetNameGeomCam(const char *name="MGeomCam") { fNameGeomCam = name; }
+
+    UInt_t  GetEntries() { return fNumEntries; }
+    TString GetFullFileName() const { return "cer000000"; }
+    //virtual Bool_t  Rewind();
+
+    ClassDef(MSimCalibrationSignal, 0) // Task to create a fake signal (derives from MRead)
+};
+
+#endif
Index: /trunk/MagicSoft/Mars/msimcamera/MSimCamera.cc
===================================================================
--- /trunk/MagicSoft/Mars/msimcamera/MSimCamera.cc	(revision 9256)
+++ /trunk/MagicSoft/Mars/msimcamera/MSimCamera.cc	(revision 9256)
@@ -0,0 +1,325 @@
+/* ======================================================================== *\
+!
+! *
+! * This file is part of CheObs, the Modular Analysis and Reconstruction
+! * Software. It is distributed to you in the hope that it can be a useful
+! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
+! * It is distributed WITHOUT ANY WARRANTY.
+! *
+! * Permission to use, copy, modify and distribute this software and its
+! * documentation for any purpose is hereby granted without fee,
+! * provided that the above copyright notice appears in all copies and
+! * that both that copyright notice and this permission notice appear
+! * in supporting documentation. It is provided "as is" without express
+! * or implied warranty.
+! *
+!
+!
+!   Author(s): Thomas Bretz,  1/2009 <mailto:tbretz@astro.uni-wuerzburg.de>
+!
+!   Copyright: CheObs Software Development, 2000-2009
+!
+!
+\* ======================================================================== */
+
+//////////////////////////////////////////////////////////////////////////////
+//
+//  MSimCamera
+//
+//  This task initializes the analog channels with analog noise and simulated
+//  the analog pulses from the photon signal.
+//
+//  Input Containers:
+//   MPhotonEvent
+//   MPhotonStatistics
+//   MRawRunHeader
+//
+//  Output Containers:
+//   MAnalogChannels
+//
+//////////////////////////////////////////////////////////////////////////////
+#include "MSimCamera.h"
+
+#include <TF1.h>
+
+#include "MLog.h"
+#include "MLogManip.h"
+
+#include "MSpline3.h"
+
+#include "MParList.h"
+
+#include "MPhotonEvent.h"
+#include "MPhotonData.h"
+
+#include "MAnalogSignal.h"
+#include "MAnalogChannels.h"
+
+#include "MRawRunHeader.h"
+
+ClassImp(MSimCamera);
+
+using namespace std;
+
+// --------------------------------------------------------------------------
+//
+//  Default Constructor.
+//
+MSimCamera::MSimCamera(const char* name, const char *title)
+: fEvt(0), fStat(0), fRunHeader(0), fCamera(0), fSpline(0),
+  fFunction("exp(-(x/2)^2/2)"), fNpx(25), fXmin(-25), fXmax(25)
+{
+    fName  = name  ? name  : "MSimCamera";
+    fTitle = title ? title : "Task to simulate the electronic noise and to convert photons into pulses";
+}
+
+// --------------------------------------------------------------------------
+//
+//  Call Clear()
+//
+MSimCamera::~MSimCamera()
+{
+    Clear();
+}
+
+// --------------------------------------------------------------------------
+//
+//  Delete fSpline if set and set it to 0
+//
+void MSimCamera::Clear(Option_t *)
+{
+    if (fSpline)
+        delete fSpline;
+    fSpline=0;
+}
+
+// --------------------------------------------------------------------------
+//
+//  Read the intended pulse shape from a file and initialize the spline
+// accordingly
+//
+Bool_t MSimCamera::ReadFile(const char *fname)
+{
+    if (!fRunHeader)
+        return kFALSE;
+
+    if (fname)
+        fFileName = fname;
+
+    *fLog << inf << "Reading pulse shape from " << fFileName << endl;
+
+    const TGraph g(fFileName);
+    if (g.GetN()==0)
+    {
+        *fLog << err << "ERROR - No data points from " << fFileName << "." << endl;
+        return kFALSE;
+    }
+
+    // option: b1/e1 b2/e2   (first second derivative?)
+    // option: valbeg/valend (first second derivative?)
+
+    Clear();
+    fSpline = new MSpline3(g, fRunHeader->GetFreqSampling()/1000.);
+
+    return kTRUE;
+}
+
+void MSimCamera::SetFunction(const TF1 &f)
+{
+    // FIXME: Use TF1 directly? (In most cases this seems to be slower)
+    if (!fRunHeader)
+        return;// kFALSE;
+
+    // option: b1/e1 b2/e2   (first second derivative?)
+    // option: valbeg/valend (first second derivative?)
+
+    // if (f.GetNpar()==0)
+    // No SUPPORT
+
+    Clear();
+    fSpline = new MSpline3(f, fRunHeader->GetFreqSampling()/1000.);
+
+    fFunction = f.GetTitle();
+}
+
+Bool_t MSimCamera::SetFunction(const char *func, Int_t n, Double_t xmin, Double_t xmax)
+{
+    // FIXME: Use TF1 directly? (In most cases this seems to be slower)
+    TF1 f("f", func, xmin, xmax);
+    f.SetNpx(n);
+
+    SetFunction(f);
+
+    return kTRUE;
+}
+
+// --------------------------------------------------------------------------
+//
+// SetReadyToSave for fRunHeader
+//
+Bool_t MSimCamera::ReInit(MParList *pList)
+{
+    // make that the run-header gets written to the file
+    fRunHeader->SetReadyToSave();
+
+    return kTRUE;
+}
+
+// --------------------------------------------------------------------------
+//
+// Search for the necessayr parameter containers.
+// Setup spline for pulse shape.
+//
+Int_t MSimCamera::PreProcess(MParList *pList)
+{
+    fCamera = (MAnalogChannels*)pList->FindCreateObj("MAnalogChannels");
+    if (!fCamera)
+        return kFALSE;
+
+    fEvt = (MPhotonEvent*)pList->FindObject("MPhotonEvent");
+    if (!fEvt)
+    {
+        *fLog << err << "MPhotonEvent not found... aborting." << endl;
+        return kFALSE;
+    }
+
+    fStat = (MPhotonStatistics*)pList->FindObject("MPhotonStatistics");
+    if (!fStat)
+    {
+        *fLog << err << "MPhotonStatistics not found... aborting." << endl;
+        return kFALSE;
+    }
+
+    fRunHeader = (MRawRunHeader *)pList->FindObject("MRawRunHeader");
+    if (!fRunHeader)
+    {
+        *fLog << err << "MRawRunHeader not found... aborting." << endl;
+        return kFALSE;
+    }
+
+
+    // FIMXE: Move to ReInit in case fRunHeader is read form file?
+    if (!fFileName.IsNull())
+        return ReadFile(fFileName);
+
+    if (!fFunction.IsNull())
+        return SetFunction(fFunction, fNpx, fXmin, fXmax);
+
+    if (!fSpline)
+    {
+        *fLog << err << "No spline initialized." << endl;
+        return kFALSE;
+    }
+
+    return kTRUE;
+}
+
+// --------------------------------------------------------------------------
+//
+// fStat->GetMaxIndex must return the maximum index possible
+// (equiv. number of pixels) not just the maximum index stored!
+//
+Int_t MSimCamera::Process()
+{
+    // Calculate start time, end time and corresponding number of samples
+    const Double_t freq = fRunHeader->GetFreqSampling()/1000.;
+
+    const Double_t start = fStat->GetTimeFirst()*freq + fSpline->GetXmin();
+    const Double_t end   = fStat->GetTimeLast() *freq + fSpline->GetXmax();
+
+    const UInt_t   nlen  = TMath::CeilNint(end-start);
+
+    // FIXME: Jitter the start point of digitization by one sample [0;1]
+    // FIXME: TAKE PULSE WIDTH out of the calculation and start at TimeFirst
+
+    // Get number of pixels/channels
+    const UInt_t npix = fStat->GetMaxIndex()+1;
+
+    // Init the arrays and set the range which will contain valid data
+    fCamera->Init(npix, nlen);
+    fCamera->SetValidRange(0   -TMath::FloorNint(fSpline->GetXmin()),
+                           nlen-TMath::CeilNint( fSpline->GetXmax()));
+
+    // Add electronic noise to empty channels
+    for (UInt_t i=0; i<npix; i++)
+    {
+        // FIXME: We might add the base line here already.
+        (*fCamera)[i].AddGaussianNoise(22.5/64);
+    }
+
+    // FIXME: Simulate correlations with neighboring pixels
+
+    const Int_t num = fEvt->GetNumPhotons();
+
+    // Simulate pulses
+    for (Int_t i=0; i<num; i++)
+    {
+        const MPhotonData &ph = (*fEvt)[i];
+
+        const UInt_t   idx = ph.GetTag();
+        const Double_t t   = (ph.GetTime()-fStat->GetTimeFirst())*freq - fSpline->GetXmin();
+
+        // FIXME: Time jitter?
+        // FIXME: Add additional routing here?
+
+        (*fCamera)[idx].AddPulse(*fSpline, t, ph.GetWeight());
+    }
+
+    return kTRUE;
+}
+
+// --------------------------------------------------------------------------
+//
+// FileName: pulse-shape.txt
+// Function.Name: gaus
+// Function.Npx:    50
+// Function.Xmin:  -5
+// Function.Xmax:   5
+//
+Int_t MSimCamera::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
+{
+    Bool_t rc = kFALSE;
+    if (IsEnvDefined(env, prefix, "FileName", print))
+    {
+        rc = kTRUE;
+        SetFileName(GetEnvValue(env, prefix, "FileName", fFileName));
+    }
+
+    if (IsEnvDefined(env, prefix, "Function.Name", print))
+    {
+        rc = kTRUE;
+        SetFunction(GetEnvValue(env, prefix, "Function.Name", fFunction));
+
+        if (IsEnvDefined(env, prefix, "Function.Npx", print))
+            fNpx = GetEnvValue(env, prefix, "Function.Npx", fNpx);
+        if (IsEnvDefined(env, prefix, "Function.Xmin", print))
+            fXmin = GetEnvValue(env, prefix, "Function.Xmin", fXmin);
+        if (IsEnvDefined(env, prefix, "Function.Xmax", print))
+            fXmax = GetEnvValue(env, prefix, "Function.Xmax", fXmax);
+    }
+
+    return rc;
+}
+
+/*
+MSimCameraFiles::Process()
+{
+    // fCorsikaHeader->GetEvtNumber()   -->   fMcEvt->SetEvtNumber()
+    // fCorsikaHeader->GetTotalEnergy() -->   fMcEvt->SetEnergy()
+    // fCorsikaHeader->GetParticleID()  -->   fMcEvt->SetParticleID()
+    // fCorsikaHeader->GetImpact()      -->   fMcEvt->SetImpact()
+    // fCorsikaHeader->GetTheta()       -->   fMcEvt->SetTheta()
+    // fCorsikaHeader->GetPhi()         -->   fMcEvt->SetPhi()
+    // fPointingPos->GetTheta()         -->   fMcEvt->SetTelescopeTheta()
+    // fPointingPos->GetPhi()           -->   fMcEvt->SetTelescopePhi()
+    // fStats->GetTimeFirst()           -->   fMcEvt->SetTimeFirst()
+    // fStats->GetTimeLast()            -->   fMcEvt->SetTimeLast()
+    //                                        fMcEvt->SetReuse()
+    // MMcCorsikaRunHeader: fSlopeSpec, fELowLim, fEUppLim;
+
+    fMcEvt->Fill(*fCorsikaHeader, *fPointingPos, *fStats);
+
+    return kTRUE;
+}
+*/
+
Index: /trunk/MagicSoft/Mars/msimcamera/MSimCamera.h
===================================================================
--- /trunk/MagicSoft/Mars/msimcamera/MSimCamera.h	(revision 9256)
+++ /trunk/MagicSoft/Mars/msimcamera/MSimCamera.h	(revision 9256)
@@ -0,0 +1,59 @@
+#ifndef MARS_MSimCamera
+#define MARS_MSimCamera
+
+#ifndef MARS_MTask
+#include "MTask.h"
+#endif
+
+class MParList;
+class MPhotonEvent;
+class MPhotonStatistics;
+class MRawRunHeader;
+class MAnalogChannels;
+
+class TF1;
+class MSpline3;
+
+class MSimCamera : public MTask
+{
+private:
+    MPhotonEvent      *fEvt;        //! Event stroing the photons
+    MPhotonStatistics *fStat;       //! Valid time range of the phootn event
+    MRawRunHeader     *fRunHeader;  //! Sampling frequency
+
+    MAnalogChannels   *fCamera;     //! Output of the analog signals
+
+    MSpline3          *fSpline;     //! Spline to describe the pulse shape
+
+    TString fFileName;              // File name of a file describing the pulse shape
+
+    TString fFunction;              // Function describing the pulse shape
+    Int_t   fNpx;                   // Number of
+    Float_t fXmin;
+    Float_t fXmax;
+
+    // MParContainer
+    Int_t ReadEnv(const TEnv &env, TString prefix, Bool_t print=kFALSE);
+
+    // MTask
+    Int_t PreProcess(MParList *pList);
+    Int_t Process();
+    Bool_t ReInit(MParList *pList);
+
+    Bool_t ReadFile(const char *fname);
+    Bool_t SetFunction(const char *func, Int_t n, Double_t xmin, Double_t xmax);
+
+public:
+    MSimCamera(const char *name=NULL, const char *title=NULL);
+    ~MSimCamera();
+
+    void SetFunction(const TF1 &f);
+    void SetFunction(const char *f)  { fFunction=f; fFileName=""; }
+    void SetFileName(const char *n)  { fFileName=n; fFunction=""; }
+
+    void Clear(Option_t *o="");
+
+    ClassDef(MSimCamera, 0) // Task to simulate the electronic noise and to convert photons into pulses
+};
+
+#endif
Index: /trunk/MagicSoft/Mars/msimcamera/MSimReadout.cc
===================================================================
--- /trunk/MagicSoft/Mars/msimcamera/MSimReadout.cc	(revision 9256)
+++ /trunk/MagicSoft/Mars/msimcamera/MSimReadout.cc	(revision 9256)
@@ -0,0 +1,225 @@
+/* ======================================================================== *\
+!
+! *
+! * This file is part of CheObs, the Modular Analysis and Reconstruction
+! * Software. It is distributed to you in the hope that it can be a useful
+! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
+! * It is distributed WITHOUT ANY WARRANTY.
+! *
+! * Permission to use, copy, modify and distribute this software and its
+! * documentation for any purpose is hereby granted without fee,
+! * provided that the above copyright notice appears in all copies and
+! * that both that copyright notice and this permission notice appear
+! * in supporting documentation. It is provided "as is" without express
+! * or implied warranty.
+! *
+!
+!
+!   Author(s): Thomas Bretz,  1/2009 <mailto:tbretz@astro.uni-wuerzburg.de>
+!
+!   Copyright: CheObs Software Development, 2000-2009
+!
+!
+\* ======================================================================== */
+
+//////////////////////////////////////////////////////////////////////////////
+//
+//  MSimReadout
+//
+// Task to convert the analog channels into a digital signal. This should
+// simulate the conversion and saturation bahaviour of the FADC/readout
+// system.
+//
+//
+//  Input Containers:
+//   MAnalogChannels
+//   TriggerPos [MParameterD]
+//   IntendedPulsePos [MParameterD]
+//   MRawRunHeader
+//
+//  Output Containers:
+//   MRawEvtData
+//   MRawEvtHeader
+//
+//////////////////////////////////////////////////////////////////////////////
+#include "MSimReadout.h"
+
+#include "MLog.h"
+#include "MLogManip.h"
+
+#include "MArrayI.h"
+
+#include "MParList.h"
+#include "MParameters.h"
+
+#include "MRawRunHeader.h"
+#include "MRawEvtHeader.h"
+#include "MRawEvtData.h"
+
+#include "MAnalogSignal.h"
+#include "MAnalogChannels.h"
+
+ClassImp(MSimReadout);
+
+using namespace std;
+
+
+// ------------------------------------------------------------------------
+//
+// Default constructor
+//
+MSimReadout::MSimReadout(const char* name, const char *title)
+: fRunHeader(0), fCamera(0), fPulsePos(0), fTrigger(0), fData(0)
+{
+    fName  = name  ? name  : "MSimReadout";
+    fTitle = title ? title : "Task to simulate the analog readout (FADCs)";
+}
+
+// ------------------------------------------------------------------------
+//
+// Look for the needed parameter containers.
+// Initialize MRawEvtData from MRawEvtRunHeader.
+//
+Int_t MSimReadout::PreProcess(MParList *pList)
+{
+    fCamera = (MAnalogChannels*)pList->FindObject("MAnalogChannels");
+    if (!fCamera)
+    {
+        *fLog << err << "MAnalogChannels not found... aborting." << endl;
+        return kFALSE;
+    }
+
+    fTrigger = (MParameterD*)pList->FindObject("TriggerPos", "MParameterD");
+    if (!fTrigger)
+    {
+        *fLog << err << "TriggerPos [MParameterD] not found... aborting." << endl;
+        return kFALSE;
+    }
+
+    fPulsePos = (MParameterD*)pList->FindObject("IntendedPulsePos", "MParameterD");
+    if (!fPulsePos)
+    {
+        *fLog << err << "IntendedPulsePos [MParameterD] not found... aborting." << endl;
+        return kFALSE;
+    }
+
+
+    fRunHeader = (MRawRunHeader*)pList->FindObject("MRawRunHeader");
+    if (!fRunHeader)
+    {
+        *fLog << err << "MRawRunHeader not found... aborting." << endl;
+        return kFALSE;
+    }
+
+    // -----------------------------------------------------------------------
+
+    fData = (MRawEvtData*)pList->FindCreateObj("MRawEvtData");
+    if (!fData)
+        return kFALSE;
+
+    fData->InitRead(fRunHeader);
+    fData->ResetPixels();
+    fData->SetIndices();
+
+    return kTRUE;
+}
+
+// ------------------------------------------------------------------------
+//
+// Convert (digitize) the analog channels into digital (FADC) data.
+//
+Int_t MSimReadout::Process()
+{
+    // Sanity checks
+    if (fData->GetNumLoGainSamples()>0)
+    {
+        *fLog << err << "ERROR - Lo-gains not implemented yet." << endl;
+        return kERROR;
+    }
+
+    // Get Number of pixels
+    const UInt_t npix = fData->GetNumPixels();
+
+    // Sanity check
+    if (fData->GetNumPixels()!=fCamera->GetNumChannels())
+    {
+        *fLog << err << "ERROR - Number of analog channels doen't match number of pixels." << endl;
+        return kERROR;
+    }
+
+    if (fTrigger->GetVal()<0)
+    {
+        *fLog << err << "ERROR - MSimReadout executed for an event which has no trigger." << endl;
+        return kERROR;
+    }
+
+    // Get the intended pulse position and convert it to slices
+    const Float_t pulpos = fPulsePos->GetVal()*fRunHeader->GetFreqSampling()/1000.;
+
+    // Get trigger position and correct for intended pulse position
+    const Int_t trig = TMath::CeilNint(fTrigger->GetVal()-pulpos);
+
+    // Check if the position is valid
+    if (trig<0)
+    {
+        *fLog << err;
+        *fLog << "ERROR - Trigger position before analog signal." << endl;
+        *fLog << "        Trigger:  " << fTrigger->GetVal() << endl;
+        *fLog << "        PulsePos: " << pulpos << endl;
+        return kERROR;
+    }
+
+    // Get Number of samples in analog channels
+    const Int_t nsamp = fCamera->GetNumSamples();
+
+    // Get number of samples to be digitized
+    const Int_t nslices = fData->GetNumSamples();
+
+    // Check if the whole requested signal can be digitized
+    if (trig+nslices>=nsamp)
+    {
+        *fLog << err << "ERROR - Trigger position beyond valid analog signal range." << endl;
+        return kERROR;
+    }
+
+    const Float_t gain      = 64./1;
+    const Float_t offset    = 128;
+    const UInt_t  max       = fData->GetMax();
+
+    // FIXME: Take this into account
+//    const UInt_t scale      = 16;
+//    const UInt_t resolution = 12;
+
+    // Digitize into a buffer
+    MArrayI buffer(nslices*npix);
+
+    // Loop over all channels/pixels
+    for (UInt_t i=0; i<npix; i++)
+    {
+        // Get i-th canalog hannel
+        const MAnalogSignal &sig = (*fCamera)[i];
+
+        // Digitize all slices
+        for (Int_t j=0; j<nslices; j++)
+        {
+            Float_t slice = j+trig>=(Int_t)sig.GetSize() ? offset :
+                sig[j+trig] * gain + offset;
+
+            // FIXME: Handle/Implement saturation!
+            if (slice>max)
+                slice = max;
+            if (slice<0)
+                slice = 0;
+
+            // We have a 16 bit FADC. The resolution of the DRS4 is just about 11.5 bit.
+            // Therefore the last 4.5 bits (~22.5) are gaussian noise (is this right?)
+            buffer[nslices*i + j] = TMath::Nint(slice);
+        }
+    }
+
+    // Set samples as raw-data
+    fData->Set(buffer);
+    fData->SetReadyToSave();
+
+    return kTRUE;
+}
Index: /trunk/MagicSoft/Mars/msimcamera/MSimReadout.h
===================================================================
--- /trunk/MagicSoft/Mars/msimcamera/MSimReadout.h	(revision 9256)
+++ /trunk/MagicSoft/Mars/msimcamera/MSimReadout.h	(revision 9256)
@@ -0,0 +1,34 @@
+#ifndef MARS_MSimReadout
+#define MARS_MSimReadout
+
+#ifndef MARS_MTask
+#include "MTask.h"
+#endif
+
+class MParList;
+class MParameterD;
+class MRawEvtData;
+class MRawRunHeader;
+class MAnalogChannels;
+
+class MSimReadout : public MTask
+{
+private:
+    MRawRunHeader    *fRunHeader;  //! Digitization window and frequency
+    MAnalogChannels  *fCamera;     //! Analog channes to be read out
+    MParameterD      *fPulsePos;   //! Intended pulse position
+    MParameterD      *fTrigger;    //! Position of trigger in the analog signal
+
+    MRawEvtData      *fData;       //! Digitized FADC signal
+
+    // MTask
+    Int_t PreProcess(MParList *pList);
+    Int_t Process();
+
+public:
+    MSimReadout(const char *name=NULL, const char *title=NULL);
+
+    ClassDef(MSimReadout, 0) // Task to simulate the analog readout (FADCs)
+};
+
+#endif
Index: /trunk/MagicSoft/Mars/msimcamera/MSimTrigger.cc
===================================================================
--- /trunk/MagicSoft/Mars/msimcamera/MSimTrigger.cc	(revision 9256)
+++ /trunk/MagicSoft/Mars/msimcamera/MSimTrigger.cc	(revision 9256)
@@ -0,0 +1,290 @@
+/* ======================================================================== *\
+!
+! *
+! * This file is part of CheObs, the Modular Analysis and Reconstruction
+! * Software. It is distributed to you in the hope that it can be a useful
+! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
+! * It is distributed WITHOUT ANY WARRANTY.
+! *
+! * Permission to use, copy, modify and distribute this software and its
+! * documentation for any purpose is hereby granted without fee,
+! * provided that the above copyright notice appears in all copies and
+! * that both that copyright notice and this permission notice appear
+! * in supporting documentation. It is provided "as is" without express
+! * or implied warranty.
+! *
+!
+!
+!   Author(s): Thomas Bretz,  1/2009 <mailto:tbretz@astro.uni-wuerzburg.de>
+!
+!   Copyright: CheObs Software Development, 2000-2009
+!
+!
+\* ======================================================================== */
+
+//////////////////////////////////////////////////////////////////////////////
+//
+//  MSimTrigger
+//
+// This task takes the pure analog channels and simulates a trigger
+// electronics.
+//
+// In a first step several channels can be summed together by a look-up table
+// fRouteAC.
+//
+// In a second step from these analog channels the output of a discriminator
+// is calculated using a threshold and optional a fixed digital signal length.
+//
+// With a second look-up table fCoincidenceMap the analog channels are
+// checked for coincidences. The earliest coincide is then stored as
+// trigger position.
+//
+//
+//  Input Containers:
+//   IntendedPulsePos [MParameterD]
+//   MAnalogChannels
+//   MRawRunHeader
+//
+//  Output Containers:
+//   TriggerPos [MParameterD]
+//   MRawEvtHeader
+//
+//////////////////////////////////////////////////////////////////////////////
+#include "MSimTrigger.h"
+
+#include "MLog.h"
+#include "MLogManip.h"
+
+#include "MParList.h"
+#include "MParameters.h"
+
+#include "MLut.h"
+#include "MArrayI.h"
+
+#include "MRawEvtHeader.h"
+#include "MRawRunHeader.h"
+
+#include "MAnalogSignal.h"
+#include "MAnalogChannels.h"
+#include "MDigitalSignal.h"
+
+ClassImp(MSimTrigger);
+
+using namespace std;
+
+// --------------------------------------------------------------------------
+//
+//  Default Constructor.
+//
+MSimTrigger::MSimTrigger(const char *name, const char *title)
+    : fCamera(0), fPulsePos(0), fTrigger(0), fRunHeader(0), fEvtHeader(0)
+{
+    fName  = name  ? name  : "MSimTrigger";
+    fTitle = title ? title : "Task to simulate trigger electronics";
+}
+
+// --------------------------------------------------------------------------
+//
+// Take two TObjArrays with a collection of digital signals.
+// Every signal from one array is compared with any from the other array.
+// For all signals whihc overlaps and which have an overlap time >gate
+// a new digital signal is created storing start time and length of overlap.
+// They are collected in a newly allocated TObjArray. A pointer to this array
+// is returned.
+//
+// Th euser gains owenership of the object, ie.e., the user is responsible of
+// deleting the memory.
+//
+TObjArray *MSimTrigger::CalcCoincidence(const TObjArray &arr1, const TObjArray &arr2, Float_t gate) const
+{
+    TObjArray *res = new TObjArray;
+
+    if (arr1.GetEntriesFast()==0 || arr2.GetEntriesFast()==0)
+        return res;
+
+    TIter Next1(&arr1);
+    MDigitalSignal *ttl1 = 0;
+    while ((ttl1=static_cast<MDigitalSignal*>(Next1())))
+    {
+        TIter Next2(&arr2);
+        MDigitalSignal *ttl2 = 0;
+        while ((ttl2=static_cast<MDigitalSignal*>(Next2())))
+        {
+            MDigitalSignal *ttl = new MDigitalSignal(*ttl1, *ttl2);
+
+            if (ttl->GetLength()<=gate)
+            {
+                delete ttl;
+                continue;
+            }
+
+            res->Add(ttl);
+        }
+    }
+
+    res->SetOwner();
+
+    return res;
+}
+
+// --------------------------------------------------------------------------
+//
+// Check for the necessary parameter containers. Read the luts.
+//
+Int_t MSimTrigger::PreProcess(MParList *pList)
+{
+    fTrigger = (MParameterD*)pList->FindCreateObj("MParameterD", "TriggerPos");
+    if (!fTrigger)
+        return kFALSE;
+
+    fPulsePos = (MParameterD*)pList->FindObject("IntendedPulsePos", "MParameterD");
+    if (!fPulsePos)
+    {
+        *fLog << err << "IntendedPulsePos [MParameterD] not found... aborting." << endl;
+        return kFALSE;
+    }
+
+    fCamera = (MAnalogChannels*)pList->FindObject("MAnalogChannels");
+    if (!fCamera)
+    {
+        *fLog << err << "MAnalogChannels not found... aborting." << endl;
+        return kFALSE;
+    }
+
+    fRunHeader = (MRawRunHeader*)pList->FindObject("MRawRunHeader");
+    if (!fRunHeader)
+    {
+        *fLog << err << "MRawRunHeader not found... aborting." << endl;
+        return kFALSE;
+    }
+
+    fEvtHeader = (MRawEvtHeader*)pList->FindCreateObj("MRawEvtHeader");
+    if (!fEvtHeader)
+        return kFALSE;
+
+
+    if (fRouteAC.ReadFile(fNameRouteAC)<0)
+        return kFALSE;
+
+    if (fCoincidenceMap.ReadFile(fNameCoincidenceMap)<0)
+        return kFALSE;
+
+    return kTRUE;
+}
+
+// --------------------------------------------------------------------------
+//
+Int_t MSimTrigger::Process()
+{
+    // Invalidate trigger
+    fTrigger->SetVal(-1);
+
+    // FIXME: Set from somewhere else? (see also MSimCalibrationSignal)
+    fEvtHeader->SetDAQEvtNumber(GetNumExecutions());
+    fEvtHeader->SetReadyToSave();
+
+    // ================== Simulate channel bundling ====================
+
+    const UInt_t npatch = fRouteAC.GetEntriesFast();
+
+    MAnalogChannels patches(npatch, fCamera->GetNumSamples());
+
+    for (UInt_t i=0; i<npatch; i++)
+    {
+        const MArrayI &row = fRouteAC.GetRow(i);
+        for (UInt_t j=0; j<row.GetSize(); j++)
+        {
+            const UInt_t idx = row[j];
+            patches[i].AddSignal((*fCamera)[idx]);
+        }
+    }
+
+    // FIXME: Write patches
+
+    // ================== Simulate discriminators ====================
+
+    TObjArray ttls(npatch);
+    ttls.SetOwner();
+
+        // MAGIC: Constant length of signals between 6ns and 12ns
+    const Double_t siglen = 8; // Signal length (-1: As long as Signal-above-Threshold)
+
+    for (UInt_t i=0; i<npatch; i++)
+        ttls.AddAt(patches[i].Discriminate(fDiscriminatorThreshold, siglen), i);
+
+    // FIXME: Write TTLs!
+
+    // =================== Simulate coincidences ======================
+
+    // Calculate the minimum and maximum time for a valid trigger
+    const Double_t freq    = fRunHeader->GetFreqSampling()/1000.;
+    const Float_t  nsamp   = fRunHeader->GetNumSamplesHiGain();
+    const Float_t  pulspos = fPulsePos->GetVal()/freq;
+
+    const Float_t min = fCamera->GetValidRangeMin()+pulspos;
+    const Float_t max = fCamera->GetValidRangeMax()+pulspos-nsamp;
+
+    // Define gate time (minimum coincidence time)
+    const Double_t gate = 1; // MAGIC: minimum coincidence time 0.25ns to 1ns,
+
+    // Create an array for the individual triggers
+    TObjArray triggers;
+    triggers.SetOwner();
+
+    for (int j=0; j<fCoincidenceMap.GetEntries(); j++)
+    {
+        const MArrayI &idx = fCoincidenceMap.GetRow(j);
+
+        // Start with a copy of the first coincidence channel
+        TObjArray *arr = static_cast<TObjArray*>(ttls[idx[0]]->Clone());
+        arr->SetOwner();
+
+        // compare to all other channels in this coincidence patch, one by one
+        for (UInt_t k=1; k<idx.GetSize() && arr->GetEntriesFast()>0; k++)
+        {
+            TObjArray *res = CalcCoincidence(*arr, *static_cast<TObjArray*>(ttls[idx[k]]),
+                                             gate);
+
+            // Delete the original array and keep the new one
+            delete arr;
+            arr = res;
+        }
+
+        // Remove all signals which are not in the valid digitization range
+        // (This is not the digitization window, but the region in which
+        //  the analog channels contain usefull data)
+        TIter Next(arr);
+        MDigitalSignal *ttl = 0;
+        while ((ttl=static_cast<MDigitalSignal*>(Next())))
+            if (ttl->GetStart()<min || ttl->GetStart()>max)
+                delete arr->Remove(ttl);
+
+        // If we have at least one trigger keep the earliest one.
+        // FIXME: The triggers should be ordered in time automatically: To be checked!
+        // FIXME: Simulate trigger dead-time!
+        if (arr->GetEntriesFast()>0)
+            triggers.Add(arr->RemoveAt(0));
+
+        // delete the allocated space
+        delete arr;
+    }
+
+    // No trigger issued. Go on.
+    if (triggers.GetEntriesFast()==0)
+        return kTRUE;
+
+    // There are usually not enough entries that it is worth to search
+    // for the earliest instead of just sorting and taking the first one
+    //  FIXME: This could be improved if checking for IsSortable
+    //         is omitted
+    triggers.Sort();
+
+    // FIXME: Jitter! (Own class?)
+    fTrigger->SetVal(static_cast<MDigitalSignal*>(triggers[0])->GetStart());
+
+
+    // inf2?
+    *fLog << all << triggers.GetEntriesFast() << " triggers in " << triggers.GetEntriesFast() << " patches." << endl;
+
+    return kTRUE;
+}
Index: /trunk/MagicSoft/Mars/msimcamera/MSimTrigger.h
===================================================================
--- /trunk/MagicSoft/Mars/msimcamera/MSimTrigger.h	(revision 9256)
+++ /trunk/MagicSoft/Mars/msimcamera/MSimTrigger.h	(revision 9256)
@@ -0,0 +1,53 @@
+#ifndef MARS_MSimTrigger
+#define MARS_MSimTrigger
+
+#ifndef MARS_MTask
+#include "MTask.h"
+#endif
+
+#ifndef MARS_MLut
+#include "MLut.h"
+#endif
+
+class MParList;
+class MParameterD;
+class MAnalogChannels;
+class MRawEvtHeader;
+class MRawRunHeader;
+
+class MSimTrigger : public MTask
+{
+private:
+    MAnalogChannels *fCamera;         //! The analog input channels
+    MParameterD     *fPulsePos;       //! The intended pulse positon
+    MParameterD     *fTrigger;        //! The trigger position w.r.t. the analog channels
+    MRawRunHeader   *fRunHeader;      //! The run header storing infos about the digitization
+    MRawEvtHeader   *fEvtHeader;      //! The event header storing the trigger information
+
+    MLut fRouteAC;                    // Combinination map for the AC channels
+    MLut fCoincidenceMap;             // channels for which digital coincidence is checked
+
+    TString fNameRouteAC;             // Name for the AC routing
+    TString fNameCoincidenceMap;      // Name for the coincidence mape
+
+    Float_t fDiscriminatorThreshold;  // Discriminator threshold
+
+    // MSimTrigger
+    TObjArray *CalcCoincidence(const TObjArray &arr1, const TObjArray &arr2, Float_t gate=0) const;
+
+    // MTask
+    Int_t PreProcess(MParList *pList);
+    Int_t Process();
+
+public:
+    MSimTrigger(const char *name=NULL, const char *title=NULL);
+
+    void SetNameRouteAC(const char *name) { fNameRouteAC=name; }
+    void SetNameCoincidenceMap(const char *name) { fNameCoincidenceMap=name; }
+
+    void SetDiscriminatorThreshold(Float_t th) { fDiscriminatorThreshold=th; }
+
+    ClassDef(MSimTrigger, 0) // Task to simulate trigger electronics
+};
+
+#endif
Index: /trunk/MagicSoft/Mars/msimcamera/Makefile
===================================================================
--- /trunk/MagicSoft/Mars/msimcamera/Makefile	(revision 9256)
+++ /trunk/MagicSoft/Mars/msimcamera/Makefile	(revision 9256)
@@ -0,0 +1,42 @@
+##################################################################
+#
+#   makefile
+# 
+#   for the MARS software
+#
+##################################################################
+include ../Makefile.conf.$(OSTYPE)
+include ../Makefile.conf.general
+
+#------------------------------------------------------------------------------
+
+#
+# Handling name of the Root Dictionary Files
+#
+CINT  = SimCamera
+
+#
+#  connect the include files defined in the config.mk file
+#
+INCLUDES = -I. -I../mbase -I../mgeom -I../msim -I../msignal -I../mcorsika \
+	   -I../mmc -I../mgui -I../mcalib -I../mraw -I../mfileio -I../melectronics
+
+SRCFILES = MSimPSF.cc \
+	   MSimGeomCam.cc \
+	   MSimRandomPhotons.cc \
+	   MSimAPD.cc \
+	   MSimBundlePhotons.cc \
+	   MSimCalibrationSignal.cc \
+	   MSimExcessNoise.cc \
+	   MSimCamera.cc \
+	   MSimTrigger.cc \
+	   MSimReadout.cc \
+	   MSimSignalCam.cc
+
+############################################################
+
+all: $(OBJS)
+
+include ../Makefile.rules
+
+mrproper:	clean rmbak
Index: /trunk/MagicSoft/Mars/msimcamera/SimCameraIncl.h
===================================================================
--- /trunk/MagicSoft/Mars/msimcamera/SimCameraIncl.h	(revision 9256)
+++ /trunk/MagicSoft/Mars/msimcamera/SimCameraIncl.h	(revision 9256)
@@ -0,0 +1,3 @@
+#ifndef __CINT__
+
+#endif // __CINT__
Index: /trunk/MagicSoft/Mars/msimcamera/SimCameraLinkDef.h
===================================================================
--- /trunk/MagicSoft/Mars/msimcamera/SimCameraLinkDef.h	(revision 9256)
+++ /trunk/MagicSoft/Mars/msimcamera/SimCameraLinkDef.h	(revision 9256)
@@ -0,0 +1,20 @@
+#ifdef __CINT__
+
+#pragma link off all globals;
+#pragma link off all classes;
+#pragma link off all functions;
+
+#pragma link C++ class MSimPSF+;
+#pragma link C++ class MSimGeomCam+;
+#pragma link C++ class MSimRandomPhotons+;
+#pragma link C++ class MSimAPD+;
+#pragma link C++ class MSimExcessNoise+;
+#pragma link C++ class MSimBundlePhotons+;
+#pragma link C++ class MSimSignalCam+;
+
+#pragma link C++ class MSimCamera+;
+#pragma link C++ class MSimTrigger+;
+#pragma link C++ class MSimReadout+;
+#pragma link C++ class MSimCalibrationSignal+;
+
+#endif
