Index: trunk/MagicSoft/Mars/mpointing/MPointingDevCalc.cc
===================================================================
--- trunk/MagicSoft/Mars/mpointing/MPointingDevCalc.cc	(revision 8727)
+++ trunk/MagicSoft/Mars/mpointing/MPointingDevCalc.cc	(revision 8728)
@@ -18,5 +18,5 @@
 !   Author(s): Thomas Bretz, 07/2005 <mailto:tbretz@astro.uni-wuerzburg.de>
 !
-!   Copyright: MAGIC Software Development, 2000-2005
+!   Copyright: MAGIC Software Development, 2000-2007
 !
 !
@@ -31,13 +31,18 @@
 // There are some quality parameters to steer which are the valid
 // starguider data points:
+//
 //  * MPointingDevCalc.NumMinStars: 8
 //    Minimum number of identified stars required to accep the data
+//
 //  * MPointingDevCalc.NsbLevel:    3.0
-//    Minimum deviation (in rms) from the the mean allowed for the measured
-//    NSB (noise in the ccd camera)
+//    Minimum deviation (in rms) from the the mean allowed for the
+//    measured NSB (noise in the ccd camera)
+//
 //  * MPointingDevCalc.NsbMin:      30
 //    - minimum NSB to be used in mean/rms calculation
+//
 //  * MPointingDevCalc.NsbMax:      60
 //    - maximum NSB to be used in mean/rms calculation
+//
 //  * MPointingDevCalc.MaxAbsDev:   15
 //    - Maximum absolute deviation which is consideres as valid (arcmin)
@@ -49,6 +54,116 @@
 // The calculation of NSB mean and rms is reset for each file (ReInit)
 //
+// If your starguider data doesn't fullfill this requirement the latest
+// value which could be correctly calculated is used instead. If the time
+// for which no valid value can be calculated exceeds one minute
+// the return value is reset to 0/0. The maximum time allowed without
+// a valid value can be setup using:
+//
+//  * MPointingDevCalc.MaxAge:   1
+//    Maximum time before the starguider is reset to 0/0 in minutes
+//
+// Note, that the starguider itself is not well calibrated. Therefore
+// it is necessary to do a starguider calibration in our software.
+//
+// There are two options:
+//
+//  * Simple starguider calibration using offsets in the camera plane
+//
+//    The starguider is calibrated by taking its values (dZd/dAz)
+//    adding them to the source position, calculating the source position
+//    in the camera plane and adding the offsets. To switch off the
+//    full starguider calibration do:
+//
+//      * MPointingDevCalc.PointingModels:
+//
+//    To set the offsets (in units of degree) use
+//
+//      * MPointingDevCalc.Dx: -0.001
+//      * MPointingDevCalc.Dy: -0.004
+//
+//   * A starguider calibration using a pointing model calculated
+//     from calibration data, so called TPoints
+//
+//     Because the pointing model can change from time to time
+//     you can give the run-number from which on a new pointing
+//     model is valid. The run itself is included, e.g.:
+//
+//      * MPointingDevCalc.PointingModels: 85240 89180
+//      * MPointingDevCalc.FilePrefix:     resources/starguider
+//
+//     mean that for all runs<85240 the simple offset correction is used.
+//     For runs >=85240 and <89180 the file resources/starguider0085240.txt
+//     and for runs >=89180 the file resources/starguider0089180.txt is
+//     used. To setup a default file for all runs before 85240 setup
+//     a low number (eg. 0 or 1)
+//
+//     In the case a pointing model is used additional offsets in
+//     the x/y-camera plane (in units of deg) can be set using the DX
+//     and DY parameters of the pointing model. The fDx and fDy data
+//     members of this class are ignored. To overwrite the starguider
+//     calibrated offset in either Az or Zd with a constant, you
+//     can use the PX/PY directive in the pointing model. (To enable
+//     the overwrite set the third column, the error, to a value
+//     greater than zero)
+//
+//
+// At the PostProcessing step a table with statistics is print if the
+// debug level is greater or equal 3 (in most applications it is switched
+// on by -v3)
+//
+//
+// Pointing Models:
+// ----------------
+//
+//  What we know so far about (maybe) important changes in cosy:
+//
+//   18.03.2006: The camera holding has been repaired and the camera got
+//               shifted a little bit.
+//
+//   16.04.2006: Around this date a roque lamp focussing hass been done
+//
+//   25.04.2006: A missalignment intrduced with the roque adjust has been
+//               corrected
+//
+//   The starguider pointing model for the time before 18.3.2006 and after
+//   April 2006 (in fact there are no TPoints until 07/2006 to check it)
+//   and for the period 07/2006 to (at least) 06/2007 are very similar.
+//
+//   The pointing model for the time between 18.3.2006 and 04/2006 is
+//   clearly different, mainly giving different Azimuth values between
+//   Zenith and roughly ~25deg, and a slight offset on both axes.
+//
+//   10.5.2006:  pos1 -= pos0 commented  (What was the mentioned fix?)
+//   29.6.2006:  repaired
+//
+//   23.3.2006:  new starguider algorithm
+//
+//   17.3.2005:  Fixed units of "nompos" in MDriveCom
+//
+//
+// New pointing models have been installed (if the pointing model
+// is different, than the previous one it might mean, that also
+// the starguider calibration is different.)
+//
+//   29. Apr. 2004    ~25800
+//    5. Aug. 2004    ~32000
+//   19. Aug. 2004    ~33530
+//    7. Jun. 2005    ~57650
+//    8. Jun. 2005
+//    9. Jun. 2005    ~57860
+//   12. Sep. 2005    ~68338
+//   24. Nov. 2005    ~75562
+//   17. Oct. 2006   ~103130
+//   17. Jun. 2007   ~248193
+//
+//
+// ToDo:
+// -----
+//
+//   * Is 0/0 the best assumption if the starguider partly fails?
+//
 //
 // Input Container:
