]> git.uio.no Git - u/mrichter/AliRoot.git/blob - RALICE/AliAstrolab.cxx
11-jan-2008 NvE All files of external applications removed to facilitate
[u/mrichter/AliRoot.git] / RALICE / AliAstrolab.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 // $Id$
17
18 ///////////////////////////////////////////////////////////////////////////
19 // Class AliAstrolab
20 // Virtual lab to correlate measurements with astrophysical phenomena.
21 //
22 // This class is derived from TTask, but the only reason for this
23 // is to enable this class to serve as a base class for other TTask
24 // derived classes (e.g. AliEventSelector) without the need for
25 // multiple virtual inheritance.
26 // So, this AliAstrolab class itself does not provide any TTask
27 // related functionality.
28 //
29 // The lab can be given a terrestrial location via the usual longitude
30 // and latitude specifications.
31 // Since this class is derived from AliTimestamp, a lab can also be
32 // given a specific timestamp. Together with the terrestrial location
33 // this provides access to local (sidereal) times etc...
34 // In addition to the usual astronomical reference frames, a local
35 // lab reference frame can also be specified. Together with the lab's
36 // timestamp this uniquely defines all the coordinate transformations
37 // between the various reference frames.
38 // These lab characteristics allow a space-time correlation of lab
39 // observations with external (astrophysical) phenomena.
40 //
41 // Observations are entered as generic signals containing a position,
42 // reference frame specification and a timestamp.
43 // These observations can then be analysed in various reference frames
44 // via the available GET functions.
45 //
46 // Various external (astrophysical) phenomena may be entered as
47 // so-called reference signals.
48 // This class provides facilities (e.g. MatchRefSignal) to check
49 // correlations of the stored measurement with these reference signals.
50 // Also graphical facilities (e.g. DisplaySignals) are available to
51 // provide skymaps in various projections.
52 // 
53 // Coding example :
54 // ----------------
55 // gSystem->Load("ralice");
56 //
57 // AliAstrolab lab("IceCube","The South Pole Neutrino Observatory");
58 // lab.SetLabPosition(0,-90,"deg"); // South Pole
59 //
60 // lab.SetLocalFrame(90,180,90,270,0,0); // Local frame has X-axis to the North
61 //
62 // lab.Data(1,"dms"); // Print laboratory parameters
63 //
64 // // Enter some observed event to be investigated
65 // AliTimestamp ts;
66 // ts.SetUT(1989,7,30,8,14,23,738504,0);
67 // Float_t vec[3]={1,23.8,118.65};
68 // Ali3Vector r;
69 // r.SetVector(vec,"sph","deg");
70 // lab.SetSignal(&r,"loc","M",&ts,0,"Event10372");
71 //
72 // // Enter some reference signals
73 // Float_t alpha=194818.0;
74 // Float_t delta=84400.;
75 // lab.SetSignal(alpha,delta,"B",1950,"M",-1,"Altair");
76 // alpha=124900.0;
77 // delta=272400.;
78 // lab.SetSignal(alpha,delta,"B",1950,"M",-1,"NGP");
79 // alpha=64508.917;
80 // delta=-164258.02;
81 // lab.SetSignal(alpha,delta,"J",2000,"M",-1,"Sirius");
82 // alpha=23149.08;
83 // delta=891550.8;
84 // lab.SetSignal(alpha,delta,"J",2000,"M",-1,"Polaris");
85 // alpha=43600.;
86 // delta=163100.;
87 // lab.SetSignal(alpha,delta,"J",2000,"M",-1,"Aldebaran");
88 // Float_t l=327.531;
89 // Float_t b=-35.8903;
90 // Float_t pos[3]={1,90.-b,l};
91 // r.SetVector(pos,"sph","deg");
92 // lab.SetUT(1989,7,30,8,14,16,0,0);
93 // lab.SetSignal(&r,"gal","M",0,-1,"GRB890730");
94 //
95 // // List all stored objects
96 // lab.ListSignals("equ","M",5);
97 //
98 // // Determine minimal space and time differences with reference signals
99 // Double_t da,dt;
100 // Int_t ia,it;
101 // da=lab.GetDifference(0,"deg",dt,"s",1,&ia,&it);
102 // cout << " Minimal differences damin (deg) : " << da << " dtmin (s) : " << dt
103 //      << " damin-index : " << ia << " dtmin-index : " << it << endl;
104 // cout << " damin for "; lab->PrintSignal("equ","T",&ts,5,ia); cout << endl;
105 // cout << " dtmin for "; lab->PrintSignal("equ","T",&ts,5,it); cout << endl;
106 //
107 // // Search for space and time match with the reference signals
108 // da=5;
109 // dt=10;
110 // TArrayI* arr=lab.MatchRefSignal(da,"deg",dt,"s");
111 // Int_t index=0;
112 // if (arr)
113 // {
114 //  for (Int_t i=0; i<arr->GetSize(); i++)
115 //  {
116 //   index=arr->At(i);
117 //   cout << " Match found for index : " << index << endl;
118 //   cout << " Corresponding ref. object "; lab->PrintSignal("equ","T",&ts,5,index); cout << endl;
119 //  }
120 // }
121 //
122 // // Display all stored objects in a skymap (Hammer projection)
123 // lab.DisplaySignals("equ","M",&ts,"ham",1);
124 //
125 //--- Author: Nick van Eijndhoven 15-mar-2007 Utrecht University
126 //- Modified: NvE $Date$ Utrecht University
127 ///////////////////////////////////////////////////////////////////////////
128
129 #include "AliAstrolab.h"
130 #include "Riostream.h"
131  
132 ClassImp(AliAstrolab) // Class implementation to enable ROOT I/O
133  
134 AliAstrolab::AliAstrolab(const char* name,const char* title) : TTask(name,title),AliTimestamp()
135 {
136 // Default constructor
137
138  fToffset=0;
139  fXsig=0;
140  fRefs=0;
141  fBias=0;
142  fGal=0;
143  fIndices=0;
144  fMeridian=-999;
145  fProj="none";
146  fCanvas=0;
147  fHist=0;
148  fMarkers=0;
149 }
150 ///////////////////////////////////////////////////////////////////////////
151 AliAstrolab::~AliAstrolab()
152 {
153 // Destructor to delete all allocated memory.
154
155  if (fXsig)
156  {
157   delete fXsig;
158   fXsig=0;
159  }
160  if (fRefs)
161  {
162   delete fRefs;
163   fRefs=0;
164  }
165  if (fIndices)
166  {
167   delete fIndices;
168   fIndices=0;
169  }
170  if (fHist)
171  {
172   delete fHist;
173   fHist=0;
174  }
175  if (fMarkers)
176  {
177   delete fMarkers;
178   fMarkers=0;
179  }
180  if (fCanvas)
181  {
182   delete fCanvas;
183   fCanvas=0;
184  }
185 }
186 ///////////////////////////////////////////////////////////////////////////
187 AliAstrolab::AliAstrolab(const AliAstrolab& t) : TTask(t),AliTimestamp(t)
188 {
189 // Copy constructor
190
191  fToffset=t.fToffset;
192  fLabPos=t.fLabPos;
193  fXsig=0;
194  if (t.fXsig) fXsig=new AliSignal(*(t.fXsig));
195  fRefs=0;
196  if (t.fRefs)
197  {
198   Int_t size=t.fRefs->GetSize();
199   fRefs=new TObjArray(size);
200   for (Int_t i=0; i<size; i++)
201   {
202    AliSignal* sx=(AliSignal*)t.fRefs->At(i);
203    if (sx) fRefs->AddAt(sx->Clone(),i);
204   }
205  }
206  fBias=0;
207  fGal=0;
208  fIndices=0;
209  fMeridian=-999;
210  fProj="none";
211  fCanvas=0;
212  fHist=0;
213  fMarkers=0;
214 }
215 ///////////////////////////////////////////////////////////////////////////
216 void AliAstrolab::Data(Int_t mode,TString u)
217 {
218 // Provide lab information.
219 //
220 // "mode" indicates the mode of the timestamp info (see AliTimestamp::Date).
221 //
222 // The string argument "u" allows to choose between different angular units
223 // in case e.g. a spherical frame is selected.
224 // u = "rad" : angles provided in radians
225 //     "deg" : angles provided in degrees
226 //     "dms" : angles provided in ddd:mm:ss.sss
227 //     "hms" : angles provided in hh:mm:ss.sss
228 //
229 // The defaults are mode=1 and u="deg".
230  
231  const char* name=GetName();
232  const char* title=GetTitle();
233  cout << " *" << ClassName() << "::Data*";
234  if (strlen(name))  cout << " Name : " << GetName();
235  if (strlen(title)) cout << " Title : " << GetTitle();
236  cout << endl;
237
238  Double_t l,b;
239  GetLabPosition(l,b,"deg");
240  cout << " Lab position longitude : "; PrintAngle(l,"deg",u,2);
241  cout << " latitude : "; PrintAngle(b,"deg",u,2);
242  cout << endl;
243  cout << " Lab time offset w.r.t. UT : "; PrintTime(fToffset,12); cout << endl;
244
245  // UT and Local time info
246  Date(mode,fToffset);
247
248 ///////////////////////////////////////////////////////////////////////////
249 void AliAstrolab::SetLabPosition(Ali3Vector& p)
250 {
251 // Set the lab position in the terrestrial coordinates.
252 // The right handed reference frame is defined such that the North Pole
253 // corresponds to a polar angle theta=0 and the Greenwich meridian corresponds
254 // to an azimuth angle phi=0, with phi increasing eastwards.
255
256  fLabPos.SetPosition(p);
257
258  // Determine local time offset in fractional hours w.r.t. UT.
259  Double_t vec[3];
260  p.GetVector(vec,"sph","deg");
261  Double_t l=vec[2];
262  fToffset=l/15.;
263 }
264 ///////////////////////////////////////////////////////////////////////////
265 void AliAstrolab::SetLabPosition(Double_t l,Double_t b,TString u)
266 {
267 // Set the lab position in the terrestrial longitude (l) and latitude (b).
268 // Positions north of the equator have b>0, whereas b<0 indicates
269 // locations south of the equator.
270 // Positions east of Greenwich have l>0, whereas l<0 indicates
271 // locations west of Greenwich.
272 //
273 // The string argument "u" allows to choose between different angular units
274 // u = "rad" : angles provided in radians
275 //     "deg" : angles provided in degrees
276 //     "dms" : angles provided in dddmmss.sss
277 //     "hms" : angles provided in hhmmss.sss
278 //
279 // The default is u="deg".
280
281  Double_t r=1,theta=0,phi=0;
282
283  l=ConvertAngle(l,u,"deg");
284  b=ConvertAngle(b,u,"deg");
285
286  Double_t offset=90.;
287
288  theta=offset-b;
289  phi=l;
290
291  Double_t p[3]={r,theta,phi};
292  fLabPos.SetPosition(p,"sph","deg");
293
294  // Local time offset in fractional hours w.r.t. UT.
295  fToffset=l/15.;
296 }
297 ///////////////////////////////////////////////////////////////////////////
298 AliPosition AliAstrolab::GetLabPosition() const
299 {
300 // Provide the lab position in the terrestrial coordinates.
301 // The right handed reference frame is defined such that the North Pole
302 // corresponds to a polar angle theta=0 and the Greenwich meridian corresponds
303 // to an azimuth angle phi=0, with phi increasing eastwards.
304
305  return fLabPos;
306 }
307 ///////////////////////////////////////////////////////////////////////////
308 void AliAstrolab::GetLabPosition(Double_t& l,Double_t& b,TString u) const
309 {
310 // Provide the lab position in the terrestrial longitude (l) and latitude (b).
311 // Positions north of the equator have b>0, whereas b<0 indicates
312 // locations south of the equator.
313 // Positions east of Greenwich have l>0, whereas l<0 indicates
314 // locations west of Greenwich.
315 //
316 // The string argument "u" allows to choose between different angular units
317 // u = "rad" : angles provided in radians
318 //     "deg" : angles provided in degrees
319 //
320 // The default is u="deg".
321
322  Double_t pi=acos(-1.);
323
324  Double_t offset=90.;
325  if (u=="rad") offset=pi/2.;
326
327  Double_t p[3];
328  fLabPos.GetPosition(p,"sph",u);
329  b=offset-p[1];
330  l=p[2];
331 }
332 ///////////////////////////////////////////////////////////////////////////
333 Double_t AliAstrolab::GetLT()
334 {
335 // Provide the Lab's local time in fractional hours.
336 // A mean solar day lasts 24h (i.e. 86400s).
337 //
338 // In case a hh:mm:ss format is needed, please use the Convert() facility. 
339  
340  Double_t h=GetLT(fToffset);
341  return h;
342 }
343 ///////////////////////////////////////////////////////////////////////////
344 Double_t AliAstrolab::GetLMST()
345 {
346 // Provide the Lab's Local Mean Sidereal Time (LMST) in fractional hours.
347 // A sidereal day corresponds to 23h 56m 04.09s (i.e. 86164.09s) mean solar time.
348 // The definition of GMST is such that a sidereal clock corresponds with
349 // 24 sidereal hours per revolution of the Earth.
350 // As such, local time offsets w.r.t. UT and GMST can be treated similarly. 
351 //
352 // In case a hh:mm:ss format is needed, please use the Convert() facility. 
353
354  Double_t h=GetLMST(fToffset);
355  return h;
356 }
357 ///////////////////////////////////////////////////////////////////////////
358 Double_t AliAstrolab::GetLAST()
359 {
360 // Provide the Lab's Local Apparent Sidereal Time (LAST) in fractional hours.
361 // A sidereal day corresponds to 23h 56m 04.09s (i.e. 86164.09s) mean solar time.
362 // The definition of GMST and GAST is such that a sidereal clock corresponds with
363 // 24 sidereal hours per revolution of the Earth.
364 // As such, local time offsets w.r.t. UT, GMST and GAST can be treated similarly. 
365 //
366 // In case a hh:mm:ss format is needed, please use the Convert() facility. 
367
368  Double_t h=GetLAST(fToffset);
369  return h;
370 }
371 ///////////////////////////////////////////////////////////////////////////
372 void AliAstrolab::PrintAngle(Double_t a,TString in,TString out,Int_t ndig) const
373 {
374 // Printing of angles in various formats.
375 //
376 // The input argument "a" denotes the angle to be printed. 
377 // The string arguments "in" and "out" specify the angular I/O formats.
378 //
379 // in = "rad" : input angle provided in radians
380 //      "deg" : input angle provided in degrees
381 //      "dms" : input angle provided in dddmmss.sss
382 //      "hms" : input angle provided in hhmmss.sss
383 //
384 // out = "rad" : output angle provided in radians
385 //       "deg" : output angle provided in degrees
386 //       "dms" : output angle provided in dddmmss.sss
387 //       "hms" : output angle provided in hhmmss.sss
388 //
389 // The argument "ndig" specifies the number of digits for the fractional
390 // part (e.g. ndig=6 for "dms" corresponds to micro-arcsecond precision).
391 // No rounding will be performed, so an arcsecond count of 3.473 with ndig=1
392 // will appear as 03.4 on the output.
393 // Due to computer accuracy, precision on the pico-arcsecond level may get lost.
394 //
395 // The default is ndig=1.
396 //
397 // Note : The angle info is printed without additional spaces or "endline".
398 //        This allows the print to be included in various composite output formats.
399
400  Double_t b=ConvertAngle(a,in,out);
401
402  if (out=="deg" || out=="rad")
403  {
404   cout.setf(ios::fixed,ios::floatfield);
405   cout << setprecision(ndig) << b << " " << out.Data();
406   cout.unsetf(ios::fixed);
407   return; 
408  }
409
410  Double_t epsilon=1.e-12; // Accuracy in (arc)seconds
411  Int_t word=0,ddd=0,hh=0,mm=0,ss=0;
412  Double_t s;
413  ULong64_t sfrac=0;
414
415  if (out=="dms")
416  {
417   word=Int_t(b);
418   word=abs(word);
419   ddd=word/10000;
420   word=word%10000;
421   mm=word/100;
422   ss=word%100;
423   s=fabs(b)-Double_t(ddd*10000+mm*100+ss);
424   if (s>(1.-epsilon))
425   {
426    s=0.;
427    ss++;
428   }
429   while (ss>=60)
430   {
431    ss-=60;
432    mm++;
433   }
434   while (mm>=60)
435   {
436    mm-=60;
437    ddd++;
438   }
439   while (ddd>=360)
440   {
441    ddd-=360;
442   }
443   s*=pow(10.,ndig);
444   sfrac=ULong64_t(s);
445   if (b<0) cout << "-";
446   cout << ddd << "d " << mm << "' " << ss << "."
447        << setfill('0') << setw(ndig) << sfrac << "\"";
448   return;
449  }
450
451  if (out=="hms")
452  {
453   word=Int_t(b);
454   word=abs(word);
455   hh=word/10000;
456   word=word%10000;
457   mm=word/100;
458   ss=word%100;
459   s=fabs(b)-Double_t(hh*10000+mm*100+ss);
460   if (s>(1.-epsilon))
461   {
462    s=0.;
463    ss++;
464   }
465   while (ss>=60)
466   {
467    ss-=60;
468    mm++;
469   }
470   while (mm>=60)
471   {
472    mm-=60;
473    hh++;
474   }
475   while (hh>=24)
476   {
477    hh-=24;
478   }
479   s*=pow(10.,ndig);
480   sfrac=ULong64_t(s);
481   if (b<0) cout << "-";
482   cout << hh << "h " << mm << "m " << ss << "."
483        << setfill('0') << setw(ndig) << sfrac << "s";
484   return;
485  }
486 }
487 ///////////////////////////////////////////////////////////////////////////
488 void AliAstrolab::SetSignal(Ali3Vector* r,TString frame,TString mode,AliTimestamp* ts,Int_t jref,TString name)
489 {
490 // Store a signal as specified by the position r and the timestamp ts.
491 // The position is stored in International Celestial Reference System (ICRS) coordinates.
492 // The ICRS is a fixed, time independent frame and as such provides a unique reference
493 // frame without the need of specifying any epoch etc...
494 // The ICRS coordinate definitions match within 20 mas with the mean ones of the J2000.0
495 // equatorial system. Nevertheless, to obtain the highest accuracy, the slight
496 // coordinate correction between J2000 and ICRS is performed here via the
497 // so-called frame bias matrix.
498 // For further details see the U.S. Naval Observatory (USNO) circular 179 (2005),
499 // which is available on http://aa.usno,navy.mil/publications/docs/Circular_179.pdf.
500 //
501 // The input parameter "frame" allows the user to specify the frame to which
502 // the components of r refer. Available options are :
503 //
504 //  frame = "equ" ==> Equatorial coordinates with right ascension (a) and declination (d),
505 //                    where the "sph" components of r correspond to theta=(pi/2)-d and phi=a.
506 //          "gal" ==> Galactic coordinates with longitude (l) and latitude (b).
507 //                    where the "sph" components of r correspond to theta=(pi/2)-b and phi=l.
508 //          "ecl" ==> Ecliptic coordinates with longitude (l) and latitude (b),
509 //                    where the "sph" components of r correspond to theta=(pi/2)-b and phi=l.
510 //          "hor" ==> Horizontal coordinates at the AliAstrolab location, where the "sph"
511 //                    components of r correspond to theta=zenith angle and phi=pi-azimuth.
512 //          "icr" ==> ICRS coordinates with longitude (l) and latitude (b),
513 //                    where the "sph" components of r correspond to theta=(pi/2)-b and phi=l.
514 //          "loc" ==> Local coordinates at the AliAstrolab location, where the "sph"
515 //                    components of r correspond to the usual theta and phi angles.
516 //
517 // In case the coordinates are the equatorial right ascension and declination (a,d),
518 // they can represent so-called "mean" and "true" values.
519 // The distinction between these two representations is the following :
520 //
521 // mean values : (a,d) are only corrected for precession and not for nutation
522 // true values : (a,d) are corrected for both precession and nutation
523 //
524 // The input parameter "mode" allows the user to specifiy either "mean" or "true"
525 // values for the input in case of equatorial (a,d) coordinates.
526 //
527 // mode = "M" --> Input coordinates are the mean values 
528 //        "T" --> Input coordinates are the true values 
529 //
530 // The input parameter "jref" allows the user to store so-called "reference" signals.
531 // These reference signals may be used to check space-time event coincidences with the
532 // stored measurement (e.g. coincidence of the measurement with transient phenomena).
533 //
534 // jref = 0 --> Storage of the measurement
535 //        j --> Storage of a reference signal at the j-th position (j=1 is first)
536 //      < 0 --> Add a reference signal at the next available position
537 //
538 // Via the input argument "name" the user can give the stored signal also a name.
539 //
540 // The default values are jref=0 and name="".
541 //
542 // Note : In case ts=0 the current timestamp of the lab will be taken.
543
544  if (!r)
545  {
546   if (!jref && fXsig)
547   {
548    delete fXsig;
549    fXsig=0;
550   }
551   return;
552  }
553
554  if (frame!="equ" && frame!="gal" && frame!="ecl" && frame!="hor" && frame!="icr" && frame!="loc")
555  {
556   if (!jref && fXsig)
557   {
558    delete fXsig;
559    fXsig=0;
560   }
561   return;
562  }
563
564  if (frame=="equ" && mode!="M" && mode!="m" && mode!="T" && mode!="t")
565  {
566   if (!jref && fXsig)
567   {
568    delete fXsig;
569    fXsig=0;
570   }
571   return;
572  }
573
574  if (!ts) ts=(AliTimestamp*)this;
575
576  Double_t vec[3]={1,0,0};
577  vec[1]=r->GetX(2,"sph","rad");
578  vec[2]=r->GetX(3,"sph","rad");
579  Ali3Vector q;
580  q.SetVector(vec,"sph","rad"); 
581
582  AliSignal* sxref=0;
583
584  if (!jref) // Storage of the measurement
585  {
586   if (!fXsig)
587   {
588    fXsig=new AliSignal();
589   }
590   else
591   {
592    fXsig->Reset(1);
593   }
594   if (name != "") fXsig->SetName(name);
595   fXsig->SetTitle("Event in ICRS coordinates");
596   fXsig->SetTimestamp(*ts);
597  }
598  else // Storage of a reference signal
599  {
600   if (!fRefs) 
601   {
602    fRefs=new TObjArray();
603    fRefs->SetOwner();
604   }
605   // Expand array size if needed
606   if (jref>0 && jref>=fRefs->GetSize()) fRefs->Expand(jref+1);
607   sxref=new AliSignal();
608   if (name != "") sxref->SetName(name);
609   sxref->SetTitle("Reference event in ICRS coordinates");
610   sxref->SetTimestamp(*ts);
611  }
612
613  if (frame=="loc")
614  {
615   // Convert to horizontal coordinates
616   q=q.GetUnprimed(&fL);
617
618   // Store the signal
619   SetSignal(&q,"hor",mode,ts,jref);
620   return;
621  }
622
623  if (frame=="equ")
624  {
625   // Convert to "mean" values at specified epoch
626   if (mode=="T" || mode=="t")
627   {
628    SetNmatrix(ts);
629    q=q.GetUnprimed(&fN);
630   }
631
632   // Convert to "mean" values at J2000
633   SetPmatrix(ts);
634   q=q.GetUnprimed(&fP);
635
636   // Convert to ICRS values
637   if (!fBias) SetBmatrix(); 
638   q=q.GetUnprimed(&fB);
639  }
640
641  if (frame=="gal")
642  {
643   // Convert to J2000 equatorial mean coordinates
644   if (fGal != 2) SetGmatrix("J");
645   q=q.GetUnprimed(&fG);
646
647   // Convert to ICRS values
648   if (!fBias) SetBmatrix(); 
649   q=q.GetUnprimed(&fB);
650  }
651
652  if (frame=="ecl")
653  {
654   // Convert to mean equatorial values at specified epoch
655   SetEmatrix(ts);
656   q=q.GetUnprimed(&fE);
657
658   // Convert to "mean" values at J2000
659   SetPmatrix(ts);
660   q=q.GetUnprimed(&fP);
661
662   // Convert to ICRS values
663   if (!fBias) SetBmatrix(); 
664   q=q.GetUnprimed(&fB);
665  }
666
667  if (frame=="hor")
668  {
669   // Convert to "true" equatorial values at the specified timestamp
670   SetHmatrix(ts);
671   q=q.GetUnprimed(&fH);
672
673   // Convert to "mean" values at specified timestamp
674   SetNmatrix(ts);
675   q=q.GetUnprimed(&fN);
676
677   // Convert to "mean" values at J2000
678   SetPmatrix(ts);
679   q=q.GetUnprimed(&fP);
680
681   // Convert to ICRS values
682   if (!fBias) SetBmatrix(); 
683   q=q.GetUnprimed(&fB);
684  }
685
686  // Store the signal in ICRS coordinates
687  if (!jref) // Storage of a regular signal
688  {
689   fXsig->SetPosition(q);
690  }
691  else // Storage of a reference signal
692  {
693   sxref->SetPosition(q);
694   if (jref<0)
695   {
696    fRefs->Add(sxref);
697   }
698   else
699   {
700    fRefs->AddAt(sxref,jref-1);
701   }
702  }
703 }
704 ///////////////////////////////////////////////////////////////////////////
705 void AliAstrolab::SetSignal(Double_t a,Double_t d,TString s,Double_t e,TString mode,Int_t jref,TString name)
706 {
707 // Store a signal with right ascension (a) and declination (d) given for epoch e.
708 // The position is stored in International Celestial Reference System (ICRS) coordinates.
709 // The ICRS is a fixed, time independent frame and as such provides a unique reference
710 // frame without the need of specifying any epoch etc...
711 // The ICRS coordinate definitions match within 20 mas the mean ones of the J2000.0
712 // equatorial system. Nevertheless, to obtain the highest accuracy, the slight
713 // coordinate correction between J2000 and ICRS is performed here via the
714 // so-called frame bias matrix.
715 // For further details see the U.S. Naval Observatory (USNO) circular 179 (2005),
716 // which is available on http://aa.usno,navy.mil/publications/docs/Circular_179.pdf.
717 //
718 // The coordinates (a,d) can represent so-called "mean" and "true" values.
719 // The distinction between these two representations is the following :
720 //
721 // mean values : (a,d) are only corrected for precession and not for nutation
722 // true values : (a,d) are corrected for both precession and nutation
723 //
724 // The input parameter "mode" allows the user to specifiy either "mean" or "true"
725 // values for the input (a,d) coordinates.
726 //
727 // a    : Right ascension in hhmmss.sss
728 // d    : Declination in dddmmss.sss
729 // s    = "B" --> Besselian reference epoch.
730 //        "J" --> Julian reference epoch.
731 // e    : Reference epoch for the input coordinates (e.g. 1900, 1950, 2000,...)
732 // mode = "M" --> Input coordinates are the mean values 
733 //        "T" --> Input coordinates are the true values 
734 //
735 // The input parameter "jref" allows the user to store so-called "reference" signals.
736 // These reference signals may be used to check space-time event coincidences with the
737 // stored measurement (e.g. coincidence of the measurement with transient phenomena).
738 //
739 // jref = 0 --> Storage of the measurement
740 //        j --> Storage of a reference signal at the j-th position (j=1 is first)
741 //      < 0 --> Add a reference signal at the next available position
742 //
743 // Via the input argument "name" the user can give the stored signal also a name.
744 //
745 // The default values are jref=0 and name="".
746
747  if (s!="B" && s!="b" && s!="J" && s!="j")
748  {
749   if (!jref && fXsig)
750   {
751    delete fXsig;
752    fXsig=0;
753   }
754   return;
755  }
756
757  if (mode!="M" && mode!="m" && mode!="T" && mode!="t")
758  {
759   if (!jref && fXsig)
760   {
761    delete fXsig;
762    fXsig=0;
763   }
764   return;
765  }
766
767  // Convert coordinates to fractional degrees.
768  a=ConvertAngle(a,"hms","deg");
769  d=ConvertAngle(d,"dms","deg");
770
771
772  AliTimestamp tx;
773  tx.SetEpoch(e,s);
774
775  Ali3Vector r;
776  Double_t vec[3]={1.,90.-d,a};
777  r.SetVector(vec,"sph","deg");
778
779  SetSignal(&r,"equ",mode,&tx,jref,name);
780 }
781 ///////////////////////////////////////////////////////////////////////////
782 void AliAstrolab::SetSignal(Double_t a,Double_t d,TString mode,AliTimestamp* ts,Int_t jref,TString name)
783 {
784 // Store a signal with right ascension (a) and declination (d) given for timestamp ts.
785 // The position is stored in International Celestial Reference System (ICRS) coordinates.
786 // The ICRS is a fixed, time independent frame and as such provides a unique reference
787 // frame without the need of specifying any epoch etc...
788 // The ICRS coordinate definitions match within 20 mas the mean ones of the J2000.0
789 // equatorial system. Nevertheless, to obtain the highest accuracy, the slight
790 // coordinate correction between J2000 and ICRS is performed here via the
791 // so-called frame bias matrix.
792 // For further details see the U.S. Naval Observatory (USNO) circular 179 (2005),
793 // which is available on http://aa.usno,navy.mil/publications/docs/Circular_179.pdf.
794 //
795 // The coordinates (a,d) can represent so-called "mean" and "true" values.
796 // The distinction between these two representations is the following :
797 //
798 // mean values : (a,d) are only corrected for precession and not for nutation
799 // true values : (a,d) are corrected for both precession and nutation
800 //
801 // The input parameter "mode" allows the user to specifiy either "mean" or "true"
802 // values for the input (a,d) coordinates.
803 //
804 // a    : Right ascension in hhmmss.sss
805 // d    : Declination in dddmmss.sss
806 // mode = "M" --> Input coordinates are the mean values 
807 //        "T" --> Input coordinates are the true values 
808 //
809 // The input parameter "jref" allows the user to store so-called "reference" signals.
810 // These reference signals may be used to check space-time event coincidences with the
811 // stored measurement (e.g. coincidence of the measurement with transient phenomena).
812 //
813 // jref = 0 --> Storage of the measurement
814 //        j --> Storage of a reference signal at the j-th position (j=1 is first)
815 //      < 0 --> Add a reference signal at the next available position
816 //
817 // Via the input argument "name" the user can give the stored signal also a name.
818 //
819 // The default values are jref=0 and name="".
820 //
821 // Note : In case ts=0 the current timestamp of the lab will be taken.
822
823  // Convert coordinates to fractional degrees.
824  a=ConvertAngle(a,"hms","deg");
825  d=ConvertAngle(d,"dms","deg");
826
827  Ali3Vector r;
828  Double_t vec[3]={1.,90.-d,a};
829  r.SetVector(vec,"sph","deg");
830
831  SetSignal(&r,"equ",mode,ts,jref,name);
832 }
833 ///////////////////////////////////////////////////////////////////////////
834 AliSignal* AliAstrolab::GetSignal(Ali3Vector& r,TString frame,TString mode,AliTimestamp* ts,Int_t jref)
835 {
836 // Provide the user specified coordinates of a signal at the specific timestamp ts.
837 // The coordinates are returned via the vector argument "r".
838 // In addition also a pointer to the stored signal object is provided.
839 // In case no stored signal was available or one of the input arguments was
840 // invalid, the returned pointer will be 0.
841 //
842 // The input parameter "frame" allows the user to specify the frame to which
843 // the components of r refer. Available options are :
844 //
845 //  frame = "equ" ==> Equatorial coordinates with right ascension (a) and declination (d),
846 //                    where the "sph" components of r correspond to theta=(pi/2)-d and phi=a.
847 //          "gal" ==> Galactic coordinates with longitude (l) and latitude (b).
848 //                    where the "sph" components of r correspond to theta=(pi/2)-b and phi=l.
849 //          "ecl" ==> Ecliptic coordinates with longitude (l) and latitude (b),
850 //                    where the "sph" components of r correspond to theta=(pi/2)-b and phi=l.
851 //          "hor" ==> Horizontal coordinates at the AliAstrolab location, where the "sph"
852 //                    components of r correspond to theta=zenith angle and phi=pi-azimuth.
853 //          "icr" ==> ICRS coordinates with longitude (l) and latitude (b),
854 //                    where the "sph" components of r correspond to theta=(pi/2)-b and phi=l.
855 //          "loc" ==> Local coordinates at the AliAstrolab location, where the "sph"
856 //                    components of r correspond to the usual theta and phi angles.
857 //
858 // In case the coordinates are the equatorial right ascension and declination (a,d),
859 // they can represent so-called "mean" and "true" values.
860 // The distinction between these two representations is the following :
861 //
862 // mean values : (a,d) are only corrected for precession and not for nutation
863 // true values : (a,d) are corrected for both precession and nutation
864 //
865 // The input parameter "mode" allows the user to specifiy either "mean" or "true"
866 // values for the input in case of equatorial (a,d) coordinates.
867 //
868 // mode = "M" --> Input coordinates are the mean values 
869 //        "T" --> Input coordinates are the true values 
870 //
871 // The input parameter "jref" allows the user to access so-called "reference" signals.
872 // These reference signals may be used to check space-time event coincidences with the
873 // stored measurement (e.g. coincidence of the measurement with transient phenomena).
874 //
875 // jref = 0 --> Access to the measurement
876 //        j --> Access to the reference signal at the j-th position (j=1 is first)
877 //
878 // Default value is jref=0.
879 //
880 // Note : In case ts=0 the current timestamp of the lab will be taken.
881
882  r.SetZero();
883
884  if (frame!="equ" && frame!="gal" && frame!="ecl" && frame!="hor" && frame!="icr" && frame!="loc") return 0;
885
886  if (frame=="equ" && mode!="M" && mode!="m" && mode!="T" && mode!="t") return 0;
887
888  AliSignal* sx=GetSignal(jref);
889
890  if (!sx) return 0;
891
892  if (!ts) ts=(AliTimestamp*)this;
893
894  Double_t vec[3];
895  sx->GetPosition(vec,"sph","rad");
896  Ali3Vector q;
897  q.SetVector(vec,"sph","rad");
898
899  if (frame=="icr")
900  {
901   r.Load(q);
902   return sx;
903  }
904
905  // Convert from ICRS to equatorial J2000 coordinates
906  if (!fBias) SetBmatrix();
907  q=q.GetPrimed(&fB);
908
909  if (frame=="equ")
910  {
911   // Precess to specified timestamp
912   AliTimestamp ts1;
913   ts1.SetEpoch(2000,"J");
914   Precess(q,&ts1,ts);
915
916   // Nutation correction if requested
917   if (mode=="T" || mode=="t") Nutate(q,ts);
918  }
919
920  if (frame=="gal")
921  {
922   // Convert from equatorial J2000 to galactic
923   if (fGal != 2) SetGmatrix("J");
924   q=q.GetPrimed(&fG);
925  }
926
927  if (frame=="ecl")
928  {
929   // Precess to specified timestamp
930   AliTimestamp ts1;
931   ts1.SetEpoch(2000,"J");
932   Precess(q,&ts1,ts);
933
934   // Convert from equatorial to ecliptic coordinates
935   SetEmatrix(ts);
936   q=q.GetPrimed(&fE);
937  }
938
939  if (frame=="hor")
940  {
941   // Precess to specified timestamp
942   AliTimestamp ts1;
943   ts1.SetEpoch(2000,"J");
944   Precess(q,&ts1,ts);
945
946   // Nutation correction
947   Nutate(q,ts);
948
949   // Convert from equatorial to horizontal coordinates
950   SetHmatrix(ts);
951   q=q.GetPrimed(&fH);
952  }
953
954  if (frame=="loc")
955  {
956   // Get the signal in horizontal coordinates
957   GetSignal(q,"hor",mode,ts);
958
959   // Convert from horizontal local-frame coordinates
960   q=q.GetPrimed(&fL);
961  }
962
963  r.Load(q);
964  return sx;
965 }
966 ///////////////////////////////////////////////////////////////////////////
967 AliSignal* AliAstrolab::GetSignal(Ali3Vector& r,TString frame,TString mode,AliTimestamp* ts,TString name)
968 {
969 // Provide the user specified coordinates of the signal with the specified
970 // name at the specific timestamp ts.
971 // The coordinates are returned via the vector argument "r".
972 // In addition also a pointer to the stored signal object is provided.
973 // In case no such stored signal was available or one of the input arguments was
974 // invalid, the returned pointer will be 0.
975 //
976 // The input parameter "frame" allows the user to specify the frame to which
977 // the components of r refer. Available options are :
978 //
979 //  frame = "equ" ==> Equatorial coordinates with right ascension (a) and declination (d),
980 //                    where the "sph" components of r correspond to theta=(pi/2)-d and phi=a.
981 //          "gal" ==> Galactic coordinates with longitude (l) and latitude (b).
982 //                    where the "sph" components of r correspond to theta=(pi/2)-b and phi=l.
983 //          "ecl" ==> Ecliptic coordinates with longitude (l) and latitude (b),
984 //                    where the "sph" components of r correspond to theta=(pi/2)-b and phi=l.
985 //          "hor" ==> Horizontal coordinates at the AliAstrolab location, where the "sph"
986 //                    components of r correspond to theta=zenith angle and phi=pi-azimuth.
987 //          "icr" ==> ICRS coordinates with longitude (l) and latitude (b),
988 //                    where the "sph" components of r correspond to theta=(pi/2)-b and phi=l.
989 //          "loc" ==> Local coordinates at the AliAstrolab location, where the "sph"
990 //                    components of r correspond to the usual theta and phi angles.
991 //
992 // In case the coordinates are the equatorial right ascension and declination (a,d),
993 // they can represent so-called "mean" and "true" values.
994 // The distinction between these two representations is the following :
995 //
996 // mean values : (a,d) are only corrected for precession and not for nutation
997 // true values : (a,d) are corrected for both precession and nutation
998 //
999 // The input parameter "mode" allows the user to specifiy either "mean" or "true"
1000 // values for the input in case of equatorial (a,d) coordinates.
1001 //
1002 // mode = "M" --> Input coordinates are the mean values 
1003 //        "T" --> Input coordinates are the true values 
1004 //
1005 // Note : In case ts=0 the current timestamp of the lab will be taken.
1006
1007  AliSignal* sx=0;
1008  Int_t j=GetSignalIndex(name);
1009  if (j>=0) sx=GetSignal(r,frame,mode,ts,j);
1010  return sx;
1011 }
1012 ///////////////////////////////////////////////////////////////////////////
1013 AliSignal* AliAstrolab::GetSignal(Double_t& a,Double_t& d,TString mode,AliTimestamp* ts,Int_t jref)
1014 {
1015 // Provide precession (and nutation) corrected right ascension (a) and
1016 // declination (d) of the stored signal object at the specified timestamp.
1017 // In addition also a pointer to the stored signal object is provided.
1018 // In case no stored signal was available or one of the input arguments was
1019 // invalid, the returned pointer will be 0.
1020 //
1021 // The coordinates (a,d) can represent so-called "mean" and "true" values.
1022 // The distinction between these two representations is the following :
1023 //
1024 // mean values : (a,d) are only corrected for precession and not for nutation
1025 // true values : (a,d) are corrected for both precession and nutation
1026 //
1027 // The input parameter "mode" allows the user to select either
1028 // "mean" or "true" values for (a,d).
1029 //
1030 // The correction methods used are the new IAU 2000 ones as described in the 
1031 // U.S. Naval Observatory (USNO) circular 179 (2005), which is available on
1032 // http://aa.usno,navy.mil/publications/docs/Circular_179.pdf.
1033 //
1034 // a    : Right ascension in hhmmss.sss
1035 // d    : Declination in dddmmss.sss
1036 // mode = "M" --> Output coordinates are the mean values 
1037 //        "T" --> Output coordinates are the true values 
1038 // ts   : Timestamp at which the corrected coordinate values are requested.
1039 //
1040 // The input parameter "jref" allows the user to access so-called "reference" signals.
1041 // These reference signals may be used to check space-time event coincidences with the
1042 // stored regular signal (e.g. coincidence of the stored signal with transient phenomena).
1043 //
1044 // jref = 0 --> Access to the measurement
1045 //        j --> Access to the reference signal at the j-th position (j=1 is first)
1046 //
1047 // Default value is jref=0.
1048 //
1049 // Note : In case ts=0 the current timestamp of the lab will be taken.
1050
1051  a=0;
1052  d=0;
1053
1054  Ali3Vector r;
1055  AliSignal* sx=GetSignal(r,"equ",mode,ts,jref);
1056
1057  if (!sx) return 0;
1058
1059  // Retrieve the requested (a,d) values
1060  Double_t vec[3];
1061  r.GetVector(vec,"sph","deg");
1062  d=90.-vec[1];
1063  a=vec[2];
1064
1065  while (a<-360.)
1066  {
1067   a+=360.;
1068  }
1069  while (a>360.)
1070  {
1071   a-=360.;
1072  }
1073  while (d<-90.)
1074  {
1075   d+=90.;
1076  }
1077  while (d>90.)
1078  {
1079   d-=90.;
1080  }
1081
1082  // Convert coordinates to appropriate format
1083  a=ConvertAngle(a,"deg","hms");
1084  d=ConvertAngle(d,"deg","dms");
1085
1086  return sx;
1087 }
1088 ///////////////////////////////////////////////////////////////////////////
1089 AliSignal* AliAstrolab::GetSignal(Double_t& a,Double_t& d,TString mode,AliTimestamp* ts,TString name)
1090 {
1091 // Provide precession (and nutation) corrected right ascension (a) and
1092 // declination (d) of the stored signal object with the specified name
1093 // at the specific timestamp ts.
1094 // In addition also a pointer to the stored signal object is provided.
1095 // In case no stored signal was available or one of the input arguments was
1096 // invalid, the returned pointer will be 0.
1097 //
1098 // The coordinates (a,d) can represent so-called "mean" and "true" values.
1099 // The distinction between these two representations is the following :
1100 //
1101 // mean values : (a,d) are only corrected for precession and not for nutation
1102 // true values : (a,d) are corrected for both precession and nutation
1103 //
1104 // The input parameter "mode" allows the user to select either
1105 // "mean" or "true" values for (a,d).
1106 //
1107 // The correction methods used are the new IAU 2000 ones as described in the 
1108 // U.S. Naval Observatory (USNO) circular 179 (2005), which is available on
1109 // http://aa.usno,navy.mil/publications/docs/Circular_179.pdf.
1110 //
1111 // a    : Right ascension in hhmmss.sss
1112 // d    : Declination in dddmmss.sss
1113 // mode = "M" --> Output coordinates are the mean values 
1114 //        "T" --> Output coordinates are the true values 
1115 // ts   : Timestamp at which the corrected coordinate values are requested.
1116 // name : Name of the requested signal object
1117 //
1118 // Note : In case ts=0 the current timestamp of the lab will be taken.
1119
1120  AliSignal* sx=0;
1121  Int_t j=GetSignalIndex(name);
1122  if (j>=0) sx=GetSignal(a,d,mode,ts,j);
1123  return sx;
1124 }
1125 ///////////////////////////////////////////////////////////////////////////
1126 AliSignal* AliAstrolab::GetSignal(Double_t& a,Double_t& d,TString s,Double_t e,TString mode,Int_t jref)
1127 {
1128 // Provide precession (and nutation) corrected right ascension (a) and
1129 // declination (d) of the stored signal object at the specified epoch e.
1130 // In addition also a pointer to the stored signal object is provided.
1131 // In case no stored signal was available or one of the input arguments was
1132 // invalid, the returned pointer will be 0.
1133 //
1134 // The coordinates (a,d) can represent so-called "mean" and "true" values.
1135 // The distinction between these two representations is the following :
1136 //
1137 // mean values : (a,d) are only corrected for precession and not for nutation
1138 // true values : (a,d) are corrected for both precession and nutation
1139 //
1140 // The input parameter "mode" allows the user to specifiy either "mean" or "true"
1141 // values for the input (a,d) coordinates.
1142 //
1143 // a    : Right ascension in hhmmss.sss
1144 // d    : Declination in dddmmss.sss
1145 // s    = "B" --> Besselian reference epoch.
1146 //        "J" --> Julian reference epoch.
1147 // e    : Reference epoch for the input coordinates (e.g. 1900, 1950, 2000,...)
1148 // mode = "M" --> Input coordinates are the mean values 
1149 //        "T" --> Input coordinates are the true values 
1150 //
1151 // The input parameter "jref" allows the user to access so-called "reference" signals.
1152 // These reference signals may be used to check space-time event coincidences with the
1153 // stored measurement (e.g. coincidence of the measurement with transient phenomena).
1154 //
1155 // jref = 0 --> Access to the measurement
1156 //        j --> Access to the reference signal at the j-th position (j=1 is first)
1157 //
1158 // Default value is jref=0.
1159
1160  a=0;
1161  d=0;
1162
1163  if (s!="B" && s!="b" && s!="J" && s!="j") return 0;
1164
1165  if (mode!="M" && mode!="m" && mode!="T" && mode!="t") return 0;
1166
1167  // Convert coordinates to fractional degrees.
1168  a=ConvertAngle(a,"hms","deg");
1169  d=ConvertAngle(d,"dms","deg");
1170
1171
1172  AliTimestamp tx;
1173  tx.SetEpoch(e,s);
1174
1175  AliSignal* sx=GetSignal(a,d,mode,&tx,jref);
1176  return sx;
1177 }
1178 ///////////////////////////////////////////////////////////////////////////
1179 AliSignal* AliAstrolab::GetSignal(Double_t& a,Double_t& d,TString s,Double_t e,TString mode,TString name)
1180 {
1181 // Provide precession (and nutation) corrected right ascension (a) and
1182 // declination (d) of the stored signal object with the specified name
1183 // at the specific epoch e.
1184 // In addition also a pointer to the stored signal object is provided.
1185 // In case no stored signal was available or one of the input arguments was
1186 // invalid, the returned pointer will be 0.
1187 //
1188 // The coordinates (a,d) can represent so-called "mean" and "true" values.
1189 // The distinction between these two representations is the following :
1190 //
1191 // mean values : (a,d) are only corrected for precession and not for nutation
1192 // true values : (a,d) are corrected for both precession and nutation
1193 //
1194 // The input parameter "mode" allows the user to specifiy either "mean" or "true"
1195 // values for the input (a,d) coordinates.
1196 //
1197 // a    : Right ascension in hhmmss.sss
1198 // d    : Declination in dddmmss.sss
1199 // s    = "B" --> Besselian reference epoch.
1200 //        "J" --> Julian reference epoch.
1201 // e    : Reference epoch for the input coordinates (e.g. 1900, 1950, 2000,...)
1202 // mode = "M" --> Input coordinates are the mean values 
1203 //        "T" --> Input coordinates are the true values 
1204 // name : Name of the requested signal object
1205
1206  AliSignal* sx=0;
1207  Int_t j=GetSignalIndex(name);
1208  if (j>=0) sx=GetSignal(a,d,s,e,mode,j);
1209  return sx;
1210 }
1211 ///////////////////////////////////////////////////////////////////////////
1212 AliSignal* AliAstrolab::GetSignal(Int_t jref)
1213 {
1214 // Provide the pointer to a stored signal object.
1215 //
1216 // The input parameter "jref" allows the user to access so-called "reference" signals.
1217 // These reference signals may be used to check space-time event coincidences with the
1218 // stored measurement (e.g. coincidence of the measurement with transient phenomena).
1219 //
1220 // jref = 0 --> Access to the measurement
1221 //        j --> Access to the reference signal at the j-th position (j=1 is first)
1222 //
1223 // Default value is jref=0.
1224
1225  AliSignal* sx=0;
1226  if (!jref)
1227  {
1228   sx=fXsig;
1229  }
1230  else
1231  {
1232   if (jref>0 && jref<fRefs->GetSize()) sx=(AliSignal*)fRefs->At(jref-1);
1233  }
1234  return sx;
1235 }
1236 ///////////////////////////////////////////////////////////////////////////
1237 AliSignal* AliAstrolab::GetSignal(TString name)
1238 {
1239 // Provide the pointer to the stored signal object with the specified name.
1240
1241  AliSignal* sx=0;
1242  Int_t j=GetSignalIndex(name);
1243  if (j>=0) sx=GetSignal(j);
1244  return sx;
1245 }
1246 ///////////////////////////////////////////////////////////////////////////
1247 void AliAstrolab::RemoveRefSignal(Int_t j,Int_t compress)
1248 {
1249 // Remove the reference signal which was stored at the j-th position (j=1 is first).
1250 // Note : j=0 means that all stored reference signals will be removed.
1251 //        j<0 allows array compression (see below) without removing any signals. 
1252 //
1253 // The "compress" parameter allows compression of the ref. signal storage array.
1254 //
1255 // compress = 1 --> Array will be compressed
1256 //            0 --> Array will not be compressed
1257 //
1258 // Note : Compression of the storage array means that the indices of the
1259 //        reference signals in the storage array will change.
1260
1261  if (!fRefs) return;
1262
1263  // Clearing of the complete storage
1264  if (!j)
1265  {
1266   delete fRefs;
1267   fRefs=0;
1268   return;
1269  }
1270
1271  // Removing a specific reference signal
1272  if (j>0 && j<fRefs->GetSize())
1273  {
1274   TObject* obj=fRefs->RemoveAt(j-1);
1275   if (obj) delete obj;
1276  }
1277
1278  // Compression of the storage array
1279  if (compress) fRefs->Compress();
1280 }
1281 ///////////////////////////////////////////////////////////////////////////
1282 void AliAstrolab::RemoveRefSignal(TString name,Int_t compress)
1283 {
1284 // Remove the reference signal with the specified name.
1285 //
1286 // The "compress" parameter allows compression of the ref. signal storage array.
1287 //
1288 // compress = 1 --> Array will be compressed
1289 //            0 --> Array will not be compressed
1290 //
1291 // Note : Compression of the storage array means that the indices of the
1292 //        reference signals in the storage array will change.
1293
1294  Int_t j=GetSignalIndex(name);
1295  if (j>0) RemoveRefSignal(j,compress);
1296 }
1297 ///////////////////////////////////////////////////////////////////////////
1298 Int_t AliAstrolab::GetSignalIndex(TString name)
1299 {
1300 // Provide storage index of the signal with the specified name.
1301 // In case the name matches with the stored measurement,
1302 // the value 0 is returned.
1303 // In case no signal with the specified name was found, the value -1 is returned.
1304
1305  Int_t index=-1;
1306  
1307  if (fXsig)
1308  {
1309   if (name==fXsig->GetName()) return 0;
1310  }
1311
1312  if (!fRefs) return -1;
1313
1314  for (Int_t i=0; i<fRefs->GetSize(); i++)
1315  {
1316   AliSignal* sx=(AliSignal*)fRefs->At(i);
1317   if (!sx) continue;
1318
1319   if (name==sx->GetName())
1320   {
1321    index=i+1;
1322    break;
1323   }
1324  }
1325
1326  return index;
1327 }
1328 ///////////////////////////////////////////////////////////////////////////
1329 void AliAstrolab::PrintSignal(TString frame,TString mode,AliTimestamp* ts,Int_t ndig,Int_t jref)
1330 {
1331 // Print data of a stored signal in user specified coordinates at the specific timestamp ts.
1332 // In case no stored signal was available or one of the input arguments was
1333 // invalid, no printout is produced.
1334 //
1335 // The argument "ndig" specifies the number of digits for the fractional
1336 // part (e.g. ndig=6 for "dms" corresponds to micro-arcsecond precision).
1337 // No rounding will be performed, so an arcsecond count of 3.473 with ndig=1
1338 // will appear as 03.4 on the output.
1339 // Due to computer accuracy, precision on the pico-arcsecond level may get lost.
1340 //
1341 // Note : The angle info is printed without additional spaces or "endline".
1342 //        This allows the print to be included in various composite output formats.
1343 //
1344 // The input parameter "frame" allows the user to specify the frame to which
1345 // the coordinates refer. Available options are :
1346 //
1347 //  frame = "equ" ==> Equatorial coordinates with right ascension (a) and declination (d).
1348 //
1349 //          "gal" ==> Galactic coordinates with longitude (l) and latitude (b).
1350 //
1351 //          "ecl" ==> Ecliptic coordinates with longitude (l) and latitude (b).
1352 //
1353 //          "hor" ==> Horizontal azimuth and altitude coordinates at the AliAstrolab location.
1354 //
1355 //          "icr" ==> ICRS coordinates with longitude (l) and latitude (b).
1356 //
1357 //          "loc" ==> Local spherical angles theta and phi at the AliAstrolab location.
1358 //
1359 // In case the coordinates are the equatorial right ascension and declination (a,d),
1360 // they can represent so-called "mean" and "true" values.
1361 // The distinction between these two representations is the following :
1362 //
1363 // mean values : (a,d) are only corrected for precession and not for nutation
1364 // true values : (a,d) are corrected for both precession and nutation
1365 //
1366 // The input parameter "mode" allows the user to specifiy either "mean" or "true"
1367 // values for the input in case of equatorial (a,d) coordinates.
1368 //
1369 // mode = "M" --> Input coordinates are the mean values 
1370 //        "T" --> Input coordinates are the true values 
1371 //
1372 // The input parameter "mode" also determines which type of time and
1373 // local hour angle will appear in the printout.
1374 //
1375 // mode = "M" --> Mean Sidereal Time (MST) and Local Mean Hour Angle (LMHA)
1376 //        "T" --> Apparent Sidereal Time (AST) and Local Apparent Hour Angle (LAHA)
1377 //
1378 // The input parameter "jref" allows printing of a so-called "reference" signal.
1379 // These reference signals may serve to check space-time event coincidences with the
1380 // stored measurement (e.g. coincidence of the measurement with transient phenomena).
1381 //
1382 // jref = 0 --> Printing of the measurement
1383 //        j --> Printing of the j-th reference signal
1384 //
1385 // Default value is jref=0.
1386 //
1387 // Note : In case ts=0 the current timestamp of the lab will be taken.
1388
1389  Ali3Vector r;
1390  AliSignal* sx=GetSignal(r,frame,mode,ts,jref);
1391
1392  if (!sx) return;
1393
1394  // Local Hour Angle of the signal
1395  Double_t lha=GetHourAngle("A",ts,jref);
1396  TString slha="LAHA";
1397  if (mode=="M" || mode=="m")
1398  {
1399   lha=GetHourAngle("M",ts,jref);
1400   slha="LMHA";
1401  }
1402
1403  TString name=sx->GetName();
1404  if (name != "") cout << name.Data() << " ";
1405
1406  if (frame=="equ")
1407  {
1408   Double_t a,d;
1409   d=90.-r.GetX(2,"sph","deg");
1410   a=r.GetX(3,"sph","rad");
1411   cout << "Equatorial (" << mode.Data() <<") a : "; PrintAngle(a,"rad","hms",ndig);
1412   cout << " d : "; PrintAngle(d,"deg","dms",ndig);
1413   cout << " " << slha.Data() << " : "; PrintAngle(lha,"deg","hms",ndig);
1414   return;
1415  }
1416
1417  if (frame=="gal")
1418  {
1419   Double_t l,b;
1420   b=90.-r.GetX(2,"sph","deg");
1421   l=r.GetX(3,"sph","deg");
1422   cout << "Galactic l : "; PrintAngle(l,"deg","deg",ndig);
1423   cout << " b : "; PrintAngle(b,"deg","deg",ndig); 
1424   cout << " " << slha.Data() << " : "; PrintAngle(lha,"deg","hms",ndig);
1425   return;
1426  }
1427
1428  if (frame=="icr")
1429  {
1430   Double_t a,d;
1431   d=90.-r.GetX(2,"sph","deg");
1432   a=r.GetX(3,"sph","rad");
1433   cout << "ICRS l : "; PrintAngle(a,"rad","hms",ndig);
1434   cout << " b : "; PrintAngle(d,"deg","dms",ndig);
1435   cout << " " << slha.Data() << " : "; PrintAngle(lha,"deg","hms",ndig);
1436   return;
1437  }
1438
1439  if (frame=="ecl")
1440  {
1441   Double_t a,d;
1442   d=90.-r.GetX(2,"sph","deg");
1443   a=r.GetX(3,"sph","deg");
1444   cout << "Ecliptic l : "; PrintAngle(a,"deg","deg",ndig);
1445   cout << " b : "; PrintAngle(d,"deg","deg",ndig);
1446   cout << " " << slha.Data() << " : "; PrintAngle(lha,"deg","hms",ndig);
1447   return;
1448  }
1449
1450  if (frame=="hor")
1451  {
1452   Double_t alt=90.-r.GetX(2,"sph","deg");
1453   Double_t azi=180.-r.GetX(3,"sph","deg");
1454   while (azi>360)
1455   {
1456    azi-=360.;
1457   }
1458   while (azi<0)
1459   {
1460    azi+=360.;
1461   }
1462   cout << "Horizontal azi : "; PrintAngle(azi,"deg","deg",ndig);
1463   cout << " alt : "; PrintAngle(alt,"deg","deg",ndig);
1464   cout << " " << slha.Data() << " : "; PrintAngle(lha,"deg","hms",ndig);
1465   return;
1466  }
1467
1468  if (frame=="loc")
1469  {
1470   Double_t theta=r.GetX(2,"sph","deg");
1471   Double_t phi=r.GetX(3,"sph","deg");
1472   cout << "Local-frame phi : "; PrintAngle(phi,"deg","deg",ndig);
1473   cout << " theta : "; PrintAngle(theta,"deg","deg",ndig);
1474   cout << " " << slha.Data() << " : "; PrintAngle(lha,"deg","hms",ndig);
1475   return;
1476  }
1477 }
1478 ///////////////////////////////////////////////////////////////////////////
1479 void AliAstrolab::PrintSignal(TString frame,TString mode,AliTimestamp* ts,Int_t ndig,TString name)
1480 {
1481 // Print data of the stored signal with the specified name in user specified coordinates
1482 // at the specific timestamp ts.
1483 // In case no such stored signal was available or one of the input arguments was
1484 // invalid, no printout is produced.
1485 //
1486 // The argument "ndig" specifies the number of digits for the fractional
1487 // part (e.g. ndig=6 for "dms" corresponds to micro-arcsecond precision).
1488 // No rounding will be performed, so an arcsecond count of 3.473 with ndig=1
1489 // will appear as 03.4 on the output.
1490 // Due to computer accuracy, precision on the pico-arcsecond level may get lost.
1491 //
1492 // Note : The angle info is printed without additional spaces or "endline".
1493 //        This allows the print to be included in various composite output formats.
1494 //
1495 // The input parameter "frame" allows the user to specify the frame to which
1496 // the coordinates refer. Available options are :
1497 //
1498 //  frame = "equ" ==> Equatorial coordinates with right ascension (a) and declination (d).
1499 //
1500 //          "gal" ==> Galactic coordinates with longitude (l) and latitude (b).
1501 //
1502 //          "ecl" ==> Ecliptic coordinates with longitude (l) and latitude (b).
1503 //
1504 //          "hor" ==> Horizontal azimuth and altitude coordinates at the AliAstrolab location.
1505 //
1506 //          "icr" ==> ICRS coordinates with longitude (l) and latitude (b).
1507 //
1508 //          "loc" ==> Local spherical angles theta and phi at the AliAstrolab location.
1509 //
1510 // In case the coordinates are the equatorial right ascension and declination (a,d),
1511 // they can represent so-called "mean" and "true" values.
1512 // The distinction between these two representations is the following :
1513 //
1514 // mean values : (a,d) are only corrected for precession and not for nutation
1515 // true values : (a,d) are corrected for both precession and nutation
1516 //
1517 // The input parameter "mode" allows the user to specifiy either "mean" or "true"
1518 // values for the input in case of equatorial (a,d) coordinates.
1519 //
1520 // mode = "M" --> Input coordinates are the mean values 
1521 //        "T" --> Input coordinates are the true values 
1522 //
1523 // The input parameter "mode" also determines which type of time and
1524 // local hour angle will appear in the printout.
1525 //
1526 // mode = "M" --> Mean Sidereal Time (MST) and Local Mean Hour Angle (LMHA)
1527 //        "T" --> Apparent Sidereal Time (AST) and Local Apparent Hour Angle (LAHA)
1528 //
1529 // Note : In case ts=0 the current timestamp of the lab will be taken.
1530
1531  Int_t j=GetSignalIndex(name);
1532  if (j>=0) PrintSignal(frame,mode,ts,ndig,j);
1533 }
1534 ///////////////////////////////////////////////////////////////////////////
1535 void AliAstrolab::ListSignals(TString frame,TString mode,Int_t ndig)
1536 {
1537 // List all stored signals in user specified coordinates at the timestamp
1538 // of the actual recording of the stored measurement under investigation.
1539 // In case no (timestamp of the) actual measurement is available,
1540 // the current timestamp of the lab will be taken.
1541 // In case no stored signal is available or one of the input arguments is
1542 // invalid, no printout is produced.
1543 //
1544 // The argument "ndig" specifies the number of digits for the fractional
1545 // part (e.g. ndig=6 for "dms" corresponds to micro-arcsecond precision).
1546 // No rounding will be performed, so an arcsecond count of 3.473 with ndig=1
1547 // will appear as 03.4 on the output.
1548 // Due to computer accuracy, precision on the pico-arcsecond level may get lost.
1549 //
1550 // The default value is ndig=1.
1551 //
1552 // Note : The angle info is printed without additional spaces or "endline".
1553 //        This allows the print to be included in various composite output formats.
1554 //
1555 // The input parameter "frame" allows the user to specify the frame to which
1556 // the coordinates refer. Available options are :
1557 //
1558 //  frame = "equ" ==> Equatorial coordinates with right ascension (a) and declination (d).
1559 //
1560 //          "gal" ==> Galactic coordinates with longitude (l) and latitude (b).
1561 //
1562 //          "ecl" ==> Ecliptic coordinates with longitude (l) and latitude (b).
1563 //
1564 //          "hor" ==> Horizontal azimuth and altitude coordinates at the AliAstrolab location.
1565 //
1566 //          "icr" ==> ICRS coordinates with longitude (l) and latitude (b).
1567 //
1568 //          "loc" ==> Local spherical angles theta and phi at the AliAstrolab location.
1569 //
1570 // In case the coordinates are the equatorial right ascension and declination (a,d),
1571 // they can represent so-called "mean" and "true" values.
1572 // The distinction between these two representations is the following :
1573 //
1574 // mean values : (a,d) are only corrected for precession and not for nutation
1575 // true values : (a,d) are corrected for both precession and nutation
1576 //
1577 // The input parameter "mode" allows the user to specifiy either "mean" or "true"
1578 // values for the input in case of equatorial (a,d) coordinates.
1579 //
1580 // mode = "M" --> Input coordinates are the mean values 
1581 //        "T" --> Input coordinates are the true values 
1582 //
1583 // The input parameter "mode" also determines which type of time and
1584 // local hour angle will appear in the listing.
1585 //
1586 // mode = "M" --> Mean Sidereal Time (MST) and Local Mean Hour Angle (LMHA)
1587 //        "T" --> Apparent Sidereal Time (AST) and Local Apparent Hour Angle (LAHA)
1588
1589  Int_t iprint=0;
1590
1591  AliTimestamp* tx=0;
1592
1593  Int_t dform=1;
1594  if (mode=="T" || mode=="t") dform=-1;
1595
1596  if (fXsig)
1597  {
1598   tx=fXsig->GetTimestamp();
1599   if (!tx) tx=(AliTimestamp*)this;
1600   cout << " *AliAstrolab::ListSignals* List of all stored signals." << endl;
1601   cout << " === The measurement under investigation ===" << endl;
1602   cout << " Timestamp of the actual observation" << endl;
1603   tx->Date(dform,fToffset);
1604   cout << " Location of the actual observation" << endl;
1605   cout << " "; PrintSignal(frame,mode,tx,ndig); cout << endl;
1606   iprint=1;
1607  }
1608
1609  if (!fRefs) return;
1610
1611  for (Int_t i=1; i<=fRefs->GetSize(); i++)
1612  {
1613   AliSignal* sx=GetSignal(i);
1614   if (!sx) continue;
1615
1616   if (!iprint)
1617   {
1618    cout << " *AliAstrolab::ListRefSignals* List of all stored signals." << endl;
1619    tx=(AliTimestamp*)this;
1620    cout << " Current timestamp of the laboratory" << endl;
1621    tx->Date(dform,fToffset);
1622    iprint=1;
1623   }
1624   if (iprint==1)
1625   {
1626    cout << " === All stored reference signals according to the above timestamp ===" << endl;
1627    iprint=2;
1628   }
1629   cout << " Index : " << i << " "; PrintSignal(frame,mode,tx,ndig,i); cout << endl;
1630  }
1631 }
1632 ///////////////////////////////////////////////////////////////////////////
1633 void AliAstrolab::Precess(Ali3Vector& r,AliTimestamp* ts1,AliTimestamp* ts2)
1634 {
1635 // Correct mean right ascension and declination given for Julian date "jd"
1636 // for the earth's precession corresponding to the specified timestamp.
1637 // The results are the so-called "mean" (i.e. precession corrected) values,
1638 // corresponding to the specified timestamp.
1639 // The method used is the new IAU 2000 one as described in the 
1640 // U.S. Naval Observatory (USNO) circular 179 (2005), which is available on
1641 // http://aa.usno,navy.mil/publications/docs/Circular_179.pdf.
1642 // Since the standard reference epoch is J2000, this implies that all
1643 // input (a,d) coordinates will be first internally converted to the
1644 // corresponding J2000 values before the precession correction w.r.t. the
1645 // specified lab timestamp will be applied.
1646 //
1647 // r  : Input vector containing the right ascension and declination information
1648 //      in the form of standard Ali3Vector coordinates.
1649 //      In spherical coordinates the phi corresponds to the right ascension,
1650 //      whereas the declination corresponds to (pi/2)-theta.
1651 // jd : Julian date corresponding to the input coordinate values.
1652 // ts : Timestamp corresponding to the requested corrected coordinate values.
1653 //
1654 // Note : In case ts=0 the current timestamp of the lab will be taken.
1655
1656  // Convert back to J2000 values
1657  Ali3Vector r0;
1658  SetPmatrix(ts1);
1659  r0=r.GetUnprimed(&fP);
1660
1661  // Precess to the specified timestamp
1662  if (!ts2) ts2=(AliTimestamp*)this;
1663  SetPmatrix(ts2);
1664  r=r0.GetPrimed(&fP);
1665 }
1666 ///////////////////////////////////////////////////////////////////////////
1667 void AliAstrolab::Nutate(Ali3Vector& r,AliTimestamp* ts)
1668 {
1669 // Correct mean right ascension and declination for the earth's nutation
1670 // corresponding to the specified timestamp.
1671 // The results are the so-called "true" (i.e. nutation corrected) values,
1672 // corresponding to the specified timestamp.
1673 // The method used is the new IAU 2000 one as described in the 
1674 // U.S. Naval Observatory (USNO) circular 179 (2005), which is available on
1675 // http://aa.usno,navy.mil/publications/docs/Circular_179.pdf.
1676 //
1677 // r  : Input vector containing the right ascension and declination information
1678 //      in the form of standard Ali3Vector coordinates.
1679 //      In spherical coordinates the phi corresponds to the right ascension,
1680 //      whereas the declination corresponds to (pi/2)-theta.
1681 // ts : Timestamp for which the corrected coordinate values are requested.
1682 //
1683 // Note : In case ts=0 the current timestamp of the lab will be taken.
1684
1685  // Nutation correction for the specified timestamp
1686  if (!ts) ts=(AliTimestamp*)this;
1687  SetNmatrix(ts);
1688  r=r.GetPrimed(&fN);
1689 }
1690 ///////////////////////////////////////////////////////////////////////////
1691 void AliAstrolab::SetBmatrix()
1692 {
1693 // Set the frame bias matrix elements.
1694 // The formulas and numerical constants used are the ones from the 
1695 // U.S. Naval Observatory (USNO) circular 179 (2005), which is available on
1696 // http://aa.usno,navy.mil/publications/docs/Circular_179.pdf.
1697
1698  Double_t pi=acos(-1.);
1699  
1700  // Parameters in mas
1701  Double_t a=-14.6;
1702  Double_t x=-16.6170;
1703  Double_t e=-6.8192;
1704
1705  // Convert to radians
1706  a*=pi/(180.*3600.*1000.);
1707  x*=pi/(180.*3600.*1000.);
1708  e*=pi/(180.*3600.*1000.);
1709
1710  Double_t mat[9];
1711  mat[0]=1.-0.5*(a*a+x*x);
1712  mat[1]=a;
1713  mat[2]=-x;
1714  mat[3]=-a-e*x;
1715  mat[4]=1.-0.5*(a*a+e*e);
1716  mat[5]=-e;
1717  mat[6]=x-e*a;
1718  mat[7]=e+x*a;
1719  mat[8]=1.-0.5*(e*e+x*x);
1720
1721  fB.SetMatrix(mat);
1722  fBias=1;
1723 }
1724 ///////////////////////////////////////////////////////////////////////////
1725 void AliAstrolab::SetPmatrix(AliTimestamp* ts)
1726 {
1727 // Set precession matrix elements for Julian date jd w.r.t. J2000.
1728 // The formulas and numerical constants used are the ones from the 
1729 // U.S. Naval Observatory (USNO) circular 179 (2005), which is available on
1730 // http://aa.usno,navy.mil/publications/docs/Circular_179.pdf.
1731 // All numerical constants refer to the standard reference epoch J2000.
1732
1733  Double_t mat[9]={0,0,0,0,0,0,0,0,0};
1734  if (!ts)
1735  {
1736   fP.SetMatrix(mat);
1737   return;
1738  }
1739
1740  Double_t pi=acos(-1.);
1741
1742  Double_t t=(ts->GetJD()-2451545.0)/36525.; // Julian centuries since J2000.0
1743
1744  // Parameters for the precession matrix in arcseconds
1745  Double_t eps0=84381.406; // Mean ecliptic obliquity at J2000.0
1746  Double_t psi=5038.481507*t-1.0790069*pow(t,2)-0.00114045*pow(t,3)+0.000132851*pow(t,4)
1747                 -0.0000000951*pow(t,4);
1748  Double_t om=eps0-0.025754*t+0.0512623*pow(t,2)-0.00772503*pow(t,3)-0.000000467*pow(t,4)
1749                  +0.0000003337*pow(t,5);
1750  Double_t chi=10.556403*t-2.3814292*pow(t,2)-0.00121197*pow(t,3)+0.000170663*pow(t,4)
1751               -0.0000000560*pow(t,5);
1752
1753  // Convert to radians
1754  eps0*=pi/(180.*3600.);
1755  psi*=pi/(180.*3600.);
1756  om*=pi/(180.*3600.);
1757  chi*=pi/(180.*3600.);
1758
1759  Double_t s1=sin(eps0);
1760  Double_t s2=sin(-psi);
1761  Double_t s3=sin(-om);
1762  Double_t s4=sin(chi);
1763  Double_t c1=cos(eps0);
1764  Double_t c2=cos(-psi);
1765  Double_t c3=cos(-om);
1766  Double_t c4=cos(chi);
1767
1768  mat[0]=c4*c2-s2*s4*c3;
1769  mat[1]=c4*s2*c1+s4*c3*c2*c1-s1*s4*s3;
1770  mat[2]=c4*s2*s1+s4*c3*c2*s1+c1*s4*s3;
1771  mat[3]=-s4*c2-s2*c4*c3;
1772  mat[4]=-s4*s2*c1+c4*c3*c2*c1-s1*c4*s3;
1773  mat[5]=-s4*s2*s1+c4*c3*c2*s1+c1*c4*s3;
1774  mat[6]=s2*s3;
1775  mat[7]=-s3*c2*c1-s1*c3;
1776  mat[8]=-s3*c2*s1+c3*c1;
1777
1778  fP.SetMatrix(mat);
1779 }
1780 ///////////////////////////////////////////////////////////////////////////
1781 void AliAstrolab::SetNmatrix(AliTimestamp* ts)
1782 {
1783 // Set nutation matrix elements for the specified Julian date jd.
1784 // The formulas and numerical constants used are the ones from the 
1785 // U.S. Naval Observatory (USNO) circular 179 (2005), which is available on
1786 // http://aa.usno,navy.mil/publications/docs/Circular_179.pdf.
1787
1788  Double_t mat[9]={0,0,0,0,0,0,0,0,0};
1789  if (!ts)
1790  {
1791   fN.SetMatrix(mat);
1792   return;
1793  }
1794
1795  Double_t pi=acos(-1.);
1796  
1797  Double_t dpsi,deps,eps;
1798  ts->Almanac(&dpsi,&deps,&eps);
1799
1800  // Convert to radians
1801  dpsi*=pi/(180.*3600.);
1802  deps*=pi/(180.*3600.);
1803  eps*=pi/(180.*3600.);
1804
1805  Double_t s1=sin(eps);
1806  Double_t s2=sin(-dpsi);
1807  Double_t s3=sin(-(eps+deps));
1808  Double_t c1=cos(eps);
1809  Double_t c2=cos(-dpsi);
1810  Double_t c3=cos(-(eps+deps));
1811
1812  mat[0]=c2;
1813  mat[1]=s2*c1;
1814  mat[2]=s2*s1;
1815  mat[3]=-s2*c3;
1816  mat[4]=c3*c2*c1-s1*s3;
1817  mat[5]=c3*c2*s1+c1*s3;
1818  mat[6]=s2*s3;
1819  mat[7]=-s3*c2*c1-s1*c3;
1820  mat[8]=-s3*c2*s1+c3*c1;
1821
1822  fN.SetMatrix(mat);
1823 }
1824 ///////////////////////////////////////////////////////////////////////////
1825 void AliAstrolab::SetGmatrix(TString mode)
1826 {
1827 // Set the mean equatorial to galactic coordinate conversion matrix.
1828 // The B1950 parameters were taken from section 22.3 of the book
1829 // "An Introduction to Modern Astrophysics" by Carrol and Ostlie (1996).
1830 // The J2000 parameters are obtained by precession of the B1950 values.
1831 //
1832 // Via the input argument "mode" the required epoch can be selected
1833 // mode = "B" ==> B1950
1834 //        "J" ==> J2000
1835
1836  Ali3Vector x; // The Galactic x-axis in the equatorial frame
1837  Ali3Vector y; // The Galactic y-axis in the equatorial frame
1838  Ali3Vector z; // The Galactic z-axis in the equatorial frame
1839
1840  Double_t a,d;
1841  Double_t vec[3]={1,0,0};
1842
1843  fGal=1; // Set flag to indicate B1950 matrix values
1844
1845  // B1950 equatorial coordinates of the North Galactic Pole (NGP)
1846  a=124900.;
1847  d=272400.;
1848  a=ConvertAngle(a,"hms","deg");
1849  d=ConvertAngle(d,"dms","deg");
1850  vec[1]=90.-d;
1851  vec[2]=a;
1852  z.SetVector(vec,"sph","deg");
1853
1854  // B1950 equatorial coordinates of the Galactic l=b=0 point
1855  a=174224.;
1856  d=-285500.;
1857  a=ConvertAngle(a,"hms","deg");
1858  d=ConvertAngle(d,"dms","deg");
1859  vec[1]=90.-d;
1860  vec[2]=a;
1861  x.SetVector(vec,"sph","deg");
1862
1863  // Precess to the corresponding J2000 values if requested
1864  if (mode=="J")
1865  {
1866   fGal=2; // Set flag to indicate J2000 matrix values
1867   AliTimestamp t1;
1868   t1.SetEpoch(1950,"B");
1869   AliTimestamp t2;
1870   t2.SetEpoch(2000,"J");
1871   Precess(z,&t1,&t2);
1872   Precess(x,&t1,&t2);
1873  }
1874
1875  // The Galactic y-axis is determined for the right handed frame
1876  y=z.Cross(x);
1877
1878  fG.SetAngles(x.GetX(2,"sph","deg"),x.GetX(3,"sph","deg"),
1879               y.GetX(2,"sph","deg"),y.GetX(3,"sph","deg"),
1880               z.GetX(2,"sph","deg"),z.GetX(3,"sph","deg"));
1881 }
1882 ///////////////////////////////////////////////////////////////////////////
1883 void AliAstrolab::SetEmatrix(AliTimestamp* ts)
1884 {
1885 // Set the mean equatorial to ecliptic coordinate conversion matrix
1886 // for the specified timestamp.
1887 // A nice sketch and explanation of the two frames can be found
1888 // in chapter 3 of the book "Astronomy Methods" by Hale Bradt (2004).
1889
1890  Double_t dpsi,deps,eps;
1891  ts->Almanac(&dpsi,&deps,&eps);
1892
1893  // Convert to degrees
1894  eps/=3600.;
1895
1896  // Positions of the ecliptic axes w.r.t. the equatorial ones
1897  // at the moment of the specified timestamp 
1898  Double_t theta1=90; // Ecliptic x-axis
1899  Double_t phi1=0;
1900  Double_t theta2=90.-eps; //Ecliptic y-axis
1901  Double_t phi2=90;
1902  Double_t theta3=eps; // Ecliptic z-axis
1903  Double_t phi3=270;
1904
1905  fE.SetAngles(theta1,phi1,theta2,phi2,theta3,phi3);
1906 }
1907 ///////////////////////////////////////////////////////////////////////////
1908 void AliAstrolab::SetHmatrix(AliTimestamp* ts)
1909 {
1910 // Set the mean equatorial to horizontal coordinate conversion matrix
1911 // for the specified timestamp.
1912 // A nice sketch and explanation of the two frames can be found
1913 // in chapter 3 of the book "Astronomy Methods" by Hale Bradt (2004).
1914 //
1915 // Note : In order to simplify the calculations, we use here a
1916 //        right-handed horizontal frame.
1917
1918  Ali3Vector x; // The (South pointing) horizontal x-axis in the equatorial frame
1919  Ali3Vector y; // The (East pointing) horizontal y-axis in the equatorial frame
1920  Ali3Vector z; // The (Zenith pointing) horizontal z-axis in the equatorial frame
1921
1922  Double_t l,b;
1923  GetLabPosition(l,b,"deg");
1924
1925  Double_t a;
1926  Double_t vec[3]={1,0,0};
1927
1928  // Equatorial coordinates of the horizontal z-axis
1929  // at the moment of the specified timestamp 
1930  a=ts->GetLAST(fToffset);
1931  a*=15.; // Convert fractional hours to degrees 
1932  vec[1]=90.-b;
1933  vec[2]=a;
1934  z.SetVector(vec,"sph","deg");
1935
1936  // Equatorial coordinates of the horizontal x-axis
1937  // at the moment of the specified timestamp 
1938  vec[1]=180.-b;
1939  vec[2]=a;
1940  x.SetVector(vec,"sph","deg");
1941
1942  // The horizontal y-axis is determined for the right handed frame
1943  y=z.Cross(x);
1944
1945  fH.SetAngles(x.GetX(2,"sph","deg"),x.GetX(3,"sph","deg"),
1946               y.GetX(2,"sph","deg"),y.GetX(3,"sph","deg"),
1947               z.GetX(2,"sph","deg"),z.GetX(3,"sph","deg"));
1948 }
1949 ///////////////////////////////////////////////////////////////////////////
1950 void AliAstrolab::SetLocalFrame(Double_t t1,Double_t p1,Double_t t2,Double_t p2,Double_t t3,Double_t p3)
1951 {
1952 // Specification of the orientations of the local-frame axes.
1953 // The input arguments represent the angles (in degrees) of the local-frame axes
1954 // w.r.t. a so called Master Reference Frame (MRF), with the same convention
1955 // as the input arguments of TRotMatrix::SetAngles.
1956 //
1957 // The right handed Master Reference Frame is defined as follows :
1958 //  Z-axis : Points to the local Zenith
1959 //  X-axis : Makes an angle of 90 degrees with the Z-axis and points South
1960 //  Y-axis : Makes an angle of 90 degrees with the Z-axis and points East
1961 //
1962 // Once the user has specified the local reference frame, any observed event
1963 // can be related to astronomical space-time locations via the SetSignal
1964 // and GetSignal memberfunctions.
1965
1966  // Set the matrix for the conversion of our reference frame coordinates
1967  // into the local-frame ones.
1968
1969  fL.SetAngles(t1,p1,t2,p2,t3,p3);
1970 }
1971 ///////////////////////////////////////////////////////////////////////////
1972 Double_t AliAstrolab::ConvertAngle(Double_t a,TString in,TString out) const
1973 {
1974 // Conversion of various angular formats.
1975 //
1976 // The input argument "a" denotes the angle to be converted. 
1977 // The string arguments "in" and "out" specify the angular I/O formats.
1978 //
1979 // in = "rad" : input angle provided in radians
1980 //      "deg" : input angle provided in degrees
1981 //      "dms" : input angle provided in dddmmss.sss
1982 //      "hms" : input angle provided in hhmmss.sss
1983 //      "hrs" : input angle provided in fractional hours
1984 //
1985 // out = "rad" : output angle provided in radians
1986 //       "deg" : output angle provided in degrees
1987 //       "dms" : output angle provided in dddmmss.sss
1988 //       "hms" : output angle provided in hhmmss.sss
1989 //       "hrs" : output angle provided in fractional hours
1990  
1991  if (in==out) return a;
1992
1993  // Convert input to its absolute value in (fractional) degrees. 
1994  Double_t pi=acos(-1.);
1995  Double_t epsilon=1.e-12; // Accuracy in (arc)seconds
1996  Int_t word=0,ddd=0,hh=0,mm=0,ss=0;
1997  Double_t s=0;
1998
1999  Double_t b=fabs(a);
2000
2001  if (in=="rad") b*=180./pi;
2002
2003  if (in=="hrs") b*=15.;
2004
2005  if (in=="dms")
2006  {
2007   word=Int_t(b);
2008   ddd=word/10000;
2009   word=word%10000;
2010   mm=word/100;
2011   ss=word%100;
2012   s=b-Double_t(ddd*10000+mm*100+ss);
2013   b=Double_t(ddd)+Double_t(mm)/60.+(Double_t(ss)+s)/3600.;
2014  }
2015
2016  if (in=="hms")
2017  {
2018   word=Int_t(b);
2019   hh=word/10000;
2020   word=word%10000;
2021   mm=word/100;
2022   ss=word%100;
2023   s=b-Double_t(hh*10000+mm*100+ss);
2024   b=15.*(Double_t(hh)+Double_t(mm)/60.+(Double_t(ss)+s)/3600.);
2025  }
2026
2027  while (b>360)
2028  {
2029   b-=360.;
2030  }
2031
2032  if (out=="rad") b*=pi/180.;
2033
2034  if (out=="hrs") b/=15.;
2035
2036  if (out=="dms")
2037  {
2038   ddd=Int_t(b);
2039   b=b-Double_t(ddd);
2040   b*=60.;
2041   mm=Int_t(b);
2042   b=b-Double_t(mm);
2043   b*=60.;
2044   ss=Int_t(b);
2045   s=b-Double_t(ss);
2046   if (s>(1.-epsilon))
2047   {
2048    s=0.;
2049    ss++;
2050   }
2051   while (ss>=60)
2052   {
2053    ss-=60;
2054    mm++;
2055   }
2056   while (mm>=60)
2057   {
2058    mm-=60;
2059    ddd++;
2060   }
2061   while (ddd>=360)
2062   {
2063    ddd-=360;
2064   }
2065   b=Double_t(10000*ddd+100*mm+ss)+s;
2066  }
2067
2068  if (out=="hms")
2069  {
2070   b/=15.;
2071   hh=Int_t(b);
2072   b=b-Double_t(hh);
2073   b*=60.;
2074   mm=Int_t(b);
2075   b=b-Double_t(mm);
2076   b*=60.;
2077   ss=Int_t(b);
2078   s=b-Double_t(ss);
2079   if (s>(1.-epsilon))
2080   {
2081    s=0.;
2082    ss++;
2083   }
2084   while (ss>=60)
2085   {
2086    ss-=60;
2087    mm++;
2088   }
2089   while (mm>=60)
2090   {
2091    mm-=60;
2092    hh++;
2093   }
2094   while (hh>=24)
2095   {
2096    hh-=24;
2097   }
2098   b=Double_t(10000*hh+100*mm+ss)+s;
2099  }
2100
2101  if (a<0) b=-b;
2102
2103  return b;
2104 }
2105 ///////////////////////////////////////////////////////////////////////////
2106 Double_t AliAstrolab::GetHourAngle(TString mode,AliTimestamp* ts,Int_t jref)
2107 {
2108 // Provide the Local Hour Angle (in fractional degrees) of a stored signal
2109 // object at the specified timestamp.
2110 //
2111 // The input parameter "mode" allows the user to select either the
2112 // "mean" or "apparent" value for the returned Hour Angle.
2113 //
2114 // mode = "M" --> Output is the Mean Hour Angle
2115 //        "A" --> Output is the Apparent Hour Angle
2116 // ts   : Timestamp at which the hour angle is requested.
2117 //
2118 // The input parameter "jref" allows the user to specify so-called "reference" signals.
2119 // These reference signals may be used to check space-time event coincidences with the
2120 // stored measurement (e.g. coincidence of the measurement with transient phenomena).
2121 //
2122 // jref = 0 --> Use the stored measurement
2123 //        j --> Use the reference signal at the j-th position (j=1 is first)
2124 //
2125 // Default value is jref=0.
2126 //
2127 // Note : In case ts=0 the current timestamp of the lab will be taken.
2128
2129  if (!ts) ts=(AliTimestamp*)this;
2130
2131  // Get corrected right ascension and declination for the specified timestamp.
2132  Double_t a,d;
2133  if (mode=="M" || mode=="m") GetSignal(a,d,"M",ts,jref);
2134  if (mode=="A" || mode=="a") GetSignal(a,d,"T",ts,jref);
2135
2136  // Convert coordinates to fractional degrees.
2137  a=ConvertAngle(a,"hms","deg");
2138  d=ConvertAngle(d,"dms","deg");
2139
2140  a/=15.; // Convert a to fractional hours
2141  Double_t ha=0;
2142  if (mode=="M" || mode=="m") ha=ts->GetLMST(fToffset)-a;
2143  if (mode=="A" || mode=="a") ha=ts->GetLAST(fToffset)-a;
2144  ha*=15.; // Convert to (fractional) degrees
2145
2146  return ha;
2147 }
2148 ///////////////////////////////////////////////////////////////////////////
2149 void AliAstrolab::SetLT(Int_t y,Int_t m,Int_t d,Int_t hh,Int_t mm,Int_t ss,Int_t ns,Int_t ps)
2150 {
2151 // Set the AliTimestamp parameters corresponding to the LT date and time
2152 // in the Gregorian calendar as specified by the input arguments.
2153 //
2154 // The input arguments represent the following :
2155 // y  : year in LT (e.g. 1952, 2003 etc...)
2156 // m  : month in LT (1=jan  2=feb etc...)
2157 // d  : day in LT (1-31)
2158 // hh : elapsed hours in LT (0-23) 
2159 // mm : elapsed minutes in LT (0-59)
2160 // ss : elapsed seconds in LT (0-59)
2161 // ns : remaining fractional elapsed second of LT in nanosecond
2162 // ps : remaining fractional elapsed nanosecond of LT in picosecond
2163 //
2164 // Note : ns=0 and ps=0 are the default values.
2165 //
2166
2167  SetLT(fToffset,y,m,d,hh,mm,ss,ns,ps);
2168 }
2169 ///////////////////////////////////////////////////////////////////////////
2170 void AliAstrolab::SetLT(Int_t y,Int_t d,Int_t s,Int_t ns,Int_t ps)
2171 {
2172 // Set the AliTimestamp parameters corresponding to the specified elapsed
2173 // timespan since the beginning of the new LT year.
2174 //
2175 // The LT year and elapsed time span is entered via the following input arguments :
2176 //
2177 // y  : year in LT (e.g. 1952, 2003 etc...)
2178 // d  : elapsed number of days 
2179 // s  : (remaining) elapsed number of seconds
2180 // ns : (remaining) elapsed number of nanoseconds
2181 // ps : (remaining) elapsed number of picoseconds
2182 //
2183 // The specified d, s, ns and ps values will be used in an additive
2184 // way to determine the elapsed timespan.
2185 // So, specification of d=1, s=100, ns=0, ps=0 will result in the
2186 // same elapsed time span as d=0, s=24*3600+100, ns=0, ps=0.
2187 // However, by making use of the latter the user should take care
2188 // of possible integer overflow problems in the input arguments,
2189 // which obviously will provide incorrect results. 
2190 //
2191 // Note : ns=0 and ps=0 are the default values.
2192
2193  SetLT(fToffset,y,d,s,ns,ps);
2194 }
2195 ///////////////////////////////////////////////////////////////////////////
2196 Double_t AliAstrolab::GetDifference(Int_t j,TString au,Double_t& dt,TString tu,Int_t mode,Int_t* ia,Int_t* it)
2197 {
2198 // Provide space and time difference between the j-th reference signal
2199 // (j=1 indicates first) and the stored measurement.
2200 // 
2201 // The return value of this memberfunction provides the positional angular
2202 // difference, whereas the output argument "dt" provides the time difference.
2203 //
2204 // The units of the angular difference can be specified via the the "au"
2205 // input argument, where
2206 //
2207 // au = "rad" --> Angular difference in (fractional) radians
2208 //      "deg" --> Angular difference in (fractional) degrees
2209 //
2210 // The units of the time difference can be specified via the "tu" and "mode"
2211 // input arguments. For details please refer to AliTimestamp::GetDifference().
2212 // Also here mode=1 is the default value.
2213 //
2214 // For the time difference the reference signal is used as the standard.
2215 // This means that in case of a positive time difference, the stored
2216 // measurement occurred later than the reference signal.
2217 //
2218 // In case j=0, the stored measurement will be compared with each
2219 // reference signal and the returned angular and time differences are
2220 // the minimal differences which were encountered.
2221 // In this case the user may obtain the indices of the two stored reference signals
2222 // which had the minimal angular and minimal time difference via the output
2223 // arguments "ia" and "it" as follows :
2224 //
2225 // ia = Index of the stored reference signal with minimial angular difference
2226 // it = Index of the stored reference signal with minimial time difference
2227 //
2228 // In case these indices are the same, there obviously was 1 single reference signal
2229 // which showed both the minimal angular and time difference.
2230 //
2231 // The default values are mode=1, ia=0 and it=0;
2232
2233  Double_t dang=999;
2234  dt=1.e20;
2235  if (ia) *ia=0;
2236  if (it) *it=0;
2237
2238  if (!fRefs) return dang;
2239
2240  Ali3Vector rx; // Position of the measurement
2241  Ali3Vector r0; // Position of the reference signal
2242
2243  AliSignal* sx=GetSignal(rx,"icr","M",0);
2244  if (!sx) return dang;
2245
2246  AliTimestamp* tx=sx->GetTimestamp();
2247  if (!tx) return dang;
2248
2249  // Space and time difference w.r.t. a specific reference signal
2250  if (j>0)
2251  {
2252   AliSignal* s0=GetSignal(r0,"icr","M",0,j);
2253   if (!s0) return dang;
2254   AliTimestamp* t0=s0->GetTimestamp();
2255
2256   if (!t0) return dang;
2257
2258   dang=r0.GetOpeningAngle(rx,au);
2259   dt=t0->GetDifference(tx,tu,mode);
2260   return dang;
2261  }
2262
2263  // Minimal space and time difference encountered over all reference signals
2264  Double_t dangmin=dang;
2265  Double_t dtmin=dt;
2266  for (Int_t i=1; i<=fRefs->GetSize(); i++)
2267  {
2268   AliSignal* s0=GetSignal(r0,"icr","M",0,i);
2269   if (!s0) continue;
2270   AliTimestamp* t0=s0->GetTimestamp();
2271   if (!t0) continue;
2272   dang=r0.GetOpeningAngle(rx,au);
2273   dt=t0->GetDifference(tx,tu,mode);
2274   if (fabs(dang)<dangmin)
2275   {
2276    dangmin=fabs(dang);
2277    *ia=i;
2278   }
2279   if (fabs(dt)<dtmin)
2280   {
2281    dtmin=fabs(dt);
2282    *it=i;
2283   }
2284  }
2285
2286  dt=dtmin;
2287  return dangmin;
2288 }
2289 ///////////////////////////////////////////////////////////////////////////
2290 Double_t AliAstrolab::GetDifference(TString name,TString au,Double_t& dt,TString tu,Int_t mode)
2291 {
2292 // Provide space and time difference between the reference signal
2293 // with the specified name and the stored measurement.
2294 // 
2295 // The return value of this memberfunction provides the positional angular
2296 // difference, whereas the output argument "dt" provides the time difference.
2297 //
2298 // The units of the angular difference can be specified via the the "au"
2299 // input argument, where
2300 //
2301 // au = "rad" --> Angular difference in (fractional) radians
2302 //      "deg" --> Angular difference in (fractional) degrees
2303 //
2304 // The units of the time difference can be specified via the "tu" and "mode"
2305 // input arguments. For details please refer to AliTimestamp::GetDifference().
2306 // Also here mode=1 is the default value.
2307 //
2308 // For the time difference the reference signal is used as the standard.
2309 // This means that in case of a positive time difference, the stored
2310 // measurement occurred later than the reference signal.
2311
2312  Double_t dang=999;
2313  dt=1.e20;
2314
2315  Int_t j=GetSignalIndex(name);
2316  if (j>0) dang=GetDifference(j,au,dt,tu,mode);
2317  return dang;
2318 }
2319 ///////////////////////////////////////////////////////////////////////////
2320 TArrayI* AliAstrolab::MatchRefSignal(Double_t da,TString au,Double_t dt,TString tu,Int_t mode)
2321 {
2322 // Provide the storage indices of the reference signals which match in space
2323 // and time with the stored measurement.
2324 // The indices are returned via a pointer to a TArrayI object.
2325 // In case no matches were found, the null pointer is returned.
2326 // A reference signal is regarded as matching with the stored measurement
2327 // if the positional angular difference doesn't exceed "da" and the absolute
2328 // value of the time difference doesn't exceed "dt".
2329 //
2330 // The units of the angular difference "da" can be specified via the the "au"
2331 // input argument, where
2332 //
2333 // au = "rad" --> Angular difference in (fractional) radians
2334 //      "deg" --> Angular difference in (fractional) degrees
2335 //
2336 // The units of the time difference "dt" can be specified via the "tu" and "mode"
2337 // input arguments. For details please refer to AliTimestamp::GetDifference().
2338 // Also here mode=1 is the default value.
2339
2340  if (!fXsig || !fRefs) return 0;
2341
2342  Int_t nrefs=fRefs->GetEntries();
2343
2344  if (fIndices) delete fIndices;
2345  fIndices=new TArrayI(nrefs);
2346
2347  Double_t dang,dtime;
2348  Int_t jfill=0; 
2349  for (Int_t i=1; i<=fRefs->GetSize(); i++)
2350  {
2351   dang=GetDifference(i,au,dtime,tu,mode);
2352   if (fabs(dang)<=da && fabs(dtime)<=dt)
2353   {
2354    fIndices->AddAt(i,jfill);
2355    jfill++;
2356   }
2357  }
2358
2359  fIndices->Set(jfill);
2360  return fIndices;
2361 }
2362 ///////////////////////////////////////////////////////////////////////////
2363 void AliAstrolab::DisplaySignal(TString frame,TString mode,AliTimestamp* ts,Int_t jref,TString proj,Int_t clr)
2364 {
2365 // Display a stored signal in a user specified coordinate projection
2366 // at the specific timestamp ts.
2367 //
2368 // In case no stored signal was available or one of the input arguments was
2369 // invalid, no display is produced.
2370 //
2371 // Note : In case ts=0 the current timestamp of the lab will be taken.
2372 //
2373 // The input parameter "frame" allows the user to specify the frame to which
2374 // the coordinates refer. Available options are :
2375 //
2376 //  frame = "equ" ==> Equatorial coordinates with right ascension (a) and declination (d).
2377 //
2378 //          "gal" ==> Galactic coordinates with longitude (l) and latitude (b).
2379 //
2380 //          "ecl" ==> Ecliptic coordinates with longitude (l) and latitude (b).
2381 //
2382 //          "hor" ==> Horizontal azimuth and altitude coordinates at the AliAstrolab location.
2383 //
2384 //          "icr" ==> ICRS coordinates with longitude (l) and latitude (b).
2385 //
2386 //          "loc" ==> Local spherical angles theta and phi at the AliAstrolab location.
2387 //
2388 // In case the coordinates are the equatorial right ascension and declination (a,d),
2389 // they can represent so-called "mean" and "true" values.
2390 // The distinction between these two representations is the following :
2391 //
2392 // mean values : (a,d) are only corrected for precession and not for nutation
2393 // true values : (a,d) are corrected for both precession and nutation
2394 //
2395 // The input parameter "mode" allows the user to specifiy either "mean" or "true"
2396 // values for the input in case of equatorial (a,d) coordinates.
2397 //
2398 // mode = "M" --> Input coordinates are the mean values 
2399 //        "T" --> Input coordinates are the true values 
2400 //
2401 // The input parameter "jref" allows display of a so-called "reference" signal.
2402 // These reference signals may serve to check space-time event coincidences with the
2403 // stored measurement (e.g. coincidence of the measurement with transient phenomena).
2404 //
2405 // jref = 0 --> Display of the measurement
2406 //        j --> Display of the j-th reference signal
2407 //
2408 // Default value is jref=0.
2409 //
2410 // The input parameter "proj" allows the user to specify the desired projection.
2411 // The available projection modes are :
2412 //
2413 // cyl  : Cylindrical projection plotted with colored markers
2414 // cylh : Cylindrical projection plotted in a 2-D histogram
2415 // ham  : Hammer equal area projection plotted with colored markers
2416 // hamh : Hammer equal area projection plotted in a 2-D histogram
2417 // ait  : Aitoff projection plotted with colored markers
2418 // aith : Aitoff projection plotted in a 2-D histogram
2419 // mer  : Mercator projection plotted with colored markers
2420 // merh : Mercator projection plotted in a 2-D histogram
2421 // ang  : Straight cos(b) vs. l plot with colored markers
2422 // angh : Straight cos(b) vs. l plot in a 2-D histogram
2423 //
2424 // Note : The ang(h) plot allows for easy identification of a homogeneous distribution.
2425 //
2426 // The input argument "clr" allows to clear (1) the display before drawing or not (0).
2427 //
2428 // The default values are : jref=0, proj="ham" and clr=0.
2429 //
2430 // This routine is based on the work by Garmt de Vries-Uiterweerd.
2431
2432  Ali3Vector r;
2433  AliSignal* sx=GetSignal(r,frame,mode,ts,jref);
2434
2435  if (!sx) return;
2436
2437  // The generic input angles (in rad) for the projections 
2438  Double_t theta=0;
2439  Double_t phi=0;
2440
2441  Double_t pi=acos(-1.);
2442
2443  if (frame=="equ" || frame=="gal" || frame=="icr" || frame=="ecl" || frame=="loc")
2444  {
2445   theta=(pi/2.)-r.GetX(2,"sph","rad");
2446   phi=r.GetX(3,"sph","rad");
2447  }
2448
2449  if (frame=="hor")
2450  {
2451   theta=(pi/2.)-r.GetX(2,"sph","rad");
2452   phi=pi-r.GetX(3,"sph","rad");
2453  }
2454
2455  // Automatic choice of central meridian if not selected by the user
2456  if (fMeridian<-pi)
2457  {
2458   if (frame=="gal")
2459   {
2460    fMeridian=0;
2461   }
2462   else
2463   {
2464    fMeridian=pi;
2465   }
2466  }
2467
2468  // Obtain the projected (x,y) position
2469  Double_t x=0;
2470  Double_t y=0;
2471  Project(phi,theta,proj,x,y);
2472
2473  Int_t hist=0;
2474  if (proj=="hamh" || proj=="aith" || proj=="merh" || proj=="cylh" || proj=="angh") hist=1;
2475
2476  // Update the display for this signal position
2477
2478  // Create a new canvas if needed
2479  if (!fCanvas) fCanvas=new TCanvas("AliAstrolab","Skymap");
2480
2481  // Construct the title string for this map
2482  TString title="Projection : ";
2483  title+=frame;
2484  title+=" ";
2485  title+=proj;
2486  title+="   Center : ";
2487  Int_t ang,h,m,s,d;
2488  if (frame=="equ" || frame=="icr")
2489  {
2490   ang=int(ConvertAngle(fMeridian,"rad","hms"));
2491   h=ang/10000;
2492   ang=ang%10000;
2493   m=ang/100;
2494   s=ang%100;
2495   title+=h;
2496   title+="h ";
2497   title+=m;
2498   title+="m ";
2499   title+=s;
2500   title+="s";
2501  }
2502  else
2503  {
2504   ang=int(ConvertAngle(fMeridian,"rad","dms"));
2505   d=ang/10000;
2506   ang=ang%10000;
2507   m=ang/100;
2508   s=ang%100;
2509   title+=d;
2510   title+="d ";
2511   title+=m;
2512   title+="' ";
2513   title+=s;
2514   title+="\"";
2515  }
2516
2517  if (!hist) // 2-D Marker display (i.e. not a histogram) 
2518  {
2519   // Remove existing markers, grid and outline from display if needed
2520   if (clr==1 || proj!=fProj)
2521   {
2522    if (fMarkers)
2523    {
2524     delete fMarkers;
2525     fMarkers=0;
2526    }
2527    fCanvas->Clear();
2528    fProj=proj;
2529   }
2530
2531   if (!fMarkers)
2532   {
2533    fMarkers=new TObjArray();
2534    fMarkers->SetOwner();
2535    // Set canvas range, header and axes
2536    if (proj=="mer")
2537    {
2538     fCanvas->Range(-2.2,-6.,2.2,6.);
2539     TText* header=new TText;
2540     fMarkers->Add(header);
2541     header->DrawText(-1.4,5.5,title.Data());
2542     TLine* line=new TLine(-2,0,2,0);
2543     fMarkers->Add(line);
2544     line->Draw();
2545     line=new TLine(0,5.5,0,-5.5);
2546     fMarkers->Add(line);
2547     line->Draw();
2548    }
2549    else
2550    {
2551     fCanvas->Range(-2.2,-1.2,2.2,1.2);
2552     TText* header=new TText;
2553     fMarkers->Add(header);
2554     header->DrawText(-1.4,1.1,title.Data());
2555     TLine* line=new TLine(-2,0,2,0);
2556     fMarkers->Add(line);
2557     line->Draw();
2558     line=new TLine(0,1,0,-1);
2559     fMarkers->Add(line);
2560     line->Draw();
2561    }
2562    // Draw the outline 
2563    if (proj=="ham" || proj=="ait")
2564    {
2565     // Draw ellips outline with axes
2566     TEllipse* outline=new TEllipse(0,0,2,1);
2567     fMarkers->Add(outline);
2568     outline->Draw();
2569    }
2570   }
2571   TMarker* marker=0;
2572   if (!jref) // The measurement
2573   {
2574    marker=new TMarker(x,y,29);
2575    marker->SetMarkerColor(kRed);
2576   }
2577   else // The reference signal(s)
2578   {
2579    marker=new TMarker(x,y,20);
2580    marker->SetMarkerColor(kBlue);
2581   }
2582   marker->SetMarkerSize(1);
2583   fMarkers->Add(marker);
2584   marker->Draw();
2585  }
2586  else if (hist==1) // 2-D display via histogram
2587  {
2588   // Reset the histogram if needed
2589   if (clr==1 || proj!=fProj)
2590   {
2591    fCanvas->Clear();
2592    if (!fHist) fHist=new TH2F();
2593    fHist->Reset();
2594    fHist->SetMarkerStyle(20);
2595    fHist->SetMarkerSize(1);
2596    fHist->SetMarkerColor(kBlue);
2597    fHist->SetNameTitle("SkyMap",title.Data());
2598    if (proj=="merh")
2599    {
2600     fHist->SetBins(100,-2.2,2.2,100,-5.5,5.5);
2601    }
2602    else
2603    {
2604     fHist->SetBins(100,-2.2,2.2,100,-1.1,1.1);
2605    }
2606    fProj=proj;
2607   }
2608   fHist->Fill(x,y);
2609   fHist->Draw();
2610  }
2611 }
2612 ///////////////////////////////////////////////////////////////////////////
2613 void AliAstrolab::DisplaySignal(TString frame,TString mode,AliTimestamp* ts,TString name,TString proj,Int_t clr)
2614 {
2615 // Display the stored signal with the specified name in a user specified
2616 // coordinate projection at the specific timestamp ts.
2617 //
2618 // Note : In case ts=0 the current timestamp of the lab will be taken.
2619 //
2620 // In case no such stored signal was available or one of the input arguments was
2621 // invalid, no display is produced.
2622 //
2623 // The input parameter "frame" allows the user to specify the frame to which
2624 // the coordinates refer. Available options are :
2625 //
2626 //  frame = "equ" ==> Equatorial coordinates with right ascension (a) and declination (d).
2627 //
2628 //          "gal" ==> Galactic coordinates with longitude (l) and latitude (b).
2629 //
2630 //          "ecl" ==> Ecliptic coordinates with longitude (l) and latitude (b).
2631 //
2632 //          "hor" ==> Horizontal azimuth and altitude coordinates at the AliAstrolab location.
2633 //
2634 //          "icr" ==> ICRS coordinates with longitude (l) and latitude (b).
2635 //
2636 //          "loc" ==> Local spherical angles theta and phi at the AliAstrolab location.
2637 //
2638 // In case the coordinates are the equatorial right ascension and declination (a,d),
2639 // they can represent so-called "mean" and "true" values.
2640 // The distinction between these two representations is the following :
2641 //
2642 // mean values : (a,d) are only corrected for precession and not for nutation
2643 // true values : (a,d) are corrected for both precession and nutation
2644 //
2645 // The input parameter "mode" allows the user to specifiy either "mean" or "true"
2646 // values for the input in case of equatorial (a,d) coordinates.
2647 //
2648 // mode = "M" --> Input coordinates are the mean values 
2649 //        "T" --> Input coordinates are the true values 
2650 //
2651 // The input parameter "proj" allows the user to specify the desired projection.
2652 // The available projection modes are :
2653 //
2654 // cyl  : Cylindrical projection plotted with colored markers
2655 // cylh : Cylindrical projection plotted in a 2-D histogram
2656 // ham  : Hammer equal area projection plotted with colored markers
2657 // hamh : Hammer equal area projection plotted in a 2-D histogram
2658 // ait  : Aitoff projection plotted with colored markers
2659 // aith : Aitoff projection plotted in a 2-D histogram
2660 // mer  : Mercator projection plotted with colored markers
2661 // merh : Mercator projection plotted in a 2-D histogram
2662 // ang  : Straight cos(b) vs. l plot with colored markers
2663 // angh : Straight cos(b) vs. l plot in a 2-D histogram
2664 //
2665 // Note : The ang(h) plot allows for easy identification of a homogeneous distribution.
2666 //
2667 // The input argument "clr" allows to clear (1) the display before drawing or not (0).
2668 //
2669 // The default values are : proj="ham" and clr=0.
2670 //
2671 // This routine is based on the work by Garmt de Vries-Uiterweerd.
2672
2673  Int_t j=GetSignalIndex(name);
2674  if (j>=0) DisplaySignal(frame,mode,ts,j,proj,clr);
2675 }
2676 ///////////////////////////////////////////////////////////////////////////
2677 void AliAstrolab::DisplaySignals(TString frame,TString mode,AliTimestamp* ts,TString proj,Int_t clr)
2678 {
2679 // Display of all stored signals in user specified coordinate projection
2680 // at the specific timestamp ts.
2681 // In case ts=0, the timestamp of the actual recording of the stored measurement
2682 // under investigation will be used.
2683 // In case no (timestamp of the) actual measurement is available,
2684 // the current timestamp of the lab will be taken.
2685 // In case no stored signal is available or one of the input arguments is
2686 // invalid, no display is produced.
2687 //
2688 // The input parameter "frame" allows the user to specify the frame to which
2689 // the coordinates refer. Available options are :
2690 //
2691 //  frame = "equ" ==> Equatorial coordinates with right ascension (a) and declination (d).
2692 //
2693 //          "gal" ==> Galactic coordinates with longitude (l) and latitude (b).
2694 //
2695 //          "ecl" ==> Ecliptic coordinates with longitude (l) and latitude (b).
2696 //
2697 //          "hor" ==> Horizontal azimuth and altitude coordinates at the AliAstrolab location.
2698 //
2699 //          "icr" ==> ICRS coordinates with longitude (l) and latitude (b).
2700 //
2701 //          "loc" ==> Local spherical angles theta and phi at the AliAstrolab location.
2702 //
2703 // In case the coordinates are the equatorial right ascension and declination (a,d),
2704 // they can represent so-called "mean" and "true" values.
2705 // The distinction between these two representations is the following :
2706 //
2707 // mean values : (a,d) are only corrected for precession and not for nutation
2708 // true values : (a,d) are corrected for both precession and nutation
2709 //
2710 // The input parameter "mode" allows the user to specifiy either "mean" or "true"
2711 // values for the input in case of equatorial (a,d) coordinates.
2712 //
2713 // mode = "M" --> Input coordinates are the mean values 
2714 //        "T" --> Input coordinates are the true values 
2715 //
2716 // The input parameter "proj" allows the user to specify the desired projection.
2717 // The available projection modes are :
2718 //
2719 // cyl  : Cylindrical projection plotted with colored markers
2720 // cylh : Cylindrical projection plotted in a 2-D histogram
2721 // ham  : Hammer equal area projection plotted with colored markers
2722 // hamh : Hammer equal area projection plotted in a 2-D histogram
2723 // ait  : Aitoff projection plotted with colored markers
2724 // aith : Aitoff projection plotted in a 2-D histogram
2725 // mer  : Mercator projection plotted with colored markers
2726 // merh : Mercator projection plotted in a 2-D histogram
2727 // ang  : Straight cos(b) vs. l plot with colored markers
2728 // angh : Straight cos(b) vs. l plot in a 2-D histogram
2729 //
2730 // Note : The ang(h) plot allows for easy identification of a homogeneous distribution.
2731 //
2732 // The input argument "clr" allows to clear (1) the display before drawing or not (0).
2733 //
2734 // The default values are : proj="ham" and clr=0.
2735 //
2736 // This routine is based on the work by Garmt de Vries-Uiterweerd.
2737
2738  AliTimestamp* tx=ts;
2739  if (fXsig && !tx) tx=fXsig->GetTimestamp();
2740  if (!tx) tx=(AliTimestamp*)this;
2741
2742  // Display all stored reference signals
2743  if (fRefs)
2744  {
2745   for (Int_t i=1; i<=fRefs->GetSize(); i++)
2746   {
2747    DisplaySignal(frame,mode,tx,i,proj,clr);
2748    clr=0; // No display clear for subsequent signals
2749   }
2750  }
2751
2752  // Display the measurement
2753  DisplaySignal(frame,mode,tx,0,proj,clr);
2754 }
2755 ///////////////////////////////////////////////////////////////////////////
2756 void AliAstrolab::SetCentralMeridian(Double_t phi,TString u)
2757 {
2758 // Set the central meridian for the sky display.
2759 // Setting a value smaller than -pi will induce automatic meridian setting
2760 // in the display.
2761 // By default the central meridian is set at -999 in the constructor.
2762 //
2763 // The string argument "u" allows to choose between different angular units
2764 // u = "rad" : angle provided in radians
2765 //     "deg" : angle provided in degrees
2766 //     "dms" : angle provided in dddmmss.sss
2767 //     "hms" : angle provided in hhmmss.sss
2768 //
2769 // The default is u="deg".
2770 //
2771 // This routine is based on the work by Garmt de Vries-Uiterweerd.
2772
2773  fMeridian=ConvertAngle(phi,u,"rad");
2774 }
2775 ///////////////////////////////////////////////////////////////////////////
2776 void AliAstrolab::Project(Double_t l,Double_t b,TString proj,Double_t& x,Double_t& y)
2777 {
2778 // Generic interface for projection of a (long,lat) pair onto a (x,y) pair.
2779 //
2780 // Meaning of the arguments :
2781 // --------------------------
2782 // l    : Longitude (e.g. right ascension)
2783 // b    : Latitude (e.g. declination)
2784 // proj : Projection mode (e.g. "ham")
2785 // x    : The resulting x coordinate for the selected projection
2786 // y    : The resulting x coordinate for the selected projection
2787 //
2788 // The available projection modes are :
2789 //
2790 // cyl  : Cylindrical projection plotted with colored markers
2791 // cylh : Cylindrical projection plotted in a 2-D histogram
2792 // ham  : Hammer equal area projection plotted with colored markers
2793 // hamh : Hammer equal area projection plotted in a 2-D histogram
2794 // ait  : Aitoff projection plotted with colored markers
2795 // aith : Aitoff projection plotted in a 2-D histogram
2796 // mer  : Mercator projection plotted with colored markers
2797 // merh : Mercator projection plotted in a 2-D histogram
2798 // ang  : Straight cos(b) vs. l plot with colored markers
2799 // angh : Straight cos(b) vs. l plot in a 2-D histogram
2800 //
2801 // Note : The ang(h) plot allows for easy identification of a homogeneous distribution.
2802 //
2803 // This routine is based on the work by Garmt de Vries-Uiterweerd.
2804
2805  Double_t pi=acos(-1.);
2806
2807  // Subtract central meridian from longitude
2808  l-=fMeridian;
2809
2810  // Take l between -180 and 180 degrees
2811  while (l>pi)
2812  {
2813   l-=2*pi;
2814  }
2815  while (l<-pi)
2816  {
2817   l+=2*pi;
2818  }
2819
2820  x=0;
2821  y=0;
2822
2823  // Convert (l,b) to (x,y) with -2 < x <= 2 
2824  if (proj=="cyl" || proj=="cylh") ProjectCylindrical(l,b,x,y);
2825  if (proj=="ham" || proj=="hamh") ProjectHammer(l,b,x,y);
2826  if (proj=="ait" || proj=="aith") ProjectAitoff(l,b,x,y);
2827  if (proj=="mer" || proj=="merh") ProjectMercator(l,b,x,y);
2828  if (proj=="ang" || proj=="angh")
2829  {
2830   x=2*l/pi;
2831   y=cos(b);
2832  }
2833 }
2834 ///////////////////////////////////////////////////////////////////////////
2835 void AliAstrolab::ProjectCylindrical(Double_t l,Double_t b,Double_t& x, Double_t& y)
2836 {
2837 // Cylindrical projection of a (long,lat) coordinate pair 
2838 //
2839 // This routine is based on the work by Garmt de Vries-Uiterweerd.
2840
2841  Double_t pi=acos(-1.);
2842  x=2*l/pi;
2843  y=2*b/pi;
2844 }
2845 ///////////////////////////////////////////////////////////////////////////
2846 void AliAstrolab::ProjectHammer(Double_t l,Double_t b,Double_t& x,Double_t& y)
2847 {
2848 // Hammer-Aitoff projection of a (long,lat) coordinate pair. 
2849 // This is an equal-area projection.
2850 //
2851 // This routine is based on the work by Garmt de Vries-Uiterweerd.
2852
2853  Double_t k=1./sqrt(1.+cos(b)*cos(l/2.));
2854  x=2.*k*cos(b)*sin(l/2.);
2855  y=k*sin(b);
2856 }
2857 ///////////////////////////////////////////////////////////////////////////
2858 void AliAstrolab::ProjectAitoff(Double_t l,Double_t b,Double_t& x,Double_t& y)
2859 {
2860 // Aitoff projection of a (long,lat) coordinate pair. 
2861 //
2862 // This routine is based on the work by Garmt de Vries-Uiterweerd.
2863
2864  Double_t pi=acos(-1.);
2865  x=0;
2866  y=0;
2867  Double_t k=acos(cos(b)*cos(l/2.));
2868  if(sin(k)!=0)
2869  {
2870   x=4.*k*cos(b)*sin(l/2.)/(pi*sin(k));
2871   y=2.*k*sin(b)/(pi*sin(k));
2872  }
2873 }
2874 ///////////////////////////////////////////////////////////////////////////
2875 void AliAstrolab::ProjectMercator(Double_t l,Double_t b,Double_t& x,Double_t& y)
2876 {
2877 // Mercator projection of a (long,lat) coordinate pair 
2878 //
2879 // This routine is based on the work by Garmt de Vries-Uiterweerd.
2880
2881  Double_t pi=acos(-1.);
2882  x=2.*l/pi;
2883  y=0;
2884  if (b >= 89.*pi/180.) b=89.*pi/180.;
2885  if (b <= -89.*pi/180.) y=-89.*pi/180.;
2886  if (fabs(y) < 1) y=log((1.+sin(b))/(1.-sin(b)))/2.;
2887 }
2888 ///////////////////////////////////////////////////////////////////////////
2889 TObject* AliAstrolab::Clone(const char* name) const
2890 {
2891 // Make a deep copy of the current object and provide the pointer to the copy.
2892 // This memberfunction enables automatic creation of new objects of the
2893 // correct type depending on the object type, a feature which may be very useful
2894 // for containers when adding objects in case the container owns the objects.
2895
2896  AliAstrolab* lab=new AliAstrolab(*this);
2897  if (name)
2898  {
2899   if (strlen(name)) lab->SetName(name);
2900  }
2901  return lab;
2902 }
2903 ///////////////////////////////////////////////////////////////////////////