Index: trunk/MagicSoft/Mars/Changelog
===================================================================
--- trunk/MagicSoft/Mars/Changelog	(revision 1660)
+++ trunk/MagicSoft/Mars/Changelog	(revision 1661)
@@ -1,3 +1,3 @@
-                                                                  -*-*- END -*-*-
+                       #                                           -*-*- END -*-*-
  2002/11/21: Thomas Bretz
 
@@ -5,4 +5,11 @@
      - introduced kERROR to stop an eventloop with an error
 
+   * mbase/MTask.h:
+     - made SetFilter virtual
+
+   * mbase/MTaskList.[h,cc]:
+     - added new member function AddToListBefore/After
+     - split the code of the AddToList function into CheckAddToList
+
    * manalysis/MMultiDimDistCalc.cc:
      - introduced usage of kERROR in case the matrix is not posdef.
@@ -10,4 +17,16 @@
    * macros/collarea.C:
      - some simplifications
+
+   * mdata/MDataChain.[h,cc]:
+     - added 'sqr'
+
+   * mfilter/MF.[h,cc]:
+     - added support for MFDataChain
+
+   * mfilter/MFDataChain.[h,cc]:
+     - added
+
+   * mfilter/Makefile, mfilter/FilterLinkDef.h:
+     - added MFDataChain
 
 
Index: trunk/MagicSoft/Mars/mbase/MTask.h
===================================================================
--- trunk/MagicSoft/Mars/mbase/MTask.h	(revision 1660)
+++ trunk/MagicSoft/Mars/mbase/MTask.h	(revision 1661)
@@ -65,6 +65,7 @@
     virtual ~MTask();
 
-    void SetFilter(MFilter *filter) { fFilter=filter; }
+    virtual void SetFilter(MFilter *filter) { fFilter=filter; }
     const MFilter *GetFilter() const      { return fFilter; }
+    MFilter *GetFilter()  { return fFilter; } // for MContinue only
     virtual void PrintStatistics(const Int_t lvl=0, Bool_t title=kFALSE) const;
 
Index: trunk/MagicSoft/Mars/mbase/MTaskList.cc
===================================================================
--- trunk/MagicSoft/Mars/mbase/MTaskList.cc	(revision 1660)
+++ trunk/MagicSoft/Mars/mbase/MTaskList.cc	(revision 1661)
@@ -135,14 +135,6 @@
 }
 
