000: Error running Python from Perl [code]

id 000
title Error running Python from Perl
file starcheck/src/starcheck.pl:66
type code
severity error
aca_cl_id
note
orvdot

import os
from chandra_aca.star_probs import set_acq_model_ms_filter
import starcheck
from starcheck.pcad_att_check import make_pcad_attitude_check_report, check_characteristics_date
from starcheck.calc_ccd_temps import get_ccd_temps
from starcheck.version import version

def ccd_temp_wrapper(kwargs):
    return get_ccd_temps(**kwargs)

def plot_cat_wrapper(kwargs):
    try:
        from starcheck.plot import make_plots_for_obsid
    except ImportError as err:
        # write errors to starcheck's global warnings and STDERR
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        perl.warning("Error with Inline::Python imports {}\n".format(err))
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    return make_plots_for_obsid(**kwargs)

def starcheck_version():
    return version

def get_data_dir():
    sc_data = os.path.join(os.path.dirname(starcheck.__file__), 'data')
    return sc_data if os.path.exists(sc_data) else ""

};

001: Put out errors recorded before creation of warning function [code]

id 001
title Put out errors recorded before creation of warning function
file starcheck/src/starcheck.pl:289
type code
severity
aca_cl_id
note
orvdot

my @ps = Ska::Parse_CM_File::PS($ps_file) if ($ps_file);

# Read mech check file and parse
my @mc  = Ska::Parse_CM_File::mechcheck($mech_file) if ($mech_file);

# Read SOE file and parse
my %soe  = Ska::Parse_CM_File::SOE($soe_file) if ($soe_file);

# Read OR file and integrate into %obs
my %or = Ska::Parse_CM_File::OR($or_file) if ($or_file);

# Read FIDSEL (fid light) history file and ODB (for fid
# characteristics) and parse; use fid_time_violation later (when global_warn set up

my ($fid_time_violation, $error, $fidsel) = Ska::Parse_CM_File::fidsel($fidsel_file, \@bs) ;
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
map { warning("$_\n") } @{$error};
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX


# do a tiny AGASC search to see which method will be used
my $tiny_agasc_search = Ska::AGASC->new({ra=>0,dec=>0,w=>0.001});
my $agasc_method = $Ska::AGASC::access_method;
if ($agasc_method =~ /cfitsio/){
    warning("Ska::AGASC call to mp_get_agasc failed.  Output not approved for authoritative load review. \n");
}

## Warn if we are on Solaris

002: Could not find/run mp_get_agasc [process]

id 002
title Could not find/run mp_get_agasc
file starcheck/src/starcheck.pl:296
type process
severity red
aca_cl_id
note
orvdot


# Read OR file and integrate into %obs
my %or = Ska::Parse_CM_File::OR($or_file) if ($or_file);

# Read FIDSEL (fid light) history file and ODB (for fid
# characteristics) and parse; use fid_time_violation later (when global_warn set up

my ($fid_time_violation, $error, $fidsel) = Ska::Parse_CM_File::fidsel($fidsel_file, \@bs) ;
map { warning("$_\n") } @{$error};


# do a tiny AGASC search to see which method will be used
my $tiny_agasc_search = Ska::AGASC->new({ra=>0,dec=>0,w=>0.001});
my $agasc_method = $Ska::AGASC::access_method;
if ($agasc_method =~ /cfitsio/){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    warning("Ska::AGASC call to mp_get_agasc failed.  Output not approved for authoritative load review. \n");
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
}

## Warn if we are on Solaris
if ($OS eq 'SunOS'){
    warning("uname == SunOS; starcheck is only approved on Linux \n");
}


# See if we have database access
my $db_handle;

003: Do not run on SunOS [process]

id 003
title Do not run on SunOS
file starcheck/src/starcheck.pl:301
type process
severity red
aca_cl_id
note
orvdot

# characteristics) and parse; use fid_time_violation later (when global_warn set up

my ($fid_time_violation, $error, $fidsel) = Ska::Parse_CM_File::fidsel($fidsel_file, \@bs) ;
map { warning("$_\n") } @{$error};


# do a tiny AGASC search to see which method will be used
my $tiny_agasc_search = Ska::AGASC->new({ra=>0,dec=>0,w=>0.001});
my $agasc_method = $Ska::AGASC::access_method;
if ($agasc_method =~ /cfitsio/){
    warning("Ska::AGASC call to mp_get_agasc failed.  Output not approved for authoritative load review. \n");
}

## Warn if we are on Solaris
if ($OS eq 'SunOS'){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    warning("uname == SunOS; starcheck is only approved on Linux \n");
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
}


# See if we have database access
my $db_handle;
eval{
    eval 'use Ska::DatabaseUtil';
    $db_handle = Ska::DatabaseUtil::sql_connect( 'sybase-aca-aca_read' );

};

004: Could not read from Sybase database [process]

id 004
title Could not read from Sybase database
file starcheck/src/starcheck.pl:313
type process
severity red
aca_cl_id
note
orvdot


## Warn if we are on Solaris
if ($OS eq 'SunOS'){
    warning("uname == SunOS; starcheck is only approved on Linux \n");
}


# See if we have database access
my $db_handle;
eval{
    eval 'use Ska::DatabaseUtil';
    $db_handle = Ska::DatabaseUtil::sql_connect( 'sybase-aca-aca_read' );

};
if (($@) or (not defined $db_handle)){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    warning("Unable to connect to Sybase server; links generated for all AGASC ids by default \n");
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
}
else{
    Ska::Starcheck::Obsid::set_db_handle($db_handle);
  }

# Dark Cal Checker Section
use Ska::Starcheck::Dark_Cal_Checker;
my $dark_cal_checker;
eval{
    $dark_cal_checker = Ska::Starcheck::Dark_Cal_Checker->new({ dir => $par{dir},

005: Dark Cal Checker Failed [process]

id 005
title Dark Cal Checker Failed
file starcheck/src/starcheck.pl:328
type process
severity red
aca_cl_id
note
orvdot

    warning("Unable to connect to Sybase server; links generated for all AGASC ids by default \n");
}
else{
    Ska::Starcheck::Obsid::set_db_handle($db_handle);
  }

# Dark Cal Checker Section
use Ska::Starcheck::Dark_Cal_Checker;
my $dark_cal_checker;
eval{
    $dark_cal_checker = Ska::Starcheck::Dark_Cal_Checker->new({ dir => $par{dir},
                                                                app_data => $Starcheck_Data});
};
if ($@){
    unless ($@ =~ /No ACA commanding found/){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        warning("Dark Cal Checker Failed $@ \n");
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    }
}



# Now that global_warn exists, if the DOT wasn't made/modified by SAUSAGE
# throw an error
if ($dot_touched_by_sausage == 0 ){
    warning("DOT file not modified by SAUSAGE! \n");
}

006: DOT file not modified by SAUSAGE [process]

id 006
title DOT file not modified by SAUSAGE
file starcheck/src/starcheck.pl:337
type process
severity red
aca_cl_id
note
orvdot

eval{
    $dark_cal_checker = Ska::Starcheck::Dark_Cal_Checker->new({ dir => $par{dir},
                                                                app_data => $Starcheck_Data});
};
if ($@){
    unless ($@ =~ /No ACA commanding found/){
        warning("Dark Cal Checker Failed $@ \n");
    }
}



# Now that global_warn exists, if the DOT wasn't made/modified by SAUSAGE
# throw an error
if ($dot_touched_by_sausage == 0 ){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    warning("DOT file not modified by SAUSAGE! \n");
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
}



Ska::Starcheck::Obsid::setcolors({ red => $red_font_start,
                   blue => $blue_font_start,
                   yellow => $yellow_font_start,
                   });

my %odb = Ska::Parse_CM_File::odb($odb_file);

007: Missing Maneuver Error file [process]

id 007
title Missing Maneuver Error file
file starcheck/src/starcheck.pl:361
type process
severity red
aca_cl_id
note
orvdot


my %odb = Ska::Parse_CM_File::odb($odb_file);
Ska::Starcheck::Obsid::set_odb(%odb);


Ska::Starcheck::Obsid::set_config($config_ref);

# Set the multple star filter disabled in the model if after this date
my $MSF_ENABLED = $bs[0]->{date} lt '2016:102:00:00:00.000';
set_acq_model_ms_filter($MSF_ENABLED);

# Read Maneuver error file containing more accurate maneuver errors
my @manerr;
if ($manerr_file) {
    @manerr = Ska::Parse_CM_File::man_err($manerr_file);
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
} else { warning("Could not find Maneuver Error file in output/ directory\n") };
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX

# Read DITHER history file and backstop to determine expected dither state
my ($dither_time_violation, $dither) = Ska::Parse_CM_File::dither($dither_file, \@bs);

my ($radmon_time_violation, $radmon) = Ska::Parse_CM_File::radmon($radmon_file, \@bs);

# if dither history runs into load
if ($dither_time_violation){
    warning("Dither History runs into load\n");
}

008: Dither History runs into load [process]

id 008
title Dither History runs into load
file starcheck/src/starcheck.pl:370
type process
severity red
aca_cl_id
note
orvdot Need a replan interrupt and a replan reopen to test history files.

set_acq_model_ms_filter($MSF_ENABLED);

# Read Maneuver error file containing more accurate maneuver errors
my @manerr;
if ($manerr_file) {
    @manerr = Ska::Parse_CM_File::man_err($manerr_file);
} else { warning("Could not find Maneuver Error file in output/ directory\n") };

# Read DITHER history file and backstop to determine expected dither state
my ($dither_time_violation, $dither) = Ska::Parse_CM_File::dither($dither_file, \@bs);

my ($radmon_time_violation, $radmon) = Ska::Parse_CM_File::radmon($radmon_file, \@bs);

# if dither history runs into load
if ($dither_time_violation){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    warning("Dither History runs into load\n");
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
}

# if radmon history runs into load
if ($radmon_time_violation){
  warning("Radmon History runs into load\n");
}

# if fidsel history runs into load
if ($fid_time_violation){
    warning("Fidsel History runs into load\n");

009: Radmon History runs into load [process]

id 009
title Radmon History runs into load
file starcheck/src/starcheck.pl:375
type process
severity red
aca_cl_id
note
orvdot Need a replan interrupt and a replan reopen to test history files.

    @manerr = Ska::Parse_CM_File::man_err($manerr_file);
} else { warning("Could not find Maneuver Error file in output/ directory\n") };

# Read DITHER history file and backstop to determine expected dither state
my ($dither_time_violation, $dither) = Ska::Parse_CM_File::dither($dither_file, \@bs);

my ($radmon_time_violation, $radmon) = Ska::Parse_CM_File::radmon($radmon_file, \@bs);

# if dither history runs into load
if ($dither_time_violation){
    warning("Dither History runs into load\n");
}

# if radmon history runs into load
if ($radmon_time_violation){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
  warning("Radmon History runs into load\n");
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
}

# if fidsel history runs into load
if ($fid_time_violation){
    warning("Fidsel History runs into load\n");
}


# Read in the failed acquisition stars
warning("Could not open ACA bad acquisition stars file $bad_acqs_file\n")

010: Fidsel History runs into load [process]

id 010
title Fidsel History runs into load
file starcheck/src/starcheck.pl:380
type process
severity red
aca_cl_id
note
orvdot Need a replan interrupt and a replan reopen to test history files.


my ($radmon_time_violation, $radmon) = Ska::Parse_CM_File::radmon($radmon_file, \@bs);

# if dither history runs into load
if ($dither_time_violation){
    warning("Dither History runs into load\n");
}

# if radmon history runs into load
if ($radmon_time_violation){
  warning("Radmon History runs into load\n");
}

# if fidsel history runs into load
if ($fid_time_violation){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    warning("Fidsel History runs into load\n");
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
}


# Read in the failed acquisition stars
warning("Could not open ACA bad acquisition stars file $bad_acqs_file\n")
    unless (Ska::Starcheck::Obsid::set_bad_acqs($bad_acqs_file));


# Read in the troublesome guide stars
warning("Could not open ACA bad guide star file $bad_gui_file\n")

011: OFLS ID in guide summary but not in DOT [process]

id 011
title OFLS ID in guide summary but not in DOT
file starcheck/src/starcheck.pl:477
type process
severity red
aca_cl_id
note
orvdot

# and the next obsid
for my $obsid_idx (0 .. ($#obsid_id)){
    $obs{$obsid_id[$obsid_idx]}->{prev} = ( $obsid_idx > 0 ) ? $obs{$obsid_id[$obsid_idx-1]} : undef;
    $obs{$obsid_id[$obsid_idx]}->{next} = ( $obsid_idx < $#obsid_id) ? $obs{$obsid_id[$obsid_idx+1]} : undef;
}

# Set the NPM times.  This requires the PREV/NEXT entries
foreach my $obsid (@obsid_id) {
    $obs{$obsid}->set_npm_times();
}

# Check that every Guide summary OFLS ID has a matching OFLS ID in DOT

foreach my $oflsid (keys %guidesumm){
    unless (defined $obs{$oflsid}){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    warning("OFLS ID $oflsid in Guide Summ but not in DOT! \n");
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    }
}

# Add guide_summary data to MP_STARCAT cmd for each obsid.

HAS_GUIDE:
foreach my $oflsid (@obsid_id){
    if (defined $guidesumm{$oflsid}){
        $obs{$oflsid}->add_guide_summ($oflsid, \%guidesumm);
    }

012: No guide summary (as expected) for SIR ER [process]

id 012
title No guide summary (as expected) for SIR ER
file starcheck/src/starcheck.pl:492
type process
severity info
aca_cl_id
note
orvdot No expected coverage due to removal of SIR concept (OK).

    warning("OFLS ID $oflsid in Guide Summ but not in DOT! \n");
    }
}

# Add guide_summary data to MP_STARCAT cmd for each obsid.

HAS_GUIDE:
foreach my $oflsid (@obsid_id){
    if (defined $guidesumm{$oflsid}){
        $obs{$oflsid}->add_guide_summ($oflsid, \%guidesumm);
    }
    else {
        my $obsid = $obs{$oflsid}->{obsid};
        if (defined $obs{$oflsid}->{ok_no_starcat}){
            my $ofls_string = $obs{$oflsid}->{ok_no_starcat};
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
            push @{$obs{$oflsid}->{fyi}},
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
            sprintf(">> INFO   : No Guide Star Summary for obsid $obsid ($oflsid). OK for '$ofls_string' ER. \n");
            next HAS_GUIDE;
        }
        push @{$obs{$oflsid}->{warn}}, sprintf(">> WARNING: No Guide Star Summary for obsid $obsid ($oflsid). \n");
    }

}

# Set up for SIM-Z checking
# Find SIMTSC continuity statement from mech check file

013: No Guide Summary for obsid [process]

id 013
title No Guide Summary for obsid
file starcheck/src/starcheck.pl:496
type process
severity red
aca_cl_id
note
orvdot

# Add guide_summary data to MP_STARCAT cmd for each obsid.

HAS_GUIDE:
foreach my $oflsid (@obsid_id){
    if (defined $guidesumm{$oflsid}){
        $obs{$oflsid}->add_guide_summ($oflsid, \%guidesumm);
    }
    else {
        my $obsid = $obs{$oflsid}->{obsid};
        if (defined $obs{$oflsid}->{ok_no_starcat}){
            my $ofls_string = $obs{$oflsid}->{ok_no_starcat};
            push @{$obs{$oflsid}->{fyi}},
            sprintf(">> INFO   : No Guide Star Summary for obsid $obsid ($oflsid). OK for '$ofls_string' ER. \n");
            next HAS_GUIDE;
        }
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @{$obs{$oflsid}->{warn}}, sprintf(">> WARNING: No Guide Star Summary for obsid $obsid ($oflsid). \n");
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    }

}

# Set up for SIM-Z checking
# Find SIMTSC continuity statement from mech check file
# and find SIMTRANS statements in backstop

my @sim_trans = ();
foreach my $mc (@mc) {

014: Error getting temperatures from get_ccd_temps [deprecated/removed process]

id 014
title Error getting temperatures from get_ccd_temps
file src/starcheck.pl:578
type deprecated/removed process
severity red
aca_cl_id
note
orvdot

my $json_text = json_obsids();
my $obsid_temps;
eval{
    my $json_obsid_temps;
    $json_obsid_temps = ccd_temp_wrapper({oflsdir=> $par{dir},
                                          outdir=>$STARCHECK,
                                          json_obsids => $json_text,
                                          model_spec => "$Starcheck_Data/aca_spec.json",
                                          char_file => "$Starcheck_Data/characteristics.yaml",
                                          orlist => $or_file,
                                      });
    # convert back from JSON outside
    $obsid_temps = JSON::from_json($json_obsid_temps);
};
if ($@){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @global_warn, "Error getting temperatures from get_ccd_temps\n";
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
}

if ($obsid_temps){
    foreach my $obsid (@obsid_id) {
        $obs{$obsid}->set_ccd_temps($obsid_temps);
        # put all the interval pieces in the main obsid structure
        if (defined $obsid_temps->{$obs{$obsid}->{obsid}}){
            $obs{$obsid}->{thermal} = $obsid_temps->{$obs{$obsid}->{obsid}};
        }
    }

015: Error Python plotting catalog [deprecated/removed code]

id 015
title Error Python plotting catalog
file src/starcheck.pl:611
type deprecated/removed code
severity error
aca_cl_id
note
orvdot

    my $cat = Ska::Starcheck::Obsid::find_command($obs{$obsid}, "MP_STARCAT");
    # If the catalog is empty, don't make plots
    if (defined $cat){
        my $cat_as_array = catalog_array($cat);
        my %plot_args = (obsid=>"$obs{$obsid}->{obsid}",
                         ra=>$obs{$obsid}->{ra},
                         dec=>$obs{$obsid}->{dec},
                         roll=>$obs{$obsid}->{roll},
                         catalog=>$cat_as_array,
                         starcat_time=>"$obs{$obsid}->{date}",
                         outdir=>$STARCHECK);
        eval{
            plot_cat_wrapper(\%plot_args);
        };
        if ($@){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
            push @global_warn, "Error Python plotting catalog\n";
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        }
        $obs{$obsid}->{plot_file} = "$STARCHECK/stars_$obs{$obsid}->{obsid}.png";
        $obs{$obsid}->{plot_field_file} = "$STARCHECK/star_view_$obs{$obsid}->{obsid}.png";
        $obs{$obsid}->{compass_file} = "$STARCHECK/compass$obs{$obsid}->{obsid}.png";
    }
    $obs{$obsid}->check_monitor_commanding(\@bs, $or{$obsid});
    $obs{$obsid}->check_flick_pix_mon();
    $obs{$obsid}->set_dynamic_mag_limits();
    $obs{$obsid}->check_dither($dither);
    $obs{$obsid}->check_star_catalog($or{$obsid}, $par{vehicle});

016: More than one star catalog assigned to obsid [process]

id 016
title More than one star catalog assigned to obsid
file starcheck/src/starcheck.pl:637
type process
severity red
aca_cl_id
note
orvdot

    $obs{$obsid}->check_flick_pix_mon();
    $obs{$obsid}->set_dynamic_mag_limits();
    $obs{$obsid}->check_dither($dither);
    $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);
    $obs{$obsid}->count_good_stars();
    # 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();
    }
    $obs{$obsid}->make_figure_of_merit();
# Make sure there is only one star catalog per obsid
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    warning ("More than one star catalog assigned to Obsid $obsid\n")
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    if ($obs{$obsid}->find_command('MP_STARCAT',2));
}

my $final_json = json_obsids();
open(my $JSON_OUT, "> $STARCHECK/obsids.json")
     or die "Couldn't open $STARCHECK/obsids.json for writing\n";
print $JSON_OUT $final_json;
close($JSON_OUT);

# Produce final report

017: Print all collected warnings to starcheck output [code]

id 017
title Print all collected warnings to starcheck output
file starcheck/src/starcheck.pl:705
type code
severity
aca_cl_id
note
orvdot

    $out .= "Using ACABadPixel file from $ACA_badpix_date Dark Cal \n";
    $save_hash{run}{badpix} = $ACA_badpix_date;
    }

    $out .= "Using acquisition model for multiple star filter "
        . ($MSF_ENABLED ? "enabled\n" : "disabled\n");

    $out .= "\n";
}

if (@global_warn) {
    $out .= "------------  PROCESSING WARNING  -----------------\n\n";
    $out .= $red_font_start;
    foreach (@global_warn) {
    $out .= $_;
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @{$save_hash{processing_warning}}, $_;
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    }
    $out .= qq{${font_stop}\n};
}


# Run independent attitude checker
my $ATT_CHECK_AFTER = '2015:315:00:00:00.000';
if ((defined $char_file) or ($bs[0]->{time} > date2time($ATT_CHECK_AFTER))){
    $out .= "------------  VERIFY ATTITUDE (SI_ALIGN CHECK)  -----------------\n\n";
    # dynamic aimpoint files are required after 21-Aug-2016

018: No AOMANUVR found for MP_TARGQUAT [process]

id 018
title No AOMANUVR found for MP_TARGQUAT
file starcheck/src/starcheck.pl:1112
type process
severity red
aca_cl_id
note
orvdot

    my $set = 0;

    for my $i (reverse (0 .. $#cmd)) {
        if ($cmd[$i] eq 'COMMAND_SW' and $params[$i] =~ /AOMANUVR/) {
#        print STDERR "First: $cmd[$i], $time[$i], $date[$i] \n";
        $manv_time = $time[$i];
        $set = 1;
    }
    if ($cmd[$i] eq 'MP_TARGQUAT') {
#        print STDERR "Second: $cmd[$i], $time[$i], $date[$i] \n";
        if ($set eq 1) {
        $time[$i] = $manv_time;
#        undef $manv_time;    # Make sure that each TARGQUAT gets a unique AOMANUVR time
            $set = 0;
        } else {
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        warning ("Found MP_TARGQUAT at $date[$i] without corresponding AOMANUVR\n");
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        }
    }
    }
}


##***************************************************************************
sub set_dot_cmd {
##***************************************************************************
    %dot_cmd    = (ATS_MANVR  =>  'MP_TARGQUAT',

019: Could not find a match in DOT for cmd near date [process]

id 019
title Could not find a match in DOT for cmd near date
file starcheck/src/starcheck.pl:1176
type process
severity red
aca_cl_id
note
orvdot

    if ($dot_cmd{$cmd_identifier} eq $cmd ){
        if ( abs($dot{$obsid_index}{time} + $dt - $time) < $tolerance) {
        if ($obsid_index =~ /\S0*(\S+)\d{4}/){
            return $1;

        }
        else{
            die "Couldn't parse obsid_index = '$obsid_index' in get_obsid()\n";
        }
        }


    }
    }

# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    warning("Could not find a match in DOT for $cmd at $date\n");
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX

    # Couldn't match input command to DOT.  For TARGQUAT or STARCAT, force
    # processing by making a bogus obsid

    if ($cmd =~ /MP_(TARGQUAT|STARCAT)/) {
    $obsid = "NONE$bogus_obsid" ;
    warning("Creating bogus obsid $obsid\n") unless ($obs{$obsid});
    $bogus_obsid++ if ($cmd eq 'MP_STARCAT');
    }
    return ($obsid);

020: Creating fake obsid for star catalog in backstop but not in DOT [process]

id 020
title Creating fake obsid for star catalog in backstop but not in DOT
file starcheck/src/starcheck.pl:1183
type process
severity red
aca_cl_id
note
orvdot Replan/reopen schedule that has star catalogs prior to the start of DOT.

            die "Couldn't parse obsid_index = '$obsid_index' in get_obsid()\n";
        }
        }


    }
    }

    warning("Could not find a match in DOT for $cmd at $date\n");

    # Couldn't match input command to DOT.  For TARGQUAT or STARCAT, force
    # processing by making a bogus obsid

    if ($cmd =~ /MP_(TARGQUAT|STARCAT)/) {
    $obsid = "NONE$bogus_obsid" ;
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    warning("Creating bogus obsid $obsid\n") unless ($obs{$obsid});
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    $bogus_obsid++ if ($cmd eq 'MP_STARCAT');
    }
    return ($obsid);
}


