From 27a6d505eb853cb3a22a142ccef2b7198ad8c58b Mon Sep 17 00:00:00 2001 From: Jean Connelly Date: Sat, 5 Jan 2019 11:26:16 -0500 Subject: [PATCH 01/23] Add ccd_temp_acq to values calculated in calc_ccd_temps --- starcheck/calc_ccd_temps.py | 1 + 1 file changed, 1 insertion(+) diff --git a/starcheck/calc_ccd_temps.py b/starcheck/calc_ccd_temps.py index 6fb24f9b..c10cbbb5 100755 --- a/starcheck/calc_ccd_temps.py +++ b/starcheck/calc_ccd_temps.py @@ -210,6 +210,7 @@ def get_interval_data(intervals, times, ccd_temp, obsreqs=None): obstemps[str(interval['obsid'])] = obs continue obs['ccd_temp'] = np.max(ok_temps) + obs['ccd_temp_acq'] = np.max(ok_temps[0:2]) if len(ok_temps) > 1 else obs['ccd_temp'] obs['n100_warm_frac'] = dark_model.get_warm_fracs( 100, interval['tstart'], np.max(ok_temps)) # If we have an OR list, the obsid is in that list, and the OR list has zero-offset keys From 46c8943ebfa5f97bd89f27fd1d587bb3b91e7350 Mon Sep 17 00:00:00 2001 From: Jean Connelly Date: Sat, 5 Jan 2019 11:29:16 -0500 Subject: [PATCH 02/23] Use proseco for P_ACQ calculations --- .../src/lib/Ska/Starcheck/FigureOfMerit.pm | 101 ---------- starcheck/src/lib/Ska/Starcheck/Obsid.pm | 189 +++++++++++++++++- starcheck/src/starcheck.pl | 5 +- 3 files changed, 185 insertions(+), 110 deletions(-) delete mode 100644 starcheck/src/lib/Ska/Starcheck/FigureOfMerit.pm diff --git a/starcheck/src/lib/Ska/Starcheck/FigureOfMerit.pm b/starcheck/src/lib/Ska/Starcheck/FigureOfMerit.pm deleted file mode 100644 index c4d99591..00000000 --- a/starcheck/src/lib/Ska/Starcheck/FigureOfMerit.pm +++ /dev/null @@ -1,101 +0,0 @@ -package Ska::Starcheck::FigureOfMerit; -##***************************************************************************************** -#figure_of_merit.pm - Generates a probabilistic figure of merit for star catalogs -# within starcheck. -# -# Outputs an array of: -# the log probability of bright star hold -# the expected number of acquisition stars identified -# -# Individual star probabilities are hard coded and will need -# regular updates. -# -##***************************************************************************************** - -use strict; -use List::Util qw(min sum); - -use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); - -require Exporter; - -our @ISA = qw(Exporter); -our @EXPORT = qw(); -our @EXPORT_OK = qw( make_figure_of_merit set_dynamic_mag_limits ); -our %EXPORT_TAGS = ( all => \@EXPORT_OK ); - -use Inline Python => q{ - -from chandra_aca.star_probs import acq_success_prob, prob_n_acq, mag_for_p_acq - -def _mag_for_p_acq(p_acq, date, t_ccd): - return mag_for_p_acq(p_acq, date.decode(), t_ccd) - -def _acq_success_prob(date, t_ccd, mag, color, spoiler, halfwidth): - out = acq_success_prob(date.decode(), float(t_ccd), float(mag), float(color), spoiler, int(halfwidth)) - return out.tolist() - -def _prob_n_acq(acq_probs): - n_acq_probs, n_or_fewer_probs = prob_n_acq(acq_probs) - return n_acq_probs.tolist(), n_or_fewer_probs.tolist() -}; - - -sub make_figure_of_merit{ - my $c; - my $self = shift; - return unless ($c = $self->find_command("MP_STARCAT")); - return unless (defined $self->{ccd_temp}); - - my @probs; - my %slot_probs; - - my $t_ccd = $self->{ccd_temp}; - my $prob_limit = 0.008; - - my $date = $c->{date}; - - foreach my $i (1..16) { - if ($c->{"TYPE$i"} =~ /BOT|ACQ/) { - my $mag = $c->{"GS_MAG$i"}; - my @warnings = grep {/\[\s{0,1}$i\]/} (@{$self->{warn}}, @{$self->{yellow_warn}}); - my $spoiler = grep(/Search spoiler/i, @warnings) ? 1 : 0; - my $color = $c->{"GS_BV$i"}; - my $hw = $c->{"HALFW$i"}; - my $star_prob = _acq_success_prob($date, $t_ccd, $mag, $color, $spoiler, $hw); - push @probs, $star_prob; - $slot_probs{$c->{"IMNUM$i"}} = $star_prob; - $c->{"P_ACQ$i"} = $star_prob; - } - } - $self->{acq_probs} = \%slot_probs; - - # Calculate the probability of acquiring n stars - my ($n_acq_probs, $n_or_fewer_probs) = _prob_n_acq(\@probs); - - $self->{figure_of_merit} = {expected => substr(sum(@probs), 0, 4), - cum_prob => [map { log($_) / log(10.0) } @{$n_or_fewer_probs}], - cum_prob_bad => ($n_or_fewer_probs->[2] > $prob_limit) - }; - - - if ($n_or_fewer_probs->[2] > $prob_limit){ - push @{$self->{warn}}, ">> WARNING: Probability of 2 or fewer stars > $prob_limit\n"; - } - -} - - -sub set_dynamic_mag_limits{ - my $c; - my $self = shift; - return unless ($c = $self->find_command("MP_STARCAT")); - - my $date = $c->{date}; - my $t_ccd = $self->{ccd_temp}; - # Dynamic mag limits based on 75% and 50% chance of successful star acq - # Maximum limits of 10.3 and 10.6 - $self->{mag_faint_yellow} = min(10.3, _mag_for_p_acq(0.75, $date, $t_ccd)); - $self->{mag_faint_red} = min(10.6, _mag_for_p_acq(0.5, $date, $t_ccd)); -} - diff --git a/starcheck/src/lib/Ska/Starcheck/Obsid.pm b/starcheck/src/lib/Ska/Starcheck/Obsid.pm index 64d9e2f9..83af1e4d 100644 --- a/starcheck/src/lib/Ska/Starcheck/Obsid.pm +++ b/starcheck/src/lib/Ska/Starcheck/Obsid.pm @@ -72,7 +72,7 @@ def _get_agasc_stars(ra, dec, roll, radius, date, agasc_file): }; -use List::Util qw(max min); +use List::Util qw(min max); use Quat; use Ska::ACACoordConvert; use File::Basename; @@ -81,7 +81,6 @@ use English; use IO::All; use Ska::Convert qw(date2time time2date); -use Ska::Starcheck::FigureOfMerit qw( make_figure_of_merit set_dynamic_mag_limits ); use RDB; use SQL::Abstract; @@ -2178,14 +2177,10 @@ sub print_report { $o .= "\n"; if (exists $self->{figure_of_merit}) { - my @probs = @{ $self->{figure_of_merit}->{cum_prob}}; my $bad_FOM = $self->{figure_of_merit}->{cum_prob_bad}; $o .= "$red_font_start" if $bad_FOM; - $o .= "Probability of acquiring 2,3, and 4 or fewer stars (10^x):\t"; - # override formatting to match pre-JSON strings - foreach (2..4) { - $o .= substr(sprintf("%.4f", "$probs[$_]"), 0, 6) . "\t"; - } + $o .= "Probability of acquiring 2 or fewer stars (10^x):\t"; + $o .= substr(sprintf("%.4f", $self->{figure_of_merit}->{cum_prob_2}), 0, 6) . "\t"; $o .= "$font_stop" if $bad_FOM; $o .= "\n"; $o .= sprintf("Acquisition Stars Expected : %.2f\n", @@ -2686,14 +2681,192 @@ sub set_ccd_temps{ push @{$self->{warn}}, sprintf("$alarm Using %s (planning limit) for t_ccd for mag limits\n", $config{ccd_temp_red_limit}); $self->{ccd_temp} = $config{ccd_temp_red_limit}; + $self->{ccd_temp_acq} = $config{ccd_temp_red_limit}; return; } # set the temperature to the value for the current obsid $self->{ccd_temp} = $obsid_temps->{$self->{obsid}}->{ccd_temp}; + $self->{ccd_temp_acq} = $obsid_temps->{$self->{obsid}}->{ccd_temp_acq}; $self->{n100_warm_frac} = $obsid_temps->{$self->{obsid}}->{n100_warm_frac}; # add warnings for limit violations if ($self->{ccd_temp} > $config{ccd_temp_red_limit}){ push @{$self->{fyi}}, sprintf("$info CCD temperature exceeds %.1f C\n", $config{ccd_temp_red_limit}); } + if (($self->{ccd_temp_acq} > -1.0) or ($self->{ccd_temp_acq} < -16.0)){ + push @{$self->{yellow_warn}}, sprintf( + ">> WARNING: acq t_ccd %.2f outside range -16.0 to -1.0. Clipped.", + $self->{ccd_temp_acq}); + $self->{ccd_temp_acq} = $self->{ccd_temp_acq} > -1.0 ? -1.0 + : $self->{ccd_temp_acq} < -16.0 ? -16.0 + : $self->{ccd_temp_acq}; + } +} + +use Inline Python => q{ + +from proseco.acq import get_acq_catalog + +def calc_man_ang(q1, q2, q3, q4, initq1, initq2, initq3, initq4): + init_q = Quaternion.Quat([float(initq1), float(initq2), float(initq3), float(initq4)]) + final_q = Quaternion.Quat([float(q1), float(q2), float(q3), float(q4)]) + ang = float(np.degrees(2 * np.arccos(np.dot(init_q.q, final_q.q)))) + ang = ang if ang <= 180 else 360 - ang + return ang + + +def proseco_probs(kwargs): + + kw = de_bytestr(kwargs) + acq_cat = get_acq_catalog(obsid=0, att=Quaternion.normalize([kw['q1'], kw['q2'], kw['q3'], kw['q4']]), + n_acq=len(kw['acqs']), man_angle=kw['man_angle'], t_ccd=kw['t_ccd_acq'], + date=kw['date'], dither=(kw['dither_acq_y'], kw['dither_acq_z']), + detector=kw['detector'], sim_offset=kw['offset'], + include_ids=kw['acqs'], include_halfws=kw['halfwidths']) + p_acqs = [] + for acq in kw['acqs']: + if np.any(acq_cat['id'] == acq): + p_acqs.append(float(acq_cat['p_acq'][acq_cat['id'] == acq][0])) + else: + p_acqs.append(float(0.0)) + + return p_acqs, float(acq_cat.get_log_p_2_or_fewer()), float(np.sum(p_acqs)) +}; + + + +sub proseco_args{ + + my $self = shift; + my %proseco_args; + my $targ_cmd = find_command($self, "MP_TARGQUAT"); + my $cat_cmd = find_command($self, "MP_STARCAT"); + if ((not $targ_cmd) or (not $cat_cmd)){ + return \%proseco_args; + } + my $si = 'ACIS-S'; + my $offset = 0; + if ($self->{obsid} < 38000){ + $si = $self->{SI}; + $offset = $self->{SIM_OFFSET_Z}; + } + my $man_ang; + if (defined $targ_cmd->{initq1}){ + $man_ang = calc_man_ang( + 0 + $targ_cmd->{q1}, 0 + $targ_cmd->{q2}, + 0 + $targ_cmd->{q3}, 0 + $targ_cmd->{q4}, + 0 + $targ_cmd->{initq1}, 0 + $targ_cmd->{initq2}, + 0 + $targ_cmd->{initq3}, 0 + $targ_cmd->{initq4}); + } + + my @acq_ids; + my @acq_indexes; + my @gui_ids; + my @fid_ids; + my @halfwidths; + foreach my $i (1..16) { + if ($cat_cmd->{"TYPE$i"} =~ /BOT|ACQ/){ + push @acq_ids, $cat_cmd->{"GS_ID$i"}; + my $hw = $cat_cmd->{"HALFW$i"}; + if (($hw > 180) or ($hw < 60)){ + push @{$self->{yellow_warn}}, sprintf( + ">> WARNING: [%2d] Halfwidth %d outside range 60 to 180. Clipped for probs.", + $i, $hw); + # Clip hw if outside the range 60 to 180 for probabilities + $hw = $hw < 60 ? 60 + : $hw > 180 ? 180 + : $hw ; + } + push @halfwidths, $hw; + push @acq_indexes, $i; + } + if ($cat_cmd->{"TYPE$i"} =~ /BOT|GUI/){ + push @gui_ids, $cat_cmd->{"GS_ID$i"}; + } + if ($cat_cmd->{"TYPE$i"} =~ /FID/){ + push @fid_ids, $cat_cmd->{"GS_ID$i"}; + } + } + + %proseco_args = ( + obsid => $self->{obsid}, + date => $targ_cmd->{stop_date}, + q1 => 0 + $targ_cmd->{q1}, q2 => 0 + $targ_cmd->{q2}, q3 => 0 + $targ_cmd->{q3}, q4 =>0 + $targ_cmd->{q4}, + man_angle => $man_ang, + detector => $si, offset=> 0 + $offset, + dither_acq_y => $self->{dither_acq}->{ampl_y}, + dither_acq_z => $self->{dither_acq}->{ampl_p}, + dither_guide_y => $self->{dither_guide}->{ampl_y}, + dither_guide_z => $self->{dither_guide}->{ampl_p}, + t_ccd_acq => $self->{ccd_temp_acq}, + t_ccd_guide => $self->{ccd_temp}, + acqs => \@acq_ids, + halfwidths => \@halfwidths, + fids => \@fid_ids, + guides => \@gui_ids, + acq_indexes => \@acq_indexes); + + return \%proseco_args + +} + +my $CUM_PROB_LIMIT = 0.008; + +sub set_proseco_probs{ + my $self = shift; + my $cat_cmd = find_command($self, "MP_STARCAT"); + my $args = $self->{proseco_args}; + if ((not $cat_cmd)){ + return + } + my ($p_acqs, $two_or_fewer, $expected) = proseco_probs($args); + + my @acq_indexes = @{$args->{acq_indexes}}; + + # Assign those p_acqs to a slot hash and the catalog P_ACQ by index + my %slot_probs; + for my $idx (0 .. $#acq_indexes) { + my $i = $acq_indexes[$idx]; + $cat_cmd->{"P_ACQ$i"} = $p_acqs->[$idx]; + $slot_probs{$cat_cmd->{"IMNUM$i"}} = $p_acqs->[$idx]; + } + + $self->{acq_probs} = \%slot_probs; + + $self->{figure_of_merit} = {expected => substr($expected, 0, 4), + cum_prob_2 => $two_or_fewer, + cum_prob_bad => ($two_or_fewer > $CUM_PROB_LIMIT)}; + if ($two_or_fewer > $CUM_PROB_LIMIT){ + push @{$self->{warn}}, ">> WARNING: Probability of 2 or fewer stars > $CUM_PROB_LIMIT\n"; + } + + + +}; + + + +use Inline Python => q{ + +from chandra_aca.star_probs import mag_for_p_acq + +def _mag_for_p_acq(p_acq, date, t_ccd): + return mag_for_p_acq(p_acq, date.decode(), t_ccd) + +}; + + + +sub set_dynamic_mag_limits{ + my $c; + my $self = shift; + return unless ($c = $self->find_command("MP_STARCAT")); + + my $date = $c->{date}; + my $t_ccd = $self->{ccd_temp}; + # Dynamic mag limits based on 75% and 50% chance of successful star acq + # Maximum limits of 10.3 and 10.6 + $self->{mag_faint_yellow} = min(10.3, _mag_for_p_acq(0.75, $date, $t_ccd)); + $self->{mag_faint_red} = min(10.6, _mag_for_p_acq(0.5, $date, $t_ccd)); } + diff --git a/starcheck/src/starcheck.pl b/starcheck/src/starcheck.pl index 1b450c96..25c974d8 100755 --- a/starcheck/src/starcheck.pl +++ b/starcheck/src/starcheck.pl @@ -644,7 +644,10 @@ sub json_obsids{ if ($bs[0]->{time} > date2time('2017:043:00:00:00.000')){ $obs{$obsid}->check_big_box_stars(); } - $obs{$obsid}->make_figure_of_merit(); + # Get the args that proseco would want + $obs{$obsid}->{'proseco_args'} = $obs{$obsid}->proseco_args(); + $obs{$obsid}->set_proseco_probs(); + # Make sure there is only one star catalog per obsid warning ("More than one star catalog assigned to Obsid $obsid\n") if ($obs{$obsid}->find_command('MP_STARCAT',2)); From 003cdc696d32800ca0b55c59c223715c1cbd5a19 Mon Sep 17 00:00:00 2001 From: Jean Connelly Date: Mon, 7 Jan 2019 14:13:02 -0500 Subject: [PATCH 03/23] Remove FigureOfMerit from Makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index fb7bb105..1c94a8f9 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ SRC = starcheck/src RELATED_LIB = $(SRC)/StarcheckParser.pm BIN = $(SRC)/starcheck.pl $(SRC)/starcheck -LIB = $(SRC)/lib/Ska/Starcheck/Obsid.pm $(SRC)/lib/Ska/Starcheck/FigureOfMerit.pm \ +LIB = $(SRC)/lib/Ska/Starcheck/Obsid.pm \ $(SRC)/lib/Ska/Starcheck/Dark_Cal_Checker.pm $(SRC)/lib/Ska/Parse_CM_File.pm PYTHON_LIB = starcheck/calc_ccd_temps.py starcheck/pcad_att_check.py starcheck/plot.py \ starcheck/version.py starcheck/__init__.py From 4be5b72d27683cb1d1eaac11aa53e40df101ef0c Mon Sep 17 00:00:00 2001 From: Jean Connelly Date: Mon, 7 Jan 2019 14:14:15 -0500 Subject: [PATCH 04/23] Use maneuver summary maneuver angle instead of calculating it --- starcheck/src/lib/Ska/Starcheck/Obsid.pm | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/starcheck/src/lib/Ska/Starcheck/Obsid.pm b/starcheck/src/lib/Ska/Starcheck/Obsid.pm index 83af1e4d..197edaa6 100644 --- a/starcheck/src/lib/Ska/Starcheck/Obsid.pm +++ b/starcheck/src/lib/Ska/Starcheck/Obsid.pm @@ -2707,13 +2707,6 @@ use Inline Python => q{ from proseco.acq import get_acq_catalog -def calc_man_ang(q1, q2, q3, q4, initq1, initq2, initq3, initq4): - init_q = Quaternion.Quat([float(initq1), float(initq2), float(initq3), float(initq4)]) - final_q = Quaternion.Quat([float(q1), float(q2), float(q3), float(q4)]) - ang = float(np.degrees(2 * np.arccos(np.dot(init_q.q, final_q.q)))) - ang = ang if ang <= 180 else 360 - ang - return ang - def proseco_probs(kwargs): @@ -2750,13 +2743,9 @@ sub proseco_args{ $si = $self->{SI}; $offset = $self->{SIM_OFFSET_Z}; } - my $man_ang; - if (defined $targ_cmd->{initq1}){ - $man_ang = calc_man_ang( - 0 + $targ_cmd->{q1}, 0 + $targ_cmd->{q2}, - 0 + $targ_cmd->{q3}, 0 + $targ_cmd->{q4}, - 0 + $targ_cmd->{initq1}, 0 + $targ_cmd->{initq2}, - 0 + $targ_cmd->{initq3}, 0 + $targ_cmd->{initq4}); + my $man_ang = 90; + if (defined $targ_cmd->{angle}){ + $man_ang = $targ_cmd->{angle}; } my @acq_ids; From 911d4a3831eab45aed217cb67a5a35f1ce5eebe2 Mon Sep 17 00:00:00 2001 From: Jean Connelly Date: Mon, 7 Jan 2019 14:15:35 -0500 Subject: [PATCH 05/23] Handle missing data (ReOpen schedule beginning) for proseco probs --- starcheck/src/lib/Ska/Starcheck/Obsid.pm | 42 +++++++++++++++++------- 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/starcheck/src/lib/Ska/Starcheck/Obsid.pm b/starcheck/src/lib/Ska/Starcheck/Obsid.pm index 197edaa6..97af5451 100644 --- a/starcheck/src/lib/Ska/Starcheck/Obsid.pm +++ b/starcheck/src/lib/Ska/Starcheck/Obsid.pm @@ -2027,9 +2027,13 @@ sub print_report { my $acq_prob = ""; if ($c->{"TYPE$i"} =~ /BOT|ACQ/){ - my $prob = $self->{acq_probs}->{$c->{"IMNUM${i}"}}; - $acq_prob = sprintf("Prob Acq Success %5.3f", $prob); - + if (defined $self->{acq_probs}->{$c->{"IMNUM${i}"}}){ + my $prob = $self->{acq_probs}->{$c->{"IMNUM${i}"}}; + $acq_prob = sprintf("Prob Acq Success %5.3f", $prob); + } + else{ + $acq_prob = sprintf("Prob Acq Success 0.0"); + } } # Make the id a URL if there is star history or if star history could # not be checked (no db_handle) @@ -2753,9 +2757,25 @@ sub proseco_args{ my @gui_ids; my @fid_ids; my @halfwidths; + IDX: foreach my $i (1..16) { + (my $sid = $cat_cmd->{"GS_ID$i"}) =~ s/[\s\*]//g; + # If there is no star there is nothing for proseco probs to do so skip it. + # But warn if it was a thing that should have had an id (BOT/ACQ/GUI). + if ($sid eq '---'){ + if ($cat_cmd->{"TYPE$i"} =~ /BOT|ACQ|GUI/){ + push @{$self->{warn}}, sprintf( + ">> WARNING: [%2d] Could not calculate acq prob for star with no id.", $i); + } + next IDX; + } + $sid = int($sid); + ## Strip off asterisk if present (there's probably a cleaner Perl way to do this). + #if ($sid =~ /\*(\d+)/){ + # $sid = $1; + #} if ($cat_cmd->{"TYPE$i"} =~ /BOT|ACQ/){ - push @acq_ids, $cat_cmd->{"GS_ID$i"}; + push @acq_ids, $sid;; my $hw = $cat_cmd->{"HALFW$i"}; if (($hw > 180) or ($hw < 60)){ push @{$self->{yellow_warn}}, sprintf( @@ -2770,10 +2790,10 @@ sub proseco_args{ push @acq_indexes, $i; } if ($cat_cmd->{"TYPE$i"} =~ /BOT|GUI/){ - push @gui_ids, $cat_cmd->{"GS_ID$i"}; + push @gui_ids, $sid; } if ($cat_cmd->{"TYPE$i"} =~ /FID/){ - push @fid_ids, $cat_cmd->{"GS_ID$i"}; + push @fid_ids, $sid; } } @@ -2805,8 +2825,9 @@ sub set_proseco_probs{ my $self = shift; my $cat_cmd = find_command($self, "MP_STARCAT"); my $args = $self->{proseco_args}; - if ((not $cat_cmd)){ - return + + if (not %{$args}){ + return; } my ($p_acqs, $two_or_fewer, $expected) = proseco_probs($args); @@ -2828,10 +2849,7 @@ sub set_proseco_probs{ if ($two_or_fewer > $CUM_PROB_LIMIT){ push @{$self->{warn}}, ">> WARNING: Probability of 2 or fewer stars > $CUM_PROB_LIMIT\n"; } - - - -}; +} From a1e2276c847a12c2a2490414c13e2a15b4453f6c Mon Sep 17 00:00:00 2001 From: Jean Connelly Date: Mon, 7 Jan 2019 14:16:40 -0500 Subject: [PATCH 06/23] Use the 'last' maneuver for maneuver angle (for segmented manvrs for now) --- starcheck/src/lib/Ska/Starcheck/Obsid.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/starcheck/src/lib/Ska/Starcheck/Obsid.pm b/starcheck/src/lib/Ska/Starcheck/Obsid.pm index 97af5451..e61b4edc 100644 --- a/starcheck/src/lib/Ska/Starcheck/Obsid.pm +++ b/starcheck/src/lib/Ska/Starcheck/Obsid.pm @@ -2736,7 +2736,7 @@ sub proseco_args{ my $self = shift; my %proseco_args; - my $targ_cmd = find_command($self, "MP_TARGQUAT"); + my $targ_cmd = find_command($self, "MP_TARGQUAT", -1); my $cat_cmd = find_command($self, "MP_STARCAT"); if ((not $targ_cmd) or (not $cat_cmd)){ return \%proseco_args; From 0e75f3fd378af8ced81dd3bad3abc7d7eb81dce1 Mon Sep 17 00:00:00 2001 From: Jean Connelly Date: Mon, 7 Jan 2019 14:17:05 -0500 Subject: [PATCH 07/23] Skip trying for proseco args for NONE obsids --- starcheck/src/lib/Ska/Starcheck/Obsid.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/starcheck/src/lib/Ska/Starcheck/Obsid.pm b/starcheck/src/lib/Ska/Starcheck/Obsid.pm index e61b4edc..a6b0f194 100644 --- a/starcheck/src/lib/Ska/Starcheck/Obsid.pm +++ b/starcheck/src/lib/Ska/Starcheck/Obsid.pm @@ -2738,7 +2738,7 @@ sub proseco_args{ my %proseco_args; my $targ_cmd = find_command($self, "MP_TARGQUAT", -1); my $cat_cmd = find_command($self, "MP_STARCAT"); - if ((not $targ_cmd) or (not $cat_cmd)){ + if ((not $targ_cmd) or (not $cat_cmd) or ($self->{obsid} =~ /NONE(\d+)/)){ return \%proseco_args; } my $si = 'ACIS-S'; From 887e7bfba140e16e3bfaddaaca87548a1d4f76d8 Mon Sep 17 00:00:00 2001 From: Jean Connelly Date: Mon, 7 Jan 2019 14:43:36 -0500 Subject: [PATCH 08/23] Recharacterize big box warning as yellow_warn --- starcheck/src/lib/Ska/Starcheck/Obsid.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/starcheck/src/lib/Ska/Starcheck/Obsid.pm b/starcheck/src/lib/Ska/Starcheck/Obsid.pm index a6b0f194..43fb5f71 100644 --- a/starcheck/src/lib/Ska/Starcheck/Obsid.pm +++ b/starcheck/src/lib/Ska/Starcheck/Obsid.pm @@ -2668,7 +2668,7 @@ sub check_big_box_stars{ } } if ($big_box_count < 3){ - push @{$self->{warn}}, "$alarm Fewer than 3 ACQ stars with boxes >= 160 arcsec\n"; + push @{$self->{yellow_warn}}, "$alarm Fewer than 3 ACQ stars with boxes >= 160 arcsec\n"; } } From 98dc5bded57ab10a5ae5116cfdaf69a249b3d6f2 Mon Sep 17 00:00:00 2001 From: Jean Connelly Date: Mon, 14 Jan 2019 16:34:05 -0500 Subject: [PATCH 09/23] Add comment for empty hover-over acq prob and simplify a bit --- starcheck/src/lib/Ska/Starcheck/Obsid.pm | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/starcheck/src/lib/Ska/Starcheck/Obsid.pm b/starcheck/src/lib/Ska/Starcheck/Obsid.pm index 43fb5f71..cd7ffb66 100644 --- a/starcheck/src/lib/Ska/Starcheck/Obsid.pm +++ b/starcheck/src/lib/Ska/Starcheck/Obsid.pm @@ -2024,15 +2024,15 @@ sub print_report { $idpad_n --; } - + # Get a string for acquisition probability in the hover-over my $acq_prob = ""; if ($c->{"TYPE$i"} =~ /BOT|ACQ/){ + # Fetch this slot's acq probability for the hover-over string, + # but if the probability is not defined (expected for weird cases such as + # replan/reopen) just leave $acq_prob as the initialized empty string. if (defined $self->{acq_probs}->{$c->{"IMNUM${i}"}}){ - my $prob = $self->{acq_probs}->{$c->{"IMNUM${i}"}}; - $acq_prob = sprintf("Prob Acq Success %5.3f", $prob); - } - else{ - $acq_prob = sprintf("Prob Acq Success 0.0"); + $acq_prob = sprintf("Prob Acq Success %5.3f", + $self->{acq_probs}->{$c->{"IMNUM${i}"}}) } } # Make the id a URL if there is star history or if star history could From 2082c6d19966ac8324e0fc2d0108bca5b871dc5b Mon Sep 17 00:00:00 2001 From: Jean Connelly Date: Mon, 14 Jan 2019 16:35:21 -0500 Subject: [PATCH 10/23] Remove big box check and set proseco probs earlier in loop in starcheck.pl --- starcheck/src/lib/Ska/Starcheck/Obsid.pm | 21 --------------------- starcheck/src/starcheck.pl | 10 +++------- 2 files changed, 3 insertions(+), 28 deletions(-) diff --git a/starcheck/src/lib/Ska/Starcheck/Obsid.pm b/starcheck/src/lib/Ska/Starcheck/Obsid.pm index cd7ffb66..2a77e6ed 100644 --- a/starcheck/src/lib/Ska/Starcheck/Obsid.pm +++ b/starcheck/src/lib/Ska/Starcheck/Obsid.pm @@ -2651,27 +2651,6 @@ sub count_guide_stars{ return _guide_count(\@mags, $self->{ccd_temp}); } -################################################################################### -sub check_big_box_stars{ -################################################################################### - my $self = shift; - my $c; - my $big_box_count = 0; - return unless ($c = find_command($self, 'MP_STARCAT')); - for my $i (1 .. 16){ - my $type = $c->{"TYPE$i"}; - my $hw = $c->{"HALFW$i"}; - if ($type =~ /ACQ|BOT/){ - if ($hw >= 160){ - $big_box_count++; - } - } - } - if ($big_box_count < 3){ - push @{$self->{yellow_warn}}, "$alarm Fewer than 3 ACQ stars with boxes >= 160 arcsec\n"; - } -} - ################################################################################### sub set_ccd_temps{ diff --git a/starcheck/src/starcheck.pl b/starcheck/src/starcheck.pl index 25c974d8..1caf3a3a 100755 --- a/starcheck/src/starcheck.pl +++ b/starcheck/src/starcheck.pl @@ -635,18 +635,14 @@ sub json_obsids{ $obs{$obsid}->check_flick_pix_mon(); $obs{$obsid}->set_dynamic_mag_limits(); $obs{$obsid}->check_dither($dither); + # Get the args that proseco would want + $obs{$obsid}->{'proseco_args'} = $obs{$obsid}->proseco_args(); + $obs{$obsid}->set_proseco_probs(); $obs{$obsid}->check_star_catalog($or{$obsid}, $par{vehicle}); $obs{$obsid}->check_sim_position(@sim_trans) unless $par{vehicle}; $obs{$obsid}->check_momentum_unload(\@bs); $obs{$obsid}->check_for_special_case_er(); $obs{$obsid}->check_bright_perigee($radmon); - # Start check for big boxes at FEB1317 (which gets test products but no regress products) - if ($bs[0]->{time} > date2time('2017:043:00:00:00.000')){ - $obs{$obsid}->check_big_box_stars(); - } - # Get the args that proseco would want - $obs{$obsid}->{'proseco_args'} = $obs{$obsid}->proseco_args(); - $obs{$obsid}->set_proseco_probs(); # Make sure there is only one star catalog per obsid warning ("More than one star catalog assigned to Obsid $obsid\n") From 998ff4660e8e4f23833b4bab20af5ceaee03e892 Mon Sep 17 00:00:00 2001 From: Jean Connelly Date: Mon, 14 Jan 2019 16:51:50 -0500 Subject: [PATCH 11/23] Assume the best This change sets proseco_probs to assume that the supplied acq ids all have appropriate acq probs. It also assumes that a manuever angle is set for each observations. --- starcheck/src/lib/Ska/Starcheck/Obsid.pm | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/starcheck/src/lib/Ska/Starcheck/Obsid.pm b/starcheck/src/lib/Ska/Starcheck/Obsid.pm index 2a77e6ed..cc989d87 100644 --- a/starcheck/src/lib/Ska/Starcheck/Obsid.pm +++ b/starcheck/src/lib/Ska/Starcheck/Obsid.pm @@ -2699,12 +2699,9 @@ def proseco_probs(kwargs): date=kw['date'], dither=(kw['dither_acq_y'], kw['dither_acq_z']), detector=kw['detector'], sim_offset=kw['offset'], include_ids=kw['acqs'], include_halfws=kw['halfwidths']) - p_acqs = [] - for acq in kw['acqs']: - if np.any(acq_cat['id'] == acq): - p_acqs.append(float(acq_cat['p_acq'][acq_cat['id'] == acq][0])) - else: - p_acqs.append(float(0.0)) + + # Assign the proseco probabilities back into an array. + p_acqs = [float(acq_cat['p_acq'][acq_cat['id'] == acq][0]) for acq in kw['acqs']] return p_acqs, float(acq_cat.get_log_p_2_or_fewer()), float(np.sum(p_acqs)) }; @@ -2726,10 +2723,6 @@ sub proseco_args{ $si = $self->{SI}; $offset = $self->{SIM_OFFSET_Z}; } - my $man_ang = 90; - if (defined $targ_cmd->{angle}){ - $man_ang = $targ_cmd->{angle}; - } my @acq_ids; my @acq_indexes; @@ -2780,7 +2773,7 @@ sub proseco_args{ obsid => $self->{obsid}, date => $targ_cmd->{stop_date}, q1 => 0 + $targ_cmd->{q1}, q2 => 0 + $targ_cmd->{q2}, q3 => 0 + $targ_cmd->{q3}, q4 =>0 + $targ_cmd->{q4}, - man_angle => $man_ang, + man_angle => 0 + $targ_cmd->{angle}, detector => $si, offset=> 0 + $offset, dither_acq_y => $self->{dither_acq}->{ampl_y}, dither_acq_z => $self->{dither_acq}->{ampl_p}, From a01658b9940b69e449c1ade125edb2548fbe9605 Mon Sep 17 00:00:00 2001 From: Jean Connelly Date: Mon, 14 Jan 2019 16:55:54 -0500 Subject: [PATCH 12/23] Update comments/docstrings (and fiddle with whitespace) --- starcheck/src/lib/Ska/Starcheck/Obsid.pm | 65 ++++++++++++++++++++---- 1 file changed, 55 insertions(+), 10 deletions(-) diff --git a/starcheck/src/lib/Ska/Starcheck/Obsid.pm b/starcheck/src/lib/Ska/Starcheck/Obsid.pm index cc989d87..57408a50 100644 --- a/starcheck/src/lib/Ska/Starcheck/Obsid.pm +++ b/starcheck/src/lib/Ska/Starcheck/Obsid.pm @@ -2690,8 +2690,30 @@ use Inline Python => q{ from proseco.acq import get_acq_catalog - def proseco_probs(kwargs): + """ + Call proseco's get_acq_catalog with the parameters supplied in `kwargs` for a specific obsid catalog + and return the individual acq star probabilities, the P2 value for the catalog, and the expected + number of acq stars. + + `kwargs` will be a Perl hash converted to dict (by Inline) of the expected keyword params. These keys + must be defined: + + 'q1', 'q2', 'q3', 'q4' = the target quaternion + 'man_angle' the maneuver angle to the target quaternion in degrees. + 'acqs' list of acq star ids + 'halfwidths' list of acq star halfwidths in arcsecs + 't_ccd_acq' acquisition temperature in deg C + 'date' observation date (in Chandra.Time compatible format) + 'detector' science detector + 'sim_offset' SIM offset + + As these values are from a Perl hash, bytestrings will be converted by de_bytestr early in this method. + + :param kwargs: dict of expected keywords + :return tuple: (list of floats of star acq probabilties, float P2, float expected acq stars) + + """ kw = de_bytestr(kwargs) acq_cat = get_acq_catalog(obsid=0, att=Quaternion.normalize([kw['q1'], kw['q2'], kw['q3'], kw['q4']]), @@ -2707,16 +2729,26 @@ def proseco_probs(kwargs): }; - +################################################################################### sub proseco_args{ - +################################################################################### +# Build a hash that corresponds to reasonable arguments to use to call proseco get_acq_catalog +# to calculate marginalized acquisition probabilities for a star catalog. +# This routine also saves the guides and fids into lists, but those are not used +# by get_acq_catalog. +# If an observation does not have a target quaternion or a starcat, it is skipped and +# an empty hash is returned with no warning. my $self = shift; my %proseco_args; + # For the target quaternion, use the -1 to get the last quaternion (there could be more than + # one for a segmented maneuver). my $targ_cmd = find_command($self, "MP_TARGQUAT", -1); my $cat_cmd = find_command($self, "MP_STARCAT"); + # For observations without a target attitude, catalog, or defined obsid return an empty hash if ((not $targ_cmd) or (not $cat_cmd) or ($self->{obsid} =~ /NONE(\d+)/)){ return \%proseco_args; } + # Use a default SI (which should only be used for ERs and should have no effect without fid lights) my $si = 'ACIS-S'; my $offset = 0; if ($self->{obsid} < 38000){ @@ -2729,6 +2761,7 @@ sub proseco_args{ my @gui_ids; my @fid_ids; my @halfwidths; + # Loop over the star catalog and assign the acqs, guide stars, and fids to arrays. IDX: foreach my $i (1..16) { (my $sid = $cat_cmd->{"GS_ID$i"}) =~ s/[\s\*]//g; @@ -2742,10 +2775,7 @@ sub proseco_args{ next IDX; } $sid = int($sid); - ## Strip off asterisk if present (there's probably a cleaner Perl way to do this). - #if ($sid =~ /\*(\d+)/){ - # $sid = $1; - #} + # While assigning ACQ stars into a list, clip to allowed ranges and warn as needed. if ($cat_cmd->{"TYPE$i"} =~ /BOT|ACQ/){ push @acq_ids, $sid;; my $hw = $cat_cmd->{"HALFW$i"}; @@ -2769,6 +2799,9 @@ sub proseco_args{ } } + # Build a hash of the arguments that could be used by proseco (get_aca_catalog or get_acq_catalog). + # Zeros are added to most of the numeric parameters as that seems to help "cast" them to floats or ints in + # Perl to some extent. %proseco_args = ( obsid => $self->{obsid}, date => $targ_cmd->{stop_date}, @@ -2791,9 +2824,16 @@ sub proseco_args{ } -my $CUM_PROB_LIMIT = 0.008; +################################################################################### sub set_proseco_probs{ +################################################################################### +# For observations with a star catalog and which have valid parameters already determined +# in $self->{proseco_args}, call the Python proseco_probs method to calculate the +# marginalized probabilities, P2, and expected stars, and assign those values back +# where expected in the data structure. +# This assigns the individual acq star probabilites back into $self->{acq_probs} and +# assigns the P2 and expected values into $self->{figure_of_merit}. my $self = shift; my $cat_cmd = find_command($self, "MP_STARCAT"); my $args = $self->{proseco_args}; @@ -2812,7 +2852,6 @@ sub set_proseco_probs{ $cat_cmd->{"P_ACQ$i"} = $p_acqs->[$idx]; $slot_probs{$cat_cmd->{"IMNUM$i"}} = $p_acqs->[$idx]; } - $self->{acq_probs} = \%slot_probs; $self->{figure_of_merit} = {expected => substr($expected, 0, 4), @@ -2830,13 +2869,19 @@ use Inline Python => q{ from chandra_aca.star_probs import mag_for_p_acq def _mag_for_p_acq(p_acq, date, t_ccd): - return mag_for_p_acq(p_acq, date.decode(), t_ccd) + """ + Call mag_for_p_acq, but cast p_acq and t_ccd as floats (may or may not be needed) and + convert date from a bytestring (from the Perl interface). + """ + return mag_for_p_acq(float(p_acq), date.decode(), float(t_ccd)) }; sub set_dynamic_mag_limits{ +# Use the t_ccd at time of acquistion and time to set the mag limits corresponding to the the magnitude +# for a 75% acquisition succes (yellow limit) and a 50% acquisition success (red limit) my $c; my $self = shift; return unless ($c = $self->find_command("MP_STARCAT")); From c8a4bc04c38ced97488f53b6ef063114e89d1b8b Mon Sep 17 00:00:00 2001 From: Jean Connelly Date: Mon, 14 Jan 2019 16:56:20 -0500 Subject: [PATCH 13/23] Set P2 to 2.0 and use more local variable --- starcheck/src/lib/Ska/Starcheck/Obsid.pm | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/starcheck/src/lib/Ska/Starcheck/Obsid.pm b/starcheck/src/lib/Ska/Starcheck/Obsid.pm index 57408a50..348b367c 100644 --- a/starcheck/src/lib/Ska/Starcheck/Obsid.pm +++ b/starcheck/src/lib/Ska/Starcheck/Obsid.pm @@ -2854,11 +2854,13 @@ sub set_proseco_probs{ } $self->{acq_probs} = \%slot_probs; + # Set the P2 to be 2.0 (aka 0.01) + my $cum_prob_limit = 0.01; $self->{figure_of_merit} = {expected => substr($expected, 0, 4), cum_prob_2 => $two_or_fewer, - cum_prob_bad => ($two_or_fewer > $CUM_PROB_LIMIT)}; - if ($two_or_fewer > $CUM_PROB_LIMIT){ - push @{$self->{warn}}, ">> WARNING: Probability of 2 or fewer stars > $CUM_PROB_LIMIT\n"; + cum_prob_bad => ($two_or_fewer > $cum_prob_limit)}; + if ($two_or_fewer > $cum_prob_limit){ + push @{$self->{warn}}, ">> WARNING: Probability of 2 or fewer stars > $cum_prob_limit\n"; } } From cb88ae606a18b39d1b57ddb1f481b7d942a80fdd Mon Sep 17 00:00:00 2001 From: Jean Connelly Date: Mon, 14 Jan 2019 16:56:47 -0500 Subject: [PATCH 14/23] Use acq phase temperature for mag limits --- starcheck/src/lib/Ska/Starcheck/Obsid.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/starcheck/src/lib/Ska/Starcheck/Obsid.pm b/starcheck/src/lib/Ska/Starcheck/Obsid.pm index 348b367c..3bb32acb 100644 --- a/starcheck/src/lib/Ska/Starcheck/Obsid.pm +++ b/starcheck/src/lib/Ska/Starcheck/Obsid.pm @@ -2889,7 +2889,7 @@ sub set_dynamic_mag_limits{ return unless ($c = $self->find_command("MP_STARCAT")); my $date = $c->{date}; - my $t_ccd = $self->{ccd_temp}; + my $t_ccd = $self->{ccd_temp_acq}; # Dynamic mag limits based on 75% and 50% chance of successful star acq # Maximum limits of 10.3 and 10.6 $self->{mag_faint_yellow} = min(10.3, _mag_for_p_acq(0.75, $date, $t_ccd)); From 788a673be6318719a1e041d75f09cfef4eb4ba35 Mon Sep 17 00:00:00 2001 From: Jean Connelly Date: Mon, 14 Jan 2019 16:57:48 -0500 Subject: [PATCH 15/23] Remove if statement setting acq temperature --- starcheck/calc_ccd_temps.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/starcheck/calc_ccd_temps.py b/starcheck/calc_ccd_temps.py index c10cbbb5..bd7efbbe 100755 --- a/starcheck/calc_ccd_temps.py +++ b/starcheck/calc_ccd_temps.py @@ -210,7 +210,7 @@ def get_interval_data(intervals, times, ccd_temp, obsreqs=None): obstemps[str(interval['obsid'])] = obs continue obs['ccd_temp'] = np.max(ok_temps) - obs['ccd_temp_acq'] = np.max(ok_temps[0:2]) if len(ok_temps) > 1 else obs['ccd_temp'] + obs['ccd_temp_acq'] = np.max(ok_temps[:2]) obs['n100_warm_frac'] = dark_model.get_warm_fracs( 100, interval['tstart'], np.max(ok_temps)) # If we have an OR list, the obsid is in that list, and the OR list has zero-offset keys From 44fc15e39adbda21b1e98aa8eff7aff72caa3328 Mon Sep 17 00:00:00 2001 From: Jean Connelly Date: Tue, 15 Jan 2019 08:29:33 -0500 Subject: [PATCH 16/23] Remove halfwidth clipping and update comments and warning --- starcheck/src/lib/Ska/Starcheck/Obsid.pm | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/starcheck/src/lib/Ska/Starcheck/Obsid.pm b/starcheck/src/lib/Ska/Starcheck/Obsid.pm index 3bb32acb..24b88196 100644 --- a/starcheck/src/lib/Ska/Starcheck/Obsid.pm +++ b/starcheck/src/lib/Ska/Starcheck/Obsid.pm @@ -2775,18 +2775,15 @@ sub proseco_args{ next IDX; } $sid = int($sid); - # While assigning ACQ stars into a list, clip to allowed ranges and warn as needed. + # While assigning ACQ stars into a list, warn if outside the 60 to 180 range used by proseco + # and the grid acq model. if ($cat_cmd->{"TYPE$i"} =~ /BOT|ACQ/){ push @acq_ids, $sid;; my $hw = $cat_cmd->{"HALFW$i"}; if (($hw > 180) or ($hw < 60)){ - push @{$self->{yellow_warn}}, sprintf( - ">> WARNING: [%2d] Halfwidth %d outside range 60 to 180. Clipped for probs.", + push @{$self->{orange_warn}}, sprintf( + ">> WARNING: [%2d] Halfwidth %d outside range 60 to 180. Will be clipped in proseco probs.\n", $i, $hw); - # Clip hw if outside the range 60 to 180 for probabilities - $hw = $hw < 60 ? 60 - : $hw > 180 ? 180 - : $hw ; } push @halfwidths, $hw; push @acq_indexes, $i; From b4656b1fae819cdfed64539f5d47013c3684b04b Mon Sep 17 00:00:00 2001 From: Jean Connelly Date: Tue, 15 Jan 2019 08:33:21 -0500 Subject: [PATCH 17/23] Add newline at end of acq ccd clip warn. --- starcheck/src/lib/Ska/Starcheck/Obsid.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/starcheck/src/lib/Ska/Starcheck/Obsid.pm b/starcheck/src/lib/Ska/Starcheck/Obsid.pm index 24b88196..94c9fda3 100644 --- a/starcheck/src/lib/Ska/Starcheck/Obsid.pm +++ b/starcheck/src/lib/Ska/Starcheck/Obsid.pm @@ -2678,7 +2678,7 @@ sub set_ccd_temps{ } if (($self->{ccd_temp_acq} > -1.0) or ($self->{ccd_temp_acq} < -16.0)){ push @{$self->{yellow_warn}}, sprintf( - ">> WARNING: acq t_ccd %.2f outside range -16.0 to -1.0. Clipped.", + ">> WARNING: acq t_ccd %.2f outside range -16.0 to -1.0. Clipped.\n", $self->{ccd_temp_acq}); $self->{ccd_temp_acq} = $self->{ccd_temp_acq} > -1.0 ? -1.0 : $self->{ccd_temp_acq} < -16.0 ? -16.0 From cc897a1ae976a1bc6e79071b83ca392f840197f7 Mon Sep 17 00:00:00 2001 From: Jean Connelly Date: Tue, 15 Jan 2019 09:41:54 -0500 Subject: [PATCH 18/23] Set to be the right value for P2 and use P2 consistently --- starcheck/src/lib/Ska/Starcheck/Obsid.pm | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/starcheck/src/lib/Ska/Starcheck/Obsid.pm b/starcheck/src/lib/Ska/Starcheck/Obsid.pm index 94c9fda3..c44373ff 100644 --- a/starcheck/src/lib/Ska/Starcheck/Obsid.pm +++ b/starcheck/src/lib/Ska/Starcheck/Obsid.pm @@ -2183,8 +2183,8 @@ sub print_report { if (exists $self->{figure_of_merit}) { my $bad_FOM = $self->{figure_of_merit}->{cum_prob_bad}; $o .= "$red_font_start" if $bad_FOM; - $o .= "Probability of acquiring 2 or fewer stars (10^x):\t"; - $o .= substr(sprintf("%.4f", $self->{figure_of_merit}->{cum_prob_2}), 0, 6) . "\t"; + $o .= "Probability of acquiring 2 or fewer stars (10^-x):\t"; + $o .= substr(sprintf("%.4f", $self->{figure_of_merit}->{P2}), 0, 6) . "\t"; $o .= "$font_stop" if $bad_FOM; $o .= "\n"; $o .= sprintf("Acquisition Stars Expected : %.2f\n", @@ -2725,7 +2725,7 @@ def proseco_probs(kwargs): # Assign the proseco probabilities back into an array. p_acqs = [float(acq_cat['p_acq'][acq_cat['id'] == acq][0]) for acq in kw['acqs']] - return p_acqs, float(acq_cat.get_log_p_2_or_fewer()), float(np.sum(p_acqs)) + return p_acqs, float(-np.log10(acq_cat.calc_p_safe())), float(np.sum(p_acqs)) }; @@ -2838,7 +2838,7 @@ sub set_proseco_probs{ if (not %{$args}){ return; } - my ($p_acqs, $two_or_fewer, $expected) = proseco_probs($args); + my ($p_acqs, $P2, $expected) = proseco_probs($args); my @acq_indexes = @{$args->{acq_indexes}}; @@ -2851,13 +2851,13 @@ sub set_proseco_probs{ } $self->{acq_probs} = \%slot_probs; - # Set the P2 to be 2.0 (aka 0.01) - my $cum_prob_limit = 0.01; + # Set the P2 requirement to be 2.0 + my $P2_required = 2.0; $self->{figure_of_merit} = {expected => substr($expected, 0, 4), - cum_prob_2 => $two_or_fewer, - cum_prob_bad => ($two_or_fewer > $cum_prob_limit)}; - if ($two_or_fewer > $cum_prob_limit){ - push @{$self->{warn}}, ">> WARNING: Probability of 2 or fewer stars > $cum_prob_limit\n"; + P2 => $P2, + cum_prob_bad => ($P2 < $P2_required)}; + if ($P2 < $P2_required){ + push @{$self->{warn}}, ">> WARNING: -log10 probability of 2 or fewer stars < $P2_required\n"; } } From 33bd6e49df49f9804a9d415f76baf4b839b51bdd Mon Sep 17 00:00:00 2001 From: Jean Connelly Date: Tue, 15 Jan 2019 09:50:53 -0500 Subject: [PATCH 19/23] Use less ambiguous keys in the proseco arg hash --- starcheck/src/lib/Ska/Starcheck/Obsid.pm | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/starcheck/src/lib/Ska/Starcheck/Obsid.pm b/starcheck/src/lib/Ska/Starcheck/Obsid.pm index c44373ff..b4aa7e05 100644 --- a/starcheck/src/lib/Ska/Starcheck/Obsid.pm +++ b/starcheck/src/lib/Ska/Starcheck/Obsid.pm @@ -2701,7 +2701,7 @@ def proseco_probs(kwargs): 'q1', 'q2', 'q3', 'q4' = the target quaternion 'man_angle' the maneuver angle to the target quaternion in degrees. - 'acqs' list of acq star ids + 'acq_ids' list of acq star ids 'halfwidths' list of acq star halfwidths in arcsecs 't_ccd_acq' acquisition temperature in deg C 'date' observation date (in Chandra.Time compatible format) @@ -2717,13 +2717,13 @@ def proseco_probs(kwargs): kw = de_bytestr(kwargs) acq_cat = get_acq_catalog(obsid=0, att=Quaternion.normalize([kw['q1'], kw['q2'], kw['q3'], kw['q4']]), - n_acq=len(kw['acqs']), man_angle=kw['man_angle'], t_ccd=kw['t_ccd_acq'], + n_acq=len(kw['acq_ids']), man_angle=kw['man_angle'], t_ccd=kw['t_ccd_acq'], date=kw['date'], dither=(kw['dither_acq_y'], kw['dither_acq_z']), detector=kw['detector'], sim_offset=kw['offset'], - include_ids=kw['acqs'], include_halfws=kw['halfwidths']) + include_ids=kw['acq_ids'], include_halfws=kw['halfwidths']) # Assign the proseco probabilities back into an array. - p_acqs = [float(acq_cat['p_acq'][acq_cat['id'] == acq][0]) for acq in kw['acqs']] + p_acqs = [float(acq_cat['p_acq'][acq_cat['id'] == acq_id][0]) for acq_id in kw['acq_ids']] return p_acqs, float(-np.log10(acq_cat.calc_p_safe())), float(np.sum(p_acqs)) }; @@ -2761,7 +2761,7 @@ sub proseco_args{ my @gui_ids; my @fid_ids; my @halfwidths; - # Loop over the star catalog and assign the acqs, guide stars, and fids to arrays. + # Loop over the star catalog and assign the acq stars, guide stars, and fids to arrays. IDX: foreach my $i (1..16) { (my $sid = $cat_cmd->{"GS_ID$i"}) =~ s/[\s\*]//g; @@ -2798,7 +2798,8 @@ sub proseco_args{ # Build a hash of the arguments that could be used by proseco (get_aca_catalog or get_acq_catalog). # Zeros are added to most of the numeric parameters as that seems to help "cast" them to floats or ints in - # Perl to some extent. + # Perl to some extent. Also save the acquisition star catalog indexes to make it easier to assign back + # the probabilities without having to search again on the Perl side by agasc id. %proseco_args = ( obsid => $self->{obsid}, date => $targ_cmd->{stop_date}, @@ -2811,10 +2812,10 @@ sub proseco_args{ dither_guide_z => $self->{dither_guide}->{ampl_p}, t_ccd_acq => $self->{ccd_temp_acq}, t_ccd_guide => $self->{ccd_temp}, - acqs => \@acq_ids, + acq_ids => \@acq_ids, halfwidths => \@halfwidths, - fids => \@fid_ids, - guides => \@gui_ids, + fid_ids => \@fid_ids, + guide_ids => \@gui_ids, acq_indexes => \@acq_indexes); return \%proseco_args From 473a313644abd6636a194134f99de4d7908fb47c Mon Sep 17 00:00:00 2001 From: Jean Connelly Date: Tue, 15 Jan 2019 09:54:36 -0500 Subject: [PATCH 20/23] Add comment to temperature clipping --- starcheck/src/lib/Ska/Starcheck/Obsid.pm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/starcheck/src/lib/Ska/Starcheck/Obsid.pm b/starcheck/src/lib/Ska/Starcheck/Obsid.pm index b4aa7e05..c2609566 100644 --- a/starcheck/src/lib/Ska/Starcheck/Obsid.pm +++ b/starcheck/src/lib/Ska/Starcheck/Obsid.pm @@ -2676,6 +2676,8 @@ sub set_ccd_temps{ push @{$self->{fyi}}, sprintf("$info CCD temperature exceeds %.1f C\n", $config{ccd_temp_red_limit}); } + # Clip the acq ccd temperature to the calibrated range of the grid acq probability model + # and add a yellow warning to let the user know this has happened. if (($self->{ccd_temp_acq} > -1.0) or ($self->{ccd_temp_acq} < -16.0)){ push @{$self->{yellow_warn}}, sprintf( ">> WARNING: acq t_ccd %.2f outside range -16.0 to -1.0. Clipped.\n", From 78e19bddc408b4dc8a7e7a310417dec9304168be Mon Sep 17 00:00:00 2001 From: Jean Connelly Date: Tue, 15 Jan 2019 09:58:48 -0500 Subject: [PATCH 21/23] Use ternary to set SI and SIM_OFFSET_Z for proseco --- starcheck/src/lib/Ska/Starcheck/Obsid.pm | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/starcheck/src/lib/Ska/Starcheck/Obsid.pm b/starcheck/src/lib/Ska/Starcheck/Obsid.pm index c2609566..44419c8f 100644 --- a/starcheck/src/lib/Ska/Starcheck/Obsid.pm +++ b/starcheck/src/lib/Ska/Starcheck/Obsid.pm @@ -2750,13 +2750,10 @@ sub proseco_args{ if ((not $targ_cmd) or (not $cat_cmd) or ($self->{obsid} =~ /NONE(\d+)/)){ return \%proseco_args; } - # Use a default SI (which should only be used for ERs and should have no effect without fid lights) - my $si = 'ACIS-S'; - my $offset = 0; - if ($self->{obsid} < 38000){ - $si = $self->{SI}; - $offset = $self->{SIM_OFFSET_Z}; - } + # Use a default SI and offset for ERs (no effect without fid lights) + my $is_OR = $self->{obsid} < $ER_MIN_OBSID; + my $si = $is_OR ? $self->{SI} : 'ACIS-S'; + my $offset = $is_OR ? $self->{SIM_OFFSET_Z} : 0; my @acq_ids; my @acq_indexes; From 945fa198e5c43d337d1a475743d1a96f1be2f8ca Mon Sep 17 00:00:00 2001 From: Jean Connelly Date: Wed, 16 Jan 2019 21:00:45 -0500 Subject: [PATCH 22/23] Set more conservative P2 of 3.0 for ERs and to use as yellow-warn for ORs --- starcheck/src/lib/Ska/Starcheck/Obsid.pm | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/starcheck/src/lib/Ska/Starcheck/Obsid.pm b/starcheck/src/lib/Ska/Starcheck/Obsid.pm index 44419c8f..39b979d9 100644 --- a/starcheck/src/lib/Ska/Starcheck/Obsid.pm +++ b/starcheck/src/lib/Ska/Starcheck/Obsid.pm @@ -2851,14 +2851,20 @@ sub set_proseco_probs{ } $self->{acq_probs} = \%slot_probs; - # Set the P2 requirement to be 2.0 - my $P2_required = 2.0; + # Set the P2 requirement to be 2.0 for ORs and 3.0 for ERs. + my $P2_required = $self->{obsid} < $ER_MIN_OBSID ? 2.0 : 3.0; $self->{figure_of_merit} = {expected => substr($expected, 0, 4), P2 => $P2, cum_prob_bad => ($P2 < $P2_required)}; if ($P2 < $P2_required){ push @{$self->{warn}}, ">> WARNING: -log10 probability of 2 or fewer stars < $P2_required\n"; } + # If OR and P2 less than 3.0, yellow_warn. This probably doesn't need the check on OR/ER + # because if it is an ER and < 3.0 the if statement above was hit. + elsif (($self->{obsid} < $ER_MIN_OBSID) and ($P2 < 3.0)){ + push @{$self->{yellow_warn}}, ">> WARNING: -log10 probability of 2 or fewer stars < 3.0\n"; + } + } From 4e289bf4d16f677e2e016e5b321acc411f3754e0 Mon Sep 17 00:00:00 2001 From: Tom Aldcroft Date: Thu, 17 Jan 2019 06:51:51 -0500 Subject: [PATCH 23/23] Make a consistent P2_yellow which is P2_red + 1.0 --- starcheck/src/lib/Ska/Starcheck/Obsid.pm | 32 ++++++++++++++++-------- starcheck/src/starcheck.pl | 2 +- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/starcheck/src/lib/Ska/Starcheck/Obsid.pm b/starcheck/src/lib/Ska/Starcheck/Obsid.pm index 39b979d9..f6f40427 100644 --- a/starcheck/src/lib/Ska/Starcheck/Obsid.pm +++ b/starcheck/src/lib/Ska/Starcheck/Obsid.pm @@ -2823,7 +2823,7 @@ sub proseco_args{ ################################################################################### -sub set_proseco_probs{ +sub set_proseco_probs_and_check_P2{ ################################################################################### # For observations with a star catalog and which have valid parameters already determined # in $self->{proseco_args}, call the Python proseco_probs method to calculate the @@ -2851,18 +2851,28 @@ sub set_proseco_probs{ } $self->{acq_probs} = \%slot_probs; - # Set the P2 requirement to be 2.0 for ORs and 3.0 for ERs. - my $P2_required = $self->{obsid} < $ER_MIN_OBSID ? 2.0 : 3.0; + # Red and yellow warnings on acquisition safing probability. + + # Set the P2 requirement to be 2.0 for ORs and 3.0 for ERs. The higher limit for ER + # reflects a desire to minimize integrated mission risk for observations where the + # attitude can be selected freely. Yellow warning for marginal catalog is set to a + # factor of 10 less risk than the red limit P2 probability for OR / ER respectively). + my $P2_red = $self->{obsid} < $ER_MIN_OBSID ? 2.0 : 3.0; + my $P2_yellow = $P2_red + 1.0; + + # Create a structure that gets used for report generation only. $self->{figure_of_merit} = {expected => substr($expected, 0, 4), P2 => $P2, - cum_prob_bad => ($P2 < $P2_required)}; - if ($P2 < $P2_required){ - push @{$self->{warn}}, ">> WARNING: -log10 probability of 2 or fewer stars < $P2_required\n"; - } - # If OR and P2 less than 3.0, yellow_warn. This probably doesn't need the check on OR/ER - # because if it is an ER and < 3.0 the if statement above was hit. - elsif (($self->{obsid} < $ER_MIN_OBSID) and ($P2 < 3.0)){ - push @{$self->{yellow_warn}}, ">> WARNING: -log10 probability of 2 or fewer stars < 3.0\n"; + cum_prob_bad => ($P2 < $P2_red)}; + + # Do the actual checks + if ($P2 < $P2_red){ + push @{$self->{warn}}, + ">> WARNING: -log10 probability of 2 or fewer stars < $P2_red\n"; + } + elsif ($P2 < $P2_yellow){ + push @{$self->{yellow_warn}}, + ">> WARNING: -log10 probability of 2 or fewer stars < $P2_yellow\n"; } } diff --git a/starcheck/src/starcheck.pl b/starcheck/src/starcheck.pl index 1caf3a3a..b5bd9ce6 100755 --- a/starcheck/src/starcheck.pl +++ b/starcheck/src/starcheck.pl @@ -637,7 +637,7 @@ sub json_obsids{ $obs{$obsid}->check_dither($dither); # Get the args that proseco would want $obs{$obsid}->{'proseco_args'} = $obs{$obsid}->proseco_args(); - $obs{$obsid}->set_proseco_probs(); + $obs{$obsid}->set_proseco_probs_and_check_P2(); $obs{$obsid}->check_star_catalog($or{$obsid}, $par{vehicle}); $obs{$obsid}->check_sim_position(@sim_trans) unless $par{vehicle}; $obs{$obsid}->check_momentum_unload(\@bs);