File Coverage

blib/lib/Astro/Coords/Equatorial.pm
Criterion Covered Total %
statement 175 212 82.5
branch 74 130 56.9
condition 44 110 40.0
subroutine 23 25 92.0
pod 15 15 100.0
total 331 492 67.2


line stmt bran cond sub pod time code
1             package Astro::Coords::Equatorial;
2              
3             =head1 NAME
4              
5             Astro::Coords::Equatorial - Manipulate equatorial coordinates
6              
7             =head1 SYNOPSIS
8              
9             $c = new Astro::Coords::Equatorial( name => 'blah',
10             ra => '05:22:56',
11             dec => '-26:20:40.4',
12             type => 'B1950'
13             units=> 'sexagesimal');
14              
15             $c = new Astro::Coords::Equatorial( name => 'Vega',
16             ra => ,
17             dec => ,
18             type => 'J2000',
19             units => 'sex',
20             pm => [ 0.202, 0.286],
21             parallax => 0.13,
22             epoch => 2004.529,
23             );
24              
25             $c = new Astro::Coords( ra => '16h24m30.2s',
26             dec => '-00d54m2s',
27             type => 'J2000',
28             rv => 31,
29             vdefn => 'RADIO',
30             vframe => 'LSRK' );
31              
32              
33             =head1 DESCRIPTION
34              
35             This class is used by C<Astro::Coords> for handling coordinates
36             specified in a fixed astronomical coordinate frame.
37              
38             You are not expected to use this class directly, the C<Astro::Coords>
39             class should be used for all access (the C<Astro::Coords> constructor
40             is treated as a factory constructor).
41              
42             If proper motions and parallax information are supplied with a
43             coordinate it is assumed that the RA/Dec supplied is correct
44             for the given epoch. An equinox can be specified through the 'type'
45             constructor, where a 'type' of 'J1950' would be Julian epoch 1950.0.
46              
47             =cut
48              
49 19     19   4454217 use 5.006;
  19         75  
50 19     19   123 use strict;
  19         41  
  19         471  
51 19     19   94 use warnings;
  19         59  
  19         677  
52 19     19   108 use warnings::register;
  19         44  
  19         2194  
53 19     19   128 use Carp;
  19         45  
  19         1710  
54              
55             our $VERSION = '0.21';
56              
57 19     19   937 use Astro::PAL ();
  19         5107  
  19         532  
58 19     19   111 use base qw/ Astro::Coords /;
  19         56  
  19         3000  
59              
60 19     19   136 use overload '""' => "stringify", fallback => 1;
  19         43  
  19         138  