+//   MRawRunHeader
 //   MReportStarguider
 //
@@ -74,5 +189,14 @@
 using namespace std;
 
-const TString MPointingDevCalc::fgFileName="resources/starguider.txt";
+const TString MPointingDevCalc::fgFilePrefix="resources/starguider";
+
+// --------------------------------------------------------------------------
+//
+// Destructor. Call Clear() and delete fPointingModels if any.
+//
+MPointingDevCalc::~MPointingDevCalc()
+{
+    Clear();
+}
 
 // --------------------------------------------------------------------------
@@ -90,10 +214,117 @@
 // --------------------------------------------------------------------------
 //
+// Sort the entries in fPoinitngModels
+//
+void MPointingDevCalc::SortPointingModels()
+{
+    const int n = fPointingModels.GetSize();
+
+    TArrayI idx(n);
+
+    TMath::Sort(n, fPointingModels.GetArray(), idx.GetArray(), kFALSE);
+
+    const TArrayI arr(fPointingModels);
+
+    for (int i=0; i<n; i++)
+        fPointingModels[i] = arr[idx[i]];
+}
+
+// --------------------------------------------------------------------------
+//
+// Set new pointing models
+//
+void MPointingDevCalc::SetPointingModels(const TString &models)
+{
+    fPointingModels.Set(0);
+
+    if (models.IsNull())
+        return;
+
+    TObjArray *arr = models.Tokenize(" ");
+
+    const int n = arr->GetEntries();
+    fPointingModels.Set(n);
+
+    for (int i=0; i<n; i++)
+        fPointingModels[i] = atoi((*arr)[i]->GetName());
+
+    delete arr;
+
+    SortPointingModels();
+}
+
+// --------------------------------------------------------------------------
+//
+// Return a string with the pointing models, seperated by a space.
+//
+TString MPointingDevCalc::GetPointingModels() const
+{
+    TString rc;
+    for (int i=0; i<fPointingModels.GetSize(); i++)
+        rc += Form ("%d ", fPointingModels[i]);
+
+    return rc;
+}
+
+// --------------------------------------------------------------------------
+//
+// Add a number to the pointing models
+//
+void MPointingDevCalc::AddPointingModel(UInt_t runnum)
+{
+    const int n = fPointingModels.GetSize();
+    for (int i=0; i<n; i++)
+        if ((UInt_t)fPointingModels[i]==runnum)
+        {
+            *fLog << warn << "WARNING - Pointing model " << runnum << " already in list... ignored." << endl;
+            return;
+        }
+
+    fPointingModels.Set(n+1);
+    fPointingModels[n] = runnum;
+
+    SortPointingModels();
+}
+
+// --------------------------------------------------------------------------
+//
+// Find the highest number in the array which is lower or equal num.
+//
+UInt_t MPointingDevCalc::FindPointingModel(UInt_t num)
+{
+    const int n = fPointingModels.GetSize();
+    if (n==0)
+        return (UInt_t)-1;
+
+    // Loop over all pointing models
+    for (int i=0; i<n; i++)
+    {
+        // The number stored in the array did not yet overtake the runnumber
+        if ((UInt_t)fPointingModels[i]<num)
+            continue;
+
+        // The first pointing model is later than this run: use a default
+        if (i==0)
+            return (UInt_t)-1;
+
+        // The last entry in the array is the right one.
+        return fPointingModels[i-1];
+    }
+
+    // Runnumber is after last entry of pointing models. Use the last one.
+    return fPointingModels[n-1];
+}
+
+// --------------------------------------------------------------------------
+//
 // Clear the pointing model. If run-number >= 87751 read the new
