#!/usr/bin/perl
#
# Run a query on SIMBAD to lookup the coordinates of an object.
#
# MWR 6/22/2004
#
# Updated to use CGI and run from a browser.
# Note: A cron job will need to be added to
# delete the plot files created by this
# script.
#
# CMR 7/06/2004
#
# Modified slightly; biggest change is making a URL which is equivalent
# to the temp file in which the script places the PNG graphic,
# so that external users can look at the plot.
#
# MWR 7/13/2004
use strict;
use POSIX;
use HTTP::Request::Common qw(POST);
use LWP::UserAgent;
use CGI qw( -unique_headers -debug -compile :standard );
use CGI::Carp qw( fatalsToBrowser );
use Benchmark;
# Name the main package
package main;
# Set some CGI security settings
$CGI::POST_MAX = 1024 * 100;
$CGI::DISABLE_UPLOADS = 1;
#####################################################
# Variables that may need updating after installation
#####################################################
my ($site_title) = "Lookup Phased Light Curves From Mark IV Data";
my ($site_url) = "http://spiff.rit.edu/";
my ($www_dir) = "/var/www/html/";
my ($plot_dir) = $www_dir . "temp";
our ($gnuplot) = "/usr/bin/gnuplot";
#####################################################
# Nothing below here should need editing
#####################################################
# Variables
our ($primary_color) = "#ccccff";
our ($secondary_color) = "#cccccc";
my ($background_color) = "white";
my ($time_operations) = 0;
my ($t0, $t1) = (0, 0);
# Global variables
our ($VERSION) = "0.03";
our ($plotfile) = $plot_dir . "/" . "make_phased" . "_" . $$ . "QxQ" . ".";
our ($plot_cmd_file) = $plot_dir . "/" . "make_phased" . "_" . $$ . "QxQ" . "." . "gnu";
our ($plot_data_file) = $plot_dir . "/" . "make_phased" . "_" . $$ . "QxQ" . "." . "dat";
# External links to data and databases
our ($markiv_home) = "http://sallman.tass-survey.org/";
our ($markiv_url) = "http://sallman.tass-survey.org/servlet/markiv/action/DataDownload";
our ($simbad_home) = "http://simbad.u-strasbg.fr/";
our ($simbad_url) = "http://simbad.u-strasbg.fr/sim-id.pl";
our ($tass_img) = "http://www.tass-survey.org/tass/logo/gleeson_smaller.gif";
our ($tass_home) = "http://stupendous.rit.edu/";
our ($lookup_info) = "http://spiff.rit.edu/richmond/tass/lookup/lookup.html";
# flush output immediately
$| = 1;
# Create a CGI object (q = query)
our $q = new CGI;
# Find out if any parameters were passed in that we
# are interested in.
my ($action) = $q->param( "action" );
my ($name) = $q->param( "name" );
my ($ra) = $q->param( "ra" );
my ($dec) = $q->param( "dec" );
my ($epoch_jd) = $q->param( "epoch_jd" );
my ($period) = $q->param( "period" );
my ($multiple_values) = $q->param( "multiple_values" );
our ($debug) = $q->param( "debug" );
my ($status) = 1;
($time_operations) = $q->param( "time_operations" );
# Was going to allow different plot file types to
# be created by radio button, but my gnuplot was not
# able to create jpeg or pdf files.
#my ($file_type) = $q->param( "file_type" );
my ($file_type) = "png";
$plotfile = $plotfile . $file_type;
# Get a benchmark timestamp
if ($time_operations) {
# Get a benchmark
($t0) = new Benchmark;
}
# Print out the header
print $q->header,
$q->start_html( -title => "$site_title"),
$q->h1( {-align=>"center"}, "$site_title" ),
$q->hr;
# Place a pretty TASS image on the page
print $q->img({src=>$tass_img, align=>"right"});
# Show the menu items
&show_menu_items($q);
# Print out given arguments if debug
if ($debug) {
print $q->Dump();
}
# Ok, time to do the real work...
if (($action eq "Submit Single") || ($action eq "Submit Multiple")) {
my (@data) = ();
my ($set) = "";
my ($setid) = 0;
# Gather the data submited into an array
if ($action eq "Submit Multiple") {
@data = split (/;/, $multiple_values);
} else {
push(@data, "$name,$ra,$dec,$epoch_jd,$period");
}
if ($#data < 0) {
print $q->h3("No data submitted");
print $q->h6("I feel so empty...");
} else {
# Now generate the light curves for each set of data
foreach $set (@data) {
# generate a unique set of filenames for the graph we are
# about to make. We modify the contents of the variables
# plotfile, plot_cmd_file, plot_data_file
# so that the section between the capital Qs changes on
# each iteration.
generate_new_filenames($setid++);
# get rid of any control characters (which appear to be
# inserted at the start of the for the second, third, etc.
# lines of multiple submission)
$set = remove_control_chars($set);
my ($name, $ra, $dec, $epoch_jd, $period) = split(/,/, $set);
print $q->h3("Data set: ..$name.., $ra, $dec, $epoch_jd, $period");
# check here to see if any of the information is missing;
# if so, then we use the name to look up all the other
# quantities via SIMBAD.
#
# If the user did supply some, but not all, of the fields --
# for example, if he provided period but not RA and Dec --
# we use the name to look up all quantities via SIMBAD.
# However, we'll only use the SIMBAD values for the fields the
# user left blank; we'll retain the user's values for all
# fields he supplied.
my $ret_simbad = 0;
($ret_simbad, $name, $ra, $dec, $epoch_jd, $period) =
get_variable_info($name, $ra, $dec, $epoch_jd, $period);
if ($ret_simbad != 0) {
print $q->h3("Error looking up data from SIMBAD");
next;
}
my ($ret_plot_file) = &generate_light_curves($q, $file_type, $name, $ra,
$dec, $epoch_jd, $period);
if ($ret_plot_file) {
# the "ret_plot_file" begins with a full path on the local
# machine running this script; that is, in $www_dir. We need
# to create an equivalent URL, pointing to the same file,
# which people can access over HTTP.
my ($plot_url) = create_url_name($ret_plot_file);
if ($plot_url) {
print $q->ul(
"Link to file containing image of plot",
$q->img({src=>"$plot_url"}),
);
}
else {
print $q->h3("Error creating URL for plot file?!");
}
}
}
}
} elsif ($action eq "single_form") {
&show_lookup_form($q, $action);
} elsif ($action eq "multiple_form") {
&show_lookup_form($q, $action);
} elsif ($action eq "about") {
&show_about($q);
} else {
&show_lookup_form($q, "single_form");
}
# Get a benchmark timestamp and find out how long
# this operation took
if ($time_operations) {
# Get the ending benchmark
($t1) = new Benchmark;
my ($min, $sec) = &diff_time($t0, $t1);
print $q->p("Operation took $min:$sec");
}
# Print the end of the HTML page
print $q->end_html;
# Clean up any files created by this script
# Except the plotfile. Apache seems to need
# it until the script exits. A cron job will
# need to delete old files every few hours or so.
#unlink ($plotfile);
#unlink ($plot_cmd_file);
#unlink ($plot_data_file);
exit(0);
###########################################################################
# Display data subroutines
###########################################################################
sub show_menu_items {
my ($q) = @_;
my ($debug) = $main::debug;
my ($primary_color) = $main::primary_color;
my ($secondary_color) = $main::secondary_color;
my ($tass_home) = $main::tass_home;
my ($row) = "";
my ($index) = $q->url();
print $q->start_table();
#print $q->td({bgcolor=>$primary_color}
#print $q->a({href=>$index,"Main");
print "
";
print "Single lookup";
print " | ";
print "";
print "Multiple lookup";
print " | ";
print "";
print " ";
print " | ";
print "";
print "About";
print " | ";
# $q->td({bgcolor=>$secondary_color}
# $q->a({href=>$index},"Foo"),
# ),
# );
print $q->end_table();
return();
}
###########################################################################
# PROCEDURE: show_lookup_form
#
# DESCRIPTION: Show an HTML form which allows the user to
# enter in data which can be used to generate
# a light curve.
#
# RETURNS:
# Nothing.
#
sub show_lookup_form {
my ($q, $action) = @_;
my ($size) = 20;
my ($max_length) = 80;
my ($rows) = 10;
my ($columns) = 80;
print $q->start_form();
if ($action eq "single_form") {
print $q->h2("Lookup single phased light curve");
print $q->p("This form allows a user to look up a
single phased light curve.
You may
enter a name alone or enter multiple items.");
print $q->start_ul();
print $q->start_table();
print $q->td("Name:"),
$q->td(
$q->textfield(-name=>'name',
-default=>'',
-override=>1,
-size=>$size,
-maxlength=>$max_length),
),
$q->Tr(),
$q->td("RA:"),
$q->td(
$q->textfield(-name=>'ra',
-default=>'',
-override=>1,
-size=>$size,
-maxlength=>$max_length),
),
$q->Tr(),
$q->td("DEC:"),
$q->td(
$q->textfield(-name=>'dec',
-default=>'',
-override=>1,
-size=>$size,
-maxlength=>$max_length),
),
$q->Tr(),
$q->td("Epoch Jd:"),
$q->td(
$q->textfield(-name=>'epoch_jd',
-default=>'',
-override=>1,
-size=>$size,
-maxlength=>$max_length),
),
$q->Tr(),
$q->td("Period:"),
$q->td(
$q->textfield(-name=>'period',
-default=>'',
-override=>1,
-size=>$size,
-maxlength=>$max_length),
);
print $q->end_table();
print $q->end_ul();
print $q->submit(-name=>"action",
-value=>"Submit Single");
print $q->reset;
print $q->br;
# print $q->br("Select plot file type:");
#
#
# print $q->radio_group(-name=>'file_type',
# -values=>['png','jpeg', 'pdf'],
# -default=>'png');
# -linebreak=>'true');
#
# print $q->br;
print $q->checkbox(-name=>'debug',
-checked=>0,
-value=>'1',
-label=>'show debug information');
print $q->br;
print $q->checkbox(-name=>'time_operations',
-checked=>0,
-value=>'1',
-label=>'Time lookup');
}
if ($action eq "multiple_form") {
print $q->h2("Lookup multiple phased light curves");
print $q->p("This form allows a user to look up multiple
phased light curves.");
print $q->p("The textarea below allows the user to enter multiple data sets to
lookup. Each set of data should contain one or more of the
following items in this order: name, ra, dec, epoch_jd, period.
These items should be comma separated (,). Each set of data should
be separated by a semi colons (;).");
print $q->ul("Each set should contain: name,ra,dec,epoch_jd,period;");
print $q->p("Example:");
print $q->ul("RR_Lyr,291.36630375,42.78436,2442923.419300,0.5668677600;
RR_Lyr,291.36630375,42.78436,2442923.419300,0.5668677600;
");
print $q->ul(
$q->textarea(-name=>'multiple_values',
-default=>'',
-rows=>$rows,
-columns=>$columns),
);
print $q->p;
print $q->submit(-name=>"action",
-value=>"Submit Multiple");
print $q->reset;
print $q->br;
print $q->checkbox(-name=>'debug',
-checked=>0,
-value=>'1',
-label=>'show debug information');
print $q->br;
print $q->checkbox(-name=>'time_operations',
-checked=>0,
-value=>'1',
-label=>'Time lookup');
}
print $q->end_form();
return();
}
###########################################################################
# PROCEDURE: show_about
#
# DESCRIPTION: Show a page which describes how this script works.
#
# RETURNS:
# Nothing
#
sub show_about {
my ($q) = @_;
print $q->p("Version: $main::VERSION");
print $q->h2("General Information");
print $q->p("Given the name or position of a variable star,
this script will look
up its properties in SIMBAD, grab measurements from
the Mark IV database, calculate the phase of each Mark IV
measurement, and then create a light curve of the star. This
might be handy for checking the TASS database for several
sorts of errors; it also makes pretty pictures :-)");
print $q->p("More information on the background for this script
can be found at the following urls:");
print $q->ul(
$q->li(
$q->a({href=>$main::tass_home},$main::tass_home), "(TASS home page)"
),
$q->li(
$q->a({href=>$main::lookup_info},$main::lookup_info),
),
);
print $q->h2("Data sources");
print $q->p("This script uses the following data sources");
print $q->ul(
$q->li(
$q->a({href=>$main::markiv_home},"TASS Mark IV Database"),
),
$q->li(
$q->a({href=>$main::simbad_home},"SIMBAD Astronomical Database"),
),
);
return;
}
###########################################################################
# PROCEDURE: generate_light_curves
#
# DESCRIPTION: For each set of given data, generate
# a light curve.
#
# RETURNS:
# ret_plot_file: Filename of the generated plot
#
sub generate_light_curves {
my ($q, $file_type, $name, $ra, $dec, $epoch_jd, $period) = @_;
my ($retval);
my ($num_markiv_lines, @markiv_lines);
my ($debug) = $main::debug;
# now grab data from the Mark IV database (if it exists)
my ($num_markiv_lines, @markiv_lines) = &get_markiv_data($ra, $dec);
if ($num_markiv_lines <= 0) {
print $q->p("get_markiv_data returns no data");
return(0);
}
# make a nice graph showing the measurements phased with the known period
# CMR Note: this subroutine also returns the plot file name.
my ($ret_val, $ret_plot_file) =
&make_phased_graph($name, $ra, $dec, $epoch_jd, $period, $file_type,
$num_markiv_lines, @markiv_lines);
if ($ret_val != 0) {
print $q->p("make_phased_graph returns with error");
return(0);
}
return($ret_plot_file);
}
###########################################################################
# Data crunching subroutines
###########################################################################
###########################################################################
# PROCEDURE: get_markiv_data
#
# DESCRIPTION: go to the Mark IV database and request measurements
# of the star at a given (RA, Dec). Place the
# resulting measurements into an array and return them.
#
# RETURNS:
# (num_lines, @lines)
# num_lines number of lines of data
# lines array of data, one V,I pair per line
#
sub get_markiv_data {
my($i);
my($ra, $dec);
my($ua, $url, $req, $reply);
my($match_radius, $match_scale, $radec_string);
my($retval, $rah, $ram, $ras, $decsign, $decd, $decm, $decs);
my($num_reply_lines, @reply_lines);
my($num_data_lines, @data_lines);
my($q) = $main::q;
$ra = $_[0];
$dec = $_[1];
$ua = LWP::UserAgent->new;
$num_data_lines = 0;
@data_lines = "";
$match_radius = 5;
$match_scale = "Seconds";
# we must convert RA and Dec to sexigesimal notation in order to
# make use of full accuracy of positions (sigh)
($rah, $ram, $ras, $decsign, $decd, $decm, $decs) =
convert_deg_to_baby($ra, $dec);
if ($main::debug > 0) {
print $q->p("get_markiv_data: rah $rah ram $ram ras $ras");
print $q->p("get_markiv_data: decsign $decsign decd $decd decm $decm decs $decs");
}
# now make a nice string that the Mark IV database engine will accept
$radec_string = sprintf "%02d%02d%04.1f%s%02d%02d%04.1f",
$rah, $ram, $ras, $decsign, $decd, $decm, $decs;
if ($main::debug > 0) {
print $q->p("get_markiv_data: radec_string: ..$radec_string..");
}
# make a query to the Mark IV database
$url = $main::markiv_url;
$req = POST $url, [ "header" => 'false',
"compress" => 'false',
"position" => $radec_string,
"radius" => $match_radius,
"scale" => $match_scale
];
$reply = $ua->request($req)->as_string;
if ($main::debug > 0) {
print $q->p("get_markiv_data: reply from Mark IV database follows .. ");
print $q->p("..$reply..");
}
if ($reply =~ /Can't connect/) {
print $q->p("Error returned by $url");
print $q->pre("$reply");
return($num_data_lines, @data_lines);
}
# pick out just the lines with measurements
# first, skip lines until we reach a ""
($num_reply_lines, @reply_lines) = split_reply($reply);
for ($i = 0; $i < $num_reply_lines; $i++) {
if ($reply_lines[$i] =~ //) {
last;
}
}
if ($i == $num_reply_lines) {
# there wasn't any real data
if ($main::debug > 0) {
print $q->p("get_markiv_data: no real data ... ");
}
}
else {
# now, we copy the real data into the "@data_lines" array
for ($i++; $i < $num_reply_lines; $i++) {
if ($reply_lines[$i] =~ /Sorry/) {
last;
}
if ($reply_lines[$i] =~ /<\/pre>/) {
last;
}
$data_lines[$num_data_lines] = " " . $reply_lines[$i];
chomp($data_lines[$num_data_lines]);
if ($main::debug > 0) {
print $q->p("get_markiv_data: data line $num_data_lines is ..$data_lines[$num_data_lines]..");
}
$num_data_lines++;
}
}
# there is a single blank line just before the , so get rid of it
if ($num_data_lines > 0) {
$num_data_lines--;
}
return($num_data_lines, @data_lines);
}
###########################################################################
# PROCEDURE: convert_deg_to_baby
#
# DESCRIPTION: convert (RA, Dec) from decimal degrees to babylonian
# notation: HH MM SS.sss and "sign" DD MM SS.ss.
#
# Note that we return values which are ALWAYS positive
# for decd, decm, decs; only the separate "sign" value
# indicates the sign of the Declination. The "sign"
# will be either "+" or "-".
#
# RETURNS:
# (rah, ram, ras, decsign, decd, decm, decs)
#
sub convert_deg_to_baby {
my($ra, $dec);
my($rah, $ram, $ras, $decsign, $decd, $decm, $decs);
my($q) = $main::q;
$ra = $_[0];
$dec = $_[1];
if ($main::debug > 0) {
print $q->p("convert_deg_to_baby: ra ..$ra.. dec ..$dec.. ");
}
# pick apart the RA first
$rah = int($ra/15.0);
$ram = int(($ra - 15*$rah)*4.0);
$ras = $ra - ($rah*15) - ($ram/4.0);
$ras *= 240.0;
# now figure out the Dec value
if ($dec < 0) {
$decsign = "-";
$dec = 0.0 - $dec;
} else {
$decsign = "+";
}
$decd = int($dec);
$decm = int(($dec - $decd)*60.0);
$decs = $dec - ($decd) - ($decm/60);
$decs *= 3600.0;
if ($main::debug > 0) {
print $q->p("convert_deg_to_baby: RA ..$rah.. ..$ram.. ..$ras.. ");
print $q->p("convert_deg_to_baby: Dec ..$decsign.. ..$decd.. ..$decm.. ..$decs.. ");
}
return($rah, $ram, $ras, $decsign, $decd, $decm, $decs);
}
###########################################################################
# PROCEDURE: convert_baby_to_deg
#
# DESCRIPTION: convert (RA, Dec) from babylonian notation,
# HH MM SS.sss and "sign" DD MM SS.ss, to decimal degrees.
# Expect input in the form of two strings:
#
# "HH MM SS.ss" and "+DD MM SS.s"
#
# and convert to two values: RA and Dec.
# RETURNS:
# (ra, dec)
#
sub convert_baby_to_deg {
my($ra_string, $dec_string);
my($rah, $ram, $ras, $decsign, $decd, $decm, $decs);
my($ra, $dec);
my($q) = $main::q;
$ra_string = $_[0];
$dec_string = $_[1];
if ($main::debug > 0) {
print $q->p("convert_baby_to_deg: ra ..$ra_string.. dec ..$dec_string.. ");
}
# first, we replace any colons in input strings by spaces
$ra_string =~ s/:/ /g;
$dec_string =~ s/:/ /g;
# break up the RA string into three pieces, which are rah, ram, ras
($rah, $ram, $ras) = split(/\s+/, $ra_string);
# break up the Dec string into three pieces, which are decd, decm, decs
($decd, $decm, $decs) = split(/\s+/, $dec_string);
if ($main::debug > 0) {
print $q->p("convert_baby_to_deg: rah ..$rah.. ram ..$ram.. ras ..$ras..");
print $q->p("convert_baby_to_deg: decd ..$decd.. decm ..$decm.. decs ..$decs.. ");
}
# convert RA to decimal degrees
$ra = ($rah*15) + ($ram*(15/60.0)) + ($ras*(15/3600.0));
# convert Dec to decimal degrees; be careful about negative dec values
if ($decd < 0) {
$decsign = -1;
$decd = 0.0 - $decd;
}
else {
$decsign = 1;
}
$dec = $decsign*($decd + ($decm/60.0) + ($decs/3600.0));
if ($main::debug > 0) {
print $q->p("convert_baby_to_deg: RA ..$ra.. ");
print $q->p("convert_baby_to_deg: Dec ..$dec.. ");
}
return($ra, $dec);
}
###########################################################################
# PROCEDURE: is_baby
#
# DESCRIPTION: A very simple test: is the given coordinate in
# Babylonian notation? We answer "yes" if it looks like
#
# "HH MM SS.s"
# or
# "HH:MM:SS.s"
#
# RETURNS:
# 1 if the coordinate _is_ babylonian
# 0 if the coordinate is _not_ babylonian
#
sub is_baby {
my($coord_string, @words);
my($q) = $main::q;
$coord_string = $_[0];
if ($main::debug > 0) {
print $q->p("is_baby: coord ..$coord_string.. ");
}
# first, we replace any colons in input strings by spaces
$coord_string =~ s/:/ /g;
# now, if it has three pieces (separated by spaces), we count
# it as babylonian. That's the only test we make.
@words = split(/\s+/, $coord_string);
if ($#words == 2) {
if ($main::debug > 0) {
print $q->p("is_baby: yes, ..$coord_string.. is baby");
}
return(1);
}
else {
if ($main::debug > 0) {
print $q->p("is_baby: no, ..$coord_string.. is NOT baby");
}
return(0);
}
}
###########################################################################
# PROCEDURE: get_variable_info
#
# DESCRIPTION: We are given a set of fields with info about the star,
#
# name, ra, dec, epoch_jd, period
#
# some of which may be empty. Our job is to fill in any
# fields which are empty with data from SIMBAD.
#
# The two cases we can handle successfully are:
# we are given
# a name: "TT Boo"
# or
# a position: "12.2343 +23.8873"
# (J2000) "12 33 43.7 -02 12 58"
#
# (which we assume is the position of a variable star)
# use SIMBAD to look up information on the star.
# We get 5 quantities:
#
# name official name of variable
# ra Right Ascension (J2000)
# dec Declination (J2000)
# epoch time of max or min (JD)
# period period of variability (days)
#
# We will insert the SIMBAD values into any of these 5 fields
# which were not supplied by the user.
#
# Convert RA and Dec into decimal degrees, if necessary
#
# RETURNS:
# a list of 6 quantities:
# proc_retval 0 if all okay, 1 if error occurs
# name
# ra (decimal degrees)
# dec (decimal degrees)
# epoch
# period
#
#
sub get_variable_info {
my($simbad_search_string);
my($input_name, $input_ra, $input_dec, $input_epoch_jd, $input_period);
my($simbad_name, $simbad_ra, $simbad_dec, $simbad_epoch_jd, $simbad_period);
my($output_name, $output_ra, $output_dec, $output_epoch_jd, $output_period);
my($q);
my($proc_retval);
my($ua);
my($line);
my($num_reply_lines, @reply_lines);
my($search_string);
my ($retval);
my($q) = $main::q;
$input_name = $_[0];
$input_ra = $_[1];
$input_dec = $_[2];
$input_epoch_jd = $_[3];
$input_period = $_[4];
if ($main::debug > 0) {
print $q->p("get_variable_info: input_name ..$input_name..");
print $q->p("get_variable_info: input_ra ..$input_ra..");
print $q->p("get_variable_info: input_dec ..$input_dec..");
print $q->p("get_variable_info: input_epoch_jd ..$input_epoch_jd..");
print $q->p("get_variable_info: input_period ..$input_period..");
}
# by default, we fail
$proc_retval = 1;
# initialize some return values to nonsensical values
$output_name = "NoName";
$output_ra = -99.0;
$output_dec = -99.0;
$output_epoch_jd = -99.0;
$output_period = -99.0;
$ua = LWP::UserAgent->new;
# case 1: the user has provided all five values.
# All we have to do is copy the provided values into the output
if (($input_name ne "") && ($input_ra ne "") && ($input_dec ne "") &&
($input_epoch_jd ne "") && ($input_period ne "")) {
$output_name = $input_name;
# if the user supplied Babylonian coords HH MM SS.s, we need
# to convert to decimal degrees before returning them
if (is_baby($input_ra)) {
($output_ra, $output_dec) = convert_baby_to_deg($input_ra, $input_dec);
}
else {
$output_ra = $input_ra;
$output_dec = $input_dec;
}
$output_epoch_jd = $input_epoch_jd;
$output_period = $input_period;
$proc_retval = 0;
return($proc_retval, $output_name, $output_ra, $output_dec,
$output_epoch_jd, $output_period);
}
# case 2: the user has provided the name, but not all other quantities.
# We will search for information by name.
if (($input_name ne "") &&
( ($input_ra eq "") || ($input_dec eq "") || ($input_epoch_jd eq "") ||
($input_period eq "") )) {
$simbad_search_string = $input_name;
}
# case 3: the user has NOT provided the name, but has provided the
# RA and Dec. We will search for information by position.
if (($input_name eq "") && ( ($input_ra ne "") && ($input_dec ne "") )) {
$simbad_search_string = sprintf "%s %s", $input_ra, $input_dec;
}
# case 4: the user has NOT provided name or position. We must give up.
if (($input_name eq "") && ($input_ra eq "") && ($input_dec eq "")) {
print $q->p("You must provide either name or (RA and Dec) ");
return($proc_retval, $output_name, $output_ra, $output_dec,
$output_epoch_jd, $output_period);
}
# okay, we are ready to query SIMBAD for information about this object
# these are the parameters we'll need for the lookup request to SIMBAD
my $Protocol = "html";
my $Ident = $simbad_search_string;
my $NbIdent = 1;
my $Radius = "5";
my $Radius_unit = "arcsec";
my $CooFrame = "FK5";
my $CooEpoch = 2000;
my $CooEquinox = 2000;
my $Output_max = "all";
my $Output_mesdisp = "N";
my $Bibyear1 = 1983;
my $Bibyear2 = 2004;
my $Frame1 = "FK5";
my $Equi1 = "2000.0";
my $Epoch1 = "2000.0";
my $Frame2 = "none";
my $Equi2 = "2000.0";
my $Epoch2 = "2000.0";
my $Frame3 = "none";
my $Equi3 = "2000.0";
my $Epoch3 = "2000.0";
my $url = $main::simbad_url;
my $req = POST $url, [
# protocol => "ascii",
"Ident" => $Ident,
"NbIdent" => $NbIdent,
"Radius" => $Radius,
"Radius.unit" => $Radius_unit,
"CooFrame" => $CooFrame,
"CooEpoch" => $CooEpoch,
"CooEquinox" => $CooEquinox,
"output.max" => $Output_max,
"output.mesdisp" => $Output_mesdisp,
"Bibyear1" => $Bibyear1,
"Bibyear2" => $Bibyear2,
"Frame1" => $Frame1,
"Equi1" => $Equi1,
"Frame2" => $Frame2,
"Equi2" => $Equi2,
"Frame3" => $Frame3,
"Equi3" => $Equi3
];
my $reply_stuff = $ua->request($req)->as_string;
if ($main::debug > 0) {
print $q->p("SIMBAD reply_stuff is ..$reply_stuff.. ");
}
# split the reply into individual lines
($num_reply_lines, @reply_lines) = split_reply($reply_stuff);
if ($num_reply_lines == 0) {
print $q->p("SIMBAD ID query returns empty?! ");
return($proc_retval, $output_name, $output_ra, $output_dec,
$output_epoch_jd, $output_period);
}
# make the special search through the data for the line
# containing the RA and Dec; if found, we'll get
# back RA and Dec in decimal degrees (J2000)
($retval, $simbad_ra, $simbad_dec) =
get_radec($input_name, $num_reply_lines, @reply_lines);
if ($retval != 0) {
print $q->p("get_radec fails ?! ");
return($proc_retval, $output_name, $output_ra, $output_dec,
$output_epoch_jd, $output_period);
}
# look for the entry for this object in the GCVS,
# to get the name, period and time of max/min
($retval, $simbad_name, $simbad_epoch_jd, $simbad_period) =
get_epoch_period($input_name, $num_reply_lines, @reply_lines);
if ($retval != 0) {
print $q->p("get_variable_info: get_epoch_period fails !? ");
return($proc_retval, $output_name, $output_ra, $output_dec,
$output_epoch_jd, $output_period);
}
# okay, we've looked up information about this star in SIMBAD.
# Now, for every item the user did NOT supply, we insert the SIMBAD value.
# Name
if ($input_name eq "") {
$output_name = $simbad_name;
} else {
$output_name = $input_name;
}
# RA
if ($input_ra eq "") {
$output_ra = $simbad_ra;
} else {
$output_ra = $input_ra;
}
# Dec
if ($input_dec eq "") {
$output_dec = $simbad_dec;
} else {
$output_dec = $input_dec;
}
# Epoch
if ($input_epoch_jd eq "") {
$output_epoch_jd = $simbad_epoch_jd;
} else {
$output_epoch_jd = $input_epoch_jd;
}
# Period
if ($input_period eq "") {
$output_period = $simbad_period;
} else {
$output_period = $input_period;
}
# check to see if we need to convert RA and Dec to decimal degrees;
# if we do, perform the conversion
if (is_baby($output_ra)) {
($output_ra, $output_dec) = convert_baby_to_deg($output_ra, $output_dec);
}
if ($main::debug > 0) {
print $q->p("get_variable_info: output_name ..$output_name..");
print $q->p("get_variable_info: output_ra ..$output_ra..");
print $q->p("get_variable_info: output_dec ..$output_dec..");
print $q->p("get_variable_info: output_epoch_jd ..$output_epoch_jd..");
print $q->p("get_variable_info: output_period ..$output_period..");
}
$proc_retval = 0;
return($proc_retval, $output_name, $output_ra, $output_dec,
$output_epoch_jd, $output_period);
}
############################################################################
# PROCEDURE: get_epoch_period
#
# DESCRIPTION: Given an array of lines containing the reply to our
# request to SIMBAD, search through it for the
# line which contains a URL to _another_ SIMBAD
# bit of info: the entry for this star in the GCVS.
# Post that URL and look in _its_ reply for the
# official GCVS name, period and epoch of maximum/minimum light.
#
# We need to handle two cases:
# a) the user gave the name of the star ("RR Lyr"),
# in which case the reply from SIMBAD has one format
# b) the user gave only a position in RA and Dec,
# in which case the reply from SIMBAD has a different
# format
# Based on the "input_name" value, we parse the SIMBAD
# lines in the appropriate way to find the URL to further
# information.
#
# RETURNS:
# (proc_retval, name, epoch_jd, period)
# where proc_retval = 0 if all OK, = 1 if error occurs
# name official GCVS name of variable
# epoch_jd JD of max/min light
# period period of variable (days)
#
# we use values of -99 for epoch_jd and period by default
# to indicate no real data available
#
#
sub get_epoch_period {
my($proc_retval);
my($i);
my($input_name);
my($num_reply_lines);
my($name);
my($gcvs_num_lines, @gcvs_lines);
my($gcvs_url, $gcvs_reply);
my($simbad_url, $simbad_varname);
my($retval, $search_string, $line);
my($epoch_jd, $period);
my($q) = $main::q;
$input_name = $_[0];
$num_reply_lines = $_[1];
$proc_retval = 1;
$name = "no_name";
$epoch_jd = -99.0;
$period = -99.0;
# check to see which format the SIMBAD reply has
if ($input_name ne "") {
# the user provided a name to SIMBAD. We look for a URL in a line
# signalled by "Catalogue information"
#
for ($i = 0; $i < $num_reply_lines; $i++) {
# skip ahead to the "Catalogue information" line
if ($_[2 + $i] =~ /^\Catalogue information/) {
if ($main::debug > 0) {
print $q->p("get_epoch_period: found Catalogue info in line ..$_[2 + $i]..");
#$_[2 + $i];
}
last;
}
}
if ($i == $num_reply_lines) {
# there wasn't any "Catalogue information" line
if ($main::debug > 0) {
print $q->p("get_epoch_period: no Catalogue info ... ");
}
return($proc_retval, $name, $epoch_jd, $period);
}
# get the RA and Dec, which occur a few lines later ...
for ( ; $i < $num_reply_lines; $i++) {
# CMR Note: You don't really mean "\V" here, do you?
if ($_[2 + $i] =~ /\V\*/) {
if ($main::debug > 0) {
print $q->p("get_epoch_period: found V* in line ..$_[2 + $i].."); #, $_[2 + $i];
}
last;
}
else {
if ($main::debug > 0) {
print $q->p("get_epoch_period: skipping line $i is ..$_[2 + $i]..\n"); #, $_[2 + $i];
}
}
}
if ($i == $num_reply_lines) {
# there wasn't any link to GCVS entry
if ($main::debug > 0) {
print $q->p("get_epoch_period: no GCVS entry ... ");
}
return($proc_retval, $name, $epoch_jd, $period);
}
$line = $_[2 + $i];
chomp($line);
if ($main::debug > 0) {
print $q->p("get_epoch_perod: look for GCVS entry in ..$line.. ");
}
if ($line !~ /.*HREF="(.*)"/) {
# rats! No link to the GCVS query?!
if ($main::debug > 0) {
print $q->p("get_epoch_period: no HREF inside line ..$line.. ?! ");
return($proc_retval, $name, $epoch_jd, $period);
}
}
# the line did have the right format -- here's the URL for GCVS query
$gcvs_url = $1;
if ($main::debug > 0) {
print $q->p("get_epoch_period: gcvs_url is ..$gcvs_url..");
}
}
else {
# the user supplied as input only a position in (RA, Dec). That means
# that SIMBAD's reply has a different format. We key on the line
# starting with "identifier" to find the URL for further information.
#
# Actually, we'll build the URL for GCVS information on this star
# ourselves. All we need from the SIMBAD lines is the proper name
# for the star.
for ($i = 0; $i < $num_reply_lines; $i++) {
# skip ahead to the "identifier" line
if ($_[2 + $i] =~ /^identifier/) {
if ($main::debug > 0) {
print $q->p("get_epoch_period: found 'identifier' info in line ..$_[2 + $i]..");
#$_[2 + $i];
}
last;
}
}
if ($i == $num_reply_lines) {
# there wasn't any "identifier" line
if ($main::debug > 0) {
print $q->p("get_epoch_period: no Catalogue info ... ");
}
return($proc_retval, $name, $epoch_jd, $period);
}
# get the RA and Dec, which occur in the next line ...
for ( ; $i < $num_reply_lines; $i++) {
# CMR Note: You don't really mean "\V" here, do you?
if ($_[2 + $i] =~ /\V\*/) {
if ($main::debug > 0) {
print $q->p("get_epoch_period: found V* in line ..$_[2 + $i].."); #, $_[2 + $i];
}
last;
}
else {
if ($main::debug > 0) {
print $q->p("get_epoch_period: skipping line $i is ..$_[2 + $i]..\n"); #, $_[2 + $i];
}
}
}
if ($i == $num_reply_lines) {
# there wasn't any link to GCVS entry
if ($main::debug > 0) {
print $q->p("get_epoch_period: no GCVS entry ... ");
}
return($proc_retval, $name, $epoch_jd, $period);
}
$line = $_[2 + $i];
chomp($line);
if ($main::debug > 0) {
print $q->p("get_epoch_perod: look for GCVS entry in ..$line.. ");
}
if ($line !~ /.*HREF="(.*)"/) {
# rats! No link to the GCVS query?!
if ($main::debug > 0) {
print $q->p("get_epoch_period: no HREF inside line ..$line.. ?! ");
}
return($proc_retval, $name, $epoch_jd, $period);
}
# the line did have the right format -- here's the link
$simbad_url = $1;
if ($main::debug > 0) {
print $q->p("get_epoch_period: simbad_url is ..$simbad_url..");
}
# we're going to build our own GCVS URL, using the official SIMBAD
# name given in the link we've just isolated.
if ($simbad_url !~ /.*Ident=(V.*?)&/) {
# rats! couldn't parse the variable-star designation?
if ($main::debug > 0) {
print $q->p("get_epoch_period: no var designation inside line ..$simbad_url.. ?! ");
}
return($proc_retval, $name, $epoch_jd, $period);
}
else {
$simbad_varname = $1;
}
# now build a URL for the GCVS entry for this star
if ($main::debug > 0) {
print $q->p("get_epoch_period: simbad_varname is ..$simbad_varname..");
}
$gcvs_url = sprintf "http://vizier.u-strasbg.fr/viz-bin/VizieR-S?%s",
$simbad_varname;
if ($main::debug > 0) {
print $q->p("get_epoch_period: gcvs_url is ..$gcvs_url..");
}
}
# and now we run the GCVS query to get information on the variable star
my $gcvs_ua = LWP::UserAgent->new;
my $gcvs_req = new HTTP::Request ('GET', => $gcvs_url);
$gcvs_reply = $gcvs_ua->request($gcvs_req)->as_string;
if ($main::debug > 0) {
print $q->p("get_epoch_period: gcvs_reply is ..$gcvs_reply.. ");
}
# now we have to scan through the output of the gcvs reply to find
# the values for "Period" and "Epoch"
($gcvs_num_lines, @gcvs_lines) = split_reply($gcvs_reply);
if ($gcvs_num_lines == 0) {
print $q->p("get_epoch_period: gcvs query returns empty?! ");
return($proc_retval, $name, $epoch_jd, $period);
}
# look for the one line which contains the GCVS Name of the variable
$search_string = "Variable star designation";
($retval, $line) = find_reply_line($search_string,
$gcvs_num_lines, @gcvs_lines);
if ($retval != 0) {
print $q->p("get_epoch_period: can't find string $search_string");
return($proc_retval, $name, $epoch_jd, $period);
}
# strip out the name from this line
if ($line !~ /.*Vname=.*?">(.*?)<\/A/) {
print $q->p("get_epoch_period: can't match pattern for name in line ..$line.. ?! ");
return($proc_retval, $name, $epoch_jd, $period);
}
else {
$name = $1;
# and get rid of extra white space
$name =~ s/\s\s+/ /g;
if ($main::debug > 0) {
print $q->p("get_epoch_period: name is ..$name.. ");
}
}
# look for the one line which contains the Epoch of max/min light
$search_string = "Epoch for maximum light";
($retval, $line) = find_reply_line($search_string,
$gcvs_num_lines, @gcvs_lines);
if ($retval != 0) {
print $q->p("get_epoch_period: can't find string $search_string");
return($proc_retval, $name, $epoch_jd, $period);
}
# strip out the Julian Date of max/min light from this line
if ($line !~ /.*\s*([0-9].*)<\/B>/) {
print $q->p("get_epoch_period: can't match pattern for JD in Epoch line ..$line.. ?! ");
return($proc_retval, $name, $epoch_jd, $period);
}
else {
$epoch_jd = $1;
if ($main::debug > 0) {
print $q->p("get_epoch_period: epoch_jd is ..$epoch_jd.. ");
}
}
# look for the one line which contains the Period (in days)
$search_string = "Period of the variable star";
($retval, $line) = find_reply_line($search_string,
$gcvs_num_lines, @gcvs_lines);
if ($retval != 0) {
print $q->p("get_epoch_period: can't find string $search_string");
return($proc_retval, $name, $epoch_jd, $period);
}
# strip out the Period (we assume in days) from this line
if ($line !~ /.*\s*([0-9].*)<\/B>/) {
print $q->p("get_epoch_period: can't match pattern for period in Period line ..$line.. ?! ");
return($proc_retval, $name, $epoch_jd, $period);
return(1);
}
else {
$period = $1;
if ($main::debug > 0) {
print $q->p("get_epoch_period: period is ..$period.. ");
}
}
return($retval, $name, $epoch_jd, $period);
}
###########################################################################
# PROCEDURE: get_radec
#
# DESCRIPTION: We are given an array with lines from the reply to
# our HTTP request to SIMBAD. We scan through them
# for the line with the RA and Dec. After we find it,
# we read the RA and Dec in sexigesimal form and convert
# to decimal degrees.
#
# Actually, there are two possible forms for the data
# returned via SIMBAD. If the user provided a name for the
# star (e.g., "Sirius"), then SIMBAD places the RA and Dec
# of the star in a line signalled by the phrase
# "ICRS 2000.0 coordinates"
#
# On the other hand, if the user didn't provide a name,
# but only (RA, Dec) coordinates, then SIMBAD's reply
# will have a different format. We need to search for
# a line signalled by a line starting with
# "identifier"
#
# So, we check the user's "input_name", and depending
# on its value, we parse the output appropriately.
#
# RETURNS:
# (retval, ra, dec)
# where retval = 0 if all OK, 1 if error
# ra RA (decimal degrees J2000)
# dec Dec (decimal degrees J2000)
#
sub get_radec {
my($input_name);
my($num_lines, $line);
my($i);
my($search_string);
my($retval, $ra, $dec);
my(@words);
my(@words2, $j);
my($rah, $ram, $ras, $decd, $decm, $decs, $sign);
my($q) = $main::q;
$input_name = $_[0];
$num_lines = $_[1];
$retval = 1;
$ra = -99.0;
$dec = -99.0;
# figure out which sort of reply SIMBAD has given ...
if ($input_name ne "") {
# in this case, the user did provide a name, so we key on this
# string in the returned output
$search_string = "ICRS 2000.0 coordinates";
# first, skip lines until we reach a line which starts
# "ICRS 2000.0 coordinates"
for ($i = 0; $i < $num_lines; $i++) {
if ($_[2 + $i] =~ /^$search_string/) {
last;
}
}
if ($i == $num_lines) {
# there wasn't any real data
if ($main::debug > 0) {
print $q->p("get_radec: couldn't find string $search_string ");
}
return($retval, $ra, $dec);
}
# get the RA and Dec, which occur a few lines later ...
$i++;
# skip line
$i++;
# skip line
$i++;
# now we should see a line that starts like this
# 06 45 08.9173 -16 42 58.017
# strip out the , then pick out RA and Dec
$line = $_[2 + $i];
$line =~ s/\//;
@words = split(/\s+/, $line);
$rah = $words[0];
$ram = $words[1];
$ras = $words[2];
$decd = $words[3];
$decm = $words[4];
$decs = $words[5];
if ($main::debug > 0) {
print $q->p("words are rah ..$rah.. ram ..$ram.. ras ..$ras.. ");
print $q->p("words are decd ..$decd.. decm ..$decm.. decs ..$decs.. ");
}
if (substr($decd, 0, 1) eq "-") {
if ($main::debug > 0) {
print $q->p("sign is negative ");
}
$sign = -1;
# make the decd value positive, so we can convert to degrees properly
if ($decd < 0) {
$decd = 0.0 - $decd;
}
}
else {
if ($main::debug > 0) {
print $q->p("sign is positive ");
}
$sign = 1;
}
}
else {
# in this case, the user only provided an (RA, Dec) position. We have
# to sift through the output in a different fashion to get the
# RA and Dec of the star from SIMBAD (which might be more precise
# than that of the user).
$search_string = "identifier";
# first, skip lines until we reach a line which starts
# "identifier"
for ($i = 0; $i < $num_lines; $i++) {
if ($_[2 + $i] =~ /^$search_string/) {
last;
}
}
if ($i == $num_lines) {
# there wasn't any real data
if ($main::debug > 0) {
print $q->p("get_radec: couldn't find string $search_string ");
}
return($retval, $ra, $dec);
}
# get the RA and Dec, which occur in the next line ...
$i++;
# now we should see a line that starts like this
# V* RR Lyr
# this line should have 5 vertical bar field separators in it;
# the RA and Dec lie between the second and third bars,
# in babylonian form with spaces between hours, minutes, seconds
$line = $_[2 + $i];
@words = split(/\|/, $line);
if ($main::debug > 0) {
for ($j = 0; $j <= $#words; $j++) {
print $q->p("words $j is ..$words[$j]..");
}
}
@words2 = split(/\s+/, $words[2]);
$rah = $words2[1];
$ram = $words2[2];
$ras = $words2[3];
$decd = $words2[4];
$decm = $words2[5];
$decs = $words2[6];
if ($main::debug > 0) {
print $q->p("words2 are rah ..$rah.. ram ..$ram.. ras ..$ras.. ");
print $q->p("words2 are decd ..$decd.. decm ..$decm.. decs ..$decs.. ");
}
if (substr($decd, 0, 1) eq "-") {
if ($main::debug > 0) {
print $q->p("sign is negative ");
}
$sign = -1;
# make the decd value positive, so we can convert to degrees properly
if ($decd < 0) {
$decd = 0.0 - $decd;
}
}
else {
if ($main::debug > 0) {
print $q->p("sign is positive ");
}
$sign = 1;
}
}
if ($main::debug > 0) {
print $q->p("get_radec: RA is $rah $ram $ras Dec is $decd $decm $decs");
}
# now convert RA and Dec to decimal degrees
$ra = ($rah*15.0) + ($ram/4.0) + ($ras/240.0);
$dec = abs($decd) + abs($decm/60.0) + abs($decs/3600.0);
$dec *= $sign;
if ($main::debug > 0) {
print $q->p("get_radec: RA is $ra Dec is $dec");
}
# and we're done
$retval = 0;
return($retval, $ra, $dec);
}
#############################################################################
# PROCEDURE: split_reply
#
# DESCRIPTION: Given the entire reply from an HTTP request as a single
# string, break it up into individual lines. Count the lines,
# and create an array with one line per element.
#
# RETURNS:
# (num_of_lines, array_of_lines)
#
sub split_reply {
my($num_reply_lines);
my(@reply_lines);
my($big_reply_string);
my($ll);
my($q) = $main::q;
$big_reply_string = $_[0];
@reply_lines = split(/\n/, $big_reply_string);
$num_reply_lines = 0;
foreach $ll (@reply_lines) {
$num_reply_lines++;
if ($main::debug > 0) {
print $q->p("next ll is ..$ll.. ");
}
}
return($num_reply_lines, @reply_lines);
}
#########################################################################
# PROCEDURE: find_reply_line
#
# DESCRIPTION: Given an array of many lines containing the reply
# from an HTTP request, search them for the (first)
# line containing the given string.
#
# RETURNS:
# (retval, line)
# where retval = 0 if we find it
# 1 if we don't find it
#
# line = the entire line containing the string
#
sub find_reply_line {
my($search_string);
my($num_lines);
my($i);
my($retval, $line);
my($q) = $main::q;
$search_string = $_[0];
$num_lines = $_[1];
# args 2 - N are the lines we'll search
# initialize to "unsuccessful search"
$retval = 1;
for ($i = 0; $i < $num_lines; $i++) {
if ($_[2 + $i] =~ /$search_string/) {
$line = $_[2 + $i];
$retval = 0;
if ($main::debug > 0) {
print $q->p("find_reply_line: found ..$search_string.. in line ");
print $q->p(" ..$line.. ");
}
return($retval, $line);
}
}
# if we get here, there was no match
return($retval, "");
}
###########################################################################
# PROCEDURE: make_phased_graph
#
# DESCRIPTION: Given information about a variable star, including its
# period, and given a bunch of lines with Mark IV measurements,
# create a nice plot of the phased light curve.
#
# RETURNS:
# (proc_retval, plotfile)
# proc_retval = 0 if all goes well, 1 if error
# plotfile name of a file containing the plot
#
sub make_phased_graph {
my($i);
my($proc_retval, $plotfile);
my($name, $ra, $dec, $epoch_jd, $period);
my($num_data_lines, @data_lines);
my($min_v_mag, $max_v_mag);
my($min_i_mag, $max_i_mag);
my($minx, $maxx, $miny, $maxy);
my($retval, $cmd);
my($plotfile) = $main::plotfile;
my($plot_cmd_file) = $main::plot_cmd_file;
my($plot_data_file) = $main::plot_data_file;
my($q) = $main::q;
$proc_retval = 1;
$name = $_[0];
$ra = $_[1];
$dec = $_[2];
$epoch_jd = $_[3];
$period = $_[4];
$file_type = $_[5];
$num_data_lines = $_[6];
for ($i = 0; $i < $num_data_lines; $i++) {
$data_lines[$i] = $_[7 + $i];
}
if ($main::debug > 0) {
print $q->p("make_phased_graph: name is ..$name.. ra is ..$ra.. ");
}
# if there are no data lines, we return with no graph
if ($num_data_lines <= 0) {
print $q->p("make_phased_graph: no data to plot");
return($proc_retval, $plotfile);
}
# if the epoch_jd value is invalid, just pick an arbitrary date for the
# phase = 0. This can happen in the GCVS for some irregular variables
if ($epoch_jd < 0) {
$epoch_jd = 2452000.0;
}
# if the PERIOD is less than zero, then we can't make a phased graph;
# so return with error
if ($period < 0) {
return($proc_retval, $plotfile);
}
# calculate the phase for each observed magnitude, and put data into
# a file with lines that look like this:
#
# JD phase1 phase2 vmag1 vmag2 imag1 imag2
#
if (create_phased_data($plot_data_file, $epoch_jd, $period,
$num_data_lines, @data_lines) != 0) {
print $q->p("make_phased_graph: create_phased_data returns with error");
return($proc_retval, $plotfile);
}
# figure out the min, max values of V-band magnitude
($min_v_mag, $max_v_mag) = find_extreme_mags("V",
$num_data_lines, @data_lines);
($min_i_mag, $max_i_mag) = find_extreme_mags("I",
$num_data_lines, @data_lines);
if ($main::debug > 0) {
print $q->p("min_v_mag is $min_v_mag max_v_mag is $max_v_mag");
}
# figure out the min, max magnitude values on the graph
($minx, $maxx, $miny, $maxy) = find_graph_limits($min_v_mag,
$max_v_mag, $min_i_mag, $max_i_mag);
if ($main::debug > 0) {
print $q->p("graph limits: $minx $maxx $miny $maxy");
}
# open a file to hold GNUPLOT commands
# and put into it all the command necessary to make a nice plot
if (!open(CMD_FILE, ">$plot_cmd_file")) {
print $q->p("make_phased_graph: can't open file $plot_cmd_file");
return($proc_retval, $plotfile);
}
if ($main::debug > 0) {
print $q->p("make_phased_graph: putting commands into $plot_cmd_file");
}
printf CMD_FILE "set output '%s' \n", $plotfile;
#printf CMD_FILE "set term png color \n";
printf CMD_FILE "set term $file_type color \n";
printf CMD_FILE "set grid \n";
printf CMD_FILE "set xlabel 'Phase (two periods shown for clarity)' \n";
printf CMD_FILE "set ylabel 'Magnitude' \n";
printf CMD_FILE "set title 'TASS data on %s using period %.5f' \n",
$name, $period;
# here comes the big command, in which we plot all the data in both bands
# we build this very long line one bit at a time
printf CMD_FILE "plot [%f:%f][%f:%f] '%s' using 2:4 t 'V good' lt 1 pt 1 ",
$minx, $maxx, $miny, $maxy, $plot_data_file;
printf CMD_FILE " , '%s' using 3:4 t '' lt 1 pt 1 ",
$plot_data_file;
printf CMD_FILE " , '%s' using 2:5 t 'V flag' lt 1 pt 4 ps 0.8 " ,
$plot_data_file;
printf CMD_FILE " , '%s' using 3:5 t '' lt 1 pt 4 ps 0.8 " ,
$plot_data_file;
printf CMD_FILE " , '%s' using 2:6 t 'I good' lt 2 pt 1 ",
$plot_data_file;
printf CMD_FILE " , '%s' using 3:6 t '' lt 2 pt 1 ",
$plot_data_file;
printf CMD_FILE " , '%s' using 2:7 t 'I flag' lt 2 pt 4 ps 0.8 ",
$plot_data_file;
printf CMD_FILE " , '%s' using 3:7 t '' lt 2 pt 4 ps 0.8 ",
$plot_data_file;
printf CMD_FILE "\n";
close(CMD_FILE);
# execute the "gnuplot" program on the commands to create
# a file holding the graph
$cmd = "$main::gnuplot $plot_cmd_file";
$retval = `$cmd 2>&1`;
if ($? != 0) {
print $q->p("make_phased_graph: gnuplot returns with error ");
print $q->p("$retval");
return($proc_retval, $plotfile);
}
# all is done
$proc_retval = 0;
return($proc_retval, $plotfile);
}
#############################################################################
# PROCEDURE: find_extreme_mags
#
# DESCRIPTION: Given a passband and an array of data lines from
# Mark IV database, find the min and max values of the
# magnitude in the given band. We have some default
# values which are "sensible" in case there are
# no valid values.
#
# RETURNS:
# (min_mag, max_mag)
#
sub find_extreme_mags {
my($i);
my($default_min_mag, $default_max_mag);
my($bad_min_mag, $bad_max_mag);
my($min_mag, $max_mag);
my($passband);
my($mag, $mag_column);
my($line, @words);
my($num_lines);
my($q) = $main::q;
$passband = $_[0];
$num_lines = $_[1];
if ($main::debug > 0) {
print $q->p("find_extreme_mags: passband ..$passband.. num_lines $num_lines");
}
if ($passband eq "V") {
$mag_column = 7;
}
elsif ($passband eq "I") {
$mag_column = 11;
}
else {
print $q->p("find_extreme_mags: given bad passband $passband -- abort");
return(0);
}
# these will signal no real data if they persist
$bad_min_mag = 100;
$bad_max_mag = -100;
# these are sensible defaults
$default_min_mag = 6.0;
$default_max_mag = 15.0;
# find the min, max values in the data
$min_mag = $bad_min_mag;
$max_mag = $bad_max_mag;
for ($i = 0; $i < $num_lines; $i++) {
$line = " " . $_[2 + $i];
@words = split(/\s+/, $line);
$mag = $words[$mag_column];
if ($main::debug > 0) {
print $q->p("find_extreme_mags: passband $passband line $i mag $mag");
}
# we don't include values of 99
if ($mag > 90) {
next;
}
if ($mag < $min_mag) {
$min_mag = $mag;
}
if ($mag > $max_mag) {
$max_mag = $mag;
}
}
if ($min_mag == $bad_min_mag) {
$min_mag = $default_min_mag;
}
if ($max_mag == $bad_max_mag) {
$max_mag = $default_max_mag;
}
return($min_mag, $max_mag);
}
#############################################################################
# PROCEDURE: find_graph_limits
#
# DESCRIPTION: Given the min,max V and min,max I magnitudes of star,
# figure out good limits for a phased light curve.
# The "x" values are phase, and "y" values are magnitudes
# (with min at top and max at bottom)
#
# RETURNS:
# (minx, maxx, miny, maxy)
#
sub find_graph_limits {
my($extra);
my($min_v, $max_v, $min_i, $max_i);
my($min_mag, $max_mag, $delta_mag);
my($minx, $maxx, $miny, $maxy);
my($q) = $main::q;
$min_v = $_[0];
$max_v = $_[1];
$min_i = $_[2];
$max_i = $_[3];
if ($min_v < $min_i) {
$min_mag = $min_v;
}
else {
$min_mag = $min_i;
}
if ($max_v > $max_i) {
$max_mag = $max_v;
}
else {
$max_mag = $max_i;
}
# the limits in phase are simple
$minx = -0.1;
$maxx = 2.1;
# the limits in magnitude are harder -- we allow a little extra
# room at top and bottom
$delta_mag = $max_mag - $min_mag;
$extra = $delta_mag*0.10;
$miny = $max_mag + $extra;
$maxy = $min_mag - 2.0*$extra;
if ($main::debug > 0) {
print $q->p("find_graph_limits: X $minx $maxx Y $miny $maxy ");
}
return($minx, $maxx, $miny, $maxy);
}
#############################################################################
# PROCEDURE: create_phased_data
#
# DESCRIPTION: Given a filename, epoch, period, an array of data on
# a particular star, calculate the phase for each
# time of measurement. Create a datafile with format
#
# JD phase1 phase+1 vmag1 vmag2 imag1 imag2
#
# where vmag1 is the V-band mag, if no warning flags
# vmag2 is the V-band mag, if warning flag set
# imag1 is the I-band mag, if no warning flags
# imag2 is the I-band mag, if warning flag set
#
# We use a value of 99.0 for any mag which we're not going
# to plot.
#
# Write the datafile to disk.
#
# RETURNS:
# 0 if all goes well
# 1 if an error occurs
#
sub create_phased_data {
my($i);
my($retval);
my($datafile_name);
my($epoch_jd, $period);
my($num_lines);
my($line, @words);
my($jd, $vmag, $vsig, $vflag, $imag, $isig, $iflag);
my($phase, $x);
my($vmag1, $vmag2, $imag1, $imag2);
my($q) = $main::q;
# by default, we haven't succeeded
$retval = 1;
$datafile_name = $_[0];
$epoch_jd = $_[1];
$period = $_[2];
$num_lines = $_[3];
if ($main::debug > 0) {
print $q->p("create_phased_data: file $datafile_name epoch $epoch_jd period $period ");
}
# sanity checks
if ($epoch_jd < 0) {
print $q->p("create_phased_data: bad epoch $epoch_jd");
return($retval);
}
if ($period <= 0) {
print $q->p("create_phased_data: bad period $period");
return($retval);
}
if (!open(PHASED_DATA, ">$datafile_name")) {
print $q->p("create_phased_data: can't open $datafile_name");
return($retval);
}
for ($i = 0; $i < $num_lines; $i++) {
$line = " " . $_[4 + $i];
@words = split(/\s+/, $line);
$jd = $words[5];
$vmag = $words[7];
$vsig = $words[8];
$vflag = $words[9];
$imag = $words[11];
$isig = $words[12];
$iflag = $words[13];
if ($main::debug > 0) {
print $q->p("create_phased_data: jd $jd vmag $vmag imag $imag");
}
$x = ($jd - $epoch_jd)/$period;
$phase = $x - floor($x);
if ($main::debug > 0) {
print $q->p("create_phased_data: phase $phase ");
}
# look at flags, set the quantities we'll print
if ($vflag == 0) {
$vmag1 = $vmag;
$vmag2 = 99.0;
}
else {
$vmag1 = 99.0;
$vmag2 = $vmag;
}
if ($iflag == 0) {
$imag1 = $imag;
$imag2 = 99.0;
}
else {
$imag1 = 99.0;
$imag2 = $imag;
}
# now we print a line into the output datafile
printf PHASED_DATA " %12.5f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f \n",
$jd, $phase, $phase+1.0, $vmag1, $vmag2, $imag1, $imag2;
}
close(PHASED_DATA);
# if we get here, all is well!
$retval = 0;
return($retval);
}
#############################################################################
# PROCEDURE: create_plot_url
#
# DESCRIPTION: We have created a file on disk which contains a graphical
# image of the light curve, something like this:
#
# /var/www/html/temp/make_phase_3331.png
#
# The start of this full path is the $www_dir. We want to
# replace that portion of the path with an equivalent
# URL, pointing to exactly the same directory, but
# accessible to people on other machines via HTTP.
#
# All we need to do is replace the $www_dir portion
# of the full name with $site_url variable. These are
# globals defined at the top of this source code file.
# We should end up with something that looks like
#
# http://spiff.rit.edu/html/temp/make_phase_3331.png
#
#
# RETURNS:
# the full URL
#
sub create_url_name {
my($plot_file, $plot_url);
$plot_file = $_[0];
if ($main::debug > 0) {
print $q->p("create_url_name: original name is $plot_file");
}
$plot_url = $plot_file;
$plot_url =~ s/$www_dir/$site_url/;
if ($main::debug > 0) {
print $q->p("create_url_name: new name is $plot_url");
}
return($plot_url);
}
###########################################################################
# PROCEDURE: remove_control_chars
#
# DESCRIPTION: Given a string, return a copy from which all "control"
# characters (ASCII code < 32) have been removed.
#
# RETURNS:
# "clean" version of the string
#
sub remove_control_chars {
my($old, $new, $len, $i, $char);
$old = $_[0];
$new = "";
$len = length($old);
for ($i = 0; $i < $len; $i++) {
$char = substr($old, $i, 1);
if (ord($char) >= 32) {
$new .= $char;
}
}
return($new);
}
###########################################################################
# PROCEDURE: generate_new_filenames
#
# DESCRIPTION: We need to create unique versions of the global variables
# plotfile plot_cmd_file plot_data_file
#
# They have values which look something like
#
# make_phased_5123QxQ.dat
#
# What we do is modify the character(s) between the
# capital Qs. We replace those character(s) with
# the argument to this function. For example, if the
# function is called with arg "1", then we get
#
# make_phased_5123Q1Q.dat
#
# or, if called with arg "23", we get
#
#
# make_phased_5123Q23Q.dat
#
# RETURNS:
# 0 to indicate that all went well
#
sub generate_new_filenames {
my($index, $stuff);
$index = $_[0];
if ($plotfile =~ /.*Q(.*)Q/) {
$stuff = $1;
$plotfile =~ s/Q${stuff}Q/Q${index}Q/;
}
else {
print $q->p("generate_new_filenames: bad format for plotfile $plotfile ?!");
print $q->p("aborting ... ");
return(1);
}
if ($plot_cmd_file =~ /.*Q(.*)Q/) {
$stuff = $1;
$plot_cmd_file =~ s/Q${stuff}Q/Q${index}Q/;
}
else {
print $q->p("generate_new_filenames: bad format for plot_cmd_file $plot_cmd_file ?!");
print $q->p("aborting ... ");
return(1);
}
if ($plot_data_file =~ /.*Q(.*)Q/) {
$stuff = $1;
$plot_data_file =~ s/Q${stuff}Q/Q${index}Q/;
}
else {
print $q->p("generate_new_filenames: bad format for plot_data_file $plot_data_file ?!");
print $q->p("aborting ... ");
return(1);
}
return(0);
}
############################################################
# Take two Benchmark timestamps and find out
# the time difference between the two.
#
# Return: time in minutes, time in seconds.
#
sub diff_time {
my ($t0, $t1) = @_;
my ($td) = "";
my ($total_time) = "";
my (@total_time) = ();
my ($total_sec) = "";
my ($total_min) = "";
$td = timediff($t1, $t0);
$total_time = timestr($td);
$total_time =~ tr / //s;
if ($total_time =~ /^ /) { $total_time =~ s/^ //; }
@total_time = split(/ /, $total_time);
my ($time_sec) = @total_time[0];
use integer;
my ($time_min) = $time_sec/60;
no integer;
if (length($time_min) == 1) { $time_min = "0" . $time_min; }
if (length($time_sec) == 1) { $time_sec = "0" . $time_sec; }
return ($time_min, $time_sec);
}
|