##***************************************************************************
sub get_file {
##***************************************************************************
    my $glob = shift;

021: Exactly one file of each required kind was found [process]

id 021
title Exactly one file of each required kind was found
file starcheck/src/starcheck.pl:1200
type process
severity red
aca_cl_id
note
orvdot

    }
    return ($obsid);
}


##***************************************************************************
sub get_file {
##***************************************************************************
    my $glob = shift;
    my $name = shift;
    my $required = shift;
    my $warning = ($required ? "ERROR" : "WARNING");

    my @files = glob($glob);
    if (@files != 1) {
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
      my $warn = ((@files == 0) ?
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
                  "$warning: No $name file matching $glob\n"
                  : "$warning: Found more than one file matching $glob, using none\n");
      warning($warn);
    die "\n" if ($required);
    return undef;
    }
    $input_files{$name}=$files[0];
    print STDERR "Using $name file $files[0]\n";
    return $files[0];
}

022: Additional steps of assignment of warning created in '021'. [code]

id 022
title Additional steps of assignment of warning created in '021'.
file starcheck/src/starcheck.pl:1203
type code
severity
aca_cl_id
note
orvdot



##***************************************************************************
sub get_file {
##***************************************************************************
    my $glob = shift;
    my $name = shift;
    my $required = shift;
    my $warning = ($required ? "ERROR" : "WARNING");

    my @files = glob($glob);
    if (@files != 1) {
      my $warn = ((@files == 0) ?
                  "$warning: No $name file matching $glob\n"
                  : "$warning: Found more than one file matching $glob, using none\n");
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
      warning($warn);
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    die "\n" if ($required);
    return undef;
    }
    $input_files{$name}=$files[0];
    print STDERR "Using $name file $files[0]\n";
    return $files[0];
}

##***************************************************************************
#sub insert_bogus_obsid {

023: This is the general-purpose warning function [code]

id 023
title This is the general-purpose warning function
file starcheck/src/starcheck.pl:1229
type code
severity
aca_cl_id
note
orvdot

##***************************************************************************
#    @date = (@date[0..$i-1], $date[$i_last_starcat], @date[$i..$#date]);
#    @vcdu = (@vcdu[0..$i-1], $vcdu[$i_last_starcat]+4, @vcdu[$i..$#vcdu]);
#    @cmd = (@cmd[0..$i-1], 'MP_OBSID', @cmd[$i..$#cmd]);
#    @params = (@params[0..$i-1], "ID= NONE$bogus_obsid", @params[$i..$#params]);
#    warning ("A star catalog does not have an associated obsid, "
#    . "using bogus obsid NONE$bogus_obsid\n");
#    $bogus_obsid++;
#}


##***************************************************************************
sub warning {
##***************************************************************************
    my $text = shift;
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @global_warn, $text;
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    print STDERR $text;
}


##***************************************************************************
sub usage
##***************************************************************************
{
  my ( $exit ) = @_;

024: Mismatch between obsid in guide summary vs. backstop [process]

id 024
title Mismatch between obsid in guide summary vs. backstop
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:248
type process
severity red
aca_cl_id
note
orvdot

# Use the following (in order of preference):
# - Backstop command (this relies on the DOT to associate cmd with star catalog)
# - Guide summary which provides ofls_id and obsid for each star catalog
# - OFLS ID from the DOT (as a fail-thru to still get some output)
##################################################################################
    my $self = shift;
    my $gs = shift;  # Guide summary
    my $oflsid = $self->{dot_obsid};
    my $gs_obsid;
    my $bs_obsid;
    my $mp_obsid_cmd = find_command($self, "MP_OBSID");
    $gs_obsid = $gs->{$oflsid}{guide_summ_obsid} if defined $gs->{$oflsid};
    $bs_obsid = $mp_obsid_cmd->{ID} if $mp_obsid_cmd;
    $self->{obsid} = $bs_obsid || $gs_obsid || $oflsid;
    if (defined $bs_obsid and defined $gs_obsid and $bs_obsid != $gs_obsid) {
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @{$self->{warn}}, sprintf("$alarm Obsid mismatch: guide summary %d != backstop %d\n",
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
                                      $gs_obsid, $bs_obsid);
    }
}


##################################################################################
sub print_cmd_params {
##################################################################################
    my $self = shift;
    foreach my $cmd (@{$self->{commands}}) {

025: Quaternion is not normalized [aca_check]

id 025
title Quaternion is not normalized
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:363
type aca_check
severity red
aca_cl_id
note
orvdot

        foreach (keys %{$m}) {
            $c->{$_} = $m->{$_};
        }
        # Set the default maneuver error (based on WS Davis data) and cap at 85 arcsec
        $c->{man_err} = (exists $c->{angle}) ? 35 + $c->{angle}/2. : 85;
        $c->{man_err} = 85 if ($c->{man_err} > 85);
        # Now check for consistency between quaternion from MANUEVER summary
        # file and the quat from backstop (MP_TARGQUAT cmd)

        # Get quat from MP_TARGQUAT (backstop) command.
        # Compute 4th component (as only first 3 are uplinked) and renormalize.
        # Intent is to match OBC Target Reference subfunction
        my $q4_obc = sqrt(abs(1.0 - $c->{Q1}**2 - $c->{Q2}**2 - $c->{Q3}**2));
        my $norm = sqrt($c->{Q1}**2 + $c->{Q2}**2 + $c->{Q3}**2 + $q4_obc**2);
        if (abs(1.0 - $norm) > 1e-6){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
           push @{$self->{warn}}, sprintf("$alarm Uplink quaternion norm value $norm is too far from 1.0\n");
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        }
        my @c_quat_norm = ($c->{Q1} / $norm,
                           $c->{Q2} / $norm,
                           $c->{Q3} / $norm,
                           $q4_obc / $norm);

        # Get quat from MANEUVER summary file.  This is correct to high precision
        my $q_man = Quat->new($m->{ra}, $m->{dec}, $m->{roll});
        my $q_obc = Quat->new(@c_quat_norm);
        my @q_man = @{$q_man->{q}};

026: Quaternion has poor precision [aca_check]

id 026
title Quaternion has poor precision
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:377
type aca_check
severity red
aca_cl_id
note
orvdot

        if (abs(1.0 - $norm) > 1e-6){
           push @{$self->{warn}}, sprintf("$alarm Uplink quaternion norm value $norm is too far from 1.0\n");
        }
        my @c_quat_norm = ($c->{Q1} / $norm,
                           $c->{Q2} / $norm,
                           $c->{Q3} / $norm,
                           $q4_obc / $norm);

        # Get quat from MANEUVER summary file.  This is correct to high precision
        my $q_man = Quat->new($m->{ra}, $m->{dec}, $m->{roll});
        my $q_obc = Quat->new(@c_quat_norm);
        my @q_man = @{$q_man->{q}};
        my $q_diff = $q_man->divide($q_obc);

        if (abs($q_diff->{ra0}*3600) > 1.0 || abs($q_diff->{dec}*3600) > 1.0 || abs($q_diff->{roll0}*3600) > 10.0) {
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
            push @{$self->{warn}}, sprintf("$alarm Target uplink precision problem for MP_TARGQUAT at $c->{date}\n"
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
                           . "   Error is yaw, pitch, roll (arcsec) = %.2f  %.2f  %.2f\n"
                           . "   Use Q1,Q2,Q3,Q4 = %.12f %.12f %.12f %.12f\n",
                           $q_diff->{ra0}*3600, $q_diff->{dec}*3600, $q_diff->{roll0}*3600,
                           $q_man[0], $q_man[1], $q_man[2], $q_man[3]);
        }
        }


    }
    push @{$self->{yellow_warn}}, sprintf("$alarm Did not find match in MAN summary for MP_TARGQUAT at $c->{date}\n")

027: No match in maneuver summary for MP_TARGQUAT [process]

id 027
title No match in maneuver summary for MP_TARGQUAT
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:387
type process
severity yellow
aca_cl_id
note
orvdot

        my $q_obc = Quat->new(@c_quat_norm);
        my @q_man = @{$q_man->{q}};
        my $q_diff = $q_man->divide($q_obc);

        if (abs($q_diff->{ra0}*3600) > 1.0 || abs($q_diff->{dec}*3600) > 1.0 || abs($q_diff->{roll0}*3600) > 10.0) {
            push @{$self->{warn}}, sprintf("$alarm Target uplink precision problem for MP_TARGQUAT at $c->{date}\n"
                           . "   Error is yaw, pitch, roll (arcsec) = %.2f  %.2f  %.2f\n"
                           . "   Use Q1,Q2,Q3,Q4 = %.12f %.12f %.12f %.12f\n",
                           $q_diff->{ra0}*3600, $q_diff->{dec}*3600, $q_diff->{roll0}*3600,
                           $q_man[0], $q_man[1], $q_man[2], $q_man[3]);
        }
        }


    }
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @{$self->{yellow_warn}}, sprintf("$alarm Did not find match in MAN summary for MP_TARGQUAT at $c->{date}\n")
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        unless ($found);

    }
}

##################################################################################
sub set_manerr {
#
# Set the maneuver error for each MP_TARGQUAT command within the obsid
# using the more accurate values from Bill Davis' code

028: Mismatch between target quaternion at time and entry in maneuver error file [process]

id 028
title Mismatch between target quaternion at time and entry in maneuver error file
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:419
type process
severity yellow
aca_cl_id
note
orvdot

    while ($c = find_command($self, "MP_TARGQUAT", $n)) {

    foreach my $me (@manerr) {
        # There should be a one-to-one mapping between maneuver segments in the maneuver
        # error file and those in the obsid records.  First, find what *should* be the
        # match.  Then check quaternions to make sure

        if ($self->{obsid} eq $me->{obsid} && $n == $me->{Seg}) {
        if (   abs($me->{finalQ1} - $c->{Q1}) < 1e-7
               && abs($me->{finalQ2} - $c->{Q2}) < 1e-7
               && abs($me->{finalQ3} - $c->{Q3}) < 1e-7)
        {
            $c->{man_err} = $me->{MaxErrYZ} + $ACA_MANERR_PAD;
            $c->{man_err_data} = $me; # Save the whole record just in case
        } else {
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
            push @{$self->{yellow_warn}}, sprintf("$alarm Mismatch in target quaternion ($c->{date}) and maneuver error file\n");
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        }
        }
    }
    $n++;
    }
}

##################################################################################
sub set_ps_times{
# Get the observation start and stop times from the processing summary

029: Could not find obsid in MSCH processing summary (mps/ms*.sum) [process]

id 029
title Could not find obsid in MSCH processing summary (mps/ms*.sum)
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:458
type process
severity red
aca_cl_id
note
orvdot

        my $length = length($obsid);
        if (substr($tmp[0], 5-$length, $length) eq $obsid){
        $or_er_start = $tmp[2];
        $or_er_stop = $tmp[3];
        last;
        }
    }
    if (($ps_line =~ /OBSID\s=\s(\d\d\d\d\d)/) && (scalar(@tmp) >= 8 )) {
        if ( $obsid eq $1 ){
        $or_er_start = $tmp[2];
        $or_er_stop = $tmp[3];
        }
    }
    }
    if (not defined $or_er_start or not defined $or_er_stop){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @{$self->{warn}}, "$alarm Could not find obsid $obsid in processing summary\n";
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        $self->{or_er_start} = undef;
        $self->{or_er_stop} = undef;
    }
    else{
        $self->{or_er_start} = date2time($or_er_start);
        $self->{or_er_stop} = date2time($or_er_stop);
    }


}

030: Next obsid has no manvr, using next obsid start for time checks [process]

id 030
title Next obsid has no manvr, using next obsid start for time checks
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:505
type process
severity info
aca_cl_id
note
orvdot

    }

    # set the observation stop as the beginning of the next maneuever
    # or, if last obsid in load, use the processing summary or/er observation
    # stop time
    if (defined $self->{next}){
        my $next_manvr = find_command($self->{next}, "MP_TARGQUAT", -1);
        if ((defined $next_manvr) & (defined $next_manvr->{tstart})){
            $obs_tstop  = $next_manvr->{tstart};
        }
        else{
            # if the next obsid doesn't have a maneuver (ACIS undercover or whatever)
            # just use next obsid start time
            my $next_cmd_obsid = find_command($self->{next}, "MP_OBSID", -1);
            if ( (defined $next_cmd_obsid) and ( $self->{obsid} != $next_cmd_obsid->{ID}) ){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @{$self->{fyi}}, "$info Next obsid has no manvr; using next obs start date for checks (dither, momentum)\n";
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
                $obs_tstop = $next_cmd_obsid->{time};
                $self->{no_following_manvr} = 1;
            }
        }
    }
    else{
        $obs_tstop = $self->{or_er_stop};
    }

    if (not defined $obs_tstart or not defined $obs_tstop){

031: Could not determine start or stop time(s) for obsid [process]

id 031
title Could not determine start or stop time(s) for obsid
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:516
type process
severity red
aca_cl_id
note
orvdot

            # if the next obsid doesn't have a maneuver (ACIS undercover or whatever)
            # just use next obsid start time
            my $next_cmd_obsid = find_command($self->{next}, "MP_OBSID", -1);
            if ( (defined $next_cmd_obsid) and ( $self->{obsid} != $next_cmd_obsid->{ID}) ){
        push @{$self->{fyi}}, "$info Next obsid has no manvr; using next obs start date for checks (dither, momentum)\n";
                $obs_tstop = $next_cmd_obsid->{time};
                $self->{no_following_manvr} = 1;
            }
        }
    }
    else{
        $obs_tstop = $self->{or_er_stop};
    }

    if (not defined $obs_tstart or not defined $obs_tstop){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @{$self->{warn}}, "$alarm Could not determine obsid start and stop times for checks (dither, momentum)\n";
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    }
    else{
        $self->{obs_tstart} = $obs_tstart;
        $self->{obs_tstop} = $obs_tstop;

    }
}



032: Dither status not checked [aca_check]

id 032
title Dither status not checked
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:634
type aca_check
severity red
aca_cl_id
note
orvdot


    my $obs_beg_pad = 8*60;       # Check dither status at obs start + 8 minutes to allow
                                  # for disabled dither because of mon star commanding
    my $obs_end_pad = 3*60;
    my $manvr;

    if ( $self->{obsid} =~ /^\d*$/){
    return if ($self->{obsid} >= $ER_MIN_OBSID); # For eng obs, don't have OR to specify dither
    }
    # If there's no starcat on purpose, return
    if (defined $self->{ok_no_starcat} and $self->{ok_no_starcat}){
        return;
    }
    unless ($manvr = find_command($self, "MP_TARGQUAT", -1)
            and defined $manvr->{tstart}) {
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @{$self->{warn}}, "$alarm Dither status not checked\n";
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    return;
    }

    unless (defined $dthr){
      push @{$self->{warn}}, "$alarm Dither states unavailable. Dither not checked\n";
      return;
    }

    # set the observation start as the end of the maneuver
    my $obs_tstart = $self->{obs_tstart};

033: Dither states/history unavailable [aca_check]

id 033
title Dither states/history unavailable
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:639
type aca_check
severity red
aca_cl_id
note
orvdot


    if ( $self->{obsid} =~ /^\d*$/){
    return if ($self->{obsid} >= $ER_MIN_OBSID); # For eng obs, don't have OR to specify dither
    }
    # If there's no starcat on purpose, return
    if (defined $self->{ok_no_starcat} and $self->{ok_no_starcat}){
        return;
    }
    unless ($manvr = find_command($self, "MP_TARGQUAT", -1)
            and defined $manvr->{tstart}) {
    push @{$self->{warn}}, "$alarm Dither status not checked\n";
    return;
    }

    unless (defined $dthr){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
      push @{$self->{warn}}, "$alarm Dither states unavailable. Dither not checked\n";
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
      return;
    }

    # set the observation start as the end of the maneuver
    my $obs_tstart = $self->{obs_tstart};
    my $obs_tstop = $self->{obs_tstop};

    # Determine current dither status by finding the last dither commanding before
    # the start of observation (+ 8 minutes)
    my $dither;

034: Mismatch between dither enable status in OR vs. Backstop [aca_check]

id 034
title Mismatch between dither enable status in OR vs. Backstop
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:663
type aca_check
severity red
aca_cl_id 002
note
orvdot Need dither disabled observation to stress.

    # the start of observation (+ 8 minutes)
    my $dither;
    foreach my $dither_state (reverse @{$dthr}) {
    if ($obs_tstart + $obs_beg_pad >= $dither_state->{time}) {
            $dither = $dither_state;
            last;
        }
    }

    my $bs_val = $dither->{state};
    # Get the OR value of dither and compare if available
    my $or_val;
    if (defined $self->{DITHER_ON}){
        $or_val = $dthr_cmd{$self->{DITHER_ON}};
        # ACA-002
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @{$self->{warn}}, "$alarm Dither mismatch - OR: $or_val != Backstop: $bs_val\n"
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
            if ($or_val ne $bs_val);
    }
    else{
        push @{$self->{warn}},
            "$alarm Unable to determine dither from OR list\n";
    }

    # If dither is anabled according to the OR, check that parameters match OR vs Backstop
    if ((defined $or_val) and ($or_val eq 'ENAB')){
        my $y_amp = $self->{DITHER_Y_AMP} * 3600;

035: Could not determine dither enable status from OR list [process]

id 035
title Could not determine dither enable status from OR list
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:667
type process
severity red
aca_cl_id
note
orvdot

            $dither = $dither_state;
            last;
        }
    }

    my $bs_val = $dither->{state};
    # Get the OR value of dither and compare if available
    my $or_val;
    if (defined $self->{DITHER_ON}){
        $or_val = $dthr_cmd{$self->{DITHER_ON}};
        # ACA-002
        push @{$self->{warn}}, "$alarm Dither mismatch - OR: $or_val != Backstop: $bs_val\n"
            if ($or_val ne $bs_val);
    }
    else{
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @{$self->{warn}},
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
            "$alarm Unable to determine dither from OR list\n";
    }

    # If dither is anabled according to the OR, check that parameters match OR vs Backstop
    if ((defined $or_val) and ($or_val eq 'ENAB')){
        my $y_amp = $self->{DITHER_Y_AMP} * 3600;
        my $z_amp = $self->{DITHER_Z_AMP} * 3600;
        if (defined $dither->{ampl_y}
                and defined $dither->{ampl_p}
                    and (abs($y_amp - $dither->{ampl_y}) > 0.1

036: Dither amplitude mismatch OR/Backstop [aca_check]

id 036
title Dither amplitude mismatch OR/Backstop
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:679
type aca_check
severity red
aca_cl_id 002
note
orvdot Need change in commanded dither amplitude (HRC -> ACIS, ACIS -> HRC, and large dither)

            if ($or_val ne $bs_val);
    }
    else{
        push @{$self->{warn}},
            "$alarm Unable to determine dither from OR list\n";
    }

    # If dither is anabled according to the OR, check that parameters match OR vs Backstop
    if ((defined $or_val) and ($or_val eq 'ENAB')){
        my $y_amp = $self->{DITHER_Y_AMP} * 3600;
        my $z_amp = $self->{DITHER_Z_AMP} * 3600;
        if (defined $dither->{ampl_y}
                and defined $dither->{ampl_p}
                    and (abs($y_amp - $dither->{ampl_y}) > 0.1
                             or abs($z_amp - $dither->{ampl_p}) > 0.1)){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
            my $warn = sprintf("$alarm Dither amp. mismatch - OR: (Y %.1f, Z %.1f) "
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
                                   . "!= Backstop: (Y %.1f, Z %.1f)\n",
                               $y_amp, $z_amp,
                               $dither->{ampl_y}, $dither->{ampl_p});
            push @{$self->{warn}}, $warn;
        }
    }
    # Check for standard and large dither based solely on backstop/history values
    if (($bs_val eq 'ENAB') and (defined $dither->{ampl_y} and defined $dither->{ampl_p})){
        $self->{cmd_dither_y_amp} = $dither->{ampl_y};
        $self->{cmd_dither_z_amp} = $dither->{ampl_p};

037: Really just part of check '036' [code]

id 037
title Really just part of check '036'
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:683
type code
severity
aca_cl_id
note
orvdot

            "$alarm Unable to determine dither from OR list\n";
    }

    # If dither is anabled according to the OR, check that parameters match OR vs Backstop
    if ((defined $or_val) and ($or_val eq 'ENAB')){
        my $y_amp = $self->{DITHER_Y_AMP} * 3600;
        my $z_amp = $self->{DITHER_Z_AMP} * 3600;
        if (defined $dither->{ampl_y}
                and defined $dither->{ampl_p}
                    and (abs($y_amp - $dither->{ampl_y}) > 0.1
                             or abs($z_amp - $dither->{ampl_p}) > 0.1)){
            my $warn = sprintf("$alarm Dither amp. mismatch - OR: (Y %.1f, Z %.1f) "
                                   . "!= Backstop: (Y %.1f, Z %.1f)\n",
                               $y_amp, $z_amp,
                               $dither->{ampl_y}, $dither->{ampl_p});
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
            push @{$self->{warn}}, $warn;
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        }
    }
    # Check for standard and large dither based solely on backstop/history values
    if (($bs_val eq 'ENAB') and (defined $dither->{ampl_y} and defined $dither->{ampl_p})){
        $self->{cmd_dither_y_amp} = $dither->{ampl_y};
        $self->{cmd_dither_z_amp} = $dither->{ampl_p};
        if (not standard_dither($dither)){
            push @{$self->{yellow_warn}}, "$alarm Non-standard dither\n";
            if ($dither->{ampl_y} > $large_dith_thresh or $dither->{ampl_p} > $large_dith_thresh){
                $self->large_dither_checks($dither, $dthr);

038: Non-standard dither [aca_check]

id 038
title Non-standard dither
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:691
type aca_check
severity yellow
aca_cl_id
note
orvdot

                and defined $dither->{ampl_p}
                    and (abs($y_amp - $dither->{ampl_y}) > 0.1
                             or abs($z_amp - $dither->{ampl_p}) > 0.1)){
            my $warn = sprintf("$alarm Dither amp. mismatch - OR: (Y %.1f, Z %.1f) "
                                   . "!= Backstop: (Y %.1f, Z %.1f)\n",
                               $y_amp, $z_amp,
                               $dither->{ampl_y}, $dither->{ampl_p});
            push @{$self->{warn}}, $warn;
        }
    }
    # Check for standard and large dither based solely on backstop/history values
    if (($bs_val eq 'ENAB') and (defined $dither->{ampl_y} and defined $dither->{ampl_p})){
        $self->{cmd_dither_y_amp} = $dither->{ampl_y};
        $self->{cmd_dither_z_amp} = $dither->{ampl_p};
        if (not standard_dither($dither)){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
            push @{$self->{yellow_warn}}, "$alarm Non-standard dither\n";
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
            if ($dither->{ampl_y} > $large_dith_thresh or $dither->{ampl_p} > $large_dith_thresh){
                $self->large_dither_checks($dither, $dthr);
                # If this is a large dither, set a larger pad at the end, as we expect
                # standard dither parameters to be commanded at 5 minutes before end,
                # which is greater than the 3 minutes used in the "no dither changes
                # during observation check below
                $obs_end_pad = 5.5 * 60;
            }
        }
    }

039: Could not use stop time for dither check [process]

id 039
title Could not use stop time for dither check
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:706
type process
severity red
aca_cl_id
note
orvdot

            push @{$self->{yellow_warn}}, "$alarm Non-standard dither\n";
            if ($dither->{ampl_y} > $large_dith_thresh or $dither->{ampl_p} > $large_dith_thresh){
                $self->large_dither_checks($dither, $dthr);
                # If this is a large dither, set a larger pad at the end, as we expect
                # standard dither parameters to be commanded at 5 minutes before end,
                # which is greater than the 3 minutes used in the "no dither changes
                # during observation check below
                $obs_end_pad = 5.5 * 60;
            }
        }
    }

    # Loop again to check for dither changes during the observation
    # ACA-003
    if (not defined $obs_tstop ){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @{$self->{warn}},
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
            "$alarm Unable to determine obs tstop; could not check for dither changes during obs\n";
    }
    else{
        foreach my $dither (reverse @{$dthr}) {
            if ($dither->{time} > ($obs_tstart + $obs_beg_pad)
                    && $dither->{time} <= $obs_tstop - $obs_end_pad) {
                push @{$self->{warn}}, "$alarm Dither commanding at $dither->{time}.  During observation.\n";
            }
            if ($dither->{time} < $obs_tstart){
                last;

040: Unexpected dither commanding during observation [aca_check]

id 040
title Unexpected dither commanding during observation
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:713
type aca_check
severity red
aca_cl_id 003
note
orvdot

                $obs_end_pad = 5.5 * 60;
            }
        }
    }

    # Loop again to check for dither changes during the observation
    # ACA-003
    if (not defined $obs_tstop ){
        push @{$self->{warn}},
            "$alarm Unable to determine obs tstop; could not check for dither changes during obs\n";
    }
    else{
        foreach my $dither (reverse @{$dthr}) {
            if ($dither->{time} > ($obs_tstart + $obs_beg_pad)
                    && $dither->{time} <= $obs_tstop - $obs_end_pad) {
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
                push @{$self->{warn}}, "$alarm Dither commanding at $dither->{time}.  During observation.\n";
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
            }
            if ($dither->{time} < $obs_tstart){
                last;
            }
        }
    }
}



