Index: trunk/MagicSoft/Cosy/gui/MGCoordinate.cc
===================================================================
--- trunk/MagicSoft/Cosy/gui/MGCoordinate.cc	(revision 1343)
+++ trunk/MagicSoft/Cosy/gui/MGCoordinate.cc	(revision 1531)
@@ -28,5 +28,5 @@
                            const Bool_t flag, const char *txt,
                            const Int_t deg, const UInt_t min, const UInt_t sec)
-: TGFrame(p, 119, flag?76:46, kSunkenFrame|kFixedSize), fDeg(deg), fMin(min), fSec(sec)
+: TGFrame(p, 119, flag?76:46, kSunkenFrame|kFixedSize), fSign('+'), fDeg(deg), fMin(min), fSec(sec)
 {
     fList = new MGList;
@@ -139,13 +139,12 @@
 Double_t MGCoordinate::GetVal() const
 {
-    const Int_t deg = fDeg<0 ? -fDeg : fDeg;
-    const Int_t sgn = fDeg<0 ? -1 : 1;
-
-    return (Double_t)sgn*(60*(60*deg+fMin)+fSec)/3600;
+    const Int_t sgn = fSign=='-' ? -1 : 1;
+
+    return (Double_t)sgn*(60*(60*fDeg+fMin)+fSec)/3600;
 }
 
 void MGCoordinate::Print()
 {
-    cout << fLabel->GetText()->GetString() << " " << fDeg << "\xb0 " << fMin << "' " << fSec << "\"" << endl;
+    cout << fLabel->GetText()->GetString() << " " << fSign << fDeg << "\xb0 " << fMin << "' " << fSec << "\"" << endl;
 }
 
@@ -154,5 +153,5 @@
     char txt[20];
 
-    sprintf(txt, "%d", val);
+    sprintf(txt, "%s%d", label == fLabelDeg && fSign=='-'?"-":"", val);
 
     label->SetText(new TGString(txt));
@@ -163,5 +162,5 @@
     char txt[20];
 
-    sprintf(txt, "%d", val);
+    sprintf(txt, "%s%d", entry == fTextEntryDeg && fSign=='-'?"-":"", val);
 
     entry->SetText(txt);
@@ -180,6 +179,6 @@
     slaDr2af(0, d*D2PI/360.0, &sign, dms);
 
-
-    fDeg = sign=='-'?-dms[0]:dms[0];
+    fSign = sign;
+    fDeg = dms[0];
     fMin = dms[1];
     fSec = dms[2];
@@ -197,7 +196,12 @@
 Bool_t MGCoordinate::Set(TGLabel *label, Int_t &val, TGTextEntry *entry)
 {
-    Int_t newval = atoi(entry->GetText());
+    TString text = entry->GetText();
+
+    Int_t newval = abs(atoi(text));
 
     Bool_t ok = (entry == fTextEntryDeg || (newval>=0 && newval<60));
+
+    if (entry==fTextEntryDeg)
+        fSign = text.Contains("-") ? '-' : '+';
 
     if (ok)
Index: trunk/MagicSoft/Cosy/gui/MGCoordinate.h
===================================================================
--- trunk/MagicSoft/Cosy/gui/MGCoordinate.h	(revision 1343)
+++ trunk/MagicSoft/Cosy/gui/MGCoordinate.h	(revision 1531)
@@ -25,4 +25,6 @@
 class MGCoordinate : public TGFrame
 {
+    Char_t fSign;
+
     Int_t fDeg;
     Int_t fMin;
Index: trunk/MagicSoft/Cosy/gui/MGCosy.cc
===================================================================
--- trunk/MagicSoft/Cosy/gui/MGCosy.cc	(revision 1343)
+++ trunk/MagicSoft/Cosy/gui/MGCosy.cc	(revision 1531)
@@ -15,4 +15,5 @@
 #include <TGListBox.h>     // TGListBox
 #include <TG3DLine.h>      // TGHorizontal3DLine (TGSplitter)
+#include <TGTextEntry.h>   // TGTextEntry
 #include <TGFrame.h>       // TGGroupFrame
 #include <TApplication.h>  // gApplication
@@ -34,13 +35,19 @@
 #define IDM_TEXT 2
 
-#define kPB_POSITION  0x1001
-#define kPB_TRACK     0x1002
-#define kPB_STOP      0x1003
-#define kPB_CALCALTAZ 0x1004
-#define kPB_POLARIS   0x1005
-#define kPB_START     0x1006
-
-#define kEF_A         0x1010
-#define kEF_B         0x1011
+enum
+{
+    kPB_POSITION,
+    kPB_TRACK,
+    kPB_STOP,
+    kPB_CALCALTAZ,
+    kPB_TPOINT,
+    kPB_START,
+    kPB_RAp,
+    kPB_RAm,
+    kPB_DECp,
+    kPB_DECm,
+    kPB_LoadBending,
+    kPB_CALIBSE
+};
 
 void MGCosy::CreateMenu()
@@ -81,16 +88,30 @@
     TGLabel *l;
 
-    l = new TGLabel(f, "SE-Az:");
+    l = new TGLabel(f, "UTC:");
     l->Move(x-60, y);
     fList->Add(l);
 
-    l = new TGLabel(f, "SE-Zd1:");
+    l = new TGLabel(f, "Mjd:");
     l->Move(x-60, y+20);
     fList->Add(l);
 
+    fUtc = new TGLabel(f, "0000/00/00 00:00:00.0");
+    fMjd = new TGLabel(f, "00000.000000");
+    fUtc->Move(x-25, y);
+    fMjd->Move(x-25, y+20);
+    fList->Add(fUtc);
+    fList->Add(fMjd);
+
+    l = new TGLabel(f, "SE-Az:");
+    l->Move(x-60, y+60);
+    fList->Add(l);
+
+    l = new TGLabel(f, "SE-Zd1:");
+    l->Move(x-60, y+80);
+    fList->Add(l);
+
     l = new TGLabel(f, "SE-Zd2:");
-    l->Move(x-60, y+40);
+    l->Move(x-60, y+100);
     fList->Add(l);
-
 
     fLabel1 = new TGLabel*[3];
@@ -101,7 +122,7 @@
     fLabel1[1]->SetTextJustify(kTextRight);
     fLabel1[2]->SetTextJustify(kTextRight);
-    fLabel1[0]->Move(x,    y);
-    fLabel1[1]->Move(x+43, y);
-    fLabel1[2]->Move(x+70, y);
+    fLabel1[0]->Move(x,    y+60);
+    fLabel1[1]->Move(x+43, y+60);
+    fLabel1[2]->Move(x+70, y+60);
     fList->Add(fLabel1[0]);
     fList->Add(fLabel1[1]);
@@ -118,7 +139,7 @@
     fLabel2[1]->SetTextJustify(kTextRight);
     fLabel2[2]->SetTextJustify(kTextRight);
-    fLabel2[0]->Move(x,    y+20);
-    fLabel2[1]->Move(x+43, y+20);
-    fLabel2[2]->Move(x+70, y+20);
+    fLabel2[0]->Move(x,    y+80);
+    fLabel2[1]->Move(x+43, y+80);
+    fLabel2[2]->Move(x+70, y+80);
     fList->Add(fLabel2[0]);
     fList->Add(fLabel2[1]);
@@ -135,7 +156,7 @@
     fLabel3[1]->SetTextJustify(kTextRight);
     fLabel3[2]->SetTextJustify(kTextRight);
-    fLabel3[0]->Move(x,    y+40);
-    fLabel3[1]->Move(x+43, y+40);
-    fLabel3[2]->Move(x+70, y+40);
+    fLabel3[0]->Move(x,    y+100);
+    fLabel3[1]->Move(x+43, y+100);
+    fLabel3[2]->Move(x+70, y+100);
     fList->Add(fLabel3[0]);
     fList->Add(fLabel3[1]);
@@ -146,9 +167,9 @@
 
     l = new TGLabel(f, "Offset-Zd:");
-    l->Move(x-60, y+80);
+    l->Move(x-60, y+140);
     fList->Add(l);
 
     l = new TGLabel(f, "Offset-Az:");
-    l->Move(x-60, y+100);
+    l->Move(x-60, y+160);
     fList->Add(l);
 
@@ -157,6 +178,6 @@
     fOffsetZd->SetTextJustify(kTextRight);
     fOffsetAz->SetTextJustify(kTextRight);
-    fOffsetZd->Move(x, y+80);
-    fOffsetAz->Move(x, y+100);
+    fOffsetZd->Move(x, y+140);
+    fOffsetAz->Move(x, y+160);
     fList->Add(fOffsetZd);
     fList->Add(fOffsetAz);
@@ -204,7 +225,8 @@
 void MGCosy::CreateTabs(TGTab *fTab)
 {
-    TGCompositeFrame *tf1 = fTab->AddTab("Position Zd/Az");
-    TGCompositeFrame *tf2 = fTab->AddTab("Track Ra/Dec");
-    TGCompositeFrame *tf3 = fTab->AddTab("Demo Mode");
+    TGCompositeFrame *tf1 = fTab->AddTab("Position");
+    TGCompositeFrame *tf2 = fTab->AddTab("Track");
+    TGCompositeFrame *tf4 = fTab->AddTab("Calibration");
+    TGCompositeFrame *tf3 = fTab->AddTab("Demo");
 
     fCZdAz = new MGCoordinates(tf1, kETypeZdAz);
@@ -216,4 +238,7 @@
     fList->Add(fCRaDec);
 
+    fCCalib = new MGCoordinates(tf4, kETypeRaDec);
+    fCCalib->Move(27, 105);
+    fList->Add(fCCalib);
 
     const int x=15;
@@ -239,5 +264,5 @@
     l1 = new TGLabel(tf2, "Track a position given in sky coordinates.");
     l2 = new TGLabel(tf2, "Right Ascension and declination must be given");
-    l3 = new TGLabel(tf2, "in the FK5, J2000 coordinate system");
+    l3 = new TGLabel(tf2, "in the FK5, J2000 coordinate system.");
     l1->Move(x, y);
     l2->Move(x, y+h);
@@ -246,4 +271,17 @@
     fList->Add(l2);
     fList->Add(l3);
+
+    l1 = new TGLabel(tf4, "Start the calibration using the Start button.");
+    l2 = new TGLabel(tf4, "Write a coordinate pair to a TPoint file using");
+    l3 = new TGLabel(tf4, "the TPoint button. To set the Shaftencoder offset");
+    l4 = new TGLabel(tf4, "use the Calib SE button.");
+    l1->Move(x, y);
+    l2->Move(x, y+h);
+    l3->Move(x, y+2*h);
+    l4->Move(x, y+3*h);
+    fList->Add(l1);
+    fList->Add(l2);
+    fList->Add(l3);
+    fList->Add(l4);
 
     //
@@ -261,14 +299,55 @@
     TGTextButton *but;
 
-    but= new TGTextButton(this, "Calc Zd/Az",  kPB_CALCALTAZ);
+    but= new TGTextButton(tf2, "Ra -",  kPB_RAm);
+    but->Resize(50, 25);
+    but->Move(25, 210);
+    but->SetToolTipText("Right ascension -= 1'");
+    but->Associate(this);
+    fList->Add(but);
+    but= new TGTextButton(tf2, "RA +",  kPB_RAp);
+    but->Resize(50, 25);
+    but->Move(90, 210);
+    but->SetToolTipText("Right ascension += 1'");
+    but->Associate(this);
+    fList->Add(but);
+    but= new TGTextButton(tf2, "DEC +",  kPB_DECp);
+    but->Resize(50, 25);
+    but->Move(55, 185);
+    but->SetToolTipText("Declination += 1'");
+    but->Associate(this);
+    fList->Add(but);
+    but= new TGTextButton(tf2, "DEC -",  kPB_DECm);
+    but->Resize(50, 25);
+    but->Move(55, 235);
+    but->SetToolTipText("Declination -= 1'");
+    but->Associate(this);
+    fList->Add(but);
+
+    but= new TGTextButton(tf2, "Calc Zd/Az",  kPB_CALCALTAZ);
     but->Resize(80, 25);
-    but->Move(37, 257);
+    but->Move(165, 197);
     but->SetToolTipText("Calculate Zd/Az corresponding to Ra/Dec.");
+    but->Associate(this);
     fList->Add(but);
 
-    but = new TGTextButton(this, "Set Polaris", kPB_POLARIS);
+    but = new TGTextButton(tf4, "TPoint", kPB_TPOINT);
     but->Resize(80, 25);
-    but->Move(37, 288);
-    but->SetToolTipText("Set the actual position as the position of Polaris.");
+    but->Move(25, 197);
+    but->SetToolTipText("Trigger writing a tpoint coordinate pair.");
+    but->Associate(this);
+    fList->Add(but);
+
+    but = new TGTextButton(tf4, "Calib SE", kPB_CALIBSE);
+    but->Resize(80, 25);
+    but->Move(160, 197);
+    but->SetToolTipText("Set SE to given coordinates.");
+    but->Associate(this);
+    fList->Add(but);
+
+    but = new TGTextButton(tf4, "Load", kPB_LoadBending);
+    but->Resize(80, 25);
+    but->Move(25, 227);
+    but->SetToolTipText("Load bending corrections from file 'bending.txt'");
+    but->Associate(this);
     fList->Add(but);
 
@@ -278,5 +357,5 @@
     gClient->GetColorByName("Green", color);
     but->SetBackgroundColor(color);
-    but->Move(147, 275);
+    but->Move(147, 295);
     but->Resize(62, 25);
     but->SetToolTipText("Start a telescope movement.");
@@ -287,9 +366,108 @@
     gClient->GetColorByName("Red", color);
     but->SetBackgroundColor(color);
-    but->Move(212, 275);
+    but->Move(212, 295);
     but->Resize(62, 25);
     but->SetToolTipText("Stop any movement of telescope.");
     fList->Add(but);
 
+    /*
+     const Double_t ca   = 0; // Left-Right Collimation Error
+     const Double_t an   = 0; // Azimuth Axis Misalignment (N-S)
+     const Double_t aw   = 0; // Azimuth Axis Misalignment (E-W)
+     const Double_t npae = 0; // Az-El Nonperpendicularity
+     const Double_t nrx  = 0; // Nasmyth rotator displacement, horizontan
+     const Double_t nry  = 0; // Nasmyth rotator displacement, vertical
+     const Double_t crx  = 0; // Alt/Az Coude Displacement (N-S)
+     const Double_t cry  = 0; // Alt/Az Coude Displacement (E-W)
+    l1 = new TGLabel(tf5, "CA");
+    l1->SetTextJustify(kTextLeft);
+    l1->Move(x, y+2*h*1.5);
+    l1->MapWindow();
+    fList->Add(l1);
+    l1 = new TGLabel(tf5, "AN");
+    l1->SetTextJustify(kTextLeft);
+    l1->Move(x, y+3*h*1.5);
+    l1->MapWindow();
+    fList->Add(l1);
+    l1 = new TGLabel(tf5, "AW");
+    l1->SetTextJustify(kTextLeft);
+    l1->Move(x, y+4*h*1.5);
+    l1->MapWindow();
+    fList->Add(l1);
+    l1 = new TGLabel(tf5, "NPAE");
+    l1->SetTextJustify(kTextLeft);
+    l1->Move(x, y+5*h*1.5);
+    l1->MapWindow();
+    fList->Add(l1);
+    l1 = new TGLabel(tf5, "NRX");
+    l1->SetTextJustify(kTextLeft);
+    l1->Move(x, y+6*h*1.5);
+    l1->MapWindow();
+    fList->Add(l1);
+    l1 = new TGLabel(tf5, "NRY");
+    l1->SetTextJustify(kTextLeft);
+    l1->Move(x, y+7*h*1.5);
+    l1->MapWindow();
+    fList->Add(l1);
+    l1 = new TGLabel(tf5, "CRX");
+    l1->SetTextJustify(kTextLeft);
+    l1->Move(x, y+8*h*1.5);
+    l1->MapWindow();
+    fList->Add(l1);
+    l1 = new TGLabel(tf5, "CRY");
+    l1->SetTextJustify(kTextLeft);
+    l1->Move(x, y+9*h*1.5);
+    l1->MapWindow();
+    fList->Add(l1);
+    const Double_t ie   = 0; // Index Error in Elevation
+    const Double_t ia   = 0; // Index Error in Azimuth
+    const Double_t eces = 0; // Elevation Centering Error (sin)
+    const Double_t ecec = 0; // Elevation Centering Error (cos)
+    const Double_t aces = 0; // Azimuth Centering Error (sin)
+    const Double_t acec = 0; // Azimuth Centering Error (cos)
+    l1 = new TGLabel(tf5, "IE");
+    l1->SetTextJustify(kTextLeft);
+    l1->Move(x+150, y+3*h*1.5);
+    l1->MapWindow();
+    fList->Add(l1);
+    l1 = new TGLabel(tf5, "IA");
+    l1->SetTextJustify(kTextLeft);
+    l1->Move(x+150, y+4*h*1.5);
+    l1->MapWindow();
+    fList->Add(l1);
+    l1 = new TGLabel(tf5, "ECES");
+    l1->SetTextJustify(kTextLeft);
+    l1->Move(x+150, y+5*h*1.5);
+    l1->MapWindow();
+    fList->Add(l1);
+    l1 = new TGLabel(tf5, "ECEC");
+    l1->SetTextJustify(kTextLeft);
+    l1->Move(x+150, y+6*h*1.5);
+    l1->MapWindow();
+    fList->Add(l1);
+    l1 = new TGLabel(tf5, "ACES");
+    l1->SetTextJustify(kTextLeft);
+    l1->Move(x+150, y+4*h*1.5);
+    l1->MapWindow();
+    fList->Add(l1);
+    l1 = new TGLabel(tf5, "IA");
+    l1->SetTextJustify(kTextLeft);
+    l1->Move(x+150, y+4*h*1.5);
+    l1->MapWindow();
+    fList->Add(l1);
+
+
+    TGTextEntry *entry = new TGTextEntry(tf5, "****", kEF_BendIE);
+    entry->Associate(this);
+    entry->Move(x+50, y+2*h*1.5);
+    entry->MapWindow();
+    fList->Add(entry);
+
+    entry = new TGTextEntry(tf5, "*****", kEF_BendIA);
+    entry->Associate(this);
+    entry->Move(x+50, y+3*h*1.5);
+    entry->MapWindow();
+    fList->Add(entry);
+    */
 }
 
@@ -423,10 +601,36 @@
 }
 
+double MGCosy::UpdateTime()
+{
+    Timer time;
+    time.Now();
+
+    char text[256];
+
+    strcpy(text, time.GetTimeStr());
+
+    char *dot = strrchr(text, '.');
+
+    if (dot)
+        dot[2] = 0;
+
+    fUtc->SetText(new TGString(text));
+
+    double mjd = time.CalcMjd();
+
+    sprintf(text, "%12.6f", mjd);
+    fMjd->SetText(new TGString(text));
+
+    return mjd;
+}
+
 void MGCosy::Update(ZdAz pos, ZdAz acc, ZdAz vel, ZdAz off, UInt_t stat)
 {
-    fSkyPosition->Update(pos);
+    double mjd = UpdateTime();
+    fSkyPosition->Update(pos, mjd);
     fAccuracy->Update(pos, acc);
     fVelocity->Update(vel);
     UpdateOffset(off);
+    
 
 #define kError     0x01
@@ -522,6 +726,6 @@
             tm.Now();
 
-            Float_t h = 2.+tm.H()+(8.+tm.M())/60.;
-            RaDec dest(h*15, 130);
+            Float_t h = 2.+tm.H()+(10.7+tm.M())/60.;
+            RaDec dest(h*15, 129.7);
 
             cout << dest.Ra()/15 << "h " << dest.Dec() << "°" << endl;
@@ -530,5 +734,5 @@
 
             int i = 0;
-            while (!HasStopFlag() && i++<130)  // 2.5min
+            while (!HasStopFlag() && i++<60)  // 2.5min
                 usleep(1000000);
             if (HasStopFlag())
@@ -537,5 +741,5 @@
             //fQueue->PostMsg(WM_STOP, 0, 0);
 
-            ZdAz dest1(fRand.Integer(56)+5, fRand.Integer(360));
+            ZdAz dest1(fRand.Integer(36)+25, fRand.Integer(360));
 
             cout << "Demo: Zd=" << dest1.Zd() << "° Az=" << dest1.Az() << "°" << endl;
@@ -544,5 +748,5 @@
 
             i = 0;
-            while (!HasStopFlag() && i++<30)  // 30s
+            while (!HasStopFlag() && i++<15)  // 30s
                 usleep(1000000);
             if (HasStopFlag())
@@ -581,4 +785,29 @@
     demo.Stop();
 }
+
+void MGCosy::StartCalib()
+{
+    cout << "Start Calibration." << endl;
+
+    XY xy = fCCalib->GetCoordinates();
+    RaDec pos(xy.X()*360/24, xy.Y());
+
+    fQueue->PostMsg(WM_CALIB, &pos, sizeof(pos));
+
+    cout << "PostMsg (WM_Calib) returned." << endl;
+}
+
+void MGCosy::StartTPoint()
+{
+    cout << "Start writing tpoint pair." << endl;
+
+    XY xy = fCCalib->GetCoordinates();
+    RaDec pos(xy.X()*360/24, xy.Y());
+
+    //fQueue->PostMsg(WM_TPOINT, &pos, sizeof(pos));
+    fQueue->Proc(WM_TPOINT, &pos);
+
+    cout << "PostMsg (WM_TPoint) returned." << endl;
+}
 //
 // ******************************************************************
@@ -622,4 +851,7 @@
                     return kTRUE;
                 case 2:
+                    fCRaDec->SetCoordinates(fCCalib->GetCoordinates());
+                    return kTRUE;
+                case 3:
                     StartDemo();
                     return kTRUE;
@@ -637,18 +869,47 @@
             case kPB_CALCALTAZ:
                 {
-                    SlaStars sla;
-                    sla.SetMjd2Now();
-
                     XY xy = fCRaDec->GetCoordinates();
-                    RaDec rd(xy.X()*15., xy.Y());
-
-                    cout << "Ra/Dec: " << rd.Ra() << kDEG << " " << rd.Dec() << kDEG << endl;
-                    ZdAz aa=sla.CalcZdAz(rd*kDeg2Rad)*kRad2Deg;
-                    cout << "Zd/Az: " << aa.Zd() << kDEG << " " << aa.Az() << kDEG << endl;
+                    fQueue->Proc(WM_CALCALTAZ, &xy);
                 }
                 return kTRUE;
 
-            case kPB_POLARIS:
-                fQueue->PostMsg(WM_POLARIS, 0, 0);
+            case kPB_RAp:
+            case kPB_RAm:
+            case kPB_DECp:
+            case kPB_DECm:
+                {
+                    XY xy = fCRaDec->GetCoordinates();
+                    switch (mp1)
+                    {
+                    case kPB_RAp:
+                        xy.X(xy.X()+1./60);
+                        break;
+                    case kPB_RAm:
+                        xy.X(xy.X()-1./60);
+                        break;
+                    case kPB_DECp:
+                        xy.Y(xy.Y()+1./60);
+                        break;
+                    case kPB_DECm:
+                        xy.Y(xy.Y()-1./60);
+                        break;
+                    }
+                    RaDec dest(xy.X()*15., xy.Y()); // xy.X()  [h]->[ø]
+                    fQueue->PostMsg(WM_TRACK, &dest, sizeof(dest));
+                    //fQueue->Proc(WM_NEWTRACK, &dest);
+                    fCRaDec->SetCoordinates(xy);
+
+                    cout << "New Ra/Dec: " << dest.Ra() << "h " << dest.Dec() << "\xb0" << endl;
+                }
+                return kTRUE;
+
+            case kPB_TPOINT:
+                StartTPoint();
+                return kTRUE;
+            case kPB_CALIBSE:
+                StartCalib();
+                return kTRUE;
+            case kPB_LoadBending:
+                fQueue->Proc(WM_LOADBENDING, NULL);
                 return kTRUE;
 
Index: trunk/MagicSoft/Cosy/gui/MGCosy.h
===================================================================
--- trunk/MagicSoft/Cosy/gui/MGCosy.h	(revision 1343)
+++ trunk/MagicSoft/Cosy/gui/MGCosy.h	(revision 1531)
@@ -47,6 +47,10 @@
     TGLabel       *fOffsetAz;
 
+    TGLabel       *fUtc;
+    TGLabel       *fMjd;
+
     MGCoordinates *fCZdAz;
     MGCoordinates *fCRaDec;
+    MGCoordinates *fCCalib;
 
     MGSkyPosition *fSkyPosition;
@@ -74,7 +78,10 @@
     void StartTrack();
     void StartDemo();
+    void StartCalib();
+    void StartTPoint();
 
     void EnableLabel(TGLabel *label, Bool_t stat);
     void UpdateOffset(ZdAz &off);
+    double UpdateTime();
 
 public:
Index: trunk/MagicSoft/Cosy/gui/MGStarguider.cc
===================================================================
--- trunk/MagicSoft/Cosy/gui/MGStarguider.cc	(revision 1343)
+++ trunk/MagicSoft/Cosy/gui/MGStarguider.cc	(revision 1531)
@@ -1,9 +1,11 @@
 #include "MGStarguider.h"
 
-#include <iostream.h> // cout
-
+#include <fstream.h>    // ifstream
+#include <iostream.h>   // cout
+#
 #include <TGMenu.h>
 #include <TSystem.h>
 #include <TGSplitter.h>    // TGHorizontal3DLine
+#include <TGTextEntry.h>
 
 #include "MGImage.h"
@@ -15,6 +17,9 @@
 
 #include "Filter.h"
+#include "Filter2.h"
 #include "Writer.h"
 #include "base/timer.h"
+
+#include "MStarList.h"
 
 ClassImp(MGStarguider);
@@ -23,4 +28,5 @@
     IDM_kFilter,
     IDM_kCatalog,
+    IDM_kStarguider,
     IDM_kStart,
     IDM_kStop,
@@ -29,4 +35,5 @@
     IDM_kPNG,
     IDM_kOnce,
+    IDM_kUseFileRaDec,
     IDM_kContinous,
     IDM_kRate25ps,
@@ -44,10 +51,22 @@
     IDM_kLimMag7,
     IDM_kLimMag8,
-    IDM_kLimMag9
+    IDM_kLimMag9,
+    IDM_kPixSize,
+    IDM_kInterpol125,
+    IDM_kInterpol25,
+    IDM_kInterpol10,
+    IDM_kInterpol5,
+    IDM_kInterpol2,
+    IDM_kInterpol1
 };
 
+#define kZOOM 96
+
 MGStarguider::MGStarguider()
-: Camera(), TGMainFrame(gClient->GetRoot(), 768, 700)
-{
+: Camera(), TGMainFrame(gClient->GetRoot(), 768, 700), fDx((768-kZOOM)/2), fDy((512-kZOOM)/2)
+{
+    gVirtualX->GrabButton(fId, kButton2, /*kButtonPressMask|kButtonReleaseMask|*/kNone, kNone, kNone, kNone);
+
+
     fList = new MGList;
 
@@ -65,4 +84,5 @@
     fDisplay->AddEntry("&Filter",      IDM_kFilter);
     fDisplay->AddEntry("Sao &Catalog", IDM_kCatalog);
+    fDisplay->AddEntry("Starguider",   IDM_kStarguider);
     fDisplay->Associate(this);
     fList->Add(fDisplay);
@@ -121,6 +141,21 @@
     fSao->SetLimitMag(8.0);
 
+    fInterpol = new TGPopupMenu(p);
+    fInterpol->AddEntry("125", IDM_kInterpol125);
+    fInterpol->AddEntry("25",  IDM_kInterpol25);
+    fInterpol->AddEntry("10",  IDM_kInterpol10);
+    fInterpol->AddEntry("5",   IDM_kInterpol5);
+    fInterpol->AddEntry("2",   IDM_kInterpol2);
+    fInterpol->AddEntry("Off", IDM_kInterpol1);
+    fInterpol->CheckEntry(IDM_kInterpol25);
+    fInterpol->Associate(this);
+    fList->Add(fInterpol);
+
+    fIntRate = 25;
+
     fSetup = new TGPopupMenu(p);
-    fSetup->AddPopup("Lim. &Magnitude", fLimMag);
+    fSetup->AddPopup("Lim. &Magnitude",      fLimMag);
+    fSetup->AddPopup("Disp. &Interpolation", fInterpol);
+    fSetup->AddEntry("Use Ra/Dec from file", IDM_kUseFileRaDec);
     fSetup->Associate(this);
     fList->Add(fSetup);
@@ -140,7 +175,20 @@
 
     fCZdAz = new MGCoordinates(this, kETypeZdAz);
-    fCZdAz->Move(240+12, fMenu->GetDefaultHeight()+584);
+    fCZdAz->Move(240+12+10, fMenu->GetDefaultHeight()+584);
     AddFrame(fCZdAz);
     fList->Add(fCZdAz);
+
+    const Double_t pixsize = 23.4;
+
+    fSao->SetPixSize(pixsize/3600);
+
+    TString txt;
+    txt += pixsize;
+
+    fPixSize = new TGTextEntry(this, txt, IDM_kPixSize);
+    fPixSize->SetAlignment(kTextCenterX);
+    fPixSize->Move(600, fMenu->GetDefaultHeight()+584);
+    AddFrame(fPixSize);
+    fList->Add(fPixSize);
 
     // TGHorizontal3DLine *fLineSep = new TGHorizontal3DLine(this);
@@ -156,4 +204,9 @@
     fList->Add(fImage);
 
+    fZoomImage = new MGImage(this, kZOOM, kZOOM);
+    fZoomImage->Move(768-kZOOM-2, 700-kZOOM-2);
+    AddFrame(fZoomImage);
+    fList->Add(fZoomImage);
+
     //
     // Make everything visible
@@ -164,6 +217,4 @@
     MapSubwindows();
     MapWindow();
-
-    fSao->SetPixSize(0.006);
 }
 
@@ -191,8 +242,26 @@
 }
 
+void MGStarguider::Toggle(TGPopupMenu *p, UInt_t id)
+{
+    if (p->IsEntryChecked(id))
+        p->UnCheckEntry(id);
+    else
+        p->CheckEntry(id);
+
+}
+
 Bool_t MGStarguider::ProcessMessage(Long_t msg, Long_t mp1, Long_t mp2)
 {
     switch (GET_MSG(msg))
     {
+    case kC_TEXTENTRY:
+        if (GET_SUBMSG(msg)==kTE_ENTER)
+        {
+            const Float_t pixsize = atof(fPixSize->GetText());
+            cout << "Pixel Size changed to " << pixsize << "\"/pix" << endl;
+            fSao->SetPixSize(pixsize/3600);
+        }
+        return kTRUE;
+
     case kC_COMMAND:
         switch (GET_SUBMSG(msg))
@@ -202,15 +271,31 @@
             {
             case IDM_kCatalog:
+                Toggle(fDisplay, IDM_kCatalog);
                 if (fDisplay->IsEntryChecked(IDM_kCatalog))
-                    fDisplay->UnCheckEntry(IDM_kCatalog);
+                    fDisplay->EnableEntry(IDM_kStarguider);
                 else
-                    fDisplay->CheckEntry(IDM_kCatalog);
+                {
+                    fDisplay->UnCheckEntry(IDM_kStarguider);
+                    fDisplay->DisableEntry(IDM_kStarguider);
+                }
+                return kTRUE;
+
+            case IDM_kStarguider:
+                Toggle(fDisplay, IDM_kStarguider);
                 return kTRUE;
 
             case IDM_kFilter:
+                Toggle(fDisplay, IDM_kFilter);
                 if (fDisplay->IsEntryChecked(IDM_kFilter))
-                    fDisplay->UnCheckEntry(IDM_kFilter);
+                    fDisplay->EnableEntry(IDM_kStarguider);
                 else
-                    fDisplay->CheckEntry(IDM_kFilter);
+                {
+                    fDisplay->UnCheckEntry(IDM_kStarguider);
+                    fDisplay->DisableEntry(IDM_kStarguider);
+                }
+                return kTRUE;
+
+            case IDM_kUseFileRaDec:
+                Toggle(fSetup, IDM_kUseFileRaDec);
                 return kTRUE;
 
@@ -283,4 +368,38 @@
                 return kTRUE;
 
+            case IDM_kInterpol125:
+            case IDM_kInterpol25:
+            case IDM_kInterpol10:
+            case IDM_kInterpol5:
+            case IDM_kInterpol2:
+            case IDM_kInterpol1:
+                for (int i=IDM_kInterpol125; i<=IDM_kInterpol1; i++)
+                    if (mp1==i)
+                        fInterpol->CheckEntry(i);
+                    else
+                        fInterpol->UnCheckEntry(i);
+                switch (mp1)
+                {
+                case IDM_kInterpol1:
+                    fIntRate = 1;
+                    return kTRUE;
+                case IDM_kInterpol2:
+                    fIntRate = 2;
+                    return kTRUE;
+                case IDM_kInterpol5:
+                    fIntRate = 5;
+                    return kTRUE;
+                case IDM_kInterpol10:
+                    fIntRate = 10;
+                    return kTRUE;
+                case IDM_kInterpol25:
+                    fIntRate = 25;
+                    return kTRUE;
+                case IDM_kInterpol125:
+                    fIntRate = 125;
+                    return kTRUE;
+                }
+                return kTRUE;
+
             case IDM_kLimMag3:
             case IDM_kLimMag4:
@@ -303,10 +422,119 @@
         break;
     }
+
     return kTRUE;
 }
 
+void MGStarguider::GetCoordinates()
+{
+    XY xy = fCRaDec->GetCoordinates();
+
+    if (fSetup->IsEntryChecked(IDM_kUseFileRaDec))
+    {
+        ifstream fin("coordinates.txt");
+        if (!fin)
+            cout << "Error: Cannot open 'coordinates.txt' using fall back solution." << endl;
+        else
+            fin >> xy;
+    }
+
+    fCRaDec->SetCoordinates(xy);
+    fRaDec->Set(xy.X()*360/24, xy.Y());
+}
+
+void MGStarguider::CalcTrackingError(MStarList &spots, MStarList &stars)
+{
+    if (stars.GetRealEntries() < 3)
+    {
+        cout << "Sorry, less than 3 stars in FOV!" << endl;
+        return;
+    }
+
+    if (spots.GetRealEntries() < 1)
+    {
+        cout << "Sorry, less than 1 detected spot in FOV!" << endl;
+        return;
+    }
+
+    Int_t idx = 0;
+
+    MStarList sortedspots;
+
+    MStar *star;
+    MStar *spot;
+    MStarListIter NextStar(&stars);
+    MStarListIter NextSpot(&spots);
+
+    while ((spot=NextSpot()))
+    {
+        AltAz aa = fSao->CalcAltAzFromPix(spot->GetX(), spot->GetY());
+        spot->Set(aa.Az(), aa.Alt());
+    }
+
+    while ((star=NextStar()))
+    {
+        AltAz aa = fSao->CalcAltAzFromPix(star->GetX(), star->GetY());
+        star->Set(aa.Az(), aa.Alt());
+
+        const double aaz   = star->GetX();
+        const double dphi2 = aaz/2.;
+        const double cos2  = cos(dphi2)*cos(dphi2);
+        const double sin2  = sin(dphi2)*sin(dphi2);
+
+        Double_t min = 800;
+
+        NextSpot.Reset();
+        while ((spot=NextSpot()))
+        {
+            const double pzd = TMath::Pi()/2-spot->GetY();
+            const double azd = TMath::Pi()/2-star->GetY();
+
+            const double d = cos(azd)*cos2 - cos(2*pzd+azd)*sin2;
+
+            const Double_t dist = acos(d);
+
+            if (dist>=min)
+                continue;
+
+            min = dist;
+            sortedspots.AddAt(idx, spot->GetX(), spot->GetY(), spot->GetMag());
+        }
+        if (min>768)
+        {
+            cout << "ERROR!!!!!!!!" << endl;
+            return;
+        }
+        idx++;
+    }
+
+    //
+    // Now we have in sortedspots the entries with the shortest distances
+    // to the corresponding ones in stars.
+    // Now calculate the tracking error.
+    //
+    NextStar.Reset();
+    MStarListIter NextSpot2(&sortedspots);
+
+    Double_t meanx=0;
+    Double_t meany=0;
+
+    while ((star=NextStar()))
+    {
+        spot = NextSpot2();
+
+        meanx += star->GetX() - spot->GetX();
+        meany += star->GetY() - spot->GetY();
+    }
+
+    meanx /= idx;
+    meany /= idx;
+
+    cout << "Tracking Error:  dAlt=" << meany*180/TMath::Pi();
+    cout << "°  dAz=" << meanx*180/TMath::Pi() << "°    (calculated";
+    cout << " with " << idx << " stars/spots)" << endl;
+}
+
 void MGStarguider::ProcessFrame(const unsigned long n, byte *img, struct timeval *tm)
 {
-
     if (!fWrite->IsEntryEnabled(IDM_kStart) &&
         (!(n%fWrtRate) || fWriteType->IsEntryChecked(IDM_kOnce)))
@@ -315,7 +543,6 @@
         {
             static int num = 0;
-
             char name[80];
-            sprintf(name, "pix/file%04d.png", num);
+            sprintf(name, "pix/file%04d.png", num++);
             Writer::Png(name, img, tm);
         }
@@ -325,5 +552,5 @@
             static int num = 0;
             char name[80];
-            sprintf(name, "pix/file%04d.ppm", num);
+            sprintf(name, "pix/file%04d.ppm", num++);
             Writer::Ppm(name, img);
         }
@@ -333,28 +560,81 @@
     }
 
-    if (!(n%25))
-    {
-        cout << "Img: " << n << endl;
-
+    static float myimg[768*576];
+
+    for (int i=0; i<768*576; i++)
+        myimg[i] += img[i];
+
+    if (n%fIntRate)
+        return;
+
+    cout << "Img: " << n << endl;
+
+    byte c[768*576];
+    for (int i=0; i<768*576; i++)
+        c[i] = (byte)(myimg[i]/fIntRate+.5);
+
+    MStarList spots;
+    if (fDisplay->IsEntryChecked(IDM_kStarguider))
+        Filter2::Execute(spots, c);
+    else
         if (fDisplay->IsEntryChecked(IDM_kFilter))
-            Filter::Execute(img);
-
-        if (fDisplay->IsEntryChecked(IDM_kCatalog))
-        {
-            byte cimg[768*576];
-
-            XY xy = fCRaDec->GetCoordinates();
-
-            fRaDec->Set(xy.X(), xy.Y());
-
-            Timer time(tm);
-            fSao->GetImg(img, cimg, time.CalcMjd(), *fRaDec);
-            fImage->DrawColImg(img, cimg);
-
-            fCZdAz->SetCoordinates(fSao->GetZdAz());
-        }
-        else
-            fImage->DrawImg(img);
-    }
-
-}
+            Filter::Execute(c);
+
+    byte zimg[kZOOM*kZOOM];
+    for (int y=0; y<kZOOM; y++)
+        for (int x=0; x<kZOOM; x++)
+            zimg[x+y*kZOOM] = c[(fDx+(x-kZOOM/2)/2)+(fDy+(y-kZOOM/2)/2)*768];
+
+    fZoomImage->DrawImg(zimg);
+
+    if (fDisplay->IsEntryChecked(IDM_kCatalog))
+    {
+        byte cimg[768*576];
+
+        GetCoordinates();
+
+        Timer time(tm);
+
+        MStarList stars;
+        fSao->GetStars(stars, time.CalcMjd(), *fRaDec);
+        fSao->GetImg(c, cimg, stars);
+        //fSao->GetImg(c, cimg, time.CalcMjd(), *fRaDec);
+
+        fImage->DrawColImg(c, cimg);
+
+        fCZdAz->SetCoordinates(fSao->GetZdAz());
+
+        if (fDisplay->IsEntryChecked(IDM_kStarguider))
+            CalcTrackingError(spots, stars);
+    }
+    else
+        fImage->DrawImg(c);
+
+    memset(myimg, 0, 768*576*sizeof(float));
+}
+
+Bool_t MGStarguider::HandleDoubleClick(Event_t *event)
+{
+    const Int_t w = fImage->GetWidth();
+    const Int_t h = fImage->GetHeight();
+    const Int_t x = fImage->GetX();
+    const Int_t y = fImage->GetY();
+
+    if (!(event->fX>x && event->fX<x+w && event->fY>y && event->fY<y+h))
+        return kTRUE;
+
+    Int_t dx = event->fX-x;
+    Int_t dy = event->fY-y;
+
+    if (dx<kZOOM/4) dx=kZOOM/4;
+    if (dy<kZOOM/4) dy=kZOOM/4;
+    if (dx>766-kZOOM/2) dx=766-kZOOM/4;
+    if (dy>510-kZOOM/2) dy=510-kZOOM/4;
+
+    fDx = dx;
+    fDy = dy;
+
+    cout << "New coordinates for zoom: " << fDx << " " << fDy << endl;
+
+    return kTRUE;
+}
Index: trunk/MagicSoft/Cosy/gui/MGStarguider.h
===================================================================
--- trunk/MagicSoft/Cosy/gui/MGStarguider.h	(revision 1343)
+++ trunk/MagicSoft/Cosy/gui/MGStarguider.h	(revision 1531)
@@ -12,8 +12,10 @@
 #include "MGImage.h"
 
