File Coverage

blib/lib/Astro/Catalog/Query.pm
Criterion Covered Total %
statement 19 21 90.4
branch n/a
condition n/a
subroutine 7 7 100.0
pod n/a
total 26 28 92.8


line stmt bran cond sub pod time code
1             package Astro::Catalog::Query;
2              
3             =head1 NAME
4              
5             Astro::Catalog::Query - Base class for Astro::Catalog query objects
6              
7             =head1 SYNOPSIS
8              
9             use base qw/ Astro::Catalog::Query /;
10              
11             =head1 DESCRIPTION
12              
13             This class forms a base class for all the query classes provided
14             in the C distribution (eg C).
15              
16             =cut
17              
18             # L O A D M O D U L E S --------------------------------------------------
19              
20 17     17   1076571 use strict;
  17         48  
  17         1036  
21 17     17   136 use warnings;
  17         38  
  17         568  
22 17     17   161 use warnings::register;
  17         37  
  17         3474  
23 17     17   125 use vars qw/ $VERSION /;
  17         47  
  17         2192  
24              
25 17     17   109 use File::Spec;
  17         54  
  17         627  
26 17     17   104 use Carp;
  17         35  
  17         2971  
27              
28             # generic catalog objects
29 17     17   14534 use Astro::Coords;
  0            
  0            
