Index: trunk/MagicSoft/Mars/Changelog
===================================================================
--- trunk/MagicSoft/Mars/Changelog	(revision 8182)
+++ trunk/MagicSoft/Mars/Changelog	(revision 8185)
@@ -18,4 +18,19 @@
 
                                                  -*-*- END OF LINE -*-*-
+
+ 2006/11/01 Thomas Bretz
+
+   * datacenter/macros/plotdb.C, datacenter/macros/plotoptical.C:
+     - a lot of changes starting to unify the different plot macros
+     - use the new function to get the joins automatically
+     - further improved grouping
+
+   * msql/MSQLServer.[h,cc]:
+     - implemented a new function returning the primary key of a table
+     - added a new function to return the joins automatically
+       necessary to do a query
+     - changed the call to GetTables and GetColumns
+
+
 
  2006/10/31 Daniela Dorner
Index: trunk/MagicSoft/Mars/datacenter/macros/plotdb.C
===================================================================
--- trunk/MagicSoft/Mars/datacenter/macros/plotdb.C	(revision 8182)
+++ trunk/MagicSoft/Mars/datacenter/macros/plotdb.C	(revision 8185)
@@ -1,4 +1,4 @@
 /* ======================================================================== *\
-! $Name: not supported by cvs2svn $:$Id: plotdb.C,v 1.29 2006-10-27 13:36:18 tbretz Exp $
+! $Name: not supported by cvs2svn $:$Id: plotdb.C,v 1.30 2006-11-01 08:29:45 tbretz Exp $
 ! --------------------------------------------------------------------------
 !
@@ -70,4 +70,5 @@
 #include <TStyle.h>
 #include <TCanvas.h>
+#include <TPRegexp.h>
 #include <TSQLRow.h>
 #include <TSQLResult.h>
@@ -77,5 +78,5 @@
 #include "MAstro.h"
 #include "MDataSet.h"
-#include "MSQLServer.h"
+#include "MSQLMagic.h"
 #include "MStatusDisplay.h"
 
@@ -86,5 +87,7 @@
     {
         kNone,
-        kGroupByDay,
+        kGroupByPrimary,
+        kGroupByHour,
+        kGroupByNight,
         kGroupByWeek,
         kGroupByMonth,
@@ -92,7 +95,10 @@
     };
 private:
-    MSQLServer &fServer;
+    MSQLMagic &fServer;
 
     MDataSet *fDataSet;
+
+    TString   fPrimary;
+    TString   fSecondary;
 
     TString   fRequestFrom;
@@ -146,7 +152,7 @@
             const char *zd   = (*row)[1];
             const char *val  = (*row)[2];
-            const char *snum = (*row)[3];
+            const char *snum = res.GetFieldCount()>3 ? (*row)[3] : 0;
             const char *verr = res.GetFieldCount()>4 ? (*row)[5] : 0;
-            if (!date || !val || !zd || !snum)
+            if (!date || !val || !zd)
                 continue;
 
@@ -162,5 +168,5 @@
             last = TMath::Nint(TMath::Ceil(t.GetMjd()));
 
-            UInt_t seq = atoi(snum);
+            UInt_t seq = snum ? atoi(snum) : 0;
     
             Float_t value = atof(val);
@@ -207,4 +213,9 @@
 
         cerr << setprecision(4) << setw(10) << title << ":   ";
+        if (gt.GetN()==0)
+        {
+            cerr << "     <empty>" << endl;
+            return;
+        }
         cerr << setw(8) << gt.GetMean(2) << "+-" << setw(8) << gt.GetRMS(2) << "   ";
         if (gt0.GetN()>0 || gt1.GetN()>0)
@@ -314,5 +325,5 @@
 
 public:
-    MPlot(MSQLServer &server) : fServer(server), fDataSet(NULL),
+    MPlot(MSQLMagic &server) : fServer(server), fDataSet(NULL),
         fRequestPeriod(-1), fPlotMin(0), fPlotMax(-1), fHistMin(0), fHistMax(-1), fGroupBy(kNone)
     {
@@ -337,12 +348,14 @@
     void SetRequestRange(const char *from="", const char *to="") { fRequestFrom = from; fRequestTo = to; }
     void SetRequestPeriod(Int_t n=-1) { fRequestPeriod = n; }
+    void SetCondition(const char *cond="") { fCondition = cond; }
     void SetDescription(const char *d, const char *t=0) { fDescription = d; fNameTab = t; }
-    void SetCondition(const char *cond="") { fCondition = cond; }
     void SetGroupBy(GroupBy_t b=kGroupByWeek) { fGroupBy=b; }
+    void SetPrimary(const char *ts) { fPrimary=ts; }
+    void SetSecondary(const char *ts) { fSecondary=ts; }
 
     Bool_t Plot(const char *value, Float_t min=0, Float_t max=-1, Float_t resolution=0)
     {
-        TString named  = "Sequences.fRunStart";
-        TString named2 = "(Sequences.fZenithDistanceMin+Sequences.fZenithDistanceMax)/2";
+        TString named  = fPrimary;
+        TString named2 = fSecondary;
         TString namev  = value;
         TString join   = "fSequenceFirst";
@@ -354,55 +367,89 @@
         TString valued = named(named.First('.')+1, named.Length());
 
-        TString query;
+        TString query="SELECT ";
+        query += valued;
         if (fGroupBy==kNone)
-            query = Form("select %s, %s, %s, Sequences.fSequenceFirst ", valued.Data(), named2.Data(), valuev.Data());
+        {
+            query += ", ";
+            query += fSecondary;
+            query += ", ";
+            query += value;
+            query += ", ";
+            query += " Sequences.fSequenceFirst ";
+        }
         else
-            query = Form("select %s, AVG(%s), AVG(%s), Sequences.fSequenceFirst, STD(%s), STD(%s) ", valued.Data(), named2.Data(), valuev.Data(), named2.Data(), valuev.Data());
+        {
+            query += ", AVG(";
+            query += fSecondary;
+            query += "), AVG(";
+            query += value;
+            query += "), Sequences.fSequenceFirst, STD(";
+            query += fSecondary;
+            query += "), STD(";
+            query += value;
+            query += ") ";
+        }
 
         switch (fGroupBy)
         {
         case kNone:
+        case kGroupByPrimary:
             break;
-        case kGroupByDay:
-            query += Form(", date_format(adddate(%s,Interval 12 hour), '%%Y-%%m-%%d') as %s ", named.Data(), valued.Data());
+        case kGroupByHour:
+            query += Form(", DATE_FORMAT(%s, '%%Y-%%m-%%d %%H') AS %s ", named.Data(), valued.Data());
+            break;
+        case kGroupByNight:
+            query += Form(", DATE_FORMAT(ADDDATE(%s,Interval 12 hour), '%%Y-%%m-%%d') AS %s ", named.Data(), valued.Data());
             break;
         case kGroupByWeek:
-            query += Form(", date_format(adddate(%s,Interval 12 hour), '%%x%%v') as %s ", named.Data(), valued.Data());
+            query += Form(", DATE_FORMAT(ADDDATE(%s,Interval 12 hour), '%%x%%v') AS %s ", named.Data(), valued.Data());
             break;
         case kGroupByMonth:
-            query += Form(", date_format(adddate(%s,Interval 12 hour), '%%Y-%%m') as %s ", named.Data(), valued.Data());
+            query += Form(", DATE_FORMAT(ADDDATE(%s,Interval 12 hour), '%%Y-%%m') AS %s ", named.Data(), valued.Data());
             break;
         case kGroupByYear:
-            query += Form(", date_format(adddate(%s,Interval 12 hour), '%%Y') as %s ", named.Data(), valued.Data());
+            query += Form(", DATE_FORMAT(ADDDATE(%s,Interval 12 hour), '%%Y') AS %s ", named.Data(), valued.Data());
             break;
         }
 
-        query += Form("from %s left join %s ", tabled.Data(), tablev.Data());
-        query += Form("on %s.%s=%s.%s ", tabled.Data(), join.Data(), tablev.Data(), join.Data());
+        query += Form("FROM %s ", tabled.Data());
 
         const Bool_t interval = !fRequestFrom.IsNull() && !fRequestTo.IsNull();
 
+        TString where(fCondition);
         if (!fDataSet && !interval && tablev=="Star")
         {
-            if (!query.Contains("Star.fSequenceFirst"))
-                query += "left join Star on Sequences.fSequenceFirst=Star.fSequenceFirst ";
-            // This is from a plot PSF/MuonNumber
-            query += "where Star.fMuonNumber>300 ";
+            if (!where.IsNull())
+                where += " AND ";
+            where += "Star.fMuonNumber>300 ";
         }
 
         if (interval)
         {
-            query += query.Contains(" where ") ? "and " : "where ";
-            query += Form("fRunStart between '%s' and '%s' ",
-                          fRequestFrom.Data(), fRequestTo.Data());
+            if (!where.IsNull())
+                where += " AND ";
+            where += Form("%s BETWEEN '%s' AND '%s' ",
+                          fPrimary.Data(), fRequestFrom.Data(), fRequestTo.Data());
+        }
+
+        // ------------------------------
+
+        query += fServer.GetJoins(tabled, query+" "+where);
+
+        if (!where.IsNull())
+        {
+            query += "WHERE ";
+            query += where;
         }
 
         if (fGroupBy!=kNone)
         {
-            query += Form(" GROUP BY %s ", valued.Data());
+            query += Form("GROUP BY %s ", valued.Data());
             //query += Form(" HAVING COUNT(%s)=(COUNT(*)+1)/2 ", valuev.Data());
         }
-
-        query += "order by fRunStart";
+        query += Form("ORDER BY %s ", fPrimary.Data());
+
+
+        // ------------------------------
 
         TSQLResult *res = fServer.Query(query);
@@ -427,4 +474,7 @@
 {
     //plot.SetGroupBy(MPlot::kGroupByWeek);
+
+    plot.SetPrimary("Sequences.fRunStart");
+    plot.SetSecondary("(Sequences.fZenithDistanceMin+Sequences.fZenithDistanceMax)/2");
 
     //inner camera
@@ -457,4 +507,7 @@
     plot.SetDescription("Hi-/Lo-Gain ratio;", "HiLoRatio");
     plot.Plot("Calibration.fHiLoGainRatioMed", 10, 12.5, 0.05);
+
+    //plot.SetDescription("Pulse Variance;", "PulVar");
+    //plot.Plot("Calibration.fPulsePosVar", 0, 0.03, 0.001);
 
     //from star*.root
@@ -522,5 +575,5 @@
     TEnv env("sql.rc");
 
-    MSQLServer serv(env);
+    MSQLMagic serv(env);
     if (!serv.IsConnected())
     {
@@ -554,5 +607,5 @@
     TEnv env("sql.rc");
 
-    MSQLServer serv(env);
+    MSQLMagic serv(env);
     if (!serv.IsConnected())
     {
@@ -586,5 +639,5 @@
     TEnv env("sql.rc");
 
-    MSQLServer serv(env);
+    MSQLMagic serv(env);
     if (!serv.IsConnected())
     {
Index: trunk/MagicSoft/Mars/datacenter/macros/plotoptical.C
===================================================================
--- trunk/MagicSoft/Mars/datacenter/macros/plotoptical.C	(revision 8182)
+++ trunk/MagicSoft/Mars/datacenter/macros/plotoptical.C	(revision 8185)
@@ -1,4 +1,4 @@
 /* ======================================================================== *\
-! $Name: not supported by cvs2svn $:$Id: plotoptical.C,v 1.2 2006-10-20 18:26:00 tbretz Exp $
+! $Name: not supported by cvs2svn $:$Id: plotoptical.C,v 1.3 2006-11-01 08:29:45 tbretz Exp $
 ! --------------------------------------------------------------------------
 !
@@ -69,8 +69,9 @@
 #include <TFrame.h>
 #include <TStyle.h>
-#include <TGraph.h>
 #include <TCanvas.h>
+#include <TPRegexp.h>
 #include <TSQLRow.h>
 #include <TSQLResult.h>
+#include <TGraphErrors.h>
 
 #include "MTime.h"
@@ -82,4 +83,15 @@
 class MPlot : public MParContainer
 {
+public:
+    enum GroupBy_t
+    {
+        kNone,
+        kGroupByPrimary,
+        kGroupByHour,
+        kGroupByNight,
+        kGroupByWeek,
+        kGroupByMonth,
+        kGroupByYear
+    };
 private:
     MSQLMagic &fServer;
@@ -87,19 +99,22 @@
     MDataSet *fDataSet;
 
-    TString fRequestFrom;
-    TString fRequestTo;
-    Int_t   fRequestPeriod;
-
-    Float_t fPlotMin;
-    Float_t fPlotMax;
-
-    Float_t fHistMin;
-    Float_t fHistMax;
-
-    TString fDescription;
-    TString fNameTab;
-
-    TString fCondition;
-    Bool_t  fGroupBy;
+    TString   fPrimary;
+    TString   fSecondary;
+
+    TString   fRequestFrom;
+    TString   fRequestTo;
+    Int_t     fRequestPeriod;
+
+    Float_t   fPlotMin;
+    Float_t   fPlotMax;
+
+    Float_t   fHistMin;
+    Float_t   fHistMax;
+
+    TString   fDescription;
+    TString   fNameTab;
+
+    TString   fCondition;
+    GroupBy_t fGroupBy;
 
     void PlotTable(TSQLResult &res, TString name, Float_t fmin, Float_t fmax, Float_t resolution)
@@ -109,5 +124,5 @@
         TSQLRow *row;
 
-        TGraph gt;
+        TGraph &gt = res.GetFieldCount()>4 ? *new TGraphErrors : *new TGraph;
         gt.SetNameTitle(name, Form("%s vs Time", name.Data()));
         gt.SetMarkerStyle(kFullDotMedium);
@@ -138,4 +153,5 @@
             const char *val  = (*row)[2];
             const char *snum = res.GetFieldCount()>3 ? (*row)[3] : 0;
+            const char *verr = res.GetFieldCount()>4 ? (*row)[5] : 0;
             if (!date || !val || !zd)
                 continue;
@@ -174,20 +190,8 @@
             gt.SetPoint(gt.GetN(), t.GetAxisTime(), value);
             gz.SetPoint(gz.GetN(), zenith, value);
-        }
-
-        TString title = fNameTab.IsNull() ? name(name.First('.')+2, name.Length()) : fNameTab;
-        cerr << setprecision(4) << setw(10) << title << ":   ";
-        if (gt.GetN()==0)
-        {
-            cerr << "     <empty>" << endl;
-            return;
-        }
-        cerr << setw(8) << gt.GetMean(2) << "+-" << setw(8) << gt.GetRMS(2) << "   ";
-        if (gt0.GetN()>0 || gt1.GetN()>0)
-        {
-            cerr << setw(8) << gt1.GetMean(2) << "+-" << setw(8) << gt1.GetRMS(2) << "   ";
-            cerr << setw(8) << gt0.GetMean(2) << "+-" << setw(8) << gt0.GetRMS(2);
-        }
-        cerr << endl;
+
+            if (verr)
+                static_cast<TGraphErrors&>(gt).SetPointError(gt.GetN()-1, 0, atof(verr));
+        }
 
         // If this is done earlier the plots remain empty since root 5.12/00
@@ -202,8 +206,23 @@
         gROOT->SetSelectedPad(0);
 
+        TString title = fNameTab.IsNull() ? name(name.First('.')+2, name.Length()) : fNameTab;
         TCanvas &c = fDisplay ? fDisplay->AddTab(title) : *new TCanvas;
         c.SetFillColor(kWhite);
         c.SetBorderMode(0);
         c.Divide(1,2);
+
+        cerr << setprecision(4) << setw(10) << title << ":   ";
+        if (gt.GetN()==0)
+        {
+            cerr << "     <empty>" << endl;
+            return;
+        }
+        cerr << setw(8) << gt.GetMean(2) << "+-" << setw(8) << gt.GetRMS(2) << "   ";
+        if (gt0.GetN()>0 || gt1.GetN()>0)
+        {
+            cerr << setw(8) << gt1.GetMean(2) << "+-" << setw(8) << gt1.GetRMS(2) << "   ";
+            cerr << setw(8) << gt0.GetMean(2) << "+-" << setw(8) << gt0.GetRMS(2);
+        }
+        cerr << endl;
 
         TVirtualPad *pad = gPad;
@@ -308,5 +327,5 @@
 public:
     MPlot(MSQLMagic &server) : fServer(server), fDataSet(NULL),
-        fRequestPeriod(-1), fPlotMin(0), fPlotMax(-1), fHistMin(0), fHistMax(-1), fGroupBy(kFALSE)
+        fRequestPeriod(-1), fPlotMin(0), fPlotMax(-1), fHistMin(0), fHistMax(-1), fGroupBy(kNone)
     {
     }
@@ -326,16 +345,13 @@
             fDataSet = new MDataSet(filename);
     }
-    void SetPlotRange(Float_t min, Float_t max, Int_t n=5)
-    { fPlotMin = min; fPlotMax = max; }
-    void SetHistRange(Float_t min, Float_t max)
-    { fHistMin = min; fHistMax = max; }
-    void SetRequestRange(const char *from="", const char *to="")
-    { fRequestFrom = from; fRequestTo = to; }
-    void SetRequestPeriod(Int_t n=-1)
-    { fRequestPeriod = n; }
-    void SetCondition(const char *cond="")
-    { fCondition = cond; }
+    void SetPlotRange(Float_t min, Float_t max, Int_t n=5) { fPlotMin = min; fPlotMax = max; }
+    void SetHistRange(Float_t min, Float_t max) { fHistMin = min; fHistMax = max; }
+    void SetRequestRange(const char *from="", const char *to="") { fRequestFrom = from; fRequestTo = to; }
+    void SetRequestPeriod(Int_t n=-1) { fRequestPeriod = n; }
+    void SetCondition(const char *cond="") { fCondition = cond; }
     void SetDescription(const char *d, const char *t=0) { fDescription = d; fNameTab = t; }
-    void EnableGroupBy(Bool_t b=kTRUE) { fGroupBy=b; }
+    void SetGroupBy(GroupBy_t b=kGroupByWeek) { fGroupBy=b; }
+    void SetPrimary(const char *ts) { fPrimary=ts; }
+    void SetSecondary(const char *ts) { fSecondary=ts; }
 
     Int_t QueryKeyOfSource(TString src)
@@ -346,6 +362,6 @@
     Bool_t Plot(const char *value, Float_t min=0, Float_t max=-1, Float_t resolution=0)
     {
-        TString named  = "OpticalData.fTimeStamp";
-        TString named2 = fGroupBy ? "AVG(fZenithDistance)" : "fZenithDistance";
+        TString named  = fPrimary;
+        TString named2 = fSecondary;
         TString namev  = value;
         TString join   = "fSequenceFirst";
@@ -357,26 +373,78 @@
         TString valued = named(named.First('.')+1, named.Length());
 
-        TString query;
-        query  = Form("select %s, %s, %s ", valued.Data(), named2.Data(), value);
-        query += Form("from %s ",           tabled.Data());
-
-        //const Bool_t interval = !fRequestFrom.IsNull() && !fRequestTo.IsNull();
-
-        if (TString(value).Contains("Object."))
-        {
-            query += "left join Object on Object.fObjectKEY=OpticalData.fObjectKEY ";
-        }
-
-        if (!fCondition.IsNull())
-        {
-            query += "where ";
-            query += fCondition;
-            query += " ";
-        }
-
-        if (fGroupBy)
-            query += " GROUP BY fTimeStamp ";
-
-        query += "order by fTimeStamp";
+        TString query="SELECT ";
+        query += valued;
+        if (fGroupBy==kNone)
+        {
+            query += ", ";
+            query += fSecondary;
+            query += ", ";
+            query += value;
+            query += ", 0 ";
+        }
+        else
+        {
+            query += ", AVG(";
+            query += fSecondary;
+            query += "), AVG(";
+            query += value;
+            query += "), COUNT(*), STD(";
+            query += fSecondary;
+            query += "), STD(";
+            query += value;
+            query += ") ";
+        }
+
+        switch (fGroupBy)
+        {
+        case kNone:
+        case kGroupByPrimary:
+            break;
+        case kGroupByHour:
+            query += Form(", DATE_FORMAT(%s, '%%Y-%%m-%%d %%H') AS %s ", named.Data(), valued.Data());
+            break;
+        case kGroupByNight:
+            query += Form(", DATE_FORMAT(ADDDATE(%s,Interval 12 hour), '%%Y-%%m-%%d') AS %s ", named.Data(), valued.Data());
+            break;
+        case kGroupByWeek:
+            query += Form(", DATE_FORMAT(ADDDATE(%s,Interval 12 hour), '%%x%%v') AS %s ", named.Data(), valued.Data());
+            break;
+        case kGroupByMonth:
+            query += Form(", DATE_FORMAT(ADDDATE(%s,Interval 12 hour), '%%Y-%%m') AS %s ", named.Data(), valued.Data());
+            break;
+        case kGroupByYear:
+            query += Form(", DATE_FORMAT(ADDDATE(%s,Interval 12 hour), '%%Y') AS %s ", named.Data(), valued.Data());
+            break;
+        }
+
+        query += Form("FROM %s ", tabled.Data());
+
+        TString where(fCondition);
+
+        if (!where.IsNull())
+            where += " AND ";
+
+        where += fCondition;
+        where += " ";
+
+        // ------------------------------
+
+        query += fServer.GetJoins(tabled, query+" "+where);
+
+        if (!where.IsNull())
+        {
+            query += "WHERE ";
+            query += where;
+        }
+
+        if (fGroupBy!=kNone)
+        {
+            query += Form("GROUP BY %s ", valued.Data());
+            //query += Form(" HAVING COUNT(%s)=(COUNT(*)+1)/2 ", valuev.Data());
+        }
+        query += Form("ORDER BY %s ", fPrimary.Data());
+
+
+        // ------------------------------
 
         TSQLResult *res = fServer.Query(query);
@@ -396,4 +464,9 @@
 void plotall(MPlot &plot, TString source)
 {
+    plot.SetPrimary("OpticalData.fTimeStamp");
+    plot.SetSecondary("fZenithDistance");
+
+
+
     TString cond = "fStatusKEY=13";
     if (!source.IsNull())
@@ -402,5 +475,5 @@
         if (key<0)
             return;
-        cond += Form(" and fObjectKEY=%d", key);
+        cond += Form(" AND Object.fObjectKEY=%d", key);
 
     }
@@ -418,43 +491,40 @@
     plot.SetDescription("Aperture Radius;R_{A}", "ApRad");
     plot.Plot("OpticalData.fApertureRadius", 0, 10, 1);
-/*
-    plot.SetDescription("Instrumental Magnitude;M_{I}\\cdot s^{-1}", "InstMag/s");
-    plot.Plot("OpticalData.fInstrumentalMag/OpticalData.fExposure",  0, 0.2, 0.005);
-
-    plot.SetDescription("Instrumental Magnitude Error;\\sigma_{M}\\cdot s^{-1}", "MagErr/s");
-    plot.Plot("OpticalData.fInstrumentalMagErr/OpticalData.fExposure",  0, 0.01, 0.0002);
-
-    plot.SetDescription("Instrumental Magnitude;M_{I}", "InstMag");
-    plot.Plot("OpticalData.fInstrumentalMag",  0, 30, 0.5);
-
-    plot.SetDescription("Instrumental Magnitude Error;\\sigma_{M}", "MagErr");
-    plot.Plot("OpticalData.fInstrumentalMagErr",  0, 1, 0.01);
-  */
+
+    /*
+     plot.SetDescription("Instrumental Magnitude;M_{I}\\cdot s^{-1}", "InstMag/s");
+     plot.Plot("OpticalData.fInstrumentalMag/OpticalData.fExposure",  0, 0.2, 0.005);
+
+     plot.SetDescription("Instrumental Magnitude Error;\\sigma_{M}\\cdot s^{-1}", "MagErr/s");
+     plot.Plot("OpticalData.fInstrumentalMagErr/OpticalData.fExposure",  0, 0.01, 0.0002);
+
+     plot.SetDescription("Instrumental Magnitude;M_{I}", "InstMag");
+     plot.Plot("OpticalData.fInstrumentalMag",  0, 30, 0.5);
+
+     plot.SetDescription("Instrumental Magnitude Error;\\sigma_{M}", "MagErr");
+     plot.Plot("OpticalData.fInstrumentalMagErr",  0, 1, 0.01);
+     */
+
     plot.SetDescription("m_{1};m_{1}", "M1");
     plot.Plot("OpticalData.fInstrumentalMag+2.5*log10(OpticalData.fExposure)", 10, 35, 0.2);
 