+class AltAz;
 class RaDec;
 
 class TGMenuBar;
 class TGPopupMenu;
+class TGTextEntry;
 
 class MGImage;
@@ -21,4 +23,5 @@
 
 class StarCatalog;
+class MStarList;
 
 class MGStarguider : public Camera, public TGMainFrame
@@ -29,4 +32,5 @@
     TGMenuBar     *fMenu;
     MGImage       *fImage;
+    MGImage       *fZoomImage;
 
     TGPopupMenu   *fDisplay;
@@ -35,4 +39,5 @@
     TGPopupMenu   *fWriteType;
     TGPopupMenu   *fWriteRate;
+    TGPopupMenu   *fInterpol;
     TGPopupMenu   *fSetup;
     TGPopupMenu   *fLimMag;
@@ -41,11 +46,20 @@
     MGCoordinates *fCZdAz;
 
+    TGTextEntry   *fPixSize;
+
     StarCatalog   *fSao;
 
     RaDec *fRaDec;
 
+    Int_t fDx;
+    Int_t fDy;
+
+    int fIntRate;
     int fWrtRate;
 
     void SetPixSize(const double pixsize);
+    void Toggle(TGPopupMenu *p, UInt_t id);
+    void GetCoordinates();
+    void CalcTrackingError(MStarList &, MStarList &);
 
 public:
@@ -59,4 +73,5 @@
 
     Bool_t ProcessMessage(Long_t msg, Long_t parm1, Long_t parm2);
+    Bool_t HandleDoubleClick(Event_t *event);
 
     //