-
-// --------------------------------------------------------------------------
-//
-// schedule task for execution, whether as first task, or after
-// 'where'. 'tType' is the event type which should be processed
-//
-Bool_t MTaskList::AddToList(MTask *task, const char *type, MTask *where)
-{
-    // FIXME: We agreed to put the task into list in an ordered way.
-
+Bool_t MTaskList::CheckAddToList(MTask *task, const char *type, const MTask *where) const
+{
     //
     // Sanity check
@@ -182,18 +174,69 @@
     }
 
-    if (where)
-    {
-        if (!fTasks->FindObject(where))
-        {
-            *fLog << err << dbginf << "Error: Cannot find task after which the new task should be scheduled!" << endl;
-            return kFALSE;
-        }
-    }
-
-    *fLog << inf << "Adding " << name << " to " << GetName() << " for " << type << "... " << flush;
-
+    if (!where)
+        return kTRUE;
+
+    if (fTasks->FindObject(where))
+        return kTRUE;
+
+    *fLog << err << dbginf << "Error: Cannot find task after which the new task should be scheduled!" << endl;
+    return kFALSE;
+}
+
+
+// --------------------------------------------------------------------------
+//
+// schedule task for execution, before 'where'.
+// 'type' is the event type which should be processed
+//
+Bool_t MTaskList::AddToListBefore(MTask *task, const MTask *where, const char *type)
+{
+    // FIXME: We agreed to put the task into list in an ordered way.
+    if (!CheckAddToList(task, type, where))
+        return kFALSE;
+
+    *fLog << inf << "Adding " << task->GetName() << " to " << GetName() << " for " << type << "... " << flush;
+    task->SetStreamId(type);
+    fTasks->AddBefore((TObject*)where, task);
+    *fLog << "Done." << endl;
+
+    return kTRUE;
+}
+
+// --------------------------------------------------------------------------
+//
+// schedule task for execution, after 'where'.
+// 'type' is the event type which should be processed
+//
+Bool_t MTaskList::AddToListAfter(MTask *task, const MTask *where, const char *type)
+{
+    // FIXME: We agreed to put the task into list in an ordered way.
+
+    if (!CheckAddToList(task, type, where))
+        return kFALSE;
+
+    *fLog << inf << "Adding " << task->GetName() << " to " << GetName() << " for " << type << "... " << flush;
+    task->SetStreamId(type);
+    fTasks->AddAfter((TObject*)where, task);
+    *fLog << "Done." << endl;
+
+    return kTRUE;
+}
+
+// --------------------------------------------------------------------------
+//
+// schedule task for execution, 'type' is the event type which should
+// be processed
+//
+Bool_t MTaskList::AddToList(MTask *task, const char *type)
+{
+    // FIXME: We agreed to put the task into list in an ordered way.
+
+    if (!CheckAddToList(task, type))
+        return kFALSE;
+
+    *fLog << inf << "Adding " << task->GetName() << " to " << GetName() << " for " << type << "... " << flush;
     task->SetStreamId(type);
     fTasks->Add(task);
-
     *fLog << "Done." << endl;
 
@@ -325,7 +368,4 @@
         *fLog << all << task->GetName() << "... " << flush;
 
-        if (CheckClassForProcess(task->IsA()))
-            fTasksProcess.Add(task);
-
         //
         // PreProcess the task and check for it's return value.
@@ -350,4 +390,13 @@
 
     *fLog << all << endl;
+
+    Next.Reset();
+
+    //
+    // loop over all tasks for preproccesing
+    //
+    while ((task=(MTask*)Next()))
+        if (CheckClassForProcess(task->IsA()))
+            fTasksProcess.Add(task);
 
     return kTRUE;
Index: trunk/MagicSoft/Mars/mbase/MTaskList.h
===================================================================
--- trunk/MagicSoft/Mars/mbase/MTaskList.h	(revision 1660)
+++ trunk/MagicSoft/Mars/mbase/MTaskList.h	(revision 1661)
@@ -35,4 +35,6 @@
     void StreamPrimitive(ofstream &out) const;
 
+    Bool_t CheckAddToList(MTask *task, const char *tType, const MTask *where=NULL) const;
+
 public:
     MTaskList(const char *name=NULL, const char *title=NULL);
@@ -43,5 +45,7 @@
     void SetLogStream(MLog *log);
 
-    Bool_t AddToList(MTask *task, const char *tType="All", MTask *where = NULL);
+    Bool_t AddToListBefore(MTask *task, const MTask *where, const char *tType="All");
+    Bool_t AddToListAfter(MTask *task, const MTask *where, const char *tType="All");
+    Bool_t AddToList(MTask *task, const char *tType="All");
 
     TObject *FindObject(const char *name) const;
Index: trunk/MagicSoft/Mars/mdata/MDataChain.cc
===================================================================
--- trunk/MagicSoft/Mars/mdata/MDataChain.cc	(revision 1660)
+++ trunk/MagicSoft/Mars/mdata/MDataChain.cc	(revision 1661)
@@ -69,4 +69,5 @@
 //   atan(x)   arc tangent (inverse tangent) of x
 //   sqrt(x)   square root of x
+//   sqr(x)    square of x
 //   abs(x)    absolute value of x, |x|
 //   floor(x)  round down to the nearest integer (floor(9.9)=9)
@@ -225,4 +226,5 @@
     if (txt=="atan")  return kEATan;
     if (txt=="sqrt")  return kESqrt;
+    if (txt=="sqr")   return kESqr;
     if (txt=="exp")   return kEExp;
     if (txt=="pow10") return kEPow10;
@@ -468,4 +470,5 @@
     case kEATan:     return atan(val);
     case kESqrt:     return sqrt(val);
+    case kESqr:      return val*val;
     case kEExp:      return exp(val);
     case kEPow10:    return pow(10, val);
@@ -551,4 +554,5 @@
     case kEATan:     str += "atan" ; break;
     case kESqrt:     str += "sqrt" ; break;
+    case kESqr:      str += "sqr"  ; break;
     case kEExp:      str += "exp"  ; break;
     case kEPow10:    str += "pow10"; break;
Index: trunk/MagicSoft/Mars/mdata/MDataChain.h
===================================================================
--- trunk/MagicSoft/Mars/mdata/MDataChain.h	(revision 1660)
+++ trunk/MagicSoft/Mars/mdata/MDataChain.h	(revision 1661)
@@ -34,4 +34,5 @@
         kEATan,
         kESqrt,
+        kESqr,
         kEPow10,
         kEExp,
Index: trunk/MagicSoft/Mars/mfilter/FilterLinkDef.h
===================================================================
--- trunk/MagicSoft/Mars/mfilter/FilterLinkDef.h	(revision 1660)
+++ trunk/MagicSoft/Mars/mfilter/FilterLinkDef.h	(revision 1661)
@@ -12,4 +12,5 @@
 #pragma link C++ class MFTriggerLvl1+;
 #pragma link C++ class MFParticleId+;
+#pragma link C++ class MFDataChain+;
 #pragma link C++ class MFDataMember+;
 
Index: trunk/MagicSoft/Mars/mfilter/MF.cc
===================================================================
--- trunk/MagicSoft/Mars/mfilter/MF.cc	(revision 1660)
+++ trunk/MagicSoft/Mars/mfilter/MF.cc	(revision 1661)
@@ -44,4 +44,8 @@
 //   "MHillas.fSize>200 || (MHillas.fWidth<0.5 && MHillas.fLength<0.6)"
 //
+// If you want to use mathematic expressions (as defined in MDataChain)
+// you must encapsulate it in {}-Brackets, eg:
+//   "{log10(MHillas.fSize)}>3"
+//
 // The allowed logigal conditionals are:
 //   &&: logical and
@@ -53,4 +57,5 @@
 // are allowed.
 //
+//
 // Warning: There is no priority rule build in. So better use brackets
 //   to get correct results. The rule is parsed/evaluated from the left
@@ -80,4 +85,5 @@
 
 #include "MFilterList.h"
+#include "MFDataChain.h"
 #include "MFDataMember.h"
 
@@ -139,5 +145,5 @@
 // in the given string
 //
-Int_t MF::IsAlNum(TString txt)
+Int_t MF::IsAlNum(TString txt) const
 {
     int l = txt.Length();
@@ -149,4 +155,100 @@
 }
 
+MFilter *MF::ParseRule(TString &txt, MFilter *filter0) const
+{
+    TString text;
+
+    Bool_t isrule = kFALSE;
+
+    if (txt[0]=='{')
+    {
+        //
+        // Search for the corresponding bracket
+        //
+        Int_t first=1;
+        for (int cnt=0; first<txt.Length(); first++)
+        {
+            if (txt[first]=='{')
+                cnt++;
+            if (txt[first]=='}')
+                cnt--;
+
+            if (cnt==-1)
+                break;
+        }
+
+        if (first==txt.Length())
+        {
+            *fLog << err << dbginf << "Syntax Error: '}' missing." << endl;
+            return NULL;
+        }
+
+        //
+        // Make a copy of the 'interieur' and delete the substringä
+        // including the brackets
+        //
+        TString sub = txt(1, first-1);
+        txt.Remove(0, first+1);
+
+        text=sub;
+        isrule = kTRUE;
+    }
+    else
+    {
+        int i = IsAlNum(txt);
+
+        if (i==0)
+        {
+            *fLog << err << dbginf << "Syntax Error: Name of data member missing in '" << txt << "'" << endl;
+            return NULL;
+        }
+
+        text = txt(0, i);
+
+        txt.Remove(0, i);
+    }
+
+    txt = txt.Strip(TString::kBoth);
+
+    if (txt.IsNull())
+    {
+        *fLog << err << dbginf << "Syntax Error: No conditional in '" << text << "'" << endl;
+        return NULL;
+    }
+
+    char c;
+    switch (txt[0])
+    {
+    case '>':
+    case '<':
+        c = txt[0];
+        txt.Remove(0, 1);
+        break;
+
+    default:
+        *fLog << err << dbginf << "Syntax Error: Conditional '" << txt[0] << "' unknown." << endl;
+        return NULL;
+    }
+
+    char *end;
+    Double_t num = strtod(txt.Data(), &end);
+    if (!end || txt.Data()==end)
+    {
+        *fLog << err << dbginf << "Error trying to convert '" << txt << "' to value." << endl;
+        return NULL;
+    }
+
+    txt.Remove(0, end-txt.Data());
+
+    MFilter *newfilter;
+    if (isrule)
+        newfilter = new MFDataChain(text.Data(), c, num);
+    else
+        newfilter = new MFDataMember(text.Data(), c, num);
+
+    newfilter->SetName(Form("%s%c%f", text.Data(), c, num));
+
+    return newfilter;
+}
 // --------------------------------------------------------------------------
 //
@@ -222,4 +324,5 @@
             return NULL;
 
+
         case '&':
         case '|':
@@ -264,57 +367,11 @@
 
         default:
-            int i = IsAlNum(txt);
-
-            if (i==0)
+            newfilter = ParseRule(txt, filter0);
+            if (!newfilter)
             {
-                *fLog << err << dbginf << "Syntax Error: Name of data member missing in '" << txt << "'" << endl;
                 if (filter0)
                     delete filter0;
                 return NULL;
             }
-
-            TString text = txt(0, i);
-
-            txt.Remove(0, i);
-            txt = txt.Strip(TString::kBoth);
-
-            if (txt.IsNull())
-            {
-                *fLog << err << dbginf << "Syntax Error: No conditional in '" << text << "'" << endl;
-                if (filter0)
-                    delete filter0;
-                return NULL;
-            }
-
-            char c;
-            switch (txt[0])
-            {
-            case '>':
-            case '<':
-                c = txt[0];
-                txt.Remove(0, 1);
-                break;
-
-            default:
-                *fLog << err << dbginf << "Syntax Error: Conditional '" << txt[0] << "' unknown." << endl;
-                if (filter0)
-                    delete filter0;
-                return NULL;
-            }
-
-            char *end;
-            Double_t num = strtod(txt.Data(), &end);
-            if (!end || txt.Data()==end)
-            {
-                *fLog << err << dbginf << "Error trying to convert '" << txt << "' to value." << endl;
-                if (filter0)
-                    delete filter0;
-                return NULL;
-            }
-
-            txt.Remove(0, end-txt.Data());
-
-            newfilter = new MFDataMember(text.Data(), c, num);
-            newfilter->SetName(Form("%s%c%f", text.Data(), c, num));
         }
 