-    cond += " and Object.fObjectName not like '%/BL' and not IsNull(Object.fMagnitude) ";
+    cond += " AND Object.fObjectName NOT LIKE '%/BL' AND NOT ISNULL(Object.fMagnitude) ";
     plot.SetCondition(cond);
 
     TString ext("3080/25.0*pow(10, (OpticalData.fInstrumentalMag+2.5*log10(OpticalData.fExposure)-Object.fMagnitude)/-2.5)");
     ext += "+0.0028*fZenithDistance-0.08";
-/*
-    plot.SetDescription("m_{1}-m_{true} (Extinction per Object);m_{1}-m_{true}", "ExtObj");
-    plot.Plot(ext, 0.5, 1.2, 0.01);
-    */
-
-    plot.EnableGroupBy();
+
+    plot.SetGroupBy(MPlot::kGroupByPrimary);
     plot.SetDescription("m_{1}-m_{true} (Extinction per Image);m_{1}-m_{true}", "ExtImg");
-    plot.Plot(Form("AVG(%s)", ext.Data()), 0.05, 1.2, 0.01);
-
-    plot.SetDescription("Error m_{1}-m_{true} (Extinction per Image);ERR m_{1}-m_{true}", "ExtImgErr");
-    plot.Plot(Form("STD(%s)", ext.Data()), 0, 0.3, 0.005);
-
+    plot.Plot(ext/*Form("AVG(%s)", ext.Data())*/, 0.05, 1.2, 0.01);
+
+    plot.SetGroupBy(MPlot::kGroupByHour);
     plot.SetDescription("m_{1}-m_{true} (Extinction per Hour);m_{1}-m_{true}", "ExtHour");
