File Coverage

blib/lib/Astro/Catalog/Item.pm
Criterion Covered Total %
statement 16 18 88.8
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 22 24 91.6


line stmt bran cond sub pod time code
1             package Astro::Catalog::Item;
2              
3             # ---------------------------------------------------------------------------
4              
5             #+
6             # Name:
7             # Astro::Catalog::Item
8              
9             # Purposes:
10             # Generic star in a catalogue
11              
12             # Language:
13             # Perl module
14              
15             # Description:
16             # This module provides a generic star object for the Catalog object
17              
18             # Authors:
19             # Alasdair Allan (aa@astro.ex.ac.uk)
20              
21             # Revision:
22             # $Id: Item.pm,v 1.13 2007/09/25 23:23:43 cavanagh Exp $
23              
24             # Copyright:
25             # Copyright (C) 2002 University of Exeter. All Rights Reserved.
26              
27             #-
28              
29             # ---------------------------------------------------------------------------
30              
31             =head1 NAME
32              
33             Astro::Catalog::Item - A generic star object in a stellar catalogue.
34              
35             =head1 SYNOPSIS
36              
37             $star = new Astro::Catalog::Item(
38             ID => $id,
39             Coords => new Astro::Coords(),
40             Morphology => new Astro::Catalog::Item::Morphology(),
41             Fluxes => new Astro::Fluxes(),
42             Quality => $quality_flag,
43             Field => $field,
44             GSC => $in_gsc,
45             Distance => $distance_to_centre,
46             PosAngle => $position_angle,
47             X => $x_pixel_coord,
48             Y => $y_pixel_coord,
49             WCS => new Starlink::AST(),
50             Comment => $comment_string
51             SpecType => $spectral_type,
52             StarType => $star_type,
53             LongStarType => $long_star_type,
54             MoreInfo => $url,
55             InsertDate => new Time::Piece(),
56             Misc => $hash_ref,
57             );
58              
59             =head1 DESCRIPTION
60              
61             Stores generic meta-data about an individual stellar object from a catalogue.
62              
63             If the catalogue has a field center the Distance and Position Angle properties
64             should be used to store the direction to the field center, e.g. a star from the
65             USNO-A2 catalogue retrieived from the ESO/ST-ECF Archive will have these
66             properties.
67              
68             =cut
69              
70              
71             # L O A D M O D U L E S --------------------------------------------------
72              
73 13     13   851074 use 5.006;
  13         55  
  13         716  
74 13     13   89 use strict;
  13         30  
  13         782  
75 13     13   128 use warnings;
  13         36  
  13         3014  
76 13     13   76 use vars qw/ $VERSION /;
  13         25  
  13         934  
77 13     13   94 use Carp;
  13         32  
  13         1929  
78 13     13   6641 use Astro::Coords 0.12;
  0            
  0            