30             use Astro::Catalog;
31             use Astro::Catalog::Star;
32             $VERSION = "4.31";
33              
34             # C O N S T R U C T O R ----------------------------------------------------
35              
36             =head1 REVISION
37              
38             $Id: Query.pm,v 1.8 2003/09/25 21:27:50 aa Exp $
39              
40             =head1 METHODS
41              
42             =head2 Constructor
43              
44             =over 4
45              
46             =item B
47              
48             Create a new instance from a hash of options
49              
50             $q = new Astro::Catalog::Query( Coords => new Astro::Coords(),
51             Radius => $radius,
52             Bright => $magbright,
53             Faint => $magfaint,
54             Sort => $sort_type,
55             Number => $number_out );
56              
57             returns a reference to an query object. Must only called from
58             sub-classed constructors.
59              
60             RA and Dec are also allowed but are deprecated (since with only
61             RA/Dec the coordinates must always be supplied as J2000 space-separated
62             sexagesimal format).
63              
64             =cut
65              
66             sub new {
67             my $proto = shift;
68             my $class = ref($proto) || $proto;
69              
70             # bless the query hash into the class
71             my $block = bless { OPTIONS => {},
72             BUFFER => undef }, $class;
73              
74             # Configure the object [even if there are no args]
75             $block->configure( @_ );
76              
77             return $block;
78              
79             }
80              
81             =back
82              
83             =head2 Accessor Methods
84              
85             =over 4
86              
87             =item B
88              
89             Hash representing the query options to be used to query the catalog
90             server. This keys in this hash are restricted by the subclass. Some
91             keys are not usable by all catalogues.
92              
93             Returns a copy of the options hash when.
94              
95             %options = $q->query_options();
96              
97             Note that the hash keys included here are not necessarily the keys
98             used to form a remote query.
99              
100             If an argument is supplied, the value for that option is returned
101             I the option is supported.
102              
103             $ra = $q->query_options( "ra" );
104              
105             Values can not be set directly. Please use the provided accessor methods.
106              
107             =cut
108              
109             sub query_options {
110             my $self = shift;
111             if (@_) {
112             my $opt = lc(shift);
113             my %allow = $self->_get_allowed_options;
114              
115             if (!exists $allow{$opt}) {
116             warnings::warnif("Option $opt not supported by this cataloge");
117             return;
118             }
119             return $self->{OPTIONS}->{$opt};
120             }
121             return %{ $self->{OPTIONS} };
122             }
123              
124              
125             =item B
126              
127             Return (or set) the current target R.A. defined for the query
128              
129             $ra = $usno->ra();
130             $usno->ra( $ra );
131              
132             where $ra should be a string of the form "HH MM SS.SS", e.g. 21 42 42.66
133              
134             =cut
135              
136             sub ra {
137             my $self = shift;
138              
139             # SETTING R.A.
140             if (@_) {
141             # grab the new R.A.
142             my $ra = shift;
143             $self->_set_query_options( ra => $ra );
144             }
145             # Return it
146             return $self->query_options("ra");
147             }
148              
149             =item B
150              
151             Return (or set) the current target Declination defined for the query
152              
153             $dec = $q->dec();
154             $q->dec( $dec );
155              
156             where $dec should be a string of the form "+-HH MM SS.SS", e.g. +43 35 09.5
157             or -40 25 67.89
158              
159             =cut
160              
161             sub dec {
162             my $self = shift;
163              
164             # SETTING DEC
165             if (@_) {
166             # grab the new Dec
167             my $dec = shift;
168             $self->_set_query_options( dec => $dec );
169             }
170              
171             return $self->query_options("dec");
172             }
173              
174              
175             =item B
176              
177             Instead of querying by R.A. and Dec., you may also query it
178             by object name. Return (or set) the current target object defined for
179             the USNO-A2.0 query, will query SIMBAD for object name resolution.
180              
181             $ident = $usno->target();
182             $usno->target( "HT Cas" );
183              
184             using an object name will override the current R.A. and Dec settings for the
185             Query object (if currently set) and the next querydb() method call will query
186             using this identifier rather than any currently set co-ordinates.
187              
188             =cut
189              
190             sub target {
191             my $self = shift;
192              
193             # SETTING IDENTIFIER
194             if (@_) {
195              
196             # grab the new object name
197             my $ident = shift;
198              
199             # Need to clear RA and Dec iff they are allowed options
200             my %allow = $self->_get_allowed_options();
201              
202             my %clear;
203             $clear{ra} = undef if exists $allow{ra};
204             $clear{dec} = undef if exists $allow{dec};
205              
206             # Store it in the options table
207             $self->_set_query_options(
208             object => $ident,
209             %clear
210             );
211             }
212             return $self->query_options("object");
213             }
214              
215             =item B
216              
217             The radius to be searched for objects around the target R.A. and Dec in
218             arc minutes, the radius defaults to 5 arc minutes.
219              
220             $radius = $query->radius();
221             $query->radius( 20 );
222              
223             =cut
224              
225             sub radius {
226             my $self = shift;
227              
228             if (@_) {
229             $self->_set_query_options( radmax => shift );
230             }
231              
232             return $self->query_options("radmax");
233             }
234              
235             =item B
236              
237             Set (or query) the faint magnitude limit for inclusion on the results
238              
239             $faint = $query->faint();
240             $query->faint( 50 );
241              
242             =cut
243              
244             sub faint {
245             my $self = shift;
246              
247             if (@_) {
248             $self->_set_query_options( magfaint => shift );
249             }
250              
251             return $self->query_options("magfaint");
252             }
253              
254             =item B
255              
256             Set (or query) the bright magnitude limit for inclusion on the results
257              
258             $faint = $query->bright();
259             $query->bright( 2 );
260              
261             =cut
262              
263             sub bright {
264             my $self = shift;
265              
266             if (@_) {
267             $self->_set_query_options( magbright => shift );
268             }
269              
270             return $self->query_options("magbright");
271             }
272              
273             =item B
274              
275             Set or query the order in which the stars are listed in the catalogue
276              
277             $sort = $query->sort();
278             $query->sort( 'RA' );
279              
280             valid options are RA, DEC, RMAG, BMAG, DIST (distance to centre of the
281             requested field) and POS (the position angle to the centre of the field).
282              
283             =cut
284              
285             sub sort {
286             my $self = shift;
287              
288             if (@_) {
289             my $sort = shift;
290             $self->_set_query_options( sort => $sort );
291             }
292              
293             # return the sort option
294             return $self->query_options("sort");
295              
296             }
297              
298             =item B
299              
300             The number of objects to return, defaults to 2000 which should hopefully
301             be sufficent to return all objects of interest. This value should be increased
302             if a (very) large sample radius is requested.
303              
304             $num = $query->number();
305             $query->nout( 100 );
306              
307             =cut
308              
309             sub number {
310             my $self = shift;
311              
312             if (@_) {
313             $self->_set_query_options( nout => shift );
314             }
315              
316             return $self->query_options("nout");
317             }
318              
319             sub nout {
320             my $self = shift;
321             warnings::warnif("deprecated","The nout() method is deprecated. Please use number()");
322             return $self->number( @_ );
323             }
324              
325             =back
326              
327             =head2 General Methods
328              
329             =over 4
330              
331             =item B
332              
333             Configures the object, takes an options hash as an argument
334              
335             $dss->configure( %options );
336              
337             Does nothing if the array is not supplied.
338              
339             =cut
340              
341             sub configure {
342             my $self = shift;
343              
344             # CONFIGURE DEFAULTS
345             # ------------------
346              
347             # configure the default options
348             $self->_set_default_options();
349              
350              
351             # CONFIGURE FROM ARGUMENTS
352             # -------------------------
353              
354             # return unless we have arguments
355             return undef unless @_;
356              
357             # grab the argument list
358             my %args = Astro::Catalog::_normalize_hash(@_);
359              
360             # Grab the allowed options
361             my %allow = $self->_get_allowed_options();
362              
363             # Loop over the supplied arguments. If they correspond to
364             # a method, run it, if they correspond to an option, set it
365             for my $key (keys %args) {
366             my $lckey = lc($key);
367             if ($self->can($lckey)) {
368             $self->$lckey( $args{$key} );
369             } elsif (exists $allow{$lckey}) {
370             # set the option explcitly
371             $self->_set_query_options( $lckey => $args{$key} );
372             } else {
373             #warnings::warnif("Unrecognized option: $key. Ignoring it.");
374             }
375             }
376              
377             }
378              
379             # T I M E A T T H E B A R --------------------------------------------
380              
381             =back
382              
383             =begin __PRIVATE_METHODS__
384              
385             =head2 Private methods
386              
387             These methods are for internal use only.
388              
389             =over 4
390              
391              
392             =item B<_set_query_options>
393              
394             Set the query options.
395              
396             $q->_set_query_options( %newopt );
397              
398             Keys are standardised and are not necessarily those used
399             in the query. A warning is issued if an attempt is made to
400             set an option for an option that is not used by the particular
401             subclass.
402              
403             =cut
404              
405             sub _set_query_options {
406             my $self = shift;
407             my %newopt = @_;
408              
409             my %allow = $self->_get_allowed_options();
410              
411             for my $newkey (keys %newopt) {
412              
413             if (!exists $allow{$newkey}) {
414             warnings::warnif("Option $newkey not supported by catalog ".
415             ref($self)."\n");
416             next;
417             }
418             # set the option
419             $self->{OPTIONS}->{$newkey} = $newopt{$newkey};
420             }
421             return;
422             }
423              
424             =item B<_get_allowed_options>
425              
426             Return a hash with keys corresponding to the internal options
427             supported by the query, and values corresponding to the names
428             used by the specific query sub-system. Can use the keys
429             to work out whether an option is supported.
430              
431             %allow = $q->_get_allowed_options();
432              
433             Generally, must be over-ridden in subclass. By default returns all
434             the internal options, with 1-1 mapping.
435              
436             =cut
437              
438             sub _get_allowed_options {
439             return (
440             ra => 'ra',
441             dec => 'dec',
442             object => 'object',
443             radmax => 'radmax',
444             radmin => 'radmin',
445             width => 'width',
446             height => 'height',
447             magbright => 'magbright',
448             magfaint => 'magfaint',
449             sort => 'sort',
450             nout => 'nout',
451             );
452             }
453              
454             =item B<_get_supported_accessor_options>
455              
456             Returns a hash with keys corresponding to accessor methods
457             and values corresponding to the internal option.
458              
459             %opt = $q->_get_supported_accessor_options();
460              
461             This method should be superfluous if the methods had been named
462             correctly!
463              
464             Should support object init either via options or methods. This does not cover all
465             options. In configure, if there is an option available but no corresponding mapping
466             then we will just set the option directly.
467              
468             =cut
469              
470             sub _get_supported_accessor_options {
471             return (
472             ra => 'ra',
473             dec => 'dec',
474             faint => 'magfaint',
475             bright => 'magbright',
476             radius => 'radmax',
477             target => 'object',
478             sort => 'sort',
479             number => 'nout',
480             format => 'format',
481             );
482             }
483              
484             =item B<_get_default_options>
485              
486             Retrieve the defaults options for this particular catalog query.
487             Usually called by C<_set_default_options> during object configure.
488              
489             %defs = $q->_get_default_options();
490              
491             =cut
492              
493             sub _get_default_options {
494             croak "get_default_options must be subclassed";
495             }
496              
497             =item B<_set_default_options>
498              
499             Each catalogue requires different default settings for the
500             URL parameters. They should be specified in a subclass.
501              
502             =cut
503              
504             sub _set_default_options {
505             my $self = shift;
506              
507             # get the defaults
508             my %defaults = $self->_get_default_options();
509              
510             # set them
511             $self->_set_query_options( %defaults );
512             return;
513              
514             }
515              
516             =item B<_dump_raw>
517              
518             Private function for debugging and other testing purposes. It will return
519             the raw output of the last query made using querydb().
520              
521             @lines = $q->_dump_raw();
522              
523             =cut
524              
525             sub _dump_raw {
526             my $self = shift;
527              
528             # split the BUFFER into an array
529             my @portable = split( /\n/,$self->{BUFFER});
530             chomp @portable;
531              
532             return @portable;
533             }
534              
535             =item B<_set_raw>
536              
537             Private function to fill the current buffer with a string. This is used
538             when deealing with the buffer cannot be encapsulated inside a Transport
539             class and must be deal with by child classese.
540              
541             $q->_set_raw( $buffer );
542              
543             =cut
544              
545             sub _set_raw {
546             my $self = shift;
547             $self->{BUFFER} = shift;
548             }
549              
550             =item B<_dump_options>
551              
552             Private function for debugging and other testing purposes. It will return
553             the current query options as a hash.
554              
555             =cut
556              
557             sub _dump_options {
558             my $self = shift;
559              
560             return $self->query_options;
561             }
562              
563             =item B<_parse_query>
564              
565             Stub. Needs to be subclassed.
566              
567             =cut
568              
569             sub _parse_query {
570             croak "Query parsing is not generic. Please write one\n";
571             }
572              
573             =back
574              
575             =head2 Translation Methods
576              
577             The query options stored internally in the object are not necessarily
578             the form required for a query to a remote server. Methods for converting
579             from the internal representation to the external query format are
580             provided in the form of _from_$opt. ie:
581              
582             ($outkey, $outvalue) = $q->_from_ra();
583             ($outkey, $outvalue) = $q->_from_object();
584              
585             Items that have a one-to-one mapping can be declared by the query
586             subclass using the C<_translate_one_to_one> method which returns
587             a list of options that support the simplest mapping. If an explicit
588             method exists it is always used.
589              
590             If an option has no translation method and is not declared as
591             a one-to-one mapping, the translator will assume one-to-one but
592             issue a warning.
593              
594             =item B<_translate_options>
595              
596             Translates the options from the default interface into the internal
597             options specific for the sub-class
598              
599             %options = _translate_options( );
600              
601             The keys and values therefore are no longer general.
602              
603             =cut
604              
605             sub _translate_options {
606             my $self = shift;
607              
608             my %outhash;
609             my %allow = $self->_get_allowed_options();
610             my %one_one = $self->_translate_one_to_one();
611              
612             foreach my $key ( keys %allow ) {
613             # Need to translate them...
614             my $cvtmethod = "_from_" . $key;
615             my ($outkey, $outvalue);
616             if ($self->can($cvtmethod)) {
617             ($outkey, $outvalue) = $self->$cvtmethod();
618             } else {
619             # This is the one-to-one mapping section
620             # issue a warning if the method has not been declared
621             # as supporting that simply mapping
622             warnings::warnif("Unable to find translation for key $key. Assuming 1 to 1 mapping.\n")
623             unless exists $one_one{$key};
624              
625             # Translate the key and copy the value
626             $outkey = $allow{$key};
627             $outvalue = $self->query_options($key);
628             }
629             $outhash{$outkey} = $outvalue;
630             }
631             return %outhash;
632             }
633              
634             =item B<_translate_one_to_one>
635              
636             Returns (hash) indicating which of the standard options support
637             a one-to-one mapping when forming a URL (etc).
638              
639             =cut
640              
641             sub _translate_one_to_one {
642             # convert to a hash-list
643             return map { $_, undef }(qw/
644             object radmax radmin magfaint magbright
645             nout format
646             /);
647             }
648              
649              
650             # RA and Dec replace spaces with pluses and + sign with special code
651              
652             sub _from_ra {
653             my $self = shift;
654             my $ra = $self->query_options("ra");
655             my %allow = $self->_get_allowed_options();
656              
657             # Must replace spaces with +
658             $ra =~ s/\s/\+/g if defined $ra;
659              
660             return ($allow{ra},$ra);
661             }
662              
663             sub _from_dec {
664             my $self = shift;
665             my $dec = $self->query_options("dec");
666             my %allow = $self->_get_allowed_options();
667              
668             if (defined $dec) {
669             # Must replace + with %2B
670             $dec =~ s/\+/%2B/g;
671              
672             # Must replace spaces with +
673             $dec =~ s/\s/\+/g;
674             }
675              
676             return ($allow{dec},$dec);
677             }
678              
679             sub _from_sort {
680             my $self = shift;
681             my $key = "sort";
682             # case insensitive conversion
683             my $value = uc($self->query_options($key));
684              
685             my $sort;
686             # pick an option
687             if( $value eq "RA" ) {
688             # sort by RA
689             $sort = "ra";
690             } elsif ( $value eq "DEC" ) {
691             # sort by Dec
692             $sort = "dec";
693             } elsif ( $value eq "RMAG" ) {
694             # sort by R magnitude
695             $sort = "mr";
696             } elsif ( $value eq "BMAG" ) {
697             # sort by B magnitude
698             $sort = "mb";
699             } elsif ( $value eq "DIST" ) {
700             # sort by distance from field centre
701             $sort = "d";
702             } elsif ( $value eq "POS" ) {
703             # sort by position angle to field centre
704             $sort = "pos";
705             } else {
706             # in case there are no valid options sort by RA
707             warnings::warnif("Unknown sort type [$value]: using ra");
708             $sort = "ra";
709             }
710             my %allow = $self->_get_allowed_options();
711             return ($allow{$key}, $sort);
712             }
713              
714             # This is a template methdo that can be extended. This one
715             # implements a one to one mapping
716              
717             #sub _from_XXX {
718             # my $self = shift;
719             # my $key = "XXX";
720             # my $value = $self->query_options($key);
721             # my %allow = $self->_get_allowed_options();
722             # return ($allow{$key}, $value);
723             #}
724              
725              
726             =end __PRIVATE_METHODS__
727              
728             =head1 COPYRIGHT
729              
730             Copyright (C) 2001 University of Exeter. All Rights Reserved.
731             Some modifications copyright (C) 2003 Particle Physics and Astronomy
732             Research Council. All Rights Reserved.
733              
734             This program was written as part of the eSTAR project and is free software;
735             you can redistribute it and/or modify it under the terms of the GNU Public
736             License.
737              
738             =head1 AUTHORS
739              
740             Alasdair Allan Eaa@astro.ex.ac.ukE,
741             Tim Jenness Etjenness@cpan.orgE
742              
743             =cut
744              
745             # L A S T O R D E R S ------------------------------------------------------
746              
747             1;