| Astro-Catalog documentation | Contained in the Astro-Catalog distribution. |
Astro::Catalog::IO::SExtractor - SExtractor output catalogue I/O for Astro::Catalog.
$cat = Astro::Catalog::IO::SExtractor->_read_catalog( \@lines );
This class provides read and write methods for catalogues written by
SExtractor, as long as they were written in ASCII_HEAD format. The
methods are not public and should, in general, only be called from the
Astro::Catalog read_catalog and write_catalog methods.
| Astro-Catalog documentation | Contained in the Astro-Catalog distribution. |
package Astro::Catalog::IO::SExtractor;
use 5.006; use warnings; use warnings::register; use Carp; use strict; # Bring in the Astro:: modules. use Astro::Catalog; use Astro::Catalog::Item; use Astro::Catalog::Item::Morphology; use Astro::Coords; use Astro::SLA; use Number::Uncertainty; use Astro::Flux; use Astro::FluxColor; use Astro::Fluxes; use base qw/ Astro::Catalog::IO::ASCII /; use vars qw/ $VERSION $DEBUG /; $VERSION = '0.01'; $DEBUG = 0;
sub _read_catalog { my $class = shift; my $lines = shift; my %args = @_; if( ref( $lines ) ne 'ARRAY' ) { croak "Must supply catalogue contents as a reference to an array"; } if( defined( $args{'Filter'} ) && ! UNIVERSAL::isa( $args{'Filter'}, "Astro::WaveBand" ) ) { croak "Filter as passed to SExtractor->_read_catalog must be an Astro::WaveBand object"; } my $filter; if( defined( $args{'Filter'} ) ) { $filter = $args{'Filter'}->natural; } else { $filter = 'unknown'; } my $quality = $args{'Quality'}; if( ! defined( $quality ) ) { $quality = -1; } my @lines = @$lines; # Dereference, make own copy. # Create an Astro::Catalog object; my $catalog = new Astro::Catalog(); # Set up columns. my $id_column = -1; my $x_column = -1; my $x_pixel_column = -1; my $xerr_column = -1; my $xwin_column = -1; my $xwinerr_column = -1; my $y_column = -1; my $y_pixel_column = -1; my $yerr_column = -1; my $ywin_column = -1; my $ywinerr_column = -1; my $ra_column = -1; my $dec_column = -1; my $mag_iso_column = -1; my $magerr_iso_column = -1; my $flux_iso_column = -1; my $fluxerr_iso_column = -1; my $flux_isocor_column = -1; my $fluxerr_isocor_column = -1; my $mag_isocor_column = -1; my $magerr_isocor_column = -1; my $flux_aper1_column = -1; my $fluxerr_aper1_column = -1; my $mag_aper1_column = -1; my $magerr_aper1_column = -1; my $flux_aper2_column = -1; my $fluxerr_aper2_column = -1; my $mag_aper2_column = -1; my $magerr_aper2_column = -1; my $flux_auto_column = -1; my $fluxerr_auto_column = -1; my $mag_auto_column = -1; my $magerr_auto_column = -1; my $flux_best_column = -1; my $fluxerr_best_column = -1; my $mag_best_column = -1; my $magerr_best_column = -1; my $ell_column = -1; my $posang_pixel_column = -1; my $posangerr_pixel_column = -1; my $posang_world_column = -1; my $posangerr_world_column = -1; my $minor_pixel_column = -1; my $minorerr_pixel_column = -1; my $major_pixel_column = -1; my $majorerr_pixel_column = -1; my $minor_world_column = -1; my $minorerr_world_column = -1; my $major_world_column = -1; my $majorerr_world_column = -1; my $area_column = -1; my $flag_column = -1; # Loop through the lines. for ( @lines ) { my $line = $_; # If we're on a column line that starts with a #, check to see # if it's describing where the X, Y, RA, or Dec position is in # the table, or the object number, or the flux, or the error in # flux. if( $line =~ /^#/ ) { my @column = split( /\s+/, $line ); if( $column[2] =~ /^NUMBER/ ) { $id_column = $column[1] - 1; print "ID column is $id_column\n" if $DEBUG; } elsif( $column[2] =~ /^X_IMAGE/ ) { $x_column = $column[1] - 1; print "X_IMAGE column is $x_column\n" if $DEBUG; } elsif( $column[2] =~ /^Y_IMAGE/ ) { $y_column = $column[1] - 1; print "Y_IMAGE column is $y_column\n" if $DEBUG; } elsif( $column[2] =~ /^X_PIXEL/ ) { $x_pixel_column = $column[1] - 1; print "X_PIXEL column is $x_pixel_column\n" if $DEBUG; } elsif( $column[2] =~ /^Y_PIXEL/ ) { $y_pixel_column = $column[1] - 1; print "Y_PIXEL column is $y_pixel_column\n" if $DEBUG; } elsif( $column[2] =~ /^ERRX2_IMAGE/ ) { $xerr_column = $column[1] - 1; print "X ERROR column is $xerr_column\n" if $DEBUG; } elsif( $column[2] =~ /^ERRY2_IMAGE/ ) { $yerr_column = $column[1] - 1; print "Y ERROR column is $yerr_column\n" if $DEBUG; } elsif( $column[2] =~ /^XWIN_IMAGE/ ) { $xwin_column = $column[1] - 1; print "XWIN_IMAGE column is $xwin_column\n" if $DEBUG; } elsif( $column[2] =~ /^ERRX2WIN_IMAGE/ ) { $xwinerr_column = $column[1] - 1; print "ERRX2WIN_IMAGE column is $xwinerr_column\n" if $DEBUG; } elsif( $column[2] =~ /^YWIN_IMAGE/ ) { $ywin_column = $column[1] - 1; print "YWIN_IMAGE column is $ywin_column\n" if $DEBUG; } elsif( $column[2] =~ /^ERRY2WIN_IMAGE/ ) { $ywinerr_column = $column[1] - 1; print "ERRY2WIN_IMAGE column is $ywinerr_column\n" if $DEBUG; } elsif( $column[2] =~ /^ALPHA_J2000/ ) { $ra_column = $column[1] - 1; print "RA column is $ra_column\n" if $DEBUG; } elsif( $column[2] =~ /^DELTA_J2000/ ) { $dec_column = $column[1] - 1; print "DEC column is $dec_column\n" if $DEBUG; } elsif( $column[2] =~ /^MAG_ISO$/ ) { $mag_iso_column = $column[1] - 1; print "MAG_ISO column is $mag_iso_column\n" if $DEBUG; } elsif( $column[2] =~ /^MAGERR_ISO$/ ) { $magerr_iso_column = $column[1] - 1; print "MAGERR_ISO column is $magerr_iso_column\n" if $DEBUG; } elsif( $column[2] =~ /^FLUX_ISO$/ ) { $flux_iso_column = $column[1] - 1; print "FLUX_ISO column is $flux_iso_column\n" if $DEBUG; } elsif( $column[2] =~ /^FLUXERR_ISO$/ ) { $fluxerr_iso_column = $column[1] - 1; print "FLUXERR_ISO column is $fluxerr_iso_column\n" if $DEBUG; } elsif( $column[2] =~ /^FLUX_ISOCOR/ ) { $flux_isocor_column = $column[1] - 1; print "FLUX_ISOCOR column is $flux_isocor_column\n" if $DEBUG; } elsif( $column[2] =~ /^FLUXERR_ISOCOR/ ) { $fluxerr_isocor_column = $column[1] - 1; print "FLUXERR_ISOCOR column is $fluxerr_isocor_column\n" if $DEBUG; } elsif( $column[2] =~ /^MAG_ISOCOR/ ) { $mag_isocor_column = $column[1] - 1; print "MAG_ISOCOR column is $mag_isocor_column\n" if $DEBUG; } elsif( $column[2] =~ /^MAGERR_ISOCOR/ ) { $magerr_isocor_column = $column[1] - 1; print "MAGERR_ISOCOR column is $magerr_isocor_column\n" if $DEBUG; } elsif( $column[2] =~ /^FLUX_APER/ ) { $flux_aper1_column = $column[1] - 1; print "FLUX_APER column is $flux_aper1_column\n" if $DEBUG; } elsif( $column[2] =~ /^FLUXERR_APER/ ) { $fluxerr_aper1_column = $column[1] - 1; print "FLUXERR_APER column is $fluxerr_aper1_column\n" if $DEBUG; } elsif( $column[2] =~ /^MAG_APER/ ) { $mag_aper1_column = $column[1] - 1; print "MAG_APER column is $mag_aper1_column\n" if $DEBUG; } elsif( $column[2] =~ /^MAGERR_APER/ ) { $magerr_aper1_column = $column[1] - 1; print "MAGERR_APER column is $magerr_aper1_column\n" if $DEBUG; } elsif( $column[2] =~ /^FLUX_AUTO/ ) { $flux_auto_column = $column[1] - 1; print "FLUX_AUTO column is $flux_auto_column\n" if $DEBUG; } elsif( $column[2] =~ /^FLUXERR_AUTO/ ) { $fluxerr_auto_column = $column[1] - 1; print "FLUXERR_AUTO column is $fluxerr_auto_column\n" if $DEBUG; } elsif( $column[2] =~ /^MAG_AUTO/ ) { $mag_auto_column = $column[1] - 1; print "MAG_AUTO column is $mag_auto_column\n" if $DEBUG; } elsif( $column[2] =~ /^MAGERR_AUTO/ ) { $magerr_auto_column = $column[1] - 1; print "MAGERR_AUTO column is $magerr_auto_column\n" if $DEBUG; } elsif( $column[2] =~ /^FLUX_BEST/ ) { $flux_best_column = $column[1] - 1; print "FLUX_BEST column is $flux_best_column\n" if $DEBUG; } elsif( $column[2] =~ /^FLUXERR_BEST/ ) { $fluxerr_best_column = $column[1] - 1; print "FLUXERR_BEST column is $fluxerr_best_column\n" if $DEBUG; } elsif( $column[2] =~ /^MAG_BEST/ ) { $mag_best_column = $column[1] - 1; print "MAG_BEST column is $mag_best_column\n" if $DEBUG; } elsif( $column[2] =~ /^MAGERR_BEST/ ) { $magerr_best_column = $column[1] - 1; print "MAGERR_BEST_COLUMN is $magerr_best_column\n" if $DEBUG; } elsif( $column[2] =~ /^ELLIPTICITY/ ) { $ell_column = $column[1] - 1; print "ELLIPTICITY column is $ell_column\n" if $DEBUG; } elsif( $column[2] =~ /^THETA_IMAGE/ ) { $posang_pixel_column = $column[1] - 1; print "THETA_IMAGE column is $posang_pixel_column\n" if $DEBUG; } elsif( $column[2] =~ /^ERRTHETA_IMAGE/ ) { $posangerr_pixel_column = $column[1] - 1; print "ERRTHETA_IMAGE column is $posangerr_pixel_column\n" if $DEBUG; } elsif( $column[2] =~ /^THETA_SKY/ ) { $posang_world_column = $column[1] - 1; print "THETA_SKY column is $posang_world_column\n" if $DEBUG; } elsif( $column[2] =~ /^ERRTHETA_SKY/ ) { $posangerr_world_column = $column[1] - 1; print "ERRTHETA_SKY column is $posangerr_world_column\n" if $DEBUG; } elsif( $column[2] =~ /^B_IMAGE/ ) { $minor_pixel_column = $column[1] - 1; print "B_IMAGE column is $minor_pixel_column\n" if $DEBUG; } elsif( $column[2] =~ /^ERRB_IMAGE/ ) { $minorerr_pixel_column = $column[1] - 1; print "ERRB_IMAGE column is $minorerr_pixel_column\n" if $DEBUG; } elsif( $column[2] =~ /^A_IMAGE/ ) { $major_pixel_column = $column[1] - 1; print "A_IMAGE column is $major_pixel_column\n" if $DEBUG; } elsif( $column[2] =~ /^ERRA_IMAGE/ ) { $majorerr_pixel_column = $column[1] - 1; print "ERRA_IMAGE column is $majorerr_pixel_column\n" if $DEBUG; } elsif( $column[2] =~ /^B_WORLD/ ) { $minor_world_column = $column[1] - 1; print "B_WORLD column is $minor_world_column\n" if $DEBUG; } elsif( $column[2] =~ /^ERRB_WORLD/ ) { $minorerr_world_column = $column[1] - 1; print "ERRB_WORLD column is $minorerr_world_column\n" if $DEBUG; } elsif( $column[2] =~ /^A_WORLD/ ) { $major_world_column = $column[1] - 1; print "A_WORLD column is $major_world_column\n" if $DEBUG; } elsif( $column[2] =~ /^ERRA_WORLD/ ) { $majorerr_world_column = $column[1] - 1; print "ERR_AWORLD column is $majorerr_world_column\n" if $DEBUG; } elsif( $column[2] =~ /^ISOAREA_IMAGE/ ) { $area_column = $column[1] - 1; print "AREA column is $area_column\n" if $DEBUG; } elsif( $column[2] =~ /^FLAGS/ ) { $flag_column = $column[1] - 1; print "FLAGS column is $flag_column\n" if $DEBUG; } next; } # Remove leading whitespace and go to the next line if the # current one is blank. $line =~ s/^\s+//; next if length( $line ) == 0; # Form an array of the fields in the catalogue. my @fields = split( /\s+/, $line ); # Don't deal with this object if our requested quality is not -1 # and the quality of the object is not equal to the requested # quality and we have a quality flag for this object. if( ( $quality != -1 ) && ( $flag_column != -1 ) && ( $fields[$flag_column] != $quality ) ) { next; } # Create a temporary Astro::Catalog::Item object. my $star = new Astro::Catalog::Item(); # Grab the coordinates, forming an Astro::Coords object., but only # if the RA and Dec columns are defined. if( $ra_column != -1 && $dec_column != -1 ) { my $coords = new Astro::Coords( type => 'J2000', ra => $fields[$ra_column], dec => $fields[$dec_column], name => ( $id_column != -1 ? $fields[$id_column] : undef ), units => 'degrees', ); $star->coords( $coords ); } if( $flag_column != -1 ) { $star->quality( $fields[$flag_column] ); } else { $star->quality( 0 ); } if( $id_column != -1 ) { $star->id( $fields[$id_column] ); } # Set up the various flux and magnitude measurements. if( $mag_iso_column != -1 ) { my $num; if( $magerr_iso_column != -1 ) { $num = new Number::Uncertainty( Value => $fields[$mag_iso_column], Error => $fields[$magerr_iso_column] ); } else { $num = new Number::Uncertainty( Value => $fields[$mag_iso_column] ); } my $mag_iso = new Astro::Flux( $num, 'MAG_ISO', $filter ); $star->fluxes( new Astro::Fluxes( $mag_iso ) ); } if( $flux_iso_column != -1 ) { my $num; if( $fluxerr_iso_column != -1 ) { $num = new Number::Uncertainty( Value => $fields[$flux_iso_column], Error => $fields[$fluxerr_iso_column] ); } else { $num = new Number::Uncertainty( Value => $fields[$flux_iso_column] ); } my $flux_iso = new Astro::Flux( $num, 'FLUX_ISO', $filter ); $star->fluxes( new Astro::Fluxes( $flux_iso ) ); } if( $mag_isocor_column != -1 ) { my $num; if( $magerr_isocor_column != -1 ) { $num = new Number::Uncertainty( Value => $fields[$mag_isocor_column], Error => $fields[$magerr_isocor_column] ); } else { $num = new Number::Uncertainty( Value => $fields[$mag_isocor_column] ); } my $mag_isocor = new Astro::Flux( $num, 'MAG_ISOCOR', $filter ); $star->fluxes( new Astro::Fluxes( $mag_isocor ) ); } if( $flux_isocor_column != -1 ) { my $num; if( $fluxerr_isocor_column != -1 ) { $num = new Number::Uncertainty( Value => $fields[$flux_isocor_column], Error => $fields[$fluxerr_isocor_column] ); } else { $num = new Number::Uncertainty( Value => $fields[$flux_isocor_column] ); } my $flux_isocor = new Astro::Flux( $num, 'FLUX_ISOCOR', $filter ); $star->fluxes( new Astro::Fluxes( $flux_isocor ) ); } if( $mag_aper1_column != -1 ) { my $num; if( $magerr_aper1_column != -1 ) { $num = new Number::Uncertainty( Value => $fields[$mag_aper1_column], Error => $fields[$magerr_aper1_column] ); } else { $num = new Number::Uncertainty( Value => $fields[$mag_aper1_column] ); } my $mag_aper1 = new Astro::Flux( $num, 'MAG_APER1', $filter ); $star->fluxes( new Astro::Fluxes( $mag_aper1 ) ); } if( $flux_aper1_column != -1 ) { my $num; if( $fluxerr_aper1_column != -1 ) { $num = new Number::Uncertainty( Value => $fields[$flux_aper1_column], Error => $fields[$fluxerr_aper1_column] ); } else { $num = new Number::Uncertainty( Value => $fields[$flux_aper1_column] ); } my $flux_aper1 = new Astro::Flux( $num, 'FLUX_APER1', $filter ); $star->fluxes( new Astro::Fluxes( $flux_aper1 ) ); } if( $mag_auto_column != -1 ) { my $num; if( $magerr_auto_column != -1 ) { $num = new Number::Uncertainty( Value => $fields[$mag_auto_column], Error => $fields[$magerr_auto_column] ); } else { $num = new Number::Uncertainty( Value => $fields[$mag_auto_column] ); } my $mag_auto = new Astro::Flux( $num, 'MAG_AUTO', $filter ); $star->fluxes( new Astro::Fluxes( $mag_auto ) ); } if( $flux_auto_column != -1 ) { my $num; if( $fluxerr_auto_column != -1 ) { $num = new Number::Uncertainty( Value => $fields[$flux_auto_column], Error => $fields[$fluxerr_auto_column] ); } else { $num = new Number::Uncertainty( Value => $fields[$flux_auto_column] ); } my $flux_auto = new Astro::Flux( $num, 'FLUX_AUTO', $filter ); $star->fluxes( new Astro::Fluxes( $flux_auto ) ); } if( $mag_best_column != -1 ) { my $num; if( $magerr_best_column != -1 ) { $num = new Number::Uncertainty( Value => $fields[$mag_best_column], Error => $fields[$magerr_best_column] ); } else { $num = new Number::Uncertainty( Value => $fields[$mag_best_column] ); } my $mag_best = new Astro::Flux( $num, 'MAG_BEST', $filter ); $star->fluxes( new Astro::Fluxes( $mag_best ) ); } if( $flux_best_column != -1 ) { my $num; if( $fluxerr_best_column != -1 ) { $num = new Number::Uncertainty( Value => $fields[$flux_best_column], Error => $fields[$fluxerr_best_column] ); } else { $num = new Number::Uncertainty( Value => $fields[$flux_best_column] ); } my $flux_best = new Astro::Flux( $num, 'FLUX_BEST', $filter ); $star->fluxes( new Astro::Fluxes( $flux_best ) ); } # Set the x and y coordinates. Preferentially use the NDF pixel # coordinates, then the windowed coordinates, then the standard # coordinates. if( $x_pixel_column != -1 ) { $star->x( $fields[$x_pixel_column] ); } elsif( $xwin_column != -1 ) { $star->x( $fields[$xwin_column] ); } elsif( $x_column != -1 ) { $star->x( $fields[$x_column] ); } if( $y_pixel_column != -1 ) { $star->y( $fields[$y_pixel_column] ); } elsif( $ywin_column != -1 ) { $star->y( $fields[$ywin_column] ); } elsif( $x_column != -1 ) { $star->y( $fields[$y_column] ); } # Set up the star's morphology. my $ellipticity; my $position_angle_pixel; my $position_angle_world; my $major_axis_pixel; my $minor_axis_pixel; my $major_axis_world; my $minor_axis_world; my $area; if( $ell_column != -1 ) { $ellipticity = new Number::Uncertainty( Value => $fields[$ell_column] ); } if( $posang_pixel_column != -1 ) { if( $posangerr_pixel_column != -1 ) { $position_angle_pixel = new Number::Uncertainty( Value => $fields[$posang_pixel_column], Error => $fields[$posangerr_pixel_column] ); } else { $position_angle_pixel = new Number::Uncertainty( Value => $fields[$posang_pixel_column] ); } } if( $posang_world_column != -1 ) { if( $posangerr_world_column != -1 ) { $position_angle_world = new Number::Uncertainty( Value => $fields[$posang_world_column], Error => $fields[$posangerr_world_column] ); } else { $position_angle_world = new Number::Uncertainty( Value => $fields[$posang_world_column] ); } } if( $major_pixel_column != -1 ) { if( $majorerr_pixel_column != -1 ) { $major_axis_pixel = new Number::Uncertainty( Value => $fields[$major_pixel_column], Error => $fields[$majorerr_pixel_column] ); } else { $major_axis_pixel = new Number::Uncertainty( Value => $fields[$major_pixel_column] ); } } if( $major_world_column != -1 ) { if( $majorerr_world_column != -1 ) { $major_axis_world = new Number::Uncertainty( Value => $fields[$major_world_column], Error => $fields[$majorerr_world_column] ); } else { $major_axis_world = new Number::Uncertainty( Value => $fields[$major_world_column] ); } } if( $minor_pixel_column != -1 ) { if( $minorerr_pixel_column != -1 ) { $minor_axis_pixel = new Number::Uncertainty( Value => $fields[$minor_pixel_column], Error => $fields[$minorerr_pixel_column] ); } else { $minor_axis_pixel = new Number::Uncertainty( Value => $fields[$minor_pixel_column] ); } } if( $minor_world_column != -1 ) { if( $minorerr_world_column != -1 ) { $minor_axis_world = new Number::Uncertainty( Value => $fields[$minor_world_column], Error => $fields[$minorerr_world_column] ); } else { $minor_axis_world = new Number::Uncertainty( Value => $fields[$minor_world_column] ); } } if( $area_column != -1 ) { $area = new Number::Uncertainty( Value => $fields[$area_column] ); } my $morphology = new Astro::Catalog::Item::Morphology( ellipticity => $ellipticity, position_angle_pixel => $position_angle_pixel, position_angle_world => $position_angle_world, major_axis_pixel => $major_axis_pixel, minor_axis_pixel => $minor_axis_pixel, major_axis_world => $major_axis_world, minor_axis_world => $minor_axis_world, area => $area, ); $star->morphology( $morphology ); # Push the star onto the catalog. $catalog->pushstar( $star ); } $catalog->origin( 'IO::SExtractor' ); return $catalog; }
sub _write_catalog { croak ( 'Usage: _write_catalog( $catalog, [%opts] ') unless scalar(@_) >= 1; my $class = shift; my $catalog = shift; my @output; # First, the header. What we write to the header depends on what # values we have for our objects, so check for ID, X, Y, RA, and Dec # values. my $write_id = 0; my $write_x = 0; my $write_y = 0; my $write_ra = 0; my $write_dec = 0; my @stars = $catalog->stars(); if( defined( $stars[0]->id ) ) { $write_id = 1; } if( defined( $stars[0]->x ) ) { $write_x = 1; } if( defined( $stars[0]->y ) ) { $write_y = 1; } if( defined( $stars[0]->coords->ra ) ) { $write_ra = 1; } if( defined( $stars[0]->coords->dec ) ) { $write_dec = 1; } # Now for the header. my $pos = 1; if( $write_id ) { push @output, "# $pos NUMBER Running object number"; $pos++; } if( $write_x ) { push @output, "# $pos X_IMAGE Object position along x [pixel]"; $pos++; } if( $write_y ) { push @output, "# $pos Y_IMAGE Object position along y [pixel]"; $pos++; } if( $write_ra ) { push @output, "# $pos ALPHA_J2000 Right ascension of barycenter (J2000) [deg]"; $pos++; } if( $write_dec ) { push @output, "# $pos DELTA_J2000 Declination of barycenter (J2000) [deg]"; $pos++; } # Now go through the objects. foreach my $star ( @stars ) { my $output_string = ""; if( $write_id ) { $output_string .= $star->id . " "; } if( $write_x ) { $output_string .= $star->x . " "; } if( $write_y ) { $output_string .= $star->y . " "; } if( $write_ra ) { $output_string .= $star->coords->ra->degrees . " "; } if( $write_dec ) { $output_string .= $star->coords->dec->degrees . " "; } push @output, $output_string; } # And return! return \@output; }
1;