Index: /trunk/MagicSoft/Mars/Changelog
===================================================================
--- /trunk/MagicSoft/Mars/Changelog	(revision 1331)
+++ /trunk/MagicSoft/Mars/Changelog	(revision 1332)
@@ -1,3 +1,13 @@
                                                                   -*-*- END -*-*-
+ 2002/05/06: Thomas Bretz
+
+   * mbase/MReadMarsFile.cc, mbase/MReadTree.cc, mbase/MTaskList.cc:
+     - implemented usage of the return value of the Notofy function
+
+   * mdata/MDataChain.[h,cc]:
+     - implemented single-argument operators (like abs or exp)
+
+
+
  2002/05/03: Thomas Bretz
 
Index: /trunk/MagicSoft/Mars/mbase/MReadMarsFile.cc
===================================================================
--- /trunk/MagicSoft/Mars/mbase/MReadMarsFile.cc	(revision 1331)
+++ /trunk/MagicSoft/Mars/mbase/MReadMarsFile.cc	(revision 1332)
@@ -117,11 +117,15 @@
         *fLog << "(before event #" << GetEventNum()-1 << ")" << endl;
 
-        fTaskList->ReInit();
+        if (fTaskList->ReInit())
+            return kTRUE;
+
         //MReadTree::Notify();
+
+        *fLog << err << "ERROR - ReInit of '" << fTaskList->GetName() << "' failed." << endl;
     }
     else
-        *fLog << warn << "Warning: Cannot read new runheaders after reading event #" << GetEventNum() << endl;
+        *fLog << err << "ERROR - Cannot read new runheaders after reading event #" << GetEventNum() << endl;
 
-    return kTRUE;
+    return kFALSE;
 }
 
Index: /trunk/MagicSoft/Mars/mbase/MReadTree.cc
===================================================================
--- /trunk/MagicSoft/Mars/mbase/MReadTree.cc	(revision 1331)
+++ /trunk/MagicSoft/Mars/mbase/MReadTree.cc	(revision 1332)
@@ -71,9 +71,39 @@
 class MChain : public TChain
 {
+private:
+    Bool_t fNotified;
+
 public:
-    MChain() : TChain() {}
-    MChain(const char *name, const char *title="") : TChain(name, title) {}
+    MChain() : TChain(), fNotified(kFALSE) {}
+    MChain(const char *name, const char *title="") : TChain(name, title), fNotified(kFALSE) {}
 
     void ResetTree() { fTree = 0; }
+
+    virtual Bool_t Notify() { fNotified = kTRUE; return kTRUE; }
+    virtual void   SetNotify(TObject *obj) { fNotify = obj; fNotified = kFALSE; }
+
+    Int_t GetEntry(Int_t entry=0, Int_t getall=0)
+    {
+        // --------------------------------------------------------------------------
+        //
+        // This is the code from TChain::GetEntry but skips the
+        // notification in LoadTree. If LoadTree raises the notification
+        // a flag is set and the notification is done by hand. If it
+        // has not been successfull 0 is returned.
+        //
+        TObject *notify = GetNotify();
+
+        SetNotify(this);
+
+        Int_t rc = 0;
+
+        if (LoadTree(entry) >= 0)
+            if (!fNotified || (notify && notify->Notify()))
+                rc = fTree->GetEntry(fReadEntry, getall);
+
+        SetNotify(notify);
+
+        return rc;
+    }
 };
 
Index: /trunk/MagicSoft/Mars/mbase/MTaskList.cc
===================================================================
--- /trunk/MagicSoft/Mars/mbase/MTaskList.cc	(revision 1331)
+++ /trunk/MagicSoft/Mars/mbase/MTaskList.cc	(revision 1332)
@@ -228,5 +228,4 @@
 
     MTask *task=NULL;
-
     //
     // loop over all tasks for preproccesing
@@ -237,5 +236,8 @@
 
         if (!task->ReInit(pList?pList:fParList))
+        {
+            *fLog << err << "ERROR - ReInit if Task " << task->GetDescriptor() << " failed." << endl;
             return kFALSE;
+        }
     }
 