-    plot.Plot(Form("AVG(%s), date_format(fTimeStamp, '%%Y-%%m-%%d %%H') as fTimeStamp", ext.Data()),
+    plot.Plot(ext/*Form("AVG(%s), date_format(fTimeStamp, '%%Y-%%m-%%d %%H') as fTimeStamp", ext.Data())*/,
               0.5, 1.2, 0.01);
 
+    plot.SetGroupBy(MPlot::kGroupByNight);
     plot.SetDescription("m_{1}-m_{true} (Extinction per Night);m_{1}-m_{true}", "ExtNight");
-    plot.Plot(Form("AVG(%s), date_format(adddate(fTimeStamp,Interval 12 hour),'%%Y-%%m-%%d') as fTimeStamp", ext.Data()),
+    plot.Plot(ext/*Form("AVG(%s), date_format(adddate(fTimeStamp,Interval 12 hour),'%%Y-%%m-%%d') as fTimeStamp", ext.Data())*/,
               0.5, 1.2, 0.01);
 }
Index: trunk/MagicSoft/Mars/mhflux/MHFalseSource.cc
===================================================================
--- trunk/MagicSoft/Mars/mhflux/MHFalseSource.cc	(revision 8182)
+++ trunk/MagicSoft/Mars/mhflux/MHFalseSource.cc	(revision 8185)
@@ -1,4 +1,4 @@
 /* ======================================================================== *\
-! $Name: not supported by cvs2svn $:$Id: MHFalseSource.cc,v 1.20 2006-10-17 17:16:00 tbretz Exp $
+! $Name: not supported by cvs2svn $:$Id: MHFalseSource.cc,v 1.21 2006-11-01 08:29:45 tbretz Exp $
 ! --------------------------------------------------------------------------
 !
@@ -121,8 +121,10 @@
 #include <TF2.h>
 #include <TH2.h>
+#include <TLatex.h>
 #include <TGraph.h>
 #include <TStyle.h>
 #include <TCanvas.h>
 #include <TRandom.h>
+#include <TEllipse.h>
 #include <TPaveText.h>
 #include <TStopwatch.h>
@@ -640,7 +642,7 @@
 // source plot.
 //
-TObject *MHFalseSource::GetCatalog()
-{
-    const Double_t maxr = 0.98*TMath::Abs(fHist.GetBinCenter(1));
+TObject *MHFalseSource::GetCatalog() const
+{
+    const Double_t maxr = TMath::Abs(fHist.GetBinLowEdge(1))*TMath::Sqrt(2);
 
     // Create catalog...
@@ -1251,2 +1253,178 @@
     }
 }
+
+void MHFalseSource::DrawNicePlot() const
+{
+    Int_t newc = kTRUE;
+    Float_t zoom = 0.95;
+    Int_t col = kBlue+180;
+
+    if (!newc && !fDisplay)
+        return;
+
+    TH1 *h = dynamic_cast<TH1*>(FindObjectInPad("Alpha_yx_on"));
+    if (!h)
+        return;
+
+    // Open and setup canvas/pad
+    TCanvas &c = newc ? *new TCanvas("Excess", "Excess Plot", TMath::Nint(500.), TMath::Nint(500*0.77/0.89)) : fDisplay->AddTab("ThetsSq");
+
+    //c.SetPad(0.15, 0, 0.90, 1);
+
+    c.SetBorderMode(0);
+    c.SetFrameBorderMode(0);
+    c.SetFillColor(kWhite);
+
+    c.SetLeftMargin(0.11);
+    c.SetRightMargin(0.12);
+    c.SetBottomMargin(0.10);
+    c.SetTopMargin(0.01);
+
+    TH1 *h1 = (TH1*)h->Clone("");
+    h1->SetDirectory(0);
+    h1->SetTitle("");
+    h1->SetContour(99);
+    h1->SetBit(TH1::kNoStats);
+    h1->SetBit(TH1::kCanDelete);
+
+    if (h1->FindObject("stats"))
+        delete h1->FindObject("stats");
+
+    TAxis &x = *h1->GetXaxis();
+    TAxis &y = *h1->GetYaxis();
+    TAxis &z = *h1->GetZaxis();
+
+    x.SetRangeUser(-zoom, zoom);
+    y.SetRangeUser(-zoom, zoom);
+
+    x.SetTitleOffset(1.1);
+    y.SetTitleOffset(1.3);
+
+    x.SetTickLength(0.025);
+    y.SetTickLength(0.025);
+
+    x.SetAxisColor(kWhite);
+    y.SetAxisColor(kWhite);
+
+    x.CenterTitle();
+    y.CenterTitle();
+
+    x.SetTitle("Offset [#circ]");
+    y.SetTitle("Offset [#circ]");
+
+    x.SetDecimals();
+    y.SetDecimals();
+    z.SetDecimals();
+
+    MH::SetPalette("glowsym", 99);
+
+    const Float_t max = TMath::Max(h1->GetMinimum(), h1->GetMaximum());
+
+    h1->SetMinimum(-max);
+    h1->SetMaximum(max);
+
+    h1->Draw("colz");
+
+    // ------
+    // Convert pave coordinates from NDC to Pad coordinates.
+
+    gPad->Update();
+
+    Float_t x0 = 0.80;
+    Float_t y0 = 0.88;
+
+    Double_t dx  = gPad->GetX2() - gPad->GetX1();
+    Double_t dy  = gPad->GetY2() - gPad->GetY1();
+
+    // Check if pave initialisation has been done.
+    // This operation cannot take place in the Pave constructor because
+    // the Pad range may not be known at this time.
+    Float_t px = gPad->GetX1() + x0*dx;
+    Float_t py = gPad->GetY1() + y0*dy;
+    // -------
+
+    TEllipse *el = new TEllipse(px, py, 0.12, 0.12, 0, 360, 0);
+    el->SetFillStyle(4100);
+    el->SetFillColor(kBlack);
+    el->SetLineWidth(2);
+    el->SetLineColor(kWhite);
+    el->SetBit(kCanDelete);
+    el->Draw();
+
+    TString str1("el.SetX1(gPad->GetX1()+0.9*(gPad->GetX2()-gPad->GetX1()));");
+    TString str2("el.SetY1(gPad->GetY1()+0.9*(gPad->GetY2()-gPad->GetY1()));");
+
+    str1.ReplaceAll("el.", Form("((TEllipse*)%p)->", el));
+    str2.ReplaceAll("el.", Form("((TEllipse*)%p)->", el));
+
+    str1.ReplaceAll("0.9", Form("%f", x0));
+    str2.ReplaceAll("0.9", Form("%f", y0));
+
+    TLatex tex;
+    tex.SetBit(TText::kTextNDC);
+    tex.SetTextColor(kWhite);
+    tex.SetTextAlign(22);
+    tex.SetTextSize(0.04);
+    tex.SetTextAngle(0);
+    tex.DrawLatex(x0, y0, "psf");
+
+    TPad *pad = new TPad("pad", "Catalog Pad",
+                         c.GetLeftMargin(), c.GetBottomMargin(),
+                         1-c.GetRightMargin(), 1-c.GetTopMargin());
+
+    pad->SetFillStyle(4000);
+    pad->SetFillColor(kBlack);
+    pad->SetBorderMode(0);
+    pad->SetFrameBorderMode(0);
+    pad->SetBit(kCanDelete);
+    pad->Draw();
+
+    pad->Range(x.GetBinLowEdge(x.GetFirst()),
+               y.GetBinLowEdge(y.GetFirst()),
+               x.GetBinLowEdge(x.GetLast()+1),
+               y.GetBinLowEdge(y.GetLast()+1));
+
+    TString str3("pad->Range(x.GetBinLowEdge(x.GetFirst()),"
+                 "y.GetBinLowEdge(y.GetFirst()),"
+                 "x.GetBinLowEdge(x.GetLast()+1),"
+                 "y.GetBinLowEdge(y.GetLast()+1));");
+
+    str3.ReplaceAll("x.", Form("((TAxis*)%p)->", &x));
+    str3.ReplaceAll("y.", Form("((TAxis*)%p)->", &y));
+    // str3.ReplaceAll("pad", Form("((TPad*)(%p))", pad));
+
+    c.AddExec("SetPosX", str1);
+    c.AddExec("SetPosY", str2);
+    c.AddExec("Resize",  str3);
+
+    pad->cd();
+    gROOT->SetSelectedPad(0);
+
+    MAstroCatalog *cat = (MAstroCatalog*)GetCatalog();
+
+    cat->GetAttLineSky().SetLineColor(col);
+    cat->GetAttLineSky().SetLineWidth(2);
+    cat->GetAttLineSky().SetLineStyle(7);
+
+    cat->GetList()->Clear();
+    cat->SetBit(kCanDelete);
+    //    cat->AddObject(MAstro::Hms2Hor(12,17,52)*TMath::Pi()/12, TMath::DegToRad()*MAstro::Dms2Deg(30,7,0),   6, "1ES1215+303");
+    //    cat->AddObject(MAstro::Hms2Hor(12,18,27)*TMath::Pi()/12, TMath::DegToRad()*MAstro::Dms2Deg(29,48,46), 6, "Mrk766");
+
+    cat->Draw("mirror same");
+
+    /*
+     Int_t col = kBlue+180;
+
+     TLatex tex;
+     tex.SetTextColor(col);
+     tex.SetTextAlign(21);
+     tex.SetTextSize(0.04);
+     tex.DrawLatex(-0.79, -0.8, "43.0\\circ");
+     tex.DrawLatex(-0.78,  0.2, "42.0\\circ");
+
+     tex.SetTextAngle(-90);
+     tex.DrawLatex(-0.45, -0.55, "22.00h");
+     tex.DrawLatex( 0.30, -0.55, "22.07h");
+     */
+}
Index: trunk/MagicSoft/Mars/mhflux/MHFalseSource.h
===================================================================
--- trunk/MagicSoft/Mars/mhflux/MHFalseSource.h	(revision 8182)
+++ trunk/MagicSoft/Mars/mhflux/MHFalseSource.h	(revision 8185)
@@ -46,5 +46,5 @@
     Double_t fDec;
 
