27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168 | class EndOfNight(KPFFunction):
'''Send KPF in to an end of night configuration.
- kpffiu.MODE = Stowed
- Power off FVCs
- Power off LED back illuminators
- close AO hatch
- HEPA on
- Send PCU to Home
ARGS:
=====
:AO: (bool) Close AO hatch, home PCU, and turn on HEPA? (default=True)
'''
@classmethod
@obey_scriptrun
def pre_condition(cls, args):
pass
@classmethod
@add_script_log(Path(__file__).name.replace(".py", ""))
def perform(cls, args):
# Check Scripts
kpfconfig = ktl.cache('kpfconfig')
expose = ktl.cache('kpfexpose', 'EXPOSE')
scriptname = kpfconfig['SCRIPTNAME'].read()
pid = kpfconfig['SCRIPTPID'].read(binary=True)
script_running = scriptname not in ['', 'None', None] or pid >= 0
if script_running and args.get('confirm', False) is True:
log.error('Non-interactive mode set and script is running')
return
if script_running:
# ---------------------------------
# User Verification
# ---------------------------------
msg = ["",
"--------------------------------------------------------------",
f"A script ({scriptname}, {pid}) is currently running. ",
"",
"Do you wish to end the current exposure and request a script",
"stop in order to proceed with running EndOfNight?",
"",
"End Exposure and Request Script Stop?",
"(y/n) [y]:",
"--------------------------------------------------------------",
"",
]
for line in msg:
print(line)
user_input = input()
if user_input.lower() in ['n', 'no', 'q', 'quit', 'abort']:
log.warning(f'User aborted End Of Night')
return
else:
log.info('User opted to stop existing script')
kpfconfig['SCRIPTSTOP'].write(1)
expose.write('End')
waittime = 120
log.info(f'Waiting up to {waittime:.0f}s for running script to end')
kpfconfig['SCRIPTPID'].waitFor("==-1", timeout=waittime)
time.sleep(2) # time shim
check_script_running()
# Stop tip tilt and agitator
StopTipTilt.execute({})
StopAgitator.execute({})
# Start FIU stow
log.info('Setting FIU mode to Stowed')
ConfigureFIU.execute({'mode': 'Stowed', 'wait': False})
# ---------------------------------
# AO Shutdown
# ---------------------------------
if args.get('AO', True) is True and args.get('confirm', False) is False:
msg = ["",
"--------------------------------------------------------------",
"Perform shutdown of AO? This will move the AO hatch and PCU.",
"The AO area should be clear of personnel before proceeding.",
"",
"Do you wish to shutdown AO?",
"(y/n) [y]:",
"--------------------------------------------------------------",
"",
]
for line in msg:
print(line)
user_input = input()
if user_input.lower() in ['y', 'yes', '']:
log.debug('User chose to shut down AO')
log.info('Closing AO Hatch')
try:
ControlAOHatch.execute({'destination': 'closed'})
except FailedToReachDestination:
log.error(f"AO hatch did not move successfully")
log.info('Sending PCU stage to Home position')
SendPCUtoHome.execute({})
# log.info('Turning on AO HEPA Filter System')
# TurnHepaOn.execute({})
else:
log.warning(f'User chose to skip AO shutdown')
# ---------------------------------
# Remaining non-AO Actions
# ---------------------------------
# Power off FVCs
for camera in ['SCI', 'CAHK', 'CAL']:
FVCPower.execute({'camera': camera, 'power': 'off'})
# Power off LEDs
for LED in ['ExpMeterLED', 'CaHKLED', 'SciLED', 'SkyLED']:
CalLampPower.execute({'lamp': LED, 'power': 'off'})
# Finish FIU shutdown
WaitForConfigureFIU.execute({'mode': 'Stowed'})
# Set PROGNAME
log.info('Clearing values for PROGNAME, OBSERVER, OBJECT')
WaitForReady.execute({})
SetProgram.execute({'progname': ''})
SetObserver.execute({'observer': ''})
SetObject.execute({'Object': ''})
# Power off Simulcal lamp
kpfconfig = ktl.cache('kpfconfig')
calsource = kpfconfig['SIMULCALSOURCE'].read()
if calsource in ['U_gold', 'U_daily', 'Th_daily', 'Th_gold']:
CalLampPower.execute({'lamp': calsource, 'power': 'off'})
# Allow scheduled cals
log.info('Set ALLOWSCHEDULEDCALS to Yes')
kpfconfig = ktl.cache('kpfconfig')
kpfconfig['ALLOWSCHEDULEDCALS'].write('Yes')
@classmethod
def post_condition(cls, args):
pass
@classmethod
def add_cmdline_args(cls, parser):
parser.add_argument("--noAO", dest="AO",
default=True, action="store_false",
help="Skip configuring AO?")
parser.add_argument("--confirm", dest="confirm",
default=False, action="store_true",
help="Skip confirmation questions (script will be non interactive)?")
return super().add_cmdline_args(parser)
|