package Period; # Some::Module; # assumes Some/Module.pm use strict; use warnings; BEGIN { use Exporter (); our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS); # set the version for version checking $VERSION = 1.00; @ISA = qw(Exporter); @EXPORT = qw(&Analysis &HighStep &MediumStep &LowStep &PlotAnalysis &Phase &FreqFormat &ShowData); %EXPORT_TAGS = ( ); # eg: TAG => [ qw!name1 name2! ], # your exported package globals go here, # as well as any optionally exported functions @EXPORT_OK = qw(@ObsJD @ObsMag $N $GNUPlot $Montage $OUTDIR $HOME $RM $PERL $Extrema &Timespan &Brightest &Faintest); } our @EXPORT_OK; # exported package globals go here our @ObsJD; our @ObsMag; our $N; # Number of observations our $GNUPlot; our $Montage; our $OUTDIR; our $HOME; our $Extrema; our $PERL; our $RM; # non-exported package globals go here our $Nb; our $Nc; our $compact; # initialize package globals, first exported ones $N = 0; $GNUPlot = "$ENV{PeriodGNU}pgnuplot"; $Montage = "$ENV{PeriodIMM}montage"; $OUTDIR = $ENV{PeriodOUT}; $HOME = $ENV{PeriodDIR}; $PERL = "$ENV{PeriodPERL}perl"; $Extrema = "$PERL -s $ENV{PeriodDIR}Extrema.pl"; $RM = $ENV{PeriodRM}; # then the others (which are still accessible as $Some::Module::stuff) $Nb = 5; $Nc = 2; $compact = 1; # all file-scoped lexicals must be created before # the functions below that use them. # file-private lexicals go here # here's a file-private function as a closure, # callable as &$priv_func; it cannot be prototyped. # make all your functions, whether exported or not; # remember to put something interesting in the {} stubs # this one isn't exported, but could be called! END { } # module clean-up code here (global destructor) ## YOUR CODE GOES HERE #procedure ecliptical; #var x, y : real; #begin #x := cos(dec * rad) * cos(RA * 15 * rad); #y := 0.917 * cos(dec * rad) * sin(RA * 15 * rad) + 0.398 * sin(dec * rad); #cosbeta := sqrt(x * x + y * y); #if y = 0 then lambda := 0 else lambda := 2 * arctan((cosbeta - x)/y) #end; #function helio_correction(jd : real) : real; #(* accurate to better than 0.0001d for about a century *) #var M : real; #begin #jd := jd + epoch - 2451545.0; #M := 6.24 + 0.0172020 * jd; #helio_correction := 0.00578 * cosbeta * (1 - 0.017 * cos(M)) # * cos(4.883 + 0.033 * sin(M) + 0.01720212 * jd - lambda) #end; # Get the average JD sub AvgJD () { my $JD = 0; for (my $i=1;$i<=$N;$i++) { $JD += $ObsJD[$i]; } if ($N > 0) { return $JD/$N; } else { return 0; } } # Get the total time span of the observations sub Timespan () { my $JD0 = $ObsJD[1]; my $JD1 = $ObsJD[1]; for (my $i=1;$i<=$N;$i++) { if ($ObsJD[$i] < $JD0) { $JD0 = $ObsJD[$i]; } if ($ObsJD[$i] > $JD1) { $JD1 = $ObsJD[$i]; } } return $JD1 - $JD0; } # Determine the high step rate (for frequency search) sub HighStep () { return 1/Timespan/20; } # Determine the medium stop rate (for frequency search) sub MediumStep () { return 1/Timespan/15; } # Determine the low step rate (for frequency search) sub LowStep () { return 1/Timespan/10; } # Get the brightest observation sub Brightest () { my $mag = $ObsMag[1]; for (my $i=1;$i<=$N;$i++) { if ($ObsMag[$i] < $mag) { $mag = $ObsMag[$i]; } } return $mag; } # Get the faintest observation sub Faintest () { my $mag = $ObsMag[1]; for (my $i=1;$i<=$N;$i++) { if ($ObsMag[$i] > $mag) { $mag = $ObsMag[$i]; } } return $mag; } # Show all the data sub ShowData ($) { my ($delimiter) = @_; if (!$delimiter) { $delimiter = " "; } for (my $i=1;$i<=$N;$i++) { print "$ObsJD[$i]$delimiter$ObsMag[$i]\n"; } } # Make a GNUPlot command file to plot the analysis sub PlotAnalysis ($$$$) { # Create PlotAnalysis command file my ($GifFile, $FreqFile, $analysis, $out) = @_; #print "$out\n"; open (GNUPLOT, $out); print GNUPLOT "set term gif\n"; print GNUPLOT "set xlabel 'Frequency (c/d)'\n"; #print GNUPLOT "set xrange [$F0:$F1]\n"; if ($analysis eq "pdm") { print GNUPLOT "set title 'PDM Analysis'\n"; print GNUPLOT "set ylabel 'Theta (PDM)'\n"; print GNUPLOT "set yrange [0:1.05]\n"; print GNUPLOT "set ytics 0.1\n"; print GNUPLOT "set format y '%.1f'\n"; print GNUPLOT "set mytics 2\n"; } else { print GNUPLOT "set title 'Lomb-Scargle periodogram'\n"; print GNUPLOT "set ylabel 'Amplitude'\n"; } print GNUPLOT "set output '$GifFile.gif'\n"; print GNUPLOT "plot '$FreqFile' notitle with lines\n"; print GNUPLOT "set output\n"; print GNUPLOT "exit\n"; close GNUPLOT; } # Make a GNUPlot command file to plot the phase diagram sub PlotPhase ($$$$) { # Create PlotPhase command file my ($PhaseFile, $graph, $title, $out) = @_; my $faint = Faintest; my $bright = Brightest; my $margin = ($faint - $bright)/10; $faint += $margin; $bright -= $margin; #print "$out\n"; open (GNUPLOT, $out); print GNUPLOT "set term gif\n"; print GNUPLOT "set nokey\n"; print GNUPLOT "set title '$title'\n"; print GNUPLOT "set bmargin 5\n"; print GNUPLOT "set lmargin 10\n"; print GNUPLOT "set rmargin 10\n"; print GNUPLOT "set xlabel 'Phase'\n"; print GNUPLOT "set xrange [-0.2:1.2]\n"; print GNUPLOT "set xtics 0.2\n"; print GNUPLOT "set mxtics 2\n"; print GNUPLOT "set format x '%.1f'\n"; print GNUPLOT "set ylabel 'Mag'\n"; print GNUPLOT "set yrange [$faint:$bright]\n"; print GNUPLOT "set output '$graph.gif'\n"; print GNUPLOT "set multiplot\n"; print GNUPLOT "plot '$PhaseFile' using 1:2 notitle with points pointtype 7\n"; print GNUPLOT "set xrange [0.8:2.2]\n"; print GNUPLOT "set noxtics\n"; print GNUPLOT "set nomxtics\n"; print GNUPLOT "set xlabel ''\n"; print GNUPLOT "plot '$PhaseFile' using 1:2 notitle with points pointtype 7\n"; print GNUPLOT "set xrange [-1.2:0.2]\n"; print GNUPLOT "plot '$PhaseFile' using 1:2 notitle with points pointtype 7\n"; print GNUPLOT "set nomultiplot\n"; print GNUPLOT "set output\n"; print GNUPLOT "exit\n"; close GNUPLOT; } # Calculate the phase and output sub Phase ($$) { my ($freq, $out) = @_; my $phase; my $JDt = AvgJD; #print "$out\n"; open (PHASE, $out); # Loop through all observations for (my $i=1;$i<=$N;$i++) { $phase = ($ObsJD[$i] - $JDt) * $freq; $phase = $phase - int($phase); if ($phase < 0) { $phase += 1; } printf PHASE "%.3f %s\n", $phase ,$ObsMag[$i]; } close PHASE; } # Format the frequency (correct number of decimals depending on the step size) sub FreqFormat ($) { my ($Fstep) = @_; my $decimals = abs(int(log($Fstep)/log(10))) + 2; return sprintf "%%%d.%df", $decimals + 3,$decimals; } # Do the PDM analysis sub Analysis ($$$$) { my ($F0, $F1, $dF, $FreqFile) = @_; # $F0: First frequency # $F1: Last frequency # $dF: Frequency step # $FreqFile: Output destination (should contain ">" or "|") my $phase; my $bin; my @x; my @n; if ($N == 0) { return; } my $X = 0; my $X2 = 0; my $i; my $j; my $F; my $s2; my $theta = 1; my $rising = 0; my $JDt = AvgJD; for ($i=1;$i<=$N;$i++) { $X += $ObsMag[$i]; $X2 += $ObsMag[$i] * $ObsMag[$i]; } my $sigma2 = ($X2 - $X * $X/$N)/($N - 1); my $fmt = sprintf "%s %%.3f\n", FreqFormat($dF); #print "$N--$F0--$F1--$dF--$FreqFile--$fmt\n"; open THETA, "$FreqFile"; for ($F = $F0; $F <= $F1; $F += $dF) { # For each frequency # Initialize arrays for ($j = 0; $j < $Nc; $j++) { for ($i = 0; $i < $Nb; $i++) { $x[$j]->[$i] = 0; # ${$x[$j]}[i] = 0; $n[$j]->[$i] = 0; } } # Loop through all observations for ($i=1;$i<=$N;$i++) { for ($j = 0; $j < $Nc; $j++) { $phase = ($ObsJD[$i] - $JDt) * $F + $j/$Nb/$Nc; $phase = $phase - int($phase); $bin = int($Nb * $phase); $x[$j]->[$bin] += $ObsMag[$i]; $n[$j]->[$bin] += 1; } } $s2 = 0; for ($j = 0; $j < $Nc; $j++) { for ($i = 0; $i < $Nb; $i++) { if ($n[$j]->[$i] > 0) { $s2 += $x[$j]->[$i] * $x[$j]->[$i] / $n[$j]->[$i]; } } } $s2 = ($Nc * $X2 - $s2)/$Nc/($N -$Nb); if ($compact) {# Show only extrema of the statistic if ($s2 < $theta) { # statistic descends if ($rising > 0) {# statistic was rising, so has reached minimum printf THETA $fmt, $F - $dF, $theta/$sigma2; } $rising = -1; } elsif ($s2 > $theta) {# statistic rises if ($rising < 0) {# statistic was descending, so has reached maximum printf THETA $fmt, $F - $dF, $theta/$sigma2; } $rising = 1; } else { $rising = 0; } $theta = $s2; } else { printf THETA $fmt, $F, $s2/$sigma2; } # End for each frequency } close THETA; # End Analysis } 1; # don't forget to return a true value from the file