041: Large dither not enabled 5 min after EOM [aca_check]

id 041
title Large dither not enabled 5 min after EOM
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:784
type aca_check
severity red
aca_cl_id
note
orvdot Need observation with large dither commanding

    # from the actual command timing. Fix this here.
    my $obs_tstart = $self->{obs_tstart} - 10;
    my $obs_tstop = $self->{obs_tstop} - 10;

    # Now check in backstop commands for :
    #  Dither is disabled (AODSDITH) 1 min prior to the end of the maneuver (EOM)
    #    to the target attitude.
    #  Dither is enabled (AOENDITH) 5 min after EOM
    #  Dither parameters are commanded 5 min before end of observation
    # ACA-040
    # obs_tstart is defined as the tstop of the maneuver to this observation in set_npm_times
    # obs_tstop is defined as the time of the maneuver away or the end of the schedule

    # Is the large dither command enabled 5 minutes after EOM?
    if (abs($dither_state->{time} - $obs_tstart - 300) > $time_tol){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @{$self->{warn}},
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
            sprintf("$alarm Large Dither not enabled 5 min after EOM (%s)\n",
                    time2date($obs_tstart));
    }
    # What's the dither state at EOM?
    my $obs_start_dither;
    foreach my $dither (reverse @{$all_dither}) {
    if ($obs_tstart >= $dither->{time}) {
            $obs_start_dither = $dither;
            last;
        }

042: Dither not disabled 1 min before obs star for large dither obs [aca_check]

id 042
title Dither not disabled 1 min before obs star for large dither obs
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:799
type aca_check
severity red
aca_cl_id
note
orvdot Need observation with large dither commanding

        push @{$self->{warn}},
            sprintf("$alarm Large Dither not enabled 5 min after EOM (%s)\n",
                    time2date($obs_tstart));
    }
    # What's the dither state at EOM?
    my $obs_start_dither;
    foreach my $dither (reverse @{$all_dither}) {
    if ($obs_tstart >= $dither->{time}) {
            $obs_start_dither = $dither;
            last;
        }
    }
    # Is dither disabled at EOM and one minute before?
    if ((abs($obs_tstart - $obs_start_dither->{time} - 60) > $time_tol)
            or ($obs_start_dither->{state} ne 'DISA')){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @{$self->{warn}},
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
            sprintf("$alarm Dither should be disabled 1 min before obs start for Large Dither\n");
    }


    # Find the dither state at the end of the observation
    my $obs_stop_dither;
    foreach my $dither (reverse @{$all_dither}) {
    if ($obs_tstop >= $dither->{time}) {
            $obs_stop_dither = $dither;
            last;

043: Change at end of large dither observation happens too early [aca-check]

id 043
title Change at end of large dither observation happens too early
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:815
type aca-check
severity red
aca_cl_id
note
orvdot Need observation with large dither commanding

            sprintf("$alarm Dither should be disabled 1 min before obs start for Large Dither\n");
    }


    # Find the dither state at the end of the observation
    my $obs_stop_dither;
    foreach my $dither (reverse @{$all_dither}) {
    if ($obs_tstop >= $dither->{time}) {
            $obs_stop_dither = $dither;
            last;
        }
    }
    # Check that the dither state at the end of the observation started 5 minutes before
    # the end (within time_tol)
    if ((abs($obs_tstop - $obs_stop_dither->{time} - 300) > $time_tol)){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @{$self->{warn}},
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
            sprintf("$alarm Last dither state for Large Dither should start 5 minutes before obs end.\n");
    }
    # Check that the dither state at the end of the observation is standard
    if (not standard_dither($obs_stop_dither)){
        push @{$self->{warn}},
            sprintf("$alarm Dither parameters not set to standard values before obs end\n");
    }

    # If the number of warnings has not changed during this routine, it passed all checks
    if (scalar(@{$self->{warn}}) == $n_warn){

044: Dither parameters for large dither obsid not reset to standard before obs end [aca_check]

id 044
title Dither parameters for large dither obsid not reset to standard before obs end
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:820
type aca_check
severity red
aca_cl_id
note
orvdot Need observation with large dither commanding

    my $obs_stop_dither;
    foreach my $dither (reverse @{$all_dither}) {
    if ($obs_tstop >= $dither->{time}) {
            $obs_stop_dither = $dither;
            last;
        }
    }
    # Check that the dither state at the end of the observation started 5 minutes before
    # the end (within time_tol)
    if ((abs($obs_tstop - $obs_stop_dither->{time} - 300) > $time_tol)){
        push @{$self->{warn}},
            sprintf("$alarm Last dither state for Large Dither should start 5 minutes before obs end.\n");
    }
    # Check that the dither state at the end of the observation is standard
    if (not standard_dither($obs_stop_dither)){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @{$self->{warn}},
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
            sprintf("$alarm Dither parameters not set to standard values before obs end\n");
    }

    # If the number of warnings has not changed during this routine, it passed all checks
    if (scalar(@{$self->{warn}}) == $n_warn){
        push @{$self->{fyi}},
            sprintf("$info Observation passes 'big dither' checks\n");
    }
}

045: Rad zone data unavailable; could not figure out which obsids are perigee obs [process]

id 045
title Rad zone data unavailable; could not figure out which obsids are perigee obs
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:848
type process
severity red
aca_cl_id
note
orvdot



#############################################################################################
sub check_bright_perigee{
#############################################################################################
    my $self = shift;
    my $radmon = shift;
    my $min_mag = 9.0;
    my $min_n_stars = 3;

    # if this is an OR, just return
    return if (($self->{obsid} =~ /^\d+$/ && $self->{obsid} < $ER_MIN_OBSID));

    # if radmon is undefined, warn and return
    if (not defined $radmon){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
      push @{$self->{warn}}, "$alarm Perigee bright stars not being checked, no rad zone info available\n";
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    return;
    }

    # set the observation start as the end of the maneuver
    my $obs_tstart = $self->{obs_tstart};
    my $obs_tstop = $self->{obs_tstop};

    # if observation stop time is undefined, warn and return
    if (not defined $obs_tstop){
        push @{$self->{warn}}, "$alarm Perigee bright stars not being checked, no obs tstop available\n";

046: No obsid end time, so could not run perigee bright star check [process]

id 046
title No obsid end time, so could not run perigee bright star check
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:858
type process
severity red
aca_cl_id
note
orvdot

    # if this is an OR, just return
    return if (($self->{obsid} =~ /^\d+$/ && $self->{obsid} < $ER_MIN_OBSID));

    # if radmon is undefined, warn and return
    if (not defined $radmon){
      push @{$self->{warn}}, "$alarm Perigee bright stars not being checked, no rad zone info available\n";
    return;
    }

    # set the observation start as the end of the maneuver
    my $obs_tstart = $self->{obs_tstart};
    my $obs_tstop = $self->{obs_tstop};

    # if observation stop time is undefined, warn and return
    if (not defined $obs_tstop){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @{$self->{warn}}, "$alarm Perigee bright stars not being checked, no obs tstop available\n";
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    return;
    }

    # is this obsid in perigee?  assume no to start
    my $in_perigee = 0;

    for my $rad (reverse @{$radmon}){
      next if ($rad->{time} > $obs_tstop);
      if ($rad->{state} eq 'DISA'){
        $in_perigee = 1;

047: Enough bright stars for a Special Case Er [aca-check]

id 047
title Enough bright stars for a Special Case Er
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:887
type aca-check
severity info
aca_cl_id
note Expect special-case to be removed in ORVdot, can remove these checks post-transition.
orvdot

    }

    # nothing to do if not in perigee
    return if (not $in_perigee);

    my $c = find_command($self, 'MP_STARCAT');
    return if (not defined $c);

    # check for at least N bright stars
    my @bright_stars = grep { (defined $c->{"TYPE$_"})
                              and ($c->{"TYPE$_"} =~ /BOT|GUI/)
                              and ($c->{"GS_MAG$_"} < $min_mag) } (0 .. 16);
    my $bright_count = scalar(@bright_stars);
    if ($bright_count < $min_n_stars){
        if ($self->{special_case_er} == 1){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
            push @{$self->{fyi}}, "$info Only $bright_count star(s) brighter than $min_mag mag. "
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
                . "Acceptable for Special Case ER\n";
        }
        else{
            push @{$self->{warn}}, "$alarm $bright_count star(s) brighter than $min_mag mag. "
                . "Perigee requires at least $min_n_stars\n";
        }

    }
}

048: Not enough bright stars for perigee observation [aca_check]

id 048
title Not enough bright stars for perigee observation
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:891
type aca_check
severity red
aca_cl_id
note
orvdot


    my $c = find_command($self, 'MP_STARCAT');
    return if (not defined $c);

    # check for at least N bright stars
    my @bright_stars = grep { (defined $c->{"TYPE$_"})
                              and ($c->{"TYPE$_"} =~ /BOT|GUI/)
                              and ($c->{"GS_MAG$_"} < $min_mag) } (0 .. 16);
    my $bright_count = scalar(@bright_stars);
    if ($bright_count < $min_n_stars){
        if ($self->{special_case_er} == 1){
            push @{$self->{fyi}}, "$info Only $bright_count star(s) brighter than $min_mag mag. "
                . "Acceptable for Special Case ER\n";
        }
        else{
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
            push @{$self->{warn}}, "$alarm $bright_count star(s) brighter than $min_mag mag. "
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
                . "Perigee requires at least $min_n_stars\n";
        }

    }
}


#############################################################################################
sub check_momentum_unload{
#############################################################################################

049: Could not determine obsid time, so could not check for momentum unloads [process]

id 049
title Could not determine obsid time, so could not check for momentum unloads
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:908
type process
severity red
aca_cl_id
note
orvdot

        }

    }
}


#############################################################################################
sub check_momentum_unload{
#############################################################################################
    my $self = shift;
    my $backstop = shift;
    my $obs_tstart = $self->{obs_tstart};
    my $obs_tstop = $self->{obs_tstop};

    if (not defined $obs_tstart or not defined $obs_tstop){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @{$self->{warn}}, "$alarm Momentum Unloads not checked.\n";
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        return;
    }
    for my $entry (@{$backstop}){
        if ((defined $entry->{command}) and (defined $entry->{command}->{TLMSID})){
            if ($entry->{command}->{TLMSID} =~ /AOMUNLGR/){
                if (($entry->{time} >= $obs_tstart) and ($entry->{time} <= $obs_tstop )){
                    push @{$self->{fyi}}, "$info Momentum Unload (AOMUNLGR) in NPM at " . $entry->{date} . "\n";
                }
            }
        }

050: Unload in NPM []

id 050
title Unload in NPM
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:915
type
severity info
aca_cl_id
note
orvdot

sub check_momentum_unload{
#############################################################################################
    my $self = shift;
    my $backstop = shift;
    my $obs_tstart = $self->{obs_tstart};
    my $obs_tstop = $self->{obs_tstop};

    if (not defined $obs_tstart or not defined $obs_tstop){
        push @{$self->{warn}}, "$alarm Momentum Unloads not checked.\n";
        return;
    }
    for my $entry (@{$backstop}){
        if ((defined $entry->{command}) and (defined $entry->{command}->{TLMSID})){
            if ($entry->{command}->{TLMSID} =~ /AOMUNLGR/){
                if (($entry->{time} >= $obs_tstart) and ($entry->{time} <= $obs_tstop )){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
                    push @{$self->{fyi}}, "$info Momentum Unload (AOMUNLGR) in NPM at " . $entry->{date} . "\n";
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
                }
            }
        }
    }
}

#############################################################################################
sub check_for_special_case_er{
#############################################################################################
    my $self = shift;

051: Observation is a special case ER [aca_check]

id 051
title Observation is a special case ER
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:945
type aca_check
severity info
aca_cl_id
note Expect special-case to be removed in ORVdot, can remove these checks post-transition.
orvdot

    # and the pointings are the same
    # it is a special case ER
    $self->{special_case_er} = 0;
    if ($self->{obsid} =~ /^\d+$/
        and $self->{obsid} >= $ER_MIN_OBSID
        and $self->find_command("MP_STARCAT")
        and $self->{prev}
        and $self->{prev}->{obsid} =~ /^\d+$/
        and $self->{prev}->{obsid} < $ER_MIN_OBSID
        and $self->{prev}->find_command("MP_STARCAT")
        and abs($self->{ra} - $self->{prev}->{ra}) < 0.001
        and abs($self->{dec} - $self->{prev}->{dec}) < 0.001
        and abs($self->{roll} - $self->{prev}->{roll}) < 0.001){
        if (($self->{obs_tstop} - $self->{obs_tstart}) < 10*60){
            $self->{special_case_er} = 1;
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
            push @{$self->{fyi}}, "$info Special Case ER\n";
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        }
        else{
            push @{$self->{fyi}},
            sprintf("$info Same attitude as last obsid but too long (%.1f min) for Special Case ER\n", ($self->{obs_tstop} - $self->{obs_tstart})/60.);
        }
    }
}

#############################################################################################
sub check_sim_position {

052: Obsid almost a special case ER [aca_check]

id 052
title Obsid almost a special case ER
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:948
type aca_check
severity info
aca_cl_id
note Expect special-case to be removed in ORVdot, can remove these checks post-transition.
orvdot

    if ($self->{obsid} =~ /^\d+$/
        and $self->{obsid} >= $ER_MIN_OBSID
        and $self->find_command("MP_STARCAT")
        and $self->{prev}
        and $self->{prev}->{obsid} =~ /^\d+$/
        and $self->{prev}->{obsid} < $ER_MIN_OBSID
        and $self->{prev}->find_command("MP_STARCAT")
        and abs($self->{ra} - $self->{prev}->{ra}) < 0.001
        and abs($self->{dec} - $self->{prev}->{dec}) < 0.001
        and abs($self->{roll} - $self->{prev}->{roll}) < 0.001){
        if (($self->{obs_tstop} - $self->{obs_tstart}) < 10*60){
            $self->{special_case_er} = 1;
            push @{$self->{fyi}}, "$info Special Case ER\n";
        }
        else{
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
            push @{$self->{fyi}},
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
            sprintf("$info Same attitude as last obsid but too long (%.1f min) for Special Case ER\n", ($self->{obs_tstop} - $self->{obs_tstart})/60.);
        }
    }
}

#############################################################################################
sub check_sim_position {
#############################################################################################
    my $self = shift;
    my @sim_trans = @_;        # Remaining values are SIMTRANS backstop cmds

053: Missing MP_TARGQUAT [process]

id 053
title Missing MP_TARGQUAT
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:963
type process
severity red
aca_cl_id
note
orvdot

            push @{$self->{fyi}},
            sprintf("$info Same attitude as last obsid but too long (%.1f min) for Special Case ER\n", ($self->{obs_tstop} - $self->{obs_tstart})/60.);
        }
    }
}

#############################################################################################
sub check_sim_position {
#############################################################################################
    my $self = shift;
    my @sim_trans = @_;        # Remaining values are SIMTRANS backstop cmds
    my $manvr;

    return unless (exists $self->{SIM_OFFSET_Z});
    unless ($manvr = find_command($self, "MP_TARGQUAT", -1)) {
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @{$self->{warn}}, "$alarm Missing MP_TARGQUAT cmd\n";
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    return;
    }

    # Set the expected SIM Z position (steps)
    my $sim_z = $Default_SIM_Z{$self->{SI}} + $self->{SIM_OFFSET_Z};

    foreach my $st (reverse @sim_trans) {
    if (not defined $manvr->{tstop}){
        push @{$self->{warn}}, "Maneuver times not defined; SIM checking failed!\n";
    }

054: Could not check SIM position due to missing maneuver time [process]

id 054
title Could not check SIM position due to missing maneuver time
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:972
type process
severity
aca_cl_id
note
orvdot

    my $self = shift;
    my @sim_trans = @_;        # Remaining values are SIMTRANS backstop cmds
    my $manvr;

    return unless (exists $self->{SIM_OFFSET_Z});
    unless ($manvr = find_command($self, "MP_TARGQUAT", -1)) {
    push @{$self->{warn}}, "$alarm Missing MP_TARGQUAT cmd\n";
    return;
    }

    # Set the expected SIM Z position (steps)
    my $sim_z = $Default_SIM_Z{$self->{SI}} + $self->{SIM_OFFSET_Z};

    foreach my $st (reverse @sim_trans) {
    if (not defined $manvr->{tstop}){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @{$self->{warn}}, "Maneuver times not defined; SIM checking failed!\n";
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    }
    else{
        if ($manvr->{tstop} >= $st->{time}) {
        my %par = Ska::Parse_CM_File::parse_params($st->{params});
        if (abs($par{POS} - $sim_z) > 4) {
#        print STDERR "Yikes, SIM mismatch!  \n";
#        print STDERR " self->{obsid} = $self->{obsid}\n";
#        print STDERR " sim_offset_z = $self->{SIM_OFFSET_Z}   SI = $self->{SI}\n";
#        print STDERR " st->{POS} = $par{POS}   sim_z = $sim_z   delta = ", $par{POS}-$sim_z,"\n";
                    # ACA-001

055: SIM position mismatch OR vs Backstop [aca_check]

id 055
title SIM position mismatch OR vs Backstop
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:983
type aca_check
severity red
aca_cl_id 001
note
orvdot

    my $sim_z = $Default_SIM_Z{$self->{SI}} + $self->{SIM_OFFSET_Z};

    foreach my $st (reverse @sim_trans) {
    if (not defined $manvr->{tstop}){
        push @{$self->{warn}}, "Maneuver times not defined; SIM checking failed!\n";
    }
    else{
        if ($manvr->{tstop} >= $st->{time}) {
        my %par = Ska::Parse_CM_File::parse_params($st->{params});
        if (abs($par{POS} - $sim_z) > 4) {
#        print STDERR "Yikes, SIM mismatch!  \n";
#        print STDERR " self->{obsid} = $self->{obsid}\n";
#        print STDERR " sim_offset_z = $self->{SIM_OFFSET_Z}   SI = $self->{SI}\n";
#        print STDERR " st->{POS} = $par{POS}   sim_z = $sim_z   delta = ", $par{POS}-$sim_z,"\n";
                    # ACA-001
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
            push @{$self->{warn}}, "$alarm SIM position mismatch:  OR=$sim_z  BACKSTOP=$par{POS}\n";
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        }
        last;
        }
    }
    }
}

#############################################################################################
sub set_ok_no_starcat{
#############################################################################################

056: SIR ER has no target/maneuver [process]

id 056
title SIR ER has no target/maneuver
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1109
type process
severity info
aca_cl_id
note
orvdot No expected coverage due to removal of SIR concept (OK).

    my @yellow_warn = ();

    my $oflsid = $self->{dot_obsid};
    my $obsid = $self->{obsid};
    my $ok_no_starcat = $self->{ok_no_starcat};

   # Set slew error (arcsec) for this obsid, or 120 if not available
    my $slew_err;
    my $targquat;
    if ($targquat = find_command($self, "MP_TARGQUAT", -1)){
    $slew_err = $targquat->{man_err};
    }
    else{
    # if no target quaternion, warn and continue
    if (defined $ok_no_starcat){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
      push @{$self->{fyi}}, "$info No target/maneuver for obsid $obsid ($oflsid). OK for '$ok_no_starcat' ER. \n";
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    }
    else{
      push @{$self->{warn}}, "$alarm No target/maneuver for obsid $obsid ($oflsid). \n";
    }
    }
    $slew_err = 120 if not defined $slew_err;

    # ACA-004
    # if no starcat, warn and quit this subroutine
    unless ($c = find_command($self, "MP_STARCAT")) {

057: Observation has no target/maneuver [process]

id 057
title Observation has no target/maneuver
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1112
type process
severity red
aca_cl_id
note
orvdot

    my $obsid = $self->{obsid};
    my $ok_no_starcat = $self->{ok_no_starcat};

   # Set slew error (arcsec) for this obsid, or 120 if not available
    my $slew_err;
    my $targquat;
    if ($targquat = find_command($self, "MP_TARGQUAT", -1)){
    $slew_err = $targquat->{man_err};
    }
    else{
    # if no target quaternion, warn and continue
    if (defined $ok_no_starcat){
      push @{$self->{fyi}}, "$info No target/maneuver for obsid $obsid ($oflsid). OK for '$ok_no_starcat' ER. \n";
    }
    else{
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
      push @{$self->{warn}}, "$alarm No target/maneuver for obsid $obsid ($oflsid). \n";
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    }
    }
    $slew_err = 120 if not defined $slew_err;

    # ACA-004
    # if no starcat, warn and quit this subroutine
    unless ($c = find_command($self, "MP_STARCAT")) {
    if (defined $ok_no_starcat){
        push @{$self->{fyi}}, "$info No star catalog for obsid $obsid ($oflsid). OK for '$ok_no_starcat' ER. \n";
        return;

058: SIR ER has no star catalog [aca_check]

id 058
title SIR ER has no star catalog
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1121
type aca_check
severity info
aca_cl_id
note
orvdot No expected coverage due to removal of SIR concept (OK).

    else{
    # if no target quaternion, warn and continue
    if (defined $ok_no_starcat){
      push @{$self->{fyi}}, "$info No target/maneuver for obsid $obsid ($oflsid). OK for '$ok_no_starcat' ER. \n";
    }
    else{
      push @{$self->{warn}}, "$alarm No target/maneuver for obsid $obsid ($oflsid). \n";
    }
    }
    $slew_err = 120 if not defined $slew_err;

    # ACA-004
    # if no starcat, warn and quit this subroutine
    unless ($c = find_command($self, "MP_STARCAT")) {
    if (defined $ok_no_starcat){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @{$self->{fyi}}, "$info No star catalog for obsid $obsid ($oflsid). OK for '$ok_no_starcat' ER. \n";
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        return;
    }
    push @{$self->{warn}}, "$alarm No star catalog for obsid $obsid ($oflsid). \n";
    return;
    }
    # Reset the minimum number of guide stars if a monitor window is commanded
    $min_guide -= scalar grep { $c->{"TYPE$_"} eq 'MON' } (1..16);

    print STDERR "Checking star catalog for obsid $self->{obsid}\n";

059: Observation has no star catalog [aca_check]

id 059
title Observation has no star catalog
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1124
type aca_check
severity red
aca_cl_id 004
note
orvdot

      push @{$self->{fyi}}, "$info No target/maneuver for obsid $obsid ($oflsid). OK for '$ok_no_starcat' ER. \n";
    }
    else{
      push @{$self->{warn}}, "$alarm No target/maneuver for obsid $obsid ($oflsid). \n";
    }
    }
    $slew_err = 120 if not defined $slew_err;

    # ACA-004
    # if no starcat, warn and quit this subroutine
    unless ($c = find_command($self, "MP_STARCAT")) {
    if (defined $ok_no_starcat){
        push @{$self->{fyi}}, "$info No star catalog for obsid $obsid ($oflsid). OK for '$ok_no_starcat' ER. \n";
        return;
    }
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @{$self->{warn}}, "$alarm No star catalog for obsid $obsid ($oflsid). \n";
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    return;
    }
    # Reset the minimum number of guide stars if a monitor window is commanded
    $min_guide -= scalar grep { $c->{"TYPE$_"} eq 'MON' } (1..16);

    print STDERR "Checking star catalog for obsid $self->{obsid}\n";

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

060: Too few fid lights [aca_check]

id 060
title Too few fid lights
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1135
type aca_check
severity red
aca_cl_id 007
note
orvdot

    if (defined $ok_no_starcat){
        push @{$self->{fyi}}, "$info No star catalog for obsid $obsid ($oflsid). OK for '$ok_no_starcat' ER. \n";
        return;
    }
    push @{$self->{warn}}, "$alarm No star catalog for obsid $obsid ($oflsid). \n";
    return;
    }
    # Reset the minimum number of guide stars if a monitor window is commanded
    $min_guide -= scalar grep { $c->{"TYPE$_"} eq 'MON' } (1..16);

    print STDERR "Checking star catalog for obsid $self->{obsid}\n";

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

# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @warn,"$alarm Too Few Fid Lights\n" if (@{$self->{fid}} < $min_fid && $is_science);
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @warn,"$alarm Too Many Fid Lights\n" if ( (@{$self->{fid}} > 0 && $is_er) ||
                           (@{$self->{fid}} > $min_fid && $is_science) ) ;
    push @warn,"$alarm Too Few Acquisition Stars\n" if (@{$self->{acq}} < $min_acq);
    push @warn,"$alarm Too Few Guide Stars\n" if (@{$self->{gui}} < $min_guide);
    push @warn,"$alarm Too Many GUIDE + FID\n" if (@{$self->{gui}} + @{$self->{fid}} + @{$self->{mon}} > 8);
    push @warn,"$alarm Too Many Acquisition Stars\n" if (@{$self->{acq}} > 8);

    # Match positions of fids in star catalog with expected, and verify a one to one
    # correspondance between FIDSEL command and star catalog.
    # Skip this for vehicle-only loads since fids will be turned off.

061: Too many fid lights [aca_check]

id 061
title Too many fid lights
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1136
type aca_check
severity
aca_cl_id 007
note
orvdot

        push @{$self->{fyi}}, "$info No star catalog for obsid $obsid ($oflsid). OK for '$ok_no_starcat' ER. \n";
        return;
    }
    push @{$self->{warn}}, "$alarm No star catalog for obsid $obsid ($oflsid). \n";
    return;
    }
    # Reset the minimum number of guide stars if a monitor window is commanded
    $min_guide -= scalar grep { $c->{"TYPE$_"} eq 'MON' } (1..16);

    print STDERR "Checking star catalog for obsid $self->{obsid}\n";

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

    push @warn,"$alarm Too Few Fid Lights\n" if (@{$self->{fid}} < $min_fid && $is_science);
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @warn,"$alarm Too Many Fid Lights\n" if ( (@{$self->{fid}} > 0 && $is_er) ||
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
                           (@{$self->{fid}} > $min_fid && $is_science) ) ;
    push @warn,"$alarm Too Few Acquisition Stars\n" if (@{$self->{acq}} < $min_acq);
    push @warn,"$alarm Too Few Guide Stars\n" if (@{$self->{gui}} < $min_guide);
    push @warn,"$alarm Too Many GUIDE + FID\n" if (@{$self->{gui}} + @{$self->{fid}} + @{$self->{mon}} > 8);
    push @warn,"$alarm Too Many Acquisition Stars\n" if (@{$self->{acq}} > 8);

    # Match positions of fids in star catalog with expected, and verify a one to one
    # correspondance between FIDSEL command and star catalog.
    # Skip this for vehicle-only loads since fids will be turned off.
    check_fids($self, $c, \@warn) unless $vehicle;

062: Too few acquistion stars [aca_check]

id 062
title Too few acquistion stars
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1138
type aca_check
severity red
aca_cl_id 005
note
orvdot

    }
    push @{$self->{warn}}, "$alarm No star catalog for obsid $obsid ($oflsid). \n";
    return;
    }
    # Reset the minimum number of guide stars if a monitor window is commanded
    $min_guide -= scalar grep { $c->{"TYPE$_"} eq 'MON' } (1..16);

    print STDERR "Checking star catalog for obsid $self->{obsid}\n";

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

    push @warn,"$alarm Too Few Fid Lights\n" if (@{$self->{fid}} < $min_fid && $is_science);
    push @warn,"$alarm Too Many Fid Lights\n" if ( (@{$self->{fid}} > 0 && $is_er) ||
                           (@{$self->{fid}} > $min_fid && $is_science) ) ;
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @warn,"$alarm Too Few Acquisition Stars\n" if (@{$self->{acq}} < $min_acq);
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @warn,"$alarm Too Few Guide Stars\n" if (@{$self->{gui}} < $min_guide);
    push @warn,"$alarm Too Many GUIDE + FID\n" if (@{$self->{gui}} + @{$self->{fid}} + @{$self->{mon}} > 8);
    push @warn,"$alarm Too Many Acquisition Stars\n" if (@{$self->{acq}} > 8);

    # Match positions of fids in star catalog with expected, and verify a one to one
    # correspondance between FIDSEL command and star catalog.
    # Skip this for vehicle-only loads since fids will be turned off.
    check_fids($self, $c, \@warn) unless $vehicle;

    # store a list of the fid positions

063: Too few guide stars [aca_check]

id 063
title Too few guide stars
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1139
type aca_check
severity red
aca_cl_id 007,008
note
orvdot

    push @{$self->{warn}}, "$alarm No star catalog for obsid $obsid ($oflsid). \n";
    return;
    }
    # Reset the minimum number of guide stars if a monitor window is commanded
    $min_guide -= scalar grep { $c->{"TYPE$_"} eq 'MON' } (1..16);

    print STDERR "Checking star catalog for obsid $self->{obsid}\n";

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

    push @warn,"$alarm Too Few Fid Lights\n" if (@{$self->{fid}} < $min_fid && $is_science);
    push @warn,"$alarm Too Many Fid Lights\n" if ( (@{$self->{fid}} > 0 && $is_er) ||
                           (@{$self->{fid}} > $min_fid && $is_science) ) ;
    push @warn,"$alarm Too Few Acquisition Stars\n" if (@{$self->{acq}} < $min_acq);
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @warn,"$alarm Too Few Guide Stars\n" if (@{$self->{gui}} < $min_guide);
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @warn,"$alarm Too Many GUIDE + FID\n" if (@{$self->{gui}} + @{$self->{fid}} + @{$self->{mon}} > 8);
    push @warn,"$alarm Too Many Acquisition Stars\n" if (@{$self->{acq}} > 8);

    # Match positions of fids in star catalog with expected, and verify a one to one
    # correspondance between FIDSEL command and star catalog.
    # Skip this for vehicle-only loads since fids will be turned off.
    check_fids($self, $c, \@warn) unless $vehicle;

    # store a list of the fid positions
    my @fid_positions = map {{'y' => $c->{"YANG$_"}, 'z' => $c->{"ZANG$_"}}} @{$self->{fid}};

064: Too many guide + fid [aca_check]

id 064
title Too many guide + fid
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1140
type aca_check
severity red
aca_cl_id 006
note The warning and title should probably mention monitor windows.
orvdot

    return;
    }
    # Reset the minimum number of guide stars if a monitor window is commanded
    $min_guide -= scalar grep { $c->{"TYPE$_"} eq 'MON' } (1..16);

    print STDERR "Checking star catalog for obsid $self->{obsid}\n";

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

    push @warn,"$alarm Too Few Fid Lights\n" if (@{$self->{fid}} < $min_fid && $is_science);
    push @warn,"$alarm Too Many Fid Lights\n" if ( (@{$self->{fid}} > 0 && $is_er) ||
                           (@{$self->{fid}} > $min_fid && $is_science) ) ;
    push @warn,"$alarm Too Few Acquisition Stars\n" if (@{$self->{acq}} < $min_acq);
    push @warn,"$alarm Too Few Guide Stars\n" if (@{$self->{gui}} < $min_guide);
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @warn,"$alarm Too Many GUIDE + FID\n" if (@{$self->{gui}} + @{$self->{fid}} + @{$self->{mon}} > 8);
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @warn,"$alarm Too Many Acquisition Stars\n" if (@{$self->{acq}} > 8);

    # Match positions of fids in star catalog with expected, and verify a one to one
    # correspondance between FIDSEL command and star catalog.
    # Skip this for vehicle-only loads since fids will be turned off.
    check_fids($self, $c, \@warn) unless $vehicle;

    # store a list of the fid positions
    my @fid_positions = map {{'y' => $c->{"YANG$_"}, 'z' => $c->{"ZANG$_"}}} @{$self->{fid}};

