Index: trunk/MagicSoft/Mars/mdata/MDataChain.cc
===================================================================
--- trunk/MagicSoft/Mars/mdata/MDataChain.cc	(revision 1327)
+++ 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 1327)
+++ 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();
 