-    TObject *GetCatalog();
+    TObject *GetCatalog() const;
     void MakeSymmetric(TH1 *h);
 
@@ -87,4 +87,6 @@
     }
 
+    void DrawNicePlot() const; //*MENU*
+
     // MParContainer
     Int_t ReadEnv(const TEnv &env, TString prefix, Bool_t print=kFALSE);
Index: trunk/MagicSoft/Mars/msql/MSQLServer.cc
===================================================================
--- trunk/MagicSoft/Mars/msql/MSQLServer.cc	(revision 8182)
+++ trunk/MagicSoft/Mars/msql/MSQLServer.cc	(revision 8185)
@@ -1,3 +1,5 @@
 /* ======================================================================== *\
+! $Name: not supported by cvs2svn $:$Id: MSQLServer.cc,v 1.13 2006-11-01 08:29:45 tbretz Exp $
+! --------------------------------------------------------------------------
 !
 ! *
@@ -18,5 +20,5 @@
 !   Author(s): Thomas Bretz 2/2004 <mailto:tbretz@astro.uni-wuerzburg.de>
 !
-!   Copyright: MAGIC Software Development, 2000-2004
+!   Copyright: MAGIC Software Development, 2000-2006
 !
 !
@@ -47,4 +49,5 @@
 #include <TH1.h>
 #include <TEnv.h>
+#include <TPRegexp.h>
 
 #include <TSQLResult.h>
@@ -519,12 +522,12 @@
 }
 
-TSQLResult *MSQLServer::GetTables(const char *dbname, const char *wild) /*FOLD00*/
-{
-    return fType==kIsServer && fServ ? fServ->GetTables(dbname, wild) : NULL;
-}
-
-TSQLResult *MSQLServer::GetColumns(const char *dbname, const char *table, const char *wild) /*FOLD00*/
-{
-    return fType==kIsServer && fServ ? fServ->GetColumns(dbname, table, wild) : NULL;
+TSQLResult *MSQLServer::GetTables(const char *wild, const char *dbname) /*FOLD00*/
+{
+    return fType==kIsServer && fServ ? fServ->GetTables(dbname?dbname:fDataBase.Data(), wild) : NULL;
+}
+
+TSQLResult *MSQLServer::GetColumns(const char *table, const char *wild, const char *dbname) /*FOLD00*/
+{
+    return fType==kIsServer && fServ ? fServ->GetColumns(dbname?dbname:fDataBase.Data(), table, wild) : NULL;
 }
 
@@ -604,5 +607,5 @@
     }
     else