065: Too many acquisition stars [aca_check]

id 065
title Too many acquisition stars
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1141
type aca_check
severity red
aca_cl_id 005
note
orvdot

    }
    # Reset the minimum number of guide stars if a monitor window is commanded
    $min_guide -= scalar grep { $c->{"TYPE$_"} eq 'MON' } (1..16);

    print STDERR "Checking star catalog for obsid $self->{obsid}\n";

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

    push @warn,"$alarm Too Few Fid Lights\n" if (@{$self->{fid}} < $min_fid && $is_science);
    push @warn,"$alarm Too Many Fid Lights\n" if ( (@{$self->{fid}} > 0 && $is_er) ||
                           (@{$self->{fid}} > $min_fid && $is_science) ) ;
    push @warn,"$alarm Too Few Acquisition Stars\n" if (@{$self->{acq}} < $min_acq);
    push @warn,"$alarm Too Few Guide Stars\n" if (@{$self->{gui}} < $min_guide);
    push @warn,"$alarm Too Many GUIDE + FID\n" if (@{$self->{gui}} + @{$self->{fid}} + @{$self->{mon}} > 8);
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @warn,"$alarm Too Many Acquisition Stars\n" if (@{$self->{acq}} > 8);
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX

    # Match positions of fids in star catalog with expected, and verify a one to one
    # correspondance between FIDSEL command and star catalog.
    # Skip this for vehicle-only loads since fids will be turned off.
    check_fids($self, $c, \@warn) unless $vehicle;

    # store a list of the fid positions
    my @fid_positions = map {{'y' => $c->{"YANG$_"}, 'z' => $c->{"ZANG$_"}}} @{$self->{fid}};

    foreach my $i (1..16) {

066: No AGASC star near search box center [aca_check]

id 066
title No AGASC star near search box center
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1177
type aca_check
severity red
aca_cl_id 043
note
orvdot

    my $search_err = ( (defined $type) and ($type =~ /BOT|ACQ/)) ? $slew_err : 4.0;

    # Find position extrema for smallest rectangle check
    if ( $type =~ /BOT|GUI/ ) {
        $max_y = ($max_y > $yag ) ? $max_y : $yag;
        $min_y = ($min_y < $yag ) ? $min_y : $yag;
        $max_z = ($max_z > $zag ) ? $max_z : $zag;
        $min_z = ($min_z < $zag ) ? $min_z : $zag;
    }
    next if ($type eq 'NUL');
    my $slot_dither = ($type =~ /FID/ ? 5.0 : $dither); # Pseudo-dither, depending on star or fid
    my $pix_slot_dither = $slot_dither / $ang_per_pix;

       # Warn if star not identified ACA-042
    if ( $type =~ /BOT|GUI|ACQ/ and not defined $c->{"GS_IDENTIFIED$i"}) {
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @warn, sprintf("$alarm [%2d] Missing Star. No AGASC star near search center \n", $i);
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    }

    # Warn if acquisition star has non-zero aspq1
    push @yellow_warn, sprintf "$alarm [%2d] Centroid Perturbation Warning.  %s: ASPQ1 = %2d\n",
    $i, $sid, $c->{"GS_ASPQ$i"}
    if ($type =~ /BOT|ACQ|GUI/ && defined $c->{"GS_ASPQ$i"} && $c->{"GS_ASPQ$i"} != 0);

    my $obs_min_cnt = 2;
    my $obs_bad_frac = 0.3;
    # Bad Acquisition Star

067: Centroid Perturbation warning [aca_check]

id 067
title Centroid Perturbation warning
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1181
type aca_check
severity yellow
aca_cl_id
note
orvdot

        $max_y = ($max_y > $yag ) ? $max_y : $yag;
        $min_y = ($min_y < $yag ) ? $min_y : $yag;
        $max_z = ($max_z > $zag ) ? $max_z : $zag;
        $min_z = ($min_z < $zag ) ? $min_z : $zag;
    }
    next if ($type eq 'NUL');
    my $slot_dither = ($type =~ /FID/ ? 5.0 : $dither); # Pseudo-dither, depending on star or fid
    my $pix_slot_dither = $slot_dither / $ang_per_pix;

       # Warn if star not identified ACA-042
    if ( $type =~ /BOT|GUI|ACQ/ and not defined $c->{"GS_IDENTIFIED$i"}) {
        push @warn, sprintf("$alarm [%2d] Missing Star. No AGASC star near search center \n", $i);
    }

    # Warn if acquisition star has non-zero aspq1
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @yellow_warn, sprintf "$alarm [%2d] Centroid Perturbation Warning.  %s: ASPQ1 = %2d\n",
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    $i, $sid, $c->{"GS_ASPQ$i"}
    if ($type =~ /BOT|ACQ|GUI/ && defined $c->{"GS_ASPQ$i"} && $c->{"GS_ASPQ$i"} != 0);

    my $obs_min_cnt = 2;
    my $obs_bad_frac = 0.3;
    # Bad Acquisition Star
    if ($type =~ /BOT|ACQ|GUI/){
    my $n_obs = $bad_acqs{$sid}{n_obs};
        my $n_noids = $bad_acqs{$sid}{n_noids};
        if (defined $db_stats->{acq}){

068: Acquisition star has failed N out of M attempts [aca_check]

id 068
title Acquisition star has failed N out of M attempts
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1196
type aca_check
severity yellow
aca_cl_id
note
orvdot

    push @yellow_warn, sprintf "$alarm [%2d] Centroid Perturbation Warning.  %s: ASPQ1 = %2d\n",
    $i, $sid, $c->{"GS_ASPQ$i"}
    if ($type =~ /BOT|ACQ|GUI/ && defined $c->{"GS_ASPQ$i"} && $c->{"GS_ASPQ$i"} != 0);

    my $obs_min_cnt = 2;
    my $obs_bad_frac = 0.3;
    # Bad Acquisition Star
    if ($type =~ /BOT|ACQ|GUI/){
    my $n_obs = $bad_acqs{$sid}{n_obs};
        my $n_noids = $bad_acqs{$sid}{n_noids};
        if (defined $db_stats->{acq}){
            $n_obs = $db_stats->{acq};
            $n_noids = $db_stats->{acq_noid};
        }
        if ($n_noids && $n_obs > $obs_min_cnt && $n_noids/$n_obs > $obs_bad_frac){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
            push @yellow_warn, sprintf
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        "$alarm [%2d] Bad Acquisition Star. %s has %2d failed out of %2d attempts\n",
        $i, $sid, $n_noids, $n_obs;
        }
    }

    # Bad Guide Star
    if ($type =~ /BOT|GUI/){
        my $n_obs = $bad_gui{$sid}{n_obs};
        my $n_nbad = $bad_gui{$sid}{n_nbad};
        if (defined $db_stats->{gui}){

069: Guide star has had bad data N out of M attempts [aca_check]

id 069
title Guide star has had bad data N out of M attempts
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1211
type aca_check
severity yellow
aca_cl_id
note
orvdot

            push @yellow_warn, sprintf
        "$alarm [%2d] Bad Acquisition Star. %s has %2d failed out of %2d attempts\n",
        $i, $sid, $n_noids, $n_obs;
        }
    }

    # Bad Guide Star
    if ($type =~ /BOT|GUI/){
        my $n_obs = $bad_gui{$sid}{n_obs};
        my $n_nbad = $bad_gui{$sid}{n_nbad};
        if (defined $db_stats->{gui}){
            $n_obs = $db_stats->{gui};
            $n_nbad = $db_stats->{gui_bad};
        }
        if ($n_nbad && $n_obs > $obs_min_cnt && $n_nbad/$n_obs > $obs_bad_frac){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
            push @yellow_warn, sprintf
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        "$alarm [%2d] Bad Guide Star. %s has bad data %2d of %2d attempts\n",
        $i, $sid, $n_nbad, $n_obs;
        }
    }

    # Bad AGASC ID ACA-031
    push @yellow_warn,sprintf "$alarm [%2d] Non-numeric AGASC ID.  %s\n",$i,$sid if ($sid ne '---' && $sid =~ /\D/);
    push @warn,sprintf "$alarm [%2d] Bad AGASC ID.  %s\n",$i,$sid if ($bad_id{$sid});

    # Set NOTES variable for marginal or bad star based on AGASC info

070: AGASC ID is non-numeric [aca_check]

id 070
title AGASC ID is non-numeric
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1218
type aca_check
severity yellow
aca_cl_id 042
note This hits 042 to some extent but is also a check on the guide summary completeness.
orvdot

    if ($type =~ /BOT|GUI/){
        my $n_obs = $bad_gui{$sid}{n_obs};
        my $n_nbad = $bad_gui{$sid}{n_nbad};
        if (defined $db_stats->{gui}){
            $n_obs = $db_stats->{gui};
            $n_nbad = $db_stats->{gui_bad};
        }
        if ($n_nbad && $n_obs > $obs_min_cnt && $n_nbad/$n_obs > $obs_bad_frac){
            push @yellow_warn, sprintf
        "$alarm [%2d] Bad Guide Star. %s has bad data %2d of %2d attempts\n",
        $i, $sid, $n_nbad, $n_obs;
        }
    }

    # Bad AGASC ID ACA-031
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @yellow_warn,sprintf "$alarm [%2d] Non-numeric AGASC ID.  %s\n",$i,$sid if ($sid ne '---' && $sid =~ /\D/);
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @warn,sprintf "$alarm [%2d] Bad AGASC ID.  %s\n",$i,$sid if ($bad_id{$sid});

    # Set NOTES variable for marginal or bad star based on AGASC info
    $c->{"GS_NOTES$i"} = '';
    my $note = '';
    my $marginal_note = '';
    if (defined $c->{"GS_CLASS$i"}) {
        $c->{"GS_NOTES$i"} .= 'b' if ($c->{"GS_CLASS$i"} != 0);
        # ignore precision errors in color
        my $color = sprintf('%.7f', $c->{"GS_BV$i"});

071: Star is in bad star list [aca_check]

id 071
title Star is in bad star list
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1219
type aca_check
severity red
aca_cl_id 031
note Fix the warning text since it is misleading.
orvdot

        my $n_obs = $bad_gui{$sid}{n_obs};
        my $n_nbad = $bad_gui{$sid}{n_nbad};
        if (defined $db_stats->{gui}){
            $n_obs = $db_stats->{gui};
            $n_nbad = $db_stats->{gui_bad};
        }
        if ($n_nbad && $n_obs > $obs_min_cnt && $n_nbad/$n_obs > $obs_bad_frac){
            push @yellow_warn, sprintf
        "$alarm [%2d] Bad Guide Star. %s has bad data %2d of %2d attempts\n",
        $i, $sid, $n_nbad, $n_obs;
        }
    }

    # Bad AGASC ID ACA-031
    push @yellow_warn,sprintf "$alarm [%2d] Non-numeric AGASC ID.  %s\n",$i,$sid if ($sid ne '---' && $sid =~ /\D/);
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @warn,sprintf "$alarm [%2d] Bad AGASC ID.  %s\n",$i,$sid if ($bad_id{$sid});
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX

    # Set NOTES variable for marginal or bad star based on AGASC info
    $c->{"GS_NOTES$i"} = '';
    my $note = '';
    my $marginal_note = '';
    if (defined $c->{"GS_CLASS$i"}) {
        $c->{"GS_NOTES$i"} .= 'b' if ($c->{"GS_CLASS$i"} != 0);
        # ignore precision errors in color
        my $color = sprintf('%.7f', $c->{"GS_BV$i"});
        $c->{"GS_NOTES$i"} .= 'c' if ($color eq '0.7000000'); # ACA-033

072: Marginal star (0.7 color on BOT or GUI) [aca_check]

id 072
title Marginal star (0.7 color on BOT or GUI)
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1241
type aca_check
severity red
aca_cl_id 033
note
orvdot

        $c->{"GS_NOTES$i"} .= 'b' if ($c->{"GS_CLASS$i"} != 0);
        # ignore precision errors in color
        my $color = sprintf('%.7f', $c->{"GS_BV$i"});
        $c->{"GS_NOTES$i"} .= 'c' if ($color eq '0.7000000'); # ACA-033
            $c->{"GS_NOTES$i"} .= 'C' if ($color eq '1.5000000') && ($mag > 10.0);
        $c->{"GS_NOTES$i"} .= 'm' if ($c->{"GS_MAGERR$i"} > 99);
        $c->{"GS_NOTES$i"} .= 'p' if ($c->{"GS_POSERR$i"} > 399);
        $note = sprintf("B-V = %.3f, Mag_Err = %.2f, Pos_Err = %.2f",
                            $c->{"GS_BV$i"}, ($c->{"GS_MAGERR$i"})/100, ($c->{"GS_POSERR$i"})/1000)
                if ($c->{"GS_NOTES$i"} =~ /[Ccmp]/);
        $marginal_note = sprintf("$alarm [%2d] Marginal star. %s\n",$i,$note) if ($c->{"GS_NOTES$i"} =~ /[^b]/);
            # for B-V = 0.7 and guide, red warnings
            # for all others, including (B-V = 1.5 and guide), yellow warning
            if ( $marginal_note ){
                if ($color eq '0.7000000' && $type =~ /BOT|GUI/ ) {
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
                    push @warn, $marginal_note;
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
                }
                else{
                    push @yellow_warn, $marginal_note;
                }
            }
        push @warn, sprintf("$alarm [%2d] Bad star.  Class = %s %s\n", $i,$c->{"GS_CLASS$i"},$note) if ($c->{"GS_NOTES$i"} =~ /b/);
    }

    # Star/fid outside of CCD boundaries
        # ACA-019 ACA-020 ACA-021

073: Marginal star (1.5 color or bad poserr or magerr) [aca_check]

id 073
title Marginal star (1.5 color or bad poserr or magerr)
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1244
type aca_check
severity yellow
aca_cl_id
note
orvdot

        $c->{"GS_NOTES$i"} .= 'c' if ($color eq '0.7000000'); # ACA-033
            $c->{"GS_NOTES$i"} .= 'C' if ($color eq '1.5000000') && ($mag > 10.0);
        $c->{"GS_NOTES$i"} .= 'm' if ($c->{"GS_MAGERR$i"} > 99);
        $c->{"GS_NOTES$i"} .= 'p' if ($c->{"GS_POSERR$i"} > 399);
        $note = sprintf("B-V = %.3f, Mag_Err = %.2f, Pos_Err = %.2f",
                            $c->{"GS_BV$i"}, ($c->{"GS_MAGERR$i"})/100, ($c->{"GS_POSERR$i"})/1000)
                if ($c->{"GS_NOTES$i"} =~ /[Ccmp]/);
        $marginal_note = sprintf("$alarm [%2d] Marginal star. %s\n",$i,$note) if ($c->{"GS_NOTES$i"} =~ /[^b]/);
            # for B-V = 0.7 and guide, red warnings
            # for all others, including (B-V = 1.5 and guide), yellow warning
            if ( $marginal_note ){
                if ($color eq '0.7000000' && $type =~ /BOT|GUI/ ) {
                    push @warn, $marginal_note;
                }
                else{
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
                    push @yellow_warn, $marginal_note;
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
                }
            }
        push @warn, sprintf("$alarm [%2d] Bad star.  Class = %s %s\n", $i,$c->{"GS_CLASS$i"},$note) if ($c->{"GS_NOTES$i"} =~ /b/);
    }

    # Star/fid outside of CCD boundaries
        # ACA-019 ACA-020 ACA-021
    my ($pixel_row, $pixel_col);
    eval{
        ($pixel_row, $pixel_col) = toPixels( $yag, $zag);

074: Bad star class [aca_check]

id 074
title Bad star class
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1247
type aca_check
severity red
aca_cl_id
note
orvdot

        $c->{"GS_NOTES$i"} .= 'p' if ($c->{"GS_POSERR$i"} > 399);
        $note = sprintf("B-V = %.3f, Mag_Err = %.2f, Pos_Err = %.2f",
                            $c->{"GS_BV$i"}, ($c->{"GS_MAGERR$i"})/100, ($c->{"GS_POSERR$i"})/1000)
                if ($c->{"GS_NOTES$i"} =~ /[Ccmp]/);
        $marginal_note = sprintf("$alarm [%2d] Marginal star. %s\n",$i,$note) if ($c->{"GS_NOTES$i"} =~ /[^b]/);
            # for B-V = 0.7 and guide, red warnings
            # for all others, including (B-V = 1.5 and guide), yellow warning
            if ( $marginal_note ){
                if ($color eq '0.7000000' && $type =~ /BOT|GUI/ ) {
                    push @warn, $marginal_note;
                }
                else{
                    push @yellow_warn, $marginal_note;
                }
            }
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @warn, sprintf("$alarm [%2d] Bad star.  Class = %s %s\n", $i,$c->{"GS_CLASS$i"},$note) if ($c->{"GS_NOTES$i"} =~ /b/);
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    }

    # Star/fid outside of CCD boundaries
        # ACA-019 ACA-020 ACA-021
    my ($pixel_row, $pixel_col);
    eval{
        ($pixel_row, $pixel_col) = toPixels( $yag, $zag);
        };

    # toPixels throws exception if angle off the CCD altogether

075: Star or Fid off CCD [aca_check]

id 075
title Star or Fid off CCD
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1261
type aca_check
severity red
aca_cl_id 019,020,021
note
orvdot

            }
        push @warn, sprintf("$alarm [%2d] Bad star.  Class = %s %s\n", $i,$c->{"GS_CLASS$i"},$note) if ($c->{"GS_NOTES$i"} =~ /b/);
    }

    # Star/fid outside of CCD boundaries
        # ACA-019 ACA-020 ACA-021
    my ($pixel_row, $pixel_col);
    eval{
        ($pixel_row, $pixel_col) = toPixels( $yag, $zag);
        };

    # toPixels throws exception if angle off the CCD altogether
    # respond to that one and warn on all others
    if ($@) {
        if ($@ =~ /.*Coordinate off of CCD.*/ ){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @warn, sprintf "$alarm [%2d] Angle Off CCD.\n",$i;
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        }
        else {
        push @warn, sprintf "$alarm [%2d] Boundary Checks failed. toPixels() said: $@ \n",$i,$i;
        }
    }
    else{
        if (   $pixel_row > $row_max - $pix_slot_dither || $pixel_row < $row_min + $pix_slot_dither
           || $pixel_col > $col_max - $pix_slot_dither || $pixel_col < $col_min + $pix_slot_dither) {
            push @warn,sprintf "$alarm [%2d] Angle Too Large.\n",$i;
        }

076: Code to calculate CCD position failed [code]

id 076
title Code to calculate CCD position failed
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1264
type code
severity red
aca_cl_id
note
orvdot


    # Star/fid outside of CCD boundaries
        # ACA-019 ACA-020 ACA-021
    my ($pixel_row, $pixel_col);
    eval{
        ($pixel_row, $pixel_col) = toPixels( $yag, $zag);
        };

    # toPixels throws exception if angle off the CCD altogether
    # respond to that one and warn on all others
    if ($@) {
        if ($@ =~ /.*Coordinate off of CCD.*/ ){
        push @warn, sprintf "$alarm [%2d] Angle Off CCD.\n",$i;
        }
        else {
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @warn, sprintf "$alarm [%2d] Boundary Checks failed. toPixels() said: $@ \n",$i,$i;
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        }
    }
    else{
        if (   $pixel_row > $row_max - $pix_slot_dither || $pixel_row < $row_min + $pix_slot_dither
           || $pixel_col > $col_max - $pix_slot_dither || $pixel_col < $col_min + $pix_slot_dither) {
            push @warn,sprintf "$alarm [%2d] Angle Too Large.\n",$i;
        }
    }

        # Quandrant boundary interference ACA-013 ACA-014 (and ACA-012 if it were actually a check)

077: Star or fid outside allowed CCD region [aca_check]

id 077
title Star or fid outside allowed CCD region
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1270
type aca_check
severity red
aca_cl_id 019,020,021
note
orvdot

        };

    # toPixels throws exception if angle off the CCD altogether
    # respond to that one and warn on all others
    if ($@) {
        if ($@ =~ /.*Coordinate off of CCD.*/ ){
        push @warn, sprintf "$alarm [%2d] Angle Off CCD.\n",$i;
        }
        else {
        push @warn, sprintf "$alarm [%2d] Boundary Checks failed. toPixels() said: $@ \n",$i,$i;
        }
    }
    else{
        if (   $pixel_row > $row_max - $pix_slot_dither || $pixel_row < $row_min + $pix_slot_dither
           || $pixel_col > $col_max - $pix_slot_dither || $pixel_col < $col_min + $pix_slot_dither) {
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
            push @warn,sprintf "$alarm [%2d] Angle Too Large.\n",$i;
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        }
    }

        # Quandrant boundary interference ACA-013 ACA-014 (and ACA-012 if it were actually a check)
    push @yellow_warn, sprintf "$alarm [%2d] Quadrant Boundary. \n",$i
        unless ($type eq 'ACQ' or $type eq 'MON' or
            (abs($yag-$y0) > $qb_dist + $slot_dither and abs($zag-$z0) > $qb_dist + $slot_dither ));

    # Faint and bright limits ~ACA-009 ACA-010
    if ($type ne 'MON' and $mag ne '---') {

078: Guide star or fid too close to quadrant boundary [aca_check]

id 078
title Guide star or fid too close to quadrant boundary
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1275
type aca_check
severity yellow
aca_cl_id 013,014
note
orvdot

        if ($@ =~ /.*Coordinate off of CCD.*/ ){
        push @warn, sprintf "$alarm [%2d] Angle Off CCD.\n",$i;
        }
        else {
        push @warn, sprintf "$alarm [%2d] Boundary Checks failed. toPixels() said: $@ \n",$i,$i;
        }
    }
    else{
        if (   $pixel_row > $row_max - $pix_slot_dither || $pixel_row < $row_min + $pix_slot_dither
           || $pixel_col > $col_max - $pix_slot_dither || $pixel_col < $col_min + $pix_slot_dither) {
            push @warn,sprintf "$alarm [%2d] Angle Too Large.\n",$i;
        }
    }

        # Quandrant boundary interference ACA-013 ACA-014 (and ACA-012 if it were actually a check)
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @yellow_warn, sprintf "$alarm [%2d] Quadrant Boundary. \n",$i
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        unless ($type eq 'ACQ' or $type eq 'MON' or
            (abs($yag-$y0) > $qb_dist + $slot_dither and abs($zag-$z0) > $qb_dist + $slot_dither ));

    # Faint and bright limits ~ACA-009 ACA-010
    if ($type ne 'MON' and $mag ne '---') {

            if (($type eq 'GUI' or $type eq 'BOT') and $mag > 10.3){
        push @warn, sprintf "$alarm [%2d] Magnitude. Guide star %6.3f\n",$i,$mag;
            }
        if ($mag < $mag_bright or $mag > $self->{mag_faint_red}) {

079: Star or Fid too bright or too faint (red limit) [aca_check]

id 079
title Star or Fid too bright or too faint (red limit)
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1286
type aca_check
severity red
aca_cl_id 009,010,011
note
orvdot

        }
    }

        # Quandrant boundary interference ACA-013 ACA-014 (and ACA-012 if it were actually a check)
    push @yellow_warn, sprintf "$alarm [%2d] Quadrant Boundary. \n",$i
        unless ($type eq 'ACQ' or $type eq 'MON' or
            (abs($yag-$y0) > $qb_dist + $slot_dither and abs($zag-$z0) > $qb_dist + $slot_dither ));

    # Faint and bright limits ~ACA-009 ACA-010
    if ($type ne 'MON' and $mag ne '---') {

            if (($type eq 'GUI' or $type eq 'BOT') and $mag > 10.3){
        push @warn, sprintf "$alarm [%2d] Magnitude. Guide star %6.3f\n",$i,$mag;
            }
        if ($mag < $mag_bright or $mag > $self->{mag_faint_red}) {
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @warn, sprintf "$alarm [%2d] Magnitude.  %6.3f\n",$i,$mag;
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        }
        elsif ($mag > $self->{mag_faint_yellow}) {
        push @yellow_warn, sprintf "$alarm [%2d] Magnitude.  %6.3f\n",$i,$mag;
        }

    }

    # FID magnitude limits ACA-011
    if ($type eq 'FID') {
        if ($mag =~ /---/ or $mag < $fid_bright or $mag > $fid_faint) {

080: Star or Fid too faint (yellow limit) [aca_check]

id 080
title Star or Fid too faint (yellow limit)
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1289
type aca_check
severity yellow
aca_cl_id 009,010,011
note
orvdot

        # Quandrant boundary interference ACA-013 ACA-014 (and ACA-012 if it were actually a check)
    push @yellow_warn, sprintf "$alarm [%2d] Quadrant Boundary. \n",$i
        unless ($type eq 'ACQ' or $type eq 'MON' or
            (abs($yag-$y0) > $qb_dist + $slot_dither and abs($zag-$z0) > $qb_dist + $slot_dither ));

    # Faint and bright limits ~ACA-009 ACA-010
    if ($type ne 'MON' and $mag ne '---') {

            if (($type eq 'GUI' or $type eq 'BOT') and $mag > 10.3){
        push @warn, sprintf "$alarm [%2d] Magnitude. Guide star %6.3f\n",$i,$mag;
            }
        if ($mag < $mag_bright or $mag > $self->{mag_faint_red}) {
        push @warn, sprintf "$alarm [%2d] Magnitude.  %6.3f\n",$i,$mag;
        }
        elsif ($mag > $self->{mag_faint_yellow}) {
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @yellow_warn, sprintf "$alarm [%2d] Magnitude.  %6.3f\n",$i,$mag;
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        }

    }

    # FID magnitude limits ACA-011
    if ($type eq 'FID') {
        if ($mag =~ /---/ or $mag < $fid_bright or $mag > $fid_faint) {
        push @warn, sprintf "$alarm [%2d] Magnitude.  %6.3f\n",$i, $mag =~ /---/ ? 0 : $mag;
        }
    }

081: Fid magnitude limit violation [aca_check]

id 081
title Fid magnitude limit violation
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1297
type aca_check
severity red
aca_cl_id 011
note
orvdot

            if (($type eq 'GUI' or $type eq 'BOT') and $mag > 10.3){
        push @warn, sprintf "$alarm [%2d] Magnitude. Guide star %6.3f\n",$i,$mag;
            }
        if ($mag < $mag_bright or $mag > $self->{mag_faint_red}) {
        push @warn, sprintf "$alarm [%2d] Magnitude.  %6.3f\n",$i,$mag;
        }
        elsif ($mag > $self->{mag_faint_yellow}) {
        push @yellow_warn, sprintf "$alarm [%2d] Magnitude.  %6.3f\n",$i,$mag;
        }

    }

    # FID magnitude limits ACA-011
    if ($type eq 'FID') {
        if ($mag =~ /---/ or $mag < $fid_bright or $mag > $fid_faint) {
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @warn, sprintf "$alarm [%2d] Magnitude.  %6.3f\n",$i, $mag =~ /---/ ? 0 : $mag;
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        }
    }

        # Check for situation that occurred for obsid 14577 with a fid light
        # inside the search box (PR #50).
        if ($type =~ /BOT|ACQ/){
            for my $fpos (@fid_positions){
                if (abs($fpos->{y} - $yag) < $halfw and abs($fpos->{z} - $zag) < $halfw){
                    if ($type =~ /ACQ/){
                        push @yellow_warn, sprintf "$alarm [%2d] Fid light in search box\n", $i;

082: Fid light in search box (acquisition star) [aca_check]

id 082
title Fid light in search box (acquisition star)
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1307
type aca_check
severity yellow
aca_cl_id
note
orvdot

    }

    # FID magnitude limits ACA-011
    if ($type eq 'FID') {
        if ($mag =~ /---/ or $mag < $fid_bright or $mag > $fid_faint) {
        push @warn, sprintf "$alarm [%2d] Magnitude.  %6.3f\n",$i, $mag =~ /---/ ? 0 : $mag;
        }
    }

        # Check for situation that occurred for obsid 14577 with a fid light
        # inside the search box (PR #50).
        if ($type =~ /BOT|ACQ/){
            for my $fpos (@fid_positions){
                if (abs($fpos->{y} - $yag) < $halfw and abs($fpos->{z} - $zag) < $halfw){
                    if ($type =~ /ACQ/){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
                        push @yellow_warn, sprintf "$alarm [%2d] Fid light in search box\n", $i;
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
                    }
                    else{
                        push @warn, sprintf "$alarm [%2d] Fid light in search box\n", $i;
                    }
                }
            }
        }

        # ACA-041
    if ($type =~ /BOT|GUI|ACQ/){

083: Fid light in search box (BOT) [aca_check]

id 083
title Fid light in search box (BOT)
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1310
type aca_check
severity red
aca_cl_id
note This is related to checklist 023, though the concern is that the fid light would be the spoiler
orvdot

    if ($type eq 'FID') {
        if ($mag =~ /---/ or $mag < $fid_bright or $mag > $fid_faint) {
        push @warn, sprintf "$alarm [%2d] Magnitude.  %6.3f\n",$i, $mag =~ /---/ ? 0 : $mag;
        }
    }

        # Check for situation that occurred for obsid 14577 with a fid light
        # inside the search box (PR #50).
        if ($type =~ /BOT|ACQ/){
            for my $fpos (@fid_positions){
                if (abs($fpos->{y} - $yag) < $halfw and abs($fpos->{z} - $zag) < $halfw){
                    if ($type =~ /ACQ/){
                        push @yellow_warn, sprintf "$alarm [%2d] Fid light in search box\n", $i;
                    }
                    else{
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
                        push @warn, sprintf "$alarm [%2d] Fid light in search box\n", $i;
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
                    }
                }
            }
        }

        # ACA-041
    if ($type =~ /BOT|GUI|ACQ/){
        if (( $maxmag =~ /---/) or ($mag =~ /---/)){
        push @warn, sprintf "$alarm [%2d] Magnitude.  MAG or MAGMAX not defined \n",$i;
        }

084: Star magnitude error. MAG or MAXMAG not defined [aca_check]

id 084
title Star magnitude error. MAG or MAXMAG not defined
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1319
type aca_check
severity red
aca_cl_id 032
note
orvdot

            for my $fpos (@fid_positions){
                if (abs($fpos->{y} - $yag) < $halfw and abs($fpos->{z} - $zag) < $halfw){
                    if ($type =~ /ACQ/){
                        push @yellow_warn, sprintf "$alarm [%2d] Fid light in search box\n", $i;
                    }
                    else{
                        push @warn, sprintf "$alarm [%2d] Fid light in search box\n", $i;
                    }
                }
            }
        }

        # ACA-041
    if ($type =~ /BOT|GUI|ACQ/){
        if (( $maxmag =~ /---/) or ($mag =~ /---/)){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @warn, sprintf "$alarm [%2d] Magnitude.  MAG or MAGMAX not defined \n",$i;
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        }
        else{
        if (($maxmag - $mag) < $mag_faint_slot_diff){
            my $slot_diff = $maxmag - $mag;
            push @warn, sprintf "$alarm [%2d] Magnitude.  MAXMAG - MAG = %1.2f < $mag_faint_slot_diff \n",$i,$slot_diff;
        }
        }
    }


085: Magnitude error. MAXMAG - MAG < required amount [aca_check]

id 085
title Magnitude error. MAXMAG - MAG < required amount
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1324
type aca_check
severity red
aca_cl_id 041
note
orvdot

                    else{
                        push @warn, sprintf "$alarm [%2d] Fid light in search box\n", $i;
                    }
                }
            }
        }

        # ACA-041
    if ($type =~ /BOT|GUI|ACQ/){
        if (( $maxmag =~ /---/) or ($mag =~ /---/)){
        push @warn, sprintf "$alarm [%2d] Magnitude.  MAG or MAGMAX not defined \n",$i;
        }
        else{
        if (($maxmag - $mag) < $mag_faint_slot_diff){
            my $slot_diff = $maxmag - $mag;
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
            push @warn, sprintf "$alarm [%2d] Magnitude.  MAXMAG - MAG = %1.2f < $mag_faint_slot_diff \n",$i,$slot_diff;
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        }
        }
    }


    # Search box too large ACA-018
    if ($type ne 'MON' and $c->{"HALFW$i"} > 200) {
        push @warn, sprintf "$alarm [%2d] Search Box Size. Search Box Too Large. \n",$i;
    }

086: Search box too large [aca_check]

id 086
title Search box too large
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1332
type aca_check
severity red
aca_cl_id 018
note
orvdot

    if ($type =~ /BOT|GUI|ACQ/){
        if (( $maxmag =~ /---/) or ($mag =~ /---/)){
        push @warn, sprintf "$alarm [%2d] Magnitude.  MAG or MAGMAX not defined \n",$i;
        }
        else{
        if (($maxmag - $mag) < $mag_faint_slot_diff){
            my $slot_diff = $maxmag - $mag;
            push @warn, sprintf "$alarm [%2d] Magnitude.  MAXMAG - MAG = %1.2f < $mag_faint_slot_diff \n",$i,$slot_diff;
        }
        }
    }


    # Search box too large ACA-018
    if ($type ne 'MON' and $c->{"HALFW$i"} > 200) {
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @warn, sprintf "$alarm [%2d] Search Box Size. Search Box Too Large. \n",$i;
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    }

    # ACQ/BOTH search box smaller than slew error ACA-015
    if (($type =~ /BOT|ACQ/) and $c->{"HALFW$i"} < $slew_err) {
        push @warn, sprintf "$alarm [%2d] Search Box Size. Search Box smaller than slew error \n",$i;
    }

        # Double check that 180 and 160 boxes are only applied to bright stars
        if (($type =~ /BOT|ACQ/) and ($c->{"HALFW$i"} > 160)
            and (($mag + $c->{"GS_MAGERR$i"} * 3 / 100) > 9.2)){

087: Search box smaller than maneuver error [aca_check]

id 087
title Search box smaller than maneuver error
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1337
type aca_check
severity red
aca_cl_id 015
note
orvdot

        if (($maxmag - $mag) < $mag_faint_slot_diff){
            my $slot_diff = $maxmag - $mag;
            push @warn, sprintf "$alarm [%2d] Magnitude.  MAXMAG - MAG = %1.2f < $mag_faint_slot_diff \n",$i,$slot_diff;
        }
        }
    }


    # Search box too large ACA-018
    if ($type ne 'MON' and $c->{"HALFW$i"} > 200) {
        push @warn, sprintf "$alarm [%2d] Search Box Size. Search Box Too Large. \n",$i;
    }

    # ACQ/BOTH search box smaller than slew error ACA-015
    if (($type =~ /BOT|ACQ/) and $c->{"HALFW$i"} < $slew_err) {
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @warn, sprintf "$alarm [%2d] Search Box Size. Search Box smaller than slew error \n",$i;
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    }

        # Double check that 180 and 160 boxes are only applied to bright stars
        if (($type =~ /BOT|ACQ/) and ($c->{"HALFW$i"} > 160)
            and (($mag + $c->{"GS_MAGERR$i"} * 3 / 100) > 9.2)){
            push @warn, sprintf "$alarm [%2d] Search Box Size. Star too faint for > 160 box. \n",$i;
        }
        if (($type =~ /BOT|ACQ/) and ($c->{"HALFW$i"} > 120)
            and (($mag + $c->{"GS_MAGERR$i"} * 1 / 100) > 10.2)){
            push @warn, sprintf "$alarm [%2d] Search Box Size. Star too faint for > 120 box. \n",$i;

088: Unexpected 8x8 readout size, MON in OR. GUI as MON? [aca_check]

id 088
title Unexpected 8x8 readout size, MON in OR. GUI as MON?
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1353
type aca_check
severity info
aca_cl_id 030,027
note
orvdot

    }

        # Double check that 180 and 160 boxes are only applied to bright stars
        if (($type =~ /BOT|ACQ/) and ($c->{"HALFW$i"} > 160)
            and (($mag + $c->{"GS_MAGERR$i"} * 3 / 100) > 9.2)){
            push @warn, sprintf "$alarm [%2d] Search Box Size. Star too faint for > 160 box. \n",$i;
        }
        if (($type =~ /BOT|ACQ/) and ($c->{"HALFW$i"} > 120)
            and (($mag + $c->{"GS_MAGERR$i"} * 1 / 100) > 10.2)){
            push @warn, sprintf "$alarm [%2d] Search Box Size. Star too faint for > 120 box. \n",$i;
        }

    # Check that readout sizes are all 6x6 for science observations ACA-027
    if ($is_science && $type =~ /BOT|GUI|ACQ/  && $c->{"SIZE$i"} ne "6x6"){
      if (($c->{"SIZE$i"} eq "8x8") and ($or->{HAS_MON}) and ($c->{"IMNUM$i"} == 7 )){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @{$self->{fyi}}, sprintf("$info [%2d] Readout Size. 8x8 Stealth MON?", $i);
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
      }
      else{
        push @warn, sprintf("$alarm [%2d] Readout Size. %s Should be 6x6\n", $i, $c->{"SIZE$i"});
      }
    }

    # Check that readout sizes are all 8x8 for engineering observations ACA-028
    if ($is_er && $type =~ /BOT|GUI|ACQ/  && $c->{"SIZE$i"} ne "8x8"){
        push @warn, sprintf("$alarm [%2d] Readout Size.  %s Should be 8x8\n", $i, $c->{"SIZE$i"});
    }

089: Readout size should be 6x6 (OR BOT/GUI/ACQ) [aca_check]

id 089
title Readout size should be 6x6 (OR BOT/GUI/ACQ)
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1356
type aca_check
severity red
aca_cl_id 027
note
orvdot

        if (($type =~ /BOT|ACQ/) and ($c->{"HALFW$i"} > 160)
            and (($mag + $c->{"GS_MAGERR$i"} * 3 / 100) > 9.2)){
            push @warn, sprintf "$alarm [%2d] Search Box Size. Star too faint for > 160 box. \n",$i;
        }
        if (($type =~ /BOT|ACQ/) and ($c->{"HALFW$i"} > 120)
            and (($mag + $c->{"GS_MAGERR$i"} * 1 / 100) > 10.2)){
            push @warn, sprintf "$alarm [%2d] Search Box Size. Star too faint for > 120 box. \n",$i;
        }

    # Check that readout sizes are all 6x6 for science observations ACA-027
    if ($is_science && $type =~ /BOT|GUI|ACQ/  && $c->{"SIZE$i"} ne "6x6"){
      if (($c->{"SIZE$i"} eq "8x8") and ($or->{HAS_MON}) and ($c->{"IMNUM$i"} == 7 )){
        push @{$self->{fyi}}, sprintf("$info [%2d] Readout Size. 8x8 Stealth MON?", $i);
      }
      else{
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @warn, sprintf("$alarm [%2d] Readout Size. %s Should be 6x6\n", $i, $c->{"SIZE$i"});
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
      }
    }

    # Check that readout sizes are all 8x8 for engineering observations ACA-028
    if ($is_er && $type =~ /BOT|GUI|ACQ/  && $c->{"SIZE$i"} ne "8x8"){
        push @warn, sprintf("$alarm [%2d] Readout Size.  %s Should be 8x8\n", $i, $c->{"SIZE$i"});
    }

    # Check that readout sizes are all 8x8 for FID lights ACA-029
    push @warn, sprintf("$alarm [%2d] Readout Size.  %s Should be 8x8\n", $i, $c->{"SIZE$i"})

090: Readout size should be 8x8 (ER BOT/GUI/ACQ) [aca_check]

id 090
title Readout size should be 8x8 (ER BOT/GUI/ACQ)
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1362
type aca_check
severity red
aca_cl_id 028
note
orvdot

            push @warn, sprintf "$alarm [%2d] Search Box Size. Star too faint for > 120 box. \n",$i;
        }

    # Check that readout sizes are all 6x6 for science observations ACA-027
    if ($is_science && $type =~ /BOT|GUI|ACQ/  && $c->{"SIZE$i"} ne "6x6"){
      if (($c->{"SIZE$i"} eq "8x8") and ($or->{HAS_MON}) and ($c->{"IMNUM$i"} == 7 )){
        push @{$self->{fyi}}, sprintf("$info [%2d] Readout Size. 8x8 Stealth MON?", $i);
      }
      else{
        push @warn, sprintf("$alarm [%2d] Readout Size. %s Should be 6x6\n", $i, $c->{"SIZE$i"});
      }
    }

    # Check that readout sizes are all 8x8 for engineering observations ACA-028
    if ($is_er && $type =~ /BOT|GUI|ACQ/  && $c->{"SIZE$i"} ne "8x8"){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @warn, sprintf("$alarm [%2d] Readout Size.  %s Should be 8x8\n", $i, $c->{"SIZE$i"});
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    }

    # Check that readout sizes are all 8x8 for FID lights ACA-029
    push @warn, sprintf("$alarm [%2d] Readout Size.  %s Should be 8x8\n", $i, $c->{"SIZE$i"})
        if ($type =~ /FID/  && $c->{"SIZE$i"} ne "8x8");

    # Check that readout size is 8x8 for monitor windows ACA-030
    push @warn, sprintf("$alarm [%2d] Readout Size. %s Should be 8x8\n", $i, $c->{"SIZE$i"})
        if ($type =~ /MON/  && $c->{"SIZE$i"} ne "8x8");