79             use Astro::Catalog::Item::Morphology;
80             use Astro::Fluxes;
81             use Astro::Flux;
82             use Astro::FluxColor;
83              
84             # Register an Astro::Catalog::Item warning category
85             use warnings::register;
86              
87             $VERSION = "4.31";
88              
89             # Internal lookup table for Simbad star types
90             my %STAR_TYPE_LOOKUP = (
91             'vid' => 'Underdense region of the Universe',
92             'Er*' => 'Eruptive variable Star',
93             'Rad' => 'Radio-source',
94             'Q?' => 'Possible Quasar',
95             'IR' => 'Infra-Red source',
96             'SB*' => 'Spectrocopic binary',
97             'C*' => 'Carbon Star',
98             'Gl?' => 'Possible Globular Cluster',
99             'DNe' => 'Dark Nebula',
100             'GlC' => 'Globular Cluster',
101             'No*' => 'Nova',
102             'V*?' => 'Star suspected of Variability',
103             'LeG' => 'Gravitationnaly Lensed Image of a Galaxy',
104             'mAL' => 'metallic Absorption Line system',
105             'LeI' => 'Gravitationnaly Lensed Image',
106             'WU*' => 'Eclipsing binary of W UMa type',
107             'Be*' => 'Be Star',
108             'PaG' => 'Pair of Galaxies',
109             'Mas' => 'Maser',
110             'LeQ' => 'Gravitationnaly Lensed Image of a Quasar',
111             'mul' => 'Composite object',
112             'SBG' => 'Starburst Galaxy',
113             '*' => 'Star',
114             'gam' => 'gamma-ray source',
115             'bL*' => 'Eclipsing binary of beta Lyr type',
116             'S*' => 'S Star',
117             'El*' => 'Elliptical variable Star',
118             'GNe' => 'Galactic Nebula',
119             'DQ*' => 'Cataclysmic Var. DQ Her type',
120             '?' => 'Object of unknown nature',
121             'WV*' => 'Variable Star of W Vir type',
122             'SR?' => 'SuperNova Remnant Candidate',
123             'Bla' => 'Blazar',
124             'G' => 'Galaxy',
125             'SCG' => 'Supercluster of Galaxies',
126             'OH*' => 'Star with envelope of OH/IR type',
127             'Lev' => '(Micro)Lensing Event',
128             'BNe' => 'Bright Nebula',
129             'RV*' => 'Variable Star of RV Tau type',
130             'IR0' => 'IR source at lambda < 10 microns',
131             'OVV' => 'Optically Violently Variable object',
132             'a2*' => 'Variable Star of alpha2 CVn type',
133             'IR1' => 'IR source at lambda > 10 microns',
134             'Em*' => 'Emission-line Star',
135             'PM*' => 'High proper-motion Star',
136             'X' => 'X-ray source',
137             'HzG' => 'Galaxy with high redshift',
138             'Sy*' => 'Symbiotic Star',
139             'LXB' => 'Low Mass X-ray Binary',
140             '*i*' => 'Star in double system',
141             'Sy1' => 'Seyfert 1 Galaxy',
142             'Sy2' => 'Seyfert 2 Galaxy',
143             'LIN' => 'LINER-type Active Galaxy Nucleus',
144             'rG' => 'Radio Galaxy',
145             'Cl*' => 'Cluster of Stars',
146             'NL*' => 'Nova-like Star',
147             'HV*' => 'High-velocity Star',
148             'EmG' => 'Emission-line galaxy',
149             '*iA' => 'Star in Association',
150             'grv' => 'Gravitational Source',
151             '*iC' => 'Star in Cluster',
152             'SyG' => 'Seyfert Galaxy',
153             'RNe' => 'Reflection Nebula',
154             'EmO' => 'Emission Object',
155             'Ce*' => 'Classical Cepheid variable Star',
156             'CV*' => 'Cataclysmic Variable Star',
157             '*iN' => 'Star in Nebula',
158             'BY*' => 'Variable of BY Dra type',
159             'Pe*' => 'Peculiar Star',
160             'AM*' => 'Cataclysmic Var. AM Her type',
161             'FU*' => 'Variable Star of FU Ori type',
162             'HVC' => 'High-velocity Cloud',
163             'ClG' => 'Cluster of Galaxies',
164             'Ir*' => 'Variable Star of irregular type',
165             'PN?' => 'Possible Planetary Nebula',
166             'ALS' => 'Absorption Line system',
167             'cm' => 'centimetric Radio-source',
168             'As*' => 'Association of Stars',
169             'V*' => 'Variable Star',
170             'Fl*' => 'Flare Star',
171             'EB*' => 'Eclipsing binary',
172             'CGG' => 'Compact Group of Galaxies',
173             'UV' => 'UV-emission source',
174             'Ro*' => 'Rotationally variable Star',
175             'SN*' => 'SuperNova',
176             'pr*' => 'Pre-main sequence Star',
177             'CH*' => 'Star with envelope of CH type',
178             'Al*' => 'Eclipsing binary of Algol type',
179             'Pu*' => 'Pulsating variable Star',
180             'Cld' => 'Cloud of unknown nature',
181             'QSO' => 'Quasar',
182             'Psr' => 'Pulsars',
183             'GiC' => 'Galaxy in Cluster of Galaxies',
184             'V* RI*' => 'Variable Star with rapid variations',
185             'sh' => 'HI shell',
186             'GiG' => 'Galaxy in Group of Galaxies',
187             'OpC' => 'Open (galactic) Cluster',
188             'WR*' => 'Wolf-Rayet Star',
189             'BCG' => 'Blue compact Galaxy',
190             'blu' => 'Blue object',
191             'GiP' => 'Galaxy in Pair of Galaxies',
192             'LyA' => 'Ly alpha Absorption Line system',
193             'CGb' => 'Cometary Globule',
194             '**' => 'Double or multiple star',
195             'H2G' => 'HII Galaxy',
196             'RR*' => 'Variable Star of RR Lyr type',
197             'HB*' => 'Horizontal Branch Star',
198             'RC*' => 'Variable Star of R CrB type',
199             'SNR' => 'SuperNova Remnant',
200             'MoC' => 'Molecular Cloud',
201             'HXB' => 'High Mass X-ray Binary',
202             'mR' => 'metric Radio-source',
203             'TT*' => 'T Tau-type Star',
204             'DN*' => 'Dwarf Nova',
205             'eg sr*' => 'Semi-regular pulsating Star',
206             'HII' => 'HII (ionized) region',
207             'HH' => 'Herbig-Haro Object',
208             'HI' => 'HI (neutral) region',
209             'WD*' => 'White Dwarf',
210             'Or*' => 'Variable Star in Orion Nebula',
211             'dS*' => 'Variable Star of delta Sct type',
212             'DLy' => 'Dumped Ly alpha Absorption Line system',
213             'AGN' => 'Active Galaxy Nucleus',
214             'GrG' => 'Group of Galaxies',
215             'Mi*' => 'Variable Star of Mira Cet type',
216             'RS*' => 'Variable of RS CVn type',
217             'mm' => 'millimetric Radio-source',
218             'red' => 'Very red source',
219             'BLL' => 'BL Lac - type object',
220             'reg' => 'Region defined in the sky',
221             'PN' => 'Planetary Nebula',
222             'ZZ*' => 'Variable White Dwarf of ZZ Cet type',
223             'gB' => 'gamma-ray Burster',
224             'PoC' => 'Part of Cloud',
225             'XB*' => 'X-ray Binary',
226             'PoG' => 'Part of a Galaxy',
227             'Neb' => 'Nebula of unknown nature'
228             );
229              
230              
231             # C O N S T R U C T O R ----------------------------------------------------
232              
233             =head1 REVISION
234              
235             $Id: Item.pm,v 1.13 2007/09/25 23:23:43 cavanagh Exp $
236              
237             =head1 METHODS
238              
239             =head2 Constructor
240              
241             =over 4
242              
243             =item B
244              
245             Create a new instance from a hash of options
246              
247              
248             $star = new Astro::Catalog::Item(
249             ID => $id,
250             Coords => new Astro::Coords(),
251             Morphology => new Astro::Catalog::Item::Morphology(),
252             Fluxes => new Astro::Fluxes(),
253             Quality => $quality_flag,
254             Field => $field,
255             GSC => $in_gsc,
256             Distance => $distance_to_centre,
257             PosAngle => $position_angle,
258             X => $x_pixel_coord,
259             Y => $y_pixel_coord,
260             Comment => $comment_string
261             SpecType => $spectral_type,
262             StarType => $star_type,
263             LongStarType => $long_star_type,
264             MoreInfo => $url,
265             InsertDate => new Time::Piece(),
266             Misc => $misc,
267             );
268              
269             returns a reference to an Astro::Catalog::Item object.
270              
271             The coordinates can also be specified as individual RA and Dec values
272             (sexagesimal format) if they are known to be J2000.
273              
274             =cut
275              
276             sub new {
277             my $proto = shift;
278             my $class = ref($proto) || $proto;
279              
280             # bless the query hash into the class
281             my $block = bless { ID => undef,
282             FLUXES => undef,
283             MORPHOLOGY => undef,
284             QUALITY => undef,
285             FIELD => undef,
286             GSC => undef,
287             DISTANCE => undef,
288             POSANGLE => undef,
289             COORDS => undef,
290             X => undef,
291             Y => undef,
292             WCS => undef,
293             COMMENT => undef,
294             SPECTYPE => undef,
295             STARTYPE => undef,
296             LONGTYPE => undef,
297             MOREINFO => undef,
298             INSERTDATE => undef,
299             PREFERRED_MAG_TYPE => undef,
300             MISC => undef,
301             }, $class;
302              
303             # If we have arguments configure the object
304             $block->configure( @_ ) if @_;
305              
306             return $block;
307              
308             }
309              
310             # A C C E S S O R --------------------------------------------------------
311              
312             =back
313              
314             =head2 Accessor Methods
315              
316             =over 4
317              
318             =item B
319              
320             Return (or set) the ID of the star
321              
322             $id = $star->id();
323             $star->id( $id );
324              
325             If an Astro::Coords object is associated with the Star, the name
326             field is set in the underlying Astro::Coords object as well as in
327             the current Star object.
328              
329             =cut
330              
331             sub id {
332             my $self = shift;
333             if (@_) {
334             $self->{ID} = shift;
335              
336             my $c = $self->coords;
337             $c->name( $self->{ID} ) if defined $c;
338             }
339             return $self->{ID};
340             }
341              
342             =item B
343              
344             Return or set the coordinates of the star as an C
345             object.
346              
347             $c = $star->coords();
348             $star->coords( $c );
349              
350             The object returned by this method is the actual object stored
351             inside this Star object and not a clone. If the coordinates
352             are changed through this object the coordinate of the star is
353             also changed.
354              
355             Currently, if you modify the RA or Dec through the ra()
356             or dec() methods of Star, the internal object associated with
357             the Star will change.
358              
359             Returns undef if the coordinates have never been specified.
360              
361             If the name() field is defined in the Astro::Coords object
362             the id() field is set in the current Star object. Similarly for
363             the comment field.
364              
365             =cut
366              
367             sub coords {
368             my $self = shift;
369             if (@_) {
370             my $c = shift;
371             croak "Coordinates must be an Astro::Coords object"
372             unless UNIVERSAL::isa($c, "Astro::Coords");
373              
374             # force the ID and comment to match
375             $self->id( $c->name ) if defined $c->name;
376             $self->comment( $c->comment ) if $c->comment;
377              
378             # Store the new coordinate object
379             # Storing it late stops looping from the id and comment methods
380             $self->{COORDS} = $c;
381              
382             }
383             return $self->{COORDS};
384             }
385              
386             =item B
387              
388             Return (or set) the current object R.A. (J2000).
389              
390             $ra = $star->ra();
391              
392             If the Star is associated with a moving object such as a planet,
393             comet or asteroid this method will return the J2000 RA associated
394             with the time and observer position associated with the coordinate
395             object itself (by default current time, longitude of 0 degrees).
396             Returns undef if no coordinate has been associated with this star.
397              
398             $star->ra( $ra );
399              
400             The RA can be changed using this method but only if the coordinate
401             object is associated with a fixed position. Attempting to change the
402             J2000 RA of a moving object will fail. If an attempt is made to
403             change the RA when no coordinate is associated with this object then
404             a new Astro::Coords object will be created (with a
405             Dec of 0.0).
406              
407             RA accepted by this method must be in sexagesimal format, space or
408             colon-separated. Returns a space-separated sexagesimal number.
409              
410              
411             =cut
412              
413             sub ra {
414             my $self = shift;
415             if (@_) {
416             my $ra = shift;
417              
418             # Issue a warning specifically for this call
419             my @info = caller();
420             warnings::warnif("deprecated","Use of ra() method for setting RA now deprecated. Please use the coords() method instead, at $info[1] line $info[2]");
421              
422              
423             # Get the coordinate object
424             my $c = $self->coords;
425             if (defined $c) {
426             # Need to tweak RA?
427             croak "Can only adjust RA with Astro::Coords::Equatorial coordinates"
428             unless $c->isa("Astro::Coords::Equatorial");
429              
430             # For now need to kluge since Astro::Coords does not allow
431             # you to change the position (it is an immutable object)
432             $c = $c->new( type => 'J2000',
433             dec => $c->dec(format => 's'),
434             ra => $ra,
435             );
436              
437             } else {
438             $c = new Astro::Coords( type => 'J2000',
439             ra => $ra,
440             dec => '0',
441             );
442             }
443              
444             # Update the object
445             $self->coords($c);
446             }
447              
448             my $outc = $self->coords;
449             return unless defined $outc;
450              
451             # Astro::Coords inserts colons by default. Grab the old delimiter
452             # and number of decimal places if we're using a recent enough
453             # version of Astro::Coords.
454             my $ra = $outc->ra;
455             if (UNIVERSAL::isa( $ra, "Astro::Coords::Angle" ) ) {
456              
457             $ra->str_delim( ' ' );
458             $ra->str_ndp( 2 );
459             return "$ra";
460              
461             } else {
462              
463             my $outra = $outc->ra(format => 's');
464             $outra =~ s/:/ /g;
465             $outra =~ s/^\s*//;
466              
467             return $outra;
468             }
469             }
470              
471             =item B
472              
473             Return (or set) the current object Dec (J2000).
474              
475             $dec = $star->dec();
476              
477             If the Star is associated with a moving object such as a planet,
478             comet or asteroid this method will return the J2000 Dec associated
479             with the time and observer position associated with the coordinate
480             object itself (by default current time, longitude of 0 degrees).
481             Returns undef if no coordinate has been associated with this star.
482              
483             $star->dec( $dec );
484              
485             The Dec can be changed using this method but only if the coordinate
486             object is associated with a fixed position. Attempting to change the
487             J2000 Dec of a moving object will fail. If an attempt is made to
488             change the Dec when no coordinate is associated with this object then
489             a new Astro::Coords object will be created (with a
490             Dec of 0.0).
491              
492             Dec accepted by this method must be in sexagesimal format, space or
493             colon-separated. Returns a space-separated sexagesimal number
494             with a leading sign.
495              
496             =cut
497              
498             sub dec {
499             my $self = shift;
500             if (@_) {
501             my $dec = shift;
502              
503             # Issue a warning specifically for this call
504             my @info = caller();
505             warnings::warnif("deprecated","Use of ra() method for setting RA now deprecated. Please use the coords() method instead, at $info[1] line $info[2]");
506              
507             # Get the coordinate object
508             my $c = $self->coords;
509             if (defined $c) {
510             # Need to tweak RA?
511             croak "Can only adjust Dec with Astro::Coords::Equatorial coordinates"
512             unless $c->isa("Astro::Coords::Equatorial");
513              
514             # For now need to kluge since Astro::Coords does not allow
515             # you to change the position (it is an immutable object)
516             $c = $c->new( type => 'J2000',
517             ra => $c->ra(format => 's'),
518             dec => $dec,
519             );
520              
521             } else {
522             $c = new Astro::Coords( type => 'J2000',
523             dec => $dec,
524             ra => 0,
525             );
526             }
527              
528             # Update the object
529             $self->coords($c);
530             }
531              
532             my $outc = $self->coords;
533             return unless defined $outc;
534              
535             # Astro::Coords inserts colons by default. Grab the old delimiter
536             # and number of decimal places if we're using a recent enough
537             # version of Astro::Coords.
538             my $dec = $outc->dec;
539             if( UNIVERSAL::isa( $dec, "Astro::Catalog::Angle" ) ) {
540              
541             $dec->str_delim( ' ' );
542             $dec->str_ndp( 2 );
543             $dec = "$dec";
544             $dec = (substr($dec,0,1) eq '-' ? '' : '+' ) . $dec;
545             return $dec;
546              
547             } else {
548              
549             my $outdec = $outc->dec(format => 's');
550             $outdec =~ s/:/ /g;
551             $outdec =~ s/^\s*//;
552              
553             # require leading sign for backwards compatibility
554             # Sign will be there for negative
555             $outdec = (substr($outdec,0,1) eq '-' ? '' : '+' ) . $outdec;
556              
557             return $outdec;
558             }
559             }
560              
561             =item B
562              
563             Return or set the flux measurements of the star as an C
564             object.
565              
566             $f = $star->fluxes();
567             $star->fluxes( $f );
568              
569             $star->fluxes( $f, 1 ); # will replace instead of appending
570              
571              
572             The object returned by this method is the actual object stored
573             inside this Item object and not a clone. If the flux values
574             are changed through this object the flu values of the star is
575             also changed.
576              
577             If an optional flag is passed as set to the routine it will replace
578             instead of appending (default action) to an existing fluxes object
579             in the catalogue.
580              
581             Returns undef if the fluxes have never been specified.
582              
583             =cut
584              
585             sub fluxes {
586             my $self = shift;
587             if (@_) {
588             my $flux = shift;
589             my $flag = shift;
590             croak "Flux must be an Astro::Fluxes object"
591             unless UNIVERSAL::isa($flux, "Astro::Fluxes");
592              
593             if ( defined $self->{FLUXES} ) {
594             if ( defined $flag ) {
595             $self->{FLUXES} = $flux;
596             } else {
597             $self->{FLUXES}->merge( $flux );
598             }
599             } else {
600             $self->{FLUXES} = $flux;
601             }
602             }
603             return $self->{FLUXES};
604             }
605              
606             =item B
607              
608             Returns a list of the wavebands for which the object has defined values.
609              
610             @filters = $star->what_filters();
611             $num = $star->what_filters();
612              
613             if called in a scalar context it will return the number of filters which
614             have defined magnitudes in the object. It will included 'derived' values,
615             see C for details.
616              
617             =cut
618              
619             sub what_filters {
620             my $self = shift;
621              
622             my $fluxes = $self->{FLUXES};
623              
624             #use Data::Dumper; print Dumper( $self->{FLUXES} );
625             my @mags = $fluxes->original_wavebands('filters') if defined $fluxes;
626              
627             # return array of filters or number if called in scalar context
628             return wantarray ? @mags : scalar( @mags );
629             }
630              
631             =item B
632              
633             Returns a list of the colours for which the object has defined values.
634              
635             @colours = $star->what_colours();
636             $num = $star->what_colours();
637              
638             if called in a scalar context it will return the number of colours which
639             have defined values in the object.
640              
641             =cut
642              
643             sub what_colours {
644             my $self = shift;
645              
646             my $fluxes = $self->{FLUXES};
647             my @cols = $fluxes->original_colors() if defined $fluxes;
648              
649             # return array of colours or number if called in scalar context
650             return wantarray ? @cols : scalar( @cols );
651             }
652              
653              
654             =item B
655              
656             Returns the magnitude for the supplied filter if available
657              
658             $magnitude = $star->get_magnitude( 'B' );
659              
660             =cut
661              
662             sub get_magnitude {
663             my $self = shift;
664             #warnings::warn("Astro::Item::get_magnitude is deprecated")
665             # if warnings::enabled();
666              
667             my $magnitude;
668             if (@_) {
669              
670             # grab passed filter
671             my $filter = shift;
672             my $fluxes = $self->{FLUXES};
673             $magnitude = $fluxes->flux( waveband => $filter,
674             type => $self->preferred_magnitude_type );
675              
676             if( defined( $magnitude ) ) {
677             return $magnitude->quantity( $self->preferred_magnitude_type );
678             } else {
679             return undef;
680             }
681             }
682             }
683              
684             =item B
685              
686             Returns the flux quantity for the given waveband and flux type.
687              
688             my $flux = $star->get_flux_quantity( waveband => 'B',
689             type => 'mag' );
690              
691             The arguments are passed as a hash. The value for the waveband
692             argument can be either a string describing a filter or an
693             Astro::WaveBand object. The value for the flux type is
694             case-insensitive.
695              
696             Returns a scalar.
697              
698             =cut
699              
700             sub get_flux_quantity {
701             my $self = shift;
702             my %args = @_;
703              
704             if( ! defined( $args{'waveband'} ) ) {
705             croak "Must supply waveband to Astro::Catalog::Item->get_flux_quantity()";
706             }
707             if( ! defined( $args{'type'} ) ) {
708             croak "Must supply flux type to Astro::Catalog::Item->get_flux_quantity()";
709             }
710              
711             my $waveband;
712             if( ! UNIVERSAL::isa( $args{'waveband'}, "Astro::WaveBand" ) ) {
713             $waveband = new Astro::WaveBand( Filter => $args{'waveband'} );
714             } else {
715             $waveband = $args{'waveband'};
716             }
717              
718             my $fluxes = $self->fluxes;
719             if( defined( $fluxes ) ) {
720             my $flux = $fluxes->flux( waveband => $waveband, type => $args{'type'} );
721             if( defined( $flux ) ) {
722             return $flux->quantity( $args{'type'} );
723             }
724             }
725             return undef;
726             }
727              
728             =item B
729              
730             Returns the error in the magnitude value for the supplied filter if available
731              
732             $mag_errors = $star->get_errors( 'B' );
733              
734             =cut
735              
736             sub get_errors {
737             my $self = shift;
738             #warnings::warn("Astro::Item::get_errors is deprecated")
739             # if warnings::enabled();
740              
741             my $mag_error;
742             if (@_) {
743              
744             # grab passed filter
745             my $filter = shift;
746             my $fluxes = $self->{FLUXES};
747             my $magnitude = $fluxes->flux( waveband => $filter,
748             type => $self->preferred_magnitude_type );
749             if( defined( $magnitude ) ) {
750             return $magnitude->error( $self->preferred_magnitude_type );
751             } else {
752             return undef;
753             }
754             }
755             return $mag_error;
756             }
757              
758             =item B
759              
760             Returns the flux error for the given waveband and flux type.
761              
762             my $flux = $star->get_flux_error( waveband => 'B',
763             type => 'mag' );
764              
765             The arguments are passed as a hash. The value for the waveband
766             argument can be either a string describing a filter or an
767             Astro::WaveBand object. The value for the flux type is
768             case-insensitive.
769              
770             Returns a scalar.
771              
772             =cut
773              
774             sub get_flux_error {
775             my $self = shift;
776             my %args = @_;
777              
778             if( ! defined( $args{'waveband'} ) ) {
779             croak "Must supply waveband to Astro::Catalog::Item->get_flux_error()";
780             }
781             if( ! defined( $args{'type'} ) ) {
782             croak "Must supply flux type to Astro::Catalog::Item->get_flux_error()";
783             }
784              
785             my $waveband;
786             if( ! UNIVERSAL::isa( $args{'waveband'}, "Astro::WaveBand" ) ) {
787             $waveband = new Astro::WaveBand( Filter => $args{'waveband'} );
788             } else {
789             $waveband = $args{'waveband'};
790             }
791             my $fluxes = $self->fluxes;
792             if( defined( $fluxes ) ) {
793             my $flux = $fluxes->flux( waveband => $waveband, type => $args{'type'} );
794             if( defined( $flux ) ) {
795             return $flux->error( $args{'type'} );
796             }
797             }
798             return undef;
799             }
800              
801             =item B
802              
803             Returns the value of the supplied colour if available
804              
805             $colour = $star->get_colour( 'B-V' );
806              
807             =cut
808              
809             sub get_colour {
810             my $self = shift;
811             #warnings::warn("Astro::Item::get_colour is deprecated")
812             # if warnings::enabled();
813              
814             my $value;
815             if (@_) {
816              
817             # grab passed colour
818             my $colour = shift;
819             my @filters = split "-", $colour;
820             my $fluxes = $self->{FLUXES};
821             my $color = $fluxes->color(
822             upper => new Astro::WaveBand( Filter => $filters[0] ),
823             lower => new Astro::WaveBand( Filter => $filters[1] ) );
824             $value = $color->quantity('mag');
825             }
826             return $value;
827             }
828              
829             =item B
830              
831             Returns the error in the colour value for the supplied colour if available
832              
833             $col_errors = $star->get_colourerr( 'B-V' );
834              
835             =cut
836              
837             sub get_colourerr {
838             my $self = shift;
839             #warnings::warn("Astro::Item::get_colourerr is deprecated")
840             # if warnings::enabled();
841              
842             my $col_error;
843             if (@_) {
844              
845             # grab passed colour
846             my $colour = shift;
847             my @filters = split "-", $colour;
848             my $fluxes = $self->{FLUXES};
849             my $color = $fluxes->color(
850             upper => new Astro::WaveBand( Filter => $filters[0] ),
851             lower => new Astro::WaveBand( Filter => $filters[1] ) );
852              
853             #use Data::Dumper; print Dumper( $color );
854             $col_error = $color->error('mag');
855              
856              
857             }
858             return $col_error;
859             }
860              
861             =item B
862              
863             Get or set the preferred magnitude type to be returned from the get_magnitude method.
864              
865             my $type = $item->preferred_magnitude_type;
866             $item->preferred_magnitude_type( 'MAG_ISO' );
867              
868             Defaults to 'MAG'.
869              
870             =cut
871              
872             sub preferred_magnitude_type {
873             my $self = shift;
874             if( @_ ) {
875             my $type = shift;
876             $self->{PREFERRED_MAG_TYPE} = $type;
877             }
878              
879             if( ! defined( $self->{PREFERRED_MAG_TYPE} ) ) {
880             $self->{PREFERRED_MAG_TYPE} = 'MAG';
881             }
882              
883             return $self->{PREFERRED_MAG_TYPE};
884             }
885              
886             =item B
887              
888             Get or set the morphology of the star as an C
889             object.
890              
891             $star->morphology( $morphology );
892              
893             The object returned by this method is the actual object stored
894             inside this Star object and not a clone. If the morphology
895             is changed through this object the morphology of the star is
896             also changed.
897              
898             =cut
899              
900             sub morphology {
901             my $self = shift;
902             if (@_) {
903             my $m = shift;
904             croak "Morphology must be an Astro::Catalog::Item::Morphology object"
905             unless UNIVERSAL::isa($m, "Astro::Catalog::Item::Morphology");
906              
907             # Store the new coordinate object
908             # Storing it late stops looping from the id and comment methods
909             $self->{MORPHOLOGY} = $m;
910             }
911             return $self->{MORPHOLOGY};
912             }
913              
914              
915             =item B
916              
917             Return (or set) the quality flag of the star
918              
919             $quality = $star->quailty();
920             $star->quality( 0 );
921              
922             for example for the USNO-A2 catalogue, 0 denotes good quality, and 1
923             denotes a possible problem object. In the generic case any flag value,
924             including a boolean, could be used.
925              
926             These quality flags are standardised sybolically across catalogues and
927             have the following definitions:
928              
929             STARGOOD
930             STARBAD
931              
932             TBD. Need to provide quality constants and mapping to and from these
933             constants on catalog I/O.
934              
935             =cut
936              
937             sub quality {
938             my $self = shift;
939             if (@_) {
940              
941             # 2MASS hack
942             # ----------
943             # quick, dirty and ultimately icky hack. The entire quality flag
944             # code is going to have to be rewritten so it works like mag errors,
945             # and gets assocaited with a magnitude. For now, if the JHK QFlag
946             # for 2MASS is A,B or C then the internal quality flag is 0 (good),
947             # otherwise it gets set to 1 (bad). This pretty much sucks.
948              
949             # Yes Tim, I know I'm doing this in the wrong place. I'm panicing
950             # I'll fix it later. I've moved the Cluster specific hack about the
951             # star ID's out of Astro::Catalog::query::USNOA2 and into the Cluster
952             # IO module and used Scalar::Util to figure out whether I've got a
953             # number (neat solution) before blowing it away.
954              
955             # Anyway...
956             my $quality = shift;
957              
958             # Shouldn't happen?
959             unless ( defined $quality ) {
960             $self->{QUALITY} = undef;
961             return undef;
962             }
963              
964             if ( $quality =~ /^[A-Z][A-Z][A-Z]$/ ) {
965              
966             $_ = $quality;
967             m/^([A-Z])([A-Z])([A-Z])$/;
968              
969             my $j_quality = $1;
970             my $h_quality = $2;
971             my $k_quality = $3;
972              
973             if ( ($j_quality eq 'A' || $j_quality eq 'B' || $j_quality eq 'C') &&
974             ($h_quality eq 'A' || $h_quality eq 'B' || $h_quality eq 'C') ) {
975              
976             # good quality
977             $self->{QUALITY} = 0;
978              
979             } else {
980             # bad quality
981             $self->{QUALITY} = 1;
982             }
983              
984             } else {
985              
986             $self->{QUALITY} = $quality;
987             }
988              
989             }
990             return $self->{QUALITY};
991             }
992              
993             =item B
994              
995             Return (or set) the field parameter for the star
996              
997             $field = $star->field();
998             $star->field( '0080' );
999              
1000             =cut
1001              
1002             sub field {
1003             my $self = shift;
1004             if (@_) {
1005             $self->{FIELD} = shift;
1006             }
1007             return $self->{FIELD};
1008             }
1009              
1010             =item B
1011              
1012             Return (or set) the GSC flag for the object
1013              
1014             $gsc = $star->gsc();
1015             $star->gsc( 'TRUE' );
1016              
1017             the flag is TRUE if the object is known to be in the Guide Star Catalogue,
1018             and FALSE otherwise.
1019              
1020             =cut
1021              
1022             sub gsc {
1023             my $self = shift;
1024             if (@_) {
1025             $self->{GSC} = shift;
1026             }
1027             return $self->{GSC};
1028             }
1029              
1030             =item B
1031              
1032             Return (or set) the distance from the field centre
1033              
1034             $distance = $star->distance();
1035             $star->distance( '0.009' );
1036              
1037             e.g. for the USNO-A2 catalogue.
1038              
1039             =cut
1040              
1041             sub distance {
1042             my $self = shift;
1043             if (@_) {
1044             $self->{DISTANCE} = shift;
1045             }
1046             return $self->{DISTANCE};
1047             }
1048              
1049             =item B
1050              
1051             Return (or set) the position angle from the field centre
1052              
1053             $position_angle = $star->posangle();
1054             $star->posangle( '50.761' );
1055              
1056             e.g. for the USNO-A2 catalogue.
1057              
1058             =cut
1059              
1060             sub posangle {
1061             my $self = shift;
1062             if (@_) {
1063             $self->{POSANGLE} = shift;
1064             }
1065             return $self->{POSANGLE};
1066             }
1067              
1068             =item B
1069              
1070             Return (or set) the X pixel co-ordinate of the star
1071              
1072             $x = $star->x();
1073             $star->id( $x );
1074              
1075             =cut
1076              
1077             sub x {
1078             my $self = shift;
1079             if (@_) {
1080             $self->{X} = shift;
1081             }
1082              
1083             if( ! defined( $self->{X} ) &&
1084             defined( $self->wcs ) &&
1085             defined( $self->coords ) ) {
1086              
1087             # We need to get a template FK5 SkyFrame to be able to convert
1088             # properly between RA/Dec and X/Y, but we can only do this if
1089             # we load Starlink::AST. So that we don't have a major dependency
1090             # on that module, load it here at runtime.
1091             eval{ require Starlink::AST; };
1092             if( $@ ) {
1093             croak "Attempted to convert from RA/Dec to X position and cannot load Starlink::AST. Error: $@";
1094             }
1095             my $template = new Starlink::AST::SkyFrame( "System=FK5" );
1096             my $wcs = $self->wcs;
1097             my $frameset = $wcs->FindFrame( $template, "" );
1098             if( ! defined( $frameset ) ) {
1099             croak "Could not find FK5 SkyFrame to do RA/Dec to X position translation";
1100             }
1101             my( $ra, $dec ) = $self->coords->radec();
1102             my( $x, $y ) = $frameset->Tran2( [$ra->radians],
1103             [$dec->radians],
1104             0 );
1105             $self->{X} = $x->[0];
1106             }
1107             return $self->{X};
1108             }
1109              
1110             =item B
1111              
1112             Return (or set) the Y pixel co-ordinate of the star
1113              
1114             $y = $star->y();
1115             $star->id( $y );
1116              
1117             =cut
1118              
1119             sub y {
1120             my $self = shift;
1121             if (@_) {
1122             $self->{Y} = shift;
1123             }
1124              
1125             if( ! defined( $self->{Y} ) &&
1126             defined( $self->wcs ) &&
1127             defined( $self->coords ) ) {
1128              
1129             # We need to get a template FK5 SkyFrame to be able to convert
1130             # properly between RA/Dec and X/Y, but we can only do this if
1131             # we load Starlink::AST. So that we don't have a major dependency
1132             # on that module, load it here at runtime.
1133             eval{ require Starlink::AST; };
1134             if( $@ ) {
1135             croak "Attempted to convert from RA/Dec to Y position and cannot load Starlink::AST. Error: $@";
1136             }
1137             my $template = new Starlink::AST::SkyFrame( "System=FK5" );
1138             my $wcs = $self->wcs;
1139             my $frameset = $wcs->FindFrame( $template, "" );
1140             if( ! defined( $frameset ) ) {
1141             croak "Could not find FK5 SkyFrame to do RA/Dec to Y position translation";
1142             }
1143             my( $ra, $dec ) = $self->coords->radec();
1144             my( $x, $y ) = $frameset->Tran2( [$ra->radians],
1145             [$dec->radians],
1146             0 );
1147             $self->{Y} = $y->[0];
1148             }
1149              
1150             return $self->{Y};
1151             }
1152              
1153             =item B
1154              
1155             Return (or set) the WCS associated with the star.
1156              
1157             $wcs = $star->wcs;
1158             $star->wcs( $wcs );
1159              
1160             The WCS is a C object.
1161              
1162             =cut
1163              
1164             sub wcs {
1165             my $self = shift;
1166             if( @_ ) {
1167             my $wcs = shift;
1168             if( ! defined( $wcs ) ) {
1169             $self->{WCS} = undef;
1170             } elsif( UNIVERSAL::isa( $wcs, "Starlink::AST" ) ) {
1171             $self->{WCS} = $wcs;
1172             }
1173             }
1174             return $self->{WCS};
1175             }
1176              
1177             =item B
1178              
1179             Return (or set) a comment associated with the star
1180              
1181             $comment = $star->comment();
1182             $star->comment( $comment_string );
1183              
1184             The comment is propogated to the underlying coordinate
1185             object (if one is present) if the comment is updated.
1186              
1187             =cut
1188              
1189             sub comment {
1190             my $self = shift;
1191             if (@_) {
1192             $self->{COMMENT} = shift;
1193              
1194             my $c = $self->coords;
1195             $c->comment( $self->{COMMENT} ) if defined $c;
1196             }
1197             return $self->{COMMENT};
1198             }
1199              
1200             =item B
1201              
1202             The spectral type of the Star.
1203              
1204             $spec = $star->spectype;
1205              
1206             =cut
1207              
1208             sub spectype {
1209             my $self = shift;
1210             if (@_) {
1211             $self->{SPECTYPE} = shift;
1212             }
1213             return $self->{SPECTYPE};
1214             }
1215              
1216             =item B
1217              
1218             The type of star. Usually uses the Simbad abbreviation.
1219             eg. '*' for a star, 'rG' for a Radio Galaxy.
1220              
1221             $type = $star->startype;
1222              
1223             See also C for the expanded version of this type.
1224              
1225             =cut
1226              
1227             sub startype {
1228             my $self = shift;
1229             if (@_) {
1230             $self->{STARTYPE} = shift;
1231             }
1232             return $self->{STARTYPE};
1233             }
1234              
1235             =item B
1236              
1237             The full description of the type of star. Usually uses the Simbad text.
1238             If no text has been provided, a lookup will be performed using the
1239             abbreviated C.
1240              
1241             $long = $star->longstartype;
1242             $star->longstartype( "A variable star" );
1243              
1244             See also C for the expanded version of this type.
1245              
1246             =cut
1247              
1248             sub longstartype {
1249             my $self = shift;
1250             if (@_) {
1251             $self->{LONGTYPE} = shift;
1252             }
1253             # if we have nothing, attempt a look up
1254             if (!defined $self->{LONGTYPE} && defined $self->startype
1255             && exists $STAR_TYPE_LOOKUP{$self->startype}) {
1256             return $STAR_TYPE_LOOKUP{$self->startype};
1257             } else {
1258             return $self->{STARTYPE};
1259             }
1260             }
1261              
1262             =item B
1263              
1264             A link (URL) to more information on the star in question. For example
1265             this might provide a direct link to the full Simbad description.
1266              
1267             $url = $star->moreinfo;
1268              
1269             =cut
1270              
1271             sub moreinfo {
1272             my $self = shift;
1273             if (@_) {
1274             $self->{MOREINFO} = shift;
1275             }
1276             return $self->{MOREINFO};
1277             }
1278              
1279             =item B
1280              
1281             The time the information for the star in question was gathered. This
1282             is different from the time of observation of the star.
1283              
1284             $insertdate = $star->insertdate;
1285              
1286             This is a C object.
1287              
1288             =cut
1289              
1290             sub insertdate {
1291             my $self = shift;
1292             if( @_ ) {
1293             $self->{INSERTDATE} = shift;
1294             }
1295             return $self->{INSERTDATE};
1296             }
1297              
1298              
1299             =item B
1300              
1301             Apply a datestamp to all the C objects inside the
1302             C object contained within this object
1303              
1304             $star->fluxdatestamp( new DateTime() )
1305              
1306             this is different from the time for which the inormation about the
1307             star was gathered, see the insertdate() method call, and is the
1308             time of observation of the object.
1309              
1310             =cut
1311              
1312             sub fluxdatestamp {
1313             my $self = shift;
1314             if( @_ ) {
1315             my $datetime = shift;
1316             croak "Astro::Catalog::Item::fluxdatestamp()\n".
1317             "Error: Not a DateTime object\n"
1318             unless UNIVERSAL::isa( $datetime, "DateTime" );
1319             $self->{FLUXES}->datestamp( $datetime );
1320             }
1321             return $self->{FLUXES};
1322             }
1323              
1324              
1325             =item B
1326              
1327             The distance from another Item,
1328              
1329             my $distance1 = $star->distancetostar( $star2 )
1330              
1331             returns a tangent plane separation value in arcsec. Returns undef if
1332             the star is too far away.
1333              
1334             =cut
1335              
1336             sub distancetostar {
1337             my $self = shift;
1338             my $other = shift;
1339              
1340             croak "Astro::Catalog::Item::distancetostar()\n".
1341             "Error: Not an Astro::Catalog::Item object\n"
1342             unless UNIVERSAL::isa( $other, "Astro::Catalog::Item" );
1343              
1344             my $sep = $self->coords->distance( $other->coords );
1345             return (defined $sep ? $sep->arcsec : $sep );
1346             }
1347              
1348              
1349             =item B
1350              
1351             Check if the passed star is within $distance_in_arcsec of the object.
1352              
1353             my $status = $star->within( $star2, $distance_in_arcsec )
1354              
1355             returns true if this is the case.
1356              
1357             =cut
1358              
1359             sub within {
1360             my $self = shift;
1361             my $other = shift;
1362             my $max = shift;
1363              
1364             croak "Astro::Catalog::Item::within()\n".
1365             "Error: Not an Astro::Catalog::Item object\n"
1366             unless UNIVERSAL::isa( $other, "Astro::Catalog::Item" );
1367              
1368             my $distance = $self->distancetostar( $other );
1369             return 1 if $distance < $max;
1370             return 0;
1371             }
1372              
1373              
1374             =item B
1375              
1376             A hold-all method to contain information not covered by other methods.
1377              
1378             my $misc = $item->misc;
1379             $item->misc( $misc );
1380              
1381             This accessor can hold any type of variable, although it is
1382             recommended that a hash reference is used for easier lookups:
1383              
1384             my $misc = $item->misc;
1385             my $vrad = $misc->{'vrad'};
1386             my $vopt = $misc->{'vopt'}
1387              
1388             =cut
1389              
1390             sub misc {
1391             my $self = shift;
1392             if( @_ ) {
1393             $self->{'MISC'} = shift;
1394             }
1395             return $self->{'MISC'};
1396             }
1397              
1398             =back
1399              
1400             =head2 Obsolete Methods
1401              
1402             Several methods were made obsolete with the introduction of V4 of the
1403             Astro::Catalog class. These were magnitudes(), magerr(), colours() and
1404             colerr(). The functionality these supported is now part of the addfluxes()
1405             method.
1406              
1407             =cut
1408              
1409             sub magnitudes {
1410             my $self = shift;
1411             croak "Astro::Catalog::Item::magnitudes()\n" .
1412             "This method is no longer supported, use fluxes() instead.\n";
1413             }
1414              
1415             sub magerr {
1416             my $self = shift;
1417             croak "Astro::Catalog::Item::magerr()\n" .
1418             "This method is no longer supported, use fluxes() instead.\n";
1419             }
1420              
1421              
1422             sub colours {
1423             my $self = shift;
1424             croak "Astro::Catalog::Item::colours()\n" .
1425             "This method is no longer supported, use fluxes() instead.\n";
1426              
1427             }
1428              
1429             sub colerr {
1430             my $self = shift;
1431             croak "Astro::Catalog::Item::colerr()\n" .
1432             "This method is no longer supported, use fluxes() instead.\n";
1433              
1434             }
1435              
1436              
1437             # C O N F I G U R E -------------------------------------------------------
1438              
1439              
1440             =head2 General Methods
1441              
1442             =over 4
1443              
1444             =item B
1445              
1446             Configures the object from multiple pieces of information.
1447              
1448             $star->configure( %options );
1449              
1450             Takes a hash as argument with the list of keywords.
1451             The keys are not case-sensitive and map to accessor methods.
1452              
1453             Note that RA and Dec keys are allowed. The values can be supplied in either sexagesimal or decimal degrees.
1454              
1455             =cut
1456              
1457             sub configure {
1458             my $self = shift;
1459              
1460             # return unless we have arguments
1461             return unless @_;
1462              
1463             # grab the argument list
1464             my %args = @_;
1465              
1466             # First check for duplicate keys (case insensitive) with different
1467             # values and store the unique lower-cased keys
1468             my %check;
1469             for my $key (keys %args) {
1470             my $lckey = lc($key);
1471             if (exists $check{$lckey} && $check{$lckey} ne $args{$key}) {
1472             warnings::warnif("Duplicated key in constructor [$lckey] with differing values ".
1473             " '$check{$lckey}' and '$args{$key}'\n");
1474             }
1475             $check{$lckey} = $args{$key};
1476             }
1477              
1478             # Now that we have lower cased keys we can look to see if we have
1479             # ra & dec as well as coords and also verify that they are actually
1480             # the same if we have them
1481             if (exists $check{coords} && (exists $check{ra} || exists $check{dec})) {
1482             # coords + one of ra or dec is a mistake
1483             if (exists $check{ra} && exists $check{dec}) {
1484             # Create a new coords object - assume J2000
1485             my $c = new Astro::Coords( type => 'J2000',
1486             ra => $check{ra},
1487             dec => $check{dec},
1488             # units => 'sex',
1489             );
1490              
1491             # Make sure we have the same reference place and time
1492             $c->datetime( $check{coords}->datetime )
1493             if $check{coords}->has_datetime;
1494             $c->telescope( $check{coords}->telescope )
1495             if defined $check{coords}->telescope;
1496              
1497              
1498             # Check the distance
1499             my $d = $c->distance( $check{coords} );
1500              
1501             # Raise warn if the error is more than 1 arcsecond
1502             warnings::warnif( "Coords and RA/Dec were specified and they differ by more than 1 arcsec [".
1503             (defined $d ? $d->arcsec : "")
1504             ." sec]. Ignoring RA/Dec keys.\n")
1505             if (!defined $d || $d->arcsec > 1.0);
1506              
1507             } elsif (!exists $check{ra}) {
1508             warnings::warnif("Dec specified in addition to Coords but without RA. Ignoring it.");
1509             } elsif (!exists $check{dec}) {
1510             warnings::warnif("RA specified in addition to Coords but without Dec. Ignoring it.");
1511             }
1512              
1513             # Whatever happens we do not want ra and dec here
1514             delete $check{dec};
1515             delete $check{ra};
1516             } elsif (exists $check{ra} || $check{dec}) {
1517             # Generate a Astro::Coords object here in one go rather than
1518             # relying on the old ra() dec() methods individually
1519             my $ra = $check{ra} || 0.0;
1520             my $dec = $check{dec} || 0.0;
1521             $check{coords} = new Astro::Coords( type => 'J2000',
1522             ra => $ra,
1523             dec => $dec );
1524             delete $check{ra};
1525             delete $check{dec};
1526             }
1527              
1528             # Loop over the allowed keys storing the values
1529             # in the object if they exist. Case insensitive.
1530             for my $key (keys %check) {
1531             my $method = lc($key);
1532             $self->$method( $check{$key} ) if $self->can( $method );
1533             }
1534             return;
1535             }
1536              
1537             # T I M E A T T H E B A R --------------------------------------------
1538              
1539             =back
1540              
1541             =head1 COPYRIGHT
1542              
1543             Copyright (C) 2001 University of Exeter. All Rights Reserved.
1544             Some modification are Copyright (C) 2003 Particle Physics and
1545             Astronomy Research Council. All Rights Reserved.
1546              
1547             This program was written as part of the eSTAR project and is free software;
1548             you can redistribute it and/or modify it under the terms of the GNU Public
1549             License.
1550              
1551              
1552             =head1 AUTHORS
1553              
1554             Alasdair Allan Eaa@astro.ex.ac.ukE,
1555             Tim Jenness Etjenness@cpan.orgE,
1556              
1557             =cut
1558              
1559             # L A S T O R D E R S ------------------------------------------------------
1560              
1561             1;
1562