Skip to content
Draft
75 changes: 71 additions & 4 deletions starcheck/src/lib/Ska/Starcheck/Obsid.pm
Original file line number Diff line number Diff line change
Expand Up @@ -310,18 +310,37 @@ sub set_maneuver {
##################################################################################
my $self = shift;
my $mm = shift;
my $ps = shift;
my $n = 1;
my $c;
my $found;

my $dot_obsid = $self->{dot_obsid};
# If date before "2020", get the ER obsids from the processing summary
# If the $dot_obsid does not begin with a number
if ($dot_obsid !~ /^\d/ && ($self->{date} lt '2020:001:00:00:00.000')) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where did this date come from?

# The processing summary has lines that look like this
# 'P080200 CAL 2017:013:03:00:49.827 2017:013:03:00:59.827 000:00:00:10.000 OBSID = 50385 {Perigee Attitude}
# For each line like that, I want to extract the obsid as the up to 5 digit number after OBSID and I
# want to extract the "dot_obsid" as the first 5 characters of the line (P0802 in this case)
foreach my $ps_line (@$ps) {
if ($ps_line =~ /^\s*(\S{5}).*OBSID\s*=\s*(\d{1,5})/) {
if ($1 eq $dot_obsid) {
$dot_obsid = $2;
last;
}
}
}
}