091: Readout size should be 8x8 (FID) [aca_check]

id 091
title Readout size should be 8x8 (FID)
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1366
type aca_check
severity red
aca_cl_id 029
note
orvdot

    if ($is_science && $type =~ /BOT|GUI|ACQ/  && $c->{"SIZE$i"} ne "6x6"){
      if (($c->{"SIZE$i"} eq "8x8") and ($or->{HAS_MON}) and ($c->{"IMNUM$i"} == 7 )){
        push @{$self->{fyi}}, sprintf("$info [%2d] Readout Size. 8x8 Stealth MON?", $i);
      }
      else{
        push @warn, sprintf("$alarm [%2d] Readout Size. %s Should be 6x6\n", $i, $c->{"SIZE$i"});
      }
    }

    # Check that readout sizes are all 8x8 for engineering observations ACA-028
    if ($is_er && $type =~ /BOT|GUI|ACQ/  && $c->{"SIZE$i"} ne "8x8"){
        push @warn, sprintf("$alarm [%2d] Readout Size.  %s Should be 8x8\n", $i, $c->{"SIZE$i"});
    }

    # Check that readout sizes are all 8x8 for FID lights ACA-029
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @warn, sprintf("$alarm [%2d] Readout Size.  %s Should be 8x8\n", $i, $c->{"SIZE$i"})
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        if ($type =~ /FID/  && $c->{"SIZE$i"} ne "8x8");

    # Check that readout size is 8x8 for monitor windows ACA-030
    push @warn, sprintf("$alarm [%2d] Readout Size. %s Should be 8x8\n", $i, $c->{"SIZE$i"})
        if ($type =~ /MON/  && $c->{"SIZE$i"} ne "8x8");


    # Bad Pixels ACA-025
        my @close_pixels;
        my @dr;