Index: /trunk/MagicSoft/Mars/mdata/MDataChain.cc
===================================================================
--- /trunk/MagicSoft/Mars/mdata/MDataChain.cc	(revision 1331)
+++ /trunk/MagicSoft/Mars/mdata/MDataChain.cc	(revision 1332)
@@ -51,4 +51,24 @@
 //   "(MHillas.fWidth + MHillas.fLength) / HillasSource.fDist"
 //
+// You can also use mathmatical operators, eg:
+//   "5*log10(MMcEvt.fEnergy*MHillas.fSize)"
+//
+// The allowed operators are:
+//   exp(x)    e^x
+//   log(x)    natural logarithm of x
+//   pow10(x)  10^x
+//   log10(x)  logarithm of x to base ten
+//   cos(x)    cosine of x
+//   sin(x)    sine of x
+//   tan(x)    tangent of x
+//   cosh(x)   hyperbolic cosine of x
+//   sinh(x)   hyperbolic sine of x
+//   tanh(x)   hyperbolic tangent of x
+//   acos(x)   arc cosine (inverse cosine) of x
+//   asin(x)   arc sine (inverse sine) of x
+//   atan(x)   arc tangent (inverse tangent) of x
+//   sqrt(x)   square root of x
+//   abs(x)    absolute value of x, |x|
+//
 //
 // FIXME: The possibility to use other objects inheriting from MData
@@ -72,4 +92,13 @@
 #
 ClassImp(MDataChain);
+
+MDataChain::MDataChain(const char *rule, OperatorType_t op)
+    : fOperatorType(op)
+{
+    fName  = "MDataChain";
+    fTitle = rule;
+
+    fMember=ParseString(rule, 1);
+}
 
 MDataChain::MDataChain(const char *rule, const char *name, const char *title)
@@ -124,4 +153,47 @@
 }
 
+Int_t MDataChain::GetBracket(TString txt)
+{
+    Int_t first=1;
+    for (int cnt=0; first<txt.Length(); first++)
+    {
+        if (txt[first]=='(')
+            cnt++;
+        if (txt[first]==')')
+            cnt--;
+        if (cnt==-1)
+            break;
+    }
+    return first;
+}
+
+// --------------------------------------------------------------------------
+//
+// Compare a given text with the known operators. If no operator match
+// kENoop is retunred, otherwise the corresponding OperatorType_t
+//
+MDataChain::OperatorType_t MDataChain::ParseOperator(TString txt) const
+{
+    txt.ToLower();
+
+    if (txt=="abs")   return kEAbs;
+    if (txt=="log")   return kELog;
+    if (txt=="log10") return kELog10;
+    if (txt=="sin")   return kESin;
+    if (txt=="cos")   return kECos;
+    if (txt=="tan")   return kETan;
+    if (txt=="sinh")  return kESinH;
+    if (txt=="cosh")  return kECosH;
+    if (txt=="tanh")  return kETanH;
+    if (txt=="asin")  return kEASin;
+    if (txt=="acos")  return kEACos;
+    if (txt=="atan")  return kEATan;
+    if (txt=="sqrt")  return kESqrt;
+    if (txt=="exp")   return kEExp;
+    if (txt=="pow10") return kEPow10;
+
+    return kENoop;
+}
+
 MData *MDataChain::ParseString(TString txt, Int_t level)
 {
@@ -144,15 +216,5 @@
                 // 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;
-                }
+                Int_t first=GetBracket(txt);
 
                 if (first==txt.Length())
@@ -208,5 +270,5 @@
                 // filter list with the new conditional
                 //
-                if (!member0->InheritsFrom(MDataMember::Class()) || type!=is)
+                if (/*!member0->InheritsFrom(MDataMember::Class()) ||*/ type!=is)
                 {
                     MDataList *list = new MDataList(is);
@@ -269,8 +331,35 @@
 
             txt.Remove(0, i);
-
-            // *fLog << all << "Creating: '" << text.Data() << "'" << endl;
-
-            newmember = new MDataMember(text.Data());
+            txt = txt.Strip(TString::kBoth);
+
+            if (txt.IsNull() || txt[0]!='(')
+            {
+                newmember = new MDataMember(text.Data());
+                break;
+            }
+
+            OperatorType_t op = ParseOperator(text);
+            if (op==kENoop)
+            {
+                *fLog << err << dbginf << "Syntax Error: Operator '" << text << "' unknown." << endl;
+                if (member0)
+                    delete member0;
+                return NULL;
+            }
+
+            Int_t first = GetBracket(txt);
+            TString sub = txt(1, first-1);
+            txt.Remove(0, first+1);
+
+            newmember = new MDataChain(sub, op);
+
+            if (!newmember->IsValid())
+            {
+                *fLog << err << dbginf << "Syntax Error: Error parsing contents '" << sub << "' of operator " << text << endl;
+                delete newmember;
+                if (member0)
+                    delete member0;
+                return NULL;
+            }
         }
 
