|
| 1 | +#! /usr/local/bin/python |
| 2 | +# |
| 3 | +# HETG_Check.py - Perigee Passage Gratings Insertion Check |
| 4 | +# |
| 5 | +""" |
| 6 | +
|
| 7 | +Guideline: |
| 8 | +https://occweb.cfa.harvard.edu/twiki/bin/view/Constraints/MPGuidelines/Development/GuidelineRadiationSafingWithoutHRC |
| 9 | +
|
| 10 | +" When HRC data is not used for onboard radiation monitoring and safing, ensure the following: |
| 11 | +
|
| 12 | + HETG is inserted by rad entry, either during the same maneuver used to safe the |
| 13 | + SIM or prior, and kept in until at least the start of the maneuver to the first |
| 14 | + target exiting the rad zone Priority 2" |
| 15 | + |
| 16 | +Check the Weekly load to be sure that the HETG has been inserted for the Perigee passage. |
| 17 | +
|
| 18 | +IMPORTANT: VO (Vehicle Only) loads DO NOT HAVE OORMPDS or OORMPEN |
| 19 | + VO loads DO have EQF013M and EEF1000 and XQF013M, XEF1000 |
| 20 | + VpS (Vehicle plus Science) loads have EQF013M and EEF1000 and XQF013M, XEF1000 |
| 21 | + |
| 22 | + So since the proton and electron events exist in both VO and VpS files, this |
| 23 | + program focuses on using EQF013M, EEF1000, XQF013M and XEF1000 to determine |
| 24 | + Radzone entry for all loads. |
| 25 | +
|
| 26 | + There are 4 values you need in order to be sure the Gratings are in: |
| 27 | +
|
| 28 | + HETG In - MSID= 4OHETGIN |
| 29 | + HETG Out - MSID= 4OHETGRE |
| 30 | + Radzone Entry |
| 31 | + Radzone Exit |
| 32 | +
|
| 33 | + In this progam these 4 commands or states will be referred to as HETG states. |
| 34 | + The complete set of 4 states will be referred to as a state group. |
| 35 | +
|
| 36 | + The HETG is not guaranteed to be in prior to the HRC-S SIMTRANS, and it is usually retracted |
| 37 | + during the outbound ECS measurement so it's retracted prior to XEF1000. Therefore this |
| 38 | + program will check to be sure it's in during the Perigee Passage and will report the |
| 39 | + percentage time of the passage it was in. |
| 40 | +
|
| 41 | +""" |
| 42 | +import argparse |
| 43 | +import numpy as np |
| 44 | +import sys |
| 45 | + |
| 46 | +# Import the BackstopHistory class |
| 47 | +from backstop_history import BackstopHistory |
| 48 | + |
| 49 | +# ACIS Ops Imports |
| 50 | +import apt_date_secs as apt |
| 51 | +import Calc_Delta as cd |
| 52 | +import ORP_File_Class as ofc |
| 53 | +import OFLS_File_Utilities as oflsu |
| 54 | + |
| 55 | +# |
| 56 | +# Parse the input arguments |
| 57 | +# |
| 58 | +deadman_parser = argparse.ArgumentParser() |
| 59 | +deadman_parser.add_argument("review_load_path", help="Path to the Review load directory. e.g. /data/acis/LoadReviews/2022/FEB2122/ofls'") |
| 60 | + |
| 61 | +deadman_parser.add_argument("nlet_file_path", help="Path to the NLET file to be used in assembling the history. e.g. /data/acis/LoadReviews/TEST_NLET_FILES/FEB2122A_NonLoadTrackedEvents.txt") |
| 62 | + |
| 63 | +args = deadman_parser.parse_args() |
| 64 | + |
| 65 | +# |
| 66 | +# Inits |
| 67 | +# |
| 68 | +# Create an instance of the Backstop History class |
| 69 | +BSC = BackstopHistory.Backstop_History_Class('ACIS-Continuity.txt', |
| 70 | + args.nlet_file_path, |
| 71 | + args.review_load_path, |
| 72 | + 0) |
| 73 | +# Create an instance of the ORP File Class |
| 74 | +ofci = ofc.ORP_File_Class() |
| 75 | + |
| 76 | +load_week_path = args.review_load_path |
| 77 | +nlet_file_path = args.nlet_file_path |
| 78 | + |
| 79 | +# Extract the load week out from the path |
| 80 | +load_week = load_week_path.split('/')[5] |
| 81 | + |
| 82 | +# Read the review load - results are in BSC.master_list |
| 83 | +assembled_commands = BSC.Read_Review_Load(BSC.outdir) |
| 84 | + |
| 85 | +# Capture the start date and time of the Review load |
| 86 | +rev_start_date = assembled_commands[0]['date'] |
| 87 | +rev_start_time = assembled_commands[0]['time'] |
| 88 | + |
| 89 | +# Next, find the status of the HETG at the end of the Continuity load |
| 90 | +cont_status = oflsu.Get_OFLS_Status_Line(load_week_path) |
| 91 | + |
| 92 | +# Iniitalize the event dates |
| 93 | +if cont_status['HETG_status'] == 'HETG-IN': |
| 94 | + |
| 95 | + HETG_in_date = cont_status['date'] |
| 96 | + HETG_in_time = apt.secs(HETG_in_date) |
| 97 | + hetg_in = True |
| 98 | + |
| 99 | + HETG_out_date = None |
| 100 | + HETG_out_time = None |
| 101 | + hetg_out = False |
| 102 | + |
| 103 | + HETG_status = 'IN' |
| 104 | + # Inform the user that the first results are from the Continuity load. |
| 105 | + print('\nThis is the Continuity Load:') |
| 106 | + print(' ' + cont_status['date']+' HETG INSERTED in the Continuity load') |
| 107 | +else: |
| 108 | + |
| 109 | + HETG_in_date=None |
| 110 | + HETG_in_time=None |
| 111 | + hetg_in = False |
| 112 | + |
| 113 | + HETG_out_date=cont_status['date'] |
| 114 | + HETG_out_time=apt.secs(HETG_out_date) |
| 115 | + hetg_out = True |
| 116 | + |
| 117 | + HETG_status = 'UNK' |
| 118 | + |
| 119 | +EQF013M_date = None |
| 120 | +eqf013m_acq = False |
| 121 | + |
| 122 | +EEF1000_date = None |
| 123 | +eef1000_acq = False |
| 124 | + |
| 125 | +XQF013M_date = None |
| 126 | +xqf013m_acq = False |
| 127 | + |
| 128 | +XEF1000_date = None |
| 129 | +xef1000_acq = False |
| 130 | + |
| 131 | +OORMPDS_date = None |
| 132 | +OORMPDS_time = None |
| 133 | +oormpds_acq = False |
| 134 | + |
| 135 | +OORMPEN_date = None |
| 136 | +OORMPEN_time = None |
| 137 | +oormpen_acq = False |
| 138 | + |
| 139 | +# Tell the user what load week we are checking |
| 140 | +print('\n HETG Check for load week: ', load_week) |
| 141 | + |
| 142 | +# Initialize the flag which will indicate when the review load output has begun |
| 143 | +review_load_started_flag = False |
| 144 | + |
| 145 | +# Walk through the assembled history of commands and set dates and flags whenever |
| 146 | +# you read a command or event that we need to note. |
| 147 | +for each_cmd in assembled_commands: |
| 148 | + |
| 149 | + # If the date of this command is after the Review Load ToFC, then |
| 150 | + # print a line out that delineates Continuity load HETG reports from |
| 151 | + # Review load HETG reports |
| 152 | + if (each_cmd['time'] >= rev_start_time) and \ |
| 153 | + (not review_load_started_flag): |
| 154 | + # Set the flag to True so that this line gets written out only once |
| 155 | + review_load_started_flag = True |
| 156 | + # inform the user that the review load commands are being processed |
| 157 | + print('\nThis is the start of the Review Load:\n') |
| 158 | + |
| 159 | + # If this command contains one of the components we need to note, |
| 160 | + # set that component's date, time and flag. For HETG insert and retract |
| 161 | + # commands print out the execution time of the command for the load |
| 162 | + # reviewer. |
| 163 | + if 'MSID= 4OHETGIN' in each_cmd['commands']: |
| 164 | + HETG_in_date = each_cmd['date'] |
| 165 | + HETG_in_time = each_cmd['time'] |
| 166 | + hetg_in = True |
| 167 | + hetg_out = False |
| 168 | + HETG_status = 'IN' |
| 169 | + print(' '+each_cmd['date']+' HETG INSERTED') |
| 170 | + |
| 171 | + elif 'MSID= 4OHETGRE' in each_cmd['commands']: |
| 172 | + HETG_out_date = each_cmd['date'] |
| 173 | + HETG_out_time = each_cmd['time'] |
| 174 | + hetg_out = True |
| 175 | + hetg_in = False |
| 176 | + HETG_status = 'OUT' |
| 177 | + print(' '+each_cmd['date']+' HETG RETRACTED') |
| 178 | + |
| 179 | + elif 'EQF013M' in each_cmd['commands']: |
| 180 | + EQF013M_date = each_cmd['date'] |
| 181 | + eqf013m_acq = True |
| 182 | + |
| 183 | + elif 'EEF1000' in each_cmd['commands']: |
| 184 | + EEF1000_date = each_cmd['date'] |
| 185 | + eef1000_acq = True |
| 186 | + |
| 187 | + elif 'XQF013M' in each_cmd['commands']: |
| 188 | + XQF013M_date = each_cmd['date'] |
| 189 | + xqf013m_acq = True |
| 190 | + |
| 191 | + elif 'XEF1000' in each_cmd['commands']: |
| 192 | + XEF1000_date = each_cmd['date'] |
| 193 | + xef1000_acq = True |
| 194 | + |
| 195 | + # If the event is EPERIGEE, determine if the HETG is in - it better be. |
| 196 | + elif 'EPERIGEE' in each_cmd['commands']: |
| 197 | + eqf013m_acq = False |
| 198 | + eef1000_acq = False |
| 199 | + # Perigee Check - if the HETG is not in by now that is an error |
| 200 | + if HETG_status != 'IN': |
| 201 | + print('>>> ERROR - We are at perigee and the HETG is not in!') |
| 202 | + else: |
| 203 | + print(' ' + each_cmd['date'], ' EPERIGEE HETG Status is: ',HETG_status, 'ok') |
| 204 | + |
| 205 | + # Now check to see if this latest command that you've processed gives you enough |
| 206 | + # information to make an assessment |
| 207 | + |
| 208 | + # If you have both the EQF013M and EEF1000, you can calculate the Radmon Entry time |
| 209 | + if eqf013m_acq and eef1000_acq: |
| 210 | + # Calculate the Radzone Entry time. We imported ORP_File_Class which has |
| 211 | + # a method to do this, we will use that. |
| 212 | + OORMPDS_date, OORMPDS_time = ofci.Obtain_Rad_Entry_Time(EQF013M_date, EEF1000_date) |
| 213 | + # Set the flag indicating you now have the Radzone Entry time |
| 214 | + oormpds_acq = True |
| 215 | + # Set the EQF and EEF flags to false to prevent unnecessary re-calculation |
| 216 | + eqf013m_acq = False |
| 217 | + eef1000_acq = False |
| 218 | + |
| 219 | + # If you have acquired the OORMPDS time, check to see if the HETG is in |
| 220 | + if HETG_status == 'IN': |
| 221 | + print(' '+OORMPDS_date+' OORMPDS - HETG status: ', HETG_status,'ok.' ) |
| 222 | + # Shut off the booleans acquisition of OORMPDS to avoid recalculation |
| 223 | + oormpds_acq = False |
| 224 | + |
| 225 | + elif HETG_status == 'OUT': |
| 226 | + print(' '+OORMPDS_date+' >>>ERROR OORMPDS and HETG status is: ',HETG_status ) |
| 227 | + # Shut off the boolean acquisition of OORMPDS to avoid recalculation |
| 228 | + oormpds_acq = False |
| 229 | + |
| 230 | + # If you have both the XQF013M and XEF1000, you can calculate the Radmon Exit time |
| 231 | + if xqf013m_acq and xef1000_acq: |
| 232 | + # Calculate the Radzone Exit time. The ORP_File_Class has a handy method to do |
| 233 | + # this, so we will use that. |
| 234 | + OORMPEN_date, OORMPEN_time = ofci.Obtain_Rad_Exit_Time(XQF013M_date, XEF1000_date) |
| 235 | + # Show the user the execution time of OORMPEN |
| 236 | + print(' '+OORMPEN_date+' OORMPEN - HETG status: ', HETG_status ) |
| 237 | + # Next, calculate the percentage of time of the Radzone passage the HETG was IN |
| 238 | + # But you can only do this if you have all the data from a perigee passage. At |
| 239 | + # the start and end of the loads you may not have that data |
| 240 | + if (OORMPDS_date != None) and \ |
| 241 | + (OORMPEN_date != None) and \ |
| 242 | + (HETG_in_date != None) and \ |
| 243 | + (HETG_out_date != None): |
| 244 | + # Calculate the length of the perigee passage |
| 245 | + radzone_length = cd.Calc_Delta_Time(OORMPDS_date, OORMPEN_date) |
| 246 | + |
| 247 | + # If this is the end of the perigee passage and the HETG was retracted prior to |
| 248 | + # OORMPEN then calculate the percentage the HETG was in for the passage |
| 249 | + if (radzone_length[0] > 0.0) and \ |
| 250 | + (HETG_status == 'OUT'): |
| 251 | + HETG_in_length = cd.Calc_Delta_Time(HETG_in_date, HETG_out_date) |
| 252 | + percent_in = HETG_in_length[0]/radzone_length[0] * 100.0 |
| 253 | + print(' Percent time the HETG was in for this Perigee Passage: %.2f' % (percent_in),'%') |
| 254 | + elif (radzone_length[0] > 0.0) and \ |
| 255 | + (HETG_status == 'IN'): |
| 256 | + # But if the HETG is still in, calculate the percentage using the OORMPEN time |
| 257 | + # for the HETG time interval calculation |
| 258 | + HETG_in_length = cd.Calc_Delta_Time(HETG_in_date, OORMPEN_date) |
| 259 | + percent_in = HETG_in_length[0]/radzone_length[0] * 100.0 |
| 260 | + print(' Percent time the HETG was in for this Perigee Passage: %.2f' % (percent_in),'%') |
| 261 | + print('\n') |
| 262 | + # You are done with this Perigee Passage so set all of the flags to false |
| 263 | + eqf013m_acq = False |
| 264 | + eef1000_acq = False |
| 265 | + xqf013m_acq = False |
| 266 | + xef1000_acq = False |
| 267 | + oormpds_acq = False |
| 268 | + |
| 269 | + |
| 270 | +# At this point, you have processed all the complete, radzones in the load |
| 271 | +# Very often, however, a Radzone can be split across loads. So this check is |
| 272 | +# for a partial radzone: |
| 273 | +# if we are at the end of the load and OORMPDS has occurred and OORMPEN has NOT occurred then |
| 274 | +# Check the HETG status |
| 275 | + |
| 276 | +if oormpds_acq and not oormpen_acq: |
| 277 | + if HETG_status == 'IN': |
| 278 | + print('End of load; RADMON Disabled; HETG status is: ', HETG_status, 'ok.') |
| 279 | + else: |
| 280 | + print('>>>ERROR - End of load; RADMON Disabled; HETG status is: ', HETG_status, 'not ok.') |
| 281 | + |
| 282 | + |
0 commit comments