File indexing completed on 2024-09-08 03:29:00
0001 #!/usr/bin/perl 0002 # 0003 # tycdatatomysql_pm.pl Put star data from Tycho-1/Tycho-2 ASCII data file into a database 0004 # 0005 # CAUTION: Will truncate the table supplied! 0006 # 0007 # NOTE: The Tycho-1 text data file should be supplied via stdin: 0008 # use cat <tycho-1 data file> | <this script> to achieve this. 0009 # 0010 # This version of the script takes into account the proper motion of the star for J2000.0 +/- x millenia 0011 use strict; 0012 use DBI; 0013 use HTMesh; 0014 use Math::Trig; 0015 use Math::Complex; 0016 0017 my $ERROR; 0018 my @STARS; 0019 0020 my $VERBOSE = 0; 0021 0022 my $cnt; 0023 0024 # For database handling 0025 my $db_db = shift; 0026 my $db_user = shift; 0027 !($db_db eq "") and !($db_user eq "") or print "USAGE: " . $0 . " <database name> <MySQL Username> [[MySQL Password [Table [Millenia]]]\n" and exit; 0028 my $db_pass = shift; 0029 my $db_tbl = shift; 0030 my $pm_millenia = shift; 0031 ($pm_millenia eq "") and $pm_millenia = 10; 0032 if($db_tbl eq "") { 0033 $db_tbl = "tycho" 0034 } 0035 0036 my $db_query = qq/CREATE DATABASE IF NOT EXISTS `$db_db`;/; 0037 my $db_select_query = qq/USE `$db_db`/; 0038 0039 my $tbl_query = qq/ 0040 CREATE TABLE IF NOT EXISTS `$db_tbl` ( 0041 `Trixel` int NOT NULL COMMENT 'Trixel Name', 0042 `HD` int NULL COMMENT 'HD Catalog Number', 0043 `RA` double NOT NULL COMMENT 'RA Hours', 0044 `Dec` double NOT NULL COMMENT 'Declination Degrees', 0045 `dRA` double NOT NULL COMMENT 'Proper Motion along RA', 0046 `dDec` double NOT NULL COMMENT 'Proper Motion along Dec', 0047 `PM` double NOT NULL COMMENT 'Proper Motion (magnitude)', 0048 `Parallax` double NOT NULL COMMENT 'Parallax', 0049 `Mag` float NOT NULL COMMENT 'Visual Magnitude', 0050 `BV_Index` float NOT NULL COMMENT 'B-V Color Index', 0051 `Spec_Type` char(2) NOT NULL COMMENT 'Spectral Class', 0052 `Mult` tinyint(1) NOT NULL COMMENT 'Multiple?', 0053 `Var` tinyint(1) NOT NULL COMMENT 'Variable?', 0054 `Name` varchar(70) default NULL COMMENT 'Long Name', 0055 `GName` varchar(15) default NULL COMMENT 'Genetive Name', 0056 `UID` int(11) NOT NULL auto_increment COMMENT 'Unique ID', 0057 `Copies` tinyint(8) NOT NULL COMMENT 'Number of Copies of the star', 0058 PRIMARY KEY (`UID`), 0059 UNIQUE KEY `UID` (`UID`), 0060 KEY `Trixel` (`Trixel`,`PM`,`Mag`) 0061 ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;/; 0062 0063 my $tbl_trunc_query = qq/TRUNCATE TABLE `$db_tbl`/; 0064 0065 # For the HTMesh 0066 my $level = 3; # Note: If you change this, change at the TODO below as well. 0067 0068 # Create a new HTMesh, of level $level 0069 my $mesh = new HTMesh($level); 0070 0071 # Get the database handle 0072 my $dbh = DBI->connect("DBI:mysql:", $db_user, $db_pass, { RaiseError => 1, AutoCommit => 0 }); 0073 0074 my @fields = qw/Trixel HD RA Dec dRA dDec PM Parallax Mag BV_Index 0075 Spec_Type Mult Var GName Name Copies/; 0076 0077 $dbh->do($db_query); 0078 $dbh->do($db_select_query); 0079 $dbh->do($tbl_query); 0080 $dbh->do($tbl_trunc_query); 0081 $dbh->commit(); 0082 0083 if( $VERBOSE ) { 0084 for( @fields ) { 0085 printf $_ . "|"; 0086 } 0087 printf "\n"; 0088 } 0089 0090 while(<>) { 0091 m/^\s*#/ and do { print if $VERBOSE; next}; 0092 m/\S/ or do { print if $VERBOSE; next}; 0093 chomp; 0094 my $star = kstars_unpack($_) or do { 0095 warn sprintf("%4d: FORMAT ERROR ($ERROR):\n$_\n", $.); 0096 next; 0097 }; 0098 $star->{line} = $.; 0099 0100 if( $VERBOSE ) { 0101 for(@fields) { 0102 printf $star->{$_} . "|"; 0103 } 0104 printf "\n"; 0105 } 0106 0107 my ( $RA1, $Dec1 ) = proper_motion_coords( $star->{RA}, $star->{Dec}, $star->{dRA}, $star->{dDec}, -$pm_millenia * 1000 ); 0108 my ( $RA2, $Dec2 ) = proper_motion_coords( $star->{RA}, $star->{Dec}, $star->{dRA}, $star->{dDec}, $pm_millenia * 1000 ); 0109 0110 # ( $star->{PM} > 1000.0 ) and print "$RA1, $Dec1 : $star->{RA}, $star->{Dec} : $RA2, $Dec2\n"; 0111 0112 my $leftDec; 0113 my $rightDec; 0114 my $topRA; 0115 my $botRA; 0116 0117 my $verbose = 0; 0118 # if( $star->{HD} == "91125" ) { 0119 # $verbose = 1; 0120 # } 0121 # else { 0122 # print $star->{HD} . "\n"; 0123 # } 0124 0125 $verbose and print "(RA1, RA2, Dec1, Dec2) = ($RA1 ,$RA2 ,$Dec1 ,$Dec2 )\n"; 0126 0127 if( $Dec1 < $Dec2 ) { 0128 $leftDec = $Dec1; 0129 $rightDec = $Dec2; 0130 } 0131 else { 0132 $leftDec = $Dec2; 0133 $rightDec = $Dec1; 0134 } 0135 0136 if( $RA1 < $RA2 ) { 0137 $topRA = $RA1; 0138 $botRA = $RA2; 0139 } 0140 else { 0141 $topRA = $RA2; 0142 $botRA = $RA1; 0143 } 0144 0145 $verbose and print "leftDec = $leftDec and topRA = $topRA\n"; 0146 0147 my $epsilon = ( 90.0 / 3600.0 ) / 15.0; 0148 0149 $star->{originalTrixelID} = $mesh->lookup_id( $star->{RA}, $star->{Dec} ); 0150 0151 $verbose and print "Original trixel ID = " . $star->{originalTrixelID}; 0152 0153 my @trixels; 0154 if( $star->{Name} eq "" && $star->{GName} eq "" ) { 0155 my $separation = sqrt( hour2deg($botRA - $topRA) * hour2deg($botRA - $topRA) + ($leftDec - $rightDec) * ($leftDec - $rightDec) ); 0156 if( $separation > 50.0 / 60.0 ) { 0157 # $mesh->intersect_poly4( $botRA, $leftDec, 0158 # $botRA - $epsilon, $leftDec + $epsilon, 0159 # $topRA - $epsilon, $rightDec - $epsilon, 0160 # $topRA, $rightDec); 0161 $mesh->intersect_poly4( $topRA, $rightDec, 0162 $topRA - $epsilon, $rightDec - $epsilon, 0163 $botRA - $epsilon, $leftDec + $epsilon, 0164 $botRA, $leftDec); 0165 0166 @trixels = $mesh->results(); 0167 } 0168 if( !@trixels ) { 0169 @trixels = $mesh->lookup_id( $star->{RA}, $star->{Dec} ); 0170 } 0171 } 0172 else { 0173 @trixels = $mesh->lookup_id( $star->{RA}, $star->{Dec} ); 0174 } 0175 0176 for(@trixels) { 0177 my $tid = $_; 0178 $star->{Trixel} = $tid - 512; # TODO : Change if you change HTMesh level. 0179 $star->{Copies} = 0; 0180 if( $star->{originalTrixelID} == $tid ) { 0181 $star->{Copies} = @trixels; 0182 } 0183 $verbose and print "Trixel = " . $star->{Trixel} . "\n"; 0184 my $query ||= qq/INSERT INTO `$db_tbl` (/ . 0185 join(", ", map {"`$_`"} @fields) . 0186 qq/) VALUES (/ . 0187 join(", ", map {"?"} @fields) . 0188 qq/)/; 0189 my $sth ||= $dbh->prepare($query); 0190 $sth->execute(@$star{@fields}); 0191 } 0192 0193 } 0194 0195 $dbh->commit(); 0196 0197 $dbh->disconnect(); 0198 0199 exit; 0200 0201 #---------------------------------------------------------------------------- 0202 #--- Subroutines ------------------------------------------------------------ 0203 #---------------------------------------------------------------------------- 0204 0205 sub kstars_unpack { 0206 my $line = shift; 0207 chomp $line; 0208 0209 # Column number 78 demarkates between numeric data and the genetive/long names 0210 my $s1 = substr($line, 0, 80, ""); 0211 0212 # Comments on the File format: 0213 # ============================ 0214 # * Most fields are of variable width 0215 # * All fields are separated by atleast one space and have a non-blank value, 0216 # excepting the case of genetive name and long name fields 0217 # 0218 # Fields are: 0219 # ----------- 0220 # HDNum RA Dec pmRA pmDec parallax Vmag B-V mult? var? [genetive : full] 0221 # 0222 # The regexp used here is as strict as possible on the adherence to field formats 0223 0224 $s1 =~ m{^\s*(\d+)\s # HD Number 0225 \s*(\d?\d\.\d{8})\s # RA Hours 0226 \s*(-?\d?\d\.\d{8})\s # DEC DDMMSS.SS 0227 \s*(-?\d+\.\d\d)\s # dRA/dt 0228 \s*(-?\d+\.\d\d)\s # dDec/dt 0229 \s*(-?\d+\.\d[\d ])\s # Parallax 0230 \s*([- \d]\d\.\d\d)\s # Magnitude 0231 \s*([- ]\d.\d\d)\s # B-V index 0232 ([01])\s # Multiple? 0233 ([01])\s # Variable? 0234 ([A-Z ].?|sd)\s # Spectral Type 0235 }x or do 0236 { 0237 $ERROR = "Positional Error (0-59)"; 0238 return; 0239 }; 0240 0241 my $star = { 0242 HD => $1, 0243 RA => $2, 0244 Dec => $3, 0245 dRA => $4, 0246 dDec => $5, 0247 Parallax => $6, 0248 Mag => $7, 0249 BV_Index => $8, 0250 Mult => $9, 0251 Var => $10, 0252 Spec_Type => $11, 0253 line => $., 0254 PM => sqrt($4 * $4 + $5 * $5), 0255 }; 0256 0257 $line or return $star; 0258 0259 # printf $line . "\n"; 0260 $star->{GName} = (($line =~ s/^([^:\s].*?)(\s:|$)//) ? $1 : ""); 0261 $line =~ s/^://; 0262 $star->{Name} = (($line =~ s/^\s*(\S.*?)\s*$//) ? $1 : ""); 0263 return $star; 0264 } 0265 0266 sub proper_motion_coords { 0267 my ( $ra0, $dec0, $pmRA, $pmDec, $years ) = @_; 0268 0269 my $theta0 = hour2rad($ra0); 0270 my $lat0 = deg2rad($dec0); 0271 0272 my $pm = sqrt( $pmRA * $pmRA + $pmDec * $pmDec ) * $years; 0273 my $dir0 = ( $pm > 0 ) ? atan2( $pmRA, $pmDec ) : atan2( -$pmRA, -$pmDec ); 0274 ( $pm < 0 ) and $pm = - $pm; 0275 # print "$pm, $dir0\n"; 0276 0277 my $dst = milliarcsecond2rad($pm); 0278 0279 my $phi0 = pi/2 - $lat0; 0280 0281 my $lat1 = asin(sin($lat0)*cos($dst) + 0282 cos($lat0)*sin($dst)*cos($dir0)); 0283 my $dtheta = atan2(sin($dir0)*sin($dst)*cos($lat0), 0284 cos($dst)-sin($lat0)*sin($lat1)); 0285 0286 return (rad2hour($theta0 + $dtheta), rad2deg($lat1)); 0287 #return (rad2milliarcsecond($dtheta) * cos($lat0), 0288 # rad2milliarcsecond($lat1 - $lat0)); 0289 } 0290 0291 sub hour2rad { 0292 return deg2rad($_[0] * 15.); 0293 } 0294 0295 sub rad2hour { 0296 return rad2deg($_[0]) / 15.; 0297 } 0298 0299 sub milliarcsecond2rad { 0300 return deg2rad( $_[0] / ( 60 * 60 * 1000)); 0301 } 0302 sub rad2milliarcsecond { 0303 return rad2deg( $_[0]) * ( 60 * 60 * 1000); 0304 }