File Coverage

blib/lib/Astro/Catalog/IO/SExtractor.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::IO::SExtractor;
2              
3             =head1 NAME
4              
5             Astro::Catalog::IO::SExtractor - SExtractor output catalogue I/O for
6             Astro::Catalog.
7              
8             =head1 SYNOPSIS
9              
10             $cat = Astro::Catalog::IO::SExtractor->_read_catalog( \@lines );
11              
12             =head1 DESCRIPTION
13              
14             This class provides read and write methods for catalogues written by
15             SExtractor, as long as they were written in ASCII_HEAD format. The
16             methods are not public and should, in general, only be called from the
17             C C and C methods.
18              
19             =cut
20              
21 2     2   4313403 use 5.006;
  2         32  
  2         160  
22 2     2   15 use warnings;
  2         16  
  2         443  
23 2     2   72 use warnings::register;
  2         5  
  2         1564  
24 2     2   15 use Carp;
  2         4  
  2         1394  
25 2     2   440 use strict;
  2         5  
  2         105  
26              
27             # Bring in the Astro:: modules.
28 2     2   3363 use Astro::Catalog;
  0            
  0            
29             use Astro::Catalog::Item;
30             use Astro::Catalog::Item::Morphology;
31             use Astro::Coords;
32              
33             use Number::Uncertainty;
34             use Astro::Flux;
35             use Astro::FluxColor;
36             use Astro::Fluxes;
37              
38             use base qw/ Astro::Catalog::IO::ASCII /;
39              
40             use vars qw/ $VERSION $DEBUG /;
41              
42             $VERSION = '4.31';
43             $DEBUG = 0;
44              
45             =begin __PRIVATE_METHODS__
46              
47             =head1 PRIVATE METHODS
48              
49             These methods are usually called automatically from the C
50             constructor.
51              
52             =over 4
53              
54             =item B<_read_catalog>
55              
56             Parses the catalogue lines and returns a new C object
57             containing the catalogue entries.
58              
59             $cat = Astro::Catalog::IO::SExtractor->_read_catalog( \@lines );
60              
61             The catalogue lines must include column definitions as written using
62             the 'ASCII_HEAD' catalogue type from SExtractor. This implementation
63             currently only supports reading information from the following output
64             parameters:
65              
66             NUMBER id
67             X_IMAGE
68             Y_IMAGE
69             X_PIXEL
70             Y_PIXEL
71             ERRX2_IMAGE
72             ERRY2_IMAGE
73             XWIN_IMAGE
74             YWIN_IMAGE
75             ERRX2WIN_IMAGE
76             ERRY2WIN_IMAGE
77             ALPHA_J2000 coords
78             DELTA_J2000 coords
79             MAG_ISO
80             MAGERR_ISO
81             FLUX_ISO
82             FLUXERR_ISO
83             MAG_ISOCOR
84             MAGERR_ISOCOR
85             FLUX_ISOCOR
86             FLUXERR_ISOCOR
87             MAG_APER
88             MAGERR_APER
89             FLUX_APER
90             FLUXERR_APER
91             MAG_AUTO
92             MAGERR_AUTO
93             FLUX_AUTO
94             FLUXERR_AUTO
95             MAG_BEST
96             MAGERR_BEST
97             FLUX_BEST
98             FLUXERR_BEST
99             ELLIPTICITY morphology ellipticity
100             THETA_IMAGE morphology position_angle_pixel
101             ERRTHETA_IMAGE morphology position_angle_pixel
102             THETA_SKY morphology position_angle_world
103             ERRTHETA_SKY morphology position_angle_world
104             B_IMAGE morphology minor_axis_pixel
105             ERRB_IMAGE morphology minor_axis_pixel
106             A_IMAGE morphology major_axis_pixel
107             ERRA_IMAGE morphology major_axis_pixel
108             B_WORLD morphology minor_axis_world
109             ERRB_WORLD morphology minor_axis_world
110             A_WORLD morphology major_axis_world
111             ERRA_WORLD morphology major_axis_world
112             ISOAREA_IMAGE morphology area
113             FWHM_IMAGE morphology fwhm_pixel
114             FWHM_WORLD morphology fwhm_world
115             FLAGS quality
116              
117             The pixel coordinate values are special cases. As there are only two
118             available methods to hold this information in an
119             C object, x() and y(), and six potential values
120             to use, we must make a choice as to which value gets the nod. We
121             preferentially use the NDF pixel coordinates (which are only available
122             in output from the Starlink version of EXTRACTOR), then the windowed
123             coordinates that were made available in SExtractor v2.4.3, then the
124             standard coordinates.
125              
126             For the flux and magnitude values, a separate C object is
127             set up for each type with the flux type() equal to the SExtractor
128             keyword. For example, if the MAG_AUTO keyword exists in the catalogue,
129             then the output C objects will have an
130             C object of the type 'MAG_AUTO' in it.
131              
132             There are optional named parameters. These are case-sensitive, and are:
133              
134             =item Filter - An Astro::WaveBand object denoting the waveband that
135             the catalogue values were measured in.
136              
137             =item Quality - If set, then only objects that have an extraction flag
138             in the FLAGS column equal to this value will be used to generate the
139             output catalogue. Otherwise, all objects will be used.
140              
141             =cut
142              
143             sub _read_catalog {
144             my $class = shift;
145             my $lines = shift;
146             my %args = @_;
147              
148             if( ref( $lines ) ne 'ARRAY' ) {
149             croak "Must supply catalogue contents as a reference to an array";
150             }
151              
152             if( defined( $args{'Filter'} ) &&
153             ! UNIVERSAL::isa( $args{'Filter'}, "Astro::WaveBand" ) ) {
154             croak "Filter as passed to SExtractor->_read_catalog must be an Astro::WaveBand object";
155             }
156              
157             my $filter;
158             if( defined( $args{'Filter'} ) ) {
159             $filter = $args{'Filter'}->natural;
160             } else {
161             $filter = 'unknown';
162             }
163              
164             my $quality = $args{'Quality'};
165             if( ! defined( $quality ) ) {
166             $quality = -1;
167             }
168              
169             my @lines = @$lines; # Dereference, make own copy.
170              
171             # Create an Astro::Catalog object;
172             my $catalog = new Astro::Catalog();
173              
174             # Set up columns.
175             my $id_column = -1;
176             my $x_column = -1;
177             my $x_pixel_column = -1;
178             my $xerr_column = -1;
179             my $xwin_column = -1;
180             my $xwinerr_column = -1;
181             my $y_column = -1;
182             my $y_pixel_column = -1;
183             my $yerr_column = -1;
184             my $ywin_column = -1;
185             my $ywinerr_column = -1;
186             my $ra_column = -1;
187             my $dec_column = -1;
188             my $mag_iso_column = -1;
189             my $magerr_iso_column = -1;
190             my $flux_iso_column = -1;
191             my $fluxerr_iso_column = -1;
192             my $flux_isocor_column = -1;
193             my $fluxerr_isocor_column = -1;
194             my $mag_isocor_column = -1;
195             my $magerr_isocor_column = -1;
196             my $flux_aper1_column = -1;
197             my $fluxerr_aper1_column = -1;
198             my $mag_aper1_column = -1;
199             my $magerr_aper1_column = -1;
200             my $flux_aper2_column = -1;
201             my $fluxerr_aper2_column = -1;
202             my $mag_aper2_column = -1;
203             my $magerr_aper2_column = -1;
204             my $flux_auto_column = -1;
205             my $fluxerr_auto_column = -1;
206             my $mag_auto_column = -1;
207             my $magerr_auto_column = -1;
208             my $flux_best_column = -1;
209             my $fluxerr_best_column = -1;
210             my $mag_best_column = -1;
211             my $magerr_best_column = -1;
212             my $ell_column = -1;
213             my $posang_pixel_column = -1;
214             my $posangerr_pixel_column = -1;
215             my $posang_world_column = -1;
216             my $posangerr_world_column = -1;
217             my $minor_pixel_column = -1;
218             my $minorerr_pixel_column = -1;
219             my $major_pixel_column = -1;
220             my $majorerr_pixel_column = -1;
221             my $minor_world_column = -1;
222             my $minorerr_world_column = -1;
223             my $major_world_column = -1;
224             my $majorerr_world_column = -1;
225             my $area_column = -1;
226             my $fwhm_pixel_column = -1;
227             my $fwhm_world_column = -1;
228             my $flag_column = -1;
229              
230             # Loop through the lines.
231             for ( @lines ) {
232             my $line = $_;
233              
234             # If we're on a column line that starts with a #, check to see
235             # if it's describing where the X, Y, RA, or Dec position is in
236             # the table, or the object number, or the flux, or the error in
237             # flux.
238             if( $line =~ /^#/ ) {
239             my @column = split( /\s+/, $line );
240             if( $column[2] =~ /^NUMBER/ ) {
241             $id_column = $column[1] - 1;
242             print "ID column is $id_column\n" if $DEBUG;
243              
244             } elsif( $column[2] =~ /^X_IMAGE/ ) {
245             $x_column = $column[1] - 1;
246             print "X_IMAGE column is $x_column\n" if $DEBUG;
247              
248             } elsif( $column[2] =~ /^Y_IMAGE/ ) {
249             $y_column = $column[1] - 1;
250             print "Y_IMAGE column is $y_column\n" if $DEBUG;
251              
252             } elsif( $column[2] =~ /^X_PIXEL/ ) {
253             $x_pixel_column = $column[1] - 1;
254             print "X_PIXEL column is $x_pixel_column\n" if $DEBUG;
255              
256             } elsif( $column[2] =~ /^Y_PIXEL/ ) {
257             $y_pixel_column = $column[1] - 1;
258             print "Y_PIXEL column is $y_pixel_column\n" if $DEBUG;
259              
260             } elsif( $column[2] =~ /^ERRX2_IMAGE/ ) {
261             $xerr_column = $column[1] - 1;
262             print "X ERROR column is $xerr_column\n" if $DEBUG;
263              
264             } elsif( $column[2] =~ /^ERRY2_IMAGE/ ) {
265             $yerr_column = $column[1] - 1;
266             print "Y ERROR column is $yerr_column\n" if $DEBUG;
267              
268             } elsif( $column[2] =~ /^XWIN_IMAGE/ ) {
269             $xwin_column = $column[1] - 1;
270             print "XWIN_IMAGE column is $xwin_column\n" if $DEBUG;
271              
272             } elsif( $column[2] =~ /^ERRX2WIN_IMAGE/ ) {
273             $xwinerr_column = $column[1] - 1;
274             print "ERRX2WIN_IMAGE column is $xwinerr_column\n" if $DEBUG;
275              
276             } elsif( $column[2] =~ /^YWIN_IMAGE/ ) {
277             $ywin_column = $column[1] - 1;
278             print "YWIN_IMAGE column is $ywin_column\n" if $DEBUG;
279              
280             } elsif( $column[2] =~ /^ERRY2WIN_IMAGE/ ) {
281             $ywinerr_column = $column[1] - 1;
282             print "ERRY2WIN_IMAGE column is $ywinerr_column\n" if $DEBUG;
283              
284             } elsif( $column[2] =~ /^ALPHA_J2000/ ) {
285             $ra_column = $column[1] - 1;
286             print "RA column is $ra_column\n" if $DEBUG;
287              
288             } elsif( $column[2] =~ /^DELTA_J2000/ ) {
289             $dec_column = $column[1] - 1;
290             print "DEC column is $dec_column\n" if $DEBUG;
291              
292             } elsif( $column[2] =~ /^MAG_ISO$/ ) {
293             $mag_iso_column = $column[1] - 1;
294             print "MAG_ISO column is $mag_iso_column\n" if $DEBUG;
295              
296             } elsif( $column[2] =~ /^MAGERR_ISO$/ ) {
297             $magerr_iso_column = $column[1] - 1;
298             print "MAGERR_ISO column is $magerr_iso_column\n" if $DEBUG;
299              
300             } elsif( $column[2] =~ /^FLUX_ISO$/ ) {
301             $flux_iso_column = $column[1] - 1;
302             print "FLUX_ISO column is $flux_iso_column\n" if $DEBUG;
303              
304             } elsif( $column[2] =~ /^FLUXERR_ISO$/ ) {
305             $fluxerr_iso_column = $column[1] - 1;
306             print "FLUXERR_ISO column is $fluxerr_iso_column\n" if $DEBUG;
307              
308             } elsif( $column[2] =~ /^FLUX_ISOCOR/ ) {
309             $flux_isocor_column = $column[1] - 1;
310             print "FLUX_ISOCOR column is $flux_isocor_column\n" if $DEBUG;
311              
312             } elsif( $column[2] =~ /^FLUXERR_ISOCOR/ ) {
313             $fluxerr_isocor_column = $column[1] - 1;
314             print "FLUXERR_ISOCOR column is $fluxerr_isocor_column\n" if $DEBUG;
315              
316             } elsif( $column[2] =~ /^MAG_ISOCOR/ ) {
317             $mag_isocor_column = $column[1] - 1;
318             print "MAG_ISOCOR column is $mag_isocor_column\n" if $DEBUG;
319              
320             } elsif( $column[2] =~ /^MAGERR_ISOCOR/ ) {
321             $magerr_isocor_column = $column[1] - 1;
322             print "MAGERR_ISOCOR column is $magerr_isocor_column\n" if $DEBUG;
323              
324             } elsif( $column[2] =~ /^FLUX_APER/ ) {
325             $flux_aper1_column = $column[1] - 1;
326             print "FLUX_APER column is $flux_aper1_column\n" if $DEBUG;
327              
328             } elsif( $column[2] =~ /^FLUXERR_APER/ ) {
329             $fluxerr_aper1_column = $column[1] - 1;
330             print "FLUXERR_APER column is $fluxerr_aper1_column\n" if $DEBUG;
331              
332             } elsif( $column[2] =~ /^MAG_APER/ ) {
333             $mag_aper1_column = $column[1] - 1;
334             print "MAG_APER column is $mag_aper1_column\n" if $DEBUG;
335              
336             } elsif( $column[2] =~ /^MAGERR_APER/ ) {
337             $magerr_aper1_column = $column[1] - 1;
338             print "MAGERR_APER column is $magerr_aper1_column\n" if $DEBUG;
339              
340             } elsif( $column[2] =~ /^FLUX_AUTO/ ) {
341             $flux_auto_column = $column[1] - 1;
342             print "FLUX_AUTO column is $flux_auto_column\n" if $DEBUG;
343              
344             } elsif( $column[2] =~ /^FLUXERR_AUTO/ ) {
345             $fluxerr_auto_column = $column[1] - 1;
346             print "FLUXERR_AUTO column is $fluxerr_auto_column\n" if $DEBUG;
347              
348             } elsif( $column[2] =~ /^MAG_AUTO/ ) {
349             $mag_auto_column = $column[1] - 1;
350             print "MAG_AUTO column is $mag_auto_column\n" if $DEBUG;
351              
352             } elsif( $column[2] =~ /^MAGERR_AUTO/ ) {
353             $magerr_auto_column = $column[1] - 1;
354             print "MAGERR_AUTO column is $magerr_auto_column\n" if $DEBUG;
355              
356             } elsif( $column[2] =~ /^FLUX_BEST/ ) {
357             $flux_best_column = $column[1] - 1;
358             print "FLUX_BEST column is $flux_best_column\n" if $DEBUG;
359              
360             } elsif( $column[2] =~ /^FLUXERR_BEST/ ) {
361             $fluxerr_best_column = $column[1] - 1;
362             print "FLUXERR_BEST column is $fluxerr_best_column\n" if $DEBUG;
363              
364             } elsif( $column[2] =~ /^MAG_BEST/ ) {
365             $mag_best_column = $column[1] - 1;
366             print "MAG_BEST column is $mag_best_column\n" if $DEBUG;
367              
368             } elsif( $column[2] =~ /^MAGERR_BEST/ ) {
369             $magerr_best_column = $column[1] - 1;
370             print "MAGERR_BEST_COLUMN is $magerr_best_column\n" if $DEBUG;
371              
372             } elsif( $column[2] =~ /^ELLIPTICITY/ ) {
373             $ell_column = $column[1] - 1;
374             print "ELLIPTICITY column is $ell_column\n" if $DEBUG;
375              
376             } elsif( $column[2] =~ /^THETA_IMAGE/ ) {
377             $posang_pixel_column = $column[1] - 1;
378             print "THETA_IMAGE column is $posang_pixel_column\n" if $DEBUG;
379              
380             } elsif( $column[2] =~ /^ERRTHETA_IMAGE/ ) {
381             $posangerr_pixel_column = $column[1] - 1;
382             print "ERRTHETA_IMAGE column is $posangerr_pixel_column\n" if $DEBUG;
383              
384             } elsif( $column[2] =~ /^THETA_SKY/ ) {
385             $posang_world_column = $column[1] - 1;
386             print "THETA_SKY column is $posang_world_column\n" if $DEBUG;
387              
388             } elsif( $column[2] =~ /^ERRTHETA_SKY/ ) {
389             $posangerr_world_column = $column[1] - 1;
390             print "ERRTHETA_SKY column is $posangerr_world_column\n" if $DEBUG;
391              
392             } elsif( $column[2] =~ /^B_IMAGE/ ) {
393             $minor_pixel_column = $column[1] - 1;
394             print "B_IMAGE column is $minor_pixel_column\n" if $DEBUG;
395              
396             } elsif( $column[2] =~ /^ERRB_IMAGE/ ) {
397             $minorerr_pixel_column = $column[1] - 1;
398             print "ERRB_IMAGE column is $minorerr_pixel_column\n" if $DEBUG;
399              
400             } elsif( $column[2] =~ /^A_IMAGE/ ) {
401             $major_pixel_column = $column[1] - 1;
402             print "A_IMAGE column is $major_pixel_column\n" if $DEBUG;
403              
404             } elsif( $column[2] =~ /^ERRA_IMAGE/ ) {
405             $majorerr_pixel_column = $column[1] - 1;
406             print "ERRA_IMAGE column is $majorerr_pixel_column\n" if $DEBUG;
407              
408             } elsif( $column[2] =~ /^B_WORLD/ ) {
409             $minor_world_column = $column[1] - 1;
410             print "B_WORLD column is $minor_world_column\n" if $DEBUG;
411              
412             } elsif( $column[2] =~ /^ERRB_WORLD/ ) {
413             $minorerr_world_column = $column[1] - 1;
414             print "ERRB_WORLD column is $minorerr_world_column\n" if $DEBUG;
415              
416             } elsif( $column[2] =~ /^A_WORLD/ ) {
417             $major_world_column = $column[1] - 1;
418             print "A_WORLD column is $major_world_column\n" if $DEBUG;
419              
420             } elsif( $column[2] =~ /^ERRA_WORLD/ ) {
421             $majorerr_world_column = $column[1] - 1;
422             print "ERRA_WORLD column is $majorerr_world_column\n" if $DEBUG;
423              
424             } elsif( $column[2] =~ /^ISOAREA_IMAGE/ ) {
425             $area_column = $column[1] - 1;
426             print "AREA column is $area_column\n" if $DEBUG;
427              
428             } elsif( $column[2] =~ /^FWHM_IMAGE/ ) {
429             $fwhm_pixel_column = $column[1] - 1;
430             print "FWHM_IMAGE column is $fwhm_pixel_column\n" if $DEBUG;
431              
432             } elsif( $column[2] =~ /^FWHM_WORLD/ ) {
433             $fwhm_world_column = $column[1] - 1;
434             print "FWHM_WORLD column is $fwhm_world_column\n" if $DEBUG;
435              
436             } elsif( $column[2] =~ /^FLAGS/ ) {
437             $flag_column = $column[1] - 1;
438             print "FLAGS column is $flag_column\n" if $DEBUG;
439              
440             }
441             next;
442             }
443              
444             # Remove leading whitespace and go to the next line if the
445             # current one is blank.
446             $line =~ s/^\s+//;
447             next if length( $line ) == 0;
448              
449             # Form an array of the fields in the catalogue.
450             my @fields = split( /\s+/, $line );
451              
452             # Don't deal with this object if our requested quality is not -1
453             # and the quality of the object is not equal to the requested
454             # quality and we have a quality flag for this object.
455             if( ( $quality != -1 ) &&
456             ( $flag_column != -1 ) &&
457             ( $fields[$flag_column] != $quality ) ) {
458             next;
459             }
460              
461             # Create a temporary Astro::Catalog::Item object.
462             my $star = new Astro::Catalog::Item();
463              
464             # Grab the coordinates, forming an Astro::Coords object., but only
465             # if the RA and Dec columns are defined.
466             if( $ra_column != -1 &&
467             $dec_column != -1 ) {
468             my $coords = new Astro::Coords( type => 'J2000',
469             ra => $fields[$ra_column],
470             dec => $fields[$dec_column],
471             name => ( $id_column != -1 ? $fields[$id_column] : undef ),
472             units => 'degrees',
473             );
474             $star->coords( $coords );
475             }
476              
477             if( $flag_column != -1 ) {
478             $star->quality( $fields[$flag_column] );
479             } else {
480             $star->quality( 0 );
481             }
482              
483             if( $id_column != -1 ) {
484             $star->id( $fields[$id_column] );
485             }
486              
487             # Set up the various flux and magnitude measurements.
488             if( $mag_iso_column != -1 ) {
489             my $num;
490             if( $magerr_iso_column != -1 ) {
491             $num = new Number::Uncertainty( Value => $fields[$mag_iso_column],
492             Error => $fields[$magerr_iso_column] );
493             } else {
494             $num = new Number::Uncertainty( Value => $fields[$mag_iso_column] );
495             }
496             my $mag_iso = new Astro::Flux( $num, 'MAG_ISO', $filter );
497             $star->fluxes( new Astro::Fluxes( $mag_iso ) );
498             }
499             if( $flux_iso_column != -1 ) {
500             my $num;
501             if( $fluxerr_iso_column != -1 ) {
502             $num = new Number::Uncertainty( Value => $fields[$flux_iso_column],
503             Error => $fields[$fluxerr_iso_column] );
504             } else {
505             $num = new Number::Uncertainty( Value => $fields[$flux_iso_column] );
506             }
507             my $flux_iso = new Astro::Flux( $num, 'FLUX_ISO', $filter );
508             $star->fluxes( new Astro::Fluxes( $flux_iso ) );
509             }
510              
511             if( $mag_isocor_column != -1 ) {
512             my $num;
513             if( $magerr_isocor_column != -1 ) {
514             $num = new Number::Uncertainty( Value => $fields[$mag_isocor_column],
515             Error => $fields[$magerr_isocor_column] );
516             } else {
517             $num = new Number::Uncertainty( Value => $fields[$mag_isocor_column] );
518             }
519             my $mag_isocor = new Astro::Flux( $num, 'MAG_ISOCOR', $filter );
520             $star->fluxes( new Astro::Fluxes( $mag_isocor ) );
521             }
522             if( $flux_isocor_column != -1 ) {
523             my $num;
524             if( $fluxerr_isocor_column != -1 ) {
525             $num = new Number::Uncertainty( Value => $fields[$flux_isocor_column],
526             Error => $fields[$fluxerr_isocor_column] );
527             } else {
528             $num = new Number::Uncertainty( Value => $fields[$flux_isocor_column] );
529             }
530             my $flux_isocor = new Astro::Flux( $num, 'FLUX_ISOCOR', $filter );
531             $star->fluxes( new Astro::Fluxes( $flux_isocor ) );
532             }
533              
534             if( $mag_aper1_column != -1 ) {
535             my $num;
536             if( $magerr_aper1_column != -1 ) {
537             $num = new Number::Uncertainty( Value => $fields[$mag_aper1_column],
538             Error => $fields[$magerr_aper1_column] );
539             } else {
540             $num = new Number::Uncertainty( Value => $fields[$mag_aper1_column] );
541             }
542             my $mag_aper1 = new Astro::Flux( $num, 'MAG_APER1', $filter );
543             $star->fluxes( new Astro::Fluxes( $mag_aper1 ) );
544             }
545             if( $flux_aper1_column != -1 ) {
546             my $num;
547             if( $fluxerr_aper1_column != -1 ) {
548             $num = new Number::Uncertainty( Value => $fields[$flux_aper1_column],
549             Error => $fields[$fluxerr_aper1_column] );
550             } else {
551             $num = new Number::Uncertainty( Value => $fields[$flux_aper1_column] );
552             }
553             my $flux_aper1 = new Astro::Flux( $num, 'FLUX_APER1', $filter );
554             $star->fluxes( new Astro::Fluxes( $flux_aper1 ) );
555             }
556              
557             if( $mag_auto_column != -1 ) {
558             my $num;
559             if( $magerr_auto_column != -1 ) {
560             $num = new Number::Uncertainty( Value => $fields[$mag_auto_column],
561             Error => $fields[$magerr_auto_column] );
562             } else {
563             $num = new Number::Uncertainty( Value => $fields[$mag_auto_column] );
564             }
565             my $mag_auto = new Astro::Flux( $num, 'MAG_AUTO', $filter );
566             $star->fluxes( new Astro::Fluxes( $mag_auto ) );
567             }
568             if( $flux_auto_column != -1 ) {
569             my $num;
570             if( $fluxerr_auto_column != -1 ) {
571             $num = new Number::Uncertainty( Value => $fields[$flux_auto_column],
572             Error => $fields[$fluxerr_auto_column] );
573             } else {
574             $num = new Number::Uncertainty( Value => $fields[$flux_auto_column] );
575             }
576             my $flux_auto = new Astro::Flux( $num, 'FLUX_AUTO', $filter );
577             $star->fluxes( new Astro::Fluxes( $flux_auto ) );
578             }
579              
580             if( $mag_best_column != -1 ) {
581             my $num;
582             if( $magerr_best_column != -1 ) {
583             $num = new Number::Uncertainty( Value => $fields[$mag_best_column],
584             Error => $fields[$magerr_best_column] );
585             } else {
586             $num = new Number::Uncertainty( Value => $fields[$mag_best_column] );
587             }
588             my $mag_best = new Astro::Flux( $num, 'MAG_BEST', $filter );
589             $star->fluxes( new Astro::Fluxes( $mag_best ) );
590             }
591             if( $flux_best_column != -1 ) {
592             my $num;
593             if( $fluxerr_best_column != -1 ) {
594             $num = new Number::Uncertainty( Value => $fields[$flux_best_column],
595             Error => $fields[$fluxerr_best_column] );
596             } else {
597             $num = new Number::Uncertainty( Value => $fields[$flux_best_column] );
598             }
599             my $flux_best = new Astro::Flux( $num, 'FLUX_BEST', $filter );
600             $star->fluxes( new Astro::Fluxes( $flux_best ) );
601             }
602              
603             # Set the x and y coordinates. Preferentially use the NDF pixel
604             # coordinates, then the windowed coordinates, then the standard
605             # coordinates.
606             if( $x_pixel_column != -1 ) {
607             $star->x( $fields[$x_pixel_column] );
608             } elsif( $xwin_column != -1 ) {
609             $star->x( $fields[$xwin_column] );
610             } elsif( $x_column != -1 ) {
611             $star->x( $fields[$x_column] );
612             }
613             if( $y_pixel_column != -1 ) {
614             $star->y( $fields[$y_pixel_column] );
615             } elsif( $ywin_column != -1 ) {
616             $star->y( $fields[$ywin_column] );
617             } elsif( $x_column != -1 ) {
618             $star->y( $fields[$y_column] );
619             }
620              
621             # Set up the star's morphology.
622             my $ellipticity;
623             my $position_angle_pixel;
624             my $position_angle_world;
625             my $major_axis_pixel;
626             my $minor_axis_pixel;
627             my $major_axis_world;
628             my $minor_axis_world;
629             my $fwhm_pixel;
630             my $fwhm_world;
631             my $area;
632             if( $ell_column != -1 ) {
633             $ellipticity = new Number::Uncertainty( Value => $fields[$ell_column] );
634             }
635             if( $posang_pixel_column != -1 ) {
636             if( $posangerr_pixel_column != -1 ) {
637             $position_angle_pixel = new Number::Uncertainty( Value => $fields[$posang_pixel_column],
638             Error => $fields[$posangerr_pixel_column] );
639             } else {
640             $position_angle_pixel = new Number::Uncertainty( Value => $fields[$posang_pixel_column] );
641             }
642             }
643             if( $posang_world_column != -1 ) {
644             if( $posangerr_world_column != -1 ) {
645             $position_angle_world = new Number::Uncertainty( Value => $fields[$posang_world_column],
646             Error => $fields[$posangerr_world_column] );
647             } else {
648             $position_angle_world = new Number::Uncertainty( Value => $fields[$posang_world_column] );
649             }
650             }
651             if( $major_pixel_column != -1 ) {
652             if( $majorerr_pixel_column != -1 ) {
653             $major_axis_pixel = new Number::Uncertainty( Value => $fields[$major_pixel_column],
654             Error => $fields[$majorerr_pixel_column] );
655             } else {
656             $major_axis_pixel = new Number::Uncertainty( Value => $fields[$major_pixel_column] );
657             }
658             }
659             if( $major_world_column != -1 ) {
660             if( $majorerr_world_column != -1 ) {
661             $major_axis_world = new Number::Uncertainty( Value => $fields[$major_world_column],
662             Error => $fields[$majorerr_world_column] );
663             } else {
664             $major_axis_world = new Number::Uncertainty( Value => $fields[$major_world_column] );
665             }
666             }
667             if( $minor_pixel_column != -1 ) {
668             if( $minorerr_pixel_column != -1 ) {
669             $minor_axis_pixel = new Number::Uncertainty( Value => $fields[$minor_pixel_column],
670             Error => $fields[$minorerr_pixel_column] );
671             } else {
672             $minor_axis_pixel = new Number::Uncertainty( Value => $fields[$minor_pixel_column] );
673             }
674             }
675             if( $minor_world_column != -1 ) {
676             if( $minorerr_world_column != -1 ) {
677             $minor_axis_world = new Number::Uncertainty( Value => $fields[$minor_world_column],
678             Error => $fields[$minorerr_world_column] );
679             } else {
680             $minor_axis_world = new Number::Uncertainty( Value => $fields[$minor_world_column] );
681             }
682             }
683             if( $area_column != -1 ) {
684             $area = new Number::Uncertainty( Value => $fields[$area_column] );
685             }
686             if( $fwhm_pixel_column != -1 ) {
687             $fwhm_pixel = new Number::Uncertainty( Value => $fields[$fwhm_pixel_column] );
688             }
689             if( $fwhm_world_column != -1 ) {
690             $fwhm_world = new Number::Uncertainty( Value => $fields[$fwhm_world_column] );
691             }
692             my $morphology = new Astro::Catalog::Item::Morphology( ellipticity => $ellipticity,
693             position_angle_pixel => $position_angle_pixel,
694             position_angle_world => $position_angle_world,
695             major_axis_pixel => $major_axis_pixel,
696             minor_axis_pixel => $minor_axis_pixel,
697             major_axis_world => $major_axis_world,
698             minor_axis_world => $minor_axis_world,
699             area => $area,
700             fwhm_pixel => $fwhm_pixel,
701             fwhm_world => $fwhm_world,
702             );
703             $star->morphology( $morphology );
704              
705             # Push the star onto the catalog.
706             $catalog->pushstar( $star );
707             }
708              
709             $catalog->origin( 'IO::SExtractor' );
710             return $catalog;
711             }
712              
713             =item B<_write_catalog>
714              
715             Create an output catalogue in the SExtractor ASCII_HEAD format and
716             return the lines in an array.
717              
718             $ref = Astro::Catalog::IO::SExtractor->_write_catalog( $catalog );
719              
720             Argument is an C object.
721              
722             This method currently only returns the ID, X, Y, RA and Dec values in
723             the returned strings, in that order.
724              
725             =cut
726              
727             sub _write_catalog {
728             croak ( 'Usage: _write_catalog( $catalog, [%opts] ') unless scalar(@_) >= 1;
729             my $class = shift;
730             my $catalog = shift;
731              
732             my @output;
733              
734             # First, the header. What we write to the header depends on what
735             # values we have for our objects, so check for ID, X, Y, RA, and Dec
736             # values.
737             my $write_id = 0;
738             my $write_x = 0;
739             my $write_y = 0;
740             my $write_ra = 0;
741             my $write_dec = 0;
742              
743             my @stars = $catalog->stars();
744              
745             if( defined( $stars[0]->id ) ) {
746             $write_id = 1;
747             }
748             if( defined( $stars[0]->x ) ) {
749             $write_x = 1;
750             }
751             if( defined( $stars[0]->y ) ) {
752             $write_y = 1;
753             }
754             if( defined( $stars[0]->coords->ra ) ) {
755             $write_ra = 1;
756             }
757             if( defined( $stars[0]->coords->dec ) ) {
758             $write_dec = 1;
759             }
760              
761             # Now for the header.
762             my $pos = 1;
763             if( $write_id ) {
764             push @output, "# $pos NUMBER Running object number";
765             $pos++;
766             }
767             if( $write_x ) {
768             push @output, "# $pos X_IMAGE Object position along x [pixel]";
769             $pos++;
770             }
771             if( $write_y ) {
772             push @output, "# $pos Y_IMAGE Object position along y [pixel]";
773             $pos++;
774             }
775             if( $write_ra ) {
776             push @output, "# $pos ALPHA_J2000 Right ascension of barycenter (J2000) [deg]";
777             $pos++;
778             }
779             if( $write_dec ) {
780             push @output, "# $pos DELTA_J2000 Declination of barycenter (J2000) [deg]";
781             $pos++;
782             }
783              
784             # Now go through the objects.
785             foreach my $star ( @stars ) {
786              
787             my $output_string = "";
788              
789             if( $write_id ) {
790             $output_string .= $star->id . " ";
791             }
792             if( $write_x ) {
793             $output_string .= $star->x . " ";
794             }
795             if( $write_y ) {
796             $output_string .= $star->y . " ";
797             }
798             if( $write_ra ) {
799             $output_string .= $star->coords->ra->degrees . " ";
800             }
801             if( $write_dec ) {
802             $output_string .= $star->coords->dec->degrees . " ";
803             }
804              
805             push @output, $output_string;
806             }
807              
808             # And return!
809             return \@output;
810              
811             }
812              
813             =back
814              
815             =head1 REVISION
816              
817             $Id: SExtractor.pm,v 1.19 2006/06/05 21:02:49 cavanagh Exp $
818              
819             =head1 FORMAT
820              
821             The SExtractor ASCII_HEAD format consists of a header block and a
822             data block. The header block is made up of comments denoted by a
823             # as the first character. These comments describe the column number,
824             output parameter name, description of the output paramter, and units
825             of the output parameter enclosed in square brackets. The data block
826             is space-delimited.
827              
828             =head1 SEE ALSO
829              
830             L
831              
832             =head1 COPYRIGHT
833              
834             Copyright (C) 2004 Particle Physics and Astronomy Research Council.
835             All Rights Reserved.
836              
837             This module is free software; you can redistribute it and/or modify it
838             under the terms of the GNU Public License.
839              
840             =head1 AUTHORS
841              
842             Brad Cavanagh Eb.cavanagh@jach.hawaii.eduE
843              
844             =cut
845              
846             1;