092: Readout size should be 8x8 (MON) [aca_check]

id 092
title Readout size should be 8x8 (MON)
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1370
type aca_check
severity red
aca_cl_id 030
note
orvdot

      else{
        push @warn, sprintf("$alarm [%2d] Readout Size. %s Should be 6x6\n", $i, $c->{"SIZE$i"});
      }
    }

    # Check that readout sizes are all 8x8 for engineering observations ACA-028
    if ($is_er && $type =~ /BOT|GUI|ACQ/  && $c->{"SIZE$i"} ne "8x8"){
        push @warn, sprintf("$alarm [%2d] Readout Size.  %s Should be 8x8\n", $i, $c->{"SIZE$i"});
    }

    # Check that readout sizes are all 8x8 for FID lights ACA-029
    push @warn, sprintf("$alarm [%2d] Readout Size.  %s Should be 8x8\n", $i, $c->{"SIZE$i"})
        if ($type =~ /FID/  && $c->{"SIZE$i"} ne "8x8");

    # Check that readout size is 8x8 for monitor windows ACA-030
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @warn, sprintf("$alarm [%2d] Readout Size. %s Should be 8x8\n", $i, $c->{"SIZE$i"})
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        if ($type =~ /MON/  && $c->{"SIZE$i"} ne "8x8");


    # Bad Pixels ACA-025
        my @close_pixels;
        my @dr;
    if ($type ne 'ACQ' and $c->{"GS_PASS$i"} =~ /^1|\s+|g[1-2]/) {
        foreach my $pixel (@bad_pixels) {
        my $dy = abs($yag-$pixel->{yag});
        my $dz = abs($zag-$pixel->{zag});

093: Nearby ACA bad pixel [aca_check]

id 093
title Nearby ACA bad pixel
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1388
type aca_check
severity red
aca_cl_id 025
note
orvdot


    # Bad Pixels ACA-025
        my @close_pixels;
        my @dr;
    if ($type ne 'ACQ' and $c->{"GS_PASS$i"} =~ /^1|\s+|g[1-2]/) {
        foreach my $pixel (@bad_pixels) {
        my $dy = abs($yag-$pixel->{yag});
        my $dz = abs($zag-$pixel->{zag});
        my $dr = sqrt($dy**2 + $dz**2);
        next unless ( $dz < $dither+25 and $dy < $dither+25 );
        push @close_pixels, sprintf("%3d, %3d, %3d\n", $dy, $dz, $dr);
        push @dr, $dr;
        }
        if ( @close_pixels > 0 ) {
        my ($closest) = sort { $dr[$a] <=> $dr[$b] } (0 .. $#dr);
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        my $warn = sprintf("$alarm [%2d] Nearby ACA bad pixel. " .
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
                   "Y,Z,Radial seps: " . $close_pixels[$closest],
                   $i); #Only warn for the closest pixel
        push @warn, $warn;
        }
    }

    # Spoiler star (for search) and common column

    foreach my $star (values %{$self->{agasc_hash}}) {
            # Skip tests if $star is the same as the catalog star

094: Really part of '093' [code]

id 094
title Really part of '093'
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1391
type code
severity red
aca_cl_id
note
orvdot

        my @dr;
    if ($type ne 'ACQ' and $c->{"GS_PASS$i"} =~ /^1|\s+|g[1-2]/) {
        foreach my $pixel (@bad_pixels) {
        my $dy = abs($yag-$pixel->{yag});
        my $dz = abs($zag-$pixel->{zag});
        my $dr = sqrt($dy**2 + $dz**2);
        next unless ( $dz < $dither+25 and $dy < $dither+25 );
        push @close_pixels, sprintf("%3d, %3d, %3d\n", $dy, $dz, $dr);
        push @dr, $dr;
        }
        if ( @close_pixels > 0 ) {
        my ($closest) = sort { $dr[$a] <=> $dr[$b] } (0 .. $#dr);
        my $warn = sprintf("$alarm [%2d] Nearby ACA bad pixel. " .
                   "Y,Z,Radial seps: " . $close_pixels[$closest],
                   $i); #Only warn for the closest pixel
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @warn, $warn;
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        }
    }

    # Spoiler star (for search) and common column

    foreach my $star (values %{$self->{agasc_hash}}) {
            # Skip tests if $star is the same as the catalog star
        next if (  $star->{id} eq $sid ||
               ( abs($star->{yag} - $yag) < $ID_DIST_LIMIT
             && abs($star->{zag} - $zag) < $ID_DIST_LIMIT

095: Text for warning that is used in '096' or '097' [code]

id 095
title Text for warning that is used in '096' or '097'
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1413
type code
severity red
aca_cl_id
note
orvdot

            # Skip tests if $star is the same as the catalog star
        next if (  $star->{id} eq $sid ||
               ( abs($star->{yag} - $yag) < $ID_DIST_LIMIT
             && abs($star->{zag} - $zag) < $ID_DIST_LIMIT
             && abs($star->{mag_aca} - $mag) < 0.1 ) );
        my $dy = abs($yag-$star->{yag});
        my $dz = abs($zag-$star->{zag});
        my $dr = sqrt($dz**2 + $dy**2);
        my $dm = $mag ne '---' ? $mag - $star->{mag_aca} : 0.0;
        my $dm_string = $mag ne '---' ? sprintf("%4.1f", $mag - $star->{mag_aca}) : '?';

        # Fid within $dither + 25 arcsec of a star (yellow) and within 4 mags (red) ACA-024
        if ($type eq 'FID'
        and $dz < $dither+25 and $dy < $dither+25
        and $dm > -5.0) {
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        my $warn = sprintf("$alarm [%2d] Fid spoiler.  %10d: " .
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
                   "Y,Z,Radial,Mag seps: %3d %3d %3d %4s\n",$i,$star->{id},$dy,$dz,$dr,$dm_string);
        if ($dm > -4.0)  { push @warn, $warn }
        else { push @yellow_warn, $warn }
        }

        # Star within search box + search error and within 1.0 mags
        if ($type ne 'MON' and $dz < $halfw + $search_err and $dy < $halfw + $search_err and $dm > -1.0) {
        my $warn = sprintf("$alarm [%2d] Search spoiler. %10d: " .
                   "Y,Z,Radial,Mag seps: %3d %3d %3d %4s\n",$i,$star->{id},$dy,$dz,$dr,$dm_string);
        if ($dm > -0.2)  { push @warn, $warn } # ACA-022 ACA-023

096: Fid spoiler [aca_check]

id 096
title Fid spoiler
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1415
type aca_check
severity red
aca_cl_id 024
note
orvdot

               ( abs($star->{yag} - $yag) < $ID_DIST_LIMIT
             && abs($star->{zag} - $zag) < $ID_DIST_LIMIT
             && abs($star->{mag_aca} - $mag) < 0.1 ) );
        my $dy = abs($yag-$star->{yag});
        my $dz = abs($zag-$star->{zag});
        my $dr = sqrt($dz**2 + $dy**2);
        my $dm = $mag ne '---' ? $mag - $star->{mag_aca} : 0.0;
        my $dm_string = $mag ne '---' ? sprintf("%4.1f", $mag - $star->{mag_aca}) : '?';

        # Fid within $dither + 25 arcsec of a star (yellow) and within 4 mags (red) ACA-024
        if ($type eq 'FID'
        and $dz < $dither+25 and $dy < $dither+25
        and $dm > -5.0) {
        my $warn = sprintf("$alarm [%2d] Fid spoiler.  %10d: " .
                   "Y,Z,Radial,Mag seps: %3d %3d %3d %4s\n",$i,$star->{id},$dy,$dz,$dr,$dm_string);
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        if ($dm > -4.0)  { push @warn, $warn }
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        else { push @yellow_warn, $warn }
        }

        # Star within search box + search error and within 1.0 mags
        if ($type ne 'MON' and $dz < $halfw + $search_err and $dy < $halfw + $search_err and $dm > -1.0) {
        my $warn = sprintf("$alarm [%2d] Search spoiler. %10d: " .
                   "Y,Z,Radial,Mag seps: %3d %3d %3d %4s\n",$i,$star->{id},$dy,$dz,$dr,$dm_string);
        if ($dm > -0.2)  { push @warn, $warn } # ACA-022 ACA-023
        else { push @yellow_warn, $warn }
        }

097: Fid spoiler [aca_check]

id 097
title Fid spoiler
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1416
type aca_check
severity yellow
aca_cl_id
note
orvdot

             && abs($star->{zag} - $zag) < $ID_DIST_LIMIT
             && abs($star->{mag_aca} - $mag) < 0.1 ) );
        my $dy = abs($yag-$star->{yag});
        my $dz = abs($zag-$star->{zag});
        my $dr = sqrt($dz**2 + $dy**2);
        my $dm = $mag ne '---' ? $mag - $star->{mag_aca} : 0.0;
        my $dm_string = $mag ne '---' ? sprintf("%4.1f", $mag - $star->{mag_aca}) : '?';

        # Fid within $dither + 25 arcsec of a star (yellow) and within 4 mags (red) ACA-024
        if ($type eq 'FID'
        and $dz < $dither+25 and $dy < $dither+25
        and $dm > -5.0) {
        my $warn = sprintf("$alarm [%2d] Fid spoiler.  %10d: " .
                   "Y,Z,Radial,Mag seps: %3d %3d %3d %4s\n",$i,$star->{id},$dy,$dz,$dr,$dm_string);
        if ($dm > -4.0)  { push @warn, $warn }
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        else { push @yellow_warn, $warn }
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        }

        # Star within search box + search error and within 1.0 mags
        if ($type ne 'MON' and $dz < $halfw + $search_err and $dy < $halfw + $search_err and $dm > -1.0) {
        my $warn = sprintf("$alarm [%2d] Search spoiler. %10d: " .
                   "Y,Z,Radial,Mag seps: %3d %3d %3d %4s\n",$i,$star->{id},$dy,$dz,$dr,$dm_string);
        if ($dm > -0.2)  { push @warn, $warn } # ACA-022 ACA-023
        else { push @yellow_warn, $warn }
        }
        # Common column: dz within limit, spoiler is $col_sep_mag brighter than star,

098: Warning text for '099' and '100' [code]

id 098
title Warning text for '099' and '100'
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1421
type code
severity
aca_cl_id
note
orvdot

        my $dm = $mag ne '---' ? $mag - $star->{mag_aca} : 0.0;
        my $dm_string = $mag ne '---' ? sprintf("%4.1f", $mag - $star->{mag_aca}) : '?';

        # Fid within $dither + 25 arcsec of a star (yellow) and within 4 mags (red) ACA-024
        if ($type eq 'FID'
        and $dz < $dither+25 and $dy < $dither+25
        and $dm > -5.0) {
        my $warn = sprintf("$alarm [%2d] Fid spoiler.  %10d: " .
                   "Y,Z,Radial,Mag seps: %3d %3d %3d %4s\n",$i,$star->{id},$dy,$dz,$dr,$dm_string);
        if ($dm > -4.0)  { push @warn, $warn }
        else { push @yellow_warn, $warn }
        }

        # Star within search box + search error and within 1.0 mags
        if ($type ne 'MON' and $dz < $halfw + $search_err and $dy < $halfw + $search_err and $dm > -1.0) {
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        my $warn = sprintf("$alarm [%2d] Search spoiler. %10d: " .
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
                   "Y,Z,Radial,Mag seps: %3d %3d %3d %4s\n",$i,$star->{id},$dy,$dz,$dr,$dm_string);
        if ($dm > -0.2)  { push @warn, $warn } # ACA-022 ACA-023
        else { push @yellow_warn, $warn }
        }
        # Common column: dz within limit, spoiler is $col_sep_mag brighter than star,
        # and spoiler is located between star and readout ACA-026
        if ($type ne 'MON'
        and $dz < $col_sep_dist
        and $dm > $col_sep_mag
        and ($star->{yag}/$yag) > 1.0

099: Search spoiler [aca_check]

id 099
title Search spoiler
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1423
type aca_check
severity red
aca_cl_id 022,023
note
orvdot


        # Fid within $dither + 25 arcsec of a star (yellow) and within 4 mags (red) ACA-024
        if ($type eq 'FID'
        and $dz < $dither+25 and $dy < $dither+25
        and $dm > -5.0) {
        my $warn = sprintf("$alarm [%2d] Fid spoiler.  %10d: " .
                   "Y,Z,Radial,Mag seps: %3d %3d %3d %4s\n",$i,$star->{id},$dy,$dz,$dr,$dm_string);
        if ($dm > -4.0)  { push @warn, $warn }
        else { push @yellow_warn, $warn }
        }

        # Star within search box + search error and within 1.0 mags
        if ($type ne 'MON' and $dz < $halfw + $search_err and $dy < $halfw + $search_err and $dm > -1.0) {
        my $warn = sprintf("$alarm [%2d] Search spoiler. %10d: " .
                   "Y,Z,Radial,Mag seps: %3d %3d %3d %4s\n",$i,$star->{id},$dy,$dz,$dr,$dm_string);
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        if ($dm > -0.2)  { push @warn, $warn } # ACA-022 ACA-023
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        else { push @yellow_warn, $warn }
        }
        # Common column: dz within limit, spoiler is $col_sep_mag brighter than star,
        # and spoiler is located between star and readout ACA-026
        if ($type ne 'MON'
        and $dz < $col_sep_dist
        and $dm > $col_sep_mag
        and ($star->{yag}/$yag) > 1.0
        and abs($star->{yag}) < 2500) {
        push @warn,sprintf("$alarm [%2d] Common Column. %10d " .

100: Search spoiler [aca_check]

id 100
title Search spoiler
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1424
type aca_check
severity yellow
aca_cl_id
note
orvdot

        # Fid within $dither + 25 arcsec of a star (yellow) and within 4 mags (red) ACA-024
        if ($type eq 'FID'
        and $dz < $dither+25 and $dy < $dither+25
        and $dm > -5.0) {
        my $warn = sprintf("$alarm [%2d] Fid spoiler.  %10d: " .
                   "Y,Z,Radial,Mag seps: %3d %3d %3d %4s\n",$i,$star->{id},$dy,$dz,$dr,$dm_string);
        if ($dm > -4.0)  { push @warn, $warn }
        else { push @yellow_warn, $warn }
        }

        # Star within search box + search error and within 1.0 mags
        if ($type ne 'MON' and $dz < $halfw + $search_err and $dy < $halfw + $search_err and $dm > -1.0) {
        my $warn = sprintf("$alarm [%2d] Search spoiler. %10d: " .
                   "Y,Z,Radial,Mag seps: %3d %3d %3d %4s\n",$i,$star->{id},$dy,$dz,$dr,$dm_string);
        if ($dm > -0.2)  { push @warn, $warn } # ACA-022 ACA-023
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        else { push @yellow_warn, $warn }
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        }
        # Common column: dz within limit, spoiler is $col_sep_mag brighter than star,
        # and spoiler is located between star and readout ACA-026
        if ($type ne 'MON'
        and $dz < $col_sep_dist
        and $dm > $col_sep_mag
        and ($star->{yag}/$yag) > 1.0
        and abs($star->{yag}) < 2500) {
        push @warn,sprintf("$alarm [%2d] Common Column. %10d " .
                   "at Y,Z,Mag: %5d %5d %5.2f\n",$i,$star->{id},$star->{yag},$star->{zag},$star->{mag_aca});

101: Common column [aca_check]

id 101
title Common column
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1433
type aca_check
severity red
aca_cl_id 026
note
orvdot


        # Star within search box + search error and within 1.0 mags
        if ($type ne 'MON' and $dz < $halfw + $search_err and $dy < $halfw + $search_err and $dm > -1.0) {
        my $warn = sprintf("$alarm [%2d] Search spoiler. %10d: " .
                   "Y,Z,Radial,Mag seps: %3d %3d %3d %4s\n",$i,$star->{id},$dy,$dz,$dr,$dm_string);
        if ($dm > -0.2)  { push @warn, $warn } # ACA-022 ACA-023
        else { push @yellow_warn, $warn }
        }
        # Common column: dz within limit, spoiler is $col_sep_mag brighter than star,
        # and spoiler is located between star and readout ACA-026
        if ($type ne 'MON'
        and $dz < $col_sep_dist
        and $dm > $col_sep_mag
        and ($star->{yag}/$yag) > 1.0
        and abs($star->{yag}) < 2500) {
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @warn,sprintf("$alarm [%2d] Common Column. %10d " .
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
                   "at Y,Z,Mag: %5d %5d %5.2f\n",$i,$star->{id},$star->{yag},$star->{zag},$star->{mag_aca});
        }
    }
    }



# Find the smallest rectangle size that all acq stars fit in
    my $y_side = sprintf( "%.0f", $max_y - $min_y );
    my $z_side = sprintf( "%.0f", $max_z - $min_z );

102: Small box warning for checks '103' and '104' [code]

id 102
title Small box warning for checks '103' and '104'
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1444
type code
severity yellow
aca_cl_id
note
orvdot

        and $dz < $col_sep_dist
        and $dm > $col_sep_mag
        and ($star->{yag}/$yag) > 1.0
        and abs($star->{yag}) < 2500) {
        push @warn,sprintf("$alarm [%2d] Common Column. %10d " .
                   "at Y,Z,Mag: %5d %5d %5.2f\n",$i,$star->{id},$star->{yag},$star->{zag},$star->{mag_aca});
        }
    }
    }



# Find the smallest rectangle size that all acq stars fit in
    my $y_side = sprintf( "%.0f", $max_y - $min_y );
    my $z_side = sprintf( "%.0f", $max_z - $min_z );
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @yellow_warn, "$alarm Guide stars fit in $y_side x $z_side square arc-second box\n"
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    if $y_side < $min_y_side && $z_side < $min_z_side;

    # Collect warnings
    push @{$self->{warn}}, @warn;
    push @{$self->{yellow_warn}}, @yellow_warn;
}

#############################################################################################
sub check_flick_pix_mon {
#############################################################################################

103: Guide stars fit in small box (red warning) [aca_check]

id 103
title Guide stars fit in small box (red warning)
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1448
type aca_check
severity red
aca_cl_id
note
orvdot

        push @warn,sprintf("$alarm [%2d] Common Column. %10d " .
                   "at Y,Z,Mag: %5d %5d %5.2f\n",$i,$star->{id},$star->{yag},$star->{zag},$star->{mag_aca});
        }
    }
    }



# Find the smallest rectangle size that all acq stars fit in
    my $y_side = sprintf( "%.0f", $max_y - $min_y );
    my $z_side = sprintf( "%.0f", $max_z - $min_z );
    push @yellow_warn, "$alarm Guide stars fit in $y_side x $z_side square arc-second box\n"
    if $y_side < $min_y_side && $z_side < $min_z_side;

    # Collect warnings
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @{$self->{warn}}, @warn;
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @{$self->{yellow_warn}}, @yellow_warn;
}

#############################################################################################
sub check_flick_pix_mon {
#############################################################################################
    my $self = shift;

    # this only applies to ERs (and they should have numeric obsids)
    return unless ( $self->{obsid} =~ /^\d+$/ and $self->{obsid} >= $ER_MIN_OBSID );

104: Guide stars fit in small box (yellow warning) [code]

id 104
title Guide stars fit in small box (yellow warning)
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1449
type code
severity yellow
aca_cl_id
note
orvdot

                   "at Y,Z,Mag: %5d %5d %5.2f\n",$i,$star->{id},$star->{yag},$star->{zag},$star->{mag_aca});
        }
    }
    }



# Find the smallest rectangle size that all acq stars fit in
    my $y_side = sprintf( "%.0f", $max_y - $min_y );
    my $z_side = sprintf( "%.0f", $max_z - $min_z );
    push @yellow_warn, "$alarm Guide stars fit in $y_side x $z_side square arc-second box\n"
    if $y_side < $min_y_side && $z_side < $min_z_side;

    # Collect warnings
    push @{$self->{warn}}, @warn;
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @{$self->{yellow_warn}}, @yellow_warn;
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
}