-// pointing model with fFileName
+// pointing model with fFilePrefix
 //
 Bool_t MPointingDevCalc::ReadPointingModel(const MRawRunHeader &run)
 {
-    if (run.GetRunNumber()<85240)
+    const UInt_t num = FindPointingModel(run.GetRunNumber());
+
+    // No poinitng models are defined. Use simple dx/dy-calibration
+    if (num==(UInt_t)-1)
     {
         Clear();
@@ -101,14 +332,18 @@
     }
 
+    // compile the name for the starguider files
+    // The file with the number 00000000 is the default file
+    TString fname = Form("%s%08d.txt", fFilePrefix.Data(), num);
+
     if (!fPointing)
         fPointing = new MPointing;
 
-    if (fFileName==fPointing->GetName())
-    {
-        *fLog << inf << fFileName << " already loaded." << endl;
+    if (fname==fPointing->GetName())
+    {
+        *fLog << inf << fname << " already loaded." << endl;
         return kTRUE;
     }
 
-    return fPointing->Load(fFileName);
+    return fPointing->Load(fname);
 }
 
@@ -210,14 +445,7 @@
         // For calibration add MDriveReport::GetErrorZd/Az !
         fDeviation->SetDevXY(fDx, fDy); // 1arcmin ~ 5mm
-        //devzd -= 2.686/60;   
-        //devaz -= 2.840/60;
 
         return;
     }
-
-    // def?: 20.105, 773
-    // 0/0 : 20.119, 763
-    // -/- : 19.417  726
-    // +mis: 19.80,  756
 
     // Get the nominal position the star is at the sky
@@ -229,16 +457,13 @@
     // calculate as follows:
     //
-    // Position at which the starguider camera is pointing in real:
-    //       pointing position = nominal position - mis
-    ZdAz mis(devzd, devaz);
-    mis *= TMath::DegToRad();
-
-    // The pointing mode is the conversion from the real pointing
+    // The mispointing measured by the starguider:
+    //    ZdAz mis(devzd, devaz);
+    //    mis *= TMath::DegToRad();
+
+    // The pointing model is the conversion from the real pointing
     // position of the telescope into the pointing position measured
     // by the starguider.
     //
-    //  --> To get the real poiting position of the telescope we have
-    //      to convert the measured position back;
-    //
+    // To keep as close to the fitted model we use the forward correction.
 
     // Position at which the starguider camera is pointing in real:
@@ -247,5 +472,5 @@
     // The position measured as the starguider's pointing position
     ZdAz pos(nom);        // cpos = sao - dev
-    pos -= mis;
+    pos -= ZdAz(devzd, devaz)*TMath::DegToRad();
 
     // Now we convert the starguider's pointing position into the
@@ -253,10 +478,10 @@
     // the telescope pointing position into the starguider pointing
     // position)
-    ZdAz point = fPointing->CorrectBack(pos);
+    ZdAz point = fPointing->CorrectBack(pos);  //FWD!!!
 
     // MSrcPosCalc uses the following condition to calculate the
     // source position in the camera:
     //    real pointing pos = nominal pointing pos - dev
-    //
+    //      --> dev = nominal - real
     // Therefor we calculate dev as follows:
     ZdAz dev(nom);
@@ -264,13 +489,34 @@
     dev *= TMath::RadToDeg();
 
-    // Set Measured mispointing and additional offset
-    fDeviation->SetDevZdAz(dev.Zd(), dev.Az());
-    fDeviation->SetDevXY(0, 0);
+    /*
+     // We chose the other way. It is less accurate because is is the
+     // other was than the poinitng model was fittet, but it is more
+     // accurate because the nominal (i.e. real) pointing position
+     // is less accurately known than the position returned by the
+     // starguider.
+     //
+     // Calculate the deviation which would be measured by the starguider
+     // if applied to a perfectly pointing telescope.
+     ZdAz dev = fPointing->Correct(nom);
+     dev -= nom;
+
+     // Now add these offsets and the starguider measured offsets to
+     // the real pointing deviation of the telescope (note, that
+     // signs here are just conventions)
+     dev += ZdAz(devzd, devaz)*TMath::DegToRad(); // --> nom-mis
+     dev *= TMath::RadToDeg();
+     */
+
+    // Check if the starguider pointing model requests overwriting
+    // of the values with constants (e.g. 0)
+    devaz = fPointing->IsPxValid() ? fPointing->GetPx() : dev.Az();
+    devzd = fPointing->IsPyValid() ? fPointing->GetPy() : dev.Zd();
+
+    fDeviation->SetDevZdAz(devzd, devaz);
+    fDeviation->SetDevXY(fPointing->GetDxy());
 }
 
 Int_t MPointingDevCalc::ProcessStarguiderReport()
 {
-    /************* CHECK STATUS!!! ******************/
-
     Double_t devzd = fReport->GetDevZd(); // [arcmin]
     Double_t devaz = fReport->GetDevAz(); // [arcmin]
@@ -393,4 +639,8 @@
 // MPointingDevCalc.MaxAbsDev:   15
 // MPointingDevCalc.MaxAge:      1.0
+// MPointingDevCalc.Dx:         -0.001
+// MPointingDevCalc.Dy:         -0.004
+//
+// For a detailed description see the class reference.
 //
 Int_t MPointingDevCalc::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
@@ -437,4 +687,14 @@
         rc = kTRUE;
     }