Index: trunk/MagicSoft/Mars/mfilter/MF.h
===================================================================
--- trunk/MagicSoft/Mars/mfilter/MF.h	(revision 1660)
+++ trunk/MagicSoft/Mars/mfilter/MF.h	(revision 1661)
@@ -23,6 +23,7 @@
     MFilter *fFilter; // Filter
 
-    Int_t IsAlNum(TString txt);
+    Int_t IsAlNum(TString txt) const;
 
+    MFilter *ParseRule(TString &txt, MFilter *filter0) const;
     MFilter *ParseString(TString txt, Int_t level);
 
Index: trunk/MagicSoft/Mars/mfilter/MFDataChain.cc
===================================================================
--- trunk/MagicSoft/Mars/mfilter/MFDataChain.cc	(revision 1661)
+++ trunk/MagicSoft/Mars/mfilter/MFDataChain.cc	(revision 1661)
@@ -0,0 +1,121 @@
+/* ======================================================================== *\
+!
+! *
+! * This file is part of MARS, the MAGIC 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 appear 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  11/2002 <mailto:tbretz@astro.uni-wueruburg.de>
+!
+!   Copyright: MAGIC Software Development, 2000-2002
+!
+!
+\* ======================================================================== */
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// MFDataChain                                                              
+//
+// With this filter you can filter in all variables from Mars parameter
+// containers using rules (for more details see MDataChain).
+//
+// In the constructor you can give the filter variable, like
+//   "sqrt(MHillas.fLength*MHillas.fLength)"
+// Where MHillas is the name of the parameter container in the parameter
+// list and fLength is the name of the data member which should be used
+// for the filter rule. If the name of the container is use specified
+// (MyHillas) the name to give would be:
+//   "MyHillas.fLength"
+//
+// For example:
+//   MFDataChain filter("sqr(MHillas.fLength)", '<', 150);
+//
+/////////////////////////////////////////////////////////////////////////////
+#include "MFDataChain.h"
+
+#include <fstream.h>
+
+#include <TMethodCall.h>
+
+#include "MParList.h"
+
+#include "MLog.h"
+#include "MLogManip.h"
+
+ClassImp(MFDataChain);
+
+// --------------------------------------------------------------------------
+//
+MFDataChain::MFDataChain(const char *member, const char type, const Double_t val,
+                           const char *name, const char *title)
+    : fData(member), fValue(val)
+{
+    fName  = name  ? name  : "MFDataChain";
+    fTitle = title ? title : "Filter using any data member of a class";
+
+    AddToBranchList(member);
+
+    fFilterType = (type=='<' ? kELowerThan : kEGreaterThan);
+
+    if (type!='<' && type!='>')
+        *fLog << warn << dbginf << "Warning: Neither '<' nor '>' specified... using '>'." << endl;
+}
+
+// --------------------------------------------------------------------------
+//
+Bool_t MFDataChain::PreProcess(MParList *plist)
+{
+    return fData.PreProcess(plist);
+}
+
+// --------------------------------------------------------------------------
+//
+Bool_t MFDataChain::Process()
+{
+    switch (fFilterType)
+    {
+    case kELowerThan:
+        fResult = (fData.GetValue() < fValue);
+        return kTRUE;
+    case kEGreaterThan:
+        fResult = (fData.GetValue() > fValue);
+        return kTRUE;
+    }
+
+    return kFALSE;
+}
+
+void MFDataChain::Print(Option_t *) const
+{
+    *fLog << GetRule() << flush;
+}
+
+void MFDataChain::StreamPrimitive(ofstream &out) const
+{
+    out << "   MFDataChain " << GetUniqueName() << "(\"";
+    out << fData.GetRule() << "\", '";
+    out << (fFilterType==kELowerThan?"<":">");
+    out << "', " << fValue << ");" << endl;
+}
+
+TString MFDataChain::GetRule() const
+{
+    TString ret = fData.GetRule();
+    ret += fFilterType==kELowerThan?"<":">";
+
+    TString str;
+    str += fValue;
+
+    return ret+str.Strip(TString::kBoth);
+}
+
Index: trunk/MagicSoft/Mars/mfilter/MFDataChain.h
===================================================================
--- trunk/MagicSoft/Mars/mfilter/MFDataChain.h	(revision 1661)
+++ trunk/MagicSoft/Mars/mfilter/MFDataChain.h	(revision 1661)
@@ -0,0 +1,46 @@
+#ifndef MARS_MFDataChain
+#define MARS_MFDataChain
+
+/////////////////////////////////////////////////////////////////////////////
+//                                                                         //
+// MFDataChain                                                                 //
+//                                                                         //
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef MARS_MFilter
+#include "MFilter.h"
+#endif
+#ifndef MARS_MDataChain
+#include "MDataChain.h"
+#endif
+
+class MParList;
+
+class MFDataChain : public MFilter
+{
+private:
+    MDataChain fData;
+
+    typedef enum { kELowerThan, kEGreaterThan } FilterType_t;
+    FilterType_t fFilterType;
+
+    Bool_t  fResult;           //!
+    Double_t fValue;
+
+    void StreamPrimitive(ofstream &out) const;
+
+public:
+    MFDataChain(const char *member, const char type, const Double_t val,
+                 const char *name=NULL, const char *title=NULL);
+
+    Bool_t IsExpressionTrue() const { return fResult; }
+    Bool_t PreProcess(MParList *pList);
+    Bool_t Process();
+
+    void Print(Option_t *opt = "") const;
+    TString GetRule() const;
+
+    ClassDef(MFDataChain, 1) // A Filter for cuts in any data member
+};
+
+#endif
Index: trunk/MagicSoft/Mars/mfilter/MFDataMember.cc
===================================================================
--- trunk/MagicSoft/Mars/mfilter/MFDataMember.cc	(revision 1660)
+++ trunk/MagicSoft/Mars/mfilter/MFDataMember.cc	(revision 1661)
@@ -16,5 +16,5 @@
 !
 !
-!   Author(s): Thomas Bretz  01/2002 <mailto:tbretz@uni-sw.gwdg.de>
+!   Author(s): Thomas Bretz  01/2002 <mailto:tbretz@astro.uni-wueruburg.de>
 !
 !   Copyright: MAGIC Software Development, 2000-2002
Index: trunk/MagicSoft/Mars/mfilter/Makefile
===================================================================
--- trunk/MagicSoft/Mars/mfilter/Makefile	(revision 1660)
+++ trunk/MagicSoft/Mars/mfilter/Makefile	(revision 1661)
@@ -35,4 +35,5 @@
            MFilterList.cc \
            MFEventSelector.cc \
+	   MFDataChain.cc \
 	   MFDataMember.cc \
 	   MFParticleId.cc \
