File Coverage

blib/lib/Astro/Coords/Fixed.pm
Criterion Covered Total %
statement 85 93 91.4
branch 16 24 66.6
condition 9 21 42.8
subroutine 17 21 80.9
pod 13 13 100.0
total 140 172 81.4


line stmt bran cond sub pod time code
1             package Astro::Coords::Fixed;
2              
3             =head1 NAME
4              
5             Astro::Coords::Fixed - Manipulate coordinates that are fixed on the sky
6              
7             =head1 SYNOPSIS
8              
9             $c = new Astro::Coords::Fixed( az => 180,
10             el => 45,
11             units => 'degrees');
12              
13             $c = new Astro::Coords::Fixed( ha => '02:30:00.0',
14             dec => '45:30:03',
15             units => 'sexagesimal',
16             tel => $telescope,
17             );
18              
19             =head1 DESCRIPTION
20              
21             This subclass of C<Astro::Coords> allows for the manipulation
22             of coordinates that are fixed on the sky. Sometimes a telescope
23             should be commanded to go to a fixed location (eg for a calibration)
24             and this class puts those coordinates (Azimuth and elevation for telescopes
25             such as JCMT and Gemini and Hour Angle and Declination for equatorial
26             telescopes such as UKIRT) on the same footing as astronomical coordinates.
27              
28             Note that Azimuth and elevation do not require the telescope latitude
29             whereas Hour Angle and declination does.
30              
31             =cut
32              
33              
34 19     19   6688985 use 5.006;
  19         101  
35 19     19   119 use strict;
  19         73  
  19         595  
36 19     19   102 use warnings;
  19         57  
  19         690  
37 19     19   113 use Carp;
  19         44  
  19         1792  
38              
39             our $VERSION = '0.21';
40              
41 19     19   1718 use Astro::PAL ();
  19         12160  
  19         574  
42 19     19   1127 use Astro::Coords::Angle;
  19         45  
  19         528  
43 19     19   118 use base qw/ Astro::Coords /;
  19         66  
  19         3711  
44              
45 19     19   135 use overload '""' => "stringify";
  19         35  
  19         109  