+    if (IsEnvDefined(env, prefix, "FilePrefix", print))
+    {
+        fFilePrefix = GetEnvValue(env, prefix, "FilePrefix", fFilePrefix);
+        rc = kTRUE;
+    }
+    if (IsEnvDefined(env, prefix, "PointingModels", print))
+    {
+        SetPointingModels(GetEnvValue(env, prefix, "PointingModels", GetPointingModels()));
+        rc = kTRUE;
+    }
 
     return rc;
Index: trunk/MagicSoft/Mars/mpointing/MPointingDevCalc.h
===================================================================
--- trunk/MagicSoft/Mars/mpointing/MPointingDevCalc.h	(revision 8727)
+++ trunk/MagicSoft/Mars/mpointing/MPointingDevCalc.h	(revision 8728)
@@ -18,5 +18,5 @@
 {
 private:
-    static const TString fgFileName; //! default file name of pointing model
+    static const TString fgFilePrefix; //! default file name of pointing model
 
     MReportStarguider *fReport;    //! MReportStarguider to get mispointing
@@ -33,15 +33,16 @@
     Double_t fLastMjd;             //! Time of last processed report
 
-    TString fFileName;             // File name of pointing model
+    TString fFilePrefix;           // File name of pointing model
+    TArrayI fPointingModels;       // List with pointing models
 
-    UInt_t  fNumMinStars;          // Minimum number of identified stars
+    UInt_t  fNumMinStars;          // [num] Minimum number of identified stars
     Float_t fNsbLevel;             // Minimum deviation from mean in sigma
-    Float_t fNsbMin;               // Minimum NSB to calc mean and rms
-    Float_t fNsbMax;               // Maximum NSB to calc mean and rms
+    Float_t fNsbMin;               // [au] Minimum NSB to calc mean and rms
+    Float_t fNsbMax;               // [au] Maximum NSB to calc mean and rms
     Float_t fMaxAbsDev;            // [arcmin] Maximum considered absolute deviation
     Float_t fMaxAge;               // [min] Maximum age of reports to be used without an update
 
-    Float_t fDx;                   // Starguider calibration dx
-    Float_t fDy;                   // Starguider calibration dy
+    Float_t fDx;                   // [deg] Starguider calibration dx
+    Float_t fDy;                   // [deg] Starguider calibration dy
 
     // MPointingDevCalc
@@ -49,4 +50,6 @@
 
     Bool_t ReadPointingModel(const MRawRunHeader &run);
+    UInt_t FindPointingModel(UInt_t num);
+    void   SortPointingModels();
 
     Int_t ProcessStarguiderReport();
@@ -64,20 +67,19 @@
 public:
     MPointingDevCalc() : fReport(0), fDeviation(0), fPointing(0),
-        fSkip(7), fFileName(fgFileName), fNumMinStars(8),
+        fSkip(7), fFilePrefix(fgFilePrefix), fNumMinStars(8),
         fNsbLevel(3), fNsbMin(30), fNsbMax(60), fMaxAbsDev(15),
-        fMaxAge(1), fDx(-7), fDy(16)
+        fMaxAge(1), fDx(-0.001), fDy(-0.004)
     {
         fName  = "MPointingDevCalc";
-        fTitle = "Task calculating the pointing deviation";
+        fTitle = "Task calculating the starguider correction";
 
         AddToBranchList("MReportStarguider.*");
     }
-    ~MPointingDevCalc()
-    {
-        Clear();
-    }
+    ~MPointingDevCalc();
 
+    // Tobject
     void Clear(Option_t *o="");
 
+    // Setter
     void SetNumMinStars(UInt_t n)  { fNumMinStars=n; }
     void SetNsbLevel(Float_t lvl)  { fNsbLevel=lvl;  }
@@ -89,5 +91,12 @@
     void SetMaxAge(Float_t age)    { fMaxAge=age; }
 
-    ClassDef(MPointingDevCalc, 0) //Task calculating the pointing deviation
+    void SetFilePrefix(const char *n) { fFilePrefix=n; }
+
+    // Handle pointing models
+    void    SetPointingModels(const TString &models);
+    void    AddPointingModel(UInt_t runnum);
+    TString GetPointingModels() const;
+
+    ClassDef(MPointingDevCalc, 0) //Task calculating the starguider correction
 };
 
