Index: trunk/MagicSoft/Mars/melectronics/ElectronicsLinkDef.h
===================================================================
--- trunk/MagicSoft/Mars/melectronics/ElectronicsLinkDef.h	(revision 9270)
+++ trunk/MagicSoft/Mars/melectronics/ElectronicsLinkDef.h	(revision 9274)
@@ -6,4 +6,5 @@
 
 #pragma link C++ class APD+;
+#pragma link C++ class MPulseShape+;
 #pragma link C++ class MAnalogSignal+;
 #pragma link C++ class MDigitalSignal+;
Index: trunk/MagicSoft/Mars/melectronics/MAnalogSignal.cc
===================================================================
--- trunk/MagicSoft/Mars/melectronics/MAnalogSignal.cc	(revision 9270)
+++ trunk/MagicSoft/Mars/melectronics/MAnalogSignal.cc	(revision 9274)
@@ -33,4 +33,5 @@
 #include "MAnalogSignal.h"
 
+#include <TF1.h>
 #include <TRandom.h>
 #include <TObjArray.h>
@@ -69,5 +70,8 @@
 // and multiplied by f.
 //
-void MAnalogSignal::AddPulse(const MSpline3 &spline, Float_t t, Float_t f)
+// Return kTRUE if the full range of the spline could be added to the
+// analog signal, kFALSE otherwise.
+//
+Bool_t MAnalogSignal::AddPulse(const MSpline3 &spline, Float_t t, Float_t f)
 {
     // FIXME: This could be improved using a MExtralgoSpline with
@@ -79,22 +83,68 @@
     const Float_t end   = t+spline.GetXmax();
 
-    /*const*/ Int_t  first = TMath::CeilNint(start);
-    /*const*/ UInt_t last  = TMath::CeilNint(end); // Ceil:< Floor:<=
-
-    if (first<0 || last>GetSize())
-    {
-        gLog << err << "ERROR - AddPulse: Out of bounds, ";
-        gLog << "Win=[" << first << "," << last << "] N=" << GetSize() << " t=" << t;
-        gLog << " Spline=[" << spline.GetXmin() << "," << spline.GetXmax() << "]" << endl;
-
-        if (first<0)
-            first=0;
-        if (last>GetSize())
-            last=GetSize();
-    }
+    Int_t  first = TMath::CeilNint(start);
+    UInt_t last  = TMath::CeilNint(end); // Ceil:< Floor:<=
+
+    Bool_t rc = kTRUE;
+    if (first<0)
+    {
+        first=0;
+        rc = kFALSE;
+    }
+    if (last>GetSize())
+    {
+        last=GetSize();
+        rc = kFALSE;
+    }
+
+    // FIXME: As soon as we have access to TSpline3::fPoly we can
+    //        gain a lot in execution speed here.
 
     Float_t *arr = GetArray();
     for (UInt_t i=first; i<last; i++)
         arr[i] += spline.Eval(i-t)*f;
+
+    return rc;
+}
+
+// ------------------------------------------------------------------------
+//
+// Evaluate the spline an add the result between t+xmin and t+xmax
+// (xmin and xmax are the limits of the TF1) to the signal.
+// The spline is evaluated at the bin-center of the analog signal
+// and multiplied by f.
+//
+// Return kTRUE if the full range of the function could be added to the
+// analog signal, kFALSE otherwise.
+//
+Bool_t MAnalogSignal::AddPulse(const TF1 &func, Float_t t, Float_t f)
+{
+    // Both in units of the sampling frequency
+    const Float_t start = t+func.GetXmin();
+    const Float_t end   = t+func.GetXmax();
+
+    Int_t  first = TMath::CeilNint(start);
+    UInt_t last  = TMath::CeilNint(end); // Ceil:< Floor:<=
+
+    Bool_t rc = kTRUE;
+    if (first<0)
+    {
+        first=0;
+        rc = kFALSE;
+    }
+    if (last>GetSize())
+    {
+        last=GetSize();
+        rc = kFALSE;
+    }
+
+    // FIXME: As soon as we have access to TSpline3::fPoly we can
+    //        gain a lot in execution speed here.
+
+    Float_t *arr = GetArray();
+    for (UInt_t i=first; i<last; i++)
+        arr[i] += func.Eval(i-t)*f;
+
+    return rc;
 }
 
@@ -156,5 +206,5 @@
 // The user is responsible of deleting the TObjArray.
 //