-        SetBit(kZombie);
+        fType = kIsZombie;
 
     fList.SetOwner();
@@ -749,4 +752,88 @@
 }
 
+// --------------------------------------------------------------------------
+//
+// Return the name of the (first) column with a primary key
+//
+TString MSQLServer::GetPrimaryKey(const char *table)
+{
+    TSQLResult *res = GetColumns(table);
+    if (!res)
+        return "";
+
+    TString rc;
+
+    TSQLRow *row = 0;
+    while ((row=res->Next()))
+    {
+        TString key = (*row)[3];
+        if (key!="PRI")
+            continue;
+
+        rc = (*row)[0];
+        break;
+    }
+
+    delete res;
+    return rc;
+}
+
+// --------------------------------------------------------------------------
+//
+// Searches in the text for patterns like "Table.Column". If such a pettern
+// is found the primary key of the table is requested a "LEFT JOIN"
+// with this Table is added ON the identity of the primary key of Table
+// with the given table.
+//
+TString MSQLServer::GetJoins(const char *table, const TString text)
+{
+    Int_t p=0;
+
+    TString mods;
+    TArrayI pos;
+
+    // Find all Table.Column expression. Because also floating point
+    // numbers can contain a dot the result has to be checked carefully
+    TString joins;
+    TPRegexp reg = TPRegexp("\\w+[.]\\w+");
+    while (1)
+    {
+        // Check whether expression is found
+        if (reg.Match(text, mods, p, 130, &pos)==0)
+            break;
+
+        // Get expression from text
+        const TString expr = text(pos[0], pos[1]-pos[0]);
+        p = pos[1];
+
+        if (expr.IsFloat())
+            continue;
+
+        const TString tab = expr(0, expr.First('.'));
+        const TString var = expr(expr.First('.')+1, expr.Length());
+
+        // If the table found is the primary table itself skip it.
+        if (tab==table)
+            continue;
+
+        // If this join has already be set, skip it.
+        if (joins.Contains(Form(" %s ", tab.Data())))
+            continue;
+
+        // Now get the primary key of the table to be joined
+        const TString prim = GetPrimaryKey(tab);
+        if (prim.IsNull())
+            continue;
+
+        joins += Form("LEFT JOIN %s ON %s.%s=%s.%s ", tab.Data(),
+                      table, prim.Data(), tab.Data(), prim.Data());
+    }
+
+    if (!joins.IsNull())
+        joins += " ";
+
+    return joins;
+}
+
 void MSQLServer::RecursiveRemove(TObject *obj)
 {
Index: trunk/MagicSoft/Mars/msql/MSQLServer.h
===================================================================
--- trunk/MagicSoft/Mars/msql/MSQLServer.h	(revision 8182)
+++ trunk/MagicSoft/Mars/msql/MSQLServer.h	(revision 8185)
@@ -113,6 +113,6 @@
     Int_t       SelectDataBase(const char *dbname);
     TSQLResult *GetDataBases(const char *wild = 0);
-    TSQLResult *GetTables(const char *dbname, const char *wild = 0);
-    TSQLResult *GetColumns(const char *dbname, const char *table, const char *wild = 0);
+    TSQLResult *GetTables(const char *wild = 0, const char *dbname = 0);
+    TSQLResult *GetColumns(const char *table, const char *wild = 0, const char *dbname = 0);
     Int_t       CreateDataBase(const char *dbname);
     Int_t       DropDataBase(const char *dbname);
@@ -123,4 +123,6 @@
 
     TString     GetEntry(const char *where, const char *col=0, const char *table=0) const;
+    TString     GetPrimaryKey(const char *table);
+    TString     GetJoins(const char *table, const TString text);
 
     void RecursiveRemove(TObject *obj);
