Index: trunk/MagicSoft/Mars/Changelog
===================================================================
--- trunk/MagicSoft/Mars/Changelog	(revision 7980)
+++ trunk/MagicSoft/Mars/Changelog	(revision 7981)
@@ -26,4 +26,7 @@
      - fixed abug introduced 14.7.2005 which caused the M3Long of the
        anti source to be not properly evaluated in case of optimization.
+
+   * ganymed_onoff.rc, ganymed_wobble.rc:
+     - updated with comments how to use random forest
 
 
Index: trunk/MagicSoft/Mars/NEWS
===================================================================
--- trunk/MagicSoft/Mars/NEWS	(revision 7980)
+++ trunk/MagicSoft/Mars/NEWS	(revision 7981)
@@ -126,4 +126,8 @@
      of optimization with anti-theta cut switched on. This might have
      lead to improper, but not necessarily wrong, optimization results.
+
+   - ganzmed: ganymed_onoff.rc, ganymed_wobble.rc - updated with comments
+     how to use random forest
+
 
 
Index: trunk/MagicSoft/Mars/datacenter/macros/buildsequenceentries.C
===================================================================
--- trunk/MagicSoft/Mars/datacenter/macros/buildsequenceentries.C	(revision 7980)
+++ trunk/MagicSoft/Mars/datacenter/macros/buildsequenceentries.C	(revision 7981)
@@ -81,771 +81,1068 @@
 #include <fstream>
 
-#include <MSQLServer.h>
 #include <TSQLRow.h>
 #include <TSQLResult.h>
 
 #include <TEnv.h>
+#include <TMap.h>
 #include <TMath.h>
 #include <TExMap.h>
 #include <TArrayI.h>
-#include <TRegexp.h>
+#include <TArrayD.h>
+#include <TPRegexp.h>
 #include <TSystem.h>
 #include <TObjString.h>
 #include <TObjArray.h>
 
-#include <MTime.h>
-#include <MDirIter.h>
+#include "MTime.h"
+#include "MDirIter.h"
+
+#include "MSQLMagic.h"
 
 using namespace std;
 