-TObjArray *MAnalogSignal::Discriminate(Float_t threshold, Float_t len) const
+TObjArray *MAnalogSignal::Discriminate(Float_t threshold, Double_t start, Double_t end, Float_t len) const
 {
     TObjArray *ttl = new TObjArray;
@@ -175,36 +225,39 @@
 
     Double_t x1 = 0;
-    Double_t x2 = 0;
+    Double_t x2 = start;  // Start searching at x2
 
     while (1)
     {
-        x1 = sp.SearchYup(x2+deadtime, threshold);
-        if (x1<0)
-            break;
-
-        const Bool_t rising = sp.Deriv1(x1)>0;
-        if (!rising)
+        // Search for the next rising edge (starting at x2)
+        while (1)
         {
-            // The last value might just have been a local max/min
-            // or its period was short than 1e-4
+            x1 = sp.SearchYup(x2+deadtime, threshold);
+            if (x1<0 || x1>=end)
+                return ttl;
+
+            const Bool_t rising = sp.Deriv1(x1)>0;
+            if (rising)
+                break;
+
             x2 = x1;
-            //gLog << warn << "Rising edge expected at " << x1 << " (after " << x2 << ", N=" << fN << ")" << endl;
-            continue;
         }
 
-        x2 = sp.SearchYup(x1+deadtime, threshold);
-        if (x2<0)
-            break;
-
-        const Bool_t falling = sp.Deriv1(x2)<=0;
-        if (!falling)
+        // Search for the next falling edge (starting at x1)
+        while (1)
         {
-            // The last value might just have been a local max/min
-            // or its period was short than 1e-4
+            x2 = sp.SearchYup(x1+deadtime, threshold);
+            if (x2<0)
+                x2 = end;
+            if (x2>=end)
+                break;
+
+            const Bool_t falling = sp.Deriv1(x2)<0;
+            if (falling)
+                break;
+
             x1 = x2;
-            //gLog << warn << "Falling edge expected at " << x2 << " (after " << x1 << " N=" << fN << ")" << endl;
-            continue;
         }
 
+        // We found a rising and a falling edge
         MDigitalSignal *sig = new MDigitalSignal(x1, len>0?len:x2-x1);
 
@@ -228,7 +281,4 @@
     }
 
-    if (x1>=0)
-        gLog << warn << "Falling edge expected before end at N=" << fN << "!" << endl;
-
     return ttl;
 }
Index: trunk/MagicSoft/Mars/melectronics/MAnalogSignal.h
===================================================================
--- trunk/MagicSoft/Mars/melectronics/MAnalogSignal.h	(revision 9270)
+++ trunk/MagicSoft/Mars/melectronics/MAnalogSignal.h	(revision 9274)
@@ -6,4 +6,5 @@
 #endif
 
+class TF1;
 class MSpline3;
 
@@ -17,7 +18,8 @@
     MAnalogSignal(UInt_t n) { Set(n); }
 
-    void Set(UInt_t n);
-    void AddPulse(const MSpline3 &spline, Float_t t, Float_t f=1);
-    void AddSignal(const MAnalogSignal &s);
+    void   Set(UInt_t n);
+    Bool_t AddPulse(const MSpline3 &spline, Float_t t, Float_t f=1);
+    Bool_t AddPulse(const TF1 &f1, Float_t t, Float_t f=1);
+    void   AddSignal(const MAnalogSignal &s);
 
     // Deprecated. Use MSimRandomPhotons instead
@@ -26,5 +28,6 @@
     void AddGaussianNoise(Float_t amplitude=1, Float_t offset=0);
 
-    TObjArray *Discriminate(Float_t threshold, Float_t len=-1) const;
+    TObjArray *Discriminate(Float_t threshold, Double_t start, Double_t end, Float_t len=-1) const;
+    TObjArray *Discriminate(Float_t threshold, Float_t len=-1) const { return Discriminate(threshold, 0, fN-1, len); }
 
     ClassDef(MAnalogSignal, 1) // Storage class for an analog signal