#############################################################################################
sub check_flick_pix_mon {
#############################################################################################
    my $self = shift;

    # this only applies to ERs (and they should have numeric obsids)
    return unless ( $self->{obsid} =~ /^\d+$/ and $self->{obsid} >= $ER_MIN_OBSID );

105: Obsid has flickering pixel MON window [aca_check]

id 105
title Obsid has flickering pixel MON window
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1470
type aca_check
severity info
aca_cl_id
note
orvdot

    my $self = shift;

    # this only applies to ERs (and they should have numeric obsids)
    return unless ( $self->{obsid} =~ /^\d+$/ and $self->{obsid} >= $ER_MIN_OBSID );

    my $c;
    # Check for existence of a star catalog
    return unless ($c = find_command($self, "MP_STARCAT"));

    # See if there are any monitor stars.  Return if not.
    my @mon_stars = grep { $c->{"TYPE$_"} eq 'MON' } (1..16);
    return unless (@mon_stars);

    for my $mon_star (@mon_stars){

# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @{$self->{fyi}}, sprintf("$info Obsid contains flickering pixel MON\n", $mon_star);
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX


    push @{$self->{warn}}, sprintf("$alarm [%2d] Monitor Commanding. Size is not 8x8\n", $mon_star)
        unless $c->{"SIZE${mon_star}"} eq "8x8";

    push @{$self->{warn}}, sprintf("$alarm [%2d] Monitor Commanding. Monitor Window RESTRK should be 0\n", $mon_star)
        unless $c->{"RESTRK${mon_star}"} == 0;

        # Verify the DTS is set to self
    push @{$self->{warn}}, sprintf("$alarm [%2d] Monitor Commanding. DTS should be set to self\n", $mon_star)

106: Flickering Pixel Monitor window not 8x8 [aca_check]

id 106
title Flickering Pixel Monitor window not 8x8
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1473
type aca_check
severity red
aca_cl_id 024
note
orvdot

    return unless ( $self->{obsid} =~ /^\d+$/ and $self->{obsid} >= $ER_MIN_OBSID );

    my $c;
    # Check for existence of a star catalog
    return unless ($c = find_command($self, "MP_STARCAT"));

    # See if there are any monitor stars.  Return if not.
    my @mon_stars = grep { $c->{"TYPE$_"} eq 'MON' } (1..16);
    return unless (@mon_stars);

    for my $mon_star (@mon_stars){

    push @{$self->{fyi}}, sprintf("$info Obsid contains flickering pixel MON\n", $mon_star);


# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @{$self->{warn}}, sprintf("$alarm [%2d] Monitor Commanding. Size is not 8x8\n", $mon_star)
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        unless $c->{"SIZE${mon_star}"} eq "8x8";

    push @{$self->{warn}}, sprintf("$alarm [%2d] Monitor Commanding. Monitor Window RESTRK should be 0\n", $mon_star)
        unless $c->{"RESTRK${mon_star}"} == 0;

        # Verify the DTS is set to self
    push @{$self->{warn}}, sprintf("$alarm [%2d] Monitor Commanding. DTS should be set to self\n", $mon_star)
        unless $c->{"DIMDTS${mon_star}"} == $c->{"IMNUM${mon_star}"};

    }

107: Flickering Pixel Monitor Window RESTRK should be 0 [aca_check]

id 107
title Flickering Pixel Monitor Window RESTRK should be 0
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1476
type aca_check
severity red
aca_cl_id 038
note
orvdot

    # Check for existence of a star catalog
    return unless ($c = find_command($self, "MP_STARCAT"));

    # See if there are any monitor stars.  Return if not.
    my @mon_stars = grep { $c->{"TYPE$_"} eq 'MON' } (1..16);
    return unless (@mon_stars);

    for my $mon_star (@mon_stars){

    push @{$self->{fyi}}, sprintf("$info Obsid contains flickering pixel MON\n", $mon_star);


    push @{$self->{warn}}, sprintf("$alarm [%2d] Monitor Commanding. Size is not 8x8\n", $mon_star)
        unless $c->{"SIZE${mon_star}"} eq "8x8";

# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @{$self->{warn}}, sprintf("$alarm [%2d] Monitor Commanding. Monitor Window RESTRK should be 0\n", $mon_star)
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        unless $c->{"RESTRK${mon_star}"} == 0;

        # Verify the DTS is set to self
    push @{$self->{warn}}, sprintf("$alarm [%2d] Monitor Commanding. DTS should be set to self\n", $mon_star)
        unless $c->{"DIMDTS${mon_star}"} == $c->{"IMNUM${mon_star}"};

    }


}

108: Flickering Pixel Monitor DTS should be set to self [aca_check]

id 108
title Flickering Pixel Monitor DTS should be set to self
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1480
type aca_check
severity red
aca_cl_id
note
orvdot

    my @mon_stars = grep { $c->{"TYPE$_"} eq 'MON' } (1..16);
    return unless (@mon_stars);

    for my $mon_star (@mon_stars){

    push @{$self->{fyi}}, sprintf("$info Obsid contains flickering pixel MON\n", $mon_star);


    push @{$self->{warn}}, sprintf("$alarm [%2d] Monitor Commanding. Size is not 8x8\n", $mon_star)
        unless $c->{"SIZE${mon_star}"} eq "8x8";

    push @{$self->{warn}}, sprintf("$alarm [%2d] Monitor Commanding. Monitor Window RESTRK should be 0\n", $mon_star)
        unless $c->{"RESTRK${mon_star}"} == 0;

        # Verify the DTS is set to self
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @{$self->{warn}}, sprintf("$alarm [%2d] Monitor Commanding. DTS should be set to self\n", $mon_star)
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        unless $c->{"DIMDTS${mon_star}"} == $c->{"IMNUM${mon_star}"};

    }


}


#############################################################################################
sub check_monitor_commanding {

109: Monitor not in OR but in catalog [aca_check]

id 109
title Monitor not in OR but in catalog
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1527
type aca_check
severity red
aca_cl_id
note
orvdot Include monitor window commanding



    # See if there are any monitor stars requested in the OR
    my $or_has_mon = ( defined $or->{HAS_MON} ) ? 1 : 0;

    my @mon_stars = grep { $c->{"TYPE$_"} eq 'MON' } (1..16);

    # if there are no requests in the OR and there are no MON stars, exit
    return unless $or_has_mon or scalar(@mon_stars);


    my $found_mon = scalar(@mon_stars);
    my $stealth_mon = 0;

    if (($found_mon) and (not $or_has_mon)){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
      push @{$self->{warn}}, sprintf("$alarm MON not in OR, but in catalog. Position not checked.\n");
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    }

    # Where is the requested OR?
    my $q_aca = Quat->new($self->{ra}, $self->{dec}, $self->{roll});
    my ($or_yang, $or_zang);
    if ($or_has_mon){
      ($or_yang, $or_zang) = Quat::radec2yagzag($or->{MON_RA}, $or->{MON_DEC}, $q_aca) if ($or_has_mon) ;
    }

    # Check all indices

110: Monitor window off of OR specification [aca_check]

id 110
title Monitor window off of OR specification
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1563
type aca_check
severity red
aca_cl_id 031
note
orvdot Include monitor window commanding

        = map { $c->{"$_${idx}"} } qw(
                       TYPE
                       IMNUM
                       RESTRK
                       YANG
                       ZANG
                       DIMDTS
                       SIZE);
    my $y_sep = $or_yang*$r2a - $idx_hash{yang};
    my $z_sep = $or_zang*$r2a - $idx_hash{zang};
    $idx_hash{sep} = sqrt($y_sep**2 + $z_sep**2);

    # if this is a plain commanded MON
    if ($idx_hash{type} =~ /MON/ ){
      # if it doesn't match the requested location ACA-037
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
      push @{$self->{warn}}, sprintf("$alarm [%2d] Monitor Commanding. Monitor Window is %6.2f arc-seconds off of OR specification\n"
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
                     , $idx_hash{idx}, $idx_hash{sep})
        if $idx_hash{sep} > 2.5;
    # if it isn't 8x8
      push @{$self->{warn}}, sprintf("$alarm [%2d] Monitor Commanding. Size is not 8x8\n", $idx_hash{idx})
        unless $idx_hash{size} eq "8x8";

    # if it isn't in slot 7 ACA-036
      push @{$self->{warn}}, sprintf("$alarm [%2d] Monitor Commanding. Monitor Window is in slot %2d and should be in slot 7.\n"
                     , $idx_hash{idx}, $idx_hash{imnum})
        if $idx_hash{imnum} != 7;

111: Monitor window not 8x8 [aca_check]

id 111
title Monitor window not 8x8
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1567
type aca_check
severity red
aca_cl_id 024
note
orvdot Include monitor window commanding

                       YANG
                       ZANG
                       DIMDTS
                       SIZE);
    my $y_sep = $or_yang*$r2a - $idx_hash{yang};
    my $z_sep = $or_zang*$r2a - $idx_hash{zang};
    $idx_hash{sep} = sqrt($y_sep**2 + $z_sep**2);

    # if this is a plain commanded MON
    if ($idx_hash{type} =~ /MON/ ){
      # if it doesn't match the requested location ACA-037
      push @{$self->{warn}}, sprintf("$alarm [%2d] Monitor Commanding. Monitor Window is %6.2f arc-seconds off of OR specification\n"
                     , $idx_hash{idx}, $idx_hash{sep})
        if $idx_hash{sep} > 2.5;
    # if it isn't 8x8
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
      push @{$self->{warn}}, sprintf("$alarm [%2d] Monitor Commanding. Size is not 8x8\n", $idx_hash{idx})
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        unless $idx_hash{size} eq "8x8";

    # if it isn't in slot 7 ACA-036
      push @{$self->{warn}}, sprintf("$alarm [%2d] Monitor Commanding. Monitor Window is in slot %2d and should be in slot 7.\n"
                     , $idx_hash{idx}, $idx_hash{imnum})
        if $idx_hash{imnum} != 7;
    # ACA-038
    push @{$self->{warn}}, sprintf("$alarm [%2d] Monitor Commanding. Monitor Window is set to Convert-to-Track\n", $idx_hash{idx})
      if $idx_hash{restrk} == 1;

112: Monitor window in wrong slot [aca_check]

id 112
title Monitor window in wrong slot
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1571
type aca_check
severity
aca_cl_id 030
note
orvdot Include monitor window commanding

    my $y_sep = $or_yang*$r2a - $idx_hash{yang};
    my $z_sep = $or_zang*$r2a - $idx_hash{zang};
    $idx_hash{sep} = sqrt($y_sep**2 + $z_sep**2);

    # if this is a plain commanded MON
    if ($idx_hash{type} =~ /MON/ ){
      # if it doesn't match the requested location ACA-037
      push @{$self->{warn}}, sprintf("$alarm [%2d] Monitor Commanding. Monitor Window is %6.2f arc-seconds off of OR specification\n"
                     , $idx_hash{idx}, $idx_hash{sep})
        if $idx_hash{sep} > 2.5;
    # if it isn't 8x8
      push @{$self->{warn}}, sprintf("$alarm [%2d] Monitor Commanding. Size is not 8x8\n", $idx_hash{idx})
        unless $idx_hash{size} eq "8x8";

    # if it isn't in slot 7 ACA-036
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
      push @{$self->{warn}}, sprintf("$alarm [%2d] Monitor Commanding. Monitor Window is in slot %2d and should be in slot 7.\n"
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
                     , $idx_hash{idx}, $idx_hash{imnum})
        if $idx_hash{imnum} != 7;
    # ACA-038
    push @{$self->{warn}}, sprintf("$alarm [%2d] Monitor Commanding. Monitor Window is set to Convert-to-Track\n", $idx_hash{idx})
      if $idx_hash{restrk} == 1;


    # Verify the the designated track star is indeed a guide star. ACA-039
      my $dts_slot = $idx_hash{dimdts};
      my $dts_type = "NULL";

113: Monitor window is set to convert-to-track [aca_check]

id 113
title Monitor window is set to convert-to-track
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1575
type aca_check
severity red
aca_cl_id 038
note
orvdot Include monitor window commanding

    # if this is a plain commanded MON
    if ($idx_hash{type} =~ /MON/ ){
      # if it doesn't match the requested location ACA-037
      push @{$self->{warn}}, sprintf("$alarm [%2d] Monitor Commanding. Monitor Window is %6.2f arc-seconds off of OR specification\n"
                     , $idx_hash{idx}, $idx_hash{sep})
        if $idx_hash{sep} > 2.5;
    # if it isn't 8x8
      push @{$self->{warn}}, sprintf("$alarm [%2d] Monitor Commanding. Size is not 8x8\n", $idx_hash{idx})
        unless $idx_hash{size} eq "8x8";

    # if it isn't in slot 7 ACA-036
      push @{$self->{warn}}, sprintf("$alarm [%2d] Monitor Commanding. Monitor Window is in slot %2d and should be in slot 7.\n"
                     , $idx_hash{idx}, $idx_hash{imnum})
        if $idx_hash{imnum} != 7;
    # ACA-038
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @{$self->{warn}}, sprintf("$alarm [%2d] Monitor Commanding. Monitor Window is set to Convert-to-Track\n", $idx_hash{idx})
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
      if $idx_hash{restrk} == 1;


    # Verify the the designated track star is indeed a guide star. ACA-039
      my $dts_slot = $idx_hash{dimdts};
      my $dts_type = "NULL";
      foreach my $dts_index (1..16) {
        next unless $c->{"IMNUM$dts_index"} == $dts_slot and $c->{"TYPE$dts_index"} =~ /GUI|BOT/;
        $dts_type = $c->{"TYPE$dts_index"};
        last;

114: Monitor window DTS is set to slot without guide star [aca_check]

id 114
title Monitor window DTS is set to slot without guide star
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1587
type aca_check
severity red
aca_cl_id 039
note
orvdot Include monitor window commanding

                     , $idx_hash{idx}, $idx_hash{imnum})
        if $idx_hash{imnum} != 7;
    # ACA-038
    push @{$self->{warn}}, sprintf("$alarm [%2d] Monitor Commanding. Monitor Window is set to Convert-to-Track\n", $idx_hash{idx})
      if $idx_hash{restrk} == 1;


    # Verify the the designated track star is indeed a guide star. ACA-039
      my $dts_slot = $idx_hash{dimdts};
      my $dts_type = "NULL";
      foreach my $dts_index (1..16) {
        next unless $c->{"IMNUM$dts_index"} == $dts_slot and $c->{"TYPE$dts_index"} =~ /GUI|BOT/;
        $dts_type = $c->{"TYPE$dts_index"};
        last;
      }
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
      push @{$self->{warn}}, sprintf("$alarm [%2d] Monitor Commanding. DTS for [%2d] is set to slot %2d which does not contain a guide star.\n",
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
                     $idx_hash{idx}, $idx_hash{idx}, $dts_slot)
        if $dts_type =~ /NULL/;
      next IDX;
    }

    if (($idx_hash{type} =~ /GUI|BOT/) and ($idx_hash{size} eq '8x8') and ($idx_hash{imnum} == 7)){
      $stealth_mon = 1;
      push @{$self->{fyi}}, sprintf("$info [%2d] Appears to be MON used as GUI/BOT.  Has Magnitude been checked?\n",
                    $idx);
      # if it doesn't match the requested location

115: Slot appears to have MON used as GUI/BOT [aca_check]

id 115
title Slot appears to have MON used as GUI/BOT
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1595
type aca_check
severity info
aca_cl_id
note
orvdot Would require MON converted to GUI/BOT.

      my $dts_slot = $idx_hash{dimdts};
      my $dts_type = "NULL";
      foreach my $dts_index (1..16) {
        next unless $c->{"IMNUM$dts_index"} == $dts_slot and $c->{"TYPE$dts_index"} =~ /GUI|BOT/;
        $dts_type = $c->{"TYPE$dts_index"};
        last;
      }
      push @{$self->{warn}}, sprintf("$alarm [%2d] Monitor Commanding. DTS for [%2d] is set to slot %2d which does not contain a guide star.\n",
                     $idx_hash{idx}, $idx_hash{idx}, $dts_slot)
        if $dts_type =~ /NULL/;
      next IDX;
    }

    if (($idx_hash{type} =~ /GUI|BOT/) and ($idx_hash{size} eq '8x8') and ($idx_hash{imnum} == 7)){
      $stealth_mon = 1;
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
      push @{$self->{fyi}}, sprintf("$info [%2d] Appears to be MON used as GUI/BOT.  Has Magnitude been checked?\n",
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
                    $idx);
      # if it doesn't match the requested location
      push @{$self->{warn}}, sprintf("$alarm [%2d] Monitor Commanding. Guide star as MON %6.2f arc-seconds off OR specification\n"
                     , $idx_hash{idx}, $idx_hash{sep})
        if $idx_hash{sep} > 2.5;

      next IDX;
    }
    if ((not $found_mon) and ($idx_hash{sep} < 2.5)){
      # if there *should* be one there...

117: Slot has star at OR MON position but not configured correctly [aca_check]

id 117
title Slot has star at OR MON position but not configured correctly
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1606
type aca_check
severity info
aca_cl_id
note
orvdot

    }

    if (($idx_hash{type} =~ /GUI|BOT/) and ($idx_hash{size} eq '8x8') and ($idx_hash{imnum} == 7)){
      $stealth_mon = 1;
      push @{$self->{fyi}}, sprintf("$info [%2d] Appears to be MON used as GUI/BOT.  Has Magnitude been checked?\n",
                    $idx);
      # if it doesn't match the requested location
      push @{$self->{warn}}, sprintf("$alarm [%2d] Monitor Commanding. Guide star as MON %6.2f arc-seconds off OR specification\n"
                     , $idx_hash{idx}, $idx_hash{sep})
        if $idx_hash{sep} > 2.5;

      next IDX;
    }
    if ((not $found_mon) and ($idx_hash{sep} < 2.5)){
      # if there *should* be one there...
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
      push @{$self->{fyi}}, sprintf("$info [%2d] Commanded at intended OR MON position; but not configured for MON\n",
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
                    $idx);
    }

      }


    # if I don't have a plain MON or a "stealth" MON, throw a warning
    push @{$self->{warn}}, sprintf("$alarm MON requested in OR, but none found in catalog\n")
      unless ( $found_mon or $stealth_mon );

118: MON in OR but not found in catalog [aca_check]

id 118
title MON in OR but not found in catalog
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1614
type aca_check
severity red
aca_cl_id
note
orvdot Include monitor window commanding

                     , $idx_hash{idx}, $idx_hash{sep})
        if $idx_hash{sep} > 2.5;

      next IDX;
    }
    if ((not $found_mon) and ($idx_hash{sep} < 2.5)){
      # if there *should* be one there...
      push @{$self->{fyi}}, sprintf("$info [%2d] Commanded at intended OR MON position; but not configured for MON\n",
                    $idx);
    }

      }


    # if I don't have a plain MON or a "stealth" MON, throw a warning
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @{$self->{warn}}, sprintf("$alarm MON requested in OR, but none found in catalog\n")
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
      unless ( $found_mon or $stealth_mon );

    # if we're using a guide star, we don't need the rest of the dither setup
    if ($stealth_mon and not $found_mon){
      return;
    }

    # Find the associated maneuver command for this obsid.  Need this to get the
    # exact time of the end of maneuver
    my $manv;

119: No MP_TARGQUAT to check maneuver for MON commanding [process]

id 119
title No MP_TARGQUAT to check maneuver for MON commanding
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1626
type process
severity red
aca_cl_id
note
orvdot Include monitor window commanding



    # if I don't have a plain MON or a "stealth" MON, throw a warning
    push @{$self->{warn}}, sprintf("$alarm MON requested in OR, but none found in catalog\n")
      unless ( $found_mon or $stealth_mon );

    # if we're using a guide star, we don't need the rest of the dither setup
    if ($stealth_mon and not $found_mon){
      return;
    }

    # Find the associated maneuver command for this obsid.  Need this to get the
    # exact time of the end of maneuver
    my $manv;
    unless ($manv = find_command($self, "MP_TARGQUAT", -1)) {
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
      push @{$self->{warn}}, sprintf("$alarm Cannot find maneuver for checking monitor commanding\n");
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
      return;
    }


    # Now check in backstop commands for :
    #  Dither is disabled (AODSDITH) 1 min prior to the end of the maneuver (EOM)
    #    to the target attitude.
    #  The OFP Aspect Camera Process is restarted (AOACRSET) 3 minutes after EOM.
    #  Dither is enabled (AOENDITH) 5 min after EOM
    # ACA-040

120: Monitor window setup does not have expected dither commands [aca_check]

id 120
title Monitor window setup does not have expected dither commands
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1657
type aca_check
severity red
aca_cl_id
note
orvdot Include monitor window commanding

    my %param = Ska::Parse_CM_File::parse_params($bs->{params});
    next unless ($param{TLMSID} =~ /^AO/);
    foreach $cmd (keys %dt) {
        if ($cmd =~ /$param{TLMSID}/){
        if ( abs($bs->{time} - ($t_manv+$dt{$cmd})) < $time_tol){
            $cnt{$cmd}++;
        }
        }
    }
    }

    # Add warning messages unless exactly one of each command was found at the right time
    foreach $cmd (qw (AODSDITH AOACRSET AOENDITH)) {
    next if ($cnt{$cmd} == 1);
    $cnt{$cmd} = 'no' if ($cnt{$cmd} == 0);
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @{$self->{warn}}, "$alarm Found $cnt{$cmd} $cmd commands near " . time2date($t_manv+$dt{$cmd}) . "\n";
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    }
}

#############################################################################################
sub check_fids {
#############################################################################################
    my $self = shift;
    my $c = shift;        # Star catalog command
    my $warn = shift;        # Array ref to warnings for this obsid

121: Code to pass the warnings array by reference to this check function [code]

id 121
title Code to pass the warnings array by reference to this check function
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1666
type code
severity
aca_cl_id
note
orvdot

    }

    # Add warning messages unless exactly one of each command was found at the right time
    foreach $cmd (qw (AODSDITH AOACRSET AOENDITH)) {
    next if ($cnt{$cmd} == 1);
    $cnt{$cmd} = 'no' if ($cnt{$cmd} == 0);
    push @{$self->{warn}}, "$alarm Found $cnt{$cmd} $cmd commands near " . time2date($t_manv+$dt{$cmd}) . "\n";
    }
}