-int debug = 0;
-
-Bool_t DeleteSequence(MSQLServer &serv, TString datapath, TString sequpath, Int_t sequ, Bool_t dummy)
+
+class Rule : public TObject
 {
-    //queries to delete information from the database
-    TString query1(Form("DELETE FROM Calibration WHERE fSequenceFirst=%d", sequ));
-    TString query2(Form("DELETE FROM Star WHERE fSequenceFirst=%d", sequ));
-    TString query3(Form("DELETE FROM SequenceProcessStatus WHERE fSequenceFirst=%d", sequ));
-    TString query4(Form("UPDATE RunData SET fSequenceFirst=0 WHERE fSequenceFirst=%d", sequ));
-    TString query5(Form("DELETE FROM Sequences WHERE fSequenceFirst=%d AND fManuallyChangedKEY=1", sequ));
-
-    //commands to delete files from the disk
-    TString fname(Form("%s/%04d/sequence%08d.txt", sequpath.Data(),sequ/10000, sequ));
-    TString command(Form("rm -r %s/callisto/%04d/%08d/", datapath.Data(), sequ/10000, sequ));
-    TString command2(Form("rm -r %s/star/%04d/%08d/", datapath.Data(), sequ/10000, sequ));
-
-    if (dummy)
-    {
-        cout << "not using dummy=kTRUE the following commands would be executed: " << endl;
-        cout << "queries: " << endl;
-        cout << query1 << endl;
-        cout << query2 << endl;
-        cout << query3 << endl;
-        cout << query4 << endl;
-        cout << query5 << endl;
-        cout << "removing files:" << endl;
-        cout << "unlink " << fname << endl;
-        cout << command << endl;
-        cout << command2 << endl;
+private:
+    TPRegexp fRegexp;
+
+    UInt_t fMin;
+    UInt_t fMax;
+
+public:
+    Rule(const char *regexp, UInt_t min=0, UInt_t max=(UInt_t)-1) :
+        fRegexp(Form("^%s", regexp)), fMin(min), fMax(max)
+    {
+    }
+
+    Rule(TObjArray &arr) :
+        fRegexp(arr.GetEntries()>0?Form("^%s", arr[0]->GetName()):""),
+            fMin(0), fMax((UInt_t)-1)
+    {
+        if (arr.GetEntries()>1)
+            fMin = atoi(arr[1]->GetName());
+        if (arr.GetEntries()>2)
+            fMax = atoi(arr[2]->GetName());
+
+        //cout << "Regexp: " << (arr.GetEntries()>0?Form("^%s", arr[0]->GetName()):"") << " " << fMin << " " << fMax << endl;
+    }
+
+    Ssiz_t Match(const TString &str, Int_t idx, Int_t run=-1)
+    {
+        if (!IsValid(run))
+            return 0;
+
+        TString mods;
+        TArrayI pos;
+        fRegexp.Match(str.Data()+idx, mods, 0, str.Length()*10, &pos);
+
+        return pos.GetSize()<2 ? 0 : pos[1]-pos[0];
+    }
+
+    Bool_t IsValid(UInt_t run) const { return run<0 || (run>=fMin && run<=fMax); }
+    ClassDef(Rule, 0)
+};
+ClassImp(Rule);
+
+class CheckMatch : public TObject
+{
+private:
+    TPRegexp fRunType1;
+    TPRegexp fRunType2;
+
+    TPRegexp fRegexp1;
+    TPRegexp fRegexp2;
+
+    UInt_t fMin;
+    UInt_t fMax;
+
+    void Init(const TObjArray &arr, Int_t idx=0)
+    {
+        const Int_t n = arr.GetEntries();
+
+        const Bool_t isminus = n>idx && TString(arr[idx]->GetName())=="-";
+
+        for (int i=0; i<n-idx; i++)
+        {
+            //cout << arr[i+idx]->GetName() << " ";
+
+            TString str(arr[i+idx]->GetName());
+            if (str=="*")
+                str = ".*";
+
+            switch (isminus && i>1 ? i+1 : i)
+            {
+            case 0: fRunType1 = TPRegexp(Form(isminus?"-":"^%s$", str.Data())); break;
+            case 1: fRunType2 = TPRegexp(Form("^%s$", str.Data())); break;
+            case 2: fRegexp1  = TPRegexp(Form("^%s$", str.Data())); break;
+            case 3: fRegexp2  = TPRegexp(Form("^%s$", str.Data())); break;
+            case 4: fMin      = str.Atoi();               break;
+            case 5: fMax      = str.Atoi();               break;
+            }
+        }
+        //cout << endl;
+    }
+
+public:
+    CheckMatch() : fRunType1(""), fRunType2(""), fRegexp1(""), fRegexp2("") {}
+
+    CheckMatch(const TString &txt) : fRunType1(""), fRunType2(""), fRegexp1(""), fRegexp2(""), fMin(0), fMax((UInt_t)-1)
+    {
+        TObjArray *arr = txt.Tokenize(" ");
+        Init(*arr);
+        delete arr;
+    }
+
+    CheckMatch(TObjArray &arr, Int_t idx=0) : fRunType1(""), fRunType2(""), fRegexp1(""), fRegexp2(""), fMin(0), fMax((UInt_t)-1)
+    {
+        Init(arr, idx);
+    }
+
+    CheckMatch(const char *from, const char *to, Int_t min=0, Int_t max=-1)
+        : fRunType1(".*"), fRunType2(".*"), fRegexp1(Form("^%s$", from)), fRegexp2(Form("^%s$", to)), fMin(min), fMax(max)
+    {
+    }
+
+    Int_t Matches(const TString &rt1, const TString &rt2, const TString &lc1, const TString &lc2, UInt_t run=0)
+    {
+        if (run>0)
+        {
+            if (run<fMin || run>fMax)
+                return kFALSE;
+        }
+
+        const TString test("X-"); // FIXME:STUPID!
+
+        //if (test.Index(fRunType2)==1)
+         //   return -(!rt1(fRunType1).IsNull() && !lc1(fRegexp1).IsNull());
+
+        if (test.Index(fRunType1,0)==1)
+            return -(!rt2(fRunType2).IsNull() && !lc2(fRegexp2).IsNull());
+
+        return !rt1(fRunType1).IsNull() && !rt2(fRunType2).IsNull() && !lc1(fRegexp1).IsNull() && !lc2(fRegexp2).IsNull();
+    }
+    ClassDef(CheckMatch,0)
+};
+ClassImp(CheckMatch);
+
+class CheckList : public TList
+{
+public:
+    CheckList() { SetOwner(); }
+    Int_t Matches(const TString &rt1, const TString &rt2, const TString &lc1, const TString &lc2, Int_t run=-1) const
+    {
+        TIter Next(this);
+
+        CheckMatch *check = 0;
+
+        while ((check=(CheckMatch*)Next()))
+        {
+            const Int_t rc = check->Matches(rt1, rt2, lc1, lc2, run);
+            if (rc)
+                return rc;
+        }
+
+        return kFALSE;
+    }
+    ClassDef(CheckList,0)
+};
+ClassImp(CheckList);
+
+class SequenceBuild : public MSQLMagic
+{
+private:
+    TString fPathRawData;
+    TString fPathSequences;
+
+    TMap  fMap;
+    TList fListRegexp;
+
+    /*
+    TString GetKeyName(TString col, TString key)
+    {
+        col(TRegexp("^Elt")) = "";
+        return QueryNameOfKey(col, key, kFALSE);
+    }*/
+
+    Int_t CheckTransition(TSQLResult &res, const TString *keys, TSQLRow &row, Int_t i)
+    {
+        // Get the name of the column from result table
+        const TString key = res.GetFieldName(i);
+
+        // Get the list with the allowed attributed from the map
+        CheckList *list = dynamic_cast<CheckList*>(fMap.GetValue(key));
+        if (!list)
+            return kFALSE;
+
+        // Check whether the current run (row[0]) with the current attribute
+        // (row[i]) and the current run-type (row[1]) matches the attribute
+        // of the last run (keys[i] with run-type row[i])
+        return list->Matches(keys[1], row[1], keys[i], row[i], atoi(row[0]));
+    }
+
+    Bool_t InsertSequence(Int_t from, Int_t to)
+    {
+        cout << "     - Inserting Sequence into database." << endl;
+
+        // ========== Request number of events ==========
+
+        const TString runtime =
+            "SUM(if(TIME_TO_SEC(fRunStop)-TIME_TO_SEC(fRunStart)<0,"
+            " TIME_TO_SEC(fRunStop)-TIME_TO_SEC(fRunStart)+24*60*60,"
+            " TIME_TO_SEC(fRunStop)-TIME_TO_SEC(fRunStart))), ";
+
+        const TString where = Form("(fRunNumber BETWEEN %d AND %d) AND fExcludedFDAKEY=1",
+                                   from, to);
+
+        TString query;
+        query  = "SELECT SUM(fNumEvents), ";
+        query += runtime;
+        query += " MIN(fZenithDistance), MAX(fZenithDistance), ";
+        query += " MIN(fAzimuth), MAX(fAzimuth), ";
+        query += " MIN(fRunStart), MAX(fRunStop), ";
+        query += " ELT(MAX(FIELD(fLightConditionsKEY, 1, 2, 7, 5, 8)), 1, 2, 7, 5, 8) ";
+        query += " FROM RunData WHERE ";
+        query += where;
+        query += " AND fRunTypeKEY=2";
+
+        TSQLResult *res = Query(query);
+        if (!res)
+            return kFALSE;
+
+        TSQLRow *row = res->Next();
+        if (!row || res->GetFieldCount()!=9)
+        {
+            cout << "ERROR - Wrong result from query: " << query << endl;
+            return kFALSE;
+        }
+
+        const TString nevts = (*row)[0];
+        const TString secs  = (*row)[1];
+        const TString zdmin = (*row)[2];
+        const TString zdmax = (*row)[3];
+        const TString azmin = (*row)[4];
+        const TString azmax = (*row)[5];
+        const TString start = (*row)[6];
+        const TString stop  = (*row)[7];
+        const TString light = (*row)[8];
+
+        delete res;
+
+        // ========== Request data of sequence ==========
+        query = Form("SELECT fSourceKEY, fProjectKEY, "
+                     " fL1TriggerTableKEY, fL2TriggerTableKEY,"
+                     " fHvSettingsKEY, fDiscriminatorThresholdTableKEY,"
+                     " fTriggerDelayTableKEY, fObservationModeKEY "
+                     " FROM RunData WHERE fRunTypeKEY=2 AND %s"
+                     " LIMIT 1", where.Data());
+
+        res = Query(query);
+        if (!res)
+            return kFALSE;
+
+        row = res->Next();
+        if (!row || res->GetFieldCount()!=8)
+        {
+            cout << "ERROR - No result from query: " << query << endl;
+            return kFALSE;
+        }
+
+        const TString set = Form("fSequenceFirst=%d ", from);
+
+        TString query1;
+        query1 += set;
+        query1 += Form(",fSequenceLast=%d,",                   to);
+        query1 += Form(" fSourceKEY=%s,",                      (*row)[0]);
+        query1 += Form(" fProjectKEY=%s,",                     (*row)[1]);
+        query1 += Form(" fNumEvents=%s,",                      nevts.Data());
+        query1 += Form(" fRunTime=%s,",                        secs.Data());
+        query1 += Form(" fRunStart=\"%s\",",                   start.Data());
+        query1 += Form(" fRunStop=\"%s\",",                    stop.Data());
+        query1 += Form(" fZenithDistanceMin=%s,",              zdmin.Data());
+        query1 += Form(" fZenithDistanceMax=%s,",              zdmax.Data());
+        query1 += Form(" fAzimuthMin=%s,",                     azmin.Data());
+        query1 += Form(" fAzimuthMax=%s,",                     azmax.Data());
+        query1 += Form(" fL1TriggerTableKEY=%s,",              (*row)[2]);
+        query1 += Form(" fL2TriggerTableKEY=%s,",              (*row)[3]);
+        query1 += Form(" fHvSettingsKEY=%s,",                  (*row)[4]);
+        query1 += Form(" fDiscriminatorThresholdTableKEY=%s,", (*row)[5]);
+        query1 += Form(" fTriggerDelayTableKEY=%s,",           (*row)[6]);
+        query1 += Form(" fLightConditionsKEY=%s,",             light.Data());
+        query1 += Form(" fObservationModeKEY=%s, ",            (*row)[7]);
+        query1 += "fManuallyChangedKEY=1";
+
+        delete res;
+
+        const TString where2 = Form("(fRunTypeKEY BETWEEN 2 AND 4) AND %s",
+                                    where.Data());
+
+        if (!Insert("Sequences", query1))
+        {
+            cout << "ERROR - Could not insert Sequence into Sequences." << endl;
+            return kFALSE;
+        }
+
+        if (!Update("RunData", set, where))
+        {
+            cout << "ERROR - Could not update RunData." << endl;
+            return kFALSE;
+        }
+
+        if (!Insert("SequenceProcessStatus", set))
+        {
+            cout << "ERROR - Could not insert Sequence into SequenceProcessStatus." << endl;
+            return kFALSE;
+        }
+
         return kTRUE;
     }
 
-    TSQLResult *res = serv.Query(query1);
-    if (!res)
+    Bool_t DeleteSequence(Int_t sequ)
+    {
+        if (fPathRawData.IsNull() || fPathSequences.IsNull())
+        {
+            cout << "       + Deletion " << sequ << " skipped due to missing path." << endl;
+            return kTRUE;
+        }
+
+        //queries to delete information from the database
+        const TString query(Form("fSequenceFirst=%d", sequ));
+
+        //commands to delete files from the disk
+        const TString fname(Form("%s/%04d/sequence%08d.txt", fPathSequences.Data(),sequ/10000, sequ));
+        const TString cmd1(Form("rm -rf %s/callisto/%04d/%08d/", fPathRawData.Data(), sequ/10000, sequ));
+        const TString cmd2(Form("rm -rf %s/star/%04d/%08d/", fPathRawData.Data(), sequ/10000, sequ));
+
+        if (!Delete("Calibration", query))
+            return 2;
+
+        if (!Delete("Star", query))
+            return 2;
+
+        if (!Delete("SequenceProcessStatus", query))
+            return 2;
+
+        if (!Delete("Sequences", query))
+            return 2;
+
+        if (!Update("RunData", "fSequenceFirst=0", query))
+            return 2;
+
+        if (IsDummy())
+        {
+            cout << "       + unlink " << fname << endl;
+            cout << "       + " << cmd1 << endl;
+            cout << "       + " << cmd2 << endl;
+            return kTRUE;
+        }
+
+        gSystem->Unlink(fname);
+
+        gSystem->Exec(cmd1);
+        gSystem->Exec(cmd2);
+
+        return kTRUE;
+    }
+
+    Int_t CheckSequence(Int_t runstart, Int_t runstop)
+    {
+        const char *fmt1 = "SELECT fRunNumber FROM RunData WHERE";
+        const char *fmt2 = "AND fExcludedFDAKEY=1 AND (fRunTypeKEY BETWEEN 2 AND 4) ORDER BY fRunNumber";
+
+        const TString query1 = Form("%s fSequenceFirst=%d %s",            fmt1, runstart, fmt2);
+        const TString query2 = Form("%s fRunNumber BETWEEN %d AND %d %s", fmt1, runstart, runstop, fmt2);
+
+        TSQLResult *res1 = Query(query1);
+        if (!res1)
+            return 2;
+
+        TSQLResult *res2 = Query(query2);
+        if (!res2)
+        {
+            delete res1;
+            return 2;
+        }
+
+        while (1)
+        {
+            TSQLRow *row1 = res1->Next();
+            TSQLRow *row2 = res2->Next();
+
+            if (!row1 && !row2)
+                return kTRUE;
+
+            if (!row1 || !row2)
+                return kFALSE;
+
+            if (atoi((*row1)[0])!=atoi((*row2)[0]))
+                return kFALSE;
+        }
+
         return kFALSE;
-    delete res;
-
-    res = serv.Query(query2);
-    if (!res)
-        return kFALSE;
-    delete res;
-
-    res = serv.Query(query3);
-    if (!res)
-        return kFALSE;
-    delete res;
-
-    res = serv.Query(query4);
-    if (!res)
-        return kFALSE;
-    delete res;
-
-    res = serv.Query(query5);
-    if (!res)
-        return kFALSE;
-    delete res;
-
-    gSystem->Unlink(fname);
-
-    gSystem->Exec(command);
-    gSystem->Exec(command2);
-
-    return kTRUE;
-}
-
-Int_t DoCheck(TSQLResult &res)
-{
-    TArrayI data(5);
-    Int_t n = 0;
-
-    TSQLRow *row=0;
-    while ((row=res.Next()))
-    {
-        n++;
-
-        if (data[0]==0)
-        {
-            for (int i=0; i<data.GetSize(); i++)
-                data[i] = atoi((*row)[i]);
-            continue;
-        }
-
-        for (int i=1; i<data.GetSize(); i++)
-        {
-            if (data[i] != atoi((*row)[i]))
-                return i+1;
-        }
-    }
-    return n==0 ? 0 : -1;
-}
-
-
-//check values, that can be different for different runtypes
-Bool_t CheckRuns(MSQLServer &serv, Int_t from, Int_t to, Int_t type)
-{
-    TString query("SELECT fRunNumber, fL1TriggerTableKEY, fL2TriggerTableKEY,"
-                  " fCalibrationScriptKEY, fProjectKEY FROM RunData");
-    query += Form(" WHERE fRunTypeKEY=%d AND fExcludedFDAKEY=1 AND "
-                  " (fRunNumber BETWEEN %d AND %d)"
-                  " ORDER BY fRunNumber", type, from, to);
-
-    TSQLResult *res = serv.Query(query);
-    if (!res)
-        return kFALSE;
-
-    Int_t rc = DoCheck(*res);
-    delete res;
-
-    switch (rc)
-    {
-    case 0: cout << "ERROR - No runs found for check!"             << endl; break;
-    case 1: cout << "ERROR - fRunNumber doesn't match!"            << endl; break;
-    case 2: cout << "ERROR - fL1TriggerTableKEY doesn't match!"    << endl; break;
-    case 3: cout << "ERROR - fL2TriggerTableKEY doesn't match!"    << endl; break;
-    case 4: cout << "ERROR - fCalibrationScriptKEY doesn't match!" << endl; break;
-    case 5: cout << "ERROR - fProjectKEY doesn't match!"           << endl; break;
-    }
-
-    return rc<0;
-}
-
-Int_t CheckSequence(MSQLServer &serv, TString datapath, TString sequpath, Int_t from, Int_t to, Bool_t dummy)
-{
-    Int_t rc=0;
-    //rc=0 means sequence not found -> insert
-    //rc=1 means deleting sequence(s) worked -> insert
-    //rc=2 means sequence is still the same -> insert not neccessary
-    //if deleting sequence doesn't work -> return -1
-
-
-    //getting # of sequence (in sequDB) between from and to
-    TString query("SELECT fSequenceFirst FROM Sequences WHERE (fSequenceFirst ");
-    query += Form("BETWEEN %d and %d OR fSequenceLast BETWEEN %d and %d) AND "
-                  "fManuallyChangedKEY=1 ", from, to, from, to);
-
-    TSQLResult *res = serv.Query(query);
-    if (!res)
-        return -1;
-
-    TArrayI sequences;
-    Int_t numsequ=0;
-
-    TSQLRow *row=0;
-    while ((row=res->Next()))
-    {
-        numsequ++;
-        sequences.Set(numsequ);
-        sequences.AddAt(atoi((*row)[0]), numsequ-1);
-    }
-    delete res;
-
-    //if there's no sequence in the table Sequences -> check other tables
-    //if there's one sequence -> check if the sequence is identical
-    //if there are more sequences -> delete them
-    switch (numsequ)
-    {
-    case 0:
-        //FIXME: like this the check is of no use, but when doing it
-        //       without the check for manuallychanged, all manually
-        //       changed sequences would be deleted
-        cout << "   + found no sequence in Sequ-DB -> check other tables" << endl;
-        cout << "     deleting every sequence found in Calibration, Star or" << endl;
-        cout << "     SequenceProcessStatus between " << from << " and " << to << endl;
-
-        //calibration table
-        query=Form("SELECT Calibration.fSequenceFirst FROM Calibration "
-                   " LEFT JOIN Sequences ON Calibration.fSequenceFirst=Sequences.fSequenceFirst "
-                   " WHERE fManuallyChangedKEY=1 AND Calibration.fSequenceFirst BETWEEN %d and %d",
-                   from, to);
-        res = serv.Query(query);
+    }
+
+    Int_t CreateSequence(Int_t runstart, Int_t runstop)
+    {
+        cout << "   * Creating Sequence " << runstart << "-" << runstop << ":" << endl;
+
+        TString query=
+            Form("SELECT fSequenceFirst FROM RunData "
+                 " WHERE fRunNumber BETWEEN %d AND %d AND "
+                 " fSequenceFirst>0 AND "
+                 " fExcludedFDAKEY=1 AND (fRunTypeKEY BETWEEN 2 AND 4)"
+                 " GROUP BY fSequenceFirst", runstart, runstop);
+
+        TSQLResult *res = Query(query);
         if (!res)
-            return -1;
-        row=0;
-        while ((row=res->Next()))
-        {
-            if (!DeleteSequence(serv, datapath, sequpath, atoi((*row)[0]), dummy))
-                return -1;
-            rc=1;
-        }
-        delete res;
-
-        //Star table
-        query=Form("SELECT Star.fSequenceFirst FROM Star "
-                   " LEFT JOIN Sequences ON Star.fSequenceFirst=Sequences.fSequenceFirst "
-                   " WHERE fManuallyChangedKEY=1 AND  Star.fSequenceFirst BETWEEN %d and %d",
-                   from, to);
-        res = serv.Query(query);
-        if (!res)
-            return -1;
-        row=0;
-        while ((row=res->Next()))
-        {
-            if (!DeleteSequence(serv, datapath, sequpath, atoi((*row)[0]), dummy))
-                return -1;
-            rc=1;
-        }
-        delete res;
-
-        //SequenceProcessStatus table
-        query=Form("SELECT SequenceProcessStatus.fSequenceFirst FROM SequenceProcessStatus "
-                   " LEFT JOIN Sequences ON SequenceProcessStatus.fSequenceFirst=Sequences.fSequenceFirst "
-                   " WHERE fManuallyChangedKEY=1 AND  SequenceProcessStatus.fSequenceFirst BETWEEN %d and %d",
-                   from, to);
-        res = serv.Query(query);
-        if (!res)
-            return -1;
-        row=0;
-        while ((row=res->Next()))
-        {
-            if (!DeleteSequence(serv, datapath, sequpath, atoi((*row)[0]), dummy))
-                return -1;
-            rc=1;
-        }
-        delete res;
-        break;
-
-    case 1:
-        cout << "   + found one sequence: " << sequences.At(0) << " -> check sequence." << endl;
-        if (sequences.At(0)!=from)
-        {
-            if (!DeleteSequence(serv, datapath, sequpath, sequences.At(0), dummy))
-                return -1;
-            rc=1;
+            return 2;
+
+        const Int_t cnt = res->GetRowCount();
+
+        Int_t rc = kTRUE;
+        if (cnt==1)
+        {
+            TSQLRow *row=res->Next();
+            const Int_t check = CheckSequence(runstart, runstop);
+            if (check==kFALSE)
+            {
+                cout << "     - Identical sequence already existing." << endl;
+                delete res;
+                return kTRUE;
+            }
+            if (check==2)
+                rc=2;
+            else
+            {
+                cout << "     - Deleting quasi-identical sequence " << atoi((*row)[0]) << endl;
+                if (DeleteSequence(atoi((*row)[0]))==2)
+                    rc = 2;
+            }
         }
         else
         {
-            cout << "     * sequence is the same -> checking the runs." << endl;
-
-            //getting olf runs
-            query=Form("SELECT fRunNumber FROM RunData WHERE fSequenceFirst=%d ", from);
-            res = serv.Query(query);
-            if (!res)
-                return -1;
-
-            TArrayI oldruns;
-            Int_t count=0;
-            row=0;
+            TSQLRow *row=0;
             while ((row=res->Next()))
             {
-                count++;
-                oldruns.Set(count);
-                oldruns.AddAt(atoi((*row)[0]), count-1);
+                cout << "     - Deleting overlapping sequence " << atoi((*row)[0]) << endl;
+                if (DeleteSequence(atoi((*row)[0]))==2)
+                    rc = 2;
             }
-            delete res;
-
-            //getting new runs
-            query=Form("SELECT fRunNumber FROM RunData WHERE fRunNumber BETWEEN %d and %d AND fExcludedFDAKEY=1", from, to);
-            res = serv.Query(query);
-            if (!res)
-                return -1;
-            TArrayI newruns;
-            count=0;
-            row=0;
-            while ((row=res->Next()))
+        }
+
+        delete res;
+
+        if (rc==2)
+            return 2;
+
+        if (!InsertSequence(runstart, runstop))
+            return 2;
+
+        return kTRUE;
+    }
+
+    Bool_t ReadResources(const char *fname)
+    {
+        TPRegexp regexp("^\\[.*\\]$");
+
+        ifstream fin(fname);
+        if (!fin)
+        {
+            cout << "Cannot open file " << fname << ": ";
+            cout << strerror(errno) << endl;
+            return kFALSE;
+        }
+
+        Int_t section = 0;
+
+        TString key;
+        while (1)
+        {
+            TString txt;
+            txt.ReadLine(fin);
+            if (!fin)
+                break;
+
+            txt = txt.Strip(TString::kBoth);
+
+            if (txt[0]=='#' || txt.IsNull())
+                continue;
+
+            if (txt[0]=='[' && section!=2)
             {
-                count++;
-                newruns.Set(count);
-                newruns.AddAt(atoi((*row)[0]), count-1);
+                //cout << txt << endl;
+                section = 0;
+                if (txt(regexp)=="[Transition]")
+                    section = 1;
+                if (txt(regexp)=="[Regexp]")
+                    section = 2;
+                continue;
             }
-            delete res;
-
-            //comparing old and new runs (first the # of runs, if it is the same, also the single runnumbers
-            if (oldruns.GetSize()!=newruns.GetSize())
+
+            TObjArray *arr = txt.Tokenize(" ");
+
+            if (arr->GetEntries()>0)
+                switch (section)
+                {
+                case 1:
+                    {
+                        TString key = arr->At(0)->GetName();
+                        key.Prepend("f");
+                        key.Append("KEY");
+
+                        CheckList *list = dynamic_cast<CheckList*>(fMap.GetValue(key));
+                        if (!list)
+                        {
+                            //cout << key << endl;
+                            list = new CheckList;
+                            fMap.Add(new TObjString(key), list);
+                        }
+
+                        if (arr->GetEntries()>1)
+                        {
+                            //cout << key << " ";
+                            list->Add(new CheckMatch(*arr, 1));
+                        }
+                    }
+                    break;
+                case 2:
+                    fListRegexp.Add(new Rule(*arr));
+                    break;
+                }
+
+            delete arr;
+        }
+
+        return kTRUE;
+    }
+
+    TString GetELT(const char *col, TSQLResult *res, TList &regexp)
+    {
+        TObjArray names; // array with old names (including regexp)
+
+        // Add to array and expand the array if necessary
+        TSQLRow *row=0;
+        while ((row=res->Next()))
+            names.AddAtAndExpand(new TObjString((*row)[1]), atoi((*row)[0]));
+
+        // Now a LUT is build which converts the keys for
+        // the names including the regexp into keys for
+        // the names excluding the regexp
+        TString elt(Form("ELT(RunData.f%sKEY+1", col));
+
+        // loop over all entries in the list
+        const Int_t n = names.GetSize();
+        for (int i=0; i<n; i++)
+        {
+            // For all entries which are not in the list
+            // write an undefined value into the LUT
+            TObject *o = names.UncheckedAt(i);
+            if (!o)
             {
-//                cout << " number of runs (" << oldruns.GetSize() << " - " << newruns.GetSize()
-//                    << ") is not the same -> deleting sequence " << sequences.At(0) << endl;
-                if (!DeleteSequence(serv, datapath, sequpath, sequences.At(0), dummy))
-                    return -1;
-                rc=1;
+                elt += ",0";
+                continue;
             }
-            else
+
+            // Remove the regexp from the string which includes it
+            TString name = o->GetName();
+
+            TIter NextR(&regexp);
+            TObject *reg=0;
+            while ((reg=NextR()))
             {
-                cout << "       · number of runs is the same -> checking the single runnumbers." << endl;
-
-                for (Int_t i=0;i<newruns.GetSize();i++)
+                TPRegexp reg(reg->GetName());
+                const Ssiz_t pos = name.Index(reg, 0);
+                if (pos>0)
                 {
-//                    cout << "i: " << i << " - new: " << newruns.At(i) << " - old: " << oldruns.At(i) << endl;
-                    if (newruns.At(i)==oldruns.At(i))
-                        continue;
-
-                    cout << "       · " << i << ". run is not the same ( " << oldruns.At(i) << " -- " << newruns.At(i)
-                        << ") -> deleting sequence " << sequences.At(0) << endl;
-                    if (!DeleteSequence(serv, datapath, sequpath, sequences.At(0), dummy))
-                        return -1;
-                    return 1;
+                    name.Remove(pos);
+                    name += "-W";
+                    break;
                 }
             }
-        }
-        return 2;
-
-    default:
-        cout << " - found " << numsequ << " sequences -> deleting them " << endl;
-
-        for (Int_t i=0;i<sequences.GetSize();i++)
-        {
-                cout << "   + deleting sequence " << sequences.At(i) << "... <" << i << ">" << endl;
-                if (!DeleteSequence(serv, datapath, sequpath, sequences.At(i), dummy))
-                    return -1;
-                rc=1;
-        }
-    }
-
-    return rc;
-}
-
-Bool_t InsertSequence(MSQLServer &serv, Int_t from, Int_t to)
-{
-    cout << "       · Inserting sequence " << from << " ... " << endl;
-
-    // ========== Request number of events ==========
-    TString query("SELECT SUM(fNumEvents), "
-                  " SUM(if(TIME_TO_SEC(fRunStop)-TIME_TO_SEC(fRunStart)<0,"
-                  "  TIME_TO_SEC(fRunStop)-TIME_TO_SEC(fRunStart)+24*60*60,"
-                  "  TIME_TO_SEC(fRunStop)-TIME_TO_SEC(fRunStart))), ");
-    query +=      " MIN(fZenithDistance), MAX(fZenithDistance), ";
-    query +=      " MIN(fAzimuth), MAX(fAzimuth) ";
-    query += Form(" FROM RunData WHERE fRunTypeKEY=2 AND "
-                  " (fRunNumber BETWEEN %d AND %d) AND fExcludedFDAKEY=1",
-                  from, to);
-
-    TSQLResult *res = serv.Query(query);
-    if (!res)
-        return kFALSE;
-
-    TSQLRow *row = res->Next();
-    if (!row || !(*row)[0])
-    {
-        cout << "ERROR - No result from query: " << query << endl;
-        return kFALSE;
-    }
-
-    TString nevts = (*row)[0];
-    TString secs  = (*row)[1];
-    TString zdmin = (*row)[2];
-    TString zdmax = (*row)[3];
-    TString azmin = (*row)[4];
-    TString azmax = (*row)[5];
-
-    delete res;
-
-    // ========== Request start time of sequence ==========
-    query = Form("SELECT fRunStart FROM RunData WHERE fRunNumber=%d AND fExcludedFDAKEY=1", from);
-
-    res = serv.Query(query);
-    if (!res)
-        return kFALSE;
-
-    row = res->Next();
-    if (!row || !(*row)[0])
-    {
-        cout << "ERROR - No result from query: " << query << endl;
-        return kFALSE;
-    }
-
-    TString start((*row)[0]);
-
-    delete res;
-
-    // ========== Request data of sequence ==========
-    query = Form("SELECT fSourceKEY, fProjectKEY, "
-                 " fL1TriggerTableKEY, fL2TriggerTableKEY,"
-                 " fHvSettingsKEY, fDiscriminatorThresholdTableKEY,"
-                 " fTriggerDelayTableKEY, fLightConditionsKEY, "
-                 " fTestFlagKEY, fObservationModeKEY "
-                 " FROM RunData"
-                 " WHERE fRunTypeKEY=2 AND fExcludedFDAKEY=1 AND (fRunNumber BETWEEN %d AND %d)"
-                 " LIMIT 1", from, to);
-
-    res = serv.Query(query);
-    if (!res)
-        return kFALSE;
-
-    row = res->Next();
-    if (!row)
-    {
-        cout << "ERROR - No result from query: " << query << endl;
-        return kFALSE;
-    }
-
-    TString query1("INSERT Sequences SET");
-    query1 += Form(" fSequenceFirst=%d,  fSequenceLast=%d,", from, to);
-    query1 += Form(" fSourceKEY=%s,",                      (*row)[0]);
-    query1 += Form(" fProjectKEY=%s,",                     (*row)[1]);
-    query1 += Form(" fNumEvents=%s,",                      nevts.Data());
-    query1 += Form(" fRunTime=%s,",                        secs.Data());
-    query1 += Form(" fRunStart=\"%s\",",                   start.Data());
-    query1 += Form(" fZenithDistanceMin=%s,",              zdmin.Data());
-    query1 += Form(" fZenithDistanceMax=%s,",              zdmax.Data());
-    query1 += Form(" fAzimuthMin=%s,",                     azmin.Data());
-    query1 += Form(" fAzimuthMax=%s,",                     azmax.Data());
-    query1 += Form(" fL1TriggerTableKEY=%s,",              (*row)[2]);
-    query1 += Form(" fL2TriggerTableKEY=%s,",              (*row)[3]);
-    query1 += Form(" fHvSettingsKEY=%s,",                  (*row)[4]);
-    query1 += Form(" fDiscriminatorThresholdTableKEY=%s,", (*row)[5]);
-    query1 += Form(" fTriggerDelayTableKEY=%s,",           (*row)[6]);
-    query1 += Form(" fLightConditionsKEY=%s,",             (*row)[7]);
-    query1 += Form(" fTestFlagKEY=%s,",                    (*row)[8]);
-    query1 += Form(" fObservationModeKEY=%s, ",            (*row)[9]);
-    query1+="fManuallyChangedKEY=1";
-
-
-    TString query2 = Form("UPDATE RunData SET fSequenceFirst=%d WHERE"
-                          "  (fRunNumber  BETWEEN %d AND %d) AND"
-                          "  (fRunTypeKEY BETWEEN  2 AND  4) AND"
-                          "  fSourceKEY=%s AND fHvSettingsKEY=%s AND fExcludedFDAKEY=1",
-                          from, from, to, (*row)[0], (*row)[4]);
-
-    TString query3 = Form("INSERT SequenceProcessStatus SET fSequenceFirst=%d ", from);
-
-    delete res;
-
-    /*
-     cout << "q1: " << query1 << endl;
-     cout << "q2: " << query2 << endl;
-     cout << "q3: " << query3 << endl;
-     */
-
-    res = serv.Query(query1);
-    if (!res)
-    {
-        cout << "ERROR - Could not insert Sequence into Sequences." << endl;
-        return kFALSE;
-    }
-    delete res;
-
-    res = serv.Query(query2);
-    if (!res)
-    {
-        cout << "ERROR - Could not update RunData." << endl;
-        return kFALSE;
-    }
-    delete res;
-
-    res = serv.Query(query3);
-    if (!res)
-    {
-        cout << "ERROR - Could not insert Sequence into SequenceProcessStatus." << endl;
-        return kFALSE;
-    }
-    delete res;
-
-    return kTRUE;
-}
-
-//
-// Handling new sequence (checking runs; checking for old sequence; inserting sequence, if everything is okay)
-//
-Bool_t NewSequence(MSQLServer &serv, TString datapath, TString sequpath, Int_t from, Int_t to, TList &sequlist, Bool_t dummy)
-{
-    cout << " - Found Sequence (" << from << ", " << to << ") ... checking runs..." << flush;
-
-    if (!CheckRuns(serv, from, to, 2))
-    {
-        cout << "Warning - Found inconsistency in data-runs (" << from << ", " << to << ")" << endl;
-        //sequence is not built, but kTRUE is returned, to allow
-        //the automatic processing of the other sequences of this day
+
+            // Check if such a Key exists, if not insert it
+            const Int_t key = QueryKeyOfName(col, name);
+
+            // RESOLVE return code!!!
+            //if (key<0)
+            //     return "";
+
+            // add index to the LUT
+            elt += Form(",%d", key);
+        }
+
+        // close LUT expression
+        //    elt += ") AS Elt";
+        //    elt += col;
+
+        elt += ") AS f";
+        elt += col;
+        elt += "KEY";
+
+        // return result
+        return elt;
+    }
+
+    TString GetELT(const char *col, TSQLResult *res, TString regexp)
+    {
+        TList list;
+        list.SetOwner();
+        list.Add(new TObjString(regexp));
+        return GetELT(col, res, list);
+    }
+
+    Bool_t HasAtLeastOne(TString src, TString chk) const
+    {
+        src.ToLower();
+        chk.ToLower();
+
+        for (int i=0; i<chk.Length(); i++)
+            if (src.First(chk[i])<0)
+                return kFALSE;
+
         return kTRUE;
     }
-    if (!CheckRuns(serv, from, to, 3))
-    {
-        cout << "Warning - Found inconsistency in ped-runs (" << from << ", " << to << ")" << endl;
-        //sequence is not built, but kTRUE is returned, to allow
-        //the automatic processing of the other sequences of this day
-        return kTRUE;
-    }
-
-    cout << "ok." << endl;
-
-
-    cout << "   + checking sequence..." << endl;
-
-    TObject *sequ;
-    Bool_t rc=kFALSE;
-    switch (CheckSequence(serv, datapath, sequpath, from, to, dummy))
-    {
-    case 0:
-        cout << "       · sequence not found -> inserting " << from << flush;
-        if (dummy)
-        {
-            cout << " <dummy> " << endl;
+
+    TString PrepareString(TSQLResult &res, TArrayI &runs)
+    {
+        // Number of result rows
+        const Int_t rows = res.GetRowCount();
+
+        runs.Set(rows);       // initialize size of array for run numbers
+
+        TArrayD start(rows);  // instantiate array for start times
+        TArrayD stop(rows);   // instantiate array for stop times
+
+        TString str;          // result string
+
+        Int_t idx=0;
+        TSQLRow *row=0;
+        while ((row=res.Next()))
+        {
+            runs[idx] = atoi((*row)[0]);          // run number
+
+            const TString tstart = ((*row)[2]);   // start time
+            const TString tstop  = ((*row)[3]);   // stop time
+
+            start[idx] = MTime(tstart).GetMjd();  // convert to double
+            stop[idx]  = MTime(tstop).GetMjd();   // convert to double
+
+            // This is a workaround for broken start-times
+            if (tstart=="0000-00-00 00:00:00")
+                start[idx] = stop[idx];
+
+            // Add a run-type character for this run to the string
+            str += RunType((*row)[1]);
+
+            // Increase index
+            idx++;
+        }
+
+        // Now the P- and D- runs are classified by the time-distance
+        // to the next or previous C-Run
+        Double_t lastc = -1;
+        Double_t nextc = -1;
+        for (int i=0; i<str.Length(); i++)
+        {
+            if (str[i]=='C')
+            {
+                // Remember stop time of C-Run as time of last C-run
+                lastc = stop[i];
+
+                // Calculate start time of next C-Run
+                const TString residual = str(i+1, str.Length());
+                const Int_t pos = residual.First('C');
+
+                // No C-Run found anymore. Finished...
+                if (pos<0)
+                    break;
+
+                // Remember start  time of C-Run as time of next C-run
+                nextc = start[i+1+pos];
+                continue;
+            }
+
+            // Check whether the identifying character should
+            // be converted to lower case
+            if (start[i]-lastc>nextc-stop[i])
+                str[i] = tolower(str[i]);
+        }
+        //cout << str << endl;
+        return str;
+    }
+
+    void PrintResidual(Int_t runstart, Int_t runstop, TString residual, const char *descr)
+    {
+        residual.ToLower();
+
+        // Count number of unsequences "characters"
+        const Int_t nump = residual.CountChar('p');
+        const Int_t numd = residual.CountChar('d');
+        const Int_t numc = residual.CountChar('c');
+
+        // Print some information to the output steram
+        if (nump+numc+numd==0)
+            return;
+
+        cout << "   ! " << runstart << "-" << runstop << " [" << setw(3) << 100*residual.Length()/(runstop-runstart+1) << "%]: " << descr << " not sequenced:  P=" << nump << "  C=" << numc << "  D=" << numd;
+        if (numd>0)
+            cout << "  (DATA!)";
+
+        if (nump==0 || numc==0 || numd==0)
+            cout << "  Missing";
+        if (numd==0)
+            cout << " D";
+        if (nump==0)
+            cout << " P";
+        if (numc==0)
+            cout << " C";
+
+        cout << endl;
+    }
+
+    Int_t SplitBlock(Int_t runstart, Int_t runstop)
+    {
+        // Request data necessary to split block into sequences
+        const TString query=
+            Form("SELECT fRunNumber, fRunTypeKEY, fRunStart, fRunStop"
+                 " FROM RunData "
+                 " WHERE fRunNumber BETWEEN %d AND %d AND "
+                 " fExcludedFDAKEY=1 AND (fRunTypeKEY BETWEEN 2 AND 4)"
+                 " ORDER BY fRunNumber", runstart, runstop);
+
+        // Send query
+        TSQLResult *res = Query(query);
+        if (!res)
+            return 2;
+
+        // Get String containing the sequence of P-,C- and D-Runs
+        // and an array with the corresponding run-numbers
+        TArrayI runs;
+        const TString str = PrepareString(*res, runs);
+
+        delete res;
+
+        // Check if the prepared string at least contains one run of each type
+        if (!HasAtLeastOne(str, "PCD"))
+        {
+            PrintResidual(runstart, runstop, str, "Block");
             return kTRUE;
         }
-        cout << endl;
-        if ((sequ=sequlist.Remove(sequlist.FindObject(Form("%d", from)))))
-            delete sequ;
-        return InsertSequence(serv, from, to);
-
-    case 1:
-        cout << "       · deleting successfully finished -> inserting sequence " << from << flush;
-        if (dummy)
-        {
-            cout << " <dummy> " << endl;
-            return kTRUE;
-        }
-        cout << endl;
-        if ((sequ=sequlist.Remove(sequlist.FindObject(Form("%d", from)))))
-            delete sequ;
-        return InsertSequence(serv, from, to);
-
-    case 2:
-        cout << "       · sequence " << from << " is already existing -> inserting not necessary" << endl;
-        if ((sequ=sequlist.Remove(sequlist.FindObject(Form("%d", from)))))
-            delete sequ;
-        return kTRUE;
-
-    case -1:
-        cout << "       · deleting went wrong " << endl;
-        return kFALSE;
-    }
-
-
-    return rc;
-}
-
-//
-// Build Sequences in range of runs
-//
-Bool_t Process(MSQLServer &serv, TString datapath, TString sequpath, Int_t from, Int_t to,  TList &sequlist, Bool_t dummy)
-{
-
-    TString query(Form("SELECT fRunNumber, fRunTypeKEY, fRunStart, fRunStop"
-                       " FROM RunData"
-                       " WHERE fRunNumber BETWEEN %d AND %d AND "
-                       " fExcludedFDAKEY=1 AND (fRunTypeKEY BETWEEN 2 AND 4)"
-                       " ORDER BY fRunNumber", from, to));
-
-    TSQLResult *res = serv.Query(query);
-    if (!res)
-        return kFALSE;
-
-    TExMap map;
-
-    Int_t start=0;
-    Int_t stop=0;
-    Int_t last=0;
-    Int_t first=0;
-
-    MTime lasttime;
-
-    TSQLRow *row=0;
-
-    enum { UNKNOWN, PED=3, CAL=4, DATA=2 };
-    Char_t status = UNKNOWN;
-
-    Int_t nblocks = 0;
-
-    while ((row=res->Next()))
-    {
-        if (!(*row)[1])
-            continue;
-
-        if (start==0)
-        {
-            first = atoi((*row)[0]);
-            if (debug)
-                cout << "First Run: " << first << endl;
-        }
-
-        switch (atoi((*row)[1]))
-        {
-        case CAL: // ---------- CALIBRATION ----------
-            if (status!=CAL)
+
+        // Start the sequence building
+        // ---------------------------
+
+        Int_t   pos = 0;   // Position in the string
+        TExMap  map;       // Map for resulting sequences
+        TString residual;  // Unsequences "characters"
+
+        // Step through the string one character by one
+        cout << "   ";
+        while (pos<str.Length())
+        {
+            Bool_t found = kFALSE;
+
+            // Loop over the predefined regular expressions
+            TIter Next(&fListRegexp);
+            Rule *obj = 0;
+            while ((obj=(Rule*)Next()))
             {
-                start = stop = atoi((*row)[0]);
-                if (!(*row)[2])
-                    cout << "No time available... skipped." << endl;
-                else
+                // Check if regular expressions matchs
+                const Ssiz_t len = obj->Match(str, pos, runs[pos]);
+                if (len>0)
                 {
-                    MTime *tm = new MTime;
-                    tm->SetSqlDateTime((*row)[2]);
-                    map.Add((ULong_t)map.GetSize(), (Long_t)tm, (Long_t)nblocks);
+                    // In case of match get the substring which
+                    // defines the sequence and print it
+                    TString sub = str(pos, len);
+                    sub.ToUpper();
+                    cout << runs[pos]<<":"<< sub << "|";
+
+                    // Add the first and last run of the sequence to the map
+                    map.Add(runs[pos], runs[pos+len-1]);
+
+                    // A sequence was found...
+                    found = kTRUE;
+
+                    // step forward in the string by the length of the sequence
+                    pos += len;
+                    break;
                 }
             }
-            status = CAL;
-            break;
-        default:
-            if (status==CAL)
+
+            // If a sequence was found go on...
+            if (found)
+                continue;
+
+            // print unsequenced characters
+            cout << (char)tolower(str[pos]);
+
+            // Count the number of "characters" not sequenced
+            residual += str[pos];
+
+            // step one character forward
+            pos++;
+        }
+        cout << endl;
+
+        PrintResidual(runstart, runstop, residual, "Runs ");
+
+        // Create all sequences which were previously found
+        Long_t first, last;
+        TExMapIter iter(&map);
+        while (iter.Next(first, last))
+            if (CreateSequence(first, last)==2)
+                return 2;
+
+        return kTRUE;
+    }
+
+    Char_t RunType(Int_t n) const
+    {
+        switch (n)
+        {
+        case 2: return 'D';
+        case 3: return 'P';
+        case 4: return 'C';
+        }
+        return '-';
+    }
+    Char_t RunType(const char *str) const
+    {
+        return RunType(atoi(str));
+    }
+
+    Int_t BuildBlocks(TSQLResult *res, TExMap &blocks)
+    {
+        // col key content
+        // -----------------------------
+        //  0   -  runnumber
+        //  1   0  RunTypeKEY
+        //  2   1  source
+        //  3   2  project
+        //  .   .
+        //  .   .
+        //  .   .  from transition.txt
+        //
+
+        //build blocks of runs, which have the same values
+        //for each block the first and the last run are stored in a TExMap
+        //the values are checked with the help of an array of TStrings
+        Long_t runstart = -1;
+        Long_t runstop  = -1;
+
+        const UInt_t ncols = res->GetFieldCount();
+
+        TString keys[ncols]; // Index 0 is not used (Index 1: RunType)
+
+        // Loop over runs
+        TSQLRow *row=0;
+        while ((row=res->Next()))
+        {
+            // This is the runnumber of the first run in the new block
+            if (runstart<0)
+                runstart=atoi((*row)[0]);
+
+            // Check which transitions might be allowed for this run and
+            // which are not. Check also which attributes should be ignored
+            // for this run. The information about it is stored in the map.
+            Int_t rc[ncols];
+            for (UInt_t i=2; i<ncols; i++)
+                rc[i] = CheckTransition(*res, keys, *row, i);
+
+            for (UInt_t i=2; i<ncols; i++)
             {
-                MTime *tm = new MTime(lasttime);
-                map.Add((ULong_t)map.GetSize(), (Long_t)tm, (Long_t)nblocks);
-
-                stop = last;
-                nblocks++;
-                if (debug)
-                    cout << "Cal Block #" << nblocks << " from " << start << " to " << last << endl;
+                switch (rc[i])
+                {
+                case kTRUE:    // Transition allowed, switch to new attribute
+                    keys[i] = (*row)[i];
+                    continue;
+
+                case -1:       // Ignore attribute, continue with next one
+                    //if (keys[i] == (*row)[i])
+                    //    break; // Only ignore it if it is really different
+                    continue;
+
+                case kFALSE:   // No decision (nothing matching found in map)
+                    break;     //  go on checking
+
+                }
+
+                // If past-attribute is not yet initialized, do it now.
+                if (keys[i].IsNull())
+                    keys[i] = (*row)[i];
+
+                // Check whether key has changed for this run
+                // (this condition is never true for the first run)
+                // This condition in only reached if keys[i] was initialized
+                if (keys[i] == (*row)[i])
+                    continue;
+
+                // Found one block with unique keys, fill values into TExMap
+                // (except if this is the first run processed)
+                cout << endl;
+                cout << " - Identical conditions from " << runstart << " to " << runstop << endl;
+                blocks.Add((ULong_t)blocks.GetSize(), runstart, runstop);
+                if (SplitBlock(runstart, runstop)==2)
+                    return 2;
+                cout << " - Transition from " << RunType(keys[1]) << ":";
+                cout << QueryNameOfKey(res->GetFieldName(i), keys[i]) << " <" << keys[i] << "> to " << RunType((*row)[1]) << ":";
+                cout << QueryNameOfKey(res->GetFieldName(i), (*row)[i]) << " <" << (*row)[i] << ">";
+                cout << " in " << res->GetFieldName(i) << " of " << (*row)[0] << endl;
+
+                // This is already the first run of the new block
+                runstart=atoi((*row)[0]);
+
+                // These are the keys corresponding to the first run
+                // in the new block. All following runs should have
+                // identical keys. Do not set the attribute if for
+                // this attribute the transition check evaluated
+                // to "ignore".
+                for (UInt_t j=2; j<ncols; j++)
+                    keys[j] = rc[j]==-1 ? "" : (*row)[j];
+
+                break;
             }
-            status = UNKNOWN;
-            break;
-        }
-        last = atoi((*row)[0]);
-        lasttime.SetSqlDateTime((*row)[3]);
-    }
-    if (status==CAL)
-    {
-        stop = last;
-        nblocks++;
-        if (debug)
-            cout << "Cal Block #" << nblocks << " from " << start << " to " << stop << endl;
-    }
-
-    if (debug)
-        cout << "Last Run: " << last << endl;
-    delete res;
-
-    if (debug)
-        cout << "Found " << nblocks << " calibration blocks" << endl;
-
-    res = serv.Query(query);
-    if (!res)
-        return kFALSE;
-
-    Int_t n = -1;
-
-    Bool_t rc = kTRUE;
-
-    start = first;
-    while ((row=res->Next()))
-    {
-        if (!(*row)[1])
-            continue;
-
-        MTime tstart, tstop;
-        tstart.SetSqlDateTime((*row)[2]);
-        tstop.SetSqlDateTime((*row)[3]);
-
-        MTime    min;
-        Int_t    nmin = -1;
-        Double_t dmin = 1e35;
-
-        Long_t key, val;
-        TExMapIter nmap(&map);
-        while (nmap.Next(key, val))
-        {
-            MTime *t = (MTime*)key;
-
-            if (nmin==-1)
+
+            keys[1] = (*row)[1]; // Remember run type for next run
+
+            // This is the new runnumber of the last run in this block
+            runstop=atoi((*row)[0]);
+        }
+
+        // If runstart==-1 a possible block would contain a single run...
+        if (runstart>0 && runstart!=runstop)
+        {
+            cout << " - Identical conditions from " << runstart << " to " << runstop << " (last run)" << endl;
+            //fill values into TExMap (last value)
+            blocks.Add((ULong_t)blocks.GetSize(), runstart, runstop);
+            if (SplitBlock(runstart, runstop)==2)
+                return 2;
+        }
+        cout << "Done." << endl << endl;
+
+        return kTRUE;
+    }
+
+public:
+    SequenceBuild(TEnv &env) : MSQLMagic(env)
+    {
+        cout << "buildsequences" << endl;
+        cout << "--------------" << endl;
+        cout << endl;
+        cout << "Connected to " << GetName() << endl;
+
+        fListRegexp.SetOwner();
+
+        // FIXME: THIS IS NOT YET HANDLED
+        if (ReadResources("resources/sequences.rc"))
+            return;
+    }
+    SequenceBuild()
+    {
+        fMap.DeleteAll();
+    }
+    /*
+     SequenceBuild(SequenceBuild &sb) : MSQLServer(sb)
+     {
+        fPathRawData = sb.fPathRawData;
+        fPathSequences = sb.fPathSequences;
+    }*/
+    void SetPathRawData(const char *path) { fPathRawData=path; }
+    void SetPathSequences(const char *path) { fPathSequences=path; }
+
+    int Build(TString day)
+    {
+        cout << endl;
+        cout << "Night of sunrise at " << day << ":" << endl;
+
+        day += " 13:00:00";
+        const TString cond =
+            Form("(fRunStart>ADDDATE(\"%s\", INTERVAL -1 DAY) AND fRunStart<\"%s\") "
+                 "AND fExcludedFDAKEY=1 AND fRunTypeKEY BETWEEN 2 AND 4 "
+                 "ORDER BY fRunNumber",
+                 day.Data(), day.Data());
+
+
+
+        //query all sources observed in this night
+        TString querys(Form("SELECT RunData.fSourceKEY, fSourceName FROM RunData "
+                            "LEFT JOIN Source ON RunData.fSourceKEY=Source.fSourceKEY "
+                            "WHERE %s", cond.Data()));
+        TSQLResult *resx = Query(querys);
+        if (!resx)
+            return 2;
+        TString elts = GetELT("Source", resx, "\\-*W[1-9][ abc]*$");
+        delete resx;
+
+        //query all project names observed in this night
+        TString queryp(Form("SELECT RunData.fProjectKEY, fProjectName FROM RunData "
+                            "LEFT JOIN Project ON RunData.fProjectKEY=Project.fProjectKEY "
+                            "WHERE %s", cond.Data()));
+        resx = Query(queryp);
+        if (!resx)
+            return 2;
+
+        TList regexp;
+        regexp.Add(new TObjString("\\-*W[1-9][abc]?$"));
+        regexp.Add(new TObjString("\\-W[0-9]\\.[0-9][0-9]\\+[0-9][0-9][0-9]$"));
+        TString eltp2 = GetELT("Project", resx, regexp);
+        delete resx;
+        regexp.Delete();
+
+        // Setup query to get all values from the database,
+        // that are relevant for building sequences
+        TString query("SELECT fRunNumber, fRunTypeKEY, ");
+        query += elts;
+        query += ", ";
+        query += eltp2;
+
+        // Now add all entries from the transition table to the query
+        TIter NextPair(&fMap);
+        TObject *mapkey = 0;
+        while ((mapkey=(TPair*)NextPair()))
+            if (!query.Contains(mapkey->GetName()))
             {
-                nmin = val;
-                min  = *(MTime*)key;
-                dmin = fabs((Double_t)*t-(Double_t)tstart);
+                query += ", ";
+                query += mapkey->GetName();
             }
-
-            if (fabs((Double_t)*t-(Double_t)tstart) < dmin)
-            {
-                nmin = val;
-                dmin = fabs((Double_t)*t-(Double_t)tstart);
-                min = *t;
-            }
-            if (fabs((Double_t)*t-(Double_t)tstop) < dmin)
-            {
-                nmin = val;
-                dmin = fabs((Double_t)*t-(Double_t)tstop);
-                min = *t;
-            }
-        }
-
-        if (n!=nmin)
-        {
-            if (n!=-1)
-            {
-                if (!NewSequence(serv, datapath, sequpath, start, last, sequlist, dummy))
-                {
-                    rc = kFALSE;
-                    //continue;
-                }
-            }
-            n = nmin;
-            start = atoi((*row)[0]);
-        }
-        last = atoi((*row)[0]);
-    }
-
-    delete res;
-
-    if (n!=-1 && start!=last)
-    {
-        if (!NewSequence(serv, datapath, sequpath, start, last, sequlist, dummy))
-            rc = kFALSE;
-    }
-
-    if (debug)
-        cout << endl;
-
-    return rc; 
-}
-
-void buildblocks(TSQLResult *res, TExMap &blocks)
-{
-    //build blocks of runs, which have the same values
-    //for each block the first and the last run are stored in a TExMap
-    //the values are checked with the help of an array of TStrings
-    TString keys[7];
-
-    Long_t runstart = -1;
-    Long_t runstop  = -1;
-
-    // "Result set closed" means "Result set empty"
-
-    // Loop over runs
-    TSQLRow *row=0;
-    while ((row=res->Next()))
-    {
-        // Check whether all keys for this run fit
-        for (Int_t i=1; i<8; i++)
-        {
-            // Do not check project key for this runs
-            // (this condition is never true for the first run)
-            if (i==2 && runstart>20100 && runstop<45100)
-                continue;
-
-            // Check whether key has changed for this run
-            // (this condition is never true for the first run)
-            if (keys[i-1] == (*row)[i])
-                continue;
-
-            // Found one block with unique keys, fill values into TExMap
-            // (except if this is the first run processed)
-            if (runstart>0)
-                blocks.Add((ULong_t)blocks.GetSize(), runstart, runstop);
-
-            // This is the runnumber of the first run in the new block
-            runstart=atoi((*row)[0]);
-
-            // These are the keys corresponding to the first run in the new block
-            for (int i=1; i<8; i++)
-                keys[i-1] = (*row)[i];
-
-            break;
-        }
-
-        // This is the new runnumber of the last run in this block
-        runstop=atoi((*row)[0]);
-    }
-
-    if (runstart!=runstop)
-    {
-        //fill values into TExMap (last value)
-        blocks.Add((ULong_t)blocks.GetSize(), runstart, runstop);
-    }
-}
-
-//
-// Build Sequences for the night given by TString day
-//
+        query += Form(" FROM RunData WHERE %s", cond.Data());
+
+        TSQLResult *res = Query(query);
+        if (!res)
+            return 2;
+
+        TExMap blocks;
+        const Int_t rc = BuildBlocks(res, blocks);
+        delete res;
+
+        return rc;
+    }
+
+    Int_t Build()
+    {
+        //get all dates from the database
+        TSQLResult *res = Query("SELECT fDate FROM SequenceBuildStatus ORDER BY fDate DESC");
+        if (!res)
+            return 2;
+
+        //execute buildsequenceentries for all dates
+        TSQLRow *row=0;
+        while ((row=res->Next()))
+            Build((*row)[0]);
+
+        delete res;
+
+        return 1;
+    }
+    ClassDef(SequenceBuild, 0)
+};
+
+ClassImp(SequenceBuild);
+
 int buildsequenceentries(TString day, TString datapath, TString sequpath, Bool_t dummy=kTRUE)
 {
     TEnv env("sql.rc");
 
-    MSQLServer serv(env);
+    SequenceBuild serv(env);
     if (!serv.IsConnected())
     {
@@ -854,91 +1151,8 @@
     }
 
-    cout << "buildsequences" << endl;
-    cout << "--------------" << endl;
-    cout << endl;
-    cout << "Connected to " << serv.GetName() << endl;
-    cout << "Night of sunrise at: " << day << endl;
-    cout << endl;
-
-    day += " 13:00:00";
-    const TString cond(Form("(fRunStart>ADDDATE(\"%s\", INTERVAL -1 DAY) AND fRunStart<\"%s\")",
-                            day.Data(), day.Data()));
-
-    TString elts  = "fSourceKEY";
-    TString eltp2 = "fProjectKEY";
-
-    //get all values from the database, that are relevant for building sequences
-    TString query("SELECT fRunNumber, ");
-    query += elts;
-    query += ", ";
-    query += eltp2;
-    query += Form(", fHvSettingsKEY, fLightConditionsKEY, fDiscriminatorThresholdTableKEY, "
-                  "fTriggerDelayTableKEY, fObservationModeKEY FROM RunData "
-                  "WHERE %s AND fExcludedFDAKEY=1 order by fRunNumber", cond.Data());
-
-    TSQLResult *res = serv.Query(query);
-    if (!res)
-        return 2;
-
-    TExMap blocks;
-    buildblocks(res, blocks);
-    delete res;
-
-    // ---
-    // Now the blocks containing the same observation conditions
-    // are created...
-    // ---
-
-    //get list of current sequence of this night from the database and store it in sequlist
-    TList sequlist;
-    query=Form("SELECT fSequenceFirst FROM Sequences WHERE fManuallyChangedKEY=1 AND %s order by fSequenceFirst",
-               cond.Data());
-
-    res = serv.Query(query);
-    if (!res)
-        return 2;
-
-    cout << "Old sequences: " << flush;
-    TSQLRow *row=0;
-    while ((row=res->Next()))
-    {
-        const char *str =  (*row)[0];
-        cout << str << " " << flush;
-        sequlist.Add(new TObjString(str));
-    }
-    cout << endl;
-
-    delete res;
-
-    Bool_t rc = kTRUE;
-
-    //build sequences in each block of runs
-    Long_t key, val;
-    TExMapIter nblocks(&blocks);
-    while (nblocks.Next(key, val))
-    {
-        const Int_t runstart = (Int_t)key;
-        const Int_t runstop  = (Int_t)val;
-
-        cout << endl << "Datablock from " << runstart << " to " << runstop << ":" << endl;
-
-        if (!Process(serv, datapath, sequpath, runstart, runstop, sequlist, dummy))
-            rc = kFALSE;
-
-    }
-
-    //newly build or remaining sequences are removed from sequlist while building sequences
-    //delete sequences that remained in the list
-    //this is necessary if e.g. all runs of one old sequence have been excluded in the meantime
-    TIter Next(&sequlist);
-    TObject *obj = 0;
-    while ((obj=Next()))
-    {
-        cout << " - Sequence " << obj->GetName() << " deleting... " << endl;
-        if (!DeleteSequence(serv, datapath, sequpath, atoi(obj->GetName()), dummy))
-            return 2;
-    }
-
-    return rc ? 1 : 2;
+    serv.SetIsDummy(dummy);
+    serv.SetPathRawData(datapath);
+    serv.SetPathSequences(sequpath);
+    return serv.Build(day);
 }
 
@@ -950,5 +1164,5 @@
     TEnv env("sql.rc");
 
-    MSQLServer serv(env);
+    SequenceBuild serv(env);
     if (!serv.IsConnected())
     {
@@ -957,22 +1171,17 @@
     }
 
-    //get all dates from the database
-    TString query="SELECT fDate FROM SequenceBuildStatus";
-
-    TSQLResult *res = serv.Query(query);
-    if (!res)
-        return 2;
-
-    //execute buildsequenceentries for all dates
-    TString date;
-    TSQLRow *row=0;
-    while ((row=res->Next()))
-    {
-        date=(*row)[0];
-        buildsequenceentries(date, datapath, sequpath, dummy);
-    }
-
-    delete res;
-
-    return 1;
+    serv.SetIsDummy(dummy);
+    serv.SetPathRawData(datapath);
+    serv.SetPathSequences(sequpath);
+    return serv.Build();
 }
+
+int buildsequenceentries(Bool_t dummy=kTRUE)
+{
+    return buildsequenceentries("", "", dummy);
+}
+
+int buildsequenceentries(TString day, Bool_t dummy=kTRUE)
+{
+    return buildsequenceentries(day, "", "", dummy);
+}
Index: trunk/MagicSoft/Mars/ganymed_onoff.rc
===================================================================
--- trunk/MagicSoft/Mars/ganymed_onoff.rc	(revision 7980)
+++ trunk/MagicSoft/Mars/ganymed_onoff.rc	(revision 7981)
@@ -49,4 +49,5 @@
 #MPointingDevCalc.NsbMin:      30
 #MPointingDevCalc.NsbMax:      60
+#MPointingDevCalc.MaxAbsDev:   15
 #MPointingDevCalc.Dx           -7
 #MPointingDevCalc.Dy           16
@@ -112,5 +113,4 @@
 
 # Get rid of triangular events...
-#Cut0.Condition: log10(MNewImagePar.fConc1) < (-0.467)*log10(MHillas.fSize) + 0.75
 Cut0.Condition: ({0} || {1}) && {2} && {3} && {4} && {5} && {6}
 Cut0.0: MImagePar.fNumSatPixelsHG < 1
Index: trunk/MagicSoft/Mars/ganymed_wobble.rc
===================================================================
--- trunk/MagicSoft/Mars/ganymed_wobble.rc	(revision 7980)
+++ trunk/MagicSoft/Mars/ganymed_wobble.rc	(revision 7981)
@@ -55,4 +55,10 @@
 
 # -------------------------------------------------------------------------
+# Setup the misfocussing correction
+# -------------------------------------------------------------------------
+#MSrcPosCorrect.Dx: 0
+#MSrcPosCorrect.Dy: 0
+
+# -------------------------------------------------------------------------
 # Setup fit mode and ranges
 # -------------------------------------------------------------------------
@@ -71,4 +77,9 @@
 # -------------------------------------------------------------------------
 #MJCut.NameHist: MHAlpha
+
+# Be carefull: The spectrum might be done with a different binning
+# This might change the scale factor
+#MHThetaSq.NumBinsSignal:   3
+#MHThetaSq.NumBinsTotal:   75
 
 # -------------------------------------------------------------------------
@@ -120,27 +131,27 @@
 MAlphaFitter.SignalFunction: ThetaSq
 
+# For more details on the magic cuts see its class reference
 Cut1.Condition: MFMagicCuts
 Cut1.ThetaCut: Off
+# Parametrization of Disp
 Cut1.Param0:  1.221
+Cut1.Param6:  13.425
+Cut1.Param7:  1.04343
+# Parametrization for sign of disp (m3long)
+Cut1.Param5: -0.07
+# ThetaSq-Cut
 Cut1.Param1:  0.22
+# Area-Cut
 Cut1.Param2:  0.222
 Cut1.Param3:  5.524
 Cut1.Param4:  0.0878
-Cut1.Param5: -0.07
-Cut1.Param6:  13.425
-Cut1.Param7:  1.04343
 
-# Be carefull: The spectrum might be done with a different binning
-# This might change the scale factor
-#MHThetaSq.NumBinsSignal:   3
-#MHThetaSq.NumBinsTotal:   75
+# To switch on random forest uncomment the following lines
+#Cut1.HadronnessCut: Hadronness
+#Cut1.Param8: 0.5
+#Cut1.Param9: 100
 
-# -------------------------------------------------------------------------
-# Setup cuts in false source plot
-# -------------------------------------------------------------------------
-#MHFalseSource.DistMin: 0.55
-#MHFalseSource.DistMax: 0.55
-#MHFalseSource.DWMin:   0.55
-#MHFalseSource.DWMax:   0.55
+# To use both, hadronness and area cut do
+#Cut1.HadronnessCut: All
 
 # -------------------------------------------------------------------------