Index: trunk/MagicSoft/Mars/melectronics/MPulseShape.cc
===================================================================
--- trunk/MagicSoft/Mars/melectronics/MPulseShape.cc	(revision 9274)
+++ trunk/MagicSoft/Mars/melectronics/MPulseShape.cc	(revision 9274)
@@ -0,0 +1,195 @@
+/* ======================================================================== *\
+!
+! *
+! * 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
+!
+!
+\* ======================================================================== */
+
+//////////////////////////////////////////////////////////////////////////////
+//
+//  MPulseShape
+//
+// This container describes the pulse shape of a pulse.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include "MPulseShape.h"
+
+#include <TF1.h>
+
+#include "MLog.h"
+#include "MLogManip.h"
+
+#include "MSpline3.h"
+
+ClassImp(MPulseShape);
+
+using namespace std;
+
+// --------------------------------------------------------------------------
+//
+//  Default Constructor.
+//
+MPulseShape::MPulseShape(const char* name, const char *title)
+: fSpline(0), fFunction("exp(-(x/2)^2/2)"), fNpx(25), fXmin(-25), fXmax(25)
+{
+    fName  = name  ? name  : "MPulseShape";
+    fTitle = title ? title : "";
+
+    SetFunction(fFunction, fNpx, fXmin, fXmax);
+}
+
+// --------------------------------------------------------------------------
+//
+//  Call Clear()
+//
+MPulseShape::~MPulseShape()
+{
+    Clear();
+}
+
+// --------------------------------------------------------------------------
+//
+//  Delete fSpline if set and set it to 0
+//
+void MPulseShape::Clear(Option_t *)
+{
+    if (fSpline)
+        delete fSpline;
+    fSpline=0;
+}
+
+// --------------------------------------------------------------------------
+//
+//  Return the width of the range in which the spline is defined.
+//
+Float_t MPulseShape::GetPulseWidth() const
+{
+    return fSpline ? fSpline->GetXmax()-fSpline->GetXmin() : 0;
+}
+
+// --------------------------------------------------------------------------
+//
+//  Return the lower edge of the range in which the spline is defined.
+//
+Float_t MPulseShape::GetXmin() const
+{
+    return fSpline ? fSpline->GetXmin() : 0;
+}
+
+// --------------------------------------------------------------------------
+//
+//  Return the upper edge of the range in which the spline is defined.
+//
+Float_t MPulseShape::GetXmax() const
+{
+    return fSpline ? fSpline->GetXmax() : 0;
+}
+
+// --------------------------------------------------------------------------
+//
+//  Read the intended pulse shape from a file and initialize the spline
+// accordingly
+//
+Bool_t MPulseShape::ReadFile(const char *fname)
+{
+    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 MPulseShape::SetFunction(const TF1 &f)
+{
+    // FIXME: Use TF1 directly? (In most cases this seems to be slower)
+
+    // 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 MPulseShape::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;
+}
+
+// --------------------------------------------------------------------------
+//
+// FileName: pulse-shape.txt
+// Function.Name: gaus
+// Function.Npx:    50
+// Function.Xmin:  -5
+// Function.Xmax:   5
+//
+Int_t MPulseShape::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 (!fFileName.IsNull())
+            if (ReadFile(fFileName))
+                return kERROR;
+    }
+
+    if (IsEnvDefined(env, prefix, "Function.Name", print))
+    {
+        rc = kTRUE;
+
+        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);
+
+        SetFunction(GetEnvValue(env, prefix, "Function.Name", fFunction), fNpx, fXmin, fXmax);
+    }
+
+    return rc;
+}
Index: trunk/MagicSoft/Mars/melectronics/MPulseShape.h
===================================================================
--- trunk/MagicSoft/Mars/melectronics/MPulseShape.h	(revision 9274)
+++ trunk/MagicSoft/Mars/melectronics/MPulseShape.h	(revision 9274)
@@ -0,0 +1,48 @@
+#ifndef MARS_MPulseShape
+#define MARS_MPulseShape
+
+#ifndef MARS_MParContainer
+#include "MParContainer.h"
+#endif
+
+class TF1;
+class MSpline3;
+
+class MPulseShape : public MParContainer
+{
+private:
+    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 sampling points
+    Float_t fXmin;                  // lower edge of sampling
+    Float_t fXmax;                  // upper edge of sampling
+
+    Bool_t ReadFile(const char *fname);
+    Bool_t SetFunction(const char *func, Int_t n, Double_t xmin, Double_t xmax);
+
+    // MParContainer
+    Int_t ReadEnv(const TEnv &env, TString prefix, Bool_t print=kFALSE);
+
+public:
+    MPulseShape(const char *name=0, const char *title=0);
+    ~MPulseShape();
+
+    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="");
+
+    MSpline3 *GetSpline() const { return fSpline; }
+
+    Float_t GetPulseWidth() const;
+    Float_t GetXmin() const;
+    Float_t GetXmax() const;
+
+    ClassDef(MPulseShape, 0) // Parameter container to hold the setup for a pulse shape
+};
+
+#endif
Index: trunk/MagicSoft/Mars/melectronics/Makefile
===================================================================
--- trunk/MagicSoft/Mars/melectronics/Makefile	(revision 9270)
+++ trunk/MagicSoft/Mars/melectronics/Makefile	(revision 9274)
@@ -24,5 +24,6 @@
            MAnalogSignal.cc \
            MAnalogChannels.cc \
-	   MDigitalSignal.cc 
+	   MDigitalSignal.cc  \
+	   MPulseShape.cc
 
 ############################################################