46              
47             =head1 METHODS
48              
49             =head2 Constructor
50              
51             =over 4
52              
53             =item B<new>
54              
55             Constructor. Recognizes hash keys "ha", "dec" and "az", "el".
56              
57             $c = new Astro::Coords::Fixed( az => 35, el => 30 );
58              
59             $c = new Astro::Coords::Fixed( ha => $ha, dec => $dec, tel => $tel);
60              
61             Usually called via C<Astro::Coords> rather than directly.
62              
63             Note that the declination is equivalent to "Apparent Dec" used
64             elsewhere in these classes.
65              
66             Azimuth and Elevation is the internal format. Currently there is no
67             caching (so there is always overhead converting to apparent
68             RA and Dec) since there is no cache flushing when the telescope
69             is changed.
70              
71             A telescope is required (in the form of an C<Astro::Telescope> object)
72             if the position is specified as HA/Dec.
73              
74             A reference to a 2-element array can be given to specify different units
75             for the two coordinates, e.g. C<['hours', 'degrees']>.
76              
77             A name can be associated with this position.
78              
79             =cut
80              
81             sub new {
82 13     13 1 29 my $proto = shift;
83 13   33     59 my $class = ref($proto) || $proto;
84              
85 13         40 my %args = @_;
86              
87             # We will always calculate ha, dec, az and el
88 13         24 my ($az, $el);
89              
90             # Create a new object
91 13         30 my $c = bless { }, $class;
92              
93             # Store the telescope if we have one
94 13 100       45 $c->telescope( $args{tel} ) if exists $args{tel};
95              
96 13 100       83 my ($unit_c1, $unit_c2) = (ref $args{'units'}) ? @{$args{'units'}} : ($args{'units'}) x 2;
  3         9  
97              
98 13 100 66     121 if (exists $args{ha} && exists $args{dec} and exists $args{tel}
    50 33        
      33        
      33        
99             and UNIVERSAL::isa($args{tel}, "Astro::Telescope")) {
100             # HA and Dec
101              
102             # Convert input args to radians
103 3         14 my $ha = Astro::Coords::Angle::Hour->to_radians($args{ha}, $unit_c1);
104 3         11 my $dec = Astro::Coords::Angle->to_radians($args{dec}, $unit_c2);
105              
106             # Convert to "native" format
107 3         11 my $lat = $args{tel}->lat;
108 3         40 ($az, $el) = Astro::PAL::palDe2h( $ha, $dec, $lat );
109              
110 3         10 $az = new Astro::Coords::Angle( $az, units => 'rad', range => '2PI');
111 3         8 $el = new Astro::Coords::Angle( $el, units => 'rad');
112              
113             # native form
114 3         8 $c->native( 'hadec' );
115              
116             } elsif (exists $args{az} and exists $args{el}) {
117             # Az and El
118              
119             # Convert input args to radians
120 10         49 $az = new Astro::Coords::Angle( $args{az}, units => $unit_c1,
121             range => '2PI' );
122 10         51 $el = new Astro::Coords::Angle( $args{el}, units => $unit_c2);
123              
124             # native form
125 10         78 $c->native( 'azel' );
126              
127             } else {
128 0         0 return undef;
129             }
130              
131             # Store the name
132 13 50       42 $c->name( $args{name} ) if exists $args{name};
133              
134             # Store it in the object
135 13         60 $c->azel( $az, $el );
136              
137 13         57 return $c;
138             }
139              
140              
141             =back
142              
143             =head2 Accessor Methods
144              
145             =over 4
146              
147             =item B<azel>
148              
149             Return azimuth and elevation (as two C<Astro::Coords::Angle> objects);
150              
151             ($az, $el) = $c->azel;
152              
153             Can also be used to store the azimuth and elevation
154             (as C<Astro::Coords::Angle> objects)
155              
156             $c->_azel( $az, $el);
157              
158             =cut
159              
160             sub azel {
161 37     37 1 70 my $self = shift;
162 37 100       74 if (@_) {
163 13         32 my ($az, $el) = @_;
164 13 50       59 croak "Azimuth not an Astro::Coords::Angle object"
165             unless UNIVERSAL::isa( $az, "Astro::Coords::Angle");
166 13 50       37 croak "Elevation not an Astro::Coords::Angle object"
167             unless UNIVERSAL::isa( $el, "Astro::Coords::Angle");
168 13         27 $self->{Az} = $az;
169 13         26 $self->{El} = $el;
170             }
171 37         78 return ($self->{Az}, $self->{El});
172             }
173              
174             =back
175              
176             =head2 General Methods
177              
178             =over 4
179              
180             =item B<type>
181              
182             Returns the generic type associated with the coordinate system.
183             For this class the answer is always "FIXED".
184              
185             This is used to aid construction of summary tables when using
186             mixed coordinates.
187              
188             =cut
189              
190             sub type {
191 2     2 1 15 return "FIXED";
192             }
193              
194             =item B<stringify>
195              
196             Returns a string representation of the object. Returns
197             Azimth and Elevation in degrees.
198              
199             =cut
200              
201             sub stringify {
202 1     1 1 18 my $self = shift;
203 1         9 my $az = $self->az( format => "degrees" );
204 1         8 my $el = $self->el( format => "degrees" );
205 1         46 return "$az $el";
206             }
207              
208             =item B<summary>
209              
210             Return a one line summary of the coordinates.
211             In the future will accept arguments to control output.
212              
213             $summary = $c->summary();
214              
215             =cut
216              
217             sub summary {
218 0     0 1 0 my $self = shift;
219 0         0 my $name = $self->name;
220 0 0       0 $name = '' unless defined $name;
221 0         0 return sprintf("%-16s %-12s %-13s AZEL",$name,
222             $self->az(format=>"s"),
223             $self->el(format =>"s"));
224             }
225              
226             =item B<array>
227              
228             Array summarizing the object. Retuns
229             Return back 11 element array with first 3 elements being the
230             coordinate type (FIXED) and the az/el coordinates
231             (radians).
232              
233             This method returns a standardised set of elements across all
234             types of coordinates.
235              
236             =cut
237              
238             sub array {
239 1     1 1 11 my $self = shift;
240 1         5 my ($az, $el) = $self->azel();
241 1         4 return ( $self->type, $az->radians, $el->radians,
242             undef, undef, undef, undef, undef, undef, undef, undef);
243             }
244              
245             =item B<ha>
246              
247             Get the hour angle for the currently stored LST. By default
248             returns format as for other angular methods.
249              
250             $ha = $c->ha;
251             $ha = $c->ha( format => "deg" );
252              
253             =cut
254              
255             sub ha {
256 3     3 1 1864 my $self = shift;
257 3         10 my %opt = @_;
258 3         10 my $ha = ($self->hadec)[0];
259 3         14 return $ha->in_format( $opt{format} );
260             }
261              
262             =item B<apparent>
263              
264             Return the apparent RA and Dec (as two C<Astro::Coords::Angle> objects)
265             for the current time [note that the apparent declination
266             is fixed and the apparent RA changes].
267              
268             If no telescope is present the equator is used.
269              
270             =cut
271              
272             sub apparent {
273 4     4 1 8 my $self = shift;
274              
275 4         14 my ($ra_app, $dec_app) = $self->_cache_read( "RA_APP", "DEC_APP" );
276              
277 4 50 33     18 if (!defined $ra_app || !defined $dec_app) {
278              
279 4         14 (my $ha, $dec_app) = $self->hadec;
280 4         21 $ra_app = $self->_lst - $ha->radians;
281 4         18 $ra_app = new Astro::Coords::Angle::Hour( $ra_app, units => 'rad', range => '2PI' );
282              
283             # should not cache the DEC_APP since we did not calculate it
284 4         16 $self->_cache_write( "RA_APP" => $ra_app );
285             }
286              
287 4         12 return( $ra_app, $dec_app);
288             }
289              
290             =item B<hadec>
291              
292             Return the Hour angle and apparent declination (as two C<Astro::Coords::Angle> objects).
293             If no telescope is present the equator is used.
294              
295             ($ha, $dec) = $c->hadec;
296              
297             =cut
298              
299             sub hadec {
300 10     10 1 34 my $self = shift;
301              
302 10         32 my ($ha, $dec_app) = $self->_cache_read( "HA", "DEC_APP" );
303              
304 10 100 66     39 if (!defined $ha || !defined $dec_app) {
305              
306 7         17 my ($az, $el) = $self->azel;
307 7         21 my $tel = $self->telescope;
308 7 50       33 my $lat = ( defined $tel ? $tel->lat : 0.0);
309              
310             # First need to get the hour angle and declination from the Az and El
311 7         64 ($ha, $dec_app) = Astro::PAL::palDh2e($az->radians, $el->radians, $lat );
312              
313 7         28 $ha = new Astro::Coords::Angle::Hour( $ha, units => 'rad', range => 'PI');
314 7         33 $dec_app = new Astro::Coords::Angle( $dec_app, units => 'rad');
315              
316 7         39 $self->_cache_write( "HA" => $ha, "DEC_APP" => $dec_app );
317             }
318              
319 10         35 return ($ha, $dec_app);
320             }
321              
322             =item B<ha_set>
323              
324             For a fixed source, the setting Hour Angle has no meaning.
325              
326             =cut
327              
328             sub ha_set {
329 0     0 1 0 return ();
330             }
331              
332             =item B<meridian_time>
333              
334             Meridian time is not defined for a fixed source.
335              
336             =cut
337              
338             sub meridian_time {
339 0     0 1 0 return ();
340             }
341              
342             =item B<transit_el>
343              
344             Transit elevation is not defined for a fixed source. Always returns undef.
345              
346             =cut
347              
348             sub transit_el {
349 0     0 1 0 return ();
350             }
351              
352             =item B<apply_offset>
353              
354             Overrided method to prevent C<Astro::Coords::apply_offset> being
355             called on this subclass.
356              
357             =cut
358              
359             sub apply_offset {
360 1     1 1 218 croak 'apply_offset: attempting to apply an offset to fixed coordinates';
361             }
362              
363             =back
364              
365             =head1 NOTES
366              
367             Usually called via C<Astro::Coords>.
368              
369             =head1 REQUIREMENTS
370              
371             C<Astro::PAL> is used for all internal astrometric calculations.
372              
373             =head1 AUTHOR
374              
375             Tim Jenness E<lt>tjenness@cpan.orgE<gt>
376              
377             =head1 COPYRIGHT
378              
379             Copyright (C) 2001-2005 Particle Physics and Astronomy Research Council.
380             All Rights Reserved.
381              
382             This program is free software; you can redistribute it and/or modify it under
383             the terms of the GNU General Public License as published by the Free Software
384             Foundation; either version 3 of the License, or (at your option) any later
385             version.
386              
387             This program is distributed in the hope that it will be useful,but WITHOUT ANY
388             WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
389             PARTICULAR PURPOSE. See the GNU General Public License for more details.
390              
391             You should have received a copy of the GNU General Public License along with
392             this program; if not, write to the Free Software Foundation, Inc., 59 Temple
393             Place,Suite 330, Boston, MA 02111-1307, USA
394              
395             =cut
396              
397             1;