while ($c = find_command($self, "MP_TARGQUAT", $n++)) {
$found = 0;
foreach my $m (@{$mm}) {
my $manvr_obsid = $m->{final_obsid};

# where manvr_dest is either the final_obsid of a maneuver or the eventual destination obsid
# of a segmented maneuver
if ( ($manvr_obsid eq $self->{dot_obsid})
if ( ($manvr_obsid eq $dot_obsid)
&& abs($m->{q1} - $c->{Q1}) < 1e-7
&& abs($m->{q2} - $c->{Q2}) < 1e-7
&& abs($m->{q3} - $c->{Q3}) < 1e-7)
Expand Down Expand Up @@ -383,6 +402,11 @@ sub set_maneuver {
sprintf("Did not find match in maneuvers for MP_TARGQUAT at $c->{date}\n")
unless ($found);

unless ($found) {
# throw error and quit
exit(1);
}

}
}

Expand Down Expand Up @@ -1029,6 +1053,49 @@ sub check_for_srdcs {
}
}

#############################################################################################
sub check_planets{
#############################################################################################
my $self = shift;
my $c = find_command($self, 'MP_STARCAT');
$self->{planet_full_mitigation} = 0;
my $bright_data = call_python("utils.run_sparkles_planet_checks",
[ $self->{'proseco_args'} ]);

if (exists $bright_data->{planet_full_mitigation}) {
$self->{planet_full_mitigation} = $bright_data->{planet_full_mitigation} ? 1 : 0;
}

for my $warn_type (qw(warn fyi orange_warn yellow_warn)) {
if (exists $bright_data->{$warn_type}) {
for my $warn (@{ $bright_data->{$warn_type} }) {
# If the warning has an idx in it and an id, update the text to match the starcheck
# version of the catalog
if ($warn =~ /idx (\d+) id (\d+)/) {
my $idx = $1;
my $star_id = '---';
if (defined $c) {
for my $i (1 .. 16) {
if ($c->{"TYPE$i"} ne 'NUL') {
$idx--;
if ($idx == 0) {
$star_id = $c->{"GS_ID$i"} if (defined $c->{"GS_ID$i"});
last;
}
}
}
$star_id = $c->{"GS_ID$idx"} if (defined $c->{"GS_ID$idx"});
}
$warn =~ s/IDX=$idx/STAR_ID=$star_id/;
}

push @{ $self->{$warn_type} }, "$warn\n";
}
}
}
}


#############################################################################################
sub check_sim_position {
#############################################################################################
Expand Down Expand Up @@ -1109,7 +1176,7 @@ sub check_star_catalog {
my $is_er = ($self->{obsid} =~ /^\d+$/ && $self->{obsid} >= $ER_MIN_OBSID);
my $min_guide = $is_science ? 5 : 6; # Minimum number of each object type
my $min_acq = $is_science ? 4 : 5;
my $min_fid = 3;
my $min_fid = ($self->{planet_full_mitigation}) ? 2 : 3;
########################################################################

my @warn = ();
Expand Down Expand Up @@ -1157,7 +1224,6 @@ sub check_star_catalog {

# Global checks on star/fid numbers
# ACA-005 ACA-006 ACA-007 ACA-008 ACA-044

push @warn, "Too Few Fid Lights\n" if (@{ $self->{fid} } < $min_fid && $is_science);
push @warn, "Too Many Fid Lights\n"
if ( (@{ $self->{fid} } > 0 && $is_er)
Expand Down Expand Up @@ -3120,6 +3186,8 @@ sub proseco_args {
%proseco_args = (
obsid => $self->{obsid},
date => $targ_cmd->{stop_date},
duration => $self->{obs_tstop} - $self->{obs_tstart},
target_name => ($self->{TARGET_NAME}) ? $self->{TARGET_NAME} : $self->{SS_OBJECT},
att => [
0 + $targ_cmd->{q1},
0 + $targ_cmd->{q2},
Expand All @@ -3143,7 +3211,6 @@ sub proseco_args {
n_fid => scalar(@fid_ids),
acq_indexes => \@acq_indexes
);

return \%proseco_args;

}
Expand Down
8 changes: 7 additions & 1 deletion starcheck/src/starcheck.pl
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
'run_start_time=s',
'maude!',
'max_obsids:i',
'save_pkl=s',
) || exit(1);

usage(1)
Expand Down Expand Up @@ -437,7 +438,7 @@
$obs{$obsid}->set_obsid(\%guidesumm); # Commanded obsid
$obs{$obsid}->set_target();
$obs{$obsid}->set_star_catalog();
$obs{$obsid}->set_maneuver($mm);
$obs{$obsid}->set_maneuver($mm, \@ps);
$obs{$obsid}->set_files(
$STARCHECK,
$backstop,
Expand Down Expand Up @@ -642,6 +643,7 @@ sub json_obsids {
# Get the args that proseco would want
$obs{$obsid}->{'proseco_args'} = $obs{$obsid}->proseco_args();
$obs{$obsid}->set_proseco_probs_and_check_P2();
$obs{$obsid}->check_planets();
$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);
Expand All @@ -650,6 +652,10 @@ sub json_obsids {
$obs{$obsid}->check_for_srdcs(\@bs);
}

if ($par{save_pkl}) {
call_python("utils.save_proseco_catalogs", [ $par{save_pkl} ]);
}

# 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));
Expand Down
76 changes: 76 additions & 0 deletions starcheck/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -584,3 +584,79 @@ def vehicle_filter_backstop(backstop_file, outfile):
]
# Write the filtered commands to the output file
write_backstop(filtered_cmds, outfile)


def get_proseco_catalog(**kw):
# Note that the fid ids in starcheck are 1-6
# ACIS, 7-10 HRC-I 11-14 HRC-S. Proseco just uses indexes 1-6 so
# subtract off the offsets.
fid_ids = np.array(kw["fid_ids"])
if kw["detector"] == "HRC-I":
fid_offset = 6
elif kw["detector"] == "HRC-S":
fid_offset = 10
else:
fid_offset = 0
fid_ids -= fid_offset

args = {
"obsid": int(kw["obsid"]),
"att": Quaternion.normalize(kw["att"]),
"duration": kw["duration"],
"target_name": kw["target_name"],
"date": kw["date"],
"n_acq": kw["n_acq"],
"n_guide": kw["n_guide"],
"man_angle": kw["man_angle"],
"t_ccd_acq": kw["t_ccd_acq"],
"t_ccd_guide": kw["t_ccd_guide"],
"dither_acq": ACABox(kw["dither_acq"]),
"dither_guide": ACABox(kw["dither_guide"]),
"include_ids_acq": kw["include_ids_acq"],
"include_halfws_acq": kw["include_halfws_acq"],
"detector": kw["detector"],
"sim_offset": kw["sim_offset"],
"include_ids_guide": kw["include_ids_guide"],
"include_ids_fid": list(fid_ids),
"n_fid": len(kw["fid_ids"]),
"focus_offset": 0,
}
if "monitors" in kw:
args["monitors"] = kw["monitors"]
aca = get_aca_catalog(**args)
return aca


# Module-level accumulator for proseco catalogs; populated by get_and_collect_proseco_catalog.
_proseco_catalogs = {}


def get_and_collect_proseco_catalog(proseco_args):
"""Build a proseco catalog, accumulate it by obsid, and return it."""
aca = get_proseco_catalog(**proseco_args)
_proseco_catalogs[proseco_args["obsid"]] = aca
return aca


def run_sparkles_planet_checks(proseco_args):
from sparkles.checks import get_planet_check_data
from sparkles.messages import MessagesList

aca = get_and_collect_proseco_catalog(proseco_args)
acar = aca.get_review_table()
planet_check_data = get_planet_check_data(acar)
msgs = MessagesList(planet_check_data["messages"])
return {
"warn": [w["text"] for w in msgs == "critical"],
"orange_warn": [w["text"] for w in msgs == "caution"],
"yellow_warn": [w["text"] for w in msgs == "warning"],
"fyi": [w["text"] for w in msgs == "info"],
"planet_full_mitigation": planet_check_data["planet_full_mitigation"],
}


def save_proseco_catalogs(path):
import pickle

with open(path, "wb") as f:
pickle.dump(_proseco_catalogs, f)
Loading