#############################################################################################
sub check_fids {
#############################################################################################
    my $self = shift;
    my $c = shift;        # Star catalog command
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    my $warn = shift;        # Array ref to warnings for this obsid
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX

    my (@fid_ok, @fidsel_ok);
    my ($i, $i_fid);

    # If no star cat fids and no commanded fids, then return
    my $fid_number = @{$self->{fid}};
    return if ($fid_number == 0 && @{$self->{fidsel}} == 0);

    # Make sure we have SI and SIM_OFFSET_Z to be able to calculate fid yang and zang
    unless (defined $self->{SI}) {

122: Unable to check fids because SI undefined [aca_check]

id 122
title Unable to check fids because SI undefined
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1677
type aca_check
severity red
aca_cl_id
note
orvdot

sub check_fids {
#############################################################################################
    my $self = shift;
    my $c = shift;        # Star catalog command
    my $warn = shift;        # Array ref to warnings for this obsid

    my (@fid_ok, @fidsel_ok);
    my ($i, $i_fid);

    # If no star cat fids and no commanded fids, then return
    my $fid_number = @{$self->{fid}};
    return if ($fid_number == 0 && @{$self->{fidsel}} == 0);

    # Make sure we have SI and SIM_OFFSET_Z to be able to calculate fid yang and zang
    unless (defined $self->{SI}) {
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @{$warn}, "$alarm Unable to check fids because SI undefined\n";
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    return;
    }
    unless (defined $self->{SIM_OFFSET_Z}){
    push @{$warn}, "$alarm Unable to check fids because SIM_OFFSET_Z undefined\n";
    return;
    }

    @fid_ok = map { 0 } @{$self->{fid}};

    # Calculate yang and zang for each commanded fid, then cross-correlate with

123: Unable to check fids because SIM_OFFSET_Z undefined [aca_check]

id 123
title Unable to check fids because SIM_OFFSET_Z undefined
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1681
type aca_check
severity red
aca_cl_id
note
orvdot

    my $warn = shift;        # Array ref to warnings for this obsid

    my (@fid_ok, @fidsel_ok);
    my ($i, $i_fid);

    # If no star cat fids and no commanded fids, then return
    my $fid_number = @{$self->{fid}};
    return if ($fid_number == 0 && @{$self->{fidsel}} == 0);

    # Make sure we have SI and SIM_OFFSET_Z to be able to calculate fid yang and zang
    unless (defined $self->{SI}) {
    push @{$warn}, "$alarm Unable to check fids because SI undefined\n";
    return;
    }
    unless (defined $self->{SIM_OFFSET_Z}){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @{$warn}, "$alarm Unable to check fids because SIM_OFFSET_Z undefined\n";
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    return;
    }

    @fid_ok = map { 0 } @{$self->{fid}};

    # Calculate yang and zang for each commanded fid, then cross-correlate with
    # all commanded fids.
    foreach my $fid (@{$self->{fidsel}}) {

    my ($yag, $zag, $error) = calc_fid_ang($fid, $self->{SI}, $self->{SIM_OFFSET_Z}, $self->{obsid});

124: Commanded fid light does not correspond to detector [aca_check]

id 124
title Commanded fid light does not correspond to detector
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1694
type aca_check
severity red
aca_cl_id
note
orvdot

    }
    unless (defined $self->{SIM_OFFSET_Z}){
    push @{$warn}, "$alarm Unable to check fids because SIM_OFFSET_Z undefined\n";
    return;
    }

    @fid_ok = map { 0 } @{$self->{fid}};

    # Calculate yang and zang for each commanded fid, then cross-correlate with
    # all commanded fids.
    foreach my $fid (@{$self->{fidsel}}) {

    my ($yag, $zag, $error) = calc_fid_ang($fid, $self->{SI}, $self->{SIM_OFFSET_Z}, $self->{obsid});

    if ($error) {
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @{$warn}, "$alarm $error\n";
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        next;
    }
    my $fidsel_ok = 0;

    # Cross-correlate with all star cat fids
    for  $i_fid (0 .. $#fid_ok) {
        $i = $self->{fid}[$i_fid]; # Index into star catalog entries

        # Check if starcat fid matches fidsel fid position to within 10 arcsec
        if (abs($yag - $c->{"YANG$i"}) < 10.0 && abs($zag - $c->{"ZANG$i"}) < 10.0) {

125: Fid light from FIDSEL not found within 10 arcsec of yag,zag [aca_check]

id 125
title Fid light from FIDSEL not found within 10 arcsec of yag,zag
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1712
type aca_check
severity red
aca_cl_id 029
note
orvdot

    my $fidsel_ok = 0;

    # Cross-correlate with all star cat fids
    for  $i_fid (0 .. $#fid_ok) {
        $i = $self->{fid}[$i_fid]; # Index into star catalog entries

        # Check if starcat fid matches fidsel fid position to within 10 arcsec
        if (abs($yag - $c->{"YANG$i"}) < 10.0 && abs($zag - $c->{"ZANG$i"}) < 10.0) {
        $fidsel_ok = 1;
        $fid_ok[$i_fid] = 1;
        last;
        }
    }

        # ACA-034
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @{$warn}, sprintf("$alarm Fid $self->{SI} FIDSEL $fid not found within 10 arcsec of (%.1f, %.1f)\n",
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
                   $yag, $zag)
        unless ($fidsel_ok);
    }
    # ACA-035
    for $i_fid (0 .. $#fid_ok) {
    push @{$warn}, "$alarm Fid with IDX=\[$self->{fid}[$i_fid]\] is in star catalog but is not turned on via FIDSEL\n"
        unless ($fid_ok[$i_fid]);
    }
}

126: Fid in star catalog but not FIDSEL [aca_check]

id 126
title Fid in star catalog but not FIDSEL
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1718
type aca_check
severity red
aca_cl_id 028
note
orvdot

        # Check if starcat fid matches fidsel fid position to within 10 arcsec
        if (abs($yag - $c->{"YANG$i"}) < 10.0 && abs($zag - $c->{"ZANG$i"}) < 10.0) {
        $fidsel_ok = 1;
        $fid_ok[$i_fid] = 1;
        last;
        }
    }

        # ACA-034
    push @{$warn}, sprintf("$alarm Fid $self->{SI} FIDSEL $fid not found within 10 arcsec of (%.1f, %.1f)\n",
                   $yag, $zag)
        unless ($fidsel_ok);
    }
    # ACA-035
    for $i_fid (0 .. $#fid_ok) {
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @{$warn}, "$alarm Fid with IDX=\[$self->{fid}[$i_fid]\] is in star catalog but is not turned on via FIDSEL\n"
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        unless ($fid_ok[$i_fid]);
    }
}

##############################################################################
sub calc_fid_ang {
#   From OFLS SDS:
#   Y_ang = fid position angle measured about the ACA z-axis as shown in
#           Fig. 4.3-5.  In that figure, Y_ang corresponds to the ACA
#           y angle, or "yag".

127: Guide star summary does not match commanded catalog [process]

id 127
title Guide star summary does not match commanded catalog
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:2129
type process
severity red
aca_cl_id
note
orvdot

        $c->{"GS_PASS$j"} = defined $f[7] ? ($f[7] =~ /\*+/ ? length $f[7] : $f[7]) : ' ';
        $c->{"GS_PASS$j"} =~ s/[agf]1//g;
    }
    else {
        # if the position of the line item in the guide summary doesn't match
        # set the variable once (so we don't have a warning for all the remaining lines
        # if there is one missing...)
        $bad_idx_match = 1;
    }

    }

    # if the position of an item didn't match, warn that the guide summary does not match
    # the backstop commanded catalog
    if ($bad_idx_match == 1){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    push @{$self->{warn}}, ">> WARNING: Guide summary does not match commanded catalog.\n";
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    }
}

#############################################################################################
sub get_agasc_stars {
#############################################################################################

    my $self = shift;
    my $AGASC_DIR = shift;
    my $c;

128: Star in field has very bad mag or magerr [aca_check]

id 128
title Star in field has very bad mag or magerr
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:2164
type aca_check
severity red
aca_cl_id 026
note
orvdot

    });

    my $q_aca = Quat->new($self->{ra}, $self->{dec}, $self->{roll});

    for my $id ($agasc_region->list_ids() )  {

    my $star = $agasc_region->get_star($id);

    my ($yag, $zag) = Quat::radec2yagzag(
                         $star->ra_pmcorrected(),
                         $star->dec_pmcorrected(),
                         $q_aca);
    $yag *= $r2a;
    $zag *= $r2a;
    if ($star->mag_aca() < -10 or $star->mag_aca_err() < -10) {
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @{$self->{warn}}, sprintf("$alarm Star with bad mag %.1f or magerr %.1f at (yag,zag)=%.1f,%.1f\n",
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
                       $star->mag_aca(), $star->mag_aca_err(), $yag, $zag);
    }
    $self->{agasc_hash}{$id} = {
        id=> $id,
        class => $star->class(),
        ra  => $star->ra_pmcorrected(),
        dec => $star->dec_pmcorrected(),
        mag_aca => $star->mag_aca(),
        bv  => $star->color1(),
        mag_aca_err => $star->mag_aca_err(),

129: Guide star not found in AGASC by RA/Dec [aca_check]

id 129
title Guide star not found in AGASC by RA/Dec
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:2214
type aca_check
severity red
aca_cl_id 035
note
orvdot

    next if ($type eq 'NUL');
    next if ($type eq 'FID');

    my $yag = $c->{"YANG$i"};
    my $zag = $c->{"ZANG$i"};
    my $gs_id = $c->{"GS_ID$i"};
    my $gs_ra = $c->{"GS_RA$i"};
    my $gs_dec = $c->{"GS_DEC$i"};

    # strip * off gs_id if present
    $gs_id =~ s/^\*/^/;

    # if the star is defined in the guide summary but doesn't seem to be present in the
    # agasc hash for this ra and dec, throw a warning
    unless ((defined $self->{agasc_hash}{$gs_id}) or ($gs_id eq '---')){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @{$self->{warn}},
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
              sprintf("$alarm [%2d] Star $gs_id is not in retrieved AGASC region by RA and DEC! \n", $i);
    }


    # if the star is defined in the agasc hash, copy
    # the information from the agasc to the catalog

    if (defined $self->{agasc_hash}{$gs_id}){
        my $star = $self->{agasc_hash}{$gs_id};

130: Star position in AGASC off from backstop by > 3 arcsecs [aca_check]

id 130
title Star position in AGASC off from backstop by > 3 arcsecs
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:2235
type aca_check
severity red
aca_cl_id 035
note
orvdot

    # the information from the agasc to the catalog

    if (defined $self->{agasc_hash}{$gs_id}){
        my $star = $self->{agasc_hash}{$gs_id};

        # let's still confirm that the backstop yag zag is what we expect
        # from agasc and ra,dec,roll ACA-043

        if (abs($star->{yag} - $yag) > ($ID_DIST_LIMIT)
        || abs($star->{zag} - $zag) > ($ID_DIST_LIMIT)){
        my $dyag = abs($star->{yag} - $yag);
        my $dzag = abs($star->{zag} - $zag);

        if (abs($star->{yag} - $yag) > (2 * $ID_DIST_LIMIT) ||
            abs($star->{zag} - $zag) > (2 * $ID_DIST_LIMIT)){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
            push @{$self->{warn}},
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
                 sprintf("$alarm [%2d] Backstop YAG,ZAG differs from AGASC by > 3 arcsec: dyag = %2.2f dzag = %2.2f \n", $i, $dyag, $dzag);
        }
        else{
            push @{$self->{yellow_warn}},
                 sprintf("$alarm [%2d] Backstop YAG,ZAG differs from AGASC by > 1.5 arcsec: dyag = %2.2f dzag = %2.2f \n", $i, $dyag, $dzag);
        }
        }

        # should I put this in an else statement, or let it stand alone?

131: Star position in AGASC off from backstop by > 1.5 arcsecs (and less than 3) [aca_check]

id 131
title Star position in AGASC off from backstop by > 1.5 arcsecs (and less than 3)
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:2239
type aca_check
severity yellow
aca_cl_id 035
note
orvdot


        # let's still confirm that the backstop yag zag is what we expect
        # from agasc and ra,dec,roll ACA-043

        if (abs($star->{yag} - $yag) > ($ID_DIST_LIMIT)
        || abs($star->{zag} - $zag) > ($ID_DIST_LIMIT)){
        my $dyag = abs($star->{yag} - $yag);
        my $dzag = abs($star->{zag} - $zag);

        if (abs($star->{yag} - $yag) > (2 * $ID_DIST_LIMIT) ||
            abs($star->{zag} - $zag) > (2 * $ID_DIST_LIMIT)){
            push @{$self->{warn}},
                 sprintf("$alarm [%2d] Backstop YAG,ZAG differs from AGASC by > 3 arcsec: dyag = %2.2f dzag = %2.2f \n", $i, $dyag, $dzag);
        }
        else{
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
            push @{$self->{yellow_warn}},
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
                 sprintf("$alarm [%2d] Backstop YAG,ZAG differs from AGASC by > 1.5 arcsec: dyag = %2.2f dzag = %2.2f \n", $i, $dyag, $dzag);
        }
        }

        # should I put this in an else statement, or let it stand alone?

        $c->{"GS_IDENTIFIED$i"} = 1;
        $c->{"GS_BV$i"} = $star->{bv};
        $c->{"GS_MAGERR$i"} = $star->{mag_aca_err};
        $c->{"GS_POSERR$i"} = $star->{poserr};

132: No CCD temperature prediction for obsid [process]

id 132
title No CCD temperature prediction for obsid
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:2594
type process
severity red
aca_cl_id
note
orvdot

        last;
    }
    }

    return $warn_boolean;
}

###################################################################################
sub set_ccd_temps{
###################################################################################
    my $self = shift;
    my $obsid_temps = shift;
    # if no temperature data, just return
    if ((not defined $obsid_temps->{$self->{obsid}})
        or (not defined $obsid_temps->{$self->{obsid}}->{ccd_temp})){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @{$self->{warn}}, "$alarm No CCD temperature prediction for obsid\n";
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        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};
        return;
    }
    # set the temperature to the value for the current obsid
    $self->{ccd_temp} = $obsid_temps->{$self->{obsid}}->{ccd_temp};
    $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}){

133: Using default/planning limit for CCD temperature [process]

id 133
title Using default/planning limit for CCD temperature
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:2595
type process
severity red
aca_cl_id
note
orvdot

    }
    }

    return $warn_boolean;
}

###################################################################################
sub set_ccd_temps{
###################################################################################
    my $self = shift;
    my $obsid_temps = shift;
    # if no temperature data, just return
    if ((not defined $obsid_temps->{$self->{obsid}})
        or (not defined $obsid_temps->{$self->{obsid}}->{ccd_temp})){
        push @{$self->{warn}}, "$alarm No CCD temperature prediction for obsid\n";
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @{$self->{warn}}, sprintf("$alarm Using %s (planning limit) for t_ccd for mag limits\n",
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
                                       $config{ccd_temp_red_limit});
        $self->{ccd_temp} = $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->{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",

134: CCD temperature exceeds red limit [process]

id 134
title CCD temperature exceeds red limit
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:2605
type process
severity info
aca_cl_id
note
orvdot

    my $obsid_temps = shift;
    # if no temperature data, just return
    if ((not defined $obsid_temps->{$self->{obsid}})
        or (not defined $obsid_temps->{$self->{obsid}}->{ccd_temp})){
        push @{$self->{warn}}, "$alarm No CCD temperature prediction for obsid\n";
        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};
        return;
    }
    # set the temperature to the value for the current obsid
    $self->{ccd_temp} = $obsid_temps->{$self->{obsid}}->{ccd_temp};
    $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}){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @{$self->{fyi}}, sprintf("$info CCD temperature exceeds %.1f C\n",
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
                                       $config{ccd_temp_red_limit});
    }
}

136: Overall acquisition probability is poor [aca_check]

id 136
title Overall acquisition probability is poor
file starcheck/src/lib/Ska/Starcheck/FigureOfMerit.pm:77
type aca_check
severity red
aca_cl_id
note
orvdot

        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] > $CUM_PROB_LIMIT)
                                };
    if ($n_or_fewer_probs->[2] > $CUM_PROB_LIMIT){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @{$self->{warn}}, ">> WARNING: Probability of 2 or fewer stars > $CUM_PROB_LIMIT\n";
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    }

}


sub set_dynamic_mag_limits{
    my $c;
    my $self = shift;
    return unless ($c = $self->find_command("MP_STARCAT"));

137: Spurious check entry due to unexpected regex match [spurious]

id 137
title Spurious check entry due to unexpected regex match
file starcheck/src/lib/Ska/Starcheck/FigureOfMerit.pm:134
type spurious
severity
aca_cl_id
note
orvdot

    if (($mag < 8.5) or ($prob > $max_star_prob)){
        $prob = $max_star_prob;
    }

    foreach my $warning (@warnings) {
    if ($warning =~ /B-V = 0.700/) {
        $prob *= $p_0p7color;
    }
        if ($warning =~ /B-V = 1.500/) {
            $prob *= $p_1p5color;
        }
    if ($warning =~ /Search Spoiler/) {
        $prob *= $p_seaspo;
    }
    if ($warning =~ /Bad Acquisition Star/){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        my ($failed, $total) = parse_bad_acq_warning($warning);
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        $prob = ($total - $failed) / $total;
            last;
    }
    }
    return $prob;
}


##*****************************************************************************************
sub parse_bad_acq_warning {

138: Could not parse fidsel file [process]

id 138
title Could not parse fidsel file
file starcheck/src/lib/Ska/Parse_CM_File.pm:262
type process
severity red
aca_cl_id
note
orvdot


    for (my $i = 0; $i <= $#{$times}; $i++) {
    # If command contains RESET, then turn off (i.e. set tstop) any
    # fid light that is on
    if ($actions->[$i] =~ /RESET/) {
        foreach my $fid (1 .. 14) {
        foreach my $fid_interval (@{$fs[$fid]}) {
            $fid_interval->{tstop} = $times->[$i] unless ($fid_interval->{tstop});
        }
        }
    }
    # Otherwise turn fid on by adding a new entry with tstart=time
    elsif ((my $fid) = ($actions->[$i] =~ /FID\s+(\d+)\s+ON/)) {
        push @{$fs[$fid]}, { tstart => $times->[$i] };
    } else {
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @{$error}, "Parse_cm_file::fidsel: WARNING - Could not parse $actions->[$i]";
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    }
    }

    return ($fid_time_violation, $error, \@fs);
}

###############################################################
sub get_fid_actions {
###############################################################
    my $fs_file = shift;    # Fidsel file name

139: Monitor window off from OR specification (guide star version) []

id 139
title Monitor window off from OR specification (guide star version)
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1598
type
severity red
aca_cl_id 031
note
orvdot Would require MON converted to GUI/BOT.

        next unless $c->{"IMNUM$dts_index"} == $dts_slot and $c->{"TYPE$dts_index"} =~ /GUI|BOT/;
        $dts_type = $c->{"TYPE$dts_index"};
        last;
      }
      push @{$self->{warn}}, sprintf("$alarm [%2d] Monitor Commanding. DTS for [%2d] is set to slot %2d which does not contain a guide star.\n",
                     $idx_hash{idx}, $idx_hash{idx}, $dts_slot)
        if $dts_type =~ /NULL/;
      next IDX;
    }

    if (($idx_hash{type} =~ /GUI|BOT/) and ($idx_hash{size} eq '8x8') and ($idx_hash{imnum} == 7)){
      $stealth_mon = 1;
      push @{$self->{fyi}}, sprintf("$info [%2d] Appears to be MON used as GUI/BOT.  Has Magnitude been checked?\n",
                    $idx);
      # if it doesn't match the requested location
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
      push @{$self->{warn}}, sprintf("$alarm [%2d] Monitor Commanding. Guide star as MON %6.2f arc-seconds off OR specification\n"
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
                     , $idx_hash{idx}, $idx_hash{sep})
        if $idx_hash{sep} > 2.5;

      next IDX;
    }
    if ((not $found_mon) and ($idx_hash{sep} < 2.5)){
      # if there *should* be one there...
      push @{$self->{fyi}}, sprintf("$info [%2d] Commanded at intended OR MON position; but not configured for MON\n",
                    $idx);
    }

140: Observation passes 'big dither' checks [aca_check]

id 140
title Observation passes 'big dither' checks
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:826
type aca_check
severity info
aca_cl_id
note
orvdot

    }
    # Check that the dither state at the end of the observation started 5 minutes before
    # the end (within time_tol)
    if ((abs($obs_tstop - $obs_stop_dither->{time} - 300) > $time_tol)){
        push @{$self->{warn}},
            sprintf("$alarm Last dither state for Large Dither should start 5 minutes before obs end.\n");
    }
    # Check that the dither state at the end of the observation is standard
    if (not standard_dither($obs_stop_dither)){
        push @{$self->{warn}},
            sprintf("$alarm Dither parameters not set to standard values before obs end\n");
    }

    # If the number of warnings has not changed during this routine, it passed all checks
    if (scalar(@{$self->{warn}}) == $n_warn){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @{$self->{fyi}},
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
            sprintf("$info Observation passes 'big dither' checks\n");
    }
}





#############################################################################################
sub check_bright_perigee{

141: Guide star fainter than 10.3 mags [aca_check]

id 141
title Guide star fainter than 10.3 mags
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1283
type aca_check
severity red
aca_cl_id
note
orvdot

        if (   $pixel_row > $row_max - $pix_slot_dither || $pixel_row < $row_min + $pix_slot_dither
           || $pixel_col > $col_max - $pix_slot_dither || $pixel_col < $col_min + $pix_slot_dither) {
            push @warn,sprintf "$alarm [%2d] Angle Too Large.\n",$i;
        }
    }

        # Quandrant boundary interference ACA-013 ACA-014 (and ACA-012 if it were actually a check)
    push @yellow_warn, sprintf "$alarm [%2d] Quadrant Boundary. \n",$i
        unless ($type eq 'ACQ' or $type eq 'MON' or
            (abs($yag-$y0) > $qb_dist + $slot_dither and abs($zag-$z0) > $qb_dist + $slot_dither ));

    # Faint and bright limits ~ACA-009 ACA-010
    if ($type ne 'MON' and $mag ne '---') {

            if (($type eq 'GUI' or $type eq 'BOT') and $mag > 10.3){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @warn, sprintf "$alarm [%2d] Magnitude. Guide star %6.3f\n",$i,$mag;
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
            }
        if ($mag < $mag_bright or $mag > $self->{mag_faint_red}) {
        push @warn, sprintf "$alarm [%2d] Magnitude.  %6.3f\n",$i,$mag;
        }
        elsif ($mag > $self->{mag_faint_yellow}) {
        push @yellow_warn, sprintf "$alarm [%2d] Magnitude.  %6.3f\n",$i,$mag;
        }

    }

142: Search box greater than 160 not allowed for faint star [aca_check]

id 142
title Search box greater than 160 not allowed for faint star
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1343
type aca_check
severity red
aca_cl_id
note
orvdot



    # Search box too large ACA-018
    if ($type ne 'MON' and $c->{"HALFW$i"} > 200) {
        push @warn, sprintf "$alarm [%2d] Search Box Size. Search Box Too Large. \n",$i;
    }

    # ACQ/BOTH search box smaller than slew error ACA-015
    if (($type =~ /BOT|ACQ/) and $c->{"HALFW$i"} < $slew_err) {
        push @warn, sprintf "$alarm [%2d] Search Box Size. Search Box smaller than slew error \n",$i;
    }

        # Double check that 180 and 160 boxes are only applied to bright stars
        if (($type =~ /BOT|ACQ/) and ($c->{"HALFW$i"} > 160)
            and (($mag + $c->{"GS_MAGERR$i"} * 3 / 100) > 9.2)){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
            push @warn, sprintf "$alarm [%2d] Search Box Size. Star too faint for > 160 box. \n",$i;
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        }
        if (($type =~ /BOT|ACQ/) and ($c->{"HALFW$i"} > 120)
            and (($mag + $c->{"GS_MAGERR$i"} * 1 / 100) > 10.2)){
            push @warn, sprintf "$alarm [%2d] Search Box Size. Star too faint for > 120 box. \n",$i;
        }

    # Check that readout sizes are all 6x6 for science observations ACA-027
    if ($is_science && $type =~ /BOT|GUI|ACQ/  && $c->{"SIZE$i"} ne "6x6"){
      if (($c->{"SIZE$i"} eq "8x8") and ($or->{HAS_MON}) and ($c->{"IMNUM$i"} == 7 )){
        push @{$self->{fyi}}, sprintf("$info [%2d] Readout Size. 8x8 Stealth MON?", $i);

143: Search box greater than 120 not allowed for faint star [aca_check]

id 143
title Search box greater than 120 not allowed for faint star
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:1347
type aca_check
severity red
aca_cl_id
note
orvdot

        push @warn, sprintf "$alarm [%2d] Search Box Size. Search Box Too Large. \n",$i;
    }

    # ACQ/BOTH search box smaller than slew error ACA-015
    if (($type =~ /BOT|ACQ/) and $c->{"HALFW$i"} < $slew_err) {
        push @warn, sprintf "$alarm [%2d] Search Box Size. Search Box smaller than slew error \n",$i;
    }

        # Double check that 180 and 160 boxes are only applied to bright stars
        if (($type =~ /BOT|ACQ/) and ($c->{"HALFW$i"} > 160)
            and (($mag + $c->{"GS_MAGERR$i"} * 3 / 100) > 9.2)){
            push @warn, sprintf "$alarm [%2d] Search Box Size. Star too faint for > 160 box. \n",$i;
        }
        if (($type =~ /BOT|ACQ/) and ($c->{"HALFW$i"} > 120)
            and (($mag + $c->{"GS_MAGERR$i"} * 1 / 100) > 10.2)){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
            push @warn, sprintf "$alarm [%2d] Search Box Size. Star too faint for > 120 box. \n",$i;
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        }

    # Check that readout sizes are all 6x6 for science observations ACA-027
    if ($is_science && $type =~ /BOT|GUI|ACQ/  && $c->{"SIZE$i"} ne "6x6"){
      if (($c->{"SIZE$i"} eq "8x8") and ($or->{HAS_MON}) and ($c->{"IMNUM$i"} == 7 )){
        push @{$self->{fyi}}, sprintf("$info [%2d] Readout Size. 8x8 Stealth MON?", $i);
      }
      else{
        push @warn, sprintf("$alarm [%2d] Readout Size. %s Should be 6x6\n", $i, $c->{"SIZE$i"});
      }

144: Not enough big boxes on acquisition stars [aca_check]

id 144
title Not enough big boxes on acquisition stars
file starcheck/src/lib/Ska/Starcheck/Obsid.pm:2550
type aca_check
severity red
aca_cl_id
note
orvdot

###################################################################################
    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){
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
        push @{$self->{warn}}, "$alarm Fewer than 3 ACQ stars with boxes >= 160 arcsec\n";
# XXXXXXXXXXXXX MARKED WARNING XXXXXXXXXXXXX
    }
}



###################################################################################
sub check_idx_warn{
###################################################################################

    my $self = shift;

m001: Dark cal commanding is incorrect [aca_check]

id m001
title Dark cal commanding is incorrect
file :
type aca_check
severity red
aca_cl_id 045
note
orvdot Include a dark cal and split dark cal observation