@@ -292,9 +381,63 @@
 Double_t MDataChain::GetValue() const
 {
-    return fMember ? fMember->GetValue() : 0;
+    if (!fMember)
+        return 0;
+
+    const Double_t val = fMember->GetValue();
+
+    switch (fOperatorType)
+    {
+    case kEAbs:   return fabs(val);
+    case kELog:   return log(val);
+    case kELog10: return log10(val);
+    case kESin:   return sin(val);
+    case kECos:   return cos(val);
+    case kETan:   return tan(val);
+    case kESinH:  return sinh(val);
+    case kECosH:  return cosh(val);
+    case kETanH:  return tanh(val);
+    case kEASin:  return asin(val);
+    case kEACos:  return acos(val);
+    case kEATan:  return atan(val);
+    case kESqrt:  return sqrt(val);
+    case kEExp:   return exp(val);
+    case kEPow10: return pow(10, val);
+    case kENoop:  return val;
+    }
+
+    return 0;
 }
 
 void MDataChain::Print(Option_t *opt) const
 {
+    Bool_t bracket = fOperatorType!=kENoop && !fMember->InheritsFrom(MDataList::Class());
+
+    switch (fOperatorType)
+    {
+    case kEAbs:   *fLog << "abs"   << flush; break;
+    case kELog:   *fLog << "log"   << flush; break;
+    case kELog10: *fLog << "log10" << flush; break;
+    case kESin:   *fLog << "sin"   << flush; break;
+    case kECos:   *fLog << "cos"   << flush; break;
+    case kETan:   *fLog << "tan"   << flush; break;
+    case kESinH:  *fLog << "sinh"  << flush; break;
+    case kECosH:  *fLog << "cosh"  << flush; break;
+    case kETanH:  *fLog << "tanh"  << flush; break;
+    case kEASin:  *fLog << "asin"  << flush; break;
+    case kEACos:  *fLog << "acos"  << flush; break;
+    case kEATan:  *fLog << "atan"  << flush; break;
+    case kESqrt:  *fLog << "sqrt"  << flush; break;
+    case kEExp:   *fLog << "exp"   << flush; break;
+    case kEPow10: *fLog << "pow10" << flush; break;
+    case kENoop:
+        break;
+    }
+
+    if (bracket)
+        *fLog << "(" << flush;
+
     fMember->Print();
-}
+
+    if (bracket)
+        *fLog << ")" << flush;
+}
Index: /trunk/MagicSoft/Mars/mdata/MDataChain.h
===================================================================
--- /trunk/MagicSoft/Mars/mdata/MDataChain.h	(revision 1331)
+++ /trunk/MagicSoft/Mars/mdata/MDataChain.h	(revision 1332)
@@ -19,10 +19,36 @@
     MData *fMember; // Filter
 
+    typedef enum {
+        kENoop,
+        kELog10,
+        kELog,
+        kEAbs,
+        kESin,
+        kECos,
+        kETan,
+        kESinH,
+        kECosH,
+        kETanH,
+        kEASin,
+        kEACos,
+        kEATan,
+        kESqrt,
+        kEPow10,
+        kEExp
+    } OperatorType_t;
+
+    OperatorType_t fOperatorType;
+
+    OperatorType_t ParseOperator(TString txt) const;
+
     Int_t IsAlNum(TString txt);
+    Int_t GetBracket(TString txt);
 
     MData *ParseString(TString txt, Int_t level);
 
+    MDataChain(const char *rule, OperatorType_t op);
+
 public:
-    MDataChain(const char *text, const char *name=NULL, const char *title=NULL);
+    MDataChain(const char *rule, const char *name=NULL, const char *title=NULL);
     ~MDataChain();
 