61              
62             =head1 METHODS
63              
64             =head2 Constructor
65              
66             =over 4
67              
68             =item B<new>
69              
70             Instantiate a new object using the supplied options.
71              
72             $c = new Astro::Coords::Equatorial(
73             name =>
74             ra =>
75             dec =>
76             long =>
77             lat =>
78             pm =>
79             parallax =>
80             type =>
81             units =>
82             epoch =>
83             );
84              
85             C<ra> and C<dec> are used for HMSDeg systems (eg type=J2000). Long and
86             Lat are used for degdeg systems (eg where type=galactic). C<type> can
87             be "galactic", "j2000", "b1950", and "supergalactic". The C<units>
88             can be specified as "sexagesimal" (when using colon or space-separated
89             strings), "degrees" or "radians". The default is determined from
90             context. A reference to a 2-element array can be given to specify
91             different units for the two coordinates, e.g. C<['hours', 'degrees']>.
92              
93             The name is just a string you can associate with the sky position.
94              
95             All coordinates are converted to FK5 J2000 [epoch 2000.0] internally.
96              
97             Units of parallax are arcsec. Units of proper motion are arcsec/year
98             (no correction for declination; tropical year for B1950, Julian year
99             for J2000). If proper motions are supplied they must both be supplied
100             in a reference to an array:
101              
102             pm => [ 0.13, 0.45 ],
103              
104             Additionally if non-zero proper motions are supplied then a non-zero
105             parallax must also be supplied.
106              
107             If parallax and proper motions are given, the ra/dec coordinates are
108             assumed to be correct for the specified EQUINOX (Epoch = 2000.0 for
109             J2000, epoch = 1950.0 for B1950) unless an explicit epoch is
110             specified. If the epoch is supplied it is assumed to be a Besselian
111             epoch for FK4 coordinates and Julian epoch for all others.
112              
113             Radial velocities can be specified using hash arguments:
114              
115             rv => radial velocity (km/s)
116             vdefn => velocity definition (RADIO, OPTICAL, RELATIVSTIC) [default: OPTICAL]
117             vframe => velocity reference frame (HEL,GEO,TOP,LSRK,LSRD) [default: HEL]
118              
119             Note that the radial velocity is only used to calculate position if
120             parallax or proper motions are also supplied. These values will be used
121             for calculating a doppler correction.
122              
123             Additionally, a redshift can be specified:
124              
125             redshift => 2.3
126              
127             this overrides rv, vdefn and vframe. A redshift is assumed to be an optical
128             velocity in the heliocentric frame.
129              
130             Usually called via C<Astro::Coords> as a factor method.
131              
132             =cut
133              
134             sub new {
135 1029     1029 1 2131 my $proto = shift;
136 1029   33     3203 my $class = ref($proto) || $proto;
137              
138 1029         3497 my %args = @_;
139              
140 1029 50       2680 return undef unless exists $args{type};
141              
142             # make sure we are upper cased.
143 1029         2195 $args{type} = uc($args{type});
144              
145 1029 100       3451 my ($unit_c1, $unit_c2) = (ref $args{'units'}) ? @{$args{'units'}} : ($args{'units'}) x 2;
  1         3  
146              
147             # Convert input args to radians
148             $args{ra} = Astro::Coords::Angle::Hour->to_radians($args{ra}, $unit_c1 )
149 1029 100       4520 if exists $args{ra};
150             $args{dec} = Astro::Coords::Angle->to_radians($args{dec}, $unit_c2 )
151 1029 100       4013 if exists $args{dec};
152             $args{long} = Astro::Coords::Angle->to_radians($args{long}, $unit_c1 )
153 1029 100       2441 if exists $args{long};
154             $args{lat} = Astro::Coords::Angle->to_radians($args{lat}, $unit_c2 )
155 1029 100       2358 if exists $args{lat};
156              
157             # Default values for parallax and proper motions
158 1029         1835 my( $pm, $parallax );
159 1029 100       2133 if( exists( $args{parallax} ) ) {
160 2         5 $parallax = $args{parallax};
161             } else {
162 1027         1640 $parallax = 0;
163             }
164 1029 100       1959 if( exists( $args{pm} ) ) {
165 2         5 $pm = $args{pm};
166             } else {
167 1027         2469 $pm = [0,0];
168             }
169              
170             # Try to sort out what we have been given. We need to convert
171             # everything to FK5 J2000
172 1029 50       2887 croak "Proper motions are supplied but not as a ref to array"
173             unless ref($pm) eq 'ARRAY';
174              
175             # Extract the proper motions into convenience variables
176 1029         1919 my $pm1 = $pm->[0];
177 1029         1628 my $pm2 = $pm->[1];
178              
179 1029         1787 my ($ra, $dec, $native);
180              
181 1029 100       5220 if ($args{type} =~ /^j([0-9\.]+)/i) {
    100          
    50          
    0          
182 525 50 33     2759 return undef unless exists $args{ra} and exists $args{dec};
183 525 50 33     2121 return undef unless defined $args{ra} and defined $args{dec};
184              
185 525         944 $native = 'radec';
186              
187 525         960 $ra = $args{ra};
188 525         816 $dec = $args{dec};
189              
190             # The equinox is everything after the J.
191 525         1415 my $equinox = $1;
192              
193             # Wind the RA/Dec to J2000 if the equinox isn't 2000.
194 525 50       1791 if( $equinox != 2000 ) {
195 0         0 ($ra, $dec) = Astro::PAL::palPreces( 'FK5', $equinox, '2000.0', $ra, $dec );
196             }
197              
198             # Get the epoch. If it's not given (in $args{epoch}) then it's
199             # the same as the equinox.
200             my $epoch = ( ( exists( $args{epoch} ) && defined( $args{epoch} ) ) ?
201             $args{epoch} :
202 525 50 33     1861 $equinox );
203              
204             # Wind the RA/Dec to epoch 2000.0 if the epoch isn't 2000.0,
205             # taking the proper motion and parallax into account.
206 525 0 0     1493 if( $epoch != 2000 &&
      33        
207             ( $pm1 != 0 || $pm2 != 0 || $parallax != 0 ) ) {
208             # Assume we are HEL without checking
209 0 0 0     0 my $rv = ( exists $args{rv} && $args{rv} ? $args{rv} : 0);
210              
211 0 0 0     0 warnings::warnif('Proper motion specified without parallax')
      0        
212             if ( $pm1 != 0 || $pm2 != 0 ) && ! $parallax;
213              
214 0         0 ( $ra, $dec ) = Astro::PAL::palPm( $ra, $dec,
215             Astro::PAL::DAS2R * $pm1,
216             Astro::PAL::DAS2R * $pm2,
217             $parallax,
218             $rv,
219             $epoch, # input epoch
220             2000.0, # output epoch
221             );
222             }
223              
224             } elsif ($args{type} =~ /^b([0-9\.]+)/i) {
225 501 50 33     2280 return undef unless exists $args{ra} and exists $args{dec};
226 501 50 33     1922 return undef unless defined $args{ra} and defined $args{dec};
227              
228 501         894 $native = 'radec1950';
229 501         986 $ra = $args{ra};
230 501         842 $dec = $args{dec};
231              
232             # The equinox is everything after the B.
233 501         1421 my $equinox = $1;
234              
235             # Get the epoch. If it's not given (in $args{epoch}) then it's
236             # the same as the equinox. Assume supplied epoch is Besselian
237             my $epoch = ( ( exists( $args{epoch} ) && defined( $args{epoch} ) ) ?
238             $args{epoch} :
239 501 100 66     1519 $equinox );
240              
241 501         922 my ( $ra0, $dec0 );
242              
243             # For the implementation details, see section 4.1 of SUN/67.
244 501 50 66     2852 if( $pm1 != 0 || $pm2 != 0 || $parallax != 0 ) {
      66        
245             # Assume we are HEL without checking
246 1 50 33     8 my $rv = ( exists $args{rv} && $args{rv} ? $args{rv} : 0);
247              
248 1 50 33     6 warnings::warnif('Proper motion specified without parallax')
      33        
249             if ( $pm1 != 0 || $pm2 != 0 ) && ! $parallax;
250              
251             # We are converting to J2000 but we need to convert that to Besselian epoch
252 1         14 ($ra, $dec) = Astro::PAL::palPm( $ra, $dec,
253             Astro::PAL::DAS2R * $pm1,
254             Astro::PAL::DAS2R * $pm2,
255             $parallax,
256             $rv,
257             $epoch,
258             Astro::PAL::palEpco('B','J',2000.0), # Besselian epoch
259             );
260             }
261              
262 501 100       1572 if( $equinox != 1950 ) {
263              
264             # Remove the E-terms for the specified Besselian equinox
265 2         20 ($ra, $dec) = Astro::PAL::palSubet( $ra, $dec, $equinox );
266              
267             # Wind the RA/Dec to B1950 if the equinox isn't 1950.
268 2         21 ($ra, $dec) = Astro::PAL::palPreces( 'FK4', $equinox, 1950.0, $ra, $dec );
269              
270             # Add the E-terms back in.
271 2         13 ($ra, $dec) = Astro::PAL::palAddet( $ra, $dec, 1950.0 );
272             }
273              
274             # Convert to J2000, no proper motion. We need the epoch at which the
275             # coordinate was valid
276 501         4891 ($ra, $dec) = Astro::PAL::palFk45z($ra, $dec, $epoch );
277              
278             } elsif ($args{type} =~ /^gal/i) {
279 3         6 $native = 'glonglat';
280 3 50 33     33 return undef unless exists $args{long} and exists $args{lat};
281 3 50 33     15 return undef unless defined $args{long} and defined $args{lat};
282              
283 3         22 ($ra, $dec) = Astro::PAL::palGaleq( $args{long}, $args{lat} );
284              
285             } elsif ($args{type} =~ /^supergal/i) {
286 0 0 0     0 return undef unless exists $args{long} and exists $args{lat};
287 0 0 0     0 return undef unless defined $args{long} and defined $args{lat};
288              
289 0         0 $native = 'sglonglat';
290 0         0 my ($glong, $glat) = Astro::PAL::palSupgal( $args{long}, $args{lat});
291 0         0 ($ra, $dec) = Astro::PAL::palGaleq( $glong, $glat );
292              
293             } else {
294 0 0       0 my $type = (defined $args{type} ? $args{type} : "<undef>");
295 0         0 croak "Supplied coordinate type [$type] not recognized";
296             }
297              
298             # Now the actual object
299             my $c = bless { ra2000 => new Astro::Coords::Angle::Hour($ra, units => 'rad', range => '2PI'),
300             dec2000 => new Astro::Coords::Angle($dec, units => 'rad'),
301             name => $args{name},
302             pm => $args{pm}, parallax => $args{parallax}
303 1029         3900 }, $class;
304              
305             # Specify the native encoding
306 1029         3880 $c->native( $native );
307              
308             # Now set the velocity parameters
309 1029 100       2067 if (exists $args{redshift}) {
310 1         8 $c->_set_redshift( $args{redshift} );
311             } else {
312 1028 100       2136 $c->_set_rv( $args{rv} ) if exists $args{rv};
313 1028 100       2259 $c->_set_vdefn( $args{vdefn} ) if exists $args{vdefn};
314 1028 100       2254 $c->_set_vframe( $args{vframe} ) if exists $args{vframe};
315             }
316              
317 1029         4354 return $c;
318             }
319              
320              
321             =back
322              
323             =head2 Accessor Methods
324              
325             =over 4
326              
327             =item B<radec>
328              
329             Retrieve the Right Ascension and Declination (FK5 J2000) for the date
330             stored in the C<datetime> method. Defaults to current date if no time
331             is stored in the object.
332              
333             ($ra, $dec) = $c->radec();
334              
335             For J2000 coordinates without proper motions or parallax, this will
336             return the same values as returned from the C<radec2000> method.
337              
338             An explicit equinox can be supplied as either Besselian or Julian
339             epoch:
340              
341             ($ra, $dec) = $c->radec( 'B1950' );
342             ($ra, $dec) = $c->radec( 'J2050' );
343             ($ra, $dec) = $c->radec( 'B1900' );
344              
345             Defaults to 'J2000'. Note that the epoch (as stored in the C<datetime>
346             attribute) is required when converting from FK5 to FK4 so calling this
347             method with 'B1950' will not be the same as calling the C<radec1950>
348             method unless the C<datetime> epoch is B1950.
349              
350             Coordinates are returned as two C<Astro::Coords::Angle> objects.
351              
352             =cut
353              
354             sub radec {
355 107     107 1 650 my $self = shift;
356 107   100     516 my ($sys, $equ) = $self->_parse_equinox( shift || 'J2000' );
357              
358             # If we have proper motions we need to take them into account
359             # Do this using palPm rather than via the base class since it
360             # must be more efficient than going through apparent
361 107         309 my @pm = $self->pm;
362 107         235 my $par = $self->parallax;
363              
364             # First convert to J2000 current epoch
365              
366             # Fix PM array and parallax if none-defined
367 107 100       294 @pm = (0,0) unless @pm;
368 107 100       228 $par = 0 unless defined $par;
369              
370             # J2000 Epoch 2000.0
371 107         210 my ($ra,$dec) = $self->radec2000();
372 107 50 66     610 if ($pm[0] != 0 || $pm[1] != 0 || $par != 0) {
      66        
373             # We have proper motions
374             # Radial velocity in HEL frame
375             # Note that we need to calculate the RA/Dec to get the HEL frame
376             # if the radial velocity is not already in HEL
377             # We have to ignore it for now and only use rv if it is
378             # already heliocentric
379 3         6 my $rv = 0;
380 3 50       12 $rv = $self->rv if $self->vframe eq 'HEL';
381              
382             # Correct for proper motion
383 3         14 ($ra, $dec) = Astro::PAL::palPm( $ra, $dec, Astro::PAL::DAS2R * $pm[0],
384             Astro::PAL::DAS2R * $pm[1], $par, $rv, 2000.0,
385             Astro::PAL::palEpj($self->_mjd_tt));
386              
387             # Convert to Angle objects
388 3         16 $ra = new Astro::Coords::Angle::Hour( $ra, units => 'rad', range => '2PI');
389 3         15 $dec = new Astro::Coords::Angle( $dec, units => 'rad' );
390             }
391              
392             # Return it if we have the right answer
393 107 100 66     470 if ($sys eq 'FK5' && $equ == 2000.0) {
    50          
394             # Already have the right answer
395             } elsif ($sys eq 'FK5') {
396             # Preces to new equinox
397 0         0 ($ra, $dec) = Astro::PAL::palPreces( 'FK5', 2000.0, $equ, $ra, $dec );
398              
399             } else {
400             # Convert to BYYYY
401 2         9 ($ra, $dec) = $self->_j2000_to_byyyy( $equ, $ra, $dec);
402              
403             }
404              
405 107         335 return (new Astro::Coords::Angle::Hour($ra, units => 'rad', range => '2PI'),
406             new Astro::Coords::Angle($dec, units => 'rad'));
407              
408             }
409              
410              
411             =item B<ra>
412              
413             Retrieve the Right Ascension (FK5 J2000) for the date stored in the
414             C<datetime> method. Defaults to current date if no time is stored
415             in the object.
416              
417             $ra = $c->ra( format => 's' );
418              
419             For J2000 coordinates without proper motions or parallax, this will
420             return the same values as returned from the C<ra2000> method.
421              
422             See L<Astro::Coords/"NOTES"> for details on the supported format
423             specifiers and default calling convention.
424              
425             =cut
426              
427             sub ra {
428 9     9 1 2733 my $self = shift;
429 9         33 my %opt = @_;
430 9         66 my ($ra, $dec) = $self->radec;
431 9         42 my $retval = $ra->in_format( $opt{format} );
432              
433             # Tidy up array to remove sign
434 9 100       41 shift(@$retval) if ref($retval) eq "ARRAY";
435 9         62 return $retval;
436             }
437              
438             =item B<dec>
439              
440             Retrieve the Declination (FK5 J2000) for the date stored in the
441             C<datetime> method. Defaults to current date if no time is stored
442             in the object.
443              
444             $dec = $c->dec( format => 's' );
445              
446             For J2000 coordinates without proper motions or parallax, this will
447             return the same values as returned from the C<dec2000> method.
448              
449             See L<Astro::Coords/"NOTES"> for details on the supported format
450             specifiers and default calling convention.
451              
452             =cut
453              
454             sub dec {
455 10     10 1 31 my $self = shift;
456 10         34 my %opt = @_;
457 10         35 my ($ra, $dec) = $self->radec;
458 10         40 return $dec->in_format( $opt{format} );
459             }
460              
461             =item B<radec2000>
462              
463             Retrieve the Right Ascension (FK5 J2000, epoch 2000.0). Default
464             is to return it as an C<Astro::Coords::Angle::Hour> object.
465              
466             Proper motions and parallax are taken into account (although this may
467             happen in the object constructor). Use the C<radec> method if you want
468             J2000, reference epoch.
469              
470             ($ra, $dec) = $c->radec2000;
471              
472             Results are returned as C<Astro::Coords::Angle> objects.
473              
474             =cut
475              
476             sub radec2000 {
477 112     112 1 161 my $self = shift;
478 112         217 return ($self->ra2000, $self->dec2000);
479             }
480              
481             =item B<ra2000>
482              
483             Retrieve the Right Ascension (FK5 J2000, epoch 2000.0). Default
484             is to return it as an C<Astro::Coords::Angle::Hour> object.
485              
486             Proper motions and parallax are taken into account (although this may
487             happen in the object constructor). Use the C<ra> method if you want
488             J2000, reference epoch.
489              
490             $ra = $c->ra2000( format => "s" );
491              
492             See L<Astro::Coords/"NOTES"> for details on the supported format
493             specifiers and default calling convention.
494              
495             =cut
496              
497             sub ra2000 {
498 2729     2729 1 4014 my $self = shift;
499 2729         4639 my %opt = @_;
500 2729         4546 my $ra = $self->{ra2000};
501 2729         10097 my $retval = $ra->in_format( $opt{format} );
502              
503             # Tidy up array
504 2729 50       9287 shift(@$retval) if ref($retval) eq "ARRAY";
505 2729         6043 return $retval;
506             }
507              
508             =item B<dec2000>
509              
510             Retrieve the declination (FK5 J2000, epoch 2000.0). Default
511             is to return it in radians.
512              
513             $dec = $c->dec( format => "sexagesimal" );
514              
515             Proper motions and parallax are taken into account (although this may
516             happen in the object constructor). Use the C<dec> method if you want
517             J2000, reference epoch.
518              
519             See L<Astro::Coords/"NOTES"> for details on the supported format
520             specifiers and default calling convention.
521              
522             =cut
523              
524             sub dec2000 {
525 2729     2729 1 4450 my $self = shift;
526 2729         4326 my %opt = @_;
527 2729         4398 my $dec = $self->{dec2000};
528 2729         8232 return $dec->in_format( $opt{format} );
529             }
530              
531              
532             =item B<parallax>
533              
534             Retrieve (or set) the parallax of the target. Units should be
535             given in arcseconds. There is no default.
536              
537             $par = $c->parallax();
538             $c->parallax( 0.13 );
539              
540             =cut
541              
542             sub parallax {
543 5762     5762 1 8626 my $self = shift;
544 5762 50       11177 if (@_) {
545 0         0 $self->{parallax} = shift;
546             }
547 5762         13610 return $self->{parallax};
548             }
549              
550             =item B<pm>
551              
552             Proper motions in units of arcsec / Julian year (not corrected for
553             declination).
554              
555             @pm = $self->pm();
556             $self->pm( $pm1, $pm2);
557              
558             If the proper motions are not defined, an empty list will be returned.
559              
560             If non-zero proper motions are supplied then a non-zero
561             parallax must also be supplied.
562              
563             =cut
564              
565             sub pm {
566 5762     5762 1 8110 my $self = shift;
567 5762 50       11259 if (@_) {
568 0         0 my $pm1 = shift;
569 0         0 my $pm2 = shift;
570 0 0       0 if (!defined $pm1) {
571 0         0 warnings::warnif("Proper motion 1 not defined. Using 0.0 arcsec/year");
572 0         0 $pm1 = 0.0;
573             }
574 0 0       0 if (!defined $pm2) {
575 0         0 warnings::warnif("Proper motion 2 not defined. Using 0.0 arcsec/year");
576 0         0 $pm2 = 0.0;
577             }
578 0         0 $self->{pm} = [ $pm1, $pm2 ];
579              
580 0         0 my $parallax = $self->parallax;
581 0 0 0     0 warnings::warnif('Proper motion specified without parallax')
      0        
582             if ( $pm1 != 0 || $pm2 != 0 ) && ! $parallax;
583             }
584 5762 100       11536 if( !defined( $self->{pm} ) ) { $self->{pm} = []; }
  1021         1990  
585 5762         7927 return @{ $self->{pm} };
  5762         15432  
586             }
587              
588             =back
589              
590             =head2 General Methods
591              
592             =over 4
593              
594             =item B<apparent>
595              
596             Return the apparent RA and Dec as two C<Astro::Coords::Angle> objects for the current
597             coordinates and time.
598              
599             ($ra_app, $dec_app) = $self->apparent();
600              
601             =cut
602              
603             sub apparent {
604 2634     2634 1 4152 my $self = shift;
605              
606             # Assumes that Parallax and proper motions are constants for this object
607 2634         5432 my ($ra_app, $dec_app) = $self->_cache_read( "RA_APP", "DEC_APP" );
608              
609 2634 100 66     6768 if (!defined $ra_app || !defined $dec_app) {
610              
611 2616         5709 my $ra = $self->ra2000;
612 2616         5655 my $dec = $self->dec2000;
613 2616         8639 my $mjd = $self->_mjd_tt;
614 2616         5629 my $par = $self->parallax;
615 2616         4875 my @pm = $self->pm;
616              
617 2616 50       7094 @pm = (0,0) unless @pm;
618 2616 50       6037 $par = 0.0 unless defined $par;
619              
620             # do not attempt to correct for radial velocity unless we are doing parallax or
621             # proper motion correction
622 2616         3721 my $rv = 0;
623 2616 50 33     12103 if ($par != 0 || $pm[0] != 0 || $pm[1] != 0 ) {
      33        
624             # Radial velocity in HEL frame
625             # Note that we need to calculate the apparent RA/Dec to get the HEL frame
626             # if the radial velocity is not already in HEL
627             # We have to ignore it for now and only use rv if it is heliocentric
628 0 0       0 $rv = $self->rv if $self->vframe eq 'HEL';
629             }
630              
631 2616         12247 ($ra_app, $dec_app) = Astro::PAL::palMap( $ra, $dec,
632             Astro::PAL::DAS2R * $pm[0],
633             Astro::PAL::DAS2R * $pm[1], $par, $rv, 2000.0, $mjd );
634              
635 2616         13091 $ra_app = new Astro::Coords::Angle::Hour($ra_app, units => 'rad', range => '2PI');
636 2616         6838 $dec_app = new Astro::Coords::Angle($dec_app, units => 'rad');
637              
638 2616         8201 $self->_cache_write( "RA_APP" => $ra_app, "DEC_APP" => $dec_app );
639             }
640              
641 2634         6904 return ($ra_app, $dec_app);
642             }
643              
644             =item B<array>
645              
646             Return back 11 element array with first 3 elements being the
647             coordinate type (RADEC) and the ra/dec coordinates in J2000
648             epoch 2000.0 (radians).
649              
650             This method returns a standardised set of elements across all
651             types of coordinates.
652              
653             =cut
654              
655             sub array {
656 3     3 1 13 my $self = shift;
657 3         9 my ($ra, $dec) = $self->radec2000;
658 3         23 return ( $self->type, $ra->radians, $dec->radians,
659             undef, undef, undef, undef, undef, undef, undef, undef);
660             }
661              
662             =item B<type>
663              
664             Returns the generic type associated with the coordinate system.
665             For this class the answer is always "RADEC".
666              
667             This is used to aid construction of summary tables when using
668             mixed coordinates.
669              
670             =cut
671              
672             sub type {
673 5     5 1 17 return "RADEC";
674             }
675              
676             =item B<stringify>
677              
678             A string representation of the object.
679              
680             Returns RA and Dec (J2000) in string format.
681              
682             =cut
683              
684             sub stringify {
685 5     5 1 791 my $self = shift;
686 5         21 my ($ra, $dec) = $self->radec();
687 5         25 return "$ra $dec";
688             }
689              
690             =item B<summary>
691              
692             Return a one line summary of the coordinates.
693             In the future will accept arguments to control output.
694              
695             $summary = $c->summary();
696              
697             =cut
698              
699             sub summary {
700 0     0 1 0 my $self = shift;
701 0         0 my $name = $self->name;
702 0 0       0 $name = '' unless defined $name;
703 0         0 my ($ra, $dec) = $self->radec;
704              
705 0         0 return sprintf("%-16s %-12s %-13s J2000",$name,$ra, $dec);
706             }
707              
708             =item B<set_vel_pars>
709              
710             Set the velocity parameters.
711              
712             $c->set_vel_pars( $rv, $vdefn, $vframe );
713              
714             This does not include redshift.
715              
716             =cut
717              
718             sub set_vel_pars {
719 0     0 1 0 my $self = shift;
720 0         0 my ($rv, $vdefn, $vframe) = @_;
721              
722 0 0       0 $self->_set_rv( $rv ) if defined $rv;
723 0 0       0 $self->_set_vdefn( $vdefn ) if defined $vdefn;
724 0 0       0 $self->_set_vframe( $vframe ) if defined $vframe;
725              
726 0         0 return;
727             }
728              
729             =back
730              
731             =begin __PRIVATE_METHODS__
732              
733             =head2 Private Methods
734              
735             =over 4
736              
737             =item B<_calc_mtime>
738              
739             Calculate meridian time, in the direction specified by C<$event>
740             (-1 before, +1 after).
741              
742             $mtime = $self->_calc_mtime($reftime, $event);
743              
744             This is a non-iterative version of Astro::Coords::_calc_mtime,
745             for the simplest case. It calls the superclass method if
746             proper motion or parallax are involved.
747              
748             =cut
749              
750             sub _calc_mtime {
751 1492     1492   2396 my $self = shift;
752 1492 50 33     3480 return $self->SUPER::_calc_mtime(@_)
753             if $self->parallax() or $self->pm();
754              
755 1492         3620 my ($reftime, $event ) = @_;
756              
757             # event must be 1 or -1
758 1492 50 66     5950 if (!defined $event || ($event != 1 && $event != -1)) {
      33        
759 0         0 croak "Event must be either +1 or -1";
760             }
761              
762             # do we have DateTime objects
763 1492         3694 my $dtime = $self->_isdt();
764              
765 1492         3665 my $mtime = $self->_local_mtcalc();
766 1492         1405835 my $diff = $mtime->epoch - $reftime->epoch;
767              
768 1492 100 100     24914 if (($diff >= 0 and $event == +1)
      100        
      100        
769             or ($diff <= 0 and $event == -1)) {
770 780         2615 return $mtime;
771             }
772             else {
773             # We went the wrong way.
774 712 100       1660 if ($dtime) {
775 708         2392 $mtime->add(seconds => $event * $self->_sidereal_period());
776             } else {
777 4         17 $mtime = $mtime + ($event * $self->_sidereal_period());
778             }
779             }
780 712         636361 return $mtime;
781             }
782              
783             =item B<_iterative_el>
784              
785             For the simplest case, the initial guess should have been good enough,
786             so iterating would not be necessary. Therefore if there is no
787             proper motion or parallax, this subroutine does nothing.
788              
789             See L<Astro::Coords/_iterative_el>.
790              
791             =cut
792              
793              
794             sub _iterative_el {
795 1547     1547   2458 my $self = shift;
796 1547 50 33     3374 return $self->SUPER::_iterative_el(@_)
797             if $self->parallax() or $self->pm();
798              
799             # Check that the elevation is indeed correct:
800             # (Should not be necessary, remove if it wastes too much time.)
801 1547         3993 my ($refel, undef) = @_;
802 1547         4044 my $el = $self->el();
803 1547         3731 my $tol = 30 * Astro::PAL::DAS2R;
804 1547 100       4682 return $self->SUPER::_iterative_el(@_)
805             if (abs($el - $refel) > $tol);
806              
807 1546         4658 return 1;
808             }
809              
810             =back
811              
812             =end __PRIVATE_METHODS__
813              
814             =head1 NOTES
815              
816             Usually called via C<Astro::Coords>.
817              
818             =head1 REQUIREMENTS
819              
820             C<Astro::PAL> is used for all internal astrometric calculations.
821              
822             =head1 AUTHOR
823              
824             Tim Jenness E<lt>tjenness@cpan.orgE<gt>
825              
826             Proper motion, equinox and epoch support added by Brad Cavanagh
827             <b.cavanagh@jach.hawaii.edu>
828              
829             =head1 COPYRIGHT
830              
831             Copyright (C) 2001-2005 Particle Physics and Astronomy Research Council.
832             All Rights Reserved.
833              
834             This program is free software; you can redistribute it and/or modify it under
835             the terms of the GNU General Public License as published by the Free Software
836             Foundation; either version 3 of the License, or (at your option) any later
837             version.
838              
839             This program is distributed in the hope that it will be useful,but WITHOUT ANY
840             WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
841             PARTICULAR PURPOSE. See the GNU General Public License for more details.
842              
843             You should have received a copy of the GNU General Public License along with
844             this program; if not, write to the Free Software Foundation, Inc., 59 Temple
845             Place,Suite 330, Boston, MA 02111-1307, USA
846              
847             =cut
848              
849             1;