#!/usr/bin/perl # # Finds the best match for the given star/raw data files # # $Name: $ # # $Log: matchStars.pl,v $ # Revision 1.5 2002/01/29 04:55:33 robc # General re-write so matching is 'deterministic'. # Add support for AppConfig config file parsing. # Remove mounds of old code. # Perltidy. # # Revision 1.4 2001/12/09 01:36:08 robc # Change to use pixel scale from fits header rather than hard coded values # # Revision 1.3 2001/11/14 04:01:15 robc # Perltidy code # # Revision 1.2 2001/10/06 10:15:34 robc # General hacking to try to get it working correctly. # # Revision 1.1 2001/09/23 17:31:41 robc # *** empty log message *** # use warnings; use strict; use lib( $ENV{ TASSIV_FITS_PM } ); use CFITSIO qw( :longnames :constants ); use IO::Socket; use Math::NumberCruncher; use FITS; use Astro::Time; use DB_File; use AppConfig qw( :argcount :expand ); autoflush STDOUT; my $ID = q$Id: matchStars.pl,v 1.5 2002/01/29 04:55:33 robc Exp $; my $version = join ( ' ', ( split ( ' ', $ID ) )[ 1 .. 3 ] ); $version =~ s/,v\b//; $version =~ s/(\S+)$/($1)/; sub find_best( $$$$$$$$ ); sub initialize_star_catalog( $$$ ); sub find_subset( $$$$$$ ); sub calculate_perc( $$$$ ); sub setup_args( $$ ); die "Please specify the fit file to use\n" unless my $fit_file = shift; my $CONFIG_FILE = '/tass/src/tassiv_reduce/tassiv_reduce.cfg'; my $c = AppConfig->new( { CREATE => 1, GLOBAL => { EXPAND => EXPAND_VAR, ARGCOUNT => ARGCOUNT_ONE } } ); $c = setup_args( $c, $CONFIG_FILE ); my $star_file = $fit_file . ".raw"; my $dest_file = $fit_file . ".mat"; die "$star_file doesn\'t exist" unless -e $star_file; die "$dest_file already exists" if -e $dest_file; print "$fit_file...\n"; my ( $file_ra, $file_dec ) = FITS_get_ra_dec( $fit_file ); $file_ra = rad2deg( $file_ra ); $file_dec = rad2deg( $file_dec ); my ( $size_x, $size_y ) = FITS_get_size( $fit_file ); my ( $ra_cov, $dec_cov ) = FITS_get_pixel_size( $fit_file ); $ra_cov = abs( $ra_cov * $size_x ); $dec_cov = abs( $dec_cov * $size_y ); my $start_ra = $file_ra - $ra_cov * $c->search_ra; my $ra_inc = 2 * $ra_cov * $c->search_ra / $c->div_ra; my $start_dec = $file_dec - $dec_cov * $c->search_dec; my $dec_inc = 2 * $dec_cov * $c->search_dec / $c->div_dec; my $match_star = 'match_star.list'; my $match_cat = 'match_cat.list'; my $temp_file = $fit_file . '.temp'; my $cmd = 'sort -n -k ' . ( $c->mag_col + 1 ) . " $star_file | head -"; $cmd .= $c->keep_process . " > $match_star"; `$cmd`; my ( $band ) = uc eval FITS_get_key_value( $fit_file, 'FILTER' ); my ( $real_ra, $real_dec ) = ( $file_ra, $file_dec ); my ( $x, $y, $per ); my $done = 0; my ( %star_ra, %star_dec, @star_catalog ); $star_ra{ min } = $start_ra - $ra_cov; $star_ra{ max } = $file_ra + $ra_cov * $c->search_ra + $ra_cov; $star_dec{ min } = $start_dec - $dec_cov; $star_dec{ max } = $file_dec + $dec_cov * $c->search_dec + $dec_cov; @star_catalog = initialize_star_catalog( $band, \%star_ra, \%star_dec ); $c->div_ra, $c->div_dec; for ( my $x = 0; $x < $c->iterations; ++$x ) { ( $real_ra, $real_dec, $per ) = find_best( $start_ra, $start_dec, $ra_cov, $dec_cov, $ra_inc, $dec_inc, $c->div_ra, $c->div_dec ); last if $per < $c->keep_percent; $ra_inc /= $c->inc_reduction; $dec_inc /= $c->inc_reduction; $start_ra = $real_ra - $c->div_ra * $ra_inc / 2; $start_dec = $real_dec - $c->div_dec * $dec_inc / 2; } if ( $per > $c->keep_percent ) { printf( "Finding final match using RA: %6.2f (%6.2f) DEC: %6.2f (%6.2f)\n", $real_ra, $file_ra, $real_dec, $file_dec ); $cmd = 'sort -n -k ' . ( $c->mag_col + 1 ) . " $star_file | head -"; $cmd .= $c->keep_final . " > $match_star"; `$cmd`; find_subset( $real_ra, $real_dec, $ra_cov, $dec_cov, $match_cat, $c->keep_final ); my $cmd = "match $match_star"; $cmd .= ' ' . $c->x_col; $cmd .= ' ' . $c->y_col; $cmd .= ' ' . $c->mag_col; $cmd .= " $match_cat 1 2 3"; $cmd .= ' linear nobjs=' . $c->keep_final; $cmd .= ' triad=0.0015 matchrad=0.0000242'; # $cmd .= " recalc max_iter=3"; # $cmd .= " halt_sigma=1.0e-11 scale=1.0"; my $best_output = `$cmd`; `wc -l matched.mtA` =~ /(\d+)/; my $match_count = $1; $best_output =~ /a\=([-.\d]+)\s+ b\=([-.\d]+)\s+ c\=([-.\d]+)\s+ d\=([-.\d]+)\s+ e\=([-.\d]+)\s+ f\=([-.\d]+)\s+ /x; my $a = $1; my $b = $2; my $c = $3; my $d = $4; my $e = $5; my $f = $6; my $sum1 = abs( $b ) + abs( $f ); my $sub1 = abs( abs( $b ) - abs( $f ) ); my $sum2 = abs( $c ) + abs( $e ); my $sub2 = abs( abs( $c ) - abs( $e ) ); if ( $sum1 == 0 or $sum2 == 0 ) { print "Very bad match\n"; } else { my $per1 = 100 * $sub1 / $sum1; my $per2 = 100 * $sub2 / $sum2; if ( ( $per1 > 10 ) || ( $per2 > .2 ) ) { printf "Bad match %5.1f%% & %5.1f%%\n", $per1, $per2; } else { printf "Good match %5.1f%% & %5.1f%%\n", $per1, $per2; tie my %thash, "DB_File", $dest_file or die "Error: cannot tie hash to $dest_file"; $thash{ type } = "Linear"; $thash{ a } = $a; $thash{ b } = $b; $thash{ c } = $c; $thash{ d } = $d; $thash{ e } = $e; $thash{ f } = $f; $thash{ ra } = $real_ra; $thash{ dec } = $real_dec; $thash{ count } = $match_count; $thash{ to_cat } = 1; untie %thash; } } } else { open( FILE, ">> matchStars.bad" ); printf FILE "$star_file matched %6.2f%%\n", $per; close( FILE ); printf( "Not enough stars matched %5.2f%%\n\n", $per ); } sub find_best( $$$$$$$$ ) { my ( $start_ra, $start_dec, $ra_cov, $dec_cov, $ra_inc, $dec_inc, $end_x, $end_y ) = @_; my ( $x, $y, $percent, $output, $use_ra, $use_dec ); my ( $best_percent, $bra, $bdec ) = ( 0, $start_ra, $start_dec ); printf( "%6.2f->%6.2fx%4.2f %5.2f->%5.2fx%4.2f ", $start_ra, $start_ra + $ra_inc * $end_x, $ra_inc, $start_dec, $start_dec + $dec_inc * $end_y, $dec_inc ); for ( $x = 0; $x < $end_x; ++$x ) { $use_ra = $start_ra + $x * $ra_inc; for ( $y = 0; $y < $end_y; ++$y ) { $use_dec = $start_dec + $y * $dec_inc; ( $percent, $output ) = calculate_perc( $use_ra, $use_dec, $ra_cov, $dec_cov ); if ( ( $percent > $best_percent ) ) { $best_percent = $percent; $bra = $use_ra; $bdec = $use_dec; } } printf( "." ); } printf( " %6.2f%% %6.2f %6.2f\n", $best_percent, $bra, $bdec ); return ( $bra, $bdec, $best_percent ); } sub initialize_star_catalog( $$$ ) { my ( $band, $rah, $dech ) = @_; my ( @catalog, @data, $cmd ); my $ra = $rah->{ min } + ( $rah->{ max } - $rah->{ min } ) / 2; my $dec = $dech->{ min } + ( $dech->{ max } - $dech->{ min } ) / 2; my $dra = ( $rah->{ max } - $ra ); my $ddec = ( $dech->{ max } - $dec ); print "Initializing star catalog for:\n"; printf "\tRA: %6.2f +-%5.2f DEC: %6.2f +-%5.2f...\n", $ra, $dra, $dec, $ddec; $cmd = "findStars.pl $band $ra $dec $dra $ddec |"; open FILE, "> test.out"; open( DATA, $cmd ); while ( ) { @data = split ( /\s+/, $_ ); push @catalog, [ @data ]; print FILE join ' ', @data, "\n"; } close FILE; @catalog = sort( { $$a[ 3 ] <=> $$b[ 3 ] } @catalog ); return ( @catalog ); } sub find_subset( $$$$$$ ) { my ( $ra, $dec, $ra_cov, $dec_cov, $file, $keep ) = @_; my $star_count = 0; my @ra_min = $ra - $ra_cov / 2; my @ra_max = $ra + $ra_cov / 2; my $dec_min = $dec - $dec_cov / 2; my $dec_max = $dec + $dec_cov / 2; if ( ( $ra_min[ 0 ] < $star_ra{ min } ) || ( $ra_max[ 0 ] > $star_ra{ max } ) || ( $dec_min < $star_dec{ min } ) || ( $dec_max > $star_dec{ max } ) ) { print( "\n$ra_min[ 0 ] < $star_ra{ min }\n" ); print( "$ra_max[ 0 ] > $star_ra{ max }\n" ); print( "$dec_min < $star_dec{ min }\n" ); print( "$dec_max > $star_dec{ max }\n" ); die "\nError: didn't initialize catalog with enough stars\n"; } my $split_range = 0; if ( $ra_min[ 0 ] < 0 ) { $ra_min[ 1 ] = $ra_min[ 0 ] + 360; $ra_min[ 0 ] = 0; $ra_max[ 1 ] = 360; $split_range = 1; } elsif ( $ra_max[ 0 ] > 360 ) { $ra_min[ 1 ] = 0; $ra_max[ 1 ] = $ra_max[ 0 ] - 360; $ra_max[ 0 ] = 360; $split_range = 1; } open( STAR, "> $temp_file" ); if ( $split_range ) { foreach my $star ( @star_catalog ) { if ( ( $$star[ 2 ] >= $dec_min ) && ( $$star[ 2 ] <= $dec_max ) ) { if ( ( ( $$star[ 1 ] >= $ra_min[ 0 ] ) && ( $$star[ 1 ] <= $ra_max[ 0 ] ) ) || ( ( $$star[ 1 ] >= $ra_min[ 1 ] ) && ( $$star[ 1 ] <= $ra_max[ 1 ] ) ) ) { print STAR join ( "\t", @$star ) . "\n"; last if ( $keep && ( ++$star_count >= $keep ) ); } } } } else { foreach my $star ( @star_catalog ) { if ( ( $$star[ 2 ] >= $dec_min ) && ( $$star[ 2 ] <= $dec_max ) ) { if ( ( $$star[ 1 ] >= $ra_min[ 0 ] ) && ( $$star[ 1 ] <= $ra_max[ 0 ] ) ) { ++$star_count; print STAR join ( "\t", @$star ) . "\n"; last if ( $keep && ( ++$star_count >= $keep ) ); } } } } close( STAR ); `project_coords $temp_file 1 2 $ra $dec outfile=$file`; unlink( $temp_file ); return ( $star_count ); } sub calculate_perc( $$$$ ) { my ( $ra, $dec, $ra_cov, $dec_cov ) = @_; my ( $match_count, $output ) = ( 0 ); if ( find_subset( $ra, $dec, $ra_cov, $dec_cov, $match_cat, $c->keep_process ) ) { my $cmd = "match $match_star"; $cmd .= ' ' . $c->x_col; $cmd .= ' ' . $c->y_col; $cmd .= ' ' . $c->mag_col; $cmd .= " $match_cat 1 2 3"; $cmd .= ' linear nobjs=' . $c->keep_process; $cmd .= ' triad=0.0015 matchrad=0.0000242'; `$cmd`; `wc -l matched.mtA` =~ /(\d+)/; $match_count = $1; #print "--$match_count--\n"; #print "$cmd\n"; #exit; } return ( 100 * $match_count / $c->keep_process ); } sub setup_args( $$ ) { my ( $c, $file ) = @_; $c->define( Match_Stars_search_ra => { DEFAULT => 1, ALIAS => 'search_ra' }, Match_Stars_search_dec => { DEFAULT => 1, ALIAS => 'search_dec' }, Match_Stars_div_ra => { DEFAULT => 5, ALIAS => 'div_ra' }, Match_Stars_div_dec => { DEFAULT => 5, ALIAS => 'div_dec' }, Match_Stars_inc_reduction => { DEFAULT => 3.5, ALIAS => 'inc_reduction' }, Match_Stars_iterations => { DEFAULT => 3, ALIAS => 'iterations' }, Match_Stars_keep_percent => { DEFAULT => 19, ALIAS => 'keep_percent' }, Match_Stars_keep_process => { DEFAULT => 61, ALIAS => 'keep_process' }, Match_Stars_keep_final => { DEFAULT => 91, ALIAS => 'keep_final' }, Match_Stars_mag_column => { DEFAULT => 2, ALIAS => 'mag_col' }, Match_Stars_x_column => { DEFAULT => 0, ALIAS => 'x_col' }, Match_Stars_y_column => { DEFAULT => 1, ALIAS => 'y_col' }, ); $c->file( $file ); $c->define( 'help|h!' ); $c->define( 'version|v!' ); $c->define( 'force|f!' ); $c->args( \@ARGV ); return $c; }