diff --git a/index.html b/index.html index 68647d51..f2e613a7 100644 --- a/index.html +++ b/index.html @@ -312,5 +312,5 @@

Instrument Description

diff --git a/search/search_index.json b/search/search_index.json index 4c91031e..0dc95c7c 100644 --- a/search/search_index.json +++ b/search/search_index.json @@ -1 +1 @@ -{"config":{"indexing":"full","lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"Keck Planet Finder (KPF) Email Contact: kpf_info@keck.hawaii.edu Instrument Scientist: Josh Walawender Deputy Instrument Scientist: Sherry Yeh Instrument Description The Keck Planet Finder (KPF) is a \ufb01ber-fed, high-resolution, high-stability cross dispersed, spectrometer designed to characterize exoplanets via Doppler spectroscopy with a goal of a single measurement precision of 0.3 m/s or better. KPF covers a wavelength range of 445 nm to 870 nm over green and red channels. KPF consists of 3 independant spectrographs: The primary science spectrograph described above which is designed to be highly stable and has both a green and red arm. The spectrograph optical bench is made from low expansion Zerodur and is kept is a temperature stabilized environment. A Calcium H&K spectrograph which gets the light blueward of the main science spectrograph and is used to simultaneously measure stellar activity using the Ca H&K lines. The exposure meter spectrograph which gets a portion of the science light and is used to measure the flux level during long exposures of the primary science detectors. The exposure meter both measures the time weighted flux midpoint of each exposure, and can also be used to terminate an exposure at a specified flux level. All three spectrographs are fed by optical fiber from the Fiber Injection Unit (FIU) which sits on the Keck I AO bench. The light entering the FIU is not AO corrected, but is fed off a fast tip tilt mirror which is used to maintain the target star's position on the science fiber within 50 mas rms of the fiber center. Performance of the tip tilt loop is to be confirmed during commissioning. During observations, the spectrograph can be fed with light from a simultaneous calibration fiber. This places calibration light alongside science and sky spectra in the pseudo-slit. The calibration light is fed from the calibration bench which contains several calibration sources. In addition to the simultaneous calibration light, the calibration bench can be configured to feed light up to the FIU and through the science and sky fibers in order to bring cal light in to the science and sky portions of the pseudo-slit. The system overview diagram showing the relationships between the different subsystems of the instrument. KPF's Zerodur optical bench during integration at the Space Sciences Lab at UC Berkeley. The echelle grating can be seen at the upper right.","title":"KPF Home"},{"location":"#keck-planet-finder-kpf","text":"Email Contact: kpf_info@keck.hawaii.edu Instrument Scientist: Josh Walawender Deputy Instrument Scientist: Sherry Yeh","title":"Keck Planet Finder (KPF)"},{"location":"#instrument-description","text":"The Keck Planet Finder (KPF) is a \ufb01ber-fed, high-resolution, high-stability cross dispersed, spectrometer designed to characterize exoplanets via Doppler spectroscopy with a goal of a single measurement precision of 0.3 m/s or better. KPF covers a wavelength range of 445 nm to 870 nm over green and red channels. KPF consists of 3 independant spectrographs: The primary science spectrograph described above which is designed to be highly stable and has both a green and red arm. The spectrograph optical bench is made from low expansion Zerodur and is kept is a temperature stabilized environment. A Calcium H&K spectrograph which gets the light blueward of the main science spectrograph and is used to simultaneously measure stellar activity using the Ca H&K lines. The exposure meter spectrograph which gets a portion of the science light and is used to measure the flux level during long exposures of the primary science detectors. The exposure meter both measures the time weighted flux midpoint of each exposure, and can also be used to terminate an exposure at a specified flux level. All three spectrographs are fed by optical fiber from the Fiber Injection Unit (FIU) which sits on the Keck I AO bench. The light entering the FIU is not AO corrected, but is fed off a fast tip tilt mirror which is used to maintain the target star's position on the science fiber within 50 mas rms of the fiber center. Performance of the tip tilt loop is to be confirmed during commissioning. During observations, the spectrograph can be fed with light from a simultaneous calibration fiber. This places calibration light alongside science and sky spectra in the pseudo-slit. The calibration light is fed from the calibration bench which contains several calibration sources. In addition to the simultaneous calibration light, the calibration bench can be configured to feed light up to the FIU and through the science and sky fibers in order to bring cal light in to the science and sky portions of the pseudo-slit. The system overview diagram showing the relationships between the different subsystems of the instrument. KPF's Zerodur optical bench during integration at the Space Sciences Lab at UC Berkeley. The echelle grating can be seen at the upper right.","title":"Instrument Description"},{"location":"CalOBparameters/","text":"","title":"Calibration OB Parameters"},{"location":"KPFTranslator/","text":"KPF Translator Most of KPF operations are controlled via the KPF Translator which is composed of Python code, which interacts with the underlying KTL keywords to automate various tasks. Each script is actually a Python class which is invoked by an execute() method which itself calls the pre_condition() , perform() , and post_condition() methods. This three-part structure allows the script to check that the system is ready for the action to be performed, then execute the action, then confirm a successful execution. These scripts can also be invoked via a command line interface to the underlying python and are used for everything from small, atomic actions which might require only a single KTL keyword write to execute, to large scripts which need significant flow control such as executing a science observation at night -- including configuring the instrument, waiting for the telescope and tip-tilt system to acquire the target, executing the specified exposures, and finally performing clean up actions. Detailed documentation on each translator script can be found in the scripts section of this documentation.","title":"Instrument Software"},{"location":"KPFTranslator/#kpf-translator","text":"Most of KPF operations are controlled via the KPF Translator which is composed of Python code, which interacts with the underlying KTL keywords to automate various tasks. Each script is actually a Python class which is invoked by an execute() method which itself calls the pre_condition() , perform() , and post_condition() methods. This three-part structure allows the script to check that the system is ready for the action to be performed, then execute the action, then confirm a successful execution. These scripts can also be invoked via a command line interface to the underlying python and are used for everything from small, atomic actions which might require only a single KTL keyword write to execute, to large scripts which need significant flow control such as executing a science observation at night -- including configuring the instrument, waiting for the telescope and tip-tilt system to acquire the target, executing the specified exposures, and finally performing clean up actions. Detailed documentation on each translator script can be found in the scripts section of this documentation.","title":"KPF Translator"},{"location":"KPFvsHIRES/","text":"Comparing KPF to HIRES This page attempts to compare KPF and HIRES for users who may be wondering which instrument they should propose for. Fundamentally HIRES is a more flexible instrument with selectable grating angles to control the wavelength coverage and selectable slits which allow the user to trade off throughput against spectral resolution while KPF is a fixed format spectrograph with a fixed input fiber. HIRES also has a wider spectral coverage than KPF and even includes the option to change the internal optics to optimize either blue or red sensitivity. Though KPF has the Calcium H&K spectrograph, a dedicated arm to examine the 382-402 nm wavelength range around the Ca H&K lines. KPF, on the other hand, has higher spectral resolution even though it has a larger entrance aperture on sky and so it may be more sensitive for use cases which need that combination. Of course, KPF is also highly stabilized and is optimized for precision radial velocity measurements. Summary Table Comparison KPF HIRES Optical Input 1.14 arcsec octagonal fibers for science and sky (fixed format) Selectable deckers and slits for different sky projections (e.g., B5 = 0.87 x 3.5 arcsec) Wavelength Coverage Fixed format: 445-870 nm (high-res) 382-402 nm (med-res) ~300-1000 nm in an adjustable format (moving the spectral format across detector) Resolving Power R=98k (445-870 nm) depends on slit e.g. R=49k for 0.86 arcsec-wide slit R=80k for 0.40 arcsec-wide slit Throughput (sky to CCD) ~8-10% peak-of-blaze (measured) 5-6% peak-of-blaze for B5-B1 deckers (measured) Doppler Precision 0.5 m/s noise floor (req.) 0.3 m/s (goal) ~2 m/s systematic noise floor Doppler Speed ~8-10x faster than HIRES Limited by need for high SNR to model iodine spectrum Comparing Using Exposure Time Calculators (ETCs) Using the HIRES ETC at UCO and the KPF ETC , we can compare the signal to noise in observations of a common target in each instrument. It should be noted that the plot below is not a direct comparison of the two instruments, but is a comparison of two exposure time calculators. Subtle differences in assumptions made in each piece of software may bias this result, so this should be taken as illustrative, not definitive. Comparison of the signal to noise estimates from ETCs for KPF and HIRES. Inputs to the ETCs were as similar as possible.","title":"KPF vs. HIRES"},{"location":"KPFvsHIRES/#comparing-kpf-to-hires","text":"This page attempts to compare KPF and HIRES for users who may be wondering which instrument they should propose for. Fundamentally HIRES is a more flexible instrument with selectable grating angles to control the wavelength coverage and selectable slits which allow the user to trade off throughput against spectral resolution while KPF is a fixed format spectrograph with a fixed input fiber. HIRES also has a wider spectral coverage than KPF and even includes the option to change the internal optics to optimize either blue or red sensitivity. Though KPF has the Calcium H&K spectrograph, a dedicated arm to examine the 382-402 nm wavelength range around the Ca H&K lines. KPF, on the other hand, has higher spectral resolution even though it has a larger entrance aperture on sky and so it may be more sensitive for use cases which need that combination. Of course, KPF is also highly stabilized and is optimized for precision radial velocity measurements.","title":"Comparing KPF to HIRES"},{"location":"KPFvsHIRES/#summary-table","text":"Comparison KPF HIRES Optical Input 1.14 arcsec octagonal fibers for science and sky (fixed format) Selectable deckers and slits for different sky projections (e.g., B5 = 0.87 x 3.5 arcsec) Wavelength Coverage Fixed format: 445-870 nm (high-res) 382-402 nm (med-res) ~300-1000 nm in an adjustable format (moving the spectral format across detector) Resolving Power R=98k (445-870 nm) depends on slit e.g. R=49k for 0.86 arcsec-wide slit R=80k for 0.40 arcsec-wide slit Throughput (sky to CCD) ~8-10% peak-of-blaze (measured) 5-6% peak-of-blaze for B5-B1 deckers (measured) Doppler Precision 0.5 m/s noise floor (req.) 0.3 m/s (goal) ~2 m/s systematic noise floor Doppler Speed ~8-10x faster than HIRES Limited by need for high SNR to model iodine spectrum","title":"Summary Table"},{"location":"KPFvsHIRES/#comparing-using-exposure-time-calculators-etcs","text":"Using the HIRES ETC at UCO and the KPF ETC , we can compare the signal to noise in observations of a common target in each instrument. It should be noted that the plot below is not a direct comparison of the two instruments, but is a comparison of two exposure time calculators. Subtle differences in assumptions made in each piece of software may bias this result, so this should be taken as illustrative, not definitive. Comparison of the signal to noise estimates from ETCs for KPF and HIRES. Inputs to the ETCs were as similar as possible.","title":"Comparing Using Exposure Time Calculators (ETCs)"},{"location":"SciOBparameters/","text":"Science OB Contents Here is an example science OB formatted as a text file (this is the YAML data format). The comments (preceded by a # symbol) are not needed, but are present to help the reader. Template_Name : kpf_sci Template_Version : 1.0 # Target Info TargetName : 10700 # Name GaiaID : DR3 2452378776434276992 # Gaia ID 2 MASSID : 01440402 - 1556141 # 2 MASS ID Parallax : 273.81 # Parallax in arcsec RadialVelocity : - 16.597 # Radial Velocity in km / s Gmag : 3.3 # G band magnitude ( eventualy used by exposure meter ) Jmag : 2.14 # J band magnitude ( eventualy used by guider ) Teff : 5266 # Effective temperature # Spectrograph Setup TriggerCaHK : False # Include CaHK in exposure ( True / False ) TriggerGreen : True # Include Green CCD in exposure ( True / False ) TriggerRed : True # Include Red CCD in exposure ( True / False ) BlockSky : False # Close the sky fiber shutter during observations ( True / False ) # Observations SEQ_Observations : # - Object : 10700 # User settable comment nExp : 4 # Number of exoposures in the OB ExpTime : 30 # Exposure time of the main spectrometer and CaH & K . See Exposure Meter section below . ExpMeterMode : control # \"monitor\" or \"control\" ( to terminate exposure based on flux ) AutoExpMeter : False # Set the exposure meter exposure time automatically ExpMeterExpTime : 0.5 # Exposure time of the Exposure Meter subframes ExpMeterBin : 3 # Exposure meter wavelength bin to use for stopping exposure ExpMeterThreshold : 1 e5 # Target science flux in e -/ nm TakeSimulCal : True # Take simultaneous calibrations ? ( True / False ) AutoNDFilters : False # Automatically set ND filters -- Not available at this time ! CalND1 : OD 4.0 # OD = Optical Density . Throughput = 10 ^- OD CalND2 : OD 0.1 # Each value in the OB is described in more detail below. Template_Name and Template_Version ( str ) These values indicate to the software what sort of observation this is and what script to execute. For a science observation, always use \"kpf_sci\" as the template name. TargetName : ( str ) This is a name chosen by the observer. GaiaID and 2MASSID : ( str ) These values are used by the DRP to identify the star and determine its properties. Parallax : ( float ) Parallax in arcseconds. RadialVelocity : ( float ) Radial Velocity in km/s. Gmag : ( float ) This is used by the DRP and by the algorithm which automatically sets the exposure meter exposure time. Jmag : ( float ) This is used by the algorithm which automatically sets the guider gain and frame rate. Teff : ( float ) The effective temperature of the star. Allowed Range: 2600 - 45000 TriggerCaHK, TriggerGreen, and TriggerRed : ( bool ) These values indicate whether to trigger the respective camera during the science exposures. All of these cameras will be synced up and will get the same exposure time. SEQ_Observations The SEQ_Observations: line is required. The following block of lines represent one entry in a list. If more than one set of exposures on a target is desired, this block of text can be repeated to build a second \"observation\" on the target with different parameters. Object : ( str ) This value will go in to the FITS header as the OBJECT keyword value. This is can be used as a notes field for the observer to explain how this set of exposures differs from any following observations of this target. This field can be left blank or set to the target name, it is entirely up to the observer. nExp : ( int ) The number of exposures to take. ExpTime : ( float ) The exposure time in seconds. Note that if the exposure meter is controlling the exposure duration, this exposure time is the maximum value which will be allowed (the exposure meter may cut the exposure short if the desired flux level is reached). ExpMeterMode : ( str ) For now, only the \"monitor\" mode is available. In \"monitor\" the exposure meter will take exposure during the science exposure and record fluxes. This data will be stored in the resulting FITS file can be used to determine the flux weighted exposure midpoint in time for accurate barycentric correction. Allowed Values: \"monitor\", \"control\", or \"off\" AutoExpMeter : ( bool ) If this is True, the software will use the Gmag value to estimate a good exposure time for the individual exposure meter exposures and use that instead of the ExpMeterExpTime value below. ExpMeterExpTime : ( float ) The exposure time in seconds for individual exposure meter exposures. This is ignored if AutoExpMeter is True. TakeSimulCal : ( bool ) Should the instrument be configured to illuminate the simultaneous calibration fiber during the science exposure? AutoNDFilters : ( bool ) Should the software automatically set the ND filters based on the target and exposure information? This is currently (June 2024) in a testing mode and is not recommended for normal use. CalND1 ( str ) The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: OD 0.1 , OD 1.0 , OD 1.3 , OD 2.0 , OD 3.0 , OD 4.0 CalND2 ( str ) The neutral density filter to put in the second filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: OD 0.1 , OD 0.3 , OD 0.5 , OD 0.8 , OD 1.0 , OD 4.0","title":"Science OB Parameters"},{"location":"SciOBparameters/#science-ob-contents","text":"Here is an example science OB formatted as a text file (this is the YAML data format). The comments (preceded by a # symbol) are not needed, but are present to help the reader. Template_Name : kpf_sci Template_Version : 1.0 # Target Info TargetName : 10700 # Name GaiaID : DR3 2452378776434276992 # Gaia ID 2 MASSID : 01440402 - 1556141 # 2 MASS ID Parallax : 273.81 # Parallax in arcsec RadialVelocity : - 16.597 # Radial Velocity in km / s Gmag : 3.3 # G band magnitude ( eventualy used by exposure meter ) Jmag : 2.14 # J band magnitude ( eventualy used by guider ) Teff : 5266 # Effective temperature # Spectrograph Setup TriggerCaHK : False # Include CaHK in exposure ( True / False ) TriggerGreen : True # Include Green CCD in exposure ( True / False ) TriggerRed : True # Include Red CCD in exposure ( True / False ) BlockSky : False # Close the sky fiber shutter during observations ( True / False ) # Observations SEQ_Observations : # - Object : 10700 # User settable comment nExp : 4 # Number of exoposures in the OB ExpTime : 30 # Exposure time of the main spectrometer and CaH & K . See Exposure Meter section below . ExpMeterMode : control # \"monitor\" or \"control\" ( to terminate exposure based on flux ) AutoExpMeter : False # Set the exposure meter exposure time automatically ExpMeterExpTime : 0.5 # Exposure time of the Exposure Meter subframes ExpMeterBin : 3 # Exposure meter wavelength bin to use for stopping exposure ExpMeterThreshold : 1 e5 # Target science flux in e -/ nm TakeSimulCal : True # Take simultaneous calibrations ? ( True / False ) AutoNDFilters : False # Automatically set ND filters -- Not available at this time ! CalND1 : OD 4.0 # OD = Optical Density . Throughput = 10 ^- OD CalND2 : OD 0.1 # Each value in the OB is described in more detail below. Template_Name and Template_Version ( str ) These values indicate to the software what sort of observation this is and what script to execute. For a science observation, always use \"kpf_sci\" as the template name. TargetName : ( str ) This is a name chosen by the observer. GaiaID and 2MASSID : ( str ) These values are used by the DRP to identify the star and determine its properties. Parallax : ( float ) Parallax in arcseconds. RadialVelocity : ( float ) Radial Velocity in km/s. Gmag : ( float ) This is used by the DRP and by the algorithm which automatically sets the exposure meter exposure time. Jmag : ( float ) This is used by the algorithm which automatically sets the guider gain and frame rate. Teff : ( float ) The effective temperature of the star. Allowed Range: 2600 - 45000 TriggerCaHK, TriggerGreen, and TriggerRed : ( bool ) These values indicate whether to trigger the respective camera during the science exposures. All of these cameras will be synced up and will get the same exposure time.","title":"Science OB Contents"},{"location":"SciOBparameters/#seq_observations","text":"The SEQ_Observations: line is required. The following block of lines represent one entry in a list. If more than one set of exposures on a target is desired, this block of text can be repeated to build a second \"observation\" on the target with different parameters. Object : ( str ) This value will go in to the FITS header as the OBJECT keyword value. This is can be used as a notes field for the observer to explain how this set of exposures differs from any following observations of this target. This field can be left blank or set to the target name, it is entirely up to the observer. nExp : ( int ) The number of exposures to take. ExpTime : ( float ) The exposure time in seconds. Note that if the exposure meter is controlling the exposure duration, this exposure time is the maximum value which will be allowed (the exposure meter may cut the exposure short if the desired flux level is reached). ExpMeterMode : ( str ) For now, only the \"monitor\" mode is available. In \"monitor\" the exposure meter will take exposure during the science exposure and record fluxes. This data will be stored in the resulting FITS file can be used to determine the flux weighted exposure midpoint in time for accurate barycentric correction. Allowed Values: \"monitor\", \"control\", or \"off\" AutoExpMeter : ( bool ) If this is True, the software will use the Gmag value to estimate a good exposure time for the individual exposure meter exposures and use that instead of the ExpMeterExpTime value below. ExpMeterExpTime : ( float ) The exposure time in seconds for individual exposure meter exposures. This is ignored if AutoExpMeter is True. TakeSimulCal : ( bool ) Should the instrument be configured to illuminate the simultaneous calibration fiber during the science exposure? AutoNDFilters : ( bool ) Should the software automatically set the ND filters based on the target and exposure information? This is currently (June 2024) in a testing mode and is not recommended for normal use. CalND1 ( str ) The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: OD 0.1 , OD 1.0 , OD 1.3 , OD 2.0 , OD 3.0 , OD 4.0 CalND2 ( str ) The neutral density filter to put in the second filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: OD 0.1 , OD 0.3 , OD 0.5 , OD 0.8 , OD 1.0 , OD 4.0","title":"SEQ_Observations"},{"location":"afternoonsetup/","text":"Afternoon Setup The afternoon setup process for the instrument itself is minimal. Calibrations are automated, so unless you have very special requirements for your observation (if so please contact the Staff Astronomer supporting your night in advance), then observers will not need to execute any calibrations. Prior to starting observing, observers should run: KPF Control Menu --> Start KPF GUIs from the background menu (or kpfStartGUIs from the command line on any KPF machine). This will start the KPF GUIs and can be run at any time prior to observing. Preparing Observing Blocks (OBs) Observers should use the afternoon to prepare Observing Blocks (OBs) and their star list if they have not done so already. Connecting to VNCs Observers can connect to the Keck VNCs to control the instrument from Keck HQ in Waimea, one of the Keck Remote Observing Stations, or from home using the Remote Observing Software. For details, see the Remote Observing documentation. Starting KPF GUIs The KPF GUIs can be started at any time. To do so, choose KPF Control Menu -> Start KPF GUIs from the FVWM menu. Check that the GUIs come up properly in the various VNC sessions. Each session is described below. control0 The control0 VNC session should contain: OB GUI : This is where the observer can build and execute observing blocks. Tip Tilt GUI : This is a view-only version of the GUI the OAs use to control the tip tilt system. Observers can use this to see the tip tilt system status and images, but observers can not control the system. control1 The control1 VNC session should contain: FIU GUI : This shows the status of the FIU including the light path. This is a good place to look if you are not seeing stars on the guider and want to know if the guider should eb seeing the sky. Exposure Meter GUI : This will show the progress of the flux measured by the exposure meter over the course of a single exposure. Spectrograph GUI : This shows the staus of the overall instrument (including a simplified FIU status). The light paths which are illuminated will show up as colored lines and arrows here to indicate where light is being directed by the various components. control2 The control2 VNC session should contain: A ds9 instance which shows the latest raw image from the Ca H&K, Green, and Red detectors. Eventsounds GUI : This is a standard Keck GUI where the users can enable/disable sounds and change what sound is produced by a given event. telstatus The telstatus VNC session should contain: FACSUM : A standard Keck GUI showing the status of the facility (telescope and dome). XMET : A standard Keck GUI showing various weather telemetry values. The OAs have more weather information which is not shown here, but this is a good summary. Magiq Observer UI : A standard Keck GUI for viewing guider images and interacting with star lists. Note that the Magiq UI may not come up if the StartGUIs script was run while KPF was not the selected instrument. The Magiq UI will always come up with the guider for the selected instrument when launched. If Magiq is not running, launch it via Telescope GUIs --> Magiq Guider UI from the FVWM menu.","title":"Afternoon Setup"},{"location":"afternoonsetup/#afternoon-setup","text":"The afternoon setup process for the instrument itself is minimal. Calibrations are automated, so unless you have very special requirements for your observation (if so please contact the Staff Astronomer supporting your night in advance), then observers will not need to execute any calibrations. Prior to starting observing, observers should run: KPF Control Menu --> Start KPF GUIs from the background menu (or kpfStartGUIs from the command line on any KPF machine). This will start the KPF GUIs and can be run at any time prior to observing.","title":"Afternoon Setup"},{"location":"afternoonsetup/#preparing-observing-blocks-obs","text":"Observers should use the afternoon to prepare Observing Blocks (OBs) and their star list if they have not done so already.","title":"Preparing Observing Blocks (OBs)"},{"location":"afternoonsetup/#connecting-to-vncs","text":"Observers can connect to the Keck VNCs to control the instrument from Keck HQ in Waimea, one of the Keck Remote Observing Stations, or from home using the Remote Observing Software. For details, see the Remote Observing documentation.","title":"Connecting to VNCs"},{"location":"afternoonsetup/#starting-kpf-guis","text":"The KPF GUIs can be started at any time. To do so, choose KPF Control Menu -> Start KPF GUIs from the FVWM menu. Check that the GUIs come up properly in the various VNC sessions. Each session is described below.","title":"Starting KPF GUIs"},{"location":"afternoonsetup/#control0","text":"The control0 VNC session should contain: OB GUI : This is where the observer can build and execute observing blocks. Tip Tilt GUI : This is a view-only version of the GUI the OAs use to control the tip tilt system. Observers can use this to see the tip tilt system status and images, but observers can not control the system.","title":"control0"},{"location":"afternoonsetup/#control1","text":"The control1 VNC session should contain: FIU GUI : This shows the status of the FIU including the light path. This is a good place to look if you are not seeing stars on the guider and want to know if the guider should eb seeing the sky. Exposure Meter GUI : This will show the progress of the flux measured by the exposure meter over the course of a single exposure. Spectrograph GUI : This shows the staus of the overall instrument (including a simplified FIU status). The light paths which are illuminated will show up as colored lines and arrows here to indicate where light is being directed by the various components.","title":"control1"},{"location":"afternoonsetup/#control2","text":"The control2 VNC session should contain: A ds9 instance which shows the latest raw image from the Ca H&K, Green, and Red detectors. Eventsounds GUI : This is a standard Keck GUI where the users can enable/disable sounds and change what sound is produced by a given event.","title":"control2"},{"location":"afternoonsetup/#telstatus","text":"The telstatus VNC session should contain: FACSUM : A standard Keck GUI showing the status of the facility (telescope and dome). XMET : A standard Keck GUI showing various weather telemetry values. The OAs have more weather information which is not shown here, but this is a good summary. Magiq Observer UI : A standard Keck GUI for viewing guider images and interacting with star lists. Note that the Magiq UI may not come up if the StartGUIs script was run while KPF was not the selected instrument. The Magiq UI will always come up with the guider for the selected instrument when launched. If Magiq is not running, launch it via Telescope GUIs --> Magiq Guider UI from the FVWM menu.","title":"telstatus"},{"location":"agitator/","text":"Agitator KPF includes a mechanical oscillator which agitates the fibers to aid in mode scrambling in the fibers. The agitator is located directly beneath the azimuth ring of the Keck I telescope. It is automatically turned on and off during science and calibration observations and needs no user intervention. The agitator oscillates at about 2 Hz.","title":"Agitator"},{"location":"agitator/#agitator","text":"KPF includes a mechanical oscillator which agitates the fibers to aid in mode scrambling in the fibers. The agitator is located directly beneath the azimuth ring of the Keck I telescope. It is automatically turned on and off during science and calibration observations and needs no user intervention. The agitator oscillates at about 2 Hz.","title":"Agitator"},{"location":"buildingOBs/","text":"Building Observing Blocks (OBs) The basic unit of KPF nighttime operations is the Observing Block (OB). An OB describes a single visit to a science target and the observations made there. The data contained in the OB is a set of keyword-value pairs. Observers can prepare OBs as text files which can be read in by the KPF software and executed or (once logged in to the KPF VNCs) they can use tools there to build the OBs and save them as files. The data in an OB can be divided in to a few rough categories: Target information : The OB will contain information about the target beyond what is in a typical Keck Star List entry in order to flow that information to the FITS header and the data reduction pipeline (DRP). Instrument Setup : The OB will also contain information about how to configure the instrument for this set of observations. Observations : Finally, the OB will contain a list of \"observations\" to be made of the target. For typical KPF observers, this will only have one entry, but multiple entries are supported. Each entry describes a set of exposures on the target and contains the information on how those exposures should be executed. KPF OB GUI A graphical tool has been built to help observers build their KPF OBs, it is launched automatically as part of the script to start all GUIs. A screenshot of the KPF OB GUI. The top section of the GUI, \"Instrument Status\" shows whether an instrument script (e.g. an observation or calibration set) is being run and allows users to request that script stop. The middle section can be used to load an OB from a file, build an OB from scratch using a Gaia DR3 catalog query, save the OB to a file, or execute the OB. The lower section is where a user can fill out the OB parameters as described in the \"KPF Science OB Contents\" section above.","title":"Building OBs"},{"location":"buildingOBs/#building-observing-blocks-obs","text":"The basic unit of KPF nighttime operations is the Observing Block (OB). An OB describes a single visit to a science target and the observations made there. The data contained in the OB is a set of keyword-value pairs. Observers can prepare OBs as text files which can be read in by the KPF software and executed or (once logged in to the KPF VNCs) they can use tools there to build the OBs and save them as files. The data in an OB can be divided in to a few rough categories: Target information : The OB will contain information about the target beyond what is in a typical Keck Star List entry in order to flow that information to the FITS header and the data reduction pipeline (DRP). Instrument Setup : The OB will also contain information about how to configure the instrument for this set of observations. Observations : Finally, the OB will contain a list of \"observations\" to be made of the target. For typical KPF observers, this will only have one entry, but multiple entries are supported. Each entry describes a set of exposures on the target and contains the information on how those exposures should be executed.","title":"Building Observing Blocks (OBs)"},{"location":"buildingOBs/#kpf-ob-gui","text":"A graphical tool has been built to help observers build their KPF OBs, it is launched automatically as part of the script to start all GUIs. A screenshot of the KPF OB GUI. The top section of the GUI, \"Instrument Status\" shows whether an instrument script (e.g. an observation or calibration set) is being run and allows users to request that script stop. The middle section can be used to load an OB from a file, build an OB from scratch using a Gaia DR3 catalog query, save the OB to a file, or execute the OB. The lower section is where a user can fill out the OB parameters as described in the \"KPF Science OB Contents\" section above.","title":"KPF OB GUI"},{"location":"cahk/","text":"Calcium H&K Spectrometer A separate small spectrometer is used to monitor the Ca H & K lines for stellar activity that could mimic Doppler shifts. A major advantage of this approach is that the KPF spectrometer does not need to cover an increased bandpass blueward to 390 nm, and can stop at 443 nm (the Doppler information is reduced for G and K stars at bluer wavelengths owing to the significantly lower flux). This approach has important advantages with respect to optical coating bandpasses and efficiency, as well as the required detector size. The Calcium H & K spectrometer is a simple system (VPH-based with doublet lenses for collimator and camera), and is fiber fed via a UV-enhanced fiber (such as CeramOptec UVNS). Light will be injected into this fiber by the FIU, to captrue this light before major UV absorption losses occur within the long fiber run. Under normal conditions, the Ca H&K spectrometer is triggered simultaneously with the main science spectrograph and the data is packaged in to the L0 file with the rest of the science data for analysis by the DRP.","title":"Ca H&K Spectrograph"},{"location":"cahk/#calcium-hk-spectrometer","text":"A separate small spectrometer is used to monitor the Ca H & K lines for stellar activity that could mimic Doppler shifts. A major advantage of this approach is that the KPF spectrometer does not need to cover an increased bandpass blueward to 390 nm, and can stop at 443 nm (the Doppler information is reduced for G and K stars at bluer wavelengths owing to the significantly lower flux). This approach has important advantages with respect to optical coating bandpasses and efficiency, as well as the required detector size. The Calcium H & K spectrometer is a simple system (VPH-based with doublet lenses for collimator and camera), and is fiber fed via a UV-enhanced fiber (such as CeramOptec UVNS). Light will be injected into this fiber by the FIU, to captrue this light before major UV absorption losses occur within the long fiber run. Under normal conditions, the Ca H&K spectrometer is triggered simultaneously with the main science spectrograph and the data is packaged in to the L0 file with the rest of the science data for analysis by the DRP.","title":"Calcium H&K Spectrometer"},{"location":"calbench/","text":"Calibration Bench The cal bench contains several calibration light sources and can inject light in to the simultaneous calibration fiber (one of the components of the pseudo slit) or to inject light to the FIU and thus illuminate the science and sky fibers with the chosen calibration lamp. Most of the calibration sources are located in the \"octagon\". A rotating fold mirror can direct light from one of 8 ports to the calibration fibers. The octagon light sources are: EtalonFiber : Light from a \"SuperK\" continuum source which has passed through the Etalon. BrdbandFiber : A broadband lamp. U_gold : A UNe arc lamp U_daily : A UNe arc lamp Th_daily : A ThAr arc lamp Th_gold : A ThAr arc lamp SoCal-CalFib : Light from the Solar Calibrator LFCFiber : Light from the Laser Frequency Comb (LFC) Etalon The KPF etalon is a thermally stable (~1 mK RMS) resonant cavity fed by an NKT SuperK EVO light source. The resulting line forest covers all of the KPF science passband. The Etalon spectrum evolves slowly with time, so it is not used for obsolte calibration, but it can be used to track the short time scale evolution of the instrument. Effectively \"filling in\" between absolute wavelength calibrators such as the LFC or the arc lamps. Broadband Lamp KPF takes relatively standard spectral flats using a broadband lamp. Because of the extreme requirements for PRV measurements, the flats must be extraordinarily high signal to noise and be taken daily to track any changes. Arc Lamps The arc lamps (ThAr and UNe) can be used for absolute wavelength calibration. Unlike the LFC, they do not have a regular spacing of lines, but they do provide lines in the bluest orders (see below). Two of each lamp are available in the octagon at any time. Laser Frequency Comb The LFC is the best calibrator due to the density of lines which allows a very precise measurement of the wavelength solution, but it is currently (early 2024) limited due to a lack of flux in the bluest orders. For those, the traditional Thorium and Uranium lamps provide absolute calibration.","title":"Calibration Bench"},{"location":"calbench/#calibration-bench","text":"The cal bench contains several calibration light sources and can inject light in to the simultaneous calibration fiber (one of the components of the pseudo slit) or to inject light to the FIU and thus illuminate the science and sky fibers with the chosen calibration lamp. Most of the calibration sources are located in the \"octagon\". A rotating fold mirror can direct light from one of 8 ports to the calibration fibers. The octagon light sources are: EtalonFiber : Light from a \"SuperK\" continuum source which has passed through the Etalon. BrdbandFiber : A broadband lamp. U_gold : A UNe arc lamp U_daily : A UNe arc lamp Th_daily : A ThAr arc lamp Th_gold : A ThAr arc lamp SoCal-CalFib : Light from the Solar Calibrator LFCFiber : Light from the Laser Frequency Comb (LFC)","title":"Calibration Bench"},{"location":"calbench/#etalon","text":"The KPF etalon is a thermally stable (~1 mK RMS) resonant cavity fed by an NKT SuperK EVO light source. The resulting line forest covers all of the KPF science passband. The Etalon spectrum evolves slowly with time, so it is not used for obsolte calibration, but it can be used to track the short time scale evolution of the instrument. Effectively \"filling in\" between absolute wavelength calibrators such as the LFC or the arc lamps.","title":"Etalon"},{"location":"calbench/#broadband-lamp","text":"KPF takes relatively standard spectral flats using a broadband lamp. Because of the extreme requirements for PRV measurements, the flats must be extraordinarily high signal to noise and be taken daily to track any changes.","title":"Broadband Lamp"},{"location":"calbench/#arc-lamps","text":"The arc lamps (ThAr and UNe) can be used for absolute wavelength calibration. Unlike the LFC, they do not have a regular spacing of lines, but they do provide lines in the bluest orders (see below). Two of each lamp are available in the octagon at any time.","title":"Arc Lamps"},{"location":"calbench/#laser-frequency-comb","text":"The LFC is the best calibrator due to the density of lines which allows a very precise measurement of the wavelength solution, but it is currently (early 2024) limited due to a lack of flux in the bluest orders. For those, the traditional Thorium and Uranium lamps provide absolute calibration.","title":"Laser Frequency Comb"},{"location":"calibrations/","text":"Calibrations KPF observers do not need to take afternoon cals because the calibration system is automatic (driven by cron jobs). This is important to PRV science as to get the best RVs, the instrument and its daily cycles need to be characterized, so we want to sample the calibrations in a systematic and repeatable way each day. The calibration schedule is a trade off between several factors. Because we want the calibrations to happen at a consistent time each day, we start the daily schedule based on the latest sunrise and the earliest sunset of the year. The calibrations can be broadly divided in to several categories described in the Types of Calibrations section below. The Daily Calibration Schedule Each day, the calibrations described below are executed. The needs of KPF are such that each day is filled as much as possible by calibrations. The diagram below shows what that schedule looks like over the course of a year as the sunrise and sunset times evolve with the seasons. This figure shows how the KPF calibration schedule interacts with the nighttime schedule over the course of a year (the 23A & B semesters in this case). The various lines show how daily events such as sunrise and sunset evolve in UT time. The lines are labeled on the left side of the plot. The shaded regions are the approximate duration of the scheduled calibrations. Even if no KPF observations are scheduled, the calibrations occupy 816 minutes (more than 13.5 hours) each day, or about 57% of the day. The gaps in this schedule are driven the desire to avoid having calibrations in progress when someone might be starting to operate the instrument: near sunset and at each of the quarter night boundaries. Types of Calibrations Wavelength Calibrations Wavelength calibrations are the most critical daily calibration. Absolute wavelength calibrations use the laser frequency comb (LFC) or one of the hollow cathode lamps (ThAr or UNe). The etalon is also used for wavelength calibration, but in a slightly different way. The etalon spectrum is not fixed to absolute wavelengths as the LFC and the Thorium and Uranium lamps are, but it has the advantage of being far more robust. The positions of the etalon lines can evolve slowly with time, but on short (<1 day) timescales they are stable. Thus the etalon calibration frames can be used to track the evolution of the instrument over daily timescales (anchored by the morning and afternoon wavelength cals). Thus it is valuable to have etalon observations taken periodically throughout the day and night. Broadband Flats KPF takes relatively standard spectral flats using a broadband lamp. Because of the extreme requirements for PRV measurements, the flats must be extraordinarily high signal to noise and be taken daily to track any changes. Biases and Darks KPF takes biases and darks like other instruments. We try to schedule these in to the lamp warmup time built in to other calibrations, so they end up being spread out throughout the day during other calibration OBs. Other Calibrations We currently also take two other calibrations: a set of biases for the Exposure Meter every day and a set of CRED2 guide camera biases a couple times per week. Overnight Etalon In addition to the calibrations taken during daytime, we have scheduled four long calibration sequences to happen overnight. The start times are chosen so that they should not be in progress when an observer might be starting use of the instrument (e.g. at a quarter night boundary). The scheduled cals will not begin during observations because the kpfStartOfNight script sets the kpfconfig.ALLOWSCHEDULEDCALS keyword to \u201cNo\u201d and the script to run the overnight calibrations respects that keyword. If for some reason, they are running when an observer needs to being observing, the cals can be stopped using the standard tools to halt a script in progress (e.g. the \u201cRequest Script Stop\u201d button in the OB GUI).","title":"Daytime Calibrations"},{"location":"calibrations/#calibrations","text":"KPF observers do not need to take afternoon cals because the calibration system is automatic (driven by cron jobs). This is important to PRV science as to get the best RVs, the instrument and its daily cycles need to be characterized, so we want to sample the calibrations in a systematic and repeatable way each day. The calibration schedule is a trade off between several factors. Because we want the calibrations to happen at a consistent time each day, we start the daily schedule based on the latest sunrise and the earliest sunset of the year. The calibrations can be broadly divided in to several categories described in the Types of Calibrations section below.","title":"Calibrations"},{"location":"calibrations/#the-daily-calibration-schedule","text":"Each day, the calibrations described below are executed. The needs of KPF are such that each day is filled as much as possible by calibrations. The diagram below shows what that schedule looks like over the course of a year as the sunrise and sunset times evolve with the seasons. This figure shows how the KPF calibration schedule interacts with the nighttime schedule over the course of a year (the 23A & B semesters in this case). The various lines show how daily events such as sunrise and sunset evolve in UT time. The lines are labeled on the left side of the plot. The shaded regions are the approximate duration of the scheduled calibrations. Even if no KPF observations are scheduled, the calibrations occupy 816 minutes (more than 13.5 hours) each day, or about 57% of the day. The gaps in this schedule are driven the desire to avoid having calibrations in progress when someone might be starting to operate the instrument: near sunset and at each of the quarter night boundaries.","title":"The Daily Calibration Schedule"},{"location":"calibrations/#types-of-calibrations","text":"","title":"Types of Calibrations"},{"location":"calibrations/#wavelength-calibrations","text":"Wavelength calibrations are the most critical daily calibration. Absolute wavelength calibrations use the laser frequency comb (LFC) or one of the hollow cathode lamps (ThAr or UNe). The etalon is also used for wavelength calibration, but in a slightly different way. The etalon spectrum is not fixed to absolute wavelengths as the LFC and the Thorium and Uranium lamps are, but it has the advantage of being far more robust. The positions of the etalon lines can evolve slowly with time, but on short (<1 day) timescales they are stable. Thus the etalon calibration frames can be used to track the evolution of the instrument over daily timescales (anchored by the morning and afternoon wavelength cals). Thus it is valuable to have etalon observations taken periodically throughout the day and night.","title":"Wavelength Calibrations"},{"location":"calibrations/#broadband-flats","text":"KPF takes relatively standard spectral flats using a broadband lamp. Because of the extreme requirements for PRV measurements, the flats must be extraordinarily high signal to noise and be taken daily to track any changes.","title":"Broadband Flats"},{"location":"calibrations/#biases-and-darks","text":"KPF takes biases and darks like other instruments. We try to schedule these in to the lamp warmup time built in to other calibrations, so they end up being spread out throughout the day during other calibration OBs.","title":"Biases and Darks"},{"location":"calibrations/#other-calibrations","text":"We currently also take two other calibrations: a set of biases for the Exposure Meter every day and a set of CRED2 guide camera biases a couple times per week.","title":"Other Calibrations"},{"location":"calibrations/#overnight-etalon","text":"In addition to the calibrations taken during daytime, we have scheduled four long calibration sequences to happen overnight. The start times are chosen so that they should not be in progress when an observer might be starting use of the instrument (e.g. at a quarter night boundary). The scheduled cals will not begin during observations because the kpfStartOfNight script sets the kpfconfig.ALLOWSCHEDULEDCALS keyword to \u201cNo\u201d and the script to run the overnight calibrations respects that keyword. If for some reason, they are running when an observer needs to being observing, the cals can be stopped using the standard tools to halt a script in progress (e.g. the \u201cRequest Script Stop\u201d button in the OB GUI).","title":"Overnight Etalon"},{"location":"computers/","text":"KPF Computers kpf (aka vm-kpf ) is a virtual machine at the summit. It runs the VNC sessions which observers use to interact with the instrument and runs most of the GUIs in those VNCs. kpfserver is the instrument host on which most of the critical dispatchers and keyword services run. kpffiuserver performs a similar function to kpfserver for the FIU and Ca H&K spectrometer in the (physically-separated) AO room. kpfbuild is the build host where files are installed and built. When ready they are deployed using a script to each of the run hosts ( kpfserver , kpffiuserver , and kpf ). kpfetalon is a machine in the basement which handles telemetry from the Etalon thermal controllers and sensors. tc-su-kpfetalon is a small windows machine connected to the NKT SuperK light source for the etalon. It is used when we need to run the NKT software to start up the light source. Data Storage Most KPF data is stored on /sdata1701 on kpfserver which other computers a WMKO cross-mount as /s/sdata1701 . Subdirectories within /sdata1701 are for the assigned account, e.g. kpfeng or kpf1 . Then there are date-coded directories, which correspond to the date of the start of the night (i.e. 2024jun21 is the night of June 21 Hawaii time, but data taken during the second half will be written there even though it is technically June 22 at the moment the data is taken). The date directories change at 2pm HST. An example data directory is /s/sdata1701/kpfeng/2023jul11 . Network KPF is controlled by computers and devices that are behind the WMKO firewall. Most KPF devices (e.g., vacuum controllers) are on a private network behind kpfserver, which has separate network cards for the WMKO network and the private KPF network.","title":"Computers"},{"location":"computers/#kpf-computers","text":"kpf (aka vm-kpf ) is a virtual machine at the summit. It runs the VNC sessions which observers use to interact with the instrument and runs most of the GUIs in those VNCs. kpfserver is the instrument host on which most of the critical dispatchers and keyword services run. kpffiuserver performs a similar function to kpfserver for the FIU and Ca H&K spectrometer in the (physically-separated) AO room. kpfbuild is the build host where files are installed and built. When ready they are deployed using a script to each of the run hosts ( kpfserver , kpffiuserver , and kpf ). kpfetalon is a machine in the basement which handles telemetry from the Etalon thermal controllers and sensors. tc-su-kpfetalon is a small windows machine connected to the NKT SuperK light source for the etalon. It is used when we need to run the NKT software to start up the light source.","title":"KPF Computers"},{"location":"computers/#data-storage","text":"Most KPF data is stored on /sdata1701 on kpfserver which other computers a WMKO cross-mount as /s/sdata1701 . Subdirectories within /sdata1701 are for the assigned account, e.g. kpfeng or kpf1 . Then there are date-coded directories, which correspond to the date of the start of the night (i.e. 2024jun21 is the night of June 21 Hawaii time, but data taken during the second half will be written there even though it is technically June 22 at the moment the data is taken). The date directories change at 2pm HST. An example data directory is /s/sdata1701/kpfeng/2023jul11 .","title":"Data Storage"},{"location":"computers/#network","text":"KPF is controlled by computers and devices that are behind the WMKO firewall. Most KPF devices (e.g., vacuum controllers) are on a private network behind kpfserver, which has separate network cards for the WMKO network and the private KPF network.","title":"Network"},{"location":"dataflow/","text":"Data Flow An idealized vision for the KPF data flow. This is still a work in progress. Raw Data Because KPF contains many detectors, but they are all synchronized in time, the raw data is immediately combined in to a \"Level 0\" (L0) multi-extension FITS file by the kpfassemble dispatcher. Most users will want to use that L0 data for analysis or inspection. Each detector writes data to a separate output directory and kpfassemble will collect them from these to generate the L0 file. This is a relatively quick process, typically the L0 file is written a few seconds after the component raw data are available on disk. As mentioned on the detectors page, the Green and Red detectors have 32 bit ADCs and thus the pixel data do not fall on the usual 0-65535 range you may be used to. L0 Data The L0 data is a multi extension FITS file consisting of the following HDUs: HDU # HDU Name Notes 0 PRIMARY Header only, no image data 1 GREEN_AMP1 Green image data 2 GREEN_AMP2 Green image data 3 RED_AMP1 Red image data 4 RED_AMP2 Red image data 5 CA_HK Ca H&K image data 6 EXPMETER_SCI Table of processed exposure meter spectra 7 EXPMETER_SKY Table of processed exposure meter spectra 8 GUIDER_AVG The average guider image over the duration of the exposure 9 GUIDER_CUBE_ORIGINS Table of telemetry from the tip tilt system 10 TELEMETRY Table of instrument telemetry This can change depending on the composition of the science observation. For example, if the Ca H&K detector was not triggered, that extension would not be used. A guide to examining the L0 data can be found on this page in the documentation for the KPF DRP. Keck Observatory Archive (KOA) The L0 data are immediately sent to KOA for archiving. Observers can \"subscribe\" to the L0 data via KOA's Real Time Ingestion (RTI) interface. Data Reduction The KPF Data Reduction Pipeline was built and delivered by the KPF Instrument Team and is an important part of obtaining the desired performance from the instrument. While Keck plan's to eventually run the DRP locally and provide quick look products (QLP), L1, and L2 data to observers as part of the KOA RTI interface, the KPF DRP is still under active development by the KPF science team, so the Keck deployment of the DRP is on hold until there are less frequent changes for us to track. As a result, data for programs which have partnered with CPS are available through their instance of the DRP which is run on the CPS Team's hardware. Observers who are not part of CPS should contact their Keck SA to arrange for access to reduced data products.","title":"Data Flow"},{"location":"dataflow/#data-flow","text":"An idealized vision for the KPF data flow. This is still a work in progress.","title":"Data Flow"},{"location":"dataflow/#raw-data","text":"Because KPF contains many detectors, but they are all synchronized in time, the raw data is immediately combined in to a \"Level 0\" (L0) multi-extension FITS file by the kpfassemble dispatcher. Most users will want to use that L0 data for analysis or inspection. Each detector writes data to a separate output directory and kpfassemble will collect them from these to generate the L0 file. This is a relatively quick process, typically the L0 file is written a few seconds after the component raw data are available on disk. As mentioned on the detectors page, the Green and Red detectors have 32 bit ADCs and thus the pixel data do not fall on the usual 0-65535 range you may be used to.","title":"Raw Data"},{"location":"dataflow/#l0-data","text":"The L0 data is a multi extension FITS file consisting of the following HDUs: HDU # HDU Name Notes 0 PRIMARY Header only, no image data 1 GREEN_AMP1 Green image data 2 GREEN_AMP2 Green image data 3 RED_AMP1 Red image data 4 RED_AMP2 Red image data 5 CA_HK Ca H&K image data 6 EXPMETER_SCI Table of processed exposure meter spectra 7 EXPMETER_SKY Table of processed exposure meter spectra 8 GUIDER_AVG The average guider image over the duration of the exposure 9 GUIDER_CUBE_ORIGINS Table of telemetry from the tip tilt system 10 TELEMETRY Table of instrument telemetry This can change depending on the composition of the science observation. For example, if the Ca H&K detector was not triggered, that extension would not be used. A guide to examining the L0 data can be found on this page in the documentation for the KPF DRP.","title":"L0 Data"},{"location":"dataflow/#keck-observatory-archive-koa","text":"The L0 data are immediately sent to KOA for archiving. Observers can \"subscribe\" to the L0 data via KOA's Real Time Ingestion (RTI) interface.","title":"Keck Observatory Archive (KOA)"},{"location":"dataflow/#data-reduction","text":"The KPF Data Reduction Pipeline was built and delivered by the KPF Instrument Team and is an important part of obtaining the desired performance from the instrument. While Keck plan's to eventually run the DRP locally and provide quick look products (QLP), L1, and L2 data to observers as part of the KOA RTI interface, the KPF DRP is still under active development by the KPF science team, so the Keck deployment of the DRP is on hold until there are less frequent changes for us to track. As a result, data for programs which have partnered with CPS are available through their instance of the DRP which is run on the CPS Team's hardware. Observers who are not part of CPS should contact their Keck SA to arrange for access to reduced data products.","title":"Data Reduction"},{"location":"detectors/","text":"Overview and Exposure Timing KPF utilizes 5 detectors during normal science operations. Two science detectors (green and red) sit on the main spectrograph bench in the facility basement and record the science spectrum which is used to calculate radial velocities. The Ca H&K Spectrograph is an independant optical system fed by a short fiber which runs from the FIU to a nearby echelle spectrograph which contains the third science detector. The exposure meter is another independent spectrograph which sits in the basement and contains the forth science detector. The fifth detector used during science operations is the CRED2 in the FIU and obtains fast frame rate images used to run the tip tilt system. Because precision radial velocity measurements require exquisite timing, the red and green detectors must have their exposures synced up. To do this, KPF uses a timed shutter on their common light path (before the dichroic splits the light). This is the \"Scrambler Timed Shutter\". As a result, the red and green cameras are not triggered independently. Instead the KPF software takes a single set of exposure parameters and triggers each camera to begin an exposure, then opens and closes timed shutters to ensure simultaneity where needed. In addition, the Scrambler Timed Shutter, also gates the light going to the exposure meter to ensure that its sensitivity to light is simultaneous to the red and green detectors. The Ca H&K spectrograph has its own, separate timed shutter as it is on a completely independent light path to the other detectors. Science Detector Specifications Parameter Green CCD Red CCD Ca H&K CCD Readout Time 47 s 47 s 1 s Read Noise AMP1: 4.0 e- AMP2: 4.9 e- AMP1: 4.1 e- AMP2: 4.2 e- Format 4080x4080 4080x4080 windowed to 1024x255 Gain ~5 e-/ADU ~5 e-/ADU 5.26 e-/ADU Data Format 32 bit 32 bit 16 bit Saturation ~2.1 x 10^9 ADU (~150 ke-) ~2.1 x 10^9 ADU (~150 ke-) 65,536 ADU (344 ke-) Note that the Green and Red science detectors have 32 bit readouts instead of the more common 16 bit (which the Ca H&K detector uses). This means that the values of the raw image pixels are not in the usual 0-65535 range for CCDs, but are instead much larger. To convert to the more usual range we are used to, divide by 2^16 (65536) to get ADU values in that range.","title":"Detectors"},{"location":"detectors/#overview-and-exposure-timing","text":"KPF utilizes 5 detectors during normal science operations. Two science detectors (green and red) sit on the main spectrograph bench in the facility basement and record the science spectrum which is used to calculate radial velocities. The Ca H&K Spectrograph is an independant optical system fed by a short fiber which runs from the FIU to a nearby echelle spectrograph which contains the third science detector. The exposure meter is another independent spectrograph which sits in the basement and contains the forth science detector. The fifth detector used during science operations is the CRED2 in the FIU and obtains fast frame rate images used to run the tip tilt system. Because precision radial velocity measurements require exquisite timing, the red and green detectors must have their exposures synced up. To do this, KPF uses a timed shutter on their common light path (before the dichroic splits the light). This is the \"Scrambler Timed Shutter\". As a result, the red and green cameras are not triggered independently. Instead the KPF software takes a single set of exposure parameters and triggers each camera to begin an exposure, then opens and closes timed shutters to ensure simultaneity where needed. In addition, the Scrambler Timed Shutter, also gates the light going to the exposure meter to ensure that its sensitivity to light is simultaneous to the red and green detectors. The Ca H&K spectrograph has its own, separate timed shutter as it is on a completely independent light path to the other detectors.","title":"Overview and Exposure Timing"},{"location":"detectors/#science-detector-specifications","text":"Parameter Green CCD Red CCD Ca H&K CCD Readout Time 47 s 47 s 1 s Read Noise AMP1: 4.0 e- AMP2: 4.9 e- AMP1: 4.1 e- AMP2: 4.2 e- Format 4080x4080 4080x4080 windowed to 1024x255 Gain ~5 e-/ADU ~5 e-/ADU 5.26 e-/ADU Data Format 32 bit 32 bit 16 bit Saturation ~2.1 x 10^9 ADU (~150 ke-) ~2.1 x 10^9 ADU (~150 ke-) 65,536 ADU (344 ke-) Note that the Green and Red science detectors have 32 bit readouts instead of the more common 16 bit (which the Ca H&K detector uses). This means that the values of the raw image pixels are not in the usual 0-65535 range for CCDs, but are instead much larger. To convert to the more usual range we are used to, divide by 2^16 (65536) to get ADU values in that range.","title":"Science Detector Specifications"},{"location":"expmetertermination/","text":"Exposure Meter Termination KPF contains an exposure meter which can measure the flux weighted midpoint of an exposure. This can also be used to terminate a science exposure once a desired signal level is reached. To do this the system will track the flux measured in the exposure meter spectra binned in to 4 passbands, each about 100nm wide, centered on 498.125nm, 604.375nm, 710.625nm, and 816.875nm respectively. To use exposure meter termination, the observer sets ExpMeterMode: control in the OB and then chooses one wavelength band to trigger on (using the ExpMeterBin OB value) and then chooses the target flux (in e-/nm via the ExpMeterThreshold OB value) in the resulting science spectrum that is desired. The system will convert the target value for the science spectrum in to a total ADU count for the exposure meter in that particular bandpass and when that threshold is surpassed, the exposure will stop. Regardless of whether that exposure meter threshold is passed, the exposure will stop when the nominal exposure time is reached. Thus when using exposure meter termination, the ExpTime parameter should be thought of as the maximum allowed exposure time. For example, an OB with the following values: ExpTime: 300 ExpMeterMode: control ExpMeterBin: 604.375 ExpMeterThreshold: 50000 will terminate when the exposure meter flux reaches a value which should result in approximately 50,000 e-/nm signal in the resulting science spectrum at about 604nm or when the total exposure time reaches 300 seconds, whichever comes first.","title":"Exposure Meter Termination"},{"location":"expmetertermination/#exposure-meter-termination","text":"KPF contains an exposure meter which can measure the flux weighted midpoint of an exposure. This can also be used to terminate a science exposure once a desired signal level is reached. To do this the system will track the flux measured in the exposure meter spectra binned in to 4 passbands, each about 100nm wide, centered on 498.125nm, 604.375nm, 710.625nm, and 816.875nm respectively. To use exposure meter termination, the observer sets ExpMeterMode: control in the OB and then chooses one wavelength band to trigger on (using the ExpMeterBin OB value) and then chooses the target flux (in e-/nm via the ExpMeterThreshold OB value) in the resulting science spectrum that is desired. The system will convert the target value for the science spectrum in to a total ADU count for the exposure meter in that particular bandpass and when that threshold is surpassed, the exposure will stop. Regardless of whether that exposure meter threshold is passed, the exposure will stop when the nominal exposure time is reached. Thus when using exposure meter termination, the ExpTime parameter should be thought of as the maximum allowed exposure time. For example, an OB with the following values: ExpTime: 300 ExpMeterMode: control ExpMeterBin: 604.375 ExpMeterThreshold: 50000 will terminate when the exposure meter flux reaches a value which should result in approximately 50,000 e-/nm signal in the resulting science spectrum at about 604nm or when the total exposure time reaches 300 seconds, whichever comes first.","title":"Exposure Meter Termination"},{"location":"exposuremeter/","text":"Exposure Meter An accurate measurement of the time of the flux-weighted midpoint of each exposure is essential to correct for the barycentric velocity of the Earth. During an exposure, a small fraction of the light within the spectrometer is diverted to a separate, low-resolution spectrometer that records the flux time series for all wavelengths across the main spectrometer bandpass. This system accurately tracks the photon arrival times in the parent spectrometer, allowing for precise determination of flux-weighted exposure mid-points as a function of wavelength. The optical design of the exposure meter is a prism-based spectrometer with a resolving power of approximately 100. The exposure meter accepts light from two fibers; one collecting light from the otherwise unused outboard slices of the science fiber at the spectrometer reformatter entrance, and a sky fiber from the fiber injection unit on the telescope. The optical design is shown in the following figure. Optical design of the KPF Exposure Meter","title":"Exposure Meter"},{"location":"exposuremeter/#exposure-meter","text":"An accurate measurement of the time of the flux-weighted midpoint of each exposure is essential to correct for the barycentric velocity of the Earth. During an exposure, a small fraction of the light within the spectrometer is diverted to a separate, low-resolution spectrometer that records the flux time series for all wavelengths across the main spectrometer bandpass. This system accurately tracks the photon arrival times in the parent spectrometer, allowing for precise determination of flux-weighted exposure mid-points as a function of wavelength. The optical design of the exposure meter is a prism-based spectrometer with a resolving power of approximately 100. The exposure meter accepts light from two fibers; one collecting light from the otherwise unused outboard slices of the science fiber at the spectrometer reformatter entrance, and a sky fiber from the fiber injection unit on the telescope. The optical design is shown in the following figure. Optical design of the KPF Exposure Meter","title":"Exposure Meter"},{"location":"fastreadmode/","text":"Fast Read Mode The Green and Red science detectors can operate in a fast readout mode. This reduces the readout time to 16 seconds (and significantly increases the read noise), however changing the readout modes induces a temperature change at the detectors which can impact PRV measurements. As a result, fast read mode observations should be limited to those instances where it is critical to the science (e.g. seismology or other high cadence observations of a single target) and which are scheduled such that the mode change will not have overly negative impact on other science that night. Fast read mode is not appropriate for long term cadenced RV measurements as the two read modes have different systematic offsets and so RV measurements of the same target taken in different modes can not be easily combined. If you are interested in utilizing fast read mode, please contact kpf_info well ahead of your run. Fast read mode may not be available in all cases due to the impact on other scheduled observations. If it is available for your run, the Keck SA will schedule when the mode is changed and when fast read mode calibrations (primarily biases) can be taken. Our goal will be to minimize the number of changes of the read mode. After a mode change in either direction, the system needs time to stabilize before precision RVs are possible. We have estimated this stabilization time to be about 20 minutes. Because KPF is expected to operate in normal read mode and be available for precision RVs and fast read mode is the aberration, when this 20 minute wait time is needed during the night (i.e. the mode change does not happen well before or after the observing window), then all instances of this 20 minute window should be considered part of the fast read mode program. As a result, if the read mode is normal for observations at the beginning the night, then is switched to fast, then back to normal for observations at the end of the night. Both 20 minute wait times (40 minutes total) are overhead which are considered part of the fast read mode program. Details The KPF main spectrometer CCDs can be operated in two read modes: normal and fast. The main difference is the time to read the CCDs, which is 47 sec in normal-read mode and 16 sec in fast-read mode. In general, KPF observations should be taken in normal-read mode unless there is a highly compelling reason to operate in fast-read mode. The fast-read mode is only offered for KPF observations where the speed will aid in resolving fast astrophysical phenomena (e.g., seismology) or for cases where short exposure times are required to avoid saturation and the efficiency is significantly improved by also reading the CCDs quickly (e.g., observing a very bright star during a planetary transit). This applies to sequences of exposures ranging from 1 hour to 1 night in duration. The fast-read mode should not be used to improve the efficiency of individual exposure or short sequences of exposures, which comprise the vast majority of KPF observations. The motivation for this strategy is that changing between the two modes imparts a ~10 mK temperature transient to the CCDs, which shift and stretch at the nanometer level in response. These perturbations violate the operating requirements of maintaining 1 mK rms temperature stability of the CCDs and lead to systematic errors in Doppler measurements on short timescales (< 20-30 min). On longer timescales, the CCDs appear to relax back to their original state, but this has not been measured at the sub-30 cm/s level. Out of conservatism, KPF is toggled between read modes as infrequently as possible. Automated daily calibration sequences are taken in the normal-read mode and are used in the KPF Data Reduction Pipeline (DRP) to process spectra taken with both read modes. Radial velocities measured from KPF spectra in the two modes are offset; users cannot combine RVs from the two modes in a time series. On the other hand, RVs measured from spectra taken in the fast-read mode during a single night (which are processed with a common set of calibrations) have high Doppler stability over that night-long timescale; this is the main use case for the fast-read mode. Some additional tradeoffs to consider are the increased read noise and the charge transfer inefficiency (CTI) in fast-read mode. As listed in the table below, the read noise (measured in rms noise per CCD pixel) is 1.5-2X higher in fast-read mode. This limits the utility of this mode for faint sources, which have higher Poisson noise per CCD pixel in the source spectrum. In fast-read mode, the CCDs are read out using four amplifiers at a higher clock speed (instead of two amplifiers at a slower speed). This strategy brings one amplifier on the Green CCD into play that has ~100x higher CTI than the others. CTI smears the spectrum along the direction of the CCD rows (leaving a trail of charge along pixels as they are clocked). As a result, stellar lines in the affected quadrant are smeared in the dispersion direction. The intensity of the effect depends on the number of electrons in each pixel (i.e., the SNR of the spectrum), making this effect very difficult to calibrate for precise RV measurements. When computing RVs for fast-read mode spectra, the KPF DRP ignores portions of the spectrum in the affected quadrant. This increases the RV uncertainties in the fast-read mode and adds an additional RV zero-point offset between measurements in the two modes. Fast spectroscopy to measure changes in line intensity (not line shape or center) can still be accomplished using spectra from the affected quadrant. Parameter Normal Read Mode Fast Read Mode Readout Time 47 s 16 s Read Noise Green: 4.0, 4.9 e- Red: 4.1, 4.2 e- Green: 8.2, 9.7, 8.6, 6.9 e- Red: 6.0, 5.8, 8.2, 6.6 e- Charge Transfer One green amp has ~100x higher CTI Use Cases Most KPF observations, including cadence RPV measurements and general spectroscopy Sequences of short exposures whose duration is 1 hour to 1 night.","title":"Fast Read Mode"},{"location":"fastreadmode/#fast-read-mode","text":"The Green and Red science detectors can operate in a fast readout mode. This reduces the readout time to 16 seconds (and significantly increases the read noise), however changing the readout modes induces a temperature change at the detectors which can impact PRV measurements. As a result, fast read mode observations should be limited to those instances where it is critical to the science (e.g. seismology or other high cadence observations of a single target) and which are scheduled such that the mode change will not have overly negative impact on other science that night. Fast read mode is not appropriate for long term cadenced RV measurements as the two read modes have different systematic offsets and so RV measurements of the same target taken in different modes can not be easily combined. If you are interested in utilizing fast read mode, please contact kpf_info well ahead of your run. Fast read mode may not be available in all cases due to the impact on other scheduled observations. If it is available for your run, the Keck SA will schedule when the mode is changed and when fast read mode calibrations (primarily biases) can be taken. Our goal will be to minimize the number of changes of the read mode. After a mode change in either direction, the system needs time to stabilize before precision RVs are possible. We have estimated this stabilization time to be about 20 minutes. Because KPF is expected to operate in normal read mode and be available for precision RVs and fast read mode is the aberration, when this 20 minute wait time is needed during the night (i.e. the mode change does not happen well before or after the observing window), then all instances of this 20 minute window should be considered part of the fast read mode program. As a result, if the read mode is normal for observations at the beginning the night, then is switched to fast, then back to normal for observations at the end of the night. Both 20 minute wait times (40 minutes total) are overhead which are considered part of the fast read mode program.","title":"Fast Read Mode"},{"location":"fastreadmode/#details","text":"The KPF main spectrometer CCDs can be operated in two read modes: normal and fast. The main difference is the time to read the CCDs, which is 47 sec in normal-read mode and 16 sec in fast-read mode. In general, KPF observations should be taken in normal-read mode unless there is a highly compelling reason to operate in fast-read mode. The fast-read mode is only offered for KPF observations where the speed will aid in resolving fast astrophysical phenomena (e.g., seismology) or for cases where short exposure times are required to avoid saturation and the efficiency is significantly improved by also reading the CCDs quickly (e.g., observing a very bright star during a planetary transit). This applies to sequences of exposures ranging from 1 hour to 1 night in duration. The fast-read mode should not be used to improve the efficiency of individual exposure or short sequences of exposures, which comprise the vast majority of KPF observations. The motivation for this strategy is that changing between the two modes imparts a ~10 mK temperature transient to the CCDs, which shift and stretch at the nanometer level in response. These perturbations violate the operating requirements of maintaining 1 mK rms temperature stability of the CCDs and lead to systematic errors in Doppler measurements on short timescales (< 20-30 min). On longer timescales, the CCDs appear to relax back to their original state, but this has not been measured at the sub-30 cm/s level. Out of conservatism, KPF is toggled between read modes as infrequently as possible. Automated daily calibration sequences are taken in the normal-read mode and are used in the KPF Data Reduction Pipeline (DRP) to process spectra taken with both read modes. Radial velocities measured from KPF spectra in the two modes are offset; users cannot combine RVs from the two modes in a time series. On the other hand, RVs measured from spectra taken in the fast-read mode during a single night (which are processed with a common set of calibrations) have high Doppler stability over that night-long timescale; this is the main use case for the fast-read mode. Some additional tradeoffs to consider are the increased read noise and the charge transfer inefficiency (CTI) in fast-read mode. As listed in the table below, the read noise (measured in rms noise per CCD pixel) is 1.5-2X higher in fast-read mode. This limits the utility of this mode for faint sources, which have higher Poisson noise per CCD pixel in the source spectrum. In fast-read mode, the CCDs are read out using four amplifiers at a higher clock speed (instead of two amplifiers at a slower speed). This strategy brings one amplifier on the Green CCD into play that has ~100x higher CTI than the others. CTI smears the spectrum along the direction of the CCD rows (leaving a trail of charge along pixels as they are clocked). As a result, stellar lines in the affected quadrant are smeared in the dispersion direction. The intensity of the effect depends on the number of electrons in each pixel (i.e., the SNR of the spectrum), making this effect very difficult to calibrate for precise RV measurements. When computing RVs for fast-read mode spectra, the KPF DRP ignores portions of the spectrum in the affected quadrant. This increases the RV uncertainties in the fast-read mode and adds an additional RV zero-point offset between measurements in the two modes. Fast spectroscopy to measure changes in line intensity (not line shape or center) can still be accomplished using spectra from the affected quadrant. Parameter Normal Read Mode Fast Read Mode Readout Time 47 s 16 s Read Noise Green: 4.0, 4.9 e- Red: 4.1, 4.2 e- Green: 8.2, 9.7, 8.6, 6.9 e- Red: 6.0, 5.8, 8.2, 6.6 e- Charge Transfer One green amp has ~100x higher CTI Use Cases Most KPF observations, including cadence RPV measurements and general spectroscopy Sequences of short exposures whose duration is 1 hour to 1 night.","title":"Details"},{"location":"fiu/","text":"Fiber Injection Unit (FIU) The Fiber Injection Unit (FIU) sits on the Keck I AO bench ahead of AO correction. The unit's primary role is to feed telescope light to the science, sky, and Ca H&K fibers. The unit utilizes a pair of dichroics to send light to the relevant subsystems: Wavelength Range Subsystem Notes 382-402 nm Ca H&K Spectrograph Includes two fibers (science and sky) 445-870 nm Science Spectrograph Includes two fibers (science and sky) 950-1200 nm Guide Camera Used for acquisition and fast tip tilt correction The FIU can also be configured in a mode which takes light from the calibration bench in the basement and injects it in to the science and sky fibers. Atmospheric Dispersion Correctors In addition, the FIU contains atmospheric dispersion correction (ADC) systems for both the science and Ca H&K wavelengths. Science ADC For the science arm, a pair of prisms are rotated to provide dispersion correction based on the telescope position. The ADCs are designed to keep all the science wavelengths within 50 mas. The ADC corrects atmospheric dispersion at that full 50 mas specification down to an elevation of 30 degrees. The prisms reach their maximum correction power at an elevation of 25 degrees, beyond that, their correction power is fixed and no longer increases as the elevation decreases. Ca H&K ADC For the Ca H&K arm, the fiber is on a two axis stage and is translated in such as way as to place the fiber under the correct wavelengths of light. The total wavelength range in this arm is small enough that only the differential position between this arm and the science and guide arms is corrected, there is no correction of the dispersion over the narrow wavelength range of the Ca H&K arm. FIU Layout The FIU layout when in science mode. Light from the telescope is directed to the FIU off of a tip tilt mirror located on the PCU stage. The FIU layout when in calibration mode. The calibration fibers are illuminated and a fold mirror is moved in to place to direct their light on to the science fiber. Fiber Viewing Cameras Both the science arm and the Ca H&K arm have fiber viewing cameras (FVCs) for imaging the fiber tip. These are only useful in an engineering context as it takes a very bright (roughly 1st magnitude) star to be visible because the FVCs are looking through the dichroics (and the ADC prisms in the science arm). This drastically reduced the amount of light to the FVCs and makes the images hard to interpret due to reflections and ghost images.","title":"FIU"},{"location":"fiu/#fiber-injection-unit-fiu","text":"The Fiber Injection Unit (FIU) sits on the Keck I AO bench ahead of AO correction. The unit's primary role is to feed telescope light to the science, sky, and Ca H&K fibers. The unit utilizes a pair of dichroics to send light to the relevant subsystems: Wavelength Range Subsystem Notes 382-402 nm Ca H&K Spectrograph Includes two fibers (science and sky) 445-870 nm Science Spectrograph Includes two fibers (science and sky) 950-1200 nm Guide Camera Used for acquisition and fast tip tilt correction The FIU can also be configured in a mode which takes light from the calibration bench in the basement and injects it in to the science and sky fibers.","title":"Fiber Injection Unit (FIU)"},{"location":"fiu/#atmospheric-dispersion-correctors","text":"In addition, the FIU contains atmospheric dispersion correction (ADC) systems for both the science and Ca H&K wavelengths.","title":"Atmospheric Dispersion Correctors"},{"location":"fiu/#science-adc","text":"For the science arm, a pair of prisms are rotated to provide dispersion correction based on the telescope position. The ADCs are designed to keep all the science wavelengths within 50 mas. The ADC corrects atmospheric dispersion at that full 50 mas specification down to an elevation of 30 degrees. The prisms reach their maximum correction power at an elevation of 25 degrees, beyond that, their correction power is fixed and no longer increases as the elevation decreases.","title":"Science ADC"},{"location":"fiu/#ca-hk-adc","text":"For the Ca H&K arm, the fiber is on a two axis stage and is translated in such as way as to place the fiber under the correct wavelengths of light. The total wavelength range in this arm is small enough that only the differential position between this arm and the science and guide arms is corrected, there is no correction of the dispersion over the narrow wavelength range of the Ca H&K arm.","title":"Ca H&K ADC"},{"location":"fiu/#fiu-layout","text":"The FIU layout when in science mode. Light from the telescope is directed to the FIU off of a tip tilt mirror located on the PCU stage. The FIU layout when in calibration mode. The calibration fibers are illuminated and a fold mirror is moved in to place to direct their light on to the science fiber.","title":"FIU Layout"},{"location":"fiu/#fiber-viewing-cameras","text":"Both the science arm and the Ca H&K arm have fiber viewing cameras (FVCs) for imaging the fiber tip. These are only useful in an engineering context as it takes a very bright (roughly 1st magnitude) star to be visible because the FVCs are looking through the dichroics (and the ADC prisms in the science arm). This drastically reduced the amount of light to the FVCs and makes the images hard to interpret due to reflections and ghost images.","title":"Fiber Viewing Cameras"},{"location":"guider/","text":"Guider The KPF guide camera views the science field, but behind a long pass dichroic which sends light blueward of about 950nm to the science and Ca H&K fibers. As a result, the guide camera was chosen to be a \"short wave IR\" camera utilizing an InGaS detector. Camera Model First Light CRED2 Pixel Scale 0.056 arcsec/pix Field of View 35 x 28 arcseconds Frame Rate up to 400 Hz (100 Hz recommended) Passband 950-1200 nm (0.95-1.2 microns) Gain Settings high, medium, low Note that while the camera can operate at 400 Hz, the practical limit for operations is around 100-150 Hz due to tip tilt system limitations. Rather than using traditional telescope guiding, the guide camera takes images at high frame rates and sends corrections to a fast tip tilt mirror situated just outside the FIU. We recommend running the system at 100 Hz for optimum performance. The system will offload corrections from the tip tilt mirror to the telescope drive system periodically as needed to keep the tip tilt mirror within its optimum range of travel. The OAs use a separate GUI for controlling the KPF tip tilt system (not the usual Magiq interface used on other instruments). The OAs can run Magiq in \"centroid only\" mode which will provide FWHM and flux feedback to the observer in the normal Magiq display.","title":"Guider"},{"location":"guider/#guider","text":"The KPF guide camera views the science field, but behind a long pass dichroic which sends light blueward of about 950nm to the science and Ca H&K fibers. As a result, the guide camera was chosen to be a \"short wave IR\" camera utilizing an InGaS detector. Camera Model First Light CRED2 Pixel Scale 0.056 arcsec/pix Field of View 35 x 28 arcseconds Frame Rate up to 400 Hz (100 Hz recommended) Passband 950-1200 nm (0.95-1.2 microns) Gain Settings high, medium, low Note that while the camera can operate at 400 Hz, the practical limit for operations is around 100-150 Hz due to tip tilt system limitations. Rather than using traditional telescope guiding, the guide camera takes images at high frame rates and sends corrections to a fast tip tilt mirror situated just outside the FIU. We recommend running the system at 100 Hz for optimum performance. The system will offload corrections from the tip tilt mirror to the telescope drive system periodically as needed to keep the tip tilt mirror within its optimum range of travel. The OAs use a separate GUI for controlling the KPF tip tilt system (not the usual Magiq interface used on other instruments). The OAs can run Magiq in \"centroid only\" mode which will provide FWHM and flux feedback to the observer in the normal Magiq display.","title":"Guider"},{"location":"kpfdrp/","text":"Data Reduction Pipeline WMKO automatically delivers KPF L0 data products to the Keck Observatory Archive (KOA) for distribution to observers. We plan to distribute L1 and L2 data products as well, but the KPF DRP is still under active development by the KPF science team, so the Keck deployment of the DRP is on hold until there are less frequent changes for us to track. Observers not affiliated with the KPF build team or with the California Planet Search (CPS) should contact their Staff Astronomer about access to reduced data products. Advanced users who would like to run the DRP locally can find the KPF DRP on GitHub and the documentation can be found on ReadTheDocs . Level Definitions Level Description L0 Raw spectra packaged with other instrument data (see Data Format for details) L1 1-d, wavelength calibrated spectra L2 RVs, multiple activity indicators","title":"Data Reduction"},{"location":"kpfdrp/#data-reduction-pipeline","text":"WMKO automatically delivers KPF L0 data products to the Keck Observatory Archive (KOA) for distribution to observers. We plan to distribute L1 and L2 data products as well, but the KPF DRP is still under active development by the KPF science team, so the Keck deployment of the DRP is on hold until there are less frequent changes for us to track. Observers not affiliated with the KPF build team or with the California Planet Search (CPS) should contact their Staff Astronomer about access to reduced data products. Advanced users who would like to run the DRP locally can find the KPF DRP on GitHub and the documentation can be found on ReadTheDocs .","title":"Data Reduction Pipeline"},{"location":"kpfdrp/#level-definitions","text":"Level Description L0 Raw spectra packaged with other instrument data (see Data Format for details) L1 1-d, wavelength calibrated spectra L2 RVs, multiple activity indicators","title":"Level Definitions"},{"location":"nighttimecalibrations/","text":"Nighttime Calibrations To monitor the instrumental drift, KPF needs calibrations taken throughout the night. There are two different calibrations that can be taken and each has advantages and disadvantages. As we fully characterize the instrument and as the DRP evolves, our recommendations for how best to run nighttime calibrations may change, so check back here for updates. Recommended Strategy The current recommendation is to take a slew cal roughly every hour or so. There is a \"Time Since Cal\" readout in the upper right of the OB GUI. When the time since the last calibration exceeds 1 hour, the readout will turn orange. At 2 hours, it will turn red. This is only a recommendation, so the decision of when to take a slew cal is up to the observer. See also the Observing Procedures page. What is a Slew Cal? Slew cals are a particular calibration (a single Etalon calibration exposure) which is intended to be taken during a long telescope slew. The best way to execute this is to click the \"Execute OB with Slew Cal\" button after loading the next desired OB and asking the OA to begin slewing to the target. You should let the OA know you are running a slew cal as this will close the FIU hatch and direct Etalon light through the FIU which means that they will no longer see the sky on the guider during the calibration (which takes about 2 minutes). Directing the calibration light through the FIU means that we will be illuminating the science, sky, and simulcal fibers (all 5 traces) with calibration light. Because the slew cal happens during the slew to a target, it is optimally performed with a science OB so that the guider can be configured for the science target. This is another case where executing a science OB before the slew has completed is the most efficient observing strategy. What are Simultaneous Calibrations (SimulCals)? Simultaneous Calibration (simulcal) is when the calibration trace (one of the 5 traces on the main science detectors) is illuminated with calibration light (usually the etalon). This can be done during science observations, but there are a number of caveats and potential pitfalls. The main concern when using simulcals is to get the appropriate calibration flux. Because the science exposure time changes depending on the target, the brightness of the light injected in to the simulcal fiber must be modulated to find an appropriate flux. This is accomplished with two filter wheels in the calibration bench which have neutral density (ND) filters. Too little simulcal flux is problematic because it makes the calibration less useful, but too much simulcal flux is worse. Even tiny amounts of scattered light or the far wings of an overly bright simulcal PSF can impact the science traces and bias the RV measurements. Because of this, we have built an automatic system for choosing the ND filters appropriate for the observation. This is a complex system because it must account for the color of the star as well as the brightness.","title":"Nighttime Calibrations"},{"location":"nighttimecalibrations/#nighttime-calibrations","text":"To monitor the instrumental drift, KPF needs calibrations taken throughout the night. There are two different calibrations that can be taken and each has advantages and disadvantages. As we fully characterize the instrument and as the DRP evolves, our recommendations for how best to run nighttime calibrations may change, so check back here for updates.","title":"Nighttime Calibrations"},{"location":"nighttimecalibrations/#recommended-strategy","text":"The current recommendation is to take a slew cal roughly every hour or so. There is a \"Time Since Cal\" readout in the upper right of the OB GUI. When the time since the last calibration exceeds 1 hour, the readout will turn orange. At 2 hours, it will turn red. This is only a recommendation, so the decision of when to take a slew cal is up to the observer. See also the Observing Procedures page.","title":"Recommended Strategy"},{"location":"nighttimecalibrations/#what-is-a-slew-cal","text":"Slew cals are a particular calibration (a single Etalon calibration exposure) which is intended to be taken during a long telescope slew. The best way to execute this is to click the \"Execute OB with Slew Cal\" button after loading the next desired OB and asking the OA to begin slewing to the target. You should let the OA know you are running a slew cal as this will close the FIU hatch and direct Etalon light through the FIU which means that they will no longer see the sky on the guider during the calibration (which takes about 2 minutes). Directing the calibration light through the FIU means that we will be illuminating the science, sky, and simulcal fibers (all 5 traces) with calibration light. Because the slew cal happens during the slew to a target, it is optimally performed with a science OB so that the guider can be configured for the science target. This is another case where executing a science OB before the slew has completed is the most efficient observing strategy.","title":"What is a Slew Cal?"},{"location":"nighttimecalibrations/#what-are-simultaneous-calibrations-simulcals","text":"Simultaneous Calibration (simulcal) is when the calibration trace (one of the 5 traces on the main science detectors) is illuminated with calibration light (usually the etalon). This can be done during science observations, but there are a number of caveats and potential pitfalls. The main concern when using simulcals is to get the appropriate calibration flux. Because the science exposure time changes depending on the target, the brightness of the light injected in to the simulcal fiber must be modulated to find an appropriate flux. This is accomplished with two filter wheels in the calibration bench which have neutral density (ND) filters. Too little simulcal flux is problematic because it makes the calibration less useful, but too much simulcal flux is worse. Even tiny amounts of scattered light or the far wings of an overly bright simulcal PSF can impact the science traces and bias the RV measurements. Because of this, we have built an automatic system for choosing the ND filters appropriate for the observation. This is a complex system because it must account for the color of the star as well as the brightness.","title":"What are Simultaneous Calibrations (SimulCals)?"},{"location":"observingprocedures/","text":"Quick Reference Beginning of the Night Performing Observations Switching Programs on a Split Night Bad Weather Beginning of the Night Wait for Dome to Open The Observing Assistant (OA) is not permitted to open the dome until after sunset. Please be patient while the shutter opens and the OA checks the initial telescope pointing. Run Start of Night KPF needs to be configured properly at the start of the night. There is a procedure which should be run only after the Observing Assistant (OA) has selected KPF as the instrument and after automated afternoon calibrations are complete. The selected instrument (\"INST\") can be seen in the lower left corner of the FACSUM window . It is important that this not be run while other instruments are observing. To configure KPF for observing, run KPF Control Menu --> Run Start of Night Script from the background menu (or kpfStartOfNight from the command line on any KPF machine). This will: Disable automated calibrations Configure the FIU to the observing mode Open the science and sky source select shutters Configure the AO Bench. Including positioning the PCU stage and opening the AO hatch. Configure DCS for KPF by setting dcs.ROTDEST=0 and dcs.ROTMODE=stationary Configure the tip tilt loop gain to its default setting Set data output directory Set observers from telescope schedule Slew to the Vicinity of Your First Target When ready to move the telescope, the OA will ask you for your first target and load the coordinates from your starlist file. They will select a bright star near your target and will attempt to acquire that in the guider, then will double-check the accuracy of pointing by acquiring one or two additional stars from the SAO or GSC catalogs. To monitor the guider images, run Telescope GUIs --> MAGIQ Guider UI from the background menu. Focus the Telescope The OA will run the telescope focus procedure (typically Autofoc) near your science field. On some nights, they will opt for the Mira focus procedure which takes slightly longer but is needed to calibrate the secondary mirror tilt. Performing Observations Highlight Your Target in Magiq In the Magiq star list (at the bottom of the Magiq User GUI), right click your target and select the option to highlight it for the OA (you can get the same result by middle clicking the target). This highlighting will show up on the OA's GUI making it easier for them to find the target you want to go to. Let the OA know to slew to the target when your current exposure is done. Execute Your OB Observers can load previously saved OBs or create them on the fly for KPF observing. To load and execute a saved OB: Click Load OB from File Select the OB from the file list Click Execute This OB (or Execute OB with Slew Cal) The GUI will first prompt the observers to confirm the OB execution. Once confirmed, an xterm will launch and prompt the observers with addtional information if and when needed, so watch the contents of this xterm. Executing the OB will not start an exposure immediately. The system will first configure the instrument and will then prompt the observer to confirm once the OA has acquired the target. While configuring the instrument, the OB will provide information on how to set the gain and frames per second on the guider. Because of this, it is important to execute the OB during the slew and before the OA acquires the target, so they have the right exposure parameters to see the target on the guider. The log lines which show up in the xterm with the running OB contain useful information. In general, lines with INFO are attempting to explain what the instrument is doing. Lines with WARNING are indicating that a minor problem has occurred, but the system is handling it -- these lines are purely informational, no action is needed on the part of the observer in response. Lines with ERROR indicate a serious problems which may require user intervention. Slew Cals KPF has the option of taking a \"slew cal\" immediately prior to a science observation. This is a way to make use of the time spent slewing from one target to another. If an OB is executed with a slew cal (using the \"Execute OB with Slew Cal\" button in the OB GUI), then the FIU will transition to calibration mode (the FIU hatch will close and calibration light will be directed to the science and sky fibers), and a calibration exposure will be taken. This will obscure the sky during calibration, so the OA will not be able to see the target until the slew cal is done. This process takes around 2 minutes and so fits nicely in to long slews. An alternative to a slew cal is a simultaneous calibration (simulcal). To use this enable the TakeSimulCal option in the OB or on the OB GUI and either manually set the ND filters to apply to the calibration light or enable the AutoNDFilters option. See the nighttime calibrations page for more info on both the slew cal and simulcal options. Stopping Scripts or Exposures Important : If you wish to halt an OB during execution, do NOT hit Control-c in the terminal. Use the \"Request Script STOP\" button instead. The KPF scripts have checkpoints in them which are places where the script can cleanly exit and perform important cleanup operations. The \"STOP Exposure and Script\" button does the same thing, but it will also terminate an exposure in progress. Known Issues There is a known failure mode for KPF called a \"start state error\". What happens is some sort of communication failure between the kpfexpose control software, the galil hardware which handles the timing and signaling of the detectors and shutters, and the Archon detector controllers. The result is that one of the green or red detectors does not begin the exposure properly and that detector's data will be useless. The kpf.spectrograph.StartExposure script will automatically detect this situation, terminate the bad exposure after a few seconds, and start a new one all without user intervention. This will generate several WARNING level log messages, but the user does not need to take action as the correction happens automatically. Another known failure mode which can generate WARNING level log messages is a failure of the FIU to transition in to a new mode (i.e. \"Observing\" or \"Calibration\"). The kpf.fiu.ConfigureFIU and kpf.fiu.WaitForConfigureFIU scripts will automatically retry several times before giving up and erroring out. As with the start state error above, no user action is needed, but you will see WARNING level log messages to let you know what is happening. Switching Programs on a Split Night On a KPF/KPF split night, before starting the second KPF program, run KPF Control Menu --> Set Program ID and Observers from the background menu (or kpfSetObserverFromSchedule from the command line on any KPF machine). Enter the program ID at the terminal prompt. The script will then set program ID and observers for the second KPF program, based on the telescope schedule. If you wish to set the observer names and program ID manually (i.e. without querying the telescope schedule), you can use the kpfSetProgram and kpfSetObserver scripts from the command line. For example: kpfSetProgram K123 will set program ID \"K123\" and kpfSetObserver \"E.E. Barnard, S.W. Burnham\" will set the observer name to \"E.E. Barnard, S.W. Burnham\". Note that observer names should be enclosed in quotes to handle spaces in the list of names. Bad Weather If the weather is so bad that no observing is taking place and there doesn't seem to be an immediate likelihood of observing, then we recommend that the observer runs the end of night procedure ( KPF Control Menu --> Run End of Night Script ). The main advantage of this is that running End of Night will re-enable the automatic scheduled calibrations which happen 4 times per night when KPF is not on sky. This means that the instrumental drift will be tracked with no action required by the observer (i.e. running slew cals). If one of these calibration scripts is in progress and observing should resume, use the \"Request Script STOP\" as described above. After that, run the Start of Night script just as you would at the beginning of the night (among other things it disables the autmatic scheduled calibrations).","title":"Observing Procedures"},{"location":"observingprocedures/#quick-reference","text":"Beginning of the Night Performing Observations Switching Programs on a Split Night Bad Weather","title":"Quick Reference"},{"location":"observingprocedures/#beginning-of-the-night","text":"","title":"Beginning of the Night"},{"location":"observingprocedures/#wait-for-dome-to-open","text":"The Observing Assistant (OA) is not permitted to open the dome until after sunset. Please be patient while the shutter opens and the OA checks the initial telescope pointing.","title":"Wait for Dome to Open"},{"location":"observingprocedures/#run-start-of-night","text":"KPF needs to be configured properly at the start of the night. There is a procedure which should be run only after the Observing Assistant (OA) has selected KPF as the instrument and after automated afternoon calibrations are complete. The selected instrument (\"INST\") can be seen in the lower left corner of the FACSUM window . It is important that this not be run while other instruments are observing. To configure KPF for observing, run KPF Control Menu --> Run Start of Night Script from the background menu (or kpfStartOfNight from the command line on any KPF machine). This will: Disable automated calibrations Configure the FIU to the observing mode Open the science and sky source select shutters Configure the AO Bench. Including positioning the PCU stage and opening the AO hatch. Configure DCS for KPF by setting dcs.ROTDEST=0 and dcs.ROTMODE=stationary Configure the tip tilt loop gain to its default setting Set data output directory Set observers from telescope schedule","title":"Run Start of Night"},{"location":"observingprocedures/#slew-to-the-vicinity-of-your-first-target","text":"When ready to move the telescope, the OA will ask you for your first target and load the coordinates from your starlist file. They will select a bright star near your target and will attempt to acquire that in the guider, then will double-check the accuracy of pointing by acquiring one or two additional stars from the SAO or GSC catalogs. To monitor the guider images, run Telescope GUIs --> MAGIQ Guider UI from the background menu.","title":"Slew to the Vicinity of Your First Target"},{"location":"observingprocedures/#focus-the-telescope","text":"The OA will run the telescope focus procedure (typically Autofoc) near your science field. On some nights, they will opt for the Mira focus procedure which takes slightly longer but is needed to calibrate the secondary mirror tilt.","title":"Focus the Telescope"},{"location":"observingprocedures/#performing-observations","text":"","title":"Performing Observations"},{"location":"observingprocedures/#highlight-your-target-in-magiq","text":"In the Magiq star list (at the bottom of the Magiq User GUI), right click your target and select the option to highlight it for the OA (you can get the same result by middle clicking the target). This highlighting will show up on the OA's GUI making it easier for them to find the target you want to go to. Let the OA know to slew to the target when your current exposure is done.","title":"Highlight Your Target in Magiq"},{"location":"observingprocedures/#execute-your-ob","text":"Observers can load previously saved OBs or create them on the fly for KPF observing. To load and execute a saved OB: Click Load OB from File Select the OB from the file list Click Execute This OB (or Execute OB with Slew Cal) The GUI will first prompt the observers to confirm the OB execution. Once confirmed, an xterm will launch and prompt the observers with addtional information if and when needed, so watch the contents of this xterm. Executing the OB will not start an exposure immediately. The system will first configure the instrument and will then prompt the observer to confirm once the OA has acquired the target. While configuring the instrument, the OB will provide information on how to set the gain and frames per second on the guider. Because of this, it is important to execute the OB during the slew and before the OA acquires the target, so they have the right exposure parameters to see the target on the guider. The log lines which show up in the xterm with the running OB contain useful information. In general, lines with INFO are attempting to explain what the instrument is doing. Lines with WARNING are indicating that a minor problem has occurred, but the system is handling it -- these lines are purely informational, no action is needed on the part of the observer in response. Lines with ERROR indicate a serious problems which may require user intervention.","title":"Execute Your OB"},{"location":"observingprocedures/#slew-cals","text":"KPF has the option of taking a \"slew cal\" immediately prior to a science observation. This is a way to make use of the time spent slewing from one target to another. If an OB is executed with a slew cal (using the \"Execute OB with Slew Cal\" button in the OB GUI), then the FIU will transition to calibration mode (the FIU hatch will close and calibration light will be directed to the science and sky fibers), and a calibration exposure will be taken. This will obscure the sky during calibration, so the OA will not be able to see the target until the slew cal is done. This process takes around 2 minutes and so fits nicely in to long slews. An alternative to a slew cal is a simultaneous calibration (simulcal). To use this enable the TakeSimulCal option in the OB or on the OB GUI and either manually set the ND filters to apply to the calibration light or enable the AutoNDFilters option. See the nighttime calibrations page for more info on both the slew cal and simulcal options.","title":"Slew Cals"},{"location":"observingprocedures/#stopping-scripts-or-exposures","text":"Important : If you wish to halt an OB during execution, do NOT hit Control-c in the terminal. Use the \"Request Script STOP\" button instead. The KPF scripts have checkpoints in them which are places where the script can cleanly exit and perform important cleanup operations. The \"STOP Exposure and Script\" button does the same thing, but it will also terminate an exposure in progress.","title":"Stopping Scripts or Exposures"},{"location":"observingprocedures/#known-issues","text":"There is a known failure mode for KPF called a \"start state error\". What happens is some sort of communication failure between the kpfexpose control software, the galil hardware which handles the timing and signaling of the detectors and shutters, and the Archon detector controllers. The result is that one of the green or red detectors does not begin the exposure properly and that detector's data will be useless. The kpf.spectrograph.StartExposure script will automatically detect this situation, terminate the bad exposure after a few seconds, and start a new one all without user intervention. This will generate several WARNING level log messages, but the user does not need to take action as the correction happens automatically. Another known failure mode which can generate WARNING level log messages is a failure of the FIU to transition in to a new mode (i.e. \"Observing\" or \"Calibration\"). The kpf.fiu.ConfigureFIU and kpf.fiu.WaitForConfigureFIU scripts will automatically retry several times before giving up and erroring out. As with the start state error above, no user action is needed, but you will see WARNING level log messages to let you know what is happening.","title":"Known Issues"},{"location":"observingprocedures/#switching-programs-on-a-split-night","text":"On a KPF/KPF split night, before starting the second KPF program, run KPF Control Menu --> Set Program ID and Observers from the background menu (or kpfSetObserverFromSchedule from the command line on any KPF machine). Enter the program ID at the terminal prompt. The script will then set program ID and observers for the second KPF program, based on the telescope schedule. If you wish to set the observer names and program ID manually (i.e. without querying the telescope schedule), you can use the kpfSetProgram and kpfSetObserver scripts from the command line. For example: kpfSetProgram K123 will set program ID \"K123\" and kpfSetObserver \"E.E. Barnard, S.W. Burnham\" will set the observer name to \"E.E. Barnard, S.W. Burnham\". Note that observer names should be enclosed in quotes to handle spaces in the list of names.","title":"Switching Programs on a Split Night"},{"location":"observingprocedures/#bad-weather","text":"If the weather is so bad that no observing is taking place and there doesn't seem to be an immediate likelihood of observing, then we recommend that the observer runs the end of night procedure ( KPF Control Menu --> Run End of Night Script ). The main advantage of this is that running End of Night will re-enable the automatic scheduled calibrations which happen 4 times per night when KPF is not on sky. This means that the instrumental drift will be tracked with no action required by the observer (i.e. running slew cals). If one of these calibration scripts is in progress and observing should resume, use the \"Request Script STOP\" as described above. After that, run the Start of Night script just as you would at the beginning of the night (among other things it disables the autmatic scheduled calibrations).","title":"Bad Weather"},{"location":"references/","text":"Referencing KPF The suggested instrument paper to use when referencing KPF is currently Gibson et al. (2024) in prep. Additional KPF Instrument Papers \"System Design of the Keck Planet Finder\" Gibson et al. (2024) in prep. \"A fiber injection unit for the Keck Planet Finder: opto-mechanical design\" Lilley et al. (2022) \"Keck Planet Finder: design updates\" Gibson et al. (2020) \"A optical fiber double scrambler and mechanical agitator system for the Keck planet finder spectrograph\" Sirk et al (2018) \"Keck Planet Finder: preliminary design\" Gibson et al. (2018) \"Keck Planet Finder: Zerodur optical bench mechanical design\" Smith et al. (2018) \"A comprehensive radial velocity error budget for next generation Doppler spectrometers\" Halverson et al. 2016 \"KPF: Keck Planet Finder\" Gibson et al. 2016","title":"Acknowledging KPF"},{"location":"references/#referencing-kpf","text":"The suggested instrument paper to use when referencing KPF is currently Gibson et al. (2024) in prep.","title":"Referencing KPF"},{"location":"references/#additional-kpf-instrument-papers","text":"\"System Design of the Keck Planet Finder\" Gibson et al. (2024) in prep. \"A fiber injection unit for the Keck Planet Finder: opto-mechanical design\" Lilley et al. (2022) \"Keck Planet Finder: design updates\" Gibson et al. (2020) \"A optical fiber double scrambler and mechanical agitator system for the Keck planet finder spectrograph\" Sirk et al (2018) \"Keck Planet Finder: preliminary design\" Gibson et al. (2018) \"Keck Planet Finder: Zerodur optical bench mechanical design\" Smith et al. (2018) \"A comprehensive radial velocity error budget for next generation Doppler spectrometers\" Halverson et al. 2016 \"KPF: Keck Planet Finder\" Gibson et al. 2016","title":"Additional KPF Instrument Papers"},{"location":"sensitivity/","text":"Spectrograph Sensitivity For sensitivity estimates, please see the KPF exposure time calculator written by the instrument team. More information is available on the KPF Exposure Time (and RV Precision) Calculator page or go directly to GitHub to download the exposure time calculator software . Acquiring Faint Targets We use J-band magnitude as a rough guide for the guider sensitivity, but it is important to keep in mind that this is not a perfect match to the guider passband (950-1200 nm). That said, we have acquired a J=17.0 (V=18.05) quasar using the guider with FPS=0.1 (10 second individual frame exposures). It was not a strong detection: the target was just visible by eye in the images, but the guide system struggled to lock on to it. Another test acquisition on a J=16.7 (V=17.6) object was correspondingly a bit easier. We believe this performance can be improved substantially by using sky subtraction. This is possible currently, but is a slow manual process to configure. On the second test target above (J=16.7, V=17.6), we got reasonable signal using 0.25 FPS (4 second exposures) while using sky subtraction. We are planning to script this process to make it easier and to integrate sky subtraction in to the OA's GUI for controlling the tip tilt, but the timeline for that is still TBD. If you need to acquire very faint targets (J > 16), please reach out to your SA ahead of time to discuss strategies.","title":"Sensitivity"},{"location":"sensitivity/#spectrograph-sensitivity","text":"For sensitivity estimates, please see the KPF exposure time calculator written by the instrument team. More information is available on the KPF Exposure Time (and RV Precision) Calculator page or go directly to GitHub to download the exposure time calculator software .","title":"Spectrograph Sensitivity"},{"location":"sensitivity/#acquiring-faint-targets","text":"We use J-band magnitude as a rough guide for the guider sensitivity, but it is important to keep in mind that this is not a perfect match to the guider passband (950-1200 nm). That said, we have acquired a J=17.0 (V=18.05) quasar using the guider with FPS=0.1 (10 second individual frame exposures). It was not a strong detection: the target was just visible by eye in the images, but the guide system struggled to lock on to it. Another test acquisition on a J=16.7 (V=17.6) object was correspondingly a bit easier. We believe this performance can be improved substantially by using sky subtraction. This is possible currently, but is a slow manual process to configure. On the second test target above (J=16.7, V=17.6), we got reasonable signal using 0.25 FPS (4 second exposures) while using sky subtraction. We are planning to script this process to make it easier and to integrate sky subtraction in to the OA's GUI for controlling the tip tilt, but the timeline for that is still TBD. If you need to acquire very faint targets (J > 16), please reach out to your SA ahead of time to discuss strategies.","title":"Acquiring Faint Targets"},{"location":"socal/","text":"Solar Calibrator (SoCal) The KPF Solar Calibrator (SoCal) is installed on the roof of the support building between the Keck I and Keck II domes. It consists of an EKO Sun Tracker inside an enclosure designed to protect it from strong winds and falling ice. The EKO tracker carries a pyrheliometer to measure solar intensity (used to confirm that we are on the Sun and the sky is clear) and a solar collector which feeds full disk solar light in to a fiber optic which carries it to two locations in the Calibration Bench in the basement where it can be fed in to the KPF instrument.","title":"Solar Calibrator"},{"location":"socal/#solar-calibrator-socal","text":"The KPF Solar Calibrator (SoCal) is installed on the roof of the support building between the Keck I and Keck II domes. It consists of an EKO Sun Tracker inside an enclosure designed to protect it from strong winds and falling ice. The EKO tracker carries a pyrheliometer to measure solar intensity (used to confirm that we are on the Sun and the sky is clear) and a solar collector which feeds full disk solar light in to a fiber optic which carries it to two locations in the Calibration Bench in the basement where it can be fed in to the KPF instrument.","title":"Solar Calibrator (SoCal)"},{"location":"spectrograph/","text":"Spectrometer Optical Design The baseline KPF spectrometer design is shown in the following figure. Light enters the core spectrometer following the fiber image reformatter, at the focal point of the primary collimator mirror (traditionally this would be the location of the spectrometer slit). The f/8 beam diverges past this point and then strikes the primary collimator mirror (an off-axis paraboloid). Upon reflection, the now collimated 200 mm diameter light beam travels to the echelle grating, located one primary collimator focal length away from the primary collimator. After diffraction by the echelle, the diverging monochromatic beams reflect from the primary collimator a second time. Because the echelle grating is rotated slightly out of plane (the echelle gamma angle), the dispersed light does not return along the same path, and the pre- and post-diffraction beams are separated. Therefore, after reflecting from the collimator the second time, the dispersed light does not return to the entrance slit, but forms an intermediate focus to the side of the echelle. Just before the intermediate focus, a flat mirror is employed to fold the beam, to make the spectrometer footprint more compact. Layout of the spectrograph on the optical bench. After the fold mirror reflection, the light rays go through the intermediate focus, and then the diverging monochromatic beams are collimated by the secondary collimator mirror (an off-axis paraboloid). The monochromatic beam diameter here is 160 mm, owing to the secondary collimator having a focal length 0.8x that of the primary collimator. The converging monochromatic beams next encounter a dichroic beamsplitter, where wavelengths blueward of 593 nm are reflected, and wavelengths redward of 593 nm are transmitted. After reflection, the green channel monochromatic beams continue to converge towards the white pupil, where the cross-dispersion grism (grating prism) is located. This disperser consists of a shallow apex angle prism bonded to a volume phase holographic (VPH) grating. Following the grism, the light enters the camera, which then focuses the spectrum onto the CCD detector. A summary of various spectrometer parameters is given the the following table. A brief summary table of KPF instrument properties. VPH Grating Overview As described above, the main spectrometer employs VPH-based grisms for cross-dispersion. In order to provide sufficient cross dispersion, the green channel VPH grating was produced with a line density of 800 lines per mm and the red channel VPH with 450 lines per mm. A summary of the KPF VPH grating specifications are shown in the table below. Both gratings were produced by Kaiser Optical Systems (KOSI). A brief summary table of KPF's VPH grating properties. A preliminary set of diffraction efficiency measurements was conducted by KOSI at a few locations across the clear aperture for each KPF grating. These data were re-measured and confirmed at SSL using the measurement test equipment and procedures developed by the DESI project. Overall, we were able to confirm KOSI's measurements and saw a slight (2-4%) increase in diffraction efficiency. The optimum angle of incidence (AOI) for each grating were both chosen away from their design AOI due to gains in diffraction efficiency at the \"blue\" end (green grating) and \"red\" end (red grating) of the KPF passband. For the green grating, we chose an AOI of -29.5 degree which incrased the overall band average efficiency from 86.4 degree to 87.7 degree. This increased the blue end efficiency from 77.6% to 84.6%. For the red grating, we chose an AOI of -25.4 degree which slightly increased the overall band average efficiency from 87.7% to 88.6%. This increased the red end efficiency from 82.7% to 89.6%. The following figure shows the SSL measured efficiency of the two KPF VPH gratings over the spectrometer's passband. With the changing of the AOI in each grating, we have seen significant gains (approximately 25%) in diffraction efficiency vs. the production minimum specification at both ends of the spectrometer passband. Overall these grating exceeded our production minimum specification by >5% across at all wavelengths with the noted gains at the \"blue\" and \"red\" ends of the KPF spectrometer passband. Plot of the VPH grating efficiency as a function of wavelength.","title":"Spectrograph"},{"location":"spectrograph/#spectrometer-optical-design","text":"The baseline KPF spectrometer design is shown in the following figure. Light enters the core spectrometer following the fiber image reformatter, at the focal point of the primary collimator mirror (traditionally this would be the location of the spectrometer slit). The f/8 beam diverges past this point and then strikes the primary collimator mirror (an off-axis paraboloid). Upon reflection, the now collimated 200 mm diameter light beam travels to the echelle grating, located one primary collimator focal length away from the primary collimator. After diffraction by the echelle, the diverging monochromatic beams reflect from the primary collimator a second time. Because the echelle grating is rotated slightly out of plane (the echelle gamma angle), the dispersed light does not return along the same path, and the pre- and post-diffraction beams are separated. Therefore, after reflecting from the collimator the second time, the dispersed light does not return to the entrance slit, but forms an intermediate focus to the side of the echelle. Just before the intermediate focus, a flat mirror is employed to fold the beam, to make the spectrometer footprint more compact. Layout of the spectrograph on the optical bench. After the fold mirror reflection, the light rays go through the intermediate focus, and then the diverging monochromatic beams are collimated by the secondary collimator mirror (an off-axis paraboloid). The monochromatic beam diameter here is 160 mm, owing to the secondary collimator having a focal length 0.8x that of the primary collimator. The converging monochromatic beams next encounter a dichroic beamsplitter, where wavelengths blueward of 593 nm are reflected, and wavelengths redward of 593 nm are transmitted. After reflection, the green channel monochromatic beams continue to converge towards the white pupil, where the cross-dispersion grism (grating prism) is located. This disperser consists of a shallow apex angle prism bonded to a volume phase holographic (VPH) grating. Following the grism, the light enters the camera, which then focuses the spectrum onto the CCD detector. A summary of various spectrometer parameters is given the the following table. A brief summary table of KPF instrument properties.","title":"Spectrometer Optical Design"},{"location":"spectrograph/#vph-grating-overview","text":"As described above, the main spectrometer employs VPH-based grisms for cross-dispersion. In order to provide sufficient cross dispersion, the green channel VPH grating was produced with a line density of 800 lines per mm and the red channel VPH with 450 lines per mm. A summary of the KPF VPH grating specifications are shown in the table below. Both gratings were produced by Kaiser Optical Systems (KOSI). A brief summary table of KPF's VPH grating properties. A preliminary set of diffraction efficiency measurements was conducted by KOSI at a few locations across the clear aperture for each KPF grating. These data were re-measured and confirmed at SSL using the measurement test equipment and procedures developed by the DESI project. Overall, we were able to confirm KOSI's measurements and saw a slight (2-4%) increase in diffraction efficiency. The optimum angle of incidence (AOI) for each grating were both chosen away from their design AOI due to gains in diffraction efficiency at the \"blue\" end (green grating) and \"red\" end (red grating) of the KPF passband. For the green grating, we chose an AOI of -29.5 degree which incrased the overall band average efficiency from 86.4 degree to 87.7 degree. This increased the blue end efficiency from 77.6% to 84.6%. For the red grating, we chose an AOI of -25.4 degree which slightly increased the overall band average efficiency from 87.7% to 88.6%. This increased the red end efficiency from 82.7% to 89.6%. The following figure shows the SSL measured efficiency of the two KPF VPH gratings over the spectrometer's passband. With the changing of the AOI in each grating, we have seen significant gains (approximately 25%) in diffraction efficiency vs. the production minimum specification at both ends of the spectrometer passband. Overall these grating exceeded our production minimum specification by >5% across at all wavelengths with the noted gains at the \"blue\" and \"red\" ends of the KPF spectrometer passband. Plot of the VPH grating efficiency as a function of wavelength.","title":"VPH Grating Overview"},{"location":"status/","text":"Instrument Status KPF has been commissioned on sky, and is available for use. Many aspects of the instrument are still being optimized and the long term stability is still under evaluation. Short term stability looks excellent (exceeding the 50 cm/s target spec within a night) and we expect measures of the long term RV precision to become available as the DRP evolves. A detailed summary of the instrument status was presented at the September 2023 Keck Science Meeting. The slides from that presentation are available in PDF format . Important Notice : KPF will have a lengthy \u201cservicing mission\u201d during 24B to perform several upgrades. This will involve warm up of the optical bench. The expected timeline is to do this in November 2024. Details are still being worked out. Subsystem Status This is an attempt to summarize the status of various sub-systems of the instrument. Each sub-system name is color coded to indicate the status at a glance: green means functioning normally, orange means mostly normal, but with some caveats or minor issues, and red means the sub-system is compromised in some way. Tip Tilt Corrections : The tip tilt stage X-axis has degraded once again (as of 2024 Aug 22) and we are not making fast tip tilt corrections in X. Troubleshooting is underway. Ca H&K Detector : Currently fully functional. Double Star Observations : Recent modifications to the tip tilt system should enable double star observations. There is still learning curve as we figure out how to optimize source detection though, so be patient with the OAs while trying to do this. Remember that this is not the same as the MAGIQ guiding system, so your intuition there does not transfer to KPF. Etalon : The etalon flux problem was fixed during the servicing mission in Feb 2024 and it is now provided the expected flux levels. We have not yet worked out an algorithm for recommending ND filter settings for a given observation to balance SimulCal five flux with science fiber flux, but the mode is available. We are still recommending that slew cals should be taken every hour. LFC : Is operating normally. Standard exposure parameters are now ExpTime: 60, CalND1: OD 2.0, and CalND2: OD 0.1 . Detector Systems : The red and green detectors suffer from occasional \u201cstart state errors\u201d in which the affected detector remains in the start phase and does not produce a useful exposure. The observing scripts now detect this occurrence, abort the current exposure (with read out) and start a fresh exposure on both cameras. No action is necessary on the part of the observer. This costs about a minute of time for this to happen, but the resulting data should be normal (unless another error occurs). The occurrence rate for these problems is 0.34% on the green detector and 0.22% on the red, so around one in every 180 exposures is affected by one of the two detectors experiencing this error. Simultaneous Calibration (SimulCal) : Simultaneous calibrations are supported. Observers have the option of manually specifying the ND filters to balance the calibration flux or using the AutoNDFilters option in the OB to have an algorithm set the filters based on the KPF ETC, the target parameters in the OB, and a reference calibration brightness value. See the Nighttime Calibrations page for more info. Exposure Meter Terminated Exposures : The control system supports exposure meter terminated exposures ( ExpMeterMode: control in the OB), however we are still verifying performance on sky. Nod to Sky Observations : For observations which need a sky measurement other than the built in sky fibers, nodding away to a sky position can be accomplished manually by running separate OBs for the target and sky and asking the OA to offset the telescope as appropriate. We plan to build a separate Nod To Sky observing mode which will accomplish this within a single OB, but that is not yet ready. Off Target Guiding : Not yet commissioned. Currently, the tip tilt system must be able to detect the science target in order to position it on the fiber.","title":"Instrument Status"},{"location":"status/#instrument-status","text":"KPF has been commissioned on sky, and is available for use. Many aspects of the instrument are still being optimized and the long term stability is still under evaluation. Short term stability looks excellent (exceeding the 50 cm/s target spec within a night) and we expect measures of the long term RV precision to become available as the DRP evolves. A detailed summary of the instrument status was presented at the September 2023 Keck Science Meeting. The slides from that presentation are available in PDF format . Important Notice : KPF will have a lengthy \u201cservicing mission\u201d during 24B to perform several upgrades. This will involve warm up of the optical bench. The expected timeline is to do this in November 2024. Details are still being worked out.","title":"Instrument Status"},{"location":"status/#subsystem-status","text":"This is an attempt to summarize the status of various sub-systems of the instrument. Each sub-system name is color coded to indicate the status at a glance: green means functioning normally, orange means mostly normal, but with some caveats or minor issues, and red means the sub-system is compromised in some way. Tip Tilt Corrections : The tip tilt stage X-axis has degraded once again (as of 2024 Aug 22) and we are not making fast tip tilt corrections in X. Troubleshooting is underway. Ca H&K Detector : Currently fully functional. Double Star Observations : Recent modifications to the tip tilt system should enable double star observations. There is still learning curve as we figure out how to optimize source detection though, so be patient with the OAs while trying to do this. Remember that this is not the same as the MAGIQ guiding system, so your intuition there does not transfer to KPF. Etalon : The etalon flux problem was fixed during the servicing mission in Feb 2024 and it is now provided the expected flux levels. We have not yet worked out an algorithm for recommending ND filter settings for a given observation to balance SimulCal five flux with science fiber flux, but the mode is available. We are still recommending that slew cals should be taken every hour. LFC : Is operating normally. Standard exposure parameters are now ExpTime: 60, CalND1: OD 2.0, and CalND2: OD 0.1 . Detector Systems : The red and green detectors suffer from occasional \u201cstart state errors\u201d in which the affected detector remains in the start phase and does not produce a useful exposure. The observing scripts now detect this occurrence, abort the current exposure (with read out) and start a fresh exposure on both cameras. No action is necessary on the part of the observer. This costs about a minute of time for this to happen, but the resulting data should be normal (unless another error occurs). The occurrence rate for these problems is 0.34% on the green detector and 0.22% on the red, so around one in every 180 exposures is affected by one of the two detectors experiencing this error. Simultaneous Calibration (SimulCal) : Simultaneous calibrations are supported. Observers have the option of manually specifying the ND filters to balance the calibration flux or using the AutoNDFilters option in the OB to have an algorithm set the filters based on the KPF ETC, the target parameters in the OB, and a reference calibration brightness value. See the Nighttime Calibrations page for more info. Exposure Meter Terminated Exposures : The control system supports exposure meter terminated exposures ( ExpMeterMode: control in the OB), however we are still verifying performance on sky. Nod to Sky Observations : For observations which need a sky measurement other than the built in sky fibers, nodding away to a sky position can be accomplished manually by running separate OBs for the target and sky and asking the OA to offset the telescope as appropriate. We plan to build a separate Nod To Sky observing mode which will accomplish this within a single OB, but that is not yet ready. Off Target Guiding : Not yet commissioned. Currently, the tip tilt system must be able to detect the science target in order to position it on the fiber.","title":"Subsystem Status"},{"location":"tiptilt/","text":"Tip Tilt Correction System The KPF tip tilt system takes fast (e.g. 100 FPS) subframe images from the KPF CRED2 guide camera in order to control the fast tip tilt mirror which directs light in to the KPF FIU. This fast tip tilt system maintains the stellar position on the science fiber. This is critical not for reasons of maximizing flux in to the spectrograph (though that is a side benefit), but to optimize the radial velocity measurement by keeping the illumination pattern on the fiber tip stable. Even after fiber scrambling and agitation, if the star\u2019s position on the fiber entrance fiber shifts, that can manifest as a small shift of the spectrum on the detector which would be interpreted as a radial velocity change. Thus we need to position the star on the fiber, and then hold it in a consistent place during observations and make that position consistent from observation to observation. The tip tilt mirror is a fold mirror which sits on the PCU stage on the Keck I AO bench. The mirror folds the light in to the KPF FIU and is controlled in tip and tilt by a piezo stage built by nPoint. The nominal spec for tip tilt performance is to position of the star within 50mas of the target position and then maintain that position at an RMS fo 50mas or better. The software which controls the tip tilt stage is built in to the kpffiu and kpfguide KTL keyword services.","title":"Tip Tilt Sysyem"},{"location":"tiptilt/#tip-tilt-correction-system","text":"The KPF tip tilt system takes fast (e.g. 100 FPS) subframe images from the KPF CRED2 guide camera in order to control the fast tip tilt mirror which directs light in to the KPF FIU. This fast tip tilt system maintains the stellar position on the science fiber. This is critical not for reasons of maximizing flux in to the spectrograph (though that is a side benefit), but to optimize the radial velocity measurement by keeping the illumination pattern on the fiber tip stable. Even after fiber scrambling and agitation, if the star\u2019s position on the fiber entrance fiber shifts, that can manifest as a small shift of the spectrum on the detector which would be interpreted as a radial velocity change. Thus we need to position the star on the fiber, and then hold it in a consistent place during observations and make that position consistent from observation to observation. The tip tilt mirror is a fold mirror which sits on the PCU stage on the Keck I AO bench. The mirror folds the light in to the KPF FIU and is controlled in tip and tilt by a piezo stage built by nPoint. The nominal spec for tip tilt performance is to position of the star within 50mas of the target position and then maintain that position at an RMS fo 50mas or better. The software which controls the tip tilt stage is built in to the kpffiu and kpfguide KTL keyword services.","title":"Tip Tilt Correction System"},{"location":"tiptiltinstructions/","text":"Tip Tilt Instructions for OAs Table of Contents TL:DR Procedure Tip Tilt System Overview Tip Tilt GUI GUI Layout Camera Controls Tab Object Detection Tab Offset Guiding Tab Settings Tab Plot Time Spans Tab Tip Tilt Control and Telemetry Image Display Instrument Status Status Bar Star Detection Algorithm Deblending Multiple Stars TL:DR Procedure Set the gain and FPS values for the guide camera. Acquire the star to the KPF PO using magiq. In the KPF Tip Tilt GUI, turn on the tip tilt loops. Verify normal operation of the loops (this should just require a momentary glance at the various indicators): Make sure the science target has been indentified. It should have a circle around it and a label in the image display part of the GUI. Check that an object has been selected in \"Object Choice\". Check that the Peak Flux is sufficient (the value will be color coded to help you). If needed, adjust the gain and FPS. Check that the Tip Tilt Error is decreasing over time in the plot. This indicates that the star is being moved to the target pixel. Check the \"Tip Tilt RMS\" value is around 50 mas or better. If the target is faint or there are heavy clouds or bad seeing, it may not be able to reach this, but under normal conditions we should at least be in the ballpark. If there are multiple stars in the field of view, ensure that the corect target is selected and that the stars are not blended. Each detected star will have its own OBJECTn label in the image display: make sure this is centered on the star . Inform the observer that the tip tilt loops are engaged and they can begin exposing. Troubleshooting the TL:DR Procedure If the system is not seeing the target star, adjust the \"Detect SNR\" and/or \"Detect Area\" values under the Object Detection tab in the GUI (see Star Detection Algorithm section below for details). If the system seems to be having trouble identifying stars, toggle the loops on and off (this is primarily for the Calculation loop). Doing this will cause the algorithm to re-identify the stars and may resolve ID confusion caused when stars are moving rapidly in the field. Check that there are no red indicators in the status bar at the bottom of the Tip Tilt GUI. These indicate that something substantial is wrong. Which indicator it is will tell you which keyword or dispatcher is in a bad state. Tip Tilt System Overview The KPF tip tilt system takes fast (e.g. 100 FPS) subframe images from the KPF CRED2 guide camera in order to control the fast tip tilt mirror which directs light in to the KPF FIU. This fast tip tilt system maintains the stellar position on the science fiber. This is critical not for reasons of maximizing flux in to the spectrograph (though that is a side benefit), but to optimize the radial velocity measurement. Even after fiber scrambling and agitation, if the star\u2019s position on the fiber entrance fiber shifts, that can manifest as a small shift of the spectrum on the detector which would be interpreted as a radial velocity change. Thus we need to position the star on the fiber, and then hold it in a consistent place during observations and make that position consistent from observation to observation. Tip Tilt Loops There are several components to the tip tilt loops. Controls for toggling them on and off together and individually are provided in the Tip Tilt Control and Telemetry section of the Tip Tilt GUI. The important pieces are: Calculation : The calculations are the part of the algorithm which is examining images from the guide camera, detecting and identifying objects, and calculating the relevant tip tilt commands. This can be toggled on and off using the underlying kpfguide.TIPTILT_CALC keyword. Note that once calculations are turned on the system is attempting to cross identify stars from image to image and maintain a consistent identity. One of the things it uses to do this is knowledge of the average positions of stars in recent images. Thus, if the stars are moved dramatically (e.g. by Magiq), it may confuse the IDs. If you think this might be the case, restarting calculations will force a fresh identification phase. Control : The control component takes the output of the calculations loop and sends commands to the tip tilt mirror. As long as the motions needed are within range of the tip tilt mirror, this will close the loops and should yield a stable star position. This can be toggled on and off using the underlying kpfguide.TIPTILT_CONTROL keyword. Offload : If the motion of the star carries it toward the edfe of the tip tilt mirror's range of motion, the system will \"offload\" some of that movement to the telescope (akin to a normal guiding command). Enabling offloads allows those commands to go to the telescope. This can be toggled on and off using the underlying kpfguide.OFFLOAD keyword. The kpfguide.OFFLOAD keyword will also attempt examine the telescope control system ( dcs ) to determine if offloads should be sent. This permissive is based primarily on whether KPF is the selected instrument, if not, the instrument should not be sending offloads to the telescope. The kpfguide.OFFLOAD_DCS keyword indicated whether KPF is permitted to offload and it must be \"Yes\" in order for offloads to be enabled. Tip Tilt GUI To start the GUI, open a terminal as any kpf user (e.g. kpfeng) on the kpf machine and type: TTGUI_v2 . For dark mode, add the -d option to the command. A screenshot of the Tip Tilt GUI. The Tip Tilt GUI may also be opened for observers in \"monitor\" mode, in which case none of the controls are active, but the telemetry and image display can be seen. To do this, use the TTGUI_v2 --monitor terminal command as above or select KPF Control Menu -> Subcomponents -> Start Tip Tilt GUI from the FVWM menu in a KPF VNC session. GUI Layout The top section of the GUI (beneath the \"File\" and \"Troubleshooting\" menus), is a small tabbed interface with various controls and options. See the sections below on each tab. Beneath the tabbed section is a region titled \"Tip Tilt Control and Telemetry\" this section contains control for the tip tilt loops and telemetry about the tip tilt performance. See the Tip Tilt Control and Telemetry section below for details. Beneath that is a region titled \"Image Display\" which shows the latest Magiq image cropped to the region which the tip tilt system is using (a subframe of the whole field). It also contains the tool for choosing which object in the field to guide on and controls for the image display stretch and cut. See the Image Display section below for details. Beneath that is a region titled \"Instrument Status\" which contains a very brief summary of what the instrument is doing at the moment. See the Instrument Status section below for details. The very bottom of the GUI is the status bar which will be empty if everything is in a working state for observing. See the Status Bar section below for details. Camera Controls Tab A screenshot of the Tip Tilt GUI's Camera Controls tab. When the observer executes an OB (which they should do during the slew, but they may forget or not be ready, so check if you are unsure), then the target star's J band magnitude will be populated in this GUI. This will also update the \"Recommended Gain & FPS\" values. If you wish to accept these recommendations, simply click the \"Set\" button. The recommendations will be color coded green if they match the current values or orange if they do not match. The pulldown to the left of the \"Set\" button will add in some amount of extinction (in magnitudes) to the estimated values. If you have clouds, you can put in some value for the extinction and the estimate will account for the clouds. The right hand section of the tab shows the current Gain & FPS values. You may set them here using the pulldown menus. You can set these values on the command line by modifying the relevant keywords: kpgduide.GAIN , and kpfguide.FPS . Object Detection Tab A screenshot of the Tip Tilt GUI's Object Detection tab. This is where you can set the object detection and deblending parameters discussed in the Star Detection Algorithm section below. The pulldowns will set the requested value. You can set these values on the command line by modifying the relevant keywords: kpgduide.OBJECT_INTENSITY , kpfguide.OBJECT_AREA , and kpfguide.OBJECT_DBCONT . Offset Guiding Tab Not currently implemented. Settings Tab A screenshot of the Tip Tilt GUI's Settings tab. The three options here control various settings for the kpfguide algorithms. The \"X Axis\" and \"Y Axis\" settings allow you to bypass the tip tilt mirror and control the star position only using offloads to the telescope (conceptually similar to normal Magiq guiding). These values should be \"Mirror\" unless there is a problem with the tip tilt system. The \"DAR\" setting determines whether the target pixel for the star is modified to account for differential atmospheric refraction (DAR) between the guide wavelengths (950-1200nm) and the science wavelengths (centered on 550nm). This should be set to \"Yes\" under normal observing conditions. Plot Time Spans Tab A screenshot of the Tip Tilt GUI's Plot Time Spans tab. These two pulldowns allow you to change the time span of the two plots in the Tip Tilt Control and Telemetry region of the GUI. They have no effect on the tip tilt performance, only the plots. Tip Tilt Control and Telemetry This section of the GUI is how the tip tilt loops are opened and closed. The \"Tip Tilt On/Off\" button will likely be the primary interface as it toggles all of the components off the system on and off together, but the checkboxes to the right allow each to be toggled individually. Note that the \"Offloads\" checkbox will be color coded red when kpfguide.OFFLOAD_DCS is \"No\". The \"Tip Tilt Phase\" is meant to summarise whether the system has fully controlled the star's position to the point where the observers can begin exposing. It will begin in \"Identifying\", then move to \"Acquiring\" once a star has been identified and is being moved to the target pixel, and finally reach \"Tracking\" when the star is in position. These stages are based on the position error of the star and so may not be a perfect guide, but should be useful under normal conditions. The \"Tip Tilt FPS\" value shown in the GUI is the rate at which frames are being processed by the tip tilt algorithm and should be compared to the gude camera FPS. The \"Tip Tilt FPS\" value will likely bounce around a bit, but it should stay somewhere in the range of the camera FPS (within maybe 10%). If it is much less than the camera FPS, then the tip tilt system is not keeping up with the images coming in. The GUI will color code this value with orange and red values when it deviated from the camera FPS by more than some threshold amount. The \"Tip Tilt RMS\" value shown indicates how much the stellar position varies from frame to frame. This is different than the \"Tip Tilt Error\" (used in the plot below). The RMS is a measure of the frame to frame variation while the error is the average offset between the star and the target pixel. The error should drop to <<1 pixel under good conditions as the average star position is driven to the target pixel, but as the star bounces around from frame to frame due to seeing, the RMS value will be larger than zero. Our design goal is for the RMS value to be <50 mas (<1 pixel). The \"Peak Flux\" value is the brightness (in ADU) of the brightest pixel in the star as measured by the star detection algorithm. This is a good, but imperfect indication of whether the star is saturated in the guider image. Some bad pixels are always bright and if one of them is included in the star detection then the value of that one bad pixel will affect this reading, so you should use some discretion when inspecting this value. We have plans to implement a bad pixel mask which should mitigate this, but that is not complete and will require some care to make sure it does not affect the high speed calculations in the tip tilt loops. The guide camera is 14-bit, so it saturates at a value of 16,384. We perform a bias subtraction, so in practice this value is more like 14,000 counts. Saturation is not a deal breaker for using the tip tilt system. Mild saturation of only a few pixels in the core of the star will not drastically degrade the tip tilt performance, so it is better to saturate a bit than to try to run the FPS up to extremely high values where the calculations can not keep up. The \"Total Flux\" value is the sum of all pixel values with the detected star. This is an alternate indicator of the star's brightness, but does not directly indicate whether the star saturates the camera. The \"Tip Tilt Error\" plot is the left hand plot in the GUI. This is the offset (in pixels) between the stars's average position and the target pixel. When you first turn on the loops, you should see this start at a high value (a few pixels) and drop rapidly to near 0. The \"Flux\" plot is the right hand plot in the GUI. It plots the total flux in the star over time. The behavior of this is a useful indicator of clouds. Image Display The image display section shows a cropped version of the Magiq image (cropped to the region the tip tilt algorithm is using). It is important to remember that this image is not the same as what the tip tilt system is using for its calculations! This is an average of frames over the Magiq exposure time, so you have a higher SNR in this image than you do in the individual frames going in to the tip tilt calculations. The filename displayed and the timestamp at which the file was updated are also shown near the top. Mousing over the image will read out the pixel position and value of the pixel under the cursor just below the image and next to the X and Y position of the target pixel the algorithm is trying to steer the star to (this value is updated by DAR and so will change). The image will show an overlayed circle and label with the object's name (\"OBJECT1, OBJECT2, or OBJECT3\") and the percentage value next to the label is the fraction of frames in which is object is detected. If this is much less than 100%, you should probably adjust the detection parameters or adjust the sensitivity of the guider (i.e. increase gain or lower the FPS). To the right of the image is the \"Object Choice\" box. In the case where multiple objects are detected, you will need to choose one of them to be the target. Use the pulldown to choose which one you want to drive to the target pixel. Below this is a plot showing where the tip tilt mirror is within its range. The range is indicated by the green area. Points will be drawn and fade out over time to indicate the motion of the tip tilt mirror. Finally there are two selectors for \"Image Cut\" and \"Image Scaling\", these affect the image display, so feel free to adjust as you see fit. Instrument Status There is a small section here summarizing the instrument status. It shows whether there is a script running which is a good indicator of whether data is being taken. The \"Exposure Status\" value shows whether the detectors are exposing, reading out, etc. The \"FIU Mode\" is a good guide as to whether you should expect to be seeing light from the sky on the guider images (e.g. if it is in \"Calibration\" mode, we are taking a cal exposure and you are probably seeing cal fibers, not the sky). Finally, the \"Object\" value is the string the observer has used to name the target. Status Bar The very bottom of the GUI is a status bar. It will be empty under normal operating conditions, but will contain red indicators when there is a problem that will likely halt operation of the tip tilt system. For example, in the screenshot below several errors are shown: A screenshot of the Tip Tilt GUI's Status Bar with several errors. Status bar errors which can show up include: CONTINUOUS : This indicates that the guide camera is not exposing. SAVE : This indicates that the guide camera is not saving files. TTXSRV : This indicates that the tip tilt mirror X axis is not in servo mode and thus will not correct properly. TTYSRV : This indicates that the tip tilt mirror Y axis is not in servo mode and thus will not correct properly. DAR Disabled : This indicates that the DAR is not enabled. kpfguide1 : This indicates that there is a likely problem with the kpfguide1 dispatcher and a restart is likely required. kpfguide2 : This indicates that there is a likely problem with the kpfguide2 dispatcher and a restart is likely required. kpfguide3 : This indicates that there is a likely problem with the kpfguide3 dispatcher and a restart is likely required. Star Detection Algorithm The kpfguide software uses Source Extractor via the SEP Python Library for star detection. The \"Detect SNR\" and \"Detect Area\" values in the GUI correspond to the thresh and minarea parameters of sep.extract and to kpfguide.OBJECT_INTENSITY and kpfguide.OBJECT_AREA keyword respectively. The way the algorithm detects stars is to look for adjacent clusters of pixels with values above \"Detect SNR\". If that cluster is larger than \"Detect Area\" pixels, then it is a star. Both parameters are critical in determining whether a star will be detected. Having a large \"Detect Area\" means that faint stars will often not have enough bright pixels to be considered a detection. Similarly, a large \"Detect SNR\" might mean that not enough pixels are bright enough so too few pixels will be detections to be considered a star. On faint targets, both parameters may need to come down if only the very core of the star has significant signal in it. If you're having trouble in good seeing, make sure that \"Detect Area\" is not too large for the seeing. Based on experience, starting with values of 5-7 for \"Detect SNR\" and 80-100 for \"Detect Area\" are reasonable. Deblending Multiple Stars Deblending is a term that comes from Source Extractor. It can be both perilous and useful. Early in the system\u2019s use, we were still using the default deblending contrast of 0.005, which meant that it took only a small dip in flux (0.5%) for two adjacent maxima to be considered two different objects. In practice, this meant that a single star would deblend in to multiple stars due to speckles moving about. As a result, the \u201cstar\u201d would appear to shift to one side or the other leading to sudden large corrections which would then be reversed a frame or two later when the speckles had shifted and the star was no longer deblended. This could affect several percent of all guide frames (in other words, the star was being jolted around by spurious detections several times per second). Of course, in situation where there are actually blended stars this is a useful tool. Double stars can be separated and a particular guide target chosen using this system. Based on our experience so far, leaving deblending contrast at 1.0 for most targets is the right choice. This demands that the valley between adjacent peaks be as deep as the highest peak (i.e. it goes to 0), so it turns deblending off. Since most targets are isolated stars with no close neighbors of similar brightness, this avoids the problem of tracking on speckles. If a double star is the target, decreasing the deblending contrast until it is reliably separates is the best strategy. Use the overlays in the image display to ensure that the target star has its own label and that label is centered properly on the star. If the label is not centered on the star, it might be blended with the companion which is puslling the \"center\" off toward the companion -- this is what we mean by blended stars. If the stars are blended, they must be deblended for KPF to accurately place one properly on the fiber. If the centroid is biased because the stars are not deblended you will end up with an RV effect due to the positioning of the star on the fiber being incorrect. The deblend contrast can be run down at 0.005 or lower to pull out a faint companion. Note that this is the contrast between the bright star and the faint \"gap\" between companions, so large contrast is not unexpected if the companion star is a few magnitudes fainter than the primary. For example, if the deblend contrast is 0.01 that is 5 magnitudes of contrast 2.5*log(0.01) , but that's not an unreasonable contrast for the gap if the companion star is just 2 or 3 magnitudes fainter than the primary. Also, because the algorithm is doing deblending, not trying to detect the companion as a separate object, we don't need to worry about the primary being too bright -- it is ok to saturate the primary to get the companion. Of course, a widely separated double star may be seen as two stars by the system if there is a \u201cgap\u201d between the two stars where the signal in the pixels is lower than the detection threshold. In this case, no deblending is necessary. Finally, if the star the observers are trying to acquire is too challenging and you are unable to make it work, you can ask the observer to click the \"Collect Guider Image Cube\" button on their OB GUI. This will save a brief sequence of guider images which can be analyzed offline to find out the best way to acquire that particular star (email the KPF SA to let them know to look at it). This does not help for the immediate observation, but will allow us to find the right solution for the next time this target or a similar one is observed.","title":"Tip Tilt Instructions for OAs"},{"location":"tiptiltinstructions/#tip-tilt-instructions-for-oas","text":"","title":"Tip Tilt Instructions for OAs"},{"location":"tiptiltinstructions/#table-of-contents","text":"TL:DR Procedure Tip Tilt System Overview Tip Tilt GUI GUI Layout Camera Controls Tab Object Detection Tab Offset Guiding Tab Settings Tab Plot Time Spans Tab Tip Tilt Control and Telemetry Image Display Instrument Status Status Bar Star Detection Algorithm Deblending Multiple Stars","title":"Table of Contents"},{"location":"tiptiltinstructions/#tldr-procedure","text":"Set the gain and FPS values for the guide camera. Acquire the star to the KPF PO using magiq. In the KPF Tip Tilt GUI, turn on the tip tilt loops. Verify normal operation of the loops (this should just require a momentary glance at the various indicators): Make sure the science target has been indentified. It should have a circle around it and a label in the image display part of the GUI. Check that an object has been selected in \"Object Choice\". Check that the Peak Flux is sufficient (the value will be color coded to help you). If needed, adjust the gain and FPS. Check that the Tip Tilt Error is decreasing over time in the plot. This indicates that the star is being moved to the target pixel. Check the \"Tip Tilt RMS\" value is around 50 mas or better. If the target is faint or there are heavy clouds or bad seeing, it may not be able to reach this, but under normal conditions we should at least be in the ballpark. If there are multiple stars in the field of view, ensure that the corect target is selected and that the stars are not blended. Each detected star will have its own OBJECTn label in the image display: make sure this is centered on the star . Inform the observer that the tip tilt loops are engaged and they can begin exposing.","title":"TL:DR Procedure"},{"location":"tiptiltinstructions/#troubleshooting-the-tldr-procedure","text":"If the system is not seeing the target star, adjust the \"Detect SNR\" and/or \"Detect Area\" values under the Object Detection tab in the GUI (see Star Detection Algorithm section below for details). If the system seems to be having trouble identifying stars, toggle the loops on and off (this is primarily for the Calculation loop). Doing this will cause the algorithm to re-identify the stars and may resolve ID confusion caused when stars are moving rapidly in the field. Check that there are no red indicators in the status bar at the bottom of the Tip Tilt GUI. These indicate that something substantial is wrong. Which indicator it is will tell you which keyword or dispatcher is in a bad state.","title":"Troubleshooting the TL:DR Procedure"},{"location":"tiptiltinstructions/#tip-tilt-system-overview","text":"The KPF tip tilt system takes fast (e.g. 100 FPS) subframe images from the KPF CRED2 guide camera in order to control the fast tip tilt mirror which directs light in to the KPF FIU. This fast tip tilt system maintains the stellar position on the science fiber. This is critical not for reasons of maximizing flux in to the spectrograph (though that is a side benefit), but to optimize the radial velocity measurement. Even after fiber scrambling and agitation, if the star\u2019s position on the fiber entrance fiber shifts, that can manifest as a small shift of the spectrum on the detector which would be interpreted as a radial velocity change. Thus we need to position the star on the fiber, and then hold it in a consistent place during observations and make that position consistent from observation to observation.","title":"Tip Tilt System Overview"},{"location":"tiptiltinstructions/#tip-tilt-loops","text":"There are several components to the tip tilt loops. Controls for toggling them on and off together and individually are provided in the Tip Tilt Control and Telemetry section of the Tip Tilt GUI. The important pieces are: Calculation : The calculations are the part of the algorithm which is examining images from the guide camera, detecting and identifying objects, and calculating the relevant tip tilt commands. This can be toggled on and off using the underlying kpfguide.TIPTILT_CALC keyword. Note that once calculations are turned on the system is attempting to cross identify stars from image to image and maintain a consistent identity. One of the things it uses to do this is knowledge of the average positions of stars in recent images. Thus, if the stars are moved dramatically (e.g. by Magiq), it may confuse the IDs. If you think this might be the case, restarting calculations will force a fresh identification phase. Control : The control component takes the output of the calculations loop and sends commands to the tip tilt mirror. As long as the motions needed are within range of the tip tilt mirror, this will close the loops and should yield a stable star position. This can be toggled on and off using the underlying kpfguide.TIPTILT_CONTROL keyword. Offload : If the motion of the star carries it toward the edfe of the tip tilt mirror's range of motion, the system will \"offload\" some of that movement to the telescope (akin to a normal guiding command). Enabling offloads allows those commands to go to the telescope. This can be toggled on and off using the underlying kpfguide.OFFLOAD keyword. The kpfguide.OFFLOAD keyword will also attempt examine the telescope control system ( dcs ) to determine if offloads should be sent. This permissive is based primarily on whether KPF is the selected instrument, if not, the instrument should not be sending offloads to the telescope. The kpfguide.OFFLOAD_DCS keyword indicated whether KPF is permitted to offload and it must be \"Yes\" in order for offloads to be enabled.","title":"Tip Tilt Loops"},{"location":"tiptiltinstructions/#tip-tilt-gui","text":"To start the GUI, open a terminal as any kpf user (e.g. kpfeng) on the kpf machine and type: TTGUI_v2 . For dark mode, add the -d option to the command. A screenshot of the Tip Tilt GUI. The Tip Tilt GUI may also be opened for observers in \"monitor\" mode, in which case none of the controls are active, but the telemetry and image display can be seen. To do this, use the TTGUI_v2 --monitor terminal command as above or select KPF Control Menu -> Subcomponents -> Start Tip Tilt GUI from the FVWM menu in a KPF VNC session.","title":"Tip Tilt GUI"},{"location":"tiptiltinstructions/#gui-layout","text":"The top section of the GUI (beneath the \"File\" and \"Troubleshooting\" menus), is a small tabbed interface with various controls and options. See the sections below on each tab. Beneath the tabbed section is a region titled \"Tip Tilt Control and Telemetry\" this section contains control for the tip tilt loops and telemetry about the tip tilt performance. See the Tip Tilt Control and Telemetry section below for details. Beneath that is a region titled \"Image Display\" which shows the latest Magiq image cropped to the region which the tip tilt system is using (a subframe of the whole field). It also contains the tool for choosing which object in the field to guide on and controls for the image display stretch and cut. See the Image Display section below for details. Beneath that is a region titled \"Instrument Status\" which contains a very brief summary of what the instrument is doing at the moment. See the Instrument Status section below for details. The very bottom of the GUI is the status bar which will be empty if everything is in a working state for observing. See the Status Bar section below for details.","title":"GUI Layout"},{"location":"tiptiltinstructions/#camera-controls-tab","text":"A screenshot of the Tip Tilt GUI's Camera Controls tab. When the observer executes an OB (which they should do during the slew, but they may forget or not be ready, so check if you are unsure), then the target star's J band magnitude will be populated in this GUI. This will also update the \"Recommended Gain & FPS\" values. If you wish to accept these recommendations, simply click the \"Set\" button. The recommendations will be color coded green if they match the current values or orange if they do not match. The pulldown to the left of the \"Set\" button will add in some amount of extinction (in magnitudes) to the estimated values. If you have clouds, you can put in some value for the extinction and the estimate will account for the clouds. The right hand section of the tab shows the current Gain & FPS values. You may set them here using the pulldown menus. You can set these values on the command line by modifying the relevant keywords: kpgduide.GAIN , and kpfguide.FPS .","title":"Camera Controls Tab"},{"location":"tiptiltinstructions/#object-detection-tab","text":"A screenshot of the Tip Tilt GUI's Object Detection tab. This is where you can set the object detection and deblending parameters discussed in the Star Detection Algorithm section below. The pulldowns will set the requested value. You can set these values on the command line by modifying the relevant keywords: kpgduide.OBJECT_INTENSITY , kpfguide.OBJECT_AREA , and kpfguide.OBJECT_DBCONT .","title":"Object Detection Tab"},{"location":"tiptiltinstructions/#offset-guiding-tab","text":"Not currently implemented.","title":"Offset Guiding Tab"},{"location":"tiptiltinstructions/#settings-tab","text":"A screenshot of the Tip Tilt GUI's Settings tab. The three options here control various settings for the kpfguide algorithms. The \"X Axis\" and \"Y Axis\" settings allow you to bypass the tip tilt mirror and control the star position only using offloads to the telescope (conceptually similar to normal Magiq guiding). These values should be \"Mirror\" unless there is a problem with the tip tilt system. The \"DAR\" setting determines whether the target pixel for the star is modified to account for differential atmospheric refraction (DAR) between the guide wavelengths (950-1200nm) and the science wavelengths (centered on 550nm). This should be set to \"Yes\" under normal observing conditions.","title":"Settings Tab"},{"location":"tiptiltinstructions/#plot-time-spans-tab","text":"A screenshot of the Tip Tilt GUI's Plot Time Spans tab. These two pulldowns allow you to change the time span of the two plots in the Tip Tilt Control and Telemetry region of the GUI. They have no effect on the tip tilt performance, only the plots.","title":"Plot Time Spans Tab"},{"location":"tiptiltinstructions/#tip-tilt-control-and-telemetry","text":"This section of the GUI is how the tip tilt loops are opened and closed. The \"Tip Tilt On/Off\" button will likely be the primary interface as it toggles all of the components off the system on and off together, but the checkboxes to the right allow each to be toggled individually. Note that the \"Offloads\" checkbox will be color coded red when kpfguide.OFFLOAD_DCS is \"No\". The \"Tip Tilt Phase\" is meant to summarise whether the system has fully controlled the star's position to the point where the observers can begin exposing. It will begin in \"Identifying\", then move to \"Acquiring\" once a star has been identified and is being moved to the target pixel, and finally reach \"Tracking\" when the star is in position. These stages are based on the position error of the star and so may not be a perfect guide, but should be useful under normal conditions. The \"Tip Tilt FPS\" value shown in the GUI is the rate at which frames are being processed by the tip tilt algorithm and should be compared to the gude camera FPS. The \"Tip Tilt FPS\" value will likely bounce around a bit, but it should stay somewhere in the range of the camera FPS (within maybe 10%). If it is much less than the camera FPS, then the tip tilt system is not keeping up with the images coming in. The GUI will color code this value with orange and red values when it deviated from the camera FPS by more than some threshold amount. The \"Tip Tilt RMS\" value shown indicates how much the stellar position varies from frame to frame. This is different than the \"Tip Tilt Error\" (used in the plot below). The RMS is a measure of the frame to frame variation while the error is the average offset between the star and the target pixel. The error should drop to <<1 pixel under good conditions as the average star position is driven to the target pixel, but as the star bounces around from frame to frame due to seeing, the RMS value will be larger than zero. Our design goal is for the RMS value to be <50 mas (<1 pixel). The \"Peak Flux\" value is the brightness (in ADU) of the brightest pixel in the star as measured by the star detection algorithm. This is a good, but imperfect indication of whether the star is saturated in the guider image. Some bad pixels are always bright and if one of them is included in the star detection then the value of that one bad pixel will affect this reading, so you should use some discretion when inspecting this value. We have plans to implement a bad pixel mask which should mitigate this, but that is not complete and will require some care to make sure it does not affect the high speed calculations in the tip tilt loops. The guide camera is 14-bit, so it saturates at a value of 16,384. We perform a bias subtraction, so in practice this value is more like 14,000 counts. Saturation is not a deal breaker for using the tip tilt system. Mild saturation of only a few pixels in the core of the star will not drastically degrade the tip tilt performance, so it is better to saturate a bit than to try to run the FPS up to extremely high values where the calculations can not keep up. The \"Total Flux\" value is the sum of all pixel values with the detected star. This is an alternate indicator of the star's brightness, but does not directly indicate whether the star saturates the camera. The \"Tip Tilt Error\" plot is the left hand plot in the GUI. This is the offset (in pixels) between the stars's average position and the target pixel. When you first turn on the loops, you should see this start at a high value (a few pixels) and drop rapidly to near 0. The \"Flux\" plot is the right hand plot in the GUI. It plots the total flux in the star over time. The behavior of this is a useful indicator of clouds.","title":"Tip Tilt Control and Telemetry"},{"location":"tiptiltinstructions/#image-display","text":"The image display section shows a cropped version of the Magiq image (cropped to the region the tip tilt algorithm is using). It is important to remember that this image is not the same as what the tip tilt system is using for its calculations! This is an average of frames over the Magiq exposure time, so you have a higher SNR in this image than you do in the individual frames going in to the tip tilt calculations. The filename displayed and the timestamp at which the file was updated are also shown near the top. Mousing over the image will read out the pixel position and value of the pixel under the cursor just below the image and next to the X and Y position of the target pixel the algorithm is trying to steer the star to (this value is updated by DAR and so will change). The image will show an overlayed circle and label with the object's name (\"OBJECT1, OBJECT2, or OBJECT3\") and the percentage value next to the label is the fraction of frames in which is object is detected. If this is much less than 100%, you should probably adjust the detection parameters or adjust the sensitivity of the guider (i.e. increase gain or lower the FPS). To the right of the image is the \"Object Choice\" box. In the case where multiple objects are detected, you will need to choose one of them to be the target. Use the pulldown to choose which one you want to drive to the target pixel. Below this is a plot showing where the tip tilt mirror is within its range. The range is indicated by the green area. Points will be drawn and fade out over time to indicate the motion of the tip tilt mirror. Finally there are two selectors for \"Image Cut\" and \"Image Scaling\", these affect the image display, so feel free to adjust as you see fit.","title":"Image Display"},{"location":"tiptiltinstructions/#instrument-status","text":"There is a small section here summarizing the instrument status. It shows whether there is a script running which is a good indicator of whether data is being taken. The \"Exposure Status\" value shows whether the detectors are exposing, reading out, etc. The \"FIU Mode\" is a good guide as to whether you should expect to be seeing light from the sky on the guider images (e.g. if it is in \"Calibration\" mode, we are taking a cal exposure and you are probably seeing cal fibers, not the sky). Finally, the \"Object\" value is the string the observer has used to name the target.","title":"Instrument Status"},{"location":"tiptiltinstructions/#status-bar","text":"The very bottom of the GUI is a status bar. It will be empty under normal operating conditions, but will contain red indicators when there is a problem that will likely halt operation of the tip tilt system. For example, in the screenshot below several errors are shown: A screenshot of the Tip Tilt GUI's Status Bar with several errors. Status bar errors which can show up include: CONTINUOUS : This indicates that the guide camera is not exposing. SAVE : This indicates that the guide camera is not saving files. TTXSRV : This indicates that the tip tilt mirror X axis is not in servo mode and thus will not correct properly. TTYSRV : This indicates that the tip tilt mirror Y axis is not in servo mode and thus will not correct properly. DAR Disabled : This indicates that the DAR is not enabled. kpfguide1 : This indicates that there is a likely problem with the kpfguide1 dispatcher and a restart is likely required. kpfguide2 : This indicates that there is a likely problem with the kpfguide2 dispatcher and a restart is likely required. kpfguide3 : This indicates that there is a likely problem with the kpfguide3 dispatcher and a restart is likely required.","title":"Status Bar"},{"location":"tiptiltinstructions/#star-detection-algorithm","text":"The kpfguide software uses Source Extractor via the SEP Python Library for star detection. The \"Detect SNR\" and \"Detect Area\" values in the GUI correspond to the thresh and minarea parameters of sep.extract and to kpfguide.OBJECT_INTENSITY and kpfguide.OBJECT_AREA keyword respectively. The way the algorithm detects stars is to look for adjacent clusters of pixels with values above \"Detect SNR\". If that cluster is larger than \"Detect Area\" pixels, then it is a star. Both parameters are critical in determining whether a star will be detected. Having a large \"Detect Area\" means that faint stars will often not have enough bright pixels to be considered a detection. Similarly, a large \"Detect SNR\" might mean that not enough pixels are bright enough so too few pixels will be detections to be considered a star. On faint targets, both parameters may need to come down if only the very core of the star has significant signal in it. If you're having trouble in good seeing, make sure that \"Detect Area\" is not too large for the seeing. Based on experience, starting with values of 5-7 for \"Detect SNR\" and 80-100 for \"Detect Area\" are reasonable.","title":"Star Detection Algorithm"},{"location":"tiptiltinstructions/#deblending-multiple-stars","text":"Deblending is a term that comes from Source Extractor. It can be both perilous and useful. Early in the system\u2019s use, we were still using the default deblending contrast of 0.005, which meant that it took only a small dip in flux (0.5%) for two adjacent maxima to be considered two different objects. In practice, this meant that a single star would deblend in to multiple stars due to speckles moving about. As a result, the \u201cstar\u201d would appear to shift to one side or the other leading to sudden large corrections which would then be reversed a frame or two later when the speckles had shifted and the star was no longer deblended. This could affect several percent of all guide frames (in other words, the star was being jolted around by spurious detections several times per second). Of course, in situation where there are actually blended stars this is a useful tool. Double stars can be separated and a particular guide target chosen using this system. Based on our experience so far, leaving deblending contrast at 1.0 for most targets is the right choice. This demands that the valley between adjacent peaks be as deep as the highest peak (i.e. it goes to 0), so it turns deblending off. Since most targets are isolated stars with no close neighbors of similar brightness, this avoids the problem of tracking on speckles. If a double star is the target, decreasing the deblending contrast until it is reliably separates is the best strategy. Use the overlays in the image display to ensure that the target star has its own label and that label is centered properly on the star. If the label is not centered on the star, it might be blended with the companion which is puslling the \"center\" off toward the companion -- this is what we mean by blended stars. If the stars are blended, they must be deblended for KPF to accurately place one properly on the fiber. If the centroid is biased because the stars are not deblended you will end up with an RV effect due to the positioning of the star on the fiber being incorrect. The deblend contrast can be run down at 0.005 or lower to pull out a faint companion. Note that this is the contrast between the bright star and the faint \"gap\" between companions, so large contrast is not unexpected if the companion star is a few magnitudes fainter than the primary. For example, if the deblend contrast is 0.01 that is 5 magnitudes of contrast 2.5*log(0.01) , but that's not an unreasonable contrast for the gap if the companion star is just 2 or 3 magnitudes fainter than the primary. Also, because the algorithm is doing deblending, not trying to detect the companion as a separate object, we don't need to worry about the primary being too bright -- it is ok to saturate the primary to get the companion. Of course, a widely separated double star may be seen as two stars by the system if there is a \u201cgap\u201d between the two stars where the signal in the pixels is lower than the detection threshold. In this case, no deblending is necessary. Finally, if the star the observers are trying to acquire is too challenging and you are unable to make it work, you can ask the observer to click the \"Collect Guider Image Cube\" button on their OB GUI. This will save a brief sequence of guider images which can be analyzed offline to find out the best way to acquire that particular star (email the KPF SA to let them know to look at it). This does not help for the immediate observation, but will allow us to find the right solution for the next time this target or a similar one is observed.","title":"Deblending Multiple Stars"},{"location":"scripts/AnalyzeGridSearch/","text":"AnalyzeGridSearch Bases: KPFTranslatorFunction Description Tool to analyze engineering data taken by the engineering.GridSearch or engineering.Run2DGridSearch scripts. Parameters None Source code in kpf/engineering/analysis/AnalyzeGridSearch.py 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 class AnalyzeGridSearch ( KPFTranslatorFunction ): '''# Description Tool to analyze engineering data taken by the `engineering.GridSearch` or `engineering.Run2DGridSearch` scripts. # Parameters None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): for logfile in args . get ( 'logfile' ): analyze_grid_search ( logfile , fiber = args . get ( 'fiber' ), model_seeing = args . get ( 'seeing' ), xfit = args . get ( 'xfit' ), yfit = args . get ( 'yfit' ), generate_cred2 = args . get ( 'cred2' ), ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'logfile' , type = str , nargs = '*' , help = \"The logfile or files of the grid search runs to analyze\" ) ## add flags parser . add_argument ( \"--cred2\" , dest = \"cred2\" , default = False , action = \"store_true\" , help = \"Generate CRED2 plots? (default = False)\" ) ## add options parser . add_argument ( \"--fiber\" , dest = \"fiber\" , type = str , default = 'Science' , help = \"The fiber being examined (Science, Sky, or EMSky).\" ) parser . add_argument ( \"--seeing\" , dest = \"seeing\" , type = str , choices = [ '0.5' , '0.7' , '0.9' ], default = '0.7' , help = \"The seeing model to overlay on the fiber coupling plot.\" ) parser . add_argument ( \"--xfit\" , dest = \"xfit\" , type = float , default = 335.5 , help = \"The X pixel position to use as the center when overlaying the model.\" ) parser . add_argument ( \"--yfit\" , dest = \"yfit\" , type = float , default = 258 , help = \"The X pixel position to use as the center when overlaying the model.\" ) return super () . add_cmdline_args ( parser , cfg )","title":"AnalyzeGridSearch"},{"location":"scripts/AnalyzeGridSearch/#analyzegridsearch","text":"Bases: KPFTranslatorFunction","title":"AnalyzeGridSearch"},{"location":"scripts/AnalyzeGridSearch/#kpf.engineering.analysis.AnalyzeGridSearch.AnalyzeGridSearch--description","text":"Tool to analyze engineering data taken by the engineering.GridSearch or engineering.Run2DGridSearch scripts.","title":"Description"},{"location":"scripts/AnalyzeGridSearch/#kpf.engineering.analysis.AnalyzeGridSearch.AnalyzeGridSearch--parameters","text":"None Source code in kpf/engineering/analysis/AnalyzeGridSearch.py 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 class AnalyzeGridSearch ( KPFTranslatorFunction ): '''# Description Tool to analyze engineering data taken by the `engineering.GridSearch` or `engineering.Run2DGridSearch` scripts. # Parameters None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): for logfile in args . get ( 'logfile' ): analyze_grid_search ( logfile , fiber = args . get ( 'fiber' ), model_seeing = args . get ( 'seeing' ), xfit = args . get ( 'xfit' ), yfit = args . get ( 'yfit' ), generate_cred2 = args . get ( 'cred2' ), ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'logfile' , type = str , nargs = '*' , help = \"The logfile or files of the grid search runs to analyze\" ) ## add flags parser . add_argument ( \"--cred2\" , dest = \"cred2\" , default = False , action = \"store_true\" , help = \"Generate CRED2 plots? (default = False)\" ) ## add options parser . add_argument ( \"--fiber\" , dest = \"fiber\" , type = str , default = 'Science' , help = \"The fiber being examined (Science, Sky, or EMSky).\" ) parser . add_argument ( \"--seeing\" , dest = \"seeing\" , type = str , choices = [ '0.5' , '0.7' , '0.9' ], default = '0.7' , help = \"The seeing model to overlay on the fiber coupling plot.\" ) parser . add_argument ( \"--xfit\" , dest = \"xfit\" , type = float , default = 335.5 , help = \"The X pixel position to use as the center when overlaying the model.\" ) parser . add_argument ( \"--yfit\" , dest = \"yfit\" , type = float , default = 258 , help = \"The X pixel position to use as the center when overlaying the model.\" ) return super () . add_cmdline_args ( parser , cfg )","title":"Parameters"},{"location":"scripts/AnalyzeTipTiltPerformance/","text":"AnalyzeTipTiltPerformance Bases: KPFTranslatorFunction Description Generates a plot analyzing tip tilt performance for a single observation. Can take as input either an L0 file, in which case it will strip out the guider extension for use, or a guider \"cube\" file. Parameters None Source code in kpf/engineering/analysis/AnalyzeTipTiltPerformance.py 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 class AnalyzeTipTiltPerformance ( KPFTranslatorFunction ): '''# Description Generates a plot analyzing tip tilt performance for a single observation. Can take as input either an L0 file, in which case it will strip out the guider extension for use, or a guider \"cube\" file. # Parameters None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): viewer_command = find_viewer_command ( args ) for file in args . get ( 'files' ): file = Path ( file ) . expanduser () if file . exists () is False : log . error ( f \"Could not find file { args . get ( 'file' ) } \" ) plotfile = Path ( str ( file . name ) . replace ( '.fits' , '.png' )) plot_tiptilt_stats ( file , plotfile = plotfile , start = args . get ( 'start' , None ), end = args . get ( 'end' , None ), snr = args . get ( 'snr' , None ), minarea = args . get ( 'minarea' , None ), deblend_nthresh = args . get ( 'deblend_nthresh' , None ), deblend_cont = args . get ( 'deblend_cont' , None ), ) if viewer_command is not None : log . info ( f \"Opening { plotfile } using { viewer_command } \" ) proc = subprocess . Popen ([ viewer_command , f \" { plotfile } \" ]) if args . get ( 'gif' ) is True : giffile = Path ( str ( file . name ) . replace ( '.fits' , '.gif' )) generate_cube_gif ( file , giffile ) if viewer_command is not None : log . info ( f \"Opening { giffile } using { viewer_command } \" ) proc = subprocess . Popen ([ viewer_command , f \" { giffile } \" ]) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'files' , type = str , nargs = '*' , help = \"The FITS files to analyze\" ) parser . add_argument ( \"-g\" , \"--gif\" , dest = \"gif\" , default = False , action = \"store_true\" , help = \"Generate the animated GIF of frames (computationally expensive)\" ) parser . add_argument ( \"--view\" , dest = \"view\" , default = False , action = \"store_true\" , help = \"Open a viewer once the file is generated\" ) parser . add_argument ( \"--start\" , dest = \"start\" , type = float , help = \"Zoom the plot in to this start time (in seconds).\" ) parser . add_argument ( \"--end\" , dest = \"end\" , type = float , help = \"Zoom the plot in to this end time (in seconds).\" ) parser . add_argument ( \"--snr\" , dest = \"snr\" , type = float , help = \"Run source extractor again with this SNR threshold\" ) parser . add_argument ( \"--minarea\" , dest = \"minarea\" , type = float , help = \"Run source extractor again with this minarea parameter\" ) parser . add_argument ( \"--deblend_nthresh\" , dest = \"deblend_nthresh\" , type = float , help = \"Run source extractor again with this deblend_nthresh\" ) parser . add_argument ( \"--deblend_cont\" , dest = \"deblend_cont\" , type = float , help = \"Run source extractor again with this deblend_cont parameter\" ) return super () . add_cmdline_args ( parser , cfg )","title":"AnalyzeTipTiltPerformance"},{"location":"scripts/AnalyzeTipTiltPerformance/#analyzetiptiltperformance","text":"Bases: KPFTranslatorFunction","title":"AnalyzeTipTiltPerformance"},{"location":"scripts/AnalyzeTipTiltPerformance/#kpf.engineering.analysis.AnalyzeTipTiltPerformance.AnalyzeTipTiltPerformance--description","text":"Generates a plot analyzing tip tilt performance for a single observation. Can take as input either an L0 file, in which case it will strip out the guider extension for use, or a guider \"cube\" file.","title":"Description"},{"location":"scripts/AnalyzeTipTiltPerformance/#kpf.engineering.analysis.AnalyzeTipTiltPerformance.AnalyzeTipTiltPerformance--parameters","text":"None Source code in kpf/engineering/analysis/AnalyzeTipTiltPerformance.py 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 class AnalyzeTipTiltPerformance ( KPFTranslatorFunction ): '''# Description Generates a plot analyzing tip tilt performance for a single observation. Can take as input either an L0 file, in which case it will strip out the guider extension for use, or a guider \"cube\" file. # Parameters None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): viewer_command = find_viewer_command ( args ) for file in args . get ( 'files' ): file = Path ( file ) . expanduser () if file . exists () is False : log . error ( f \"Could not find file { args . get ( 'file' ) } \" ) plotfile = Path ( str ( file . name ) . replace ( '.fits' , '.png' )) plot_tiptilt_stats ( file , plotfile = plotfile , start = args . get ( 'start' , None ), end = args . get ( 'end' , None ), snr = args . get ( 'snr' , None ), minarea = args . get ( 'minarea' , None ), deblend_nthresh = args . get ( 'deblend_nthresh' , None ), deblend_cont = args . get ( 'deblend_cont' , None ), ) if viewer_command is not None : log . info ( f \"Opening { plotfile } using { viewer_command } \" ) proc = subprocess . Popen ([ viewer_command , f \" { plotfile } \" ]) if args . get ( 'gif' ) is True : giffile = Path ( str ( file . name ) . replace ( '.fits' , '.gif' )) generate_cube_gif ( file , giffile ) if viewer_command is not None : log . info ( f \"Opening { giffile } using { viewer_command } \" ) proc = subprocess . Popen ([ viewer_command , f \" { giffile } \" ]) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'files' , type = str , nargs = '*' , help = \"The FITS files to analyze\" ) parser . add_argument ( \"-g\" , \"--gif\" , dest = \"gif\" , default = False , action = \"store_true\" , help = \"Generate the animated GIF of frames (computationally expensive)\" ) parser . add_argument ( \"--view\" , dest = \"view\" , default = False , action = \"store_true\" , help = \"Open a viewer once the file is generated\" ) parser . add_argument ( \"--start\" , dest = \"start\" , type = float , help = \"Zoom the plot in to this start time (in seconds).\" ) parser . add_argument ( \"--end\" , dest = \"end\" , type = float , help = \"Zoom the plot in to this end time (in seconds).\" ) parser . add_argument ( \"--snr\" , dest = \"snr\" , type = float , help = \"Run source extractor again with this SNR threshold\" ) parser . add_argument ( \"--minarea\" , dest = \"minarea\" , type = float , help = \"Run source extractor again with this minarea parameter\" ) parser . add_argument ( \"--deblend_nthresh\" , dest = \"deblend_nthresh\" , type = float , help = \"Run source extractor again with this deblend_nthresh\" ) parser . add_argument ( \"--deblend_cont\" , dest = \"deblend_cont\" , type = float , help = \"Run source extractor again with this deblend_cont parameter\" ) return super () . add_cmdline_args ( parser , cfg )","title":"Parameters"},{"location":"scripts/BuildMasterBias/","text":"BuildMasterBias Bases: KPFTranslatorFunction Combine a set of bias files to make a master bias. Parameters: files ( list ) \u2013 A list of files to combine. output ( str ) \u2013 The output combined filename to write. KTL Keywords Used: kpf_expmeter.BIAS_FILE Source code in kpf/expmeter/BuildMasterBias.py 22 23 24 25 26 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 class BuildMasterBias ( KPFTranslatorFunction ): '''Combine a set of bias files to make a master bias. Args: files (list): A list of files to combine. output (str): The output combined filename to write. KTL Keywords Used: - `kpf_expmeter.BIAS_FILE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'files' , allowed_types = [ list ]) @classmethod def perform ( cls , args , logger , cfg ): biasfiles = [ Path ( biasfile ) for biasfile in args . get ( 'files' )] log . debug ( f \"Combining { len ( biasfiles ) } bias frames:\" ) biases = [] timestamps = [] for biasfile in biasfiles : log . debug ( f \" { biasfile . name } \" ) this_bias = CCDData . read ( biasfile , unit = \"adu\" ) biases . append ( this_bias ) timestamps . append ( this_bias [ 0 ] . header . get ( 'DATE-BEG' )) combiner = ccdproc . Combiner ( biases ) combiner . sigma_clipping ( low_thresh = 5 , high_thresh = 5 ) combined_average = combiner . average_combine () for i , timestamp in enumerate ( timestamps ): combined_average [ 0 ] . header [ f 'DATEBEG { i : 02d } ' ] = ( timestamp , 'DATE-BEG of file {i:02d} ' ) utnow = datetime . utcnow () combined_average [ 0 ] . header [ 'DATEMADE' ] = ( utnow . isoformat (), 'UT timestamp of file creation' ) if args . get ( 'output' , None ) not in [ None , '' ]: outputfile = Path ( args . get ( 'output' )) . expanduser () else : match_fn = re . match ( '([\\w\\d_]+)(\\d {6} )\\.(\\d {3} )\\.fits' , biasfiles [ 0 ] . name ) if match_fn is not None : frameno = match_fn . group ( 2 ) outputfile = Path ( f '/s/sdata1701/ExpMeterMasterFiles/MasterBias_ { frameno } .fits' ) else : now_str = utnow . strftime ( '%Y%m %d at%H%M%S' ) outputfile = Path ( f '/s/sdata1701/ExpMeterMasterFiles/MasterBias_ { now_str } .fits' ) log . info ( f \"Writing { outputfile } \" ) combined_average . write ( outputfile , overwrite = True ) if args . get ( 'update' , False ) is True : bias_file = ktl . cache ( 'kpf_expmeter' , 'BIAS_FILE' ) bias_file . write ( f \" { outputfile } \" ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'files' , nargs = '*' , help = \"The files to combine\" ) parser . add_argument ( \"--output\" , dest = \"output\" , type = str , default = '' , help = \"The output combined bias file.\" ) parser . add_argument ( \"--update\" , dest = \"update\" , default = False , action = \"store_true\" , help = \"Update the bias file in use with the newly generated file?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"BuildMasterBias"},{"location":"scripts/BuildMasterBias/#buildmasterbias","text":"Bases: KPFTranslatorFunction Combine a set of bias files to make a master bias. Parameters: files ( list ) \u2013 A list of files to combine. output ( str ) \u2013 The output combined filename to write. KTL Keywords Used: kpf_expmeter.BIAS_FILE Source code in kpf/expmeter/BuildMasterBias.py 22 23 24 25 26 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 class BuildMasterBias ( KPFTranslatorFunction ): '''Combine a set of bias files to make a master bias. Args: files (list): A list of files to combine. output (str): The output combined filename to write. KTL Keywords Used: - `kpf_expmeter.BIAS_FILE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'files' , allowed_types = [ list ]) @classmethod def perform ( cls , args , logger , cfg ): biasfiles = [ Path ( biasfile ) for biasfile in args . get ( 'files' )] log . debug ( f \"Combining { len ( biasfiles ) } bias frames:\" ) biases = [] timestamps = [] for biasfile in biasfiles : log . debug ( f \" { biasfile . name } \" ) this_bias = CCDData . read ( biasfile , unit = \"adu\" ) biases . append ( this_bias ) timestamps . append ( this_bias [ 0 ] . header . get ( 'DATE-BEG' )) combiner = ccdproc . Combiner ( biases ) combiner . sigma_clipping ( low_thresh = 5 , high_thresh = 5 ) combined_average = combiner . average_combine () for i , timestamp in enumerate ( timestamps ): combined_average [ 0 ] . header [ f 'DATEBEG { i : 02d } ' ] = ( timestamp , 'DATE-BEG of file {i:02d} ' ) utnow = datetime . utcnow () combined_average [ 0 ] . header [ 'DATEMADE' ] = ( utnow . isoformat (), 'UT timestamp of file creation' ) if args . get ( 'output' , None ) not in [ None , '' ]: outputfile = Path ( args . get ( 'output' )) . expanduser () else : match_fn = re . match ( '([\\w\\d_]+)(\\d {6} )\\.(\\d {3} )\\.fits' , biasfiles [ 0 ] . name ) if match_fn is not None : frameno = match_fn . group ( 2 ) outputfile = Path ( f '/s/sdata1701/ExpMeterMasterFiles/MasterBias_ { frameno } .fits' ) else : now_str = utnow . strftime ( '%Y%m %d at%H%M%S' ) outputfile = Path ( f '/s/sdata1701/ExpMeterMasterFiles/MasterBias_ { now_str } .fits' ) log . info ( f \"Writing { outputfile } \" ) combined_average . write ( outputfile , overwrite = True ) if args . get ( 'update' , False ) is True : bias_file = ktl . cache ( 'kpf_expmeter' , 'BIAS_FILE' ) bias_file . write ( f \" { outputfile } \" ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'files' , nargs = '*' , help = \"The files to combine\" ) parser . add_argument ( \"--output\" , dest = \"output\" , type = str , default = '' , help = \"The output combined bias file.\" ) parser . add_argument ( \"--update\" , dest = \"update\" , default = False , action = \"store_true\" , help = \"Update the bias file in use with the newly generated file?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"BuildMasterBias"},{"location":"scripts/BuildOBfromQuery/","text":"BuildOBfromQuery Bases: KPFTranslatorFunction Source code in kpf/utils/BuildOBfromQuery.py 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 class BuildOBfromQuery ( KPFTranslatorFunction ): ''' ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'GaiaID' ) @classmethod def perform ( cls , args , logger , cfg ): gaiaid = args . get ( 'GaiaID' ) observation = { 'ExpMeterMode' : \"monitor\" , 'AutoExpMeter' : \"False\" , 'TakeSimulCal' : \"True\" } OB = ScienceOB ({ 'GaiaID' : f \"DR3 { gaiaid } \" , 'SEQ_Observations' : [ observation ]}) # Get target name and 2MASS ID from Gaia ID names = get_names_from_gaiaid ( gaiaid ) if names is None : log . warning ( f \"Query for { gaiaid } failed to return names\" ) return OB . set ( 'TargetName' , f \" { names [ 'TargetName' ] } \" ) OB . set ( '2MASSID' , f \" { names [ '2MASSID' ] } \" ) # Using 2MASS ID query for Jmag twomass_params = get_Jmag ( names [ '2MASSID' ]) OB . set ( 'Jmag' , f \" { twomass_params [ 'Jmag' ] } \" ) # Using Gaia ID, query for Gaia parameters gaia_params = get_gaia_parameters ( gaiaid ) OB . set ( 'Parallax' , f \" { gaia_params [ 'Parallax' ] } \" ) OB . set ( 'RadialVelocity' , f \" { gaia_params [ 'RadialVelocity' ] } \" ) OB . set ( 'Gmag' , f \" { gaia_params [ 'Gmag' ] } \" ) OB . set ( 'Teff' , f \" { gaia_params [ 'Teff' ] } \" ) # Defaults OB . set ( 'GuideMode' , \"auto\" ) OB . set ( 'TriggerCaHK' , \"True\" ) OB . set ( 'TriggerGreen' , \"True\" ) OB . set ( 'TriggerRed' , \"True\" ) # Build Starlist line OB . star_list_line = form_starlist_line ( names [ 'TargetName' ], gaia_params [ 'RA_ICRS' ], gaia_params [ 'DE_ICRS' ], vmag = gaia_params [ 'Gmag' ]) print ( OB ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'GaiaID' , type = str , help = 'Gaia DR3 ID to query for (e.g. \"35227046884571776\")' ) return super () . add_cmdline_args ( parser , cfg )","title":"BuildOBfromQuery"},{"location":"scripts/BuildOBfromQuery/#buildobfromquery","text":"Bases: KPFTranslatorFunction Source code in kpf/utils/BuildOBfromQuery.py 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 class BuildOBfromQuery ( KPFTranslatorFunction ): ''' ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'GaiaID' ) @classmethod def perform ( cls , args , logger , cfg ): gaiaid = args . get ( 'GaiaID' ) observation = { 'ExpMeterMode' : \"monitor\" , 'AutoExpMeter' : \"False\" , 'TakeSimulCal' : \"True\" } OB = ScienceOB ({ 'GaiaID' : f \"DR3 { gaiaid } \" , 'SEQ_Observations' : [ observation ]}) # Get target name and 2MASS ID from Gaia ID names = get_names_from_gaiaid ( gaiaid ) if names is None : log . warning ( f \"Query for { gaiaid } failed to return names\" ) return OB . set ( 'TargetName' , f \" { names [ 'TargetName' ] } \" ) OB . set ( '2MASSID' , f \" { names [ '2MASSID' ] } \" ) # Using 2MASS ID query for Jmag twomass_params = get_Jmag ( names [ '2MASSID' ]) OB . set ( 'Jmag' , f \" { twomass_params [ 'Jmag' ] } \" ) # Using Gaia ID, query for Gaia parameters gaia_params = get_gaia_parameters ( gaiaid ) OB . set ( 'Parallax' , f \" { gaia_params [ 'Parallax' ] } \" ) OB . set ( 'RadialVelocity' , f \" { gaia_params [ 'RadialVelocity' ] } \" ) OB . set ( 'Gmag' , f \" { gaia_params [ 'Gmag' ] } \" ) OB . set ( 'Teff' , f \" { gaia_params [ 'Teff' ] } \" ) # Defaults OB . set ( 'GuideMode' , \"auto\" ) OB . set ( 'TriggerCaHK' , \"True\" ) OB . set ( 'TriggerGreen' , \"True\" ) OB . set ( 'TriggerRed' , \"True\" ) # Build Starlist line OB . star_list_line = form_starlist_line ( names [ 'TargetName' ], gaia_params [ 'RA_ICRS' ], gaia_params [ 'DE_ICRS' ], vmag = gaia_params [ 'Gmag' ]) print ( OB ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'GaiaID' , type = str , help = 'Gaia DR3 ID to query for (e.g. \"35227046884571776\")' ) return super () . add_cmdline_args ( parser , cfg )","title":"BuildOBfromQuery"},{"location":"scripts/CalLampPower/","text":"CalLampPower Bases: KPFTranslatorFunction Powers off one of the cal lamps via the kpflamps keyword service. Uses the lamp names from the OCTAGON when appropriate. Parameters: lamp ( str ) \u2013 Name of the lamp to control. Allowed Values: BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, WideFlat, ExpMeterLED, CaHKLED, SciLED, SkyLED power ( str ) \u2013 Destination state for lamp power. Allowed Values: \"on\" or \"off\". KTL Keywords Used: kpflamps.BRDBANDFIBER kpflamps.U_GOLD kpflamps.U_DAILY kpflamps.TH_DAILY kpflamps.TH_GOLD kpflamps.FF_FIBER kpflamps.EXPMLED kpflamps.HKLED kpflamps.SCILED kpflamps.SKYLED Source code in kpf/calbench/CalLampPower.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class CalLampPower ( KPFTranslatorFunction ): '''Powers off one of the cal lamps via the `kpflamps` keyword service. Uses the lamp names from the OCTAGON when appropriate. Args: lamp (str): Name of the lamp to control. Allowed Values: BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, WideFlat, ExpMeterLED, CaHKLED, SciLED, SkyLED power (str): Destination state for lamp power. Allowed Values: \"on\" or \"off\". KTL Keywords Used: - `kpflamps.BRDBANDFIBER` - `kpflamps.U_GOLD` - `kpflamps.U_DAILY` - `kpflamps.TH_DAILY` - `kpflamps.TH_GOLD` - `kpflamps.FF_FIBER` - `kpflamps.EXPMLED` - `kpflamps.HKLED` - `kpflamps.SCILED` - `kpflamps.SKYLED` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): # Check lamp name lamp = standardize_lamp_name ( args . get ( 'lamp' , None )) if lamp is None : msg = f \"Could not standardize lamp name { args . get ( 'lamp' ) } \" raise FailedPreCondition ( msg ) # Check power check_input ( args , 'power' , allowed_values = [ 'on' , 'off' ]) @classmethod def perform ( cls , args , logger , cfg ): lamp = standardize_lamp_name ( args . get ( 'lamp' )) pwr = args . get ( 'power' ) log . debug ( f \"Turning { pwr } { lamp } \" ) kpflamps = ktl . cache ( 'kpflamps' ) kpflamps [ lamp ] . write ( pwr ) @classmethod def post_condition ( cls , args , logger , cfg ): lamp = standardize_lamp_name ( args . get ( 'lamp' )) pwr = args . get ( 'power' ) timeout = cfg . getfloat ( 'times' , 'lamp_timeout' , fallback = 1 ) success = ktl . waitFor ( f \"($kpflamps. { lamp } == { pwr } )\" , timeout = timeout ) if success is not True : kpflamps = ktl . cache ( 'kpflamps' ) raise FailedPostCondition ( kpflamps [ lamp ], pwr ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'lamp' , type = str , choices = [ 'BrdbandFiber' , 'U_gold' , 'U_daily' , 'Th_daily' , 'Th_gold' , 'WideFlat' , 'ExpMeterLED' , 'CaHKLED' , 'SciLED' , 'SkyLED' ], help = 'Which lamp to control?' ) parser . add_argument ( 'power' , type = str , choices = [ 'on' , 'off' ], help = 'Desired power state: \"on\" or \"off\"' ) return super () . add_cmdline_args ( parser , cfg )","title":"CalLampPower"},{"location":"scripts/CalLampPower/#callamppower","text":"Bases: KPFTranslatorFunction Powers off one of the cal lamps via the kpflamps keyword service. Uses the lamp names from the OCTAGON when appropriate. Parameters: lamp ( str ) \u2013 Name of the lamp to control. Allowed Values: BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, WideFlat, ExpMeterLED, CaHKLED, SciLED, SkyLED power ( str ) \u2013 Destination state for lamp power. Allowed Values: \"on\" or \"off\". KTL Keywords Used: kpflamps.BRDBANDFIBER kpflamps.U_GOLD kpflamps.U_DAILY kpflamps.TH_DAILY kpflamps.TH_GOLD kpflamps.FF_FIBER kpflamps.EXPMLED kpflamps.HKLED kpflamps.SCILED kpflamps.SKYLED Source code in kpf/calbench/CalLampPower.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class CalLampPower ( KPFTranslatorFunction ): '''Powers off one of the cal lamps via the `kpflamps` keyword service. Uses the lamp names from the OCTAGON when appropriate. Args: lamp (str): Name of the lamp to control. Allowed Values: BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, WideFlat, ExpMeterLED, CaHKLED, SciLED, SkyLED power (str): Destination state for lamp power. Allowed Values: \"on\" or \"off\". KTL Keywords Used: - `kpflamps.BRDBANDFIBER` - `kpflamps.U_GOLD` - `kpflamps.U_DAILY` - `kpflamps.TH_DAILY` - `kpflamps.TH_GOLD` - `kpflamps.FF_FIBER` - `kpflamps.EXPMLED` - `kpflamps.HKLED` - `kpflamps.SCILED` - `kpflamps.SKYLED` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): # Check lamp name lamp = standardize_lamp_name ( args . get ( 'lamp' , None )) if lamp is None : msg = f \"Could not standardize lamp name { args . get ( 'lamp' ) } \" raise FailedPreCondition ( msg ) # Check power check_input ( args , 'power' , allowed_values = [ 'on' , 'off' ]) @classmethod def perform ( cls , args , logger , cfg ): lamp = standardize_lamp_name ( args . get ( 'lamp' )) pwr = args . get ( 'power' ) log . debug ( f \"Turning { pwr } { lamp } \" ) kpflamps = ktl . cache ( 'kpflamps' ) kpflamps [ lamp ] . write ( pwr ) @classmethod def post_condition ( cls , args , logger , cfg ): lamp = standardize_lamp_name ( args . get ( 'lamp' )) pwr = args . get ( 'power' ) timeout = cfg . getfloat ( 'times' , 'lamp_timeout' , fallback = 1 ) success = ktl . waitFor ( f \"($kpflamps. { lamp } == { pwr } )\" , timeout = timeout ) if success is not True : kpflamps = ktl . cache ( 'kpflamps' ) raise FailedPostCondition ( kpflamps [ lamp ], pwr ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'lamp' , type = str , choices = [ 'BrdbandFiber' , 'U_gold' , 'U_daily' , 'Th_daily' , 'Th_gold' , 'WideFlat' , 'ExpMeterLED' , 'CaHKLED' , 'SciLED' , 'SkyLED' ], help = 'Which lamp to control?' ) parser . add_argument ( 'power' , type = str , choices = [ 'on' , 'off' ], help = 'Desired power state: \"on\" or \"off\"' ) return super () . add_cmdline_args ( parser , cfg )","title":"CalLampPower"},{"location":"scripts/CalculateDAR/","text":"CalculateDAR Bases: KPFTranslatorFunction Return the DAR correction in arcseconds between the CRED2 wavelength and the science wavelength. Calculation from Filippenko 1982 (PASP, 94:715-721, August 1982) ARGS: :EL: float Elevation of the telescope. Source code in kpf/utils/CalculateDAR.py 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 class CalculateDAR ( KPFTranslatorFunction ): '''Return the DAR correction in arcseconds between the CRED2 wavelength and the science wavelength. Calculation from Filippenko 1982 (PASP, 94:715-721, August 1982) ARGS: ===== :EL: `float` Elevation of the telescope. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): dcs = ktl . cache ( 'dcs1' ) EL = dcs [ 'EL' ] . read ( binary = True ) * 180 / np . pi DARarcsec = calculate_DAR_arcsec ( EL ) log . info ( f \"Calculated DAR for { EL : .1f } EL = { DARarcsec : .3f } arcsec\" ) dx , dy = calculate_DAR_pix ( DARarcsec ) log . info ( f \"Pixel shift is { dx : .1f } , { dy : .1f } = { ( dx ** 2 + dy ** 2 ) ** 0.5 : .1f } \" ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"CalculateDAR"},{"location":"scripts/CalculateDAR/#calculatedar","text":"Bases: KPFTranslatorFunction Return the DAR correction in arcseconds between the CRED2 wavelength and the science wavelength. Calculation from Filippenko 1982 (PASP, 94:715-721, August 1982)","title":"CalculateDAR"},{"location":"scripts/CalculateDAR/#kpf.utils.CalculateDAR.CalculateDAR--args","text":":EL: float Elevation of the telescope. Source code in kpf/utils/CalculateDAR.py 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 class CalculateDAR ( KPFTranslatorFunction ): '''Return the DAR correction in arcseconds between the CRED2 wavelength and the science wavelength. Calculation from Filippenko 1982 (PASP, 94:715-721, August 1982) ARGS: ===== :EL: `float` Elevation of the telescope. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): dcs = ktl . cache ( 'dcs1' ) EL = dcs [ 'EL' ] . read ( binary = True ) * 180 / np . pi DARarcsec = calculate_DAR_arcsec ( EL ) log . info ( f \"Calculated DAR for { EL : .1f } EL = { DARarcsec : .3f } arcsec\" ) dx , dy = calculate_DAR_pix ( DARarcsec ) log . info ( f \"Pixel shift is { dx : .1f } , { dy : .1f } = { ( dx ** 2 + dy ** 2 ) ** 0.5 : .1f } \" ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"ARGS:"},{"location":"scripts/CheckDewarWeights/","text":"CheckDewarWeights Bases: KPFTranslatorFunction Check the weight of the red and green dewars and send email if they are lower than expected. ARGS: :dewar: str Which dewar to check? red or green :email: bool If True, send email if dewar weight is low Source code in kpf/utils/CheckDewarWeights.py 18 19 20 21 22 23 24 25 26 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 class CheckDewarWeights ( KPFTranslatorFunction ): '''Check the weight of the red and green dewars and send email if they are lower than expected. ARGS: ===== :dewar: `str` Which dewar to check? red or green :email: `bool` If True, send email if dewar weight is low ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): dewar = args . get ( 'dewar' , 'green' ) fill_time = cfg . getint ( 'LN2' , 'fill_time' , fallback = 21 ) low_weight = cfg . getint ( 'LN2' , f 'low_weight_ { dewar } ' , fallback = 90 ) use_rate = cfg . getint ( 'LN2' , f 'use_rate_ { dewar } ' , fallback = 40 ) utcnow = datetime . utcnow () if utcnow . hour < fill_time : time_until_fill = fill_time - ( utcnow . hour + utcnow . minute / 60 ) else : time_until_fill = fill_time + 24 - ( utcnow . hour + utcnow . minute / 60 ) kpffill = ktl . cache ( 'kpffill' ) weight = kpffill [ f ' { dewar } WEIGHT' ] . read ( binary = True ) weight_at_fill = weight - ( time_until_fill / 24 ) * use_rate if weight_at_fill > low_weight : # Dewar fill level is ok print ( 'Dewar weight is OK' ) else : # Dewar fill level is not ok print ( 'Dewar weight is low!' ) if args . get ( 'email' , False ) is True : try : msg = [ f 'KPF { dewar } dewar weight is low' , f '' , f 'Current dewar weight: { weight : .1f } ' , f 'Estimated weight at 11am fill: { weight_at_fill : .1f } ' , ] SendEmail . execute ({ 'Subject' : f 'KPF { dewar } dewar weight is low' , 'Message' : ' \\n ' . join ( msg )}) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'dewar' , type = str , choices = [ 'green' , 'red' ], default = 'green' , help = 'Which dewar to check? red or green' ) parser . add_argument ( '--email' , dest = \"email\" , default = False , action = \"store_true\" , help = 'Send email if dewar weight is low' ) return super () . add_cmdline_args ( parser , cfg )","title":"CheckDewarWeights"},{"location":"scripts/CheckDewarWeights/#checkdewarweights","text":"Bases: KPFTranslatorFunction Check the weight of the red and green dewars and send email if they are lower than expected.","title":"CheckDewarWeights"},{"location":"scripts/CheckDewarWeights/#kpf.utils.CheckDewarWeights.CheckDewarWeights--args","text":":dewar: str Which dewar to check? red or green :email: bool If True, send email if dewar weight is low Source code in kpf/utils/CheckDewarWeights.py 18 19 20 21 22 23 24 25 26 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 class CheckDewarWeights ( KPFTranslatorFunction ): '''Check the weight of the red and green dewars and send email if they are lower than expected. ARGS: ===== :dewar: `str` Which dewar to check? red or green :email: `bool` If True, send email if dewar weight is low ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): dewar = args . get ( 'dewar' , 'green' ) fill_time = cfg . getint ( 'LN2' , 'fill_time' , fallback = 21 ) low_weight = cfg . getint ( 'LN2' , f 'low_weight_ { dewar } ' , fallback = 90 ) use_rate = cfg . getint ( 'LN2' , f 'use_rate_ { dewar } ' , fallback = 40 ) utcnow = datetime . utcnow () if utcnow . hour < fill_time : time_until_fill = fill_time - ( utcnow . hour + utcnow . minute / 60 ) else : time_until_fill = fill_time + 24 - ( utcnow . hour + utcnow . minute / 60 ) kpffill = ktl . cache ( 'kpffill' ) weight = kpffill [ f ' { dewar } WEIGHT' ] . read ( binary = True ) weight_at_fill = weight - ( time_until_fill / 24 ) * use_rate if weight_at_fill > low_weight : # Dewar fill level is ok print ( 'Dewar weight is OK' ) else : # Dewar fill level is not ok print ( 'Dewar weight is low!' ) if args . get ( 'email' , False ) is True : try : msg = [ f 'KPF { dewar } dewar weight is low' , f '' , f 'Current dewar weight: { weight : .1f } ' , f 'Estimated weight at 11am fill: { weight_at_fill : .1f } ' , ] SendEmail . execute ({ 'Subject' : f 'KPF { dewar } dewar weight is low' , 'Message' : ' \\n ' . join ( msg )}) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'dewar' , type = str , choices = [ 'green' , 'red' ], default = 'green' , help = 'Which dewar to check? red or green' ) parser . add_argument ( '--email' , dest = \"email\" , default = False , action = \"store_true\" , help = 'Send email if dewar weight is low' ) return super () . add_cmdline_args ( parser , cfg )","title":"ARGS:"},{"location":"scripts/CleanupAfterCalibrations/","text":"CleanupAfterCalibrations Bases: KPFTranslatorFunction Script which cleans up after Cal OBs. This must have arguments as input, either from a file using the -f command line tool, or passed in from the execution engine. Can be called by ddoi_script_functions.post_observation_cleanup . ARGS: :OB: dict A fully specified calibration observing block (OB). Source code in kpf/scripts/CleanupAfterCalibrations.py 25 26 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 class CleanupAfterCalibrations ( KPFTranslatorFunction ): '''Script which cleans up after Cal OBs. This must have arguments as input, either from a file using the `-f` command line tool, or passed in from the execution engine. Can be called by `ddoi_script_functions.post_observation_cleanup`. ARGS: ===== :OB: `dict` A fully specified calibration observing block (OB). ''' @classmethod def pre_condition ( cls , OB , logger , cfg ): pass @classmethod def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in OB : if key not in [ 'SEQ_Darks' , 'SEQ_Calibrations' ]: log . debug ( f \" { key } : { OB [ key ] } \" ) else : log . debug ( f \" { key } :\" ) for entry in OB [ key ]: log . debug ( f \" { entry } \" ) log . info ( '-------------------------' ) # Power off lamps if OB . get ( 'leave_lamps_on' , False ) == True : log . info ( 'Not turning lamps off because command line option was invoked' ) else : sequence = OB . get ( 'SEQ_Calibrations' , None ) lamps = set ([ x [ 'CalSource' ] for x in sequence if x [ 'CalSource' ] != 'Home' ]) \\ if sequence is not None else [] for lamp in lamps : if IsCalSourceEnabled . execute ({ 'CalSource' : lamp }) == True : if lamp in [ 'Th_daily' , 'Th_gold' , 'U_daily' , 'U_gold' , 'BrdbandFiber' , 'WideFlat' ]: CalLampPower . execute ({ 'lamp' : lamp , 'power' : 'off' }) if lamp == 'LFCFiber' : SetLFCtoStandbyHigh . execute ({}) kpfconfig = ktl . cache ( 'kpfconfig' ) runagitator = kpfconfig [ 'USEAGITATOR' ] . read ( binary = True ) if runagitator is True : StopAgitator . execute ({}) log . info ( f \"Stowing FIU\" ) ConfigureFIU . execute ({ 'mode' : 'Stowed' }) # Turn off exposure meter controlled exposure log . debug ( 'Clearing kpf_expmeter.USETHRESHOLD' ) kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) kpf_expmeter [ 'USETHRESHOLD' ] . write ( 'No' ) # Set OBJECT back to empty string log . info ( 'Waiting for readout to finish' ) WaitForReady . execute ({}) SetObject . execute ({ 'Object' : '' }) # Clear target info SetTargetInfo . execute ({}) # Clear script keywords clear_script_keywords () # Write L0 file name to log if can WaitForL0File . execute ({}) @classmethod def post_condition ( cls , OB , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( '--leave_lamps_on' , dest = \"leave_lamps_on\" , default = False , action = \"store_true\" , help = 'Leave the lamps on after cleanup phase?' ) return super () . add_cmdline_args ( parser , cfg )","title":"CleanupAfterCalibrations"},{"location":"scripts/CleanupAfterCalibrations/#cleanupaftercalibrations","text":"Bases: KPFTranslatorFunction Script which cleans up after Cal OBs. This must have arguments as input, either from a file using the -f command line tool, or passed in from the execution engine. Can be called by ddoi_script_functions.post_observation_cleanup .","title":"CleanupAfterCalibrations"},{"location":"scripts/CleanupAfterCalibrations/#kpf.scripts.CleanupAfterCalibrations.CleanupAfterCalibrations--args","text":":OB: dict A fully specified calibration observing block (OB). Source code in kpf/scripts/CleanupAfterCalibrations.py 25 26 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 class CleanupAfterCalibrations ( KPFTranslatorFunction ): '''Script which cleans up after Cal OBs. This must have arguments as input, either from a file using the `-f` command line tool, or passed in from the execution engine. Can be called by `ddoi_script_functions.post_observation_cleanup`. ARGS: ===== :OB: `dict` A fully specified calibration observing block (OB). ''' @classmethod def pre_condition ( cls , OB , logger , cfg ): pass @classmethod def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in OB : if key not in [ 'SEQ_Darks' , 'SEQ_Calibrations' ]: log . debug ( f \" { key } : { OB [ key ] } \" ) else : log . debug ( f \" { key } :\" ) for entry in OB [ key ]: log . debug ( f \" { entry } \" ) log . info ( '-------------------------' ) # Power off lamps if OB . get ( 'leave_lamps_on' , False ) == True : log . info ( 'Not turning lamps off because command line option was invoked' ) else : sequence = OB . get ( 'SEQ_Calibrations' , None ) lamps = set ([ x [ 'CalSource' ] for x in sequence if x [ 'CalSource' ] != 'Home' ]) \\ if sequence is not None else [] for lamp in lamps : if IsCalSourceEnabled . execute ({ 'CalSource' : lamp }) == True : if lamp in [ 'Th_daily' , 'Th_gold' , 'U_daily' , 'U_gold' , 'BrdbandFiber' , 'WideFlat' ]: CalLampPower . execute ({ 'lamp' : lamp , 'power' : 'off' }) if lamp == 'LFCFiber' : SetLFCtoStandbyHigh . execute ({}) kpfconfig = ktl . cache ( 'kpfconfig' ) runagitator = kpfconfig [ 'USEAGITATOR' ] . read ( binary = True ) if runagitator is True : StopAgitator . execute ({}) log . info ( f \"Stowing FIU\" ) ConfigureFIU . execute ({ 'mode' : 'Stowed' }) # Turn off exposure meter controlled exposure log . debug ( 'Clearing kpf_expmeter.USETHRESHOLD' ) kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) kpf_expmeter [ 'USETHRESHOLD' ] . write ( 'No' ) # Set OBJECT back to empty string log . info ( 'Waiting for readout to finish' ) WaitForReady . execute ({}) SetObject . execute ({ 'Object' : '' }) # Clear target info SetTargetInfo . execute ({}) # Clear script keywords clear_script_keywords () # Write L0 file name to log if can WaitForL0File . execute ({}) @classmethod def post_condition ( cls , OB , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( '--leave_lamps_on' , dest = \"leave_lamps_on\" , default = False , action = \"store_true\" , help = 'Leave the lamps on after cleanup phase?' ) return super () . add_cmdline_args ( parser , cfg )","title":"ARGS:"},{"location":"scripts/CleanupAfterScience/","text":"CleanupAfterScience Bases: KPFTranslatorFunction Script which cleans up at the end of Science OBs. Can be called by ddoi_script_functions.post_observation_cleanup . ARGS: :OB: dict A fully specified science observing block (OB). Source code in kpf/scripts/CleanupAfterScience.py 15 16 17 18 19 20 21 22 23 24 25 26 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 class CleanupAfterScience ( KPFTranslatorFunction ): '''Script which cleans up at the end of Science OBs. Can be called by `ddoi_script_functions.post_observation_cleanup`. ARGS: ===== :OB: `dict` A fully specified science observing block (OB). ''' @classmethod def pre_condition ( cls , OB , logger , cfg ): pass @classmethod def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) log . info ( '-------------------------' ) StopTipTilt . execute ({}) kpfconfig = ktl . cache ( 'kpfconfig' ) runagitator = kpfconfig [ 'USEAGITATOR' ] . read ( binary = True ) if runagitator is True : StopAgitator . execute ({}) # Clear target info log . debug ( 'Clearing target info' ) SetTargetInfo . execute ({}) # Turn off exposure meter controlled exposure log . debug ( 'Clearing kpf_expmeter.USETHRESHOLD' ) kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) kpf_expmeter [ 'USETHRESHOLD' ] . write ( 'No' ) # Set SKY_OFFSET back to 0 0 log . debug ( 'Clearing kpfguide.SKY_OFFSET' ) sky_offset = ktl . cache ( 'kpfguide' , 'SKY_OFFSET' ) sky_offset . write ( '0 0' ) clear_script_keywords () @classmethod def post_condition ( cls , OB , logger , cfg ): pass","title":"CleanupAfterScience"},{"location":"scripts/CleanupAfterScience/#cleanupafterscience","text":"Bases: KPFTranslatorFunction Script which cleans up at the end of Science OBs. Can be called by ddoi_script_functions.post_observation_cleanup .","title":"CleanupAfterScience"},{"location":"scripts/CleanupAfterScience/#kpf.scripts.CleanupAfterScience.CleanupAfterScience--args","text":":OB: dict A fully specified science observing block (OB). Source code in kpf/scripts/CleanupAfterScience.py 15 16 17 18 19 20 21 22 23 24 25 26 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 class CleanupAfterScience ( KPFTranslatorFunction ): '''Script which cleans up at the end of Science OBs. Can be called by `ddoi_script_functions.post_observation_cleanup`. ARGS: ===== :OB: `dict` A fully specified science observing block (OB). ''' @classmethod def pre_condition ( cls , OB , logger , cfg ): pass @classmethod def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) log . info ( '-------------------------' ) StopTipTilt . execute ({}) kpfconfig = ktl . cache ( 'kpfconfig' ) runagitator = kpfconfig [ 'USEAGITATOR' ] . read ( binary = True ) if runagitator is True : StopAgitator . execute ({}) # Clear target info log . debug ( 'Clearing target info' ) SetTargetInfo . execute ({}) # Turn off exposure meter controlled exposure log . debug ( 'Clearing kpf_expmeter.USETHRESHOLD' ) kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) kpf_expmeter [ 'USETHRESHOLD' ] . write ( 'No' ) # Set SKY_OFFSET back to 0 0 log . debug ( 'Clearing kpfguide.SKY_OFFSET' ) sky_offset = ktl . cache ( 'kpfguide' , 'SKY_OFFSET' ) sky_offset . write ( '0 0' ) clear_script_keywords () @classmethod def post_condition ( cls , OB , logger , cfg ): pass","title":"ARGS:"},{"location":"scripts/CollectGuiderDarkCubes/","text":"CollectGuiderDarkCubes Bases: KPFTranslatorFunction Obtains CRED2 \"trigger file\" data cubes under dark conditions at each of the three gain settings for the detector. Sequence: - Set FIU to Stowed - Set kpfguide.SENSORSETP = -40 - Wait for temperature to reach target - modify -s kpfexpose SRC_SHUTTERS='' - Set FPS = 100 - Set GAIN = High - Take 10s trigger cube - Set GAIN = High - Take 10s trigger cube - Set GAIN = Low - Take 10s trigger cube - Set kpfguide.SENSORSETP = 0 ARGS: None Source code in kpf/scripts/CollectGuiderDarkCubes.py 19 20 21 22 23 24 25 26 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 class CollectGuiderDarkCubes ( KPFTranslatorFunction ): '''Obtains CRED2 \"trigger file\" data cubes under dark conditions at each of the three gain settings for the detector. Sequence: - Set FIU to Stowed - Set kpfguide.SENSORSETP = -40 - Wait for temperature to reach target - modify -s kpfexpose SRC_SHUTTERS='' - Set FPS = 100 - Set GAIN = High - Take 10s trigger cube - Set GAIN = High - Take 10s trigger cube - Set GAIN = Low - Take 10s trigger cube - Set kpfguide.SENSORSETP = 0 ARGS: ===== None ''' @classmethod @obey_scriptrun def pre_condition ( cls , args , logger , cfg ): pass @classmethod @register_script ( Path ( __file__ ) . name , os . getpid ()) @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , args , logger , cfg ): output_file = Path ( '/s/sdata1701/CRED2DarkCubes/CRED2_dark_cubes.txt' ) OUTDIR = ktl . cache ( 'kpfguide' , 'OUTDIR' ) original_OUTDIR = OUTDIR . read () new_OUTDIR = str ( output_file . parent ) log . debug ( f 'Setting OUTDIR to { new_OUTDIR } ' ) OUTDIR . write ( new_OUTDIR ) SENSORSETP = ktl . cache ( 'kpfguide' , 'SENSORSETP' ) SENSORTEMP = ktl . cache ( 'kpfguide' , 'SENSORTEMP' ) CONTINUOUS = ktl . cache ( 'kpfguide' , 'CONTINUOUS' ) kpfguide = ktl . cache ( 'kpfguide' ) try : log . info ( 'Taking CRED2 dark cubes' ) ConfigureFIU . execute ({ 'mode' : 'Stowed' }) log . info ( 'Cooling CRED2' ) SENSORSETP . write ( - 40 ) log . info ( 'Waiting up to 10 minutes for detector to reach set point' ) reached_temp = SENSORTEMP . waitFor ( \"<-39.9\" , timeout = 600 ) if reached_temp == False : log . error ( 'CRED2 failed to reach set point. Exiting.' ) SENSORSETP . write ( 0 ) return check_scriptstop () log . debug ( 'Waiting additional time for temperature to stabilize' ) time . sleep ( 60 ) # shim to give time to stabilize check_scriptstop () log . debug ( 'Closing source shutters' ) SetSourceSelectShutters . execute ({}) CONTINUOUS . write ( 'Active' ) SetGuiderFPS . execute ({ 'GuideFPS' : 100 }) for gain in [ 'high' , 'medium' , 'low' ]: log . info ( f 'Collecting { gain } gain cube' ) SetGuiderGain . execute ({ 'GuideCamGain' : gain }) cube_file = TakeGuiderCube . execute ({ 'duration' : 10 }) with open ( output_file , 'a' ) as f : f . write ( f \" { gain : 12s } , { cube_file } \\n \" ) check_scriptstop () time . sleep ( 30 ) # shim to give time to recover after writing cube check_scriptstop () for gain in [ 'high' , 'medium' , 'low' ]: sub_file = kpfguide [ f 'SUB_ { gain . upper () } ' ] . read () kpfguide [ f 'SUB_ { gain . upper () } ' ] . write ( '' ) log . info ( f 'Collecting { gain } gain cube without bias subtraction' ) SetGuiderGain . execute ({ 'GuideCamGain' : gain }) cube_file = TakeGuiderCube . execute ({ 'duration' : 10 }) with open ( output_file , 'a' ) as f : gain_string = f ' { gain } _nosub' f . write ( f \" { gain_string : 12s } , { cube_file } \\n \" ) kpfguide [ f 'SUB_ { gain . upper () } ' ] . write ( sub_file ) check_scriptstop () time . sleep ( 30 ) # shim to give time to recover after writing cube check_scriptstop () except Exception as e : log . error ( 'Error running CollectGuiderDarkCubes' ) log . debug ( e ) log . info ( 'Resetting CRED2 temperature set point to 0' ) SENSORSETP . write ( 0 ) log . debug ( f 'Setting OUTDIR to { original_OUTDIR } ' ) OUTDIR . write ( original_OUTDIR ) clear_script_keywords () @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"CollectGuiderDarkCubes"},{"location":"scripts/CollectGuiderDarkCubes/#collectguiderdarkcubes","text":"Bases: KPFTranslatorFunction Obtains CRED2 \"trigger file\" data cubes under dark conditions at each of the three gain settings for the detector. Sequence: - Set FIU to Stowed - Set kpfguide.SENSORSETP = -40 - Wait for temperature to reach target - modify -s kpfexpose SRC_SHUTTERS='' - Set FPS = 100 - Set GAIN = High - Take 10s trigger cube - Set GAIN = High - Take 10s trigger cube - Set GAIN = Low - Take 10s trigger cube - Set kpfguide.SENSORSETP = 0","title":"CollectGuiderDarkCubes"},{"location":"scripts/CollectGuiderDarkCubes/#kpf.scripts.CollectGuiderDarkCubes.CollectGuiderDarkCubes--args","text":"None Source code in kpf/scripts/CollectGuiderDarkCubes.py 19 20 21 22 23 24 25 26 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 class CollectGuiderDarkCubes ( KPFTranslatorFunction ): '''Obtains CRED2 \"trigger file\" data cubes under dark conditions at each of the three gain settings for the detector. Sequence: - Set FIU to Stowed - Set kpfguide.SENSORSETP = -40 - Wait for temperature to reach target - modify -s kpfexpose SRC_SHUTTERS='' - Set FPS = 100 - Set GAIN = High - Take 10s trigger cube - Set GAIN = High - Take 10s trigger cube - Set GAIN = Low - Take 10s trigger cube - Set kpfguide.SENSORSETP = 0 ARGS: ===== None ''' @classmethod @obey_scriptrun def pre_condition ( cls , args , logger , cfg ): pass @classmethod @register_script ( Path ( __file__ ) . name , os . getpid ()) @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , args , logger , cfg ): output_file = Path ( '/s/sdata1701/CRED2DarkCubes/CRED2_dark_cubes.txt' ) OUTDIR = ktl . cache ( 'kpfguide' , 'OUTDIR' ) original_OUTDIR = OUTDIR . read () new_OUTDIR = str ( output_file . parent ) log . debug ( f 'Setting OUTDIR to { new_OUTDIR } ' ) OUTDIR . write ( new_OUTDIR ) SENSORSETP = ktl . cache ( 'kpfguide' , 'SENSORSETP' ) SENSORTEMP = ktl . cache ( 'kpfguide' , 'SENSORTEMP' ) CONTINUOUS = ktl . cache ( 'kpfguide' , 'CONTINUOUS' ) kpfguide = ktl . cache ( 'kpfguide' ) try : log . info ( 'Taking CRED2 dark cubes' ) ConfigureFIU . execute ({ 'mode' : 'Stowed' }) log . info ( 'Cooling CRED2' ) SENSORSETP . write ( - 40 ) log . info ( 'Waiting up to 10 minutes for detector to reach set point' ) reached_temp = SENSORTEMP . waitFor ( \"<-39.9\" , timeout = 600 ) if reached_temp == False : log . error ( 'CRED2 failed to reach set point. Exiting.' ) SENSORSETP . write ( 0 ) return check_scriptstop () log . debug ( 'Waiting additional time for temperature to stabilize' ) time . sleep ( 60 ) # shim to give time to stabilize check_scriptstop () log . debug ( 'Closing source shutters' ) SetSourceSelectShutters . execute ({}) CONTINUOUS . write ( 'Active' ) SetGuiderFPS . execute ({ 'GuideFPS' : 100 }) for gain in [ 'high' , 'medium' , 'low' ]: log . info ( f 'Collecting { gain } gain cube' ) SetGuiderGain . execute ({ 'GuideCamGain' : gain }) cube_file = TakeGuiderCube . execute ({ 'duration' : 10 }) with open ( output_file , 'a' ) as f : f . write ( f \" { gain : 12s } , { cube_file } \\n \" ) check_scriptstop () time . sleep ( 30 ) # shim to give time to recover after writing cube check_scriptstop () for gain in [ 'high' , 'medium' , 'low' ]: sub_file = kpfguide [ f 'SUB_ { gain . upper () } ' ] . read () kpfguide [ f 'SUB_ { gain . upper () } ' ] . write ( '' ) log . info ( f 'Collecting { gain } gain cube without bias subtraction' ) SetGuiderGain . execute ({ 'GuideCamGain' : gain }) cube_file = TakeGuiderCube . execute ({ 'duration' : 10 }) with open ( output_file , 'a' ) as f : gain_string = f ' { gain } _nosub' f . write ( f \" { gain_string : 12s } , { cube_file } \\n \" ) kpfguide [ f 'SUB_ { gain . upper () } ' ] . write ( sub_file ) check_scriptstop () time . sleep ( 30 ) # shim to give time to recover after writing cube check_scriptstop () except Exception as e : log . error ( 'Error running CollectGuiderDarkCubes' ) log . debug ( e ) log . info ( 'Resetting CRED2 temperature set point to 0' ) SENSORSETP . write ( 0 ) log . debug ( f 'Setting OUTDIR to { original_OUTDIR } ' ) OUTDIR . write ( original_OUTDIR ) clear_script_keywords () @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"ARGS:"},{"location":"scripts/ConfigureFIU/","text":"ConfigureFIU Bases: KPFTranslatorFunction Set the FIU mode (kpffiu.MODE). If the wait option is fale this will retry the move if it fails with a configurable number of retries. Parameters: mode ( str ) \u2013 The desired FIU mode. Allowed values: Stowed, Alignment, Acquisition, Observing, Calibration wait ( bool ) \u2013 Wait for move to complete before returning? (default: True) KTL Keywords Used: kpffiu.MODE Scripts Called: kpf.calbench.ConfigureFIUOnce kpf.calbench.WaitForConfigureFIU Source code in kpf/fiu/ConfigureFIU.py 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class ConfigureFIU ( KPFTranslatorFunction ): '''Set the FIU mode (kpffiu.MODE). If the wait option is fale this will retry the move if it fails with a configurable number of retries. Args: mode (str): The desired FIU mode. Allowed values: Stowed, Alignment, Acquisition, Observing, Calibration wait (bool): Wait for move to complete before returning? (default: True) KTL Keywords Used: - `kpffiu.MODE` Scripts Called: - `kpf.calbench.ConfigureFIUOnce` - `kpf.calbench.WaitForConfigureFIU` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpffiu' , 'MODE' ) allowed_values = list ( keyword . _getEnumerators ()) if 'None' in allowed_values : allowed_values . pop ( allowed_values . index ( 'None' )) check_input ( args , 'mode' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): dest = args . get ( 'mode' ) wait = args . get ( 'wait' , True ) log . info ( f \"Configuring FIU for { dest } \" ) ConfigureFIUOnce . execute ({ 'mode' : dest , 'wait' : wait }) if wait == True : WaitForConfigureFIU . execute ({ 'mode' : dest }) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'mode' , type = str , choices = [ 'Stowed' , 'Alignment' , 'Acquisition' , 'Observing' , 'Calibration' ], help = 'Desired mode (see kpffiu.MODE)' ) parser . add_argument ( \"--nowait\" , dest = \"wait\" , default = True , action = \"store_false\" , help = \"Send move and return immediately?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"ConfigureFIU"},{"location":"scripts/ConfigureFIU/#configurefiu","text":"Bases: KPFTranslatorFunction Set the FIU mode (kpffiu.MODE). If the wait option is fale this will retry the move if it fails with a configurable number of retries. Parameters: mode ( str ) \u2013 The desired FIU mode. Allowed values: Stowed, Alignment, Acquisition, Observing, Calibration wait ( bool ) \u2013 Wait for move to complete before returning? (default: True) KTL Keywords Used: kpffiu.MODE Scripts Called: kpf.calbench.ConfigureFIUOnce kpf.calbench.WaitForConfigureFIU Source code in kpf/fiu/ConfigureFIU.py 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class ConfigureFIU ( KPFTranslatorFunction ): '''Set the FIU mode (kpffiu.MODE). If the wait option is fale this will retry the move if it fails with a configurable number of retries. Args: mode (str): The desired FIU mode. Allowed values: Stowed, Alignment, Acquisition, Observing, Calibration wait (bool): Wait for move to complete before returning? (default: True) KTL Keywords Used: - `kpffiu.MODE` Scripts Called: - `kpf.calbench.ConfigureFIUOnce` - `kpf.calbench.WaitForConfigureFIU` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpffiu' , 'MODE' ) allowed_values = list ( keyword . _getEnumerators ()) if 'None' in allowed_values : allowed_values . pop ( allowed_values . index ( 'None' )) check_input ( args , 'mode' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): dest = args . get ( 'mode' ) wait = args . get ( 'wait' , True ) log . info ( f \"Configuring FIU for { dest } \" ) ConfigureFIUOnce . execute ({ 'mode' : dest , 'wait' : wait }) if wait == True : WaitForConfigureFIU . execute ({ 'mode' : dest }) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'mode' , type = str , choices = [ 'Stowed' , 'Alignment' , 'Acquisition' , 'Observing' , 'Calibration' ], help = 'Desired mode (see kpffiu.MODE)' ) parser . add_argument ( \"--nowait\" , dest = \"wait\" , default = True , action = \"store_false\" , help = \"Send move and return immediately?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"ConfigureFIU"},{"location":"scripts/ConfigureForAcquisition/","text":"ConfigureForAcquisition Bases: KPFTranslatorFunction Script which configures the instrument for Acquisition step. Sets target parameters Sets FIU mode Executes Slew Cal This must have arguments as input, either from a file using the -f command line tool, or passed in from the execution engine. ARGS: :OB: dict A fully specified science observing block (OB). Source code in kpf/scripts/ConfigureForAcquisition.py 22 23 24 25 26 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 class ConfigureForAcquisition ( KPFTranslatorFunction ): '''Script which configures the instrument for Acquisition step. - Sets target parameters - Sets FIU mode - Executes Slew Cal This must have arguments as input, either from a file using the `-f` command line tool, or passed in from the execution engine. ARGS: ===== :OB: `dict` A fully specified science observing block (OB). ''' @classmethod @obey_scriptrun def pre_condition ( cls , OB , logger , cfg ): check_input ( OB , 'Template_Name' , allowed_values = [ 'kpf_sci' ]) check_input ( OB , 'Template_Version' , version_check = True , value_min = '0.5' ) # Check Slewcals kpfconfig = ktl . cache ( 'kpfconfig' ) if kpfconfig [ 'SLEWCALREQ' ] . read ( binary = True ) is True : slewcal_argsfile = Path ( kpfconfig [ 'SLEWCALFILE' ] . read ()) if slewcal_argsfile . exists () is False : raise FailedPreCondition ( f \"Slew cal file { slewcal_argsfile } does not exist\" ) @classmethod def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in OB : if key not in [ 'SEQ_Observations' ]: log . debug ( f \" { key } : { OB [ key ] } \" ) else : log . debug ( f \" { key } :\" ) for entry in OB [ key ]: log . debug ( f \" { entry } \" ) log . info ( '-------------------------' ) kpfconfig = ktl . cache ( 'kpfconfig' ) kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) # Set Octagon kpfconfig = ktl . cache ( 'kpfconfig' ) calsource = kpfconfig [ 'SIMULCALSOURCE' ] . read () octagon = ktl . cache ( 'kpfcal' , 'OCTAGON' ) . read () log . debug ( f \"Current OCTAGON = { octagon } , desired = { calsource } \" ) if octagon != calsource : log . info ( f \"Set CalSource/Octagon: { calsource } \" ) SetCalSource . execute ({ 'CalSource' : calsource , 'wait' : False }) ## Execute Slew Cal if Requested if kpfconfig [ 'SLEWCALREQ' ] . read ( binary = True ) is True : slewcal_argsfile = Path ( kpfconfig [ 'SLEWCALFILE' ] . read ()) log . info ( f \"Beginning Slew Cal\" ) log . debug ( f \"Using: { slewcal_argsfile } \" ) with open ( slewcal_argsfile , 'r' ) as file : slewcal_OB = yaml . safe_load ( file ) slewcal_args = slewcal_OB . get ( 'SEQ_Calibrations' )[ 0 ] slewcal_args [ 'Template_Name' ] = 'kpf_slewcal' slewcal_args [ 'Template_Version' ] = '0.5' slewcal_args [ 'TriggerCaHK' ] = OB [ 'TriggerCaHK' ] slewcal_args [ 'TriggerGreen' ] = OB [ 'TriggerGreen' ] slewcal_args [ 'TriggerRed' ] = OB [ 'TriggerRed' ] ExecuteSlewCal . execute ( slewcal_args ) log . info ( 'Slew cal complete. Resetting SLEWCALREQ' ) kpfconfig [ 'SLEWCALREQ' ] . write ( 'No' ) # Set FIU Mode log . info ( 'Setting FIU mode to Observing' ) ConfigureFIU . execute ({ 'mode' : 'Observing' , 'wait' : False }) # Set Target Parameters from OB SetTargetInfo . execute ( OB ) @classmethod def post_condition ( cls , OB , logger , cfg ): pass","title":"ConfigureForAcquisition"},{"location":"scripts/ConfigureForAcquisition/#configureforacquisition","text":"Bases: KPFTranslatorFunction Script which configures the instrument for Acquisition step. Sets target parameters Sets FIU mode Executes Slew Cal This must have arguments as input, either from a file using the -f command line tool, or passed in from the execution engine.","title":"ConfigureForAcquisition"},{"location":"scripts/ConfigureForAcquisition/#kpf.scripts.ConfigureForAcquisition.ConfigureForAcquisition--args","text":":OB: dict A fully specified science observing block (OB). Source code in kpf/scripts/ConfigureForAcquisition.py 22 23 24 25 26 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 class ConfigureForAcquisition ( KPFTranslatorFunction ): '''Script which configures the instrument for Acquisition step. - Sets target parameters - Sets FIU mode - Executes Slew Cal This must have arguments as input, either from a file using the `-f` command line tool, or passed in from the execution engine. ARGS: ===== :OB: `dict` A fully specified science observing block (OB). ''' @classmethod @obey_scriptrun def pre_condition ( cls , OB , logger , cfg ): check_input ( OB , 'Template_Name' , allowed_values = [ 'kpf_sci' ]) check_input ( OB , 'Template_Version' , version_check = True , value_min = '0.5' ) # Check Slewcals kpfconfig = ktl . cache ( 'kpfconfig' ) if kpfconfig [ 'SLEWCALREQ' ] . read ( binary = True ) is True : slewcal_argsfile = Path ( kpfconfig [ 'SLEWCALFILE' ] . read ()) if slewcal_argsfile . exists () is False : raise FailedPreCondition ( f \"Slew cal file { slewcal_argsfile } does not exist\" ) @classmethod def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in OB : if key not in [ 'SEQ_Observations' ]: log . debug ( f \" { key } : { OB [ key ] } \" ) else : log . debug ( f \" { key } :\" ) for entry in OB [ key ]: log . debug ( f \" { entry } \" ) log . info ( '-------------------------' ) kpfconfig = ktl . cache ( 'kpfconfig' ) kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) # Set Octagon kpfconfig = ktl . cache ( 'kpfconfig' ) calsource = kpfconfig [ 'SIMULCALSOURCE' ] . read () octagon = ktl . cache ( 'kpfcal' , 'OCTAGON' ) . read () log . debug ( f \"Current OCTAGON = { octagon } , desired = { calsource } \" ) if octagon != calsource : log . info ( f \"Set CalSource/Octagon: { calsource } \" ) SetCalSource . execute ({ 'CalSource' : calsource , 'wait' : False }) ## Execute Slew Cal if Requested if kpfconfig [ 'SLEWCALREQ' ] . read ( binary = True ) is True : slewcal_argsfile = Path ( kpfconfig [ 'SLEWCALFILE' ] . read ()) log . info ( f \"Beginning Slew Cal\" ) log . debug ( f \"Using: { slewcal_argsfile } \" ) with open ( slewcal_argsfile , 'r' ) as file : slewcal_OB = yaml . safe_load ( file ) slewcal_args = slewcal_OB . get ( 'SEQ_Calibrations' )[ 0 ] slewcal_args [ 'Template_Name' ] = 'kpf_slewcal' slewcal_args [ 'Template_Version' ] = '0.5' slewcal_args [ 'TriggerCaHK' ] = OB [ 'TriggerCaHK' ] slewcal_args [ 'TriggerGreen' ] = OB [ 'TriggerGreen' ] slewcal_args [ 'TriggerRed' ] = OB [ 'TriggerRed' ] ExecuteSlewCal . execute ( slewcal_args ) log . info ( 'Slew cal complete. Resetting SLEWCALREQ' ) kpfconfig [ 'SLEWCALREQ' ] . write ( 'No' ) # Set FIU Mode log . info ( 'Setting FIU mode to Observing' ) ConfigureFIU . execute ({ 'mode' : 'Observing' , 'wait' : False }) # Set Target Parameters from OB SetTargetInfo . execute ( OB ) @classmethod def post_condition ( cls , OB , logger , cfg ): pass","title":"ARGS:"},{"location":"scripts/ConfigureForCalibrations/","text":"ConfigureForCalibrations Bases: KPFTranslatorFunction Script which configures the instrument for Cal OBs. This must have arguments as input, either from a file using the -f command line tool, or passed in from the execution engine. Can be called by ddoi_script_functions.configure_for_science . ARGS: :OB: dict A fully specified calibration observing block (OB). Source code in kpf/scripts/ConfigureForCalibrations.py 21 22 23 24 25 26 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 class ConfigureForCalibrations ( KPFTranslatorFunction ): '''Script which configures the instrument for Cal OBs. This must have arguments as input, either from a file using the `-f` command line tool, or passed in from the execution engine. Can be called by `ddoi_script_functions.configure_for_science`. ARGS: ===== :OB: `dict` A fully specified calibration observing block (OB). ''' @classmethod @obey_scriptrun def pre_condition ( cls , OB , logger , cfg ): check_input ( OB , 'Template_Name' , allowed_values = [ 'kpf_cal' ]) check_input ( OB , 'Template_Version' , version_check = True , value_min = '0.5' ) @classmethod def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in OB : if key not in [ 'SEQ_Darks' , 'SEQ_Calibrations' ]: log . debug ( f \" { key } : { OB [ key ] } \" ) else : log . debug ( f \" { key } :\" ) for entry in OB [ key ]: log . debug ( f \" { entry } \" ) log . info ( '-------------------------' ) check_scriptstop () # Power up needed lamps sequence = OB . get ( 'SEQ_Calibrations' , None ) lamps = set ([ x [ 'CalSource' ] for x in sequence if x [ 'CalSource' ] != 'Home' ]) \\ if sequence is not None else [] for lamp in lamps : if IsCalSourceEnabled . execute ({ 'CalSource' : lamp }) == True : if lamp in [ 'Th_daily' , 'Th_gold' , 'U_daily' , 'U_gold' , 'BrdbandFiber' , 'WideFlat' ]: CalLampPower . execute ({ 'lamp' : lamp , 'power' : 'on' }) log . debug ( f \"Ensuring back illumination LEDs are off\" ) CalLampPower . execute ({ 'lamp' : 'ExpMeterLED' , 'power' : 'off' }) CalLampPower . execute ({ 'lamp' : 'CaHKLED' , 'power' : 'off' }) CalLampPower . execute ({ 'lamp' : 'SciLED' , 'power' : 'off' }) CalLampPower . execute ({ 'lamp' : 'SkyLED' , 'power' : 'off' }) log . info ( f \"Configuring FIU\" ) ConfigureFIU . execute ({ 'mode' : 'Calibration' }) log . info ( f \"Set Detector List\" ) WaitForReady . execute ({}) SetTriggeredDetectors . execute ( OB ) @classmethod def post_condition ( cls , OB , logger , cfg ): pass","title":"ConfigureForCalibrations"},{"location":"scripts/ConfigureForCalibrations/#configureforcalibrations","text":"Bases: KPFTranslatorFunction Script which configures the instrument for Cal OBs. This must have arguments as input, either from a file using the -f command line tool, or passed in from the execution engine. Can be called by ddoi_script_functions.configure_for_science .","title":"ConfigureForCalibrations"},{"location":"scripts/ConfigureForCalibrations/#kpf.scripts.ConfigureForCalibrations.ConfigureForCalibrations--args","text":":OB: dict A fully specified calibration observing block (OB). Source code in kpf/scripts/ConfigureForCalibrations.py 21 22 23 24 25 26 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 class ConfigureForCalibrations ( KPFTranslatorFunction ): '''Script which configures the instrument for Cal OBs. This must have arguments as input, either from a file using the `-f` command line tool, or passed in from the execution engine. Can be called by `ddoi_script_functions.configure_for_science`. ARGS: ===== :OB: `dict` A fully specified calibration observing block (OB). ''' @classmethod @obey_scriptrun def pre_condition ( cls , OB , logger , cfg ): check_input ( OB , 'Template_Name' , allowed_values = [ 'kpf_cal' ]) check_input ( OB , 'Template_Version' , version_check = True , value_min = '0.5' ) @classmethod def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in OB : if key not in [ 'SEQ_Darks' , 'SEQ_Calibrations' ]: log . debug ( f \" { key } : { OB [ key ] } \" ) else : log . debug ( f \" { key } :\" ) for entry in OB [ key ]: log . debug ( f \" { entry } \" ) log . info ( '-------------------------' ) check_scriptstop () # Power up needed lamps sequence = OB . get ( 'SEQ_Calibrations' , None ) lamps = set ([ x [ 'CalSource' ] for x in sequence if x [ 'CalSource' ] != 'Home' ]) \\ if sequence is not None else [] for lamp in lamps : if IsCalSourceEnabled . execute ({ 'CalSource' : lamp }) == True : if lamp in [ 'Th_daily' , 'Th_gold' , 'U_daily' , 'U_gold' , 'BrdbandFiber' , 'WideFlat' ]: CalLampPower . execute ({ 'lamp' : lamp , 'power' : 'on' }) log . debug ( f \"Ensuring back illumination LEDs are off\" ) CalLampPower . execute ({ 'lamp' : 'ExpMeterLED' , 'power' : 'off' }) CalLampPower . execute ({ 'lamp' : 'CaHKLED' , 'power' : 'off' }) CalLampPower . execute ({ 'lamp' : 'SciLED' , 'power' : 'off' }) CalLampPower . execute ({ 'lamp' : 'SkyLED' , 'power' : 'off' }) log . info ( f \"Configuring FIU\" ) ConfigureFIU . execute ({ 'mode' : 'Calibration' }) log . info ( f \"Set Detector List\" ) WaitForReady . execute ({}) SetTriggeredDetectors . execute ( OB ) @classmethod def post_condition ( cls , OB , logger , cfg ): pass","title":"ARGS:"},{"location":"scripts/ConfigureForScience/","text":"ConfigureForScience Bases: KPFTranslatorFunction Script which configures the instrument for Science observations. Sets octagon / simulcal source Sets source select shutters Set triggered detectors This must have arguments as input, either from a file using the -f command line tool, or passed in from the execution engine. Can be called by ddoi_script_functions.configure_for_science . ARGS: :OB: dict A fully specified science observing block (OB). Source code in kpf/scripts/ConfigureForScience.py 24 25 26 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 class ConfigureForScience ( KPFTranslatorFunction ): '''Script which configures the instrument for Science observations. - Sets octagon / simulcal source - Sets source select shutters - Set triggered detectors This must have arguments as input, either from a file using the `-f` command line tool, or passed in from the execution engine. Can be called by `ddoi_script_functions.configure_for_science`. ARGS: ===== :OB: `dict` A fully specified science observing block (OB). ''' @classmethod @obey_scriptrun def pre_condition ( cls , OB , logger , cfg ): check_input ( OB , 'Template_Name' , allowed_values = [ 'kpf_sci' ]) check_input ( OB , 'Template_Version' , version_check = True , value_min = '0.5' ) return True @classmethod def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in OB : if key not in [ 'SEQ_Observations' ]: log . debug ( f \" { key } : { OB [ key ] } \" ) else : log . debug ( f \" { key } :\" ) for entry in OB [ key ]: log . debug ( f \" { entry } \" ) log . info ( '-------------------------' ) check_scriptstop () matched_PO = VerifyCurrentBase . execute ({}) if matched_PO == False : # Check with user log . debug ( 'Asking for user input' ) print () print ( \"#####################################################\" ) print ( \"The dcs.PONAME value is incosistent with CURRENT_BASE\" ) print ( \"Please double check that the target object is where you\" ) print ( \"want it to be before proceeding.\" ) print () print ( \"Do you wish to continue executing this OB?\" ) print ( \"(y/n) [y]:\" ) print ( \"#####################################################\" ) print () user_input = input () log . debug ( f 'response: \" { user_input } \"' ) if user_input . lower () . strip () in [ 'n' , 'no' , 'a' , 'abort' , 'q' , 'quit' ]: raise KPFException ( \"User chose to halt execution\" ) check_scriptstop () # Set Octagon kpfconfig = ktl . cache ( 'kpfconfig' ) calsource = kpfconfig [ 'SIMULCALSOURCE' ] . read () octagon = ktl . cache ( 'kpfcal' , 'OCTAGON' ) . read () log . debug ( f \"Current OCTAGON = { octagon } , desired = { calsource } \" ) if octagon != calsource : log . info ( f \"Set CalSource/Octagon: { calsource } \" ) SetCalSource . execute ({ 'CalSource' : calsource , 'wait' : False }) check_scriptstop () exposestatus = ktl . cache ( 'kpfexpose' , 'EXPOSE' ) if exposestatus . read () != 'Ready' : log . info ( f \"Waiting for kpfexpose to be Ready\" ) WaitForReady . execute ({}) log . debug ( f \"kpfexpose is Ready\" ) # Set source select shutters log . info ( f \"Set Source Select Shutters\" ) SetSourceSelectShutters . execute ({ 'SSS_Science' : True , 'SSS_Sky' : not OB . get ( 'BlockSky' , False ), 'SSS_SoCalSci' : False , 'SSS_SoCalCal' : False , 'SSS_CalSciSky' : False }) # Set Triggered Detectors OB [ 'TriggerGuide' ] = True SetTriggeredDetectors . execute ( OB ) check_scriptstop () @classmethod def post_condition ( cls , OB , logger , cfg ): pass","title":"ConfigureForScience"},{"location":"scripts/ConfigureForScience/#configureforscience","text":"Bases: KPFTranslatorFunction Script which configures the instrument for Science observations. Sets octagon / simulcal source Sets source select shutters Set triggered detectors This must have arguments as input, either from a file using the -f command line tool, or passed in from the execution engine. Can be called by ddoi_script_functions.configure_for_science .","title":"ConfigureForScience"},{"location":"scripts/ConfigureForScience/#kpf.scripts.ConfigureForScience.ConfigureForScience--args","text":":OB: dict A fully specified science observing block (OB). Source code in kpf/scripts/ConfigureForScience.py 24 25 26 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 class ConfigureForScience ( KPFTranslatorFunction ): '''Script which configures the instrument for Science observations. - Sets octagon / simulcal source - Sets source select shutters - Set triggered detectors This must have arguments as input, either from a file using the `-f` command line tool, or passed in from the execution engine. Can be called by `ddoi_script_functions.configure_for_science`. ARGS: ===== :OB: `dict` A fully specified science observing block (OB). ''' @classmethod @obey_scriptrun def pre_condition ( cls , OB , logger , cfg ): check_input ( OB , 'Template_Name' , allowed_values = [ 'kpf_sci' ]) check_input ( OB , 'Template_Version' , version_check = True , value_min = '0.5' ) return True @classmethod def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in OB : if key not in [ 'SEQ_Observations' ]: log . debug ( f \" { key } : { OB [ key ] } \" ) else : log . debug ( f \" { key } :\" ) for entry in OB [ key ]: log . debug ( f \" { entry } \" ) log . info ( '-------------------------' ) check_scriptstop () matched_PO = VerifyCurrentBase . execute ({}) if matched_PO == False : # Check with user log . debug ( 'Asking for user input' ) print () print ( \"#####################################################\" ) print ( \"The dcs.PONAME value is incosistent with CURRENT_BASE\" ) print ( \"Please double check that the target object is where you\" ) print ( \"want it to be before proceeding.\" ) print () print ( \"Do you wish to continue executing this OB?\" ) print ( \"(y/n) [y]:\" ) print ( \"#####################################################\" ) print () user_input = input () log . debug ( f 'response: \" { user_input } \"' ) if user_input . lower () . strip () in [ 'n' , 'no' , 'a' , 'abort' , 'q' , 'quit' ]: raise KPFException ( \"User chose to halt execution\" ) check_scriptstop () # Set Octagon kpfconfig = ktl . cache ( 'kpfconfig' ) calsource = kpfconfig [ 'SIMULCALSOURCE' ] . read () octagon = ktl . cache ( 'kpfcal' , 'OCTAGON' ) . read () log . debug ( f \"Current OCTAGON = { octagon } , desired = { calsource } \" ) if octagon != calsource : log . info ( f \"Set CalSource/Octagon: { calsource } \" ) SetCalSource . execute ({ 'CalSource' : calsource , 'wait' : False }) check_scriptstop () exposestatus = ktl . cache ( 'kpfexpose' , 'EXPOSE' ) if exposestatus . read () != 'Ready' : log . info ( f \"Waiting for kpfexpose to be Ready\" ) WaitForReady . execute ({}) log . debug ( f \"kpfexpose is Ready\" ) # Set source select shutters log . info ( f \"Set Source Select Shutters\" ) SetSourceSelectShutters . execute ({ 'SSS_Science' : True , 'SSS_Sky' : not OB . get ( 'BlockSky' , False ), 'SSS_SoCalSci' : False , 'SSS_SoCalCal' : False , 'SSS_CalSciSky' : False }) # Set Triggered Detectors OB [ 'TriggerGuide' ] = True SetTriggeredDetectors . execute ( OB ) check_scriptstop () @classmethod def post_condition ( cls , OB , logger , cfg ): pass","title":"ARGS:"},{"location":"scripts/ControlAOHatch/","text":"ControlAOHatch Bases: KPFTranslatorFunction Command the AO Hatch to open or close. Parameters: destination ( str ) \u2013 The destination position. Allowed Values: 'open' or 'close'. KTL Keywords Used: ao.AOHATCHCMD ao.AOHATCHSTS Source code in kpf/ao/ControlAOHatch.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class ControlAOHatch ( KPFTranslatorFunction ): '''Command the AO Hatch to open or close. Args: destination (str): The destination position. Allowed Values: 'open' or 'close'. KTL Keywords Used: - `ao.AOHATCHCMD` - `ao.AOHATCHSTS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'destination' , allowed_values = [ 'close' , 'closed' , 'open' ]) @classmethod def perform ( cls , args , logger , cfg ): destination = args . get ( 'destination' , '' ) . strip () ao = ktl . cache ( 'ao' ) log . debug ( f \"Setting AO Hatch to { destination } \" ) cmd = { 'close' : 1 , 'closed' : 1 , 'open' : 0 }[ destination ] ao [ 'aohatchcmd' ] . write ( cmd ) @classmethod def post_condition ( cls , args , logger , cfg ): destination = args . get ( 'destination' , '' ) . strip () final_dest = { 'close' : 'closed' , 'closed' : 'closed' , 'open' : 'open' }[ destination ] aohatchsts = ktl . cache ( 'ao' , 'AOHATCHSTS' ) success = aohatchsts . waitfor ( f \"== ' { final_dest } '\" , timeout = 30 ) if success is not True : raise FailedToReachDestination ( aohatchsts . read (), final_dest ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'destination' , type = str , choices = [ 'open' , 'close' ], help = 'Desired hatch position' ) return super () . add_cmdline_args ( parser , cfg )","title":"ControlAOHatch"},{"location":"scripts/ControlAOHatch/#controlaohatch","text":"Bases: KPFTranslatorFunction Command the AO Hatch to open or close. Parameters: destination ( str ) \u2013 The destination position. Allowed Values: 'open' or 'close'. KTL Keywords Used: ao.AOHATCHCMD ao.AOHATCHSTS Source code in kpf/ao/ControlAOHatch.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class ControlAOHatch ( KPFTranslatorFunction ): '''Command the AO Hatch to open or close. Args: destination (str): The destination position. Allowed Values: 'open' or 'close'. KTL Keywords Used: - `ao.AOHATCHCMD` - `ao.AOHATCHSTS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'destination' , allowed_values = [ 'close' , 'closed' , 'open' ]) @classmethod def perform ( cls , args , logger , cfg ): destination = args . get ( 'destination' , '' ) . strip () ao = ktl . cache ( 'ao' ) log . debug ( f \"Setting AO Hatch to { destination } \" ) cmd = { 'close' : 1 , 'closed' : 1 , 'open' : 0 }[ destination ] ao [ 'aohatchcmd' ] . write ( cmd ) @classmethod def post_condition ( cls , args , logger , cfg ): destination = args . get ( 'destination' , '' ) . strip () final_dest = { 'close' : 'closed' , 'closed' : 'closed' , 'open' : 'open' }[ destination ] aohatchsts = ktl . cache ( 'ao' , 'AOHATCHSTS' ) success = aohatchsts . waitfor ( f \"== ' { final_dest } '\" , timeout = 30 ) if success is not True : raise FailedToReachDestination ( aohatchsts . read (), final_dest ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'destination' , type = str , choices = [ 'open' , 'close' ], help = 'Desired hatch position' ) return super () . add_cmdline_args ( parser , cfg )","title":"ControlAOHatch"},{"location":"scripts/ControlFoldMirror/","text":"ControlFoldMirror Bases: KPFTranslatorFunction Insert or remove the FIU Cal Fold Mirror from the beam. Parameters: destination ( str ) \u2013 The desired FIU fold mirror position name. Allowed values: in, out wait ( bool ) \u2013 Wait for move to complete before returning? (default: True) KTL Keywords Used: kpffiu.FOLDNAM Source code in kpf/fiu/ControlFoldMirror.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class ControlFoldMirror ( KPFTranslatorFunction ): '''Insert or remove the FIU Cal Fold Mirror from the beam. Args: destination (str): The desired FIU fold mirror position name. Allowed values: in, out wait (bool): Wait for move to complete before returning? (default: True) KTL Keywords Used: - `kpffiu.FOLDNAM` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): destination = args . get ( 'destination' , '' ) . strip () if destination . lower () not in [ 'in' , 'out' ]: raise FailedPreCondition ( f \"Requested state { destination } is invalid\" ) @classmethod def perform ( cls , args , logger , cfg ): destination = args . get ( 'destination' , '' ) . strip () kpffiu = ktl . cache ( 'kpffiu' ) kpffiu [ 'FOLDNAM' ] . write ( destination ) @classmethod def post_condition ( cls , args , logger , cfg ): destination = args . get ( 'destination' , '' ) . strip () timeout = cfg . getfloat ( 'times' , 'fiu_fold_mirror_move_time' , fallback = 5 ) success = ktl . waitFor ( f '($kpffiu.foldnam == { destination } )' , timeout = timeout ) if success is not True : foldnam = ktl . cache ( 'kpffiu' , 'FOLDNAM' ) raise FailedToReachDestination ( foldnam . read (), destination ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'destination' , type = str , choices = [ 'in' , 'out' ], help = 'Desired fold mirror position' ) return super () . add_cmdline_args ( parser , cfg )","title":"ControlFoldMirror"},{"location":"scripts/ControlFoldMirror/#controlfoldmirror","text":"Bases: KPFTranslatorFunction Insert or remove the FIU Cal Fold Mirror from the beam. Parameters: destination ( str ) \u2013 The desired FIU fold mirror position name. Allowed values: in, out wait ( bool ) \u2013 Wait for move to complete before returning? (default: True) KTL Keywords Used: kpffiu.FOLDNAM Source code in kpf/fiu/ControlFoldMirror.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class ControlFoldMirror ( KPFTranslatorFunction ): '''Insert or remove the FIU Cal Fold Mirror from the beam. Args: destination (str): The desired FIU fold mirror position name. Allowed values: in, out wait (bool): Wait for move to complete before returning? (default: True) KTL Keywords Used: - `kpffiu.FOLDNAM` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): destination = args . get ( 'destination' , '' ) . strip () if destination . lower () not in [ 'in' , 'out' ]: raise FailedPreCondition ( f \"Requested state { destination } is invalid\" ) @classmethod def perform ( cls , args , logger , cfg ): destination = args . get ( 'destination' , '' ) . strip () kpffiu = ktl . cache ( 'kpffiu' ) kpffiu [ 'FOLDNAM' ] . write ( destination ) @classmethod def post_condition ( cls , args , logger , cfg ): destination = args . get ( 'destination' , '' ) . strip () timeout = cfg . getfloat ( 'times' , 'fiu_fold_mirror_move_time' , fallback = 5 ) success = ktl . waitFor ( f '($kpffiu.foldnam == { destination } )' , timeout = timeout ) if success is not True : foldnam = ktl . cache ( 'kpffiu' , 'FOLDNAM' ) raise FailedToReachDestination ( foldnam . read (), destination ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'destination' , type = str , choices = [ 'in' , 'out' ], help = 'Desired fold mirror position' ) return super () . add_cmdline_args ( parser , cfg )","title":"ControlFoldMirror"},{"location":"scripts/ControlHatch/","text":"ControlHatch Bases: KPFTranslatorFunction Open or close the FIU hatch Parameters: destination ( str ) \u2013 The desired FIU hatch position name. Allowed values: closed, open KTL Keywords Used: kpffiu.HATCH Source code in kpf/fiu/ControlHatch.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 class ControlHatch ( KPFTranslatorFunction ): '''Open or close the FIU hatch Args: destination (str): The desired FIU hatch position name. Allowed values: closed, open KTL Keywords Used: - `kpffiu.HATCH` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'destination' , allowed_values = [ 'closed' , 'open' ]) @classmethod def perform ( cls , args , logger , cfg ): destination = args . get ( 'destination' , '' ) . strip () kpffiu = ktl . cache ( 'kpffiu' ) kpffiu [ 'HATCH' ] . write ( destination ) @classmethod def post_condition ( cls , args , logger , cfg ): destination = args . get ( 'destination' , '' ) . strip () timeout = cfg . getfloat ( 'times' , 'fiu_hatch_move_time' , fallback = 1 ) success = ktl . waitFor ( f '($kpffiu.hatch == { destination } )' , timeout = timeout ) if success is not True : hatch = ktl . cache ( 'kpffiu' , 'HATCH' ) raise FailedToReachDestination ( hatch . read (), destination ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'destination' , type = str , choices = [ 'open' , 'closed' ], help = 'Desired hatch position' ) return super () . add_cmdline_args ( parser , cfg )","title":"ControlHatch"},{"location":"scripts/ControlHatch/#controlhatch","text":"Bases: KPFTranslatorFunction Open or close the FIU hatch Parameters: destination ( str ) \u2013 The desired FIU hatch position name. Allowed values: closed, open KTL Keywords Used: kpffiu.HATCH Source code in kpf/fiu/ControlHatch.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 class ControlHatch ( KPFTranslatorFunction ): '''Open or close the FIU hatch Args: destination (str): The desired FIU hatch position name. Allowed values: closed, open KTL Keywords Used: - `kpffiu.HATCH` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'destination' , allowed_values = [ 'closed' , 'open' ]) @classmethod def perform ( cls , args , logger , cfg ): destination = args . get ( 'destination' , '' ) . strip () kpffiu = ktl . cache ( 'kpffiu' ) kpffiu [ 'HATCH' ] . write ( destination ) @classmethod def post_condition ( cls , args , logger , cfg ): destination = args . get ( 'destination' , '' ) . strip () timeout = cfg . getfloat ( 'times' , 'fiu_hatch_move_time' , fallback = 1 ) success = ktl . waitFor ( f '($kpffiu.hatch == { destination } )' , timeout = timeout ) if success is not True : hatch = ktl . cache ( 'kpffiu' , 'HATCH' ) raise FailedToReachDestination ( hatch . read (), destination ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'destination' , type = str , choices = [ 'open' , 'closed' ], help = 'Desired hatch position' ) return super () . add_cmdline_args ( parser , cfg )","title":"ControlHatch"},{"location":"scripts/CorrectDAR/","text":"CorrectDAR Bases: KPFTranslatorFunction Modify the CURRENT_BASE keyword based upon the calculated differential atmospheric refraction value. This is NOT the recommended method for doing this as it is now done automatically in the kpfguide keyword service. This script predates full functionality of kpfguide and is being left in place only for emergency use. Calculation from Filippenko 1982 (PASP, 94:715-721, August 1982) ARGS: :EL: float Elevation of the telescope. Source code in kpf/utils/CorrectDAR.py 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class CorrectDAR ( KPFTranslatorFunction ): '''Modify the CURRENT_BASE keyword based upon the calculated differential atmospheric refraction value. This is NOT the recommended method for doing this as it is now done automatically in the `kpfguide` keyword service. This script predates full functionality of `kpfguide` and is being left in place only for emergency use. Calculation from Filippenko 1982 (PASP, 94:715-721, August 1982) ARGS: ===== :EL: `float` Elevation of the telescope. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) dcs = ktl . cache ( 'dcs1' ) EL = dcs [ 'EL' ] . read ( binary = True ) * 180 / np . pi DARarcsec = calculate_DAR_arcsec ( EL ) log . info ( f \"DAR is { DARarcsec : .3f } arcseconds\" ) dx , dy = calculate_DAR_pix ( DARarcsec ) total_pix = ( dx ** 2 + dy ** 2 ) ** 0.5 log . info ( f \"Pixel shift is { dx : .1f } , { dy : .1f } = { total_pix : .1f } \" ) base_names = { 'KPF' : 'SCIENCE_BASE' , 'SKY' : 'SKY_BASE' } POname = dcs [ 'PONAME' ] . read () base_name = base_names . get ( POname , None ) if base_name is None : log . error ( f \"dcs.PONAME= { POname } is not recognized\" ) log . error ( \"Leaving CURRENT_BASE unmodified\" ) return # log.error(f\"Using SCIENCE_BASE for testing\") # base_name = 'SCIENCE_BASE' # Set CURRENT_BASE log . info ( f \"dcs.PONAME is { POname } , using { base_name } as reference pixel\" ) reference_pix = list ( kpfguide [ base_name ] . read ( binary = True )) log . debug ( f \"Initial CURRENT_BASE = { reference_pix [ 0 ] : .1f } { reference_pix [ 1 ] : .1f } \" ) final_pixel = [ reference_pix [ 0 ] + dx , reference_pix [ 1 ] + dy ] final_pixel_string = f \" { final_pixel [ 0 ] : .2f } { final_pixel [ 1 ] : .2f } \" log . debug ( f \"Final Pixel = { final_pixel_string } \" ) min_x_pixel = cfg . getint ( 'guider' , 'min_x_pixel' , fallback = 0 ) max_x_pixel = cfg . getint ( 'guider' , 'max_x_pixel' , fallback = 640 ) min_y_pixel = cfg . getint ( 'guider' , 'min_y_pixel' , fallback = 0 ) max_y_pixel = cfg . getint ( 'guider' , 'max_y_pixel' , fallback = 512 ) if final_pixel [ 0 ] < min_x_pixel or final_pixel [ 0 ] > max_x_pixel or \\ final_pixel [ 1 ] < min_y_pixel or final_pixel [ 1 ] > max_y_pixel : log . error ( f \"Target pixel ( { final_pixel_string } ) is not on guide camera\" ) log . error ( \"Leaving CURRENT_BASE unmodified\" ) else : log . info ( f \"Writing new CURRENT_BASE = { final_pixel_string } \" ) kpfguide [ 'CURRENT_BASE' ] . write ( final_pixel ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"CorrectDAR"},{"location":"scripts/CorrectDAR/#correctdar","text":"Bases: KPFTranslatorFunction Modify the CURRENT_BASE keyword based upon the calculated differential atmospheric refraction value. This is NOT the recommended method for doing this as it is now done automatically in the kpfguide keyword service. This script predates full functionality of kpfguide and is being left in place only for emergency use. Calculation from Filippenko 1982 (PASP, 94:715-721, August 1982)","title":"CorrectDAR"},{"location":"scripts/CorrectDAR/#kpf.utils.CorrectDAR.CorrectDAR--args","text":":EL: float Elevation of the telescope. Source code in kpf/utils/CorrectDAR.py 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class CorrectDAR ( KPFTranslatorFunction ): '''Modify the CURRENT_BASE keyword based upon the calculated differential atmospheric refraction value. This is NOT the recommended method for doing this as it is now done automatically in the `kpfguide` keyword service. This script predates full functionality of `kpfguide` and is being left in place only for emergency use. Calculation from Filippenko 1982 (PASP, 94:715-721, August 1982) ARGS: ===== :EL: `float` Elevation of the telescope. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) dcs = ktl . cache ( 'dcs1' ) EL = dcs [ 'EL' ] . read ( binary = True ) * 180 / np . pi DARarcsec = calculate_DAR_arcsec ( EL ) log . info ( f \"DAR is { DARarcsec : .3f } arcseconds\" ) dx , dy = calculate_DAR_pix ( DARarcsec ) total_pix = ( dx ** 2 + dy ** 2 ) ** 0.5 log . info ( f \"Pixel shift is { dx : .1f } , { dy : .1f } = { total_pix : .1f } \" ) base_names = { 'KPF' : 'SCIENCE_BASE' , 'SKY' : 'SKY_BASE' } POname = dcs [ 'PONAME' ] . read () base_name = base_names . get ( POname , None ) if base_name is None : log . error ( f \"dcs.PONAME= { POname } is not recognized\" ) log . error ( \"Leaving CURRENT_BASE unmodified\" ) return # log.error(f\"Using SCIENCE_BASE for testing\") # base_name = 'SCIENCE_BASE' # Set CURRENT_BASE log . info ( f \"dcs.PONAME is { POname } , using { base_name } as reference pixel\" ) reference_pix = list ( kpfguide [ base_name ] . read ( binary = True )) log . debug ( f \"Initial CURRENT_BASE = { reference_pix [ 0 ] : .1f } { reference_pix [ 1 ] : .1f } \" ) final_pixel = [ reference_pix [ 0 ] + dx , reference_pix [ 1 ] + dy ] final_pixel_string = f \" { final_pixel [ 0 ] : .2f } { final_pixel [ 1 ] : .2f } \" log . debug ( f \"Final Pixel = { final_pixel_string } \" ) min_x_pixel = cfg . getint ( 'guider' , 'min_x_pixel' , fallback = 0 ) max_x_pixel = cfg . getint ( 'guider' , 'max_x_pixel' , fallback = 640 ) min_y_pixel = cfg . getint ( 'guider' , 'min_y_pixel' , fallback = 0 ) max_y_pixel = cfg . getint ( 'guider' , 'max_y_pixel' , fallback = 512 ) if final_pixel [ 0 ] < min_x_pixel or final_pixel [ 0 ] > max_x_pixel or \\ final_pixel [ 1 ] < min_y_pixel or final_pixel [ 1 ] > max_y_pixel : log . error ( f \"Target pixel ( { final_pixel_string } ) is not on guide camera\" ) log . error ( \"Leaving CURRENT_BASE unmodified\" ) else : log . info ( f \"Writing new CURRENT_BASE = { final_pixel_string } \" ) kpfguide [ 'CURRENT_BASE' ] . write ( final_pixel ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"ARGS:"},{"location":"scripts/CountCameraErrors/","text":"CountCameraErrors Bases: KPFTranslatorFunction Description Parameters Source code in kpf/engineering/analysis/CountCameraErrors.py 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 class CountCameraErrors ( KPFTranslatorFunction ): '''# Description # Parameters ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): output_file = Path ( '/s/sdata1701/KPFTranslator_logs/camera_errors.txt' ) if output_file . exists (): output_file . unlink () date = datetime . strptime ( '2023-06-01' , '%Y-%m- %d ' ) total_green_errors = 0 total_green_starts = 0 total_red_errors = 0 total_red_starts = 0 print ( f \"From { date . strftime ( '%Y-%m- %d ' ) } \" ) dates = [] green_errs = [] red_errs = [] green_starts = [] red_starts = [] with open ( output_file , 'w' ) as f : while date < datetime . utcnow () - timedelta ( days = 1 ): date_str = date . strftime ( '%Y-%m- %d ' ) ng_starts , nr_starts = count_start_state_instances ( date = date_str ) ng_errs , nr_errs = count_start_state_errors ( date = date_str ) dates . append ( date ) green_errs . append ( ng_errs ) red_errs . append ( nr_errs ) green_starts . append ( ng_starts ) red_starts . append ( nr_starts ) total_green_errors += ng_errs total_green_starts += ng_starts total_red_errors += nr_errs total_red_starts += nr_starts line = f \" { date_str } , { ng_errs } , { ng_starts } , { nr_errs } , { nr_starts } \" # print(line) f . write ( f \" { line } \\n \" ) date += timedelta ( days = 1 ) print ( f \"Through { date . strftime ( '%Y-%m- %d ' ) } \" ) green_error_rate = total_green_errors / total_green_starts print ( f \"Green error rate = { green_error_rate : .2% } ( { total_green_errors } / { total_green_starts } )\" ) red_error_rate = total_red_errors / total_red_starts print ( f \"Red error rate = { red_error_rate : .2% } ( { total_red_errors } / { total_red_starts } )\" ) plt . figure ( figsize = ( 12 , 8 )) plt . subplot ( 2 , 1 , 1 ) plt . title ( f \"Number of start errors per day\" ) plt . bar ( dates , green_errs , color = 'g' , alpha = 0.5 , width = 0.4 , align = 'edge' ) plt . bar ( dates , red_errs , color = 'r' , alpha = 0.5 , width =- 0.4 , align = 'edge' ) plt . ylabel ( 'N Errors' ) plt . subplot ( 2 , 1 , 2 ) plt . title ( f \"Rate of start errors per day\" ) plt . plot ( dates , np . array ( green_errs ) / np . array ( green_starts ) * 100 , 'go-' ) plt . plot ( dates , np . array ( red_errs ) / np . array ( red_starts ) * 100 , 'ro-' ) plt . ylabel ( ' % E rrors' ) plt . xlabel ( 'Date' ) plt . grid () plt . show () @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"CountCameraErrors"},{"location":"scripts/CountCameraErrors/#countcameraerrors","text":"Bases: KPFTranslatorFunction","title":"CountCameraErrors"},{"location":"scripts/CountCameraErrors/#kpf.engineering.analysis.CountCameraErrors.CountCameraErrors--description","text":"","title":"Description"},{"location":"scripts/CountCameraErrors/#kpf.engineering.analysis.CountCameraErrors.CountCameraErrors--parameters","text":"Source code in kpf/engineering/analysis/CountCameraErrors.py 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 class CountCameraErrors ( KPFTranslatorFunction ): '''# Description # Parameters ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): output_file = Path ( '/s/sdata1701/KPFTranslator_logs/camera_errors.txt' ) if output_file . exists (): output_file . unlink () date = datetime . strptime ( '2023-06-01' , '%Y-%m- %d ' ) total_green_errors = 0 total_green_starts = 0 total_red_errors = 0 total_red_starts = 0 print ( f \"From { date . strftime ( '%Y-%m- %d ' ) } \" ) dates = [] green_errs = [] red_errs = [] green_starts = [] red_starts = [] with open ( output_file , 'w' ) as f : while date < datetime . utcnow () - timedelta ( days = 1 ): date_str = date . strftime ( '%Y-%m- %d ' ) ng_starts , nr_starts = count_start_state_instances ( date = date_str ) ng_errs , nr_errs = count_start_state_errors ( date = date_str ) dates . append ( date ) green_errs . append ( ng_errs ) red_errs . append ( nr_errs ) green_starts . append ( ng_starts ) red_starts . append ( nr_starts ) total_green_errors += ng_errs total_green_starts += ng_starts total_red_errors += nr_errs total_red_starts += nr_starts line = f \" { date_str } , { ng_errs } , { ng_starts } , { nr_errs } , { nr_starts } \" # print(line) f . write ( f \" { line } \\n \" ) date += timedelta ( days = 1 ) print ( f \"Through { date . strftime ( '%Y-%m- %d ' ) } \" ) green_error_rate = total_green_errors / total_green_starts print ( f \"Green error rate = { green_error_rate : .2% } ( { total_green_errors } / { total_green_starts } )\" ) red_error_rate = total_red_errors / total_red_starts print ( f \"Red error rate = { red_error_rate : .2% } ( { total_red_errors } / { total_red_starts } )\" ) plt . figure ( figsize = ( 12 , 8 )) plt . subplot ( 2 , 1 , 1 ) plt . title ( f \"Number of start errors per day\" ) plt . bar ( dates , green_errs , color = 'g' , alpha = 0.5 , width = 0.4 , align = 'edge' ) plt . bar ( dates , red_errs , color = 'r' , alpha = 0.5 , width =- 0.4 , align = 'edge' ) plt . ylabel ( 'N Errors' ) plt . subplot ( 2 , 1 , 2 ) plt . title ( f \"Rate of start errors per day\" ) plt . plot ( dates , np . array ( green_errs ) / np . array ( green_starts ) * 100 , 'go-' ) plt . plot ( dates , np . array ( red_errs ) / np . array ( red_starts ) * 100 , 'ro-' ) plt . ylabel ( ' % E rrors' ) plt . xlabel ( 'Date' ) plt . grid () plt . show () @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"Parameters"},{"location":"scripts/DisableSoCal/","text":"DisableSoCal Bases: KPFTranslatorFunction Disables SoCal by setting kpfsocal.CAN_OPEN to No. ARGS: None Source code in kpf/socal/DisableSoCal.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class DisableSoCal ( KPFTranslatorFunction ): '''Disables SoCal by setting kpfsocal.CAN_OPEN to No. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): CAN_OPEN = ktl . cache ( 'kpfsocal' , 'CAN_OPEN' ) log . info ( 'Setting kpfsocal.CAN_OPEN = 0' ) CAN_OPEN . write ( 0 ) @classmethod def post_condition ( cls , args , logger , cfg ): CAN_OPEN = ktl . cache ( 'kpfsocal' , 'CAN_OPEN' ) success = CAN_OPEN . waitFor ( \"==0\" , timeout = 1 ) if success is False : raise FailedToReachDestination ( 'kpfsocal.CAN_OPEN is not 0' )","title":"DisableSoCal"},{"location":"scripts/DisableSoCal/#disablesocal","text":"Bases: KPFTranslatorFunction Disables SoCal by setting kpfsocal.CAN_OPEN to No.","title":"DisableSoCal"},{"location":"scripts/DisableSoCal/#kpf.socal.DisableSoCal.DisableSoCal--args","text":"None Source code in kpf/socal/DisableSoCal.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class DisableSoCal ( KPFTranslatorFunction ): '''Disables SoCal by setting kpfsocal.CAN_OPEN to No. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): CAN_OPEN = ktl . cache ( 'kpfsocal' , 'CAN_OPEN' ) log . info ( 'Setting kpfsocal.CAN_OPEN = 0' ) CAN_OPEN . write ( 0 ) @classmethod def post_condition ( cls , args , logger , cfg ): CAN_OPEN = ktl . cache ( 'kpfsocal' , 'CAN_OPEN' ) success = CAN_OPEN . waitFor ( \"==0\" , timeout = 1 ) if success is False : raise FailedToReachDestination ( 'kpfsocal.CAN_OPEN is not 0' )","title":"ARGS:"},{"location":"scripts/DisplayGuiderContinuous/","text":"DisplayGuiderContinuous Bases: KPFTranslatorFunction Continuously display latest guider images to ds9 using xpaset . KTL Keywords Used: kpfguide.LASTFILE Source code in kpf/guider/DisplayGuiderContinuous.py 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 class DisplayGuiderContinuous ( KPFTranslatorFunction ): '''Continuously display latest guider images to ds9 using `xpaset`. KTL Keywords Used: - `kpfguide.LASTFILE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): display_name = cfg . get ( 'display' , 'guider_xpa_target' , fallback = 'CRED2' ) lastfile = ktl . cache ( 'kpfguide' , 'LASTFILE' ) initial_lastfile = lastfile . read () while True : expr = f \"($kpfguide.LASTFILE != ' { initial_lastfile } ')\" is_there_a_newfile = ktl . waitFor ( expr , timeout = 10 ) if is_there_a_newfile is True : initial_lastfile = lastfile . read () print ( f \"Displaying { initial_lastfile } \" ) ds9cmd = [ 'xpaset' , display_name , 'fits' , f \" { initial_lastfile } \" , '<' , f \" { initial_lastfile } \" ] # log.debug(f\"Running: {' '.join(ds9cmd)}\") subprocess . call ( ' ' . join ( ds9cmd ), shell = True ) regfile = Path ( f '/home/kpfeng/fibers_on_cred2.reg' ) if regfile . exists () is True : overlaycmd = [ 'xpaset' , '-p' , display_name , 'regions' , 'file' , f \" { regfile } \" ] # log.debug(f\"Running: {' '.join(overlaycmd)}\") subprocess . call ( ' ' . join ( overlaycmd ), shell = True ) time . sleep ( 0.5 ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"DisplayGuiderContinuous"},{"location":"scripts/DisplayGuiderContinuous/#displayguidercontinuous","text":"Bases: KPFTranslatorFunction Continuously display latest guider images to ds9 using xpaset . KTL Keywords Used: kpfguide.LASTFILE Source code in kpf/guider/DisplayGuiderContinuous.py 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 class DisplayGuiderContinuous ( KPFTranslatorFunction ): '''Continuously display latest guider images to ds9 using `xpaset`. KTL Keywords Used: - `kpfguide.LASTFILE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): display_name = cfg . get ( 'display' , 'guider_xpa_target' , fallback = 'CRED2' ) lastfile = ktl . cache ( 'kpfguide' , 'LASTFILE' ) initial_lastfile = lastfile . read () while True : expr = f \"($kpfguide.LASTFILE != ' { initial_lastfile } ')\" is_there_a_newfile = ktl . waitFor ( expr , timeout = 10 ) if is_there_a_newfile is True : initial_lastfile = lastfile . read () print ( f \"Displaying { initial_lastfile } \" ) ds9cmd = [ 'xpaset' , display_name , 'fits' , f \" { initial_lastfile } \" , '<' , f \" { initial_lastfile } \" ] # log.debug(f\"Running: {' '.join(ds9cmd)}\") subprocess . call ( ' ' . join ( ds9cmd ), shell = True ) regfile = Path ( f '/home/kpfeng/fibers_on_cred2.reg' ) if regfile . exists () is True : overlaycmd = [ 'xpaset' , '-p' , display_name , 'regions' , 'file' , f \" { regfile } \" ] # log.debug(f\"Running: {' '.join(overlaycmd)}\") subprocess . call ( ' ' . join ( overlaycmd ), shell = True ) time . sleep ( 0.5 ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"DisplayGuiderContinuous"},{"location":"scripts/EnableSoCal/","text":"EnableSoCal Bases: KPFTranslatorFunction Enables SoCal by setting kpfsocal.CAN_OPEN to Yes. ARGS: None Source code in kpf/socal/EnableSoCal.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class EnableSoCal ( KPFTranslatorFunction ): '''Enables SoCal by setting kpfsocal.CAN_OPEN to Yes. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): CAN_OPEN = ktl . cache ( 'kpfsocal' , 'CAN_OPEN' ) log . info ( 'Setting kpfsocal.CAN_OPEN = 1' ) CAN_OPEN . write ( 1 ) @classmethod def post_condition ( cls , args , logger , cfg ): CAN_OPEN = ktl . cache ( 'kpfsocal' , 'CAN_OPEN' ) success = CAN_OPEN . waitFor ( \"==1\" , timeout = 1 ) if success is False : raise FailedToReachDestination ( 'kpfsocal.CAN_OPEN is not 1' )","title":"EnableSoCal"},{"location":"scripts/EnableSoCal/#enablesocal","text":"Bases: KPFTranslatorFunction Enables SoCal by setting kpfsocal.CAN_OPEN to Yes.","title":"EnableSoCal"},{"location":"scripts/EnableSoCal/#kpf.socal.EnableSoCal.EnableSoCal--args","text":"None Source code in kpf/socal/EnableSoCal.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class EnableSoCal ( KPFTranslatorFunction ): '''Enables SoCal by setting kpfsocal.CAN_OPEN to Yes. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): CAN_OPEN = ktl . cache ( 'kpfsocal' , 'CAN_OPEN' ) log . info ( 'Setting kpfsocal.CAN_OPEN = 1' ) CAN_OPEN . write ( 1 ) @classmethod def post_condition ( cls , args , logger , cfg ): CAN_OPEN = ktl . cache ( 'kpfsocal' , 'CAN_OPEN' ) success = CAN_OPEN . waitFor ( \"==1\" , timeout = 1 ) if success is False : raise FailedToReachDestination ( 'kpfsocal.CAN_OPEN is not 1' )","title":"ARGS:"},{"location":"scripts/EndOfNight/","text":"EndOfNight Bases: KPFTranslatorFunction 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) Source code in kpf/scripts/EndOfNight.py 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 class EndOfNight ( KPFTranslatorFunction ): '''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 , logger , cfg ): pass @classmethod @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , args , logger , cfg ): StopTipTilt . execute ({}) StopAgitator . execute ({}) # Start FIU stow log . info ( 'Setting FIU mode to Stowed' ) ConfigureFIU . execute ({ 'mode' : 'Stowed' , 'wait' : False }) # --------------------------------- # User Verification for AO Shutdown # --------------------------------- 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 , logger , cfg ): pass","title":"EndOfNight"},{"location":"scripts/EndOfNight/#endofnight","text":"Bases: KPFTranslatorFunction 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","title":"EndOfNight"},{"location":"scripts/EndOfNight/#kpf.scripts.EndOfNight.EndOfNight--args","text":":AO: (bool) Close AO hatch, home PCU, and turn on HEPA? (default=True) Source code in kpf/scripts/EndOfNight.py 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 class EndOfNight ( KPFTranslatorFunction ): '''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 , logger , cfg ): pass @classmethod @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , args , logger , cfg ): StopTipTilt . execute ({}) StopAgitator . execute ({}) # Start FIU stow log . info ( 'Setting FIU mode to Stowed' ) ConfigureFIU . execute ({ 'mode' : 'Stowed' , 'wait' : False }) # --------------------------------- # User Verification for AO Shutdown # --------------------------------- 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 , logger , cfg ): pass","title":"ARGS:"},{"location":"scripts/EnterLowPowerMode/","text":"EnterLowPowerMode Bases: KPFTranslatorFunction Set KPF to a low power mode. This is intended for use during power outages. This reduces power use in the AO electronics room. We do not currently recommend any changes in the basement due to the sensitivity of the spectrograph to thermal changes. Procedure: - If a script is running exit or terminate it (depending on --force arg) - Disable HK detector - Stop HK cooling - Power off HK systems: J1, J2, J5 - Stop CRED2 exposures (CONTINUOUS and SAVE) - Stop CRED2 cooling (if on) - Power off CRED2 (K2, K3) Source code in kpf/scripts/EnterLowPowerMode.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class EnterLowPowerMode ( KPFTranslatorFunction ): '''Set KPF to a low power mode. This is intended for use during power outages. This reduces power use in the AO electronics room. We do not currently recommend any changes in the basement due to the sensitivity of the spectrograph to thermal changes. Procedure: - If a script is running exit or terminate it (depending on --force arg) - Disable HK detector - Stop HK cooling - Power off HK systems: J1, J2, J5 - Stop CRED2 exposures (CONTINUOUS and SAVE) - Stop CRED2 cooling (if on) - Power off CRED2 (K2, K3) ''' @classmethod def pre_condition ( cls , args , logger , cfg ): log . info ( 'Configuring KPF for Low Power Mode' ) force = args . get ( 'force' , False ) SCRIPTNAME = ktl . cache ( 'kpfconfig' , 'SCRIPTNAME' ) SCRIPTNAME . monitor () if SCRIPTNAME not in [ 'None' , '' ]: log . warning ( f 'A script ( { SCRIPTNAME } ) is running' ) if force is True : log . warning ( f 'Requesting script stop' ) kpfconfig [ 'SCRIPTSTOP' ] . write ( 'Yes' ) no_script_running = SCRIPTNAME . waitFor ( \"==''\" , timeout = 120 ) if no_script_running is False : log . error ( 'Script failed to stop' ) raise FailedToReachDestination ( f ' { SCRIPTNAME . read () } ' , '' ) else : raise FailedPreCondition ( 'A script is running, not setting Low Power Mode' ) @classmethod def perform ( cls , args , logger , cfg ): kpfconfig = ktl . cache ( 'kpfconfig' ) kpfpower = ktl . cache ( 'kpfpower' ) # Power down Ca HK detector systems kpf_hk = ktl . cache ( 'kpf_hk' ) log . info ( 'Disabling Ca HK detector' ) kpfconfig [ 'CA_HK_ENABLED' ] . write ( 'No' ) log . info ( 'Turning Ca HK detector cooling off' ) kpf_hk [ 'COOLING' ] . write ( 'off' ) time . sleep ( 3 ) log . info ( 'Powering off Ca HK detector systems' ) log . debug ( f \"Powering off { kpfpower [ 'OUTLET_J1_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_J1' ] . write ( 'Off' ) log . debug ( f \"Powering off { kpfpower [ 'OUTLET_J2_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_J2' ] . write ( 'Off' ) log . debug ( f \"Powering off { kpfpower [ 'OUTLET_J5_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_J5' ] . write ( 'Off' ) # Power down CRED2 detector systems kpfguide = ktl . cache ( 'kpfguide' ) log . info ( 'Powering off CRED2 detector systems' ) kpfguide [ 'CONTINUOUS' ] . write ( 'Inactive' ) kpfguide [ 'SAVE' ] . write ( 'Inactive' ) time . sleep ( 2 ) log . debug ( f \"Powering off { kpfpower [ 'OUTLET_K2_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_K2' ] . write ( 'Off' ) log . debug ( f \"Powering off { kpfpower [ 'OUTLET_K3_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_K3' ] . write ( 'Off' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--force\" , dest = \"force\" , default = False , action = \"store_true\" , help = \"Force change? This will terminate any running scripts.\" ) return super () . add_cmdline_args ( parser , cfg )","title":"EnterLowPowerMode"},{"location":"scripts/EnterLowPowerMode/#enterlowpowermode","text":"Bases: KPFTranslatorFunction Set KPF to a low power mode. This is intended for use during power outages. This reduces power use in the AO electronics room. We do not currently recommend any changes in the basement due to the sensitivity of the spectrograph to thermal changes. Procedure: - If a script is running exit or terminate it (depending on --force arg) - Disable HK detector - Stop HK cooling - Power off HK systems: J1, J2, J5 - Stop CRED2 exposures (CONTINUOUS and SAVE) - Stop CRED2 cooling (if on) - Power off CRED2 (K2, K3) Source code in kpf/scripts/EnterLowPowerMode.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class EnterLowPowerMode ( KPFTranslatorFunction ): '''Set KPF to a low power mode. This is intended for use during power outages. This reduces power use in the AO electronics room. We do not currently recommend any changes in the basement due to the sensitivity of the spectrograph to thermal changes. Procedure: - If a script is running exit or terminate it (depending on --force arg) - Disable HK detector - Stop HK cooling - Power off HK systems: J1, J2, J5 - Stop CRED2 exposures (CONTINUOUS and SAVE) - Stop CRED2 cooling (if on) - Power off CRED2 (K2, K3) ''' @classmethod def pre_condition ( cls , args , logger , cfg ): log . info ( 'Configuring KPF for Low Power Mode' ) force = args . get ( 'force' , False ) SCRIPTNAME = ktl . cache ( 'kpfconfig' , 'SCRIPTNAME' ) SCRIPTNAME . monitor () if SCRIPTNAME not in [ 'None' , '' ]: log . warning ( f 'A script ( { SCRIPTNAME } ) is running' ) if force is True : log . warning ( f 'Requesting script stop' ) kpfconfig [ 'SCRIPTSTOP' ] . write ( 'Yes' ) no_script_running = SCRIPTNAME . waitFor ( \"==''\" , timeout = 120 ) if no_script_running is False : log . error ( 'Script failed to stop' ) raise FailedToReachDestination ( f ' { SCRIPTNAME . read () } ' , '' ) else : raise FailedPreCondition ( 'A script is running, not setting Low Power Mode' ) @classmethod def perform ( cls , args , logger , cfg ): kpfconfig = ktl . cache ( 'kpfconfig' ) kpfpower = ktl . cache ( 'kpfpower' ) # Power down Ca HK detector systems kpf_hk = ktl . cache ( 'kpf_hk' ) log . info ( 'Disabling Ca HK detector' ) kpfconfig [ 'CA_HK_ENABLED' ] . write ( 'No' ) log . info ( 'Turning Ca HK detector cooling off' ) kpf_hk [ 'COOLING' ] . write ( 'off' ) time . sleep ( 3 ) log . info ( 'Powering off Ca HK detector systems' ) log . debug ( f \"Powering off { kpfpower [ 'OUTLET_J1_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_J1' ] . write ( 'Off' ) log . debug ( f \"Powering off { kpfpower [ 'OUTLET_J2_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_J2' ] . write ( 'Off' ) log . debug ( f \"Powering off { kpfpower [ 'OUTLET_J5_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_J5' ] . write ( 'Off' ) # Power down CRED2 detector systems kpfguide = ktl . cache ( 'kpfguide' ) log . info ( 'Powering off CRED2 detector systems' ) kpfguide [ 'CONTINUOUS' ] . write ( 'Inactive' ) kpfguide [ 'SAVE' ] . write ( 'Inactive' ) time . sleep ( 2 ) log . debug ( f \"Powering off { kpfpower [ 'OUTLET_K2_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_K2' ] . write ( 'Off' ) log . debug ( f \"Powering off { kpfpower [ 'OUTLET_K3_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_K3' ] . write ( 'Off' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--force\" , dest = \"force\" , default = False , action = \"store_true\" , help = \"Force change? This will terminate any running scripts.\" ) return super () . add_cmdline_args ( parser , cfg )","title":"EnterLowPowerMode"},{"location":"scripts/EstimateOBDuration/","text":"EstimateOBDuration Bases: KPFTranslatorFunction Estimate the duration of the input OB. This script will determine the OB type (science or calibration) and invoke either EstimateCalOBDuration or EstimateSciOBDuration ARGS: :OB: dict A fully specified observing block (OB). Source code in kpf/utils/EstimateOBDuration.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 class EstimateOBDuration ( KPFTranslatorFunction ): '''Estimate the duration of the input OB. This script will determine the OB type (science or calibration) and invoke either `EstimateCalOBDuration` or `EstimateSciOBDuration` ARGS: ===== :OB: `dict` A fully specified observing block (OB). ''' @classmethod def pre_condition ( cls , OB , logger , cfg ): pass @classmethod def perform ( cls , OB , logger , cfg ): if OB [ 'Template_Name' ] == 'kpf_cal' : return EstimateCalOBDuration . execute ( OB ) elif OB [ 'Template_Name' ] == 'kpf_sci' : return EstimateSciOBDuration . execute ( OB ) else : print ( f \"Time estimate not supported for { OB [ 'Template_Name' ] } type\" ) @classmethod def post_condition ( cls , OB , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( '--fast' , '--fastread' , dest = \"fast\" , default = False , action = \"store_true\" , help = 'Use fast readout mode times for estimate?' ) return super () . add_cmdline_args ( parser , cfg )","title":"EstimateOBDuration"},{"location":"scripts/EstimateOBDuration/#estimateobduration","text":"Bases: KPFTranslatorFunction Estimate the duration of the input OB. This script will determine the OB type (science or calibration) and invoke either EstimateCalOBDuration or EstimateSciOBDuration","title":"EstimateOBDuration"},{"location":"scripts/EstimateOBDuration/#kpf.utils.EstimateOBDuration.EstimateOBDuration--args","text":":OB: dict A fully specified observing block (OB). Source code in kpf/utils/EstimateOBDuration.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 class EstimateOBDuration ( KPFTranslatorFunction ): '''Estimate the duration of the input OB. This script will determine the OB type (science or calibration) and invoke either `EstimateCalOBDuration` or `EstimateSciOBDuration` ARGS: ===== :OB: `dict` A fully specified observing block (OB). ''' @classmethod def pre_condition ( cls , OB , logger , cfg ): pass @classmethod def perform ( cls , OB , logger , cfg ): if OB [ 'Template_Name' ] == 'kpf_cal' : return EstimateCalOBDuration . execute ( OB ) elif OB [ 'Template_Name' ] == 'kpf_sci' : return EstimateSciOBDuration . execute ( OB ) else : print ( f \"Time estimate not supported for { OB [ 'Template_Name' ] } type\" ) @classmethod def post_condition ( cls , OB , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( '--fast' , '--fastread' , dest = \"fast\" , default = False , action = \"store_true\" , help = 'Use fast readout mode times for estimate?' ) return super () . add_cmdline_args ( parser , cfg )","title":"ARGS:"},{"location":"scripts/ExecuteSlewCal/","text":"ExecuteSlewCal Bases: KPFTranslatorFunction Script which executes the observations of a Slew Cal This must have arguments as input, either from a file using the -f command line tool, or passed in from the execution engine. ARGS: :OB: dict A fully specified slew cal observing block (OB). Source code in kpf/scripts/ExecuteSlewCal.py 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 class ExecuteSlewCal ( KPFTranslatorFunction ): '''Script which executes the observations of a Slew Cal This must have arguments as input, either from a file using the `-f` command line tool, or passed in from the execution engine. ARGS: ===== :OB: `dict` A fully specified slew cal observing block (OB). ''' abortable = True @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'Template_Name' , allowed_values = [ 'kpf_slewcal' ]) check_input ( args , 'Template_Version' , version_check = True , value_min = '0.4' ) @classmethod def perform ( cls , args , logger , cfg ): set_script_keywords ( Path ( __file__ ) . name , os . getpid ()) log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in args : log . debug ( f \" { key } : { args [ key ] } \" ) log . info ( '-------------------------' ) kpfconfig = ktl . cache ( 'kpfconfig' ) calsource = kpfconfig [ 'SIMULCALSOURCE' ] . read () runagitator = kpfconfig [ 'USEAGITATOR' ] . read ( binary = True ) fast_read_mode = QueryFastReadMode . execute ({}) # Fill in args in case this is not called by configure for acquisition if args . get ( 'TriggerCaHK' , None ) is None : args [ 'TriggerCaHK' ] = False if args . get ( 'TriggerGreen' , None ) is None : args [ 'TriggerGreen' ] = True if args . get ( 'TriggerRed' , None ) is None : args [ 'TriggerRed' ] = True # Skip this lamp if it is not enabled if IsCalSourceEnabled . execute ({ 'CalSource' : calsource }) == False : return # Set Octagon calsource = kpfconfig [ 'SIMULCALSOURCE' ] . read () octagon = ktl . cache ( 'kpfcal' , 'OCTAGON' ) . read () log . debug ( f \"Current OCTAGON = { octagon } , desired = { calsource } \" ) if octagon != calsource : log . info ( f \"Set CalSource/Octagon: { calsource } \" ) SetCalSource . execute ({ 'CalSource' : calsource , 'wait' : False }) progname = ktl . cache ( 'kpfexpose' , 'PROGNAME' ) original_progname = progname . read () ## ---------------------------------------------------------------- ## First, configure lamps and cal bench (may happen during readout) ## ---------------------------------------------------------------- log . info ( f \"Configuring FIU\" ) ConfigureFIU . execute ({ 'mode' : 'Calibration' , 'wait' : False }) check_scriptstop () # Stop here if requested # Configure Cal Bench nd1 = args . get ( 'CalND1' ) nd2 = args . get ( 'CalND2' ) log . info ( f \"Set ND1, ND2 Filter Wheels: { nd1 } , { nd2 } \" ) SetND1 . execute ({ 'CalND1' : nd1 , 'wait' : False }) SetND2 . execute ({ 'CalND2' : nd2 , 'wait' : False }) log . info ( f \"Waiting for Octagon/CalSource, ND1, ND2, FIU\" ) WaitForND1 . execute ( args ) WaitForND2 . execute ( args ) WaitForCalSource . execute ({ 'CalSource' : calsource }) WaitForConfigureFIU . execute ({ 'mode' : 'Calibration' }) check_scriptstop () # Stop here if requested ## ---------------------------------------------------------------- ## Second, configure kpfexpose (may not happen during readout) ## ---------------------------------------------------------------- # Wait for current exposure to readout exposestatus = ktl . cache ( 'kpfexpose' , 'EXPOSE' ) if exposestatus . read () != 'Ready' : log . info ( f \"Waiting for kpfexpose to be Ready\" ) WaitForReady . execute ({}) log . info ( f \"Readout complete\" ) check_scriptstop () # Stop here if requested log . info ( f \"Set Detector List\" ) SetTriggeredDetectors . execute ( args ) log . info ( f \"Set Source Select Shutters\" ) SetSourceSelectShutters . execute ({ 'SSS_Science' : True , 'SSS_Sky' : True , 'SSS_SoCalSci' : False , 'SSS_SoCalCal' : False , 'SSS_CalSciSky' : True }) log . info ( f \"Set exposure time: { args . get ( 'ExpTime' ) : .3f } \" ) SetExpTime . execute ( args ) # No need to specify TimedShutter_Scrambler args [ 'TimedShutter_Scrambler' ] = True log . debug ( f \"Automatically setting TimedShutter_Scrambler: { args [ 'TimedShutter_Scrambler' ] } \" ) # No need to specify TimedShutter_CaHK args [ 'TimedShutter_CaHK' ] = args . get ( 'TriggerCaHK' , False ) log . debug ( f \"Automatically setting TimedShutter_CaHK: { args [ 'TimedShutter_CaHK' ] } \" ) # No need to specify TimedShutter_FlatField args [ 'TimedShutter_FlatField' ] = False log . debug ( f \"Automatically setting TimedShutter_FlatField: { args [ 'TimedShutter_FlatField' ] } \" ) # Set TimedShutter_SimulCal args [ 'TimedShutter_SimulCal' ] = args [ 'TakeSimulCal' ] log . debug ( f \"Automatically setting TimedShutter_SimulCal: { args [ 'TimedShutter_SimulCal' ] } \" ) log . info ( f \"Setting timed shutters\" ) SetTimedShutters . execute ( args ) log . info ( f \"Setting OBJECT: { args . get ( 'Object' ) } \" ) SetObject . execute ( args ) log . info ( f \"Clearing stellar parameters\" ) SetTargetInfo . execute ({}) SetProgram . execute ({ 'progname' : 'ENG' }) ## ---------------------------------------------------------------- ## Third, take actual exposures ## ---------------------------------------------------------------- nexp = args . get ( 'nExp' , 1 ) # If we are in fast read mode, turn on agitator once if runagitator and fast_read_mode : StartAgitator . execute ({}) for j in range ( nexp ): check_scriptstop () # Stop here if requested # Wait for current exposure to readout if exposestatus . read () != 'Ready' : log . info ( f \"Waiting for kpfexpose to be Ready\" ) WaitForReady . execute ({}) log . info ( f \"Readout complete\" ) check_scriptstop () # Stop here if requested # Start next exposure if runagitator and not fast_read_mode : StartAgitator . execute ({}) log . info ( f \"Starting expoure { j + 1 } / { nexp } ( { args . get ( 'Object' ) } )\" ) StartExposure . execute ({}) WaitForReadout . execute ({}) log . info ( f \"Readout has begun\" ) if runagitator and not fast_read_mode : StopAgitator . execute ({}) ZeroOutSlewCalTime . execute ({}) # If we are in fast read mode, turn off agitator at end if runagitator and fast_read_mode : StopAgitator . execute ({}) # Set FIU Mode log . info ( 'Setting FIU mode to Observing' ) ConfigureFIU . execute ({ 'mode' : 'Observing' , 'wait' : False }) # Set PROGNAME log . info ( f 'Setting PROGNAME back to { original_progname } ' ) SetProgram . execute ({ 'progname' : original_progname }) clear_script_keywords () @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"ExecuteSlewCal"},{"location":"scripts/ExecuteSlewCal/#executeslewcal","text":"Bases: KPFTranslatorFunction Script which executes the observations of a Slew Cal This must have arguments as input, either from a file using the -f command line tool, or passed in from the execution engine.","title":"ExecuteSlewCal"},{"location":"scripts/ExecuteSlewCal/#kpf.scripts.ExecuteSlewCal.ExecuteSlewCal--args","text":":OB: dict A fully specified slew cal observing block (OB). Source code in kpf/scripts/ExecuteSlewCal.py 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 class ExecuteSlewCal ( KPFTranslatorFunction ): '''Script which executes the observations of a Slew Cal This must have arguments as input, either from a file using the `-f` command line tool, or passed in from the execution engine. ARGS: ===== :OB: `dict` A fully specified slew cal observing block (OB). ''' abortable = True @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'Template_Name' , allowed_values = [ 'kpf_slewcal' ]) check_input ( args , 'Template_Version' , version_check = True , value_min = '0.4' ) @classmethod def perform ( cls , args , logger , cfg ): set_script_keywords ( Path ( __file__ ) . name , os . getpid ()) log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in args : log . debug ( f \" { key } : { args [ key ] } \" ) log . info ( '-------------------------' ) kpfconfig = ktl . cache ( 'kpfconfig' ) calsource = kpfconfig [ 'SIMULCALSOURCE' ] . read () runagitator = kpfconfig [ 'USEAGITATOR' ] . read ( binary = True ) fast_read_mode = QueryFastReadMode . execute ({}) # Fill in args in case this is not called by configure for acquisition if args . get ( 'TriggerCaHK' , None ) is None : args [ 'TriggerCaHK' ] = False if args . get ( 'TriggerGreen' , None ) is None : args [ 'TriggerGreen' ] = True if args . get ( 'TriggerRed' , None ) is None : args [ 'TriggerRed' ] = True # Skip this lamp if it is not enabled if IsCalSourceEnabled . execute ({ 'CalSource' : calsource }) == False : return # Set Octagon calsource = kpfconfig [ 'SIMULCALSOURCE' ] . read () octagon = ktl . cache ( 'kpfcal' , 'OCTAGON' ) . read () log . debug ( f \"Current OCTAGON = { octagon } , desired = { calsource } \" ) if octagon != calsource : log . info ( f \"Set CalSource/Octagon: { calsource } \" ) SetCalSource . execute ({ 'CalSource' : calsource , 'wait' : False }) progname = ktl . cache ( 'kpfexpose' , 'PROGNAME' ) original_progname = progname . read () ## ---------------------------------------------------------------- ## First, configure lamps and cal bench (may happen during readout) ## ---------------------------------------------------------------- log . info ( f \"Configuring FIU\" ) ConfigureFIU . execute ({ 'mode' : 'Calibration' , 'wait' : False }) check_scriptstop () # Stop here if requested # Configure Cal Bench nd1 = args . get ( 'CalND1' ) nd2 = args . get ( 'CalND2' ) log . info ( f \"Set ND1, ND2 Filter Wheels: { nd1 } , { nd2 } \" ) SetND1 . execute ({ 'CalND1' : nd1 , 'wait' : False }) SetND2 . execute ({ 'CalND2' : nd2 , 'wait' : False }) log . info ( f \"Waiting for Octagon/CalSource, ND1, ND2, FIU\" ) WaitForND1 . execute ( args ) WaitForND2 . execute ( args ) WaitForCalSource . execute ({ 'CalSource' : calsource }) WaitForConfigureFIU . execute ({ 'mode' : 'Calibration' }) check_scriptstop () # Stop here if requested ## ---------------------------------------------------------------- ## Second, configure kpfexpose (may not happen during readout) ## ---------------------------------------------------------------- # Wait for current exposure to readout exposestatus = ktl . cache ( 'kpfexpose' , 'EXPOSE' ) if exposestatus . read () != 'Ready' : log . info ( f \"Waiting for kpfexpose to be Ready\" ) WaitForReady . execute ({}) log . info ( f \"Readout complete\" ) check_scriptstop () # Stop here if requested log . info ( f \"Set Detector List\" ) SetTriggeredDetectors . execute ( args ) log . info ( f \"Set Source Select Shutters\" ) SetSourceSelectShutters . execute ({ 'SSS_Science' : True , 'SSS_Sky' : True , 'SSS_SoCalSci' : False , 'SSS_SoCalCal' : False , 'SSS_CalSciSky' : True }) log . info ( f \"Set exposure time: { args . get ( 'ExpTime' ) : .3f } \" ) SetExpTime . execute ( args ) # No need to specify TimedShutter_Scrambler args [ 'TimedShutter_Scrambler' ] = True log . debug ( f \"Automatically setting TimedShutter_Scrambler: { args [ 'TimedShutter_Scrambler' ] } \" ) # No need to specify TimedShutter_CaHK args [ 'TimedShutter_CaHK' ] = args . get ( 'TriggerCaHK' , False ) log . debug ( f \"Automatically setting TimedShutter_CaHK: { args [ 'TimedShutter_CaHK' ] } \" ) # No need to specify TimedShutter_FlatField args [ 'TimedShutter_FlatField' ] = False log . debug ( f \"Automatically setting TimedShutter_FlatField: { args [ 'TimedShutter_FlatField' ] } \" ) # Set TimedShutter_SimulCal args [ 'TimedShutter_SimulCal' ] = args [ 'TakeSimulCal' ] log . debug ( f \"Automatically setting TimedShutter_SimulCal: { args [ 'TimedShutter_SimulCal' ] } \" ) log . info ( f \"Setting timed shutters\" ) SetTimedShutters . execute ( args ) log . info ( f \"Setting OBJECT: { args . get ( 'Object' ) } \" ) SetObject . execute ( args ) log . info ( f \"Clearing stellar parameters\" ) SetTargetInfo . execute ({}) SetProgram . execute ({ 'progname' : 'ENG' }) ## ---------------------------------------------------------------- ## Third, take actual exposures ## ---------------------------------------------------------------- nexp = args . get ( 'nExp' , 1 ) # If we are in fast read mode, turn on agitator once if runagitator and fast_read_mode : StartAgitator . execute ({}) for j in range ( nexp ): check_scriptstop () # Stop here if requested # Wait for current exposure to readout if exposestatus . read () != 'Ready' : log . info ( f \"Waiting for kpfexpose to be Ready\" ) WaitForReady . execute ({}) log . info ( f \"Readout complete\" ) check_scriptstop () # Stop here if requested # Start next exposure if runagitator and not fast_read_mode : StartAgitator . execute ({}) log . info ( f \"Starting expoure { j + 1 } / { nexp } ( { args . get ( 'Object' ) } )\" ) StartExposure . execute ({}) WaitForReadout . execute ({}) log . info ( f \"Readout has begun\" ) if runagitator and not fast_read_mode : StopAgitator . execute ({}) ZeroOutSlewCalTime . execute ({}) # If we are in fast read mode, turn off agitator at end if runagitator and fast_read_mode : StopAgitator . execute ({}) # Set FIU Mode log . info ( 'Setting FIU mode to Observing' ) ConfigureFIU . execute ({ 'mode' : 'Observing' , 'wait' : False }) # Set PROGNAME log . info ( f 'Setting PROGNAME back to { original_progname } ' ) SetProgram . execute ({ 'progname' : original_progname }) clear_script_keywords () @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"ARGS:"},{"location":"scripts/FVCPower/","text":"FVCPower Bases: KPFTranslatorFunction Turn on or off the power for the specified FVC camera. Parameters: camera ( str ) \u2013 Which FVC camera? Allowed values: SCI, CAHK, EXT, CAL power ( str ) \u2013 The desired state. Allowed values: on or off KTL Keywords Used: kpfpower.KPFFVC1 kpfpower.KPFFVC2 kpfpower.KPFFVC3 Source code in kpf/fvc/FVCPower.py 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class FVCPower ( KPFTranslatorFunction ): '''Turn on or off the power for the specified FVC camera. Args: camera (str): Which FVC camera? Allowed values: SCI, CAHK, EXT, CAL power (str): The desired state. Allowed values: on or off KTL Keywords Used: - `kpfpower.KPFFVC1` - `kpfpower.KPFFVC2` - `kpfpower.KPFFVC3` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'camera' , allowed_values = [ 'SCI' , 'CAHK' , 'CAL' ]) @classmethod def perform ( cls , args , logger , cfg ): camera = args . get ( 'camera' ) camnum = { 'SCI' : 1 , 'CAHK' : 2 , 'CAL' : 3 }[ camera ] powerkw = ktl . cache ( 'kpfpower' , f 'KPFFVC { camnum } ' ) dest = args . get ( 'power' ) if powerkw . read () . lower () != dest . lower (): log . info ( f \"Turning { dest } { camera } FVC\" ) powerkw . write ( args . get ( 'power' )) shim = cfg . getfloat ( 'times' , 'fvc_command_timeshim' , fallback = 2 ) time . sleep ( shim ) @classmethod def post_condition ( cls , args , logger , cfg ): camera = args . get ( 'camera' ) camnum = { 'SCI' : 1 , 'CAHK' : 2 , 'CAL' : 3 }[ camera ] powerkw = ktl . cache ( 'kpfpower' , f 'KPFFVC { camnum } ' ) timeout = cfg . getfloat ( 'times' , 'fvc_command_timeout' , fallback = 1 ) dest = args . get ( 'power' ) success = powerkw . waitFor ( f \"== ' { dest } '\" , timeout = timeout ) if success is False : raise FailedToReachDestination ( powerkw . read (), dest ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'camera' , type = str , choices = [ 'SCI' , 'CAHK' , 'CAL' ], help = 'The FVC camera' ) parser . add_argument ( 'power' , type = str , choices = [ 'on' , 'off' ], help = 'Desired power state: \"on\" or \"off\"' ) return super () . add_cmdline_args ( parser , cfg )","title":"FVCPower"},{"location":"scripts/FVCPower/#fvcpower","text":"Bases: KPFTranslatorFunction Turn on or off the power for the specified FVC camera. Parameters: camera ( str ) \u2013 Which FVC camera? Allowed values: SCI, CAHK, EXT, CAL power ( str ) \u2013 The desired state. Allowed values: on or off KTL Keywords Used: kpfpower.KPFFVC1 kpfpower.KPFFVC2 kpfpower.KPFFVC3 Source code in kpf/fvc/FVCPower.py 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class FVCPower ( KPFTranslatorFunction ): '''Turn on or off the power for the specified FVC camera. Args: camera (str): Which FVC camera? Allowed values: SCI, CAHK, EXT, CAL power (str): The desired state. Allowed values: on or off KTL Keywords Used: - `kpfpower.KPFFVC1` - `kpfpower.KPFFVC2` - `kpfpower.KPFFVC3` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'camera' , allowed_values = [ 'SCI' , 'CAHK' , 'CAL' ]) @classmethod def perform ( cls , args , logger , cfg ): camera = args . get ( 'camera' ) camnum = { 'SCI' : 1 , 'CAHK' : 2 , 'CAL' : 3 }[ camera ] powerkw = ktl . cache ( 'kpfpower' , f 'KPFFVC { camnum } ' ) dest = args . get ( 'power' ) if powerkw . read () . lower () != dest . lower (): log . info ( f \"Turning { dest } { camera } FVC\" ) powerkw . write ( args . get ( 'power' )) shim = cfg . getfloat ( 'times' , 'fvc_command_timeshim' , fallback = 2 ) time . sleep ( shim ) @classmethod def post_condition ( cls , args , logger , cfg ): camera = args . get ( 'camera' ) camnum = { 'SCI' : 1 , 'CAHK' : 2 , 'CAL' : 3 }[ camera ] powerkw = ktl . cache ( 'kpfpower' , f 'KPFFVC { camnum } ' ) timeout = cfg . getfloat ( 'times' , 'fvc_command_timeout' , fallback = 1 ) dest = args . get ( 'power' ) success = powerkw . waitFor ( f \"== ' { dest } '\" , timeout = timeout ) if success is False : raise FailedToReachDestination ( powerkw . read (), dest ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'camera' , type = str , choices = [ 'SCI' , 'CAHK' , 'CAL' ], help = 'The FVC camera' ) parser . add_argument ( 'power' , type = str , choices = [ 'on' , 'off' ], help = 'Desired power state: \"on\" or \"off\"' ) return super () . add_cmdline_args ( parser , cfg )","title":"FVCPower"},{"location":"scripts/Fit2DGridSearch/","text":"Fit2DGridSearch Bases: KPFTranslatorFunction Description Take two 1D grid search runs (one in X and one in Y) ... Parameters None Source code in kpf/engineering/analysis/Fit2DGridSearch.py 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 class Fit2DGridSearch ( KPFTranslatorFunction ): '''# Description Take two 1D grid search runs (one in X and one in Y) ... # Parameters None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # 20240718at140930_GridSearch.log # TipTilt20240718at140930_GridSearch.fits log_file_x = Path ( args . get ( 'logfileX' )) fgs_cube_fileX = log_file_x . parent / Path ( f 'TipTilt { log_file_x . stem } .fits' ) log_file_y = Path ( args . get ( 'logfileY' )) fgs_cube_fileY = log_file_y . parent / Path ( f 'TipTilt { log_file_y . stem } .fits' ) # Try to determine targname/comment try : with open ( log_file_x ) as FO : lines = FO . readlines () for line in lines [: 60 ]: m_comment = re . search ( \"comment: (.*)\" , line ) if m_comment is not None : comment = m_comment . groups ()[ 0 ] . strip ( ' \\n ' ) log . info ( f \" Log Comment: { comment } \" ) except : comment = '' fit_2D_fiber_center ( fgs_cube_fileX , fgs_cube_fileY , xcent = args . get ( 'xfit' ), ycent = args . get ( 'yfit' ), targname = comment ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'logfileX' , type = str , help = \"The GridSearch log file for the X pixel scan\" ) parser . add_argument ( 'logfileY' , type = str , help = \"The GridSearch log file for the Y pixel scan\" ) parser . add_argument ( \"--xfit\" , dest = \"xfit\" , type = float , default = 335.5 , help = \"The X pixel position to use as the center when overlaying the model.\" ) parser . add_argument ( \"--yfit\" , dest = \"yfit\" , type = float , default = 258 , help = \"The X pixel position to use as the center when overlaying the model.\" ) return super () . add_cmdline_args ( parser , cfg )","title":"Fit2DGridSearch"},{"location":"scripts/Fit2DGridSearch/#fit2dgridsearch","text":"Bases: KPFTranslatorFunction","title":"Fit2DGridSearch"},{"location":"scripts/Fit2DGridSearch/#kpf.engineering.analysis.Fit2DGridSearch.Fit2DGridSearch--description","text":"Take two 1D grid search runs (one in X and one in Y) ...","title":"Description"},{"location":"scripts/Fit2DGridSearch/#kpf.engineering.analysis.Fit2DGridSearch.Fit2DGridSearch--parameters","text":"None Source code in kpf/engineering/analysis/Fit2DGridSearch.py 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 class Fit2DGridSearch ( KPFTranslatorFunction ): '''# Description Take two 1D grid search runs (one in X and one in Y) ... # Parameters None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # 20240718at140930_GridSearch.log # TipTilt20240718at140930_GridSearch.fits log_file_x = Path ( args . get ( 'logfileX' )) fgs_cube_fileX = log_file_x . parent / Path ( f 'TipTilt { log_file_x . stem } .fits' ) log_file_y = Path ( args . get ( 'logfileY' )) fgs_cube_fileY = log_file_y . parent / Path ( f 'TipTilt { log_file_y . stem } .fits' ) # Try to determine targname/comment try : with open ( log_file_x ) as FO : lines = FO . readlines () for line in lines [: 60 ]: m_comment = re . search ( \"comment: (.*)\" , line ) if m_comment is not None : comment = m_comment . groups ()[ 0 ] . strip ( ' \\n ' ) log . info ( f \" Log Comment: { comment } \" ) except : comment = '' fit_2D_fiber_center ( fgs_cube_fileX , fgs_cube_fileY , xcent = args . get ( 'xfit' ), ycent = args . get ( 'yfit' ), targname = comment ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'logfileX' , type = str , help = \"The GridSearch log file for the X pixel scan\" ) parser . add_argument ( 'logfileY' , type = str , help = \"The GridSearch log file for the Y pixel scan\" ) parser . add_argument ( \"--xfit\" , dest = \"xfit\" , type = float , default = 335.5 , help = \"The X pixel position to use as the center when overlaying the model.\" ) parser . add_argument ( \"--yfit\" , dest = \"yfit\" , type = float , default = 258 , help = \"The X pixel position to use as the center when overlaying the model.\" ) return super () . add_cmdline_args ( parser , cfg )","title":"Parameters"},{"location":"scripts/GetGaiaStars/","text":"GetGaiaStars Bases: KPFTranslatorFunction Build a ds9 region file of Gaia catalog stars which ought to be present in the specified guider image. Parameters: file ( str ) \u2013 The file to retrieve stars for. Source code in kpf/guider/GetGaiaStars.py 20 21 22 23 24 25 26 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 class GetGaiaStars ( KPFTranslatorFunction ): '''Build a ds9 region file of Gaia catalog stars which ought to be present in the specified guider image. Args: file (str): The file to retrieve stars for. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): if Vizier is None : raise FailedPreCondition ( 'Unable to import astroquery.vizier' ) file = Path ( args . get ( 'file' , '/tmp/CRED2.fits' )) . expanduser () . absolute () if file . exists () is False : raise FailedPreCondition ( f 'Fould not find input file: { file } ' ) @classmethod def perform ( cls , args , logger , cfg ): catalog_id = cfg . get ( 'stellar_catalog' , 'catalog_id' , fallback = 'I/345/gaia2' ) search_radius = cfg . getfloat ( 'stellar_catalog' , 'search_radius' , fallback = 28 ) ds9_color = cfg . get ( 'stellar_catalog' , 'ds9_color' , fallback = 'cyan' ) ds9_font = cfg . get ( 'stellar_catalog' , 'ds9_font' , fallback = 'helvetica 10 normal roman' ) requery_threshold = cfg . getfloat ( 'stellar_catalog' , 'requery_threshold' , fallback = 5 ) region_file = Path ( '~/.CRED2_auto_regions.reg' ) . expanduser () cntr_file = Path ( '~/.CRED2_auto_regions.cntr' ) . expanduser () file = Path ( args . get ( 'file' , './junk.fits' )) . expanduser () . absolute () # hdul = fits.open(file) header = fits . getheader ( file ) w = WCS ( header ) # cntr = w.pixel_to_world(hdul[0].data.shape[0]/2, hdul[0].data.shape[1]/2) cntr = w . pixel_to_world ( int ( header . get ( 'NAXIS2' )) / 2 , int ( header . get ( 'NAXIS1' )) / 2 ) if cntr_file . exists () is False : with open ( cntr_file , 'w' ) as FO : FO . write ( cntr . to_string ( 'hmsdms' , precision = 2 )) else : with open ( cntr_file , 'r' ) as FO : cntr_file_string = FO . readlines () file_cntr = SkyCoord ( cntr_file_string , unit = ( u . hourangle , u . deg ), frame = 'icrs' ) sep = file_cntr . separation ( cntr ) # If we're in a new position, query for a new catalog of stars and # write a new region file if sep [ 0 ] . to ( u . arcsec ) . value > requery_threshold : print ( f 'Querying for catalog: { cntr . to_string ( \"hmsdms\" , precision = 2 ) } ' ) gaia = Vizier . query_region ( cntr , radius = search_radius * u . arcsec , catalog = catalog_id )[ 0 ] regions = [ f '# Region file format: DS9 version 4.1' , f 'global color= { ds9_color } dashlist=8 3 width=1 font=\" { ds9_font } \"' , ] for star in gaia : sc = SkyCoord ( star [ 'RA_ICRS' ], star [ 'DE_ICRS' ], unit = ( u . deg , u . deg ), frame = 'icrs' ) coord_string = sc . to_string ( 'hmsdms' , sep = ':' , precision = 2 ) . replace ( ' ' , ',' ) newline = f \"circle( { coord_string } ,0.5 \\\" )\" # \\# text=\\{\"#\\}\" newline += \" # text={\" newline += f \" { star [ 'RPmag' ] : .1f } \" newline += \"}\" regions . append ( newline ) if region_file . exists (): region_file . unlink () with open ( region_file , 'w' ) as FO : for line in regions : FO . write ( line + ' \\n ' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'file' , type = str , help = 'The CRED2 file to retrieve stars for' ) return super () . add_cmdline_args ( parser , cfg )","title":"GetGaiaStars"},{"location":"scripts/GetGaiaStars/#getgaiastars","text":"Bases: KPFTranslatorFunction Build a ds9 region file of Gaia catalog stars which ought to be present in the specified guider image. Parameters: file ( str ) \u2013 The file to retrieve stars for. Source code in kpf/guider/GetGaiaStars.py 20 21 22 23 24 25 26 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 class GetGaiaStars ( KPFTranslatorFunction ): '''Build a ds9 region file of Gaia catalog stars which ought to be present in the specified guider image. Args: file (str): The file to retrieve stars for. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): if Vizier is None : raise FailedPreCondition ( 'Unable to import astroquery.vizier' ) file = Path ( args . get ( 'file' , '/tmp/CRED2.fits' )) . expanduser () . absolute () if file . exists () is False : raise FailedPreCondition ( f 'Fould not find input file: { file } ' ) @classmethod def perform ( cls , args , logger , cfg ): catalog_id = cfg . get ( 'stellar_catalog' , 'catalog_id' , fallback = 'I/345/gaia2' ) search_radius = cfg . getfloat ( 'stellar_catalog' , 'search_radius' , fallback = 28 ) ds9_color = cfg . get ( 'stellar_catalog' , 'ds9_color' , fallback = 'cyan' ) ds9_font = cfg . get ( 'stellar_catalog' , 'ds9_font' , fallback = 'helvetica 10 normal roman' ) requery_threshold = cfg . getfloat ( 'stellar_catalog' , 'requery_threshold' , fallback = 5 ) region_file = Path ( '~/.CRED2_auto_regions.reg' ) . expanduser () cntr_file = Path ( '~/.CRED2_auto_regions.cntr' ) . expanduser () file = Path ( args . get ( 'file' , './junk.fits' )) . expanduser () . absolute () # hdul = fits.open(file) header = fits . getheader ( file ) w = WCS ( header ) # cntr = w.pixel_to_world(hdul[0].data.shape[0]/2, hdul[0].data.shape[1]/2) cntr = w . pixel_to_world ( int ( header . get ( 'NAXIS2' )) / 2 , int ( header . get ( 'NAXIS1' )) / 2 ) if cntr_file . exists () is False : with open ( cntr_file , 'w' ) as FO : FO . write ( cntr . to_string ( 'hmsdms' , precision = 2 )) else : with open ( cntr_file , 'r' ) as FO : cntr_file_string = FO . readlines () file_cntr = SkyCoord ( cntr_file_string , unit = ( u . hourangle , u . deg ), frame = 'icrs' ) sep = file_cntr . separation ( cntr ) # If we're in a new position, query for a new catalog of stars and # write a new region file if sep [ 0 ] . to ( u . arcsec ) . value > requery_threshold : print ( f 'Querying for catalog: { cntr . to_string ( \"hmsdms\" , precision = 2 ) } ' ) gaia = Vizier . query_region ( cntr , radius = search_radius * u . arcsec , catalog = catalog_id )[ 0 ] regions = [ f '# Region file format: DS9 version 4.1' , f 'global color= { ds9_color } dashlist=8 3 width=1 font=\" { ds9_font } \"' , ] for star in gaia : sc = SkyCoord ( star [ 'RA_ICRS' ], star [ 'DE_ICRS' ], unit = ( u . deg , u . deg ), frame = 'icrs' ) coord_string = sc . to_string ( 'hmsdms' , sep = ':' , precision = 2 ) . replace ( ' ' , ',' ) newline = f \"circle( { coord_string } ,0.5 \\\" )\" # \\# text=\\{\"#\\}\" newline += \" # text={\" newline += f \" { star [ 'RPmag' ] : .1f } \" newline += \"}\" regions . append ( newline ) if region_file . exists (): region_file . unlink () with open ( region_file , 'w' ) as FO : for line in regions : FO . write ( line + ' \\n ' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'file' , type = str , help = 'The CRED2 file to retrieve stars for' ) return super () . add_cmdline_args ( parser , cfg )","title":"GetGaiaStars"},{"location":"scripts/GridSearch/","text":"GridSearch Bases: KPFTranslatorFunction Executes an engineering grid search OB. This must have arguments as input, either from a file using the -f command line tool, or passed in from the execution engine. ARGS: None Source code in kpf/engineering/GridSearch.py 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 class GridSearch ( KPFTranslatorFunction ): '''Executes an engineering grid search OB. This must have arguments as input, either from a file using the `-f` command line tool, or passed in from the execution engine. ARGS: ===== None ''' abortable = True @classmethod @obey_scriptrun def pre_condition ( cls , OB , logger , cfg ): check_input ( OB , 'Template_Name' , allowed_values = [ 'kpf_eng_grid' ]) check_input ( OB , 'Template_Version' , version_check = True , value_min = '0.4' ) check_input ( OB , 'Grid' , allowed_values = [ 'TipTilt' , 'SciADC' ]) check_input ( OB , 'nx' ) check_input ( OB , 'ny' ) check_input ( OB , 'dx' ) check_input ( OB , 'dy' ) check_input ( OB , 'ExpMeter_exptime' ) FVCs = OB . get ( 'FVCs' , '' ) . split ( ',' ) for FVC in FVCs : if FVC not in [ 'SCI' , 'CAHK' , 'EXT' , '' ]: raise FailedPreCondition ( f \"FVC { FVC } not supported\" ) @classmethod @register_script ( Path ( __file__ ) . name , os . getpid ()) @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in OB : log . debug ( f \" { key } : { OB [ key ] } \" ) log . info ( '-------------------------' ) grid = OB . get ( 'Grid' ) this_file_name = Path ( __file__ ) . name . replace ( '.py' , '' ) utnow = datetime . utcnow () now_str = utnow . strftime ( '%Y%m %d at%H%M%S' ) date_str = ( utnow - timedelta ( days = 1 )) . strftime ( '%Y%b %d ' ) . lower () log_path = Path ( f '/s/sdata1701/KPFTranslator_logs/ { date_str } ' ) images_file = log_path / Path ( f ' { grid }{ this_file_name } _images_ { now_str } .txt' ) fluxes_file = log_path / Path ( f ' { grid }{ this_file_name } _fluxes_ { now_str } .txt' ) images = Table ( names = ( 'file' , 'camera' , 'x' , 'y' ), dtype = ( 'a90' , 'a10' , 'f4' , 'f4' )) expmeter_flux = Table ( names = ( 'i' , 'j' , 'x' , 'y' , 'bck1' , 'bck2' , 'bck3' , 'bck4' , 'cur1' , 'cur2' , 'cur3' , 'cur4' , 'raw1' , 'raw2' , 'raw3' , 'raw4' , 'nimages' ), dtype = ( 'i4' , 'i4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'i4' )) FVCs = OB . get ( 'FVCs' , '' ) . split ( ',' ) nx = OB . get ( 'nx' ) ny = OB . get ( 'ny' ) dx = OB . get ( 'dx' ) dy = OB . get ( 'dy' ) xis = [ xi for xi in range ( int ( - nx / 2 ), int (( nx + 1 ) / 2 ), 1 )] yis = [ yi for yi in range ( int ( - ny / 2 ), int (( ny + 1 ) / 2 ), 1 )] xindicies = [ ind for ind in range ( nx )] yindicies = [ ind for ind in range ( ny )] xs = [ xi * dx for xi in xis ] ys = [ yi * dy for yi in yis ] # Set up guider (assume parameters set during acquisition of star) kpfguide = ktl . cache ( 'kpfguide' ) log . info ( 'Setting TRIGCUBE Inactive' ) kpfguide [ 'TRIGCUBE' ] . write ( 'Inactive' ) if grid == 'TipTilt' : log . info ( f \"DAR_ENABLE = { kpfguide [ 'DAR_ENABLE' ] . read () } \" ) dar_offset = kpfguide [ 'DAR_OFFSET' ] . read ( binary = True ) log . info ( f \"DAR_OFFSET = { dar_offset [ 0 ] : .2f } { dar_offset [ 1 ] : .2f } \" ) xpix0 , ypix0 = kpfguide [ 'PIX_TARGET' ] . read ( binary = True ) log . info ( f \"PIX_TARGET is { xpix0 : .2f } , { ypix0 : .2f } \" ) basex , basey = kpfguide [ 'CURRENT_BASE' ] . read ( binary = True ) log . info ( f \"CURRENT_BASE is { basex : .2f } , { basey : .2f } \" ) # Pixel targets must be in absolute coordinates xs = [ basex + xpix for xpix in xs ] ys = [ basey + ypix for ypix in ys ] elif grid == 'SciADC' : kpffiu = ktl . cache ( 'kpffiu' ) kpffiu [ 'ADCTRACK' ] . write ( 'Off' ) nominalx , nominaly = kpffiu [ 'ADCPRISMS' ] . read ( binary = True ) x0 = OB . get ( 'ADC1Position' ) if str ( x0 ) . lower () == 'nominal' : x0 = nominalx else : x0 = float ( OB . get ( 'ADC1Position' )) y0 = OB . get ( 'ADC2Position' ) if str ( y0 ) . lower () == 'nominal' : y0 = nominaly else : y0 = float ( OB . get ( 'ADC2Position' )) log . info ( f \"ADC starting position: { x0 : .1f } { y0 : .1f } \" ) # Apply reverse rotation if requested if OB . get ( 'ADC1Reverse' , False ) is True : x0 = - x0 if OB . get ( 'ADC2Reverse' , False ) is True : y0 = - y0 log . info ( f \"ADC reverse nominal position: { x0 : .1f } { y0 : .1f } \" ) # Apply flip if requested if OB . get ( 'ADC1Flip' , False ) is True : x0 += 180 if OB . get ( 'ADC2Flip' , False ) is True : y0 += 180 log . info ( f \"ADC flip nominal position: { x0 : .1f } { y0 : .1f } \" ) xs = [ x + x0 for x in xs ] ys = [ y + y0 for y in ys ] # Set up kpfexpose kpfexpose = ktl . cache ( 'kpfexpose' ) SetSourceSelectShutters . execute ( OB ) OB [ 'TimedShutter_Scrambler' ] = True OB [ 'TimedShutter_CaHK' ] = OB . get ( 'TriggerCaHK' , False ) SetTimedShutters . execute ( OB ) SetTriggeredDetectors . execute ( OB ) total_exptime = OB . get ( 'TimeOnPosition' ) SetExpTime . execute ({ 'ExpTime' : total_exptime }) # Configure Exposure Meter kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) ExpMeter_exptime = OB . get ( 'ExpMeter_exptime' ) log . info ( f \"Setting kpf_expmeter.EXPOSURE = { ExpMeter_exptime : .2f } s\" ) kpf_expmeter [ 'EXPOSURE' ] . write ( ExpMeter_exptime ) # Set up FVCs kpffvc = ktl . cache ( 'kpffvc' ) for FVC in [ 'SCI' , 'CAHK' , 'EXT' ]: if FVC in FVCs and OB . get ( f ' { FVC } FVC_exptime' , None ) != None : exptime = OB . get ( f ' { FVC } FVC_exptime' ) log . info ( f \"Setting { FVC } FVC ExpTime = { exptime : .2f } s\" ) SetFVCExpTime . execute ({ 'camera' : FVC , 'exptime' : exptime }) for i in xindicies : yindicies . reverse () for j in yindicies : check_scriptstop () if grid == 'TipTilt' : ##------------------------------------------------------ ## Tip Tilt ##------------------------------------------------------ log . info ( f \"Adjusting CURRENT_BASE to ( { xs [ i ] : .2f } , { ys [ j ] : .2f } ) ( { xis [ i ] } , { yis [ j ] } )\" ) max_move = 3 precisison = 0.01 current_base = ktl . cache ( 'kpfguide' , 'CURRENT_BASE' ) current_cb = current_base . read ( binary = True ) delta_cb = ( xs [ i ] - current_cb [ 0 ], ys [ j ] - current_cb [ 1 ]) while abs ( delta_cb [ 0 ]) > precisison or abs ( delta_cb [ 1 ]) > precisison : # Calc X move new_X_target = current_cb [ 0 ] if abs ( delta_cb [ 0 ]) > precisison : move_sign_X = delta_cb [ 0 ] / abs ( delta_cb [ 0 ]) move_mag_X = min ([ max_move , abs ( delta_cb [ 0 ])]) new_X_target += move_sign_X * move_mag_X # Calc Y move new_Y_target = current_cb [ 1 ] if abs ( delta_cb [ 1 ]) > precisison : move_sign_Y = delta_cb [ 1 ] / abs ( delta_cb [ 1 ]) move_mag_Y = min ([ max_move , abs ( delta_cb [ 1 ])]) new_Y_target += move_sign_Y * move_mag_Y log . info ( f \" Setting CURRENT_BASE to { new_X_target : .2f } , { new_Y_target : .2f } \" ) SetTipTiltTargetPixel . execute ({ 'x' : new_X_target , 'y' : new_Y_target }) success = ktl . waitFor ( \"$kpfguide.TIPTILT_PHASE == 'Tracking'\" , timeout = 5 ) current_cb = current_base . read ( binary = True ) delta_cb = ( xs [ i ] - current_cb [ 0 ], ys [ j ] - current_cb [ 1 ]) xpix , ypix = kpfguide [ 'PIX_TARGET' ] . read ( binary = True ) log . info ( f \"PIX_TARGET is { xpix : .2f } , { ypix : .2f } \" ) # Check for lost star obj_choice = kpfguide [ 'OBJECT_CHOICE' ] . read () if obj_choice in [ None , 'None' ]: log . error ( f \" --> Lost star <--\" ) log . info ( f \"Stopping tip tilt\" ) StopTipTilt . execute ({}) time . sleep ( 1 ) log . info ( f \"Starting tip tilt\" ) StartTipTilt . execute ({}) time . sleep ( 5 ) # Check for lost star obj_choice = kpfguide [ 'OBJECT_CHOICE' ] . read () if obj_choice in [ None , 'None' ]: log . error ( f \" --> Lost star <--\" ) subprocess . call ([ 'kpf' , 'restart' , 'kpfguide2' ]) time . sleep ( 5 ) log . info ( f \"Starting tip tilt\" ) StartTipTilt . execute ({}) time . sleep ( 5 ) obj_choice = kpfguide [ 'OBJECT_CHOICE' ] . read () if obj_choice in [ None , 'None' ]: log . error ( f \" --> Lost star <--\" ) raise KPFException ( 'Lost Star' ) elif grid == 'SciADC' : ##------------------------------------------------------ ## Science ADC ##------------------------------------------------------ log . info ( f \"Offsetting to ( { xs [ i ] : .2f } , { ys [ j ] : .2f } ) ( { xis [ i ] } , { yis [ j ] } )\" ) kpffiu [ 'ADC1VAL' ] . write ( xs [ i ]) kpffiu [ 'ADC2VAL' ] . write ( ys [ j ]) log . info ( f \"Absolute position: { xs [ i ] : .1f } { ys [ j ] : .1f } \" ) expr = '($kpffiu.ADC1STA == Ready) and ($kpffiu.ADC2STA == Ready)' success = ktl . waitFor ( expr , timeout = 2 * max ([ dx * nx , dy * ny ]) / 5 ) if success is not True : ADC1STA = kpffiu [ 'ADC1STA' ] . read () ADC2STA = kpffiu [ 'ADC2STA' ] . read () msg = f 'Timed out waiting for ADCs: ADC1STA= { ADC1STA } ADC2STA= { ADC2STA } ' raise KPFException ( msg ) WaitForReady . execute ({}) check_scriptstop () # Stop here if requested # Start Exposure Meter and Science Cameras kpfexpose [ 'OBJECT' ] . write ( f 'Grid search { xs [ i ] } , { ys [ j ] } ' ) log . info ( f \"Starting kpfexpose cameras\" ) StartExposure . execute ({}) # Begin timestamp for history retrieval begin = time . time () # Take CRED2 image if OB . get ( 'UseCRED2' , True ) is True : log . info ( 'Starting guider Trigger file' ) initial_last_cube = kpfguide [ 'LASTTRIGFILE' ] . read () StartTriggerFile . execute ({}) # Start FVC Exposures initial_lastfile = {} failedFVCs = [] for FVC in [ 'SCI' , 'CAHK' , 'EXT' ]: if FVC in FVCs : initial_lastfile [ FVC ] = kpffvc [ f \" { FVC } LASTFILE\" ] . read () log . debug ( f \" Initial lastfile for { FVC } = { initial_lastfile [ FVC ] } \" ) log . info ( f \" Starting { FVC } FVC exposure\" ) try : TakeFVCExposure . execute ({ 'camera' : FVC , 'wait' : False }) except : log . error ( 'Starting FVC image failed' ) failedFVCs . append ( FVC ) check_scriptstop () # Collect files for FVC exposures for FVC in [ 'SCI' , 'CAHK' , 'EXT' ]: if FVC in FVCs and FVC not in failedFVCs : log . info ( f \" Looking for output file for { FVC } \" ) expr = f '($kpffvc. { FVC } LASTFILE != \" { initial_lastfile [ FVC ] } \")' log . debug ( f \" Waiting for: { expr } \" ) if ktl . waitFor ( expr , timeout = 20 ) is False : lastfile = kpffvc [ f ' { FVC } LASTFILE' ] . read () log . error ( 'No new FVC file found' ) log . error ( f \" kpffvc. { FVC } LASTFILE = { lastfile } \" ) else : lastfile = kpffvc [ f ' { FVC } LASTFILE' ] . read () log . debug ( f \"Found { lastfile } \" ) row = { 'file' : lastfile , 'camera' : FVC , 'x' : xs [ i ], 'y' : ys [ j ]} images . add_row ( row ) check_scriptstop () # Here's where we wait for the remainder of the TimeOnPosition log . info ( f \" Waiting for kpfexpose to be ready\" ) WaitForReady . execute ({}) # Collect CRED2 File if OB . get ( 'UseCRED2' , True ) is True : StopTriggerFile . execute ({}) WaitForTriggerFile . execute ({ 'initial_lastfile' : initial_last_cube }) last_cube = kpfguide [ 'LASTTRIGFILE' ] . read () row = { 'file' : last_cube , 'camera' : 'CRED2' , 'x' : xs [ i ], 'y' : ys [ j ]} images . add_row ( row ) # Stop Exposure Meter log . info ( f \" Waiting for ExpMeter to be Ready\" ) EMsuccess = ktl . waitFor ( '$kpf_expmeter.EXPSTATE == Ready' , timeout = 5 ) time . sleep ( 0.5 ) # Time shim because paranoia if EMsuccess is True : lastfile = kpf_expmeter [ 'FITSFILE' ] . read () else : lastfile = 'failed' log . debug ( f ' Done. FITSFILE= { lastfile } ' ) row = { 'file' : lastfile , 'camera' : 'ExpMeter' , 'x' : xs [ i ], 'y' : ys [ j ]} images . add_row ( row ) if EMsuccess is True : loutfile = kpf_expmeter [ 'LOUTFILE' ] . read () else : loutfile = 'failed' log . debug ( f ' Done. LOUTFILE= { loutfile } ' ) row = { 'file' : loutfile , 'camera' : 'ExpMeter_1Dspec' , 'x' : xs [ i ], 'y' : ys [ j ]} images . add_row ( row ) # Retrieve keyword history end = time . time () expmeter_data = { 'x' : xs [ i ], 'y' : ys [ j ], 'i' : i , 'j' : j , } log . info ( f \" Retrieving keyword history\" ) for counts_kw in [ 'CUR_COUNTS' , 'RAW_COUNTS' , 'BCK_COUNTS' ]: log . debug ( f \" Retrieving keyword history for { counts_kw } \" ) kws = { 'kpf_expmeter' : [ counts_kw ]} counts_history = keygrabber . retrieve ( kws , begin = begin , end = end ) # Extract counts and save to table (initial style output) fluxes = np . zeros (( len ( counts_history ) - 2 , 4 )) for k , entry in enumerate ( counts_history ): if k != 0 and k != len ( counts_history ) - 1 : value_floats = [ float ( v ) for v in entry [ 'ascvalue' ] . split ()] ts = datetime . fromtimestamp ( entry [ 'time' ]) . strftime ( '%Y-%m- %d %H:%M:%S' ) log . debug ( f \" { ts } : { value_floats } \" ) fluxes [ k - 1 ] = value_floats avg_fluxes = np . mean ( fluxes , axis = 0 ) expmeter_data [ f \" { counts_kw [: 3 ] . lower () } 1\" ] = avg_fluxes [ 0 ] expmeter_data [ f \" { counts_kw [: 3 ] . lower () } 2\" ] = avg_fluxes [ 1 ] expmeter_data [ f \" { counts_kw [: 3 ] . lower () } 3\" ] = avg_fluxes [ 2 ] expmeter_data [ f \" { counts_kw [: 3 ] . lower () } 4\" ] = avg_fluxes [ 3 ] expmeter_data [ 'nimages' ] = len ( counts_history ) expmeter_flux . add_row ( expmeter_data ) if images_file . exists (): images_file . unlink () images . write ( images_file , format = 'ascii.csv' ) if fluxes_file . exists (): fluxes_file . unlink () expmeter_flux . write ( fluxes_file , format = 'ascii.csv' ) if images_file . exists (): images_file . unlink () images . write ( images_file , format = 'ascii.csv' ) if fluxes_file . exists (): fluxes_file . unlink () expmeter_flux . write ( fluxes_file , format = 'ascii.csv' ) if grid == 'TipTilt' : SetTipTiltTargetPixel . execute ({ 'x' : basex , 'y' : basey }) StopTipTilt . execute ({}) elif grid == 'SciADC' : kpffiu [ 'ADC1NAM' ] . write ( 'Null' ) kpffiu [ 'ADC2NAM' ] . write ( 'Null' ) # kpffiu['ADCTRACK'].write('On') @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"GridSearch"},{"location":"scripts/GridSearch/#gridsearch","text":"Bases: KPFTranslatorFunction Executes an engineering grid search OB. This must have arguments as input, either from a file using the -f command line tool, or passed in from the execution engine.","title":"GridSearch"},{"location":"scripts/GridSearch/#kpf.engineering.GridSearch.GridSearch--args","text":"None Source code in kpf/engineering/GridSearch.py 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 class GridSearch ( KPFTranslatorFunction ): '''Executes an engineering grid search OB. This must have arguments as input, either from a file using the `-f` command line tool, or passed in from the execution engine. ARGS: ===== None ''' abortable = True @classmethod @obey_scriptrun def pre_condition ( cls , OB , logger , cfg ): check_input ( OB , 'Template_Name' , allowed_values = [ 'kpf_eng_grid' ]) check_input ( OB , 'Template_Version' , version_check = True , value_min = '0.4' ) check_input ( OB , 'Grid' , allowed_values = [ 'TipTilt' , 'SciADC' ]) check_input ( OB , 'nx' ) check_input ( OB , 'ny' ) check_input ( OB , 'dx' ) check_input ( OB , 'dy' ) check_input ( OB , 'ExpMeter_exptime' ) FVCs = OB . get ( 'FVCs' , '' ) . split ( ',' ) for FVC in FVCs : if FVC not in [ 'SCI' , 'CAHK' , 'EXT' , '' ]: raise FailedPreCondition ( f \"FVC { FVC } not supported\" ) @classmethod @register_script ( Path ( __file__ ) . name , os . getpid ()) @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in OB : log . debug ( f \" { key } : { OB [ key ] } \" ) log . info ( '-------------------------' ) grid = OB . get ( 'Grid' ) this_file_name = Path ( __file__ ) . name . replace ( '.py' , '' ) utnow = datetime . utcnow () now_str = utnow . strftime ( '%Y%m %d at%H%M%S' ) date_str = ( utnow - timedelta ( days = 1 )) . strftime ( '%Y%b %d ' ) . lower () log_path = Path ( f '/s/sdata1701/KPFTranslator_logs/ { date_str } ' ) images_file = log_path / Path ( f ' { grid }{ this_file_name } _images_ { now_str } .txt' ) fluxes_file = log_path / Path ( f ' { grid }{ this_file_name } _fluxes_ { now_str } .txt' ) images = Table ( names = ( 'file' , 'camera' , 'x' , 'y' ), dtype = ( 'a90' , 'a10' , 'f4' , 'f4' )) expmeter_flux = Table ( names = ( 'i' , 'j' , 'x' , 'y' , 'bck1' , 'bck2' , 'bck3' , 'bck4' , 'cur1' , 'cur2' , 'cur3' , 'cur4' , 'raw1' , 'raw2' , 'raw3' , 'raw4' , 'nimages' ), dtype = ( 'i4' , 'i4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'i4' )) FVCs = OB . get ( 'FVCs' , '' ) . split ( ',' ) nx = OB . get ( 'nx' ) ny = OB . get ( 'ny' ) dx = OB . get ( 'dx' ) dy = OB . get ( 'dy' ) xis = [ xi for xi in range ( int ( - nx / 2 ), int (( nx + 1 ) / 2 ), 1 )] yis = [ yi for yi in range ( int ( - ny / 2 ), int (( ny + 1 ) / 2 ), 1 )] xindicies = [ ind for ind in range ( nx )] yindicies = [ ind for ind in range ( ny )] xs = [ xi * dx for xi in xis ] ys = [ yi * dy for yi in yis ] # Set up guider (assume parameters set during acquisition of star) kpfguide = ktl . cache ( 'kpfguide' ) log . info ( 'Setting TRIGCUBE Inactive' ) kpfguide [ 'TRIGCUBE' ] . write ( 'Inactive' ) if grid == 'TipTilt' : log . info ( f \"DAR_ENABLE = { kpfguide [ 'DAR_ENABLE' ] . read () } \" ) dar_offset = kpfguide [ 'DAR_OFFSET' ] . read ( binary = True ) log . info ( f \"DAR_OFFSET = { dar_offset [ 0 ] : .2f } { dar_offset [ 1 ] : .2f } \" ) xpix0 , ypix0 = kpfguide [ 'PIX_TARGET' ] . read ( binary = True ) log . info ( f \"PIX_TARGET is { xpix0 : .2f } , { ypix0 : .2f } \" ) basex , basey = kpfguide [ 'CURRENT_BASE' ] . read ( binary = True ) log . info ( f \"CURRENT_BASE is { basex : .2f } , { basey : .2f } \" ) # Pixel targets must be in absolute coordinates xs = [ basex + xpix for xpix in xs ] ys = [ basey + ypix for ypix in ys ] elif grid == 'SciADC' : kpffiu = ktl . cache ( 'kpffiu' ) kpffiu [ 'ADCTRACK' ] . write ( 'Off' ) nominalx , nominaly = kpffiu [ 'ADCPRISMS' ] . read ( binary = True ) x0 = OB . get ( 'ADC1Position' ) if str ( x0 ) . lower () == 'nominal' : x0 = nominalx else : x0 = float ( OB . get ( 'ADC1Position' )) y0 = OB . get ( 'ADC2Position' ) if str ( y0 ) . lower () == 'nominal' : y0 = nominaly else : y0 = float ( OB . get ( 'ADC2Position' )) log . info ( f \"ADC starting position: { x0 : .1f } { y0 : .1f } \" ) # Apply reverse rotation if requested if OB . get ( 'ADC1Reverse' , False ) is True : x0 = - x0 if OB . get ( 'ADC2Reverse' , False ) is True : y0 = - y0 log . info ( f \"ADC reverse nominal position: { x0 : .1f } { y0 : .1f } \" ) # Apply flip if requested if OB . get ( 'ADC1Flip' , False ) is True : x0 += 180 if OB . get ( 'ADC2Flip' , False ) is True : y0 += 180 log . info ( f \"ADC flip nominal position: { x0 : .1f } { y0 : .1f } \" ) xs = [ x + x0 for x in xs ] ys = [ y + y0 for y in ys ] # Set up kpfexpose kpfexpose = ktl . cache ( 'kpfexpose' ) SetSourceSelectShutters . execute ( OB ) OB [ 'TimedShutter_Scrambler' ] = True OB [ 'TimedShutter_CaHK' ] = OB . get ( 'TriggerCaHK' , False ) SetTimedShutters . execute ( OB ) SetTriggeredDetectors . execute ( OB ) total_exptime = OB . get ( 'TimeOnPosition' ) SetExpTime . execute ({ 'ExpTime' : total_exptime }) # Configure Exposure Meter kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) ExpMeter_exptime = OB . get ( 'ExpMeter_exptime' ) log . info ( f \"Setting kpf_expmeter.EXPOSURE = { ExpMeter_exptime : .2f } s\" ) kpf_expmeter [ 'EXPOSURE' ] . write ( ExpMeter_exptime ) # Set up FVCs kpffvc = ktl . cache ( 'kpffvc' ) for FVC in [ 'SCI' , 'CAHK' , 'EXT' ]: if FVC in FVCs and OB . get ( f ' { FVC } FVC_exptime' , None ) != None : exptime = OB . get ( f ' { FVC } FVC_exptime' ) log . info ( f \"Setting { FVC } FVC ExpTime = { exptime : .2f } s\" ) SetFVCExpTime . execute ({ 'camera' : FVC , 'exptime' : exptime }) for i in xindicies : yindicies . reverse () for j in yindicies : check_scriptstop () if grid == 'TipTilt' : ##------------------------------------------------------ ## Tip Tilt ##------------------------------------------------------ log . info ( f \"Adjusting CURRENT_BASE to ( { xs [ i ] : .2f } , { ys [ j ] : .2f } ) ( { xis [ i ] } , { yis [ j ] } )\" ) max_move = 3 precisison = 0.01 current_base = ktl . cache ( 'kpfguide' , 'CURRENT_BASE' ) current_cb = current_base . read ( binary = True ) delta_cb = ( xs [ i ] - current_cb [ 0 ], ys [ j ] - current_cb [ 1 ]) while abs ( delta_cb [ 0 ]) > precisison or abs ( delta_cb [ 1 ]) > precisison : # Calc X move new_X_target = current_cb [ 0 ] if abs ( delta_cb [ 0 ]) > precisison : move_sign_X = delta_cb [ 0 ] / abs ( delta_cb [ 0 ]) move_mag_X = min ([ max_move , abs ( delta_cb [ 0 ])]) new_X_target += move_sign_X * move_mag_X # Calc Y move new_Y_target = current_cb [ 1 ] if abs ( delta_cb [ 1 ]) > precisison : move_sign_Y = delta_cb [ 1 ] / abs ( delta_cb [ 1 ]) move_mag_Y = min ([ max_move , abs ( delta_cb [ 1 ])]) new_Y_target += move_sign_Y * move_mag_Y log . info ( f \" Setting CURRENT_BASE to { new_X_target : .2f } , { new_Y_target : .2f } \" ) SetTipTiltTargetPixel . execute ({ 'x' : new_X_target , 'y' : new_Y_target }) success = ktl . waitFor ( \"$kpfguide.TIPTILT_PHASE == 'Tracking'\" , timeout = 5 ) current_cb = current_base . read ( binary = True ) delta_cb = ( xs [ i ] - current_cb [ 0 ], ys [ j ] - current_cb [ 1 ]) xpix , ypix = kpfguide [ 'PIX_TARGET' ] . read ( binary = True ) log . info ( f \"PIX_TARGET is { xpix : .2f } , { ypix : .2f } \" ) # Check for lost star obj_choice = kpfguide [ 'OBJECT_CHOICE' ] . read () if obj_choice in [ None , 'None' ]: log . error ( f \" --> Lost star <--\" ) log . info ( f \"Stopping tip tilt\" ) StopTipTilt . execute ({}) time . sleep ( 1 ) log . info ( f \"Starting tip tilt\" ) StartTipTilt . execute ({}) time . sleep ( 5 ) # Check for lost star obj_choice = kpfguide [ 'OBJECT_CHOICE' ] . read () if obj_choice in [ None , 'None' ]: log . error ( f \" --> Lost star <--\" ) subprocess . call ([ 'kpf' , 'restart' , 'kpfguide2' ]) time . sleep ( 5 ) log . info ( f \"Starting tip tilt\" ) StartTipTilt . execute ({}) time . sleep ( 5 ) obj_choice = kpfguide [ 'OBJECT_CHOICE' ] . read () if obj_choice in [ None , 'None' ]: log . error ( f \" --> Lost star <--\" ) raise KPFException ( 'Lost Star' ) elif grid == 'SciADC' : ##------------------------------------------------------ ## Science ADC ##------------------------------------------------------ log . info ( f \"Offsetting to ( { xs [ i ] : .2f } , { ys [ j ] : .2f } ) ( { xis [ i ] } , { yis [ j ] } )\" ) kpffiu [ 'ADC1VAL' ] . write ( xs [ i ]) kpffiu [ 'ADC2VAL' ] . write ( ys [ j ]) log . info ( f \"Absolute position: { xs [ i ] : .1f } { ys [ j ] : .1f } \" ) expr = '($kpffiu.ADC1STA == Ready) and ($kpffiu.ADC2STA == Ready)' success = ktl . waitFor ( expr , timeout = 2 * max ([ dx * nx , dy * ny ]) / 5 ) if success is not True : ADC1STA = kpffiu [ 'ADC1STA' ] . read () ADC2STA = kpffiu [ 'ADC2STA' ] . read () msg = f 'Timed out waiting for ADCs: ADC1STA= { ADC1STA } ADC2STA= { ADC2STA } ' raise KPFException ( msg ) WaitForReady . execute ({}) check_scriptstop () # Stop here if requested # Start Exposure Meter and Science Cameras kpfexpose [ 'OBJECT' ] . write ( f 'Grid search { xs [ i ] } , { ys [ j ] } ' ) log . info ( f \"Starting kpfexpose cameras\" ) StartExposure . execute ({}) # Begin timestamp for history retrieval begin = time . time () # Take CRED2 image if OB . get ( 'UseCRED2' , True ) is True : log . info ( 'Starting guider Trigger file' ) initial_last_cube = kpfguide [ 'LASTTRIGFILE' ] . read () StartTriggerFile . execute ({}) # Start FVC Exposures initial_lastfile = {} failedFVCs = [] for FVC in [ 'SCI' , 'CAHK' , 'EXT' ]: if FVC in FVCs : initial_lastfile [ FVC ] = kpffvc [ f \" { FVC } LASTFILE\" ] . read () log . debug ( f \" Initial lastfile for { FVC } = { initial_lastfile [ FVC ] } \" ) log . info ( f \" Starting { FVC } FVC exposure\" ) try : TakeFVCExposure . execute ({ 'camera' : FVC , 'wait' : False }) except : log . error ( 'Starting FVC image failed' ) failedFVCs . append ( FVC ) check_scriptstop () # Collect files for FVC exposures for FVC in [ 'SCI' , 'CAHK' , 'EXT' ]: if FVC in FVCs and FVC not in failedFVCs : log . info ( f \" Looking for output file for { FVC } \" ) expr = f '($kpffvc. { FVC } LASTFILE != \" { initial_lastfile [ FVC ] } \")' log . debug ( f \" Waiting for: { expr } \" ) if ktl . waitFor ( expr , timeout = 20 ) is False : lastfile = kpffvc [ f ' { FVC } LASTFILE' ] . read () log . error ( 'No new FVC file found' ) log . error ( f \" kpffvc. { FVC } LASTFILE = { lastfile } \" ) else : lastfile = kpffvc [ f ' { FVC } LASTFILE' ] . read () log . debug ( f \"Found { lastfile } \" ) row = { 'file' : lastfile , 'camera' : FVC , 'x' : xs [ i ], 'y' : ys [ j ]} images . add_row ( row ) check_scriptstop () # Here's where we wait for the remainder of the TimeOnPosition log . info ( f \" Waiting for kpfexpose to be ready\" ) WaitForReady . execute ({}) # Collect CRED2 File if OB . get ( 'UseCRED2' , True ) is True : StopTriggerFile . execute ({}) WaitForTriggerFile . execute ({ 'initial_lastfile' : initial_last_cube }) last_cube = kpfguide [ 'LASTTRIGFILE' ] . read () row = { 'file' : last_cube , 'camera' : 'CRED2' , 'x' : xs [ i ], 'y' : ys [ j ]} images . add_row ( row ) # Stop Exposure Meter log . info ( f \" Waiting for ExpMeter to be Ready\" ) EMsuccess = ktl . waitFor ( '$kpf_expmeter.EXPSTATE == Ready' , timeout = 5 ) time . sleep ( 0.5 ) # Time shim because paranoia if EMsuccess is True : lastfile = kpf_expmeter [ 'FITSFILE' ] . read () else : lastfile = 'failed' log . debug ( f ' Done. FITSFILE= { lastfile } ' ) row = { 'file' : lastfile , 'camera' : 'ExpMeter' , 'x' : xs [ i ], 'y' : ys [ j ]} images . add_row ( row ) if EMsuccess is True : loutfile = kpf_expmeter [ 'LOUTFILE' ] . read () else : loutfile = 'failed' log . debug ( f ' Done. LOUTFILE= { loutfile } ' ) row = { 'file' : loutfile , 'camera' : 'ExpMeter_1Dspec' , 'x' : xs [ i ], 'y' : ys [ j ]} images . add_row ( row ) # Retrieve keyword history end = time . time () expmeter_data = { 'x' : xs [ i ], 'y' : ys [ j ], 'i' : i , 'j' : j , } log . info ( f \" Retrieving keyword history\" ) for counts_kw in [ 'CUR_COUNTS' , 'RAW_COUNTS' , 'BCK_COUNTS' ]: log . debug ( f \" Retrieving keyword history for { counts_kw } \" ) kws = { 'kpf_expmeter' : [ counts_kw ]} counts_history = keygrabber . retrieve ( kws , begin = begin , end = end ) # Extract counts and save to table (initial style output) fluxes = np . zeros (( len ( counts_history ) - 2 , 4 )) for k , entry in enumerate ( counts_history ): if k != 0 and k != len ( counts_history ) - 1 : value_floats = [ float ( v ) for v in entry [ 'ascvalue' ] . split ()] ts = datetime . fromtimestamp ( entry [ 'time' ]) . strftime ( '%Y-%m- %d %H:%M:%S' ) log . debug ( f \" { ts } : { value_floats } \" ) fluxes [ k - 1 ] = value_floats avg_fluxes = np . mean ( fluxes , axis = 0 ) expmeter_data [ f \" { counts_kw [: 3 ] . lower () } 1\" ] = avg_fluxes [ 0 ] expmeter_data [ f \" { counts_kw [: 3 ] . lower () } 2\" ] = avg_fluxes [ 1 ] expmeter_data [ f \" { counts_kw [: 3 ] . lower () } 3\" ] = avg_fluxes [ 2 ] expmeter_data [ f \" { counts_kw [: 3 ] . lower () } 4\" ] = avg_fluxes [ 3 ] expmeter_data [ 'nimages' ] = len ( counts_history ) expmeter_flux . add_row ( expmeter_data ) if images_file . exists (): images_file . unlink () images . write ( images_file , format = 'ascii.csv' ) if fluxes_file . exists (): fluxes_file . unlink () expmeter_flux . write ( fluxes_file , format = 'ascii.csv' ) if images_file . exists (): images_file . unlink () images . write ( images_file , format = 'ascii.csv' ) if fluxes_file . exists (): fluxes_file . unlink () expmeter_flux . write ( fluxes_file , format = 'ascii.csv' ) if grid == 'TipTilt' : SetTipTiltTargetPixel . execute ({ 'x' : basex , 'y' : basey }) StopTipTilt . execute ({}) elif grid == 'SciADC' : kpffiu [ 'ADC1NAM' ] . write ( 'Null' ) kpffiu [ 'ADC2NAM' ] . write ( 'Null' ) # kpffiu['ADCTRACK'].write('On') @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"ARGS:"},{"location":"scripts/GuiderLastfile/","text":"GuiderLastfile Bases: KPFTranslatorFunction Print the value of the kpfguide.LASTFILE keyword to STDOUT Parameters: wait ( bool ) \u2013 Return only after lastfile is updated? (default = False) KTL Keywords Used: kpfguide.LASTFILE Source code in kpf/guider/GuiderLastfile.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class GuiderLastfile ( KPFTranslatorFunction ): '''Print the value of the kpfguide.LASTFILE keyword to STDOUT Args: wait (bool): Return only after lastfile is updated? (default = False) KTL Keywords Used: - `kpfguide.LASTFILE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) if args . get ( 'wait' , True ) is True : exptime = kpfguide [ 'EXPTIME' ] . read ( binary = True ) initial_lastfile = kpfguide [ 'LASTFILE' ] . read () timeout = cfg . getfloat ( 'times' , 'kpfguide_shim_time' , fallback = 0.01 ) expr = f \"($kpfguide.LASTFILE != ' { initial_lastfile } ')\" ktl . waitFor ( expr , timeout = exptime + timeout ) lastfile = kpfguide [ 'LASTFILE' ] . read () print ( lastfile ) return lastfile @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--nowait\" , dest = \"wait\" , default = True , action = \"store_false\" , help = \"Send exposure command and return immediately?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"GuiderLastfile"},{"location":"scripts/GuiderLastfile/#guiderlastfile","text":"Bases: KPFTranslatorFunction Print the value of the kpfguide.LASTFILE keyword to STDOUT Parameters: wait ( bool ) \u2013 Return only after lastfile is updated? (default = False) KTL Keywords Used: kpfguide.LASTFILE Source code in kpf/guider/GuiderLastfile.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class GuiderLastfile ( KPFTranslatorFunction ): '''Print the value of the kpfguide.LASTFILE keyword to STDOUT Args: wait (bool): Return only after lastfile is updated? (default = False) KTL Keywords Used: - `kpfguide.LASTFILE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) if args . get ( 'wait' , True ) is True : exptime = kpfguide [ 'EXPTIME' ] . read ( binary = True ) initial_lastfile = kpfguide [ 'LASTFILE' ] . read () timeout = cfg . getfloat ( 'times' , 'kpfguide_shim_time' , fallback = 0.01 ) expr = f \"($kpfguide.LASTFILE != ' { initial_lastfile } ')\" ktl . waitFor ( expr , timeout = exptime + timeout ) lastfile = kpfguide [ 'LASTFILE' ] . read () print ( lastfile ) return lastfile @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--nowait\" , dest = \"wait\" , default = True , action = \"store_false\" , help = \"Send exposure command and return immediately?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"GuiderLastfile"},{"location":"scripts/GuiderOutdir/","text":"GuiderOutdir Bases: KPFTranslatorFunction Print the value of the kpfguide.OUTDIR keyword to STDOUT KTL Keywords Used: kpfguide.OUTDIR Source code in kpf/guider/GuiderOutdir.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class GuiderOutdir ( KPFTranslatorFunction ): '''Print the value of the kpfguide.OUTDIR keyword to STDOUT KTL Keywords Used: - `kpfguide.OUTDIR` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) outdir = kpfguide [ 'OUTDIR' ] . read () print ( outdir ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"GuiderOutdir"},{"location":"scripts/GuiderOutdir/#guideroutdir","text":"Bases: KPFTranslatorFunction Print the value of the kpfguide.OUTDIR keyword to STDOUT KTL Keywords Used: kpfguide.OUTDIR Source code in kpf/guider/GuiderOutdir.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class GuiderOutdir ( KPFTranslatorFunction ): '''Print the value of the kpfguide.OUTDIR keyword to STDOUT KTL Keywords Used: - `kpfguide.OUTDIR` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) outdir = kpfguide [ 'OUTDIR' ] . read () print ( outdir ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"GuiderOutdir"},{"location":"scripts/ImageBackIlluminatedFibers/","text":"ImageBackIlluminatedFibers Bases: KPFTranslatorFunction Take images of the back illuminated fibers using the FVCs Source code in kpf/engineering/ImageBackIlluminatedFibers.py 20 21 22 23 24 25 26 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 class ImageBackIlluminatedFibers ( KPFTranslatorFunction ): '''Take images of the back illuminated fibers using the FVCs ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): this_file_name = Path ( __file__ ) . name . replace ( '.py' , '' ) log_path = Path ( f '/s/sdata1701/KPFTranslator_logs/' ) images_file = log_path / Path ( f ' { this_file_name } _images.txt' ) hstnow = datetime . now () now_str = hstnow . strftime ( '%Y-%m- %d %H:%M:%S' ) LEDoutlets = { 'Science' : 'E7' , 'Sky' : 'E8' , 'CaHK' : 'J7' , 'ExpMeter' : 'H1' } LEDnames = { 'Science' : 'Science Back-Illumination LED' , 'Sky' : 'Sky Back-Illumination LED' , 'CaHK' : 'HK Back-Illumination LED' , 'ExpMeter' : 'Exp Meter Back Illum LED' } exptimes = { 'SCI' : { 'Science' : 0.1 , 'Sky' : 1 , 'ExpMeter' : 2 }, 'CAHK' : { 'CaHK' : 5 } } kpffvc = ktl . cache ( 'kpffvc' ) kpfpower = ktl . cache ( 'kpfpower' ) kpffiu = ktl . cache ( 'kpffiu' ) def take_back_illuminated_image ( camera , LEDname ): log . info ( f \"Taking back illuminated image of { LEDname } fiber with { camera } FVC\" ) camnum = { 'SCI' : 1 , 'CAHK' : 2 }[ camera ] powerkw = ktl . cache ( 'kpfpower' , f 'KPFFVC { camnum } ' ) if powerkw . read () == 'Off' : FVCPower . execute ({ 'camera' : camera , 'power' : 'on' }) # Time shim to let FVC service connect to camera after power up time . sleep ( 10 ) # Set ADC to Null if camera == 'SCI' : kpffiu [ 'ADC1NAM' ] . write ( 'Null' ) kpffiu [ 'ADC2NAM' ] . write ( 'Null' ) success1 = kpffiu [ 'ADC1NAM' ] . waitFor ( \"=='Null'\" , timeout = 30 ) success2 = kpffiu [ 'ADC2NAM' ] . waitFor ( \"=='Null'\" , timeout = 30 ) if success1 is False or success2 is False : raise KPFException ( 'Failed to reach Null position on science ADC' ) elif camera == 'CAHK' : kpffiu [ 'HKXNAM' ] . write ( 'Null' ) kpffiu [ 'HKYNAM' ] . write ( 'Null' ) success1 = kpffiu [ 'HKXNAM' ] . waitFor ( \"=='Null'\" , timeout = 30 ) success2 = kpffiu [ 'HKYNAM' ] . waitFor ( \"=='Null'\" , timeout = 30 ) if success1 is False or success2 is False : raise KPFException ( 'Failed to reach Null position on HK ADC' ) # Turn LED on outlet = LEDoutlets [ LEDname ] if LEDnames [ LEDname ] != kpfpower [ f \"OUTLET_ { outlet } _NAME\" ] . read (): raise KPFException ( f \"Expected outlet { outlet } to have name { LEDnames [ LEDname ] } \" ) log . debug ( 'Turning LED on' ) kpfpower [ f \"OUTLET_ { outlet } \" ] . write ( 'On' ) # Take FVC Image SetFVCExpTime . execute ({ 'camera' : camera , 'exptime' : exptimes [ camera ][ LEDname ]}) lastfile = TakeFVCExposure . execute ({ 'camera' : camera }) log . info ( f ' LASTFILE: { lastfile } ' ) log . debug ( 'Turning LED off' ) kpfpower [ f \"OUTLET_ { outlet } \" ] . write ( 'Off' ) # Append to images file if images_file . exists () is False : # Write header line header = f \"# HST date, camera, LED, file \\n \" with open ( images_file , 'w' ) as f : f . write ( header ) row = f \" { now_str } , { camera : 4s } , { LEDname : 8s } , { lastfile } \\n \" with open ( images_file , 'a' ) as f : f . write ( row ) if args . get ( 'SCI' , False ) is True : take_back_illuminated_image ( 'SCI' , 'Science' ) take_back_illuminated_image ( 'SCI' , 'Sky' ) take_back_illuminated_image ( 'SCI' , 'ExpMeter' ) if args . get ( 'CAHK' , False ) is True : take_back_illuminated_image ( 'CAHK' , 'CaHK' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--Science\" , \"--Sci\" , \"--science\" , \"--sci\" , \"--SCI\" , dest = \"SCI\" , default = False , action = \"store_true\" , help = \"Image science and sky fibers with science FVC?\" ) parser . add_argument ( \"--CaHK\" , \"--HK\" , \"--cahk\" , \"--hk\" , \"--CAHK\" , dest = \"CAHK\" , default = False , action = \"store_true\" , help = \"Image CaHK fiber with CaHK FVC?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"ImageBackIlluminatedFibers"},{"location":"scripts/ImageBackIlluminatedFibers/#imagebackilluminatedfibers","text":"Bases: KPFTranslatorFunction Take images of the back illuminated fibers using the FVCs Source code in kpf/engineering/ImageBackIlluminatedFibers.py 20 21 22 23 24 25 26 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 class ImageBackIlluminatedFibers ( KPFTranslatorFunction ): '''Take images of the back illuminated fibers using the FVCs ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): this_file_name = Path ( __file__ ) . name . replace ( '.py' , '' ) log_path = Path ( f '/s/sdata1701/KPFTranslator_logs/' ) images_file = log_path / Path ( f ' { this_file_name } _images.txt' ) hstnow = datetime . now () now_str = hstnow . strftime ( '%Y-%m- %d %H:%M:%S' ) LEDoutlets = { 'Science' : 'E7' , 'Sky' : 'E8' , 'CaHK' : 'J7' , 'ExpMeter' : 'H1' } LEDnames = { 'Science' : 'Science Back-Illumination LED' , 'Sky' : 'Sky Back-Illumination LED' , 'CaHK' : 'HK Back-Illumination LED' , 'ExpMeter' : 'Exp Meter Back Illum LED' } exptimes = { 'SCI' : { 'Science' : 0.1 , 'Sky' : 1 , 'ExpMeter' : 2 }, 'CAHK' : { 'CaHK' : 5 } } kpffvc = ktl . cache ( 'kpffvc' ) kpfpower = ktl . cache ( 'kpfpower' ) kpffiu = ktl . cache ( 'kpffiu' ) def take_back_illuminated_image ( camera , LEDname ): log . info ( f \"Taking back illuminated image of { LEDname } fiber with { camera } FVC\" ) camnum = { 'SCI' : 1 , 'CAHK' : 2 }[ camera ] powerkw = ktl . cache ( 'kpfpower' , f 'KPFFVC { camnum } ' ) if powerkw . read () == 'Off' : FVCPower . execute ({ 'camera' : camera , 'power' : 'on' }) # Time shim to let FVC service connect to camera after power up time . sleep ( 10 ) # Set ADC to Null if camera == 'SCI' : kpffiu [ 'ADC1NAM' ] . write ( 'Null' ) kpffiu [ 'ADC2NAM' ] . write ( 'Null' ) success1 = kpffiu [ 'ADC1NAM' ] . waitFor ( \"=='Null'\" , timeout = 30 ) success2 = kpffiu [ 'ADC2NAM' ] . waitFor ( \"=='Null'\" , timeout = 30 ) if success1 is False or success2 is False : raise KPFException ( 'Failed to reach Null position on science ADC' ) elif camera == 'CAHK' : kpffiu [ 'HKXNAM' ] . write ( 'Null' ) kpffiu [ 'HKYNAM' ] . write ( 'Null' ) success1 = kpffiu [ 'HKXNAM' ] . waitFor ( \"=='Null'\" , timeout = 30 ) success2 = kpffiu [ 'HKYNAM' ] . waitFor ( \"=='Null'\" , timeout = 30 ) if success1 is False or success2 is False : raise KPFException ( 'Failed to reach Null position on HK ADC' ) # Turn LED on outlet = LEDoutlets [ LEDname ] if LEDnames [ LEDname ] != kpfpower [ f \"OUTLET_ { outlet } _NAME\" ] . read (): raise KPFException ( f \"Expected outlet { outlet } to have name { LEDnames [ LEDname ] } \" ) log . debug ( 'Turning LED on' ) kpfpower [ f \"OUTLET_ { outlet } \" ] . write ( 'On' ) # Take FVC Image SetFVCExpTime . execute ({ 'camera' : camera , 'exptime' : exptimes [ camera ][ LEDname ]}) lastfile = TakeFVCExposure . execute ({ 'camera' : camera }) log . info ( f ' LASTFILE: { lastfile } ' ) log . debug ( 'Turning LED off' ) kpfpower [ f \"OUTLET_ { outlet } \" ] . write ( 'Off' ) # Append to images file if images_file . exists () is False : # Write header line header = f \"# HST date, camera, LED, file \\n \" with open ( images_file , 'w' ) as f : f . write ( header ) row = f \" { now_str } , { camera : 4s } , { LEDname : 8s } , { lastfile } \\n \" with open ( images_file , 'a' ) as f : f . write ( row ) if args . get ( 'SCI' , False ) is True : take_back_illuminated_image ( 'SCI' , 'Science' ) take_back_illuminated_image ( 'SCI' , 'Sky' ) take_back_illuminated_image ( 'SCI' , 'ExpMeter' ) if args . get ( 'CAHK' , False ) is True : take_back_illuminated_image ( 'CAHK' , 'CaHK' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--Science\" , \"--Sci\" , \"--science\" , \"--sci\" , \"--SCI\" , dest = \"SCI\" , default = False , action = \"store_true\" , help = \"Image science and sky fibers with science FVC?\" ) parser . add_argument ( \"--CaHK\" , \"--HK\" , \"--cahk\" , \"--hk\" , \"--CAHK\" , dest = \"CAHK\" , default = False , action = \"store_true\" , help = \"Image CaHK fiber with CaHK FVC?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"ImageBackIlluminatedFibers"},{"location":"scripts/InitializeTipTilt/","text":"InitializeTipTilt Bases: KPFTranslatorFunction Initialize the tip tilt system by setting the control mode to closed loop and setting the target values in X and Y to 0. KTL Keywords Used: kpfguide.TIPTILT_HOME kpffiu.TTXSRV kpffiu.TTYSRV kpffiu.TTXVAX kpffiu.TTYVAX Source code in kpf/fiu/InitializeTipTilt.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class InitializeTipTilt ( KPFTranslatorFunction ): '''Initialize the tip tilt system by setting the control mode to closed loop and setting the target values in X and Y to 0. KTL Keywords Used: - `kpfguide.TIPTILT_HOME` - `kpffiu.TTXSRV` - `kpffiu.TTYSRV` - `kpffiu.TTXVAX` - `kpffiu.TTYVAX` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): log . debug ( f \"Initializing tip tilt mirror\" ) kpffiu = ktl . cache ( 'kpffiu' ) tthome = ktl . cache ( 'kpfguide' , 'TIPTILT_HOME' ) home = tthome . read ( binary = True ) kpffiu [ 'TTXSRV' ] . write ( 'closed' ) kpffiu [ 'TTYSRV' ] . write ( 'closed' ) time . sleep ( 1 ) log . debug ( f 'Sending Tip tilt mirror to home: { home [ 0 ] } { home [ 1 ] } ' ) kpffiu [ 'TTXVAX' ] . write ( home [ 0 ]) kpffiu [ 'TTYVAX' ] . write ( home [ 1 ]) @classmethod def post_condition ( cls , args , logger , cfg ): kpffiu = ktl . cache ( 'kpffiu' ) tthome = ktl . cache ( 'kpfguide' , 'TIPTILT_HOME' ) home = tthome . read ( binary = True ) movetime = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) timeout = 1000 * movetime tol = cfg . getfloat ( 'tolerances' , 'tip_tilt_move_tolerance' , fallback = 0.1 ) if not ktl . waitFor ( '($kpffiu.TTXSRV == closed)' , timeout = timeout ): raise FailedToReachDestination ( kpffiu [ 'TTXSRV' ] . read (), 'closed' ) if not ktl . waitFor ( '($kpffiu.TTYSRV == closed)' , timeout = timeout ): raise FailedToReachDestination ( kpffiu [ 'TTYSRV' ] . read (), 'closed' ) expr = ( f '($kpffiu.TTXVAX >= { home [ 0 ] - tol } ) and ' \\ f '($kpffiu.TTXVAX <= { home [ 0 ] + tol } )' ) if not ktl . waitFor ( expr , timeout = timeout ): raise FailedToReachDestination ( kpffiu [ 'TTXVAX' ] . read (), f \" { home [ 0 ] } \" ) expr = ( f '($kpffiu.TTYVAX >= { home [ 1 ] - tol } ) and ' \\ f '($kpffiu.TTYVAX <= { home [ 1 ] + tol } )' ) if not ktl . waitFor ( expr , timeout = timeout ): raise FailedToReachDestination ( kpffiu [ 'TTYVAX' ] . read (), f \" { home [ 1 ] } \" )","title":"InitializeTipTilt"},{"location":"scripts/InitializeTipTilt/#initializetiptilt","text":"Bases: KPFTranslatorFunction Initialize the tip tilt system by setting the control mode to closed loop and setting the target values in X and Y to 0. KTL Keywords Used: kpfguide.TIPTILT_HOME kpffiu.TTXSRV kpffiu.TTYSRV kpffiu.TTXVAX kpffiu.TTYVAX Source code in kpf/fiu/InitializeTipTilt.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class InitializeTipTilt ( KPFTranslatorFunction ): '''Initialize the tip tilt system by setting the control mode to closed loop and setting the target values in X and Y to 0. KTL Keywords Used: - `kpfguide.TIPTILT_HOME` - `kpffiu.TTXSRV` - `kpffiu.TTYSRV` - `kpffiu.TTXVAX` - `kpffiu.TTYVAX` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): log . debug ( f \"Initializing tip tilt mirror\" ) kpffiu = ktl . cache ( 'kpffiu' ) tthome = ktl . cache ( 'kpfguide' , 'TIPTILT_HOME' ) home = tthome . read ( binary = True ) kpffiu [ 'TTXSRV' ] . write ( 'closed' ) kpffiu [ 'TTYSRV' ] . write ( 'closed' ) time . sleep ( 1 ) log . debug ( f 'Sending Tip tilt mirror to home: { home [ 0 ] } { home [ 1 ] } ' ) kpffiu [ 'TTXVAX' ] . write ( home [ 0 ]) kpffiu [ 'TTYVAX' ] . write ( home [ 1 ]) @classmethod def post_condition ( cls , args , logger , cfg ): kpffiu = ktl . cache ( 'kpffiu' ) tthome = ktl . cache ( 'kpfguide' , 'TIPTILT_HOME' ) home = tthome . read ( binary = True ) movetime = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) timeout = 1000 * movetime tol = cfg . getfloat ( 'tolerances' , 'tip_tilt_move_tolerance' , fallback = 0.1 ) if not ktl . waitFor ( '($kpffiu.TTXSRV == closed)' , timeout = timeout ): raise FailedToReachDestination ( kpffiu [ 'TTXSRV' ] . read (), 'closed' ) if not ktl . waitFor ( '($kpffiu.TTYSRV == closed)' , timeout = timeout ): raise FailedToReachDestination ( kpffiu [ 'TTYSRV' ] . read (), 'closed' ) expr = ( f '($kpffiu.TTXVAX >= { home [ 0 ] - tol } ) and ' \\ f '($kpffiu.TTXVAX <= { home [ 0 ] + tol } )' ) if not ktl . waitFor ( expr , timeout = timeout ): raise FailedToReachDestination ( kpffiu [ 'TTXVAX' ] . read (), f \" { home [ 0 ] } \" ) expr = ( f '($kpffiu.TTYVAX >= { home [ 1 ] - tol } ) and ' \\ f '($kpffiu.TTYVAX <= { home [ 1 ] + tol } )' ) if not ktl . waitFor ( expr , timeout = timeout ): raise FailedToReachDestination ( kpffiu [ 'TTYVAX' ] . read (), f \" { home [ 1 ] } \" )","title":"InitializeTipTilt"},{"location":"scripts/IsCalSourceEnabled/","text":"IsCalSourceEnabled Bases: KPFTranslatorFunction Return a boolean indicating whether the input CalSource is enabled as reported by the kpfconfig.%_ENABLED keywords. Parameters: CalSource ( str ) \u2013 Which lamp to check? Allowed Values: EtalonFiber, BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, SoCal-CalFib, LFCFiber, SoCal-SciSky, WideFlat Returns: \u2013 The return value. True for enabled, False for disabled. KTL Keywords Used: kpfcal.OCTAGON kpfconfig.BRDBANDFIBER_ENABLED kpfconfig.U_GOLD_ENABLED kpfconfig.U_DAILY_ENABLED kpfconfig.TH_DAILY_ENABLED kpfconfig.TH_GOLD_ENABLED kpfconfig.FF_FIBER_ENABLED kpfconfig.EXPMLED_ENABLED kpfconfig.HKLED_ENABLED kpfconfig.SCILED_ENABLED kpfconfig.SKYLED_ENABLED Source code in kpf/calbench/IsCalSourceEnabled.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class IsCalSourceEnabled ( KPFTranslatorFunction ): '''Return a boolean indicating whether the input CalSource is enabled as reported by the kpfconfig.%_ENABLED keywords. Args: CalSource (str): Which lamp to check? Allowed Values: EtalonFiber, BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, SoCal-CalFib, LFCFiber, SoCal-SciSky, WideFlat Returns: The return value. True for enabled, False for disabled. KTL Keywords Used: - `kpfcal.OCTAGON` - `kpfconfig.BRDBANDFIBER_ENABLED` - `kpfconfig.U_GOLD_ENABLED` - `kpfconfig.U_DAILY_ENABLED` - `kpfconfig.TH_DAILY_ENABLED` - `kpfconfig.TH_GOLD_ENABLED` - `kpfconfig.FF_FIBER_ENABLED` - `kpfconfig.EXPMLED_ENABLED` - `kpfconfig.HKLED_ENABLED` - `kpfconfig.SCILED_ENABLED` - `kpfconfig.SKYLED_ENABLED` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'OCTAGON' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) allowed_values . append ( 'SoCal-SciSky' ) allowed_values . append ( 'WideFlat' ) check_input ( args , 'CalSource' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): calsource = args . get ( 'CalSource' ) if calsource in [ 'BrdbandFiber' , 'WideFlat' , 'Th_daily' , 'Th_gold' , 'U_daily' , 'U_gold' ]: lamp_name = standardize_lamp_name ( calsource ) elif calsource in [ 'LFCFiber' , 'EtalonFiber' ]: lamp_name = calsource . upper () elif calsource in [ 'SoCal-CalFib' , 'SoCal-SciSky' ]: lamp_name = calsource . replace ( '-' , '_' ) . replace ( 'Sky' , 'FIB' ) else : log . warning ( f \"IsCalSourceEnabled does not recognize ' { calsource } '\" ) return True lamp_enabledkw = ktl . cache ( 'kpfconfig' , f ' { lamp_name } _ENABLED' ) lamp_enabled = lamp_enabledkw . read ( binary = True ) if lamp_enabled is True : log . debug ( f \"Cal source { calsource } is enabled\" ) else : log . warning ( f \"Cal source { calsource } is disabled\" ) return lamp_enabled @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalSource' , type = str , choices = [ 'BrdbandFiber' , 'WideFlat' , 'Th_daily' , 'Th_gold' , 'U_daily' , 'U_gold' , 'LFCFiber' , 'EtalonFiber' , 'SoCal-CalFib' , 'SoCal-SciSky' ], help = 'Which lamp to check?' ) return super () . add_cmdline_args ( parser , cfg )","title":"IsCalSourceEnabled"},{"location":"scripts/IsCalSourceEnabled/#iscalsourceenabled","text":"Bases: KPFTranslatorFunction Return a boolean indicating whether the input CalSource is enabled as reported by the kpfconfig.%_ENABLED keywords. Parameters: CalSource ( str ) \u2013 Which lamp to check? Allowed Values: EtalonFiber, BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, SoCal-CalFib, LFCFiber, SoCal-SciSky, WideFlat Returns: \u2013 The return value. True for enabled, False for disabled. KTL Keywords Used: kpfcal.OCTAGON kpfconfig.BRDBANDFIBER_ENABLED kpfconfig.U_GOLD_ENABLED kpfconfig.U_DAILY_ENABLED kpfconfig.TH_DAILY_ENABLED kpfconfig.TH_GOLD_ENABLED kpfconfig.FF_FIBER_ENABLED kpfconfig.EXPMLED_ENABLED kpfconfig.HKLED_ENABLED kpfconfig.SCILED_ENABLED kpfconfig.SKYLED_ENABLED Source code in kpf/calbench/IsCalSourceEnabled.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class IsCalSourceEnabled ( KPFTranslatorFunction ): '''Return a boolean indicating whether the input CalSource is enabled as reported by the kpfconfig.%_ENABLED keywords. Args: CalSource (str): Which lamp to check? Allowed Values: EtalonFiber, BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, SoCal-CalFib, LFCFiber, SoCal-SciSky, WideFlat Returns: The return value. True for enabled, False for disabled. KTL Keywords Used: - `kpfcal.OCTAGON` - `kpfconfig.BRDBANDFIBER_ENABLED` - `kpfconfig.U_GOLD_ENABLED` - `kpfconfig.U_DAILY_ENABLED` - `kpfconfig.TH_DAILY_ENABLED` - `kpfconfig.TH_GOLD_ENABLED` - `kpfconfig.FF_FIBER_ENABLED` - `kpfconfig.EXPMLED_ENABLED` - `kpfconfig.HKLED_ENABLED` - `kpfconfig.SCILED_ENABLED` - `kpfconfig.SKYLED_ENABLED` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'OCTAGON' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) allowed_values . append ( 'SoCal-SciSky' ) allowed_values . append ( 'WideFlat' ) check_input ( args , 'CalSource' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): calsource = args . get ( 'CalSource' ) if calsource in [ 'BrdbandFiber' , 'WideFlat' , 'Th_daily' , 'Th_gold' , 'U_daily' , 'U_gold' ]: lamp_name = standardize_lamp_name ( calsource ) elif calsource in [ 'LFCFiber' , 'EtalonFiber' ]: lamp_name = calsource . upper () elif calsource in [ 'SoCal-CalFib' , 'SoCal-SciSky' ]: lamp_name = calsource . replace ( '-' , '_' ) . replace ( 'Sky' , 'FIB' ) else : log . warning ( f \"IsCalSourceEnabled does not recognize ' { calsource } '\" ) return True lamp_enabledkw = ktl . cache ( 'kpfconfig' , f ' { lamp_name } _ENABLED' ) lamp_enabled = lamp_enabledkw . read ( binary = True ) if lamp_enabled is True : log . debug ( f \"Cal source { calsource } is enabled\" ) else : log . warning ( f \"Cal source { calsource } is disabled\" ) return lamp_enabled @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalSource' , type = str , choices = [ 'BrdbandFiber' , 'WideFlat' , 'Th_daily' , 'Th_gold' , 'U_daily' , 'U_gold' , 'LFCFiber' , 'EtalonFiber' , 'SoCal-CalFib' , 'SoCal-SciSky' ], help = 'Which lamp to check?' ) return super () . add_cmdline_args ( parser , cfg )","title":"IsCalSourceEnabled"},{"location":"scripts/IsSoCalClosed/","text":"IsSoCalClosed Bases: KPFTranslatorFunction Returns True if SoCal enclsoure is closed. ARGS: None Source code in kpf/socal/IsSoCalClosed.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class IsSoCalClosed ( KPFTranslatorFunction ): '''Returns True if SoCal enclsoure is closed. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'SoCal' , 'enclosure_status_time' , fallback = 10 ) ENCSTA = ktl . cache ( 'kpfsocal' , 'ENCSTA' ) is_closed = ENCSTA . waitFor ( \"==1\" , timeout = timeout ) msg = { True : 'SoCal is Closed' , False : 'SoCal is NOT Closed' }[ is_closed ] print ( msg ) return is_closed @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"IsSoCalClosed"},{"location":"scripts/IsSoCalClosed/#issocalclosed","text":"Bases: KPFTranslatorFunction Returns True if SoCal enclsoure is closed.","title":"IsSoCalClosed"},{"location":"scripts/IsSoCalClosed/#kpf.socal.IsSoCalClosed.IsSoCalClosed--args","text":"None Source code in kpf/socal/IsSoCalClosed.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class IsSoCalClosed ( KPFTranslatorFunction ): '''Returns True if SoCal enclsoure is closed. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'SoCal' , 'enclosure_status_time' , fallback = 10 ) ENCSTA = ktl . cache ( 'kpfsocal' , 'ENCSTA' ) is_closed = ENCSTA . waitFor ( \"==1\" , timeout = timeout ) msg = { True : 'SoCal is Closed' , False : 'SoCal is NOT Closed' }[ is_closed ] print ( msg ) return is_closed @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"ARGS:"},{"location":"scripts/IsSoCalOpen/","text":"IsSoCalOpen Bases: KPFTranslatorFunction Returns True if SoCal enclsoure is open. ARGS: None Source code in kpf/socal/IsSoCalOpen.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class IsSoCalOpen ( KPFTranslatorFunction ): '''Returns True if SoCal enclsoure is open. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'SoCal' , 'enclosure_status_time' , fallback = 10 ) ENCSTA = ktl . cache ( 'kpfsocal' , 'ENCSTA' ) is_open = ENCSTA . waitFor ( \"==0\" , timeout = timeout ) msg = { True : 'SoCal is Open' , False : 'SoCal is NOT Open' }[ is_open ] print ( msg ) return is_open @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"IsSoCalOpen"},{"location":"scripts/IsSoCalOpen/#issocalopen","text":"Bases: KPFTranslatorFunction Returns True if SoCal enclsoure is open.","title":"IsSoCalOpen"},{"location":"scripts/IsSoCalOpen/#kpf.socal.IsSoCalOpen.IsSoCalOpen--args","text":"None Source code in kpf/socal/IsSoCalOpen.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class IsSoCalOpen ( KPFTranslatorFunction ): '''Returns True if SoCal enclsoure is open. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'SoCal' , 'enclosure_status_time' , fallback = 10 ) ENCSTA = ktl . cache ( 'kpfsocal' , 'ENCSTA' ) is_open = ENCSTA . waitFor ( \"==0\" , timeout = timeout ) msg = { True : 'SoCal is Open' , False : 'SoCal is NOT Open' }[ is_open ] print ( msg ) return is_open @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"ARGS:"},{"location":"scripts/IsSoCalShutDown/","text":"IsSoCalShutDown Bases: KPFTranslatorFunction Returns True if SoCal enclosure is closed and tracker is parked. ARGS: None Source code in kpf/socal/IsSoCalShutDown.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class IsSoCalShutDown ( KPFTranslatorFunction ): '''Returns True if SoCal enclosure is closed and tracker is parked. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # Enclosure timeout = cfg . getfloat ( 'SoCal' , 'enclosure_status_time' , fallback = 10 ) ENCSTA = ktl . cache ( 'kpfsocal' , 'ENCSTA' ) is_closed = ENCSTA . waitFor ( \"==1\" , timeout = timeout ) EKOHOME = ktl . cache ( 'kpfsocal' , 'EKOHOME' ) is_home = EKOHOME . waitFor ( \"==1\" , timeout = timeout ) closedstr = { True : '' , False : 'NOT ' }[ is_closed ] parkedstr = { True : '' , False : 'NOT ' }[ is_home ] msg = f 'SoCal is { closedstr } closed and { parkedstr } parked' print ( msg ) shutdown = is_closed and is_home if not shutdown and args . get ( 'email' , False ) is True : try : SendEmail . execute ({ 'Subject' : f 'KPF SoCal is not shut down properly' , 'Message' : msg }) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) return shutdown @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( '--email' , dest = \"email\" , default = False , action = \"store_true\" , help = 'Send email if SoCal is not shut down?' ) return super () . add_cmdline_args ( parser , cfg )","title":"IsSoCalShutDown"},{"location":"scripts/IsSoCalShutDown/#issocalshutdown","text":"Bases: KPFTranslatorFunction Returns True if SoCal enclosure is closed and tracker is parked.","title":"IsSoCalShutDown"},{"location":"scripts/IsSoCalShutDown/#kpf.socal.IsSoCalShutDown.IsSoCalShutDown--args","text":"None Source code in kpf/socal/IsSoCalShutDown.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class IsSoCalShutDown ( KPFTranslatorFunction ): '''Returns True if SoCal enclosure is closed and tracker is parked. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # Enclosure timeout = cfg . getfloat ( 'SoCal' , 'enclosure_status_time' , fallback = 10 ) ENCSTA = ktl . cache ( 'kpfsocal' , 'ENCSTA' ) is_closed = ENCSTA . waitFor ( \"==1\" , timeout = timeout ) EKOHOME = ktl . cache ( 'kpfsocal' , 'EKOHOME' ) is_home = EKOHOME . waitFor ( \"==1\" , timeout = timeout ) closedstr = { True : '' , False : 'NOT ' }[ is_closed ] parkedstr = { True : '' , False : 'NOT ' }[ is_home ] msg = f 'SoCal is { closedstr } closed and { parkedstr } parked' print ( msg ) shutdown = is_closed and is_home if not shutdown and args . get ( 'email' , False ) is True : try : SendEmail . execute ({ 'Subject' : f 'KPF SoCal is not shut down properly' , 'Message' : msg }) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) return shutdown @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( '--email' , dest = \"email\" , default = False , action = \"store_true\" , help = 'Send email if SoCal is not shut down?' ) return super () . add_cmdline_args ( parser , cfg )","title":"ARGS:"},{"location":"scripts/LockFIU/","text":"LockFIU Bases: KPFTranslatorFunction Lock the FIU mechanisms Parameters: comment ( str ) \u2013 A comment (must not be empty) designating why the mechanisms are locked. KTL Keywords Used: kpffiu.ADC1LCK kpffiu.ADC2LCK kpffiu.FOLDLCK kpffiu.HKXLCK kpffiu.HKYLCK kpffiu.TTXLCK kpffiu.TTYLCK Source code in kpf/fiu/LockFIU.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 class LockFIU ( KPFTranslatorFunction ): '''Lock the FIU mechanisms Args: comment (str): A comment (must not be empty) designating why the mechanisms are locked. KTL Keywords Used: - `kpffiu.ADC1LCK` - `kpffiu.ADC2LCK` - `kpffiu.FOLDLCK` - `kpffiu.HKXLCK` - `kpffiu.HKYLCK` - `kpffiu.TTXLCK` - `kpffiu.TTYLCK` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): comment = args . get ( 'comment' , 'locked' ) . strip () kpffiu = ktl . cache ( 'kpffiu' ) kpffiu [ 'adc1lck' ] . write ( comment ) kpffiu [ 'adc2lck' ] . write ( comment ) kpffiu [ 'foldlck' ] . write ( comment ) kpffiu [ 'hkxlck' ] . write ( comment ) kpffiu [ 'hkylck' ] . write ( comment ) kpffiu [ 'ttxlck' ] . write ( comment ) kpffiu [ 'ttylck' ] . write ( comment ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'comment' , type = str , help = 'Comment for lock keywords' ) return super () . add_cmdline_args ( parser , cfg )","title":"LockFIU"},{"location":"scripts/LockFIU/#lockfiu","text":"Bases: KPFTranslatorFunction Lock the FIU mechanisms Parameters: comment ( str ) \u2013 A comment (must not be empty) designating why the mechanisms are locked. KTL Keywords Used: kpffiu.ADC1LCK kpffiu.ADC2LCK kpffiu.FOLDLCK kpffiu.HKXLCK kpffiu.HKYLCK kpffiu.TTXLCK kpffiu.TTYLCK Source code in kpf/fiu/LockFIU.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 class LockFIU ( KPFTranslatorFunction ): '''Lock the FIU mechanisms Args: comment (str): A comment (must not be empty) designating why the mechanisms are locked. KTL Keywords Used: - `kpffiu.ADC1LCK` - `kpffiu.ADC2LCK` - `kpffiu.FOLDLCK` - `kpffiu.HKXLCK` - `kpffiu.HKYLCK` - `kpffiu.TTXLCK` - `kpffiu.TTYLCK` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): comment = args . get ( 'comment' , 'locked' ) . strip () kpffiu = ktl . cache ( 'kpffiu' ) kpffiu [ 'adc1lck' ] . write ( comment ) kpffiu [ 'adc2lck' ] . write ( comment ) kpffiu [ 'foldlck' ] . write ( comment ) kpffiu [ 'hkxlck' ] . write ( comment ) kpffiu [ 'hkylck' ] . write ( comment ) kpffiu [ 'ttxlck' ] . write ( comment ) kpffiu [ 'ttylck' ] . write ( comment ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'comment' , type = str , help = 'Comment for lock keywords' ) return super () . add_cmdline_args ( parser , cfg )","title":"LockFIU"},{"location":"scripts/MeasureTipTiltMirrorRange/","text":"MeasureTipTiltMirrorRange Bases: KPFTranslatorFunction Measure the range of the tip tilt mirror. Prints to screen the keyword modify commands to update the range parameters. KTL Keywords Used: kpffiu.TTXVAX kpffiu.TTYVAX kpffiu.TTXMEX kpffiu.TTYMEX kpffiu.TTXMED kpffiu.TTYMED kpfguide.TIPTILT_HOME Scripts Called: kpf.fiu.InitializeTipTilt kpf.fiu.ShutdownTipTilt Source code in kpf/fiu/MeasureTipTiltMirrorRange.py 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 class MeasureTipTiltMirrorRange ( KPFTranslatorFunction ): '''Measure the range of the tip tilt mirror. Prints to screen the keyword modify commands to update the range parameters. KTL Keywords Used: - `kpffiu.TTXVAX` - `kpffiu.TTYVAX` - `kpffiu.TTXMEX` - `kpffiu.TTYMEX` - `kpffiu.TTXMED` - `kpffiu.TTYMED` - `kpfguide.TIPTILT_HOME` Scripts Called: - `kpf.fiu.InitializeTipTilt` - `kpf.fiu.ShutdownTipTilt` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # Measure tip tilt ranges log . info ( 'Beginning MeasureTipTiltMirrorRange' ) InitializeTipTilt . execute ({}) sleeptime = 10 # Set by the 5 second time in the %MEX and %MEV keywords # Need to account for worst case tol = cfg . getfloat ( 'tolerances' , 'tip_tilt_move_tolerance' , fallback = 0.1 ) n = args . get ( 'repeats' ) kpffiu = ktl . cache ( 'kpffiu' ) kpfguide = ktl . cache ( 'kpfguide' ) measured_range = {} axis = [ 'X' , 'Y' ] rawvals = {} update_ax = { 'X' : False , 'Y' : False } for i , ax in enumerate ( axis ): nominal_range = { 'X' : 15.9 , 'Y' : 24.6 }[ ax ] home = 0 measured_range [ ax ] = [ - nominal_range , nominal_range ] rawvals [ ax ] = [ None , None ] # Negative side commanded_position = home - nominal_range new_limit = find_new_limit ( ax , commanded_position , sleeptime = sleeptime , tol = tol , n = n ) if new_limit is not None : update_ax [ ax ] = True measured_range [ ax ][ 0 ] = new_limit # Positive side commanded_position = home + nominal_range new_limit = find_new_limit ( ax , commanded_position , sleeptime = sleeptime , tol = tol , n = n ) if new_limit is not None : update_ax [ ax ] = True measured_range [ ax ][ 1 ] = new_limit time . sleep ( sleeptime ) InitializeTipTilt . execute ({}) time . sleep ( sleeptime ) log . info ( f \"Measured X range: { measured_range [ 'X' ] } \" ) log . info ( f \"Measured Y range: { measured_range [ 'Y' ] } \" ) new_home = [ np . mean ( measured_range [ 'X' ]), np . mean ( measured_range [ 'Y' ])] current_home = kpfguide [ 'TIPTILT_HOME' ] . read ( binary = True ) if np . isclose ( current_home [ 0 ], new_home [ 0 ]) and np . isclose ( current_home [ 1 ], new_home [ 1 ]): print ( f 'TIPTILT_HOME OK: gshow -s kpfguide TIPTILT_HOME matches { new_home } ' ) else : print ( f \"modify -s kpfguide TIPTILT_HOME=' { new_home [ 0 ] : .1f } { new_home [ 1 ] : .1f } '\" ) for i , ax in enumerate ( axis ): print () range = ( max ( measured_range [ ax ]) - min ( measured_range [ ax ])) / 2 print ( f \"modify -s kpfguide TIPTILT_ { ax } RANGE= { range : .1f } \" ) print ( f \" Sending { ax } to home\" ) kpffiu [ f 'TT { ax } VAX' ] . write ( new_home [ i ]) time . sleep ( sleeptime ) new_RON = kpffiu [ f 'TT { ax } MED' ] . read () print ( f \"modify -s kpffiu TT { ax } RON='| { new_RON } |0|Home'\" ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( '--repeats' , type = int , default = 1 , help = \"The number of iterations to use in the calculation\" ) return super () . add_cmdline_args ( parser , cfg )","title":"MeasureTipTiltMirrorRange"},{"location":"scripts/MeasureTipTiltMirrorRange/#measuretiptiltmirrorrange","text":"Bases: KPFTranslatorFunction Measure the range of the tip tilt mirror. Prints to screen the keyword modify commands to update the range parameters. KTL Keywords Used: kpffiu.TTXVAX kpffiu.TTYVAX kpffiu.TTXMEX kpffiu.TTYMEX kpffiu.TTXMED kpffiu.TTYMED kpfguide.TIPTILT_HOME Scripts Called: kpf.fiu.InitializeTipTilt kpf.fiu.ShutdownTipTilt Source code in kpf/fiu/MeasureTipTiltMirrorRange.py 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 class MeasureTipTiltMirrorRange ( KPFTranslatorFunction ): '''Measure the range of the tip tilt mirror. Prints to screen the keyword modify commands to update the range parameters. KTL Keywords Used: - `kpffiu.TTXVAX` - `kpffiu.TTYVAX` - `kpffiu.TTXMEX` - `kpffiu.TTYMEX` - `kpffiu.TTXMED` - `kpffiu.TTYMED` - `kpfguide.TIPTILT_HOME` Scripts Called: - `kpf.fiu.InitializeTipTilt` - `kpf.fiu.ShutdownTipTilt` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # Measure tip tilt ranges log . info ( 'Beginning MeasureTipTiltMirrorRange' ) InitializeTipTilt . execute ({}) sleeptime = 10 # Set by the 5 second time in the %MEX and %MEV keywords # Need to account for worst case tol = cfg . getfloat ( 'tolerances' , 'tip_tilt_move_tolerance' , fallback = 0.1 ) n = args . get ( 'repeats' ) kpffiu = ktl . cache ( 'kpffiu' ) kpfguide = ktl . cache ( 'kpfguide' ) measured_range = {} axis = [ 'X' , 'Y' ] rawvals = {} update_ax = { 'X' : False , 'Y' : False } for i , ax in enumerate ( axis ): nominal_range = { 'X' : 15.9 , 'Y' : 24.6 }[ ax ] home = 0 measured_range [ ax ] = [ - nominal_range , nominal_range ] rawvals [ ax ] = [ None , None ] # Negative side commanded_position = home - nominal_range new_limit = find_new_limit ( ax , commanded_position , sleeptime = sleeptime , tol = tol , n = n ) if new_limit is not None : update_ax [ ax ] = True measured_range [ ax ][ 0 ] = new_limit # Positive side commanded_position = home + nominal_range new_limit = find_new_limit ( ax , commanded_position , sleeptime = sleeptime , tol = tol , n = n ) if new_limit is not None : update_ax [ ax ] = True measured_range [ ax ][ 1 ] = new_limit time . sleep ( sleeptime ) InitializeTipTilt . execute ({}) time . sleep ( sleeptime ) log . info ( f \"Measured X range: { measured_range [ 'X' ] } \" ) log . info ( f \"Measured Y range: { measured_range [ 'Y' ] } \" ) new_home = [ np . mean ( measured_range [ 'X' ]), np . mean ( measured_range [ 'Y' ])] current_home = kpfguide [ 'TIPTILT_HOME' ] . read ( binary = True ) if np . isclose ( current_home [ 0 ], new_home [ 0 ]) and np . isclose ( current_home [ 1 ], new_home [ 1 ]): print ( f 'TIPTILT_HOME OK: gshow -s kpfguide TIPTILT_HOME matches { new_home } ' ) else : print ( f \"modify -s kpfguide TIPTILT_HOME=' { new_home [ 0 ] : .1f } { new_home [ 1 ] : .1f } '\" ) for i , ax in enumerate ( axis ): print () range = ( max ( measured_range [ ax ]) - min ( measured_range [ ax ])) / 2 print ( f \"modify -s kpfguide TIPTILT_ { ax } RANGE= { range : .1f } \" ) print ( f \" Sending { ax } to home\" ) kpffiu [ f 'TT { ax } VAX' ] . write ( new_home [ i ]) time . sleep ( sleeptime ) new_RON = kpffiu [ f 'TT { ax } MED' ] . read () print ( f \"modify -s kpffiu TT { ax } RON='| { new_RON } |0|Home'\" ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( '--repeats' , type = int , default = 1 , help = \"The number of iterations to use in the calculation\" ) return super () . add_cmdline_args ( parser , cfg )","title":"MeasureTipTiltMirrorRange"},{"location":"scripts/ParkSoCal/","text":"ParkSoCal Bases: KPFTranslatorFunction Parks SoCal. This includes setting AUTONOMOUS to \"Manual\", closing the enclosure, and parking the solar tracker. ARGS: None Source code in kpf/socal/ParkSoCal.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 class ParkSoCal ( KPFTranslatorFunction ): '''Parks SoCal. This includes setting AUTONOMOUS to \"Manual\", closing the enclosure, and parking the solar tracker. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): SoCalStopAutonomous . execute ({}) log . info ( 'Parking SoCal' ) kpfsocal = ktl . cache ( 'kpfsocal' ) kpfsocal [ 'ENCCMD' ] . write ( 'close' ) kpfsocal [ 'EKOSLEW' ] . write ( 0 ) kpfsocal [ 'EKOTARGALT' ] . write ( 0 ) kpfsocal [ 'EKOTARGAZ' ] . write ( 0 ) kpfsocal [ 'EKOMODE' ] . write ( 0 ) kpfsocal [ 'EKOSLEW' ] . write ( 1 ) kpfsocal [ 'EKOSLEW' ] . write ( 0 ) @classmethod def post_condition ( cls , args , logger , cfg ): kpfsocal = ktl . cache ( 'kpfsocal' ) timeout = cfg . getfloat ( 'SoCal' , 'park_time' , fallback = 300 ) expr = '($kpfsocal.ENCSTA == 1) ' expr += 'and ($kpfsocal.EKOHOME == 1)' success = ktl . waitFor ( expr , timeout = timeout ) if success is False : raise FailedToReachDestination ( 'SoCal failed to park completely' )","title":"ParkSoCal"},{"location":"scripts/ParkSoCal/#parksocal","text":"Bases: KPFTranslatorFunction Parks SoCal. This includes setting AUTONOMOUS to \"Manual\", closing the enclosure, and parking the solar tracker.","title":"ParkSoCal"},{"location":"scripts/ParkSoCal/#kpf.socal.ParkSoCal.ParkSoCal--args","text":"None Source code in kpf/socal/ParkSoCal.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 class ParkSoCal ( KPFTranslatorFunction ): '''Parks SoCal. This includes setting AUTONOMOUS to \"Manual\", closing the enclosure, and parking the solar tracker. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): SoCalStopAutonomous . execute ({}) log . info ( 'Parking SoCal' ) kpfsocal = ktl . cache ( 'kpfsocal' ) kpfsocal [ 'ENCCMD' ] . write ( 'close' ) kpfsocal [ 'EKOSLEW' ] . write ( 0 ) kpfsocal [ 'EKOTARGALT' ] . write ( 0 ) kpfsocal [ 'EKOTARGAZ' ] . write ( 0 ) kpfsocal [ 'EKOMODE' ] . write ( 0 ) kpfsocal [ 'EKOSLEW' ] . write ( 1 ) kpfsocal [ 'EKOSLEW' ] . write ( 0 ) @classmethod def post_condition ( cls , args , logger , cfg ): kpfsocal = ktl . cache ( 'kpfsocal' ) timeout = cfg . getfloat ( 'SoCal' , 'park_time' , fallback = 300 ) expr = '($kpfsocal.ENCSTA == 1) ' expr += 'and ($kpfsocal.EKOHOME == 1)' success = ktl . waitFor ( expr , timeout = timeout ) if success is False : raise FailedToReachDestination ( 'SoCal failed to park completely' )","title":"ARGS:"},{"location":"scripts/PowerCycleCaHK/","text":"PowerCycleCaHK Bases: KPFTranslatorFunction Script which will power cycle the Ca HK detector control system and restart the services. Use as a last resort measure after other troubleshooting measures such as resetting the detector and restarting software have already failed. KTL Keywords Used: kpfpower.OUTLET_J1% kpfpower.OUTLET_J2% kpfpower.OUTLET_J5% Scripts Called: - kpf start/stop/status/restart kpfexpose2 - kpf start/stop/status/restart kpf_hk Source code in kpf/cahk/PowerCycleCaHK.py 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class PowerCycleCaHK ( KPFTranslatorFunction ): '''Script which will power cycle the Ca HK detector control system and restart the services. Use as a last resort measure after other troubleshooting measures such as resetting the detector and restarting software have already failed. KTL Keywords Used: - `kpfpower.OUTLET_J1%` - `kpfpower.OUTLET_J2%` - `kpfpower.OUTLET_J5%` Scripts Called: -`kpf start/stop/status/restart kpfexpose2` -`kpf start/stop/status/restart kpf_hk` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): kpfpower = ktl . cache ( 'kpfpower' ) outlets = [( 'J1' , 'kpfexpose2 Galil RIO controller' ), ( 'J2' , 'kpfexpose2 Galil output bank' ), ( 'J5' , 'Andor Newton PS' ), ] for outlet_id , outlet_name in outlets : name = kpfpower [ f 'OUTLET_ { outlet_id } _NAME' ] . read () if name . find ( outlet_name ) < 0 : raise FailedPreCondition ( f \"Outlet name: { outlet_id } != ' { outlet_name } '\" ) @classmethod def perform ( cls , args , logger , cfg ): log . warning ( 'Stopping kpfexpose2 dispatcher' ) cmd = [ 'kpf' , 'stop' , 'kpfexpose2' ] result = subprocess . run ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) log . debug ( f \" args: { result . args } \" ) log . debug ( f \" rtncode: { result . returncode } \" ) log . debug ( f \" STDOUT: { result . stdout . decode () } \" ) log . debug ( f \" STDERR: { result . stderr . decode () } \" ) if result . returncode != 0 : raise FailedPostCondition ( f \"The kpf stop kpfexpose2 command appears to have failed\" ) time . sleep ( 2 ) log . warning ( 'Stopping kpf_hk keyword service' ) cmd = [ 'kpf' , 'stop' , 'kpf_hk' ] result = subprocess . run ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) log . debug ( f \" args: { result . args } \" ) log . debug ( f \" rtncode: { result . returncode } \" ) log . debug ( f \" STDOUT: { result . stdout . decode () } \" ) log . debug ( f \" STDERR: { result . stderr . decode () } \" ) if result . returncode != 0 : raise FailedPostCondition ( f \"The kpf stop kpf_hk command appears to have failed\" ) time . sleep ( 2 ) # Get status response for log cmd = [ 'kpf' , 'status' , 'kpf_hk' ] result = subprocess . run ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) log . debug ( f \" args: { result . args } \" ) log . debug ( f \" rtncode: { result . returncode } \" ) log . debug ( f \" STDOUT: { result . stdout . decode () } \" ) log . debug ( f \" STDERR: { result . stderr . decode () } \" ) log . warning ( 'Power cycling the Ca HK detector system' ) kpfpower = ktl . cache ( 'kpfpower' ) outlets = [( 'J5' , 'Andor Newton PS' ), ( 'J1' , 'kpfexpose2 Galil RIO controller' ), ( 'J2' , 'kpfexpose2 Galil output bank' ), ] for outlet_id , outlet_name in outlets : log . info ( f \"Powering off { outlet_id } : { outlet_name } \" ) kpfpower [ f 'OUTLET_ { outlet_id } ' ] . write ( 'Off' ) time . sleep ( 10 ) for outlet_id , outlet_name in outlets : log . info ( f \"Powering on { outlet_id } : { outlet_name } \" ) kpfpower [ f 'OUTLET_ { outlet_id } ' ] . write ( 'On' ) time . sleep ( 10 ) log . warning ( 'Restarting kpf_hk keyword service' ) cmd = [ 'kpf' , 'restart' , 'kpf_hk' ] result = subprocess . run ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) log . debug ( f \" args: { result . args } \" ) log . debug ( f \" rtncode: { result . returncode } \" ) log . debug ( f \" STDOUT: { result . stdout . decode () } \" ) log . debug ( f \" STDERR: { result . stderr . decode () } \" ) if result . returncode != 0 : raise FailedPostCondition ( f \"The kpf restart kpf_hk command appears to have failed\" ) time . sleep ( 10 ) # Get status response for log cmd = [ 'kpf' , 'status' , 'kpf_hk' ] result = subprocess . run ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) log . debug ( f \" args: { result . args } \" ) log . debug ( f \" rtncode: { result . returncode } \" ) log . debug ( f \" STDOUT: { result . stdout . decode () } \" ) log . debug ( f \" STDERR: { result . stderr . decode () } \" ) log . warning ( 'Restarting kpfexpose2 keyword service' ) cmd = [ 'kpf' , 'restart' , 'kpfexpose2' ] result = subprocess . run ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) log . debug ( f \" args: { result . args } \" ) log . debug ( f \" rtncode: { result . returncode } \" ) log . debug ( f \" STDOUT: { result . stdout . decode () } \" ) log . debug ( f \" STDERR: { result . stderr . decode () } \" ) if result . returncode != 0 : raise FailedPostCondition ( f \"The kpf restart kpfexpose2 command appears to have failed\" ) time . sleep ( 10 ) # Get status response for log cmd = [ 'kpf' , 'status' , 'kpfexpose2' ] result = subprocess . run ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) log . debug ( f \" args: { result . args } \" ) log . debug ( f \" rtncode: { result . returncode } \" ) log . debug ( f \" STDOUT: { result . stdout . decode () } \" ) log . debug ( f \" STDERR: { result . stderr . decode () } \" ) log . warning ( 'Resetting Ca HK' ) ResetCaHKDetector . execute ({}) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"PowerCycleCaHK"},{"location":"scripts/PowerCycleCaHK/#powercyclecahk","text":"Bases: KPFTranslatorFunction Script which will power cycle the Ca HK detector control system and restart the services. Use as a last resort measure after other troubleshooting measures such as resetting the detector and restarting software have already failed. KTL Keywords Used: kpfpower.OUTLET_J1% kpfpower.OUTLET_J2% kpfpower.OUTLET_J5% Scripts Called: - kpf start/stop/status/restart kpfexpose2 - kpf start/stop/status/restart kpf_hk Source code in kpf/cahk/PowerCycleCaHK.py 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class PowerCycleCaHK ( KPFTranslatorFunction ): '''Script which will power cycle the Ca HK detector control system and restart the services. Use as a last resort measure after other troubleshooting measures such as resetting the detector and restarting software have already failed. KTL Keywords Used: - `kpfpower.OUTLET_J1%` - `kpfpower.OUTLET_J2%` - `kpfpower.OUTLET_J5%` Scripts Called: -`kpf start/stop/status/restart kpfexpose2` -`kpf start/stop/status/restart kpf_hk` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): kpfpower = ktl . cache ( 'kpfpower' ) outlets = [( 'J1' , 'kpfexpose2 Galil RIO controller' ), ( 'J2' , 'kpfexpose2 Galil output bank' ), ( 'J5' , 'Andor Newton PS' ), ] for outlet_id , outlet_name in outlets : name = kpfpower [ f 'OUTLET_ { outlet_id } _NAME' ] . read () if name . find ( outlet_name ) < 0 : raise FailedPreCondition ( f \"Outlet name: { outlet_id } != ' { outlet_name } '\" ) @classmethod def perform ( cls , args , logger , cfg ): log . warning ( 'Stopping kpfexpose2 dispatcher' ) cmd = [ 'kpf' , 'stop' , 'kpfexpose2' ] result = subprocess . run ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) log . debug ( f \" args: { result . args } \" ) log . debug ( f \" rtncode: { result . returncode } \" ) log . debug ( f \" STDOUT: { result . stdout . decode () } \" ) log . debug ( f \" STDERR: { result . stderr . decode () } \" ) if result . returncode != 0 : raise FailedPostCondition ( f \"The kpf stop kpfexpose2 command appears to have failed\" ) time . sleep ( 2 ) log . warning ( 'Stopping kpf_hk keyword service' ) cmd = [ 'kpf' , 'stop' , 'kpf_hk' ] result = subprocess . run ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) log . debug ( f \" args: { result . args } \" ) log . debug ( f \" rtncode: { result . returncode } \" ) log . debug ( f \" STDOUT: { result . stdout . decode () } \" ) log . debug ( f \" STDERR: { result . stderr . decode () } \" ) if result . returncode != 0 : raise FailedPostCondition ( f \"The kpf stop kpf_hk command appears to have failed\" ) time . sleep ( 2 ) # Get status response for log cmd = [ 'kpf' , 'status' , 'kpf_hk' ] result = subprocess . run ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) log . debug ( f \" args: { result . args } \" ) log . debug ( f \" rtncode: { result . returncode } \" ) log . debug ( f \" STDOUT: { result . stdout . decode () } \" ) log . debug ( f \" STDERR: { result . stderr . decode () } \" ) log . warning ( 'Power cycling the Ca HK detector system' ) kpfpower = ktl . cache ( 'kpfpower' ) outlets = [( 'J5' , 'Andor Newton PS' ), ( 'J1' , 'kpfexpose2 Galil RIO controller' ), ( 'J2' , 'kpfexpose2 Galil output bank' ), ] for outlet_id , outlet_name in outlets : log . info ( f \"Powering off { outlet_id } : { outlet_name } \" ) kpfpower [ f 'OUTLET_ { outlet_id } ' ] . write ( 'Off' ) time . sleep ( 10 ) for outlet_id , outlet_name in outlets : log . info ( f \"Powering on { outlet_id } : { outlet_name } \" ) kpfpower [ f 'OUTLET_ { outlet_id } ' ] . write ( 'On' ) time . sleep ( 10 ) log . warning ( 'Restarting kpf_hk keyword service' ) cmd = [ 'kpf' , 'restart' , 'kpf_hk' ] result = subprocess . run ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) log . debug ( f \" args: { result . args } \" ) log . debug ( f \" rtncode: { result . returncode } \" ) log . debug ( f \" STDOUT: { result . stdout . decode () } \" ) log . debug ( f \" STDERR: { result . stderr . decode () } \" ) if result . returncode != 0 : raise FailedPostCondition ( f \"The kpf restart kpf_hk command appears to have failed\" ) time . sleep ( 10 ) # Get status response for log cmd = [ 'kpf' , 'status' , 'kpf_hk' ] result = subprocess . run ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) log . debug ( f \" args: { result . args } \" ) log . debug ( f \" rtncode: { result . returncode } \" ) log . debug ( f \" STDOUT: { result . stdout . decode () } \" ) log . debug ( f \" STDERR: { result . stderr . decode () } \" ) log . warning ( 'Restarting kpfexpose2 keyword service' ) cmd = [ 'kpf' , 'restart' , 'kpfexpose2' ] result = subprocess . run ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) log . debug ( f \" args: { result . args } \" ) log . debug ( f \" rtncode: { result . returncode } \" ) log . debug ( f \" STDOUT: { result . stdout . decode () } \" ) log . debug ( f \" STDERR: { result . stderr . decode () } \" ) if result . returncode != 0 : raise FailedPostCondition ( f \"The kpf restart kpfexpose2 command appears to have failed\" ) time . sleep ( 10 ) # Get status response for log cmd = [ 'kpf' , 'status' , 'kpfexpose2' ] result = subprocess . run ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) log . debug ( f \" args: { result . args } \" ) log . debug ( f \" rtncode: { result . returncode } \" ) log . debug ( f \" STDOUT: { result . stdout . decode () } \" ) log . debug ( f \" STDERR: { result . stderr . decode () } \" ) log . warning ( 'Resetting Ca HK' ) ResetCaHKDetector . execute ({}) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"PowerCycleCaHK"},{"location":"scripts/PredictExpMeterParameters/","text":"PredictExpMeterParameters Bases: KPFTranslatorFunction Estimate the proper exposure meter exposure time given the stellar Gmag. Parameters: Gmag ( float ) \u2013 The Gaia g magnitude of the target. Source code in kpf/expmeter/PredictExpMeterParameters.py 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 class PredictExpMeterParameters ( KPFTranslatorFunction ): '''Estimate the proper exposure meter exposure time given the stellar Gmag. Args: Gmag (float): The Gaia g magnitude of the target. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'Gmag' , allowed_types = [ int , float ]) @classmethod def perform ( cls , args , logger , cfg ): Gmag = args . get ( 'Gmag' ) if Gmag < 4.0 : exptime = 0.5 elif Gmag < 9.0 : exptime = 1.0 elif Gmag < 11.0 : exptime = 2.0 elif Gmag < 13.0 : exptime = 4.0 elif Gmag < 15.0 : exptime = 8.0 else : exptime = 16.0 log . info ( f \"Predicted ExpMeterExpTime = { exptime : .1f } s\" ) return { 'ExpMeterExpTime' : exptime } @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'Gmag' , type = float , help = \"The Gaia g magnitude of the target\" ) return super () . add_cmdline_args ( parser , cfg )","title":"PredictExpMeterParameters"},{"location":"scripts/PredictExpMeterParameters/#predictexpmeterparameters","text":"Bases: KPFTranslatorFunction Estimate the proper exposure meter exposure time given the stellar Gmag. Parameters: Gmag ( float ) \u2013 The Gaia g magnitude of the target. Source code in kpf/expmeter/PredictExpMeterParameters.py 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 class PredictExpMeterParameters ( KPFTranslatorFunction ): '''Estimate the proper exposure meter exposure time given the stellar Gmag. Args: Gmag (float): The Gaia g magnitude of the target. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'Gmag' , allowed_types = [ int , float ]) @classmethod def perform ( cls , args , logger , cfg ): Gmag = args . get ( 'Gmag' ) if Gmag < 4.0 : exptime = 0.5 elif Gmag < 9.0 : exptime = 1.0 elif Gmag < 11.0 : exptime = 2.0 elif Gmag < 13.0 : exptime = 4.0 elif Gmag < 15.0 : exptime = 8.0 else : exptime = 16.0 log . info ( f \"Predicted ExpMeterExpTime = { exptime : .1f } s\" ) return { 'ExpMeterExpTime' : exptime } @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'Gmag' , type = float , help = \"The Gaia g magnitude of the target\" ) return super () . add_cmdline_args ( parser , cfg )","title":"PredictExpMeterParameters"},{"location":"scripts/PredictFVCParameters/","text":"PredictFVCParameters Bases: KPFTranslatorFunction Estimate the exposure time given the stellar Gmag and which camera. Based on scaling from a single, poorly measured data point: For Vmag ~ 4, the SCIFVC_exptime = 1 and CAHKFVC_exptime = 15 Parameters: Gmag ( float ) \u2013 The G magnitude of the target. Source code in kpf/fvc/PredictFVCParameters.py 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class PredictFVCParameters ( KPFTranslatorFunction ): '''Estimate the exposure time given the stellar Gmag and which camera. Based on scaling from a single, poorly measured data point: For Vmag ~ 4, the SCIFVC_exptime = 1 and CAHKFVC_exptime = 15 Args: Gmag (float): The G magnitude of the target. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'Gmag' , allowed_types = [ int , float ]) @classmethod def perform ( cls , args , logger , cfg ): Gmag = args . get ( 'Gmag' ) delta_mag = 4 - Gmag flux_ratio = 10 ** ( delta_mag / 2.5 ) if flux_ratio > 10 : exptime = { 'SCI' : 0.1 , 'CAHK' : 1.5 } elif flux_ratio > 5 : exptime = { 'SCI' : 0.2 , 'CAHK' : 3 } elif flux_ratio > 2 : exptime = { 'SCI' : 0.5 , 'CAHK' : 8 } elif flux_ratio > 0.5 : exptime = { 'SCI' : 1 , 'CAHK' : 15 } elif flux_ratio > 0.2 : exptime = { 'SCI' : 5 , 'CAHK' : 15 } elif flux_ratio > 0.05 : exptime = { 'SCI' : 10 , 'CAHK' : 15 } result = { 'SCIFVC_exptime' : exptime [ 'SCI' ], 'CAHKFVC_exptime' : exptime [ 'CAHK' ]} print ( result ) if args . get ( 'set' , False ): SetFVCExpTime . execute ({ 'camera' : 'SCI' , 'exptime' : exptime [ 'SCI' ]}) SetFVCExpTime . execute ({ 'camera' : 'CAHK' , 'exptime' : exptime [ 'CAHK' ]}) return result @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'Gmag' , type = float , help = \"The G magnitude of the target\" ) parser . add_argument ( \"--set\" , dest = \"set\" , default = False , action = \"store_true\" , help = \"Set these values after calculating?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"PredictFVCParameters"},{"location":"scripts/PredictFVCParameters/#predictfvcparameters","text":"Bases: KPFTranslatorFunction Estimate the exposure time given the stellar Gmag and which camera. Based on scaling from a single, poorly measured data point: For Vmag ~ 4, the SCIFVC_exptime = 1 and CAHKFVC_exptime = 15 Parameters: Gmag ( float ) \u2013 The G magnitude of the target. Source code in kpf/fvc/PredictFVCParameters.py 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class PredictFVCParameters ( KPFTranslatorFunction ): '''Estimate the exposure time given the stellar Gmag and which camera. Based on scaling from a single, poorly measured data point: For Vmag ~ 4, the SCIFVC_exptime = 1 and CAHKFVC_exptime = 15 Args: Gmag (float): The G magnitude of the target. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'Gmag' , allowed_types = [ int , float ]) @classmethod def perform ( cls , args , logger , cfg ): Gmag = args . get ( 'Gmag' ) delta_mag = 4 - Gmag flux_ratio = 10 ** ( delta_mag / 2.5 ) if flux_ratio > 10 : exptime = { 'SCI' : 0.1 , 'CAHK' : 1.5 } elif flux_ratio > 5 : exptime = { 'SCI' : 0.2 , 'CAHK' : 3 } elif flux_ratio > 2 : exptime = { 'SCI' : 0.5 , 'CAHK' : 8 } elif flux_ratio > 0.5 : exptime = { 'SCI' : 1 , 'CAHK' : 15 } elif flux_ratio > 0.2 : exptime = { 'SCI' : 5 , 'CAHK' : 15 } elif flux_ratio > 0.05 : exptime = { 'SCI' : 10 , 'CAHK' : 15 } result = { 'SCIFVC_exptime' : exptime [ 'SCI' ], 'CAHKFVC_exptime' : exptime [ 'CAHK' ]} print ( result ) if args . get ( 'set' , False ): SetFVCExpTime . execute ({ 'camera' : 'SCI' , 'exptime' : exptime [ 'SCI' ]}) SetFVCExpTime . execute ({ 'camera' : 'CAHK' , 'exptime' : exptime [ 'CAHK' ]}) return result @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'Gmag' , type = float , help = \"The G magnitude of the target\" ) parser . add_argument ( \"--set\" , dest = \"set\" , default = False , action = \"store_true\" , help = \"Set these values after calculating?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"PredictFVCParameters"},{"location":"scripts/PredictGuiderParameters/","text":"PredictGuiderParameters Bases: KPFTranslatorFunction Estimate the proper gain and FPS given the stellar Jmag. Parameters: Jmag ( float ) \u2013 The J magnitude of the target. Scripts Called: kpf.guider.SetGuiderGain kpf.guider.SetGuiderFPS Source code in kpf/guider/PredictGuiderParameters.py 26 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 class PredictGuiderParameters ( KPFTranslatorFunction ): '''Estimate the proper gain and FPS given the stellar Jmag. Args: Jmag (float): The J magnitude of the target. Scripts Called: - `kpf.guider.SetGuiderGain` - `kpf.guider.SetGuiderFPS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'Jmag' , allowed_types = [ int , float ]) @classmethod def perform ( cls , args , logger , cfg ): Jmag = args . get ( 'Jmag' ) if Jmag < 5.5 : gain = 'Low' fps = 100 elif Jmag < 8.0 : gain = 'Medium' fps = 100 elif Jmag < 12.0 : gain = 'High' fps = 100 elif Jmag < 12.8 : gain = 'High' fps = 50 elif Jmag < 13.8 : gain = 'High' fps = 20 elif Jmag < 14.5 : gain = 'High' fps = 10 elif Jmag < 17.0 : gain = 'high' fps = 1 else : gain = 'high' fps = 1 log . info ( f \"Predicted GuideCamGain = { gain } \" ) log . info ( f \"Predicted GuideFPS = { fps : d } \" ) result = { 'GuideCamGain' : gain , 'GuideFPS' : fps } if args . get ( 'set' , False ): SetGuiderGain . execute ( result ) SetGuiderFPS . execute ( result ) return result @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'Jmag' , type = float , help = \"The J magnitude of the target\" ) parser . add_argument ( \"--set\" , dest = \"set\" , default = False , action = \"store_true\" , help = \"Set these values after calculating?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"PredictGuiderParameters"},{"location":"scripts/PredictGuiderParameters/#predictguiderparameters","text":"Bases: KPFTranslatorFunction Estimate the proper gain and FPS given the stellar Jmag. Parameters: Jmag ( float ) \u2013 The J magnitude of the target. Scripts Called: kpf.guider.SetGuiderGain kpf.guider.SetGuiderFPS Source code in kpf/guider/PredictGuiderParameters.py 26 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 class PredictGuiderParameters ( KPFTranslatorFunction ): '''Estimate the proper gain and FPS given the stellar Jmag. Args: Jmag (float): The J magnitude of the target. Scripts Called: - `kpf.guider.SetGuiderGain` - `kpf.guider.SetGuiderFPS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'Jmag' , allowed_types = [ int , float ]) @classmethod def perform ( cls , args , logger , cfg ): Jmag = args . get ( 'Jmag' ) if Jmag < 5.5 : gain = 'Low' fps = 100 elif Jmag < 8.0 : gain = 'Medium' fps = 100 elif Jmag < 12.0 : gain = 'High' fps = 100 elif Jmag < 12.8 : gain = 'High' fps = 50 elif Jmag < 13.8 : gain = 'High' fps = 20 elif Jmag < 14.5 : gain = 'High' fps = 10 elif Jmag < 17.0 : gain = 'high' fps = 1 else : gain = 'high' fps = 1 log . info ( f \"Predicted GuideCamGain = { gain } \" ) log . info ( f \"Predicted GuideFPS = { fps : d } \" ) result = { 'GuideCamGain' : gain , 'GuideFPS' : fps } if args . get ( 'set' , False ): SetGuiderGain . execute ( result ) SetGuiderFPS . execute ( result ) return result @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'Jmag' , type = float , help = \"The J magnitude of the target\" ) parser . add_argument ( \"--set\" , dest = \"set\" , default = False , action = \"store_true\" , help = \"Set these values after calculating?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"PredictGuiderParameters"},{"location":"scripts/PredictNDFilters/","text":"PredictNDFilters Bases: KPFTranslatorFunction Predict which ND filters should be used for simultaneous calibrations. Parameters: ? ( float ) \u2013 Scripts Called: kpf.calbench.SetND Source code in kpf/calbench/PredictNDFilters.py 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 class PredictNDFilters ( KPFTranslatorFunction ): '''Predict which ND filters should be used for simultaneous calibrations. Args: ? (float): Scripts Called: - `kpf.calbench.SetND` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'Gmag' , allowed_types = [ int , float ]) check_input ( args , 'Teff' , allowed_types = [ int , float ]) check_input ( args , 'ExpTime' , allowed_types = [ int , float ]) @classmethod def perform ( cls , args , logger , cfg ): tick = datetime . datetime . now () gmag = args . get ( 'Gmag' ) teff = args . get ( 'Teff' ) log . debug ( 'Estimating Vmag from Gmag:' ) vmag = gmag - get_GminusV ( teff ) log . debug ( f ' Gmag= { gmag : .2f } --> Vmag= { vmag : .2f } ' ) obs_exp_time = args . get ( 'ExpTime' ) # reference calibration file to scale up/down #cal_file = 'KP.20240529.80736.43_L1.fits' # reference etalon L1 file data_dir = Path ( __file__ ) . parent . parent . parent / 'data' cal_file = data_dir / 'KP.20240529.80736.43_L1.fits' # Filter wheel populations for both wheels # od_arr_scical = [0.1, 0.3, 0.5, 0.8, 1.0, 4.0] # od_arr_cal = [0.1, 1.0, 1.3, 2., 3., 4.] # od_arr_scical = [0.1, 1.0, 1.3, 2., 3., 4.] # od_arr_cal = [0.1, 0.3, 0.5, 0.8, 1.0, 4.0] ND1POS = ktl . cache ( 'kpfcal' , 'ND1POS' ) ND1POS_allowed_values = list ( ND1POS . _getEnumerators ()) if 'Unknown' in ND1POS_allowed_values : ND1POS_allowed_values . pop ( ND1POS_allowed_values . index ( 'Unknown' )) od_arr_scical = [ float ( pos [ 3 :]) for pos in ND1POS_allowed_values ] ND2POS = ktl . cache ( 'kpfcal' , 'ND2POS' ) ND2POS_allowed_values = list ( ND2POS . _getEnumerators ()) if 'Unknown' in ND2POS_allowed_values : ND2POS_allowed_values . pop ( ND2POS_allowed_values . index ( 'Unknown' )) od_arr_cal = [ float ( pos [ 3 :]) for pos in ND2POS_allowed_values ] od_vals_all , filter_configs_all = all_possible_sums_with_indices_sorted ( od_arr_scical , od_arr_cal ) od , nd_config = get_simulcal_od ( vmag , teff , obs_exp_time , cal_file , ref_wave = 5500 , od_values = od_vals_all , filter_configs = filter_configs_all ) result = { 'CalND1' : f 'OD { nd_config [ 0 ] } ' , 'CalND2' : f 'OD { nd_config [ 1 ] } ' } log . info ( f \"Predicted ND1 = { result [ 'CalND1' ] } \" ) log . info ( f \"Predicted ND2 = { result [ 'CalND2' ] } \" ) tock = datetime . datetime . now () elapsed = ( tock - tick ) . total_seconds () log . debug ( f 'ND filter calculation took { elapsed : .1f } s' ) if args . get ( 'set' , False ): SetND . execute ( result ) return result @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'Gmag' , type = float , help = \"The gaia G magnitude of the target\" ) parser . add_argument ( 'Teff' , type = float , help = \"The effective temperature of the target\" ) parser . add_argument ( 'ExpTime' , type = float , help = \"The exposure time on target\" ) parser . add_argument ( \"--set\" , dest = \"set\" , default = False , action = \"store_true\" , help = \"Set these values after calculating?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"PredictNDFilters"},{"location":"scripts/PredictNDFilters/#predictndfilters","text":"Bases: KPFTranslatorFunction Predict which ND filters should be used for simultaneous calibrations. Parameters: ? ( float ) \u2013 Scripts Called: kpf.calbench.SetND Source code in kpf/calbench/PredictNDFilters.py 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 class PredictNDFilters ( KPFTranslatorFunction ): '''Predict which ND filters should be used for simultaneous calibrations. Args: ? (float): Scripts Called: - `kpf.calbench.SetND` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'Gmag' , allowed_types = [ int , float ]) check_input ( args , 'Teff' , allowed_types = [ int , float ]) check_input ( args , 'ExpTime' , allowed_types = [ int , float ]) @classmethod def perform ( cls , args , logger , cfg ): tick = datetime . datetime . now () gmag = args . get ( 'Gmag' ) teff = args . get ( 'Teff' ) log . debug ( 'Estimating Vmag from Gmag:' ) vmag = gmag - get_GminusV ( teff ) log . debug ( f ' Gmag= { gmag : .2f } --> Vmag= { vmag : .2f } ' ) obs_exp_time = args . get ( 'ExpTime' ) # reference calibration file to scale up/down #cal_file = 'KP.20240529.80736.43_L1.fits' # reference etalon L1 file data_dir = Path ( __file__ ) . parent . parent . parent / 'data' cal_file = data_dir / 'KP.20240529.80736.43_L1.fits' # Filter wheel populations for both wheels # od_arr_scical = [0.1, 0.3, 0.5, 0.8, 1.0, 4.0] # od_arr_cal = [0.1, 1.0, 1.3, 2., 3., 4.] # od_arr_scical = [0.1, 1.0, 1.3, 2., 3., 4.] # od_arr_cal = [0.1, 0.3, 0.5, 0.8, 1.0, 4.0] ND1POS = ktl . cache ( 'kpfcal' , 'ND1POS' ) ND1POS_allowed_values = list ( ND1POS . _getEnumerators ()) if 'Unknown' in ND1POS_allowed_values : ND1POS_allowed_values . pop ( ND1POS_allowed_values . index ( 'Unknown' )) od_arr_scical = [ float ( pos [ 3 :]) for pos in ND1POS_allowed_values ] ND2POS = ktl . cache ( 'kpfcal' , 'ND2POS' ) ND2POS_allowed_values = list ( ND2POS . _getEnumerators ()) if 'Unknown' in ND2POS_allowed_values : ND2POS_allowed_values . pop ( ND2POS_allowed_values . index ( 'Unknown' )) od_arr_cal = [ float ( pos [ 3 :]) for pos in ND2POS_allowed_values ] od_vals_all , filter_configs_all = all_possible_sums_with_indices_sorted ( od_arr_scical , od_arr_cal ) od , nd_config = get_simulcal_od ( vmag , teff , obs_exp_time , cal_file , ref_wave = 5500 , od_values = od_vals_all , filter_configs = filter_configs_all ) result = { 'CalND1' : f 'OD { nd_config [ 0 ] } ' , 'CalND2' : f 'OD { nd_config [ 1 ] } ' } log . info ( f \"Predicted ND1 = { result [ 'CalND1' ] } \" ) log . info ( f \"Predicted ND2 = { result [ 'CalND2' ] } \" ) tock = datetime . datetime . now () elapsed = ( tock - tick ) . total_seconds () log . debug ( f 'ND filter calculation took { elapsed : .1f } s' ) if args . get ( 'set' , False ): SetND . execute ( result ) return result @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'Gmag' , type = float , help = \"The gaia G magnitude of the target\" ) parser . add_argument ( 'Teff' , type = float , help = \"The effective temperature of the target\" ) parser . add_argument ( 'ExpTime' , type = float , help = \"The exposure time on target\" ) parser . add_argument ( \"--set\" , dest = \"set\" , default = False , action = \"store_true\" , help = \"Set these values after calculating?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"PredictNDFilters"},{"location":"scripts/QueryFastReadMode/","text":"QueryFastReadMode Bases: KPFTranslatorFunction Returns True if both ACF files are consistent with fast read mode. Source code in kpf/spectrograph/QueryFastReadMode.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class QueryFastReadMode ( KPFTranslatorFunction ): '''Returns True if both ACF files are consistent with fast read mode. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): green_mode , red_mode = QueryReadMode . execute ({}) return ( green_mode == 'fast' ) and ( red_mode == 'fast' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"QueryFastReadMode"},{"location":"scripts/QueryFastReadMode/#queryfastreadmode","text":"Bases: KPFTranslatorFunction Returns True if both ACF files are consistent with fast read mode. Source code in kpf/spectrograph/QueryFastReadMode.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class QueryFastReadMode ( KPFTranslatorFunction ): '''Returns True if both ACF files are consistent with fast read mode. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): green_mode , red_mode = QueryReadMode . execute ({}) return ( green_mode == 'fast' ) and ( red_mode == 'fast' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"QueryFastReadMode"},{"location":"scripts/QueryReadMode/","text":"QueryReadMode Bases: KPFTranslatorFunction Returns string describing the read mode. Source code in kpf/spectrograph/QueryReadMode.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 class QueryReadMode ( KPFTranslatorFunction ): '''Returns string describing the read mode. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfgreen = ktl . cache ( 'kpfgreen' ) green_normal_file = cfg . get ( 'acf_files' , 'green_normal' ) green_fast_file = cfg . get ( 'acf_files' , 'green_fast' ) green_ACFFILE = Path ( kpfgreen [ 'ACFFILE' ] . read ()) . stem if green_ACFFILE == green_normal_file : green_mode = 'normal' elif green_ACFFILE == green_fast_file : green_mode = 'fast' else : green_mode = 'unknown' kpfred = ktl . cache ( 'kpfred' ) red_normal_file = cfg . get ( 'acf_files' , 'red_normal' ) red_fast_file = cfg . get ( 'acf_files' , 'red_fast' ) red_ACFFILE = Path ( kpfred [ 'ACFFILE' ] . read ()) . stem if red_ACFFILE == red_normal_file : red_mode = 'normal' elif red_ACFFILE == red_fast_file : red_mode = 'fast' else : red_mode = 'unknown' log . debug ( f \"Green read mode: { green_mode } , Red read mode: { red_mode } \" ) print ( f \"Green read mode: { green_mode } \" ) print ( f \"Red read mode: { red_mode } \" ) return green_mode , red_mode @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"QueryReadMode"},{"location":"scripts/QueryReadMode/#queryreadmode","text":"Bases: KPFTranslatorFunction Returns string describing the read mode. Source code in kpf/spectrograph/QueryReadMode.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 class QueryReadMode ( KPFTranslatorFunction ): '''Returns string describing the read mode. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfgreen = ktl . cache ( 'kpfgreen' ) green_normal_file = cfg . get ( 'acf_files' , 'green_normal' ) green_fast_file = cfg . get ( 'acf_files' , 'green_fast' ) green_ACFFILE = Path ( kpfgreen [ 'ACFFILE' ] . read ()) . stem if green_ACFFILE == green_normal_file : green_mode = 'normal' elif green_ACFFILE == green_fast_file : green_mode = 'fast' else : green_mode = 'unknown' kpfred = ktl . cache ( 'kpfred' ) red_normal_file = cfg . get ( 'acf_files' , 'red_normal' ) red_fast_file = cfg . get ( 'acf_files' , 'red_fast' ) red_ACFFILE = Path ( kpfred [ 'ACFFILE' ] . read ()) . stem if red_ACFFILE == red_normal_file : red_mode = 'normal' elif red_ACFFILE == red_fast_file : red_mode = 'fast' else : red_mode = 'unknown' log . debug ( f \"Green read mode: { green_mode } , Red read mode: { red_mode } \" ) print ( f \"Green read mode: { green_mode } \" ) print ( f \"Red read mode: { red_mode } \" ) return green_mode , red_mode @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"QueryReadMode"},{"location":"scripts/RecoverDetectors/","text":"RecoverDetectors Bases: KPFTranslatorFunction Try to examine the state of all detectors an run the appropriate recovery ARGS: None Source code in kpf/spectrograph/ResetDetectors.py 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 class RecoverDetectors ( KPFTranslatorFunction ): '''Try to examine the state of all detectors an run the appropriate recovery ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): log . warning ( 'Attempting a detector recovery' ) timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) kpfmon = ktl . cache ( 'kpfmon' ) camera_status = kpfmon [ 'CAMSTATESTA' ] . read () if camera_status == 'OK' : log . warning ( 'No camera error state detected by kpfmon' ) explainnr = ktl . cache ( 'kpfexpose' , 'EXPLAINNR' ) explainnr_str = explainnr . read () if explainnr_str . find ( 'hk:' ) >= 0 : log . warning ( 'kpfexpose.EXPLAINNR contains hk' ) ResetCaHKDetector . execute ({}) elif camera_status == 'ERROR' : if kpfmon [ 'G_STATESTA' ] . read () == 'ERROR' : ResetGreenDetector . execute ({}) if kpfmon [ 'R_STATESTA' ] . read () == 'ERROR' : ResetRedDetector . execute ({}) if kpfmon [ 'H_STATESTA' ] . read () == 'ERROR' : ResetCaHKDetector . execute ({}) if kpfmon [ 'E_STATESTA' ] . read () == 'ERROR' : ResetExpMeterDetector . execute ({}) else : log . warning ( f 'kpfmon.CAMSTATESTA= { camera_status } . No action taken.' ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) log . debug ( f 'Waiting { timeout : .1f } s for EXPOSE to be Readout or Ready' ) expr = f \"($kpfexpose.EXPOSE == 'Ready') or ($kpfexpose.EXPOSE == 'Readout')\" log . warning ( f \"Waiting for kpfexpose to be Ready or Readout\" ) success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : kpfexposeexpose = ktl . cache ( 'kpfexpose' , 'EXPOSE' ) raise FailedToReachDestination ( kpfexposeexpose . read (), 'Ready or Readout' ) else : kpfexpose = ktl . cache ( 'kpfexpose' ) log . info ( f \"Reset detectors done\" ) log . info ( f \"kpfexpose.EXPOSE = { kpfexpose [ 'EXPOSE' ] . read () } \" ) log . info ( f \"kpfexpose.EXPLAINR = { kpfexpose [ 'EXPLAINR' ] . read () } \" ) log . info ( f \"kpfexpose.EXPLAINNR = { kpfexpose [ 'EXPLAINNR' ] . read () } \" )","title":"RecoverDetectors"},{"location":"scripts/RecoverDetectors/#recoverdetectors","text":"Bases: KPFTranslatorFunction Try to examine the state of all detectors an run the appropriate recovery","title":"RecoverDetectors"},{"location":"scripts/RecoverDetectors/#kpf.spectrograph.ResetDetectors.RecoverDetectors--args","text":"None Source code in kpf/spectrograph/ResetDetectors.py 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 class RecoverDetectors ( KPFTranslatorFunction ): '''Try to examine the state of all detectors an run the appropriate recovery ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): log . warning ( 'Attempting a detector recovery' ) timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) kpfmon = ktl . cache ( 'kpfmon' ) camera_status = kpfmon [ 'CAMSTATESTA' ] . read () if camera_status == 'OK' : log . warning ( 'No camera error state detected by kpfmon' ) explainnr = ktl . cache ( 'kpfexpose' , 'EXPLAINNR' ) explainnr_str = explainnr . read () if explainnr_str . find ( 'hk:' ) >= 0 : log . warning ( 'kpfexpose.EXPLAINNR contains hk' ) ResetCaHKDetector . execute ({}) elif camera_status == 'ERROR' : if kpfmon [ 'G_STATESTA' ] . read () == 'ERROR' : ResetGreenDetector . execute ({}) if kpfmon [ 'R_STATESTA' ] . read () == 'ERROR' : ResetRedDetector . execute ({}) if kpfmon [ 'H_STATESTA' ] . read () == 'ERROR' : ResetCaHKDetector . execute ({}) if kpfmon [ 'E_STATESTA' ] . read () == 'ERROR' : ResetExpMeterDetector . execute ({}) else : log . warning ( f 'kpfmon.CAMSTATESTA= { camera_status } . No action taken.' ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) log . debug ( f 'Waiting { timeout : .1f } s for EXPOSE to be Readout or Ready' ) expr = f \"($kpfexpose.EXPOSE == 'Ready') or ($kpfexpose.EXPOSE == 'Readout')\" log . warning ( f \"Waiting for kpfexpose to be Ready or Readout\" ) success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : kpfexposeexpose = ktl . cache ( 'kpfexpose' , 'EXPOSE' ) raise FailedToReachDestination ( kpfexposeexpose . read (), 'Ready or Readout' ) else : kpfexpose = ktl . cache ( 'kpfexpose' ) log . info ( f \"Reset detectors done\" ) log . info ( f \"kpfexpose.EXPOSE = { kpfexpose [ 'EXPOSE' ] . read () } \" ) log . info ( f \"kpfexpose.EXPLAINR = { kpfexpose [ 'EXPLAINR' ] . read () } \" ) log . info ( f \"kpfexpose.EXPLAINNR = { kpfexpose [ 'EXPLAINNR' ] . read () } \" )","title":"ARGS:"},{"location":"scripts/RecoverFromLowPowerMode/","text":"RecoverFromLowPowerMode Bases: KPFTranslatorFunction Recover from low power mode. Power on the Ca HK systems Restore cooling to Ca HK detector Re-enable Ca HK detector Power on CRED2 systems Source code in kpf/scripts/RecoverFromLowPowerMode.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class RecoverFromLowPowerMode ( KPFTranslatorFunction ): '''Recover from low power mode. - Power on the Ca HK systems - Restore cooling to Ca HK detector - Re-enable Ca HK detector - Power on CRED2 systems ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfconfig = ktl . cache ( 'kpfconfig' ) kpfpower = ktl . cache ( 'kpfpower' ) # Power up Ca HK detector systems kpf_hk = ktl . cache ( 'kpf_hk' ) log . info ( 'Powering on Ca HK detector systems' ) log . debug ( f \"Powering on { kpfpower [ 'OUTLET_J1_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_J1' ] . write ( 'On' ) log . debug ( f \"Powering on { kpfpower [ 'OUTLET_J2_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_J2' ] . write ( 'On' ) log . debug ( f \"Powering on { kpfpower [ 'OUTLET_J5_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_J5' ] . write ( 'On' ) time . sleep ( 10 ) log . info ( 'Turning Ca HK detector cooling on' ) kpf_hk [ 'COOLING' ] . write ( 'On' ) kpf_hk [ 'COOLTARG' ] . write ( - 60 ) log . info ( 'Enabling Ca HK detector' ) kpfconfig [ 'CA_HK_ENABLED' ] . write ( 'Yes' ) # Power up CRED2 detector systems log . info ( 'Powering on CRED2 detector systems' ) log . debug ( f \"Powering on { kpfpower [ 'OUTLET_K2_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_K2' ] . write ( 'On' ) log . debug ( f \"Powering on { kpfpower [ 'OUTLET_K3_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_K3' ] . write ( 'On' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--force\" , dest = \"force\" , default = False , action = \"store_true\" , help = \"Force change? This will terminate any running scripts.\" ) return super () . add_cmdline_args ( parser , cfg )","title":"RecoverFromLowPowerMode"},{"location":"scripts/RecoverFromLowPowerMode/#recoverfromlowpowermode","text":"Bases: KPFTranslatorFunction Recover from low power mode. Power on the Ca HK systems Restore cooling to Ca HK detector Re-enable Ca HK detector Power on CRED2 systems Source code in kpf/scripts/RecoverFromLowPowerMode.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class RecoverFromLowPowerMode ( KPFTranslatorFunction ): '''Recover from low power mode. - Power on the Ca HK systems - Restore cooling to Ca HK detector - Re-enable Ca HK detector - Power on CRED2 systems ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfconfig = ktl . cache ( 'kpfconfig' ) kpfpower = ktl . cache ( 'kpfpower' ) # Power up Ca HK detector systems kpf_hk = ktl . cache ( 'kpf_hk' ) log . info ( 'Powering on Ca HK detector systems' ) log . debug ( f \"Powering on { kpfpower [ 'OUTLET_J1_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_J1' ] . write ( 'On' ) log . debug ( f \"Powering on { kpfpower [ 'OUTLET_J2_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_J2' ] . write ( 'On' ) log . debug ( f \"Powering on { kpfpower [ 'OUTLET_J5_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_J5' ] . write ( 'On' ) time . sleep ( 10 ) log . info ( 'Turning Ca HK detector cooling on' ) kpf_hk [ 'COOLING' ] . write ( 'On' ) kpf_hk [ 'COOLTARG' ] . write ( - 60 ) log . info ( 'Enabling Ca HK detector' ) kpfconfig [ 'CA_HK_ENABLED' ] . write ( 'Yes' ) # Power up CRED2 detector systems log . info ( 'Powering on CRED2 detector systems' ) log . debug ( f \"Powering on { kpfpower [ 'OUTLET_K2_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_K2' ] . write ( 'On' ) log . debug ( f \"Powering on { kpfpower [ 'OUTLET_K3_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_K3' ] . write ( 'On' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--force\" , dest = \"force\" , default = False , action = \"store_true\" , help = \"Force change? This will terminate any running scripts.\" ) return super () . add_cmdline_args ( parser , cfg )","title":"RecoverFromLowPowerMode"},{"location":"scripts/ResetCaHKDetector/","text":"ResetCaHKDetector Bases: KPFTranslatorFunction Resets the Ca HK detector by aborting the exposure ARGS: None Source code in kpf/spectrograph/ResetDetectors.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class ResetCaHKDetector ( KPFTranslatorFunction ): '''Resets the Ca HK detector by aborting the exposure ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): expose = ktl . cache ( 'kpf_hk' , 'EXPOSE' ) log . warning ( f \"Resetting/Aborting: kpf_hk.EXPOSE = abort\" ) expose . write ( 'abort' ) log . debug ( 'Reset/abort command sent' ) @classmethod def post_condition ( cls , args , logger , cfg ): expstate = ktl . cache ( 'kpf_hk' , 'EXPSTATE' ) timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) log . warning ( f \"Waiting for kpf_hk to be Ready\" ) success = expstate . waitFor ( '==\"Ready\"' , timeout = timeout ) if success is not True : raise FailedToReachDestination ( expstate . read (), 'Ready' )","title":"ResetCaHKDetector"},{"location":"scripts/ResetCaHKDetector/#resetcahkdetector","text":"Bases: KPFTranslatorFunction Resets the Ca HK detector by aborting the exposure","title":"ResetCaHKDetector"},{"location":"scripts/ResetCaHKDetector/#kpf.spectrograph.ResetDetectors.ResetCaHKDetector--args","text":"None Source code in kpf/spectrograph/ResetDetectors.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class ResetCaHKDetector ( KPFTranslatorFunction ): '''Resets the Ca HK detector by aborting the exposure ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): expose = ktl . cache ( 'kpf_hk' , 'EXPOSE' ) log . warning ( f \"Resetting/Aborting: kpf_hk.EXPOSE = abort\" ) expose . write ( 'abort' ) log . debug ( 'Reset/abort command sent' ) @classmethod def post_condition ( cls , args , logger , cfg ): expstate = ktl . cache ( 'kpf_hk' , 'EXPSTATE' ) timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) log . warning ( f \"Waiting for kpf_hk to be Ready\" ) success = expstate . waitFor ( '==\"Ready\"' , timeout = timeout ) if success is not True : raise FailedToReachDestination ( expstate . read (), 'Ready' )","title":"ARGS:"},{"location":"scripts/ResetDetectors/","text":"ResetDetectors Bases: KPFTranslatorFunction Resets the kpfexpose service by setting kpfexpose.EXPOSE = Reset Description from Will Deich: This sets EXPOSE=Reset for the appropriate service. For the ktlcamerad services, that just means, \u201ceven though you\u2019ve not received (from camerad) the normal sequence of messages for a completed exposure, pretend everything is fine for starting a new exposure.\u201d ARGS: None Source code in kpf/spectrograph/ResetDetectors.py 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 class ResetDetectors ( KPFTranslatorFunction ): '''Resets the kpfexpose service by setting kpfexpose.EXPOSE = Reset Description from Will Deich: This sets EXPOSE=Reset for the appropriate service. For the ktlcamerad services, that just means, \u201ceven though you\u2019ve not received (from camerad) the normal sequence of messages for a completed exposure, pretend everything is fine for starting a new exposure.\u201d ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) log . warning ( f \"Resetting: kpfexpose.EXPOSE = Reset\" ) kpfexpose [ 'EXPOSE' ] . write ( 'Reset' ) log . debug ( 'Reset command sent' ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) log . debug ( f 'Waiting { timeout : .1f } s for EXPOSE to be Readout or Ready' ) expr = f \"($kpfexpose.EXPOSE == 'Ready') or ($kpfexpose.EXPOSE == 'Readout')\" log . warning ( f \"Waiting for kpfexpose to be Ready or Readout\" ) success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : kpfexposeexpose = ktl . cache ( 'kpfexpose' , 'EXPOSE' ) raise FailedToReachDestination ( kpfexposeexpose . read (), 'Ready or Readout' ) else : kpfexpose = ktl . cache ( 'kpfexpose' ) log . info ( f \"Reset detectors done\" ) log . info ( f \"kpfexpose.EXPOSE = { kpfexpose [ 'EXPOSE' ] . read () } \" ) log . info ( f \"kpfexpose.EXPLAINR = { kpfexpose [ 'EXPLAINR' ] . read () } \" ) log . info ( f \"kpfexpose.EXPLAINNR = { kpfexpose [ 'EXPLAINNR' ] . read () } \" )","title":"ResetDetectors"},{"location":"scripts/ResetDetectors/#resetdetectors","text":"Bases: KPFTranslatorFunction Resets the kpfexpose service by setting kpfexpose.EXPOSE = Reset Description from Will Deich: This sets EXPOSE=Reset for the appropriate service. For the ktlcamerad services, that just means, \u201ceven though you\u2019ve not received (from camerad) the normal sequence of messages for a completed exposure, pretend everything is fine for starting a new exposure.\u201d","title":"ResetDetectors"},{"location":"scripts/ResetDetectors/#kpf.spectrograph.ResetDetectors.ResetDetectors--args","text":"None Source code in kpf/spectrograph/ResetDetectors.py 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 class ResetDetectors ( KPFTranslatorFunction ): '''Resets the kpfexpose service by setting kpfexpose.EXPOSE = Reset Description from Will Deich: This sets EXPOSE=Reset for the appropriate service. For the ktlcamerad services, that just means, \u201ceven though you\u2019ve not received (from camerad) the normal sequence of messages for a completed exposure, pretend everything is fine for starting a new exposure.\u201d ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) log . warning ( f \"Resetting: kpfexpose.EXPOSE = Reset\" ) kpfexpose [ 'EXPOSE' ] . write ( 'Reset' ) log . debug ( 'Reset command sent' ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) log . debug ( f 'Waiting { timeout : .1f } s for EXPOSE to be Readout or Ready' ) expr = f \"($kpfexpose.EXPOSE == 'Ready') or ($kpfexpose.EXPOSE == 'Readout')\" log . warning ( f \"Waiting for kpfexpose to be Ready or Readout\" ) success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : kpfexposeexpose = ktl . cache ( 'kpfexpose' , 'EXPOSE' ) raise FailedToReachDestination ( kpfexposeexpose . read (), 'Ready or Readout' ) else : kpfexpose = ktl . cache ( 'kpfexpose' ) log . info ( f \"Reset detectors done\" ) log . info ( f \"kpfexpose.EXPOSE = { kpfexpose [ 'EXPOSE' ] . read () } \" ) log . info ( f \"kpfexpose.EXPLAINR = { kpfexpose [ 'EXPLAINR' ] . read () } \" ) log . info ( f \"kpfexpose.EXPLAINNR = { kpfexpose [ 'EXPLAINNR' ] . read () } \" )","title":"ARGS:"},{"location":"scripts/ResetExpMeterDetector/","text":"ResetExpMeterDetector Bases: KPFTranslatorFunction Resets the exposure meter detector ARGS: None Source code in kpf/spectrograph/ResetDetectors.py 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 class ResetExpMeterDetector ( KPFTranslatorFunction ): '''Resets the exposure meter detector ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): expose = ktl . cache ( 'kpf_expmeter' , 'EXPOSE' ) log . warning ( f \"Resetting: kpf_expmeter.EXPOSE = abort\" ) expose . write ( 'Reset' ) log . debug ( 'Reset command sent' ) @classmethod def post_condition ( cls , args , logger , cfg ): expstate = ktl . cache ( 'kpf_expmeter' , 'EXPSTATE' ) timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) log . warning ( f \"Waiting for kpf_expmeter to be Ready\" ) success = expstate . waitFor ( '==\"Ready\"' , timeout = timeout ) if success is not True : raise FailedToReachDestination ( expstate . read (), 'Ready' )","title":"ResetExpMeterDetector"},{"location":"scripts/ResetExpMeterDetector/#resetexpmeterdetector","text":"Bases: KPFTranslatorFunction Resets the exposure meter detector","title":"ResetExpMeterDetector"},{"location":"scripts/ResetExpMeterDetector/#kpf.spectrograph.ResetDetectors.ResetExpMeterDetector--args","text":"None Source code in kpf/spectrograph/ResetDetectors.py 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 class ResetExpMeterDetector ( KPFTranslatorFunction ): '''Resets the exposure meter detector ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): expose = ktl . cache ( 'kpf_expmeter' , 'EXPOSE' ) log . warning ( f \"Resetting: kpf_expmeter.EXPOSE = abort\" ) expose . write ( 'Reset' ) log . debug ( 'Reset command sent' ) @classmethod def post_condition ( cls , args , logger , cfg ): expstate = ktl . cache ( 'kpf_expmeter' , 'EXPSTATE' ) timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) log . warning ( f \"Waiting for kpf_expmeter to be Ready\" ) success = expstate . waitFor ( '==\"Ready\"' , timeout = timeout ) if success is not True : raise FailedToReachDestination ( expstate . read (), 'Ready' )","title":"ARGS:"},{"location":"scripts/ResetGreenDetector/","text":"ResetGreenDetector Bases: KPFTranslatorFunction Resets the kpfgreen detector ARGS: None Source code in kpf/spectrograph/ResetDetectors.py 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 class ResetGreenDetector ( KPFTranslatorFunction ): '''Resets the kpfgreen detector ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # Check if the auto reset is already doing this current_expstate = ktl . cache ( 'kpfgreen' , 'EXPSTATE' ) current_expstate . read () if current_expstate == 'Resetting' : return elif current_expstate == 'Exposing' : log . warning ( 'Can not send reset during exposure' ) return # Send the reset expose = ktl . cache ( 'kpfgreen' , 'EXPOSE' ) log . warning ( f \"Resetting: kpfgreen.EXPOSE = Reset\" ) expose . write ( 'Reset' ) log . debug ( 'Reset command sent' ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) log . warning ( f \"Waiting for kpfgreen to be Readout or Ready\" ) expr = f \"($kpfgreen.EXPOSE == 'Ready') or ($kpfgreen.EXPOSE == 'Readout')\" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : expose = ktl . cache ( 'kpfgreen' , 'EXPOSE' ) raise FailedToReachDestination ( expose . read (), 'Ready or Readout' ) else : kpfexpose = ktl . cache ( 'kpfexpose' ) log . info ( f \"ResetGreenDetector done\" ) log . info ( f \"kpfexpose.EXPOSE = { kpfexpose [ 'EXPOSE' ] . read () } \" ) log . info ( f \"kpfexpose.EXPLAINR = { kpfexpose [ 'EXPLAINR' ] . read () } \" ) log . info ( f \"kpfexpose.EXPLAINNR = { kpfexpose [ 'EXPLAINNR' ] . read () } \" )","title":"ResetGreenDetector"},{"location":"scripts/ResetGreenDetector/#resetgreendetector","text":"Bases: KPFTranslatorFunction Resets the kpfgreen detector","title":"ResetGreenDetector"},{"location":"scripts/ResetGreenDetector/#kpf.spectrograph.ResetDetectors.ResetGreenDetector--args","text":"None Source code in kpf/spectrograph/ResetDetectors.py 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 class ResetGreenDetector ( KPFTranslatorFunction ): '''Resets the kpfgreen detector ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # Check if the auto reset is already doing this current_expstate = ktl . cache ( 'kpfgreen' , 'EXPSTATE' ) current_expstate . read () if current_expstate == 'Resetting' : return elif current_expstate == 'Exposing' : log . warning ( 'Can not send reset during exposure' ) return # Send the reset expose = ktl . cache ( 'kpfgreen' , 'EXPOSE' ) log . warning ( f \"Resetting: kpfgreen.EXPOSE = Reset\" ) expose . write ( 'Reset' ) log . debug ( 'Reset command sent' ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) log . warning ( f \"Waiting for kpfgreen to be Readout or Ready\" ) expr = f \"($kpfgreen.EXPOSE == 'Ready') or ($kpfgreen.EXPOSE == 'Readout')\" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : expose = ktl . cache ( 'kpfgreen' , 'EXPOSE' ) raise FailedToReachDestination ( expose . read (), 'Ready or Readout' ) else : kpfexpose = ktl . cache ( 'kpfexpose' ) log . info ( f \"ResetGreenDetector done\" ) log . info ( f \"kpfexpose.EXPOSE = { kpfexpose [ 'EXPOSE' ] . read () } \" ) log . info ( f \"kpfexpose.EXPLAINR = { kpfexpose [ 'EXPLAINR' ] . read () } \" ) log . info ( f \"kpfexpose.EXPLAINNR = { kpfexpose [ 'EXPLAINNR' ] . read () } \" )","title":"ARGS:"},{"location":"scripts/ResetRedDetector/","text":"ResetRedDetector Bases: KPFTranslatorFunction Resets the kpfred detector ARGS: None Source code in kpf/spectrograph/ResetDetectors.py 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 class ResetRedDetector ( KPFTranslatorFunction ): '''Resets the kpfred detector ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # Check if the auto reset is already doing this current_expstate = ktl . cache ( 'kpfred' , 'EXPSTATE' ) current_expstate . read () if current_expstate == 'Resetting' : return elif current_expstate == 'Exposing' : log . warning ( 'Can not send reset during exposure' ) return # Send the reset expose = ktl . cache ( 'kpfred' , 'EXPOSE' ) log . warning ( f \"Resetting: kpfred.EXPOSE = Reset\" ) expose . write ( 'Reset' ) log . debug ( 'Reset command sent' ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) log . warning ( f \"Waiting for kpfred to be Readout or Ready\" ) expr = f \"($kpfred.EXPOSE == 'Ready') or ($kpfred.EXPOSE == 'Readout')\" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : expose = ktl . cache ( 'kpfred' , 'EXPOSE' ) raise FailedToReachDestination ( expose . read (), 'Ready or Readout' ) else : kpfexpose = ktl . cache ( 'kpfexpose' ) log . info ( f \"ResetRedDetector done\" ) log . info ( f \"kpfexpose.EXPOSE = { kpfexpose [ 'EXPOSE' ] . read () } \" ) log . info ( f \"kpfexpose.EXPLAINR = { kpfexpose [ 'EXPLAINR' ] . read () } \" ) log . info ( f \"kpfexpose.EXPLAINNR = { kpfexpose [ 'EXPLAINNR' ] . read () } \" )","title":"ResetRedDetector"},{"location":"scripts/ResetRedDetector/#resetreddetector","text":"Bases: KPFTranslatorFunction Resets the kpfred detector","title":"ResetRedDetector"},{"location":"scripts/ResetRedDetector/#kpf.spectrograph.ResetDetectors.ResetRedDetector--args","text":"None Source code in kpf/spectrograph/ResetDetectors.py 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 class ResetRedDetector ( KPFTranslatorFunction ): '''Resets the kpfred detector ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # Check if the auto reset is already doing this current_expstate = ktl . cache ( 'kpfred' , 'EXPSTATE' ) current_expstate . read () if current_expstate == 'Resetting' : return elif current_expstate == 'Exposing' : log . warning ( 'Can not send reset during exposure' ) return # Send the reset expose = ktl . cache ( 'kpfred' , 'EXPOSE' ) log . warning ( f \"Resetting: kpfred.EXPOSE = Reset\" ) expose . write ( 'Reset' ) log . debug ( 'Reset command sent' ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) log . warning ( f \"Waiting for kpfred to be Readout or Ready\" ) expr = f \"($kpfred.EXPOSE == 'Ready') or ($kpfred.EXPOSE == 'Readout')\" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : expose = ktl . cache ( 'kpfred' , 'EXPOSE' ) raise FailedToReachDestination ( expose . read (), 'Ready or Readout' ) else : kpfexpose = ktl . cache ( 'kpfexpose' ) log . info ( f \"ResetRedDetector done\" ) log . info ( f \"kpfexpose.EXPOSE = { kpfexpose [ 'EXPOSE' ] . read () } \" ) log . info ( f \"kpfexpose.EXPLAINR = { kpfexpose [ 'EXPLAINR' ] . read () } \" ) log . info ( f \"kpfexpose.EXPLAINNR = { kpfexpose [ 'EXPLAINNR' ] . read () } \" )","title":"ARGS:"},{"location":"scripts/Run2DGridSearch/","text":"Run2DGridSearch Bases: KPFTranslatorFunction Source code in kpf/engineering/Run2DGridSearch.py 16 17 18 19 20 21 22 23 24 25 26 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 class Run2DGridSearch ( KPFTranslatorFunction ): ''' ''' @classmethod @obey_scriptrun def pre_condition ( cls , OB , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): n = args . get ( 'n' ) d = args . get ( 'd' ) Gmag = args . get ( 'Gmag' ) time_on_position = args . get ( 'time_on_position' ) comment = args . get ( 'comment' , '' ) em_parameters = PredictExpMeterParameters . execute ({ 'Gmag' : Gmag }) # Check if FVCs are on, if so, use them FVCs_that_are_on = [] for camera in [ 'SCI' , 'CAHK' ]: camnum = { 'SCI' : 1 , 'CAHK' : 2 }[ camera ] powerkw = ktl . cache ( 'kpfpower' , f 'KPFFVC { camnum } ' ) if powerkw . read () . lower () == 'on' : FVCs_that_are_on . append ( camera ) FVCstring = ',' . join ( FVCs_that_are_on ) if len ( FVCs_that_are_on ) > 0 : fvc_parameters = PredictFVCParameters . execute ({ 'Gmag' : Gmag }) print ( f \"Predicted FVC parameters:\" ) print ( fvc_parameters ) print ( 'Set the FVC parameters manually and press enter to continue' ) user_input = input () dcs = ktl . cache ( 'dcs1' ) targname = dcs [ 'TARGNAME' ] . read () args = { 'Template_Name' : 'kpf_eng_grid' , 'Template_Version' : 0.4 , 'Grid' : 'TipTilt' , 'dx' : d , 'dy' : d , 'TimeOnPosition' : time_on_position , 'TriggerCaHK' : False , 'TriggerGreen' : False , 'TriggerRed' : False , 'TriggerExpMeter' : True , 'UseCRED2' : True , 'SSS_Science' : True , 'SSS_Sky' : True , 'SSS_CalSciSky' : False , 'ExpMeter_exptime' : em_parameters [ 'ExpMeterExpTime' ], 'FVCs' : FVCstring , } x_args = { 'comment' : f '1D in X { targname } (G= { Gmag : .1f } ) { comment } ' , 'nx' : n , 'ny' : 1 , } args . update ( x_args ) GridSearch . execute ( args ) y_args = { 'comment' : f '1D in Y { targname } (G= { Gmag : .1f } ) { comment } ' , 'nx' : 1 , 'ny' : n , } args . update ( y_args ) GridSearch . execute ( args ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'd' , type = float , help = \"Separation between positions (in guder pix)\" ) parser . add_argument ( 'n' , type = int , help = \"Number of position samples in each axis\" ) parser . add_argument ( 'Gmag' , type = float , help = \"The G magnitude of the target\" ) parser . add_argument ( \"--comment\" , dest = \"comment\" , type = str , default = '' , help = \"Additional comment text\" ) parser . add_argument ( \"--time\" , dest = \"time_on_position\" , type = float , default = 15 , help = \"Dwell time at each position (s)\" ) return super () . add_cmdline_args ( parser , cfg )","title":"Run2DGridSearch"},{"location":"scripts/Run2DGridSearch/#run2dgridsearch","text":"Bases: KPFTranslatorFunction Source code in kpf/engineering/Run2DGridSearch.py 16 17 18 19 20 21 22 23 24 25 26 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 class Run2DGridSearch ( KPFTranslatorFunction ): ''' ''' @classmethod @obey_scriptrun def pre_condition ( cls , OB , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): n = args . get ( 'n' ) d = args . get ( 'd' ) Gmag = args . get ( 'Gmag' ) time_on_position = args . get ( 'time_on_position' ) comment = args . get ( 'comment' , '' ) em_parameters = PredictExpMeterParameters . execute ({ 'Gmag' : Gmag }) # Check if FVCs are on, if so, use them FVCs_that_are_on = [] for camera in [ 'SCI' , 'CAHK' ]: camnum = { 'SCI' : 1 , 'CAHK' : 2 }[ camera ] powerkw = ktl . cache ( 'kpfpower' , f 'KPFFVC { camnum } ' ) if powerkw . read () . lower () == 'on' : FVCs_that_are_on . append ( camera ) FVCstring = ',' . join ( FVCs_that_are_on ) if len ( FVCs_that_are_on ) > 0 : fvc_parameters = PredictFVCParameters . execute ({ 'Gmag' : Gmag }) print ( f \"Predicted FVC parameters:\" ) print ( fvc_parameters ) print ( 'Set the FVC parameters manually and press enter to continue' ) user_input = input () dcs = ktl . cache ( 'dcs1' ) targname = dcs [ 'TARGNAME' ] . read () args = { 'Template_Name' : 'kpf_eng_grid' , 'Template_Version' : 0.4 , 'Grid' : 'TipTilt' , 'dx' : d , 'dy' : d , 'TimeOnPosition' : time_on_position , 'TriggerCaHK' : False , 'TriggerGreen' : False , 'TriggerRed' : False , 'TriggerExpMeter' : True , 'UseCRED2' : True , 'SSS_Science' : True , 'SSS_Sky' : True , 'SSS_CalSciSky' : False , 'ExpMeter_exptime' : em_parameters [ 'ExpMeterExpTime' ], 'FVCs' : FVCstring , } x_args = { 'comment' : f '1D in X { targname } (G= { Gmag : .1f } ) { comment } ' , 'nx' : n , 'ny' : 1 , } args . update ( x_args ) GridSearch . execute ( args ) y_args = { 'comment' : f '1D in Y { targname } (G= { Gmag : .1f } ) { comment } ' , 'nx' : 1 , 'ny' : n , } args . update ( y_args ) GridSearch . execute ( args ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'd' , type = float , help = \"Separation between positions (in guder pix)\" ) parser . add_argument ( 'n' , type = int , help = \"Number of position samples in each axis\" ) parser . add_argument ( 'Gmag' , type = float , help = \"The G magnitude of the target\" ) parser . add_argument ( \"--comment\" , dest = \"comment\" , type = str , default = '' , help = \"Additional comment text\" ) parser . add_argument ( \"--time\" , dest = \"time_on_position\" , type = float , default = 15 , help = \"Dwell time at each position (s)\" ) return super () . add_cmdline_args ( parser , cfg )","title":"Run2DGridSearch"},{"location":"scripts/RunCalOB/","text":"RunCalOB Bases: KPFTranslatorFunction Script to run a full Calibration OB from the command line. This must have arguments as input, typically from a file using the -f command line tool. This script is abortable. When .abort_execution() is invoked, the kpconfig.SCRIPTSTOP is set to Yes. This script checked for this value at various locations in the script. As a result, the script will not stop immediately, but will stop when it reaches a breakpoint. ARGS: OB - dict A fully specified observing block (OB). Source code in kpf/scripts/RunCalOB.py 26 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 class RunCalOB ( KPFTranslatorFunction ): '''Script to run a full Calibration OB from the command line. This must have arguments as input, typically from a file using the `-f` command line tool. This script is abortable. When `.abort_execution()` is invoked, the `kpconfig.SCRIPTSTOP` is set to Yes. This script checked for this value at various locations in the script. As a result, the script will not stop immediately, but will stop when it reaches a breakpoint. ARGS: ===== * __OB__ - `dict` A fully specified observing block (OB). ''' abortable = True @classmethod def pre_condition ( cls , OB , logger , cfg ): check_input ( OB , 'Template_Name' , allowed_values = [ 'kpf_cal' ]) check_input ( OB , 'Template_Version' , version_check = True , value_min = '0.5' ) @classmethod @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in OB : if key not in [ 'SEQ_Darks' , 'SEQ_Calibrations' ]: log . debug ( f \" { key } : { OB [ key ] } \" ) else : log . debug ( f \" { key } :\" ) for entry in OB [ key ]: log . debug ( f \" { entry } \" ) log . info ( '-------------------------' ) # Configure: Turn on Lamps try : ConfigureForCalibrations . execute ( OB ) except ExistingScriptRunning as e : log . error ( 'ExistingScriptRunning' ) sys . exit ( 1 ) except Exception as e : log . error ( 'ConfigureForCalibrations Failed' ) log . error ( e ) traceback_text = traceback . format_exc () log . error ( traceback_text ) # Email error to kpf_info if not isinstance ( e , ScriptStopTriggered ): try : msg = [ f ' { type ( e ) } ' , f ' { traceback_text } ' , '' , f ' { OB } ' ] SendEmail . execute ({ 'Subject' : 'ConfigureForCalibrations Failed' , 'Message' : ' \\n ' . join ( msg )}) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) log . error ( 'Running CleanupAfterCalibrations and exiting' ) CleanupAfterCalibrations . execute ( OB ) raise e check_script_running () set_script_keywords ( Path ( __file__ ) . name , os . getpid ()) # Execute the Dark Sequence try : darks = OB . get ( 'SEQ_Darks' , []) if len ( darks ) > 0 : log . info ( f \"Setting source select shutters\" ) SetSourceSelectShutters . execute ({}) # No args defaults all to false log . info ( f \"Setting timed shutters\" ) SetTimedShutters . execute ({}) # No args defaults all to false log . info ( f \"Setting OCTAGON to Home position\" ) SetCalSource . execute ({ 'CalSource' : 'Home' }) log . info ( f \"Setting FlatField Fiber position to 'Blank'\" ) SetFlatFieldFiberPos . execute ({ 'FF_FiberPos' : 'Blank' }) for dark in darks : # Wrap in try/except so that cleanup happens dark [ 'Template_Name' ] = 'kpf_dark' dark [ 'Template_Version' ] = OB [ 'Template_Version' ] ExecuteDark . execute ( dark ) except Exception as e : log . error ( \"ExecuteDarks failed:\" ) log . error ( e ) traceback_text = traceback . format_exc () log . error ( traceback_text ) # Email error to kpf_info if not isinstance ( e , ScriptStopTriggered ): try : msg = [ f ' { type ( e ) } ' , f ' { traceback_text } ' , '' , f ' { OB } ' ] SendEmail . execute ({ 'Subject' : 'ExecuteDarks Failed' , 'Message' : ' \\n ' . join ( msg )}) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) # Cleanup log . error ( 'Running CleanupAfterCalibrations and exiting' ) CleanupAfterCalibrations . execute ( OB ) sys . exit ( 1 ) # Execute the Cal Sequence try : cals = OB . get ( 'SEQ_Calibrations' , []) for cal in cals : cal [ 'TriggerCaHK' ] = OB [ 'TriggerCaHK' ] cal [ 'TriggerGreen' ] = OB [ 'TriggerGreen' ] cal [ 'TriggerRed' ] = OB [ 'TriggerRed' ] # No need to specify TimedShutter_CaHK in OB/calibration cal [ 'TimedShutter_CaHK' ] = OB . get ( 'TriggerCaHK' , False ) log . debug ( f \"Automatically setting TimedShutter_CaHK: { cal [ 'TimedShutter_CaHK' ] } \" ) cal [ 'Template_Name' ] = 'kpf_lamp' cal [ 'Template_Version' ] = OB [ 'Template_Version' ] cal [ 'nointensemon' ] = OB . get ( 'nointensemon' , False ) cal [ 'leave_lamps_on' ] = OB . get ( 'leave_lamps_on' , False ) # Only needed for LFC ExecuteCal . execute ( cal ) except Exception as e : log . error ( \"ExecuteCal failed:\" ) log . error ( e ) traceback_text = traceback . format_exc () log . error ( traceback_text ) # Email error to kpf_info if not isinstance ( e , ScriptStopTriggered ): try : msg = [ f ' { type ( e ) } ' , f ' { traceback . format_exc () } ' , '' , f ' { OB } ' ] SendEmail . execute ({ 'Subject' : 'ExecuteCals Failed' , 'Message' : ' \\n ' . join ( msg )}) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) # Cleanup log . error ( 'Running CleanupAfterCalibrations and exiting' ) CleanupAfterCalibrations . execute ( OB ) sys . exit ( 1 ) # Cleanup: Turn off lamps try : CleanupAfterCalibrations . execute ( OB ) except Exception as e : log . error ( \"CleanupAfterCalibrations failed:\" ) log . error ( e ) traceback_text = traceback . format_exc () log . error ( traceback_text ) clear_script_keywords () # Email error to kpf_info try : msg = [ f ' { type ( e ) } ' , f ' { traceback_text } ' , '' , f ' { OB } ' ] SendEmail . execute ({ 'Subject' : 'CleanupAfterCalibrations Failed' , 'Message' : ' \\n ' . join ( msg )}) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) @classmethod def post_condition ( cls , OB , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( '--leave_lamps_on' , dest = \"leave_lamps_on\" , default = False , action = \"store_true\" , help = 'Leave the lamps on after cleanup phase?' ) parser . add_argument ( '--nointensemon' , dest = \"nointensemon\" , default = False , action = \"store_true\" , help = 'Skip the intensity monitor measurement?' ) return super () . add_cmdline_args ( parser , cfg )","title":"RunCalOB"},{"location":"scripts/RunCalOB/#runcalob","text":"Bases: KPFTranslatorFunction Script to run a full Calibration OB from the command line. This must have arguments as input, typically from a file using the -f command line tool. This script is abortable. When .abort_execution() is invoked, the kpconfig.SCRIPTSTOP is set to Yes. This script checked for this value at various locations in the script. As a result, the script will not stop immediately, but will stop when it reaches a breakpoint.","title":"RunCalOB"},{"location":"scripts/RunCalOB/#kpf.scripts.RunCalOB.RunCalOB--args","text":"OB - dict A fully specified observing block (OB). Source code in kpf/scripts/RunCalOB.py 26 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 class RunCalOB ( KPFTranslatorFunction ): '''Script to run a full Calibration OB from the command line. This must have arguments as input, typically from a file using the `-f` command line tool. This script is abortable. When `.abort_execution()` is invoked, the `kpconfig.SCRIPTSTOP` is set to Yes. This script checked for this value at various locations in the script. As a result, the script will not stop immediately, but will stop when it reaches a breakpoint. ARGS: ===== * __OB__ - `dict` A fully specified observing block (OB). ''' abortable = True @classmethod def pre_condition ( cls , OB , logger , cfg ): check_input ( OB , 'Template_Name' , allowed_values = [ 'kpf_cal' ]) check_input ( OB , 'Template_Version' , version_check = True , value_min = '0.5' ) @classmethod @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in OB : if key not in [ 'SEQ_Darks' , 'SEQ_Calibrations' ]: log . debug ( f \" { key } : { OB [ key ] } \" ) else : log . debug ( f \" { key } :\" ) for entry in OB [ key ]: log . debug ( f \" { entry } \" ) log . info ( '-------------------------' ) # Configure: Turn on Lamps try : ConfigureForCalibrations . execute ( OB ) except ExistingScriptRunning as e : log . error ( 'ExistingScriptRunning' ) sys . exit ( 1 ) except Exception as e : log . error ( 'ConfigureForCalibrations Failed' ) log . error ( e ) traceback_text = traceback . format_exc () log . error ( traceback_text ) # Email error to kpf_info if not isinstance ( e , ScriptStopTriggered ): try : msg = [ f ' { type ( e ) } ' , f ' { traceback_text } ' , '' , f ' { OB } ' ] SendEmail . execute ({ 'Subject' : 'ConfigureForCalibrations Failed' , 'Message' : ' \\n ' . join ( msg )}) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) log . error ( 'Running CleanupAfterCalibrations and exiting' ) CleanupAfterCalibrations . execute ( OB ) raise e check_script_running () set_script_keywords ( Path ( __file__ ) . name , os . getpid ()) # Execute the Dark Sequence try : darks = OB . get ( 'SEQ_Darks' , []) if len ( darks ) > 0 : log . info ( f \"Setting source select shutters\" ) SetSourceSelectShutters . execute ({}) # No args defaults all to false log . info ( f \"Setting timed shutters\" ) SetTimedShutters . execute ({}) # No args defaults all to false log . info ( f \"Setting OCTAGON to Home position\" ) SetCalSource . execute ({ 'CalSource' : 'Home' }) log . info ( f \"Setting FlatField Fiber position to 'Blank'\" ) SetFlatFieldFiberPos . execute ({ 'FF_FiberPos' : 'Blank' }) for dark in darks : # Wrap in try/except so that cleanup happens dark [ 'Template_Name' ] = 'kpf_dark' dark [ 'Template_Version' ] = OB [ 'Template_Version' ] ExecuteDark . execute ( dark ) except Exception as e : log . error ( \"ExecuteDarks failed:\" ) log . error ( e ) traceback_text = traceback . format_exc () log . error ( traceback_text ) # Email error to kpf_info if not isinstance ( e , ScriptStopTriggered ): try : msg = [ f ' { type ( e ) } ' , f ' { traceback_text } ' , '' , f ' { OB } ' ] SendEmail . execute ({ 'Subject' : 'ExecuteDarks Failed' , 'Message' : ' \\n ' . join ( msg )}) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) # Cleanup log . error ( 'Running CleanupAfterCalibrations and exiting' ) CleanupAfterCalibrations . execute ( OB ) sys . exit ( 1 ) # Execute the Cal Sequence try : cals = OB . get ( 'SEQ_Calibrations' , []) for cal in cals : cal [ 'TriggerCaHK' ] = OB [ 'TriggerCaHK' ] cal [ 'TriggerGreen' ] = OB [ 'TriggerGreen' ] cal [ 'TriggerRed' ] = OB [ 'TriggerRed' ] # No need to specify TimedShutter_CaHK in OB/calibration cal [ 'TimedShutter_CaHK' ] = OB . get ( 'TriggerCaHK' , False ) log . debug ( f \"Automatically setting TimedShutter_CaHK: { cal [ 'TimedShutter_CaHK' ] } \" ) cal [ 'Template_Name' ] = 'kpf_lamp' cal [ 'Template_Version' ] = OB [ 'Template_Version' ] cal [ 'nointensemon' ] = OB . get ( 'nointensemon' , False ) cal [ 'leave_lamps_on' ] = OB . get ( 'leave_lamps_on' , False ) # Only needed for LFC ExecuteCal . execute ( cal ) except Exception as e : log . error ( \"ExecuteCal failed:\" ) log . error ( e ) traceback_text = traceback . format_exc () log . error ( traceback_text ) # Email error to kpf_info if not isinstance ( e , ScriptStopTriggered ): try : msg = [ f ' { type ( e ) } ' , f ' { traceback . format_exc () } ' , '' , f ' { OB } ' ] SendEmail . execute ({ 'Subject' : 'ExecuteCals Failed' , 'Message' : ' \\n ' . join ( msg )}) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) # Cleanup log . error ( 'Running CleanupAfterCalibrations and exiting' ) CleanupAfterCalibrations . execute ( OB ) sys . exit ( 1 ) # Cleanup: Turn off lamps try : CleanupAfterCalibrations . execute ( OB ) except Exception as e : log . error ( \"CleanupAfterCalibrations failed:\" ) log . error ( e ) traceback_text = traceback . format_exc () log . error ( traceback_text ) clear_script_keywords () # Email error to kpf_info try : msg = [ f ' { type ( e ) } ' , f ' { traceback_text } ' , '' , f ' { OB } ' ] SendEmail . execute ({ 'Subject' : 'CleanupAfterCalibrations Failed' , 'Message' : ' \\n ' . join ( msg )}) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) @classmethod def post_condition ( cls , OB , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( '--leave_lamps_on' , dest = \"leave_lamps_on\" , default = False , action = \"store_true\" , help = 'Leave the lamps on after cleanup phase?' ) parser . add_argument ( '--nointensemon' , dest = \"nointensemon\" , default = False , action = \"store_true\" , help = 'Skip the intensity monitor measurement?' ) return super () . add_cmdline_args ( parser , cfg )","title":"ARGS:"},{"location":"scripts/RunSciOB/","text":"RunSciOB Bases: KPFTranslatorFunction Script to run a full Science OB from the command line. This must have arguments as input, typically from a file using the -f command line tool. This script is abortable. When .abort_execution() is invoked, the kpconfig.SCRIPTSTOP is set to Yes. This script checked for this value at various locations in the script. As a result, the script will not stop immediately, but will stop when it reaches a breakpoint. ARGS: OB - dict A fully specified observing block (OB). Source code in kpf/scripts/RunSciOB.py 23 24 25 26 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 class RunSciOB ( KPFTranslatorFunction ): '''Script to run a full Science OB from the command line. This must have arguments as input, typically from a file using the `-f` command line tool. This script is abortable. When `.abort_execution()` is invoked, the `kpconfig.SCRIPTSTOP` is set to Yes. This script checked for this value at various locations in the script. As a result, the script will not stop immediately, but will stop when it reaches a breakpoint. ARGS: ===== * __OB__ - `dict` A fully specified observing block (OB). ''' abortable = True @classmethod def pre_condition ( cls , OB , logger , cfg ): check_input ( OB , 'Template_Name' , allowed_values = [ 'kpf_sci' ]) check_input ( OB , 'Template_Version' , version_check = True , value_min = '0.5' ) @classmethod @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) log . info ( '-------------------------' ) check_scriptstop () # Configure: log . info ( f \"Configuring for Acquisition\" ) ConfigureForAcquisition . execute ( OB ) WaitForConfigureAcquisition . execute ( OB ) check_scriptstop () log . debug ( 'Asking for user input' ) print () print ( \"###############################################################\" ) print ( \" Before continuing, please ensure that the OA has placed\" ) print ( \" the star on the KPF PO and they have initiated tip tilt\" ) print ( \" corrections (if desired).\" ) print () print ( \" Press 'Enter' to begin exposure(s) or 'a' to abort script\" ) print ( \"###############################################################\" ) print () user_input = input () log . debug ( f 'response: \" { user_input } \"' ) if user_input . lower () in [ 'a' , 'abort' , 'q' , 'quit' ]: raise KPFException ( \"User chose to halt execution\" ) check_scriptstop () log . info ( f \"Configuring for Science\" ) ConfigureForScience . execute ( OB ) WaitForConfigureScience . execute ( OB ) check_script_running () set_script_keywords ( Path ( __file__ ) . name , os . getpid ()) # Execute the Cal Sequence # Wrap in try/except so that cleanup happens observations = OB . get ( 'SEQ_Observations' , []) for observation in observations : observation [ 'Template_Name' ] = 'kpf_sci' observation [ 'Template_Version' ] = OB [ 'Template_Version' ] log . debug ( f \"Automatically setting TimedShutter_CaHK: { OB [ 'TriggerCaHK' ] } \" ) observation [ 'TimedShutter_CaHK' ] = OB [ 'TriggerCaHK' ] observation [ 'TriggerCaHK' ] = OB [ 'TriggerCaHK' ] observation [ 'TriggerGreen' ] = OB [ 'TriggerGreen' ] observation [ 'TriggerRed' ] = OB [ 'TriggerRed' ] # Note: pyyaml resolver currently converts off string to False boolean observation [ 'TriggerGuide' ] = True observation [ 'Gmag' ] = OB [ 'Gmag' ] try : ExecuteSci . execute ( observation ) except Exception as e : log . error ( \"ExecuteSci failed:\" ) log . error ( e ) traceback_text = traceback . format_exc () log . error ( traceback_text ) # Cleanup clear_script_keywords () log . error ( 'Running CleanupAfterScience and exiting' ) CleanupAfterScience . execute ( OB ) sys . exit ( 1 ) # Cleanup CleanupAfterScience . execute ( OB ) @classmethod def post_condition ( cls , OB , logger , cfg ): pass","title":"RunSciOB"},{"location":"scripts/RunSciOB/#runsciob","text":"Bases: KPFTranslatorFunction Script to run a full Science OB from the command line. This must have arguments as input, typically from a file using the -f command line tool. This script is abortable. When .abort_execution() is invoked, the kpconfig.SCRIPTSTOP is set to Yes. This script checked for this value at various locations in the script. As a result, the script will not stop immediately, but will stop when it reaches a breakpoint.","title":"RunSciOB"},{"location":"scripts/RunSciOB/#kpf.scripts.RunSciOB.RunSciOB--args","text":"OB - dict A fully specified observing block (OB). Source code in kpf/scripts/RunSciOB.py 23 24 25 26 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 class RunSciOB ( KPFTranslatorFunction ): '''Script to run a full Science OB from the command line. This must have arguments as input, typically from a file using the `-f` command line tool. This script is abortable. When `.abort_execution()` is invoked, the `kpconfig.SCRIPTSTOP` is set to Yes. This script checked for this value at various locations in the script. As a result, the script will not stop immediately, but will stop when it reaches a breakpoint. ARGS: ===== * __OB__ - `dict` A fully specified observing block (OB). ''' abortable = True @classmethod def pre_condition ( cls , OB , logger , cfg ): check_input ( OB , 'Template_Name' , allowed_values = [ 'kpf_sci' ]) check_input ( OB , 'Template_Version' , version_check = True , value_min = '0.5' ) @classmethod @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) log . info ( '-------------------------' ) check_scriptstop () # Configure: log . info ( f \"Configuring for Acquisition\" ) ConfigureForAcquisition . execute ( OB ) WaitForConfigureAcquisition . execute ( OB ) check_scriptstop () log . debug ( 'Asking for user input' ) print () print ( \"###############################################################\" ) print ( \" Before continuing, please ensure that the OA has placed\" ) print ( \" the star on the KPF PO and they have initiated tip tilt\" ) print ( \" corrections (if desired).\" ) print () print ( \" Press 'Enter' to begin exposure(s) or 'a' to abort script\" ) print ( \"###############################################################\" ) print () user_input = input () log . debug ( f 'response: \" { user_input } \"' ) if user_input . lower () in [ 'a' , 'abort' , 'q' , 'quit' ]: raise KPFException ( \"User chose to halt execution\" ) check_scriptstop () log . info ( f \"Configuring for Science\" ) ConfigureForScience . execute ( OB ) WaitForConfigureScience . execute ( OB ) check_script_running () set_script_keywords ( Path ( __file__ ) . name , os . getpid ()) # Execute the Cal Sequence # Wrap in try/except so that cleanup happens observations = OB . get ( 'SEQ_Observations' , []) for observation in observations : observation [ 'Template_Name' ] = 'kpf_sci' observation [ 'Template_Version' ] = OB [ 'Template_Version' ] log . debug ( f \"Automatically setting TimedShutter_CaHK: { OB [ 'TriggerCaHK' ] } \" ) observation [ 'TimedShutter_CaHK' ] = OB [ 'TriggerCaHK' ] observation [ 'TriggerCaHK' ] = OB [ 'TriggerCaHK' ] observation [ 'TriggerGreen' ] = OB [ 'TriggerGreen' ] observation [ 'TriggerRed' ] = OB [ 'TriggerRed' ] # Note: pyyaml resolver currently converts off string to False boolean observation [ 'TriggerGuide' ] = True observation [ 'Gmag' ] = OB [ 'Gmag' ] try : ExecuteSci . execute ( observation ) except Exception as e : log . error ( \"ExecuteSci failed:\" ) log . error ( e ) traceback_text = traceback . format_exc () log . error ( traceback_text ) # Cleanup clear_script_keywords () log . error ( 'Running CleanupAfterScience and exiting' ) CleanupAfterScience . execute ( OB ) sys . exit ( 1 ) # Cleanup CleanupAfterScience . execute ( OB ) @classmethod def post_condition ( cls , OB , logger , cfg ): pass","title":"ARGS:"},{"location":"scripts/RunSoCalObservingLoop/","text":"RunSoCalObservingLoop Bases: KPFTranslatorFunction This script runs a control loop to execute SoCal observations. When the script is invoked, it puts SoCal in AUTONOMOUS mode. This means that the SoCal dispatcher number 4 will handle opening the enclosure, acquiring and tracking the Sun, and will perform a weather safety shutdown if needed. The AUTONOMOUS mode will respect the CAN_OPEN keyword as well, so that keyword will lock out SoCal motions if that is desired. The script takes two required inputs: a start and end time in decimal hours (in HST). The start time can be after the invocation of this script. This is in fact the recommended operational strategy as the SoCal AUTONOMOUS mode will then have time to open and acquire the Sun before observations start. If needed, the script will wait until the start time before taking further actions (beyond setting AUTONOMOUS). Once the start time has passed, the script will check the kpfconfig.SCRIPT% keywords to see if something is currently running. If so, it will wait for the script keywords to clear before starting operations. Next the script will try to determine if SoCal is successfully observing the Sun by invoking the WaitForSoCalOnTarget script. If SoCal is on target, then a short observation of the Sun is performed. Some of the parameters can be modified in the KPFTranslator configuration file ( kpf_inst_config.ini ). This observation, as currently configured, takes about 15 minutes to complete. If SoCal is not on target (according to the WaitForSoCalOnTarget script), then an Etalon calibration set is taken. This is a way to make use of time that would otherwise be unproductive. This etalon script also takes around 15 minutes or a bit less to complete. Once either of the two observations above has completed, the script repeats the loop as long as there is enough time before the end time to complete a SoCal observation. Once the end time has passed, the system will perform basic cleanup of KPF, then it will park SoCal using ParkSoCal if the park flag is set. Arguments StartTimeHST - float The time (in decimal hours HST) to begin observing. EndTimeHST - float The time (in decimal hours HST) to end observing. park - bool If True, the script will park SoCal when complete. scheduled - bool If True, the script will not run if the keyword kpfconfig.ALLOWSCHEDULEDCALS is \"No\". Source code in kpf/scripts/RunSoCalObservingLoop.py 23 24 25 26 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 class RunSoCalObservingLoop ( KPFTranslatorFunction ): '''This script runs a control loop to execute SoCal observations. When the script is invoked, it puts SoCal in AUTONOMOUS mode. This means that the SoCal dispatcher number 4 will handle opening the enclosure, acquiring and tracking the Sun, and will perform a weather safety shutdown if needed. The AUTONOMOUS mode will respect the CAN_OPEN keyword as well, so that keyword will lock out SoCal motions if that is desired. The script takes two required inputs: a start and end time in decimal hours (in HST). The start time can be after the invocation of this script. This is in fact the recommended operational strategy as the SoCal AUTONOMOUS mode will then have time to open and acquire the Sun before observations start. If needed, the script will wait until the start time before taking further actions (beyond setting AUTONOMOUS). Once the start time has passed, the script will check the `kpfconfig.SCRIPT%` keywords to see if something is currently running. If so, it will wait for the script keywords to clear before starting operations. Next the script will try to determine if SoCal is successfully observing the Sun by invoking the `WaitForSoCalOnTarget` script. If SoCal is on target, then a short observation of the Sun is performed. Some of the parameters can be modified in the `KPFTranslator` configuration file (`kpf_inst_config.ini`). This observation, as currently configured, takes about 15 minutes to complete. If SoCal is not on target (according to the `WaitForSoCalOnTarget` script), then an Etalon calibration set is taken. This is a way to make use of time that would otherwise be unproductive. This etalon script also takes around 15 minutes or a bit less to complete. Once either of the two observations above has completed, the script repeats the loop as long as there is enough time before the end time to complete a SoCal observation. Once the end time has passed, the system will perform basic cleanup of KPF, then it will park SoCal using `ParkSoCal` if the park flag is set. ## Arguments * __StartTimeHST__ - `float` The time (in decimal hours HST) to begin observing. * __EndTimeHST__ - `float` The time (in decimal hours HST) to end observing. * __park__ - `bool` If True, the script will park SoCal when complete. * __scheduled__ - `bool` If True, the script will not run if the keyword `kpfconfig.ALLOWSCHEDULEDCALS` is \"No\". ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , args , logger , cfg ): # Check the ALLOWSCHEDULEDCALS value if args . get ( 'scheduled' , True ) is True : ALLOWSCHEDULED = ktl . cache ( 'kpfconfig' , 'ALLOWSCHEDULEDCALS' ) . read () if ALLOWSCHEDULED == 'No' : return log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) log . info ( '-------------------------' ) # Prepare SoCal parameters to pass to ExecuteCal socal_ND1 = cfg . get ( 'SoCal' , 'ND1' , fallback = 'OD 0.1' ) socal_ND2 = cfg . get ( 'SoCal' , 'ND2' , fallback = 'OD 0.1' ) socal_ExpTime = cfg . getfloat ( 'SoCal' , 'ExpTime' , fallback = 12 ) SoCal_observation = { 'Template_Name' : 'kpf_lamp' , 'Template_Version' : '1.0' , 'TargetName' : 'Sun' , 'TriggerCaHK' : False , 'TimedShutter_CaHK' : False , 'TriggerGreen' : True , 'TriggerRed' : True , 'TriggerExpMeter' : False , 'RunAgitator' : True , 'CalSource' : 'SoCal-SciSky' , 'Object' : 'SoCal' , 'CalND1' : socal_ND1 , 'CalND2' : socal_ND2 , 'ExpTime' : socal_ExpTime , 'nExp' : 15 , 'SSS_Science' : True , 'SSS_Sky' : True , 'TakeSimulCal' : True , 'nointensemon' : True , } readout_red = cfg . getfloat ( 'time_estimates' , f 'readout_red' , fallback = 60 ) readout_green = cfg . getfloat ( 'time_estimates' , f 'readout_green' , fallback = 60 ) readout_cahk = cfg . getfloat ( 'time_estimates' , 'readout_cahk' , fallback = 1 ) archon_time_shim = cfg . getfloat ( 'times' , 'archon_temperature_time_shim' , fallback = 2 ) readout = max ([ readout_red , readout_green , readout_cahk ]) SoCal_duration = int ( SoCal_observation [ 'nExp' ]) * max ([ float ( SoCal_observation [ 'ExpTime' ]), archon_time_shim ]) SoCal_duration += int ( SoCal_observation [ 'nExp' ]) * readout log . debug ( f \"Estimated SoCal observation time = { SoCal_duration } \" ) # Prepare Etalon parameters to pass to ExecuteCal Etalon_ND1 = cfg . get ( 'SoCal' , 'EtalonND1' , fallback = 'OD 0.1' ) Etalon_ND2 = cfg . get ( 'SoCal' , 'EtalonND2' , fallback = 'OD 0.1' ) Etalon_ExpTime = cfg . getfloat ( 'SoCal' , 'EtalonExpTime' , fallback = 60 ) Etalon_observation = { 'Template_Name' : 'kpf_lamp' , 'Template_Version' : '1.0' , 'TriggerCaHK' : True , 'TimedShutter_CaHK' : True , 'TriggerGreen' : True , 'TriggerRed' : True , 'TriggerExpMeter' : False , 'RunAgitator' : True , 'CalSource' : 'EtalonFiber' , 'Object' : 'slewcal' , 'CalND1' : Etalon_ND1 , 'CalND2' : Etalon_ND2 , 'ExpTime' : Etalon_ExpTime , 'nExp' : 8 , 'SSS_Science' : True , 'SSS_Sky' : True , 'TakeSimulCal' : True , 'nointensemon' : True , } Etalon_duration = int ( Etalon_observation [ 'nExp' ]) * max ([ float ( Etalon_observation [ 'ExpTime' ]), archon_time_shim ]) Etalon_duration += int ( Etalon_observation [ 'nExp' ]) * readout log . debug ( f \"Estimated Etalon observation time = { Etalon_duration } \" ) # Start SoCal in autonomous mode SoCalStartAutonomous . execute ({}) # Start Loop max_wait_per_iteration = 60 start_time = args . get ( 'StartTimeHST' , 9 ) end_time = args . get ( 'EndTimeHST' , 12 ) - SoCal_duration / 3600 - 0.05 now = datetime . datetime . now () now_decimal = ( now . hour + now . minute / 60 + now . second / 3600 ) if now_decimal < start_time : wait = ( start_time - now_decimal ) * 3600 log . info ( f 'Waiting { wait : .0f } s for SoCal window start time' ) time . sleep ( wait ) elif now_decimal > end_time : log . info ( \"End time for today's SoCal window has passed\" ) return SCRIPTPID = ktl . cache ( 'kpfconfig' , 'SCRIPTPID' ) if SCRIPTPID . read ( binary = True ) >= 0 : SCRIPTNAME = ktl . cache ( 'kpfconfig' , 'SCRIPTNAME' ) . read () waittime = ( end_time - now_decimal ) * 3600 - SoCal_duration - 180 log . warning ( f 'Script is currently running: { SCRIPTNAME } ' ) if waittime > 0 : log . info ( f 'Waiting up to { waittime : .0f } s for running script to end' ) SCRIPTPID . waitFor ( \"==-1\" , timeout = waittime ) time . sleep ( 10 ) # time shim check_script_running () set_script_keywords ( Path ( __file__ ) . name , os . getpid ()) log . info ( f 'Starting SoCal observation loop' ) log . info ( f 'Start time: { start_time : .2f } HST' ) log . info ( f 'End Time: { end_time : .2f } HST' ) check_scriptstop () nSoCalObs = 0 nEtalonObs = 0 now = datetime . datetime . now () now_decimal = ( now . hour + now . minute / 60 + now . second / 3600 ) while now_decimal >= start_time and now_decimal < end_time : log . debug ( 'Checking if SoCal is on the Sun' ) on_target = WaitForSoCalOnTarget . execute ({ 'timeout' : max_wait_per_iteration }) observation = { True : SoCal_observation , False : Etalon_observation }[ on_target ] log . info ( f 'SoCal on target: { on_target } ' ) log . info ( f \"Executing { observation [ 'Object' ] } \" ) try : check_scriptstop () ExecuteCal . execute ( observation ) if on_target == True : nSoCalObs += 1 else : nEtalonObs += 1 except ScriptStopTriggered as e : raise e except Exception as e : log . error ( \"ExecuteCal failed:\" ) log . error ( e ) traceback_text = traceback . format_exc () log . error ( traceback_text ) # Email error to kpf_info if not isinstance ( e , ScriptStopTriggered ): try : msg = [ f ' { type ( e ) } ' , f ' { traceback . format_exc () } ' , '' , f ' { OB } ' ] SendEmail . execute ({ 'Subject' : 'ExecuteCals Failed' , 'Message' : ' \\n ' . join ( msg )}) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) check_scriptstop () # Update loop inputs now = datetime . datetime . now () now_decimal = ( now . hour + now . minute / 60 + now . second / 3600 ) log . info ( 'SoCal observation loop completed' ) log . info ( f 'Executed { nSoCalObs } SoCal sequences' ) log . info ( f 'Executed { nEtalonObs } Etalon sequences' ) # Cleanup try : CleanupAfterCalibrations . execute ( Etalon_observation ) except Exception as e : log . error ( \"CleanupAfterCalibrations failed:\" ) log . error ( e ) traceback_text = traceback . format_exc () log . error ( traceback_text ) clear_script_keywords () # Email error to kpf_info try : msg = [ f ' { type ( e ) } ' , f ' { traceback_text } ' , '' , f ' { OB } ' ] SendEmail . execute ({ 'Subject' : 'CleanupAfterCalibrations Failed' , 'Message' : ' \\n ' . join ( msg )}) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) # Park SoCal? if args . get ( 'park' , False ) == True : ParkSoCal . execute ({}) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'StartTimeHST' , type = float , help = 'Start of daily observing window in decimal hours HST.' ) parser . add_argument ( 'EndTimeHST' , type = float , help = 'End of daily observing window in decimal hours HST.' ) parser . add_argument ( \"--park\" , dest = \"park\" , default = False , action = \"store_true\" , help = \"Close and park SoCal when done?\" ) parser . add_argument ( \"--notscheduled\" , dest = \"scheduled\" , default = True , action = \"store_false\" , help = \"Do not respect the kpfconfig.ALLOWSCHEDULEDCALS flag.\" ) return super () . add_cmdline_args ( parser , cfg )","title":"RunSoCalObservingLoop"},{"location":"scripts/RunSoCalObservingLoop/#runsocalobservingloop","text":"Bases: KPFTranslatorFunction This script runs a control loop to execute SoCal observations. When the script is invoked, it puts SoCal in AUTONOMOUS mode. This means that the SoCal dispatcher number 4 will handle opening the enclosure, acquiring and tracking the Sun, and will perform a weather safety shutdown if needed. The AUTONOMOUS mode will respect the CAN_OPEN keyword as well, so that keyword will lock out SoCal motions if that is desired. The script takes two required inputs: a start and end time in decimal hours (in HST). The start time can be after the invocation of this script. This is in fact the recommended operational strategy as the SoCal AUTONOMOUS mode will then have time to open and acquire the Sun before observations start. If needed, the script will wait until the start time before taking further actions (beyond setting AUTONOMOUS). Once the start time has passed, the script will check the kpfconfig.SCRIPT% keywords to see if something is currently running. If so, it will wait for the script keywords to clear before starting operations. Next the script will try to determine if SoCal is successfully observing the Sun by invoking the WaitForSoCalOnTarget script. If SoCal is on target, then a short observation of the Sun is performed. Some of the parameters can be modified in the KPFTranslator configuration file ( kpf_inst_config.ini ). This observation, as currently configured, takes about 15 minutes to complete. If SoCal is not on target (according to the WaitForSoCalOnTarget script), then an Etalon calibration set is taken. This is a way to make use of time that would otherwise be unproductive. This etalon script also takes around 15 minutes or a bit less to complete. Once either of the two observations above has completed, the script repeats the loop as long as there is enough time before the end time to complete a SoCal observation. Once the end time has passed, the system will perform basic cleanup of KPF, then it will park SoCal using ParkSoCal if the park flag is set.","title":"RunSoCalObservingLoop"},{"location":"scripts/RunSoCalObservingLoop/#kpf.scripts.RunSoCalObservingLoop.RunSoCalObservingLoop--arguments","text":"StartTimeHST - float The time (in decimal hours HST) to begin observing. EndTimeHST - float The time (in decimal hours HST) to end observing. park - bool If True, the script will park SoCal when complete. scheduled - bool If True, the script will not run if the keyword kpfconfig.ALLOWSCHEDULEDCALS is \"No\". Source code in kpf/scripts/RunSoCalObservingLoop.py 23 24 25 26 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 class RunSoCalObservingLoop ( KPFTranslatorFunction ): '''This script runs a control loop to execute SoCal observations. When the script is invoked, it puts SoCal in AUTONOMOUS mode. This means that the SoCal dispatcher number 4 will handle opening the enclosure, acquiring and tracking the Sun, and will perform a weather safety shutdown if needed. The AUTONOMOUS mode will respect the CAN_OPEN keyword as well, so that keyword will lock out SoCal motions if that is desired. The script takes two required inputs: a start and end time in decimal hours (in HST). The start time can be after the invocation of this script. This is in fact the recommended operational strategy as the SoCal AUTONOMOUS mode will then have time to open and acquire the Sun before observations start. If needed, the script will wait until the start time before taking further actions (beyond setting AUTONOMOUS). Once the start time has passed, the script will check the `kpfconfig.SCRIPT%` keywords to see if something is currently running. If so, it will wait for the script keywords to clear before starting operations. Next the script will try to determine if SoCal is successfully observing the Sun by invoking the `WaitForSoCalOnTarget` script. If SoCal is on target, then a short observation of the Sun is performed. Some of the parameters can be modified in the `KPFTranslator` configuration file (`kpf_inst_config.ini`). This observation, as currently configured, takes about 15 minutes to complete. If SoCal is not on target (according to the `WaitForSoCalOnTarget` script), then an Etalon calibration set is taken. This is a way to make use of time that would otherwise be unproductive. This etalon script also takes around 15 minutes or a bit less to complete. Once either of the two observations above has completed, the script repeats the loop as long as there is enough time before the end time to complete a SoCal observation. Once the end time has passed, the system will perform basic cleanup of KPF, then it will park SoCal using `ParkSoCal` if the park flag is set. ## Arguments * __StartTimeHST__ - `float` The time (in decimal hours HST) to begin observing. * __EndTimeHST__ - `float` The time (in decimal hours HST) to end observing. * __park__ - `bool` If True, the script will park SoCal when complete. * __scheduled__ - `bool` If True, the script will not run if the keyword `kpfconfig.ALLOWSCHEDULEDCALS` is \"No\". ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , args , logger , cfg ): # Check the ALLOWSCHEDULEDCALS value if args . get ( 'scheduled' , True ) is True : ALLOWSCHEDULED = ktl . cache ( 'kpfconfig' , 'ALLOWSCHEDULEDCALS' ) . read () if ALLOWSCHEDULED == 'No' : return log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) log . info ( '-------------------------' ) # Prepare SoCal parameters to pass to ExecuteCal socal_ND1 = cfg . get ( 'SoCal' , 'ND1' , fallback = 'OD 0.1' ) socal_ND2 = cfg . get ( 'SoCal' , 'ND2' , fallback = 'OD 0.1' ) socal_ExpTime = cfg . getfloat ( 'SoCal' , 'ExpTime' , fallback = 12 ) SoCal_observation = { 'Template_Name' : 'kpf_lamp' , 'Template_Version' : '1.0' , 'TargetName' : 'Sun' , 'TriggerCaHK' : False , 'TimedShutter_CaHK' : False , 'TriggerGreen' : True , 'TriggerRed' : True , 'TriggerExpMeter' : False , 'RunAgitator' : True , 'CalSource' : 'SoCal-SciSky' , 'Object' : 'SoCal' , 'CalND1' : socal_ND1 , 'CalND2' : socal_ND2 , 'ExpTime' : socal_ExpTime , 'nExp' : 15 , 'SSS_Science' : True , 'SSS_Sky' : True , 'TakeSimulCal' : True , 'nointensemon' : True , } readout_red = cfg . getfloat ( 'time_estimates' , f 'readout_red' , fallback = 60 ) readout_green = cfg . getfloat ( 'time_estimates' , f 'readout_green' , fallback = 60 ) readout_cahk = cfg . getfloat ( 'time_estimates' , 'readout_cahk' , fallback = 1 ) archon_time_shim = cfg . getfloat ( 'times' , 'archon_temperature_time_shim' , fallback = 2 ) readout = max ([ readout_red , readout_green , readout_cahk ]) SoCal_duration = int ( SoCal_observation [ 'nExp' ]) * max ([ float ( SoCal_observation [ 'ExpTime' ]), archon_time_shim ]) SoCal_duration += int ( SoCal_observation [ 'nExp' ]) * readout log . debug ( f \"Estimated SoCal observation time = { SoCal_duration } \" ) # Prepare Etalon parameters to pass to ExecuteCal Etalon_ND1 = cfg . get ( 'SoCal' , 'EtalonND1' , fallback = 'OD 0.1' ) Etalon_ND2 = cfg . get ( 'SoCal' , 'EtalonND2' , fallback = 'OD 0.1' ) Etalon_ExpTime = cfg . getfloat ( 'SoCal' , 'EtalonExpTime' , fallback = 60 ) Etalon_observation = { 'Template_Name' : 'kpf_lamp' , 'Template_Version' : '1.0' , 'TriggerCaHK' : True , 'TimedShutter_CaHK' : True , 'TriggerGreen' : True , 'TriggerRed' : True , 'TriggerExpMeter' : False , 'RunAgitator' : True , 'CalSource' : 'EtalonFiber' , 'Object' : 'slewcal' , 'CalND1' : Etalon_ND1 , 'CalND2' : Etalon_ND2 , 'ExpTime' : Etalon_ExpTime , 'nExp' : 8 , 'SSS_Science' : True , 'SSS_Sky' : True , 'TakeSimulCal' : True , 'nointensemon' : True , } Etalon_duration = int ( Etalon_observation [ 'nExp' ]) * max ([ float ( Etalon_observation [ 'ExpTime' ]), archon_time_shim ]) Etalon_duration += int ( Etalon_observation [ 'nExp' ]) * readout log . debug ( f \"Estimated Etalon observation time = { Etalon_duration } \" ) # Start SoCal in autonomous mode SoCalStartAutonomous . execute ({}) # Start Loop max_wait_per_iteration = 60 start_time = args . get ( 'StartTimeHST' , 9 ) end_time = args . get ( 'EndTimeHST' , 12 ) - SoCal_duration / 3600 - 0.05 now = datetime . datetime . now () now_decimal = ( now . hour + now . minute / 60 + now . second / 3600 ) if now_decimal < start_time : wait = ( start_time - now_decimal ) * 3600 log . info ( f 'Waiting { wait : .0f } s for SoCal window start time' ) time . sleep ( wait ) elif now_decimal > end_time : log . info ( \"End time for today's SoCal window has passed\" ) return SCRIPTPID = ktl . cache ( 'kpfconfig' , 'SCRIPTPID' ) if SCRIPTPID . read ( binary = True ) >= 0 : SCRIPTNAME = ktl . cache ( 'kpfconfig' , 'SCRIPTNAME' ) . read () waittime = ( end_time - now_decimal ) * 3600 - SoCal_duration - 180 log . warning ( f 'Script is currently running: { SCRIPTNAME } ' ) if waittime > 0 : log . info ( f 'Waiting up to { waittime : .0f } s for running script to end' ) SCRIPTPID . waitFor ( \"==-1\" , timeout = waittime ) time . sleep ( 10 ) # time shim check_script_running () set_script_keywords ( Path ( __file__ ) . name , os . getpid ()) log . info ( f 'Starting SoCal observation loop' ) log . info ( f 'Start time: { start_time : .2f } HST' ) log . info ( f 'End Time: { end_time : .2f } HST' ) check_scriptstop () nSoCalObs = 0 nEtalonObs = 0 now = datetime . datetime . now () now_decimal = ( now . hour + now . minute / 60 + now . second / 3600 ) while now_decimal >= start_time and now_decimal < end_time : log . debug ( 'Checking if SoCal is on the Sun' ) on_target = WaitForSoCalOnTarget . execute ({ 'timeout' : max_wait_per_iteration }) observation = { True : SoCal_observation , False : Etalon_observation }[ on_target ] log . info ( f 'SoCal on target: { on_target } ' ) log . info ( f \"Executing { observation [ 'Object' ] } \" ) try : check_scriptstop () ExecuteCal . execute ( observation ) if on_target == True : nSoCalObs += 1 else : nEtalonObs += 1 except ScriptStopTriggered as e : raise e except Exception as e : log . error ( \"ExecuteCal failed:\" ) log . error ( e ) traceback_text = traceback . format_exc () log . error ( traceback_text ) # Email error to kpf_info if not isinstance ( e , ScriptStopTriggered ): try : msg = [ f ' { type ( e ) } ' , f ' { traceback . format_exc () } ' , '' , f ' { OB } ' ] SendEmail . execute ({ 'Subject' : 'ExecuteCals Failed' , 'Message' : ' \\n ' . join ( msg )}) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) check_scriptstop () # Update loop inputs now = datetime . datetime . now () now_decimal = ( now . hour + now . minute / 60 + now . second / 3600 ) log . info ( 'SoCal observation loop completed' ) log . info ( f 'Executed { nSoCalObs } SoCal sequences' ) log . info ( f 'Executed { nEtalonObs } Etalon sequences' ) # Cleanup try : CleanupAfterCalibrations . execute ( Etalon_observation ) except Exception as e : log . error ( \"CleanupAfterCalibrations failed:\" ) log . error ( e ) traceback_text = traceback . format_exc () log . error ( traceback_text ) clear_script_keywords () # Email error to kpf_info try : msg = [ f ' { type ( e ) } ' , f ' { traceback_text } ' , '' , f ' { OB } ' ] SendEmail . execute ({ 'Subject' : 'CleanupAfterCalibrations Failed' , 'Message' : ' \\n ' . join ( msg )}) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) # Park SoCal? if args . get ( 'park' , False ) == True : ParkSoCal . execute ({}) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'StartTimeHST' , type = float , help = 'Start of daily observing window in decimal hours HST.' ) parser . add_argument ( 'EndTimeHST' , type = float , help = 'End of daily observing window in decimal hours HST.' ) parser . add_argument ( \"--park\" , dest = \"park\" , default = False , action = \"store_true\" , help = \"Close and park SoCal when done?\" ) parser . add_argument ( \"--notscheduled\" , dest = \"scheduled\" , default = True , action = \"store_false\" , help = \"Do not respect the kpfconfig.ALLOWSCHEDULEDCALS flag.\" ) return super () . add_cmdline_args ( parser , cfg )","title":"Arguments"},{"location":"scripts/RunTwilightRVStandard/","text":"RunTwilightRVStandard Bases: KPFTranslatorFunction Executes a twilight observation of one a selected RV standard star. This script performs all necessary instrument actions from sart up to shut down. Sequence of Actions (and who performs them) once this script is invoked: - (Script): run StartOfNight - (Script): Start Sci OB + Slew Cal - (OA): Slew to target - (OA): Perform autofoc - (Script): Obtain science data - (OA): Release to regular use, OA can park or do other tasks - (Script): run EndOfNight - (Script): run Calibration Source code in kpf/scripts/RunTwilightRVStandard.py 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 class RunTwilightRVStandard ( KPFTranslatorFunction ): '''Executes a twilight observation of one a selected RV standard star. This script performs all necessary instrument actions from sart up to shut down. Sequence of Actions (and who performs them) once this script is invoked: - (Script): run StartOfNight - (Script): Start Sci OB + Slew Cal - (OA): Slew to target - (OA): Perform autofoc - (Script): Obtain science data - (OA): Release to regular use, OA can park or do other tasks - (Script): run EndOfNight - (Script): run Calibration ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , args , logger , cfg ): # --------------------------------- # Select Target # --------------------------------- horizon = 30 * u . deg starlist_file = Path ( f '/s/sdata1701/OBs/kpftwilight/starlist.txt' ) all_targets = rank_targets ( starlist_file , horizon = horizon ) if len ( all_targets ) == 0 : log . error ( f 'No targets available above horizon ( { horizon : .1f } )' ) return targname = all_targets [ 0 ] . targname sciOBfile = starlist_file . parent / f ' { targname } .yaml' with open ( sciOBfile , 'r' ) as f : sciOB = yaml . safe_load ( f ) calOBfile = Path ( '/s/sdata1701/OBs/kpftwilight/twilight_program_cal.yaml' ) if calOBfile . exists () is False : log . error ( f \"Could not load OB file: { calOBfile } \" ) return with open ( calOBfile , 'r' ) as f : calOB = yaml . safe_load ( f ) log_string = f \"Selected: { targname } at { all_targets [ 0 ] . alt () : .1f } , \" \\ f \"priority= { all_targets [ 0 ] . priority } \" log . debug ( log_string ) if args . get ( 'test_only' , False ) is True : print ( log_string ) return # --------------------------------- # Start Of Night # --------------------------------- msg = [ \"\" , \"-------------------------------------------------------------\" , \"Thank you for executing a KPF Twilight Stability Measurement.\" , \"If you encounter urgent problems or questions contact one of\" , \"the KPF SAs. Contact info:\" , \" Josh Walawender: 808-990-4294 (cell)\" , \"\" , \"Please load the starlist at\" , f \" { starlist_file } \" , \"\" , f \"Our target will be:\" , f \" { targname } \" , \"\" , \"If the instrument has not been in use, you will presumably\" , \"need to run the Start Of Night script. This will open the AO\" , \"hatch and configure AO and KPF for observing. This is not\" , \"needed if KPF has been observing immediately prior to this.\" , \"Do you wish to run the Start Of Night Script? [Y/n]\" , \"-------------------------------------------------------------\" , \"\" , ] for line in msg : print ( line ) user_input = input () if user_input . lower () in [ 'n' , 'no' , 'cancel' ]: log . warning ( 'User opted to skip Start Of Night script' ) else : StartOfNight . execute ({}) SetProgram . execute ({ 'progname' : 'K444' }) SetObserver . execute ({ 'observer' : 'OA' }) # Wrap operations in try/except to ensure we get to end of night try : log . info ( f \"Configuring for Acquisition\" ) ConfigureForAcquisition . execute ( sciOB ) # --------------------------------- # OA Focus # --------------------------------- msg = [ \"\" , \"-------------------------------------------------------------\" , \"The instrument is being configured now, please begin slewing\" , \"to the target. Once you are on target:\" , \" - Focus on target using autfoc\" , \" - Then place the target on the KPF PO\" , \"When those steps are done, press Enter to continue.\" , \"-------------------------------------------------------------\" , \"\" , ] for line in msg : print ( line ) user_input = input () # Open an xshow for exposure status cmd = [ 'xshow' , '-s' , 'kpfexpose' , 'EXPOSE' , 'ELAPSED' , 'EXPOSURE' ] xshow_proc = subprocess . Popen ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) # --------------------------------- # Execute Observation # --------------------------------- WaitForConfigureAcquisition . execute ( sciOB ) log . info ( f \"Configuring for Science\" ) ConfigureForScience . execute ( sciOB ) WaitForConfigureScience . execute ( sciOB ) # Execute Sequences check_script_running () set_script_keywords ( Path ( __file__ ) . name , os . getpid ()) # Execute the Cal Sequence observations = sciOB . get ( 'SEQ_Observations' , []) for observation in observations : observation [ 'Template_Name' ] = 'kpf_sci' observation [ 'Template_Version' ] = sciOB [ 'Template_Version' ] observation [ 'Gmag' ] = sciOB [ 'Gmag' ] log . debug ( f \"Automatically setting TimedShutter_CaHK: { sciOB [ 'TriggerCaHK' ] } \" ) observation [ 'TimedShutter_CaHK' ] = sciOB [ 'TriggerCaHK' ] observation [ 'TriggerCaHK' ] = sciOB [ 'TriggerCaHK' ] observation [ 'TriggerGreen' ] = sciOB [ 'TriggerGreen' ] observation [ 'TriggerRed' ] = sciOB [ 'TriggerRed' ] observation [ 'TriggerGuide' ] = ( sciOB . get ( 'GuideMode' , 'off' ) != 'off' ) # Wrap in try/except so that cleanup happens try : ExecuteSci . execute ( observation ) except Exception as e : log . error ( \"ExecuteSci failed:\" ) log . error ( e ) clear_script_keywords () except Exception as e : log . error ( f 'Encountered exception during operations' ) log . error ( e ) log . error ( traceback . format_exc ()) # Cleanup CleanupAfterScience . execute ( sciOB ) # Close xshow xshow_proc . terminate () # --------------------------------- # Done with telescope # --------------------------------- log . debug ( 'Observations complete. Alerting OA.' ) msg = [ \"\" , \"-------------------------------------------------------------\" , \"Observation complete. Do you wish to run end of night and\" , \"perform a calibration set? Please answer yes if this is a\" , \"morning twilight or if some other instrument will be observing.\" , \"\" , \"Regardless of the choice below, you may perform other tasks as\" , \"needed after answering.\" , \"\" , \"Run End of Night and then start calibrations? [Y/n]\" , \"-------------------------------------------------------------\" , \"\" , ] for line in msg : print ( line ) user_input = input () if user_input . lower () in [ 'y' , 'yes' ]: EndOfNight . execute ({}) RunCalOB . execute ( calOB ) # Send email email = { 'To' : 'kpf_info@keck.hawaii.edu,ahoward@caltech.edu,sphalverson@gmail.com' , # 'To': 'jwalawender@keck.hawaii.edu', 'Subject' : 'KPF Twilight Program Completed' , 'Message' : 'A KPF twilight observation has been completed.' } SendEmail . execute ( email ) print () print ( 'Script complete.' ) time . sleep ( 120 ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( '--test' , dest = \"test_only\" , default = False , action = \"store_true\" , help = 'Only execute the target selection code' ) return super () . add_cmdline_args ( parser , cfg )","title":"RunTwilightRVStandard"},{"location":"scripts/RunTwilightRVStandard/#runtwilightrvstandard","text":"Bases: KPFTranslatorFunction Executes a twilight observation of one a selected RV standard star. This script performs all necessary instrument actions from sart up to shut down. Sequence of Actions (and who performs them) once this script is invoked: - (Script): run StartOfNight - (Script): Start Sci OB + Slew Cal - (OA): Slew to target - (OA): Perform autofoc - (Script): Obtain science data - (OA): Release to regular use, OA can park or do other tasks - (Script): run EndOfNight - (Script): run Calibration Source code in kpf/scripts/RunTwilightRVStandard.py 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 class RunTwilightRVStandard ( KPFTranslatorFunction ): '''Executes a twilight observation of one a selected RV standard star. This script performs all necessary instrument actions from sart up to shut down. Sequence of Actions (and who performs them) once this script is invoked: - (Script): run StartOfNight - (Script): Start Sci OB + Slew Cal - (OA): Slew to target - (OA): Perform autofoc - (Script): Obtain science data - (OA): Release to regular use, OA can park or do other tasks - (Script): run EndOfNight - (Script): run Calibration ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , args , logger , cfg ): # --------------------------------- # Select Target # --------------------------------- horizon = 30 * u . deg starlist_file = Path ( f '/s/sdata1701/OBs/kpftwilight/starlist.txt' ) all_targets = rank_targets ( starlist_file , horizon = horizon ) if len ( all_targets ) == 0 : log . error ( f 'No targets available above horizon ( { horizon : .1f } )' ) return targname = all_targets [ 0 ] . targname sciOBfile = starlist_file . parent / f ' { targname } .yaml' with open ( sciOBfile , 'r' ) as f : sciOB = yaml . safe_load ( f ) calOBfile = Path ( '/s/sdata1701/OBs/kpftwilight/twilight_program_cal.yaml' ) if calOBfile . exists () is False : log . error ( f \"Could not load OB file: { calOBfile } \" ) return with open ( calOBfile , 'r' ) as f : calOB = yaml . safe_load ( f ) log_string = f \"Selected: { targname } at { all_targets [ 0 ] . alt () : .1f } , \" \\ f \"priority= { all_targets [ 0 ] . priority } \" log . debug ( log_string ) if args . get ( 'test_only' , False ) is True : print ( log_string ) return # --------------------------------- # Start Of Night # --------------------------------- msg = [ \"\" , \"-------------------------------------------------------------\" , \"Thank you for executing a KPF Twilight Stability Measurement.\" , \"If you encounter urgent problems or questions contact one of\" , \"the KPF SAs. Contact info:\" , \" Josh Walawender: 808-990-4294 (cell)\" , \"\" , \"Please load the starlist at\" , f \" { starlist_file } \" , \"\" , f \"Our target will be:\" , f \" { targname } \" , \"\" , \"If the instrument has not been in use, you will presumably\" , \"need to run the Start Of Night script. This will open the AO\" , \"hatch and configure AO and KPF for observing. This is not\" , \"needed if KPF has been observing immediately prior to this.\" , \"Do you wish to run the Start Of Night Script? [Y/n]\" , \"-------------------------------------------------------------\" , \"\" , ] for line in msg : print ( line ) user_input = input () if user_input . lower () in [ 'n' , 'no' , 'cancel' ]: log . warning ( 'User opted to skip Start Of Night script' ) else : StartOfNight . execute ({}) SetProgram . execute ({ 'progname' : 'K444' }) SetObserver . execute ({ 'observer' : 'OA' }) # Wrap operations in try/except to ensure we get to end of night try : log . info ( f \"Configuring for Acquisition\" ) ConfigureForAcquisition . execute ( sciOB ) # --------------------------------- # OA Focus # --------------------------------- msg = [ \"\" , \"-------------------------------------------------------------\" , \"The instrument is being configured now, please begin slewing\" , \"to the target. Once you are on target:\" , \" - Focus on target using autfoc\" , \" - Then place the target on the KPF PO\" , \"When those steps are done, press Enter to continue.\" , \"-------------------------------------------------------------\" , \"\" , ] for line in msg : print ( line ) user_input = input () # Open an xshow for exposure status cmd = [ 'xshow' , '-s' , 'kpfexpose' , 'EXPOSE' , 'ELAPSED' , 'EXPOSURE' ] xshow_proc = subprocess . Popen ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) # --------------------------------- # Execute Observation # --------------------------------- WaitForConfigureAcquisition . execute ( sciOB ) log . info ( f \"Configuring for Science\" ) ConfigureForScience . execute ( sciOB ) WaitForConfigureScience . execute ( sciOB ) # Execute Sequences check_script_running () set_script_keywords ( Path ( __file__ ) . name , os . getpid ()) # Execute the Cal Sequence observations = sciOB . get ( 'SEQ_Observations' , []) for observation in observations : observation [ 'Template_Name' ] = 'kpf_sci' observation [ 'Template_Version' ] = sciOB [ 'Template_Version' ] observation [ 'Gmag' ] = sciOB [ 'Gmag' ] log . debug ( f \"Automatically setting TimedShutter_CaHK: { sciOB [ 'TriggerCaHK' ] } \" ) observation [ 'TimedShutter_CaHK' ] = sciOB [ 'TriggerCaHK' ] observation [ 'TriggerCaHK' ] = sciOB [ 'TriggerCaHK' ] observation [ 'TriggerGreen' ] = sciOB [ 'TriggerGreen' ] observation [ 'TriggerRed' ] = sciOB [ 'TriggerRed' ] observation [ 'TriggerGuide' ] = ( sciOB . get ( 'GuideMode' , 'off' ) != 'off' ) # Wrap in try/except so that cleanup happens try : ExecuteSci . execute ( observation ) except Exception as e : log . error ( \"ExecuteSci failed:\" ) log . error ( e ) clear_script_keywords () except Exception as e : log . error ( f 'Encountered exception during operations' ) log . error ( e ) log . error ( traceback . format_exc ()) # Cleanup CleanupAfterScience . execute ( sciOB ) # Close xshow xshow_proc . terminate () # --------------------------------- # Done with telescope # --------------------------------- log . debug ( 'Observations complete. Alerting OA.' ) msg = [ \"\" , \"-------------------------------------------------------------\" , \"Observation complete. Do you wish to run end of night and\" , \"perform a calibration set? Please answer yes if this is a\" , \"morning twilight or if some other instrument will be observing.\" , \"\" , \"Regardless of the choice below, you may perform other tasks as\" , \"needed after answering.\" , \"\" , \"Run End of Night and then start calibrations? [Y/n]\" , \"-------------------------------------------------------------\" , \"\" , ] for line in msg : print ( line ) user_input = input () if user_input . lower () in [ 'y' , 'yes' ]: EndOfNight . execute ({}) RunCalOB . execute ( calOB ) # Send email email = { 'To' : 'kpf_info@keck.hawaii.edu,ahoward@caltech.edu,sphalverson@gmail.com' , # 'To': 'jwalawender@keck.hawaii.edu', 'Subject' : 'KPF Twilight Program Completed' , 'Message' : 'A KPF twilight observation has been completed.' } SendEmail . execute ( email ) print () print ( 'Script complete.' ) time . sleep ( 120 ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( '--test' , dest = \"test_only\" , default = False , action = \"store_true\" , help = 'Only execute the target selection code' ) return super () . add_cmdline_args ( parser , cfg )","title":"RunTwilightRVStandard"},{"location":"scripts/SendPCUtoHome/","text":"SendPCUtoHome Bases: KPFTranslatorFunction Send the PCU stage to the \"home\" named position. KTL Keywords Used: ao.PCSFNAME ao.PCSFSTST Source code in kpf/ao/SendPCUtoHome.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 class SendPCUtoHome ( KPFTranslatorFunction ): '''Send the PCU stage to the \"home\" named position. KTL Keywords Used: - `ao.PCSFNAME` - `ao.PCSFSTST` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): PCSFSTST = ktl . cache ( 'ao' , 'PCSFSTST' ) success = PCSFSTST . waitFor ( '!= \"FAULT\"' ) if success is not True : raise FailedPreCondition ( 'PCSFSTST is faulted' ) @classmethod def perform ( cls , args , logger , cfg ): PCSstagekw = ktl . cache ( 'ao' , 'PCSFNAME' ) log . info ( f \"Sending PCU to Home\" ) PCSstagekw . write ( 'home' ) shim_time = cfg . getfloat ( 'times' , 'ao_pcu_shim_time' , fallback = 5 ) time . sleep ( shim_time ) @classmethod def post_condition ( cls , args , logger , cfg ): PCSstagekw = ktl . cache ( 'ao' , 'PCSFSTST' ) timeout = cfg . getfloat ( 'times' , 'ao_pcu_move_time' , fallback = 150 ) success = PCSstagekw . waitfor ( \"== INPOS\" , timeout = timeout ) if success is False : raise FailedToReachDestination ( PCSstagekw . read (), 'home' )","title":"SendPCUtoHome"},{"location":"scripts/SendPCUtoHome/#sendpcutohome","text":"Bases: KPFTranslatorFunction Send the PCU stage to the \"home\" named position. KTL Keywords Used: ao.PCSFNAME ao.PCSFSTST Source code in kpf/ao/SendPCUtoHome.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 class SendPCUtoHome ( KPFTranslatorFunction ): '''Send the PCU stage to the \"home\" named position. KTL Keywords Used: - `ao.PCSFNAME` - `ao.PCSFSTST` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): PCSFSTST = ktl . cache ( 'ao' , 'PCSFSTST' ) success = PCSFSTST . waitFor ( '!= \"FAULT\"' ) if success is not True : raise FailedPreCondition ( 'PCSFSTST is faulted' ) @classmethod def perform ( cls , args , logger , cfg ): PCSstagekw = ktl . cache ( 'ao' , 'PCSFNAME' ) log . info ( f \"Sending PCU to Home\" ) PCSstagekw . write ( 'home' ) shim_time = cfg . getfloat ( 'times' , 'ao_pcu_shim_time' , fallback = 5 ) time . sleep ( shim_time ) @classmethod def post_condition ( cls , args , logger , cfg ): PCSstagekw = ktl . cache ( 'ao' , 'PCSFSTST' ) timeout = cfg . getfloat ( 'times' , 'ao_pcu_move_time' , fallback = 150 ) success = PCSstagekw . waitfor ( \"== INPOS\" , timeout = timeout ) if success is False : raise FailedToReachDestination ( PCSstagekw . read (), 'home' )","title":"SendPCUtoHome"},{"location":"scripts/SendPCUtoKPF/","text":"SendPCUtoKPF Bases: KPFTranslatorFunction Send the PCU stage to the \"kpf\" named position. KTL Keywords Used: ao.PCSFNAME ao.PCSFSTST Source code in kpf/ao/SendPCUtoKPF.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 class SendPCUtoKPF ( KPFTranslatorFunction ): '''Send the PCU stage to the \"kpf\" named position. KTL Keywords Used: - `ao.PCSFNAME` - `ao.PCSFSTST` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) success = ao [ 'PCSFSTST' ] . waitFor ( '!= \"FAULT\"' ) if success is not True : raise FailedPreCondition ( 'PCSFSTST is faulted' ) success = ktl . waitfor ( \"($ao.PCSFSTST == INPOS)\" , timeout = 120 ) if success is False : raise FailedPreCondition ( 'PCU is in motion' ) success = ktl . waitfor ( \"($ao.PCSFNAME == home)\" , timeout = 120 ) if success is False : raise FailedPreCondition ( 'PCU must be at home before moving to KPF' ) @classmethod def perform ( cls , args , logger , cfg ): PCSstagekw = ktl . cache ( 'ao' , 'PCSFNAME' ) log . info ( f \"Sending PCU to KPF\" ) PCSstagekw . write ( 'kpf' ) shim_time = cfg . getfloat ( 'times' , 'ao_pcu_shim_time' , fallback = 5 ) time . sleep ( shim_time ) @classmethod def post_condition ( cls , args , logger , cfg ): PCSstagekw = ktl . cache ( 'ao' , 'PCSFSTST' ) timeout = cfg . getfloat ( 'times' , 'ao_pcu_move_time' , fallback = 150 ) success = PCSstagekw . waitfor ( \"== INPOS\" , timeout = timeout ) if success is False : raise FailedToReachDestination ( PCSstagekw . read (), 'kpf' )","title":"SendPCUtoKPF"},{"location":"scripts/SendPCUtoKPF/#sendpcutokpf","text":"Bases: KPFTranslatorFunction Send the PCU stage to the \"kpf\" named position. KTL Keywords Used: ao.PCSFNAME ao.PCSFSTST Source code in kpf/ao/SendPCUtoKPF.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 class SendPCUtoKPF ( KPFTranslatorFunction ): '''Send the PCU stage to the \"kpf\" named position. KTL Keywords Used: - `ao.PCSFNAME` - `ao.PCSFSTST` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) success = ao [ 'PCSFSTST' ] . waitFor ( '!= \"FAULT\"' ) if success is not True : raise FailedPreCondition ( 'PCSFSTST is faulted' ) success = ktl . waitfor ( \"($ao.PCSFSTST == INPOS)\" , timeout = 120 ) if success is False : raise FailedPreCondition ( 'PCU is in motion' ) success = ktl . waitfor ( \"($ao.PCSFNAME == home)\" , timeout = 120 ) if success is False : raise FailedPreCondition ( 'PCU must be at home before moving to KPF' ) @classmethod def perform ( cls , args , logger , cfg ): PCSstagekw = ktl . cache ( 'ao' , 'PCSFNAME' ) log . info ( f \"Sending PCU to KPF\" ) PCSstagekw . write ( 'kpf' ) shim_time = cfg . getfloat ( 'times' , 'ao_pcu_shim_time' , fallback = 5 ) time . sleep ( shim_time ) @classmethod def post_condition ( cls , args , logger , cfg ): PCSstagekw = ktl . cache ( 'ao' , 'PCSFSTST' ) timeout = cfg . getfloat ( 'times' , 'ao_pcu_move_time' , fallback = 150 ) success = PCSstagekw . waitfor ( \"== INPOS\" , timeout = timeout ) if success is False : raise FailedToReachDestination ( PCSstagekw . read (), 'kpf' )","title":"SendPCUtoKPF"},{"location":"scripts/SetADCAngles/","text":"SetADCAngles Bases: KPFTranslatorFunction Quick and dirty code to manually set ADC angles for a notional NULL position. KTL Keywords Used: kpffiu.ADC1VAL kpffiu.ADC2VAL Source code in kpf/fiu/SetADCAngles.py 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 class SetADCAngles ( KPFTranslatorFunction ): '''Quick and dirty code to manually set ADC angles for a notional NULL position. KTL Keywords Used: - `kpffiu.ADC1VAL` - `kpffiu.ADC2VAL` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpffiu = ktl . cache ( 'kpffiu' ) el = args . get ( 'EL' ) za = 90 - el ADC_delta = calculate_ADC_delta ( za ) log . info ( f \"ADC Hack: za= { za : .1f } , ADC_delta= { ADC_delta : .1f } \" ) # Constants common_angle = 60 ADC1_offset = - 5 ADC2_offset = 5 log . debug ( f \"ADC Hack: common_angle= { common_angle : .1f } \" ) log . debug ( f \"ADC Hack: ADC1_offset= { ADC1_offset : .1f } \" ) log . debug ( f \"ADC Hack: ADC2_offset= { ADC2_offset : .1f } \" ) # Calculations ADC1 = common_angle + ADC1_offset + za - ADC_delta ADC2 = common_angle + ADC2_offset - za - ADC_delta log . info ( f \"ADC Hack: Writing ADC1VAL= { ADC1 : .1f } , ADC2VAL= { ADC2 : .1f } \" ) kpffiu [ 'ADC1VAL' ] . write ( ADC1 ) kpffiu [ 'ADC2VAL' ] . write ( ADC2 ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'EL' , type = float , help = \"The telescope elevation to use in the calculation\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetADCAngles"},{"location":"scripts/SetADCAngles/#setadcangles","text":"Bases: KPFTranslatorFunction Quick and dirty code to manually set ADC angles for a notional NULL position. KTL Keywords Used: kpffiu.ADC1VAL kpffiu.ADC2VAL Source code in kpf/fiu/SetADCAngles.py 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 class SetADCAngles ( KPFTranslatorFunction ): '''Quick and dirty code to manually set ADC angles for a notional NULL position. KTL Keywords Used: - `kpffiu.ADC1VAL` - `kpffiu.ADC2VAL` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpffiu = ktl . cache ( 'kpffiu' ) el = args . get ( 'EL' ) za = 90 - el ADC_delta = calculate_ADC_delta ( za ) log . info ( f \"ADC Hack: za= { za : .1f } , ADC_delta= { ADC_delta : .1f } \" ) # Constants common_angle = 60 ADC1_offset = - 5 ADC2_offset = 5 log . debug ( f \"ADC Hack: common_angle= { common_angle : .1f } \" ) log . debug ( f \"ADC Hack: ADC1_offset= { ADC1_offset : .1f } \" ) log . debug ( f \"ADC Hack: ADC2_offset= { ADC2_offset : .1f } \" ) # Calculations ADC1 = common_angle + ADC1_offset + za - ADC_delta ADC2 = common_angle + ADC2_offset - za - ADC_delta log . info ( f \"ADC Hack: Writing ADC1VAL= { ADC1 : .1f } , ADC2VAL= { ADC2 : .1f } \" ) kpffiu [ 'ADC1VAL' ] . write ( ADC1 ) kpffiu [ 'ADC2VAL' ] . write ( ADC2 ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'EL' , type = float , help = \"The telescope elevation to use in the calculation\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetADCAngles"},{"location":"scripts/SetADCOffsets/","text":"SetADCOffsets Bases: KPFTranslatorFunction Quick and dirty code to manually set ADC angles to prescribed offsets from nominal based on the telescope position. Parameters: ADC1OFF ( float ) \u2013 Offset for ADC1 (in degrees). ADC2OFF ( float ) \u2013 Offset for ADC2 (in degrees). KTL Keywords Used: kpffiu.ADC1VAL kpffiu.ADC2VAL kpffiu.ADCTRACK kpffiu.ADCPRISMS Source code in kpf/fiu/SetADCOffsets.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetADCOffsets ( KPFTranslatorFunction ): '''Quick and dirty code to manually set ADC angles to prescribed offsets from nominal based on the telescope position. Args: ADC1OFF (float): Offset for ADC1 (in degrees). ADC2OFF (float): Offset for ADC2 (in degrees). KTL Keywords Used: - `kpffiu.ADC1VAL` - `kpffiu.ADC2VAL` - `kpffiu.ADCTRACK` - `kpffiu.ADCPRISMS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpffiu = ktl . cache ( 'kpffiu' ) if kpffiu [ 'ADCTRACK' ] . read () == 'On' : log . info ( f 'Setting ADCTRACK to Off' ) kpffiu [ 'ADCTRACK' ] . write ( 'Off' ) time . sleep ( 1 ) ADC1_nominal , ADC2_nominal = kpffiu [ 'ADCPRISMS' ] . read ( binary = True ) ADC1 = ADC1_nominal + args . get ( 'ADC1OFF' ) ADC2 = ADC2_nominal + args . get ( 'ADC2OFF' ) log . info ( f \"Setting ADC to offset angles: ADC1VAL= { ADC1 : .1f } , ADC2VAL= { ADC2 : .1f } \" ) kpffiu [ 'ADC1VAL' ] . write ( ADC1 ) kpffiu [ 'ADC2VAL' ] . write ( ADC2 ) @classmethod def post_condition ( cls , args , logger , cfg ): kpffiu = ktl . cache ( 'kpffiu' ) tol = 0.1 ADC1_nominal , ADC2_nominal = kpffiu [ 'ADCPRISMS' ] . read ( binary = True ) adc1targ = ADC1_nominal + args . get ( 'ADC1OFF' ) adc2targ = ADC2_nominal + args . get ( 'ADC2OFF' ) expr = ( f \"($kpffiu.ADC1VAL > { adc1targ - tol } ) \" f \"and ($kpffiu.ADC1VAL < { adc1targ + tol } ) \" f \"and ($kpffiu.ADC2VAL > { adc2targ - tol } ) \" f \"and ($kpffiu.ADC2VAL < { adc2targ + tol } )\" ) success = ktl . waitFor ( expr , timeout = 20 ) if success is False : raise FailedPostCondition ( 'ADC Prisms did not reach destination angles' ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'ADC1OFF' , type = float , help = \"Offset for ADC1 (in degrees)\" ) parser . add_argument ( 'ADC2OFF' , type = float , help = \"Offset for ADC2 (in degrees)\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetADCOffsets"},{"location":"scripts/SetADCOffsets/#setadcoffsets","text":"Bases: KPFTranslatorFunction Quick and dirty code to manually set ADC angles to prescribed offsets from nominal based on the telescope position. Parameters: ADC1OFF ( float ) \u2013 Offset for ADC1 (in degrees). ADC2OFF ( float ) \u2013 Offset for ADC2 (in degrees). KTL Keywords Used: kpffiu.ADC1VAL kpffiu.ADC2VAL kpffiu.ADCTRACK kpffiu.ADCPRISMS Source code in kpf/fiu/SetADCOffsets.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetADCOffsets ( KPFTranslatorFunction ): '''Quick and dirty code to manually set ADC angles to prescribed offsets from nominal based on the telescope position. Args: ADC1OFF (float): Offset for ADC1 (in degrees). ADC2OFF (float): Offset for ADC2 (in degrees). KTL Keywords Used: - `kpffiu.ADC1VAL` - `kpffiu.ADC2VAL` - `kpffiu.ADCTRACK` - `kpffiu.ADCPRISMS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpffiu = ktl . cache ( 'kpffiu' ) if kpffiu [ 'ADCTRACK' ] . read () == 'On' : log . info ( f 'Setting ADCTRACK to Off' ) kpffiu [ 'ADCTRACK' ] . write ( 'Off' ) time . sleep ( 1 ) ADC1_nominal , ADC2_nominal = kpffiu [ 'ADCPRISMS' ] . read ( binary = True ) ADC1 = ADC1_nominal + args . get ( 'ADC1OFF' ) ADC2 = ADC2_nominal + args . get ( 'ADC2OFF' ) log . info ( f \"Setting ADC to offset angles: ADC1VAL= { ADC1 : .1f } , ADC2VAL= { ADC2 : .1f } \" ) kpffiu [ 'ADC1VAL' ] . write ( ADC1 ) kpffiu [ 'ADC2VAL' ] . write ( ADC2 ) @classmethod def post_condition ( cls , args , logger , cfg ): kpffiu = ktl . cache ( 'kpffiu' ) tol = 0.1 ADC1_nominal , ADC2_nominal = kpffiu [ 'ADCPRISMS' ] . read ( binary = True ) adc1targ = ADC1_nominal + args . get ( 'ADC1OFF' ) adc2targ = ADC2_nominal + args . get ( 'ADC2OFF' ) expr = ( f \"($kpffiu.ADC1VAL > { adc1targ - tol } ) \" f \"and ($kpffiu.ADC1VAL < { adc1targ + tol } ) \" f \"and ($kpffiu.ADC2VAL > { adc2targ - tol } ) \" f \"and ($kpffiu.ADC2VAL < { adc2targ + tol } )\" ) success = ktl . waitFor ( expr , timeout = 20 ) if success is False : raise FailedPostCondition ( 'ADC Prisms did not reach destination angles' ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'ADC1OFF' , type = float , help = \"Offset for ADC1 (in degrees)\" ) parser . add_argument ( 'ADC2OFF' , type = float , help = \"Offset for ADC2 (in degrees)\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetADCOffsets"},{"location":"scripts/SetAFMtoMirror/","text":"SetAFMtoMirror Bases: KPFTranslatorFunction Set AFM to Mirror so ACAM sees light KTL Keywords Used: ao.OBAMNAME ao.OBAMSLEW ao.OBAMSTST Source code in kpf/ao/SetAFMtoMirror.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class SetAFMtoMirror ( KPFTranslatorFunction ): '''Set AFM to Mirror so ACAM sees light KTL Keywords Used: - `ao.OBAMNAME` - `ao.OBAMSLEW` - `ao.OBAMSTST` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) log . debug ( f \"Setting AFM to Mirror\" ) ao [ 'OBAMNAME' ] . write ( 'Mirror' ) ao [ 'OBAMSLEW' ] . write ( '1' ) @classmethod def post_condition ( cls , args , logger , cfg ): expr = '($ao.OBAMSTST == INPOS) and ($ao.OBAMNAME == Mirror)' aoamstst_success = ktl . waitfor ( expr , timeout = 60 ) if not aoamstst_success : ao = ktl . cache ( 'ao' ) FailedToReachDestination ( ao [ 'OBAMNAME' ] . read (), 'Mirror' )","title":"SetAFMtoMirror"},{"location":"scripts/SetAFMtoMirror/#setafmtomirror","text":"Bases: KPFTranslatorFunction Set AFM to Mirror so ACAM sees light KTL Keywords Used: ao.OBAMNAME ao.OBAMSLEW ao.OBAMSTST Source code in kpf/ao/SetAFMtoMirror.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class SetAFMtoMirror ( KPFTranslatorFunction ): '''Set AFM to Mirror so ACAM sees light KTL Keywords Used: - `ao.OBAMNAME` - `ao.OBAMSLEW` - `ao.OBAMSTST` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) log . debug ( f \"Setting AFM to Mirror\" ) ao [ 'OBAMNAME' ] . write ( 'Mirror' ) ao [ 'OBAMSLEW' ] . write ( '1' ) @classmethod def post_condition ( cls , args , logger , cfg ): expr = '($ao.OBAMSTST == INPOS) and ($ao.OBAMNAME == Mirror)' aoamstst_success = ktl . waitfor ( expr , timeout = 60 ) if not aoamstst_success : ao = ktl . cache ( 'ao' ) FailedToReachDestination ( ao [ 'OBAMNAME' ] . read (), 'Mirror' )","title":"SetAFMtoMirror"},{"location":"scripts/SetAFStoNGS/","text":"SetAFStoNGS Bases: KPFTranslatorFunction ACAM should be set to NGS focus. LGS focus will not work for KPF. KTL Keywords Used: ao.OBASNAME ao.OBASSLEW ao.OBASSTST Source code in kpf/ao/SetAFStoNGS.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class SetAFStoNGS ( KPFTranslatorFunction ): '''ACAM should be set to NGS focus. LGS focus will not work for KPF. KTL Keywords Used: - `ao.OBASNAME` - `ao.OBASSLEW` - `ao.OBASSTST` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) log . debug ( f \"Setting AFS to NGS\" ) ao [ 'OBASNAME' ] . write ( 'ngs' ) ao [ 'OBASSLEW' ] . write ( '1' ) @classmethod def post_condition ( cls , args , logger , cfg ): expr = f '($ao.OBASSTST == INPOS) and ($ao.OBASNAME == ngs)' aoamstst_success = ktl . waitfor ( expr , timeout = 60 ) if not aoamstst_success : ao = ktl . cache ( 'ao' ) raise FailedToReachDestination ( ao [ 'OBASNAME' ] . read (), 'ngs' )","title":"SetAFStoNGS"},{"location":"scripts/SetAFStoNGS/#setafstongs","text":"Bases: KPFTranslatorFunction ACAM should be set to NGS focus. LGS focus will not work for KPF. KTL Keywords Used: ao.OBASNAME ao.OBASSLEW ao.OBASSTST Source code in kpf/ao/SetAFStoNGS.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class SetAFStoNGS ( KPFTranslatorFunction ): '''ACAM should be set to NGS focus. LGS focus will not work for KPF. KTL Keywords Used: - `ao.OBASNAME` - `ao.OBASSLEW` - `ao.OBASSTST` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) log . debug ( f \"Setting AFS to NGS\" ) ao [ 'OBASNAME' ] . write ( 'ngs' ) ao [ 'OBASSLEW' ] . write ( '1' ) @classmethod def post_condition ( cls , args , logger , cfg ): expr = f '($ao.OBASSTST == INPOS) and ($ao.OBASNAME == ngs)' aoamstst_success = ktl . waitfor ( expr , timeout = 60 ) if not aoamstst_success : ao = ktl . cache ( 'ao' ) raise FailedToReachDestination ( ao [ 'OBASNAME' ] . read (), 'ngs' )","title":"SetAFStoNGS"},{"location":"scripts/SetAODCStoSIM/","text":"SetAODCStoSIM Bases: KPFTranslatorFunction Set AO in AO DCS sim mode, so AO doesn't communicate with telescope KTL Keywords Used: ao.AODCSSIM ao.AOCOMSIM ao.AODCSSFP Source code in kpf/ao/SetAODCStoSIM.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 class SetAODCStoSIM ( KPFTranslatorFunction ): '''Set AO in AO DCS sim mode, so AO doesn't communicate with telescope KTL Keywords Used: - `ao.AODCSSIM` - `ao.AOCOMSIM` - `ao.AODCSSFP` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) log . debug ( \"Setting AO DCS to Sim\" ) ao [ 'AODCSSIM' ] . write ( '1' ) ao [ 'AOCOMSIM' ] . write ( '1' ) ao [ 'AODCSSFP' ] . write ( '0' ) @classmethod def post_condition ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) aodcssim_success = ktl . waitfor ( '($ao.AODCSSIM == enabled)' , timeout = 3 ) if not aodcssim_success : raise FailedToReachDestination ( ao [ 'AODCSSIM' ] . read (), 'enabled' ) aocomsim_success = ktl . waitfor ( '($ao.AOCOMSIM == enabled)' , timeout = 3 ) if not aocomsim_success : raise FailedToReachDestination ( ao [ 'AOCOMSIM' ] . read (), 'enabled' ) aodcssfp_success = ktl . waitfor ( '($ao.AODCSSFP == disabled)' , timeout = 3 ) if not aodcssfp_success : raise FailedToReachDestination ( ao [ 'AODCSSFP' ] . read (), 'disabled' )","title":"SetAODCStoSIM"},{"location":"scripts/SetAODCStoSIM/#setaodcstosim","text":"Bases: KPFTranslatorFunction Set AO in AO DCS sim mode, so AO doesn't communicate with telescope KTL Keywords Used: ao.AODCSSIM ao.AOCOMSIM ao.AODCSSFP Source code in kpf/ao/SetAODCStoSIM.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 class SetAODCStoSIM ( KPFTranslatorFunction ): '''Set AO in AO DCS sim mode, so AO doesn't communicate with telescope KTL Keywords Used: - `ao.AODCSSIM` - `ao.AOCOMSIM` - `ao.AODCSSFP` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) log . debug ( \"Setting AO DCS to Sim\" ) ao [ 'AODCSSIM' ] . write ( '1' ) ao [ 'AOCOMSIM' ] . write ( '1' ) ao [ 'AODCSSFP' ] . write ( '0' ) @classmethod def post_condition ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) aodcssim_success = ktl . waitfor ( '($ao.AODCSSIM == enabled)' , timeout = 3 ) if not aodcssim_success : raise FailedToReachDestination ( ao [ 'AODCSSIM' ] . read (), 'enabled' ) aocomsim_success = ktl . waitfor ( '($ao.AOCOMSIM == enabled)' , timeout = 3 ) if not aocomsim_success : raise FailedToReachDestination ( ao [ 'AOCOMSIM' ] . read (), 'enabled' ) aodcssfp_success = ktl . waitfor ( '($ao.AODCSSFP == disabled)' , timeout = 3 ) if not aodcssfp_success : raise FailedToReachDestination ( ao [ 'AODCSSFP' ] . read (), 'disabled' )","title":"SetAODCStoSIM"},{"location":"scripts/SetAORotator/","text":"SetAORotator Bases: KPFTranslatorFunction Set the AO rotator destination KTL Keywords Used: ao.AODCSSIM ao.AOCOMSIM ao.AODCSSFP Parameters: dest ( float ) \u2013 Angle in degrees for the physical drive angle of the rotator. Source code in kpf/ao/SetAORotator.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class SetAORotator ( KPFTranslatorFunction ): '''Set the AO rotator destination KTL Keywords Used: - `ao.AODCSSIM` - `ao.AOCOMSIM` - `ao.AODCSSFP` Args: dest (float): Angle in degrees for the physical drive angle of the rotator. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'dest' ) @classmethod def perform ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) dest = args . get ( 'dest' , 0 ) log . debug ( f \"Setting AO Rotator to { dest : .1f } \" ) ao [ 'OBRT' ] . write ( dest ) ao [ 'OBRTMOVE' ] . write ( '1' ) @classmethod def post_condition ( cls , args , logger , cfg ): success = ktl . waitfor ( '($ao.OBRTSTST == INPOS)' , timeout = 180 ) if success is not True : ao = ktl . cache ( 'ao' ) raise FailedToReachDestination ( ao [ 'OBRTSTST' ] . read (), 'INPOS' ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'dest' , type = float , help = \"Desired rotator position\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetAORotator"},{"location":"scripts/SetAORotator/#setaorotator","text":"Bases: KPFTranslatorFunction Set the AO rotator destination KTL Keywords Used: ao.AODCSSIM ao.AOCOMSIM ao.AODCSSFP Parameters: dest ( float ) \u2013 Angle in degrees for the physical drive angle of the rotator. Source code in kpf/ao/SetAORotator.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class SetAORotator ( KPFTranslatorFunction ): '''Set the AO rotator destination KTL Keywords Used: - `ao.AODCSSIM` - `ao.AOCOMSIM` - `ao.AODCSSFP` Args: dest (float): Angle in degrees for the physical drive angle of the rotator. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'dest' ) @classmethod def perform ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) dest = args . get ( 'dest' , 0 ) log . debug ( f \"Setting AO Rotator to { dest : .1f } \" ) ao [ 'OBRT' ] . write ( dest ) ao [ 'OBRTMOVE' ] . write ( '1' ) @classmethod def post_condition ( cls , args , logger , cfg ): success = ktl . waitfor ( '($ao.OBRTSTST == INPOS)' , timeout = 180 ) if success is not True : ao = ktl . cache ( 'ao' ) raise FailedToReachDestination ( ao [ 'OBRTSTST' ] . read (), 'INPOS' ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'dest' , type = float , help = \"Desired rotator position\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetAORotator"},{"location":"scripts/SetAORotatorManual/","text":"SetAORotatorManual Bases: KPFTranslatorFunction AO rotator needs to be in the Manual mode before observing. KTL Keywords Used: ao.OBRTDSRC ao.OBRTMOVE Source code in kpf/ao/SetAORotatorManual.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class SetAORotatorManual ( KPFTranslatorFunction ): '''AO rotator needs to be in the Manual mode before observing. KTL Keywords Used: - `ao.OBRTDSRC` - `ao.OBRTMOVE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) log . debug ( \"Setting AO rotator to manual mode\" ) ao [ 'OBRTDSRC' ] . write ( '0' ) ao [ 'OBRTMOVE' ] . write ( '1' ) @classmethod def post_condition ( cls , args , logger , cfg ): success = ktl . waitfor ( '($ao.OBRTDSRC == manual)' , timeout = 3 ) if success is not True : ao = ktl . cache ( 'ao' ) raise FailedToReachDestination ( ao [ 'OBRTDSRC' ] . read (), 'manual' )","title":"SetAORotatorManual"},{"location":"scripts/SetAORotatorManual/#setaorotatormanual","text":"Bases: KPFTranslatorFunction AO rotator needs to be in the Manual mode before observing. KTL Keywords Used: ao.OBRTDSRC ao.OBRTMOVE Source code in kpf/ao/SetAORotatorManual.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class SetAORotatorManual ( KPFTranslatorFunction ): '''AO rotator needs to be in the Manual mode before observing. KTL Keywords Used: - `ao.OBRTDSRC` - `ao.OBRTMOVE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) log . debug ( \"Setting AO rotator to manual mode\" ) ao [ 'OBRTDSRC' ] . write ( '0' ) ao [ 'OBRTMOVE' ] . write ( '1' ) @classmethod def post_condition ( cls , args , logger , cfg ): success = ktl . waitfor ( '($ao.OBRTDSRC == manual)' , timeout = 3 ) if success is not True : ao = ktl . cache ( 'ao' ) raise FailedToReachDestination ( ao [ 'OBRTDSRC' ] . read (), 'manual' )","title":"SetAORotatorManual"},{"location":"scripts/SetCalSource/","text":"SetCalSource Bases: KPFTranslatorFunction Selects which source is fed from the octagon in to the cal bench via the kpfcal.OCTAGON keyword. Parameters: CalSource ( str ) \u2013 Which lamp to select? Allowed Values: EtalonFiber, BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, SoCal-CalFib, LFCFiber KTL Keywords Used: kpfcal.OCTAGON Source code in kpf/calbench/SetCalSource.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetCalSource ( KPFTranslatorFunction ): '''Selects which source is fed from the octagon in to the cal bench via the `kpfcal.OCTAGON` keyword. Args: CalSource (str): Which lamp to select? Allowed Values: EtalonFiber, BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, SoCal-CalFib, LFCFiber KTL Keywords Used: - `kpfcal.OCTAGON` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'OCTAGON' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) check_input ( args , 'CalSource' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): target = args . get ( 'CalSource' ) kpfcal = ktl . cache ( 'kpfcal' ) log . debug ( f \"Setting Cal Source (Octagon) to { target } \" ) kpfcal [ 'OCTAGON' ] . write ( target , wait = args . get ( 'wait' , True )) @classmethod def post_condition ( cls , args , logger , cfg ): target = args . get ( 'CalSource' ) timeout = cfg . getfloat ( 'times' , 'octagon_move_time' , fallback = 90 ) expr = f \"($kpfcal.OCTAGON == { target } )\" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : kpfcal = ktl . cache ( 'kpfcal' ) raise FailedToReachDestination ( kpfcal [ 'OCTAGON' ] . read (), target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalSource' , type = str , choices = [ 'Home' , 'EtalonFiber' , 'BrdbandFiber' , 'U_gold' , 'U_daily' , 'Th_daily' , 'Th_gold' , 'SoCal-CalFib' , 'LFCFiber' ], help = 'Octagon position to choose?' ) parser . add_argument ( \"--nowait\" , dest = \"wait\" , default = True , action = \"store_false\" , help = \"Send move and return immediately?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetCalSource"},{"location":"scripts/SetCalSource/#setcalsource","text":"Bases: KPFTranslatorFunction Selects which source is fed from the octagon in to the cal bench via the kpfcal.OCTAGON keyword. Parameters: CalSource ( str ) \u2013 Which lamp to select? Allowed Values: EtalonFiber, BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, SoCal-CalFib, LFCFiber KTL Keywords Used: kpfcal.OCTAGON Source code in kpf/calbench/SetCalSource.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetCalSource ( KPFTranslatorFunction ): '''Selects which source is fed from the octagon in to the cal bench via the `kpfcal.OCTAGON` keyword. Args: CalSource (str): Which lamp to select? Allowed Values: EtalonFiber, BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, SoCal-CalFib, LFCFiber KTL Keywords Used: - `kpfcal.OCTAGON` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'OCTAGON' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) check_input ( args , 'CalSource' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): target = args . get ( 'CalSource' ) kpfcal = ktl . cache ( 'kpfcal' ) log . debug ( f \"Setting Cal Source (Octagon) to { target } \" ) kpfcal [ 'OCTAGON' ] . write ( target , wait = args . get ( 'wait' , True )) @classmethod def post_condition ( cls , args , logger , cfg ): target = args . get ( 'CalSource' ) timeout = cfg . getfloat ( 'times' , 'octagon_move_time' , fallback = 90 ) expr = f \"($kpfcal.OCTAGON == { target } )\" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : kpfcal = ktl . cache ( 'kpfcal' ) raise FailedToReachDestination ( kpfcal [ 'OCTAGON' ] . read (), target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalSource' , type = str , choices = [ 'Home' , 'EtalonFiber' , 'BrdbandFiber' , 'U_gold' , 'U_daily' , 'Th_daily' , 'Th_gold' , 'SoCal-CalFib' , 'LFCFiber' ], help = 'Octagon position to choose?' ) parser . add_argument ( \"--nowait\" , dest = \"wait\" , default = True , action = \"store_false\" , help = \"Send move and return immediately?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetCalSource"},{"location":"scripts/SetExpMeterExpTime/","text":"SetExpMeterExpTime Bases: KPFTranslatorFunction Sets the exposure time for the exposure meter Parameters: ExpMeterExpTime ( float ) \u2013 The exposure time in seconds. KTL Keywords Used: kpf_expmeter.EXPOSURE Source code in kpf/expmeter/SetExpMeterExpTime.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 class SetExpMeterExpTime ( KPFTranslatorFunction ): '''Sets the exposure time for the exposure meter Args: ExpMeterExpTime (float): The exposure time in seconds. KTL Keywords Used: - `kpf_expmeter.EXPOSURE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'ExpMeterExpTime' , allowed_types = [ int , float ]) @classmethod def perform ( cls , args , logger , cfg ): kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) exptime = args . get ( 'ExpMeterExpTime' ) log . debug ( f \"Setting exposure time to { exptime : .3f } \" ) kpf_expmeter [ 'EXPOSURE' ] . write ( exptime ) @classmethod def post_condition ( cls , args , logger , cfg ): log . debug ( \"Checking for success\" ) exptime = args . get ( 'ExpMeterExpTime' ) tol = cfg . getfloat ( 'tolerances' , 'kpfexpose_exptime_tolerance' , fallback = 0.01 ) timeout = cfg . getfloat ( 'times' , 'kpfexpose_response_time' , fallback = 1 ) expr = ( f \"($kpf_expmeter.EXPOSURE >= { exptime - tol } ) and \" f \"($kpf_expmeter.EXPOSURE <= { exptime + tol } )\" ) log . debug ( expr ) success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : exposure = ktl . cache ( 'kpf_expmeter' , 'EXPOSURE' ) raise FailedToReachDestination ( exposure . read (), exptime ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'ExpMeterExpTime' , type = float , help = \"The exposure time in seconds\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetExpMeterExpTime"},{"location":"scripts/SetExpMeterExpTime/#setexpmeterexptime","text":"Bases: KPFTranslatorFunction Sets the exposure time for the exposure meter Parameters: ExpMeterExpTime ( float ) \u2013 The exposure time in seconds. KTL Keywords Used: kpf_expmeter.EXPOSURE Source code in kpf/expmeter/SetExpMeterExpTime.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 class SetExpMeterExpTime ( KPFTranslatorFunction ): '''Sets the exposure time for the exposure meter Args: ExpMeterExpTime (float): The exposure time in seconds. KTL Keywords Used: - `kpf_expmeter.EXPOSURE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'ExpMeterExpTime' , allowed_types = [ int , float ]) @classmethod def perform ( cls , args , logger , cfg ): kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) exptime = args . get ( 'ExpMeterExpTime' ) log . debug ( f \"Setting exposure time to { exptime : .3f } \" ) kpf_expmeter [ 'EXPOSURE' ] . write ( exptime ) @classmethod def post_condition ( cls , args , logger , cfg ): log . debug ( \"Checking for success\" ) exptime = args . get ( 'ExpMeterExpTime' ) tol = cfg . getfloat ( 'tolerances' , 'kpfexpose_exptime_tolerance' , fallback = 0.01 ) timeout = cfg . getfloat ( 'times' , 'kpfexpose_response_time' , fallback = 1 ) expr = ( f \"($kpf_expmeter.EXPOSURE >= { exptime - tol } ) and \" f \"($kpf_expmeter.EXPOSURE <= { exptime + tol } )\" ) log . debug ( expr ) success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : exposure = ktl . cache ( 'kpf_expmeter' , 'EXPOSURE' ) raise FailedToReachDestination ( exposure . read (), exptime ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'ExpMeterExpTime' , type = float , help = \"The exposure time in seconds\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetExpMeterExpTime"},{"location":"scripts/SetExpMeterTerminationParameters/","text":"SetExpMeterTerminationParameters Bases: KPFTranslatorFunction Sets the exposure meter exposure termination control parameters Parameters: Band ( int ) \u2013 Which of the 4 exposure meter bands to use? 0=All, 1=498nm, 2=604nm, 3=711nm, 4=817nm (from kpf_expmeter.THRESHOLDBIN). Flux ( float ) \u2013 The target flux (e/nm) in the science spectrum. KTL Keywords Used: kpf_expmeter.THRESHOLDBIN kpf_expmeter.THRESHOLD kpf_expmeter.USETHRESHOLD Source code in kpf/expmeter/SetExpMeterTerminationParameters.py 18 19 20 21 22 23 24 25 26 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 class SetExpMeterTerminationParameters ( KPFTranslatorFunction ): '''Sets the exposure meter exposure termination control parameters Args: Band (int): Which of the 4 exposure meter bands to use? 0=All, 1=498nm, 2=604nm, 3=711nm, 4=817nm (from kpf_expmeter.THRESHOLDBIN). Flux (float): The target flux (e/nm) in the science spectrum. KTL Keywords Used: - `kpf_expmeter.THRESHOLDBIN` - `kpf_expmeter.THRESHOLD` - `kpf_expmeter.USETHRESHOLD` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'ExpMeterThreshold' , allowed_types = [ int , float ], value_min = 0 ) check_input ( args , 'ExpMeterBin' ) # Manually check ExpMeterBin inputs band = args . get ( 'ExpMeterBin' ) tbin = ktl . cache ( 'kpf_expmeter' , 'THRESHOLDBIN' ) allowed_values = list ( tbin . _getEnumerators ()) if isinstance ( band , float ): band = str ( band ) if isinstance ( band , str ): if band not in allowed_values : raise FailedPreCondition ( f \"ExpMeterBin ' { band } ' not in { allowed_values } \" ) else : raise FailedPreCondition ( f \"ExpMeterBin ' { band } ' could not be parsed\" ) @classmethod def perform ( cls , args , logger , cfg ): band = str ( args . get ( 'ExpMeterBin' )) spectrograph_flux = args . get ( 'ExpMeterThreshold' ) expmeter_flux = expeter_flux_target ( spectrograph_flux , band ) kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) kpf_expmeter [ 'THRESHOLDBIN' ] . write ( band ) kpf_expmeter [ 'THRESHOLD' ] . write ( expmeter_flux ) kpf_expmeter [ 'USETHRESHOLD' ] . write ( 'Yes' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'ExpMeterBin' , type = int , choices = [ 1 , 2 , 3 , 4 ], help = \"Which exposure meter band to use (1, 2, 3, or 4)\" ) parser . add_argument ( 'ExpMeterThreshold' , type = float , help = \"Threshold flux in e-/nm in the main spectrograph\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetExpMeterTerminationParameters"},{"location":"scripts/SetExpMeterTerminationParameters/#setexpmeterterminationparameters","text":"Bases: KPFTranslatorFunction Sets the exposure meter exposure termination control parameters Parameters: Band ( int ) \u2013 Which of the 4 exposure meter bands to use? 0=All, 1=498nm, 2=604nm, 3=711nm, 4=817nm (from kpf_expmeter.THRESHOLDBIN). Flux ( float ) \u2013 The target flux (e/nm) in the science spectrum. KTL Keywords Used: kpf_expmeter.THRESHOLDBIN kpf_expmeter.THRESHOLD kpf_expmeter.USETHRESHOLD Source code in kpf/expmeter/SetExpMeterTerminationParameters.py 18 19 20 21 22 23 24 25 26 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 class SetExpMeterTerminationParameters ( KPFTranslatorFunction ): '''Sets the exposure meter exposure termination control parameters Args: Band (int): Which of the 4 exposure meter bands to use? 0=All, 1=498nm, 2=604nm, 3=711nm, 4=817nm (from kpf_expmeter.THRESHOLDBIN). Flux (float): The target flux (e/nm) in the science spectrum. KTL Keywords Used: - `kpf_expmeter.THRESHOLDBIN` - `kpf_expmeter.THRESHOLD` - `kpf_expmeter.USETHRESHOLD` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'ExpMeterThreshold' , allowed_types = [ int , float ], value_min = 0 ) check_input ( args , 'ExpMeterBin' ) # Manually check ExpMeterBin inputs band = args . get ( 'ExpMeterBin' ) tbin = ktl . cache ( 'kpf_expmeter' , 'THRESHOLDBIN' ) allowed_values = list ( tbin . _getEnumerators ()) if isinstance ( band , float ): band = str ( band ) if isinstance ( band , str ): if band not in allowed_values : raise FailedPreCondition ( f \"ExpMeterBin ' { band } ' not in { allowed_values } \" ) else : raise FailedPreCondition ( f \"ExpMeterBin ' { band } ' could not be parsed\" ) @classmethod def perform ( cls , args , logger , cfg ): band = str ( args . get ( 'ExpMeterBin' )) spectrograph_flux = args . get ( 'ExpMeterThreshold' ) expmeter_flux = expeter_flux_target ( spectrograph_flux , band ) kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) kpf_expmeter [ 'THRESHOLDBIN' ] . write ( band ) kpf_expmeter [ 'THRESHOLD' ] . write ( expmeter_flux ) kpf_expmeter [ 'USETHRESHOLD' ] . write ( 'Yes' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'ExpMeterBin' , type = int , choices = [ 1 , 2 , 3 , 4 ], help = \"Which exposure meter band to use (1, 2, 3, or 4)\" ) parser . add_argument ( 'ExpMeterThreshold' , type = float , help = \"Threshold flux in e-/nm in the main spectrograph\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetExpMeterTerminationParameters"},{"location":"scripts/SetExpTime/","text":"SetExpTime Bases: KPFTranslatorFunction Sets the exposure time for the science detectors in the kpfexpose keyword service. ARGS: :ExpTime: float The exposure time in seconds Source code in kpf/spectrograph/SetExpTime.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class SetExpTime ( KPFTranslatorFunction ): '''Sets the exposure time for the science detectors in the kpfexpose keyword service. ARGS: ===== :ExpTime: `float` The exposure time in seconds ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'ExpTime' , allowed_types = [ int , float ]) @classmethod def perform ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) exptime = args . get ( 'ExpTime' ) log . debug ( f \"Setting exposure time to { exptime : .3f } \" ) kpfexpose [ 'EXPOSURE' ] . write ( exptime ) @classmethod def post_condition ( cls , args , logger , cfg ): log . debug ( \"Checking for success\" ) exptime = args . get ( 'ExpTime' ) tol = cfg . getfloat ( 'tolerances' , 'kpfexpose_exptime_tolerance' , fallback = 0.01 ) timeout = cfg . getfloat ( 'times' , 'kpfexpose_response_time' , fallback = 1 ) expr = ( f \"($kpfexpose.EXPOSURE >= { exptime - tol } ) and \" f \"($kpfexpose.EXPOSURE <= { exptime + tol } )\" ) log . debug ( expr ) success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : exposure = ktl . cache ( 'kpfexpose' , 'EXPOSURE' ) raise FailedToReachDestination ( exposure . read (), exptime ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'ExpTime' , type = float , help = 'The exposure time in seconds' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetExpTime"},{"location":"scripts/SetExpTime/#setexptime","text":"Bases: KPFTranslatorFunction Sets the exposure time for the science detectors in the kpfexpose keyword service.","title":"SetExpTime"},{"location":"scripts/SetExpTime/#kpf.spectrograph.SetExpTime.SetExpTime--args","text":":ExpTime: float The exposure time in seconds Source code in kpf/spectrograph/SetExpTime.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class SetExpTime ( KPFTranslatorFunction ): '''Sets the exposure time for the science detectors in the kpfexpose keyword service. ARGS: ===== :ExpTime: `float` The exposure time in seconds ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'ExpTime' , allowed_types = [ int , float ]) @classmethod def perform ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) exptime = args . get ( 'ExpTime' ) log . debug ( f \"Setting exposure time to { exptime : .3f } \" ) kpfexpose [ 'EXPOSURE' ] . write ( exptime ) @classmethod def post_condition ( cls , args , logger , cfg ): log . debug ( \"Checking for success\" ) exptime = args . get ( 'ExpTime' ) tol = cfg . getfloat ( 'tolerances' , 'kpfexpose_exptime_tolerance' , fallback = 0.01 ) timeout = cfg . getfloat ( 'times' , 'kpfexpose_response_time' , fallback = 1 ) expr = ( f \"($kpfexpose.EXPOSURE >= { exptime - tol } ) and \" f \"($kpfexpose.EXPOSURE <= { exptime + tol } )\" ) log . debug ( expr ) success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : exposure = ktl . cache ( 'kpfexpose' , 'EXPOSURE' ) raise FailedToReachDestination ( exposure . read (), exptime ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'ExpTime' , type = float , help = 'The exposure time in seconds' ) return super () . add_cmdline_args ( parser , cfg )","title":"ARGS:"},{"location":"scripts/SetFVCExpTime/","text":"SetFVCExpTime Bases: KPFTranslatorFunction Set the exposure time of the specified fiber viewing camera Parameters: camera ( str ) \u2013 Which FVC camera? Allowed values: SCI, CAHK, EXT, CAL exptime ( float ) \u2013 The exposure time in seconds. KTL Keywords Used: kpffvc.SCIEXPTIME kpffvc.CAHKEXPTIME kpffvc.EXTEXPTIME kpffvc.CALEXPTIME kpfpower.KPFFVC1 kpfpower.KPFFVC2 kpfpower.KPFFVC3 Source code in kpf/fvc/SetFVCExpTime.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetFVCExpTime ( KPFTranslatorFunction ): '''Set the exposure time of the specified fiber viewing camera Args: camera (str): Which FVC camera? Allowed values: SCI, CAHK, EXT, CAL exptime (float): The exposure time in seconds. KTL Keywords Used: - `kpffvc.SCIEXPTIME` - `kpffvc.CAHKEXPTIME` - `kpffvc.EXTEXPTIME` - `kpffvc.CALEXPTIME` - `kpfpower.KPFFVC1` - `kpfpower.KPFFVC2` - `kpfpower.KPFFVC3` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'camera' , allowed_values = [ 'SCI' , 'CAHK' , 'CAL' , 'EXT' ]) check_input ( args , 'exptime' , value_min = 0.005 , value_max = 60 ) # Check if power is on camera = args . get ( 'camera' ) camnum = { 'SCI' : 1 , 'CAHK' : 2 , 'CAL' : 3 , 'EXT' : None }[ camera ] if camnum is not None : powerkw = ktl . cache ( 'kpfpower' , f \"KPFFVC { camnum } \" ) if powerkw . read () != 'On' : raise FailedPreCondition ( f \" { camera } FVC power is not On\" ) @classmethod def perform ( cls , args , logger , cfg ): camera = args . get ( 'camera' ) kpffvc = ktl . cache ( 'kpffvc' ) exptime = args . get ( 'exptime' ) log . debug ( f \"Setting { camera } FVC exposure time to { exptime : .3f } s\" ) kpffvc [ f ' { camera } EXPTIME' ] . write ( exptime ) @classmethod def post_condition ( cls , args , logger , cfg ): camera = args . get ( 'camera' ) exptime = args . get ( 'exptime' ) timeout = cfg . getfloat ( 'times' , 'fvc_command_timeout' , fallback = 5 ) tol = cfg . getfloat ( 'tolerances' , 'guider_exptime_tolerance' , fallback = 0.01 ) expr = ( f '($kpffvc. { camera } EXPTIME > { exptime } - { tol } ) ' \\ f 'and ($kpffvc. { camera } EXPTIME < { exptime } + { tol } )' ) success = ktl . waitfor ( expr , timeout = timeout ) if success is not True : exptimekw = ktl . cache ( 'kpffvc' , f \" { camera } EXPTIME\" ) raise FailedToReachDestination ( exptimekw . read (), exptime ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'camera' , type = str , choices = [ 'SCI' , 'CAHK' , 'CAL' , 'EXT' ], help = 'The FVC camera' ) parser . add_argument ( 'exptime' , type = float , help = 'The exposure time in seconds' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetFVCExpTime"},{"location":"scripts/SetFVCExpTime/#setfvcexptime","text":"Bases: KPFTranslatorFunction Set the exposure time of the specified fiber viewing camera Parameters: camera ( str ) \u2013 Which FVC camera? Allowed values: SCI, CAHK, EXT, CAL exptime ( float ) \u2013 The exposure time in seconds. KTL Keywords Used: kpffvc.SCIEXPTIME kpffvc.CAHKEXPTIME kpffvc.EXTEXPTIME kpffvc.CALEXPTIME kpfpower.KPFFVC1 kpfpower.KPFFVC2 kpfpower.KPFFVC3 Source code in kpf/fvc/SetFVCExpTime.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetFVCExpTime ( KPFTranslatorFunction ): '''Set the exposure time of the specified fiber viewing camera Args: camera (str): Which FVC camera? Allowed values: SCI, CAHK, EXT, CAL exptime (float): The exposure time in seconds. KTL Keywords Used: - `kpffvc.SCIEXPTIME` - `kpffvc.CAHKEXPTIME` - `kpffvc.EXTEXPTIME` - `kpffvc.CALEXPTIME` - `kpfpower.KPFFVC1` - `kpfpower.KPFFVC2` - `kpfpower.KPFFVC3` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'camera' , allowed_values = [ 'SCI' , 'CAHK' , 'CAL' , 'EXT' ]) check_input ( args , 'exptime' , value_min = 0.005 , value_max = 60 ) # Check if power is on camera = args . get ( 'camera' ) camnum = { 'SCI' : 1 , 'CAHK' : 2 , 'CAL' : 3 , 'EXT' : None }[ camera ] if camnum is not None : powerkw = ktl . cache ( 'kpfpower' , f \"KPFFVC { camnum } \" ) if powerkw . read () != 'On' : raise FailedPreCondition ( f \" { camera } FVC power is not On\" ) @classmethod def perform ( cls , args , logger , cfg ): camera = args . get ( 'camera' ) kpffvc = ktl . cache ( 'kpffvc' ) exptime = args . get ( 'exptime' ) log . debug ( f \"Setting { camera } FVC exposure time to { exptime : .3f } s\" ) kpffvc [ f ' { camera } EXPTIME' ] . write ( exptime ) @classmethod def post_condition ( cls , args , logger , cfg ): camera = args . get ( 'camera' ) exptime = args . get ( 'exptime' ) timeout = cfg . getfloat ( 'times' , 'fvc_command_timeout' , fallback = 5 ) tol = cfg . getfloat ( 'tolerances' , 'guider_exptime_tolerance' , fallback = 0.01 ) expr = ( f '($kpffvc. { camera } EXPTIME > { exptime } - { tol } ) ' \\ f 'and ($kpffvc. { camera } EXPTIME < { exptime } + { tol } )' ) success = ktl . waitfor ( expr , timeout = timeout ) if success is not True : exptimekw = ktl . cache ( 'kpffvc' , f \" { camera } EXPTIME\" ) raise FailedToReachDestination ( exptimekw . read (), exptime ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'camera' , type = str , choices = [ 'SCI' , 'CAHK' , 'CAL' , 'EXT' ], help = 'The FVC camera' ) parser . add_argument ( 'exptime' , type = float , help = 'The exposure time in seconds' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetFVCExpTime"},{"location":"scripts/SetFlatFieldFiberPos/","text":"SetFlatFieldFiberPos Bases: KPFTranslatorFunction Description Set the flat field fiber aperture via the kpfcal.FF_FIBERPOS keyword. Parameters: FF_FiberPos ( str ) \u2013 The name of the flat field fiber position desired. Allowed Values: \"Blank\", \"6 mm f/5\", \"7.5 mm f/4\", \"10 mm f/3\", \"13.2 mm f/2.3\", \"Open\". wait ( bool ) \u2013 Wait for move to complete before returning? default: True KTL Keywords Used kpfcal.FF_FIBERPOS Source code in kpf/calbench/SetFlatFieldFiberPos.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetFlatFieldFiberPos ( KPFTranslatorFunction ): '''# Description Set the flat field fiber aperture via the `kpfcal.FF_FIBERPOS` keyword. Args: FF_FiberPos (str): The name of the flat field fiber position desired. Allowed Values: \"Blank\", \"6 mm f/5\", \"7.5 mm f/4\", \"10 mm f/3\", \"13.2 mm f/2.3\", \"Open\". wait (bool): Wait for move to complete before returning? default: True ## KTL Keywords Used - `kpfcal.FF_FIBERPOS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'FF_FiberPos' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) check_input ( args , 'FF_FiberPos' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): target = args . get ( 'FF_FiberPos' ) log . debug ( f \"Setting FF_FiberPos to { target } \" ) kpfcal = ktl . cache ( 'kpfcal' ) kpfcal [ 'FF_FiberPos' ] . write ( target , wait = args . get ( 'wait' , True )) @classmethod def post_condition ( cls , args , logger , cfg ): target = args . get ( 'FF_FiberPos' ) timeout = cfg . getfloat ( 'times' , 'nd_move_time' , fallback = 20 ) expr = f \"($kpfcal.FF_FiberPos == ' { target } ')\" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : kpfcal = ktl . cache ( 'kpfcal' ) raise FailedToReachDestination ( kpfcal [ 'FF_FiberPos' ] . read (), target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'FF_FiberPos' , type = str , choices = [ \"Blank\" , \"6 mm f/5\" , \"7.5 mm f/4\" , \"10 mm f/3\" , \"13.2 mm f/2.3\" , \"Open\" ], help = 'Wide flat aperture to use.' ) parser . add_argument ( \"--nowait\" , dest = \"wait\" , default = True , action = \"store_false\" , help = \"Send move and return immediately?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetFlatFieldFiberPos"},{"location":"scripts/SetFlatFieldFiberPos/#setflatfieldfiberpos","text":"Bases: KPFTranslatorFunction","title":"SetFlatFieldFiberPos"},{"location":"scripts/SetFlatFieldFiberPos/#kpf.calbench.SetFlatFieldFiberPos.SetFlatFieldFiberPos--description","text":"Set the flat field fiber aperture via the kpfcal.FF_FIBERPOS keyword. Parameters: FF_FiberPos ( str ) \u2013 The name of the flat field fiber position desired. Allowed Values: \"Blank\", \"6 mm f/5\", \"7.5 mm f/4\", \"10 mm f/3\", \"13.2 mm f/2.3\", \"Open\". wait ( bool ) \u2013 Wait for move to complete before returning? default: True","title":"Description"},{"location":"scripts/SetFlatFieldFiberPos/#kpf.calbench.SetFlatFieldFiberPos.SetFlatFieldFiberPos--ktl-keywords-used","text":"kpfcal.FF_FIBERPOS Source code in kpf/calbench/SetFlatFieldFiberPos.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetFlatFieldFiberPos ( KPFTranslatorFunction ): '''# Description Set the flat field fiber aperture via the `kpfcal.FF_FIBERPOS` keyword. Args: FF_FiberPos (str): The name of the flat field fiber position desired. Allowed Values: \"Blank\", \"6 mm f/5\", \"7.5 mm f/4\", \"10 mm f/3\", \"13.2 mm f/2.3\", \"Open\". wait (bool): Wait for move to complete before returning? default: True ## KTL Keywords Used - `kpfcal.FF_FIBERPOS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'FF_FiberPos' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) check_input ( args , 'FF_FiberPos' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): target = args . get ( 'FF_FiberPos' ) log . debug ( f \"Setting FF_FiberPos to { target } \" ) kpfcal = ktl . cache ( 'kpfcal' ) kpfcal [ 'FF_FiberPos' ] . write ( target , wait = args . get ( 'wait' , True )) @classmethod def post_condition ( cls , args , logger , cfg ): target = args . get ( 'FF_FiberPos' ) timeout = cfg . getfloat ( 'times' , 'nd_move_time' , fallback = 20 ) expr = f \"($kpfcal.FF_FiberPos == ' { target } ')\" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : kpfcal = ktl . cache ( 'kpfcal' ) raise FailedToReachDestination ( kpfcal [ 'FF_FiberPos' ] . read (), target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'FF_FiberPos' , type = str , choices = [ \"Blank\" , \"6 mm f/5\" , \"7.5 mm f/4\" , \"10 mm f/3\" , \"13.2 mm f/2.3\" , \"Open\" ], help = 'Wide flat aperture to use.' ) parser . add_argument ( \"--nowait\" , dest = \"wait\" , default = True , action = \"store_false\" , help = \"Send move and return immediately?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"KTL Keywords Used"},{"location":"scripts/SetGuiderExpTime/","text":"SetGuiderExpTime Bases: KPFTranslatorFunction Set the guider exposure time (in seconds) via the kpfguide.EXPTIME keyword. The guider exposure time is governed by several factors. The exposure time controlled here is generated by stacking (averaging) multiple frames as needed to obtain the specified exposure time. Those individual frames are controlled by the FPS, AVERAGE, STACK, and EXPTIME keywords. From Kyle: If you want to tweak an exposure setting, I recommend MAGIQ use the EXPTIME keyword as its preferred knob. This will translate to changing the number of frames averaged together. You can also choose to stack frames, but I doubt that will be necessary. Notice how EXPTIME remains unchanged when I change the STACK keyword: [klanclos@kpffiuserver ~]$ gshow -s kpfguide fps average stack exptime FPS = 100.0000 frames/second AVERAGE = 100 frames STACK = 1 averaged frames EXPTIME = 1.000000 seconds [klanclos@kpffiuserver ~]$ modify -s kpfguide stack=2 setting stack = 2 (wait) [klanclos@kpffiuserver ~]$ gshow -s kpfguide fps average stack exptime FPS = 100.0000 frames/second AVERAGE = 50 frames STACK = 2 averaged frames EXPTIME = 1.000000 seconds ...but if I change AVERAGE, EXPTIME reflects the change: [klanclos@kpffiuserver ~]$ modify -s kpfguide average=20 setting average = 20 (wait) [klanclos@kpffiuserver ~]$ gshow -s kpfguide fps average stack exptime FPS = 100.0000 frames/second AVERAGE = 20 frames STACK = 1 averaged frames EXPTIME = 0.200000 seconds Stick to changing EXPTIME and you won't have to worry about it. Changing the frames per second is not recommended, because the tip/tilt system will be consuming this image stream, and it needs to retain full control of what an individual frame looks like. Parameters: exptime ( float ) \u2013 The exposure time in seconds. KTL Keywords Used: kpfguide.EXPTIME Source code in kpf/guider/SetGuiderExpTime.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetGuiderExpTime ( KPFTranslatorFunction ): '''Set the guider exposure time (in seconds) via the kpfguide.EXPTIME keyword. The guider exposure time is governed by several factors. The exposure time controlled here is generated by stacking (averaging) multiple frames as needed to obtain the specified exposure time. Those individual frames are controlled by the FPS, AVERAGE, STACK, and EXPTIME keywords. From Kyle: If you want to tweak an exposure setting, I recommend MAGIQ use the EXPTIME keyword as its preferred knob. This will translate to changing the number of frames averaged together. You can also choose to stack frames, but I doubt that will be necessary. Notice how EXPTIME remains unchanged when I change the STACK keyword: [klanclos@kpffiuserver ~]$ gshow -s kpfguide fps average stack exptime FPS = 100.0000 frames/second AVERAGE = 100 frames STACK = 1 averaged frames EXPTIME = 1.000000 seconds [klanclos@kpffiuserver ~]$ modify -s kpfguide stack=2 setting stack = 2 (wait) [klanclos@kpffiuserver ~]$ gshow -s kpfguide fps average stack exptime FPS = 100.0000 frames/second AVERAGE = 50 frames STACK = 2 averaged frames EXPTIME = 1.000000 seconds ...but if I change AVERAGE, EXPTIME reflects the change: [klanclos@kpffiuserver ~]$ modify -s kpfguide average=20 setting average = 20 (wait) [klanclos@kpffiuserver ~]$ gshow -s kpfguide fps average stack exptime FPS = 100.0000 frames/second AVERAGE = 20 frames STACK = 1 averaged frames EXPTIME = 0.200000 seconds Stick to changing EXPTIME and you won't have to worry about it. Changing the frames per second is not recommended, because the tip/tilt system will be consuming this image stream, and it needs to retain full control of what an individual frame looks like. Args: exptime (float): The exposure time in seconds. KTL Keywords Used: - `kpfguide.EXPTIME` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'exptime' , value_min = 0 ) @classmethod def perform ( cls , args , logger , cfg ): exptimekw = ktl . cache ( 'kpfguide' , 'EXPTIME' ) exptime = args . get ( 'exptime' ) exptimekw . write ( exptime ) @classmethod def post_condition ( cls , args , logger , cfg ): exptol = cfg . getfloat ( 'tolerances' , 'guider_exptime_tolerance' , fallback = 0.01 ) exptimekw = ktl . cache ( 'kpfguide' , 'EXPTIME' ) exptimeread = exptimekw . read ( binary = True ) exptime = args . get ( 'exptime' ) expr = ( f '($kpfguide.EXPTIME >= { exptime - exptol } ) and ' \\ f '($kpfguide.EXPTIME <= { exptime + exptol } )' ) success = ktl . waitFor ( expr , timeout = exptimeread + 1 ) if not success : raise FailedToReachDestination ( exptimekw . read (), exptime ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'exptime' , type = float , help = 'The exposure time in seconds' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetGuiderExpTime"},{"location":"scripts/SetGuiderExpTime/#setguiderexptime","text":"Bases: KPFTranslatorFunction Set the guider exposure time (in seconds) via the kpfguide.EXPTIME keyword. The guider exposure time is governed by several factors. The exposure time controlled here is generated by stacking (averaging) multiple frames as needed to obtain the specified exposure time. Those individual frames are controlled by the FPS, AVERAGE, STACK, and EXPTIME keywords. From Kyle: If you want to tweak an exposure setting, I recommend MAGIQ use the EXPTIME keyword as its preferred knob. This will translate to changing the number of frames averaged together. You can also choose to stack frames, but I doubt that will be necessary. Notice how EXPTIME remains unchanged when I change the STACK keyword: [klanclos@kpffiuserver ~]$ gshow -s kpfguide fps average stack exptime FPS = 100.0000 frames/second AVERAGE = 100 frames STACK = 1 averaged frames EXPTIME = 1.000000 seconds [klanclos@kpffiuserver ~]$ modify -s kpfguide stack=2 setting stack = 2 (wait) [klanclos@kpffiuserver ~]$ gshow -s kpfguide fps average stack exptime FPS = 100.0000 frames/second AVERAGE = 50 frames STACK = 2 averaged frames EXPTIME = 1.000000 seconds ...but if I change AVERAGE, EXPTIME reflects the change: [klanclos@kpffiuserver ~]$ modify -s kpfguide average=20 setting average = 20 (wait) [klanclos@kpffiuserver ~]$ gshow -s kpfguide fps average stack exptime FPS = 100.0000 frames/second AVERAGE = 20 frames STACK = 1 averaged frames EXPTIME = 0.200000 seconds Stick to changing EXPTIME and you won't have to worry about it. Changing the frames per second is not recommended, because the tip/tilt system will be consuming this image stream, and it needs to retain full control of what an individual frame looks like. Parameters: exptime ( float ) \u2013 The exposure time in seconds. KTL Keywords Used: kpfguide.EXPTIME Source code in kpf/guider/SetGuiderExpTime.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetGuiderExpTime ( KPFTranslatorFunction ): '''Set the guider exposure time (in seconds) via the kpfguide.EXPTIME keyword. The guider exposure time is governed by several factors. The exposure time controlled here is generated by stacking (averaging) multiple frames as needed to obtain the specified exposure time. Those individual frames are controlled by the FPS, AVERAGE, STACK, and EXPTIME keywords. From Kyle: If you want to tweak an exposure setting, I recommend MAGIQ use the EXPTIME keyword as its preferred knob. This will translate to changing the number of frames averaged together. You can also choose to stack frames, but I doubt that will be necessary. Notice how EXPTIME remains unchanged when I change the STACK keyword: [klanclos@kpffiuserver ~]$ gshow -s kpfguide fps average stack exptime FPS = 100.0000 frames/second AVERAGE = 100 frames STACK = 1 averaged frames EXPTIME = 1.000000 seconds [klanclos@kpffiuserver ~]$ modify -s kpfguide stack=2 setting stack = 2 (wait) [klanclos@kpffiuserver ~]$ gshow -s kpfguide fps average stack exptime FPS = 100.0000 frames/second AVERAGE = 50 frames STACK = 2 averaged frames EXPTIME = 1.000000 seconds ...but if I change AVERAGE, EXPTIME reflects the change: [klanclos@kpffiuserver ~]$ modify -s kpfguide average=20 setting average = 20 (wait) [klanclos@kpffiuserver ~]$ gshow -s kpfguide fps average stack exptime FPS = 100.0000 frames/second AVERAGE = 20 frames STACK = 1 averaged frames EXPTIME = 0.200000 seconds Stick to changing EXPTIME and you won't have to worry about it. Changing the frames per second is not recommended, because the tip/tilt system will be consuming this image stream, and it needs to retain full control of what an individual frame looks like. Args: exptime (float): The exposure time in seconds. KTL Keywords Used: - `kpfguide.EXPTIME` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'exptime' , value_min = 0 ) @classmethod def perform ( cls , args , logger , cfg ): exptimekw = ktl . cache ( 'kpfguide' , 'EXPTIME' ) exptime = args . get ( 'exptime' ) exptimekw . write ( exptime ) @classmethod def post_condition ( cls , args , logger , cfg ): exptol = cfg . getfloat ( 'tolerances' , 'guider_exptime_tolerance' , fallback = 0.01 ) exptimekw = ktl . cache ( 'kpfguide' , 'EXPTIME' ) exptimeread = exptimekw . read ( binary = True ) exptime = args . get ( 'exptime' ) expr = ( f '($kpfguide.EXPTIME >= { exptime - exptol } ) and ' \\ f '($kpfguide.EXPTIME <= { exptime + exptol } )' ) success = ktl . waitFor ( expr , timeout = exptimeread + 1 ) if not success : raise FailedToReachDestination ( exptimekw . read (), exptime ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'exptime' , type = float , help = 'The exposure time in seconds' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetGuiderExpTime"},{"location":"scripts/SetGuiderFPS/","text":"SetGuiderFPS Bases: KPFTranslatorFunction Set the guider FPS (frames per second) via the kpfguide.FPS keyword. Parameters: GuideFPS ( float ) \u2013 Number of frames per second. KTL Keywords Used: kpfguide.FPS Source code in kpf/guider/SetGuiderFPS.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class SetGuiderFPS ( KPFTranslatorFunction ): '''Set the guider FPS (frames per second) via the kpfguide.FPS keyword. Args: GuideFPS (float): Number of frames per second. KTL Keywords Used: - `kpfguide.FPS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'GuideFPS' , value_min = 0.0001 , value_max = 400 ) return True @classmethod def perform ( cls , args , logger , cfg ): fpskw = ktl . cache ( 'kpfguide' , 'FPS' ) fps = args . get ( 'GuideFPS' ) log . debug ( f 'Setting guider FPS to { fps } ' ) fpskw . write ( fps ) @classmethod def post_condition ( cls , args , logger , cfg ): fpstol = cfg . getfloat ( 'tolerances' , 'guider_fps_tolerance' , fallback = 0.01 ) fpskw = ktl . cache ( 'kpfguide' , 'FPS' ) fps = args . get ( 'GuideFPS' ) expr = ( f '($kpfguide.FPS >= { fps - fpstol } ) and ' \\ f '($kpfguide.FPS <= { fps + fpstol } )' ) success = ktl . waitFor ( expr , timeout = 1 ) if not success : raise FailedToReachDestination ( fpskw . read (), fps ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'GuideFPS' , type = float , help = 'The frames per second (FPS)' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetGuiderFPS"},{"location":"scripts/SetGuiderFPS/#setguiderfps","text":"Bases: KPFTranslatorFunction Set the guider FPS (frames per second) via the kpfguide.FPS keyword. Parameters: GuideFPS ( float ) \u2013 Number of frames per second. KTL Keywords Used: kpfguide.FPS Source code in kpf/guider/SetGuiderFPS.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class SetGuiderFPS ( KPFTranslatorFunction ): '''Set the guider FPS (frames per second) via the kpfguide.FPS keyword. Args: GuideFPS (float): Number of frames per second. KTL Keywords Used: - `kpfguide.FPS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'GuideFPS' , value_min = 0.0001 , value_max = 400 ) return True @classmethod def perform ( cls , args , logger , cfg ): fpskw = ktl . cache ( 'kpfguide' , 'FPS' ) fps = args . get ( 'GuideFPS' ) log . debug ( f 'Setting guider FPS to { fps } ' ) fpskw . write ( fps ) @classmethod def post_condition ( cls , args , logger , cfg ): fpstol = cfg . getfloat ( 'tolerances' , 'guider_fps_tolerance' , fallback = 0.01 ) fpskw = ktl . cache ( 'kpfguide' , 'FPS' ) fps = args . get ( 'GuideFPS' ) expr = ( f '($kpfguide.FPS >= { fps - fpstol } ) and ' \\ f '($kpfguide.FPS <= { fps + fpstol } )' ) success = ktl . waitFor ( expr , timeout = 1 ) if not success : raise FailedToReachDestination ( fpskw . read (), fps ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'GuideFPS' , type = float , help = 'The frames per second (FPS)' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetGuiderFPS"},{"location":"scripts/SetGuiderGain/","text":"SetGuiderGain Bases: KPFTranslatorFunction Set the guider gain via the kpfguide.GAIN keyword. Parameters: GuideCamGain ( str ) \u2013 The desired gain. Allowed values: high, medium, or low. KTL Keywords Used: kpfguide.GAIN Source code in kpf/guider/SetGuiderGain.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 class SetGuiderGain ( KPFTranslatorFunction ): '''Set the guider gain via the kpfguide.GAIN keyword. Args: GuideCamGain (str): The desired gain. Allowed values: high, medium, or low. KTL Keywords Used: - `kpfguide.GAIN` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'GuideCamGain' , allowed_values = [ 'high' , 'medium' , 'low' ]) @classmethod def perform ( cls , args , logger , cfg ): gainkw = ktl . cache ( 'kpfguide' , 'GAIN' ) gain = args . get ( 'GuideCamGain' ) log . debug ( f 'Setting guider gain to { gain } ' ) gainkw . write ( gain ) @classmethod def post_condition ( cls , args , logger , cfg ): gainkw = ktl . cache ( 'kpfguide' , 'GAIN' ) gain = args . get ( 'GuideCamGain' ) expr = ( f \"($kpfguide.GAIN == ' { gain } ')\" ) success = ktl . waitFor ( expr , timeout = 1 ) if not success : raise FailedToReachDestination ( gainkw . read (), gain ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'GuideCamGain' , type = str , choices = [ 'high' , 'medium' , 'low' ], help = 'The gain' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetGuiderGain"},{"location":"scripts/SetGuiderGain/#setguidergain","text":"Bases: KPFTranslatorFunction Set the guider gain via the kpfguide.GAIN keyword. Parameters: GuideCamGain ( str ) \u2013 The desired gain. Allowed values: high, medium, or low. KTL Keywords Used: kpfguide.GAIN Source code in kpf/guider/SetGuiderGain.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 class SetGuiderGain ( KPFTranslatorFunction ): '''Set the guider gain via the kpfguide.GAIN keyword. Args: GuideCamGain (str): The desired gain. Allowed values: high, medium, or low. KTL Keywords Used: - `kpfguide.GAIN` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'GuideCamGain' , allowed_values = [ 'high' , 'medium' , 'low' ]) @classmethod def perform ( cls , args , logger , cfg ): gainkw = ktl . cache ( 'kpfguide' , 'GAIN' ) gain = args . get ( 'GuideCamGain' ) log . debug ( f 'Setting guider gain to { gain } ' ) gainkw . write ( gain ) @classmethod def post_condition ( cls , args , logger , cfg ): gainkw = ktl . cache ( 'kpfguide' , 'GAIN' ) gain = args . get ( 'GuideCamGain' ) expr = ( f \"($kpfguide.GAIN == ' { gain } ')\" ) success = ktl . waitFor ( expr , timeout = 1 ) if not success : raise FailedToReachDestination ( gainkw . read (), gain ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'GuideCamGain' , type = str , choices = [ 'high' , 'medium' , 'low' ], help = 'The gain' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetGuiderGain"},{"location":"scripts/SetGuiderOutdir/","text":"SetGuiderOutdir Bases: KPFTranslatorFunction Set the value of the kpfguide.OUTDIR keyword Parameters: outdir ( str ) \u2013 The desired output path. KTL Keywords Used: kpfguide.OUTDIR Source code in kpf/guider/SetGuiderOutdir.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 class SetGuiderOutdir ( KPFTranslatorFunction ): '''Set the value of the kpfguide.OUTDIR keyword Args: outdir (str): The desired output path. KTL Keywords Used: - `kpfguide.OUTDIR` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'outdir' ) @classmethod def perform ( cls , args , logger , cfg ): newoutdir = Path ( args . get ( 'outdir' )) . expanduser () . absolute () kpfguide = ktl . cache ( 'kpfguide' ) kpfguide [ 'OUTDIR' ] . write ( f \" { newoutdir } \" ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'outdir' , type = str , help = 'The desired output path' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetGuiderOutdir"},{"location":"scripts/SetGuiderOutdir/#setguideroutdir","text":"Bases: KPFTranslatorFunction Set the value of the kpfguide.OUTDIR keyword Parameters: outdir ( str ) \u2013 The desired output path. KTL Keywords Used: kpfguide.OUTDIR Source code in kpf/guider/SetGuiderOutdir.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 class SetGuiderOutdir ( KPFTranslatorFunction ): '''Set the value of the kpfguide.OUTDIR keyword Args: outdir (str): The desired output path. KTL Keywords Used: - `kpfguide.OUTDIR` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'outdir' ) @classmethod def perform ( cls , args , logger , cfg ): newoutdir = Path ( args . get ( 'outdir' )) . expanduser () . absolute () kpfguide = ktl . cache ( 'kpfguide' ) kpfguide [ 'OUTDIR' ] . write ( f \" { newoutdir } \" ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'outdir' , type = str , help = 'The desired output path' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetGuiderOutdir"},{"location":"scripts/SetLFCtoAstroComb/","text":"SetLFCtoAstroComb Bases: KPFTranslatorFunction Set the Laser Frequency Comb (LFC) to \"AstroComb\" mode. This should be used during operation of the LFC. KTL Keywords Used: kpfcal.OPERATIONMODE kpfmon.HB_MENLOSTA Scripts Called: kpf.calbench.WaitForLFCReady Source code in kpf/calbench/SetLFCtoAstroComb.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class SetLFCtoAstroComb ( KPFTranslatorFunction ): '''Set the Laser Frequency Comb (LFC) to \"AstroComb\" mode. This should be used during operation of the LFC. KTL Keywords Used: - `kpfcal.OPERATIONMODE` - `kpfmon.HB_MENLOSTA` Scripts Called: - `kpf.calbench.WaitForLFCReady` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): heartbeat = ktl . cache ( 'kpfmon' , 'HB_MENLOSTA' ) hb_success = heartbeat . waitFor ( '== \"OK\"' , timeout = 3 ) if hb_success is False : raise FailedPreCondition ( f \"Menlo heartbeat is not OK: { heartbeat . read () } \" ) lfc_mode = ktl . cache ( 'kpfcal' , 'OPERATIONMODE' ) . read () if lfc_mode not in [ 'AstroComb' , 'StandbyHigh' ]: raise FailedPreCondition ( f \"LFC must be in AstroComb or StandbyHigh: { lfc_mode } \" ) @classmethod def perform ( cls , args , logger , cfg ): lfc_mode = ktl . cache ( 'kpfcal' , 'OPERATIONMODE' ) log . info ( 'Setting LFC to AstroComb' ) lfc_mode . write ( 'AstroComb' ) time_shim = cfg . getfloat ( 'times' , 'LFC_shim_time' , fallback = 10 ) time . sleep ( time_shim ) @classmethod def post_condition ( cls , args , logger , cfg ): success = WaitForLFCReady . execute ({}) if success is not True : raise FailedPostCondition ( 'LFC did not reach expected state' )","title":"SetLFCtoAstroComb"},{"location":"scripts/SetLFCtoAstroComb/#setlfctoastrocomb","text":"Bases: KPFTranslatorFunction Set the Laser Frequency Comb (LFC) to \"AstroComb\" mode. This should be used during operation of the LFC. KTL Keywords Used: kpfcal.OPERATIONMODE kpfmon.HB_MENLOSTA Scripts Called: kpf.calbench.WaitForLFCReady Source code in kpf/calbench/SetLFCtoAstroComb.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class SetLFCtoAstroComb ( KPFTranslatorFunction ): '''Set the Laser Frequency Comb (LFC) to \"AstroComb\" mode. This should be used during operation of the LFC. KTL Keywords Used: - `kpfcal.OPERATIONMODE` - `kpfmon.HB_MENLOSTA` Scripts Called: - `kpf.calbench.WaitForLFCReady` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): heartbeat = ktl . cache ( 'kpfmon' , 'HB_MENLOSTA' ) hb_success = heartbeat . waitFor ( '== \"OK\"' , timeout = 3 ) if hb_success is False : raise FailedPreCondition ( f \"Menlo heartbeat is not OK: { heartbeat . read () } \" ) lfc_mode = ktl . cache ( 'kpfcal' , 'OPERATIONMODE' ) . read () if lfc_mode not in [ 'AstroComb' , 'StandbyHigh' ]: raise FailedPreCondition ( f \"LFC must be in AstroComb or StandbyHigh: { lfc_mode } \" ) @classmethod def perform ( cls , args , logger , cfg ): lfc_mode = ktl . cache ( 'kpfcal' , 'OPERATIONMODE' ) log . info ( 'Setting LFC to AstroComb' ) lfc_mode . write ( 'AstroComb' ) time_shim = cfg . getfloat ( 'times' , 'LFC_shim_time' , fallback = 10 ) time . sleep ( time_shim ) @classmethod def post_condition ( cls , args , logger , cfg ): success = WaitForLFCReady . execute ({}) if success is not True : raise FailedPostCondition ( 'LFC did not reach expected state' )","title":"SetLFCtoAstroComb"},{"location":"scripts/SetLFCtoStandbyHigh/","text":"SetLFCtoStandbyHigh Bases: KPFTranslatorFunction Set the Laser Frequency Comb (LFC) to \"StandbyHigh\" mode. This is the mode which should be set after operation of the LFC for science is complete. KTL Keywords Used: kpfcal.OPERATIONMODE kpfmon.HB_MENLOSTA kpfmon.LFCREADYSTA Source code in kpf/calbench/SetLFCtoStandbyHigh.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 class SetLFCtoStandbyHigh ( KPFTranslatorFunction ): '''Set the Laser Frequency Comb (LFC) to \"StandbyHigh\" mode. This is the mode which should be set after operation of the LFC for science is complete. KTL Keywords Used: - `kpfcal.OPERATIONMODE` - `kpfmon.HB_MENLOSTA` - `kpfmon.LFCREADYSTA` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): heartbeat = ktl . cache ( 'kpfmon' , 'HB_MENLOSTA' ) success = heartbeat . waitFor ( '== \"OK\"' , timeout = 3 ) if success is False : raise FailedPreCondition ( f \"Menlo heartbeat is not OK: { heartbeat . read () } \" ) lfc_mode = ktl . cache ( 'kpfcal' , 'OPERATIONMODE' ) . read () if lfc_mode not in [ 'AstroComb' , 'StandbyHigh' ]: raise FailedPreCondition ( f \"LFC must be in AstroComb: { lfc_mode } \" ) @classmethod def perform ( cls , args , logger , cfg ): lfc_mode = ktl . cache ( 'kpfcal' , 'OPERATIONMODE' ) log . info ( 'Setting LFC to StandbyHigh' ) lfc_mode . write ( 'StandbyHigh' ) time_shim = cfg . getfloat ( 'times' , 'LFC_shim_time' , fallback = 10 ) time . sleep ( time_shim ) @classmethod def post_condition ( cls , args , logger , cfg ): LFCready = ktl . cache ( 'kpfmon' , 'LFCREADYSTA' ) timeout = cfg . getfloat ( 'times' , 'LFC_startup_time' , fallback = 60 ) success = LFCready . waitFor ( '== \"OK\"' , timeout = timeout ) if success is not True : raise FailedPostCondition ( 'kpfmon.LFCREADYSTA is not OK' )","title":"SetLFCtoStandbyHigh"},{"location":"scripts/SetLFCtoStandbyHigh/#setlfctostandbyhigh","text":"Bases: KPFTranslatorFunction Set the Laser Frequency Comb (LFC) to \"StandbyHigh\" mode. This is the mode which should be set after operation of the LFC for science is complete. KTL Keywords Used: kpfcal.OPERATIONMODE kpfmon.HB_MENLOSTA kpfmon.LFCREADYSTA Source code in kpf/calbench/SetLFCtoStandbyHigh.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 class SetLFCtoStandbyHigh ( KPFTranslatorFunction ): '''Set the Laser Frequency Comb (LFC) to \"StandbyHigh\" mode. This is the mode which should be set after operation of the LFC for science is complete. KTL Keywords Used: - `kpfcal.OPERATIONMODE` - `kpfmon.HB_MENLOSTA` - `kpfmon.LFCREADYSTA` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): heartbeat = ktl . cache ( 'kpfmon' , 'HB_MENLOSTA' ) success = heartbeat . waitFor ( '== \"OK\"' , timeout = 3 ) if success is False : raise FailedPreCondition ( f \"Menlo heartbeat is not OK: { heartbeat . read () } \" ) lfc_mode = ktl . cache ( 'kpfcal' , 'OPERATIONMODE' ) . read () if lfc_mode not in [ 'AstroComb' , 'StandbyHigh' ]: raise FailedPreCondition ( f \"LFC must be in AstroComb: { lfc_mode } \" ) @classmethod def perform ( cls , args , logger , cfg ): lfc_mode = ktl . cache ( 'kpfcal' , 'OPERATIONMODE' ) log . info ( 'Setting LFC to StandbyHigh' ) lfc_mode . write ( 'StandbyHigh' ) time_shim = cfg . getfloat ( 'times' , 'LFC_shim_time' , fallback = 10 ) time . sleep ( time_shim ) @classmethod def post_condition ( cls , args , logger , cfg ): LFCready = ktl . cache ( 'kpfmon' , 'LFCREADYSTA' ) timeout = cfg . getfloat ( 'times' , 'LFC_startup_time' , fallback = 60 ) success = LFCready . waitFor ( '== \"OK\"' , timeout = timeout ) if success is not True : raise FailedPostCondition ( 'kpfmon.LFCREADYSTA is not OK' )","title":"SetLFCtoStandbyHigh"},{"location":"scripts/SetMasterBiasToDefault/","text":"SetMasterBiasToDefault Bases: KPFTranslatorFunction Sets the master bias file for the exposure meter to the default value KTL Keywords Used: kpf_expmeter.BIAS_FILE Source code in kpf/expmeter/SetMasterBiasToDefault.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class SetMasterBiasToDefault ( KPFTranslatorFunction ): '''Sets the master bias file for the exposure meter to the default value KTL Keywords Used: - `kpf_expmeter.BIAS_FILE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) default_file = '/kroot/rel/default/data/kpf_expmeter/full_bias.fits' log . debug ( f \"Setting master bias file to { default_file } \" ) kpf_expmeter [ 'BIAS_FILE' ] . write ( default_file ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"SetMasterBiasToDefault"},{"location":"scripts/SetMasterBiasToDefault/#setmasterbiastodefault","text":"Bases: KPFTranslatorFunction Sets the master bias file for the exposure meter to the default value KTL Keywords Used: kpf_expmeter.BIAS_FILE Source code in kpf/expmeter/SetMasterBiasToDefault.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class SetMasterBiasToDefault ( KPFTranslatorFunction ): '''Sets the master bias file for the exposure meter to the default value KTL Keywords Used: - `kpf_expmeter.BIAS_FILE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) default_file = '/kroot/rel/default/data/kpf_expmeter/full_bias.fits' log . debug ( f \"Setting master bias file to { default_file } \" ) kpf_expmeter [ 'BIAS_FILE' ] . write ( default_file ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"SetMasterBiasToDefault"},{"location":"scripts/SetND/","text":"SetND Bases: KPFTranslatorFunction Set the filter in the ND1 & ND2 filter wheels via the kpfcal.ND1POS and kpfcal.ND2POS keywords. Parameters: CalND1 ( str ) \u2013 The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: OD 0.1 , OD 1.0 , OD 1.3 , OD 2.0 , OD 3.0 , OD 4.0 CalND2 ( str ) \u2013 The neutral density filter to put in the first filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: OD 0.1 , OD 0.3 , OD 0.5 , OD 0.8 , OD 1.0 , OD 4.0 wait ( bool ) \u2013 Wait for move to complete before returning? default: True Scripts Called: kpf.calbench.SetND1 kpf.calbench.SetND2 Source code in kpf/calbench/SetND.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetND ( KPFTranslatorFunction ): '''Set the filter in the ND1 & ND2 filter wheels via the `kpfcal.ND1POS` and `kpfcal.ND2POS` keywords. Args: CalND1 (str): The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: `OD 0.1`, `OD 1.0`, `OD 1.3`, `OD 2.0`, `OD 3.0`, `OD 4.0` CalND2 (str): The neutral density filter to put in the first filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: `OD 0.1`, `OD 0.3`, `OD 0.5`, `OD 0.8`, `OD 1.0`, `OD 4.0` wait (bool): Wait for move to complete before returning? default: True Scripts Called: - `kpf.calbench.SetND1` - `kpf.calbench.SetND2` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): SetND1 . execute ( args ) SetND2 . execute ( args ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalND1' , type = str , choices = [ \"OD 0.1\" , \"OD 1.0\" , \"OD 1.3\" , \"OD 2.0\" , \"OD 3.0\" , \"OD 4.0\" ], help = 'ND1 Filter to use.' ) parser . add_argument ( 'CalND2' , type = str , choices = [ \"OD 0.1\" , \"OD 0.3\" , \"OD 0.5\" , \"OD 0.8\" , \"OD 1.0\" , \"OD 4.0\" ], help = 'ND2 Filter to use.' ) parser . add_argument ( \"--nowait\" , dest = \"wait\" , default = True , action = \"store_false\" , help = \"Send move and return immediately?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetND"},{"location":"scripts/SetND/#setnd","text":"Bases: KPFTranslatorFunction Set the filter in the ND1 & ND2 filter wheels via the kpfcal.ND1POS and kpfcal.ND2POS keywords. Parameters: CalND1 ( str ) \u2013 The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: OD 0.1 , OD 1.0 , OD 1.3 , OD 2.0 , OD 3.0 , OD 4.0 CalND2 ( str ) \u2013 The neutral density filter to put in the first filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: OD 0.1 , OD 0.3 , OD 0.5 , OD 0.8 , OD 1.0 , OD 4.0 wait ( bool ) \u2013 Wait for move to complete before returning? default: True Scripts Called: kpf.calbench.SetND1 kpf.calbench.SetND2 Source code in kpf/calbench/SetND.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetND ( KPFTranslatorFunction ): '''Set the filter in the ND1 & ND2 filter wheels via the `kpfcal.ND1POS` and `kpfcal.ND2POS` keywords. Args: CalND1 (str): The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: `OD 0.1`, `OD 1.0`, `OD 1.3`, `OD 2.0`, `OD 3.0`, `OD 4.0` CalND2 (str): The neutral density filter to put in the first filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: `OD 0.1`, `OD 0.3`, `OD 0.5`, `OD 0.8`, `OD 1.0`, `OD 4.0` wait (bool): Wait for move to complete before returning? default: True Scripts Called: - `kpf.calbench.SetND1` - `kpf.calbench.SetND2` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): SetND1 . execute ( args ) SetND2 . execute ( args ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalND1' , type = str , choices = [ \"OD 0.1\" , \"OD 1.0\" , \"OD 1.3\" , \"OD 2.0\" , \"OD 3.0\" , \"OD 4.0\" ], help = 'ND1 Filter to use.' ) parser . add_argument ( 'CalND2' , type = str , choices = [ \"OD 0.1\" , \"OD 0.3\" , \"OD 0.5\" , \"OD 0.8\" , \"OD 1.0\" , \"OD 4.0\" ], help = 'ND2 Filter to use.' ) parser . add_argument ( \"--nowait\" , dest = \"wait\" , default = True , action = \"store_false\" , help = \"Send move and return immediately?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetND"},{"location":"scripts/SetND1/","text":"SetND1 Bases: KPFTranslatorFunction Set the filter in the ND1 filter wheel (the one at the output of the octagon) via the kpfcal.ND1POS keyword. Parameters: CalND1 ( str ) \u2013 The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: OD 0.1 , OD 1.0 , OD 1.3 , OD 2.0 , OD 3.0 , OD 4.0 wait ( bool ) \u2013 Wait for move to complete before returning? default: True KTL Keywords Used: kpfcal.ND1POS Source code in kpf/calbench/SetND1.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetND1 ( KPFTranslatorFunction ): '''Set the filter in the ND1 filter wheel (the one at the output of the octagon) via the `kpfcal.ND1POS` keyword. Args: CalND1 (str): The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: `OD 0.1`, `OD 1.0`, `OD 1.3`, `OD 2.0`, `OD 3.0`, `OD 4.0` wait (bool): Wait for move to complete before returning? default: True KTL Keywords Used: - `kpfcal.ND1POS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'ND1POS' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) check_input ( args , 'CalND1' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): target = args . get ( 'CalND1' ) log . debug ( f \"Setting ND1POS to { target } \" ) kpfcal = ktl . cache ( 'kpfcal' ) kpfcal [ 'ND1POS' ] . write ( target , wait = args . get ( 'wait' , True )) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'nd_move_time' , fallback = 20 ) ND1target = args . get ( 'CalND1' ) ND1POS = ktl . cache ( 'kpfcal' , 'ND1POS' ) if ND1POS . waitFor ( f \"== ' { ND1target } '\" , timeout = timeout ) == False : raise FailedToReachDestination ( ND1POS . read (), ND1target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalND1' , type = str , choices = [ \"OD 0.1\" , \"OD 1.0\" , \"OD 1.3\" , \"OD 2.0\" , \"OD 3.0\" , \"OD 4.0\" ], help = 'ND1 Filter to use.' ) parser . add_argument ( \"--nowait\" , dest = \"wait\" , default = True , action = \"store_false\" , help = \"Send move and return immediately?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetND1"},{"location":"scripts/SetND1/#setnd1","text":"Bases: KPFTranslatorFunction Set the filter in the ND1 filter wheel (the one at the output of the octagon) via the kpfcal.ND1POS keyword. Parameters: CalND1 ( str ) \u2013 The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: OD 0.1 , OD 1.0 , OD 1.3 , OD 2.0 , OD 3.0 , OD 4.0 wait ( bool ) \u2013 Wait for move to complete before returning? default: True KTL Keywords Used: kpfcal.ND1POS Source code in kpf/calbench/SetND1.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetND1 ( KPFTranslatorFunction ): '''Set the filter in the ND1 filter wheel (the one at the output of the octagon) via the `kpfcal.ND1POS` keyword. Args: CalND1 (str): The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: `OD 0.1`, `OD 1.0`, `OD 1.3`, `OD 2.0`, `OD 3.0`, `OD 4.0` wait (bool): Wait for move to complete before returning? default: True KTL Keywords Used: - `kpfcal.ND1POS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'ND1POS' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) check_input ( args , 'CalND1' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): target = args . get ( 'CalND1' ) log . debug ( f \"Setting ND1POS to { target } \" ) kpfcal = ktl . cache ( 'kpfcal' ) kpfcal [ 'ND1POS' ] . write ( target , wait = args . get ( 'wait' , True )) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'nd_move_time' , fallback = 20 ) ND1target = args . get ( 'CalND1' ) ND1POS = ktl . cache ( 'kpfcal' , 'ND1POS' ) if ND1POS . waitFor ( f \"== ' { ND1target } '\" , timeout = timeout ) == False : raise FailedToReachDestination ( ND1POS . read (), ND1target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalND1' , type = str , choices = [ \"OD 0.1\" , \"OD 1.0\" , \"OD 1.3\" , \"OD 2.0\" , \"OD 3.0\" , \"OD 4.0\" ], help = 'ND1 Filter to use.' ) parser . add_argument ( \"--nowait\" , dest = \"wait\" , default = True , action = \"store_false\" , help = \"Send move and return immediately?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetND1"},{"location":"scripts/SetND2/","text":"SetND2 Bases: KPFTranslatorFunction Set the filter in the ND2 filter wheel (the one at the output of the octagon) via the kpfcal.ND2POS keyword. Parameters: CalND2 ( str ) \u2013 The neutral density filter to put in the first filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: OD 0.1 , OD 0.3 , OD 0.5 , OD 0.8 , OD 1.0 , OD 4.0 wait ( bool ) \u2013 Wait for move to complete before returning? default: True KTL Keywords Used: kpfcal.ND2POS Source code in kpf/calbench/SetND2.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetND2 ( KPFTranslatorFunction ): '''Set the filter in the ND2 filter wheel (the one at the output of the octagon) via the `kpfcal.ND2POS` keyword. Args: CalND2 (str): The neutral density filter to put in the first filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: `OD 0.1`, `OD 0.3`, `OD 0.5`, `OD 0.8`, `OD 1.0`, `OD 4.0` wait (bool): Wait for move to complete before returning? default: True KTL Keywords Used: - `kpfcal.ND2POS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'ND2POS' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) check_input ( args , 'CalND2' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): target = args . get ( 'CalND2' ) log . debug ( f \"Setting ND2POS to { target } \" ) kpfcal = ktl . cache ( 'kpfcal' ) kpfcal [ 'ND2POS' ] . write ( target , wait = args . get ( 'wait' , True )) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'nd_move_time' , fallback = 20 ) ND2target = args . get ( 'CalND2' ) ND2POS = ktl . cache ( 'kpfcal' , 'ND2POS' ) if ND2POS . waitFor ( f \"== ' { ND2target } '\" , timeout = timeout ) == False : raise FailedToReachDestination ( ND2POS . read (), ND2target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalND2' , type = str , choices = [ \"OD 0.1\" , \"OD 0.3\" , \"OD 0.5\" , \"OD 0.8\" , \"OD 1.0\" , \"OD 4.0\" ], help = 'ND2 Filter to use.' ) parser . add_argument ( \"--nowait\" , dest = \"wait\" , default = True , action = \"store_false\" , help = \"Send move and return immediately?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetND2"},{"location":"scripts/SetND2/#setnd2","text":"Bases: KPFTranslatorFunction Set the filter in the ND2 filter wheel (the one at the output of the octagon) via the kpfcal.ND2POS keyword. Parameters: CalND2 ( str ) \u2013 The neutral density filter to put in the first filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: OD 0.1 , OD 0.3 , OD 0.5 , OD 0.8 , OD 1.0 , OD 4.0 wait ( bool ) \u2013 Wait for move to complete before returning? default: True KTL Keywords Used: kpfcal.ND2POS Source code in kpf/calbench/SetND2.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetND2 ( KPFTranslatorFunction ): '''Set the filter in the ND2 filter wheel (the one at the output of the octagon) via the `kpfcal.ND2POS` keyword. Args: CalND2 (str): The neutral density filter to put in the first filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: `OD 0.1`, `OD 0.3`, `OD 0.5`, `OD 0.8`, `OD 1.0`, `OD 4.0` wait (bool): Wait for move to complete before returning? default: True KTL Keywords Used: - `kpfcal.ND2POS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'ND2POS' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) check_input ( args , 'CalND2' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): target = args . get ( 'CalND2' ) log . debug ( f \"Setting ND2POS to { target } \" ) kpfcal = ktl . cache ( 'kpfcal' ) kpfcal [ 'ND2POS' ] . write ( target , wait = args . get ( 'wait' , True )) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'nd_move_time' , fallback = 20 ) ND2target = args . get ( 'CalND2' ) ND2POS = ktl . cache ( 'kpfcal' , 'ND2POS' ) if ND2POS . waitFor ( f \"== ' { ND2target } '\" , timeout = timeout ) == False : raise FailedToReachDestination ( ND2POS . read (), ND2target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalND2' , type = str , choices = [ \"OD 0.1\" , \"OD 0.3\" , \"OD 0.5\" , \"OD 0.8\" , \"OD 1.0\" , \"OD 4.0\" ], help = 'ND2 Filter to use.' ) parser . add_argument ( \"--nowait\" , dest = \"wait\" , default = True , action = \"store_false\" , help = \"Send move and return immediately?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetND2"},{"location":"scripts/SetObject/","text":"SetObject Bases: KPFTranslatorFunction Sets the OBJECT keyword for the science detectors in the kpfexpose keyword service. ARGS: :Object: str The desired object keyword value. Source code in kpf/spectrograph/SetObject.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 class SetObject ( KPFTranslatorFunction ): '''Sets the OBJECT keyword for the science detectors in the kpfexpose keyword service. ARGS: ===== :Object: `str` The desired object keyword value. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) obj = args . get ( 'Object' , '' ) if obj is None : obj = '' log . debug ( f \"Setting OBJECT to ' { obj } '\" ) kpfexpose [ 'OBJECT' ] . write ( obj ) time_shim = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.1 ) time . sleep ( time_shim ) @classmethod def post_condition ( cls , args , logger , cfg ): obj = args . get ( 'Object' , '' ) if obj is None : obj = '' timeout = cfg . getfloat ( 'times' , 'kpfexpose_response_time' , fallback = 1 ) expr = f \"($kpfexpose.OBJECT == ' { obj } ')\" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : objectkw = ktl . cache ( 'kpfexpose' , 'OBJECT' ) raise FailedToReachDestination ( objectkw . read (), obj ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'Object' , type = str , help = 'The OBJECT keyword' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetObject"},{"location":"scripts/SetObject/#setobject","text":"Bases: KPFTranslatorFunction Sets the OBJECT keyword for the science detectors in the kpfexpose keyword service.","title":"SetObject"},{"location":"scripts/SetObject/#kpf.spectrograph.SetObject.SetObject--args","text":":Object: str The desired object keyword value. Source code in kpf/spectrograph/SetObject.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 class SetObject ( KPFTranslatorFunction ): '''Sets the OBJECT keyword for the science detectors in the kpfexpose keyword service. ARGS: ===== :Object: `str` The desired object keyword value. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) obj = args . get ( 'Object' , '' ) if obj is None : obj = '' log . debug ( f \"Setting OBJECT to ' { obj } '\" ) kpfexpose [ 'OBJECT' ] . write ( obj ) time_shim = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.1 ) time . sleep ( time_shim ) @classmethod def post_condition ( cls , args , logger , cfg ): obj = args . get ( 'Object' , '' ) if obj is None : obj = '' timeout = cfg . getfloat ( 'times' , 'kpfexpose_response_time' , fallback = 1 ) expr = f \"($kpfexpose.OBJECT == ' { obj } ')\" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : objectkw = ktl . cache ( 'kpfexpose' , 'OBJECT' ) raise FailedToReachDestination ( objectkw . read (), obj ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'Object' , type = str , help = 'The OBJECT keyword' ) return super () . add_cmdline_args ( parser , cfg )","title":"ARGS:"},{"location":"scripts/SetObserver/","text":"SetObserver Bases: KPFTranslatorFunction Sets the OBSERVER keyword for the science detectors in the kpfexpose keyword service. ARGS: :observer: str The desired value of the OBSERVER keyword. Source code in kpf/spectrograph/SetObserver.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class SetObserver ( KPFTranslatorFunction ): '''Sets the OBSERVER keyword for the science detectors in the kpfexpose keyword service. ARGS: ===== :observer: `str` The desired value of the OBSERVER keyword. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'observer' ) @classmethod def perform ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) observer = args . get ( 'observer' ) log . info ( f \"Setting OBSERVER to { observer } \" ) kpfexpose [ 'OBSERVER' ] . write ( observer ) time_shim = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.1 ) time . sleep ( time_shim ) @classmethod def post_condition ( cls , args , logger , cfg ): observer = args . get ( 'observer' ) timeout = cfg . getfloat ( 'times' , 'kpfexpose_response_time' , fallback = 1 ) expr = f '($kpfexpose.OBSERVER == \" { observer } \")' success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : observerkw = ktl . cache ( 'kpfexpose' , 'OBSERVER' ) raise FailedToReachDestination ( observerkw . read () . strip (), observer . strip ()) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'observer' , type = str , help = 'The OBSERVER keyword' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetObserver"},{"location":"scripts/SetObserver/#setobserver","text":"Bases: KPFTranslatorFunction Sets the OBSERVER keyword for the science detectors in the kpfexpose keyword service.","title":"SetObserver"},{"location":"scripts/SetObserver/#kpf.spectrograph.SetObserver.SetObserver--args","text":":observer: str The desired value of the OBSERVER keyword. Source code in kpf/spectrograph/SetObserver.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class SetObserver ( KPFTranslatorFunction ): '''Sets the OBSERVER keyword for the science detectors in the kpfexpose keyword service. ARGS: ===== :observer: `str` The desired value of the OBSERVER keyword. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'observer' ) @classmethod def perform ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) observer = args . get ( 'observer' ) log . info ( f \"Setting OBSERVER to { observer } \" ) kpfexpose [ 'OBSERVER' ] . write ( observer ) time_shim = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.1 ) time . sleep ( time_shim ) @classmethod def post_condition ( cls , args , logger , cfg ): observer = args . get ( 'observer' ) timeout = cfg . getfloat ( 'times' , 'kpfexpose_response_time' , fallback = 1 ) expr = f '($kpfexpose.OBSERVER == \" { observer } \")' success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : observerkw = ktl . cache ( 'kpfexpose' , 'OBSERVER' ) raise FailedToReachDestination ( observerkw . read () . strip (), observer . strip ()) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'observer' , type = str , help = 'The OBSERVER keyword' ) return super () . add_cmdline_args ( parser , cfg )","title":"ARGS:"},{"location":"scripts/SetObserverFromSchedule/","text":"SetObserverFromSchedule Bases: KPFTranslatorFunction Look up the telescope schedule and try to determine the observer names based on the current date and the scheduled programs. If only one KPF program is on the schedule, the script will use that to set the observer names. If multiple programs are on the schedule, it will use the progname input (see below) or query the user if no progname is given. ARGS: :progname: str The program name to set if a choice is needed. Source code in kpf/utils/SetObserverFromSchedule.py 17 18 19 20 21 22 23 24 25 26 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 class SetObserverFromSchedule ( KPFTranslatorFunction ): '''Look up the telescope schedule and try to determine the observer names based on the current date and the scheduled programs. If only one KPF program is on the schedule, the script will use that to set the observer names. If multiple programs are on the schedule, it will use the progname input (see below) or query the user if no progname is given. ARGS: ===== :progname: `str` The program name to set if a choice is needed. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): utnow = datetime . utcnow () date = utnow - timedelta ( days = 1 ) date_str = date . strftime ( '%Y-%m- %d ' ) KPF_programs = [ s for s in get_schedule ( date_str , 1 ) if s [ 'Instrument' ] == 'KPF' ] nKPFprograms = len ( KPF_programs ) log . debug ( f \"Found { nKPFprograms } KPF programs in schedule for tonight\" ) project_codes = [ p [ 'ProjCode' ] for p in KPF_programs ] # Look at the schedule to find programs scheduled for tonight if nKPFprograms == 0 : log . warning ( f \"No KPF programs found on schedule\" ) progname = None elif nKPFprograms == 1 : progname = KPF_programs [ 0 ][ 'ProjCode' ] elif nKPFprograms > 1 : progname = args . get ( 'progname' , None ) if progname is None : print () print ( f \"########################################\" ) print ( f \" Found { nKPFprograms } KPF programs for tonight:\" ) for project_code in project_codes : print ( f \" { project_code } \" ) print ( f \" Please enter the program ID for your observations:\" ) print ( f \"########################################\" ) print () progname = input () if progname . strip () not in project_codes : log . warning ( f \"Project code { progname } not on schedule\" ) # Set the program if progname is None : time . sleep ( 0.5 ) # try time shim for log line print () print ( f \" Please enter the program ID for your observations:\" ) print () progname = input () if progname == '' : log . info ( 'No progname specified' ) else : SetProgram . execute ({ 'progname' : progname }) # Set Observers this_program = [ p for p in KPF_programs if p [ 'ProjCode' ] == progname ] if len ( this_program ) > 0 : observers = this_program [ 0 ][ 'Observers' ] else : print () print ( f \" Please enter the observer names:\" ) print () observers = input () log . info ( f \"Setting observer list: { observers } \" ) SetObserver . execute ({ 'observer' : observers }) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"SetObserverFromSchedule"},{"location":"scripts/SetObserverFromSchedule/#setobserverfromschedule","text":"Bases: KPFTranslatorFunction Look up the telescope schedule and try to determine the observer names based on the current date and the scheduled programs. If only one KPF program is on the schedule, the script will use that to set the observer names. If multiple programs are on the schedule, it will use the progname input (see below) or query the user if no progname is given.","title":"SetObserverFromSchedule"},{"location":"scripts/SetObserverFromSchedule/#kpf.utils.SetObserverFromSchedule.SetObserverFromSchedule--args","text":":progname: str The program name to set if a choice is needed. Source code in kpf/utils/SetObserverFromSchedule.py 17 18 19 20 21 22 23 24 25 26 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 class SetObserverFromSchedule ( KPFTranslatorFunction ): '''Look up the telescope schedule and try to determine the observer names based on the current date and the scheduled programs. If only one KPF program is on the schedule, the script will use that to set the observer names. If multiple programs are on the schedule, it will use the progname input (see below) or query the user if no progname is given. ARGS: ===== :progname: `str` The program name to set if a choice is needed. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): utnow = datetime . utcnow () date = utnow - timedelta ( days = 1 ) date_str = date . strftime ( '%Y-%m- %d ' ) KPF_programs = [ s for s in get_schedule ( date_str , 1 ) if s [ 'Instrument' ] == 'KPF' ] nKPFprograms = len ( KPF_programs ) log . debug ( f \"Found { nKPFprograms } KPF programs in schedule for tonight\" ) project_codes = [ p [ 'ProjCode' ] for p in KPF_programs ] # Look at the schedule to find programs scheduled for tonight if nKPFprograms == 0 : log . warning ( f \"No KPF programs found on schedule\" ) progname = None elif nKPFprograms == 1 : progname = KPF_programs [ 0 ][ 'ProjCode' ] elif nKPFprograms > 1 : progname = args . get ( 'progname' , None ) if progname is None : print () print ( f \"########################################\" ) print ( f \" Found { nKPFprograms } KPF programs for tonight:\" ) for project_code in project_codes : print ( f \" { project_code } \" ) print ( f \" Please enter the program ID for your observations:\" ) print ( f \"########################################\" ) print () progname = input () if progname . strip () not in project_codes : log . warning ( f \"Project code { progname } not on schedule\" ) # Set the program if progname is None : time . sleep ( 0.5 ) # try time shim for log line print () print ( f \" Please enter the program ID for your observations:\" ) print () progname = input () if progname == '' : log . info ( 'No progname specified' ) else : SetProgram . execute ({ 'progname' : progname }) # Set Observers this_program = [ p for p in KPF_programs if p [ 'ProjCode' ] == progname ] if len ( this_program ) > 0 : observers = this_program [ 0 ][ 'Observers' ] else : print () print ( f \" Please enter the observer names:\" ) print () observers = input () log . info ( f \"Setting observer list: { observers } \" ) SetObserver . execute ({ 'observer' : observers }) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"ARGS:"},{"location":"scripts/SetOutdirs/","text":"SetOutdirs Bases: KPFTranslatorFunction Set output directories for all detectors based on the current date. ARGS: None Source code in kpf/utils/SetOutdirs.py 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 class SetOutdirs ( KPFTranslatorFunction ): '''Set output directories for all detectors based on the current date. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): log . info ( f \"SetOutdirs invoked\" ) utnow = datetime . utcnow () date = utnow - timedelta ( days = 1 ) date_str = date . strftime ( '%Y%b %d ' ) . lower () outdir = Path ( f \"/s/sdata1701/ { os . getlogin () } / { date_str } \" ) magiq_outdir = Path ( f \"/s/sdata1701/kpfguide/ { date_str } \" ) log . debug ( f \"base outdir: { outdir } \" ) log . debug ( f \"magiq outdir: { magiq_outdir } \" ) if args . get ( 'CRED2' , True ) is True : log . info ( f \"Setting guider OUTDIR to { magiq_outdir } \" ) guide_outdir = ktl . cache ( 'kpfguide' , 'OUTDIR' ) try : guide_outdir . write ( f \" { magiq_outdir } \" ) except Exception as e : log . error ( f \"ERROR setting guider outdir\" ) log . error ( e ) log . info ( f \"Setting guider TRIGOUTDIR to { outdir / 'CRED2' } \" ) trig_outdir = ktl . cache ( 'kpfguide' , 'TRIGOUTDIR' ) try : trig_outdir . write ( f \" { outdir / 'CRED2' } \" ) except Exception as e : log . error ( f \"ERROR setting guider TRIGOUTDIR\" ) log . error ( e ) kpffvc = ktl . cache ( 'kpffvc' ) if args . get ( 'FVC1' , True ) is True : log . info ( f \"Setting FVC1 OUTDIR to { outdir / 'FVC1' } \" ) try : kpffvc [ 'SCIOUTDIR' ] . write ( f \" { outdir / 'FVC1' } \" ) except Exception as e : log . error ( f \"ERROR setting SCI FVC outdir\" ) log . error ( e ) if args . get ( 'FVC2' , True ) is True : log . info ( f \"Setting FVC2 OUTDIR to { outdir / 'FVC2' } \" ) try : kpffvc [ 'CAHKOUTDIR' ] . write ( f \" { outdir / 'FVC2' } \" ) except Exception as e : log . error ( f \"ERROR setting CAHK FVC outdir\" ) log . error ( e ) if args . get ( 'FVC3' , True ) is True : log . info ( f \"Setting FVC3 OUTDIR to { outdir / 'FVC3' } \" ) try : kpffvc [ 'CALOUTDIR' ] . write ( f \" { outdir / 'FVC3' } \" ) except Exception as e : log . error ( f \"ERROR setting CAL FVC outdir\" ) log . error ( e ) if args . get ( 'FVC4' , True ) is True : log . info ( f \"Setting FVC4 OUTDIR to { outdir / 'FVC4' } \" ) try : kpffvc [ 'EXTOUTDIR' ] . write ( f \" { outdir / 'FVC4' } \" ) except Exception as e : log . error ( f \"ERROR setting EXT FVC outdir\" ) log . error ( e ) if args . get ( 'ExpMeter' , True ) is True : expmeter_outdir = outdir / 'ExpMeter' log . info ( f \"Setting exposure meter DATADIR to { expmeter_outdir } \" ) kpf_expmeter_outdir = ktl . cache ( 'kpf_expmeter' , 'DATADIR' ) try : kpf_expmeter_outdir . write ( f \" { expmeter_outdir } \" ) except Exception as e : log . error ( f \"ERROR setting ExpMeter outdir\" ) log . error ( e ) if args . get ( 'CaHK' , True ) is True : cahk_outdir = outdir / 'CaHK' log . info ( f \"Setting CaHK RECORDDIR to { cahk_outdir } \" ) kpf_hk_outdir = ktl . cache ( 'kpf_hk' , 'RECORDDIR' ) try : kpf_hk_outdir . write ( f \" { cahk_outdir } \" ) except Exception as e : log . error ( f \"ERROR setting CaHK outdir\" ) log . error ( e ) if args . get ( 'Green' , True ) is True : green_outdir = outdir / 'Green' log . info ( f \"Setting Green FITSDIR to { green_outdir } \" ) kpfgreen_outdir = ktl . cache ( 'kpfgreen' , 'FITSDIR' ) try : kpfgreen_outdir . write ( f \" { green_outdir } \" ) except Exception as e : log . error ( f \"ERROR setting Green outdir\" ) log . error ( e ) if args . get ( 'Red' , True ) is True : red_outdir = outdir / 'Red' log . info ( f \"Setting Red FITSDIR to { red_outdir } \" ) kpfred_outdir = ktl . cache ( 'kpfred' , 'FITSDIR' ) try : kpfred_outdir . write ( f \" { red_outdir } \" ) except Exception as e : log . error ( f \"ERROR setting Red outdir\" ) log . error ( e ) if args . get ( 'L0' , True ) is True : L0_outdir = outdir / 'L0' log . info ( f \"Setting kpfasemble OUTDIR to { L0_outdir } \" ) kpfassemble_outdir = ktl . cache ( 'kpfassemble' , 'OUTDIR' ) try : kpfassemble_outdir . write ( f \" { L0_outdir } \" ) except Exception as e : log . error ( f \"ERROR setting kpfasemble outdir\" ) log . error ( e ) @classmethod def post_condition ( cls , args , logger , cfg ): utnow = datetime . utcnow () date = utnow - timedelta ( days = 1 ) date_str = date . strftime ( '%Y%b %d ' ) . lower () outdir = Path ( f \"/s/sdata1701/ { os . getlogin () } / { date_str } \" ) tests = [] if args . get ( 'CRED2' , True ) is True : expr = f \"$kpfguide.OUTDIR == '/s/sdata1701/kpfguide'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'CRED2' , True ) is True : expr = f \"$kpfguide.TRIGOUTDIR == ' { outdir } /CRED2'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'FVC1' , True ) is True : expr = f \"$kpffvc.SCIOUTDIR == ' { outdir } /FVC1'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'FVC2' , True ) is True : expr = f \"$kpffvc.CAHKOUTDIR == ' { outdir } /FVC2'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'FVC3' , True ) is True : expr = f \"$kpffvc.CALOUTDIR == ' { outdir } /FVC3'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'FVC4' , False ) is True : expr = f \"$kpffvc.EXTOUTDIR == ' { outdir } /FVC4'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'ExpMeter' , True ) is True : expr = f \"$kpf_expmeter.DATADIR == ' { outdir } /ExpMeter'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'CaHK' , True ) is True : expr = f \"$kpf_hk.RECORDDIR == ' { outdir } /CaHK'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'Green' , True ) is True : expr = f \"$kpfgreen.FITSDIR == ' { outdir } /Green'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'Red' , True ) is True : expr = f \"$kpfred.FITSDIR == ' { outdir } /Red'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'L0' , True ) is True : expr = f \"$kpfassemble.OUTDIR == ' { outdir } /L0'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) return np . all ( np . array ( tests )) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser = cls . _add_bool_arg ( parser , 'CRED2' , 'Set CRED2 OUTDIR (kpfguide.OUTDIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'FVC1' , 'Set FVC1 OUTDIR (kpffvc.SCIOUTDIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'FVC2' , 'Set FVC2 OUTDIR (kpffvc.CAHKOUTDIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'FVC3' , 'Set FVC3 OUTDIR (kpffvc.CALOUTDIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'FVC4' , 'Set FVC4 OUTDIR (kpffvc.EXTOUTDIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'ExpMeter' , 'Set ExpMeter OUTDIR (kpf_expmeter.DATADIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'CaHK' , 'Set CaHK OUTDIR (kpf_hk.RECORDDIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'Green' , 'Set Green OUTDIR (kpfgreen.FITSDIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'Red' , 'Set Red OUTDIR (kpfred.FITSDIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'L0' , 'Set Red OUTDIR (kpfassemble.OUTDIR)?' , default = True ) return super () . add_cmdline_args ( parser , cfg )","title":"SetOutdirs"},{"location":"scripts/SetOutdirs/#setoutdirs","text":"Bases: KPFTranslatorFunction Set output directories for all detectors based on the current date.","title":"SetOutdirs"},{"location":"scripts/SetOutdirs/#kpf.utils.SetOutdirs.SetOutdirs--args","text":"None Source code in kpf/utils/SetOutdirs.py 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 class SetOutdirs ( KPFTranslatorFunction ): '''Set output directories for all detectors based on the current date. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): log . info ( f \"SetOutdirs invoked\" ) utnow = datetime . utcnow () date = utnow - timedelta ( days = 1 ) date_str = date . strftime ( '%Y%b %d ' ) . lower () outdir = Path ( f \"/s/sdata1701/ { os . getlogin () } / { date_str } \" ) magiq_outdir = Path ( f \"/s/sdata1701/kpfguide/ { date_str } \" ) log . debug ( f \"base outdir: { outdir } \" ) log . debug ( f \"magiq outdir: { magiq_outdir } \" ) if args . get ( 'CRED2' , True ) is True : log . info ( f \"Setting guider OUTDIR to { magiq_outdir } \" ) guide_outdir = ktl . cache ( 'kpfguide' , 'OUTDIR' ) try : guide_outdir . write ( f \" { magiq_outdir } \" ) except Exception as e : log . error ( f \"ERROR setting guider outdir\" ) log . error ( e ) log . info ( f \"Setting guider TRIGOUTDIR to { outdir / 'CRED2' } \" ) trig_outdir = ktl . cache ( 'kpfguide' , 'TRIGOUTDIR' ) try : trig_outdir . write ( f \" { outdir / 'CRED2' } \" ) except Exception as e : log . error ( f \"ERROR setting guider TRIGOUTDIR\" ) log . error ( e ) kpffvc = ktl . cache ( 'kpffvc' ) if args . get ( 'FVC1' , True ) is True : log . info ( f \"Setting FVC1 OUTDIR to { outdir / 'FVC1' } \" ) try : kpffvc [ 'SCIOUTDIR' ] . write ( f \" { outdir / 'FVC1' } \" ) except Exception as e : log . error ( f \"ERROR setting SCI FVC outdir\" ) log . error ( e ) if args . get ( 'FVC2' , True ) is True : log . info ( f \"Setting FVC2 OUTDIR to { outdir / 'FVC2' } \" ) try : kpffvc [ 'CAHKOUTDIR' ] . write ( f \" { outdir / 'FVC2' } \" ) except Exception as e : log . error ( f \"ERROR setting CAHK FVC outdir\" ) log . error ( e ) if args . get ( 'FVC3' , True ) is True : log . info ( f \"Setting FVC3 OUTDIR to { outdir / 'FVC3' } \" ) try : kpffvc [ 'CALOUTDIR' ] . write ( f \" { outdir / 'FVC3' } \" ) except Exception as e : log . error ( f \"ERROR setting CAL FVC outdir\" ) log . error ( e ) if args . get ( 'FVC4' , True ) is True : log . info ( f \"Setting FVC4 OUTDIR to { outdir / 'FVC4' } \" ) try : kpffvc [ 'EXTOUTDIR' ] . write ( f \" { outdir / 'FVC4' } \" ) except Exception as e : log . error ( f \"ERROR setting EXT FVC outdir\" ) log . error ( e ) if args . get ( 'ExpMeter' , True ) is True : expmeter_outdir = outdir / 'ExpMeter' log . info ( f \"Setting exposure meter DATADIR to { expmeter_outdir } \" ) kpf_expmeter_outdir = ktl . cache ( 'kpf_expmeter' , 'DATADIR' ) try : kpf_expmeter_outdir . write ( f \" { expmeter_outdir } \" ) except Exception as e : log . error ( f \"ERROR setting ExpMeter outdir\" ) log . error ( e ) if args . get ( 'CaHK' , True ) is True : cahk_outdir = outdir / 'CaHK' log . info ( f \"Setting CaHK RECORDDIR to { cahk_outdir } \" ) kpf_hk_outdir = ktl . cache ( 'kpf_hk' , 'RECORDDIR' ) try : kpf_hk_outdir . write ( f \" { cahk_outdir } \" ) except Exception as e : log . error ( f \"ERROR setting CaHK outdir\" ) log . error ( e ) if args . get ( 'Green' , True ) is True : green_outdir = outdir / 'Green' log . info ( f \"Setting Green FITSDIR to { green_outdir } \" ) kpfgreen_outdir = ktl . cache ( 'kpfgreen' , 'FITSDIR' ) try : kpfgreen_outdir . write ( f \" { green_outdir } \" ) except Exception as e : log . error ( f \"ERROR setting Green outdir\" ) log . error ( e ) if args . get ( 'Red' , True ) is True : red_outdir = outdir / 'Red' log . info ( f \"Setting Red FITSDIR to { red_outdir } \" ) kpfred_outdir = ktl . cache ( 'kpfred' , 'FITSDIR' ) try : kpfred_outdir . write ( f \" { red_outdir } \" ) except Exception as e : log . error ( f \"ERROR setting Red outdir\" ) log . error ( e ) if args . get ( 'L0' , True ) is True : L0_outdir = outdir / 'L0' log . info ( f \"Setting kpfasemble OUTDIR to { L0_outdir } \" ) kpfassemble_outdir = ktl . cache ( 'kpfassemble' , 'OUTDIR' ) try : kpfassemble_outdir . write ( f \" { L0_outdir } \" ) except Exception as e : log . error ( f \"ERROR setting kpfasemble outdir\" ) log . error ( e ) @classmethod def post_condition ( cls , args , logger , cfg ): utnow = datetime . utcnow () date = utnow - timedelta ( days = 1 ) date_str = date . strftime ( '%Y%b %d ' ) . lower () outdir = Path ( f \"/s/sdata1701/ { os . getlogin () } / { date_str } \" ) tests = [] if args . get ( 'CRED2' , True ) is True : expr = f \"$kpfguide.OUTDIR == '/s/sdata1701/kpfguide'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'CRED2' , True ) is True : expr = f \"$kpfguide.TRIGOUTDIR == ' { outdir } /CRED2'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'FVC1' , True ) is True : expr = f \"$kpffvc.SCIOUTDIR == ' { outdir } /FVC1'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'FVC2' , True ) is True : expr = f \"$kpffvc.CAHKOUTDIR == ' { outdir } /FVC2'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'FVC3' , True ) is True : expr = f \"$kpffvc.CALOUTDIR == ' { outdir } /FVC3'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'FVC4' , False ) is True : expr = f \"$kpffvc.EXTOUTDIR == ' { outdir } /FVC4'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'ExpMeter' , True ) is True : expr = f \"$kpf_expmeter.DATADIR == ' { outdir } /ExpMeter'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'CaHK' , True ) is True : expr = f \"$kpf_hk.RECORDDIR == ' { outdir } /CaHK'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'Green' , True ) is True : expr = f \"$kpfgreen.FITSDIR == ' { outdir } /Green'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'Red' , True ) is True : expr = f \"$kpfred.FITSDIR == ' { outdir } /Red'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'L0' , True ) is True : expr = f \"$kpfassemble.OUTDIR == ' { outdir } /L0'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) return np . all ( np . array ( tests )) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser = cls . _add_bool_arg ( parser , 'CRED2' , 'Set CRED2 OUTDIR (kpfguide.OUTDIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'FVC1' , 'Set FVC1 OUTDIR (kpffvc.SCIOUTDIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'FVC2' , 'Set FVC2 OUTDIR (kpffvc.CAHKOUTDIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'FVC3' , 'Set FVC3 OUTDIR (kpffvc.CALOUTDIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'FVC4' , 'Set FVC4 OUTDIR (kpffvc.EXTOUTDIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'ExpMeter' , 'Set ExpMeter OUTDIR (kpf_expmeter.DATADIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'CaHK' , 'Set CaHK OUTDIR (kpf_hk.RECORDDIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'Green' , 'Set Green OUTDIR (kpfgreen.FITSDIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'Red' , 'Set Red OUTDIR (kpfred.FITSDIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'L0' , 'Set Red OUTDIR (kpfassemble.OUTDIR)?' , default = True ) return super () . add_cmdline_args ( parser , cfg )","title":"ARGS:"},{"location":"scripts/SetProgram/","text":"SetProgram Bases: KPFTranslatorFunction Sets the PROGNAME keyword for the science detectors in the kpfexpose keyword service. ARGS: :progname: str The program ID to set. Source code in kpf/spectrograph/SetProgram.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 class SetProgram ( KPFTranslatorFunction ): '''Sets the PROGNAME keyword for the science detectors in the kpfexpose keyword service. ARGS: ===== :progname: `str` The program ID to set. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'progname' ) @classmethod def perform ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) progname = args . get ( 'progname' ) log . debug ( 'Waiting for kpfexpose to be ready' ) WaitForReady . execute ({}) log . info ( f \"Setting PROGNAME to ' { progname } '\" ) kpfexpose [ 'PROGNAME' ] . write ( progname ) time_shim = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.1 ) time . sleep ( time_shim ) @classmethod def post_condition ( cls , args , logger , cfg ): progname = args . get ( 'progname' ) timeout = cfg . getfloat ( 'times' , 'kpfexpose_response_time' , fallback = 1 ) expr = f \"($kpfexpose.PROGNAME == ' { progname } ')\" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : prognamekw = ktl . cache ( 'kpfexpose' , 'PROGNAME' ) raise FailedToReachDestination ( prognamekw . read (), progname ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'progname' , type = str , help = 'The PROGNAME keyword' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetProgram"},{"location":"scripts/SetProgram/#setprogram","text":"Bases: KPFTranslatorFunction Sets the PROGNAME keyword for the science detectors in the kpfexpose keyword service.","title":"SetProgram"},{"location":"scripts/SetProgram/#kpf.spectrograph.SetProgram.SetProgram--args","text":":progname: str The program ID to set. Source code in kpf/spectrograph/SetProgram.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 class SetProgram ( KPFTranslatorFunction ): '''Sets the PROGNAME keyword for the science detectors in the kpfexpose keyword service. ARGS: ===== :progname: `str` The program ID to set. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'progname' ) @classmethod def perform ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) progname = args . get ( 'progname' ) log . debug ( 'Waiting for kpfexpose to be ready' ) WaitForReady . execute ({}) log . info ( f \"Setting PROGNAME to ' { progname } '\" ) kpfexpose [ 'PROGNAME' ] . write ( progname ) time_shim = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.1 ) time . sleep ( time_shim ) @classmethod def post_condition ( cls , args , logger , cfg ): progname = args . get ( 'progname' ) timeout = cfg . getfloat ( 'times' , 'kpfexpose_response_time' , fallback = 1 ) expr = f \"($kpfexpose.PROGNAME == ' { progname } ')\" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : prognamekw = ktl . cache ( 'kpfexpose' , 'PROGNAME' ) raise FailedToReachDestination ( prognamekw . read (), progname ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'progname' , type = str , help = 'The PROGNAME keyword' ) return super () . add_cmdline_args ( parser , cfg )","title":"ARGS:"},{"location":"scripts/SetReadModeFast/","text":"SetReadModeFast Bases: KPFTranslatorFunction Configure both detectors to fast read mode by changing the ACF files they are using. ARGS: None Source code in kpf/spectrograph/SetReadModeFast.py 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetReadModeFast ( KPFTranslatorFunction ): '''Configure both detectors to fast read mode by changing the ACF files they are using. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): green_mode , red_mode = QueryReadMode . execute ({}) if green_mode != 'fast' : msg = f 'Setting Green CCD read mode fast' log . info ( msg ) # Email to kpf_info try : SendEmail . execute ({ 'Subject' : msg , 'Message' : msg }) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) kpfgreen = ktl . cache ( 'kpfgreen' ) green_fast_file = cfg . get ( 'acf_files' , 'green_fast' ) green_ACFFILE = Path ( kpfgreen [ 'ACFFILE' ] . read ()) . stem if green_ACFFILE != green_fast_file : kpfgreen [ 'ACF' ] . write ( green_fast_file ) time . sleep ( 1 ) if red_mode != 'fast' : msg = f 'Setting Red CCD read mode fast' log . info ( msg ) # Email to kpf_info try : SendEmail . execute ({ 'Subject' : msg , 'Message' : msg }) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) kpfred = ktl . cache ( 'kpfred' ) red_fast_file = cfg . get ( 'acf_files' , 'red_fast' ) red_ACFFILE = Path ( kpfred [ 'ACFFILE' ] . read ()) . stem if red_ACFFILE != red_fast_file : kpfred [ 'ACF' ] . write ( red_fast_file ) time . sleep ( 1 ) @classmethod def post_condition ( cls , args , logger , cfg ): green_mode , red_mode = QueryReadMode . execute ({}) if green_mode != 'fast' or red_mode != 'fast' : raise FailedPostCondition ( f \"Read mode change failed\" )","title":"SetReadModeFast"},{"location":"scripts/SetReadModeFast/#setreadmodefast","text":"Bases: KPFTranslatorFunction Configure both detectors to fast read mode by changing the ACF files they are using.","title":"SetReadModeFast"},{"location":"scripts/SetReadModeFast/#kpf.spectrograph.SetReadModeFast.SetReadModeFast--args","text":"None Source code in kpf/spectrograph/SetReadModeFast.py 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetReadModeFast ( KPFTranslatorFunction ): '''Configure both detectors to fast read mode by changing the ACF files they are using. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): green_mode , red_mode = QueryReadMode . execute ({}) if green_mode != 'fast' : msg = f 'Setting Green CCD read mode fast' log . info ( msg ) # Email to kpf_info try : SendEmail . execute ({ 'Subject' : msg , 'Message' : msg }) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) kpfgreen = ktl . cache ( 'kpfgreen' ) green_fast_file = cfg . get ( 'acf_files' , 'green_fast' ) green_ACFFILE = Path ( kpfgreen [ 'ACFFILE' ] . read ()) . stem if green_ACFFILE != green_fast_file : kpfgreen [ 'ACF' ] . write ( green_fast_file ) time . sleep ( 1 ) if red_mode != 'fast' : msg = f 'Setting Red CCD read mode fast' log . info ( msg ) # Email to kpf_info try : SendEmail . execute ({ 'Subject' : msg , 'Message' : msg }) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) kpfred = ktl . cache ( 'kpfred' ) red_fast_file = cfg . get ( 'acf_files' , 'red_fast' ) red_ACFFILE = Path ( kpfred [ 'ACFFILE' ] . read ()) . stem if red_ACFFILE != red_fast_file : kpfred [ 'ACF' ] . write ( red_fast_file ) time . sleep ( 1 ) @classmethod def post_condition ( cls , args , logger , cfg ): green_mode , red_mode = QueryReadMode . execute ({}) if green_mode != 'fast' or red_mode != 'fast' : raise FailedPostCondition ( f \"Read mode change failed\" )","title":"ARGS:"},{"location":"scripts/SetReadModeNormal/","text":"SetReadModeNormal Bases: KPFTranslatorFunction Configure both detectors to normal read mode by changing the ACF files they are using. ARGS: None Source code in kpf/spectrograph/SetReadModeNormal.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetReadModeNormal ( KPFTranslatorFunction ): '''Configure both detectors to normal read mode by changing the ACF files they are using. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): green_mode , red_mode = QueryReadMode . execute ({}) if green_mode != 'normal' : msg = f 'Setting Green CCD read mode normal' log . info ( msg ) # Email to kpf_info try : SendEmail . execute ({ 'Subject' : msg , 'Message' : msg }) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) kpfgreen = ktl . cache ( 'kpfgreen' ) green_normal_file = cfg . get ( 'acf_files' , 'green_normal' ) green_ACFFILE = Path ( kpfgreen [ 'ACFFILE' ] . read ()) . stem if green_ACFFILE != green_normal_file : kpfgreen [ 'ACF' ] . write ( green_normal_file ) time . sleep ( 1 ) if red_mode != 'normal' : msg = f 'Setting Red CCD read mode normal' log . info ( msg ) # Email to kpf_info try : SendEmail . execute ({ 'Subject' : msg , 'Message' : msg }) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) kpfred = ktl . cache ( 'kpfred' ) red_normal_file = cfg . get ( 'acf_files' , 'red_normal' ) red_ACFFILE = Path ( kpfred [ 'ACFFILE' ] . read ()) . stem if red_ACFFILE != red_normal_file : kpfred [ 'ACF' ] . write ( red_normal_file ) time . sleep ( 1 ) @classmethod def post_condition ( cls , args , logger , cfg ): green_mode , red_mode = QueryReadMode . execute ({}) if green_mode != 'normal' or red_mode != 'normal' : raise FailedPostCondition ( f \"Read mode change failed\" )","title":"SetReadModeNormal"},{"location":"scripts/SetReadModeNormal/#setreadmodenormal","text":"Bases: KPFTranslatorFunction Configure both detectors to normal read mode by changing the ACF files they are using.","title":"SetReadModeNormal"},{"location":"scripts/SetReadModeNormal/#kpf.spectrograph.SetReadModeNormal.SetReadModeNormal--args","text":"None Source code in kpf/spectrograph/SetReadModeNormal.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetReadModeNormal ( KPFTranslatorFunction ): '''Configure both detectors to normal read mode by changing the ACF files they are using. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): green_mode , red_mode = QueryReadMode . execute ({}) if green_mode != 'normal' : msg = f 'Setting Green CCD read mode normal' log . info ( msg ) # Email to kpf_info try : SendEmail . execute ({ 'Subject' : msg , 'Message' : msg }) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) kpfgreen = ktl . cache ( 'kpfgreen' ) green_normal_file = cfg . get ( 'acf_files' , 'green_normal' ) green_ACFFILE = Path ( kpfgreen [ 'ACFFILE' ] . read ()) . stem if green_ACFFILE != green_normal_file : kpfgreen [ 'ACF' ] . write ( green_normal_file ) time . sleep ( 1 ) if red_mode != 'normal' : msg = f 'Setting Red CCD read mode normal' log . info ( msg ) # Email to kpf_info try : SendEmail . execute ({ 'Subject' : msg , 'Message' : msg }) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) kpfred = ktl . cache ( 'kpfred' ) red_normal_file = cfg . get ( 'acf_files' , 'red_normal' ) red_ACFFILE = Path ( kpfred [ 'ACFFILE' ] . read ()) . stem if red_ACFFILE != red_normal_file : kpfred [ 'ACF' ] . write ( red_normal_file ) time . sleep ( 1 ) @classmethod def post_condition ( cls , args , logger , cfg ): green_mode , red_mode = QueryReadMode . execute ({}) if green_mode != 'normal' or red_mode != 'normal' : raise FailedPostCondition ( f \"Read mode change failed\" )","title":"ARGS:"},{"location":"scripts/SetSimulCalSource/","text":"SetSimulCalSource Bases: KPFTranslatorFunction Set the slew cal and simultaneous calibration source. Valid names: EtalonFiber, U_gold, U_daily, Th_daily, Th_gold, LFCFiber ARGS: :calsource: The calibration source to use (must be one of Etalon, LFC, Th_daily, Th_gold, U_daily, U_gold). Source code in kpf/utils/SetSimulCalSource.py 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetSimulCalSource ( KPFTranslatorFunction ): '''Set the slew cal and simultaneous calibration source. Valid names: EtalonFiber, U_gold, U_daily, Th_daily, Th_gold, LFCFiber ARGS: ===== :calsource: The calibration source to use (must be one of Etalon, LFC, Th_daily, Th_gold, U_daily, U_gold). ''' @classmethod def pre_condition ( cls , args , logger , cfg ): valid_names = [ 'EtalonFiber' , 'U_gold' , 'U_daily' , 'Th_daily' , 'Th_gold' , 'LFCFiber' ] if args . get ( 'CalSource' , None ) not in valid_names : raise FailedPreCondition ( f \"calsource ' { calsource } ' must be one of { valid_names } \" ) @classmethod def perform ( cls , args , logger , cfg ): log . info ( f \"Setting simul cal / slew cal source\" ) calsource = args . get ( 'CalSource' ) kpfconfig = ktl . cache ( 'kpfconfig' ) slew_cal_file = Path ( f '/kroot/rel/default/data/obs/kpf/SlewCal_ { calsource } .yaml' ) if slew_cal_file . exists () is False : raise KPFException ( f 'The slew cal file for { calsource } does not exist' ) else : log . info ( f 'Writing kpfconfig.SIMULCALSOURCE = { calsource } ' ) kpfconfig [ 'SIMULCALSOURCE' ] . write ( calsource ) log . info ( f 'Writing kpfconfig.SLEWCALFILE = { slew_cal_file } ' ) kpfconfig [ 'SLEWCALFILE' ] . write ( f \" { slew_cal_file } \" ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalSource' , type = str , choices = [ 'EtalonFiber' , 'U_gold' , 'U_daily' , 'Th_daily' , 'Th_gold' , 'LFCFiber' ], help = 'Which lamp to use for simultaneous calibration and slew cals' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetSimulCalSource"},{"location":"scripts/SetSimulCalSource/#setsimulcalsource","text":"Bases: KPFTranslatorFunction Set the slew cal and simultaneous calibration source. Valid names: EtalonFiber, U_gold, U_daily, Th_daily, Th_gold, LFCFiber","title":"SetSimulCalSource"},{"location":"scripts/SetSimulCalSource/#kpf.utils.SetSimulCalSource.SetSimulCalSource--args","text":":calsource: The calibration source to use (must be one of Etalon, LFC, Th_daily, Th_gold, U_daily, U_gold). Source code in kpf/utils/SetSimulCalSource.py 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetSimulCalSource ( KPFTranslatorFunction ): '''Set the slew cal and simultaneous calibration source. Valid names: EtalonFiber, U_gold, U_daily, Th_daily, Th_gold, LFCFiber ARGS: ===== :calsource: The calibration source to use (must be one of Etalon, LFC, Th_daily, Th_gold, U_daily, U_gold). ''' @classmethod def pre_condition ( cls , args , logger , cfg ): valid_names = [ 'EtalonFiber' , 'U_gold' , 'U_daily' , 'Th_daily' , 'Th_gold' , 'LFCFiber' ] if args . get ( 'CalSource' , None ) not in valid_names : raise FailedPreCondition ( f \"calsource ' { calsource } ' must be one of { valid_names } \" ) @classmethod def perform ( cls , args , logger , cfg ): log . info ( f \"Setting simul cal / slew cal source\" ) calsource = args . get ( 'CalSource' ) kpfconfig = ktl . cache ( 'kpfconfig' ) slew_cal_file = Path ( f '/kroot/rel/default/data/obs/kpf/SlewCal_ { calsource } .yaml' ) if slew_cal_file . exists () is False : raise KPFException ( f 'The slew cal file for { calsource } does not exist' ) else : log . info ( f 'Writing kpfconfig.SIMULCALSOURCE = { calsource } ' ) kpfconfig [ 'SIMULCALSOURCE' ] . write ( calsource ) log . info ( f 'Writing kpfconfig.SLEWCALFILE = { slew_cal_file } ' ) kpfconfig [ 'SLEWCALFILE' ] . write ( f \" { slew_cal_file } \" ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalSource' , type = str , choices = [ 'EtalonFiber' , 'U_gold' , 'U_daily' , 'Th_daily' , 'Th_gold' , 'LFCFiber' ], help = 'Which lamp to use for simultaneous calibration and slew cals' ) return super () . add_cmdline_args ( parser , cfg )","title":"ARGS:"},{"location":"scripts/SetSourceSelectShutters/","text":"SetSourceSelectShutters Bases: KPFTranslatorFunction Opens and closes the source select shutters via the kpfexpose.SRC_SHUTTERS keyword. ARGS: :SSS_Science: bool Open the SciSelect shutter? (default=False) :SSS_Sky: bool Open the SkySelect shutter? (default=False) :SSS_CalSciSky: bool Open the Cal_SciSky shutter? (default=False) :SSS_SoCalSci: bool Open the SoCalSci shutter? (default=False) :SSS_SoCalCal: bool Open the SoCalCal shutter? (default=False) Source code in kpf/spectrograph/SetSourceSelectShutters.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetSourceSelectShutters ( KPFTranslatorFunction ): '''Opens and closes the source select shutters via the `kpfexpose.SRC_SHUTTERS` keyword. ARGS: ===== :SSS_Science: `bool` Open the SciSelect shutter? (default=False) :SSS_Sky: `bool` Open the SkySelect shutter? (default=False) :SSS_CalSciSky: `bool` Open the Cal_SciSky shutter? (default=False) :SSS_SoCalSci: `bool` Open the SoCalSci shutter? (default=False) :SSS_SoCalCal: `bool` Open the SoCalCal shutter? (default=False) ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): shutter_list = [] if args . get ( 'SSS_Science' , False ) is True : shutter_list . append ( 'SciSelect' ) if args . get ( 'SSS_Sky' , False ) is True : shutter_list . append ( 'SkySelect' ) if args . get ( 'SSS_SoCalSci' , False ) is True : shutter_list . append ( 'SoCalSci' ) if args . get ( 'SSS_SoCalCal' , False ) is True : shutter_list . append ( 'SoCalCal' ) if args . get ( 'SSS_CalSciSky' , False ) is True : shutter_list . append ( 'Cal_SciSky' ) shutters_string = ',' . join ( shutter_list ) log . debug ( f \"Setting source select shutters to ' { shutters_string } '\" ) kpfexpose = ktl . cache ( 'kpfexpose' ) kpfexpose [ 'SRC_SHUTTERS' ] . write ( shutters_string ) shim_time = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.1 ) sleep ( shim_time ) @classmethod def post_condition ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) timeshim = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.01 ) sleep ( timeshim ) shutters = kpfexpose [ 'SRC_SHUTTERS' ] . read () shutter_list = shutters . split ( ',' ) shutter_names = [( 'SciSelect' , 'SSS_Science' ), ( 'SkySelect' , 'SSS_Sky' ), ( 'SoCalSci' , 'SSS_SoCalSci' ), ( 'SoCalCal' , 'SSS_SoCalCal' ), ( 'Cal_SciSky' , 'SSS_CalSciSky' )] for shutter in shutter_names : shutter_status = shutter [ 0 ] in shutter_list shutter_target = args . get ( shutter [ 1 ], False ) if shutter_target != shutter_status : raise FailedToReachDestination ( shutter_status , shutter_target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--Science\" , \"--Sci\" , \"--science\" , \"--sci\" , dest = \"SSS_Science\" , default = False , action = \"store_true\" , help = \"Open the SciSelect shutter?\" ) parser . add_argument ( \"--Sky\" , \"--sky\" , dest = \"SSS_Sky\" , default = False , action = \"store_true\" , help = \"Open the SkySelect shutter?\" ) parser . add_argument ( \"--CalSciSky\" , dest = \"SSS_CalSciSky\" , default = False , action = \"store_true\" , help = \"Open the Cal_SciSky shutter?\" ) parser . add_argument ( \"--SoCalSci\" , dest = \"SSS_SoCalSci\" , default = False , action = \"store_true\" , help = \"Open the SoCalSci shutter?\" ) parser . add_argument ( \"--SoCalCal\" , dest = \"SSS_SoCalCal\" , default = False , action = \"store_true\" , help = \"Open the SoCalCal shutter?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetSourceSelectShutters"},{"location":"scripts/SetSourceSelectShutters/#setsourceselectshutters","text":"Bases: KPFTranslatorFunction Opens and closes the source select shutters via the kpfexpose.SRC_SHUTTERS keyword.","title":"SetSourceSelectShutters"},{"location":"scripts/SetSourceSelectShutters/#kpf.spectrograph.SetSourceSelectShutters.SetSourceSelectShutters--args","text":":SSS_Science: bool Open the SciSelect shutter? (default=False) :SSS_Sky: bool Open the SkySelect shutter? (default=False) :SSS_CalSciSky: bool Open the Cal_SciSky shutter? (default=False) :SSS_SoCalSci: bool Open the SoCalSci shutter? (default=False) :SSS_SoCalCal: bool Open the SoCalCal shutter? (default=False) Source code in kpf/spectrograph/SetSourceSelectShutters.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetSourceSelectShutters ( KPFTranslatorFunction ): '''Opens and closes the source select shutters via the `kpfexpose.SRC_SHUTTERS` keyword. ARGS: ===== :SSS_Science: `bool` Open the SciSelect shutter? (default=False) :SSS_Sky: `bool` Open the SkySelect shutter? (default=False) :SSS_CalSciSky: `bool` Open the Cal_SciSky shutter? (default=False) :SSS_SoCalSci: `bool` Open the SoCalSci shutter? (default=False) :SSS_SoCalCal: `bool` Open the SoCalCal shutter? (default=False) ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): shutter_list = [] if args . get ( 'SSS_Science' , False ) is True : shutter_list . append ( 'SciSelect' ) if args . get ( 'SSS_Sky' , False ) is True : shutter_list . append ( 'SkySelect' ) if args . get ( 'SSS_SoCalSci' , False ) is True : shutter_list . append ( 'SoCalSci' ) if args . get ( 'SSS_SoCalCal' , False ) is True : shutter_list . append ( 'SoCalCal' ) if args . get ( 'SSS_CalSciSky' , False ) is True : shutter_list . append ( 'Cal_SciSky' ) shutters_string = ',' . join ( shutter_list ) log . debug ( f \"Setting source select shutters to ' { shutters_string } '\" ) kpfexpose = ktl . cache ( 'kpfexpose' ) kpfexpose [ 'SRC_SHUTTERS' ] . write ( shutters_string ) shim_time = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.1 ) sleep ( shim_time ) @classmethod def post_condition ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) timeshim = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.01 ) sleep ( timeshim ) shutters = kpfexpose [ 'SRC_SHUTTERS' ] . read () shutter_list = shutters . split ( ',' ) shutter_names = [( 'SciSelect' , 'SSS_Science' ), ( 'SkySelect' , 'SSS_Sky' ), ( 'SoCalSci' , 'SSS_SoCalSci' ), ( 'SoCalCal' , 'SSS_SoCalCal' ), ( 'Cal_SciSky' , 'SSS_CalSciSky' )] for shutter in shutter_names : shutter_status = shutter [ 0 ] in shutter_list shutter_target = args . get ( shutter [ 1 ], False ) if shutter_target != shutter_status : raise FailedToReachDestination ( shutter_status , shutter_target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--Science\" , \"--Sci\" , \"--science\" , \"--sci\" , dest = \"SSS_Science\" , default = False , action = \"store_true\" , help = \"Open the SciSelect shutter?\" ) parser . add_argument ( \"--Sky\" , \"--sky\" , dest = \"SSS_Sky\" , default = False , action = \"store_true\" , help = \"Open the SkySelect shutter?\" ) parser . add_argument ( \"--CalSciSky\" , dest = \"SSS_CalSciSky\" , default = False , action = \"store_true\" , help = \"Open the Cal_SciSky shutter?\" ) parser . add_argument ( \"--SoCalSci\" , dest = \"SSS_SoCalSci\" , default = False , action = \"store_true\" , help = \"Open the SoCalSci shutter?\" ) parser . add_argument ( \"--SoCalCal\" , dest = \"SSS_SoCalCal\" , default = False , action = \"store_true\" , help = \"Open the SoCalCal shutter?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"ARGS:"},{"location":"scripts/SetTargetInfo/","text":"SetTargetInfo Bases: KPFTranslatorFunction Set the target info keywords based on the target information in the OB. ARGS OB : ( dict ) A fully specified observing block (OB) or at least the target components of an OB. Source code in kpf/utils/SetTargetInfo.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetTargetInfo ( KPFTranslatorFunction ): '''Set the target info keywords based on the target information in the OB. ### ARGS **OB**: (`dict`) A fully specified observing block (OB) or at least the target components of an OB. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , OB , logger , cfg ): log . info ( f \"Setting target parameters\" ) kpfconfig = ktl . cache ( 'kpfconfig' ) kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) dcs = ktl . cache ( 'dcs1' ) kpfconfig [ 'TARGET_NAME' ] . write ( OB . get ( 'TargetName' , '' )) kpfconfig [ 'TARGET_GAIA' ] . write ( OB . get ( 'GaiaID' , '' )) kpfconfig [ 'TARGET_2MASS' ] . write ( OB . get ( '2MASSID' , '' )) kpfconfig [ 'TARGET_GMAG' ] . write ( OB . get ( 'Gmag' , '' )) kpfconfig [ 'TARGET_JMAG' ] . write ( OB . get ( 'Jmag' , '' )) TARGET_TEFF = OB . get ( 'Teff' , 45000 ) try : kpf_expmeter [ 'TARGET_TEFF' ] . write ( float ( TARGET_TEFF )) except : log . warning ( f \"Unable to set kpf_expmeter.TARGET_TEFF to { TARGET_TEFF } ( { type ( TARGET_TEFF ) } )\" ) TARGPLAX = OB . get ( 'Parallax' , 0 ) try : dcs [ 'TARGPLAX' ] . write ( float ( TARGPLAX )) except : log . warning ( f \"Unable to set dcs.TARGPLAX to { TARGPLAX } ( { type ( TARGPLAX ) } )\" ) TARGRADV = OB . get ( 'RadialVelocity' , 0 ) try : dcs [ 'TARGRADV' ] . write ( float ( TARGRADV )) except : log . warning ( f \"Unable to set dcs.TARGRADV to { TARGRADV } ( { type ( TARGRADV ) } )\" ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"SetTargetInfo"},{"location":"scripts/SetTargetInfo/#settargetinfo","text":"Bases: KPFTranslatorFunction Set the target info keywords based on the target information in the OB.","title":"SetTargetInfo"},{"location":"scripts/SetTargetInfo/#kpf.utils.SetTargetInfo.SetTargetInfo--args","text":"OB : ( dict ) A fully specified observing block (OB) or at least the target components of an OB. Source code in kpf/utils/SetTargetInfo.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetTargetInfo ( KPFTranslatorFunction ): '''Set the target info keywords based on the target information in the OB. ### ARGS **OB**: (`dict`) A fully specified observing block (OB) or at least the target components of an OB. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , OB , logger , cfg ): log . info ( f \"Setting target parameters\" ) kpfconfig = ktl . cache ( 'kpfconfig' ) kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) dcs = ktl . cache ( 'dcs1' ) kpfconfig [ 'TARGET_NAME' ] . write ( OB . get ( 'TargetName' , '' )) kpfconfig [ 'TARGET_GAIA' ] . write ( OB . get ( 'GaiaID' , '' )) kpfconfig [ 'TARGET_2MASS' ] . write ( OB . get ( '2MASSID' , '' )) kpfconfig [ 'TARGET_GMAG' ] . write ( OB . get ( 'Gmag' , '' )) kpfconfig [ 'TARGET_JMAG' ] . write ( OB . get ( 'Jmag' , '' )) TARGET_TEFF = OB . get ( 'Teff' , 45000 ) try : kpf_expmeter [ 'TARGET_TEFF' ] . write ( float ( TARGET_TEFF )) except : log . warning ( f \"Unable to set kpf_expmeter.TARGET_TEFF to { TARGET_TEFF } ( { type ( TARGET_TEFF ) } )\" ) TARGPLAX = OB . get ( 'Parallax' , 0 ) try : dcs [ 'TARGPLAX' ] . write ( float ( TARGPLAX )) except : log . warning ( f \"Unable to set dcs.TARGPLAX to { TARGPLAX } ( { type ( TARGPLAX ) } )\" ) TARGRADV = OB . get ( 'RadialVelocity' , 0 ) try : dcs [ 'TARGRADV' ] . write ( float ( TARGRADV )) except : log . warning ( f \"Unable to set dcs.TARGRADV to { TARGRADV } ( { type ( TARGRADV ) } )\" ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"ARGS"},{"location":"scripts/SetTimedShutters/","text":"SetTimedShutters Bases: KPFTranslatorFunction Selects which timed shutters will be triggered by setting the kpfexpose.TIMED_SHUTTERS keyword value. ARGS: :TimedShutter_Scrambler: bool Open the TimedShutter_Scrambler shutter? (default=False) :TimedShutter_SimulCal: bool Open the TimedShutter_SimulCal shutter? (default=False) :TimedShutter_CaHK: bool Open the TimedShutter_CaHK shutter? (default=False) :TimedShutter_FlatField: bool Open the TimedShutter_FlatField shutter? (default=False) Source code in kpf/spectrograph/SetTimedShutters.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetTimedShutters ( KPFTranslatorFunction ): '''Selects which timed shutters will be triggered by setting the `kpfexpose.TIMED_SHUTTERS` keyword value. ARGS: ===== :TimedShutter_Scrambler: `bool` Open the TimedShutter_Scrambler shutter? (default=False) :TimedShutter_SimulCal: `bool` Open the TimedShutter_SimulCal shutter? (default=False) :TimedShutter_CaHK: `bool` Open the TimedShutter_CaHK shutter? (default=False) :TimedShutter_FlatField: `bool` Open the TimedShutter_FlatField shutter? (default=False) ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # Scrambler 2 SimulCal 3 FF_Fiber 4 Ca_HK timed_shutters_list = [] if args . get ( 'TimedShutter_Scrambler' , False ) is True : timed_shutters_list . append ( 'Scrambler' ) if args . get ( 'TimedShutter_SimulCal' , False ) is True : timed_shutters_list . append ( 'SimulCal' ) if args . get ( 'TimedShutter_FlatField' , False ) is True : timed_shutters_list . append ( 'FF_Fiber' ) if args . get ( 'TimedShutter_CaHK' , False ) is True : timed_shutters_list . append ( 'Ca_HK' ) timed_shutters_string = ',' . join ( timed_shutters_list ) log . debug ( f \"Setting timed shutters to ' { timed_shutters_string } '\" ) kpfexpose = ktl . cache ( 'kpfexpose' ) kpfexpose [ 'TIMED_TARG' ] . write ( timed_shutters_string ) shim_time = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.1 ) sleep ( shim_time ) @classmethod def post_condition ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) timeshim = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.01 ) sleep ( timeshim ) shutters = kpfexpose [ 'TIMED_TARG' ] . read () log . debug ( f \"TIMED_TARG: { shutters } \" ) shutter_list = shutters . split ( ',' ) shutter_names = [( 'Scrambler' , 'TimedShutter_Scrambler' ), ( 'SimulCal' , 'TimedShutter_SimulCal' ), ( 'FF_Fiber' , 'TimedShutter_FlatField' ), ( 'Ca_HK' , 'TimedShutter_CaHK' )] for shutter in shutter_names : shutter_status = shutter [ 0 ] in shutter_list shutter_target = args . get ( shutter [ 1 ], False ) if shutter_target != shutter_status : raise FailedToReachDestination ( shutter_status , shutter_target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--Scrambler\" , \"--scrambler\" , dest = \"TimedShutter_Scrambler\" , default = False , action = \"store_true\" , help = \"Open the Scrambler Timed Shutter during exposure?\" ) parser . add_argument ( \"--SimulCal\" , \"--simulcal\" , dest = \"TimedShutter_SimulCal\" , default = False , action = \"store_true\" , help = \"Open the SimulCal Timed Shutter during exposure?\" ) parser . add_argument ( \"--CaHK\" , \"--HK\" , \"--cahk\" , \"--hk\" , dest = \"TimedShutter_CaHK\" , default = False , action = \"store_true\" , help = \"Open the CaHK Timed Shutter during exposure?\" ) parser . add_argument ( \"--FlatField\" , \"--flatfield\" , dest = \"TimedShutter_FlatField\" , default = False , action = \"store_true\" , help = \"Open the FlatField Timed Shutter during exposure?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetTimedShutters"},{"location":"scripts/SetTimedShutters/#settimedshutters","text":"Bases: KPFTranslatorFunction Selects which timed shutters will be triggered by setting the kpfexpose.TIMED_SHUTTERS keyword value.","title":"SetTimedShutters"},{"location":"scripts/SetTimedShutters/#kpf.spectrograph.SetTimedShutters.SetTimedShutters--args","text":":TimedShutter_Scrambler: bool Open the TimedShutter_Scrambler shutter? (default=False) :TimedShutter_SimulCal: bool Open the TimedShutter_SimulCal shutter? (default=False) :TimedShutter_CaHK: bool Open the TimedShutter_CaHK shutter? (default=False) :TimedShutter_FlatField: bool Open the TimedShutter_FlatField shutter? (default=False) Source code in kpf/spectrograph/SetTimedShutters.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetTimedShutters ( KPFTranslatorFunction ): '''Selects which timed shutters will be triggered by setting the `kpfexpose.TIMED_SHUTTERS` keyword value. ARGS: ===== :TimedShutter_Scrambler: `bool` Open the TimedShutter_Scrambler shutter? (default=False) :TimedShutter_SimulCal: `bool` Open the TimedShutter_SimulCal shutter? (default=False) :TimedShutter_CaHK: `bool` Open the TimedShutter_CaHK shutter? (default=False) :TimedShutter_FlatField: `bool` Open the TimedShutter_FlatField shutter? (default=False) ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # Scrambler 2 SimulCal 3 FF_Fiber 4 Ca_HK timed_shutters_list = [] if args . get ( 'TimedShutter_Scrambler' , False ) is True : timed_shutters_list . append ( 'Scrambler' ) if args . get ( 'TimedShutter_SimulCal' , False ) is True : timed_shutters_list . append ( 'SimulCal' ) if args . get ( 'TimedShutter_FlatField' , False ) is True : timed_shutters_list . append ( 'FF_Fiber' ) if args . get ( 'TimedShutter_CaHK' , False ) is True : timed_shutters_list . append ( 'Ca_HK' ) timed_shutters_string = ',' . join ( timed_shutters_list ) log . debug ( f \"Setting timed shutters to ' { timed_shutters_string } '\" ) kpfexpose = ktl . cache ( 'kpfexpose' ) kpfexpose [ 'TIMED_TARG' ] . write ( timed_shutters_string ) shim_time = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.1 ) sleep ( shim_time ) @classmethod def post_condition ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) timeshim = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.01 ) sleep ( timeshim ) shutters = kpfexpose [ 'TIMED_TARG' ] . read () log . debug ( f \"TIMED_TARG: { shutters } \" ) shutter_list = shutters . split ( ',' ) shutter_names = [( 'Scrambler' , 'TimedShutter_Scrambler' ), ( 'SimulCal' , 'TimedShutter_SimulCal' ), ( 'FF_Fiber' , 'TimedShutter_FlatField' ), ( 'Ca_HK' , 'TimedShutter_CaHK' )] for shutter in shutter_names : shutter_status = shutter [ 0 ] in shutter_list shutter_target = args . get ( shutter [ 1 ], False ) if shutter_target != shutter_status : raise FailedToReachDestination ( shutter_status , shutter_target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--Scrambler\" , \"--scrambler\" , dest = \"TimedShutter_Scrambler\" , default = False , action = \"store_true\" , help = \"Open the Scrambler Timed Shutter during exposure?\" ) parser . add_argument ( \"--SimulCal\" , \"--simulcal\" , dest = \"TimedShutter_SimulCal\" , default = False , action = \"store_true\" , help = \"Open the SimulCal Timed Shutter during exposure?\" ) parser . add_argument ( \"--CaHK\" , \"--HK\" , \"--cahk\" , \"--hk\" , dest = \"TimedShutter_CaHK\" , default = False , action = \"store_true\" , help = \"Open the CaHK Timed Shutter during exposure?\" ) parser . add_argument ( \"--FlatField\" , \"--flatfield\" , dest = \"TimedShutter_FlatField\" , default = False , action = \"store_true\" , help = \"Open the FlatField Timed Shutter during exposure?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"ARGS:"},{"location":"scripts/SetTipTiltCalculations/","text":"SetTipTiltCalculations Bases: KPFTranslatorFunction Turn the tip tilt calculation software on or off. Parameters: calculations ( str ) \u2013 The desired state of the calculations. Allowed values: Active or Inactive KTL Keywords Used: kpfguide.TIPTILT_CALC Source code in kpf/fiu/SetTipTiltCalculations.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class SetTipTiltCalculations ( KPFTranslatorFunction ): '''Turn the tip tilt calculation software on or off. Args: calculations (str): The desired state of the calculations. Allowed values: Active or Inactive KTL Keywords Used: - `kpfguide.TIPTILT_CALC` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): allowed_values = [ 'Active' , 'Inactive' , '1' , '0' , 1 , 0 ] check_input ( args , 'calculations' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): calculations = args . get ( 'calculations' ) tiptiltcalc = ktl . cache ( 'kpfguide' , 'TIPTILT_CALC' ) tiptiltcalc . write ( calculations ) @classmethod def post_condition ( cls , args , logger , cfg ): calculations = args . get ( 'calculations' ) timeout = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) expr = f \"($kpfguide.TIPTILT_CALC == { calculations } ) \" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : tiptilt = ktl . cache ( 'kpfguide' , 'TIPTILT_CALC' ) raise FailedToReachDestination ( tiptilt . read (), calculations ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'calculations' , type = str , choices = [ 'Active' , 'Inactive' ], help = 'Calulations \"Active\" or \"Inactive\"' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetTipTiltCalculations"},{"location":"scripts/SetTipTiltCalculations/#settiptiltcalculations","text":"Bases: KPFTranslatorFunction Turn the tip tilt calculation software on or off. Parameters: calculations ( str ) \u2013 The desired state of the calculations. Allowed values: Active or Inactive KTL Keywords Used: kpfguide.TIPTILT_CALC Source code in kpf/fiu/SetTipTiltCalculations.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class SetTipTiltCalculations ( KPFTranslatorFunction ): '''Turn the tip tilt calculation software on or off. Args: calculations (str): The desired state of the calculations. Allowed values: Active or Inactive KTL Keywords Used: - `kpfguide.TIPTILT_CALC` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): allowed_values = [ 'Active' , 'Inactive' , '1' , '0' , 1 , 0 ] check_input ( args , 'calculations' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): calculations = args . get ( 'calculations' ) tiptiltcalc = ktl . cache ( 'kpfguide' , 'TIPTILT_CALC' ) tiptiltcalc . write ( calculations ) @classmethod def post_condition ( cls , args , logger , cfg ): calculations = args . get ( 'calculations' ) timeout = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) expr = f \"($kpfguide.TIPTILT_CALC == { calculations } ) \" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : tiptilt = ktl . cache ( 'kpfguide' , 'TIPTILT_CALC' ) raise FailedToReachDestination ( tiptilt . read (), calculations ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'calculations' , type = str , choices = [ 'Active' , 'Inactive' ], help = 'Calulations \"Active\" or \"Inactive\"' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetTipTiltCalculations"},{"location":"scripts/SetTipTiltControl/","text":"SetTipTiltControl Bases: KPFTranslatorFunction Turn the tip tilt control software on or off. Parameters: control ( str ) \u2013 The desired state of the control. Allowed values: Active or Inactive KTL Keywords Used: kpfguide.TIPTILT_CONTROL Source code in kpf/fiu/SetTipTiltControl.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class SetTipTiltControl ( KPFTranslatorFunction ): '''Turn the tip tilt control software on or off. Args: control (str): The desired state of the control. Allowed values: Active or Inactive KTL Keywords Used: - `kpfguide.TIPTILT_CONTROL` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): allowed_values = [ 'Active' , 'Inactive' , '1' , '0' , 1 , 0 ] check_input ( args , 'control' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): control = args . get ( 'control' ) tiptiltcontrol = ktl . cache ( 'kpfguide' , 'TIPTILT_CONTROL' ) tiptiltcontrol . write ( control ) @classmethod def post_condition ( cls , args , logger , cfg ): control = args . get ( 'control' ) timeout = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) expr = f \"($kpfguide.TIPTILT_CONTROL == { calculations } ) \" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : tiptiltcontrol = ktl . cache ( 'kpfguide' , 'TIPTILT_CONTROL' ) raise FailedToReachDestination ( tiptiltcontrol . read (), control ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'control' , type = str , choices = [ 'Active' , 'Inactive' ], help = 'Control \"Active\" or \"Inactive\"' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetTipTiltControl"},{"location":"scripts/SetTipTiltControl/#settiptiltcontrol","text":"Bases: KPFTranslatorFunction Turn the tip tilt control software on or off. Parameters: control ( str ) \u2013 The desired state of the control. Allowed values: Active or Inactive KTL Keywords Used: kpfguide.TIPTILT_CONTROL Source code in kpf/fiu/SetTipTiltControl.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class SetTipTiltControl ( KPFTranslatorFunction ): '''Turn the tip tilt control software on or off. Args: control (str): The desired state of the control. Allowed values: Active or Inactive KTL Keywords Used: - `kpfguide.TIPTILT_CONTROL` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): allowed_values = [ 'Active' , 'Inactive' , '1' , '0' , 1 , 0 ] check_input ( args , 'control' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): control = args . get ( 'control' ) tiptiltcontrol = ktl . cache ( 'kpfguide' , 'TIPTILT_CONTROL' ) tiptiltcontrol . write ( control ) @classmethod def post_condition ( cls , args , logger , cfg ): control = args . get ( 'control' ) timeout = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) expr = f \"($kpfguide.TIPTILT_CONTROL == { calculations } ) \" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : tiptiltcontrol = ktl . cache ( 'kpfguide' , 'TIPTILT_CONTROL' ) raise FailedToReachDestination ( tiptiltcontrol . read (), control ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'control' , type = str , choices = [ 'Active' , 'Inactive' ], help = 'Control \"Active\" or \"Inactive\"' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetTipTiltControl"},{"location":"scripts/SetTipTiltGain/","text":"SetTipTiltGain Bases: KPFTranslatorFunction Set the guide loop gain. Parameters: GuideLoopGain ( float ) \u2013 The desired gain value. KTL Keywords Used: kpfguide.TIPTILT_GAIN Source code in kpf/fiu/SetTipTiltGain.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 class SetTipTiltGain ( KPFTranslatorFunction ): '''Set the guide loop gain. Args: GuideLoopGain (float): The desired gain value. KTL Keywords Used: - `kpfguide.TIPTILT_GAIN` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'GuideLoopGain' , value_min = 0 , value_max = 1 ) @classmethod def perform ( cls , args , logger , cfg ): gain = float ( args . get ( 'GuideLoopGain' )) tiptiltgain = ktl . cache ( 'kpfguide' , 'TIPTILT_GAIN' ) tiptiltgain . write ( gain ) @classmethod def post_condition ( cls , args , logger , cfg ): gain = float ( args . get ( 'GuideLoopGain' )) timeout = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) tol = cfg . getfloat ( 'tolerances' , 'tip_tilt_gain_tolerance' , fallback = 0.001 ) expr = ( f \"($kpfguide.TIPTILT_GAIN >= { gain - tol } ) and \" f \"($kpfguide.TIPTILT_GAIN <= { gain + tol } )\" ) success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : tiptiltgain = ktl . cache ( 'kpfguide' , 'TIPTILT_GAIN' ) raise FailedToReachDestination ( tiptiltgain . read (), gain ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'GuideLoopGain' , type = float , help = \"Tip tilt control loop gain\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetTipTiltGain"},{"location":"scripts/SetTipTiltGain/#settiptiltgain","text":"Bases: KPFTranslatorFunction Set the guide loop gain. Parameters: GuideLoopGain ( float ) \u2013 The desired gain value. KTL Keywords Used: kpfguide.TIPTILT_GAIN Source code in kpf/fiu/SetTipTiltGain.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 class SetTipTiltGain ( KPFTranslatorFunction ): '''Set the guide loop gain. Args: GuideLoopGain (float): The desired gain value. KTL Keywords Used: - `kpfguide.TIPTILT_GAIN` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'GuideLoopGain' , value_min = 0 , value_max = 1 ) @classmethod def perform ( cls , args , logger , cfg ): gain = float ( args . get ( 'GuideLoopGain' )) tiptiltgain = ktl . cache ( 'kpfguide' , 'TIPTILT_GAIN' ) tiptiltgain . write ( gain ) @classmethod def post_condition ( cls , args , logger , cfg ): gain = float ( args . get ( 'GuideLoopGain' )) timeout = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) tol = cfg . getfloat ( 'tolerances' , 'tip_tilt_gain_tolerance' , fallback = 0.001 ) expr = ( f \"($kpfguide.TIPTILT_GAIN >= { gain - tol } ) and \" f \"($kpfguide.TIPTILT_GAIN <= { gain + tol } )\" ) success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : tiptiltgain = ktl . cache ( 'kpfguide' , 'TIPTILT_GAIN' ) raise FailedToReachDestination ( tiptiltgain . read (), gain ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'GuideLoopGain' , type = float , help = \"Tip tilt control loop gain\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetTipTiltGain"},{"location":"scripts/SetTipTiltPosition/","text":"SetTipTiltPosition Bases: KPFTranslatorFunction Set the position of the tip tilt mirror. This should only be used in an engineering context. To control the position of a star, set the CURRENT_BASE or PIX_TARGET keywords as appropriate, e.g. via the kpf.fiu.SetTipTiltTargetPixel translator module function. Parameters: x ( float ) \u2013 The desired X position (TTXVAX). y ( float ) \u2013 The desired Y position (TTYVAX). KTL Keywords Used: kpffiu.TTXVAX kpffiu.TTYVAX Source code in kpf/fiu/SetTipTiltPosition.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetTipTiltPosition ( KPFTranslatorFunction ): '''Set the position of the tip tilt mirror. This should only be used in an engineering context. To control the position of a star, set the CURRENT_BASE or PIX_TARGET keywords as appropriate, e.g. via the `kpf.fiu.SetTipTiltTargetPixel` translator module function. Args: x (float): The desired X position (TTXVAX). y (float): The desired Y position (TTYVAX). KTL Keywords Used: - `kpffiu.TTXVAX` - `kpffiu.TTYVAX` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'x' ) check_input ( args , 'y' ) @classmethod def perform ( cls , args , logger , cfg ): kpffiu = ktl . cache ( 'kpffiu' ) kpffiu [ 'TTXVAX' ] . write ( args . get ( 'x' )) kpffiu [ 'TTYVAX' ] . write ( args . get ( 'y' )) time_shim = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) time . sleep ( time_shim ) @classmethod def post_condition ( cls , args , logger , cfg ): kpffiu = ktl . cache ( 'kpffiu' ) timeout = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) tol = cfg . getfloat ( 'tolerances' , 'tip_tilt_move_tolerance' , fallback = 0.1 ) xdest = args . get ( 'x' ) ydest = args . get ( 'y' ) expr = ( f '($kpffiu.TTXVAX > { xdest - tol } ) and ' \\ f '($kpffiu.TTXVAX < { xdest + tol } )' ) successx = ktl . waitFor ( expr , timeout = timeout ) if successx is not True : raise FailedToReachDestination ( kpffiu [ 'TTXVAX' ] . read (), xdest ) expr = ( f '($kpffiu.TTYVAX > { ydest - tol } ) and ' \\ f '($kpffiu.TTYVAX < { ydest + tol } )' ) successy = ktl . waitFor ( expr , timeout = timeout ) if successy is not True : raise FailedToReachDestination ( kpffiu [ 'TTYVAX' ] . read (), ydest ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'x' , type = float , help = \"X position of the tip tilt mirror (TTXVAX)\" ) parser . add_argument ( 'y' , type = float , help = \"X position of the tip tilt mirror (TTYVAX)\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetTipTiltPosition"},{"location":"scripts/SetTipTiltPosition/#settiptiltposition","text":"Bases: KPFTranslatorFunction Set the position of the tip tilt mirror. This should only be used in an engineering context. To control the position of a star, set the CURRENT_BASE or PIX_TARGET keywords as appropriate, e.g. via the kpf.fiu.SetTipTiltTargetPixel translator module function. Parameters: x ( float ) \u2013 The desired X position (TTXVAX). y ( float ) \u2013 The desired Y position (TTYVAX). KTL Keywords Used: kpffiu.TTXVAX kpffiu.TTYVAX Source code in kpf/fiu/SetTipTiltPosition.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetTipTiltPosition ( KPFTranslatorFunction ): '''Set the position of the tip tilt mirror. This should only be used in an engineering context. To control the position of a star, set the CURRENT_BASE or PIX_TARGET keywords as appropriate, e.g. via the `kpf.fiu.SetTipTiltTargetPixel` translator module function. Args: x (float): The desired X position (TTXVAX). y (float): The desired Y position (TTYVAX). KTL Keywords Used: - `kpffiu.TTXVAX` - `kpffiu.TTYVAX` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'x' ) check_input ( args , 'y' ) @classmethod def perform ( cls , args , logger , cfg ): kpffiu = ktl . cache ( 'kpffiu' ) kpffiu [ 'TTXVAX' ] . write ( args . get ( 'x' )) kpffiu [ 'TTYVAX' ] . write ( args . get ( 'y' )) time_shim = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) time . sleep ( time_shim ) @classmethod def post_condition ( cls , args , logger , cfg ): kpffiu = ktl . cache ( 'kpffiu' ) timeout = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) tol = cfg . getfloat ( 'tolerances' , 'tip_tilt_move_tolerance' , fallback = 0.1 ) xdest = args . get ( 'x' ) ydest = args . get ( 'y' ) expr = ( f '($kpffiu.TTXVAX > { xdest - tol } ) and ' \\ f '($kpffiu.TTXVAX < { xdest + tol } )' ) successx = ktl . waitFor ( expr , timeout = timeout ) if successx is not True : raise FailedToReachDestination ( kpffiu [ 'TTXVAX' ] . read (), xdest ) expr = ( f '($kpffiu.TTYVAX > { ydest - tol } ) and ' \\ f '($kpffiu.TTYVAX < { ydest + tol } )' ) successy = ktl . waitFor ( expr , timeout = timeout ) if successy is not True : raise FailedToReachDestination ( kpffiu [ 'TTYVAX' ] . read (), ydest ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'x' , type = float , help = \"X position of the tip tilt mirror (TTXVAX)\" ) parser . add_argument ( 'y' , type = float , help = \"X position of the tip tilt mirror (TTYVAX)\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetTipTiltPosition"},{"location":"scripts/SetTipTiltTargetPixel/","text":"SetTipTiltTargetPixel Bases: KPFTranslatorFunction Set the target pixel of the tip tilt mirror. This sets the CURRENT_BASE keyword. Parameters: x ( float ) \u2013 The desired X target pixel. y ( float ) \u2013 The desired Y target pixel. KTL Keywords Used: kpfguide.CURRENT_BASE Source code in kpf/fiu/SetTipTiltTargetPixel.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 class SetTipTiltTargetPixel ( KPFTranslatorFunction ): '''Set the target pixel of the tip tilt mirror. This sets the CURRENT_BASE keyword. Args: x (float): The desired X target pixel. y (float): The desired Y target pixel. KTL Keywords Used: - `kpfguide.CURRENT_BASE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): min_x_pixel = cfg . getint ( 'guider' , 'min_x_pixel' , fallback = 0 ) max_x_pixel = cfg . getint ( 'guider' , 'max_x_pixel' , fallback = 640 ) min_y_pixel = cfg . getint ( 'guider' , 'min_y_pixel' , fallback = 0 ) max_y_pixel = cfg . getint ( 'guider' , 'max_y_pixel' , fallback = 512 ) check_input ( args , 'x' , value_min = min_x_pixel , value_max = max_x_pixel ) check_input ( args , 'y' , value_min = min_y_pixel , value_max = max_y_pixel ) @classmethod def perform ( cls , args , logger , cfg ): x = args . get ( 'x' ) y = args . get ( 'y' ) pixtarget = ktl . cache ( 'kpfguide' , 'CURRENT_BASE' ) pixtarget . write (( x , y )) time_shim = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.01 ) time . sleep ( time_shim ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'x' , type = float , help = \"X pixel target (CURRENT_BASE)\" ) parser . add_argument ( 'y' , type = float , help = \"Y pixel target (CURRENT_BASE)\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetTipTiltTargetPixel"},{"location":"scripts/SetTipTiltTargetPixel/#settiptilttargetpixel","text":"Bases: KPFTranslatorFunction Set the target pixel of the tip tilt mirror. This sets the CURRENT_BASE keyword. Parameters: x ( float ) \u2013 The desired X target pixel. y ( float ) \u2013 The desired Y target pixel. KTL Keywords Used: kpfguide.CURRENT_BASE Source code in kpf/fiu/SetTipTiltTargetPixel.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 class SetTipTiltTargetPixel ( KPFTranslatorFunction ): '''Set the target pixel of the tip tilt mirror. This sets the CURRENT_BASE keyword. Args: x (float): The desired X target pixel. y (float): The desired Y target pixel. KTL Keywords Used: - `kpfguide.CURRENT_BASE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): min_x_pixel = cfg . getint ( 'guider' , 'min_x_pixel' , fallback = 0 ) max_x_pixel = cfg . getint ( 'guider' , 'max_x_pixel' , fallback = 640 ) min_y_pixel = cfg . getint ( 'guider' , 'min_y_pixel' , fallback = 0 ) max_y_pixel = cfg . getint ( 'guider' , 'max_y_pixel' , fallback = 512 ) check_input ( args , 'x' , value_min = min_x_pixel , value_max = max_x_pixel ) check_input ( args , 'y' , value_min = min_y_pixel , value_max = max_y_pixel ) @classmethod def perform ( cls , args , logger , cfg ): x = args . get ( 'x' ) y = args . get ( 'y' ) pixtarget = ktl . cache ( 'kpfguide' , 'CURRENT_BASE' ) pixtarget . write (( x , y )) time_shim = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.01 ) time . sleep ( time_shim ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'x' , type = float , help = \"X pixel target (CURRENT_BASE)\" ) parser . add_argument ( 'y' , type = float , help = \"Y pixel target (CURRENT_BASE)\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetTipTiltTargetPixel"},{"location":"scripts/SetTriggeredDetectors/","text":"SetTriggeredDetectors Bases: KPFTranslatorFunction Selects which cameras will be triggered by setting the kpfexpose.TRIG_TARG keyword value. ARGS: :TriggerRed: bool Trigger the Red detector? (default=False) :TriggerGreen: bool Trigger the Green detector? (default=False) :TriggerCaHK: bool Trigger the CaH&K detector? (default=False) :TriggerExpMeter: bool Trigger the ExpMeter detector? (default=False) Source code in kpf/spectrograph/SetTriggeredDetectors.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetTriggeredDetectors ( KPFTranslatorFunction ): '''Selects which cameras will be triggered by setting the `kpfexpose.TRIG_TARG` keyword value. ARGS: ===== :TriggerRed: `bool` Trigger the Red detector? (default=False) :TriggerGreen: `bool` Trigger the Green detector? (default=False) :TriggerCaHK: `bool` Trigger the CaH&K detector? (default=False) :TriggerExpMeter: `bool` Trigger the ExpMeter detector? (default=False) ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfconfig = ktl . cache ( 'kpfconfig' ) detector_list = [] if args . get ( 'TriggerRed' , False ) is True : if kpfconfig [ 'RED_ENABLED' ] . read ( binary = True ) == False : log . warning ( f 'Red detector is not enabled' ) else : detector_list . append ( 'Red' ) if args . get ( 'TriggerGreen' , False ) is True : if kpfconfig [ 'GREEN_ENABLED' ] . read ( binary = True ) == False : log . warning ( f 'Green detector is not enabled' ) else : detector_list . append ( 'Green' ) if args . get ( 'TriggerCaHK' , False ) is True : if kpfconfig [ 'CA_HK_ENABLED' ] . read ( binary = True ) == False : log . warning ( f 'Ca HK detector is not enabled' ) else : detector_list . append ( 'Ca_HK' ) if args . get ( 'TriggerExpMeter' , False ) is True : if kpfconfig [ 'EXPMETER_ENABLED' ] . read ( binary = True ) == False : log . warning ( f 'ExpMeter detector is not enabled' ) else : detector_list . append ( 'ExpMeter' ) if args . get ( 'TriggerGuide' , False ) is True : detector_list . append ( 'Guide' ) detectors_string = ',' . join ( detector_list ) log . debug ( f \"Setting triggered detectors to ' { detectors_string } '\" ) kpfexpose = ktl . cache ( 'kpfexpose' ) kpfexpose [ 'TRIG_TARG' ] . write ( detectors_string ) shim_time = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.1 ) sleep ( shim_time ) @classmethod def post_condition ( cls , args , logger , cfg ): kpfconfig = ktl . cache ( 'kpfconfig' ) kpfexpose = ktl . cache ( 'kpfexpose' ) timeshim = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.1 ) sleep ( timeshim ) detectors = kpfexpose [ 'TRIG_TARG' ] . read () detector_list = detectors . split ( ',' ) detector_names = [( 'Red' , 'TriggerRed' ), ( 'Green' , 'TriggerGreen' ), ( 'Ca_HK' , 'TriggerCaHK' ), ( 'ExpMeter' , 'TriggerExpMeter' ), # ('Guide', 'TriggerGuide'), ] # Don't check on guide because there is no enabled keyword for it for detector in detector_names : detector_status = detector [ 0 ] in detector_list enabled = kpfconfig [ f ' { detector [ 0 ] . upper () } _ENABLED' ] . read ( binary = True ) detector_target = args . get ( detector [ 1 ], False ) and enabled if detector_target != detector_status : raise FailedToReachDestination ( detector_status , detector_target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--Red\" , \"--red\" , \"-r\" , dest = \"TriggerRed\" , default = False , action = \"store_true\" , help = \"Trigger the Red detector during exposure?\" ) parser . add_argument ( \"--Green\" , \"--green\" , \"-g\" , dest = \"TriggerGreen\" , default = False , action = \"store_true\" , help = \"Trigger the Green detector during exposure?\" ) parser . add_argument ( \"--CaHK\" , \"--HK\" , \"--cahk\" , \"--hk\" , dest = \"TriggerCaHK\" , default = False , action = \"store_true\" , help = \"Trigger the CaHK detector during exposure?\" ) parser . add_argument ( \"--ExpMeter\" , \"--expmeter\" , \"--EM\" , \"--em\" , dest = \"TriggerExpMeter\" , default = False , action = \"store_true\" , help = \"Trigger the ExpMeter detector during exposure?\" ) parser . add_argument ( \"--Guide\" , \"--Guider\" , \"--guide\" , \"--guider\" , \"--CRED2\" , dest = \"TriggerGuide\" , default = False , action = \"store_true\" , help = \"Trigger the Guider detector during exposure?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetTriggeredDetectors"},{"location":"scripts/SetTriggeredDetectors/#settriggereddetectors","text":"Bases: KPFTranslatorFunction Selects which cameras will be triggered by setting the kpfexpose.TRIG_TARG keyword value.","title":"SetTriggeredDetectors"},{"location":"scripts/SetTriggeredDetectors/#kpf.spectrograph.SetTriggeredDetectors.SetTriggeredDetectors--args","text":":TriggerRed: bool Trigger the Red detector? (default=False) :TriggerGreen: bool Trigger the Green detector? (default=False) :TriggerCaHK: bool Trigger the CaH&K detector? (default=False) :TriggerExpMeter: bool Trigger the ExpMeter detector? (default=False) Source code in kpf/spectrograph/SetTriggeredDetectors.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetTriggeredDetectors ( KPFTranslatorFunction ): '''Selects which cameras will be triggered by setting the `kpfexpose.TRIG_TARG` keyword value. ARGS: ===== :TriggerRed: `bool` Trigger the Red detector? (default=False) :TriggerGreen: `bool` Trigger the Green detector? (default=False) :TriggerCaHK: `bool` Trigger the CaH&K detector? (default=False) :TriggerExpMeter: `bool` Trigger the ExpMeter detector? (default=False) ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfconfig = ktl . cache ( 'kpfconfig' ) detector_list = [] if args . get ( 'TriggerRed' , False ) is True : if kpfconfig [ 'RED_ENABLED' ] . read ( binary = True ) == False : log . warning ( f 'Red detector is not enabled' ) else : detector_list . append ( 'Red' ) if args . get ( 'TriggerGreen' , False ) is True : if kpfconfig [ 'GREEN_ENABLED' ] . read ( binary = True ) == False : log . warning ( f 'Green detector is not enabled' ) else : detector_list . append ( 'Green' ) if args . get ( 'TriggerCaHK' , False ) is True : if kpfconfig [ 'CA_HK_ENABLED' ] . read ( binary = True ) == False : log . warning ( f 'Ca HK detector is not enabled' ) else : detector_list . append ( 'Ca_HK' ) if args . get ( 'TriggerExpMeter' , False ) is True : if kpfconfig [ 'EXPMETER_ENABLED' ] . read ( binary = True ) == False : log . warning ( f 'ExpMeter detector is not enabled' ) else : detector_list . append ( 'ExpMeter' ) if args . get ( 'TriggerGuide' , False ) is True : detector_list . append ( 'Guide' ) detectors_string = ',' . join ( detector_list ) log . debug ( f \"Setting triggered detectors to ' { detectors_string } '\" ) kpfexpose = ktl . cache ( 'kpfexpose' ) kpfexpose [ 'TRIG_TARG' ] . write ( detectors_string ) shim_time = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.1 ) sleep ( shim_time ) @classmethod def post_condition ( cls , args , logger , cfg ): kpfconfig = ktl . cache ( 'kpfconfig' ) kpfexpose = ktl . cache ( 'kpfexpose' ) timeshim = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.1 ) sleep ( timeshim ) detectors = kpfexpose [ 'TRIG_TARG' ] . read () detector_list = detectors . split ( ',' ) detector_names = [( 'Red' , 'TriggerRed' ), ( 'Green' , 'TriggerGreen' ), ( 'Ca_HK' , 'TriggerCaHK' ), ( 'ExpMeter' , 'TriggerExpMeter' ), # ('Guide', 'TriggerGuide'), ] # Don't check on guide because there is no enabled keyword for it for detector in detector_names : detector_status = detector [ 0 ] in detector_list enabled = kpfconfig [ f ' { detector [ 0 ] . upper () } _ENABLED' ] . read ( binary = True ) detector_target = args . get ( detector [ 1 ], False ) and enabled if detector_target != detector_status : raise FailedToReachDestination ( detector_status , detector_target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--Red\" , \"--red\" , \"-r\" , dest = \"TriggerRed\" , default = False , action = \"store_true\" , help = \"Trigger the Red detector during exposure?\" ) parser . add_argument ( \"--Green\" , \"--green\" , \"-g\" , dest = \"TriggerGreen\" , default = False , action = \"store_true\" , help = \"Trigger the Green detector during exposure?\" ) parser . add_argument ( \"--CaHK\" , \"--HK\" , \"--cahk\" , \"--hk\" , dest = \"TriggerCaHK\" , default = False , action = \"store_true\" , help = \"Trigger the CaHK detector during exposure?\" ) parser . add_argument ( \"--ExpMeter\" , \"--expmeter\" , \"--EM\" , \"--em\" , dest = \"TriggerExpMeter\" , default = False , action = \"store_true\" , help = \"Trigger the ExpMeter detector during exposure?\" ) parser . add_argument ( \"--Guide\" , \"--Guider\" , \"--guide\" , \"--guider\" , \"--CRED2\" , dest = \"TriggerGuide\" , default = False , action = \"store_true\" , help = \"Trigger the Guider detector during exposure?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"ARGS:"},{"location":"scripts/SetupAOforACAM/","text":"SetupAOforACAM Bases: KPFTranslatorFunction Set up AO in the safe mode for ACAM operation to assist KPF acquisition Scripts Called: kpf.ao.SetAFMtoMirror kpf.ao.SetAFStoNGS Source code in kpf/ao/SetupAOforACAM.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class SetupAOforACAM ( KPFTranslatorFunction ): '''Set up AO in the safe mode for ACAM operation to assist KPF acquisition Scripts Called: - `kpf.ao.SetAFMtoMirror` - `kpf.ao.SetAFStoNGS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): log . info ( 'Set AFM to Mirror' ) SetAFMtoMirror . execute ({}) log . info ( 'Set AFS to NGS' ) SetAFStoNGS . execute ({}) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"SetupAOforACAM"},{"location":"scripts/SetupAOforACAM/#setupaoforacam","text":"Bases: KPFTranslatorFunction Set up AO in the safe mode for ACAM operation to assist KPF acquisition Scripts Called: kpf.ao.SetAFMtoMirror kpf.ao.SetAFStoNGS Source code in kpf/ao/SetupAOforACAM.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class SetupAOforACAM ( KPFTranslatorFunction ): '''Set up AO in the safe mode for ACAM operation to assist KPF acquisition Scripts Called: - `kpf.ao.SetAFMtoMirror` - `kpf.ao.SetAFStoNGS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): log . info ( 'Set AFM to Mirror' ) SetAFMtoMirror . execute ({}) log . info ( 'Set AFS to NGS' ) SetAFStoNGS . execute ({}) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"SetupAOforACAM"},{"location":"scripts/SetupAOforKPF/","text":"SetupAOforKPF Bases: KPFTranslatorFunction Set up AO in the safe mode for KPF operation Set AO roator in Manual mode Set AO rotator to 0 deg Turn off HEPA Set AO in DCS sim mode Home PCU Move PCU to the KPF position Open AO hatch KTL Keywords Used: ao.PCSFNAME Scripts Called: kpf.ao.SetAORotatorManual kpf.ao.SetAORotator kpf.ao.TurnHepaOff kpf.ao.SetAODCStoSIM kpf.ao.TurnLightSourceOff kpf.ao.SendPCUtoHome kpf.ao.SendPCUtoKPF Source code in kpf/ao/SetupAOforKPF.py 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetupAOforKPF ( KPFTranslatorFunction ): '''Set up AO in the safe mode for KPF operation - Set AO roator in Manual mode - Set AO rotator to 0 deg - Turn off HEPA - Set AO in DCS sim mode - Home PCU - Move PCU to the KPF position - Open AO hatch KTL Keywords Used: - `ao.PCSFNAME` Scripts Called: - `kpf.ao.SetAORotatorManual` - `kpf.ao.SetAORotator` - `kpf.ao.TurnHepaOff` - `kpf.ao.SetAODCStoSIM` - `kpf.ao.TurnLightSourceOff` - `kpf.ao.SendPCUtoHome` - `kpf.ao.SendPCUtoKPF` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): log . info ( 'Set AO rotator to Manual' ) SetAORotatorManual . execute ({}) log . info ( 'Set AO rotator to 0 deg' ) SetAORotator . execute ({ 'dest' : 0 }) log . info ( 'Turn off HEPA' ) TurnHepaOff . execute ({}) log . info ( 'Set AO in DCS sim mode' ) SetAODCStoSIM . execute ({}) log . info ( 'Turn K1 AO light source off' ) TurnLightSourceOff . execute ({}) PCSstagekw = ktl . cache ( 'ao' , 'PCSFNAME' ) if PCSstagekw . read () != 'kpf' : log . info ( 'Move PCU to Home' ) SendPCUtoHome . execute ({}) log . info ( 'Move PCU to KPF' ) SendPCUtoKPF . execute ({}) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"SetupAOforKPF"},{"location":"scripts/SetupAOforKPF/#setupaoforkpf","text":"Bases: KPFTranslatorFunction Set up AO in the safe mode for KPF operation Set AO roator in Manual mode Set AO rotator to 0 deg Turn off HEPA Set AO in DCS sim mode Home PCU Move PCU to the KPF position Open AO hatch KTL Keywords Used: ao.PCSFNAME Scripts Called: kpf.ao.SetAORotatorManual kpf.ao.SetAORotator kpf.ao.TurnHepaOff kpf.ao.SetAODCStoSIM kpf.ao.TurnLightSourceOff kpf.ao.SendPCUtoHome kpf.ao.SendPCUtoKPF Source code in kpf/ao/SetupAOforKPF.py 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetupAOforKPF ( KPFTranslatorFunction ): '''Set up AO in the safe mode for KPF operation - Set AO roator in Manual mode - Set AO rotator to 0 deg - Turn off HEPA - Set AO in DCS sim mode - Home PCU - Move PCU to the KPF position - Open AO hatch KTL Keywords Used: - `ao.PCSFNAME` Scripts Called: - `kpf.ao.SetAORotatorManual` - `kpf.ao.SetAORotator` - `kpf.ao.TurnHepaOff` - `kpf.ao.SetAODCStoSIM` - `kpf.ao.TurnLightSourceOff` - `kpf.ao.SendPCUtoHome` - `kpf.ao.SendPCUtoKPF` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): log . info ( 'Set AO rotator to Manual' ) SetAORotatorManual . execute ({}) log . info ( 'Set AO rotator to 0 deg' ) SetAORotator . execute ({ 'dest' : 0 }) log . info ( 'Turn off HEPA' ) TurnHepaOff . execute ({}) log . info ( 'Set AO in DCS sim mode' ) SetAODCStoSIM . execute ({}) log . info ( 'Turn K1 AO light source off' ) TurnLightSourceOff . execute ({}) PCSstagekw = ktl . cache ( 'ao' , 'PCSFNAME' ) if PCSstagekw . read () != 'kpf' : log . info ( 'Move PCU to Home' ) SendPCUtoHome . execute ({}) log . info ( 'Move PCU to KPF' ) SendPCUtoKPF . execute ({}) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"SetupAOforKPF"},{"location":"scripts/SetupExpMeter/","text":"SetupExpMeter Bases: KPFTranslatorFunction Configure the exposure meter using the given OB arguments. Parameters: ExpMeterMode ( str ) \u2013 See Science OB definition. TriggerExpMeter ( bool ) \u2013 See Science OB definition. KTL Keywords Used: kpf_expmeter.USETHRESHOLD kpfconfig.EXPMETER_ENABLED Scripts Called: kpf.expmeter.SetExpMeterTerminationParameters Source code in kpf/expmeter/SetupExpMeter.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetupExpMeter ( KPFTranslatorFunction ): '''Configure the exposure meter using the given OB arguments. Args: ExpMeterMode (str): See Science OB definition. TriggerExpMeter (bool): See Science OB definition. KTL Keywords Used: - `kpf_expmeter.USETHRESHOLD` - `kpfconfig.EXPMETER_ENABLED` Scripts Called: - `kpf.expmeter.SetExpMeterTerminationParameters` ''' abortable = False @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'Template_Name' , allowed_values = [ 'kpf_lamp' , 'kpf_sci' ]) check_input ( args , 'Template_Version' , version_check = True , value_min = '0.5' ) @classmethod def perform ( cls , args , logger , cfg ): kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) kpfconfig = ktl . cache ( 'kpfconfig' ) ## ---------------------------------------------------------------- ## Configure exposure meter ## ---------------------------------------------------------------- log . debug ( 'Setting up exposure meter using SetupExpMeter' ) EM_mode = args . get ( 'ExpMeterMode' , 'off' ) EM_enabled = kpfconfig [ 'EXPMETER_ENABLED' ] . read () == 'Yes' if EM_mode == 'monitor' and EM_enabled : kpf_expmeter [ 'USETHRESHOLD' ] . write ( 'No' ) args [ 'TriggerExpMeter' ] = True elif EM_mode == 'control' and EM_enabled : args [ 'TriggerExpMeter' ] = True try : SetExpMeterTerminationParameters . execute ( args ) except Exception as e : log . error ( 'SetExpMeterTerminationParameters failed' ) log . error ( e ) traceback_text = traceback . format_exc () log . error ( traceback_text ) kpf_expmeter [ 'USETHRESHOLD' ] . write ( 'No' ) elif EM_mode in [ 'off' , False ]: # pyyaml converts 'off' to False, so handle both args [ 'TriggerExpMeter' ] = False elif EM_enabled == False : log . warning ( 'ExpMeter is disabled' ) else : log . warning ( f \"ExpMeterMode { EM_mode } is not available\" ) kpf_expmeter [ 'USETHRESHOLD' ] . write ( 'No' ) # Must return args as we have edited them return args @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( '--nointensemon' , dest = \"nointensemon\" , default = False , action = \"store_true\" , help = 'Skip the intensity monitor measurement?' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetupExpMeter"},{"location":"scripts/SetupExpMeter/#setupexpmeter","text":"Bases: KPFTranslatorFunction Configure the exposure meter using the given OB arguments. Parameters: ExpMeterMode ( str ) \u2013 See Science OB definition. TriggerExpMeter ( bool ) \u2013 See Science OB definition. KTL Keywords Used: kpf_expmeter.USETHRESHOLD kpfconfig.EXPMETER_ENABLED Scripts Called: kpf.expmeter.SetExpMeterTerminationParameters Source code in kpf/expmeter/SetupExpMeter.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetupExpMeter ( KPFTranslatorFunction ): '''Configure the exposure meter using the given OB arguments. Args: ExpMeterMode (str): See Science OB definition. TriggerExpMeter (bool): See Science OB definition. KTL Keywords Used: - `kpf_expmeter.USETHRESHOLD` - `kpfconfig.EXPMETER_ENABLED` Scripts Called: - `kpf.expmeter.SetExpMeterTerminationParameters` ''' abortable = False @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'Template_Name' , allowed_values = [ 'kpf_lamp' , 'kpf_sci' ]) check_input ( args , 'Template_Version' , version_check = True , value_min = '0.5' ) @classmethod def perform ( cls , args , logger , cfg ): kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) kpfconfig = ktl . cache ( 'kpfconfig' ) ## ---------------------------------------------------------------- ## Configure exposure meter ## ---------------------------------------------------------------- log . debug ( 'Setting up exposure meter using SetupExpMeter' ) EM_mode = args . get ( 'ExpMeterMode' , 'off' ) EM_enabled = kpfconfig [ 'EXPMETER_ENABLED' ] . read () == 'Yes' if EM_mode == 'monitor' and EM_enabled : kpf_expmeter [ 'USETHRESHOLD' ] . write ( 'No' ) args [ 'TriggerExpMeter' ] = True elif EM_mode == 'control' and EM_enabled : args [ 'TriggerExpMeter' ] = True try : SetExpMeterTerminationParameters . execute ( args ) except Exception as e : log . error ( 'SetExpMeterTerminationParameters failed' ) log . error ( e ) traceback_text = traceback . format_exc () log . error ( traceback_text ) kpf_expmeter [ 'USETHRESHOLD' ] . write ( 'No' ) elif EM_mode in [ 'off' , False ]: # pyyaml converts 'off' to False, so handle both args [ 'TriggerExpMeter' ] = False elif EM_enabled == False : log . warning ( 'ExpMeter is disabled' ) else : log . warning ( f \"ExpMeterMode { EM_mode } is not available\" ) kpf_expmeter [ 'USETHRESHOLD' ] . write ( 'No' ) # Must return args as we have edited them return args @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( '--nointensemon' , dest = \"nointensemon\" , default = False , action = \"store_true\" , help = 'Skip the intensity monitor measurement?' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetupExpMeter"},{"location":"scripts/ShutdownTipTilt/","text":"ShutdownTipTilt Bases: KPFTranslatorFunction Shutdown the tip tilt system by setting the control mode to open loop and setting the target values in X and Y to 0. KTL Keywords Used: kpffiu.TTXSRV kpffiu.TTYSRV kpffiu.TTXVAX kpffiu.TTYVAX kpfguide.TIPTILT_CONTROL kpfguide.TIPTILT_CALC kpfguide.TIPTILT_HOME Source code in kpf/fiu/ShutdownTipTilt.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class ShutdownTipTilt ( KPFTranslatorFunction ): '''Shutdown the tip tilt system by setting the control mode to open loop and setting the target values in X and Y to 0. KTL Keywords Used: - `kpffiu.TTXSRV` - `kpffiu.TTYSRV` - `kpffiu.TTXVAX` - `kpffiu.TTYVAX` - `kpfguide.TIPTILT_CONTROL` - `kpfguide.TIPTILT_CALC` - `kpfguide.TIPTILT_HOME` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) kpffiu = ktl . cache ( 'kpffiu' ) xopen = kpffiu [ 'TTXSRV' ] . read () == 'Open' yopen = kpffiu [ 'TTYSRV' ] . read () == 'Open' if xopen and yopen : # No actions needed return elif xopen == False and yopen == False : # Both axis are in closed loop mode # Shut down tip tilt activity and park mirror before opening loops kpfguide [ 'TIPTILT_CONTROL' ] . write ( 'Inactive' ) kpfguide [ 'TIPTILT_CALC' ] . write ( 'Inactive' ) tthome = ktl . cache ( 'kpfguide' , 'TIPTILT_HOME' ) home = tthome . read ( binary = True ) log . debug ( f 'Sending Tip tilt mirror to home: { home [ 0 ] } { home [ 1 ] } ' ) kpffiu [ 'TTXVAX' ] . write ( home [ 0 ]) kpffiu [ 'TTYVAX' ] . write ( home [ 1 ]) log . debug ( 'Opening tip tilt mirror servo loops' ) kpffiu [ 'TTXSRV' ] . write ( 'open' ) kpffiu [ 'TTYSRV' ] . write ( 'open' ) else : # We're in a mixed state, just open the loops log . debug ( 'Opening tip tilt mirror servo loops' ) kpffiu [ 'TTXSRV' ] . write ( 'open' ) kpffiu [ 'TTYSRV' ] . write ( 'open' ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) success1 = ktl . waitFor ( '($kpffiu.TTXSRV == open)' , timeout = timeout ) success2 = ktl . waitFor ( '($kpffiu.TTYSRV == open)' , timeout = timeout ) if success1 == False or success2 == False : raise FailedPostCondition ( f 'TT[X and/or Y]SRV did not open' )","title":"ShutdownTipTilt"},{"location":"scripts/ShutdownTipTilt/#shutdowntiptilt","text":"Bases: KPFTranslatorFunction Shutdown the tip tilt system by setting the control mode to open loop and setting the target values in X and Y to 0. KTL Keywords Used: kpffiu.TTXSRV kpffiu.TTYSRV kpffiu.TTXVAX kpffiu.TTYVAX kpfguide.TIPTILT_CONTROL kpfguide.TIPTILT_CALC kpfguide.TIPTILT_HOME Source code in kpf/fiu/ShutdownTipTilt.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class ShutdownTipTilt ( KPFTranslatorFunction ): '''Shutdown the tip tilt system by setting the control mode to open loop and setting the target values in X and Y to 0. KTL Keywords Used: - `kpffiu.TTXSRV` - `kpffiu.TTYSRV` - `kpffiu.TTXVAX` - `kpffiu.TTYVAX` - `kpfguide.TIPTILT_CONTROL` - `kpfguide.TIPTILT_CALC` - `kpfguide.TIPTILT_HOME` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) kpffiu = ktl . cache ( 'kpffiu' ) xopen = kpffiu [ 'TTXSRV' ] . read () == 'Open' yopen = kpffiu [ 'TTYSRV' ] . read () == 'Open' if xopen and yopen : # No actions needed return elif xopen == False and yopen == False : # Both axis are in closed loop mode # Shut down tip tilt activity and park mirror before opening loops kpfguide [ 'TIPTILT_CONTROL' ] . write ( 'Inactive' ) kpfguide [ 'TIPTILT_CALC' ] . write ( 'Inactive' ) tthome = ktl . cache ( 'kpfguide' , 'TIPTILT_HOME' ) home = tthome . read ( binary = True ) log . debug ( f 'Sending Tip tilt mirror to home: { home [ 0 ] } { home [ 1 ] } ' ) kpffiu [ 'TTXVAX' ] . write ( home [ 0 ]) kpffiu [ 'TTYVAX' ] . write ( home [ 1 ]) log . debug ( 'Opening tip tilt mirror servo loops' ) kpffiu [ 'TTXSRV' ] . write ( 'open' ) kpffiu [ 'TTYSRV' ] . write ( 'open' ) else : # We're in a mixed state, just open the loops log . debug ( 'Opening tip tilt mirror servo loops' ) kpffiu [ 'TTXSRV' ] . write ( 'open' ) kpffiu [ 'TTYSRV' ] . write ( 'open' ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) success1 = ktl . waitFor ( '($kpffiu.TTXSRV == open)' , timeout = timeout ) success2 = ktl . waitFor ( '($kpffiu.TTYSRV == open)' , timeout = timeout ) if success1 == False or success2 == False : raise FailedPostCondition ( f 'TT[X and/or Y]SRV did not open' )","title":"ShutdownTipTilt"},{"location":"scripts/SoCalStartAutonomous/","text":"SoCalStartAutonomous Bases: KPFTranslatorFunction Start SoCal's AUTONOMOUS mode by setting AUTONOMOUS=1 ARGS: None Source code in kpf/socal/SoCalStartAutonomous.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class SoCalStartAutonomous ( KPFTranslatorFunction ): '''Start SoCal's AUTONOMOUS mode by setting AUTONOMOUS=1 ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): AUTONOMOUS = ktl . cache ( 'kpfsocal' , 'AUTONOMOUS' ) log . info ( 'Setting kpfsocal.AUTONOMOUS = 1' ) AUTONOMOUS . write ( 1 ) @classmethod def post_condition ( cls , args , logger , cfg ): AUTONOMOUS = ktl . cache ( 'kpfsocal' , 'AUTONOMOUS' ) success = AUTONOMOUS . waitFor ( \"==1\" , timeout = 1 ) if success is False : raise FailedToReachDestination ( 'kpfsocal.AUTONOMOUS is not 1' )","title":"SoCalStartAutonomous"},{"location":"scripts/SoCalStartAutonomous/#socalstartautonomous","text":"Bases: KPFTranslatorFunction Start SoCal's AUTONOMOUS mode by setting AUTONOMOUS=1","title":"SoCalStartAutonomous"},{"location":"scripts/SoCalStartAutonomous/#kpf.socal.SoCalStartAutonomous.SoCalStartAutonomous--args","text":"None Source code in kpf/socal/SoCalStartAutonomous.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class SoCalStartAutonomous ( KPFTranslatorFunction ): '''Start SoCal's AUTONOMOUS mode by setting AUTONOMOUS=1 ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): AUTONOMOUS = ktl . cache ( 'kpfsocal' , 'AUTONOMOUS' ) log . info ( 'Setting kpfsocal.AUTONOMOUS = 1' ) AUTONOMOUS . write ( 1 ) @classmethod def post_condition ( cls , args , logger , cfg ): AUTONOMOUS = ktl . cache ( 'kpfsocal' , 'AUTONOMOUS' ) success = AUTONOMOUS . waitFor ( \"==1\" , timeout = 1 ) if success is False : raise FailedToReachDestination ( 'kpfsocal.AUTONOMOUS is not 1' )","title":"ARGS:"},{"location":"scripts/SoCalStopAutonomous/","text":"SoCalStopAutonomous Bases: KPFTranslatorFunction Stop SoCal's AUTONOMOUS mode by setting AUTONOMOUS=0 ARGS: None Source code in kpf/socal/SoCalStopAutonomous.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class SoCalStopAutonomous ( KPFTranslatorFunction ): '''Stop SoCal's AUTONOMOUS mode by setting AUTONOMOUS=0 ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): AUTONOMOUS = ktl . cache ( 'kpfsocal' , 'AUTONOMOUS' ) log . info ( 'Setting kpfsocal.AUTONOMOUS = 0' ) AUTONOMOUS . write ( 0 ) @classmethod def post_condition ( cls , args , logger , cfg ): AUTONOMOUS = ktl . cache ( 'kpfsocal' , 'AUTONOMOUS' ) success = AUTONOMOUS . waitFor ( \"==0\" , timeout = 1 ) if success is False : raise FailedToReachDestination ( 'kpfsocal.AUTONOMOUS is not 0' )","title":"SoCalStopAutonomous"},{"location":"scripts/SoCalStopAutonomous/#socalstopautonomous","text":"Bases: KPFTranslatorFunction Stop SoCal's AUTONOMOUS mode by setting AUTONOMOUS=0","title":"SoCalStopAutonomous"},{"location":"scripts/SoCalStopAutonomous/#kpf.socal.SoCalStopAutonomous.SoCalStopAutonomous--args","text":"None Source code in kpf/socal/SoCalStopAutonomous.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class SoCalStopAutonomous ( KPFTranslatorFunction ): '''Stop SoCal's AUTONOMOUS mode by setting AUTONOMOUS=0 ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): AUTONOMOUS = ktl . cache ( 'kpfsocal' , 'AUTONOMOUS' ) log . info ( 'Setting kpfsocal.AUTONOMOUS = 0' ) AUTONOMOUS . write ( 0 ) @classmethod def post_condition ( cls , args , logger , cfg ): AUTONOMOUS = ktl . cache ( 'kpfsocal' , 'AUTONOMOUS' ) success = AUTONOMOUS . waitFor ( \"==0\" , timeout = 1 ) if success is False : raise FailedToReachDestination ( 'kpfsocal.AUTONOMOUS is not 0' )","title":"ARGS:"},{"location":"scripts/StartAgitator/","text":"StartAgitator Bases: KPFTranslatorFunction Start the agitator motion and wait the appropriate startup time before returning. ARGS: None Source code in kpf/spectrograph/StartAgitator.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class StartAgitator ( KPFTranslatorFunction ): '''Start the agitator motion and wait the appropriate startup time before returning. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): agitator = ktl . cache ( 'kpfmot' , 'AGITATOR' ) if agitator . read () == 'Running' : log . debug ( 'Agitator is running' ) else : startup = cfg . getfloat ( 'times' , 'agitator_startup_time' , fallback = 0.325 ) log . debug ( 'Starting agitator motion' ) try : agitator . write ( 'Run' ) except Exception as e : log . warning ( 'Write to kpfmot.AGITATOR failed' ) log . debug ( e ) log . warning ( 'Retrying' ) time . sleep ( 1 ) agitator . write ( 'Run' ) time . sleep ( startup ) @classmethod def post_condition ( cls , args , logger , cfg ): startup = cfg . getfloat ( 'times' , 'agitator_startup_time' , fallback = 0.325 ) success = ktl . waitFor ( '$kpfmot.AGITATOR == Running' , timeout = 5 * startup ) if success is not True : agitator = ktl . cache ( 'kpfmot' , 'AGITATOR' ) raise FailedToReachDestination ( agitator . read (), 'Running' )","title":"StartAgitator"},{"location":"scripts/StartAgitator/#startagitator","text":"Bases: KPFTranslatorFunction Start the agitator motion and wait the appropriate startup time before returning.","title":"StartAgitator"},{"location":"scripts/StartAgitator/#kpf.spectrograph.StartAgitator.StartAgitator--args","text":"None Source code in kpf/spectrograph/StartAgitator.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class StartAgitator ( KPFTranslatorFunction ): '''Start the agitator motion and wait the appropriate startup time before returning. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): agitator = ktl . cache ( 'kpfmot' , 'AGITATOR' ) if agitator . read () == 'Running' : log . debug ( 'Agitator is running' ) else : startup = cfg . getfloat ( 'times' , 'agitator_startup_time' , fallback = 0.325 ) log . debug ( 'Starting agitator motion' ) try : agitator . write ( 'Run' ) except Exception as e : log . warning ( 'Write to kpfmot.AGITATOR failed' ) log . debug ( e ) log . warning ( 'Retrying' ) time . sleep ( 1 ) agitator . write ( 'Run' ) time . sleep ( startup ) @classmethod def post_condition ( cls , args , logger , cfg ): startup = cfg . getfloat ( 'times' , 'agitator_startup_time' , fallback = 0.325 ) success = ktl . waitFor ( '$kpfmot.AGITATOR == Running' , timeout = 5 * startup ) if success is not True : agitator = ktl . cache ( 'kpfmot' , 'AGITATOR' ) raise FailedToReachDestination ( agitator . read (), 'Running' )","title":"ARGS:"},{"location":"scripts/StartExposure/","text":"StartExposure Bases: KPFTranslatorFunction Begins an triggered exposure by setting the kpfexpose.EXPOSE keyword to Start. This will return immediately after. Use commands like WaitForReadout or WaitForReady to determine when an exposure is done. ARGS: None Source code in kpf/spectrograph/StartExposure.py 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class StartExposure ( KPFTranslatorFunction ): '''Begins an triggered exposure by setting the `kpfexpose.EXPOSE` keyword to Start. This will return immediately after. Use commands like WaitForReadout or WaitForReady to determine when an exposure is done. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): expose = ktl . cache ( 'kpfexpose' , 'EXPOSE' ) WaitForReady . execute ({}) log . debug ( f \"Beginning Exposure\" ) expose . write ( 'Start' ) @classmethod def post_condition ( cls , args , logger , cfg ): expr = f \"(kpfexpose.EXPOSE != Start)\" kpfexpose = ktl . cache ( 'kpfexpose' ) is_GREEN_ENABLED = ktl . cache ( 'kpfconfig' , 'GREEN_ENABLED' ) . read () == 'Yes' is_RED_ENABLED = ktl . cache ( 'kpfconfig' , 'RED_ENABLED' ) . read () == 'Yes' is_CA_HK_ENABLED = ktl . cache ( 'kpfconfig' , 'CA_HK_ENABLED' ) . read () == 'Yes' trig_targ = kpfexpose [ 'TRIG_TARG' ] . read () . split ( ',' ) if 'Green' in trig_targ and is_GREEN_ENABLED : expr += ' and ($kpfgreen.EXPSTATE != Start)' if 'Red' in trig_targ and is_RED_ENABLED : expr += ' and ($kpfred.EXPSTATE != Start)' if 'Ca_HK' in trig_targ and is_CA_HK_ENABLED : expr += ' and ($kpf_hk.EXPSTATE != Start)' exptime = kpfexpose [ 'EXPOSURE' ] . read ( binary = True ) timeout = 6 left_start_state = ktl . waitFor ( expr , timeout = timeout ) if left_start_state is False : log . error ( f 'We are still in start state after { timeout } s' ) # Figure out which detector is stuck in the start state? if is_GREEN_ENABLED : green_expstate = ktl . cache ( 'kpfgreen' , 'EXPSTATE' ) . read () log . debug ( f 'kpfgreen.EXPSTATE = { green_expstate } ' ) if is_RED_ENABLED : red_expstate = ktl . cache ( 'kpfred' , 'EXPSTATE' ) . read () log . debug ( f 'kpfred.EXPSTATE = { red_expstate } ' ) if is_CA_HK_ENABLED : cahk_expstate = ktl . cache ( 'kpf_hk' , 'EXPSTATE' ) . read () log . debug ( f 'kpf_hk.EXPSTATE = { cahk_expstate } ' ) # Abort the current exposure elapsed = kpfexpose [ 'ELAPSED' ] . read ( binary = True ) remaining = exptime - elapsed if remaining <= 10 : # Don't stop exposure, just wait it out log . debug ( f 'Waiting out remaining { remaining } s of exposure' ) time . sleep ( remaining + 2 ) else : log . warning ( 'Stopping current exposure (with read out)' ) kpfexpose [ 'EXPOSE' ] . write ( 'End' ) time . sleep ( 2 ) # Time shim, this time is a WAG # Now reset the offending detector if is_GREEN_ENABLED : if green_expstate == 'Start' : ResetGreenDetector . execute ({}) if is_RED_ENABLED : if red_expstate == 'Start' : ResetRedDetector . execute ({}) if is_CA_HK_ENABLED : if cahk_expstate == 'Start' : ResetCaHKDetector . execute ({}) # Now start a fresh exposure WaitForReady . execute ({}) time . sleep ( 1.0 ) # This time shim and the WaitForReady are hacks to catch if the WaitForReady . execute ({}) # reset detector went in to readout, but we didn't know. log . warning ( 'Restarting exposure' ) StartExposure . execute ( args )","title":"StartExposure"},{"location":"scripts/StartExposure/#startexposure","text":"Bases: KPFTranslatorFunction Begins an triggered exposure by setting the kpfexpose.EXPOSE keyword to Start. This will return immediately after. Use commands like WaitForReadout or WaitForReady to determine when an exposure is done.","title":"StartExposure"},{"location":"scripts/StartExposure/#kpf.spectrograph.StartExposure.StartExposure--args","text":"None Source code in kpf/spectrograph/StartExposure.py 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class StartExposure ( KPFTranslatorFunction ): '''Begins an triggered exposure by setting the `kpfexpose.EXPOSE` keyword to Start. This will return immediately after. Use commands like WaitForReadout or WaitForReady to determine when an exposure is done. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): expose = ktl . cache ( 'kpfexpose' , 'EXPOSE' ) WaitForReady . execute ({}) log . debug ( f \"Beginning Exposure\" ) expose . write ( 'Start' ) @classmethod def post_condition ( cls , args , logger , cfg ): expr = f \"(kpfexpose.EXPOSE != Start)\" kpfexpose = ktl . cache ( 'kpfexpose' ) is_GREEN_ENABLED = ktl . cache ( 'kpfconfig' , 'GREEN_ENABLED' ) . read () == 'Yes' is_RED_ENABLED = ktl . cache ( 'kpfconfig' , 'RED_ENABLED' ) . read () == 'Yes' is_CA_HK_ENABLED = ktl . cache ( 'kpfconfig' , 'CA_HK_ENABLED' ) . read () == 'Yes' trig_targ = kpfexpose [ 'TRIG_TARG' ] . read () . split ( ',' ) if 'Green' in trig_targ and is_GREEN_ENABLED : expr += ' and ($kpfgreen.EXPSTATE != Start)' if 'Red' in trig_targ and is_RED_ENABLED : expr += ' and ($kpfred.EXPSTATE != Start)' if 'Ca_HK' in trig_targ and is_CA_HK_ENABLED : expr += ' and ($kpf_hk.EXPSTATE != Start)' exptime = kpfexpose [ 'EXPOSURE' ] . read ( binary = True ) timeout = 6 left_start_state = ktl . waitFor ( expr , timeout = timeout ) if left_start_state is False : log . error ( f 'We are still in start state after { timeout } s' ) # Figure out which detector is stuck in the start state? if is_GREEN_ENABLED : green_expstate = ktl . cache ( 'kpfgreen' , 'EXPSTATE' ) . read () log . debug ( f 'kpfgreen.EXPSTATE = { green_expstate } ' ) if is_RED_ENABLED : red_expstate = ktl . cache ( 'kpfred' , 'EXPSTATE' ) . read () log . debug ( f 'kpfred.EXPSTATE = { red_expstate } ' ) if is_CA_HK_ENABLED : cahk_expstate = ktl . cache ( 'kpf_hk' , 'EXPSTATE' ) . read () log . debug ( f 'kpf_hk.EXPSTATE = { cahk_expstate } ' ) # Abort the current exposure elapsed = kpfexpose [ 'ELAPSED' ] . read ( binary = True ) remaining = exptime - elapsed if remaining <= 10 : # Don't stop exposure, just wait it out log . debug ( f 'Waiting out remaining { remaining } s of exposure' ) time . sleep ( remaining + 2 ) else : log . warning ( 'Stopping current exposure (with read out)' ) kpfexpose [ 'EXPOSE' ] . write ( 'End' ) time . sleep ( 2 ) # Time shim, this time is a WAG # Now reset the offending detector if is_GREEN_ENABLED : if green_expstate == 'Start' : ResetGreenDetector . execute ({}) if is_RED_ENABLED : if red_expstate == 'Start' : ResetRedDetector . execute ({}) if is_CA_HK_ENABLED : if cahk_expstate == 'Start' : ResetCaHKDetector . execute ({}) # Now start a fresh exposure WaitForReady . execute ({}) time . sleep ( 1.0 ) # This time shim and the WaitForReady are hacks to catch if the WaitForReady . execute ({}) # reset detector went in to readout, but we didn't know. log . warning ( 'Restarting exposure' ) StartExposure . execute ( args )","title":"ARGS:"},{"location":"scripts/StartGUIs/","text":"StartGUIs Bases: KPFTranslatorFunction Start KPF GUIs ARGS None Source code in kpf/utils/StartGUIs.py 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 class StartGUIs ( KPFTranslatorFunction ): '''Start KPF GUIs ### ARGS None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # Get DISPLAY varibales env = os . environ uidisp = {} # for dispno in [0, 1, 2, 3]: # uidisp_proc = subprocess.run(['uidisp', f'{dispno}'], env=env, # stdout=subprocess.PIPE) # uidisp[dispno] = uidisp_proc.stdout.decode().strip('\\n') kvncstatus_proc = subprocess . run ([ 'kvncstatus' ], env = env , stdout = subprocess . PIPE ) kvncstatus = Table . read ( kvncstatus_proc . stdout . decode (), format = 'ascii' ) username = os . getlogin () display = { 'control0' : kvncstatus [ kvncstatus [ 'Desktop' ] == f 'kpf- { username } -control0' ][ 'Display' ][ 0 ], 'control1' : kvncstatus [ kvncstatus [ 'Desktop' ] == f 'kpf- { username } -control1' ][ 'Display' ][ 0 ], 'control2' : kvncstatus [ kvncstatus [ 'Desktop' ] == f 'kpf- { username } -control2' ][ 'Display' ][ 0 ], 'telstatus' : kvncstatus [ kvncstatus [ 'Desktop' ] == f 'kpf- { username } -telstatus' ][ 'Display' ][ 0 ], } # Start GUIs if needed for GUI in GUI_list : # Find out of GUIs are Running log . debug ( f \"Setting DISPLAY to kpf { display [ GUI [ 'display' ]] } \" ) env [ 'DISPLAY' ] = f \"kpf { display [ GUI [ 'display' ]] } \" window_names = get_window_list ( env = env ) GUIname = GUI [ 'name' ] if GUIname not in window_names and args . get ( 'position_only' , False ) is False : instrume = ktl . cache ( 'dcs1' , 'INSTRUME' ) if GUIname == 'MAGIQ - Observer UI: KPF on Keck1' and instrume . read () != 'KPF' : log . info ( f 'Selected instrument is not KPF, not starting magiq' ) success = False else : log . info ( f \"Starting ' { GUIname } ' GUI\" ) gui_proc = subprocess . Popen ( GUI [ 'cmd' ], env = env , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) success = waitfor_window_to_appear ( GUIname , env = env ) if success is False : log . error ( f ' { GUIname } did not come up' ) stdout , stderr = gui_proc . communicate () log . error ( f \"STDERR: { stderr . decode () } \" ) log . error ( f \"STDOUT: { stdout . decode () } \" ) else : log . info ( f \"Existing ' { GUIname } ' window found\" ) success = True time . sleep ( 2 ) if GUI . get ( 'position' , None ) is not None and success is True : log . info ( f \"Positioning ' { GUIname } ' GUI\" ) wmctrl_cmd = [ 'wmctrl' , '-r' , f '\" { GUIname } \"' , '-e' , GUI [ 'position' ]] log . debug ( f \" Running: { ' ' . join ( wmctrl_cmd ) } \" ) wmctrl_proc = subprocess . run ( ' ' . join ( wmctrl_cmd ), env = env , shell = True ) if GUI [ 'cmd' ][ 0 ] == 'xterm' : xterm_title = GUI [ 'cmd' ][ 2 ] success = waitfor_window_to_appear ( xterm_title , env = env ) log . info ( f \"Minimizing ' { xterm_title } '\" ) wmctrl_cmd = [ 'wmctrl' , '-r' , xterm_title , '-b' , 'add,hidden' ] wmctrl_proc = subprocess . run ( ' ' . join ( wmctrl_cmd ), env = env , shell = True ) if GUIname == 'SAOImage kpfds9' : # Configure ds9 initial color maps and scaling cmaps = { '1' : 'cool' , '2' : 'green' , '3' : 'heat' } for frameno in cmaps . keys (): xpaset_cmds = [[ 'xpaset' , '-p' , 'kpfds9' , 'frame' , 'frameno' , f ' { frameno } ' ], [ 'xpaset' , '-p' , 'kpfds9' , 'cmap' , f ' { cmaps [ frameno ] } ' ], [ 'xpaset' , '-p' , 'kpfds9' , 'scale' , '99.5' ]] for xpaset_cmd in xpaset_cmds : xpa_proc = subprocess . Popen ( xpaset_cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) time . sleep ( 1 ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--position\" , \"-p\" , dest = \"position_only\" , default = False , action = \"store_true\" , help = \"Only position the GUIs, do not start\" ) return super () . add_cmdline_args ( parser , cfg )","title":"StartGUIs"},{"location":"scripts/StartGUIs/#startguis","text":"Bases: KPFTranslatorFunction Start KPF GUIs","title":"StartGUIs"},{"location":"scripts/StartGUIs/#kpf.utils.StartGUIs.StartGUIs--args","text":"None Source code in kpf/utils/StartGUIs.py 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 class StartGUIs ( KPFTranslatorFunction ): '''Start KPF GUIs ### ARGS None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # Get DISPLAY varibales env = os . environ uidisp = {} # for dispno in [0, 1, 2, 3]: # uidisp_proc = subprocess.run(['uidisp', f'{dispno}'], env=env, # stdout=subprocess.PIPE) # uidisp[dispno] = uidisp_proc.stdout.decode().strip('\\n') kvncstatus_proc = subprocess . run ([ 'kvncstatus' ], env = env , stdout = subprocess . PIPE ) kvncstatus = Table . read ( kvncstatus_proc . stdout . decode (), format = 'ascii' ) username = os . getlogin () display = { 'control0' : kvncstatus [ kvncstatus [ 'Desktop' ] == f 'kpf- { username } -control0' ][ 'Display' ][ 0 ], 'control1' : kvncstatus [ kvncstatus [ 'Desktop' ] == f 'kpf- { username } -control1' ][ 'Display' ][ 0 ], 'control2' : kvncstatus [ kvncstatus [ 'Desktop' ] == f 'kpf- { username } -control2' ][ 'Display' ][ 0 ], 'telstatus' : kvncstatus [ kvncstatus [ 'Desktop' ] == f 'kpf- { username } -telstatus' ][ 'Display' ][ 0 ], } # Start GUIs if needed for GUI in GUI_list : # Find out of GUIs are Running log . debug ( f \"Setting DISPLAY to kpf { display [ GUI [ 'display' ]] } \" ) env [ 'DISPLAY' ] = f \"kpf { display [ GUI [ 'display' ]] } \" window_names = get_window_list ( env = env ) GUIname = GUI [ 'name' ] if GUIname not in window_names and args . get ( 'position_only' , False ) is False : instrume = ktl . cache ( 'dcs1' , 'INSTRUME' ) if GUIname == 'MAGIQ - Observer UI: KPF on Keck1' and instrume . read () != 'KPF' : log . info ( f 'Selected instrument is not KPF, not starting magiq' ) success = False else : log . info ( f \"Starting ' { GUIname } ' GUI\" ) gui_proc = subprocess . Popen ( GUI [ 'cmd' ], env = env , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) success = waitfor_window_to_appear ( GUIname , env = env ) if success is False : log . error ( f ' { GUIname } did not come up' ) stdout , stderr = gui_proc . communicate () log . error ( f \"STDERR: { stderr . decode () } \" ) log . error ( f \"STDOUT: { stdout . decode () } \" ) else : log . info ( f \"Existing ' { GUIname } ' window found\" ) success = True time . sleep ( 2 ) if GUI . get ( 'position' , None ) is not None and success is True : log . info ( f \"Positioning ' { GUIname } ' GUI\" ) wmctrl_cmd = [ 'wmctrl' , '-r' , f '\" { GUIname } \"' , '-e' , GUI [ 'position' ]] log . debug ( f \" Running: { ' ' . join ( wmctrl_cmd ) } \" ) wmctrl_proc = subprocess . run ( ' ' . join ( wmctrl_cmd ), env = env , shell = True ) if GUI [ 'cmd' ][ 0 ] == 'xterm' : xterm_title = GUI [ 'cmd' ][ 2 ] success = waitfor_window_to_appear ( xterm_title , env = env ) log . info ( f \"Minimizing ' { xterm_title } '\" ) wmctrl_cmd = [ 'wmctrl' , '-r' , xterm_title , '-b' , 'add,hidden' ] wmctrl_proc = subprocess . run ( ' ' . join ( wmctrl_cmd ), env = env , shell = True ) if GUIname == 'SAOImage kpfds9' : # Configure ds9 initial color maps and scaling cmaps = { '1' : 'cool' , '2' : 'green' , '3' : 'heat' } for frameno in cmaps . keys (): xpaset_cmds = [[ 'xpaset' , '-p' , 'kpfds9' , 'frame' , 'frameno' , f ' { frameno } ' ], [ 'xpaset' , '-p' , 'kpfds9' , 'cmap' , f ' { cmaps [ frameno ] } ' ], [ 'xpaset' , '-p' , 'kpfds9' , 'scale' , '99.5' ]] for xpaset_cmd in xpaset_cmds : xpa_proc = subprocess . Popen ( xpaset_cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) time . sleep ( 1 ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--position\" , \"-p\" , dest = \"position_only\" , default = False , action = \"store_true\" , help = \"Only position the GUIs, do not start\" ) return super () . add_cmdline_args ( parser , cfg )","title":"ARGS"},{"location":"scripts/StartGuiderContinuous/","text":"StartGuiderContinuous Bases: KPFTranslatorFunction Put the guider in to continuous exposure mode and set images to be saved. KTL Keywords Used: kpfguide.CONTINUOUS kpfguide.SAVE Source code in kpf/guider/StartGuiderContinuous.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class StartGuiderContinuous ( KPFTranslatorFunction ): '''Put the guider in to continuous exposure mode and set images to be saved. KTL Keywords Used: - `kpfguide.CONTINUOUS` - `kpfguide.SAVE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) kpfguide [ 'CONTINUOUS' ] . write ( 'active' ) kpfguide [ 'SAVE' ] . write ( 'active' ) @classmethod def post_condition ( cls , args , logger , cfg ): if guider_is_active () == False : raise FailedPostCondition ( 'Guider is not active' ) if guider_is_saving () == False : raise FailedPostCondition ( 'Guider is not saving' )","title":"StartGuiderContinuous"},{"location":"scripts/StartGuiderContinuous/#startguidercontinuous","text":"Bases: KPFTranslatorFunction Put the guider in to continuous exposure mode and set images to be saved. KTL Keywords Used: kpfguide.CONTINUOUS kpfguide.SAVE Source code in kpf/guider/StartGuiderContinuous.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class StartGuiderContinuous ( KPFTranslatorFunction ): '''Put the guider in to continuous exposure mode and set images to be saved. KTL Keywords Used: - `kpfguide.CONTINUOUS` - `kpfguide.SAVE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) kpfguide [ 'CONTINUOUS' ] . write ( 'active' ) kpfguide [ 'SAVE' ] . write ( 'active' ) @classmethod def post_condition ( cls , args , logger , cfg ): if guider_is_active () == False : raise FailedPostCondition ( 'Guider is not active' ) if guider_is_saving () == False : raise FailedPostCondition ( 'Guider is not saving' )","title":"StartGuiderContinuous"},{"location":"scripts/StartOfNight/","text":"StartOfNight Bases: KPFTranslatorFunction Send KPF in to a reasonable starting configuration set FIU mode to observing Setup AO for KPF Configure DCS (ROTDEST and ROTMODE) ARGS: AO - bool Open AO hatch, send PCU to KPF, and turn on HEPA? (default=True) Source code in kpf/scripts/StartOfNight.py 24 25 26 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 class StartOfNight ( KPFTranslatorFunction ): '''Send KPF in to a reasonable starting configuration - set FIU mode to observing - Setup AO for KPF - Configure DCS (ROTDEST and ROTMODE) ARGS: ===== * __AO__ - `bool` Open AO hatch, send PCU to KPF, and turn on HEPA? (default=True) ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , args , logger , cfg ): log . info ( f \"Running KPF Start of Night script\" ) # Check Scripts kpfconfig = ktl . cache ( 'kpfconfig' ) expose = ktl . cache ( 'kpfexpose' , 'EXPOSE' ) scriptname = kpfconfig [ 'SCRIPTNAME' ] . read () pid = kpfconfig [ 'SCRIPTPID' ] . read ( binary = True ) if scriptname not in [ '' , 'None' , None ] or pid >= 0 : # --------------------------------- # User Verification # --------------------------------- msg = [ \"\" , \"--------------------------------------------------------------\" , f \"A script ( { scriptname } , { pid } ) is currently running. \" , \"\" , \"Depending on when you are seeing this, it may be a scheduled\" , \"nighttime calibration which can and should be interrupted to\" , \"enable observing.\" , \"\" , \"Do you wish to end the current exposure and request a script\" , \"stop in order to proceed with running StartOfNight?\" , \"\" , \"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 Start 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 () # --------------------------------- # Remaining non-AO Actions # --------------------------------- # Disallow cron job calibration scripts log . info ( 'Set ALLOWSCHEDULEDCALS to No' ) kpfconfig = ktl . cache ( 'kpfconfig' ) kpfconfig [ 'ALLOWSCHEDULEDCALS' ] . write ( 'No' ) # Configure FIU log . info ( 'Configure FIU for \"Observing\"' ) ConfigureFIU . execute ({ 'mode' : 'Observing' }) # Set DCS rotator parameters dcs = ktl . cache ( 'dcs1' ) inst = dcs [ 'INSTRUME' ] . read () if inst == 'KPF' : log . info ( f \"Setting dcs.ROTDEST = 0\" ) dcs [ 'ROTDEST' ] . write ( 0 ) log . info ( f \"Setting dcs.ROTMODE = stationary\" ) dcs [ 'ROTMODE' ] . write ( 'stationary' ) else : log . warning ( f \"Instrument is { inst } , not configuring DCS\" ) # Report Agitator status runagitator = kpfconfig [ 'USEAGITATOR' ] . read ( binary = True ) if runagitator is True : log . info ( f \"Agitator use is enabled\" ) else : log . warning ( f \"Agitator use is disabled for tonight\" ) # Pre-configure cal source calsource = kpfconfig [ 'SIMULCALSOURCE' ] . read () log . info ( f \"Setting simultaneous CalSource/Octagon: { calsource } \" ) SetCalSource . execute ({ 'CalSource' : calsource , 'wait' : True }) # Power on Simulcal lamp if needed if calsource in [ 'U_gold' , 'U_daily' , 'Th_daily' , 'Th_gold' ]: CalLampPower . execute ({ 'lamp' : calsource , 'power' : 'on' }) # Set tip tilt loop gain to default value kpfguide = ktl . cache ( 'kpfguide' ) tip_tilt_gain = cfg . getfloat ( 'tiptilt' , 'tiptilt_loop_gain' , fallback = 0.3 ) log . info ( f \"Setting default tip tilt loop gain of { tip_tilt_gain } \" ) SetTipTiltGain . execute ({ 'GuideLoopGain' : tip_tilt_gain }) # Set tip tilt loop detection threshold to default value detect_snr = cfg . getfloat ( 'tiptilt' , 'detect_snr' , fallback = 7 ) log . info ( f \"Setting default tip tilt detection SNR of { detect_snr } \" ) kpfguide [ 'OBJECT_INTENSITY' ] . write ( detect_snr ) # Set tip tilt loop detection area to default value detect_area = cfg . getfloat ( 'tiptilt' , 'detect_area' , fallback = 100 ) log . info ( f \"Setting default tip tilt detection area of { detect_area } \" ) kpfguide [ 'OBJECT_AREA' ] . write ( detect_area ) # Set tip tilt loop deblend parameter to default value deblend = cfg . getfloat ( 'tiptilt' , 'deblend' , fallback = 1 ) log . info ( f \"Setting default tip tilt deblending parameter of { deblend } \" ) kpfguide [ 'OBJECT_DBCONT' ] . write ( 1.0 ) # Set DAR parameter to default value log . info ( f \"Ensuring DAR correction is on\" ) kpfguide [ 'DAR_ENABLE' ] . write ( 'Yes' ) # Set Outdirs if expose . read () != 'Ready' : log . info ( 'Waiting for kpfexpose to be Ready' ) WaitForReady . execute ({}) SetOutdirs . execute ({}) # Set guider gain to high for initial acquisition and focus SetGuiderGain . execute ({ 'GuideCamGain' : 'high' }) # Set progname and observer SetObserverFromSchedule . execute ({}) # Summarize Detector Disabled States cahk_enabled = kpfconfig [ 'CA_HK_ENABLED' ] . read ( binary = True ) if cahk_enabled is False : log . warning ( f \"The CA_HK detector is disabled tonight\" ) green_enabled = kpfconfig [ 'GREEN_ENABLED' ] . read ( binary = True ) if green_enabled is False : log . warning ( f \"The Green detector is disabled tonight\" ) red_enabled = kpfconfig [ 'RED_ENABLED' ] . read ( binary = True ) if red_enabled is False : log . warning ( f \"The Red detector is disabled tonight\" ) expmeter_enabled = kpfconfig [ 'EXPMETER_ENABLED' ] . read ( binary = True ) if expmeter_enabled is False : log . warning ( f \"The ExpMeter detector is disabled tonight\" ) # Setup AO if args . get ( 'AO' , True ) is True : # --------------------------------- # User Verification # --------------------------------- msg = [ \"\" , \"--------------------------------------------------------------\" , \"This script will configure the FIU and AO bench for observing.\" , \"The AO bench area should be clear of personnel before proceeding.\" , \"Do you wish to to continue?\" , \"(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 Start Of Night' ) return else : SetupAOforKPF . execute ({}) log . info ( 'Open AO hatch' ) try : ControlAOHatch . execute ({ 'destination' : 'open' }) except FailedToReachDestination : log . error ( f \"AO hatch did not move successfully\" ) print () print ( '----------------------------------------------------------' ) print ( 'AO hatch reported problems moving. Make sure stars are' ) print ( 'visible on guide camera before proceeding.' ) print ( '----------------------------------------------------------' ) print () @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--noAO\" , dest = \"AO\" , default = True , action = \"store_false\" , help = \"Skip configuring AO?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"StartOfNight"},{"location":"scripts/StartOfNight/#startofnight","text":"Bases: KPFTranslatorFunction Send KPF in to a reasonable starting configuration set FIU mode to observing Setup AO for KPF Configure DCS (ROTDEST and ROTMODE)","title":"StartOfNight"},{"location":"scripts/StartOfNight/#kpf.scripts.StartOfNight.StartOfNight--args","text":"AO - bool Open AO hatch, send PCU to KPF, and turn on HEPA? (default=True) Source code in kpf/scripts/StartOfNight.py 24 25 26 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 class StartOfNight ( KPFTranslatorFunction ): '''Send KPF in to a reasonable starting configuration - set FIU mode to observing - Setup AO for KPF - Configure DCS (ROTDEST and ROTMODE) ARGS: ===== * __AO__ - `bool` Open AO hatch, send PCU to KPF, and turn on HEPA? (default=True) ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , args , logger , cfg ): log . info ( f \"Running KPF Start of Night script\" ) # Check Scripts kpfconfig = ktl . cache ( 'kpfconfig' ) expose = ktl . cache ( 'kpfexpose' , 'EXPOSE' ) scriptname = kpfconfig [ 'SCRIPTNAME' ] . read () pid = kpfconfig [ 'SCRIPTPID' ] . read ( binary = True ) if scriptname not in [ '' , 'None' , None ] or pid >= 0 : # --------------------------------- # User Verification # --------------------------------- msg = [ \"\" , \"--------------------------------------------------------------\" , f \"A script ( { scriptname } , { pid } ) is currently running. \" , \"\" , \"Depending on when you are seeing this, it may be a scheduled\" , \"nighttime calibration which can and should be interrupted to\" , \"enable observing.\" , \"\" , \"Do you wish to end the current exposure and request a script\" , \"stop in order to proceed with running StartOfNight?\" , \"\" , \"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 Start 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 () # --------------------------------- # Remaining non-AO Actions # --------------------------------- # Disallow cron job calibration scripts log . info ( 'Set ALLOWSCHEDULEDCALS to No' ) kpfconfig = ktl . cache ( 'kpfconfig' ) kpfconfig [ 'ALLOWSCHEDULEDCALS' ] . write ( 'No' ) # Configure FIU log . info ( 'Configure FIU for \"Observing\"' ) ConfigureFIU . execute ({ 'mode' : 'Observing' }) # Set DCS rotator parameters dcs = ktl . cache ( 'dcs1' ) inst = dcs [ 'INSTRUME' ] . read () if inst == 'KPF' : log . info ( f \"Setting dcs.ROTDEST = 0\" ) dcs [ 'ROTDEST' ] . write ( 0 ) log . info ( f \"Setting dcs.ROTMODE = stationary\" ) dcs [ 'ROTMODE' ] . write ( 'stationary' ) else : log . warning ( f \"Instrument is { inst } , not configuring DCS\" ) # Report Agitator status runagitator = kpfconfig [ 'USEAGITATOR' ] . read ( binary = True ) if runagitator is True : log . info ( f \"Agitator use is enabled\" ) else : log . warning ( f \"Agitator use is disabled for tonight\" ) # Pre-configure cal source calsource = kpfconfig [ 'SIMULCALSOURCE' ] . read () log . info ( f \"Setting simultaneous CalSource/Octagon: { calsource } \" ) SetCalSource . execute ({ 'CalSource' : calsource , 'wait' : True }) # Power on Simulcal lamp if needed if calsource in [ 'U_gold' , 'U_daily' , 'Th_daily' , 'Th_gold' ]: CalLampPower . execute ({ 'lamp' : calsource , 'power' : 'on' }) # Set tip tilt loop gain to default value kpfguide = ktl . cache ( 'kpfguide' ) tip_tilt_gain = cfg . getfloat ( 'tiptilt' , 'tiptilt_loop_gain' , fallback = 0.3 ) log . info ( f \"Setting default tip tilt loop gain of { tip_tilt_gain } \" ) SetTipTiltGain . execute ({ 'GuideLoopGain' : tip_tilt_gain }) # Set tip tilt loop detection threshold to default value detect_snr = cfg . getfloat ( 'tiptilt' , 'detect_snr' , fallback = 7 ) log . info ( f \"Setting default tip tilt detection SNR of { detect_snr } \" ) kpfguide [ 'OBJECT_INTENSITY' ] . write ( detect_snr ) # Set tip tilt loop detection area to default value detect_area = cfg . getfloat ( 'tiptilt' , 'detect_area' , fallback = 100 ) log . info ( f \"Setting default tip tilt detection area of { detect_area } \" ) kpfguide [ 'OBJECT_AREA' ] . write ( detect_area ) # Set tip tilt loop deblend parameter to default value deblend = cfg . getfloat ( 'tiptilt' , 'deblend' , fallback = 1 ) log . info ( f \"Setting default tip tilt deblending parameter of { deblend } \" ) kpfguide [ 'OBJECT_DBCONT' ] . write ( 1.0 ) # Set DAR parameter to default value log . info ( f \"Ensuring DAR correction is on\" ) kpfguide [ 'DAR_ENABLE' ] . write ( 'Yes' ) # Set Outdirs if expose . read () != 'Ready' : log . info ( 'Waiting for kpfexpose to be Ready' ) WaitForReady . execute ({}) SetOutdirs . execute ({}) # Set guider gain to high for initial acquisition and focus SetGuiderGain . execute ({ 'GuideCamGain' : 'high' }) # Set progname and observer SetObserverFromSchedule . execute ({}) # Summarize Detector Disabled States cahk_enabled = kpfconfig [ 'CA_HK_ENABLED' ] . read ( binary = True ) if cahk_enabled is False : log . warning ( f \"The CA_HK detector is disabled tonight\" ) green_enabled = kpfconfig [ 'GREEN_ENABLED' ] . read ( binary = True ) if green_enabled is False : log . warning ( f \"The Green detector is disabled tonight\" ) red_enabled = kpfconfig [ 'RED_ENABLED' ] . read ( binary = True ) if red_enabled is False : log . warning ( f \"The Red detector is disabled tonight\" ) expmeter_enabled = kpfconfig [ 'EXPMETER_ENABLED' ] . read ( binary = True ) if expmeter_enabled is False : log . warning ( f \"The ExpMeter detector is disabled tonight\" ) # Setup AO if args . get ( 'AO' , True ) is True : # --------------------------------- # User Verification # --------------------------------- msg = [ \"\" , \"--------------------------------------------------------------\" , \"This script will configure the FIU and AO bench for observing.\" , \"The AO bench area should be clear of personnel before proceeding.\" , \"Do you wish to to continue?\" , \"(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 Start Of Night' ) return else : SetupAOforKPF . execute ({}) log . info ( 'Open AO hatch' ) try : ControlAOHatch . execute ({ 'destination' : 'open' }) except FailedToReachDestination : log . error ( f \"AO hatch did not move successfully\" ) print () print ( '----------------------------------------------------------' ) print ( 'AO hatch reported problems moving. Make sure stars are' ) print ( 'visible on guide camera before proceeding.' ) print ( '----------------------------------------------------------' ) print () @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--noAO\" , dest = \"AO\" , default = True , action = \"store_false\" , help = \"Skip configuring AO?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"ARGS:"},{"location":"scripts/StartTipTilt/","text":"StartTipTilt Bases: KPFTranslatorFunction Start the tip tilt control loop. This uses the ALL_LOOPS keyword to start all functions including DAR (via DAR_ENABLE), tip tilt calculations (via TIPTILT_CALC), tip tilt control (via TIPTILT_CONTROL), offloading to the telescope (via OFFLOAD_DCS and OFFLOAD). KTL Keywords Used: kpffiu.TTXSRV kpffiu.TTYSRV kpfguide.DAR_ENABLE kpfguide.ALL_LOOPS Source code in kpf/fiu/StartTipTilt.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class StartTipTilt ( KPFTranslatorFunction ): '''Start the tip tilt control loop. This uses the ALL_LOOPS keyword to start all functions including DAR (via DAR_ENABLE), tip tilt calculations (via TIPTILT_CALC), tip tilt control (via TIPTILT_CONTROL), offloading to the telescope (via OFFLOAD_DCS and OFFLOAD). KTL Keywords Used: - `kpffiu.TTXSRV` - `kpffiu.TTYSRV` - `kpfguide.DAR_ENABLE` - `kpfguide.ALL_LOOPS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): expr = \"($kpffiu.TTXSRV == 'Closed') and ($kpffiu.TTYSRV == 'Closed')\" servo_loops_closed = ktl . waitFor ( expr , timeout = 0.5 ) if not servo_loops_closed : kpffiu = ktl . cache ( 'kpffiu' ) log . info ( 'Closing servo loops' ) kpffiu [ 'TTXSRV' ] . write ( 'Closed' ) kpffiu [ 'TTYSRV' ] . write ( 'Closed' ) movetime = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) time . sleep ( 10 * movetime ) kpfguide = ktl . cache ( 'kpfguide' ) log . info ( 'Turning kpfguide.ALL_LOOPS on' ) kpfguide [ 'ALL_LOOPS' ] . write ( 'Active' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"StartTipTilt"},{"location":"scripts/StartTipTilt/#starttiptilt","text":"Bases: KPFTranslatorFunction Start the tip tilt control loop. This uses the ALL_LOOPS keyword to start all functions including DAR (via DAR_ENABLE), tip tilt calculations (via TIPTILT_CALC), tip tilt control (via TIPTILT_CONTROL), offloading to the telescope (via OFFLOAD_DCS and OFFLOAD). KTL Keywords Used: kpffiu.TTXSRV kpffiu.TTYSRV kpfguide.DAR_ENABLE kpfguide.ALL_LOOPS Source code in kpf/fiu/StartTipTilt.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class StartTipTilt ( KPFTranslatorFunction ): '''Start the tip tilt control loop. This uses the ALL_LOOPS keyword to start all functions including DAR (via DAR_ENABLE), tip tilt calculations (via TIPTILT_CALC), tip tilt control (via TIPTILT_CONTROL), offloading to the telescope (via OFFLOAD_DCS and OFFLOAD). KTL Keywords Used: - `kpffiu.TTXSRV` - `kpffiu.TTYSRV` - `kpfguide.DAR_ENABLE` - `kpfguide.ALL_LOOPS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): expr = \"($kpffiu.TTXSRV == 'Closed') and ($kpffiu.TTYSRV == 'Closed')\" servo_loops_closed = ktl . waitFor ( expr , timeout = 0.5 ) if not servo_loops_closed : kpffiu = ktl . cache ( 'kpffiu' ) log . info ( 'Closing servo loops' ) kpffiu [ 'TTXSRV' ] . write ( 'Closed' ) kpffiu [ 'TTYSRV' ] . write ( 'Closed' ) movetime = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) time . sleep ( 10 * movetime ) kpfguide = ktl . cache ( 'kpfguide' ) log . info ( 'Turning kpfguide.ALL_LOOPS on' ) kpfguide [ 'ALL_LOOPS' ] . write ( 'Active' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"StartTipTilt"},{"location":"scripts/StartTriggerFile/","text":"StartTriggerFile Bases: KPFTranslatorFunction Start a \"trigger file\" from the guide camera. KTL Keywords Used: kpfguide.TRIGCUBE kpfguide.TRIGGER Source code in kpf/guider/StartTriggerFile.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class StartTriggerFile ( KPFTranslatorFunction ): '''Start a \"trigger file\" from the guide camera. KTL Keywords Used: - `kpfguide.TRIGCUBE` - `kpfguide.TRIGGER` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) cube = kpfguide [ 'TRIGCUBE' ] . read () log . info ( f \"Start guider trigger file data collection: TRIGCUBE= { cube } \" ) kpfguide [ 'TRIGGER' ] . write ( 'Active' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"StartTriggerFile"},{"location":"scripts/StartTriggerFile/#starttriggerfile","text":"Bases: KPFTranslatorFunction Start a \"trigger file\" from the guide camera. KTL Keywords Used: kpfguide.TRIGCUBE kpfguide.TRIGGER Source code in kpf/guider/StartTriggerFile.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class StartTriggerFile ( KPFTranslatorFunction ): '''Start a \"trigger file\" from the guide camera. KTL Keywords Used: - `kpfguide.TRIGCUBE` - `kpfguide.TRIGGER` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) cube = kpfguide [ 'TRIGCUBE' ] . read () log . info ( f \"Start guider trigger file data collection: TRIGCUBE= { cube } \" ) kpfguide [ 'TRIGGER' ] . write ( 'Active' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"StartTriggerFile"},{"location":"scripts/StartUp/","text":"StartUp Bases: KPFTranslatorFunction Start KPF software for afternoon setup. ARGS: None Source code in kpf/scripts/StartUp.py 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class StartUp ( KPFTranslatorFunction ): '''Start KPF software for afternoon setup. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # Start GUIs StartGUIs . execute ({}) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"StartUp"},{"location":"scripts/StartUp/#startup","text":"Bases: KPFTranslatorFunction Start KPF software for afternoon setup.","title":"StartUp"},{"location":"scripts/StartUp/#kpf.scripts.StartUp.StartUp--args","text":"None Source code in kpf/scripts/StartUp.py 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class StartUp ( KPFTranslatorFunction ): '''Start KPF software for afternoon setup. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # Start GUIs StartGUIs . execute ({}) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"ARGS:"},{"location":"scripts/StopAgitator/","text":"StopAgitator Bases: KPFTranslatorFunction Stop the agitator motion. ARGS: None Source code in kpf/spectrograph/StopAgitator.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 class StopAgitator ( KPFTranslatorFunction ): '''Stop the agitator motion. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): agitator = ktl . cache ( 'kpfmot' , 'AGITATOR' ) if agitator . read () == 'Stopped' : log . debug ( 'Agitator is stopped' ) else : log . debug ( 'Stopping agitator' ) try : agitator . write ( 'Stop' ) except Exception as e : log . warning ( 'Write to kpfmot.AGITATOR failed' ) log . debug ( e ) log . warning ( 'Retrying' ) time . sleep ( 1 ) agitator . write ( 'Stop' ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'agitator_startup_time' , fallback = 0.325 ) success = ktl . waitFor ( '$kpfmot.AGITATOR == Stopped' , timeout = 5 * timeout ) if success is not True : agitator = ktl . cache ( 'kpfmot' , 'AGITATOR' ) raise FailedToReachDestination ( agitator . read (), 'Stopped' )","title":"StopAgitator"},{"location":"scripts/StopAgitator/#stopagitator","text":"Bases: KPFTranslatorFunction Stop the agitator motion.","title":"StopAgitator"},{"location":"scripts/StopAgitator/#kpf.spectrograph.StopAgitator.StopAgitator--args","text":"None Source code in kpf/spectrograph/StopAgitator.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 class StopAgitator ( KPFTranslatorFunction ): '''Stop the agitator motion. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): agitator = ktl . cache ( 'kpfmot' , 'AGITATOR' ) if agitator . read () == 'Stopped' : log . debug ( 'Agitator is stopped' ) else : log . debug ( 'Stopping agitator' ) try : agitator . write ( 'Stop' ) except Exception as e : log . warning ( 'Write to kpfmot.AGITATOR failed' ) log . debug ( e ) log . warning ( 'Retrying' ) time . sleep ( 1 ) agitator . write ( 'Stop' ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'agitator_startup_time' , fallback = 0.325 ) success = ktl . waitFor ( '$kpfmot.AGITATOR == Stopped' , timeout = 5 * timeout ) if success is not True : agitator = ktl . cache ( 'kpfmot' , 'AGITATOR' ) raise FailedToReachDestination ( agitator . read (), 'Stopped' )","title":"ARGS:"},{"location":"scripts/StopGUIs/","text":"StopGUIs Bases: KPFTranslatorFunction Stop KPF GUIs ARGS None Source code in kpf/utils/StopGUIs.py 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 class StopGUIs ( KPFTranslatorFunction ): '''Stop KPF GUIs ### ARGS None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): for GUI in GUI_list : GUIname = GUI [ 'name' ] if GUI [ 'cmd' ][ 0 ] == 'kpf' : GUIscriptname = GUI [ 'cmd' ][ 2 ] status_cmd = GUI [ 'cmd' ] status_cmd [ 1 ] = 'status' log . info ( f \"Getting status of ' { GUIname } ' GUI\" ) gui_proc = subprocess . run ( status_cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) stdout = gui_proc . stdout . decode () . strip () is_running = re . search ( 'is running on' , stdout ) if is_running is not None : stop_cmd = GUI [ 'cmd' ] stop_cmd [ 1 ] = 'stop' log . info ( f \"Stopping ' { GUIname } ' GUI\" ) stopout = subprocess . run ( stop_cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) log . debug ( f \" { stopout . returncode } \" ) log . debug ( f \" { stopout . stdout . decode () } \" ) log . debug ( f \" { stopout . stderr . decode () } \" ) else : log . info ( f \" { GUIname } is not running\" ) log . debug ( f \" { stdout } \" ) elif GUIname == 'MAGIQ - Observer UI' : log . info ( f \"Stopping ' { GUIname } ' GUI\" ) stop_cmd = GUI [ 'cmd' ] stop_cmd [ 4 ] = 'stop' gui_proc = subprocess . Popen ( stop_cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) else : log . info ( f \"Stopping ' { GUIname } ' GUI\" ) kill_process ( GUI [ 'cmd' ], server = 'kpf' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"StopGUIs"},{"location":"scripts/StopGUIs/#stopguis","text":"Bases: KPFTranslatorFunction Stop KPF GUIs","title":"StopGUIs"},{"location":"scripts/StopGUIs/#kpf.utils.StopGUIs.StopGUIs--args","text":"None Source code in kpf/utils/StopGUIs.py 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 class StopGUIs ( KPFTranslatorFunction ): '''Stop KPF GUIs ### ARGS None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): for GUI in GUI_list : GUIname = GUI [ 'name' ] if GUI [ 'cmd' ][ 0 ] == 'kpf' : GUIscriptname = GUI [ 'cmd' ][ 2 ] status_cmd = GUI [ 'cmd' ] status_cmd [ 1 ] = 'status' log . info ( f \"Getting status of ' { GUIname } ' GUI\" ) gui_proc = subprocess . run ( status_cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) stdout = gui_proc . stdout . decode () . strip () is_running = re . search ( 'is running on' , stdout ) if is_running is not None : stop_cmd = GUI [ 'cmd' ] stop_cmd [ 1 ] = 'stop' log . info ( f \"Stopping ' { GUIname } ' GUI\" ) stopout = subprocess . run ( stop_cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) log . debug ( f \" { stopout . returncode } \" ) log . debug ( f \" { stopout . stdout . decode () } \" ) log . debug ( f \" { stopout . stderr . decode () } \" ) else : log . info ( f \" { GUIname } is not running\" ) log . debug ( f \" { stdout } \" ) elif GUIname == 'MAGIQ - Observer UI' : log . info ( f \"Stopping ' { GUIname } ' GUI\" ) stop_cmd = GUI [ 'cmd' ] stop_cmd [ 4 ] = 'stop' gui_proc = subprocess . Popen ( stop_cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) else : log . info ( f \"Stopping ' { GUIname } ' GUI\" ) kill_process ( GUI [ 'cmd' ], server = 'kpf' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"ARGS"},{"location":"scripts/StopGuiderContinuous/","text":"StopGuiderContinuous Bases: KPFTranslatorFunction Stop the guider's continuous exposure mode and stop saving images. KTL Keywords Used: kpfguide.CONTINUOUS kpfguide.SAVE Source code in kpf/guider/StopGuiderContinuous.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class StopGuiderContinuous ( KPFTranslatorFunction ): '''Stop the guider's continuous exposure mode and stop saving images. KTL Keywords Used: - `kpfguide.CONTINUOUS` - `kpfguide.SAVE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) kpfguide [ 'CONTINUOUS' ] . write ( 'inactive' ) kpfguide [ 'SAVE' ] . write ( 'inactive' ) @classmethod def post_condition ( cls , args , logger , cfg ): if guider_is_active () != False : raise FailedPostCondition ( 'Guider is not inactive' ) if guider_is_saving () != False : raise FailedPostCondition ( 'Guider is still saving' )","title":"StopGuiderContinuous"},{"location":"scripts/StopGuiderContinuous/#stopguidercontinuous","text":"Bases: KPFTranslatorFunction Stop the guider's continuous exposure mode and stop saving images. KTL Keywords Used: kpfguide.CONTINUOUS kpfguide.SAVE Source code in kpf/guider/StopGuiderContinuous.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class StopGuiderContinuous ( KPFTranslatorFunction ): '''Stop the guider's continuous exposure mode and stop saving images. KTL Keywords Used: - `kpfguide.CONTINUOUS` - `kpfguide.SAVE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) kpfguide [ 'CONTINUOUS' ] . write ( 'inactive' ) kpfguide [ 'SAVE' ] . write ( 'inactive' ) @classmethod def post_condition ( cls , args , logger , cfg ): if guider_is_active () != False : raise FailedPostCondition ( 'Guider is not inactive' ) if guider_is_saving () != False : raise FailedPostCondition ( 'Guider is still saving' )","title":"StopGuiderContinuous"},{"location":"scripts/StopTipTilt/","text":"StopTipTilt Bases: KPFTranslatorFunction Stop the tip tilt control loop. This uses the ALL_LOOPS keyword to stop all functions including DAR (via DAR_ENABLE), tip tilt calculations (via TIPTILT_CALC), tip tilt control (via TIPTILT_CONTROL), offloading to the telescope (via OFFLOAD_DCS and OFFLOAD). KTL Keywords Used: kpfguide.TIPTILT_CALC kpfguide.TIPTILT_CONTROL kpfguide.OFFLOAD kpfguide.ALL_LOOPS Source code in kpf/fiu/StopTipTilt.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 class StopTipTilt ( KPFTranslatorFunction ): '''Stop the tip tilt control loop. This uses the ALL_LOOPS keyword to stop all functions including DAR (via DAR_ENABLE), tip tilt calculations (via TIPTILT_CALC), tip tilt control (via TIPTILT_CONTROL), offloading to the telescope (via OFFLOAD_DCS and OFFLOAD). KTL Keywords Used: - `kpfguide.TIPTILT_CALC` - `kpfguide.TIPTILT_CONTROL` - `kpfguide.OFFLOAD` - `kpfguide.ALL_LOOPS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) kpfguide [ 'ALL_LOOPS' ] . write ( 'Inactive' ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) TIPTILT_CALC = ktl . cache ( 'kpfguide' , 'TIPTILT_CALC' ) success = TIPTILT_CALC . waitFor ( \"== 'Inactive'\" ) if success is False : raise FailedToReachDestination ( TIPTILT_CALC . read (), 'Inactive' ) TIPTILT_CONTROL = ktl . cache ( 'kpfguide' , 'TIPTILT_CONTROL' ) success = TIPTILT_CONTROL . waitFor ( \"== 'Inactive'\" ) if success is False : raise FailedToReachDestination ( TIPTILT_CONTROL . read (), 'Inactive' ) OFFLOAD = ktl . cache ( 'kpfguide' , 'OFFLOAD' ) success = OFFLOAD . waitFor ( \"== 'Inactive'\" ) if success is False : raise FailedToReachDestination ( OFFLOAD . read (), 'Inactive' )","title":"StopTipTilt"},{"location":"scripts/StopTipTilt/#stoptiptilt","text":"Bases: KPFTranslatorFunction Stop the tip tilt control loop. This uses the ALL_LOOPS keyword to stop all functions including DAR (via DAR_ENABLE), tip tilt calculations (via TIPTILT_CALC), tip tilt control (via TIPTILT_CONTROL), offloading to the telescope (via OFFLOAD_DCS and OFFLOAD). KTL Keywords Used: kpfguide.TIPTILT_CALC kpfguide.TIPTILT_CONTROL kpfguide.OFFLOAD kpfguide.ALL_LOOPS Source code in kpf/fiu/StopTipTilt.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 class StopTipTilt ( KPFTranslatorFunction ): '''Stop the tip tilt control loop. This uses the ALL_LOOPS keyword to stop all functions including DAR (via DAR_ENABLE), tip tilt calculations (via TIPTILT_CALC), tip tilt control (via TIPTILT_CONTROL), offloading to the telescope (via OFFLOAD_DCS and OFFLOAD). KTL Keywords Used: - `kpfguide.TIPTILT_CALC` - `kpfguide.TIPTILT_CONTROL` - `kpfguide.OFFLOAD` - `kpfguide.ALL_LOOPS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) kpfguide [ 'ALL_LOOPS' ] . write ( 'Inactive' ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) TIPTILT_CALC = ktl . cache ( 'kpfguide' , 'TIPTILT_CALC' ) success = TIPTILT_CALC . waitFor ( \"== 'Inactive'\" ) if success is False : raise FailedToReachDestination ( TIPTILT_CALC . read (), 'Inactive' ) TIPTILT_CONTROL = ktl . cache ( 'kpfguide' , 'TIPTILT_CONTROL' ) success = TIPTILT_CONTROL . waitFor ( \"== 'Inactive'\" ) if success is False : raise FailedToReachDestination ( TIPTILT_CONTROL . read (), 'Inactive' ) OFFLOAD = ktl . cache ( 'kpfguide' , 'OFFLOAD' ) success = OFFLOAD . waitFor ( \"== 'Inactive'\" ) if success is False : raise FailedToReachDestination ( OFFLOAD . read (), 'Inactive' )","title":"StopTipTilt"},{"location":"scripts/StopTriggerFile/","text":"StopTriggerFile Bases: KPFTranslatorFunction Stop a \"trigger file\" from the guide camera. KTL Keywords Used: kpfguide.TRIGGER Source code in kpf/guider/StopTriggerFile.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class StopTriggerFile ( KPFTranslatorFunction ): '''Stop a \"trigger file\" from the guide camera. KTL Keywords Used: - `kpfguide.TRIGGER` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) log . info ( f \"Stopping guider trigger file data collection\" ) kpfguide [ 'TRIGGER' ] . write ( 'Inactive' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"StopTriggerFile"},{"location":"scripts/StopTriggerFile/#stoptriggerfile","text":"Bases: KPFTranslatorFunction Stop a \"trigger file\" from the guide camera. KTL Keywords Used: kpfguide.TRIGGER Source code in kpf/guider/StopTriggerFile.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class StopTriggerFile ( KPFTranslatorFunction ): '''Stop a \"trigger file\" from the guide camera. KTL Keywords Used: - `kpfguide.TRIGGER` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) log . info ( f \"Stopping guider trigger file data collection\" ) kpfguide [ 'TRIGGER' ] . write ( 'Inactive' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"StopTriggerFile"},{"location":"scripts/TakeADCGridData/","text":"TakeADCGridData Bases: KPFTranslatorFunction Source code in kpf/engineering/TakeADCGridData.py 18 19 20 21 22 23 24 25 26 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 class TakeADCGridData ( KPFTranslatorFunction ): ''' ''' @classmethod def pre_condition ( cls , OB , logger , cfg ): pass @classmethod @register_script ( Path ( __file__ ) . name , os . getpid ()) @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , args , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in args : log . debug ( f \" { key } : { args [ key ] } \" ) log . info ( '-------------------------' ) adc1min = args . get ( 'ADC1MIN' , 60 ) adc1max = args . get ( 'ADC1MAX' , 70 ) adc2min = args . get ( 'ADC2MIN' , 60 ) adc2max = args . get ( 'ADC2MAX' , 70 ) adcstep = args . get ( 'ADCSTEP' , 1 ) adc1vals = np . arange ( adc1min , adc1max + adcstep , adcstep ) adc2vals = np . arange ( adc2min , adc2max + adcstep , adcstep ) adcsleeptime = 1 fvcsleeptime = 0.25 ADC1VAL = ktl . cache ( 'kpffiu' , 'ADC1VAL' ) ADC1VAL . monitor () ADC2VAL = ktl . cache ( 'kpffiu' , 'ADC2VAL' ) ADC2VAL . monitor () LASTFILE = ktl . cache ( 'kpffvc' , 'EXTLASTFILE' ) LASTFILE . monitor () this_file_name = Path ( __file__ ) . name . replace ( '.py' , '' ) utnow = datetime . utcnow () now_str = utnow . strftime ( '%Y%m %d at%H%M%S' ) date_str = ( utnow - timedelta ( days = 1 )) . strftime ( '%Y%b %d ' ) . lower () log_path = Path ( f '/s/sdata1701/KPFTranslator_logs/ { date_str } ' ) images_file = log_path / Path ( f ' { this_file_name } _ { now_str } .txt' ) images = Table ( names = ( 'file' , 'ADC1VAL' , 'ADC2VAL' ), dtype = ( 'a90' , 'f4' , 'f4' )) for i , adc1 in enumerate ( adc1vals ): for j , adc2 in enumerate ( adc2vals ): log . info ( f 'Moving ADC1 to { adc1 : .1f } , ADC2 to { adc2 : .1f } ' ) ADC1VAL . write ( f \" { adc1 : .1f } \" ) ADC2VAL . write ( f \" { adc2 : .1f } \" ) time . sleep ( adcsleeptime ) log . info ( 'Taking EXT FVC exposure' ) TakeFVCExposure . execute ({ 'camera' : 'EXT' }) time . sleep ( fvcsleeptime ) row = { 'file' : str ( LASTFILE ), 'ADC1VAL' : str ( ADC1VAL ), 'ADC2VAL' : str ( ADC2VAL )} log . info ( f ' { row [ \"file\" ] } ' ) images . add_row ( row ) if images_file . exists (): images_file . unlink () images . write ( images_file , format = 'ascii.csv' ) log . info ( 'Done' ) @classmethod def post_condition ( cls , OB , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'ADC1MIN' , type = float , help = \"Starting ADC1 angle\" ) parser . add_argument ( 'ADC1MAX' , type = float , help = \"Ending ADC1 angle\" ) parser . add_argument ( 'ADC2MIN' , type = float , help = \"Starting ADC2 angle\" ) parser . add_argument ( 'ADC2MAX' , type = float , help = \"Ending ADC2 angle\" ) parser . add_argument ( 'ADCSTEP' , type = float , help = \"Anglular step size\" ) return super () . add_cmdline_args ( parser , cfg )","title":"TakeADCGridData"},{"location":"scripts/TakeADCGridData/#takeadcgriddata","text":"Bases: KPFTranslatorFunction Source code in kpf/engineering/TakeADCGridData.py 18 19 20 21 22 23 24 25 26 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 class TakeADCGridData ( KPFTranslatorFunction ): ''' ''' @classmethod def pre_condition ( cls , OB , logger , cfg ): pass @classmethod @register_script ( Path ( __file__ ) . name , os . getpid ()) @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , args , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in args : log . debug ( f \" { key } : { args [ key ] } \" ) log . info ( '-------------------------' ) adc1min = args . get ( 'ADC1MIN' , 60 ) adc1max = args . get ( 'ADC1MAX' , 70 ) adc2min = args . get ( 'ADC2MIN' , 60 ) adc2max = args . get ( 'ADC2MAX' , 70 ) adcstep = args . get ( 'ADCSTEP' , 1 ) adc1vals = np . arange ( adc1min , adc1max + adcstep , adcstep ) adc2vals = np . arange ( adc2min , adc2max + adcstep , adcstep ) adcsleeptime = 1 fvcsleeptime = 0.25 ADC1VAL = ktl . cache ( 'kpffiu' , 'ADC1VAL' ) ADC1VAL . monitor () ADC2VAL = ktl . cache ( 'kpffiu' , 'ADC2VAL' ) ADC2VAL . monitor () LASTFILE = ktl . cache ( 'kpffvc' , 'EXTLASTFILE' ) LASTFILE . monitor () this_file_name = Path ( __file__ ) . name . replace ( '.py' , '' ) utnow = datetime . utcnow () now_str = utnow . strftime ( '%Y%m %d at%H%M%S' ) date_str = ( utnow - timedelta ( days = 1 )) . strftime ( '%Y%b %d ' ) . lower () log_path = Path ( f '/s/sdata1701/KPFTranslator_logs/ { date_str } ' ) images_file = log_path / Path ( f ' { this_file_name } _ { now_str } .txt' ) images = Table ( names = ( 'file' , 'ADC1VAL' , 'ADC2VAL' ), dtype = ( 'a90' , 'f4' , 'f4' )) for i , adc1 in enumerate ( adc1vals ): for j , adc2 in enumerate ( adc2vals ): log . info ( f 'Moving ADC1 to { adc1 : .1f } , ADC2 to { adc2 : .1f } ' ) ADC1VAL . write ( f \" { adc1 : .1f } \" ) ADC2VAL . write ( f \" { adc2 : .1f } \" ) time . sleep ( adcsleeptime ) log . info ( 'Taking EXT FVC exposure' ) TakeFVCExposure . execute ({ 'camera' : 'EXT' }) time . sleep ( fvcsleeptime ) row = { 'file' : str ( LASTFILE ), 'ADC1VAL' : str ( ADC1VAL ), 'ADC2VAL' : str ( ADC2VAL )} log . info ( f ' { row [ \"file\" ] } ' ) images . add_row ( row ) if images_file . exists (): images_file . unlink () images . write ( images_file , format = 'ascii.csv' ) log . info ( 'Done' ) @classmethod def post_condition ( cls , OB , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'ADC1MIN' , type = float , help = \"Starting ADC1 angle\" ) parser . add_argument ( 'ADC1MAX' , type = float , help = \"Ending ADC1 angle\" ) parser . add_argument ( 'ADC2MIN' , type = float , help = \"Starting ADC2 angle\" ) parser . add_argument ( 'ADC2MAX' , type = float , help = \"Ending ADC2 angle\" ) parser . add_argument ( 'ADCSTEP' , type = float , help = \"Anglular step size\" ) return super () . add_cmdline_args ( parser , cfg )","title":"TakeADCGridData"},{"location":"scripts/TakeADCOffsetGridData/","text":"TakeADCOffsetGridData Bases: KPFTranslatorFunction Source code in kpf/engineering/TakeADCOffsetGridData.py 18 19 20 21 22 23 24 25 26 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 class TakeADCOffsetGridData ( KPFTranslatorFunction ): ''' ''' @classmethod def pre_condition ( cls , OB , logger , cfg ): pass @classmethod @register_script ( Path ( __file__ ) . name , os . getpid ()) @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , args , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in args : log . debug ( f \" { key } : { args [ key ] } \" ) log . info ( '-------------------------' ) adc1delta = args . get ( 'ADC1DELTA' , 5 ) adc2delta = args . get ( 'ADC2DELTA' , 5 ) adcstep = args . get ( 'ADCSTEP' , 1 ) adc1deltas = np . arange ( - adc1delta , adc1delta , adcstep ) adc2deltas = np . arange ( - adc2delta , adc2delta , adcstep ) fvcsleeptime = 0.25 ADCPRISMS = ktl . cache ( 'kpffiu' , 'ADCPRISMS' ) ADCPRISMS . monitor () ADC1VAL = ktl . cache ( 'kpffiu' , 'ADC1VAL' ) ADC1VAL . monitor () ADC2VAL = ktl . cache ( 'kpffiu' , 'ADC2VAL' ) ADC2VAL . monitor () LASTFILE = ktl . cache ( 'kpffvc' , 'EXTLASTFILE' ) LASTFILE . monitor () this_file_name = Path ( __file__ ) . name . replace ( '.py' , '' ) utnow = datetime . utcnow () now_str = utnow . strftime ( '%Y%m %d at%H%M%S' ) date_str = ( utnow - timedelta ( days = 1 )) . strftime ( '%Y%b %d ' ) . lower () log_path = Path ( f '/s/sdata1701/KPFTranslator_logs/ { date_str } ' ) images_file = log_path / Path ( f ' { this_file_name } _ { now_str } .txt' ) images = Table ( names = ( 'file' , 'DELTA1' , 'DELTA2' , 'ADC1VAL' , 'ADC2VAL' ), dtype = ( 'a90' , 'f4' , 'f4' , 'f4' , 'f4' )) for i , delta1 in enumerate ( adc1deltas ): for j , delta2 in enumerate ( adc2deltas ): log . info ( f 'Moving ADCs to offset positions: { delta1 : .1f } , { delta2 : .1f } ' ) SetADCOffsets . execute ({ 'ADC1OFF' : delta1 , 'ADC2OFF' : delta2 }) log . info ( 'Taking EXT FVC exposure' ) TakeFVCExposure . execute ({ 'camera' : 'EXT' }) time . sleep ( fvcsleeptime ) row = { 'file' : str ( LASTFILE ), 'DELTA1' : delta1 , 'DELTA2' : delta2 , 'ADC1VAL' : str ( ADC1VAL ), 'ADC2VAL' : str ( ADC2VAL )} log . info ( f ' { row [ \"file\" ] } ' ) images . add_row ( row ) if images_file . exists (): images_file . unlink () images . write ( images_file , format = 'ascii.csv' ) log . info ( 'Done' ) @classmethod def post_condition ( cls , OB , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'ADC1DELTA' , type = float , help = \"Maximum ADC1 offset from nominal\" ) parser . add_argument ( 'ADC2DELTA' , type = float , help = \"Maximum ADC2 offset from nominal\" ) parser . add_argument ( 'ADCSTEP' , type = float , help = \"Anglular step size\" ) return super () . add_cmdline_args ( parser , cfg )","title":"TakeADCOffsetGridData"},{"location":"scripts/TakeADCOffsetGridData/#takeadcoffsetgriddata","text":"Bases: KPFTranslatorFunction Source code in kpf/engineering/TakeADCOffsetGridData.py 18 19 20 21 22 23 24 25 26 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 class TakeADCOffsetGridData ( KPFTranslatorFunction ): ''' ''' @classmethod def pre_condition ( cls , OB , logger , cfg ): pass @classmethod @register_script ( Path ( __file__ ) . name , os . getpid ()) @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , args , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in args : log . debug ( f \" { key } : { args [ key ] } \" ) log . info ( '-------------------------' ) adc1delta = args . get ( 'ADC1DELTA' , 5 ) adc2delta = args . get ( 'ADC2DELTA' , 5 ) adcstep = args . get ( 'ADCSTEP' , 1 ) adc1deltas = np . arange ( - adc1delta , adc1delta , adcstep ) adc2deltas = np . arange ( - adc2delta , adc2delta , adcstep ) fvcsleeptime = 0.25 ADCPRISMS = ktl . cache ( 'kpffiu' , 'ADCPRISMS' ) ADCPRISMS . monitor () ADC1VAL = ktl . cache ( 'kpffiu' , 'ADC1VAL' ) ADC1VAL . monitor () ADC2VAL = ktl . cache ( 'kpffiu' , 'ADC2VAL' ) ADC2VAL . monitor () LASTFILE = ktl . cache ( 'kpffvc' , 'EXTLASTFILE' ) LASTFILE . monitor () this_file_name = Path ( __file__ ) . name . replace ( '.py' , '' ) utnow = datetime . utcnow () now_str = utnow . strftime ( '%Y%m %d at%H%M%S' ) date_str = ( utnow - timedelta ( days = 1 )) . strftime ( '%Y%b %d ' ) . lower () log_path = Path ( f '/s/sdata1701/KPFTranslator_logs/ { date_str } ' ) images_file = log_path / Path ( f ' { this_file_name } _ { now_str } .txt' ) images = Table ( names = ( 'file' , 'DELTA1' , 'DELTA2' , 'ADC1VAL' , 'ADC2VAL' ), dtype = ( 'a90' , 'f4' , 'f4' , 'f4' , 'f4' )) for i , delta1 in enumerate ( adc1deltas ): for j , delta2 in enumerate ( adc2deltas ): log . info ( f 'Moving ADCs to offset positions: { delta1 : .1f } , { delta2 : .1f } ' ) SetADCOffsets . execute ({ 'ADC1OFF' : delta1 , 'ADC2OFF' : delta2 }) log . info ( 'Taking EXT FVC exposure' ) TakeFVCExposure . execute ({ 'camera' : 'EXT' }) time . sleep ( fvcsleeptime ) row = { 'file' : str ( LASTFILE ), 'DELTA1' : delta1 , 'DELTA2' : delta2 , 'ADC1VAL' : str ( ADC1VAL ), 'ADC2VAL' : str ( ADC2VAL )} log . info ( f ' { row [ \"file\" ] } ' ) images . add_row ( row ) if images_file . exists (): images_file . unlink () images . write ( images_file , format = 'ascii.csv' ) log . info ( 'Done' ) @classmethod def post_condition ( cls , OB , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'ADC1DELTA' , type = float , help = \"Maximum ADC1 offset from nominal\" ) parser . add_argument ( 'ADC2DELTA' , type = float , help = \"Maximum ADC2 offset from nominal\" ) parser . add_argument ( 'ADCSTEP' , type = float , help = \"Anglular step size\" ) return super () . add_cmdline_args ( parser , cfg )","title":"TakeADCOffsetGridData"},{"location":"scripts/TakeExpMeterBiases/","text":"TakeExpMeterBiases Bases: KPFTranslatorFunction Take a set of bias frames for the exposure meter. Obeys kpfconfig.ALLOWSCHEDULEDCALS (will not run if that is set to No) Parameters: nExp ( int ) \u2013 The number of frames to take. combine ( bool ) \u2013 Combine the files in to a master bias? output ( str ) \u2013 The output combined bias file. update ( bool ) \u2013 Update the bias file in use with the newly generated file? (only used if combine is True). KTL Keywords Used: kpfconfig.EXPMETER_ENABLED kpfconfig.ALLOWSCHEDULEDCALS kpf_expmeter.COOLING kpf_expmeter.COOLTARG kpf_expmeter.COOLTEMP kpf_expmeter.BINX kpf_expmeter.BINY kpf_expmeter.TOP kpf_expmeter.LEFT kpf_expmeter.WIDTH kpf_expmeter.HEIGHT kpf_expmeter.EXPOSURE kpf_expmeter.OBJECT kpf_expmeter.OBSERVER kpf_expmeter.EXPMODE kpf_expmeter.EXPSTATE kpf_expmeter.EXPOSE kpf_expmeter.SEQNUM kpf_expmeter.FITSFILE kpfexpose.TRIG_TARG Scripts Called: kpf.calbench.SetCalSource kpf.calbench.WaitForCalSource kpf.spectrograph.WaitForReady kpf.spectrograph.SetSourceSelectShutters kpf.expmeter.BuildMasterBias kpf.spectrograph.ResetDetectors.ResetExpMeterDetector Source code in kpf/expmeter/TakeExpMeterBiases.py 20 21 22 23 24 25 26 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 class TakeExpMeterBiases ( KPFTranslatorFunction ): '''Take a set of bias frames for the exposure meter. Obeys kpfconfig.ALLOWSCHEDULEDCALS (will not run if that is set to No) Args: nExp (int): The number of frames to take. combine (bool): Combine the files in to a master bias? output (str): The output combined bias file. update (bool): Update the bias file in use with the newly generated file? (only used if combine is True). KTL Keywords Used: - `kpfconfig.EXPMETER_ENABLED` - `kpfconfig.ALLOWSCHEDULEDCALS` - `kpf_expmeter.COOLING` - `kpf_expmeter.COOLTARG` - `kpf_expmeter.COOLTEMP` - `kpf_expmeter.BINX` - `kpf_expmeter.BINY` - `kpf_expmeter.TOP` - `kpf_expmeter.LEFT` - `kpf_expmeter.WIDTH` - `kpf_expmeter.HEIGHT` - `kpf_expmeter.EXPOSURE` - `kpf_expmeter.OBJECT` - `kpf_expmeter.OBSERVER` - `kpf_expmeter.EXPMODE` - `kpf_expmeter.EXPSTATE` - `kpf_expmeter.EXPOSE` - `kpf_expmeter.SEQNUM` - `kpf_expmeter.FITSFILE` - `kpfexpose.TRIG_TARG` Scripts Called: - `kpf.calbench.SetCalSource` - `kpf.calbench.WaitForCalSource` - `kpf.spectrograph.WaitForReady` - `kpf.spectrograph.SetSourceSelectShutters` - `kpf.expmeter.BuildMasterBias` - `kpf.spectrograph.ResetDetectors.ResetExpMeterDetector` ''' @classmethod @obey_scriptrun def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'nExp' , allowed_types = [ int ]) kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) # Check exposure meter enabled kpfconfig = ktl . cache ( 'kpfconfig' ) EM_enabled = kpfconfig [ 'EXPMETER_ENABLED' ] . read () == 'Yes' if EM_enabled == False : raise FailedPreCondition ( 'Exposure meter is not enabled' ) # Check on exposure meter detector status if kpf_expmeter [ 'COOLING' ] . read ( binary = True ) != True : raise FailedPreCondition ( 'Exposure meter cooling is not On' ) cooltarg = kpf_expmeter [ 'COOLTARG' ] . read ( binary = True ) currtemp = kpf_expmeter [ 'CURRTEMP' ] . read ( binary = True ) deltaT = abs ( currtemp - cooltarg ) deltaT_threshold = cfg . getfloat ( 'tolerances' , 'expmeter_detector_temperature_tolerance' , fallback = 0.5 ) if deltaT > deltaT_threshold : raise FailedPreCondition ( 'Exposure meter not near target temperature' ) @classmethod @register_script ( Path ( __file__ ) . name , os . getpid ()) @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , args , logger , cfg ): # Check if we're ok to take data allowscheduledcals = ktl . cache ( 'kpfconfig' , 'ALLOWSCHEDULEDCALS' ) if allowscheduledcals . read ( binary = True ) == False : log . warning ( f 'kpfconfig.ALLOWSCHEDULEDCALS=No. Not taking biases.' ) return [] # Proceed with taking biases nExp = int ( args . get ( 'nExp' )) log . info ( f \"Taking { nExp } exposure meter bias frames\" ) kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) # Set exposure meter to full frame to take biases log . info ( f \"Setting exposure meter to full frame for biases\" ) kpf_expmeter [ 'BINX' ] . write ( 1 ) kpf_expmeter [ 'BINY' ] . write ( 1 ) kpf_expmeter [ 'TOP' ] . write ( 0 ) kpf_expmeter [ 'LEFT' ] . write ( 0 ) kpf_expmeter [ 'WIDTH' ] . write ( 1072 ) kpf_expmeter [ 'HEIGHT' ] . write ( 1024 ) kpf_expmeter [ 'EXPOSURE' ] . write ( 0.12 ) kpf_expmeter [ 'OBJECT' ] . write ( 'bias' ) kpf_expmeter [ 'OBSERVER' ] . write ( 'TakeExpMeterBiases' ) kpf_expmeter [ 'EXPMODE' ] . write ( 'Continuous' ) log . debug ( 'Set Octagon to Home and close all source select shutters' ) SetCalSource . execute ({ 'CalSource' : 'Home' }) WaitForReady . execute ({}) SetSourceSelectShutters . execute ({}) WaitForCalSource . execute ({ 'CalSource' : 'Home' }) # Set TRIG_TARG to None, so that kpfassemble doesn't try # to pick up this data set trig_targ = ktl . cache ( 'kpfexpose' , 'TRIG_TARG' ) trig_targ . write ( 'None' ) ready = kpf_expmeter [ 'EXPSTATE' ] . waitFor ( \"== 'Ready'\" , timeout = 60 ) if ready is not True : raise KPFException ( f \"Exposure Meter did not reach ready state\" ) # Start continuous exposures log . info ( f \"Starting continuous exposures\" ) kpf_expmeter [ 'EXPOSE' ] . write ( 'Start' ) started = kpf_expmeter [ 'EXPSTATE' ] . waitFor ( \"!= 'Ready'\" , timeout = 5 ) if started is not True : raise KPFException ( f \"Exposure Meter did not start exposures\" ) got_frames = kpf_expmeter [ 'SEQNUM' ] . waitFor ( f \"== { nExp } \" , timeout = 2 * nExp ) if got_frames is not True : raise KPFException ( f \"Exposure Meter did not get all exposures\" ) log . info ( f \"Stopping continuous exposures\" ) kpf_expmeter [ 'EXPOSE' ] . write ( 'End' ) # Arbitrary wait to let file writing and DRP finish time . sleep ( 2 ) # Get FITSFILE lastfile = Path ( kpf_expmeter [ 'FITSFILE' ] . read ()) if lastfile . exists () is False : raise KPFException ( f \"Could not find file: { lastfile } \" ) filename_parts = lastfile . name . split ( '.' ) filename_parts [ 1 ] = '*' biases = [ f for f in lastfile . parent . glob ( '.' . join ( filename_parts ))] # Set exposure meter back to operations settings log . info ( f \"Setting exposure meter to operational windowing\" ) kpf_expmeter [ 'BINX' ] . write ( 1 ) kpf_expmeter [ 'BINY' ] . write ( 1 ) kpf_expmeter [ 'TOP' ] . write ( 0 ) kpf_expmeter [ 'LEFT' ] . write ( 1 ) kpf_expmeter [ 'WIDTH' ] . write ( 651 ) kpf_expmeter [ 'HEIGHT' ] . write ( 300 ) kpf_expmeter [ 'OBJECT' ] . write ( '' ) if args . get ( 'combine' , False ) is True : BuildMasterBias . execute ({ 'files' : biases , 'output' : args . get ( 'output' ), 'update' : args . get ( 'update' )}) return biases @classmethod def post_condition ( cls , args , logger , cfg ): expstate = ktl . cache ( 'kpf_expmeter' , 'EXPSTATE' ) expstate . monitor () timeout = 60 ready = expstate . waitFor ( \"== 'Ready'\" , timeout = timeout ) if ready is not True : log . error ( f 'ExpMeter is not Ready after { timeout } s' ) log . warning ( f 'ExpMeter is { expstate . ascii } . Resetting.' ) ResetExpMeterDetector . execute ({}) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'nExp' , type = int , help = \"The number of frames to take\" ) parser . add_argument ( \"-c\" , \"--combine\" , dest = \"combine\" , default = False , action = \"store_true\" , help = \"Combine the files in to a master bias?\" ) parser . add_argument ( \"--update\" , dest = \"update\" , default = False , action = \"store_true\" , help = \"Update the bias file in use with the newly generated file? (only used if --combine is used)\" ) parser . add_argument ( \"--output\" , dest = \"output\" , type = str , default = '' , help = \"The output combined bias file.\" ) return super () . add_cmdline_args ( parser , cfg )","title":"TakeExpMeterBiases"},{"location":"scripts/TakeExpMeterBiases/#takeexpmeterbiases","text":"Bases: KPFTranslatorFunction Take a set of bias frames for the exposure meter. Obeys kpfconfig.ALLOWSCHEDULEDCALS (will not run if that is set to No) Parameters: nExp ( int ) \u2013 The number of frames to take. combine ( bool ) \u2013 Combine the files in to a master bias? output ( str ) \u2013 The output combined bias file. update ( bool ) \u2013 Update the bias file in use with the newly generated file? (only used if combine is True). KTL Keywords Used: kpfconfig.EXPMETER_ENABLED kpfconfig.ALLOWSCHEDULEDCALS kpf_expmeter.COOLING kpf_expmeter.COOLTARG kpf_expmeter.COOLTEMP kpf_expmeter.BINX kpf_expmeter.BINY kpf_expmeter.TOP kpf_expmeter.LEFT kpf_expmeter.WIDTH kpf_expmeter.HEIGHT kpf_expmeter.EXPOSURE kpf_expmeter.OBJECT kpf_expmeter.OBSERVER kpf_expmeter.EXPMODE kpf_expmeter.EXPSTATE kpf_expmeter.EXPOSE kpf_expmeter.SEQNUM kpf_expmeter.FITSFILE kpfexpose.TRIG_TARG Scripts Called: kpf.calbench.SetCalSource kpf.calbench.WaitForCalSource kpf.spectrograph.WaitForReady kpf.spectrograph.SetSourceSelectShutters kpf.expmeter.BuildMasterBias kpf.spectrograph.ResetDetectors.ResetExpMeterDetector Source code in kpf/expmeter/TakeExpMeterBiases.py 20 21 22 23 24 25 26 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 class TakeExpMeterBiases ( KPFTranslatorFunction ): '''Take a set of bias frames for the exposure meter. Obeys kpfconfig.ALLOWSCHEDULEDCALS (will not run if that is set to No) Args: nExp (int): The number of frames to take. combine (bool): Combine the files in to a master bias? output (str): The output combined bias file. update (bool): Update the bias file in use with the newly generated file? (only used if combine is True). KTL Keywords Used: - `kpfconfig.EXPMETER_ENABLED` - `kpfconfig.ALLOWSCHEDULEDCALS` - `kpf_expmeter.COOLING` - `kpf_expmeter.COOLTARG` - `kpf_expmeter.COOLTEMP` - `kpf_expmeter.BINX` - `kpf_expmeter.BINY` - `kpf_expmeter.TOP` - `kpf_expmeter.LEFT` - `kpf_expmeter.WIDTH` - `kpf_expmeter.HEIGHT` - `kpf_expmeter.EXPOSURE` - `kpf_expmeter.OBJECT` - `kpf_expmeter.OBSERVER` - `kpf_expmeter.EXPMODE` - `kpf_expmeter.EXPSTATE` - `kpf_expmeter.EXPOSE` - `kpf_expmeter.SEQNUM` - `kpf_expmeter.FITSFILE` - `kpfexpose.TRIG_TARG` Scripts Called: - `kpf.calbench.SetCalSource` - `kpf.calbench.WaitForCalSource` - `kpf.spectrograph.WaitForReady` - `kpf.spectrograph.SetSourceSelectShutters` - `kpf.expmeter.BuildMasterBias` - `kpf.spectrograph.ResetDetectors.ResetExpMeterDetector` ''' @classmethod @obey_scriptrun def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'nExp' , allowed_types = [ int ]) kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) # Check exposure meter enabled kpfconfig = ktl . cache ( 'kpfconfig' ) EM_enabled = kpfconfig [ 'EXPMETER_ENABLED' ] . read () == 'Yes' if EM_enabled == False : raise FailedPreCondition ( 'Exposure meter is not enabled' ) # Check on exposure meter detector status if kpf_expmeter [ 'COOLING' ] . read ( binary = True ) != True : raise FailedPreCondition ( 'Exposure meter cooling is not On' ) cooltarg = kpf_expmeter [ 'COOLTARG' ] . read ( binary = True ) currtemp = kpf_expmeter [ 'CURRTEMP' ] . read ( binary = True ) deltaT = abs ( currtemp - cooltarg ) deltaT_threshold = cfg . getfloat ( 'tolerances' , 'expmeter_detector_temperature_tolerance' , fallback = 0.5 ) if deltaT > deltaT_threshold : raise FailedPreCondition ( 'Exposure meter not near target temperature' ) @classmethod @register_script ( Path ( __file__ ) . name , os . getpid ()) @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , args , logger , cfg ): # Check if we're ok to take data allowscheduledcals = ktl . cache ( 'kpfconfig' , 'ALLOWSCHEDULEDCALS' ) if allowscheduledcals . read ( binary = True ) == False : log . warning ( f 'kpfconfig.ALLOWSCHEDULEDCALS=No. Not taking biases.' ) return [] # Proceed with taking biases nExp = int ( args . get ( 'nExp' )) log . info ( f \"Taking { nExp } exposure meter bias frames\" ) kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) # Set exposure meter to full frame to take biases log . info ( f \"Setting exposure meter to full frame for biases\" ) kpf_expmeter [ 'BINX' ] . write ( 1 ) kpf_expmeter [ 'BINY' ] . write ( 1 ) kpf_expmeter [ 'TOP' ] . write ( 0 ) kpf_expmeter [ 'LEFT' ] . write ( 0 ) kpf_expmeter [ 'WIDTH' ] . write ( 1072 ) kpf_expmeter [ 'HEIGHT' ] . write ( 1024 ) kpf_expmeter [ 'EXPOSURE' ] . write ( 0.12 ) kpf_expmeter [ 'OBJECT' ] . write ( 'bias' ) kpf_expmeter [ 'OBSERVER' ] . write ( 'TakeExpMeterBiases' ) kpf_expmeter [ 'EXPMODE' ] . write ( 'Continuous' ) log . debug ( 'Set Octagon to Home and close all source select shutters' ) SetCalSource . execute ({ 'CalSource' : 'Home' }) WaitForReady . execute ({}) SetSourceSelectShutters . execute ({}) WaitForCalSource . execute ({ 'CalSource' : 'Home' }) # Set TRIG_TARG to None, so that kpfassemble doesn't try # to pick up this data set trig_targ = ktl . cache ( 'kpfexpose' , 'TRIG_TARG' ) trig_targ . write ( 'None' ) ready = kpf_expmeter [ 'EXPSTATE' ] . waitFor ( \"== 'Ready'\" , timeout = 60 ) if ready is not True : raise KPFException ( f \"Exposure Meter did not reach ready state\" ) # Start continuous exposures log . info ( f \"Starting continuous exposures\" ) kpf_expmeter [ 'EXPOSE' ] . write ( 'Start' ) started = kpf_expmeter [ 'EXPSTATE' ] . waitFor ( \"!= 'Ready'\" , timeout = 5 ) if started is not True : raise KPFException ( f \"Exposure Meter did not start exposures\" ) got_frames = kpf_expmeter [ 'SEQNUM' ] . waitFor ( f \"== { nExp } \" , timeout = 2 * nExp ) if got_frames is not True : raise KPFException ( f \"Exposure Meter did not get all exposures\" ) log . info ( f \"Stopping continuous exposures\" ) kpf_expmeter [ 'EXPOSE' ] . write ( 'End' ) # Arbitrary wait to let file writing and DRP finish time . sleep ( 2 ) # Get FITSFILE lastfile = Path ( kpf_expmeter [ 'FITSFILE' ] . read ()) if lastfile . exists () is False : raise KPFException ( f \"Could not find file: { lastfile } \" ) filename_parts = lastfile . name . split ( '.' ) filename_parts [ 1 ] = '*' biases = [ f for f in lastfile . parent . glob ( '.' . join ( filename_parts ))] # Set exposure meter back to operations settings log . info ( f \"Setting exposure meter to operational windowing\" ) kpf_expmeter [ 'BINX' ] . write ( 1 ) kpf_expmeter [ 'BINY' ] . write ( 1 ) kpf_expmeter [ 'TOP' ] . write ( 0 ) kpf_expmeter [ 'LEFT' ] . write ( 1 ) kpf_expmeter [ 'WIDTH' ] . write ( 651 ) kpf_expmeter [ 'HEIGHT' ] . write ( 300 ) kpf_expmeter [ 'OBJECT' ] . write ( '' ) if args . get ( 'combine' , False ) is True : BuildMasterBias . execute ({ 'files' : biases , 'output' : args . get ( 'output' ), 'update' : args . get ( 'update' )}) return biases @classmethod def post_condition ( cls , args , logger , cfg ): expstate = ktl . cache ( 'kpf_expmeter' , 'EXPSTATE' ) expstate . monitor () timeout = 60 ready = expstate . waitFor ( \"== 'Ready'\" , timeout = timeout ) if ready is not True : log . error ( f 'ExpMeter is not Ready after { timeout } s' ) log . warning ( f 'ExpMeter is { expstate . ascii } . Resetting.' ) ResetExpMeterDetector . execute ({}) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'nExp' , type = int , help = \"The number of frames to take\" ) parser . add_argument ( \"-c\" , \"--combine\" , dest = \"combine\" , default = False , action = \"store_true\" , help = \"Combine the files in to a master bias?\" ) parser . add_argument ( \"--update\" , dest = \"update\" , default = False , action = \"store_true\" , help = \"Update the bias file in use with the newly generated file? (only used if --combine is used)\" ) parser . add_argument ( \"--output\" , dest = \"output\" , type = str , default = '' , help = \"The output combined bias file.\" ) return super () . add_cmdline_args ( parser , cfg )","title":"TakeExpMeterBiases"},{"location":"scripts/TakeFVCContinuous/","text":"TakeFVCContinuous Bases: KPFTranslatorFunction Take exposures with the specified FVC continuously and display to ds9. Parameters: camera ( str ) \u2013 Which FVC camera? Allowed values: SCI, CAHK, EXT, CAL exptime ( float ) \u2013 The exposure time in seconds. KTL Keywords Used: kpffvc.SCIEXPTIME kpffvc.CAHKEXPTIME kpffvc.EXTEXPTIME kpffvc.CALEXPTIME kpfpower.KPFFVC1 kpfpower.KPFFVC2 kpfpower.KPFFVC3 Source code in kpf/fvc/TakeFVCContinuous.py 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class TakeFVCContinuous ( KPFTranslatorFunction ): '''Take exposures with the specified FVC continuously and display to ds9. Args: camera (str): Which FVC camera? Allowed values: SCI, CAHK, EXT, CAL exptime (float): The exposure time in seconds. KTL Keywords Used: - `kpffvc.SCIEXPTIME` - `kpffvc.CAHKEXPTIME` - `kpffvc.EXTEXPTIME` - `kpffvc.CALEXPTIME` - `kpfpower.KPFFVC1` - `kpfpower.KPFFVC2` - `kpfpower.KPFFVC3` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'camera' , allowed_values = [ 'SCI' , 'CAHK' , 'CAL' , 'EXT' ]) # Check if power is on camera = args . get ( 'camera' ) camnum = { 'SCI' : 1 , 'CAHK' : 2 , 'CAL' : 3 }[ camera ] powerkw = ktl . cache ( 'kpfpower' , f \"KPFFVC { camnum } \" ) if powerkw . read () != 'On' : raise FailedPreCondition ( f \" { camera } FVC power is not On\" ) @classmethod def perform ( cls , args , logger , cfg ): camera = args . get ( 'camera' ) exptime = args . get ( 'exptime' ) SetFVCExpTime . execute ( args ) while True : TakeFVCExposure . execute ({ 'camera' : camera , 'display' : True }) time . sleep ( 0.5 ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'camera' , type = str , choices = [ 'SCI' , 'CAHK' , 'CAL' , 'EXT' ], help = 'The FVC camera' ) parser . add_argument ( 'exptime' , type = float , help = 'The exposure time in seconds' ) return super () . add_cmdline_args ( parser , cfg )","title":"TakeFVCContinuous"},{"location":"scripts/TakeFVCContinuous/#takefvccontinuous","text":"Bases: KPFTranslatorFunction Take exposures with the specified FVC continuously and display to ds9. Parameters: camera ( str ) \u2013 Which FVC camera? Allowed values: SCI, CAHK, EXT, CAL exptime ( float ) \u2013 The exposure time in seconds. KTL Keywords Used: kpffvc.SCIEXPTIME kpffvc.CAHKEXPTIME kpffvc.EXTEXPTIME kpffvc.CALEXPTIME kpfpower.KPFFVC1 kpfpower.KPFFVC2 kpfpower.KPFFVC3 Source code in kpf/fvc/TakeFVCContinuous.py 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class TakeFVCContinuous ( KPFTranslatorFunction ): '''Take exposures with the specified FVC continuously and display to ds9. Args: camera (str): Which FVC camera? Allowed values: SCI, CAHK, EXT, CAL exptime (float): The exposure time in seconds. KTL Keywords Used: - `kpffvc.SCIEXPTIME` - `kpffvc.CAHKEXPTIME` - `kpffvc.EXTEXPTIME` - `kpffvc.CALEXPTIME` - `kpfpower.KPFFVC1` - `kpfpower.KPFFVC2` - `kpfpower.KPFFVC3` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'camera' , allowed_values = [ 'SCI' , 'CAHK' , 'CAL' , 'EXT' ]) # Check if power is on camera = args . get ( 'camera' ) camnum = { 'SCI' : 1 , 'CAHK' : 2 , 'CAL' : 3 }[ camera ] powerkw = ktl . cache ( 'kpfpower' , f \"KPFFVC { camnum } \" ) if powerkw . read () != 'On' : raise FailedPreCondition ( f \" { camera } FVC power is not On\" ) @classmethod def perform ( cls , args , logger , cfg ): camera = args . get ( 'camera' ) exptime = args . get ( 'exptime' ) SetFVCExpTime . execute ( args ) while True : TakeFVCExposure . execute ({ 'camera' : camera , 'display' : True }) time . sleep ( 0.5 ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'camera' , type = str , choices = [ 'SCI' , 'CAHK' , 'CAL' , 'EXT' ], help = 'The FVC camera' ) parser . add_argument ( 'exptime' , type = float , help = 'The exposure time in seconds' ) return super () . add_cmdline_args ( parser , cfg )","title":"TakeFVCContinuous"},{"location":"scripts/TakeFVCExposure/","text":"TakeFVCExposure Bases: KPFTranslatorFunction Take an exposure with the specified fiber viewing camera Parameters: camera ( str ) \u2013 Which FVC camera? Allowed values: SCI, CAHK, EXT, CAL wait ( bool ) \u2013 Wait for image to complete before returning? (default: True) display ( bool ) \u2013 Display the resulting image to the engineering ds9 instance for FVCs using XPA? KTL Keywords Used: kpffvc.SCIEXPTIME kpffvc.CAHKEXPTIME kpffvc.EXTEXPTIME kpffvc.CALEXPTIME kpffvc.SCILASTFILE kpffvc.CALLASTFILE kpffvc.EXTLASTFILE kpffvc.CAHKLASTFILE kpffvc.SCIEXPOSE kpffvc.CALEXPOSE kpffvc.EXTEXPOSE kpffvc.CAHKEXPOSE kpfpower.KPFFVC1 kpfpower.KPFFVC2 kpfpower.KPFFVC3 Source code in kpf/fvc/TakeFVCExposure.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class TakeFVCExposure ( KPFTranslatorFunction ): '''Take an exposure with the specified fiber viewing camera Args: camera (str): Which FVC camera? Allowed values: SCI, CAHK, EXT, CAL wait (bool): Wait for image to complete before returning? (default: True) display (bool): Display the resulting image to the engineering ds9 instance for FVCs using XPA? KTL Keywords Used: - `kpffvc.SCIEXPTIME` - `kpffvc.CAHKEXPTIME` - `kpffvc.EXTEXPTIME` - `kpffvc.CALEXPTIME` - `kpffvc.SCILASTFILE` - `kpffvc.CALLASTFILE` - `kpffvc.EXTLASTFILE` - `kpffvc.CAHKLASTFILE` - `kpffvc.SCIEXPOSE` - `kpffvc.CALEXPOSE` - `kpffvc.EXTEXPOSE` - `kpffvc.CAHKEXPOSE` - `kpfpower.KPFFVC1` - `kpfpower.KPFFVC2` - `kpfpower.KPFFVC3` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'camera' , allowed_values = [ 'SCI' , 'CAHK' , 'CAL' , 'EXT' ]) # Check if power is on camera = args . get ( 'camera' ) camnum = { 'SCI' : 1 , 'CAHK' : 2 , 'CAL' : 3 , 'EXT' : None }[ camera ] if camnum is not None : powerkw = ktl . cache ( 'kpfpower' , f \"KPFFVC { camnum } \" ) if powerkw . read () != 'On' : raise FailedPreCondition ( f \" { camera } FVC power is not On\" ) @classmethod def perform ( cls , args , logger , cfg ): camera = args . get ( 'camera' ) kpffvc = ktl . cache ( 'kpffvc' ) exptime = kpffvc [ f ' { camera } EXPTIME' ] . read ( binary = True ) lastfile = kpffvc [ f ' { camera } LASTFILE' ] initial_lastfile = lastfile . read () wait = args . get ( 'wait' , True ) kpffvc [ f ' { camera } EXPOSE' ] . write ( 'yes' , wait = wait ) if wait is True : timeout = cfg . getfloat ( 'times' , 'fvc_command_timeout' , fallback = 5 ) expr = f \"($kpffvc. { camera } LASTFILE != ' { initial_lastfile } ')\" ktl . waitFor ( expr , timeout = exptime + timeout ) if wait is True and args . get ( 'display' , False ) is True : display_name = cfg . get ( 'display' , 'fvc_xpa_target' , fallback = 'FVC' ) ds9cmd = [ 'xpaset' , display_name , 'fits' , f \" { lastfile . read () } \" , '<' , f \" { lastfile . read () } \" ] log . debug ( f \"Running: { ' ' . join ( ds9cmd ) } \" ) subprocess . call ( ' ' . join ( ds9cmd ), shell = True ) regfile = Path ( f '/home/kpfeng/fibers_on_ { camera . lower () } fvc.reg' ) if regfile . exists () is True : overlaycmd = [ 'xpaset' , '-p' , display_name , 'regions' , 'file' , f \" { regfile } \" ] log . debug ( f \"Running: { ' ' . join ( overlaycmd ) } \" ) subprocess . call ( ' ' . join ( overlaycmd ), shell = True ) return kpffvc [ f \" { camera } LASTFILE\" ] . read () @classmethod def post_condition ( cls , args , logger , cfg ): camera = args . get ( 'camera' , 'SCI' ) kpffvc = ktl . cache ( 'kpffvc' ) lastfile = kpffvc [ f ' { camera } LASTFILE' ] lastfile . monitor () new_file = Path ( f \" { lastfile } \" ) log . debug ( f \" { camera } FVC LASTFILE: { new_file } \" ) if new_file . exists () == False : raise FailedPostCondition ( f 'Output file not found: { new_file } ' ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'camera' , type = str , choices = [ 'SCI' , 'CAHK' , 'CAL' , 'EXT' ], help = 'The FVC camera' ) parser . add_argument ( \"--nowait\" , dest = \"wait\" , default = True , action = \"store_false\" , help = \"Send exposure command and return immediately?\" ) parser . add_argument ( \"--display\" , dest = \"display\" , default = False , action = \"store_true\" , help = \"Display image via engineering ds9?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"TakeFVCExposure"},{"location":"scripts/TakeFVCExposure/#takefvcexposure","text":"Bases: KPFTranslatorFunction Take an exposure with the specified fiber viewing camera Parameters: camera ( str ) \u2013 Which FVC camera? Allowed values: SCI, CAHK, EXT, CAL wait ( bool ) \u2013 Wait for image to complete before returning? (default: True) display ( bool ) \u2013 Display the resulting image to the engineering ds9 instance for FVCs using XPA? KTL Keywords Used: kpffvc.SCIEXPTIME kpffvc.CAHKEXPTIME kpffvc.EXTEXPTIME kpffvc.CALEXPTIME kpffvc.SCILASTFILE kpffvc.CALLASTFILE kpffvc.EXTLASTFILE kpffvc.CAHKLASTFILE kpffvc.SCIEXPOSE kpffvc.CALEXPOSE kpffvc.EXTEXPOSE kpffvc.CAHKEXPOSE kpfpower.KPFFVC1 kpfpower.KPFFVC2 kpfpower.KPFFVC3 Source code in kpf/fvc/TakeFVCExposure.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class TakeFVCExposure ( KPFTranslatorFunction ): '''Take an exposure with the specified fiber viewing camera Args: camera (str): Which FVC camera? Allowed values: SCI, CAHK, EXT, CAL wait (bool): Wait for image to complete before returning? (default: True) display (bool): Display the resulting image to the engineering ds9 instance for FVCs using XPA? KTL Keywords Used: - `kpffvc.SCIEXPTIME` - `kpffvc.CAHKEXPTIME` - `kpffvc.EXTEXPTIME` - `kpffvc.CALEXPTIME` - `kpffvc.SCILASTFILE` - `kpffvc.CALLASTFILE` - `kpffvc.EXTLASTFILE` - `kpffvc.CAHKLASTFILE` - `kpffvc.SCIEXPOSE` - `kpffvc.CALEXPOSE` - `kpffvc.EXTEXPOSE` - `kpffvc.CAHKEXPOSE` - `kpfpower.KPFFVC1` - `kpfpower.KPFFVC2` - `kpfpower.KPFFVC3` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'camera' , allowed_values = [ 'SCI' , 'CAHK' , 'CAL' , 'EXT' ]) # Check if power is on camera = args . get ( 'camera' ) camnum = { 'SCI' : 1 , 'CAHK' : 2 , 'CAL' : 3 , 'EXT' : None }[ camera ] if camnum is not None : powerkw = ktl . cache ( 'kpfpower' , f \"KPFFVC { camnum } \" ) if powerkw . read () != 'On' : raise FailedPreCondition ( f \" { camera } FVC power is not On\" ) @classmethod def perform ( cls , args , logger , cfg ): camera = args . get ( 'camera' ) kpffvc = ktl . cache ( 'kpffvc' ) exptime = kpffvc [ f ' { camera } EXPTIME' ] . read ( binary = True ) lastfile = kpffvc [ f ' { camera } LASTFILE' ] initial_lastfile = lastfile . read () wait = args . get ( 'wait' , True ) kpffvc [ f ' { camera } EXPOSE' ] . write ( 'yes' , wait = wait ) if wait is True : timeout = cfg . getfloat ( 'times' , 'fvc_command_timeout' , fallback = 5 ) expr = f \"($kpffvc. { camera } LASTFILE != ' { initial_lastfile } ')\" ktl . waitFor ( expr , timeout = exptime + timeout ) if wait is True and args . get ( 'display' , False ) is True : display_name = cfg . get ( 'display' , 'fvc_xpa_target' , fallback = 'FVC' ) ds9cmd = [ 'xpaset' , display_name , 'fits' , f \" { lastfile . read () } \" , '<' , f \" { lastfile . read () } \" ] log . debug ( f \"Running: { ' ' . join ( ds9cmd ) } \" ) subprocess . call ( ' ' . join ( ds9cmd ), shell = True ) regfile = Path ( f '/home/kpfeng/fibers_on_ { camera . lower () } fvc.reg' ) if regfile . exists () is True : overlaycmd = [ 'xpaset' , '-p' , display_name , 'regions' , 'file' , f \" { regfile } \" ] log . debug ( f \"Running: { ' ' . join ( overlaycmd ) } \" ) subprocess . call ( ' ' . join ( overlaycmd ), shell = True ) return kpffvc [ f \" { camera } LASTFILE\" ] . read () @classmethod def post_condition ( cls , args , logger , cfg ): camera = args . get ( 'camera' , 'SCI' ) kpffvc = ktl . cache ( 'kpffvc' ) lastfile = kpffvc [ f ' { camera } LASTFILE' ] lastfile . monitor () new_file = Path ( f \" { lastfile } \" ) log . debug ( f \" { camera } FVC LASTFILE: { new_file } \" ) if new_file . exists () == False : raise FailedPostCondition ( f 'Output file not found: { new_file } ' ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'camera' , type = str , choices = [ 'SCI' , 'CAHK' , 'CAL' , 'EXT' ], help = 'The FVC camera' ) parser . add_argument ( \"--nowait\" , dest = \"wait\" , default = True , action = \"store_false\" , help = \"Send exposure command and return immediately?\" ) parser . add_argument ( \"--display\" , dest = \"display\" , default = False , action = \"store_true\" , help = \"Display image via engineering ds9?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"TakeFVCExposure"},{"location":"scripts/TakeGuiderCube/","text":"TakeGuiderCube Bases: KPFTranslatorFunction Take a \"trigger file\" from the guide camera of a given duration. Parameters: duration ( float ) \u2013 The duration in seconds of the image set. ImageCube ( bool ) \u2013 Collect the full cube of images? (default True) This will slow down file write considerably. KTL Keywords Used: kpfguide.TRIGCUBE kpfguide.LASTTRIGFILE kpfguide.ALL_LOOPS Scripts Called: kpf.guider.StartTriggerFile kpf.guider.StopTriggerFile kpf.guider.WaitForTriggerFile Source code in kpf/guider/TakeGuiderCube.py 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class TakeGuiderCube ( KPFTranslatorFunction ): '''Take a \"trigger file\" from the guide camera of a given duration. Args: duration (float): The duration in seconds of the image set. ImageCube (bool): Collect the full cube of images? (default True) This will slow down file write considerably. KTL Keywords Used: - `kpfguide.TRIGCUBE` - `kpfguide.LASTTRIGFILE` - `kpfguide.ALL_LOOPS` Scripts Called: - `kpf.guider.StartTriggerFile` - `kpf.guider.StopTriggerFile` - `kpf.guider.WaitForTriggerFile` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'duration' , value_min = 0 ) @classmethod def perform ( cls , args , logger , cfg ): duration = float ( args . get ( 'duration' )) kpfguide = ktl . cache ( 'kpfguide' ) # Read initial conditions, so we can set them back at the end initial_trigcube = kpfguide [ 'TRIGCUBE' ] . read () initial_lastfile = kpfguide [ 'LASTTRIGFILE' ] . read () initial_all_loops = kpfguide [ 'ALL_LOOPS' ] . read () # Do we want to take the image cube? collect_image_cube = args . get ( 'ImageCube' , True ) set_trigcube = { True : 'Active' , False : 'Inactive' }[ collect_image_cube ] kpfguide [ 'TRIGCUBE' ] . write ( set_trigcube ) # Trigger data collection log . info ( f \"Starting guider cube data collection, duration = { duration : .1f } s\" ) StartTriggerFile . execute ({}) time . sleep ( duration ) StopTriggerFile . execute ({}) # Stop all loops if we're writing out a full image cube # if initial_all_loops == 'Active' and collect_image_cube == True: # kpfguide['ALL_LOOPS'].write('Inactive', wait=False) cube_file = WaitForTriggerFile . execute ({ 'initial_lastfile' : initial_lastfile }) # Reset TRIGCUBE kpfguide [ 'TRIGCUBE' ] . write ( initial_trigcube ) # Reset ALL_LOOPS to initial values # if initial_all_loops == 'Active' and collect_image_cube == True: # kpfguide['ALL_LOOPS'].write(initial_all_loops) return cube_file @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'duration' , type = float , help = 'The duration in seconds' ) parser . add_argument ( \"--noTRIGCUBE\" , dest = \"ImageCube\" , default = True , action = \"store_false\" , help = \"Collect the full image cube?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"TakeGuiderCube"},{"location":"scripts/TakeGuiderCube/#takeguidercube","text":"Bases: KPFTranslatorFunction Take a \"trigger file\" from the guide camera of a given duration. Parameters: duration ( float ) \u2013 The duration in seconds of the image set. ImageCube ( bool ) \u2013 Collect the full cube of images? (default True) This will slow down file write considerably. KTL Keywords Used: kpfguide.TRIGCUBE kpfguide.LASTTRIGFILE kpfguide.ALL_LOOPS Scripts Called: kpf.guider.StartTriggerFile kpf.guider.StopTriggerFile kpf.guider.WaitForTriggerFile Source code in kpf/guider/TakeGuiderCube.py 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class TakeGuiderCube ( KPFTranslatorFunction ): '''Take a \"trigger file\" from the guide camera of a given duration. Args: duration (float): The duration in seconds of the image set. ImageCube (bool): Collect the full cube of images? (default True) This will slow down file write considerably. KTL Keywords Used: - `kpfguide.TRIGCUBE` - `kpfguide.LASTTRIGFILE` - `kpfguide.ALL_LOOPS` Scripts Called: - `kpf.guider.StartTriggerFile` - `kpf.guider.StopTriggerFile` - `kpf.guider.WaitForTriggerFile` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'duration' , value_min = 0 ) @classmethod def perform ( cls , args , logger , cfg ): duration = float ( args . get ( 'duration' )) kpfguide = ktl . cache ( 'kpfguide' ) # Read initial conditions, so we can set them back at the end initial_trigcube = kpfguide [ 'TRIGCUBE' ] . read () initial_lastfile = kpfguide [ 'LASTTRIGFILE' ] . read () initial_all_loops = kpfguide [ 'ALL_LOOPS' ] . read () # Do we want to take the image cube? collect_image_cube = args . get ( 'ImageCube' , True ) set_trigcube = { True : 'Active' , False : 'Inactive' }[ collect_image_cube ] kpfguide [ 'TRIGCUBE' ] . write ( set_trigcube ) # Trigger data collection log . info ( f \"Starting guider cube data collection, duration = { duration : .1f } s\" ) StartTriggerFile . execute ({}) time . sleep ( duration ) StopTriggerFile . execute ({}) # Stop all loops if we're writing out a full image cube # if initial_all_loops == 'Active' and collect_image_cube == True: # kpfguide['ALL_LOOPS'].write('Inactive', wait=False) cube_file = WaitForTriggerFile . execute ({ 'initial_lastfile' : initial_lastfile }) # Reset TRIGCUBE kpfguide [ 'TRIGCUBE' ] . write ( initial_trigcube ) # Reset ALL_LOOPS to initial values # if initial_all_loops == 'Active' and collect_image_cube == True: # kpfguide['ALL_LOOPS'].write(initial_all_loops) return cube_file @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'duration' , type = float , help = 'The duration in seconds' ) parser . add_argument ( \"--noTRIGCUBE\" , dest = \"ImageCube\" , default = True , action = \"store_false\" , help = \"Collect the full image cube?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"TakeGuiderCube"},{"location":"scripts/TakeGuiderExposure/","text":"TakeGuiderExposure Bases: KPFTranslatorFunction Depending on whether the guide camera is running in continuous mode or not, this will either grab the next exposure (if in continuous mode) or trigger a new exposure. KTL Keywords Used: kpfguide.EXPTIME kpfguide.LASTFILE Scripts Called: kpf.guider.TriggerSingleGuiderExposure kpf.guider.GrabGuiderExposure Source code in kpf/guider/TakeGuiderExposure.py 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class TakeGuiderExposure ( KPFTranslatorFunction ): '''Depending on whether the guide camera is running in continuous mode or not, this will either grab the next exposure (if in continuous mode) or trigger a new exposure. KTL Keywords Used: - `kpfguide.EXPTIME` - `kpfguide.LASTFILE` Scripts Called: - `kpf.guider.TriggerSingleGuiderExposure` - `kpf.guider.GrabGuiderExposure` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) exptime = kpfguide [ 'EXPTIME' ] . read ( binary = True ) lastfile = kpfguide [ 'LASTFILE' ] if guider_is_active (): if guider_is_saving (): GrabGuiderExposure . execute ({}) else : # not sure what right action is here log . warning ( 'Guider is active, but not saving. No image saved.' ) else : TriggerSingleGuiderExposure . execute ({}) lastfile . monitor () lastfile . wait ( timeout = exptime * 2 + 1 ) # Wait for update which signals a new file @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"TakeGuiderExposure"},{"location":"scripts/TakeGuiderExposure/#takeguiderexposure","text":"Bases: KPFTranslatorFunction Depending on whether the guide camera is running in continuous mode or not, this will either grab the next exposure (if in continuous mode) or trigger a new exposure. KTL Keywords Used: kpfguide.EXPTIME kpfguide.LASTFILE Scripts Called: kpf.guider.TriggerSingleGuiderExposure kpf.guider.GrabGuiderExposure Source code in kpf/guider/TakeGuiderExposure.py 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class TakeGuiderExposure ( KPFTranslatorFunction ): '''Depending on whether the guide camera is running in continuous mode or not, this will either grab the next exposure (if in continuous mode) or trigger a new exposure. KTL Keywords Used: - `kpfguide.EXPTIME` - `kpfguide.LASTFILE` Scripts Called: - `kpf.guider.TriggerSingleGuiderExposure` - `kpf.guider.GrabGuiderExposure` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) exptime = kpfguide [ 'EXPTIME' ] . read ( binary = True ) lastfile = kpfguide [ 'LASTFILE' ] if guider_is_active (): if guider_is_saving (): GrabGuiderExposure . execute ({}) else : # not sure what right action is here log . warning ( 'Guider is active, but not saving. No image saved.' ) else : TriggerSingleGuiderExposure . execute ({}) lastfile . monitor () lastfile . wait ( timeout = exptime * 2 + 1 ) # Wait for update which signals a new file @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"TakeGuiderExposure"},{"location":"scripts/TakeGuiderSensitivityData/","text":"TakeGuiderSensitivityData Bases: KPFTranslatorFunction Source code in kpf/engineering/TakeGuiderSensitivityData.py 19 20 21 22 23 24 25 26 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 class TakeGuiderSensitivityData ( KPFTranslatorFunction ): ''' ''' @classmethod @obey_scriptrun def pre_condition ( cls , OB , logger , cfg ): check_input ( OB , 'Template_Name' , allowed_values = [ 'kpf_eng_tgsd' ]) check_input ( OB , 'Template_Version' , version_check = True , value_min = '0.3' ) check_input ( OB , 'FPSvalues' ) @classmethod @register_script ( Path ( __file__ ) . name , os . getpid ()) @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in OB : log . debug ( f \" { key } : { OB [ key ] } \" ) log . info ( '-------------------------' ) images_file = log_dir / Path ( f ' { this_file_name } _images_ { now_str } .txt' ) images = Table ( names = ( 'cube file' , 'fps' ), dtype = ( 'a90' , 'f4' )) kpfguide = ktl . cache ( 'kpfguide' ) log . info ( f \"Guider gain is { kpfguide [ 'GAIN' ] . read () } \" ) log . info ( f \"Ensuring TRIGCUBE is Active\" ) kpfguide [ 'TRIGCUBE' ] . write ( 'Active' ) all_loops = kpfguide [ 'ALL_LOOPS' ] . read ( binary = True ) cube_duration = OB . get ( 'cube_duration' ) for FPS in OB . get ( 'FPSvalues' ): log . info ( f \"Setting FPS to { FPS } \" ) SetGuiderFPS . execute ({ 'GuideFPS' : FPS }) # Start cube collection log . info ( f 'Starting data collection for { cube_duration } s' ) initial_lastfile = kpfguide [ 'LASTTRIGFILE' ] . read () kpfguide [ 'TRIGGER' ] . write ( 'Active' ) log . debug ( f \"Sleeping { cube_duration } s\" ) time . sleep ( cube_duration ) # End cube collection kpfguide [ 'TRIGGER' ] . write ( 'Inactive' , wait = False ) kpfguide [ 'ALL_LOOPS' ] . write ( 'Inactive' ) # Wait for cube file to be updated ktl . waitFor ( f \"$kpfguide.LASTTRIGFILE != ' { initial_lastfile } '\" ) cube_file = kpfguide [ 'LASTTRIGFILE' ] . read () log . info ( f \" cube file: { cube_file } \" ) if all_loops == 1 : kpfguide [ 'ALL_LOOPS' ] . write ( 1 ) row = { 'cube file' : cube_file , 'fps' : FPS } images . add_row ( row ) if images_file . exists (): images_file . unlink () images . write ( images_file , format = 'ascii.csv' ) @classmethod def post_condition ( cls , OB , logger , cfg ): pass","title":"TakeGuiderSensitivityData"},{"location":"scripts/TakeGuiderSensitivityData/#takeguidersensitivitydata","text":"Bases: KPFTranslatorFunction Source code in kpf/engineering/TakeGuiderSensitivityData.py 19 20 21 22 23 24 25 26 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 class TakeGuiderSensitivityData ( KPFTranslatorFunction ): ''' ''' @classmethod @obey_scriptrun def pre_condition ( cls , OB , logger , cfg ): check_input ( OB , 'Template_Name' , allowed_values = [ 'kpf_eng_tgsd' ]) check_input ( OB , 'Template_Version' , version_check = True , value_min = '0.3' ) check_input ( OB , 'FPSvalues' ) @classmethod @register_script ( Path ( __file__ ) . name , os . getpid ()) @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in OB : log . debug ( f \" { key } : { OB [ key ] } \" ) log . info ( '-------------------------' ) images_file = log_dir / Path ( f ' { this_file_name } _images_ { now_str } .txt' ) images = Table ( names = ( 'cube file' , 'fps' ), dtype = ( 'a90' , 'f4' )) kpfguide = ktl . cache ( 'kpfguide' ) log . info ( f \"Guider gain is { kpfguide [ 'GAIN' ] . read () } \" ) log . info ( f \"Ensuring TRIGCUBE is Active\" ) kpfguide [ 'TRIGCUBE' ] . write ( 'Active' ) all_loops = kpfguide [ 'ALL_LOOPS' ] . read ( binary = True ) cube_duration = OB . get ( 'cube_duration' ) for FPS in OB . get ( 'FPSvalues' ): log . info ( f \"Setting FPS to { FPS } \" ) SetGuiderFPS . execute ({ 'GuideFPS' : FPS }) # Start cube collection log . info ( f 'Starting data collection for { cube_duration } s' ) initial_lastfile = kpfguide [ 'LASTTRIGFILE' ] . read () kpfguide [ 'TRIGGER' ] . write ( 'Active' ) log . debug ( f \"Sleeping { cube_duration } s\" ) time . sleep ( cube_duration ) # End cube collection kpfguide [ 'TRIGGER' ] . write ( 'Inactive' , wait = False ) kpfguide [ 'ALL_LOOPS' ] . write ( 'Inactive' ) # Wait for cube file to be updated ktl . waitFor ( f \"$kpfguide.LASTTRIGFILE != ' { initial_lastfile } '\" ) cube_file = kpfguide [ 'LASTTRIGFILE' ] . read () log . info ( f \" cube file: { cube_file } \" ) if all_loops == 1 : kpfguide [ 'ALL_LOOPS' ] . write ( 1 ) row = { 'cube file' : cube_file , 'fps' : FPS } images . add_row ( row ) if images_file . exists (): images_file . unlink () images . write ( images_file , format = 'ascii.csv' ) @classmethod def post_condition ( cls , OB , logger , cfg ): pass","title":"TakeGuiderSensitivityData"},{"location":"scripts/TakeIntensityReading/","text":"TakeIntensityReading Bases: KPFTranslatorFunction Insert the intensity monitor (aka \"cal diode\") in to the beam and record a measurement of the cal lamp intensity. KTL Keywords Used: kpflamps.INTENSEMON kpfcal.SERIALCONN kpfcal.INTENMON kpfcal.NAVG kpfcal.AVG kpfcal.MEASURING Scripts Called: kpf.utils.SendEmail Source code in kpf/calbench/TakeIntensityReading.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class TakeIntensityReading ( KPFTranslatorFunction ): '''Insert the intensity monitor (aka \"cal diode\") in to the beam and record a measurement of the cal lamp intensity. KTL Keywords Used: - `kpflamps.INTENSEMON` - `kpfcal.SERIALCONN` - `kpfcal.INTENMON` - `kpfcal.NAVG` - `kpfcal.AVG` - `kpfcal.MEASURING` Scripts Called: - `kpf.utils.SendEmail` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfcal = ktl . cache ( 'kpfcal' ) intensemon = ktl . cache ( 'kpflamps' , 'INTENSEMON' ) # Turn on intensity monitor if intensemon . read () == 'Off' : log . debug ( 'Turning kpflamps.INTENSEMON on' ) intensemon . write ( 'On' ) boottime = cfg . getfloat ( 'times' , 'intenmon_boot_time' , fallback = 5 ) time . sleep ( boottime ) # Verify serial connection is active if kpfcal [ 'SERIALCONN' ] . read () == 'Off' : log . debug ( 'Initiating serial connection' ) kpfcal [ 'SERIALCONN' ] . write ( 'On' ) expr = f \"($kpfcal.SERIALCONN == 'On')\" boottime = cfg . getfloat ( 'times' , 'intenmon_boot_time' , fallback = 5 ) success = ktl . waitFor ( expr , timeout = boottime ) if success is False : msg = f 'Intensity monitor serial connection is Off' log . error ( msg ) SendEmail . execute ({ 'Subject' : 'TakeIntensityReading Failed' , 'Message' : f ' { msg } ' }) # Move sensor in to beam log . info ( 'Moving Intensity Monitor in to beam' ) kpfcal [ 'INTENMON' ] . write ( 'Boresight' ) # Set averaging navg = cfg . getfloat ( 'times' , 'intenmon_avg_time' , fallback = 60 ) log . info ( f 'Starting measurement: NAVG= { navg } ' ) kpfcal [ 'NAVG' ] . write ( navg ) kpfcal [ 'AVG' ] . write ( 'On' ) # Check whether measuring is taking place expr = f \"($kpfcal.MEASURING == 'Yes')\" success = ktl . waitFor ( expr , timeout = 5 ) if success is False : msg = f 'Intensity monitor is not measuring' log . error ( msg ) SendEmail . execute ({ 'Subject' : 'TakeIntensityReading Failed' , 'Message' : f ' { msg } ' }) # Wait for readings to be complete expr = f \"($kpfcal.AVG == 'Off')\" success = ktl . waitFor ( expr , timeout = navg + 10 ) if success is False : msg = f 'Intensity monitor measurement timed out' log . error ( msg ) SendEmail . execute ({ 'Subject' : 'TakeIntensityReading Failed' , 'Message' : f ' { msg } ' }) # Move sensor out of beam log . info ( 'Moving Intensity Monitor out of beam' ) kpfcal [ 'INTENMON' ] . write ( 'Out' ) # Turn off intensity monitor log . debug ( 'Turning kpflamps.INTENSEMON off' ) intensemon . write ( 'Off' ) log . debug ( 'Turning kpfcal.SERIALCONN off' ) kpfcal [ 'SERIALCONN' ] . write ( 'Off' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"TakeIntensityReading"},{"location":"scripts/TakeIntensityReading/#takeintensityreading","text":"Bases: KPFTranslatorFunction Insert the intensity monitor (aka \"cal diode\") in to the beam and record a measurement of the cal lamp intensity. KTL Keywords Used: kpflamps.INTENSEMON kpfcal.SERIALCONN kpfcal.INTENMON kpfcal.NAVG kpfcal.AVG kpfcal.MEASURING Scripts Called: kpf.utils.SendEmail Source code in kpf/calbench/TakeIntensityReading.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class TakeIntensityReading ( KPFTranslatorFunction ): '''Insert the intensity monitor (aka \"cal diode\") in to the beam and record a measurement of the cal lamp intensity. KTL Keywords Used: - `kpflamps.INTENSEMON` - `kpfcal.SERIALCONN` - `kpfcal.INTENMON` - `kpfcal.NAVG` - `kpfcal.AVG` - `kpfcal.MEASURING` Scripts Called: - `kpf.utils.SendEmail` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfcal = ktl . cache ( 'kpfcal' ) intensemon = ktl . cache ( 'kpflamps' , 'INTENSEMON' ) # Turn on intensity monitor if intensemon . read () == 'Off' : log . debug ( 'Turning kpflamps.INTENSEMON on' ) intensemon . write ( 'On' ) boottime = cfg . getfloat ( 'times' , 'intenmon_boot_time' , fallback = 5 ) time . sleep ( boottime ) # Verify serial connection is active if kpfcal [ 'SERIALCONN' ] . read () == 'Off' : log . debug ( 'Initiating serial connection' ) kpfcal [ 'SERIALCONN' ] . write ( 'On' ) expr = f \"($kpfcal.SERIALCONN == 'On')\" boottime = cfg . getfloat ( 'times' , 'intenmon_boot_time' , fallback = 5 ) success = ktl . waitFor ( expr , timeout = boottime ) if success is False : msg = f 'Intensity monitor serial connection is Off' log . error ( msg ) SendEmail . execute ({ 'Subject' : 'TakeIntensityReading Failed' , 'Message' : f ' { msg } ' }) # Move sensor in to beam log . info ( 'Moving Intensity Monitor in to beam' ) kpfcal [ 'INTENMON' ] . write ( 'Boresight' ) # Set averaging navg = cfg . getfloat ( 'times' , 'intenmon_avg_time' , fallback = 60 ) log . info ( f 'Starting measurement: NAVG= { navg } ' ) kpfcal [ 'NAVG' ] . write ( navg ) kpfcal [ 'AVG' ] . write ( 'On' ) # Check whether measuring is taking place expr = f \"($kpfcal.MEASURING == 'Yes')\" success = ktl . waitFor ( expr , timeout = 5 ) if success is False : msg = f 'Intensity monitor is not measuring' log . error ( msg ) SendEmail . execute ({ 'Subject' : 'TakeIntensityReading Failed' , 'Message' : f ' { msg } ' }) # Wait for readings to be complete expr = f \"($kpfcal.AVG == 'Off')\" success = ktl . waitFor ( expr , timeout = navg + 10 ) if success is False : msg = f 'Intensity monitor measurement timed out' log . error ( msg ) SendEmail . execute ({ 'Subject' : 'TakeIntensityReading Failed' , 'Message' : f ' { msg } ' }) # Move sensor out of beam log . info ( 'Moving Intensity Monitor out of beam' ) kpfcal [ 'INTENMON' ] . write ( 'Out' ) # Turn off intensity monitor log . debug ( 'Turning kpflamps.INTENSEMON off' ) intensemon . write ( 'Off' ) log . debug ( 'Turning kpfcal.SERIALCONN off' ) kpfcal [ 'SERIALCONN' ] . write ( 'Off' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"TakeIntensityReading"},{"location":"scripts/TestTipTiltMirrorRange/","text":"TestTipTiltMirrorRange Bases: KPFTranslatorFunction Verify if the tip tilt system is reaching the nominal range. Output is only via log messages. KTL Keywords Used: kpffiu.TTXVAX kpffiu.TTYVAX kpfguide.TIPTILT_HOME kpfguide.TIPTILT_XRANGE kpfguide.TIPTILT_YRANGE Scripts Called: kpf.fiu.InitializeTipTilt kpf.fiu.ShutdownTipTilt Source code in kpf/fiu/TestTipTiltMirrorRange.py 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class TestTipTiltMirrorRange ( KPFTranslatorFunction ): '''Verify if the tip tilt system is reaching the nominal range. Output is only via log messages. KTL Keywords Used: - `kpffiu.TTXVAX` - `kpffiu.TTYVAX` - `kpfguide.TIPTILT_HOME` - `kpfguide.TIPTILT_XRANGE` - `kpfguide.TIPTILT_YRANGE` Scripts Called: - `kpf.fiu.InitializeTipTilt` - `kpf.fiu.ShutdownTipTilt` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # Measure tip tilt ranges log . info ( 'Beginning TestTipTiltMirrorRange' ) InitializeTipTilt . execute ({}) movetime = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) tol = cfg . getfloat ( 'tolerances' , 'tip_tilt_move_tolerance' , fallback = 0.1 ) kpffiu = ktl . cache ( 'kpffiu' ) kpfguide = ktl . cache ( 'kpfguide' ) axis = [ 'X' , 'Y' ] for i , ax in enumerate ( axis ): nominal_range = kpfguide [ f 'TIPTILT_ { ax } RANGE' ] . read ( binary = True ) home = kpfguide [ 'TIPTILT_HOME' ] . read ( binary = True )[ i ] commanded_position = home - nominal_range log . info ( f \"Sending TT { ax } VAX to { commanded_position } \" ) kpffiu [ f 'TT { ax } VAX' ] . write ( commanded_position ) time . sleep ( movetime * 100 ) current_position = kpffiu [ f 'TT { ax } VAX' ] . read ( binary = True ) if abs ( current_position - commanded_position ) < tol : log . info ( f \" { ax } reached nominal range: { commanded_position } \" ) else : log . error ( f \" { ax } failed to reach { commanded_position } : { current_position } \" ) commanded_position = home + nominal_range log . info ( f \"Sending TT { ax } VAX to { commanded_position } \" ) kpffiu [ f 'TT { ax } VAX' ] . write ( commanded_position ) time . sleep ( movetime * 100 ) current_position = kpffiu [ f 'TT { ax } VAX' ] . read ( binary = True ) if abs ( current_position - commanded_position ) < tol : log . info ( f \" { ax } reached nominal range: { commanded_position } \" ) else : log . error ( f \" { ax } failed to reach { commanded_position } : { current_position } \" ) time . sleep ( movetime * 100 ) InitializeTipTilt . execute ({}) time . sleep ( movetime * 100 ) ShutdownTipTilt . execute ({}) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"TestTipTiltMirrorRange"},{"location":"scripts/TestTipTiltMirrorRange/#testtiptiltmirrorrange","text":"Bases: KPFTranslatorFunction Verify if the tip tilt system is reaching the nominal range. Output is only via log messages. KTL Keywords Used: kpffiu.TTXVAX kpffiu.TTYVAX kpfguide.TIPTILT_HOME kpfguide.TIPTILT_XRANGE kpfguide.TIPTILT_YRANGE Scripts Called: kpf.fiu.InitializeTipTilt kpf.fiu.ShutdownTipTilt Source code in kpf/fiu/TestTipTiltMirrorRange.py 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class TestTipTiltMirrorRange ( KPFTranslatorFunction ): '''Verify if the tip tilt system is reaching the nominal range. Output is only via log messages. KTL Keywords Used: - `kpffiu.TTXVAX` - `kpffiu.TTYVAX` - `kpfguide.TIPTILT_HOME` - `kpfguide.TIPTILT_XRANGE` - `kpfguide.TIPTILT_YRANGE` Scripts Called: - `kpf.fiu.InitializeTipTilt` - `kpf.fiu.ShutdownTipTilt` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # Measure tip tilt ranges log . info ( 'Beginning TestTipTiltMirrorRange' ) InitializeTipTilt . execute ({}) movetime = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) tol = cfg . getfloat ( 'tolerances' , 'tip_tilt_move_tolerance' , fallback = 0.1 ) kpffiu = ktl . cache ( 'kpffiu' ) kpfguide = ktl . cache ( 'kpfguide' ) axis = [ 'X' , 'Y' ] for i , ax in enumerate ( axis ): nominal_range = kpfguide [ f 'TIPTILT_ { ax } RANGE' ] . read ( binary = True ) home = kpfguide [ 'TIPTILT_HOME' ] . read ( binary = True )[ i ] commanded_position = home - nominal_range log . info ( f \"Sending TT { ax } VAX to { commanded_position } \" ) kpffiu [ f 'TT { ax } VAX' ] . write ( commanded_position ) time . sleep ( movetime * 100 ) current_position = kpffiu [ f 'TT { ax } VAX' ] . read ( binary = True ) if abs ( current_position - commanded_position ) < tol : log . info ( f \" { ax } reached nominal range: { commanded_position } \" ) else : log . error ( f \" { ax } failed to reach { commanded_position } : { current_position } \" ) commanded_position = home + nominal_range log . info ( f \"Sending TT { ax } VAX to { commanded_position } \" ) kpffiu [ f 'TT { ax } VAX' ] . write ( commanded_position ) time . sleep ( movetime * 100 ) current_position = kpffiu [ f 'TT { ax } VAX' ] . read ( binary = True ) if abs ( current_position - commanded_position ) < tol : log . info ( f \" { ax } reached nominal range: { commanded_position } \" ) else : log . error ( f \" { ax } failed to reach { commanded_position } : { current_position } \" ) time . sleep ( movetime * 100 ) InitializeTipTilt . execute ({}) time . sleep ( movetime * 100 ) ShutdownTipTilt . execute ({}) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"TestTipTiltMirrorRange"},{"location":"scripts/TriggerGreenMiniFill/","text":"TriggerGreenMiniFill Bases: KPFTranslatorFunction I really hope this is not necessary in the long term. Source code in kpf/engineering/TriggerGreenMiniFill.py 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class TriggerGreenMiniFill ( KPFTranslatorFunction ): '''I really hope this is not necessary in the long term. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): kpffill = ktl . cache ( 'kpffill' ) if kpffill [ 'GREENFILLIP' ] . read () == 'True' : raise FailedPreCondition ( 'Green fill already in progress' ) @classmethod def perform ( cls , args , logger , cfg ): kpffill = ktl . cache ( 'kpffill' ) # Start fill log . warning ( f 'Starting green mini fill' ) kpffill [ 'GREENSTART' ] . write ( 1 ) # Wait sleep_time = args . get ( 'duration' , 240 ) log . debug ( f 'Sleeping { sleep_time : .0f } s' ) time . sleep ( sleep_time ) # Stop fill if kpffill [ 'GREENFILLIP' ] . read () == 'True' : log . warning ( f 'Stopping green mini fill' ) kpffill [ 'GREENSTOP' ] . write ( 1 ) time . sleep ( 5 ) else : msg = 'Expected green mini fill to be in progress.' SendEmail . execute ({ 'Subject' : 'TriggerGreenMiniFill Failed' , 'Message' : f ' { msg } ' }) raise KPFException ( msg ) @classmethod def post_condition ( cls , args , logger , cfg ): kpffill = ktl . cache ( 'kpffill' ) if kpffill [ 'GREENFILLIP' ] . read () == 'True' : msg = 'Green still in progress, should be stopped!' SendEmail . execute ({ 'Subject' : 'TriggerGreenMiniFill Failed' , 'Message' : f ' { msg } ' }) raise FailedPostCondition ( msg ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'duration' , type = float , help = 'The duration of the fill in seconds (240 recommended)' ) return super () . add_cmdline_args ( parser , cfg )","title":"TriggerGreenMiniFill"},{"location":"scripts/TriggerGreenMiniFill/#triggergreenminifill","text":"Bases: KPFTranslatorFunction I really hope this is not necessary in the long term. Source code in kpf/engineering/TriggerGreenMiniFill.py 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class TriggerGreenMiniFill ( KPFTranslatorFunction ): '''I really hope this is not necessary in the long term. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): kpffill = ktl . cache ( 'kpffill' ) if kpffill [ 'GREENFILLIP' ] . read () == 'True' : raise FailedPreCondition ( 'Green fill already in progress' ) @classmethod def perform ( cls , args , logger , cfg ): kpffill = ktl . cache ( 'kpffill' ) # Start fill log . warning ( f 'Starting green mini fill' ) kpffill [ 'GREENSTART' ] . write ( 1 ) # Wait sleep_time = args . get ( 'duration' , 240 ) log . debug ( f 'Sleeping { sleep_time : .0f } s' ) time . sleep ( sleep_time ) # Stop fill if kpffill [ 'GREENFILLIP' ] . read () == 'True' : log . warning ( f 'Stopping green mini fill' ) kpffill [ 'GREENSTOP' ] . write ( 1 ) time . sleep ( 5 ) else : msg = 'Expected green mini fill to be in progress.' SendEmail . execute ({ 'Subject' : 'TriggerGreenMiniFill Failed' , 'Message' : f ' { msg } ' }) raise KPFException ( msg ) @classmethod def post_condition ( cls , args , logger , cfg ): kpffill = ktl . cache ( 'kpffill' ) if kpffill [ 'GREENFILLIP' ] . read () == 'True' : msg = 'Green still in progress, should be stopped!' SendEmail . execute ({ 'Subject' : 'TriggerGreenMiniFill Failed' , 'Message' : f ' { msg } ' }) raise FailedPostCondition ( msg ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'duration' , type = float , help = 'The duration of the fill in seconds (240 recommended)' ) return super () . add_cmdline_args ( parser , cfg )","title":"TriggerGreenMiniFill"},{"location":"scripts/TriggerRedMiniFill/","text":"TriggerRedMiniFill Bases: KPFTranslatorFunction I really hope this is not necessary in the long term. Source code in kpf/engineering/TriggerRedMiniFill.py 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class TriggerRedMiniFill ( KPFTranslatorFunction ): '''I really hope this is not necessary in the long term. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): kpffill = ktl . cache ( 'kpffill' ) if kpffill [ 'REDFILLIP' ] . read () == 'True' : raise FailedPreCondition ( 'Red fill already in progress' ) @classmethod def perform ( cls , args , logger , cfg ): kpffill = ktl . cache ( 'kpffill' ) # Start fill log . warning ( f 'Starting Red mini fill' ) kpffill [ 'REDSTART' ] . write ( 1 ) # Wait sleep_time = args . get ( 'duration' , 240 ) log . debug ( f 'Sleeping { sleep_time : .0f } s' ) time . sleep ( sleep_time ) # Stop fill if kpffill [ 'REDFILLIP' ] . read () == 'True' : log . warning ( f 'Stopping Red mini fill' ) kpffill [ 'REDSTOP' ] . write ( 1 ) time . sleep ( 5 ) else : msg = 'Expected Red mini fill to be in progress.' SendEmail . execute ({ 'Subject' : 'TriggerRedMiniFill Failed' , 'Message' : f ' { msg } ' }) raise KPFException ( msg ) @classmethod def post_condition ( cls , args , logger , cfg ): kpffill = ktl . cache ( 'kpffill' ) if kpffill [ 'RedFILLIP' ] . read () == 'True' : msg = 'Red still in progress, should be stopped!' SendEmail . execute ({ 'Subject' : 'TriggerRedMiniFill Failed' , 'Message' : f ' { msg } ' }) raise FailedPostCondition ( msg ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'duration' , type = float , help = 'The duration of the fill in seconds (240 recommended)' ) return super () . add_cmdline_args ( parser , cfg )","title":"TriggerRedMiniFill"},{"location":"scripts/TriggerRedMiniFill/#triggerredminifill","text":"Bases: KPFTranslatorFunction I really hope this is not necessary in the long term. Source code in kpf/engineering/TriggerRedMiniFill.py 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class TriggerRedMiniFill ( KPFTranslatorFunction ): '''I really hope this is not necessary in the long term. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): kpffill = ktl . cache ( 'kpffill' ) if kpffill [ 'REDFILLIP' ] . read () == 'True' : raise FailedPreCondition ( 'Red fill already in progress' ) @classmethod def perform ( cls , args , logger , cfg ): kpffill = ktl . cache ( 'kpffill' ) # Start fill log . warning ( f 'Starting Red mini fill' ) kpffill [ 'REDSTART' ] . write ( 1 ) # Wait sleep_time = args . get ( 'duration' , 240 ) log . debug ( f 'Sleeping { sleep_time : .0f } s' ) time . sleep ( sleep_time ) # Stop fill if kpffill [ 'REDFILLIP' ] . read () == 'True' : log . warning ( f 'Stopping Red mini fill' ) kpffill [ 'REDSTOP' ] . write ( 1 ) time . sleep ( 5 ) else : msg = 'Expected Red mini fill to be in progress.' SendEmail . execute ({ 'Subject' : 'TriggerRedMiniFill Failed' , 'Message' : f ' { msg } ' }) raise KPFException ( msg ) @classmethod def post_condition ( cls , args , logger , cfg ): kpffill = ktl . cache ( 'kpffill' ) if kpffill [ 'RedFILLIP' ] . read () == 'True' : msg = 'Red still in progress, should be stopped!' SendEmail . execute ({ 'Subject' : 'TriggerRedMiniFill Failed' , 'Message' : f ' { msg } ' }) raise FailedPostCondition ( msg ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'duration' , type = float , help = 'The duration of the fill in seconds (240 recommended)' ) return super () . add_cmdline_args ( parser , cfg )","title":"TriggerRedMiniFill"},{"location":"scripts/TurnHepaOff/","text":"TurnHepaOff Bases: KPFTranslatorFunction Turn HEPA Filter system off KTL Keywords Used: ao.OBHPAON ao.OBHPASTA Source code in kpf/ao/TurnHepaOff.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class TurnHepaOff ( KPFTranslatorFunction ): '''Turn HEPA Filter system off KTL Keywords Used: - `ao.OBHPAON` - `ao.OBHPASTA` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) log . debug ( 'Setting AO HEPA filter to off' ) ao [ 'OBHPAON' ] . write ( 0 ) @classmethod def post_condition ( cls , args , logger , cfg ): success = ktl . waitfor ( '($ao.OBHPASTA == off)' , timeout = 3 ) if success is not True : ao = ktl . cache ( 'ao' ) raise FailedToReachDestination ( ao [ 'OBHPASTA' ] . read (), 'off' )","title":"TurnHepaOff"},{"location":"scripts/TurnHepaOff/#turnhepaoff","text":"Bases: KPFTranslatorFunction Turn HEPA Filter system off KTL Keywords Used: ao.OBHPAON ao.OBHPASTA Source code in kpf/ao/TurnHepaOff.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class TurnHepaOff ( KPFTranslatorFunction ): '''Turn HEPA Filter system off KTL Keywords Used: - `ao.OBHPAON` - `ao.OBHPASTA` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) log . debug ( 'Setting AO HEPA filter to off' ) ao [ 'OBHPAON' ] . write ( 0 ) @classmethod def post_condition ( cls , args , logger , cfg ): success = ktl . waitfor ( '($ao.OBHPASTA == off)' , timeout = 3 ) if success is not True : ao = ktl . cache ( 'ao' ) raise FailedToReachDestination ( ao [ 'OBHPASTA' ] . read (), 'off' )","title":"TurnHepaOff"},{"location":"scripts/TurnHepaOn/","text":"TurnHepaOn Bases: KPFTranslatorFunction Turn HEPA Filter system on KTL Keywords Used: ao.OBHPAON ao.OBHPASTA Source code in kpf/ao/TurnHepaOn.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class TurnHepaOn ( KPFTranslatorFunction ): '''Turn HEPA Filter system on KTL Keywords Used: - `ao.OBHPAON` - `ao.OBHPASTA` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) log . debug ( 'Setting AO HEPA filter to on' ) ao [ 'OBHPAON' ] . write ( 1 ) @classmethod def post_condition ( cls , args , logger , cfg ): success = ktl . waitfor ( '($ao.OBHPASTA == on)' , timeout = 3 ) if success is not True : ao = ktl . cache ( 'ao' ) raise FailedToReachDestination ( ao [ 'OBHPASTA' ] . read (), 'on' )","title":"TurnHepaOn"},{"location":"scripts/TurnHepaOn/#turnhepaon","text":"Bases: KPFTranslatorFunction Turn HEPA Filter system on KTL Keywords Used: ao.OBHPAON ao.OBHPASTA Source code in kpf/ao/TurnHepaOn.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class TurnHepaOn ( KPFTranslatorFunction ): '''Turn HEPA Filter system on KTL Keywords Used: - `ao.OBHPAON` - `ao.OBHPASTA` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) log . debug ( 'Setting AO HEPA filter to on' ) ao [ 'OBHPAON' ] . write ( 1 ) @classmethod def post_condition ( cls , args , logger , cfg ): success = ktl . waitfor ( '($ao.OBHPASTA == on)' , timeout = 3 ) if success is not True : ao = ktl . cache ( 'ao' ) raise FailedToReachDestination ( ao [ 'OBHPASTA' ] . read (), 'on' )","title":"TurnHepaOn"},{"location":"scripts/TurnLightSourceOff/","text":"TurnLightSourceOff Bases: KPFTranslatorFunction Turn K1 AO light source off KTL Keywords Used: ao.OBSWON ao.OBSWSTA Source code in kpf/ao/TurnLightSourceOff.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class TurnLightSourceOff ( KPFTranslatorFunction ): '''Turn K1 AO light source off KTL Keywords Used: - `ao.OBSWON` - `ao.OBSWSTA` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) log . debug ( 'Turning AO light source off' ) ao [ 'OBSWON' ] . write ( 0 ) @classmethod def post_condition ( cls , args , logger , cfg ): success = ktl . waitfor ( '($ao.OBSWSTA == off)' , timeout = 3 ) if success is not True : ao = ktl . cache ( 'ao' ) raise FailedToReachDestination ( ao [ 'OBSWSTA' ] . read (), 'off' )","title":"TurnLightSourceOff"},{"location":"scripts/TurnLightSourceOff/#turnlightsourceoff","text":"Bases: KPFTranslatorFunction Turn K1 AO light source off KTL Keywords Used: ao.OBSWON ao.OBSWSTA Source code in kpf/ao/TurnLightSourceOff.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class TurnLightSourceOff ( KPFTranslatorFunction ): '''Turn K1 AO light source off KTL Keywords Used: - `ao.OBSWON` - `ao.OBSWSTA` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) log . debug ( 'Turning AO light source off' ) ao [ 'OBSWON' ] . write ( 0 ) @classmethod def post_condition ( cls , args , logger , cfg ): success = ktl . waitfor ( '($ao.OBSWSTA == off)' , timeout = 3 ) if success is not True : ao = ktl . cache ( 'ao' ) raise FailedToReachDestination ( ao [ 'OBSWSTA' ] . read (), 'off' )","title":"TurnLightSourceOff"},{"location":"scripts/UnlockFIU/","text":"UnlockFIU Bases: KPFTranslatorFunction Unlock the FIU mechanisms KTL Keywords Used: kpffiu.ADC1LCK kpffiu.ADC2LCK kpffiu.FOLDLCK kpffiu.HKXLCK kpffiu.HKYLCK kpffiu.TTXLCK kpffiu.TTYLCK Source code in kpf/fiu/UnlockFIU.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 class UnlockFIU ( KPFTranslatorFunction ): '''Unlock the FIU mechanisms KTL Keywords Used: - `kpffiu.ADC1LCK` - `kpffiu.ADC2LCK` - `kpffiu.FOLDLCK` - `kpffiu.HKXLCK` - `kpffiu.HKYLCK` - `kpffiu.TTXLCK` - `kpffiu.TTYLCK` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpffiu = ktl . cache ( 'kpffiu' ) kpffiu [ 'adc1lck' ] . write ( '' ) kpffiu [ 'adc2lck' ] . write ( '' ) kpffiu [ 'foldlck' ] . write ( '' ) kpffiu [ 'hkxlck' ] . write ( '' ) kpffiu [ 'hkylck' ] . write ( '' ) kpffiu [ 'ttxlck' ] . write ( '' ) kpffiu [ 'ttylck' ] . write ( '' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"UnlockFIU"},{"location":"scripts/UnlockFIU/#unlockfiu","text":"Bases: KPFTranslatorFunction Unlock the FIU mechanisms KTL Keywords Used: kpffiu.ADC1LCK kpffiu.ADC2LCK kpffiu.FOLDLCK kpffiu.HKXLCK kpffiu.HKYLCK kpffiu.TTXLCK kpffiu.TTYLCK Source code in kpf/fiu/UnlockFIU.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 class UnlockFIU ( KPFTranslatorFunction ): '''Unlock the FIU mechanisms KTL Keywords Used: - `kpffiu.ADC1LCK` - `kpffiu.ADC2LCK` - `kpffiu.FOLDLCK` - `kpffiu.HKXLCK` - `kpffiu.HKYLCK` - `kpffiu.TTXLCK` - `kpffiu.TTYLCK` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpffiu = ktl . cache ( 'kpffiu' ) kpffiu [ 'adc1lck' ] . write ( '' ) kpffiu [ 'adc2lck' ] . write ( '' ) kpffiu [ 'foldlck' ] . write ( '' ) kpffiu [ 'hkxlck' ] . write ( '' ) kpffiu [ 'hkylck' ] . write ( '' ) kpffiu [ 'ttxlck' ] . write ( '' ) kpffiu [ 'ttylck' ] . write ( '' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"UnlockFIU"},{"location":"scripts/VerifyCurrentBase/","text":"VerifyCurrentBase Bases: KPFTranslatorFunction Check whether the tip tilt system's target pixel (kpffiu.CURRENT_BASE) is consistent with the selected pointing origin (dcs.PONAME) KTL Keywords Used: dcs1.PONAME kpfguide.CURRENT_BASE kpfguide.SCIENCE_BASE kpfguide.SKY_BASE Source code in kpf/fiu/VerifyCurrentBase.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class VerifyCurrentBase ( KPFTranslatorFunction ): '''Check whether the tip tilt system's target pixel (kpffiu.CURRENT_BASE) is consistent with the selected pointing origin (dcs.PONAME) KTL Keywords Used: - `dcs1.PONAME` - `kpfguide.CURRENT_BASE` - `kpfguide.SCIENCE_BASE` - `kpfguide.SKY_BASE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): ponamekw = ktl . cache ( 'dcs1' , 'PONAME' ) poname = ponamekw . read () . upper () kpfguide = ktl . cache ( 'kpfguide' ) current_base = kpfguide [ 'CURRENT_BASE' ] . read ( binary = True ) science_base = kpfguide [ 'SCIENCE_BASE' ] . read ( binary = True ) sky_base = kpfguide [ 'SKY_BASE' ] . read ( binary = True ) science_match = np . all ( np . isclose ( current_base , science_base , atol = 0.01 )) sky_match = np . all ( np . isclose ( current_base , sky_base , atol = 0.01 )) msg = f \"CURRENT_BASE=\" if science_match : log . debug ( f \"CURRENT_BASE is science fiber, PO = { poname } \" ) msg += 'SCIENCE_BASE' elif sky_match : log . debug ( f \"CURRENT_BASE is sky fiber, PO = { poname } \" ) msg += 'SKY_BASE' else : log . debug ( f \"CURRENT_BASE is { current_base } , PO = { poname } \" ) msg += 'custom' poname_match = ( science_match and poname == 'KPF' ) \\ or ( sky_match and poname == 'SKY' ) if poname_match : msg += f \" which is consistent with PONAME= { poname } \" log . debug ( msg ) else : msg += f \" which is NOT consistent with PONAME= { poname } \" log . error ( msg ) print ( msg ) return poname_match @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"VerifyCurrentBase"},{"location":"scripts/VerifyCurrentBase/#verifycurrentbase","text":"Bases: KPFTranslatorFunction Check whether the tip tilt system's target pixel (kpffiu.CURRENT_BASE) is consistent with the selected pointing origin (dcs.PONAME) KTL Keywords Used: dcs1.PONAME kpfguide.CURRENT_BASE kpfguide.SCIENCE_BASE kpfguide.SKY_BASE Source code in kpf/fiu/VerifyCurrentBase.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class VerifyCurrentBase ( KPFTranslatorFunction ): '''Check whether the tip tilt system's target pixel (kpffiu.CURRENT_BASE) is consistent with the selected pointing origin (dcs.PONAME) KTL Keywords Used: - `dcs1.PONAME` - `kpfguide.CURRENT_BASE` - `kpfguide.SCIENCE_BASE` - `kpfguide.SKY_BASE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): ponamekw = ktl . cache ( 'dcs1' , 'PONAME' ) poname = ponamekw . read () . upper () kpfguide = ktl . cache ( 'kpfguide' ) current_base = kpfguide [ 'CURRENT_BASE' ] . read ( binary = True ) science_base = kpfguide [ 'SCIENCE_BASE' ] . read ( binary = True ) sky_base = kpfguide [ 'SKY_BASE' ] . read ( binary = True ) science_match = np . all ( np . isclose ( current_base , science_base , atol = 0.01 )) sky_match = np . all ( np . isclose ( current_base , sky_base , atol = 0.01 )) msg = f \"CURRENT_BASE=\" if science_match : log . debug ( f \"CURRENT_BASE is science fiber, PO = { poname } \" ) msg += 'SCIENCE_BASE' elif sky_match : log . debug ( f \"CURRENT_BASE is sky fiber, PO = { poname } \" ) msg += 'SKY_BASE' else : log . debug ( f \"CURRENT_BASE is { current_base } , PO = { poname } \" ) msg += 'custom' poname_match = ( science_match and poname == 'KPF' ) \\ or ( sky_match and poname == 'SKY' ) if poname_match : msg += f \" which is consistent with PONAME= { poname } \" log . debug ( msg ) else : msg += f \" which is NOT consistent with PONAME= { poname } \" log . error ( msg ) print ( msg ) return poname_match @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"VerifyCurrentBase"},{"location":"scripts/WaitForCalSource/","text":"WaitForCalSource Bases: KPFTranslatorFunction Wait for the move to a cal source is complete (kpfcal.OCTAGON keyword). Parameters: CalSource ( str ) \u2013 Which lamp to select? Allowed Values: EtalonFiber, BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, SoCal-CalFib, LFCFiber KTL Keywords Used: kpfcal.OCTAGON Source code in kpf/calbench/WaitForCalSource.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class WaitForCalSource ( KPFTranslatorFunction ): '''Wait for the move to a cal source is complete (kpfcal.OCTAGON keyword). Args: CalSource (str): Which lamp to select? Allowed Values: EtalonFiber, BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, SoCal-CalFib, LFCFiber KTL Keywords Used: - `kpfcal.OCTAGON` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'OCTAGON' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) check_input ( args , 'CalSource' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): target = args . get ( 'CalSource' ) timeout = cfg . getfloat ( 'times' , 'octagon_move_time' , fallback = 60 ) expr = f \"($kpfcal.OCTAGON == { target } )\" success = ktl . waitFor ( expr , timeout = timeout ) if success is False : log . error ( f \"Timed out waiting for octagon\" ) @classmethod def post_condition ( cls , args , logger , cfg ): target = args . get ( 'CalSource' ) timeout = cfg . getfloat ( 'times' , 'octagon_move_time' , fallback = 60 ) expr = f \"($kpfcal.OCTAGON == { target } )\" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : kpfcal = ktl . cache ( 'kpfcal' ) raise FailedToReachDestination ( kpfcal [ 'OCTAGON' ] . read (), target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalSource' , type = str , choices = [ 'Home' , 'EtalonFiber' , 'BrdbandFiber' , 'U_gold' , 'U_daily' , 'Th_daily' , 'Th_gold' , 'SoCal-CalFib' , 'LFCFiber' ], help = 'Octagon position to choose?' ) return super () . add_cmdline_args ( parser , cfg )","title":"WaitForCalSource"},{"location":"scripts/WaitForCalSource/#waitforcalsource","text":"Bases: KPFTranslatorFunction Wait for the move to a cal source is complete (kpfcal.OCTAGON keyword). Parameters: CalSource ( str ) \u2013 Which lamp to select? Allowed Values: EtalonFiber, BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, SoCal-CalFib, LFCFiber KTL Keywords Used: kpfcal.OCTAGON Source code in kpf/calbench/WaitForCalSource.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class WaitForCalSource ( KPFTranslatorFunction ): '''Wait for the move to a cal source is complete (kpfcal.OCTAGON keyword). Args: CalSource (str): Which lamp to select? Allowed Values: EtalonFiber, BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, SoCal-CalFib, LFCFiber KTL Keywords Used: - `kpfcal.OCTAGON` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'OCTAGON' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) check_input ( args , 'CalSource' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): target = args . get ( 'CalSource' ) timeout = cfg . getfloat ( 'times' , 'octagon_move_time' , fallback = 60 ) expr = f \"($kpfcal.OCTAGON == { target } )\" success = ktl . waitFor ( expr , timeout = timeout ) if success is False : log . error ( f \"Timed out waiting for octagon\" ) @classmethod def post_condition ( cls , args , logger , cfg ): target = args . get ( 'CalSource' ) timeout = cfg . getfloat ( 'times' , 'octagon_move_time' , fallback = 60 ) expr = f \"($kpfcal.OCTAGON == { target } )\" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : kpfcal = ktl . cache ( 'kpfcal' ) raise FailedToReachDestination ( kpfcal [ 'OCTAGON' ] . read (), target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalSource' , type = str , choices = [ 'Home' , 'EtalonFiber' , 'BrdbandFiber' , 'U_gold' , 'U_daily' , 'Th_daily' , 'Th_gold' , 'SoCal-CalFib' , 'LFCFiber' ], help = 'Octagon position to choose?' ) return super () . add_cmdline_args ( parser , cfg )","title":"WaitForCalSource"},{"location":"scripts/WaitForConfigureCalibrations/","text":"WaitForConfigureCalibrations Bases: KPFTranslatorFunction Script which waits for the instrument to be configured for calibrations. ARGS: None Source code in kpf/scripts/WaitForConfigureCalibrations.py 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 class WaitForConfigureCalibrations ( KPFTranslatorFunction ): '''Script which waits for the instrument to be configured for calibrations. ARGS: ===== None ''' @classmethod def pre_condition ( cls , OB , logger , cfg ): check_input ( OB , 'Template_Name' , allowed_values = [ 'kpf_cal' ]) check_input ( OB , 'Template_Version' , version_check = True , value_min = '0.5' ) @classmethod def perform ( cls , OB , logger , cfg ): WaitForCalSource . execute ( OB ) WaitForConfigureFIU . execute ({ 'mode' : 'Calibration' }) WaitForReady . execute ({}) @classmethod def post_condition ( cls , OB , logger , cfg ): pass","title":"WaitForConfigureCalibrations"},{"location":"scripts/WaitForConfigureCalibrations/#waitforconfigurecalibrations","text":"Bases: KPFTranslatorFunction Script which waits for the instrument to be configured for calibrations.","title":"WaitForConfigureCalibrations"},{"location":"scripts/WaitForConfigureCalibrations/#kpf.scripts.WaitForConfigureCalibrations.WaitForConfigureCalibrations--args","text":"None Source code in kpf/scripts/WaitForConfigureCalibrations.py 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 class WaitForConfigureCalibrations ( KPFTranslatorFunction ): '''Script which waits for the instrument to be configured for calibrations. ARGS: ===== None ''' @classmethod def pre_condition ( cls , OB , logger , cfg ): check_input ( OB , 'Template_Name' , allowed_values = [ 'kpf_cal' ]) check_input ( OB , 'Template_Version' , version_check = True , value_min = '0.5' ) @classmethod def perform ( cls , OB , logger , cfg ): WaitForCalSource . execute ( OB ) WaitForConfigureFIU . execute ({ 'mode' : 'Calibration' }) WaitForReady . execute ({}) @classmethod def post_condition ( cls , OB , logger , cfg ): pass","title":"ARGS:"},{"location":"scripts/WaitForConfigureFIU/","text":"WaitForConfigureFIU Bases: KPFTranslatorFunction Wait for the FIU to reach specified mode (kpffiu.MODE). This will retry the configure command if the system fails to reach its destination. Parameters: mode ( str ) \u2013 The desired FIU mode. Allowed values: Stowed, Alignment, Acquisition, Observing, Calibration KTL Keywords Used: kpffiu.MODE Scripts Called: kpf.calbench.ConfigureFIUOnce Source code in kpf/fiu/WaitForConfigureFIU.py 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 class WaitForConfigureFIU ( KPFTranslatorFunction ): '''Wait for the FIU to reach specified mode (kpffiu.MODE). This will retry the configure command if the system fails to reach its destination. Args: mode (str): The desired FIU mode. Allowed values: Stowed, Alignment, Acquisition, Observing, Calibration KTL Keywords Used: - `kpffiu.MODE` Scripts Called: - `kpf.calbench.ConfigureFIUOnce` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpffiu' , 'MODE' ) allowed_values = list ( keyword . _getEnumerators ()) if 'None' in allowed_values : allowed_values . pop ( allowed_values . index ( 'None' )) check_input ( args , 'mode' , allowed_values = allowed_values ) return True @classmethod def perform ( cls , args , logger , cfg ): dest = args . get ( 'mode' ) ntries = cfg . getint ( 'retries' , 'fiu_mode_tries' , fallback = 2 ) shim_time = cfg . getfloat ( 'times' , 'fiu_mode_shim_time' , fallback = 2 ) for i in range ( ntries ): ok = WaitForConfigureFIUOnce . execute ({ 'mode' : dest }) if ok is False : log . warning ( f 'FIU move failed on attempt { i + 1 } of { ntries } ' ) time . sleep ( shim_time ) ConfigureFIUOnce . execute ({ 'mode' : dest , 'wait' : True }) else : break @classmethod def post_condition ( cls , args , logger , cfg ): dest = args . get ( 'mode' ) kpffiu = ktl . cache ( 'kpffiu' ) modes = kpffiu [ 'MODE' ] . read () if dest . lower () not in modes . lower () . split ( ',' ): raise FailedToReachDestination ( modes , dest ) else : log . info ( f \"FIU mode is now { dest } \" ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'mode' , type = str , choices = [ 'Stowed' , 'Alignment' , 'Acquisition' , 'Observing' , 'Calibration' ], help = 'Desired mode (see kpffiu.MODE)' ) return super () . add_cmdline_args ( parser , cfg )","title":"WaitForConfigureFIU"},{"location":"scripts/WaitForConfigureFIU/#waitforconfigurefiu","text":"Bases: KPFTranslatorFunction Wait for the FIU to reach specified mode (kpffiu.MODE). This will retry the configure command if the system fails to reach its destination. Parameters: mode ( str ) \u2013 The desired FIU mode. Allowed values: Stowed, Alignment, Acquisition, Observing, Calibration KTL Keywords Used: kpffiu.MODE Scripts Called: kpf.calbench.ConfigureFIUOnce Source code in kpf/fiu/WaitForConfigureFIU.py 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 class WaitForConfigureFIU ( KPFTranslatorFunction ): '''Wait for the FIU to reach specified mode (kpffiu.MODE). This will retry the configure command if the system fails to reach its destination. Args: mode (str): The desired FIU mode. Allowed values: Stowed, Alignment, Acquisition, Observing, Calibration KTL Keywords Used: - `kpffiu.MODE` Scripts Called: - `kpf.calbench.ConfigureFIUOnce` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpffiu' , 'MODE' ) allowed_values = list ( keyword . _getEnumerators ()) if 'None' in allowed_values : allowed_values . pop ( allowed_values . index ( 'None' )) check_input ( args , 'mode' , allowed_values = allowed_values ) return True @classmethod def perform ( cls , args , logger , cfg ): dest = args . get ( 'mode' ) ntries = cfg . getint ( 'retries' , 'fiu_mode_tries' , fallback = 2 ) shim_time = cfg . getfloat ( 'times' , 'fiu_mode_shim_time' , fallback = 2 ) for i in range ( ntries ): ok = WaitForConfigureFIUOnce . execute ({ 'mode' : dest }) if ok is False : log . warning ( f 'FIU move failed on attempt { i + 1 } of { ntries } ' ) time . sleep ( shim_time ) ConfigureFIUOnce . execute ({ 'mode' : dest , 'wait' : True }) else : break @classmethod def post_condition ( cls , args , logger , cfg ): dest = args . get ( 'mode' ) kpffiu = ktl . cache ( 'kpffiu' ) modes = kpffiu [ 'MODE' ] . read () if dest . lower () not in modes . lower () . split ( ',' ): raise FailedToReachDestination ( modes , dest ) else : log . info ( f \"FIU mode is now { dest } \" ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'mode' , type = str , choices = [ 'Stowed' , 'Alignment' , 'Acquisition' , 'Observing' , 'Calibration' ], help = 'Desired mode (see kpffiu.MODE)' ) return super () . add_cmdline_args ( parser , cfg )","title":"WaitForConfigureFIU"},{"location":"scripts/WaitForFlatFieldFiberPos/","text":"WaitForFlatFieldFiberPos Bases: KPFTranslatorFunction Wait for the flat field fiber aperture via the kpfcal.FF_FIBERPOS keyword. Parameters: FF_FiberPos ( str ) \u2013 The name of the flat field fiber position desired. Allowed Values: \"Blank\", \"6 mm f/5\", \"7.5 mm f/4\", \"10 mm f/3\", \"13.2 mm f/2.3\", \"Open\". wait ( bool ) \u2013 Wait for move to complete before returning? default: True KTL Keywords Used kpfcal.FF_FIBERPOS Source code in kpf/calbench/WaitForFlatFieldFiberPos.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class WaitForFlatFieldFiberPos ( KPFTranslatorFunction ): '''Wait for the flat field fiber aperture via the `kpfcal.FF_FIBERPOS` keyword. Args: FF_FiberPos (str): The name of the flat field fiber position desired. Allowed Values: \"Blank\", \"6 mm f/5\", \"7.5 mm f/4\", \"10 mm f/3\", \"13.2 mm f/2.3\", \"Open\". wait (bool): Wait for move to complete before returning? default: True ## KTL Keywords Used - `kpfcal.FF_FIBERPOS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'FF_FiberPos' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) check_input ( args , 'FF_FiberPos' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): target = args . get ( 'FF_FiberPos' ) timeout = cfg . getfloat ( 'times' , 'nd_move_time' , fallback = 20 ) expr = f \"($kpfcal.FF_FiberPos == ' { target } ')\" success = ktl . waitFor ( expr , timeout = timeout ) if success is False : log . error ( f \"Timed out waiting for FF_FiberPos filter wheel\" ) @classmethod def post_condition ( cls , args , logger , cfg ): target = args . get ( 'FF_FiberPos' ) expr = f \"($kpfcal.FF_FiberPos == ' { target } ')\" success = ktl . waitFor ( expr , timeout = 0.1 ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'FF_FiberPos' , type = str , choices = [ \"Blank\" , \"6 mm f/5\" , \"7.5 mm f/4\" , \"10 mm f/3\" , \"13.2 mm f/2.3\" , \"Open\" ], help = 'Wide flat aperture to use.' ) return super () . add_cmdline_args ( parser , cfg )","title":"WaitForFlatFieldFiberPos"},{"location":"scripts/WaitForFlatFieldFiberPos/#waitforflatfieldfiberpos","text":"Bases: KPFTranslatorFunction Wait for the flat field fiber aperture via the kpfcal.FF_FIBERPOS keyword. Parameters: FF_FiberPos ( str ) \u2013 The name of the flat field fiber position desired. Allowed Values: \"Blank\", \"6 mm f/5\", \"7.5 mm f/4\", \"10 mm f/3\", \"13.2 mm f/2.3\", \"Open\". wait ( bool ) \u2013 Wait for move to complete before returning? default: True","title":"WaitForFlatFieldFiberPos"},{"location":"scripts/WaitForFlatFieldFiberPos/#kpf.calbench.WaitForFlatFieldFiberPos.WaitForFlatFieldFiberPos--ktl-keywords-used","text":"kpfcal.FF_FIBERPOS Source code in kpf/calbench/WaitForFlatFieldFiberPos.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class WaitForFlatFieldFiberPos ( KPFTranslatorFunction ): '''Wait for the flat field fiber aperture via the `kpfcal.FF_FIBERPOS` keyword. Args: FF_FiberPos (str): The name of the flat field fiber position desired. Allowed Values: \"Blank\", \"6 mm f/5\", \"7.5 mm f/4\", \"10 mm f/3\", \"13.2 mm f/2.3\", \"Open\". wait (bool): Wait for move to complete before returning? default: True ## KTL Keywords Used - `kpfcal.FF_FIBERPOS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'FF_FiberPos' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) check_input ( args , 'FF_FiberPos' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): target = args . get ( 'FF_FiberPos' ) timeout = cfg . getfloat ( 'times' , 'nd_move_time' , fallback = 20 ) expr = f \"($kpfcal.FF_FiberPos == ' { target } ')\" success = ktl . waitFor ( expr , timeout = timeout ) if success is False : log . error ( f \"Timed out waiting for FF_FiberPos filter wheel\" ) @classmethod def post_condition ( cls , args , logger , cfg ): target = args . get ( 'FF_FiberPos' ) expr = f \"($kpfcal.FF_FiberPos == ' { target } ')\" success = ktl . waitFor ( expr , timeout = 0.1 ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'FF_FiberPos' , type = str , choices = [ \"Blank\" , \"6 mm f/5\" , \"7.5 mm f/4\" , \"10 mm f/3\" , \"13.2 mm f/2.3\" , \"Open\" ], help = 'Wide flat aperture to use.' ) return super () . add_cmdline_args ( parser , cfg )","title":"KTL Keywords Used"},{"location":"scripts/WaitForL0File/","text":"WaitForL0File Bases: KPFTranslatorFunction Wait a short time to see if kpfassemble writes a new L0 file. If it does, print a log line with that file name. KTL Keywords Used: kpfassemble.LOUTFILE Source code in kpf/spectrograph/WaitForL0File.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 class WaitForL0File ( KPFTranslatorFunction ): '''Wait a short time to see if `kpfassemble` writes a new L0 file. If it does, print a log line with that file name. KTL Keywords Used: - `kpfassemble.LOUTFILE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): LOUTFILE = ktl . cache ( 'kpfassemble' , 'LOUTFILE' ) initial_LOUTFILE = LOUTFILE . read () timeout = 10 found_new_file = LOUTFILE . waitFor ( f '!=\" { initial_LOUTFILE } \"' , timeout = timeout ) if found_new_file is True : log . info ( f 'kpfassemble wrote { LOUTFILE . read () } ' ) else : log . debug ( 'WaitForL0File did not find new file' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"WaitForL0File"},{"location":"scripts/WaitForL0File/#waitforl0file","text":"Bases: KPFTranslatorFunction Wait a short time to see if kpfassemble writes a new L0 file. If it does, print a log line with that file name. KTL Keywords Used: kpfassemble.LOUTFILE Source code in kpf/spectrograph/WaitForL0File.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 class WaitForL0File ( KPFTranslatorFunction ): '''Wait a short time to see if `kpfassemble` writes a new L0 file. If it does, print a log line with that file name. KTL Keywords Used: - `kpfassemble.LOUTFILE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): LOUTFILE = ktl . cache ( 'kpfassemble' , 'LOUTFILE' ) initial_LOUTFILE = LOUTFILE . read () timeout = 10 found_new_file = LOUTFILE . waitFor ( f '!=\" { initial_LOUTFILE } \"' , timeout = timeout ) if found_new_file is True : log . info ( f 'kpfassemble wrote { LOUTFILE . read () } ' ) else : log . debug ( 'WaitForL0File did not find new file' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"WaitForL0File"},{"location":"scripts/WaitForLFCReady/","text":"WaitForLFCReady Bases: KPFTranslatorFunction Wait for the Laser Frequency Comb (LFC) to be ready and in \"AstroComb\" mode KTL Keywords Used: kpfmon.HB_MENLOSTA kpfmon.LFCREADYSTA kpfcal.WOBBLE kpfcal.OPERATIONMODE kpfcal.SPECFLAT Source code in kpf/calbench/WaitForLFCReady.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 class WaitForLFCReady ( KPFTranslatorFunction ): '''Wait for the Laser Frequency Comb (LFC) to be ready and in \"AstroComb\" mode KTL Keywords Used: - `kpfmon.HB_MENLOSTA` - `kpfmon.LFCREADYSTA` - `kpfcal.WOBBLE` - `kpfcal.OPERATIONMODE` - `kpfcal.SPECFLAT` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): expr = f \"($kpfmon.HB_MENLOSTA == 'OK')\" expr += f \"and ($kpfmon.LFCREADYSTA == 'OK')\" expr += f \"and ($kpfcal.WOBBLE == 'False')\" expr += f \"and ($kpfcal.OPERATIONMODE == 'AstroComb')\" expr += f \"and ($kpfcal.SPECFLAT == 'True')\" timeout = cfg . getfloat ( 'times' , 'LFC_startup_time' , fallback = 300 ) success = ktl . waitFor ( expr , timeout = timeout ) return success @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"WaitForLFCReady"},{"location":"scripts/WaitForLFCReady/#waitforlfcready","text":"Bases: KPFTranslatorFunction Wait for the Laser Frequency Comb (LFC) to be ready and in \"AstroComb\" mode KTL Keywords Used: kpfmon.HB_MENLOSTA kpfmon.LFCREADYSTA kpfcal.WOBBLE kpfcal.OPERATIONMODE kpfcal.SPECFLAT Source code in kpf/calbench/WaitForLFCReady.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 class WaitForLFCReady ( KPFTranslatorFunction ): '''Wait for the Laser Frequency Comb (LFC) to be ready and in \"AstroComb\" mode KTL Keywords Used: - `kpfmon.HB_MENLOSTA` - `kpfmon.LFCREADYSTA` - `kpfcal.WOBBLE` - `kpfcal.OPERATIONMODE` - `kpfcal.SPECFLAT` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): expr = f \"($kpfmon.HB_MENLOSTA == 'OK')\" expr += f \"and ($kpfmon.LFCREADYSTA == 'OK')\" expr += f \"and ($kpfcal.WOBBLE == 'False')\" expr += f \"and ($kpfcal.OPERATIONMODE == 'AstroComb')\" expr += f \"and ($kpfcal.SPECFLAT == 'True')\" timeout = cfg . getfloat ( 'times' , 'LFC_startup_time' , fallback = 300 ) success = ktl . waitFor ( expr , timeout = timeout ) return success @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"WaitForLFCReady"},{"location":"scripts/WaitForLampWarm/","text":"WaitForLampWarm Bases: KPFTranslatorFunction Wait for the specified lamp to be warm. Parameters: CalSource ( str ) \u2013 Which lamp to wait for. Allowed Values: BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, WideFlat KTL Keywords Used: kpflamps.FF_FIBER_STATUS kpflamps.FF_FIBER_TIMEON kpflamps.FF_FIBER_THRESHOLD kpflamps.BRDBANDFIBER_STATUS kpflamps.BRDBANDFIBER_TIMEON kpflamps.BRDBANDFIBER_THRESHOLD kpflamps.TH_DAILY_STATUS kpflamps.TH_DAILY_TIMEON kpflamps.TH_DAILY_THRESHOLD kpflamps.TH_GOLD_STATUS kpflamps.TH_GOLD_TIMEON kpflamps.TH_GOLD_THRESHOLD kpflamps.U_DAILY_STATUS kpflamps.U_DAILY_TIMEON kpflamps.U_DAILY_THRESHOLD kpflamps.U_GOLD_STATUS kpflamps.U_GOLD_TIMEON kpflamps.U_GOLD_THRESHOLD Scripts Called: kpf.calbench.CalLampPower Source code in kpf/calbench/WaitForLampWarm.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class WaitForLampWarm ( KPFTranslatorFunction ): '''Wait for the specified lamp to be warm. Args: CalSource (str): Which lamp to wait for. Allowed Values: BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, WideFlat KTL Keywords Used: - `kpflamps.FF_FIBER_STATUS` - `kpflamps.FF_FIBER_TIMEON` - `kpflamps.FF_FIBER_THRESHOLD` - `kpflamps.BRDBANDFIBER_STATUS` - `kpflamps.BRDBANDFIBER_TIMEON` - `kpflamps.BRDBANDFIBER_THRESHOLD` - `kpflamps.TH_DAILY_STATUS` - `kpflamps.TH_DAILY_TIMEON` - `kpflamps.TH_DAILY_THRESHOLD` - `kpflamps.TH_GOLD_STATUS` - `kpflamps.TH_GOLD_TIMEON` - `kpflamps.TH_GOLD_THRESHOLD` - `kpflamps.U_DAILY_STATUS` - `kpflamps.U_DAILY_TIMEON` - `kpflamps.U_DAILY_THRESHOLD` - `kpflamps.U_GOLD_STATUS` - `kpflamps.U_GOLD_TIMEON` - `kpflamps.U_GOLD_THRESHOLD` Scripts Called: - `kpf.calbench.CalLampPower` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'CalSource' ) @classmethod def perform ( cls , args , logger , cfg ): lamp = standardize_lamp_name ( args . get ( 'CalSource' )) lamps_that_need_warmup = [ 'FF_FIBER' , 'BRDBANDFIBER' , 'TH_DAILY' , 'TH_GOLD' , 'U_DAILY' , 'U_GOLD' ] if lamp in lamps_that_need_warmup : kpflamps = ktl . cache ( 'kpflamps' ) log . debug ( f 'Lamp { lamp } does need to be warmed up before use' ) # Check that lamp is actually on lamp = standardize_lamp_name ( args . get ( 'CalSource' )) lamp_statuskw = ktl . cache ( 'kpflamps' , f ' { lamp } _STATUS' ) lamp_status = lamp_statuskw . read () if lamp_status == 'Off' : log . warning ( f \"Lamp { lamp } is not on: { lamp_status } \" ) CalLampPower . execute ({ 'lamp' : args . get ( 'CalSource' ), 'power' : 'on' }) lamp_status = lamp_statuskw . read () if lamp_status == 'Off' : raise KPFException ( f \"Lamp { lamp } should be on: { lamp_status } \" ) elif lamp_status == 'Warm' : log . debug ( f \"Lamp { lamp } is warm\" ) elif lamp_status == 'Warming' : lamp_timeon = kpflamps [ f ' { lamp } _TIMEON' ] . read ( binary = True ) lamp_threshold = kpflamps [ f ' { lamp } _THRESHOLD' ] . read ( binary = True ) time_to_wait = lamp_threshold - lamp_timeon log . info ( f \"Lamp { lamp } is warming\" ) log . info ( f \"Estimated time remaining = { time_to_wait : .0f } s\" ) while lamp_statuskw . read () != 'Warm' : # Check if scriptstop has been activated check_scriptstop () log . debug ( f 'Waiting for { lamp } _STATUS == Warm' ) expr = f \"($kpflamps. { lamp } _STATUS == 'Warm')\" warm = ktl . waitFor ( expr , timeout = 30 ) if warm is False : new_lamp_timeton = kpflamps [ f ' { lamp } _TIMEON' ] . read ( binary = True ) if new_lamp_timeton <= lamp_timeon : break lamp_timeon = new_lamp_timeton @classmethod def post_condition ( cls , args , logger , cfg ): lamp = standardize_lamp_name ( args . get ( 'CalSource' )) lamps_that_need_warmup = [ 'FF_FIBER' , 'BRDBANDFIBER' , 'TH_DAILY' , 'TH_GOLD' , 'U_DAILY' , 'U_GOLD' ] if lamp in lamps_that_need_warmup : lamp_statuskw = ktl . cache ( 'kpflamps' , f ' { lamp } _STATUS' ) lamp_status = lamp_statuskw . read () if lamp_status != 'Warm' : raise FailedPostCondition ( f \"Lamp { lamp } should be warm: { lamp_status } \" ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'lamp' , type = str , choices = [ 'BrdbandFiber' , 'U_gold' , 'U_daily' , 'Th_daily' , 'Th_gold' , 'WideFlat' ], help = 'Which lamp are we waiting on?' ) return super () . add_cmdline_args ( parser , cfg )","title":"WaitForLampWarm"},{"location":"scripts/WaitForLampWarm/#waitforlampwarm","text":"Bases: KPFTranslatorFunction Wait for the specified lamp to be warm. Parameters: CalSource ( str ) \u2013 Which lamp to wait for. Allowed Values: BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, WideFlat KTL Keywords Used: kpflamps.FF_FIBER_STATUS kpflamps.FF_FIBER_TIMEON kpflamps.FF_FIBER_THRESHOLD kpflamps.BRDBANDFIBER_STATUS kpflamps.BRDBANDFIBER_TIMEON kpflamps.BRDBANDFIBER_THRESHOLD kpflamps.TH_DAILY_STATUS kpflamps.TH_DAILY_TIMEON kpflamps.TH_DAILY_THRESHOLD kpflamps.TH_GOLD_STATUS kpflamps.TH_GOLD_TIMEON kpflamps.TH_GOLD_THRESHOLD kpflamps.U_DAILY_STATUS kpflamps.U_DAILY_TIMEON kpflamps.U_DAILY_THRESHOLD kpflamps.U_GOLD_STATUS kpflamps.U_GOLD_TIMEON kpflamps.U_GOLD_THRESHOLD Scripts Called: kpf.calbench.CalLampPower Source code in kpf/calbench/WaitForLampWarm.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class WaitForLampWarm ( KPFTranslatorFunction ): '''Wait for the specified lamp to be warm. Args: CalSource (str): Which lamp to wait for. Allowed Values: BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, WideFlat KTL Keywords Used: - `kpflamps.FF_FIBER_STATUS` - `kpflamps.FF_FIBER_TIMEON` - `kpflamps.FF_FIBER_THRESHOLD` - `kpflamps.BRDBANDFIBER_STATUS` - `kpflamps.BRDBANDFIBER_TIMEON` - `kpflamps.BRDBANDFIBER_THRESHOLD` - `kpflamps.TH_DAILY_STATUS` - `kpflamps.TH_DAILY_TIMEON` - `kpflamps.TH_DAILY_THRESHOLD` - `kpflamps.TH_GOLD_STATUS` - `kpflamps.TH_GOLD_TIMEON` - `kpflamps.TH_GOLD_THRESHOLD` - `kpflamps.U_DAILY_STATUS` - `kpflamps.U_DAILY_TIMEON` - `kpflamps.U_DAILY_THRESHOLD` - `kpflamps.U_GOLD_STATUS` - `kpflamps.U_GOLD_TIMEON` - `kpflamps.U_GOLD_THRESHOLD` Scripts Called: - `kpf.calbench.CalLampPower` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'CalSource' ) @classmethod def perform ( cls , args , logger , cfg ): lamp = standardize_lamp_name ( args . get ( 'CalSource' )) lamps_that_need_warmup = [ 'FF_FIBER' , 'BRDBANDFIBER' , 'TH_DAILY' , 'TH_GOLD' , 'U_DAILY' , 'U_GOLD' ] if lamp in lamps_that_need_warmup : kpflamps = ktl . cache ( 'kpflamps' ) log . debug ( f 'Lamp { lamp } does need to be warmed up before use' ) # Check that lamp is actually on lamp = standardize_lamp_name ( args . get ( 'CalSource' )) lamp_statuskw = ktl . cache ( 'kpflamps' , f ' { lamp } _STATUS' ) lamp_status = lamp_statuskw . read () if lamp_status == 'Off' : log . warning ( f \"Lamp { lamp } is not on: { lamp_status } \" ) CalLampPower . execute ({ 'lamp' : args . get ( 'CalSource' ), 'power' : 'on' }) lamp_status = lamp_statuskw . read () if lamp_status == 'Off' : raise KPFException ( f \"Lamp { lamp } should be on: { lamp_status } \" ) elif lamp_status == 'Warm' : log . debug ( f \"Lamp { lamp } is warm\" ) elif lamp_status == 'Warming' : lamp_timeon = kpflamps [ f ' { lamp } _TIMEON' ] . read ( binary = True ) lamp_threshold = kpflamps [ f ' { lamp } _THRESHOLD' ] . read ( binary = True ) time_to_wait = lamp_threshold - lamp_timeon log . info ( f \"Lamp { lamp } is warming\" ) log . info ( f \"Estimated time remaining = { time_to_wait : .0f } s\" ) while lamp_statuskw . read () != 'Warm' : # Check if scriptstop has been activated check_scriptstop () log . debug ( f 'Waiting for { lamp } _STATUS == Warm' ) expr = f \"($kpflamps. { lamp } _STATUS == 'Warm')\" warm = ktl . waitFor ( expr , timeout = 30 ) if warm is False : new_lamp_timeton = kpflamps [ f ' { lamp } _TIMEON' ] . read ( binary = True ) if new_lamp_timeton <= lamp_timeon : break lamp_timeon = new_lamp_timeton @classmethod def post_condition ( cls , args , logger , cfg ): lamp = standardize_lamp_name ( args . get ( 'CalSource' )) lamps_that_need_warmup = [ 'FF_FIBER' , 'BRDBANDFIBER' , 'TH_DAILY' , 'TH_GOLD' , 'U_DAILY' , 'U_GOLD' ] if lamp in lamps_that_need_warmup : lamp_statuskw = ktl . cache ( 'kpflamps' , f ' { lamp } _STATUS' ) lamp_status = lamp_statuskw . read () if lamp_status != 'Warm' : raise FailedPostCondition ( f \"Lamp { lamp } should be warm: { lamp_status } \" ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'lamp' , type = str , choices = [ 'BrdbandFiber' , 'U_gold' , 'U_daily' , 'Th_daily' , 'Th_gold' , 'WideFlat' ], help = 'Which lamp are we waiting on?' ) return super () . add_cmdline_args ( parser , cfg )","title":"WaitForLampWarm"},{"location":"scripts/WaitForND/","text":"WaitForND Bases: KPFTranslatorFunction Wait for both ND filter wheels. Parameters: CalND1 ( str ) \u2013 The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: OD 0.1 , OD 1.0 , OD 1.3 , OD 2.0 , OD 3.0 , OD 4.0 CalND2 ( str ) \u2013 The neutral density filter to put in the first filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: OD 0.1 , OD 0.3 , OD 0.5 , OD 0.8 , OD 1.0 , OD 4.0 Scripts Called: kpf.calbench.WaitForND1 kpf.calbench.WaitForND2 Source code in kpf/calbench/WaitForND.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 class WaitForND ( KPFTranslatorFunction ): '''Wait for both ND filter wheels. Args: CalND1 (str): The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: `OD 0.1`, `OD 1.0`, `OD 1.3`, `OD 2.0`, `OD 3.0`, `OD 4.0` CalND2 (str): The neutral density filter to put in the first filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: `OD 0.1`, `OD 0.3`, `OD 0.5`, `OD 0.8`, `OD 1.0`, `OD 4.0` Scripts Called: - `kpf.calbench.WaitForND1` - `kpf.calbench.WaitForND2` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): WaitForND1 . execute ( args ) WaitForND2 . execute ( args ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalND1' , type = str , choices = [ \"OD 0.1\" , \"OD 1.0\" , \"OD 1.3\" , \"OD 2.0\" , \"OD 3.0\" , \"OD 4.0\" ], help = 'ND1 Filter to use.' ) parser . add_argument ( 'CalND2' , type = str , help = 'ND2 Filter to use.' ) return super () . add_cmdline_args ( parser , cfg )","title":"WaitForND"},{"location":"scripts/WaitForND/#waitfornd","text":"Bases: KPFTranslatorFunction Wait for both ND filter wheels. Parameters: CalND1 ( str ) \u2013 The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: OD 0.1 , OD 1.0 , OD 1.3 , OD 2.0 , OD 3.0 , OD 4.0 CalND2 ( str ) \u2013 The neutral density filter to put in the first filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: OD 0.1 , OD 0.3 , OD 0.5 , OD 0.8 , OD 1.0 , OD 4.0 Scripts Called: kpf.calbench.WaitForND1 kpf.calbench.WaitForND2 Source code in kpf/calbench/WaitForND.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 class WaitForND ( KPFTranslatorFunction ): '''Wait for both ND filter wheels. Args: CalND1 (str): The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: `OD 0.1`, `OD 1.0`, `OD 1.3`, `OD 2.0`, `OD 3.0`, `OD 4.0` CalND2 (str): The neutral density filter to put in the first filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: `OD 0.1`, `OD 0.3`, `OD 0.5`, `OD 0.8`, `OD 1.0`, `OD 4.0` Scripts Called: - `kpf.calbench.WaitForND1` - `kpf.calbench.WaitForND2` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): WaitForND1 . execute ( args ) WaitForND2 . execute ( args ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalND1' , type = str , choices = [ \"OD 0.1\" , \"OD 1.0\" , \"OD 1.3\" , \"OD 2.0\" , \"OD 3.0\" , \"OD 4.0\" ], help = 'ND1 Filter to use.' ) parser . add_argument ( 'CalND2' , type = str , help = 'ND2 Filter to use.' ) return super () . add_cmdline_args ( parser , cfg )","title":"WaitForND"},{"location":"scripts/WaitForND1/","text":"WaitForND1 Bases: KPFTranslatorFunction Wait for the ND1 filter wheel (the one at the output of the octagon) via the kpfcal.ND1POS keyword. Parameters: CalND1 ( str ) \u2013 The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: OD 0.1 , OD 1.0 , OD 1.3 , OD 2.0 , OD 3.0 , OD 4.0 KTL Keywords Used: kpfcal.ND1POS Source code in kpf/calbench/WaitForND1.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class WaitForND1 ( KPFTranslatorFunction ): '''Wait for the ND1 filter wheel (the one at the output of the octagon) via the `kpfcal.ND1POS` keyword. Args: CalND1 (str): The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: `OD 0.1`, `OD 1.0`, `OD 1.3`, `OD 2.0`, `OD 3.0`, `OD 4.0` KTL Keywords Used: - `kpfcal.ND1POS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'ND1POS' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) check_input ( args , 'CalND1' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): target = args . get ( 'CalND1' ) timeout = cfg . getfloat ( 'times' , 'nd_move_time' , fallback = 20 ) expr = f \"($kpfcal.ND1POS == ' { target } ')\" success = ktl . waitFor ( expr , timeout = timeout ) if success is False : log . error ( f \"Timed out waiting for ND1 filter wheel\" ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'nd_move_time' , fallback = 20 ) ND1target = args . get ( 'CalND1' ) ND1POS = ktl . cache ( 'kpfcal' , 'ND1POS' ) if ND1POS . waitFor ( f \"== ' { ND1target } '\" , timeout = timeout ) == False : raise FailedToReachDestination ( ND1POS . read (), ND1target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalND1' , type = str , choices = [ \"OD 0.1\" , \"OD 1.0\" , \"OD 1.3\" , \"OD 2.0\" , \"OD 3.0\" , \"OD 4.0\" ], help = 'ND1 Filter to use.' ) return super () . add_cmdline_args ( parser , cfg )","title":"WaitForND1"},{"location":"scripts/WaitForND1/#waitfornd1","text":"Bases: KPFTranslatorFunction Wait for the ND1 filter wheel (the one at the output of the octagon) via the kpfcal.ND1POS keyword. Parameters: CalND1 ( str ) \u2013 The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: OD 0.1 , OD 1.0 , OD 1.3 , OD 2.0 , OD 3.0 , OD 4.0 KTL Keywords Used: kpfcal.ND1POS Source code in kpf/calbench/WaitForND1.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class WaitForND1 ( KPFTranslatorFunction ): '''Wait for the ND1 filter wheel (the one at the output of the octagon) via the `kpfcal.ND1POS` keyword. Args: CalND1 (str): The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: `OD 0.1`, `OD 1.0`, `OD 1.3`, `OD 2.0`, `OD 3.0`, `OD 4.0` KTL Keywords Used: - `kpfcal.ND1POS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'ND1POS' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) check_input ( args , 'CalND1' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): target = args . get ( 'CalND1' ) timeout = cfg . getfloat ( 'times' , 'nd_move_time' , fallback = 20 ) expr = f \"($kpfcal.ND1POS == ' { target } ')\" success = ktl . waitFor ( expr , timeout = timeout ) if success is False : log . error ( f \"Timed out waiting for ND1 filter wheel\" ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'nd_move_time' , fallback = 20 ) ND1target = args . get ( 'CalND1' ) ND1POS = ktl . cache ( 'kpfcal' , 'ND1POS' ) if ND1POS . waitFor ( f \"== ' { ND1target } '\" , timeout = timeout ) == False : raise FailedToReachDestination ( ND1POS . read (), ND1target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalND1' , type = str , choices = [ \"OD 0.1\" , \"OD 1.0\" , \"OD 1.3\" , \"OD 2.0\" , \"OD 3.0\" , \"OD 4.0\" ], help = 'ND1 Filter to use.' ) return super () . add_cmdline_args ( parser , cfg )","title":"WaitForND1"},{"location":"scripts/WaitForND2/","text":"WaitForND2 Bases: KPFTranslatorFunction Description Set the filter in the ND2 filter wheel (the one at the output of the octagon) via the kpfcal.ND2POS keyword. Parameters: CalND2 ( str ) \u2013 The neutral density filter to put in the first filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: OD 0.1 , OD 0.3 , OD 0.5 , OD 0.8 , OD 1.0 , OD 4.0 KTL Keywords Used: kpfcal.ND2POS Source code in kpf/calbench/WaitForND2.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class WaitForND2 ( KPFTranslatorFunction ): '''# Description Set the filter in the ND2 filter wheel (the one at the output of the octagon) via the `kpfcal.ND2POS` keyword. Args: CalND2 (str): The neutral density filter to put in the first filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: `OD 0.1`, `OD 0.3`, `OD 0.5`, `OD 0.8`, `OD 1.0`, `OD 4.0` KTL Keywords Used: - `kpfcal.ND2POS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'ND2POS' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) check_input ( args , 'CalND2' , allowed_values = allowed_values ) return True @classmethod def perform ( cls , args , logger , cfg ): target = args . get ( 'CalND2' ) timeout = cfg . getfloat ( 'times' , 'nd_move_time' , fallback = 20 ) expr = f \"($kpfcal.ND2POS == ' { target } ')\" success = ktl . waitFor ( expr , timeout = timeout ) if success is False : log . error ( f \"Timed out waiting for ND2 filter wheel\" ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'nd_move_time' , fallback = 20 ) ND2target = args . get ( 'CalND2' ) ND2POS = ktl . cache ( 'kpfcal' , 'ND2POS' ) if ND2POS . waitFor ( f \"== ' { ND2target } '\" , timeout = timeout ) == False : raise FailedToReachDestination ( ND2POS . read (), ND2target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalND2' , type = str , choices = [ \"OD 0.1\" , \"OD 0.3\" , \"OD 0.5\" , \"OD 0.8\" , \"OD 1.0\" , \"OD 4.0\" ], help = 'ND2 Filter to use.' ) return super () . add_cmdline_args ( parser , cfg )","title":"WaitForND2"},{"location":"scripts/WaitForND2/#waitfornd2","text":"Bases: KPFTranslatorFunction","title":"WaitForND2"},{"location":"scripts/WaitForND2/#kpf.calbench.WaitForND2.WaitForND2--description","text":"Set the filter in the ND2 filter wheel (the one at the output of the octagon) via the kpfcal.ND2POS keyword. Parameters: CalND2 ( str ) \u2013 The neutral density filter to put in the first filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: OD 0.1 , OD 0.3 , OD 0.5 , OD 0.8 , OD 1.0 , OD 4.0 KTL Keywords Used: kpfcal.ND2POS Source code in kpf/calbench/WaitForND2.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class WaitForND2 ( KPFTranslatorFunction ): '''# Description Set the filter in the ND2 filter wheel (the one at the output of the octagon) via the `kpfcal.ND2POS` keyword. Args: CalND2 (str): The neutral density filter to put in the first filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: `OD 0.1`, `OD 0.3`, `OD 0.5`, `OD 0.8`, `OD 1.0`, `OD 4.0` KTL Keywords Used: - `kpfcal.ND2POS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'ND2POS' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) check_input ( args , 'CalND2' , allowed_values = allowed_values ) return True @classmethod def perform ( cls , args , logger , cfg ): target = args . get ( 'CalND2' ) timeout = cfg . getfloat ( 'times' , 'nd_move_time' , fallback = 20 ) expr = f \"($kpfcal.ND2POS == ' { target } ')\" success = ktl . waitFor ( expr , timeout = timeout ) if success is False : log . error ( f \"Timed out waiting for ND2 filter wheel\" ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'nd_move_time' , fallback = 20 ) ND2target = args . get ( 'CalND2' ) ND2POS = ktl . cache ( 'kpfcal' , 'ND2POS' ) if ND2POS . waitFor ( f \"== ' { ND2target } '\" , timeout = timeout ) == False : raise FailedToReachDestination ( ND2POS . read (), ND2target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalND2' , type = str , choices = [ \"OD 0.1\" , \"OD 0.3\" , \"OD 0.5\" , \"OD 0.8\" , \"OD 1.0\" , \"OD 4.0\" ], help = 'ND2 Filter to use.' ) return super () . add_cmdline_args ( parser , cfg )","title":"Description"},{"location":"scripts/WaitForReadout/","text":"WaitForReadout Bases: KPFTranslatorFunction Waits for the kpfexpose.EXPOSE keyword to be \"Readout\". This will block until the camera enters the readout state. ARGS: None Source code in kpf/spectrograph/WaitForReadout.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class WaitForReadout ( KPFTranslatorFunction ): '''Waits for the `kpfexpose.EXPOSE` keyword to be \"Readout\". This will block until the camera enters the readout state. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) exptime = kpfexpose [ 'EXPOSURE' ] . read ( binary = True ) starting_status = kpfexpose [ 'EXPOSE' ] . read ( binary = True ) detectors = kpfexpose [ 'TRIG_TARG' ] . read () detector_list = detectors . split ( ',' ) buffer_time = cfg . getfloat ( 'times' , 'readout_buffer_time' , fallback = 10 ) wait_time = exptime + buffer_time if starting_status < 3 else buffer_time wait_logic_steps = [ '($kpfexpose.EXPOSE == 4)' ] if 'Green' in detector_list : wait_logic_steps . append ( \"($kpfgreen.EXPSTATE == 4)\" ) if 'Red' in detector_list : wait_logic_steps . append ( \"($kpfred.EXPSTATE == 4)\" ) if 'Ca_HK' in detector_list : wait_logic_steps . append ( \"($kpf_hk.EXPSTATE == 4)\" ) wait_logic = ' and ' . join ( wait_logic_steps ) log . debug ( f \"Waiting ( { wait_time : .0f } s max) for readout to begin\" ) success = ktl . waitFor ( wait_logic , timeout = wait_time ) if success is True : log . debug ( f 'kpfexpose is { kpfexpose [ \"EXPOSE\" ] . read () } ' ) if 'Green' in detector_list : nextfile = ktl . cache ( 'kpfgreen' , 'NEXTFILE' ) log . debug ( f \"Green nextfile: { nextfile . read () } \" ) if 'Red' in detector_list : nextfile = ktl . cache ( 'kpfred' , 'NEXTFILE' ) log . debug ( f \"Red nextfile: { nextfile . read () } \" ) else : log . warning ( 'WaitForReadout failed to reach expected state' ) log . debug ( f 'kpfexpose is { kpfexpose [ \"EXPOSE\" ] . read () } ' ) log . debug ( f 'kpfexpose EXPLAINR = { kpfexpose [ \"EXPLAINR\" ] . read () } ' ) log . debug ( f 'kpfexpose EXPLAINNR = { kpfexpose [ \"EXPLAINNR\" ] . read () } ' ) RecoverDetectors . execute ({}) @classmethod def post_condition ( cls , args , logger , cfg ): expr = \"($kpfexpose.EXPOSE == 'Ready') or ($kpfexpose.EXPOSE == 'Readout')\" timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) ok = ktl . waitFor ( expr , timeout = timeout ) if ok is not True : expose = ktl . cache ( 'kpfexpose' , 'EXPOSE' ) raise FailedPostCondition ( f \"kpfexpose.EXPOSE= { expose . read () } is not Ready or Readout\" )","title":"WaitForReadout"},{"location":"scripts/WaitForReadout/#waitforreadout","text":"Bases: KPFTranslatorFunction Waits for the kpfexpose.EXPOSE keyword to be \"Readout\". This will block until the camera enters the readout state.","title":"WaitForReadout"},{"location":"scripts/WaitForReadout/#kpf.spectrograph.WaitForReadout.WaitForReadout--args","text":"None Source code in kpf/spectrograph/WaitForReadout.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class WaitForReadout ( KPFTranslatorFunction ): '''Waits for the `kpfexpose.EXPOSE` keyword to be \"Readout\". This will block until the camera enters the readout state. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) exptime = kpfexpose [ 'EXPOSURE' ] . read ( binary = True ) starting_status = kpfexpose [ 'EXPOSE' ] . read ( binary = True ) detectors = kpfexpose [ 'TRIG_TARG' ] . read () detector_list = detectors . split ( ',' ) buffer_time = cfg . getfloat ( 'times' , 'readout_buffer_time' , fallback = 10 ) wait_time = exptime + buffer_time if starting_status < 3 else buffer_time wait_logic_steps = [ '($kpfexpose.EXPOSE == 4)' ] if 'Green' in detector_list : wait_logic_steps . append ( \"($kpfgreen.EXPSTATE == 4)\" ) if 'Red' in detector_list : wait_logic_steps . append ( \"($kpfred.EXPSTATE == 4)\" ) if 'Ca_HK' in detector_list : wait_logic_steps . append ( \"($kpf_hk.EXPSTATE == 4)\" ) wait_logic = ' and ' . join ( wait_logic_steps ) log . debug ( f \"Waiting ( { wait_time : .0f } s max) for readout to begin\" ) success = ktl . waitFor ( wait_logic , timeout = wait_time ) if success is True : log . debug ( f 'kpfexpose is { kpfexpose [ \"EXPOSE\" ] . read () } ' ) if 'Green' in detector_list : nextfile = ktl . cache ( 'kpfgreen' , 'NEXTFILE' ) log . debug ( f \"Green nextfile: { nextfile . read () } \" ) if 'Red' in detector_list : nextfile = ktl . cache ( 'kpfred' , 'NEXTFILE' ) log . debug ( f \"Red nextfile: { nextfile . read () } \" ) else : log . warning ( 'WaitForReadout failed to reach expected state' ) log . debug ( f 'kpfexpose is { kpfexpose [ \"EXPOSE\" ] . read () } ' ) log . debug ( f 'kpfexpose EXPLAINR = { kpfexpose [ \"EXPLAINR\" ] . read () } ' ) log . debug ( f 'kpfexpose EXPLAINNR = { kpfexpose [ \"EXPLAINNR\" ] . read () } ' ) RecoverDetectors . execute ({}) @classmethod def post_condition ( cls , args , logger , cfg ): expr = \"($kpfexpose.EXPOSE == 'Ready') or ($kpfexpose.EXPOSE == 'Readout')\" timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) ok = ktl . waitFor ( expr , timeout = timeout ) if ok is not True : expose = ktl . cache ( 'kpfexpose' , 'EXPOSE' ) raise FailedPostCondition ( f \"kpfexpose.EXPOSE= { expose . read () } is not Ready or Readout\" )","title":"ARGS:"},{"location":"scripts/WaitForReady/","text":"WaitForReady Bases: KPFTranslatorFunction Waits for the kpfexpose.EXPOSE keyword to be \"Ready\". This will block until the camera is ready for another exposure. Times out after waiting for exposure time plus a set buffer time. ARGS: None Source code in kpf/spectrograph/WaitForReady.py 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class WaitForReady ( KPFTranslatorFunction ): '''Waits for the `kpfexpose.EXPOSE` keyword to be \"Ready\". This will block until the camera is ready for another exposure. Times out after waiting for exposure time plus a set buffer time. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) exptime = kpfexpose [ 'EXPOSURE' ] . read ( binary = True ) starting_status = kpfexpose [ 'EXPOSE' ] . read ( binary = True ) detectors = kpfexpose [ 'TRIG_TARG' ] . read () detector_list = detectors . split ( ',' ) buffer_time = cfg . getfloat ( 'times' , 'readout_buffer_time' , fallback = 10 ) read_times = [ cfg . getfloat ( 'time_estimates' , 'readout_red' , fallback = 60 ), cfg . getfloat ( 'time_estimates' , 'readout_green' , fallback = 60 ), cfg . getfloat ( 'time_estimates' , 'readout_cahk' , fallback = 1 ), cfg . getfloat ( 'time_estimates' , 'readout_expmeter' , fallback = 1 ), ] slowest_read = max ( read_times ) wait_time = exptime + slowest_read + buffer_time if starting_status < 3 else slowest_read + buffer_time wait_logic_steps = [ '($kpfexpose.EXPOSE == 0)' ] if 'Green' in detector_list : wait_logic_steps . append ( \"($kpfgreen.EXPSTATE == 0)\" ) if 'Red' in detector_list : wait_logic_steps . append ( \"($kpfred.EXPSTATE == 0)\" ) if 'Ca_HK' in detector_list : wait_logic_steps . append ( \"($kpf_hk.EXPSTATE == 0)\" ) wait_logic = ' and ' . join ( wait_logic_steps ) log . debug ( f \"Waiting ( { wait_time : .0f } s max) for detectors to be ready\" ) success = ktl . waitFor ( wait_logic , timeout = wait_time ) if success is True : log . debug ( f 'kpfexpose is { kpfexpose [ \"EXPOSE\" ] . read () } ' ) else : log . warning ( 'WaitForReady failed to reach expected state' ) log . debug ( f 'kpfexpose is { kpfexpose [ \"EXPOSE\" ] . read () } ' ) log . debug ( f 'kpfexpose EXPLAINR = { kpfexpose [ \"EXPLAINR\" ] . read () } ' ) log . debug ( f 'kpfexpose EXPLAINNR = { kpfexpose [ \"EXPLAINNR\" ] . read () } ' ) if kpfexpose [ 'EXPOSE' ] . read () == 'Readout' : # Readout errors are handled in kpfred and kpfgreen services. # Just wait some extra time for that to recover the system. success = ktl . waitFor ( wait_logic , timeout = wait_time ) else : RecoverDetectors . execute ({}) @classmethod def post_condition ( cls , args , logger , cfg ): expr = \"($kpfexpose.EXPOSE == 'Ready')\" timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) ok = ktl . waitFor ( expr , timeout = timeout ) if ok is not True : expose = ktl . cache ( 'kpfexpose' , 'EXPOSE' ) raise FailedPostCondition ( f \"kpfexpose.EXPOSE= { expose . read () } is not Ready\" )","title":"WaitForReady"},{"location":"scripts/WaitForReady/#waitforready","text":"Bases: KPFTranslatorFunction Waits for the kpfexpose.EXPOSE keyword to be \"Ready\". This will block until the camera is ready for another exposure. Times out after waiting for exposure time plus a set buffer time.","title":"WaitForReady"},{"location":"scripts/WaitForReady/#kpf.spectrograph.WaitForReady.WaitForReady--args","text":"None Source code in kpf/spectrograph/WaitForReady.py 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class WaitForReady ( KPFTranslatorFunction ): '''Waits for the `kpfexpose.EXPOSE` keyword to be \"Ready\". This will block until the camera is ready for another exposure. Times out after waiting for exposure time plus a set buffer time. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) exptime = kpfexpose [ 'EXPOSURE' ] . read ( binary = True ) starting_status = kpfexpose [ 'EXPOSE' ] . read ( binary = True ) detectors = kpfexpose [ 'TRIG_TARG' ] . read () detector_list = detectors . split ( ',' ) buffer_time = cfg . getfloat ( 'times' , 'readout_buffer_time' , fallback = 10 ) read_times = [ cfg . getfloat ( 'time_estimates' , 'readout_red' , fallback = 60 ), cfg . getfloat ( 'time_estimates' , 'readout_green' , fallback = 60 ), cfg . getfloat ( 'time_estimates' , 'readout_cahk' , fallback = 1 ), cfg . getfloat ( 'time_estimates' , 'readout_expmeter' , fallback = 1 ), ] slowest_read = max ( read_times ) wait_time = exptime + slowest_read + buffer_time if starting_status < 3 else slowest_read + buffer_time wait_logic_steps = [ '($kpfexpose.EXPOSE == 0)' ] if 'Green' in detector_list : wait_logic_steps . append ( \"($kpfgreen.EXPSTATE == 0)\" ) if 'Red' in detector_list : wait_logic_steps . append ( \"($kpfred.EXPSTATE == 0)\" ) if 'Ca_HK' in detector_list : wait_logic_steps . append ( \"($kpf_hk.EXPSTATE == 0)\" ) wait_logic = ' and ' . join ( wait_logic_steps ) log . debug ( f \"Waiting ( { wait_time : .0f } s max) for detectors to be ready\" ) success = ktl . waitFor ( wait_logic , timeout = wait_time ) if success is True : log . debug ( f 'kpfexpose is { kpfexpose [ \"EXPOSE\" ] . read () } ' ) else : log . warning ( 'WaitForReady failed to reach expected state' ) log . debug ( f 'kpfexpose is { kpfexpose [ \"EXPOSE\" ] . read () } ' ) log . debug ( f 'kpfexpose EXPLAINR = { kpfexpose [ \"EXPLAINR\" ] . read () } ' ) log . debug ( f 'kpfexpose EXPLAINNR = { kpfexpose [ \"EXPLAINNR\" ] . read () } ' ) if kpfexpose [ 'EXPOSE' ] . read () == 'Readout' : # Readout errors are handled in kpfred and kpfgreen services. # Just wait some extra time for that to recover the system. success = ktl . waitFor ( wait_logic , timeout = wait_time ) else : RecoverDetectors . execute ({}) @classmethod def post_condition ( cls , args , logger , cfg ): expr = \"($kpfexpose.EXPOSE == 'Ready')\" timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) ok = ktl . waitFor ( expr , timeout = timeout ) if ok is not True : expose = ktl . cache ( 'kpfexpose' , 'EXPOSE' ) raise FailedPostCondition ( f \"kpfexpose.EXPOSE= { expose . read () } is not Ready\" )","title":"ARGS:"},{"location":"scripts/WaitForSoCalOnTarget/","text":"WaitForSoCalOnTarget Bases: KPFTranslatorFunction Returns True if, within a set timeout, a set of conditions which suggest that SoCal is on the Sun accurately evaluate to True. ARGS: None Source code in kpf/socal/WaitForSoCalOnTarget.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class WaitForSoCalOnTarget ( KPFTranslatorFunction ): '''Returns True if, within a set timeout, a set of conditions which suggest that SoCal is on the Sun accurately evaluate to True. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'SoCal' , 'enclosure_status_time' , fallback = 10 ) pyrirrad_threshold = cfg . getfloat ( 'SoCal' , 'pyrirrad_threshold' , fallback = 1000 ) expr = '($kpfsocal.ENCSTA == 0) ' expr += 'and ($kpfsocal.EKOONLINE == Online)' expr += 'and ($kpfsocal.EKOMODE == 3)' expr += f 'and ($kpfsocal.PYRIRRAD > { pyrirrad_threshold } )' expr += 'and ($kpfsocal.AUTONOMOUS == 1)' expr += 'and ($kpfsocal.CAN_OPEN == True)' expr += 'and ($kpfsocal.IS_OPEN == True)' expr += 'and ($kpfsocal.IS_TRACKING == True)' expr += 'and ($kpfsocal.ONLINE == True)' expr += 'and ($kpfsocal.STATE == Tracking)' on_target = ktl . waitFor ( expr , timeout = timeout ) msg = { True : 'On Target' , False : 'NOT On Target' }[ on_target ] print ( msg ) if on_target == False : kpfsocal = ktl . cache ( 'kpfsocal' ) if kpfsocal [ 'ENCSTA' ] . read ( binary = True ) != 0 : log . debug ( f 'ENCSTA != 0' ) if kpfsocal [ 'EKOONLINE' ] . read () != 'Online' : log . debug ( f 'EKOONLINE != Online' ) if kpfsocal [ 'EKOMODE' ] . read ( binary = True ) != 3 : log . debug ( f 'EKOMODE != 3' ) if kpfsocal [ 'PYRIRRAD' ] . read ( binary = True ) < pyrirrad_threshold : log . debug ( f 'PYRIRRAD < { pyrirrad_threshold } ' ) if kpfsocal [ 'AUTONOMOUS' ] . read ( binary = True ) != 1 : log . debug ( f 'AUTONOMOUS != 1' ) if kpfsocal [ 'IS_OPEN' ] . read ( binary = True ) != True : log . debug ( f 'IS_OPEN != True' ) if kpfsocal [ 'IS_TRACKING' ] . read ( binary = True ) != True : log . debug ( f 'IS_TRACKING != True' ) if kpfsocal [ 'ONLINE' ] . read ( binary = True ) != True : log . debug ( f 'ONLINE != True' ) if kpfsocal [ 'STATE' ] . read () != 'Tracking' : log . debug ( f 'STATE != Tracking' ) return on_target @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"WaitForSoCalOnTarget"},{"location":"scripts/WaitForSoCalOnTarget/#waitforsocalontarget","text":"Bases: KPFTranslatorFunction Returns True if, within a set timeout, a set of conditions which suggest that SoCal is on the Sun accurately evaluate to True.","title":"WaitForSoCalOnTarget"},{"location":"scripts/WaitForSoCalOnTarget/#kpf.socal.WaitForSoCalOnTarget.WaitForSoCalOnTarget--args","text":"None Source code in kpf/socal/WaitForSoCalOnTarget.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class WaitForSoCalOnTarget ( KPFTranslatorFunction ): '''Returns True if, within a set timeout, a set of conditions which suggest that SoCal is on the Sun accurately evaluate to True. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'SoCal' , 'enclosure_status_time' , fallback = 10 ) pyrirrad_threshold = cfg . getfloat ( 'SoCal' , 'pyrirrad_threshold' , fallback = 1000 ) expr = '($kpfsocal.ENCSTA == 0) ' expr += 'and ($kpfsocal.EKOONLINE == Online)' expr += 'and ($kpfsocal.EKOMODE == 3)' expr += f 'and ($kpfsocal.PYRIRRAD > { pyrirrad_threshold } )' expr += 'and ($kpfsocal.AUTONOMOUS == 1)' expr += 'and ($kpfsocal.CAN_OPEN == True)' expr += 'and ($kpfsocal.IS_OPEN == True)' expr += 'and ($kpfsocal.IS_TRACKING == True)' expr += 'and ($kpfsocal.ONLINE == True)' expr += 'and ($kpfsocal.STATE == Tracking)' on_target = ktl . waitFor ( expr , timeout = timeout ) msg = { True : 'On Target' , False : 'NOT On Target' }[ on_target ] print ( msg ) if on_target == False : kpfsocal = ktl . cache ( 'kpfsocal' ) if kpfsocal [ 'ENCSTA' ] . read ( binary = True ) != 0 : log . debug ( f 'ENCSTA != 0' ) if kpfsocal [ 'EKOONLINE' ] . read () != 'Online' : log . debug ( f 'EKOONLINE != Online' ) if kpfsocal [ 'EKOMODE' ] . read ( binary = True ) != 3 : log . debug ( f 'EKOMODE != 3' ) if kpfsocal [ 'PYRIRRAD' ] . read ( binary = True ) < pyrirrad_threshold : log . debug ( f 'PYRIRRAD < { pyrirrad_threshold } ' ) if kpfsocal [ 'AUTONOMOUS' ] . read ( binary = True ) != 1 : log . debug ( f 'AUTONOMOUS != 1' ) if kpfsocal [ 'IS_OPEN' ] . read ( binary = True ) != True : log . debug ( f 'IS_OPEN != True' ) if kpfsocal [ 'IS_TRACKING' ] . read ( binary = True ) != True : log . debug ( f 'IS_TRACKING != True' ) if kpfsocal [ 'ONLINE' ] . read ( binary = True ) != True : log . debug ( f 'ONLINE != True' ) if kpfsocal [ 'STATE' ] . read () != 'Tracking' : log . debug ( f 'STATE != Tracking' ) return on_target @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"ARGS:"},{"location":"scripts/WaitForTipTilt/","text":"WaitForTipTilt Bases: KPFTranslatorFunction Dumb versions which simply waits for a few seconds. Source code in kpf/fiu/WaitForTipTilt.py 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class WaitForTipTilt ( KPFTranslatorFunction ): '''Dumb versions which simply waits for a few seconds. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): loop_close_time = cfg . getfloat ( 'times' , 'tip_tilt_close_time' , fallback = 3 ) time . sleep ( loop_close_time ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"WaitForTipTilt"},{"location":"scripts/WaitForTipTilt/#waitfortiptilt","text":"Bases: KPFTranslatorFunction Dumb versions which simply waits for a few seconds. Source code in kpf/fiu/WaitForTipTilt.py 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class WaitForTipTilt ( KPFTranslatorFunction ): '''Dumb versions which simply waits for a few seconds. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): loop_close_time = cfg . getfloat ( 'times' , 'tip_tilt_close_time' , fallback = 3 ) time . sleep ( loop_close_time ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"WaitForTipTilt"},{"location":"scripts/WaitForTriggerFile/","text":"WaitForTriggerFile Bases: KPFTranslatorFunction Wait for a trigger file in progress to finish being collected. KTL Keywords Used: kpfguide.LASTTRIGFILE Source code in kpf/guider/WaitForTriggerFile.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 class WaitForTriggerFile ( KPFTranslatorFunction ): '''Wait for a trigger file in progress to finish being collected. KTL Keywords Used: - `kpfguide.LASTTRIGFILE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'initial_lastfile' ) @classmethod def perform ( cls , args , logger , cfg ): initial_lastfile = args . get ( 'initial_lastfile' , False ) kpfguide = ktl . cache ( 'kpfguide' ) log . debug ( f \"Waiting for guider trigger file to be written out\" ) # Wait for cube file to be updated expr = f \"$kpfguide.LASTTRIGFILE != ' { initial_lastfile } '\" success = ktl . waitFor ( expr , timeout = 20 ) cube_file = kpfguide [ 'LASTTRIGFILE' ] . read () log . info ( f \"New cube file: { cube_file } \" ) return cube_file @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"WaitForTriggerFile"},{"location":"scripts/WaitForTriggerFile/#waitfortriggerfile","text":"Bases: KPFTranslatorFunction Wait for a trigger file in progress to finish being collected. KTL Keywords Used: kpfguide.LASTTRIGFILE Source code in kpf/guider/WaitForTriggerFile.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 class WaitForTriggerFile ( KPFTranslatorFunction ): '''Wait for a trigger file in progress to finish being collected. KTL Keywords Used: - `kpfguide.LASTTRIGFILE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'initial_lastfile' ) @classmethod def perform ( cls , args , logger , cfg ): initial_lastfile = args . get ( 'initial_lastfile' , False ) kpfguide = ktl . cache ( 'kpfguide' ) log . debug ( f \"Waiting for guider trigger file to be written out\" ) # Wait for cube file to be updated expr = f \"$kpfguide.LASTTRIGFILE != ' { initial_lastfile } '\" success = ktl . waitFor ( expr , timeout = 20 ) cube_file = kpfguide [ 'LASTTRIGFILE' ] . read () log . info ( f \"New cube file: { cube_file } \" ) return cube_file @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"WaitForTriggerFile"},{"location":"scripts/ZeroOutSlewCalTime/","text":"ZeroOutSlewCalTime Bases: KPFTranslatorFunction Zero out the slew cal timer by setting it to the current timestamp. ARGS None Source code in kpf/utils/ZeroOutSlewCalTime.py 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class ZeroOutSlewCalTime ( KPFTranslatorFunction ): '''Zero out the slew cal timer by setting it to the current timestamp. ### ARGS None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): log . debug ( 'Updating LASTSLEWCAL time stamp to reset slew cal timer' ) ktl . write ( 'kpfconfig' , 'LASTSLEWCAL' , time . time (), binary = True ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"ZeroOutSlewCalTime"},{"location":"scripts/ZeroOutSlewCalTime/#zerooutslewcaltime","text":"Bases: KPFTranslatorFunction Zero out the slew cal timer by setting it to the current timestamp.","title":"ZeroOutSlewCalTime"},{"location":"scripts/ZeroOutSlewCalTime/#kpf.utils.ZeroOutSlewCalTime.ZeroOutSlewCalTime--args","text":"None Source code in kpf/utils/ZeroOutSlewCalTime.py 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class ZeroOutSlewCalTime ( KPFTranslatorFunction ): '''Zero out the slew cal timer by setting it to the current timestamp. ### ARGS None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): log . debug ( 'Updating LASTSLEWCAL time stamp to reset slew cal timer' ) ktl . write ( 'kpfconfig' , 'LASTSLEWCAL' , time . time (), binary = True ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"ARGS"},{"location":"scripts/scripts/","text":"Scripts kpf.ao ControlAOHatch SendPCUtoHome SendPCUtoKPF SetAFMtoMirror SetAFStoNGS SetAODCStoSIM SetAORotator SetAORotatorManual SetupAOforACAM SetupAOforKPF TurnHepaOff TurnHepaOn TurnLightSourceOff kpf.cahk PowerCycleCaHK kpf.calbench CalLampPower IsCalSourceEnabled PredictNDFilters SetCalSource SetFlatFieldFiberPos SetLFCtoAstroComb SetLFCtoStandbyHigh SetND SetND1 SetND2 TakeIntensityReading WaitForCalSource WaitForFlatFieldFiberPos WaitForLampWarm WaitForLFCReady WaitForND WaitForND1 WaitForND2 kpf.engineering GridSearch ImageBackIlluminatedFibers Run2DGridSearch TakeADCGridData TakeADCOffsetGridData TakeGuiderSensitivityData TriggerGreenMiniFill TriggerRedMiniFill AnalyzeGridSearch AnalyzeTipTiltPerformance Fit2DGridSearch CountCameraErrors kpf.expmeter BuildMasterBias SetExpMeterExpTime SetExpMeterTerminationParameters PredictExpMeterParameters SetMasterBiasToDefault SetupExpMeter TakeExpMeterBiases kpf.fiu ConfigureFIU ControlFoldMirror ControlHatch InitializeTipTilt LockFIU UnlockFIU MeasureTipTiltMirrorRange SetADCAngles SetADCOffsets SetTipTiltCalculations SetTipTiltControl SetTipTiltGain SetTipTiltPosition SetTipTiltTargetPixel ShutdownTipTilt StartTipTilt StopTipTilt TestTipTiltMirrorRange VerifyCurrentBase WaitForConfigureFIU WaitForTipTilt kpf.fvc FVCPower PredictFVCParameters TakeFVCContinuous TakeFVCExposure SetFVCExpTime kpf.guider DisplayGuiderContinuous GetGaiaStars GuiderLastfile GuiderOutdir PredictGuiderParameters SetGuiderExpTime SetGuiderFPS SetGuiderGain SetGuiderOutdir StartGuiderContinuous StartTriggerFile StopGuiderContinuous StopTriggerFile TakeGuiderCube TakeGuiderExposure WaitForTriggerFile kpf.scripts CleanupAfterCalibrations CleanupAfterScience CollectGuiderDarkCubes ConfigureForAcquisition ConfigureForCalibrations ConfigureForScience EndOfNight EnterLowPowerMode ExecuteSlewCal RecoverFromLowPowerMode RunCalOB RunSciOB RunSoCalObservingLoop RunTwilightRVStandard StartOfNight StartUp WaitForConfigureCalibrations kpf.socal DisableSoCal EnableSoCal IsSoCalClosed IsSoCalOpen IsSoCalShutDown ParkSoCal SoCalStartAutonomous SoCalStopAutonomous WaitForSoCalOnTarget kpf.spectrograph QueryReadMode QueryFastReadMode RecoverDetectors ResetCaHKDetector ResetExpMeterDetector ResetGreenDetector ResetRedDetector ResetDetectors SetExpTime SetObject SetObserver SetProgram SetReadModeFast SetReadModeNormal SetSourceSelectShutters SetTimedShutters SetTriggeredDetectors StartAgitator StartExposure StopAgitator WaitForL0File WaitForReadout WaitForReady kpf.utils BuildOBfromQuery CalculateDAR CheckDewarWeights CorrectDAR EstimateOBDuration SetObserverFromSchedule SetOutdirs SetSimulCalSource SetTargetInfo StartGUIs StopGUIs ZeroOutSlewCalTime","title":"Operations Scripts"},{"location":"scripts/scripts/#scripts","text":"kpf.ao ControlAOHatch SendPCUtoHome SendPCUtoKPF SetAFMtoMirror SetAFStoNGS SetAODCStoSIM SetAORotator SetAORotatorManual SetupAOforACAM SetupAOforKPF TurnHepaOff TurnHepaOn TurnLightSourceOff kpf.cahk PowerCycleCaHK kpf.calbench CalLampPower IsCalSourceEnabled PredictNDFilters SetCalSource SetFlatFieldFiberPos SetLFCtoAstroComb SetLFCtoStandbyHigh SetND SetND1 SetND2 TakeIntensityReading WaitForCalSource WaitForFlatFieldFiberPos WaitForLampWarm WaitForLFCReady WaitForND WaitForND1 WaitForND2 kpf.engineering GridSearch ImageBackIlluminatedFibers Run2DGridSearch TakeADCGridData TakeADCOffsetGridData TakeGuiderSensitivityData TriggerGreenMiniFill TriggerRedMiniFill AnalyzeGridSearch AnalyzeTipTiltPerformance Fit2DGridSearch CountCameraErrors kpf.expmeter BuildMasterBias SetExpMeterExpTime SetExpMeterTerminationParameters PredictExpMeterParameters SetMasterBiasToDefault SetupExpMeter TakeExpMeterBiases kpf.fiu ConfigureFIU ControlFoldMirror ControlHatch InitializeTipTilt LockFIU UnlockFIU MeasureTipTiltMirrorRange SetADCAngles SetADCOffsets SetTipTiltCalculations SetTipTiltControl SetTipTiltGain SetTipTiltPosition SetTipTiltTargetPixel ShutdownTipTilt StartTipTilt StopTipTilt TestTipTiltMirrorRange VerifyCurrentBase WaitForConfigureFIU WaitForTipTilt kpf.fvc FVCPower PredictFVCParameters TakeFVCContinuous TakeFVCExposure SetFVCExpTime kpf.guider DisplayGuiderContinuous GetGaiaStars GuiderLastfile GuiderOutdir PredictGuiderParameters SetGuiderExpTime SetGuiderFPS SetGuiderGain SetGuiderOutdir StartGuiderContinuous StartTriggerFile StopGuiderContinuous StopTriggerFile TakeGuiderCube TakeGuiderExposure WaitForTriggerFile kpf.scripts CleanupAfterCalibrations CleanupAfterScience CollectGuiderDarkCubes ConfigureForAcquisition ConfigureForCalibrations ConfigureForScience EndOfNight EnterLowPowerMode ExecuteSlewCal RecoverFromLowPowerMode RunCalOB RunSciOB RunSoCalObservingLoop RunTwilightRVStandard StartOfNight StartUp WaitForConfigureCalibrations kpf.socal DisableSoCal EnableSoCal IsSoCalClosed IsSoCalOpen IsSoCalShutDown ParkSoCal SoCalStartAutonomous SoCalStopAutonomous WaitForSoCalOnTarget kpf.spectrograph QueryReadMode QueryFastReadMode RecoverDetectors ResetCaHKDetector ResetExpMeterDetector ResetGreenDetector ResetRedDetector ResetDetectors SetExpTime SetObject SetObserver SetProgram SetReadModeFast SetReadModeNormal SetSourceSelectShutters SetTimedShutters SetTriggeredDetectors StartAgitator StartExposure StopAgitator WaitForL0File WaitForReadout WaitForReady kpf.utils BuildOBfromQuery CalculateDAR CheckDewarWeights CorrectDAR EstimateOBDuration SetObserverFromSchedule SetOutdirs SetSimulCalSource SetTargetInfo StartGUIs StopGUIs ZeroOutSlewCalTime","title":"Scripts"}]} \ No newline at end of file +{"config":{"indexing":"full","lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"Keck Planet Finder (KPF) Email Contact: kpf_info@keck.hawaii.edu Instrument Scientist: Josh Walawender Deputy Instrument Scientist: Sherry Yeh Instrument Description The Keck Planet Finder (KPF) is a \ufb01ber-fed, high-resolution, high-stability cross dispersed, spectrometer designed to characterize exoplanets via Doppler spectroscopy with a goal of a single measurement precision of 0.3 m/s or better. KPF covers a wavelength range of 445 nm to 870 nm over green and red channels. KPF consists of 3 independant spectrographs: The primary science spectrograph described above which is designed to be highly stable and has both a green and red arm. The spectrograph optical bench is made from low expansion Zerodur and is kept is a temperature stabilized environment. A Calcium H&K spectrograph which gets the light blueward of the main science spectrograph and is used to simultaneously measure stellar activity using the Ca H&K lines. The exposure meter spectrograph which gets a portion of the science light and is used to measure the flux level during long exposures of the primary science detectors. The exposure meter both measures the time weighted flux midpoint of each exposure, and can also be used to terminate an exposure at a specified flux level. All three spectrographs are fed by optical fiber from the Fiber Injection Unit (FIU) which sits on the Keck I AO bench. The light entering the FIU is not AO corrected, but is fed off a fast tip tilt mirror which is used to maintain the target star's position on the science fiber within 50 mas rms of the fiber center. Performance of the tip tilt loop is to be confirmed during commissioning. During observations, the spectrograph can be fed with light from a simultaneous calibration fiber. This places calibration light alongside science and sky spectra in the pseudo-slit. The calibration light is fed from the calibration bench which contains several calibration sources. In addition to the simultaneous calibration light, the calibration bench can be configured to feed light up to the FIU and through the science and sky fibers in order to bring cal light in to the science and sky portions of the pseudo-slit. The system overview diagram showing the relationships between the different subsystems of the instrument. KPF's Zerodur optical bench during integration at the Space Sciences Lab at UC Berkeley. The echelle grating can be seen at the upper right.","title":"KPF Home"},{"location":"#keck-planet-finder-kpf","text":"Email Contact: kpf_info@keck.hawaii.edu Instrument Scientist: Josh Walawender Deputy Instrument Scientist: Sherry Yeh","title":"Keck Planet Finder (KPF)"},{"location":"#instrument-description","text":"The Keck Planet Finder (KPF) is a \ufb01ber-fed, high-resolution, high-stability cross dispersed, spectrometer designed to characterize exoplanets via Doppler spectroscopy with a goal of a single measurement precision of 0.3 m/s or better. KPF covers a wavelength range of 445 nm to 870 nm over green and red channels. KPF consists of 3 independant spectrographs: The primary science spectrograph described above which is designed to be highly stable and has both a green and red arm. The spectrograph optical bench is made from low expansion Zerodur and is kept is a temperature stabilized environment. A Calcium H&K spectrograph which gets the light blueward of the main science spectrograph and is used to simultaneously measure stellar activity using the Ca H&K lines. The exposure meter spectrograph which gets a portion of the science light and is used to measure the flux level during long exposures of the primary science detectors. The exposure meter both measures the time weighted flux midpoint of each exposure, and can also be used to terminate an exposure at a specified flux level. All three spectrographs are fed by optical fiber from the Fiber Injection Unit (FIU) which sits on the Keck I AO bench. The light entering the FIU is not AO corrected, but is fed off a fast tip tilt mirror which is used to maintain the target star's position on the science fiber within 50 mas rms of the fiber center. Performance of the tip tilt loop is to be confirmed during commissioning. During observations, the spectrograph can be fed with light from a simultaneous calibration fiber. This places calibration light alongside science and sky spectra in the pseudo-slit. The calibration light is fed from the calibration bench which contains several calibration sources. In addition to the simultaneous calibration light, the calibration bench can be configured to feed light up to the FIU and through the science and sky fibers in order to bring cal light in to the science and sky portions of the pseudo-slit. The system overview diagram showing the relationships between the different subsystems of the instrument. KPF's Zerodur optical bench during integration at the Space Sciences Lab at UC Berkeley. The echelle grating can be seen at the upper right.","title":"Instrument Description"},{"location":"CalOBparameters/","text":"","title":"Calibration OB Parameters"},{"location":"KPFTranslator/","text":"KPF Translator Most of KPF operations are controlled via the KPF Translator which is composed of Python code, which interacts with the underlying KTL keywords to automate various tasks. Each script is actually a Python class which is invoked by an execute() method which itself calls the pre_condition() , perform() , and post_condition() methods. This three-part structure allows the script to check that the system is ready for the action to be performed, then execute the action, then confirm a successful execution. These scripts can also be invoked via a command line interface to the underlying python and are used for everything from small, atomic actions which might require only a single KTL keyword write to execute, to large scripts which need significant flow control such as executing a science observation at night -- including configuring the instrument, waiting for the telescope and tip-tilt system to acquire the target, executing the specified exposures, and finally performing clean up actions. Detailed documentation on each translator script can be found in the scripts section of this documentation.","title":"Instrument Software"},{"location":"KPFTranslator/#kpf-translator","text":"Most of KPF operations are controlled via the KPF Translator which is composed of Python code, which interacts with the underlying KTL keywords to automate various tasks. Each script is actually a Python class which is invoked by an execute() method which itself calls the pre_condition() , perform() , and post_condition() methods. This three-part structure allows the script to check that the system is ready for the action to be performed, then execute the action, then confirm a successful execution. These scripts can also be invoked via a command line interface to the underlying python and are used for everything from small, atomic actions which might require only a single KTL keyword write to execute, to large scripts which need significant flow control such as executing a science observation at night -- including configuring the instrument, waiting for the telescope and tip-tilt system to acquire the target, executing the specified exposures, and finally performing clean up actions. Detailed documentation on each translator script can be found in the scripts section of this documentation.","title":"KPF Translator"},{"location":"KPFvsHIRES/","text":"Comparing KPF to HIRES This page attempts to compare KPF and HIRES for users who may be wondering which instrument they should propose for. Fundamentally HIRES is a more flexible instrument with selectable grating angles to control the wavelength coverage and selectable slits which allow the user to trade off throughput against spectral resolution while KPF is a fixed format spectrograph with a fixed input fiber. HIRES also has a wider spectral coverage than KPF and even includes the option to change the internal optics to optimize either blue or red sensitivity. Though KPF has the Calcium H&K spectrograph, a dedicated arm to examine the 382-402 nm wavelength range around the Ca H&K lines. KPF, on the other hand, has higher spectral resolution even though it has a larger entrance aperture on sky and so it may be more sensitive for use cases which need that combination. Of course, KPF is also highly stabilized and is optimized for precision radial velocity measurements. Summary Table Comparison KPF HIRES Optical Input 1.14 arcsec octagonal fibers for science and sky (fixed format) Selectable deckers and slits for different sky projections (e.g., B5 = 0.87 x 3.5 arcsec) Wavelength Coverage Fixed format: 445-870 nm (high-res) 382-402 nm (med-res) ~300-1000 nm in an adjustable format (moving the spectral format across detector) Resolving Power R=98k (445-870 nm) depends on slit e.g. R=49k for 0.86 arcsec-wide slit R=80k for 0.40 arcsec-wide slit Throughput (sky to CCD) ~8-10% peak-of-blaze (measured) 5-6% peak-of-blaze for B5-B1 deckers (measured) Doppler Precision 0.5 m/s noise floor (req.) 0.3 m/s (goal) ~2 m/s systematic noise floor Doppler Speed ~8-10x faster than HIRES Limited by need for high SNR to model iodine spectrum Comparing Using Exposure Time Calculators (ETCs) Using the HIRES ETC at UCO and the KPF ETC , we can compare the signal to noise in observations of a common target in each instrument. It should be noted that the plot below is not a direct comparison of the two instruments, but is a comparison of two exposure time calculators. Subtle differences in assumptions made in each piece of software may bias this result, so this should be taken as illustrative, not definitive. Comparison of the signal to noise estimates from ETCs for KPF and HIRES. Inputs to the ETCs were as similar as possible.","title":"KPF vs. HIRES"},{"location":"KPFvsHIRES/#comparing-kpf-to-hires","text":"This page attempts to compare KPF and HIRES for users who may be wondering which instrument they should propose for. Fundamentally HIRES is a more flexible instrument with selectable grating angles to control the wavelength coverage and selectable slits which allow the user to trade off throughput against spectral resolution while KPF is a fixed format spectrograph with a fixed input fiber. HIRES also has a wider spectral coverage than KPF and even includes the option to change the internal optics to optimize either blue or red sensitivity. Though KPF has the Calcium H&K spectrograph, a dedicated arm to examine the 382-402 nm wavelength range around the Ca H&K lines. KPF, on the other hand, has higher spectral resolution even though it has a larger entrance aperture on sky and so it may be more sensitive for use cases which need that combination. Of course, KPF is also highly stabilized and is optimized for precision radial velocity measurements.","title":"Comparing KPF to HIRES"},{"location":"KPFvsHIRES/#summary-table","text":"Comparison KPF HIRES Optical Input 1.14 arcsec octagonal fibers for science and sky (fixed format) Selectable deckers and slits for different sky projections (e.g., B5 = 0.87 x 3.5 arcsec) Wavelength Coverage Fixed format: 445-870 nm (high-res) 382-402 nm (med-res) ~300-1000 nm in an adjustable format (moving the spectral format across detector) Resolving Power R=98k (445-870 nm) depends on slit e.g. R=49k for 0.86 arcsec-wide slit R=80k for 0.40 arcsec-wide slit Throughput (sky to CCD) ~8-10% peak-of-blaze (measured) 5-6% peak-of-blaze for B5-B1 deckers (measured) Doppler Precision 0.5 m/s noise floor (req.) 0.3 m/s (goal) ~2 m/s systematic noise floor Doppler Speed ~8-10x faster than HIRES Limited by need for high SNR to model iodine spectrum","title":"Summary Table"},{"location":"KPFvsHIRES/#comparing-using-exposure-time-calculators-etcs","text":"Using the HIRES ETC at UCO and the KPF ETC , we can compare the signal to noise in observations of a common target in each instrument. It should be noted that the plot below is not a direct comparison of the two instruments, but is a comparison of two exposure time calculators. Subtle differences in assumptions made in each piece of software may bias this result, so this should be taken as illustrative, not definitive. Comparison of the signal to noise estimates from ETCs for KPF and HIRES. Inputs to the ETCs were as similar as possible.","title":"Comparing Using Exposure Time Calculators (ETCs)"},{"location":"SciOBparameters/","text":"Science OB Contents Here is an example science OB formatted as a text file (this is the YAML data format). The comments (preceded by a # symbol) are not needed, but are present to help the reader. Template_Name : kpf_sci Template_Version : 1.0 # Target Info TargetName : 10700 # Name GaiaID : DR3 2452378776434276992 # Gaia ID 2 MASSID : 01440402 - 1556141 # 2 MASS ID Parallax : 273.81 # Parallax in arcsec RadialVelocity : - 16.597 # Radial Velocity in km / s Gmag : 3.3 # G band magnitude ( eventualy used by exposure meter ) Jmag : 2.14 # J band magnitude ( eventualy used by guider ) Teff : 5266 # Effective temperature # Spectrograph Setup TriggerCaHK : False # Include CaHK in exposure ( True / False ) TriggerGreen : True # Include Green CCD in exposure ( True / False ) TriggerRed : True # Include Red CCD in exposure ( True / False ) BlockSky : False # Close the sky fiber shutter during observations ( True / False ) # Observations SEQ_Observations : # - Object : 10700 # User settable comment nExp : 4 # Number of exoposures in the OB ExpTime : 30 # Exposure time of the main spectrometer and CaH & K . See Exposure Meter section below . ExpMeterMode : control # \"monitor\" or \"control\" ( to terminate exposure based on flux ) AutoExpMeter : False # Set the exposure meter exposure time automatically ExpMeterExpTime : 0.5 # Exposure time of the Exposure Meter subframes ExpMeterBin : 3 # Exposure meter wavelength bin to use for stopping exposure ExpMeterThreshold : 1 e5 # Target science flux in e -/ nm TakeSimulCal : True # Take simultaneous calibrations ? ( True / False ) AutoNDFilters : False # Automatically set ND filters -- Not available at this time ! CalND1 : OD 4.0 # OD = Optical Density . Throughput = 10 ^- OD CalND2 : OD 0.1 # Each value in the OB is described in more detail below. Template_Name and Template_Version ( str ) These values indicate to the software what sort of observation this is and what script to execute. For a science observation, always use \"kpf_sci\" as the template name. TargetName : ( str ) This is a name chosen by the observer. GaiaID and 2MASSID : ( str ) These values are used by the DRP to identify the star and determine its properties. Parallax : ( float ) Parallax in arcseconds. RadialVelocity : ( float ) Radial Velocity in km/s. Gmag : ( float ) This is used by the DRP and by the algorithm which automatically sets the exposure meter exposure time. Jmag : ( float ) This is used by the algorithm which automatically sets the guider gain and frame rate. Teff : ( float ) The effective temperature of the star. Allowed Range: 2600 - 45000 TriggerCaHK, TriggerGreen, and TriggerRed : ( bool ) These values indicate whether to trigger the respective camera during the science exposures. All of these cameras will be synced up and will get the same exposure time. SEQ_Observations The SEQ_Observations: line is required. The following block of lines represent one entry in a list. If more than one set of exposures on a target is desired, this block of text can be repeated to build a second \"observation\" on the target with different parameters. Object : ( str ) This value will go in to the FITS header as the OBJECT keyword value. This is can be used as a notes field for the observer to explain how this set of exposures differs from any following observations of this target. This field can be left blank or set to the target name, it is entirely up to the observer. nExp : ( int ) The number of exposures to take. ExpTime : ( float ) The exposure time in seconds. Note that if the exposure meter is controlling the exposure duration, this exposure time is the maximum value which will be allowed (the exposure meter may cut the exposure short if the desired flux level is reached). ExpMeterMode : ( str ) For now, only the \"monitor\" mode is available. In \"monitor\" the exposure meter will take exposure during the science exposure and record fluxes. This data will be stored in the resulting FITS file can be used to determine the flux weighted exposure midpoint in time for accurate barycentric correction. Allowed Values: \"monitor\", \"control\", or \"off\" AutoExpMeter : ( bool ) If this is True, the software will use the Gmag value to estimate a good exposure time for the individual exposure meter exposures and use that instead of the ExpMeterExpTime value below. ExpMeterExpTime : ( float ) The exposure time in seconds for individual exposure meter exposures. This is ignored if AutoExpMeter is True. TakeSimulCal : ( bool ) Should the instrument be configured to illuminate the simultaneous calibration fiber during the science exposure? AutoNDFilters : ( bool ) Should the software automatically set the ND filters based on the target and exposure information? This is currently (June 2024) in a testing mode and is not recommended for normal use. CalND1 ( str ) The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: OD 0.1 , OD 1.0 , OD 1.3 , OD 2.0 , OD 3.0 , OD 4.0 CalND2 ( str ) The neutral density filter to put in the second filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: OD 0.1 , OD 0.3 , OD 0.5 , OD 0.8 , OD 1.0 , OD 4.0","title":"Science OB Parameters"},{"location":"SciOBparameters/#science-ob-contents","text":"Here is an example science OB formatted as a text file (this is the YAML data format). The comments (preceded by a # symbol) are not needed, but are present to help the reader. Template_Name : kpf_sci Template_Version : 1.0 # Target Info TargetName : 10700 # Name GaiaID : DR3 2452378776434276992 # Gaia ID 2 MASSID : 01440402 - 1556141 # 2 MASS ID Parallax : 273.81 # Parallax in arcsec RadialVelocity : - 16.597 # Radial Velocity in km / s Gmag : 3.3 # G band magnitude ( eventualy used by exposure meter ) Jmag : 2.14 # J band magnitude ( eventualy used by guider ) Teff : 5266 # Effective temperature # Spectrograph Setup TriggerCaHK : False # Include CaHK in exposure ( True / False ) TriggerGreen : True # Include Green CCD in exposure ( True / False ) TriggerRed : True # Include Red CCD in exposure ( True / False ) BlockSky : False # Close the sky fiber shutter during observations ( True / False ) # Observations SEQ_Observations : # - Object : 10700 # User settable comment nExp : 4 # Number of exoposures in the OB ExpTime : 30 # Exposure time of the main spectrometer and CaH & K . See Exposure Meter section below . ExpMeterMode : control # \"monitor\" or \"control\" ( to terminate exposure based on flux ) AutoExpMeter : False # Set the exposure meter exposure time automatically ExpMeterExpTime : 0.5 # Exposure time of the Exposure Meter subframes ExpMeterBin : 3 # Exposure meter wavelength bin to use for stopping exposure ExpMeterThreshold : 1 e5 # Target science flux in e -/ nm TakeSimulCal : True # Take simultaneous calibrations ? ( True / False ) AutoNDFilters : False # Automatically set ND filters -- Not available at this time ! CalND1 : OD 4.0 # OD = Optical Density . Throughput = 10 ^- OD CalND2 : OD 0.1 # Each value in the OB is described in more detail below. Template_Name and Template_Version ( str ) These values indicate to the software what sort of observation this is and what script to execute. For a science observation, always use \"kpf_sci\" as the template name. TargetName : ( str ) This is a name chosen by the observer. GaiaID and 2MASSID : ( str ) These values are used by the DRP to identify the star and determine its properties. Parallax : ( float ) Parallax in arcseconds. RadialVelocity : ( float ) Radial Velocity in km/s. Gmag : ( float ) This is used by the DRP and by the algorithm which automatically sets the exposure meter exposure time. Jmag : ( float ) This is used by the algorithm which automatically sets the guider gain and frame rate. Teff : ( float ) The effective temperature of the star. Allowed Range: 2600 - 45000 TriggerCaHK, TriggerGreen, and TriggerRed : ( bool ) These values indicate whether to trigger the respective camera during the science exposures. All of these cameras will be synced up and will get the same exposure time.","title":"Science OB Contents"},{"location":"SciOBparameters/#seq_observations","text":"The SEQ_Observations: line is required. The following block of lines represent one entry in a list. If more than one set of exposures on a target is desired, this block of text can be repeated to build a second \"observation\" on the target with different parameters. Object : ( str ) This value will go in to the FITS header as the OBJECT keyword value. This is can be used as a notes field for the observer to explain how this set of exposures differs from any following observations of this target. This field can be left blank or set to the target name, it is entirely up to the observer. nExp : ( int ) The number of exposures to take. ExpTime : ( float ) The exposure time in seconds. Note that if the exposure meter is controlling the exposure duration, this exposure time is the maximum value which will be allowed (the exposure meter may cut the exposure short if the desired flux level is reached). ExpMeterMode : ( str ) For now, only the \"monitor\" mode is available. In \"monitor\" the exposure meter will take exposure during the science exposure and record fluxes. This data will be stored in the resulting FITS file can be used to determine the flux weighted exposure midpoint in time for accurate barycentric correction. Allowed Values: \"monitor\", \"control\", or \"off\" AutoExpMeter : ( bool ) If this is True, the software will use the Gmag value to estimate a good exposure time for the individual exposure meter exposures and use that instead of the ExpMeterExpTime value below. ExpMeterExpTime : ( float ) The exposure time in seconds for individual exposure meter exposures. This is ignored if AutoExpMeter is True. TakeSimulCal : ( bool ) Should the instrument be configured to illuminate the simultaneous calibration fiber during the science exposure? AutoNDFilters : ( bool ) Should the software automatically set the ND filters based on the target and exposure information? This is currently (June 2024) in a testing mode and is not recommended for normal use. CalND1 ( str ) The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: OD 0.1 , OD 1.0 , OD 1.3 , OD 2.0 , OD 3.0 , OD 4.0 CalND2 ( str ) The neutral density filter to put in the second filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: OD 0.1 , OD 0.3 , OD 0.5 , OD 0.8 , OD 1.0 , OD 4.0","title":"SEQ_Observations"},{"location":"afternoonsetup/","text":"Afternoon Setup The afternoon setup process for the instrument itself is minimal. Calibrations are automated, so unless you have very special requirements for your observation (if so please contact the Staff Astronomer supporting your night in advance), then observers will not need to execute any calibrations. Prior to starting observing, observers should run: KPF Control Menu --> Start KPF GUIs from the background menu (or kpfStartGUIs from the command line on any KPF machine). This will start the KPF GUIs and can be run at any time prior to observing. Preparing Observing Blocks (OBs) Observers should use the afternoon to prepare Observing Blocks (OBs) and their star list if they have not done so already. Connecting to VNCs Observers can connect to the Keck VNCs to control the instrument from Keck HQ in Waimea, one of the Keck Remote Observing Stations, or from home using the Remote Observing Software. For details, see the Remote Observing documentation. Starting KPF GUIs The KPF GUIs can be started at any time. To do so, choose KPF Control Menu -> Start KPF GUIs from the FVWM menu. Check that the GUIs come up properly in the various VNC sessions. Each session is described below. control0 The control0 VNC session should contain: OB GUI : This is where the observer can build and execute observing blocks. Tip Tilt GUI : This is a view-only version of the GUI the OAs use to control the tip tilt system. Observers can use this to see the tip tilt system status and images, but observers can not control the system. control1 The control1 VNC session should contain: FIU GUI : This shows the status of the FIU including the light path. This is a good place to look if you are not seeing stars on the guider and want to know if the guider should eb seeing the sky. Exposure Meter GUI : This will show the progress of the flux measured by the exposure meter over the course of a single exposure. Spectrograph GUI : This shows the staus of the overall instrument (including a simplified FIU status). The light paths which are illuminated will show up as colored lines and arrows here to indicate where light is being directed by the various components. control2 The control2 VNC session should contain: A ds9 instance which shows the latest raw image from the Ca H&K, Green, and Red detectors. Eventsounds GUI : This is a standard Keck GUI where the users can enable/disable sounds and change what sound is produced by a given event. telstatus The telstatus VNC session should contain: FACSUM : A standard Keck GUI showing the status of the facility (telescope and dome). XMET : A standard Keck GUI showing various weather telemetry values. The OAs have more weather information which is not shown here, but this is a good summary. Magiq Observer UI : A standard Keck GUI for viewing guider images and interacting with star lists. Note that the Magiq UI may not come up if the StartGUIs script was run while KPF was not the selected instrument. The Magiq UI will always come up with the guider for the selected instrument when launched. If Magiq is not running, launch it via Telescope GUIs --> Magiq Guider UI from the FVWM menu.","title":"Afternoon Setup"},{"location":"afternoonsetup/#afternoon-setup","text":"The afternoon setup process for the instrument itself is minimal. Calibrations are automated, so unless you have very special requirements for your observation (if so please contact the Staff Astronomer supporting your night in advance), then observers will not need to execute any calibrations. Prior to starting observing, observers should run: KPF Control Menu --> Start KPF GUIs from the background menu (or kpfStartGUIs from the command line on any KPF machine). This will start the KPF GUIs and can be run at any time prior to observing.","title":"Afternoon Setup"},{"location":"afternoonsetup/#preparing-observing-blocks-obs","text":"Observers should use the afternoon to prepare Observing Blocks (OBs) and their star list if they have not done so already.","title":"Preparing Observing Blocks (OBs)"},{"location":"afternoonsetup/#connecting-to-vncs","text":"Observers can connect to the Keck VNCs to control the instrument from Keck HQ in Waimea, one of the Keck Remote Observing Stations, or from home using the Remote Observing Software. For details, see the Remote Observing documentation.","title":"Connecting to VNCs"},{"location":"afternoonsetup/#starting-kpf-guis","text":"The KPF GUIs can be started at any time. To do so, choose KPF Control Menu -> Start KPF GUIs from the FVWM menu. Check that the GUIs come up properly in the various VNC sessions. Each session is described below.","title":"Starting KPF GUIs"},{"location":"afternoonsetup/#control0","text":"The control0 VNC session should contain: OB GUI : This is where the observer can build and execute observing blocks. Tip Tilt GUI : This is a view-only version of the GUI the OAs use to control the tip tilt system. Observers can use this to see the tip tilt system status and images, but observers can not control the system.","title":"control0"},{"location":"afternoonsetup/#control1","text":"The control1 VNC session should contain: FIU GUI : This shows the status of the FIU including the light path. This is a good place to look if you are not seeing stars on the guider and want to know if the guider should eb seeing the sky. Exposure Meter GUI : This will show the progress of the flux measured by the exposure meter over the course of a single exposure. Spectrograph GUI : This shows the staus of the overall instrument (including a simplified FIU status). The light paths which are illuminated will show up as colored lines and arrows here to indicate where light is being directed by the various components.","title":"control1"},{"location":"afternoonsetup/#control2","text":"The control2 VNC session should contain: A ds9 instance which shows the latest raw image from the Ca H&K, Green, and Red detectors. Eventsounds GUI : This is a standard Keck GUI where the users can enable/disable sounds and change what sound is produced by a given event.","title":"control2"},{"location":"afternoonsetup/#telstatus","text":"The telstatus VNC session should contain: FACSUM : A standard Keck GUI showing the status of the facility (telescope and dome). XMET : A standard Keck GUI showing various weather telemetry values. The OAs have more weather information which is not shown here, but this is a good summary. Magiq Observer UI : A standard Keck GUI for viewing guider images and interacting with star lists. Note that the Magiq UI may not come up if the StartGUIs script was run while KPF was not the selected instrument. The Magiq UI will always come up with the guider for the selected instrument when launched. If Magiq is not running, launch it via Telescope GUIs --> Magiq Guider UI from the FVWM menu.","title":"telstatus"},{"location":"agitator/","text":"Agitator KPF includes a mechanical oscillator which agitates the fibers to aid in mode scrambling in the fibers. The agitator is located directly beneath the azimuth ring of the Keck I telescope. It is automatically turned on and off during science and calibration observations and needs no user intervention. The agitator oscillates at about 2 Hz.","title":"Agitator"},{"location":"agitator/#agitator","text":"KPF includes a mechanical oscillator which agitates the fibers to aid in mode scrambling in the fibers. The agitator is located directly beneath the azimuth ring of the Keck I telescope. It is automatically turned on and off during science and calibration observations and needs no user intervention. The agitator oscillates at about 2 Hz.","title":"Agitator"},{"location":"buildingOBs/","text":"Building Observing Blocks (OBs) The basic unit of KPF nighttime operations is the Observing Block (OB). An OB describes a single visit to a science target and the observations made there. The data contained in the OB is a set of keyword-value pairs. Observers can prepare OBs as text files which can be read in by the KPF software and executed or (once logged in to the KPF VNCs) they can use tools there to build the OBs and save them as files. The data in an OB can be divided in to a few rough categories: Target information : The OB will contain information about the target beyond what is in a typical Keck Star List entry in order to flow that information to the FITS header and the data reduction pipeline (DRP). Instrument Setup : The OB will also contain information about how to configure the instrument for this set of observations. Observations : Finally, the OB will contain a list of \"observations\" to be made of the target. For typical KPF observers, this will only have one entry, but multiple entries are supported. Each entry describes a set of exposures on the target and contains the information on how those exposures should be executed. KPF OB GUI A graphical tool has been built to help observers build their KPF OBs, it is launched automatically as part of the script to start all GUIs. A screenshot of the KPF OB GUI. The top section of the GUI, \"Instrument Status\" shows whether an instrument script (e.g. an observation or calibration set) is being run and allows users to request that script stop. The middle section can be used to load an OB from a file, build an OB from scratch using a Gaia DR3 catalog query, save the OB to a file, or execute the OB. The lower section is where a user can fill out the OB parameters as described in the \"KPF Science OB Contents\" section above.","title":"Building OBs"},{"location":"buildingOBs/#building-observing-blocks-obs","text":"The basic unit of KPF nighttime operations is the Observing Block (OB). An OB describes a single visit to a science target and the observations made there. The data contained in the OB is a set of keyword-value pairs. Observers can prepare OBs as text files which can be read in by the KPF software and executed or (once logged in to the KPF VNCs) they can use tools there to build the OBs and save them as files. The data in an OB can be divided in to a few rough categories: Target information : The OB will contain information about the target beyond what is in a typical Keck Star List entry in order to flow that information to the FITS header and the data reduction pipeline (DRP). Instrument Setup : The OB will also contain information about how to configure the instrument for this set of observations. Observations : Finally, the OB will contain a list of \"observations\" to be made of the target. For typical KPF observers, this will only have one entry, but multiple entries are supported. Each entry describes a set of exposures on the target and contains the information on how those exposures should be executed.","title":"Building Observing Blocks (OBs)"},{"location":"buildingOBs/#kpf-ob-gui","text":"A graphical tool has been built to help observers build their KPF OBs, it is launched automatically as part of the script to start all GUIs. A screenshot of the KPF OB GUI. The top section of the GUI, \"Instrument Status\" shows whether an instrument script (e.g. an observation or calibration set) is being run and allows users to request that script stop. The middle section can be used to load an OB from a file, build an OB from scratch using a Gaia DR3 catalog query, save the OB to a file, or execute the OB. The lower section is where a user can fill out the OB parameters as described in the \"KPF Science OB Contents\" section above.","title":"KPF OB GUI"},{"location":"cahk/","text":"Calcium H&K Spectrometer A separate small spectrometer is used to monitor the Ca H & K lines for stellar activity that could mimic Doppler shifts. A major advantage of this approach is that the KPF spectrometer does not need to cover an increased bandpass blueward to 390 nm, and can stop at 443 nm (the Doppler information is reduced for G and K stars at bluer wavelengths owing to the significantly lower flux). This approach has important advantages with respect to optical coating bandpasses and efficiency, as well as the required detector size. The Calcium H & K spectrometer is a simple system (VPH-based with doublet lenses for collimator and camera), and is fiber fed via a UV-enhanced fiber (such as CeramOptec UVNS). Light will be injected into this fiber by the FIU, to captrue this light before major UV absorption losses occur within the long fiber run. Under normal conditions, the Ca H&K spectrometer is triggered simultaneously with the main science spectrograph and the data is packaged in to the L0 file with the rest of the science data for analysis by the DRP.","title":"Ca H&K Spectrograph"},{"location":"cahk/#calcium-hk-spectrometer","text":"A separate small spectrometer is used to monitor the Ca H & K lines for stellar activity that could mimic Doppler shifts. A major advantage of this approach is that the KPF spectrometer does not need to cover an increased bandpass blueward to 390 nm, and can stop at 443 nm (the Doppler information is reduced for G and K stars at bluer wavelengths owing to the significantly lower flux). This approach has important advantages with respect to optical coating bandpasses and efficiency, as well as the required detector size. The Calcium H & K spectrometer is a simple system (VPH-based with doublet lenses for collimator and camera), and is fiber fed via a UV-enhanced fiber (such as CeramOptec UVNS). Light will be injected into this fiber by the FIU, to captrue this light before major UV absorption losses occur within the long fiber run. Under normal conditions, the Ca H&K spectrometer is triggered simultaneously with the main science spectrograph and the data is packaged in to the L0 file with the rest of the science data for analysis by the DRP.","title":"Calcium H&K Spectrometer"},{"location":"calbench/","text":"Calibration Bench The cal bench contains several calibration light sources and can inject light in to the simultaneous calibration fiber (one of the components of the pseudo slit) or to inject light to the FIU and thus illuminate the science and sky fibers with the chosen calibration lamp. Most of the calibration sources are located in the \"octagon\". A rotating fold mirror can direct light from one of 8 ports to the calibration fibers. The octagon light sources are: EtalonFiber : Light from a \"SuperK\" continuum source which has passed through the Etalon. BrdbandFiber : A broadband lamp. U_gold : A UNe arc lamp U_daily : A UNe arc lamp Th_daily : A ThAr arc lamp Th_gold : A ThAr arc lamp SoCal-CalFib : Light from the Solar Calibrator LFCFiber : Light from the Laser Frequency Comb (LFC) Etalon The KPF etalon is a thermally stable (~1 mK RMS) resonant cavity fed by an NKT SuperK EVO light source. The resulting line forest covers all of the KPF science passband. The Etalon spectrum evolves slowly with time, so it is not used for obsolte calibration, but it can be used to track the short time scale evolution of the instrument. Effectively \"filling in\" between absolute wavelength calibrators such as the LFC or the arc lamps. Broadband Lamp KPF takes relatively standard spectral flats using a broadband lamp. Because of the extreme requirements for PRV measurements, the flats must be extraordinarily high signal to noise and be taken daily to track any changes. Arc Lamps The arc lamps (ThAr and UNe) can be used for absolute wavelength calibration. Unlike the LFC, they do not have a regular spacing of lines, but they do provide lines in the bluest orders (see below). Two of each lamp are available in the octagon at any time. Laser Frequency Comb The LFC is the best calibrator due to the density of lines which allows a very precise measurement of the wavelength solution, but it is currently (early 2024) limited due to a lack of flux in the bluest orders. For those, the traditional Thorium and Uranium lamps provide absolute calibration.","title":"Calibration Bench"},{"location":"calbench/#calibration-bench","text":"The cal bench contains several calibration light sources and can inject light in to the simultaneous calibration fiber (one of the components of the pseudo slit) or to inject light to the FIU and thus illuminate the science and sky fibers with the chosen calibration lamp. Most of the calibration sources are located in the \"octagon\". A rotating fold mirror can direct light from one of 8 ports to the calibration fibers. The octagon light sources are: EtalonFiber : Light from a \"SuperK\" continuum source which has passed through the Etalon. BrdbandFiber : A broadband lamp. U_gold : A UNe arc lamp U_daily : A UNe arc lamp Th_daily : A ThAr arc lamp Th_gold : A ThAr arc lamp SoCal-CalFib : Light from the Solar Calibrator LFCFiber : Light from the Laser Frequency Comb (LFC)","title":"Calibration Bench"},{"location":"calbench/#etalon","text":"The KPF etalon is a thermally stable (~1 mK RMS) resonant cavity fed by an NKT SuperK EVO light source. The resulting line forest covers all of the KPF science passband. The Etalon spectrum evolves slowly with time, so it is not used for obsolte calibration, but it can be used to track the short time scale evolution of the instrument. Effectively \"filling in\" between absolute wavelength calibrators such as the LFC or the arc lamps.","title":"Etalon"},{"location":"calbench/#broadband-lamp","text":"KPF takes relatively standard spectral flats using a broadband lamp. Because of the extreme requirements for PRV measurements, the flats must be extraordinarily high signal to noise and be taken daily to track any changes.","title":"Broadband Lamp"},{"location":"calbench/#arc-lamps","text":"The arc lamps (ThAr and UNe) can be used for absolute wavelength calibration. Unlike the LFC, they do not have a regular spacing of lines, but they do provide lines in the bluest orders (see below). Two of each lamp are available in the octagon at any time.","title":"Arc Lamps"},{"location":"calbench/#laser-frequency-comb","text":"The LFC is the best calibrator due to the density of lines which allows a very precise measurement of the wavelength solution, but it is currently (early 2024) limited due to a lack of flux in the bluest orders. For those, the traditional Thorium and Uranium lamps provide absolute calibration.","title":"Laser Frequency Comb"},{"location":"calibrations/","text":"Calibrations KPF observers do not need to take afternoon cals because the calibration system is automatic (driven by cron jobs). This is important to PRV science as to get the best RVs, the instrument and its daily cycles need to be characterized, so we want to sample the calibrations in a systematic and repeatable way each day. The calibration schedule is a trade off between several factors. Because we want the calibrations to happen at a consistent time each day, we start the daily schedule based on the latest sunrise and the earliest sunset of the year. The calibrations can be broadly divided in to several categories described in the Types of Calibrations section below. The Daily Calibration Schedule Each day, the calibrations described below are executed. The needs of KPF are such that each day is filled as much as possible by calibrations. The diagram below shows what that schedule looks like over the course of a year as the sunrise and sunset times evolve with the seasons. This figure shows how the KPF calibration schedule interacts with the nighttime schedule over the course of a year (the 23A & B semesters in this case). The various lines show how daily events such as sunrise and sunset evolve in UT time. The lines are labeled on the left side of the plot. The shaded regions are the approximate duration of the scheduled calibrations. Even if no KPF observations are scheduled, the calibrations occupy 816 minutes (more than 13.5 hours) each day, or about 57% of the day. The gaps in this schedule are driven the desire to avoid having calibrations in progress when someone might be starting to operate the instrument: near sunset and at each of the quarter night boundaries. Types of Calibrations Wavelength Calibrations Wavelength calibrations are the most critical daily calibration. Absolute wavelength calibrations use the laser frequency comb (LFC) or one of the hollow cathode lamps (ThAr or UNe). The etalon is also used for wavelength calibration, but in a slightly different way. The etalon spectrum is not fixed to absolute wavelengths as the LFC and the Thorium and Uranium lamps are, but it has the advantage of being far more robust. The positions of the etalon lines can evolve slowly with time, but on short (<1 day) timescales they are stable. Thus the etalon calibration frames can be used to track the evolution of the instrument over daily timescales (anchored by the morning and afternoon wavelength cals). Thus it is valuable to have etalon observations taken periodically throughout the day and night. Broadband Flats KPF takes relatively standard spectral flats using a broadband lamp. Because of the extreme requirements for PRV measurements, the flats must be extraordinarily high signal to noise and be taken daily to track any changes. Biases and Darks KPF takes biases and darks like other instruments. We try to schedule these in to the lamp warmup time built in to other calibrations, so they end up being spread out throughout the day during other calibration OBs. Other Calibrations We currently also take two other calibrations: a set of biases for the Exposure Meter every day and a set of CRED2 guide camera biases a couple times per week. Overnight Etalon In addition to the calibrations taken during daytime, we have scheduled four long calibration sequences to happen overnight. The start times are chosen so that they should not be in progress when an observer might be starting use of the instrument (e.g. at a quarter night boundary). The scheduled cals will not begin during observations because the kpfStartOfNight script sets the kpfconfig.ALLOWSCHEDULEDCALS keyword to \u201cNo\u201d and the script to run the overnight calibrations respects that keyword. If for some reason, they are running when an observer needs to being observing, the cals can be stopped using the standard tools to halt a script in progress (e.g. the \u201cRequest Script Stop\u201d button in the OB GUI).","title":"Daytime Calibrations"},{"location":"calibrations/#calibrations","text":"KPF observers do not need to take afternoon cals because the calibration system is automatic (driven by cron jobs). This is important to PRV science as to get the best RVs, the instrument and its daily cycles need to be characterized, so we want to sample the calibrations in a systematic and repeatable way each day. The calibration schedule is a trade off between several factors. Because we want the calibrations to happen at a consistent time each day, we start the daily schedule based on the latest sunrise and the earliest sunset of the year. The calibrations can be broadly divided in to several categories described in the Types of Calibrations section below.","title":"Calibrations"},{"location":"calibrations/#the-daily-calibration-schedule","text":"Each day, the calibrations described below are executed. The needs of KPF are such that each day is filled as much as possible by calibrations. The diagram below shows what that schedule looks like over the course of a year as the sunrise and sunset times evolve with the seasons. This figure shows how the KPF calibration schedule interacts with the nighttime schedule over the course of a year (the 23A & B semesters in this case). The various lines show how daily events such as sunrise and sunset evolve in UT time. The lines are labeled on the left side of the plot. The shaded regions are the approximate duration of the scheduled calibrations. Even if no KPF observations are scheduled, the calibrations occupy 816 minutes (more than 13.5 hours) each day, or about 57% of the day. The gaps in this schedule are driven the desire to avoid having calibrations in progress when someone might be starting to operate the instrument: near sunset and at each of the quarter night boundaries.","title":"The Daily Calibration Schedule"},{"location":"calibrations/#types-of-calibrations","text":"","title":"Types of Calibrations"},{"location":"calibrations/#wavelength-calibrations","text":"Wavelength calibrations are the most critical daily calibration. Absolute wavelength calibrations use the laser frequency comb (LFC) or one of the hollow cathode lamps (ThAr or UNe). The etalon is also used for wavelength calibration, but in a slightly different way. The etalon spectrum is not fixed to absolute wavelengths as the LFC and the Thorium and Uranium lamps are, but it has the advantage of being far more robust. The positions of the etalon lines can evolve slowly with time, but on short (<1 day) timescales they are stable. Thus the etalon calibration frames can be used to track the evolution of the instrument over daily timescales (anchored by the morning and afternoon wavelength cals). Thus it is valuable to have etalon observations taken periodically throughout the day and night.","title":"Wavelength Calibrations"},{"location":"calibrations/#broadband-flats","text":"KPF takes relatively standard spectral flats using a broadband lamp. Because of the extreme requirements for PRV measurements, the flats must be extraordinarily high signal to noise and be taken daily to track any changes.","title":"Broadband Flats"},{"location":"calibrations/#biases-and-darks","text":"KPF takes biases and darks like other instruments. We try to schedule these in to the lamp warmup time built in to other calibrations, so they end up being spread out throughout the day during other calibration OBs.","title":"Biases and Darks"},{"location":"calibrations/#other-calibrations","text":"We currently also take two other calibrations: a set of biases for the Exposure Meter every day and a set of CRED2 guide camera biases a couple times per week.","title":"Other Calibrations"},{"location":"calibrations/#overnight-etalon","text":"In addition to the calibrations taken during daytime, we have scheduled four long calibration sequences to happen overnight. The start times are chosen so that they should not be in progress when an observer might be starting use of the instrument (e.g. at a quarter night boundary). The scheduled cals will not begin during observations because the kpfStartOfNight script sets the kpfconfig.ALLOWSCHEDULEDCALS keyword to \u201cNo\u201d and the script to run the overnight calibrations respects that keyword. If for some reason, they are running when an observer needs to being observing, the cals can be stopped using the standard tools to halt a script in progress (e.g. the \u201cRequest Script Stop\u201d button in the OB GUI).","title":"Overnight Etalon"},{"location":"computers/","text":"KPF Computers kpf (aka vm-kpf ) is a virtual machine at the summit. It runs the VNC sessions which observers use to interact with the instrument and runs most of the GUIs in those VNCs. kpfserver is the instrument host on which most of the critical dispatchers and keyword services run. kpffiuserver performs a similar function to kpfserver for the FIU and Ca H&K spectrometer in the (physically-separated) AO room. kpfbuild is the build host where files are installed and built. When ready they are deployed using a script to each of the run hosts ( kpfserver , kpffiuserver , and kpf ). kpfetalon is a machine in the basement which handles telemetry from the Etalon thermal controllers and sensors. tc-su-kpfetalon is a small windows machine connected to the NKT SuperK light source for the etalon. It is used when we need to run the NKT software to start up the light source. Data Storage Most KPF data is stored on /sdata1701 on kpfserver which other computers a WMKO cross-mount as /s/sdata1701 . Subdirectories within /sdata1701 are for the assigned account, e.g. kpfeng or kpf1 . Then there are date-coded directories, which correspond to the date of the start of the night (i.e. 2024jun21 is the night of June 21 Hawaii time, but data taken during the second half will be written there even though it is technically June 22 at the moment the data is taken). The date directories change at 2pm HST. An example data directory is /s/sdata1701/kpfeng/2023jul11 . Network KPF is controlled by computers and devices that are behind the WMKO firewall. Most KPF devices (e.g., vacuum controllers) are on a private network behind kpfserver, which has separate network cards for the WMKO network and the private KPF network.","title":"Computers"},{"location":"computers/#kpf-computers","text":"kpf (aka vm-kpf ) is a virtual machine at the summit. It runs the VNC sessions which observers use to interact with the instrument and runs most of the GUIs in those VNCs. kpfserver is the instrument host on which most of the critical dispatchers and keyword services run. kpffiuserver performs a similar function to kpfserver for the FIU and Ca H&K spectrometer in the (physically-separated) AO room. kpfbuild is the build host where files are installed and built. When ready they are deployed using a script to each of the run hosts ( kpfserver , kpffiuserver , and kpf ). kpfetalon is a machine in the basement which handles telemetry from the Etalon thermal controllers and sensors. tc-su-kpfetalon is a small windows machine connected to the NKT SuperK light source for the etalon. It is used when we need to run the NKT software to start up the light source.","title":"KPF Computers"},{"location":"computers/#data-storage","text":"Most KPF data is stored on /sdata1701 on kpfserver which other computers a WMKO cross-mount as /s/sdata1701 . Subdirectories within /sdata1701 are for the assigned account, e.g. kpfeng or kpf1 . Then there are date-coded directories, which correspond to the date of the start of the night (i.e. 2024jun21 is the night of June 21 Hawaii time, but data taken during the second half will be written there even though it is technically June 22 at the moment the data is taken). The date directories change at 2pm HST. An example data directory is /s/sdata1701/kpfeng/2023jul11 .","title":"Data Storage"},{"location":"computers/#network","text":"KPF is controlled by computers and devices that are behind the WMKO firewall. Most KPF devices (e.g., vacuum controllers) are on a private network behind kpfserver, which has separate network cards for the WMKO network and the private KPF network.","title":"Network"},{"location":"dataflow/","text":"Data Flow An idealized vision for the KPF data flow. This is still a work in progress. Raw Data Because KPF contains many detectors, but they are all synchronized in time, the raw data is immediately combined in to a \"Level 0\" (L0) multi-extension FITS file by the kpfassemble dispatcher. Most users will want to use that L0 data for analysis or inspection. Each detector writes data to a separate output directory and kpfassemble will collect them from these to generate the L0 file. This is a relatively quick process, typically the L0 file is written a few seconds after the component raw data are available on disk. As mentioned on the detectors page, the Green and Red detectors have 32 bit ADCs and thus the pixel data do not fall on the usual 0-65535 range you may be used to. L0 Data The L0 data is a multi extension FITS file consisting of the following HDUs: HDU # HDU Name Notes 0 PRIMARY Header only, no image data 1 GREEN_AMP1 Green image data 2 GREEN_AMP2 Green image data 3 RED_AMP1 Red image data 4 RED_AMP2 Red image data 5 CA_HK Ca H&K image data 6 EXPMETER_SCI Table of processed exposure meter spectra 7 EXPMETER_SKY Table of processed exposure meter spectra 8 GUIDER_AVG The average guider image over the duration of the exposure 9 GUIDER_CUBE_ORIGINS Table of telemetry from the tip tilt system 10 TELEMETRY Table of instrument telemetry This can change depending on the composition of the science observation. For example, if the Ca H&K detector was not triggered, that extension would not be used. A guide to examining the L0 data can be found on this page in the documentation for the KPF DRP. Keck Observatory Archive (KOA) The L0 data are immediately sent to KOA for archiving. Observers can \"subscribe\" to the L0 data via KOA's Real Time Ingestion (RTI) interface. Data Reduction The KPF Data Reduction Pipeline was built and delivered by the KPF Instrument Team and is an important part of obtaining the desired performance from the instrument. While Keck plan's to eventually run the DRP locally and provide quick look products (QLP), L1, and L2 data to observers as part of the KOA RTI interface, the KPF DRP is still under active development by the KPF science team, so the Keck deployment of the DRP is on hold until there are less frequent changes for us to track. As a result, data for programs which have partnered with CPS are available through their instance of the DRP which is run on the CPS Team's hardware. Observers who are not part of CPS should contact their Keck SA to arrange for access to reduced data products.","title":"Data Flow"},{"location":"dataflow/#data-flow","text":"An idealized vision for the KPF data flow. This is still a work in progress.","title":"Data Flow"},{"location":"dataflow/#raw-data","text":"Because KPF contains many detectors, but they are all synchronized in time, the raw data is immediately combined in to a \"Level 0\" (L0) multi-extension FITS file by the kpfassemble dispatcher. Most users will want to use that L0 data for analysis or inspection. Each detector writes data to a separate output directory and kpfassemble will collect them from these to generate the L0 file. This is a relatively quick process, typically the L0 file is written a few seconds after the component raw data are available on disk. As mentioned on the detectors page, the Green and Red detectors have 32 bit ADCs and thus the pixel data do not fall on the usual 0-65535 range you may be used to.","title":"Raw Data"},{"location":"dataflow/#l0-data","text":"The L0 data is a multi extension FITS file consisting of the following HDUs: HDU # HDU Name Notes 0 PRIMARY Header only, no image data 1 GREEN_AMP1 Green image data 2 GREEN_AMP2 Green image data 3 RED_AMP1 Red image data 4 RED_AMP2 Red image data 5 CA_HK Ca H&K image data 6 EXPMETER_SCI Table of processed exposure meter spectra 7 EXPMETER_SKY Table of processed exposure meter spectra 8 GUIDER_AVG The average guider image over the duration of the exposure 9 GUIDER_CUBE_ORIGINS Table of telemetry from the tip tilt system 10 TELEMETRY Table of instrument telemetry This can change depending on the composition of the science observation. For example, if the Ca H&K detector was not triggered, that extension would not be used. A guide to examining the L0 data can be found on this page in the documentation for the KPF DRP.","title":"L0 Data"},{"location":"dataflow/#keck-observatory-archive-koa","text":"The L0 data are immediately sent to KOA for archiving. Observers can \"subscribe\" to the L0 data via KOA's Real Time Ingestion (RTI) interface.","title":"Keck Observatory Archive (KOA)"},{"location":"dataflow/#data-reduction","text":"The KPF Data Reduction Pipeline was built and delivered by the KPF Instrument Team and is an important part of obtaining the desired performance from the instrument. While Keck plan's to eventually run the DRP locally and provide quick look products (QLP), L1, and L2 data to observers as part of the KOA RTI interface, the KPF DRP is still under active development by the KPF science team, so the Keck deployment of the DRP is on hold until there are less frequent changes for us to track. As a result, data for programs which have partnered with CPS are available through their instance of the DRP which is run on the CPS Team's hardware. Observers who are not part of CPS should contact their Keck SA to arrange for access to reduced data products.","title":"Data Reduction"},{"location":"detectors/","text":"Overview and Exposure Timing KPF utilizes 5 detectors during normal science operations. Two science detectors (green and red) sit on the main spectrograph bench in the facility basement and record the science spectrum which is used to calculate radial velocities. The Ca H&K Spectrograph is an independant optical system fed by a short fiber which runs from the FIU to a nearby echelle spectrograph which contains the third science detector. The exposure meter is another independent spectrograph which sits in the basement and contains the forth science detector. The fifth detector used during science operations is the CRED2 in the FIU and obtains fast frame rate images used to run the tip tilt system. Because precision radial velocity measurements require exquisite timing, the red and green detectors must have their exposures synced up. To do this, KPF uses a timed shutter on their common light path (before the dichroic splits the light). This is the \"Scrambler Timed Shutter\". As a result, the red and green cameras are not triggered independently. Instead the KPF software takes a single set of exposure parameters and triggers each camera to begin an exposure, then opens and closes timed shutters to ensure simultaneity where needed. In addition, the Scrambler Timed Shutter, also gates the light going to the exposure meter to ensure that its sensitivity to light is simultaneous to the red and green detectors. The Ca H&K spectrograph has its own, separate timed shutter as it is on a completely independent light path to the other detectors. Science Detector Specifications Parameter Green CCD Red CCD Ca H&K CCD Readout Time 47 s 47 s 1 s Read Noise AMP1: 4.0 e- AMP2: 4.9 e- AMP1: 4.1 e- AMP2: 4.2 e- Format 4080x4080 4080x4080 windowed to 1024x255 Gain ~5 e-/ADU ~5 e-/ADU 5.26 e-/ADU Data Format 32 bit 32 bit 16 bit Saturation ~2.1 x 10^9 ADU (~150 ke-) ~2.1 x 10^9 ADU (~150 ke-) 65,536 ADU (344 ke-) Note that the Green and Red science detectors have 32 bit readouts instead of the more common 16 bit (which the Ca H&K detector uses). This means that the values of the raw image pixels are not in the usual 0-65535 range for CCDs, but are instead much larger. To convert to the more usual range we are used to, divide by 2^16 (65536) to get ADU values in that range.","title":"Detectors"},{"location":"detectors/#overview-and-exposure-timing","text":"KPF utilizes 5 detectors during normal science operations. Two science detectors (green and red) sit on the main spectrograph bench in the facility basement and record the science spectrum which is used to calculate radial velocities. The Ca H&K Spectrograph is an independant optical system fed by a short fiber which runs from the FIU to a nearby echelle spectrograph which contains the third science detector. The exposure meter is another independent spectrograph which sits in the basement and contains the forth science detector. The fifth detector used during science operations is the CRED2 in the FIU and obtains fast frame rate images used to run the tip tilt system. Because precision radial velocity measurements require exquisite timing, the red and green detectors must have their exposures synced up. To do this, KPF uses a timed shutter on their common light path (before the dichroic splits the light). This is the \"Scrambler Timed Shutter\". As a result, the red and green cameras are not triggered independently. Instead the KPF software takes a single set of exposure parameters and triggers each camera to begin an exposure, then opens and closes timed shutters to ensure simultaneity where needed. In addition, the Scrambler Timed Shutter, also gates the light going to the exposure meter to ensure that its sensitivity to light is simultaneous to the red and green detectors. The Ca H&K spectrograph has its own, separate timed shutter as it is on a completely independent light path to the other detectors.","title":"Overview and Exposure Timing"},{"location":"detectors/#science-detector-specifications","text":"Parameter Green CCD Red CCD Ca H&K CCD Readout Time 47 s 47 s 1 s Read Noise AMP1: 4.0 e- AMP2: 4.9 e- AMP1: 4.1 e- AMP2: 4.2 e- Format 4080x4080 4080x4080 windowed to 1024x255 Gain ~5 e-/ADU ~5 e-/ADU 5.26 e-/ADU Data Format 32 bit 32 bit 16 bit Saturation ~2.1 x 10^9 ADU (~150 ke-) ~2.1 x 10^9 ADU (~150 ke-) 65,536 ADU (344 ke-) Note that the Green and Red science detectors have 32 bit readouts instead of the more common 16 bit (which the Ca H&K detector uses). This means that the values of the raw image pixels are not in the usual 0-65535 range for CCDs, but are instead much larger. To convert to the more usual range we are used to, divide by 2^16 (65536) to get ADU values in that range.","title":"Science Detector Specifications"},{"location":"expmetertermination/","text":"Exposure Meter Termination KPF contains an exposure meter which can measure the flux weighted midpoint of an exposure. This can also be used to terminate a science exposure once a desired signal level is reached. To do this the system will track the flux measured in the exposure meter spectra binned in to 4 passbands, each about 100nm wide, centered on 498.125nm, 604.375nm, 710.625nm, and 816.875nm respectively. To use exposure meter termination, the observer sets ExpMeterMode: control in the OB and then chooses one wavelength band to trigger on (using the ExpMeterBin OB value) and then chooses the target flux (in e-/nm via the ExpMeterThreshold OB value) in the resulting science spectrum that is desired. The system will convert the target value for the science spectrum in to a total ADU count for the exposure meter in that particular bandpass and when that threshold is surpassed, the exposure will stop. Regardless of whether that exposure meter threshold is passed, the exposure will stop when the nominal exposure time is reached. Thus when using exposure meter termination, the ExpTime parameter should be thought of as the maximum allowed exposure time. For example, an OB with the following values: ExpTime: 300 ExpMeterMode: control ExpMeterBin: 604.375 ExpMeterThreshold: 50000 will terminate when the exposure meter flux reaches a value which should result in approximately 50,000 e-/nm signal in the resulting science spectrum at about 604nm or when the total exposure time reaches 300 seconds, whichever comes first.","title":"Exposure Meter Termination"},{"location":"expmetertermination/#exposure-meter-termination","text":"KPF contains an exposure meter which can measure the flux weighted midpoint of an exposure. This can also be used to terminate a science exposure once a desired signal level is reached. To do this the system will track the flux measured in the exposure meter spectra binned in to 4 passbands, each about 100nm wide, centered on 498.125nm, 604.375nm, 710.625nm, and 816.875nm respectively. To use exposure meter termination, the observer sets ExpMeterMode: control in the OB and then chooses one wavelength band to trigger on (using the ExpMeterBin OB value) and then chooses the target flux (in e-/nm via the ExpMeterThreshold OB value) in the resulting science spectrum that is desired. The system will convert the target value for the science spectrum in to a total ADU count for the exposure meter in that particular bandpass and when that threshold is surpassed, the exposure will stop. Regardless of whether that exposure meter threshold is passed, the exposure will stop when the nominal exposure time is reached. Thus when using exposure meter termination, the ExpTime parameter should be thought of as the maximum allowed exposure time. For example, an OB with the following values: ExpTime: 300 ExpMeterMode: control ExpMeterBin: 604.375 ExpMeterThreshold: 50000 will terminate when the exposure meter flux reaches a value which should result in approximately 50,000 e-/nm signal in the resulting science spectrum at about 604nm or when the total exposure time reaches 300 seconds, whichever comes first.","title":"Exposure Meter Termination"},{"location":"exposuremeter/","text":"Exposure Meter An accurate measurement of the time of the flux-weighted midpoint of each exposure is essential to correct for the barycentric velocity of the Earth. During an exposure, a small fraction of the light within the spectrometer is diverted to a separate, low-resolution spectrometer that records the flux time series for all wavelengths across the main spectrometer bandpass. This system accurately tracks the photon arrival times in the parent spectrometer, allowing for precise determination of flux-weighted exposure mid-points as a function of wavelength. The optical design of the exposure meter is a prism-based spectrometer with a resolving power of approximately 100. The exposure meter accepts light from two fibers; one collecting light from the otherwise unused outboard slices of the science fiber at the spectrometer reformatter entrance, and a sky fiber from the fiber injection unit on the telescope. The optical design is shown in the following figure. Optical design of the KPF Exposure Meter","title":"Exposure Meter"},{"location":"exposuremeter/#exposure-meter","text":"An accurate measurement of the time of the flux-weighted midpoint of each exposure is essential to correct for the barycentric velocity of the Earth. During an exposure, a small fraction of the light within the spectrometer is diverted to a separate, low-resolution spectrometer that records the flux time series for all wavelengths across the main spectrometer bandpass. This system accurately tracks the photon arrival times in the parent spectrometer, allowing for precise determination of flux-weighted exposure mid-points as a function of wavelength. The optical design of the exposure meter is a prism-based spectrometer with a resolving power of approximately 100. The exposure meter accepts light from two fibers; one collecting light from the otherwise unused outboard slices of the science fiber at the spectrometer reformatter entrance, and a sky fiber from the fiber injection unit on the telescope. The optical design is shown in the following figure. Optical design of the KPF Exposure Meter","title":"Exposure Meter"},{"location":"fastreadmode/","text":"Fast Read Mode The Green and Red science detectors can operate in a fast readout mode. This reduces the readout time to 16 seconds (and significantly increases the read noise), however changing the readout modes induces a temperature change at the detectors which can impact PRV measurements. As a result, fast read mode observations should be limited to those instances where it is critical to the science (e.g. seismology or other high cadence observations of a single target) and which are scheduled such that the mode change will not have overly negative impact on other science that night. Fast read mode is not appropriate for long term cadenced RV measurements as the two read modes have different systematic offsets and so RV measurements of the same target taken in different modes can not be easily combined. If you are interested in utilizing fast read mode, please contact kpf_info well ahead of your run. Fast read mode may not be available in all cases due to the impact on other scheduled observations. If it is available for your run, the Keck SA will schedule when the mode is changed and when fast read mode calibrations (primarily biases) can be taken. Our goal will be to minimize the number of changes of the read mode. After a mode change in either direction, the system needs time to stabilize before precision RVs are possible. We have estimated this stabilization time to be about 20 minutes. Because KPF is expected to operate in normal read mode and be available for precision RVs and fast read mode is the aberration, when this 20 minute wait time is needed during the night (i.e. the mode change does not happen well before or after the observing window), then all instances of this 20 minute window should be considered part of the fast read mode program. As a result, if the read mode is normal for observations at the beginning the night, then is switched to fast, then back to normal for observations at the end of the night. Both 20 minute wait times (40 minutes total) are overhead which are considered part of the fast read mode program. Details The KPF main spectrometer CCDs can be operated in two read modes: normal and fast. The main difference is the time to read the CCDs, which is 47 sec in normal-read mode and 16 sec in fast-read mode. In general, KPF observations should be taken in normal-read mode unless there is a highly compelling reason to operate in fast-read mode. The fast-read mode is only offered for KPF observations where the speed will aid in resolving fast astrophysical phenomena (e.g., seismology) or for cases where short exposure times are required to avoid saturation and the efficiency is significantly improved by also reading the CCDs quickly (e.g., observing a very bright star during a planetary transit). This applies to sequences of exposures ranging from 1 hour to 1 night in duration. The fast-read mode should not be used to improve the efficiency of individual exposure or short sequences of exposures, which comprise the vast majority of KPF observations. The motivation for this strategy is that changing between the two modes imparts a ~10 mK temperature transient to the CCDs, which shift and stretch at the nanometer level in response. These perturbations violate the operating requirements of maintaining 1 mK rms temperature stability of the CCDs and lead to systematic errors in Doppler measurements on short timescales (< 20-30 min). On longer timescales, the CCDs appear to relax back to their original state, but this has not been measured at the sub-30 cm/s level. Out of conservatism, KPF is toggled between read modes as infrequently as possible. Automated daily calibration sequences are taken in the normal-read mode and are used in the KPF Data Reduction Pipeline (DRP) to process spectra taken with both read modes. Radial velocities measured from KPF spectra in the two modes are offset; users cannot combine RVs from the two modes in a time series. On the other hand, RVs measured from spectra taken in the fast-read mode during a single night (which are processed with a common set of calibrations) have high Doppler stability over that night-long timescale; this is the main use case for the fast-read mode. Some additional tradeoffs to consider are the increased read noise and the charge transfer inefficiency (CTI) in fast-read mode. As listed in the table below, the read noise (measured in rms noise per CCD pixel) is 1.5-2X higher in fast-read mode. This limits the utility of this mode for faint sources, which have higher Poisson noise per CCD pixel in the source spectrum. In fast-read mode, the CCDs are read out using four amplifiers at a higher clock speed (instead of two amplifiers at a slower speed). This strategy brings one amplifier on the Green CCD into play that has ~100x higher CTI than the others. CTI smears the spectrum along the direction of the CCD rows (leaving a trail of charge along pixels as they are clocked). As a result, stellar lines in the affected quadrant are smeared in the dispersion direction. The intensity of the effect depends on the number of electrons in each pixel (i.e., the SNR of the spectrum), making this effect very difficult to calibrate for precise RV measurements. When computing RVs for fast-read mode spectra, the KPF DRP ignores portions of the spectrum in the affected quadrant. This increases the RV uncertainties in the fast-read mode and adds an additional RV zero-point offset between measurements in the two modes. Fast spectroscopy to measure changes in line intensity (not line shape or center) can still be accomplished using spectra from the affected quadrant. Parameter Normal Read Mode Fast Read Mode Readout Time 47 s 16 s Read Noise Green: 4.0, 4.9 e- Red: 4.1, 4.2 e- Green: 8.2, 9.7, 8.6, 6.9 e- Red: 6.0, 5.8, 8.2, 6.6 e- Charge Transfer One green amp has ~100x higher CTI Use Cases Most KPF observations, including cadence RPV measurements and general spectroscopy Sequences of short exposures whose duration is 1 hour to 1 night.","title":"Fast Read Mode"},{"location":"fastreadmode/#fast-read-mode","text":"The Green and Red science detectors can operate in a fast readout mode. This reduces the readout time to 16 seconds (and significantly increases the read noise), however changing the readout modes induces a temperature change at the detectors which can impact PRV measurements. As a result, fast read mode observations should be limited to those instances where it is critical to the science (e.g. seismology or other high cadence observations of a single target) and which are scheduled such that the mode change will not have overly negative impact on other science that night. Fast read mode is not appropriate for long term cadenced RV measurements as the two read modes have different systematic offsets and so RV measurements of the same target taken in different modes can not be easily combined. If you are interested in utilizing fast read mode, please contact kpf_info well ahead of your run. Fast read mode may not be available in all cases due to the impact on other scheduled observations. If it is available for your run, the Keck SA will schedule when the mode is changed and when fast read mode calibrations (primarily biases) can be taken. Our goal will be to minimize the number of changes of the read mode. After a mode change in either direction, the system needs time to stabilize before precision RVs are possible. We have estimated this stabilization time to be about 20 minutes. Because KPF is expected to operate in normal read mode and be available for precision RVs and fast read mode is the aberration, when this 20 minute wait time is needed during the night (i.e. the mode change does not happen well before or after the observing window), then all instances of this 20 minute window should be considered part of the fast read mode program. As a result, if the read mode is normal for observations at the beginning the night, then is switched to fast, then back to normal for observations at the end of the night. Both 20 minute wait times (40 minutes total) are overhead which are considered part of the fast read mode program.","title":"Fast Read Mode"},{"location":"fastreadmode/#details","text":"The KPF main spectrometer CCDs can be operated in two read modes: normal and fast. The main difference is the time to read the CCDs, which is 47 sec in normal-read mode and 16 sec in fast-read mode. In general, KPF observations should be taken in normal-read mode unless there is a highly compelling reason to operate in fast-read mode. The fast-read mode is only offered for KPF observations where the speed will aid in resolving fast astrophysical phenomena (e.g., seismology) or for cases where short exposure times are required to avoid saturation and the efficiency is significantly improved by also reading the CCDs quickly (e.g., observing a very bright star during a planetary transit). This applies to sequences of exposures ranging from 1 hour to 1 night in duration. The fast-read mode should not be used to improve the efficiency of individual exposure or short sequences of exposures, which comprise the vast majority of KPF observations. The motivation for this strategy is that changing between the two modes imparts a ~10 mK temperature transient to the CCDs, which shift and stretch at the nanometer level in response. These perturbations violate the operating requirements of maintaining 1 mK rms temperature stability of the CCDs and lead to systematic errors in Doppler measurements on short timescales (< 20-30 min). On longer timescales, the CCDs appear to relax back to their original state, but this has not been measured at the sub-30 cm/s level. Out of conservatism, KPF is toggled between read modes as infrequently as possible. Automated daily calibration sequences are taken in the normal-read mode and are used in the KPF Data Reduction Pipeline (DRP) to process spectra taken with both read modes. Radial velocities measured from KPF spectra in the two modes are offset; users cannot combine RVs from the two modes in a time series. On the other hand, RVs measured from spectra taken in the fast-read mode during a single night (which are processed with a common set of calibrations) have high Doppler stability over that night-long timescale; this is the main use case for the fast-read mode. Some additional tradeoffs to consider are the increased read noise and the charge transfer inefficiency (CTI) in fast-read mode. As listed in the table below, the read noise (measured in rms noise per CCD pixel) is 1.5-2X higher in fast-read mode. This limits the utility of this mode for faint sources, which have higher Poisson noise per CCD pixel in the source spectrum. In fast-read mode, the CCDs are read out using four amplifiers at a higher clock speed (instead of two amplifiers at a slower speed). This strategy brings one amplifier on the Green CCD into play that has ~100x higher CTI than the others. CTI smears the spectrum along the direction of the CCD rows (leaving a trail of charge along pixels as they are clocked). As a result, stellar lines in the affected quadrant are smeared in the dispersion direction. The intensity of the effect depends on the number of electrons in each pixel (i.e., the SNR of the spectrum), making this effect very difficult to calibrate for precise RV measurements. When computing RVs for fast-read mode spectra, the KPF DRP ignores portions of the spectrum in the affected quadrant. This increases the RV uncertainties in the fast-read mode and adds an additional RV zero-point offset between measurements in the two modes. Fast spectroscopy to measure changes in line intensity (not line shape or center) can still be accomplished using spectra from the affected quadrant. Parameter Normal Read Mode Fast Read Mode Readout Time 47 s 16 s Read Noise Green: 4.0, 4.9 e- Red: 4.1, 4.2 e- Green: 8.2, 9.7, 8.6, 6.9 e- Red: 6.0, 5.8, 8.2, 6.6 e- Charge Transfer One green amp has ~100x higher CTI Use Cases Most KPF observations, including cadence RPV measurements and general spectroscopy Sequences of short exposures whose duration is 1 hour to 1 night.","title":"Details"},{"location":"fiu/","text":"Fiber Injection Unit (FIU) The Fiber Injection Unit (FIU) sits on the Keck I AO bench ahead of AO correction. The unit's primary role is to feed telescope light to the science, sky, and Ca H&K fibers. The unit utilizes a pair of dichroics to send light to the relevant subsystems: Wavelength Range Subsystem Notes 382-402 nm Ca H&K Spectrograph Includes two fibers (science and sky) 445-870 nm Science Spectrograph Includes two fibers (science and sky) 950-1200 nm Guide Camera Used for acquisition and fast tip tilt correction The FIU can also be configured in a mode which takes light from the calibration bench in the basement and injects it in to the science and sky fibers. Atmospheric Dispersion Correctors In addition, the FIU contains atmospheric dispersion correction (ADC) systems for both the science and Ca H&K wavelengths. Science ADC For the science arm, a pair of prisms are rotated to provide dispersion correction based on the telescope position. The ADCs are designed to keep all the science wavelengths within 50 mas. The ADC corrects atmospheric dispersion at that full 50 mas specification down to an elevation of 30 degrees. The prisms reach their maximum correction power at an elevation of 25 degrees, beyond that, their correction power is fixed and no longer increases as the elevation decreases. Ca H&K ADC For the Ca H&K arm, the fiber is on a two axis stage and is translated in such as way as to place the fiber under the correct wavelengths of light. The total wavelength range in this arm is small enough that only the differential position between this arm and the science and guide arms is corrected, there is no correction of the dispersion over the narrow wavelength range of the Ca H&K arm. FIU Layout The FIU layout when in science mode. Light from the telescope is directed to the FIU off of a tip tilt mirror located on the PCU stage. The FIU layout when in calibration mode. The calibration fibers are illuminated and a fold mirror is moved in to place to direct their light on to the science fiber. Fiber Viewing Cameras Both the science arm and the Ca H&K arm have fiber viewing cameras (FVCs) for imaging the fiber tip. These are only useful in an engineering context as it takes a very bright (roughly 1st magnitude) star to be visible because the FVCs are looking through the dichroics (and the ADC prisms in the science arm). This drastically reduced the amount of light to the FVCs and makes the images hard to interpret due to reflections and ghost images.","title":"FIU"},{"location":"fiu/#fiber-injection-unit-fiu","text":"The Fiber Injection Unit (FIU) sits on the Keck I AO bench ahead of AO correction. The unit's primary role is to feed telescope light to the science, sky, and Ca H&K fibers. The unit utilizes a pair of dichroics to send light to the relevant subsystems: Wavelength Range Subsystem Notes 382-402 nm Ca H&K Spectrograph Includes two fibers (science and sky) 445-870 nm Science Spectrograph Includes two fibers (science and sky) 950-1200 nm Guide Camera Used for acquisition and fast tip tilt correction The FIU can also be configured in a mode which takes light from the calibration bench in the basement and injects it in to the science and sky fibers.","title":"Fiber Injection Unit (FIU)"},{"location":"fiu/#atmospheric-dispersion-correctors","text":"In addition, the FIU contains atmospheric dispersion correction (ADC) systems for both the science and Ca H&K wavelengths.","title":"Atmospheric Dispersion Correctors"},{"location":"fiu/#science-adc","text":"For the science arm, a pair of prisms are rotated to provide dispersion correction based on the telescope position. The ADCs are designed to keep all the science wavelengths within 50 mas. The ADC corrects atmospheric dispersion at that full 50 mas specification down to an elevation of 30 degrees. The prisms reach their maximum correction power at an elevation of 25 degrees, beyond that, their correction power is fixed and no longer increases as the elevation decreases.","title":"Science ADC"},{"location":"fiu/#ca-hk-adc","text":"For the Ca H&K arm, the fiber is on a two axis stage and is translated in such as way as to place the fiber under the correct wavelengths of light. The total wavelength range in this arm is small enough that only the differential position between this arm and the science and guide arms is corrected, there is no correction of the dispersion over the narrow wavelength range of the Ca H&K arm.","title":"Ca H&K ADC"},{"location":"fiu/#fiu-layout","text":"The FIU layout when in science mode. Light from the telescope is directed to the FIU off of a tip tilt mirror located on the PCU stage. The FIU layout when in calibration mode. The calibration fibers are illuminated and a fold mirror is moved in to place to direct their light on to the science fiber.","title":"FIU Layout"},{"location":"fiu/#fiber-viewing-cameras","text":"Both the science arm and the Ca H&K arm have fiber viewing cameras (FVCs) for imaging the fiber tip. These are only useful in an engineering context as it takes a very bright (roughly 1st magnitude) star to be visible because the FVCs are looking through the dichroics (and the ADC prisms in the science arm). This drastically reduced the amount of light to the FVCs and makes the images hard to interpret due to reflections and ghost images.","title":"Fiber Viewing Cameras"},{"location":"guider/","text":"Guider The KPF guide camera views the science field, but behind a long pass dichroic which sends light blueward of about 950nm to the science and Ca H&K fibers. As a result, the guide camera was chosen to be a \"short wave IR\" camera utilizing an InGaS detector. Camera Model First Light CRED2 Pixel Scale 0.056 arcsec/pix Field of View 35 x 28 arcseconds Frame Rate up to 400 Hz (100 Hz recommended) Passband 950-1200 nm (0.95-1.2 microns) Gain Settings high, medium, low Note that while the camera can operate at 400 Hz, the practical limit for operations is around 100-150 Hz due to tip tilt system limitations. Rather than using traditional telescope guiding, the guide camera takes images at high frame rates and sends corrections to a fast tip tilt mirror situated just outside the FIU. We recommend running the system at 100 Hz for optimum performance. The system will offload corrections from the tip tilt mirror to the telescope drive system periodically as needed to keep the tip tilt mirror within its optimum range of travel. The OAs use a separate GUI for controlling the KPF tip tilt system (not the usual Magiq interface used on other instruments). The OAs can run Magiq in \"centroid only\" mode which will provide FWHM and flux feedback to the observer in the normal Magiq display.","title":"Guider"},{"location":"guider/#guider","text":"The KPF guide camera views the science field, but behind a long pass dichroic which sends light blueward of about 950nm to the science and Ca H&K fibers. As a result, the guide camera was chosen to be a \"short wave IR\" camera utilizing an InGaS detector. Camera Model First Light CRED2 Pixel Scale 0.056 arcsec/pix Field of View 35 x 28 arcseconds Frame Rate up to 400 Hz (100 Hz recommended) Passband 950-1200 nm (0.95-1.2 microns) Gain Settings high, medium, low Note that while the camera can operate at 400 Hz, the practical limit for operations is around 100-150 Hz due to tip tilt system limitations. Rather than using traditional telescope guiding, the guide camera takes images at high frame rates and sends corrections to a fast tip tilt mirror situated just outside the FIU. We recommend running the system at 100 Hz for optimum performance. The system will offload corrections from the tip tilt mirror to the telescope drive system periodically as needed to keep the tip tilt mirror within its optimum range of travel. The OAs use a separate GUI for controlling the KPF tip tilt system (not the usual Magiq interface used on other instruments). The OAs can run Magiq in \"centroid only\" mode which will provide FWHM and flux feedback to the observer in the normal Magiq display.","title":"Guider"},{"location":"kpfdrp/","text":"Data Reduction Pipeline WMKO automatically delivers KPF L0 data products to the Keck Observatory Archive (KOA) for distribution to observers. We plan to distribute L1 and L2 data products as well, but the KPF DRP is still under active development by the KPF science team, so the Keck deployment of the DRP is on hold until there are less frequent changes for us to track. Observers not affiliated with the KPF build team or with the California Planet Search (CPS) should contact their Staff Astronomer about access to reduced data products. Advanced users who would like to run the DRP locally can find the KPF DRP on GitHub and the documentation can be found on ReadTheDocs . Level Definitions Level Description L0 Raw spectra packaged with other instrument data (see Data Format for details) L1 1-d, wavelength calibrated spectra L2 RVs, multiple activity indicators","title":"Data Reduction"},{"location":"kpfdrp/#data-reduction-pipeline","text":"WMKO automatically delivers KPF L0 data products to the Keck Observatory Archive (KOA) for distribution to observers. We plan to distribute L1 and L2 data products as well, but the KPF DRP is still under active development by the KPF science team, so the Keck deployment of the DRP is on hold until there are less frequent changes for us to track. Observers not affiliated with the KPF build team or with the California Planet Search (CPS) should contact their Staff Astronomer about access to reduced data products. Advanced users who would like to run the DRP locally can find the KPF DRP on GitHub and the documentation can be found on ReadTheDocs .","title":"Data Reduction Pipeline"},{"location":"kpfdrp/#level-definitions","text":"Level Description L0 Raw spectra packaged with other instrument data (see Data Format for details) L1 1-d, wavelength calibrated spectra L2 RVs, multiple activity indicators","title":"Level Definitions"},{"location":"nighttimecalibrations/","text":"Nighttime Calibrations To monitor the instrumental drift, KPF needs calibrations taken throughout the night. There are two different calibrations that can be taken and each has advantages and disadvantages. As we fully characterize the instrument and as the DRP evolves, our recommendations for how best to run nighttime calibrations may change, so check back here for updates. Recommended Strategy The current recommendation is to take a slew cal roughly every hour or so. There is a \"Time Since Cal\" readout in the upper right of the OB GUI. When the time since the last calibration exceeds 1 hour, the readout will turn orange. At 2 hours, it will turn red. This is only a recommendation, so the decision of when to take a slew cal is up to the observer. See also the Observing Procedures page. What is a Slew Cal? Slew cals are a particular calibration (a single Etalon calibration exposure) which is intended to be taken during a long telescope slew. The best way to execute this is to click the \"Execute OB with Slew Cal\" button after loading the next desired OB and asking the OA to begin slewing to the target. You should let the OA know you are running a slew cal as this will close the FIU hatch and direct Etalon light through the FIU which means that they will no longer see the sky on the guider during the calibration (which takes about 2 minutes). Directing the calibration light through the FIU means that we will be illuminating the science, sky, and simulcal fibers (all 5 traces) with calibration light. Because the slew cal happens during the slew to a target, it is optimally performed with a science OB so that the guider can be configured for the science target. This is another case where executing a science OB before the slew has completed is the most efficient observing strategy. What are Simultaneous Calibrations (SimulCals)? Simultaneous Calibration (simulcal) is when the calibration trace (one of the 5 traces on the main science detectors) is illuminated with calibration light (usually the etalon). This can be done during science observations, but there are a number of caveats and potential pitfalls. The main concern when using simulcals is to get the appropriate calibration flux. Because the science exposure time changes depending on the target, the brightness of the light injected in to the simulcal fiber must be modulated to find an appropriate flux. This is accomplished with two filter wheels in the calibration bench which have neutral density (ND) filters. Too little simulcal flux is problematic because it makes the calibration less useful, but too much simulcal flux is worse. Even tiny amounts of scattered light or the far wings of an overly bright simulcal PSF can impact the science traces and bias the RV measurements. Because of this, we have built an automatic system for choosing the ND filters appropriate for the observation. This is a complex system because it must account for the color of the star as well as the brightness.","title":"Nighttime Calibrations"},{"location":"nighttimecalibrations/#nighttime-calibrations","text":"To monitor the instrumental drift, KPF needs calibrations taken throughout the night. There are two different calibrations that can be taken and each has advantages and disadvantages. As we fully characterize the instrument and as the DRP evolves, our recommendations for how best to run nighttime calibrations may change, so check back here for updates.","title":"Nighttime Calibrations"},{"location":"nighttimecalibrations/#recommended-strategy","text":"The current recommendation is to take a slew cal roughly every hour or so. There is a \"Time Since Cal\" readout in the upper right of the OB GUI. When the time since the last calibration exceeds 1 hour, the readout will turn orange. At 2 hours, it will turn red. This is only a recommendation, so the decision of when to take a slew cal is up to the observer. See also the Observing Procedures page.","title":"Recommended Strategy"},{"location":"nighttimecalibrations/#what-is-a-slew-cal","text":"Slew cals are a particular calibration (a single Etalon calibration exposure) which is intended to be taken during a long telescope slew. The best way to execute this is to click the \"Execute OB with Slew Cal\" button after loading the next desired OB and asking the OA to begin slewing to the target. You should let the OA know you are running a slew cal as this will close the FIU hatch and direct Etalon light through the FIU which means that they will no longer see the sky on the guider during the calibration (which takes about 2 minutes). Directing the calibration light through the FIU means that we will be illuminating the science, sky, and simulcal fibers (all 5 traces) with calibration light. Because the slew cal happens during the slew to a target, it is optimally performed with a science OB so that the guider can be configured for the science target. This is another case where executing a science OB before the slew has completed is the most efficient observing strategy.","title":"What is a Slew Cal?"},{"location":"nighttimecalibrations/#what-are-simultaneous-calibrations-simulcals","text":"Simultaneous Calibration (simulcal) is when the calibration trace (one of the 5 traces on the main science detectors) is illuminated with calibration light (usually the etalon). This can be done during science observations, but there are a number of caveats and potential pitfalls. The main concern when using simulcals is to get the appropriate calibration flux. Because the science exposure time changes depending on the target, the brightness of the light injected in to the simulcal fiber must be modulated to find an appropriate flux. This is accomplished with two filter wheels in the calibration bench which have neutral density (ND) filters. Too little simulcal flux is problematic because it makes the calibration less useful, but too much simulcal flux is worse. Even tiny amounts of scattered light or the far wings of an overly bright simulcal PSF can impact the science traces and bias the RV measurements. Because of this, we have built an automatic system for choosing the ND filters appropriate for the observation. This is a complex system because it must account for the color of the star as well as the brightness.","title":"What are Simultaneous Calibrations (SimulCals)?"},{"location":"observingprocedures/","text":"Quick Reference Beginning of the Night Performing Observations Switching Programs on a Split Night Bad Weather Beginning of the Night Wait for Dome to Open The Observing Assistant (OA) is not permitted to open the dome until after sunset. Please be patient while the shutter opens and the OA checks the initial telescope pointing. Run Start of Night KPF needs to be configured properly at the start of the night. There is a procedure which should be run only after the Observing Assistant (OA) has selected KPF as the instrument and after automated afternoon calibrations are complete. The selected instrument (\"INST\") can be seen in the lower left corner of the FACSUM window . It is important that this not be run while other instruments are observing. To configure KPF for observing, run KPF Control Menu --> Run Start of Night Script from the background menu (or kpfStartOfNight from the command line on any KPF machine). This will: Disable automated calibrations Configure the FIU to the observing mode Open the science and sky source select shutters Configure the AO Bench. Including positioning the PCU stage and opening the AO hatch. Configure DCS for KPF by setting dcs.ROTDEST=0 and dcs.ROTMODE=stationary Configure the tip tilt loop gain to its default setting Set data output directory Set observers from telescope schedule Slew to the Vicinity of Your First Target When ready to move the telescope, the OA will ask you for your first target and load the coordinates from your starlist file. They will select a bright star near your target and will attempt to acquire that in the guider, then will double-check the accuracy of pointing by acquiring one or two additional stars from the SAO or GSC catalogs. To monitor the guider images, run Telescope GUIs --> MAGIQ Guider UI from the background menu. Focus the Telescope The OA will run the telescope focus procedure (typically Autofoc) near your science field. On some nights, they will opt for the Mira focus procedure which takes slightly longer but is needed to calibrate the secondary mirror tilt. Performing Observations Highlight Your Target in Magiq In the Magiq star list (at the bottom of the Magiq User GUI), right click your target and select the option to highlight it for the OA (you can get the same result by middle clicking the target). This highlighting will show up on the OA's GUI making it easier for them to find the target you want to go to. Let the OA know to slew to the target when your current exposure is done. Execute Your OB Observers can load previously saved OBs or create them on the fly for KPF observing. To load and execute a saved OB: Click Load OB from File Select the OB from the file list Click Execute This OB (or Execute OB with Slew Cal) The GUI will first prompt the observers to confirm the OB execution. Once confirmed, an xterm will launch and prompt the observers with addtional information if and when needed, so watch the contents of this xterm. Executing the OB will not start an exposure immediately. The system will first configure the instrument and will then prompt the observer to confirm once the OA has acquired the target. While configuring the instrument, the OB will provide information on how to set the gain and frames per second on the guider. Because of this, it is important to execute the OB during the slew and before the OA acquires the target, so they have the right exposure parameters to see the target on the guider. The log lines which show up in the xterm with the running OB contain useful information. In general, lines with INFO are attempting to explain what the instrument is doing. Lines with WARNING are indicating that a minor problem has occurred, but the system is handling it -- these lines are purely informational, no action is needed on the part of the observer in response. Lines with ERROR indicate a serious problems which may require user intervention. Slew Cals KPF has the option of taking a \"slew cal\" immediately prior to a science observation. This is a way to make use of the time spent slewing from one target to another. If an OB is executed with a slew cal (using the \"Execute OB with Slew Cal\" button in the OB GUI), then the FIU will transition to calibration mode (the FIU hatch will close and calibration light will be directed to the science and sky fibers), and a calibration exposure will be taken. This will obscure the sky during calibration, so the OA will not be able to see the target until the slew cal is done. This process takes around 2 minutes and so fits nicely in to long slews. An alternative to a slew cal is a simultaneous calibration (simulcal). To use this enable the TakeSimulCal option in the OB or on the OB GUI and either manually set the ND filters to apply to the calibration light or enable the AutoNDFilters option. See the nighttime calibrations page for more info on both the slew cal and simulcal options. Stopping Scripts or Exposures Important : If you wish to halt an OB during execution, do NOT hit Control-c in the terminal. Use the \"Request Script STOP\" button instead. The KPF scripts have checkpoints in them which are places where the script can cleanly exit and perform important cleanup operations. The \"STOP Exposure and Script\" button does the same thing, but it will also terminate an exposure in progress. Known Issues There is a known failure mode for KPF called a \"start state error\". What happens is some sort of communication failure between the kpfexpose control software, the galil hardware which handles the timing and signaling of the detectors and shutters, and the Archon detector controllers. The result is that one of the green or red detectors does not begin the exposure properly and that detector's data will be useless. The kpf.spectrograph.StartExposure script will automatically detect this situation, terminate the bad exposure after a few seconds, and start a new one all without user intervention. This will generate several WARNING level log messages, but the user does not need to take action as the correction happens automatically. Another known failure mode which can generate WARNING level log messages is a failure of the FIU to transition in to a new mode (i.e. \"Observing\" or \"Calibration\"). The kpf.fiu.ConfigureFIU and kpf.fiu.WaitForConfigureFIU scripts will automatically retry several times before giving up and erroring out. As with the start state error above, no user action is needed, but you will see WARNING level log messages to let you know what is happening. Switching Programs on a Split Night On a KPF/KPF split night, before starting the second KPF program, run KPF Control Menu --> Set Program ID and Observers from the background menu (or kpfSetObserverFromSchedule from the command line on any KPF machine). Enter the program ID at the terminal prompt. The script will then set program ID and observers for the second KPF program, based on the telescope schedule. If you wish to set the observer names and program ID manually (i.e. without querying the telescope schedule), you can use the kpfSetProgram and kpfSetObserver scripts from the command line. For example: kpfSetProgram K123 will set program ID \"K123\" and kpfSetObserver \"E.E. Barnard, S.W. Burnham\" will set the observer name to \"E.E. Barnard, S.W. Burnham\". Note that observer names should be enclosed in quotes to handle spaces in the list of names. Bad Weather If the weather is so bad that no observing is taking place and there doesn't seem to be an immediate likelihood of observing, then we recommend that the observer runs the end of night procedure ( KPF Control Menu --> Run End of Night Script ). The main advantage of this is that running End of Night will re-enable the automatic scheduled calibrations which happen 4 times per night when KPF is not on sky. This means that the instrumental drift will be tracked with no action required by the observer (i.e. running slew cals). If one of these calibration scripts is in progress and observing should resume, use the \"Request Script STOP\" as described above. After that, run the Start of Night script just as you would at the beginning of the night (among other things it disables the autmatic scheduled calibrations).","title":"Observing Procedures"},{"location":"observingprocedures/#quick-reference","text":"Beginning of the Night Performing Observations Switching Programs on a Split Night Bad Weather","title":"Quick Reference"},{"location":"observingprocedures/#beginning-of-the-night","text":"","title":"Beginning of the Night"},{"location":"observingprocedures/#wait-for-dome-to-open","text":"The Observing Assistant (OA) is not permitted to open the dome until after sunset. Please be patient while the shutter opens and the OA checks the initial telescope pointing.","title":"Wait for Dome to Open"},{"location":"observingprocedures/#run-start-of-night","text":"KPF needs to be configured properly at the start of the night. There is a procedure which should be run only after the Observing Assistant (OA) has selected KPF as the instrument and after automated afternoon calibrations are complete. The selected instrument (\"INST\") can be seen in the lower left corner of the FACSUM window . It is important that this not be run while other instruments are observing. To configure KPF for observing, run KPF Control Menu --> Run Start of Night Script from the background menu (or kpfStartOfNight from the command line on any KPF machine). This will: Disable automated calibrations Configure the FIU to the observing mode Open the science and sky source select shutters Configure the AO Bench. Including positioning the PCU stage and opening the AO hatch. Configure DCS for KPF by setting dcs.ROTDEST=0 and dcs.ROTMODE=stationary Configure the tip tilt loop gain to its default setting Set data output directory Set observers from telescope schedule","title":"Run Start of Night"},{"location":"observingprocedures/#slew-to-the-vicinity-of-your-first-target","text":"When ready to move the telescope, the OA will ask you for your first target and load the coordinates from your starlist file. They will select a bright star near your target and will attempt to acquire that in the guider, then will double-check the accuracy of pointing by acquiring one or two additional stars from the SAO or GSC catalogs. To monitor the guider images, run Telescope GUIs --> MAGIQ Guider UI from the background menu.","title":"Slew to the Vicinity of Your First Target"},{"location":"observingprocedures/#focus-the-telescope","text":"The OA will run the telescope focus procedure (typically Autofoc) near your science field. On some nights, they will opt for the Mira focus procedure which takes slightly longer but is needed to calibrate the secondary mirror tilt.","title":"Focus the Telescope"},{"location":"observingprocedures/#performing-observations","text":"","title":"Performing Observations"},{"location":"observingprocedures/#highlight-your-target-in-magiq","text":"In the Magiq star list (at the bottom of the Magiq User GUI), right click your target and select the option to highlight it for the OA (you can get the same result by middle clicking the target). This highlighting will show up on the OA's GUI making it easier for them to find the target you want to go to. Let the OA know to slew to the target when your current exposure is done.","title":"Highlight Your Target in Magiq"},{"location":"observingprocedures/#execute-your-ob","text":"Observers can load previously saved OBs or create them on the fly for KPF observing. To load and execute a saved OB: Click Load OB from File Select the OB from the file list Click Execute This OB (or Execute OB with Slew Cal) The GUI will first prompt the observers to confirm the OB execution. Once confirmed, an xterm will launch and prompt the observers with addtional information if and when needed, so watch the contents of this xterm. Executing the OB will not start an exposure immediately. The system will first configure the instrument and will then prompt the observer to confirm once the OA has acquired the target. While configuring the instrument, the OB will provide information on how to set the gain and frames per second on the guider. Because of this, it is important to execute the OB during the slew and before the OA acquires the target, so they have the right exposure parameters to see the target on the guider. The log lines which show up in the xterm with the running OB contain useful information. In general, lines with INFO are attempting to explain what the instrument is doing. Lines with WARNING are indicating that a minor problem has occurred, but the system is handling it -- these lines are purely informational, no action is needed on the part of the observer in response. Lines with ERROR indicate a serious problems which may require user intervention.","title":"Execute Your OB"},{"location":"observingprocedures/#slew-cals","text":"KPF has the option of taking a \"slew cal\" immediately prior to a science observation. This is a way to make use of the time spent slewing from one target to another. If an OB is executed with a slew cal (using the \"Execute OB with Slew Cal\" button in the OB GUI), then the FIU will transition to calibration mode (the FIU hatch will close and calibration light will be directed to the science and sky fibers), and a calibration exposure will be taken. This will obscure the sky during calibration, so the OA will not be able to see the target until the slew cal is done. This process takes around 2 minutes and so fits nicely in to long slews. An alternative to a slew cal is a simultaneous calibration (simulcal). To use this enable the TakeSimulCal option in the OB or on the OB GUI and either manually set the ND filters to apply to the calibration light or enable the AutoNDFilters option. See the nighttime calibrations page for more info on both the slew cal and simulcal options.","title":"Slew Cals"},{"location":"observingprocedures/#stopping-scripts-or-exposures","text":"Important : If you wish to halt an OB during execution, do NOT hit Control-c in the terminal. Use the \"Request Script STOP\" button instead. The KPF scripts have checkpoints in them which are places where the script can cleanly exit and perform important cleanup operations. The \"STOP Exposure and Script\" button does the same thing, but it will also terminate an exposure in progress.","title":"Stopping Scripts or Exposures"},{"location":"observingprocedures/#known-issues","text":"There is a known failure mode for KPF called a \"start state error\". What happens is some sort of communication failure between the kpfexpose control software, the galil hardware which handles the timing and signaling of the detectors and shutters, and the Archon detector controllers. The result is that one of the green or red detectors does not begin the exposure properly and that detector's data will be useless. The kpf.spectrograph.StartExposure script will automatically detect this situation, terminate the bad exposure after a few seconds, and start a new one all without user intervention. This will generate several WARNING level log messages, but the user does not need to take action as the correction happens automatically. Another known failure mode which can generate WARNING level log messages is a failure of the FIU to transition in to a new mode (i.e. \"Observing\" or \"Calibration\"). The kpf.fiu.ConfigureFIU and kpf.fiu.WaitForConfigureFIU scripts will automatically retry several times before giving up and erroring out. As with the start state error above, no user action is needed, but you will see WARNING level log messages to let you know what is happening.","title":"Known Issues"},{"location":"observingprocedures/#switching-programs-on-a-split-night","text":"On a KPF/KPF split night, before starting the second KPF program, run KPF Control Menu --> Set Program ID and Observers from the background menu (or kpfSetObserverFromSchedule from the command line on any KPF machine). Enter the program ID at the terminal prompt. The script will then set program ID and observers for the second KPF program, based on the telescope schedule. If you wish to set the observer names and program ID manually (i.e. without querying the telescope schedule), you can use the kpfSetProgram and kpfSetObserver scripts from the command line. For example: kpfSetProgram K123 will set program ID \"K123\" and kpfSetObserver \"E.E. Barnard, S.W. Burnham\" will set the observer name to \"E.E. Barnard, S.W. Burnham\". Note that observer names should be enclosed in quotes to handle spaces in the list of names.","title":"Switching Programs on a Split Night"},{"location":"observingprocedures/#bad-weather","text":"If the weather is so bad that no observing is taking place and there doesn't seem to be an immediate likelihood of observing, then we recommend that the observer runs the end of night procedure ( KPF Control Menu --> Run End of Night Script ). The main advantage of this is that running End of Night will re-enable the automatic scheduled calibrations which happen 4 times per night when KPF is not on sky. This means that the instrumental drift will be tracked with no action required by the observer (i.e. running slew cals). If one of these calibration scripts is in progress and observing should resume, use the \"Request Script STOP\" as described above. After that, run the Start of Night script just as you would at the beginning of the night (among other things it disables the autmatic scheduled calibrations).","title":"Bad Weather"},{"location":"references/","text":"Referencing KPF The suggested instrument paper to use when referencing KPF is currently Gibson et al. (2024) in prep. Additional KPF Instrument Papers \"System Design of the Keck Planet Finder\" Gibson et al. (2024) in prep. \"A fiber injection unit for the Keck Planet Finder: opto-mechanical design\" Lilley et al. (2022) \"Keck Planet Finder: design updates\" Gibson et al. (2020) \"A optical fiber double scrambler and mechanical agitator system for the Keck planet finder spectrograph\" Sirk et al (2018) \"Keck Planet Finder: preliminary design\" Gibson et al. (2018) \"Keck Planet Finder: Zerodur optical bench mechanical design\" Smith et al. (2018) \"A comprehensive radial velocity error budget for next generation Doppler spectrometers\" Halverson et al. 2016 \"KPF: Keck Planet Finder\" Gibson et al. 2016","title":"Acknowledging KPF"},{"location":"references/#referencing-kpf","text":"The suggested instrument paper to use when referencing KPF is currently Gibson et al. (2024) in prep.","title":"Referencing KPF"},{"location":"references/#additional-kpf-instrument-papers","text":"\"System Design of the Keck Planet Finder\" Gibson et al. (2024) in prep. \"A fiber injection unit for the Keck Planet Finder: opto-mechanical design\" Lilley et al. (2022) \"Keck Planet Finder: design updates\" Gibson et al. (2020) \"A optical fiber double scrambler and mechanical agitator system for the Keck planet finder spectrograph\" Sirk et al (2018) \"Keck Planet Finder: preliminary design\" Gibson et al. (2018) \"Keck Planet Finder: Zerodur optical bench mechanical design\" Smith et al. (2018) \"A comprehensive radial velocity error budget for next generation Doppler spectrometers\" Halverson et al. 2016 \"KPF: Keck Planet Finder\" Gibson et al. 2016","title":"Additional KPF Instrument Papers"},{"location":"sensitivity/","text":"Spectrograph Sensitivity For sensitivity estimates, please see the KPF exposure time calculator written by the instrument team. More information is available on the KPF Exposure Time (and RV Precision) Calculator page or go directly to GitHub to download the exposure time calculator software . Acquiring Faint Targets We use J-band magnitude as a rough guide for the guider sensitivity, but it is important to keep in mind that this is not a perfect match to the guider passband (950-1200 nm). That said, we have acquired a J=17.0 (V=18.05) quasar using the guider with FPS=0.1 (10 second individual frame exposures). It was not a strong detection: the target was just visible by eye in the images, but the guide system struggled to lock on to it. Another test acquisition on a J=16.7 (V=17.6) object was correspondingly a bit easier. We believe this performance can be improved substantially by using sky subtraction. This is possible currently, but is a slow manual process to configure. On the second test target above (J=16.7, V=17.6), we got reasonable signal using 0.25 FPS (4 second exposures) while using sky subtraction. We are planning to script this process to make it easier and to integrate sky subtraction in to the OA's GUI for controlling the tip tilt, but the timeline for that is still TBD. If you need to acquire very faint targets (J > 16), please reach out to your SA ahead of time to discuss strategies.","title":"Sensitivity"},{"location":"sensitivity/#spectrograph-sensitivity","text":"For sensitivity estimates, please see the KPF exposure time calculator written by the instrument team. More information is available on the KPF Exposure Time (and RV Precision) Calculator page or go directly to GitHub to download the exposure time calculator software .","title":"Spectrograph Sensitivity"},{"location":"sensitivity/#acquiring-faint-targets","text":"We use J-band magnitude as a rough guide for the guider sensitivity, but it is important to keep in mind that this is not a perfect match to the guider passband (950-1200 nm). That said, we have acquired a J=17.0 (V=18.05) quasar using the guider with FPS=0.1 (10 second individual frame exposures). It was not a strong detection: the target was just visible by eye in the images, but the guide system struggled to lock on to it. Another test acquisition on a J=16.7 (V=17.6) object was correspondingly a bit easier. We believe this performance can be improved substantially by using sky subtraction. This is possible currently, but is a slow manual process to configure. On the second test target above (J=16.7, V=17.6), we got reasonable signal using 0.25 FPS (4 second exposures) while using sky subtraction. We are planning to script this process to make it easier and to integrate sky subtraction in to the OA's GUI for controlling the tip tilt, but the timeline for that is still TBD. If you need to acquire very faint targets (J > 16), please reach out to your SA ahead of time to discuss strategies.","title":"Acquiring Faint Targets"},{"location":"socal/","text":"Solar Calibrator (SoCal) The KPF Solar Calibrator (SoCal) is installed on the roof of the support building between the Keck I and Keck II domes. It consists of an EKO Sun Tracker inside an enclosure designed to protect it from strong winds and falling ice. The EKO tracker carries a pyrheliometer to measure solar intensity (used to confirm that we are on the Sun and the sky is clear) and a solar collector which feeds full disk solar light in to a fiber optic which carries it to two locations in the Calibration Bench in the basement where it can be fed in to the KPF instrument.","title":"Solar Calibrator"},{"location":"socal/#solar-calibrator-socal","text":"The KPF Solar Calibrator (SoCal) is installed on the roof of the support building between the Keck I and Keck II domes. It consists of an EKO Sun Tracker inside an enclosure designed to protect it from strong winds and falling ice. The EKO tracker carries a pyrheliometer to measure solar intensity (used to confirm that we are on the Sun and the sky is clear) and a solar collector which feeds full disk solar light in to a fiber optic which carries it to two locations in the Calibration Bench in the basement where it can be fed in to the KPF instrument.","title":"Solar Calibrator (SoCal)"},{"location":"spectrograph/","text":"Spectrometer Optical Design The baseline KPF spectrometer design is shown in the following figure. Light enters the core spectrometer following the fiber image reformatter, at the focal point of the primary collimator mirror (traditionally this would be the location of the spectrometer slit). The f/8 beam diverges past this point and then strikes the primary collimator mirror (an off-axis paraboloid). Upon reflection, the now collimated 200 mm diameter light beam travels to the echelle grating, located one primary collimator focal length away from the primary collimator. After diffraction by the echelle, the diverging monochromatic beams reflect from the primary collimator a second time. Because the echelle grating is rotated slightly out of plane (the echelle gamma angle), the dispersed light does not return along the same path, and the pre- and post-diffraction beams are separated. Therefore, after reflecting from the collimator the second time, the dispersed light does not return to the entrance slit, but forms an intermediate focus to the side of the echelle. Just before the intermediate focus, a flat mirror is employed to fold the beam, to make the spectrometer footprint more compact. Layout of the spectrograph on the optical bench. After the fold mirror reflection, the light rays go through the intermediate focus, and then the diverging monochromatic beams are collimated by the secondary collimator mirror (an off-axis paraboloid). The monochromatic beam diameter here is 160 mm, owing to the secondary collimator having a focal length 0.8x that of the primary collimator. The converging monochromatic beams next encounter a dichroic beamsplitter, where wavelengths blueward of 593 nm are reflected, and wavelengths redward of 593 nm are transmitted. After reflection, the green channel monochromatic beams continue to converge towards the white pupil, where the cross-dispersion grism (grating prism) is located. This disperser consists of a shallow apex angle prism bonded to a volume phase holographic (VPH) grating. Following the grism, the light enters the camera, which then focuses the spectrum onto the CCD detector. A summary of various spectrometer parameters is given the the following table. A brief summary table of KPF instrument properties. VPH Grating Overview As described above, the main spectrometer employs VPH-based grisms for cross-dispersion. In order to provide sufficient cross dispersion, the green channel VPH grating was produced with a line density of 800 lines per mm and the red channel VPH with 450 lines per mm. A summary of the KPF VPH grating specifications are shown in the table below. Both gratings were produced by Kaiser Optical Systems (KOSI). A brief summary table of KPF's VPH grating properties. A preliminary set of diffraction efficiency measurements was conducted by KOSI at a few locations across the clear aperture for each KPF grating. These data were re-measured and confirmed at SSL using the measurement test equipment and procedures developed by the DESI project. Overall, we were able to confirm KOSI's measurements and saw a slight (2-4%) increase in diffraction efficiency. The optimum angle of incidence (AOI) for each grating were both chosen away from their design AOI due to gains in diffraction efficiency at the \"blue\" end (green grating) and \"red\" end (red grating) of the KPF passband. For the green grating, we chose an AOI of -29.5 degree which incrased the overall band average efficiency from 86.4 degree to 87.7 degree. This increased the blue end efficiency from 77.6% to 84.6%. For the red grating, we chose an AOI of -25.4 degree which slightly increased the overall band average efficiency from 87.7% to 88.6%. This increased the red end efficiency from 82.7% to 89.6%. The following figure shows the SSL measured efficiency of the two KPF VPH gratings over the spectrometer's passband. With the changing of the AOI in each grating, we have seen significant gains (approximately 25%) in diffraction efficiency vs. the production minimum specification at both ends of the spectrometer passband. Overall these grating exceeded our production minimum specification by >5% across at all wavelengths with the noted gains at the \"blue\" and \"red\" ends of the KPF spectrometer passband. Plot of the VPH grating efficiency as a function of wavelength.","title":"Spectrograph"},{"location":"spectrograph/#spectrometer-optical-design","text":"The baseline KPF spectrometer design is shown in the following figure. Light enters the core spectrometer following the fiber image reformatter, at the focal point of the primary collimator mirror (traditionally this would be the location of the spectrometer slit). The f/8 beam diverges past this point and then strikes the primary collimator mirror (an off-axis paraboloid). Upon reflection, the now collimated 200 mm diameter light beam travels to the echelle grating, located one primary collimator focal length away from the primary collimator. After diffraction by the echelle, the diverging monochromatic beams reflect from the primary collimator a second time. Because the echelle grating is rotated slightly out of plane (the echelle gamma angle), the dispersed light does not return along the same path, and the pre- and post-diffraction beams are separated. Therefore, after reflecting from the collimator the second time, the dispersed light does not return to the entrance slit, but forms an intermediate focus to the side of the echelle. Just before the intermediate focus, a flat mirror is employed to fold the beam, to make the spectrometer footprint more compact. Layout of the spectrograph on the optical bench. After the fold mirror reflection, the light rays go through the intermediate focus, and then the diverging monochromatic beams are collimated by the secondary collimator mirror (an off-axis paraboloid). The monochromatic beam diameter here is 160 mm, owing to the secondary collimator having a focal length 0.8x that of the primary collimator. The converging monochromatic beams next encounter a dichroic beamsplitter, where wavelengths blueward of 593 nm are reflected, and wavelengths redward of 593 nm are transmitted. After reflection, the green channel monochromatic beams continue to converge towards the white pupil, where the cross-dispersion grism (grating prism) is located. This disperser consists of a shallow apex angle prism bonded to a volume phase holographic (VPH) grating. Following the grism, the light enters the camera, which then focuses the spectrum onto the CCD detector. A summary of various spectrometer parameters is given the the following table. A brief summary table of KPF instrument properties.","title":"Spectrometer Optical Design"},{"location":"spectrograph/#vph-grating-overview","text":"As described above, the main spectrometer employs VPH-based grisms for cross-dispersion. In order to provide sufficient cross dispersion, the green channel VPH grating was produced with a line density of 800 lines per mm and the red channel VPH with 450 lines per mm. A summary of the KPF VPH grating specifications are shown in the table below. Both gratings were produced by Kaiser Optical Systems (KOSI). A brief summary table of KPF's VPH grating properties. A preliminary set of diffraction efficiency measurements was conducted by KOSI at a few locations across the clear aperture for each KPF grating. These data were re-measured and confirmed at SSL using the measurement test equipment and procedures developed by the DESI project. Overall, we were able to confirm KOSI's measurements and saw a slight (2-4%) increase in diffraction efficiency. The optimum angle of incidence (AOI) for each grating were both chosen away from their design AOI due to gains in diffraction efficiency at the \"blue\" end (green grating) and \"red\" end (red grating) of the KPF passband. For the green grating, we chose an AOI of -29.5 degree which incrased the overall band average efficiency from 86.4 degree to 87.7 degree. This increased the blue end efficiency from 77.6% to 84.6%. For the red grating, we chose an AOI of -25.4 degree which slightly increased the overall band average efficiency from 87.7% to 88.6%. This increased the red end efficiency from 82.7% to 89.6%. The following figure shows the SSL measured efficiency of the two KPF VPH gratings over the spectrometer's passband. With the changing of the AOI in each grating, we have seen significant gains (approximately 25%) in diffraction efficiency vs. the production minimum specification at both ends of the spectrometer passband. Overall these grating exceeded our production minimum specification by >5% across at all wavelengths with the noted gains at the \"blue\" and \"red\" ends of the KPF spectrometer passband. Plot of the VPH grating efficiency as a function of wavelength.","title":"VPH Grating Overview"},{"location":"status/","text":"Instrument Status KPF has been commissioned on sky, and is available for use. Many aspects of the instrument are still being optimized and the long term stability is still under evaluation. Short term stability looks excellent (exceeding the 50 cm/s target spec within a night) and we expect measures of the long term RV precision to become available as the DRP evolves. A detailed summary of the instrument status was presented at the September 2023 Keck Science Meeting. The slides from that presentation are available in PDF format . Important Notice : KPF will have a lengthy \u201cservicing mission\u201d during 24B to perform several upgrades. This will involve warm up of the detectors. The work is expected to commence around Oct 27 and be complete before Nov 24. Subsystem Status This is an attempt to summarize the status of various sub-systems of the instrument. Each sub-system name is color coded to indicate the status at a glance: green means functioning normally, orange means mostly normal, but with some caveats or minor issues, and red means the sub-system is compromised in some way. Tip Tilt Corrections : The tip tilt stage X-axis has degraded once again (as of 2024 Aug 22) and we are not making fast tip tilt corrections in X. Troubleshooting is underway. Ca H&K Detector : Currently fully functional. Double Star Observations : Operational. Etalon : Operational and providing the expected flux. LFC : Is operating normally. Detector Systems : The red and green detectors suffer from occasional \u201cstart state errors\u201d in which the affected detector remains in the start phase and does not produce a useful exposure. The observing scripts now detect this occurrence, abort the current exposure (with read out) and start a fresh exposure on both cameras. No action is necessary on the part of the observer. This costs about a minute of time for this to happen, but the resulting data should be normal (unless another error occurs). The occurrence rate for these problems is 0.34% on the green detector and 0.22% on the red, so around one in every 180 exposures is affected by one of the two detectors experiencing this error. Simultaneous Calibration (SimulCal) : Simultaneous calibrations are supported. Observers have the option of manually specifying the ND filters to balance the calibration flux or using the AutoNDFilters option in the OB to have an algorithm set the filters based on the KPF ETC, the target parameters in the OB, and a reference calibration brightness value. See the Nighttime Calibrations page for more info. Exposure Meter Terminated Exposures : The control system supports exposure meter terminated exposures ( ExpMeterMode: control in the OB), however we are still documenting performance on sky. Nod to Sky Observations : For observations which need a sky measurement other than the built in sky fibers, nodding away to a sky position can be accomplished manually by running separate OBs for the target and sky and asking the OA to offset the telescope as appropriate. We plan to build a separate Nod To Sky observing mode which will accomplish this within a single OB, but that is not yet ready. Off Target Guiding : Not yet commissioned. Currently, the tip tilt system must be able to detect the science target in order to position it on the fiber.","title":"Instrument Status"},{"location":"status/#instrument-status","text":"KPF has been commissioned on sky, and is available for use. Many aspects of the instrument are still being optimized and the long term stability is still under evaluation. Short term stability looks excellent (exceeding the 50 cm/s target spec within a night) and we expect measures of the long term RV precision to become available as the DRP evolves. A detailed summary of the instrument status was presented at the September 2023 Keck Science Meeting. The slides from that presentation are available in PDF format . Important Notice : KPF will have a lengthy \u201cservicing mission\u201d during 24B to perform several upgrades. This will involve warm up of the detectors. The work is expected to commence around Oct 27 and be complete before Nov 24.","title":"Instrument Status"},{"location":"status/#subsystem-status","text":"This is an attempt to summarize the status of various sub-systems of the instrument. Each sub-system name is color coded to indicate the status at a glance: green means functioning normally, orange means mostly normal, but with some caveats or minor issues, and red means the sub-system is compromised in some way. Tip Tilt Corrections : The tip tilt stage X-axis has degraded once again (as of 2024 Aug 22) and we are not making fast tip tilt corrections in X. Troubleshooting is underway. Ca H&K Detector : Currently fully functional. Double Star Observations : Operational. Etalon : Operational and providing the expected flux. LFC : Is operating normally. Detector Systems : The red and green detectors suffer from occasional \u201cstart state errors\u201d in which the affected detector remains in the start phase and does not produce a useful exposure. The observing scripts now detect this occurrence, abort the current exposure (with read out) and start a fresh exposure on both cameras. No action is necessary on the part of the observer. This costs about a minute of time for this to happen, but the resulting data should be normal (unless another error occurs). The occurrence rate for these problems is 0.34% on the green detector and 0.22% on the red, so around one in every 180 exposures is affected by one of the two detectors experiencing this error. Simultaneous Calibration (SimulCal) : Simultaneous calibrations are supported. Observers have the option of manually specifying the ND filters to balance the calibration flux or using the AutoNDFilters option in the OB to have an algorithm set the filters based on the KPF ETC, the target parameters in the OB, and a reference calibration brightness value. See the Nighttime Calibrations page for more info. Exposure Meter Terminated Exposures : The control system supports exposure meter terminated exposures ( ExpMeterMode: control in the OB), however we are still documenting performance on sky. Nod to Sky Observations : For observations which need a sky measurement other than the built in sky fibers, nodding away to a sky position can be accomplished manually by running separate OBs for the target and sky and asking the OA to offset the telescope as appropriate. We plan to build a separate Nod To Sky observing mode which will accomplish this within a single OB, but that is not yet ready. Off Target Guiding : Not yet commissioned. Currently, the tip tilt system must be able to detect the science target in order to position it on the fiber.","title":"Subsystem Status"},{"location":"tiptilt/","text":"Tip Tilt Correction System The KPF tip tilt system takes fast (e.g. 100 FPS) subframe images from the KPF CRED2 guide camera in order to control the fast tip tilt mirror which directs light in to the KPF FIU. This fast tip tilt system maintains the stellar position on the science fiber. This is critical not for reasons of maximizing flux in to the spectrograph (though that is a side benefit), but to optimize the radial velocity measurement by keeping the illumination pattern on the fiber tip stable. Even after fiber scrambling and agitation, if the star\u2019s position on the fiber entrance fiber shifts, that can manifest as a small shift of the spectrum on the detector which would be interpreted as a radial velocity change. Thus we need to position the star on the fiber, and then hold it in a consistent place during observations and make that position consistent from observation to observation. The tip tilt mirror is a fold mirror which sits on the PCU stage on the Keck I AO bench. The mirror folds the light in to the KPF FIU and is controlled in tip and tilt by a piezo stage built by nPoint. The nominal spec for tip tilt performance is to position of the star within 50mas of the target position and then maintain that position at an RMS fo 50mas or better. The software which controls the tip tilt stage is built in to the kpffiu and kpfguide KTL keyword services.","title":"Tip Tilt Sysyem"},{"location":"tiptilt/#tip-tilt-correction-system","text":"The KPF tip tilt system takes fast (e.g. 100 FPS) subframe images from the KPF CRED2 guide camera in order to control the fast tip tilt mirror which directs light in to the KPF FIU. This fast tip tilt system maintains the stellar position on the science fiber. This is critical not for reasons of maximizing flux in to the spectrograph (though that is a side benefit), but to optimize the radial velocity measurement by keeping the illumination pattern on the fiber tip stable. Even after fiber scrambling and agitation, if the star\u2019s position on the fiber entrance fiber shifts, that can manifest as a small shift of the spectrum on the detector which would be interpreted as a radial velocity change. Thus we need to position the star on the fiber, and then hold it in a consistent place during observations and make that position consistent from observation to observation. The tip tilt mirror is a fold mirror which sits on the PCU stage on the Keck I AO bench. The mirror folds the light in to the KPF FIU and is controlled in tip and tilt by a piezo stage built by nPoint. The nominal spec for tip tilt performance is to position of the star within 50mas of the target position and then maintain that position at an RMS fo 50mas or better. The software which controls the tip tilt stage is built in to the kpffiu and kpfguide KTL keyword services.","title":"Tip Tilt Correction System"},{"location":"tiptiltinstructions/","text":"Tip Tilt Instructions for OAs Table of Contents TL:DR Procedure Tip Tilt System Overview Tip Tilt GUI GUI Layout Camera Controls Tab Object Detection Tab Offset Guiding Tab Settings Tab Plot Time Spans Tab Tip Tilt Control and Telemetry Image Display Instrument Status Status Bar Star Detection Algorithm Deblending Multiple Stars TL:DR Procedure Set the gain and FPS values for the guide camera. Acquire the star to the KPF PO using magiq. In the KPF Tip Tilt GUI, turn on the tip tilt loops. Verify normal operation of the loops (this should just require a momentary glance at the various indicators): Make sure the science target has been indentified. It should have a circle around it and a label in the image display part of the GUI. Check that an object has been selected in \"Object Choice\". Check that the Peak Flux is sufficient (the value will be color coded to help you). If needed, adjust the gain and FPS. Check that the Tip Tilt Error is decreasing over time in the plot. This indicates that the star is being moved to the target pixel. Check the \"Tip Tilt RMS\" value is around 50 mas or better. If the target is faint or there are heavy clouds or bad seeing, it may not be able to reach this, but under normal conditions we should at least be in the ballpark. If there are multiple stars in the field of view, ensure that the corect target is selected and that the stars are not blended. Each detected star will have its own OBJECTn label in the image display: make sure this is centered on the star . Inform the observer that the tip tilt loops are engaged and they can begin exposing. Troubleshooting the TL:DR Procedure If the system is not seeing the target star, adjust the \"Detect SNR\" and/or \"Detect Area\" values under the Object Detection tab in the GUI (see Star Detection Algorithm section below for details). If the system seems to be having trouble identifying stars, toggle the loops on and off (this is primarily for the Calculation loop). Doing this will cause the algorithm to re-identify the stars and may resolve ID confusion caused when stars are moving rapidly in the field. Check that there are no red indicators in the status bar at the bottom of the Tip Tilt GUI. These indicate that something substantial is wrong. Which indicator it is will tell you which keyword or dispatcher is in a bad state. Tip Tilt System Overview The KPF tip tilt system takes fast (e.g. 100 FPS) subframe images from the KPF CRED2 guide camera in order to control the fast tip tilt mirror which directs light in to the KPF FIU. This fast tip tilt system maintains the stellar position on the science fiber. This is critical not for reasons of maximizing flux in to the spectrograph (though that is a side benefit), but to optimize the radial velocity measurement. Even after fiber scrambling and agitation, if the star\u2019s position on the fiber entrance fiber shifts, that can manifest as a small shift of the spectrum on the detector which would be interpreted as a radial velocity change. Thus we need to position the star on the fiber, and then hold it in a consistent place during observations and make that position consistent from observation to observation. Tip Tilt Loops There are several components to the tip tilt loops. Controls for toggling them on and off together and individually are provided in the Tip Tilt Control and Telemetry section of the Tip Tilt GUI. The important pieces are: Calculation : The calculations are the part of the algorithm which is examining images from the guide camera, detecting and identifying objects, and calculating the relevant tip tilt commands. This can be toggled on and off using the underlying kpfguide.TIPTILT_CALC keyword. Note that once calculations are turned on the system is attempting to cross identify stars from image to image and maintain a consistent identity. One of the things it uses to do this is knowledge of the average positions of stars in recent images. Thus, if the stars are moved dramatically (e.g. by Magiq), it may confuse the IDs. If you think this might be the case, restarting calculations will force a fresh identification phase. Control : The control component takes the output of the calculations loop and sends commands to the tip tilt mirror. As long as the motions needed are within range of the tip tilt mirror, this will close the loops and should yield a stable star position. This can be toggled on and off using the underlying kpfguide.TIPTILT_CONTROL keyword. Offload : If the motion of the star carries it toward the edfe of the tip tilt mirror's range of motion, the system will \"offload\" some of that movement to the telescope (akin to a normal guiding command). Enabling offloads allows those commands to go to the telescope. This can be toggled on and off using the underlying kpfguide.OFFLOAD keyword. The kpfguide.OFFLOAD keyword will also attempt examine the telescope control system ( dcs ) to determine if offloads should be sent. This permissive is based primarily on whether KPF is the selected instrument, if not, the instrument should not be sending offloads to the telescope. The kpfguide.OFFLOAD_DCS keyword indicated whether KPF is permitted to offload and it must be \"Yes\" in order for offloads to be enabled. Tip Tilt GUI To start the GUI, open a terminal as any kpf user (e.g. kpfeng) on the kpf machine and type: TTGUI_v2 . For dark mode, add the -d option to the command. A screenshot of the Tip Tilt GUI. The Tip Tilt GUI may also be opened for observers in \"monitor\" mode, in which case none of the controls are active, but the telemetry and image display can be seen. To do this, use the TTGUI_v2 --monitor terminal command as above or select KPF Control Menu -> Subcomponents -> Start Tip Tilt GUI from the FVWM menu in a KPF VNC session. GUI Layout The top section of the GUI (beneath the \"File\" and \"Troubleshooting\" menus), is a small tabbed interface with various controls and options. See the sections below on each tab. Beneath the tabbed section is a region titled \"Tip Tilt Control and Telemetry\" this section contains control for the tip tilt loops and telemetry about the tip tilt performance. See the Tip Tilt Control and Telemetry section below for details. Beneath that is a region titled \"Image Display\" which shows the latest Magiq image cropped to the region which the tip tilt system is using (a subframe of the whole field). It also contains the tool for choosing which object in the field to guide on and controls for the image display stretch and cut. See the Image Display section below for details. Beneath that is a region titled \"Instrument Status\" which contains a very brief summary of what the instrument is doing at the moment. See the Instrument Status section below for details. The very bottom of the GUI is the status bar which will be empty if everything is in a working state for observing. See the Status Bar section below for details. Camera Controls Tab A screenshot of the Tip Tilt GUI's Camera Controls tab. When the observer executes an OB (which they should do during the slew, but they may forget or not be ready, so check if you are unsure), then the target star's J band magnitude will be populated in this GUI. This will also update the \"Recommended Gain & FPS\" values. If you wish to accept these recommendations, simply click the \"Set\" button. The recommendations will be color coded green if they match the current values or orange if they do not match. The pulldown to the left of the \"Set\" button will add in some amount of extinction (in magnitudes) to the estimated values. If you have clouds, you can put in some value for the extinction and the estimate will account for the clouds. The right hand section of the tab shows the current Gain & FPS values. You may set them here using the pulldown menus. You can set these values on the command line by modifying the relevant keywords: kpgduide.GAIN , and kpfguide.FPS . Object Detection Tab A screenshot of the Tip Tilt GUI's Object Detection tab. This is where you can set the object detection and deblending parameters discussed in the Star Detection Algorithm section below. The pulldowns will set the requested value. You can set these values on the command line by modifying the relevant keywords: kpgduide.OBJECT_INTENSITY , kpfguide.OBJECT_AREA , and kpfguide.OBJECT_DBCONT . Offset Guiding Tab Not currently implemented. Settings Tab A screenshot of the Tip Tilt GUI's Settings tab. The three options here control various settings for the kpfguide algorithms. The \"X Axis\" and \"Y Axis\" settings allow you to bypass the tip tilt mirror and control the star position only using offloads to the telescope (conceptually similar to normal Magiq guiding). These values should be \"Mirror\" unless there is a problem with the tip tilt system. The \"DAR\" setting determines whether the target pixel for the star is modified to account for differential atmospheric refraction (DAR) between the guide wavelengths (950-1200nm) and the science wavelengths (centered on 550nm). This should be set to \"Yes\" under normal observing conditions. Plot Time Spans Tab A screenshot of the Tip Tilt GUI's Plot Time Spans tab. These two pulldowns allow you to change the time span of the two plots in the Tip Tilt Control and Telemetry region of the GUI. They have no effect on the tip tilt performance, only the plots. Tip Tilt Control and Telemetry This section of the GUI is how the tip tilt loops are opened and closed. The \"Tip Tilt On/Off\" button will likely be the primary interface as it toggles all of the components off the system on and off together, but the checkboxes to the right allow each to be toggled individually. Note that the \"Offloads\" checkbox will be color coded red when kpfguide.OFFLOAD_DCS is \"No\". The \"Tip Tilt Phase\" is meant to summarise whether the system has fully controlled the star's position to the point where the observers can begin exposing. It will begin in \"Identifying\", then move to \"Acquiring\" once a star has been identified and is being moved to the target pixel, and finally reach \"Tracking\" when the star is in position. These stages are based on the position error of the star and so may not be a perfect guide, but should be useful under normal conditions. The \"Tip Tilt FPS\" value shown in the GUI is the rate at which frames are being processed by the tip tilt algorithm and should be compared to the gude camera FPS. The \"Tip Tilt FPS\" value will likely bounce around a bit, but it should stay somewhere in the range of the camera FPS (within maybe 10%). If it is much less than the camera FPS, then the tip tilt system is not keeping up with the images coming in. The GUI will color code this value with orange and red values when it deviated from the camera FPS by more than some threshold amount. The \"Tip Tilt RMS\" value shown indicates how much the stellar position varies from frame to frame. This is different than the \"Tip Tilt Error\" (used in the plot below). The RMS is a measure of the frame to frame variation while the error is the average offset between the star and the target pixel. The error should drop to <<1 pixel under good conditions as the average star position is driven to the target pixel, but as the star bounces around from frame to frame due to seeing, the RMS value will be larger than zero. Our design goal is for the RMS value to be <50 mas (<1 pixel). The \"Peak Flux\" value is the brightness (in ADU) of the brightest pixel in the star as measured by the star detection algorithm. This is a good, but imperfect indication of whether the star is saturated in the guider image. Some bad pixels are always bright and if one of them is included in the star detection then the value of that one bad pixel will affect this reading, so you should use some discretion when inspecting this value. We have plans to implement a bad pixel mask which should mitigate this, but that is not complete and will require some care to make sure it does not affect the high speed calculations in the tip tilt loops. The guide camera is 14-bit, so it saturates at a value of 16,384. We perform a bias subtraction, so in practice this value is more like 14,000 counts. Saturation is not a deal breaker for using the tip tilt system. Mild saturation of only a few pixels in the core of the star will not drastically degrade the tip tilt performance, so it is better to saturate a bit than to try to run the FPS up to extremely high values where the calculations can not keep up. The \"Total Flux\" value is the sum of all pixel values with the detected star. This is an alternate indicator of the star's brightness, but does not directly indicate whether the star saturates the camera. The \"Tip Tilt Error\" plot is the left hand plot in the GUI. This is the offset (in pixels) between the stars's average position and the target pixel. When you first turn on the loops, you should see this start at a high value (a few pixels) and drop rapidly to near 0. The \"Flux\" plot is the right hand plot in the GUI. It plots the total flux in the star over time. The behavior of this is a useful indicator of clouds. Image Display The image display section shows a cropped version of the Magiq image (cropped to the region the tip tilt algorithm is using). It is important to remember that this image is not the same as what the tip tilt system is using for its calculations! This is an average of frames over the Magiq exposure time, so you have a higher SNR in this image than you do in the individual frames going in to the tip tilt calculations. The filename displayed and the timestamp at which the file was updated are also shown near the top. Mousing over the image will read out the pixel position and value of the pixel under the cursor just below the image and next to the X and Y position of the target pixel the algorithm is trying to steer the star to (this value is updated by DAR and so will change). The image will show an overlayed circle and label with the object's name (\"OBJECT1, OBJECT2, or OBJECT3\") and the percentage value next to the label is the fraction of frames in which is object is detected. If this is much less than 100%, you should probably adjust the detection parameters or adjust the sensitivity of the guider (i.e. increase gain or lower the FPS). To the right of the image is the \"Object Choice\" box. In the case where multiple objects are detected, you will need to choose one of them to be the target. Use the pulldown to choose which one you want to drive to the target pixel. Below this is a plot showing where the tip tilt mirror is within its range. The range is indicated by the green area. Points will be drawn and fade out over time to indicate the motion of the tip tilt mirror. Finally there are two selectors for \"Image Cut\" and \"Image Scaling\", these affect the image display, so feel free to adjust as you see fit. Instrument Status There is a small section here summarizing the instrument status. It shows whether there is a script running which is a good indicator of whether data is being taken. The \"Exposure Status\" value shows whether the detectors are exposing, reading out, etc. The \"FIU Mode\" is a good guide as to whether you should expect to be seeing light from the sky on the guider images (e.g. if it is in \"Calibration\" mode, we are taking a cal exposure and you are probably seeing cal fibers, not the sky). Finally, the \"Object\" value is the string the observer has used to name the target. Status Bar The very bottom of the GUI is a status bar. It will be empty under normal operating conditions, but will contain red indicators when there is a problem that will likely halt operation of the tip tilt system. For example, in the screenshot below several errors are shown: A screenshot of the Tip Tilt GUI's Status Bar with several errors. Status bar errors which can show up include: CONTINUOUS : This indicates that the guide camera is not exposing. SAVE : This indicates that the guide camera is not saving files. TTXSRV : This indicates that the tip tilt mirror X axis is not in servo mode and thus will not correct properly. TTYSRV : This indicates that the tip tilt mirror Y axis is not in servo mode and thus will not correct properly. DAR Disabled : This indicates that the DAR is not enabled. kpfguide1 : This indicates that there is a likely problem with the kpfguide1 dispatcher and a restart is likely required. kpfguide2 : This indicates that there is a likely problem with the kpfguide2 dispatcher and a restart is likely required. kpfguide3 : This indicates that there is a likely problem with the kpfguide3 dispatcher and a restart is likely required. Star Detection Algorithm The kpfguide software uses Source Extractor via the SEP Python Library for star detection. The \"Detect SNR\" and \"Detect Area\" values in the GUI correspond to the thresh and minarea parameters of sep.extract and to kpfguide.OBJECT_INTENSITY and kpfguide.OBJECT_AREA keyword respectively. The way the algorithm detects stars is to look for adjacent clusters of pixels with values above \"Detect SNR\". If that cluster is larger than \"Detect Area\" pixels, then it is a star. Both parameters are critical in determining whether a star will be detected. Having a large \"Detect Area\" means that faint stars will often not have enough bright pixels to be considered a detection. Similarly, a large \"Detect SNR\" might mean that not enough pixels are bright enough so too few pixels will be detections to be considered a star. On faint targets, both parameters may need to come down if only the very core of the star has significant signal in it. If you're having trouble in good seeing, make sure that \"Detect Area\" is not too large for the seeing. Based on experience, starting with values of 5-7 for \"Detect SNR\" and 80-100 for \"Detect Area\" are reasonable. Deblending Multiple Stars Deblending is a term that comes from Source Extractor. It can be both perilous and useful. Early in the system\u2019s use, we were still using the default deblending contrast of 0.005, which meant that it took only a small dip in flux (0.5%) for two adjacent maxima to be considered two different objects. In practice, this meant that a single star would deblend in to multiple stars due to speckles moving about. As a result, the \u201cstar\u201d would appear to shift to one side or the other leading to sudden large corrections which would then be reversed a frame or two later when the speckles had shifted and the star was no longer deblended. This could affect several percent of all guide frames (in other words, the star was being jolted around by spurious detections several times per second). Of course, in situation where there are actually blended stars this is a useful tool. Double stars can be separated and a particular guide target chosen using this system. Based on our experience so far, leaving deblending contrast at 1.0 for most targets is the right choice. This demands that the valley between adjacent peaks be as deep as the highest peak (i.e. it goes to 0), so it turns deblending off. Since most targets are isolated stars with no close neighbors of similar brightness, this avoids the problem of tracking on speckles. If a double star is the target, decreasing the deblending contrast until it is reliably separates is the best strategy. Use the overlays in the image display to ensure that the target star has its own label and that label is centered properly on the star. If the label is not centered on the star, it might be blended with the companion which is puslling the \"center\" off toward the companion -- this is what we mean by blended stars. If the stars are blended, they must be deblended for KPF to accurately place one properly on the fiber. If the centroid is biased because the stars are not deblended you will end up with an RV effect due to the positioning of the star on the fiber being incorrect. The deblend contrast can be run down at 0.005 or lower to pull out a faint companion. Note that this is the contrast between the bright star and the faint \"gap\" between companions, so large contrast is not unexpected if the companion star is a few magnitudes fainter than the primary. For example, if the deblend contrast is 0.01 that is 5 magnitudes of contrast 2.5*log(0.01) , but that's not an unreasonable contrast for the gap if the companion star is just 2 or 3 magnitudes fainter than the primary. Also, because the algorithm is doing deblending, not trying to detect the companion as a separate object, we don't need to worry about the primary being too bright -- it is ok to saturate the primary to get the companion. Of course, a widely separated double star may be seen as two stars by the system if there is a \u201cgap\u201d between the two stars where the signal in the pixels is lower than the detection threshold. In this case, no deblending is necessary. Finally, if the star the observers are trying to acquire is too challenging and you are unable to make it work, you can ask the observer to click the \"Collect Guider Image Cube\" button on their OB GUI. This will save a brief sequence of guider images which can be analyzed offline to find out the best way to acquire that particular star (email the KPF SA to let them know to look at it). This does not help for the immediate observation, but will allow us to find the right solution for the next time this target or a similar one is observed.","title":"Tip Tilt Instructions for OAs"},{"location":"tiptiltinstructions/#tip-tilt-instructions-for-oas","text":"","title":"Tip Tilt Instructions for OAs"},{"location":"tiptiltinstructions/#table-of-contents","text":"TL:DR Procedure Tip Tilt System Overview Tip Tilt GUI GUI Layout Camera Controls Tab Object Detection Tab Offset Guiding Tab Settings Tab Plot Time Spans Tab Tip Tilt Control and Telemetry Image Display Instrument Status Status Bar Star Detection Algorithm Deblending Multiple Stars","title":"Table of Contents"},{"location":"tiptiltinstructions/#tldr-procedure","text":"Set the gain and FPS values for the guide camera. Acquire the star to the KPF PO using magiq. In the KPF Tip Tilt GUI, turn on the tip tilt loops. Verify normal operation of the loops (this should just require a momentary glance at the various indicators): Make sure the science target has been indentified. It should have a circle around it and a label in the image display part of the GUI. Check that an object has been selected in \"Object Choice\". Check that the Peak Flux is sufficient (the value will be color coded to help you). If needed, adjust the gain and FPS. Check that the Tip Tilt Error is decreasing over time in the plot. This indicates that the star is being moved to the target pixel. Check the \"Tip Tilt RMS\" value is around 50 mas or better. If the target is faint or there are heavy clouds or bad seeing, it may not be able to reach this, but under normal conditions we should at least be in the ballpark. If there are multiple stars in the field of view, ensure that the corect target is selected and that the stars are not blended. Each detected star will have its own OBJECTn label in the image display: make sure this is centered on the star . Inform the observer that the tip tilt loops are engaged and they can begin exposing.","title":"TL:DR Procedure"},{"location":"tiptiltinstructions/#troubleshooting-the-tldr-procedure","text":"If the system is not seeing the target star, adjust the \"Detect SNR\" and/or \"Detect Area\" values under the Object Detection tab in the GUI (see Star Detection Algorithm section below for details). If the system seems to be having trouble identifying stars, toggle the loops on and off (this is primarily for the Calculation loop). Doing this will cause the algorithm to re-identify the stars and may resolve ID confusion caused when stars are moving rapidly in the field. Check that there are no red indicators in the status bar at the bottom of the Tip Tilt GUI. These indicate that something substantial is wrong. Which indicator it is will tell you which keyword or dispatcher is in a bad state.","title":"Troubleshooting the TL:DR Procedure"},{"location":"tiptiltinstructions/#tip-tilt-system-overview","text":"The KPF tip tilt system takes fast (e.g. 100 FPS) subframe images from the KPF CRED2 guide camera in order to control the fast tip tilt mirror which directs light in to the KPF FIU. This fast tip tilt system maintains the stellar position on the science fiber. This is critical not for reasons of maximizing flux in to the spectrograph (though that is a side benefit), but to optimize the radial velocity measurement. Even after fiber scrambling and agitation, if the star\u2019s position on the fiber entrance fiber shifts, that can manifest as a small shift of the spectrum on the detector which would be interpreted as a radial velocity change. Thus we need to position the star on the fiber, and then hold it in a consistent place during observations and make that position consistent from observation to observation.","title":"Tip Tilt System Overview"},{"location":"tiptiltinstructions/#tip-tilt-loops","text":"There are several components to the tip tilt loops. Controls for toggling them on and off together and individually are provided in the Tip Tilt Control and Telemetry section of the Tip Tilt GUI. The important pieces are: Calculation : The calculations are the part of the algorithm which is examining images from the guide camera, detecting and identifying objects, and calculating the relevant tip tilt commands. This can be toggled on and off using the underlying kpfguide.TIPTILT_CALC keyword. Note that once calculations are turned on the system is attempting to cross identify stars from image to image and maintain a consistent identity. One of the things it uses to do this is knowledge of the average positions of stars in recent images. Thus, if the stars are moved dramatically (e.g. by Magiq), it may confuse the IDs. If you think this might be the case, restarting calculations will force a fresh identification phase. Control : The control component takes the output of the calculations loop and sends commands to the tip tilt mirror. As long as the motions needed are within range of the tip tilt mirror, this will close the loops and should yield a stable star position. This can be toggled on and off using the underlying kpfguide.TIPTILT_CONTROL keyword. Offload : If the motion of the star carries it toward the edfe of the tip tilt mirror's range of motion, the system will \"offload\" some of that movement to the telescope (akin to a normal guiding command). Enabling offloads allows those commands to go to the telescope. This can be toggled on and off using the underlying kpfguide.OFFLOAD keyword. The kpfguide.OFFLOAD keyword will also attempt examine the telescope control system ( dcs ) to determine if offloads should be sent. This permissive is based primarily on whether KPF is the selected instrument, if not, the instrument should not be sending offloads to the telescope. The kpfguide.OFFLOAD_DCS keyword indicated whether KPF is permitted to offload and it must be \"Yes\" in order for offloads to be enabled.","title":"Tip Tilt Loops"},{"location":"tiptiltinstructions/#tip-tilt-gui","text":"To start the GUI, open a terminal as any kpf user (e.g. kpfeng) on the kpf machine and type: TTGUI_v2 . For dark mode, add the -d option to the command. A screenshot of the Tip Tilt GUI. The Tip Tilt GUI may also be opened for observers in \"monitor\" mode, in which case none of the controls are active, but the telemetry and image display can be seen. To do this, use the TTGUI_v2 --monitor terminal command as above or select KPF Control Menu -> Subcomponents -> Start Tip Tilt GUI from the FVWM menu in a KPF VNC session.","title":"Tip Tilt GUI"},{"location":"tiptiltinstructions/#gui-layout","text":"The top section of the GUI (beneath the \"File\" and \"Troubleshooting\" menus), is a small tabbed interface with various controls and options. See the sections below on each tab. Beneath the tabbed section is a region titled \"Tip Tilt Control and Telemetry\" this section contains control for the tip tilt loops and telemetry about the tip tilt performance. See the Tip Tilt Control and Telemetry section below for details. Beneath that is a region titled \"Image Display\" which shows the latest Magiq image cropped to the region which the tip tilt system is using (a subframe of the whole field). It also contains the tool for choosing which object in the field to guide on and controls for the image display stretch and cut. See the Image Display section below for details. Beneath that is a region titled \"Instrument Status\" which contains a very brief summary of what the instrument is doing at the moment. See the Instrument Status section below for details. The very bottom of the GUI is the status bar which will be empty if everything is in a working state for observing. See the Status Bar section below for details.","title":"GUI Layout"},{"location":"tiptiltinstructions/#camera-controls-tab","text":"A screenshot of the Tip Tilt GUI's Camera Controls tab. When the observer executes an OB (which they should do during the slew, but they may forget or not be ready, so check if you are unsure), then the target star's J band magnitude will be populated in this GUI. This will also update the \"Recommended Gain & FPS\" values. If you wish to accept these recommendations, simply click the \"Set\" button. The recommendations will be color coded green if they match the current values or orange if they do not match. The pulldown to the left of the \"Set\" button will add in some amount of extinction (in magnitudes) to the estimated values. If you have clouds, you can put in some value for the extinction and the estimate will account for the clouds. The right hand section of the tab shows the current Gain & FPS values. You may set them here using the pulldown menus. You can set these values on the command line by modifying the relevant keywords: kpgduide.GAIN , and kpfguide.FPS .","title":"Camera Controls Tab"},{"location":"tiptiltinstructions/#object-detection-tab","text":"A screenshot of the Tip Tilt GUI's Object Detection tab. This is where you can set the object detection and deblending parameters discussed in the Star Detection Algorithm section below. The pulldowns will set the requested value. You can set these values on the command line by modifying the relevant keywords: kpgduide.OBJECT_INTENSITY , kpfguide.OBJECT_AREA , and kpfguide.OBJECT_DBCONT .","title":"Object Detection Tab"},{"location":"tiptiltinstructions/#offset-guiding-tab","text":"Not currently implemented.","title":"Offset Guiding Tab"},{"location":"tiptiltinstructions/#settings-tab","text":"A screenshot of the Tip Tilt GUI's Settings tab. The three options here control various settings for the kpfguide algorithms. The \"X Axis\" and \"Y Axis\" settings allow you to bypass the tip tilt mirror and control the star position only using offloads to the telescope (conceptually similar to normal Magiq guiding). These values should be \"Mirror\" unless there is a problem with the tip tilt system. The \"DAR\" setting determines whether the target pixel for the star is modified to account for differential atmospheric refraction (DAR) between the guide wavelengths (950-1200nm) and the science wavelengths (centered on 550nm). This should be set to \"Yes\" under normal observing conditions.","title":"Settings Tab"},{"location":"tiptiltinstructions/#plot-time-spans-tab","text":"A screenshot of the Tip Tilt GUI's Plot Time Spans tab. These two pulldowns allow you to change the time span of the two plots in the Tip Tilt Control and Telemetry region of the GUI. They have no effect on the tip tilt performance, only the plots.","title":"Plot Time Spans Tab"},{"location":"tiptiltinstructions/#tip-tilt-control-and-telemetry","text":"This section of the GUI is how the tip tilt loops are opened and closed. The \"Tip Tilt On/Off\" button will likely be the primary interface as it toggles all of the components off the system on and off together, but the checkboxes to the right allow each to be toggled individually. Note that the \"Offloads\" checkbox will be color coded red when kpfguide.OFFLOAD_DCS is \"No\". The \"Tip Tilt Phase\" is meant to summarise whether the system has fully controlled the star's position to the point where the observers can begin exposing. It will begin in \"Identifying\", then move to \"Acquiring\" once a star has been identified and is being moved to the target pixel, and finally reach \"Tracking\" when the star is in position. These stages are based on the position error of the star and so may not be a perfect guide, but should be useful under normal conditions. The \"Tip Tilt FPS\" value shown in the GUI is the rate at which frames are being processed by the tip tilt algorithm and should be compared to the gude camera FPS. The \"Tip Tilt FPS\" value will likely bounce around a bit, but it should stay somewhere in the range of the camera FPS (within maybe 10%). If it is much less than the camera FPS, then the tip tilt system is not keeping up with the images coming in. The GUI will color code this value with orange and red values when it deviated from the camera FPS by more than some threshold amount. The \"Tip Tilt RMS\" value shown indicates how much the stellar position varies from frame to frame. This is different than the \"Tip Tilt Error\" (used in the plot below). The RMS is a measure of the frame to frame variation while the error is the average offset between the star and the target pixel. The error should drop to <<1 pixel under good conditions as the average star position is driven to the target pixel, but as the star bounces around from frame to frame due to seeing, the RMS value will be larger than zero. Our design goal is for the RMS value to be <50 mas (<1 pixel). The \"Peak Flux\" value is the brightness (in ADU) of the brightest pixel in the star as measured by the star detection algorithm. This is a good, but imperfect indication of whether the star is saturated in the guider image. Some bad pixels are always bright and if one of them is included in the star detection then the value of that one bad pixel will affect this reading, so you should use some discretion when inspecting this value. We have plans to implement a bad pixel mask which should mitigate this, but that is not complete and will require some care to make sure it does not affect the high speed calculations in the tip tilt loops. The guide camera is 14-bit, so it saturates at a value of 16,384. We perform a bias subtraction, so in practice this value is more like 14,000 counts. Saturation is not a deal breaker for using the tip tilt system. Mild saturation of only a few pixels in the core of the star will not drastically degrade the tip tilt performance, so it is better to saturate a bit than to try to run the FPS up to extremely high values where the calculations can not keep up. The \"Total Flux\" value is the sum of all pixel values with the detected star. This is an alternate indicator of the star's brightness, but does not directly indicate whether the star saturates the camera. The \"Tip Tilt Error\" plot is the left hand plot in the GUI. This is the offset (in pixels) between the stars's average position and the target pixel. When you first turn on the loops, you should see this start at a high value (a few pixels) and drop rapidly to near 0. The \"Flux\" plot is the right hand plot in the GUI. It plots the total flux in the star over time. The behavior of this is a useful indicator of clouds.","title":"Tip Tilt Control and Telemetry"},{"location":"tiptiltinstructions/#image-display","text":"The image display section shows a cropped version of the Magiq image (cropped to the region the tip tilt algorithm is using). It is important to remember that this image is not the same as what the tip tilt system is using for its calculations! This is an average of frames over the Magiq exposure time, so you have a higher SNR in this image than you do in the individual frames going in to the tip tilt calculations. The filename displayed and the timestamp at which the file was updated are also shown near the top. Mousing over the image will read out the pixel position and value of the pixel under the cursor just below the image and next to the X and Y position of the target pixel the algorithm is trying to steer the star to (this value is updated by DAR and so will change). The image will show an overlayed circle and label with the object's name (\"OBJECT1, OBJECT2, or OBJECT3\") and the percentage value next to the label is the fraction of frames in which is object is detected. If this is much less than 100%, you should probably adjust the detection parameters or adjust the sensitivity of the guider (i.e. increase gain or lower the FPS). To the right of the image is the \"Object Choice\" box. In the case where multiple objects are detected, you will need to choose one of them to be the target. Use the pulldown to choose which one you want to drive to the target pixel. Below this is a plot showing where the tip tilt mirror is within its range. The range is indicated by the green area. Points will be drawn and fade out over time to indicate the motion of the tip tilt mirror. Finally there are two selectors for \"Image Cut\" and \"Image Scaling\", these affect the image display, so feel free to adjust as you see fit.","title":"Image Display"},{"location":"tiptiltinstructions/#instrument-status","text":"There is a small section here summarizing the instrument status. It shows whether there is a script running which is a good indicator of whether data is being taken. The \"Exposure Status\" value shows whether the detectors are exposing, reading out, etc. The \"FIU Mode\" is a good guide as to whether you should expect to be seeing light from the sky on the guider images (e.g. if it is in \"Calibration\" mode, we are taking a cal exposure and you are probably seeing cal fibers, not the sky). Finally, the \"Object\" value is the string the observer has used to name the target.","title":"Instrument Status"},{"location":"tiptiltinstructions/#status-bar","text":"The very bottom of the GUI is a status bar. It will be empty under normal operating conditions, but will contain red indicators when there is a problem that will likely halt operation of the tip tilt system. For example, in the screenshot below several errors are shown: A screenshot of the Tip Tilt GUI's Status Bar with several errors. Status bar errors which can show up include: CONTINUOUS : This indicates that the guide camera is not exposing. SAVE : This indicates that the guide camera is not saving files. TTXSRV : This indicates that the tip tilt mirror X axis is not in servo mode and thus will not correct properly. TTYSRV : This indicates that the tip tilt mirror Y axis is not in servo mode and thus will not correct properly. DAR Disabled : This indicates that the DAR is not enabled. kpfguide1 : This indicates that there is a likely problem with the kpfguide1 dispatcher and a restart is likely required. kpfguide2 : This indicates that there is a likely problem with the kpfguide2 dispatcher and a restart is likely required. kpfguide3 : This indicates that there is a likely problem with the kpfguide3 dispatcher and a restart is likely required.","title":"Status Bar"},{"location":"tiptiltinstructions/#star-detection-algorithm","text":"The kpfguide software uses Source Extractor via the SEP Python Library for star detection. The \"Detect SNR\" and \"Detect Area\" values in the GUI correspond to the thresh and minarea parameters of sep.extract and to kpfguide.OBJECT_INTENSITY and kpfguide.OBJECT_AREA keyword respectively. The way the algorithm detects stars is to look for adjacent clusters of pixels with values above \"Detect SNR\". If that cluster is larger than \"Detect Area\" pixels, then it is a star. Both parameters are critical in determining whether a star will be detected. Having a large \"Detect Area\" means that faint stars will often not have enough bright pixels to be considered a detection. Similarly, a large \"Detect SNR\" might mean that not enough pixels are bright enough so too few pixels will be detections to be considered a star. On faint targets, both parameters may need to come down if only the very core of the star has significant signal in it. If you're having trouble in good seeing, make sure that \"Detect Area\" is not too large for the seeing. Based on experience, starting with values of 5-7 for \"Detect SNR\" and 80-100 for \"Detect Area\" are reasonable.","title":"Star Detection Algorithm"},{"location":"tiptiltinstructions/#deblending-multiple-stars","text":"Deblending is a term that comes from Source Extractor. It can be both perilous and useful. Early in the system\u2019s use, we were still using the default deblending contrast of 0.005, which meant that it took only a small dip in flux (0.5%) for two adjacent maxima to be considered two different objects. In practice, this meant that a single star would deblend in to multiple stars due to speckles moving about. As a result, the \u201cstar\u201d would appear to shift to one side or the other leading to sudden large corrections which would then be reversed a frame or two later when the speckles had shifted and the star was no longer deblended. This could affect several percent of all guide frames (in other words, the star was being jolted around by spurious detections several times per second). Of course, in situation where there are actually blended stars this is a useful tool. Double stars can be separated and a particular guide target chosen using this system. Based on our experience so far, leaving deblending contrast at 1.0 for most targets is the right choice. This demands that the valley between adjacent peaks be as deep as the highest peak (i.e. it goes to 0), so it turns deblending off. Since most targets are isolated stars with no close neighbors of similar brightness, this avoids the problem of tracking on speckles. If a double star is the target, decreasing the deblending contrast until it is reliably separates is the best strategy. Use the overlays in the image display to ensure that the target star has its own label and that label is centered properly on the star. If the label is not centered on the star, it might be blended with the companion which is puslling the \"center\" off toward the companion -- this is what we mean by blended stars. If the stars are blended, they must be deblended for KPF to accurately place one properly on the fiber. If the centroid is biased because the stars are not deblended you will end up with an RV effect due to the positioning of the star on the fiber being incorrect. The deblend contrast can be run down at 0.005 or lower to pull out a faint companion. Note that this is the contrast between the bright star and the faint \"gap\" between companions, so large contrast is not unexpected if the companion star is a few magnitudes fainter than the primary. For example, if the deblend contrast is 0.01 that is 5 magnitudes of contrast 2.5*log(0.01) , but that's not an unreasonable contrast for the gap if the companion star is just 2 or 3 magnitudes fainter than the primary. Also, because the algorithm is doing deblending, not trying to detect the companion as a separate object, we don't need to worry about the primary being too bright -- it is ok to saturate the primary to get the companion. Of course, a widely separated double star may be seen as two stars by the system if there is a \u201cgap\u201d between the two stars where the signal in the pixels is lower than the detection threshold. In this case, no deblending is necessary. Finally, if the star the observers are trying to acquire is too challenging and you are unable to make it work, you can ask the observer to click the \"Collect Guider Image Cube\" button on their OB GUI. This will save a brief sequence of guider images which can be analyzed offline to find out the best way to acquire that particular star (email the KPF SA to let them know to look at it). This does not help for the immediate observation, but will allow us to find the right solution for the next time this target or a similar one is observed.","title":"Deblending Multiple Stars"},{"location":"scripts/AnalyzeGridSearch/","text":"AnalyzeGridSearch Bases: KPFTranslatorFunction Description Tool to analyze engineering data taken by the engineering.GridSearch or engineering.Run2DGridSearch scripts. Parameters None Source code in kpf/engineering/analysis/AnalyzeGridSearch.py 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 class AnalyzeGridSearch ( KPFTranslatorFunction ): '''# Description Tool to analyze engineering data taken by the `engineering.GridSearch` or `engineering.Run2DGridSearch` scripts. # Parameters None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): for logfile in args . get ( 'logfile' ): analyze_grid_search ( logfile , fiber = args . get ( 'fiber' ), model_seeing = args . get ( 'seeing' ), xfit = args . get ( 'xfit' ), yfit = args . get ( 'yfit' ), generate_cred2 = args . get ( 'cred2' ), ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'logfile' , type = str , nargs = '*' , help = \"The logfile or files of the grid search runs to analyze\" ) ## add flags parser . add_argument ( \"--cred2\" , dest = \"cred2\" , default = False , action = \"store_true\" , help = \"Generate CRED2 plots? (default = False)\" ) ## add options parser . add_argument ( \"--fiber\" , dest = \"fiber\" , type = str , default = 'Science' , help = \"The fiber being examined (Science, Sky, or EMSky).\" ) parser . add_argument ( \"--seeing\" , dest = \"seeing\" , type = str , choices = [ '0.5' , '0.7' , '0.9' ], default = '0.7' , help = \"The seeing model to overlay on the fiber coupling plot.\" ) parser . add_argument ( \"--xfit\" , dest = \"xfit\" , type = float , default = 335.5 , help = \"The X pixel position to use as the center when overlaying the model.\" ) parser . add_argument ( \"--yfit\" , dest = \"yfit\" , type = float , default = 258 , help = \"The X pixel position to use as the center when overlaying the model.\" ) return super () . add_cmdline_args ( parser , cfg )","title":"AnalyzeGridSearch"},{"location":"scripts/AnalyzeGridSearch/#analyzegridsearch","text":"Bases: KPFTranslatorFunction","title":"AnalyzeGridSearch"},{"location":"scripts/AnalyzeGridSearch/#kpf.engineering.analysis.AnalyzeGridSearch.AnalyzeGridSearch--description","text":"Tool to analyze engineering data taken by the engineering.GridSearch or engineering.Run2DGridSearch scripts.","title":"Description"},{"location":"scripts/AnalyzeGridSearch/#kpf.engineering.analysis.AnalyzeGridSearch.AnalyzeGridSearch--parameters","text":"None Source code in kpf/engineering/analysis/AnalyzeGridSearch.py 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 class AnalyzeGridSearch ( KPFTranslatorFunction ): '''# Description Tool to analyze engineering data taken by the `engineering.GridSearch` or `engineering.Run2DGridSearch` scripts. # Parameters None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): for logfile in args . get ( 'logfile' ): analyze_grid_search ( logfile , fiber = args . get ( 'fiber' ), model_seeing = args . get ( 'seeing' ), xfit = args . get ( 'xfit' ), yfit = args . get ( 'yfit' ), generate_cred2 = args . get ( 'cred2' ), ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'logfile' , type = str , nargs = '*' , help = \"The logfile or files of the grid search runs to analyze\" ) ## add flags parser . add_argument ( \"--cred2\" , dest = \"cred2\" , default = False , action = \"store_true\" , help = \"Generate CRED2 plots? (default = False)\" ) ## add options parser . add_argument ( \"--fiber\" , dest = \"fiber\" , type = str , default = 'Science' , help = \"The fiber being examined (Science, Sky, or EMSky).\" ) parser . add_argument ( \"--seeing\" , dest = \"seeing\" , type = str , choices = [ '0.5' , '0.7' , '0.9' ], default = '0.7' , help = \"The seeing model to overlay on the fiber coupling plot.\" ) parser . add_argument ( \"--xfit\" , dest = \"xfit\" , type = float , default = 335.5 , help = \"The X pixel position to use as the center when overlaying the model.\" ) parser . add_argument ( \"--yfit\" , dest = \"yfit\" , type = float , default = 258 , help = \"The X pixel position to use as the center when overlaying the model.\" ) return super () . add_cmdline_args ( parser , cfg )","title":"Parameters"},{"location":"scripts/AnalyzeTipTiltPerformance/","text":"AnalyzeTipTiltPerformance Bases: KPFTranslatorFunction Description Generates a plot analyzing tip tilt performance for a single observation. Can take as input either an L0 file, in which case it will strip out the guider extension for use, or a guider \"cube\" file. Parameters None Source code in kpf/engineering/analysis/AnalyzeTipTiltPerformance.py 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 class AnalyzeTipTiltPerformance ( KPFTranslatorFunction ): '''# Description Generates a plot analyzing tip tilt performance for a single observation. Can take as input either an L0 file, in which case it will strip out the guider extension for use, or a guider \"cube\" file. # Parameters None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): viewer_command = find_viewer_command ( args ) for file in args . get ( 'files' ): file = Path ( file ) . expanduser () if file . exists () is False : log . error ( f \"Could not find file { args . get ( 'file' ) } \" ) plotfile = Path ( str ( file . name ) . replace ( '.fits' , '.png' )) plot_tiptilt_stats ( file , plotfile = plotfile , start = args . get ( 'start' , None ), end = args . get ( 'end' , None ), snr = args . get ( 'snr' , None ), minarea = args . get ( 'minarea' , None ), deblend_nthresh = args . get ( 'deblend_nthresh' , None ), deblend_cont = args . get ( 'deblend_cont' , None ), ) if viewer_command is not None : log . info ( f \"Opening { plotfile } using { viewer_command } \" ) proc = subprocess . Popen ([ viewer_command , f \" { plotfile } \" ]) if args . get ( 'gif' ) is True : giffile = Path ( str ( file . name ) . replace ( '.fits' , '.gif' )) generate_cube_gif ( file , giffile ) if viewer_command is not None : log . info ( f \"Opening { giffile } using { viewer_command } \" ) proc = subprocess . Popen ([ viewer_command , f \" { giffile } \" ]) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'files' , type = str , nargs = '*' , help = \"The FITS files to analyze\" ) parser . add_argument ( \"-g\" , \"--gif\" , dest = \"gif\" , default = False , action = \"store_true\" , help = \"Generate the animated GIF of frames (computationally expensive)\" ) parser . add_argument ( \"--view\" , dest = \"view\" , default = False , action = \"store_true\" , help = \"Open a viewer once the file is generated\" ) parser . add_argument ( \"--start\" , dest = \"start\" , type = float , help = \"Zoom the plot in to this start time (in seconds).\" ) parser . add_argument ( \"--end\" , dest = \"end\" , type = float , help = \"Zoom the plot in to this end time (in seconds).\" ) parser . add_argument ( \"--snr\" , dest = \"snr\" , type = float , help = \"Run source extractor again with this SNR threshold\" ) parser . add_argument ( \"--minarea\" , dest = \"minarea\" , type = float , help = \"Run source extractor again with this minarea parameter\" ) parser . add_argument ( \"--deblend_nthresh\" , dest = \"deblend_nthresh\" , type = float , help = \"Run source extractor again with this deblend_nthresh\" ) parser . add_argument ( \"--deblend_cont\" , dest = \"deblend_cont\" , type = float , help = \"Run source extractor again with this deblend_cont parameter\" ) return super () . add_cmdline_args ( parser , cfg )","title":"AnalyzeTipTiltPerformance"},{"location":"scripts/AnalyzeTipTiltPerformance/#analyzetiptiltperformance","text":"Bases: KPFTranslatorFunction","title":"AnalyzeTipTiltPerformance"},{"location":"scripts/AnalyzeTipTiltPerformance/#kpf.engineering.analysis.AnalyzeTipTiltPerformance.AnalyzeTipTiltPerformance--description","text":"Generates a plot analyzing tip tilt performance for a single observation. Can take as input either an L0 file, in which case it will strip out the guider extension for use, or a guider \"cube\" file.","title":"Description"},{"location":"scripts/AnalyzeTipTiltPerformance/#kpf.engineering.analysis.AnalyzeTipTiltPerformance.AnalyzeTipTiltPerformance--parameters","text":"None Source code in kpf/engineering/analysis/AnalyzeTipTiltPerformance.py 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 class AnalyzeTipTiltPerformance ( KPFTranslatorFunction ): '''# Description Generates a plot analyzing tip tilt performance for a single observation. Can take as input either an L0 file, in which case it will strip out the guider extension for use, or a guider \"cube\" file. # Parameters None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): viewer_command = find_viewer_command ( args ) for file in args . get ( 'files' ): file = Path ( file ) . expanduser () if file . exists () is False : log . error ( f \"Could not find file { args . get ( 'file' ) } \" ) plotfile = Path ( str ( file . name ) . replace ( '.fits' , '.png' )) plot_tiptilt_stats ( file , plotfile = plotfile , start = args . get ( 'start' , None ), end = args . get ( 'end' , None ), snr = args . get ( 'snr' , None ), minarea = args . get ( 'minarea' , None ), deblend_nthresh = args . get ( 'deblend_nthresh' , None ), deblend_cont = args . get ( 'deblend_cont' , None ), ) if viewer_command is not None : log . info ( f \"Opening { plotfile } using { viewer_command } \" ) proc = subprocess . Popen ([ viewer_command , f \" { plotfile } \" ]) if args . get ( 'gif' ) is True : giffile = Path ( str ( file . name ) . replace ( '.fits' , '.gif' )) generate_cube_gif ( file , giffile ) if viewer_command is not None : log . info ( f \"Opening { giffile } using { viewer_command } \" ) proc = subprocess . Popen ([ viewer_command , f \" { giffile } \" ]) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'files' , type = str , nargs = '*' , help = \"The FITS files to analyze\" ) parser . add_argument ( \"-g\" , \"--gif\" , dest = \"gif\" , default = False , action = \"store_true\" , help = \"Generate the animated GIF of frames (computationally expensive)\" ) parser . add_argument ( \"--view\" , dest = \"view\" , default = False , action = \"store_true\" , help = \"Open a viewer once the file is generated\" ) parser . add_argument ( \"--start\" , dest = \"start\" , type = float , help = \"Zoom the plot in to this start time (in seconds).\" ) parser . add_argument ( \"--end\" , dest = \"end\" , type = float , help = \"Zoom the plot in to this end time (in seconds).\" ) parser . add_argument ( \"--snr\" , dest = \"snr\" , type = float , help = \"Run source extractor again with this SNR threshold\" ) parser . add_argument ( \"--minarea\" , dest = \"minarea\" , type = float , help = \"Run source extractor again with this minarea parameter\" ) parser . add_argument ( \"--deblend_nthresh\" , dest = \"deblend_nthresh\" , type = float , help = \"Run source extractor again with this deblend_nthresh\" ) parser . add_argument ( \"--deblend_cont\" , dest = \"deblend_cont\" , type = float , help = \"Run source extractor again with this deblend_cont parameter\" ) return super () . add_cmdline_args ( parser , cfg )","title":"Parameters"},{"location":"scripts/BuildMasterBias/","text":"BuildMasterBias Bases: KPFTranslatorFunction Combine a set of bias files to make a master bias. Parameters: files ( list ) \u2013 A list of files to combine. output ( str ) \u2013 The output combined filename to write. KTL Keywords Used: kpf_expmeter.BIAS_FILE Source code in kpf/expmeter/BuildMasterBias.py 22 23 24 25 26 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 class BuildMasterBias ( KPFTranslatorFunction ): '''Combine a set of bias files to make a master bias. Args: files (list): A list of files to combine. output (str): The output combined filename to write. KTL Keywords Used: - `kpf_expmeter.BIAS_FILE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'files' , allowed_types = [ list ]) @classmethod def perform ( cls , args , logger , cfg ): biasfiles = [ Path ( biasfile ) for biasfile in args . get ( 'files' )] log . debug ( f \"Combining { len ( biasfiles ) } bias frames:\" ) biases = [] timestamps = [] for biasfile in biasfiles : log . debug ( f \" { biasfile . name } \" ) this_bias = CCDData . read ( biasfile , unit = \"adu\" ) biases . append ( this_bias ) timestamps . append ( this_bias [ 0 ] . header . get ( 'DATE-BEG' )) combiner = ccdproc . Combiner ( biases ) combiner . sigma_clipping ( low_thresh = 5 , high_thresh = 5 ) combined_average = combiner . average_combine () for i , timestamp in enumerate ( timestamps ): combined_average [ 0 ] . header [ f 'DATEBEG { i : 02d } ' ] = ( timestamp , 'DATE-BEG of file {i:02d} ' ) utnow = datetime . utcnow () combined_average [ 0 ] . header [ 'DATEMADE' ] = ( utnow . isoformat (), 'UT timestamp of file creation' ) if args . get ( 'output' , None ) not in [ None , '' ]: outputfile = Path ( args . get ( 'output' )) . expanduser () else : match_fn = re . match ( '([\\w\\d_]+)(\\d {6} )\\.(\\d {3} )\\.fits' , biasfiles [ 0 ] . name ) if match_fn is not None : frameno = match_fn . group ( 2 ) outputfile = Path ( f '/s/sdata1701/ExpMeterMasterFiles/MasterBias_ { frameno } .fits' ) else : now_str = utnow . strftime ( '%Y%m %d at%H%M%S' ) outputfile = Path ( f '/s/sdata1701/ExpMeterMasterFiles/MasterBias_ { now_str } .fits' ) log . info ( f \"Writing { outputfile } \" ) combined_average . write ( outputfile , overwrite = True ) if args . get ( 'update' , False ) is True : bias_file = ktl . cache ( 'kpf_expmeter' , 'BIAS_FILE' ) bias_file . write ( f \" { outputfile } \" ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'files' , nargs = '*' , help = \"The files to combine\" ) parser . add_argument ( \"--output\" , dest = \"output\" , type = str , default = '' , help = \"The output combined bias file.\" ) parser . add_argument ( \"--update\" , dest = \"update\" , default = False , action = \"store_true\" , help = \"Update the bias file in use with the newly generated file?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"BuildMasterBias"},{"location":"scripts/BuildMasterBias/#buildmasterbias","text":"Bases: KPFTranslatorFunction Combine a set of bias files to make a master bias. Parameters: files ( list ) \u2013 A list of files to combine. output ( str ) \u2013 The output combined filename to write. KTL Keywords Used: kpf_expmeter.BIAS_FILE Source code in kpf/expmeter/BuildMasterBias.py 22 23 24 25 26 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 class BuildMasterBias ( KPFTranslatorFunction ): '''Combine a set of bias files to make a master bias. Args: files (list): A list of files to combine. output (str): The output combined filename to write. KTL Keywords Used: - `kpf_expmeter.BIAS_FILE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'files' , allowed_types = [ list ]) @classmethod def perform ( cls , args , logger , cfg ): biasfiles = [ Path ( biasfile ) for biasfile in args . get ( 'files' )] log . debug ( f \"Combining { len ( biasfiles ) } bias frames:\" ) biases = [] timestamps = [] for biasfile in biasfiles : log . debug ( f \" { biasfile . name } \" ) this_bias = CCDData . read ( biasfile , unit = \"adu\" ) biases . append ( this_bias ) timestamps . append ( this_bias [ 0 ] . header . get ( 'DATE-BEG' )) combiner = ccdproc . Combiner ( biases ) combiner . sigma_clipping ( low_thresh = 5 , high_thresh = 5 ) combined_average = combiner . average_combine () for i , timestamp in enumerate ( timestamps ): combined_average [ 0 ] . header [ f 'DATEBEG { i : 02d } ' ] = ( timestamp , 'DATE-BEG of file {i:02d} ' ) utnow = datetime . utcnow () combined_average [ 0 ] . header [ 'DATEMADE' ] = ( utnow . isoformat (), 'UT timestamp of file creation' ) if args . get ( 'output' , None ) not in [ None , '' ]: outputfile = Path ( args . get ( 'output' )) . expanduser () else : match_fn = re . match ( '([\\w\\d_]+)(\\d {6} )\\.(\\d {3} )\\.fits' , biasfiles [ 0 ] . name ) if match_fn is not None : frameno = match_fn . group ( 2 ) outputfile = Path ( f '/s/sdata1701/ExpMeterMasterFiles/MasterBias_ { frameno } .fits' ) else : now_str = utnow . strftime ( '%Y%m %d at%H%M%S' ) outputfile = Path ( f '/s/sdata1701/ExpMeterMasterFiles/MasterBias_ { now_str } .fits' ) log . info ( f \"Writing { outputfile } \" ) combined_average . write ( outputfile , overwrite = True ) if args . get ( 'update' , False ) is True : bias_file = ktl . cache ( 'kpf_expmeter' , 'BIAS_FILE' ) bias_file . write ( f \" { outputfile } \" ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'files' , nargs = '*' , help = \"The files to combine\" ) parser . add_argument ( \"--output\" , dest = \"output\" , type = str , default = '' , help = \"The output combined bias file.\" ) parser . add_argument ( \"--update\" , dest = \"update\" , default = False , action = \"store_true\" , help = \"Update the bias file in use with the newly generated file?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"BuildMasterBias"},{"location":"scripts/BuildOBfromQuery/","text":"BuildOBfromQuery Bases: KPFTranslatorFunction Source code in kpf/utils/BuildOBfromQuery.py 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 class BuildOBfromQuery ( KPFTranslatorFunction ): ''' ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'GaiaID' ) @classmethod def perform ( cls , args , logger , cfg ): gaiaid = args . get ( 'GaiaID' ) observation = { 'ExpMeterMode' : \"monitor\" , 'AutoExpMeter' : \"False\" , 'TakeSimulCal' : \"True\" } OB = ScienceOB ({ 'GaiaID' : f \"DR3 { gaiaid } \" , 'SEQ_Observations' : [ observation ]}) # Get target name and 2MASS ID from Gaia ID names = get_names_from_gaiaid ( gaiaid ) if names is None : log . warning ( f \"Query for { gaiaid } failed to return names\" ) return OB . set ( 'TargetName' , f \" { names [ 'TargetName' ] } \" ) OB . set ( '2MASSID' , f \" { names [ '2MASSID' ] } \" ) # Using 2MASS ID query for Jmag twomass_params = get_Jmag ( names [ '2MASSID' ]) OB . set ( 'Jmag' , f \" { twomass_params [ 'Jmag' ] } \" ) # Using Gaia ID, query for Gaia parameters gaia_params = get_gaia_parameters ( gaiaid ) OB . set ( 'Parallax' , f \" { gaia_params [ 'Parallax' ] } \" ) OB . set ( 'RadialVelocity' , f \" { gaia_params [ 'RadialVelocity' ] } \" ) OB . set ( 'Gmag' , f \" { gaia_params [ 'Gmag' ] } \" ) OB . set ( 'Teff' , f \" { gaia_params [ 'Teff' ] } \" ) # Defaults OB . set ( 'GuideMode' , \"auto\" ) OB . set ( 'TriggerCaHK' , \"True\" ) OB . set ( 'TriggerGreen' , \"True\" ) OB . set ( 'TriggerRed' , \"True\" ) # Build Starlist line OB . star_list_line = form_starlist_line ( names [ 'TargetName' ], gaia_params [ 'RA_ICRS' ], gaia_params [ 'DE_ICRS' ], vmag = gaia_params [ 'Gmag' ]) print ( OB ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'GaiaID' , type = str , help = 'Gaia DR3 ID to query for (e.g. \"35227046884571776\")' ) return super () . add_cmdline_args ( parser , cfg )","title":"BuildOBfromQuery"},{"location":"scripts/BuildOBfromQuery/#buildobfromquery","text":"Bases: KPFTranslatorFunction Source code in kpf/utils/BuildOBfromQuery.py 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 class BuildOBfromQuery ( KPFTranslatorFunction ): ''' ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'GaiaID' ) @classmethod def perform ( cls , args , logger , cfg ): gaiaid = args . get ( 'GaiaID' ) observation = { 'ExpMeterMode' : \"monitor\" , 'AutoExpMeter' : \"False\" , 'TakeSimulCal' : \"True\" } OB = ScienceOB ({ 'GaiaID' : f \"DR3 { gaiaid } \" , 'SEQ_Observations' : [ observation ]}) # Get target name and 2MASS ID from Gaia ID names = get_names_from_gaiaid ( gaiaid ) if names is None : log . warning ( f \"Query for { gaiaid } failed to return names\" ) return OB . set ( 'TargetName' , f \" { names [ 'TargetName' ] } \" ) OB . set ( '2MASSID' , f \" { names [ '2MASSID' ] } \" ) # Using 2MASS ID query for Jmag twomass_params = get_Jmag ( names [ '2MASSID' ]) OB . set ( 'Jmag' , f \" { twomass_params [ 'Jmag' ] } \" ) # Using Gaia ID, query for Gaia parameters gaia_params = get_gaia_parameters ( gaiaid ) OB . set ( 'Parallax' , f \" { gaia_params [ 'Parallax' ] } \" ) OB . set ( 'RadialVelocity' , f \" { gaia_params [ 'RadialVelocity' ] } \" ) OB . set ( 'Gmag' , f \" { gaia_params [ 'Gmag' ] } \" ) OB . set ( 'Teff' , f \" { gaia_params [ 'Teff' ] } \" ) # Defaults OB . set ( 'GuideMode' , \"auto\" ) OB . set ( 'TriggerCaHK' , \"True\" ) OB . set ( 'TriggerGreen' , \"True\" ) OB . set ( 'TriggerRed' , \"True\" ) # Build Starlist line OB . star_list_line = form_starlist_line ( names [ 'TargetName' ], gaia_params [ 'RA_ICRS' ], gaia_params [ 'DE_ICRS' ], vmag = gaia_params [ 'Gmag' ]) print ( OB ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'GaiaID' , type = str , help = 'Gaia DR3 ID to query for (e.g. \"35227046884571776\")' ) return super () . add_cmdline_args ( parser , cfg )","title":"BuildOBfromQuery"},{"location":"scripts/CalLampPower/","text":"CalLampPower Bases: KPFTranslatorFunction Powers off one of the cal lamps via the kpflamps keyword service. Uses the lamp names from the OCTAGON when appropriate. Parameters: lamp ( str ) \u2013 Name of the lamp to control. Allowed Values: BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, WideFlat, ExpMeterLED, CaHKLED, SciLED, SkyLED power ( str ) \u2013 Destination state for lamp power. Allowed Values: \"on\" or \"off\". KTL Keywords Used: kpflamps.BRDBANDFIBER kpflamps.U_GOLD kpflamps.U_DAILY kpflamps.TH_DAILY kpflamps.TH_GOLD kpflamps.FF_FIBER kpflamps.EXPMLED kpflamps.HKLED kpflamps.SCILED kpflamps.SKYLED Source code in kpf/calbench/CalLampPower.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class CalLampPower ( KPFTranslatorFunction ): '''Powers off one of the cal lamps via the `kpflamps` keyword service. Uses the lamp names from the OCTAGON when appropriate. Args: lamp (str): Name of the lamp to control. Allowed Values: BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, WideFlat, ExpMeterLED, CaHKLED, SciLED, SkyLED power (str): Destination state for lamp power. Allowed Values: \"on\" or \"off\". KTL Keywords Used: - `kpflamps.BRDBANDFIBER` - `kpflamps.U_GOLD` - `kpflamps.U_DAILY` - `kpflamps.TH_DAILY` - `kpflamps.TH_GOLD` - `kpflamps.FF_FIBER` - `kpflamps.EXPMLED` - `kpflamps.HKLED` - `kpflamps.SCILED` - `kpflamps.SKYLED` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): # Check lamp name lamp = standardize_lamp_name ( args . get ( 'lamp' , None )) if lamp is None : msg = f \"Could not standardize lamp name { args . get ( 'lamp' ) } \" raise FailedPreCondition ( msg ) # Check power check_input ( args , 'power' , allowed_values = [ 'on' , 'off' ]) @classmethod def perform ( cls , args , logger , cfg ): lamp = standardize_lamp_name ( args . get ( 'lamp' )) pwr = args . get ( 'power' ) log . debug ( f \"Turning { pwr } { lamp } \" ) kpflamps = ktl . cache ( 'kpflamps' ) kpflamps [ lamp ] . write ( pwr ) @classmethod def post_condition ( cls , args , logger , cfg ): lamp = standardize_lamp_name ( args . get ( 'lamp' )) pwr = args . get ( 'power' ) timeout = cfg . getfloat ( 'times' , 'lamp_timeout' , fallback = 1 ) success = ktl . waitFor ( f \"($kpflamps. { lamp } == { pwr } )\" , timeout = timeout ) if success is not True : kpflamps = ktl . cache ( 'kpflamps' ) raise FailedPostCondition ( kpflamps [ lamp ], pwr ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'lamp' , type = str , choices = [ 'BrdbandFiber' , 'U_gold' , 'U_daily' , 'Th_daily' , 'Th_gold' , 'WideFlat' , 'ExpMeterLED' , 'CaHKLED' , 'SciLED' , 'SkyLED' ], help = 'Which lamp to control?' ) parser . add_argument ( 'power' , type = str , choices = [ 'on' , 'off' ], help = 'Desired power state: \"on\" or \"off\"' ) return super () . add_cmdline_args ( parser , cfg )","title":"CalLampPower"},{"location":"scripts/CalLampPower/#callamppower","text":"Bases: KPFTranslatorFunction Powers off one of the cal lamps via the kpflamps keyword service. Uses the lamp names from the OCTAGON when appropriate. Parameters: lamp ( str ) \u2013 Name of the lamp to control. Allowed Values: BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, WideFlat, ExpMeterLED, CaHKLED, SciLED, SkyLED power ( str ) \u2013 Destination state for lamp power. Allowed Values: \"on\" or \"off\". KTL Keywords Used: kpflamps.BRDBANDFIBER kpflamps.U_GOLD kpflamps.U_DAILY kpflamps.TH_DAILY kpflamps.TH_GOLD kpflamps.FF_FIBER kpflamps.EXPMLED kpflamps.HKLED kpflamps.SCILED kpflamps.SKYLED Source code in kpf/calbench/CalLampPower.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class CalLampPower ( KPFTranslatorFunction ): '''Powers off one of the cal lamps via the `kpflamps` keyword service. Uses the lamp names from the OCTAGON when appropriate. Args: lamp (str): Name of the lamp to control. Allowed Values: BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, WideFlat, ExpMeterLED, CaHKLED, SciLED, SkyLED power (str): Destination state for lamp power. Allowed Values: \"on\" or \"off\". KTL Keywords Used: - `kpflamps.BRDBANDFIBER` - `kpflamps.U_GOLD` - `kpflamps.U_DAILY` - `kpflamps.TH_DAILY` - `kpflamps.TH_GOLD` - `kpflamps.FF_FIBER` - `kpflamps.EXPMLED` - `kpflamps.HKLED` - `kpflamps.SCILED` - `kpflamps.SKYLED` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): # Check lamp name lamp = standardize_lamp_name ( args . get ( 'lamp' , None )) if lamp is None : msg = f \"Could not standardize lamp name { args . get ( 'lamp' ) } \" raise FailedPreCondition ( msg ) # Check power check_input ( args , 'power' , allowed_values = [ 'on' , 'off' ]) @classmethod def perform ( cls , args , logger , cfg ): lamp = standardize_lamp_name ( args . get ( 'lamp' )) pwr = args . get ( 'power' ) log . debug ( f \"Turning { pwr } { lamp } \" ) kpflamps = ktl . cache ( 'kpflamps' ) kpflamps [ lamp ] . write ( pwr ) @classmethod def post_condition ( cls , args , logger , cfg ): lamp = standardize_lamp_name ( args . get ( 'lamp' )) pwr = args . get ( 'power' ) timeout = cfg . getfloat ( 'times' , 'lamp_timeout' , fallback = 1 ) success = ktl . waitFor ( f \"($kpflamps. { lamp } == { pwr } )\" , timeout = timeout ) if success is not True : kpflamps = ktl . cache ( 'kpflamps' ) raise FailedPostCondition ( kpflamps [ lamp ], pwr ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'lamp' , type = str , choices = [ 'BrdbandFiber' , 'U_gold' , 'U_daily' , 'Th_daily' , 'Th_gold' , 'WideFlat' , 'ExpMeterLED' , 'CaHKLED' , 'SciLED' , 'SkyLED' ], help = 'Which lamp to control?' ) parser . add_argument ( 'power' , type = str , choices = [ 'on' , 'off' ], help = 'Desired power state: \"on\" or \"off\"' ) return super () . add_cmdline_args ( parser , cfg )","title":"CalLampPower"},{"location":"scripts/CalculateDAR/","text":"CalculateDAR Bases: KPFTranslatorFunction Return the DAR correction in arcseconds between the CRED2 wavelength and the science wavelength. Calculation from Filippenko 1982 (PASP, 94:715-721, August 1982) ARGS: :EL: float Elevation of the telescope. Source code in kpf/utils/CalculateDAR.py 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 class CalculateDAR ( KPFTranslatorFunction ): '''Return the DAR correction in arcseconds between the CRED2 wavelength and the science wavelength. Calculation from Filippenko 1982 (PASP, 94:715-721, August 1982) ARGS: ===== :EL: `float` Elevation of the telescope. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): dcs = ktl . cache ( 'dcs1' ) EL = dcs [ 'EL' ] . read ( binary = True ) * 180 / np . pi DARarcsec = calculate_DAR_arcsec ( EL ) log . info ( f \"Calculated DAR for { EL : .1f } EL = { DARarcsec : .3f } arcsec\" ) dx , dy = calculate_DAR_pix ( DARarcsec ) log . info ( f \"Pixel shift is { dx : .1f } , { dy : .1f } = { ( dx ** 2 + dy ** 2 ) ** 0.5 : .1f } \" ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"CalculateDAR"},{"location":"scripts/CalculateDAR/#calculatedar","text":"Bases: KPFTranslatorFunction Return the DAR correction in arcseconds between the CRED2 wavelength and the science wavelength. Calculation from Filippenko 1982 (PASP, 94:715-721, August 1982)","title":"CalculateDAR"},{"location":"scripts/CalculateDAR/#kpf.utils.CalculateDAR.CalculateDAR--args","text":":EL: float Elevation of the telescope. Source code in kpf/utils/CalculateDAR.py 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 class CalculateDAR ( KPFTranslatorFunction ): '''Return the DAR correction in arcseconds between the CRED2 wavelength and the science wavelength. Calculation from Filippenko 1982 (PASP, 94:715-721, August 1982) ARGS: ===== :EL: `float` Elevation of the telescope. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): dcs = ktl . cache ( 'dcs1' ) EL = dcs [ 'EL' ] . read ( binary = True ) * 180 / np . pi DARarcsec = calculate_DAR_arcsec ( EL ) log . info ( f \"Calculated DAR for { EL : .1f } EL = { DARarcsec : .3f } arcsec\" ) dx , dy = calculate_DAR_pix ( DARarcsec ) log . info ( f \"Pixel shift is { dx : .1f } , { dy : .1f } = { ( dx ** 2 + dy ** 2 ) ** 0.5 : .1f } \" ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"ARGS:"},{"location":"scripts/CheckDewarWeights/","text":"CheckDewarWeights Bases: KPFTranslatorFunction Check the weight of the red and green dewars and send email if they are lower than expected. ARGS: :dewar: str Which dewar to check? red or green :email: bool If True, send email if dewar weight is low Source code in kpf/utils/CheckDewarWeights.py 18 19 20 21 22 23 24 25 26 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 class CheckDewarWeights ( KPFTranslatorFunction ): '''Check the weight of the red and green dewars and send email if they are lower than expected. ARGS: ===== :dewar: `str` Which dewar to check? red or green :email: `bool` If True, send email if dewar weight is low ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): dewar = args . get ( 'dewar' , 'green' ) fill_time = cfg . getint ( 'LN2' , 'fill_time' , fallback = 21 ) low_weight = cfg . getint ( 'LN2' , f 'low_weight_ { dewar } ' , fallback = 90 ) use_rate = cfg . getint ( 'LN2' , f 'use_rate_ { dewar } ' , fallback = 40 ) utcnow = datetime . utcnow () if utcnow . hour < fill_time : time_until_fill = fill_time - ( utcnow . hour + utcnow . minute / 60 ) else : time_until_fill = fill_time + 24 - ( utcnow . hour + utcnow . minute / 60 ) kpffill = ktl . cache ( 'kpffill' ) weight = kpffill [ f ' { dewar } WEIGHT' ] . read ( binary = True ) weight_at_fill = weight - ( time_until_fill / 24 ) * use_rate if weight_at_fill > low_weight : # Dewar fill level is ok print ( 'Dewar weight is OK' ) else : # Dewar fill level is not ok print ( 'Dewar weight is low!' ) if args . get ( 'email' , False ) is True : try : msg = [ f 'KPF { dewar } dewar weight is low' , f '' , f 'Current dewar weight: { weight : .1f } ' , f 'Estimated weight at 11am fill: { weight_at_fill : .1f } ' , ] SendEmail . execute ({ 'Subject' : f 'KPF { dewar } dewar weight is low' , 'Message' : ' \\n ' . join ( msg )}) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'dewar' , type = str , choices = [ 'green' , 'red' ], default = 'green' , help = 'Which dewar to check? red or green' ) parser . add_argument ( '--email' , dest = \"email\" , default = False , action = \"store_true\" , help = 'Send email if dewar weight is low' ) return super () . add_cmdline_args ( parser , cfg )","title":"CheckDewarWeights"},{"location":"scripts/CheckDewarWeights/#checkdewarweights","text":"Bases: KPFTranslatorFunction Check the weight of the red and green dewars and send email if they are lower than expected.","title":"CheckDewarWeights"},{"location":"scripts/CheckDewarWeights/#kpf.utils.CheckDewarWeights.CheckDewarWeights--args","text":":dewar: str Which dewar to check? red or green :email: bool If True, send email if dewar weight is low Source code in kpf/utils/CheckDewarWeights.py 18 19 20 21 22 23 24 25 26 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 class CheckDewarWeights ( KPFTranslatorFunction ): '''Check the weight of the red and green dewars and send email if they are lower than expected. ARGS: ===== :dewar: `str` Which dewar to check? red or green :email: `bool` If True, send email if dewar weight is low ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): dewar = args . get ( 'dewar' , 'green' ) fill_time = cfg . getint ( 'LN2' , 'fill_time' , fallback = 21 ) low_weight = cfg . getint ( 'LN2' , f 'low_weight_ { dewar } ' , fallback = 90 ) use_rate = cfg . getint ( 'LN2' , f 'use_rate_ { dewar } ' , fallback = 40 ) utcnow = datetime . utcnow () if utcnow . hour < fill_time : time_until_fill = fill_time - ( utcnow . hour + utcnow . minute / 60 ) else : time_until_fill = fill_time + 24 - ( utcnow . hour + utcnow . minute / 60 ) kpffill = ktl . cache ( 'kpffill' ) weight = kpffill [ f ' { dewar } WEIGHT' ] . read ( binary = True ) weight_at_fill = weight - ( time_until_fill / 24 ) * use_rate if weight_at_fill > low_weight : # Dewar fill level is ok print ( 'Dewar weight is OK' ) else : # Dewar fill level is not ok print ( 'Dewar weight is low!' ) if args . get ( 'email' , False ) is True : try : msg = [ f 'KPF { dewar } dewar weight is low' , f '' , f 'Current dewar weight: { weight : .1f } ' , f 'Estimated weight at 11am fill: { weight_at_fill : .1f } ' , ] SendEmail . execute ({ 'Subject' : f 'KPF { dewar } dewar weight is low' , 'Message' : ' \\n ' . join ( msg )}) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'dewar' , type = str , choices = [ 'green' , 'red' ], default = 'green' , help = 'Which dewar to check? red or green' ) parser . add_argument ( '--email' , dest = \"email\" , default = False , action = \"store_true\" , help = 'Send email if dewar weight is low' ) return super () . add_cmdline_args ( parser , cfg )","title":"ARGS:"},{"location":"scripts/CleanupAfterCalibrations/","text":"CleanupAfterCalibrations Bases: KPFTranslatorFunction Script which cleans up after Cal OBs. This must have arguments as input, either from a file using the -f command line tool, or passed in from the execution engine. Can be called by ddoi_script_functions.post_observation_cleanup . ARGS: :OB: dict A fully specified calibration observing block (OB). Source code in kpf/scripts/CleanupAfterCalibrations.py 25 26 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 class CleanupAfterCalibrations ( KPFTranslatorFunction ): '''Script which cleans up after Cal OBs. This must have arguments as input, either from a file using the `-f` command line tool, or passed in from the execution engine. Can be called by `ddoi_script_functions.post_observation_cleanup`. ARGS: ===== :OB: `dict` A fully specified calibration observing block (OB). ''' @classmethod def pre_condition ( cls , OB , logger , cfg ): pass @classmethod def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in OB : if key not in [ 'SEQ_Darks' , 'SEQ_Calibrations' ]: log . debug ( f \" { key } : { OB [ key ] } \" ) else : log . debug ( f \" { key } :\" ) for entry in OB [ key ]: log . debug ( f \" { entry } \" ) log . info ( '-------------------------' ) # Power off lamps if OB . get ( 'leave_lamps_on' , False ) == True : log . info ( 'Not turning lamps off because command line option was invoked' ) else : sequence = OB . get ( 'SEQ_Calibrations' , None ) lamps = set ([ x [ 'CalSource' ] for x in sequence if x [ 'CalSource' ] != 'Home' ]) \\ if sequence is not None else [] for lamp in lamps : if IsCalSourceEnabled . execute ({ 'CalSource' : lamp }) == True : if lamp in [ 'Th_daily' , 'Th_gold' , 'U_daily' , 'U_gold' , 'BrdbandFiber' , 'WideFlat' ]: CalLampPower . execute ({ 'lamp' : lamp , 'power' : 'off' }) if lamp == 'LFCFiber' : SetLFCtoStandbyHigh . execute ({}) kpfconfig = ktl . cache ( 'kpfconfig' ) runagitator = kpfconfig [ 'USEAGITATOR' ] . read ( binary = True ) if runagitator is True : StopAgitator . execute ({}) log . info ( f \"Stowing FIU\" ) ConfigureFIU . execute ({ 'mode' : 'Stowed' }) # Turn off exposure meter controlled exposure log . debug ( 'Clearing kpf_expmeter.USETHRESHOLD' ) kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) kpf_expmeter [ 'USETHRESHOLD' ] . write ( 'No' ) # Set OBJECT back to empty string log . info ( 'Waiting for readout to finish' ) WaitForReady . execute ({}) SetObject . execute ({ 'Object' : '' }) # Clear target info SetTargetInfo . execute ({}) # Clear script keywords clear_script_keywords () # Write L0 file name to log if can WaitForL0File . execute ({}) @classmethod def post_condition ( cls , OB , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( '--leave_lamps_on' , dest = \"leave_lamps_on\" , default = False , action = \"store_true\" , help = 'Leave the lamps on after cleanup phase?' ) return super () . add_cmdline_args ( parser , cfg )","title":"CleanupAfterCalibrations"},{"location":"scripts/CleanupAfterCalibrations/#cleanupaftercalibrations","text":"Bases: KPFTranslatorFunction Script which cleans up after Cal OBs. This must have arguments as input, either from a file using the -f command line tool, or passed in from the execution engine. Can be called by ddoi_script_functions.post_observation_cleanup .","title":"CleanupAfterCalibrations"},{"location":"scripts/CleanupAfterCalibrations/#kpf.scripts.CleanupAfterCalibrations.CleanupAfterCalibrations--args","text":":OB: dict A fully specified calibration observing block (OB). Source code in kpf/scripts/CleanupAfterCalibrations.py 25 26 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 class CleanupAfterCalibrations ( KPFTranslatorFunction ): '''Script which cleans up after Cal OBs. This must have arguments as input, either from a file using the `-f` command line tool, or passed in from the execution engine. Can be called by `ddoi_script_functions.post_observation_cleanup`. ARGS: ===== :OB: `dict` A fully specified calibration observing block (OB). ''' @classmethod def pre_condition ( cls , OB , logger , cfg ): pass @classmethod def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in OB : if key not in [ 'SEQ_Darks' , 'SEQ_Calibrations' ]: log . debug ( f \" { key } : { OB [ key ] } \" ) else : log . debug ( f \" { key } :\" ) for entry in OB [ key ]: log . debug ( f \" { entry } \" ) log . info ( '-------------------------' ) # Power off lamps if OB . get ( 'leave_lamps_on' , False ) == True : log . info ( 'Not turning lamps off because command line option was invoked' ) else : sequence = OB . get ( 'SEQ_Calibrations' , None ) lamps = set ([ x [ 'CalSource' ] for x in sequence if x [ 'CalSource' ] != 'Home' ]) \\ if sequence is not None else [] for lamp in lamps : if IsCalSourceEnabled . execute ({ 'CalSource' : lamp }) == True : if lamp in [ 'Th_daily' , 'Th_gold' , 'U_daily' , 'U_gold' , 'BrdbandFiber' , 'WideFlat' ]: CalLampPower . execute ({ 'lamp' : lamp , 'power' : 'off' }) if lamp == 'LFCFiber' : SetLFCtoStandbyHigh . execute ({}) kpfconfig = ktl . cache ( 'kpfconfig' ) runagitator = kpfconfig [ 'USEAGITATOR' ] . read ( binary = True ) if runagitator is True : StopAgitator . execute ({}) log . info ( f \"Stowing FIU\" ) ConfigureFIU . execute ({ 'mode' : 'Stowed' }) # Turn off exposure meter controlled exposure log . debug ( 'Clearing kpf_expmeter.USETHRESHOLD' ) kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) kpf_expmeter [ 'USETHRESHOLD' ] . write ( 'No' ) # Set OBJECT back to empty string log . info ( 'Waiting for readout to finish' ) WaitForReady . execute ({}) SetObject . execute ({ 'Object' : '' }) # Clear target info SetTargetInfo . execute ({}) # Clear script keywords clear_script_keywords () # Write L0 file name to log if can WaitForL0File . execute ({}) @classmethod def post_condition ( cls , OB , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( '--leave_lamps_on' , dest = \"leave_lamps_on\" , default = False , action = \"store_true\" , help = 'Leave the lamps on after cleanup phase?' ) return super () . add_cmdline_args ( parser , cfg )","title":"ARGS:"},{"location":"scripts/CleanupAfterScience/","text":"CleanupAfterScience Bases: KPFTranslatorFunction Script which cleans up at the end of Science OBs. Can be called by ddoi_script_functions.post_observation_cleanup . ARGS: :OB: dict A fully specified science observing block (OB). Source code in kpf/scripts/CleanupAfterScience.py 15 16 17 18 19 20 21 22 23 24 25 26 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 class CleanupAfterScience ( KPFTranslatorFunction ): '''Script which cleans up at the end of Science OBs. Can be called by `ddoi_script_functions.post_observation_cleanup`. ARGS: ===== :OB: `dict` A fully specified science observing block (OB). ''' @classmethod def pre_condition ( cls , OB , logger , cfg ): pass @classmethod def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) log . info ( '-------------------------' ) StopTipTilt . execute ({}) kpfconfig = ktl . cache ( 'kpfconfig' ) runagitator = kpfconfig [ 'USEAGITATOR' ] . read ( binary = True ) if runagitator is True : StopAgitator . execute ({}) # Clear target info log . debug ( 'Clearing target info' ) SetTargetInfo . execute ({}) # Turn off exposure meter controlled exposure log . debug ( 'Clearing kpf_expmeter.USETHRESHOLD' ) kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) kpf_expmeter [ 'USETHRESHOLD' ] . write ( 'No' ) # Set SKY_OFFSET back to 0 0 log . debug ( 'Clearing kpfguide.SKY_OFFSET' ) sky_offset = ktl . cache ( 'kpfguide' , 'SKY_OFFSET' ) sky_offset . write ( '0 0' ) clear_script_keywords () @classmethod def post_condition ( cls , OB , logger , cfg ): pass","title":"CleanupAfterScience"},{"location":"scripts/CleanupAfterScience/#cleanupafterscience","text":"Bases: KPFTranslatorFunction Script which cleans up at the end of Science OBs. Can be called by ddoi_script_functions.post_observation_cleanup .","title":"CleanupAfterScience"},{"location":"scripts/CleanupAfterScience/#kpf.scripts.CleanupAfterScience.CleanupAfterScience--args","text":":OB: dict A fully specified science observing block (OB). Source code in kpf/scripts/CleanupAfterScience.py 15 16 17 18 19 20 21 22 23 24 25 26 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 class CleanupAfterScience ( KPFTranslatorFunction ): '''Script which cleans up at the end of Science OBs. Can be called by `ddoi_script_functions.post_observation_cleanup`. ARGS: ===== :OB: `dict` A fully specified science observing block (OB). ''' @classmethod def pre_condition ( cls , OB , logger , cfg ): pass @classmethod def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) log . info ( '-------------------------' ) StopTipTilt . execute ({}) kpfconfig = ktl . cache ( 'kpfconfig' ) runagitator = kpfconfig [ 'USEAGITATOR' ] . read ( binary = True ) if runagitator is True : StopAgitator . execute ({}) # Clear target info log . debug ( 'Clearing target info' ) SetTargetInfo . execute ({}) # Turn off exposure meter controlled exposure log . debug ( 'Clearing kpf_expmeter.USETHRESHOLD' ) kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) kpf_expmeter [ 'USETHRESHOLD' ] . write ( 'No' ) # Set SKY_OFFSET back to 0 0 log . debug ( 'Clearing kpfguide.SKY_OFFSET' ) sky_offset = ktl . cache ( 'kpfguide' , 'SKY_OFFSET' ) sky_offset . write ( '0 0' ) clear_script_keywords () @classmethod def post_condition ( cls , OB , logger , cfg ): pass","title":"ARGS:"},{"location":"scripts/CollectGuiderDarkCubes/","text":"CollectGuiderDarkCubes Bases: KPFTranslatorFunction Obtains CRED2 \"trigger file\" data cubes under dark conditions at each of the three gain settings for the detector. Sequence: - Set FIU to Stowed - Set kpfguide.SENSORSETP = -40 - Wait for temperature to reach target - modify -s kpfexpose SRC_SHUTTERS='' - Set FPS = 100 - Set GAIN = High - Take 10s trigger cube - Set GAIN = High - Take 10s trigger cube - Set GAIN = Low - Take 10s trigger cube - Set kpfguide.SENSORSETP = 0 ARGS: None Source code in kpf/scripts/CollectGuiderDarkCubes.py 19 20 21 22 23 24 25 26 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 class CollectGuiderDarkCubes ( KPFTranslatorFunction ): '''Obtains CRED2 \"trigger file\" data cubes under dark conditions at each of the three gain settings for the detector. Sequence: - Set FIU to Stowed - Set kpfguide.SENSORSETP = -40 - Wait for temperature to reach target - modify -s kpfexpose SRC_SHUTTERS='' - Set FPS = 100 - Set GAIN = High - Take 10s trigger cube - Set GAIN = High - Take 10s trigger cube - Set GAIN = Low - Take 10s trigger cube - Set kpfguide.SENSORSETP = 0 ARGS: ===== None ''' @classmethod @obey_scriptrun def pre_condition ( cls , args , logger , cfg ): pass @classmethod @register_script ( Path ( __file__ ) . name , os . getpid ()) @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , args , logger , cfg ): output_file = Path ( '/s/sdata1701/CRED2DarkCubes/CRED2_dark_cubes.txt' ) OUTDIR = ktl . cache ( 'kpfguide' , 'OUTDIR' ) original_OUTDIR = OUTDIR . read () new_OUTDIR = str ( output_file . parent ) log . debug ( f 'Setting OUTDIR to { new_OUTDIR } ' ) OUTDIR . write ( new_OUTDIR ) SENSORSETP = ktl . cache ( 'kpfguide' , 'SENSORSETP' ) SENSORTEMP = ktl . cache ( 'kpfguide' , 'SENSORTEMP' ) CONTINUOUS = ktl . cache ( 'kpfguide' , 'CONTINUOUS' ) kpfguide = ktl . cache ( 'kpfguide' ) try : log . info ( 'Taking CRED2 dark cubes' ) ConfigureFIU . execute ({ 'mode' : 'Stowed' }) log . info ( 'Cooling CRED2' ) SENSORSETP . write ( - 40 ) log . info ( 'Waiting up to 10 minutes for detector to reach set point' ) reached_temp = SENSORTEMP . waitFor ( \"<-39.9\" , timeout = 600 ) if reached_temp == False : log . error ( 'CRED2 failed to reach set point. Exiting.' ) SENSORSETP . write ( 0 ) return check_scriptstop () log . debug ( 'Waiting additional time for temperature to stabilize' ) time . sleep ( 60 ) # shim to give time to stabilize check_scriptstop () log . debug ( 'Closing source shutters' ) SetSourceSelectShutters . execute ({}) CONTINUOUS . write ( 'Active' ) SetGuiderFPS . execute ({ 'GuideFPS' : 100 }) for gain in [ 'high' , 'medium' , 'low' ]: log . info ( f 'Collecting { gain } gain cube' ) SetGuiderGain . execute ({ 'GuideCamGain' : gain }) cube_file = TakeGuiderCube . execute ({ 'duration' : 10 }) with open ( output_file , 'a' ) as f : f . write ( f \" { gain : 12s } , { cube_file } \\n \" ) check_scriptstop () time . sleep ( 30 ) # shim to give time to recover after writing cube check_scriptstop () for gain in [ 'high' , 'medium' , 'low' ]: sub_file = kpfguide [ f 'SUB_ { gain . upper () } ' ] . read () kpfguide [ f 'SUB_ { gain . upper () } ' ] . write ( '' ) log . info ( f 'Collecting { gain } gain cube without bias subtraction' ) SetGuiderGain . execute ({ 'GuideCamGain' : gain }) cube_file = TakeGuiderCube . execute ({ 'duration' : 10 }) with open ( output_file , 'a' ) as f : gain_string = f ' { gain } _nosub' f . write ( f \" { gain_string : 12s } , { cube_file } \\n \" ) kpfguide [ f 'SUB_ { gain . upper () } ' ] . write ( sub_file ) check_scriptstop () time . sleep ( 30 ) # shim to give time to recover after writing cube check_scriptstop () except Exception as e : log . error ( 'Error running CollectGuiderDarkCubes' ) log . debug ( e ) log . info ( 'Resetting CRED2 temperature set point to 0' ) SENSORSETP . write ( 0 ) log . debug ( f 'Setting OUTDIR to { original_OUTDIR } ' ) OUTDIR . write ( original_OUTDIR ) clear_script_keywords () @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"CollectGuiderDarkCubes"},{"location":"scripts/CollectGuiderDarkCubes/#collectguiderdarkcubes","text":"Bases: KPFTranslatorFunction Obtains CRED2 \"trigger file\" data cubes under dark conditions at each of the three gain settings for the detector. Sequence: - Set FIU to Stowed - Set kpfguide.SENSORSETP = -40 - Wait for temperature to reach target - modify -s kpfexpose SRC_SHUTTERS='' - Set FPS = 100 - Set GAIN = High - Take 10s trigger cube - Set GAIN = High - Take 10s trigger cube - Set GAIN = Low - Take 10s trigger cube - Set kpfguide.SENSORSETP = 0","title":"CollectGuiderDarkCubes"},{"location":"scripts/CollectGuiderDarkCubes/#kpf.scripts.CollectGuiderDarkCubes.CollectGuiderDarkCubes--args","text":"None Source code in kpf/scripts/CollectGuiderDarkCubes.py 19 20 21 22 23 24 25 26 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 class CollectGuiderDarkCubes ( KPFTranslatorFunction ): '''Obtains CRED2 \"trigger file\" data cubes under dark conditions at each of the three gain settings for the detector. Sequence: - Set FIU to Stowed - Set kpfguide.SENSORSETP = -40 - Wait for temperature to reach target - modify -s kpfexpose SRC_SHUTTERS='' - Set FPS = 100 - Set GAIN = High - Take 10s trigger cube - Set GAIN = High - Take 10s trigger cube - Set GAIN = Low - Take 10s trigger cube - Set kpfguide.SENSORSETP = 0 ARGS: ===== None ''' @classmethod @obey_scriptrun def pre_condition ( cls , args , logger , cfg ): pass @classmethod @register_script ( Path ( __file__ ) . name , os . getpid ()) @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , args , logger , cfg ): output_file = Path ( '/s/sdata1701/CRED2DarkCubes/CRED2_dark_cubes.txt' ) OUTDIR = ktl . cache ( 'kpfguide' , 'OUTDIR' ) original_OUTDIR = OUTDIR . read () new_OUTDIR = str ( output_file . parent ) log . debug ( f 'Setting OUTDIR to { new_OUTDIR } ' ) OUTDIR . write ( new_OUTDIR ) SENSORSETP = ktl . cache ( 'kpfguide' , 'SENSORSETP' ) SENSORTEMP = ktl . cache ( 'kpfguide' , 'SENSORTEMP' ) CONTINUOUS = ktl . cache ( 'kpfguide' , 'CONTINUOUS' ) kpfguide = ktl . cache ( 'kpfguide' ) try : log . info ( 'Taking CRED2 dark cubes' ) ConfigureFIU . execute ({ 'mode' : 'Stowed' }) log . info ( 'Cooling CRED2' ) SENSORSETP . write ( - 40 ) log . info ( 'Waiting up to 10 minutes for detector to reach set point' ) reached_temp = SENSORTEMP . waitFor ( \"<-39.9\" , timeout = 600 ) if reached_temp == False : log . error ( 'CRED2 failed to reach set point. Exiting.' ) SENSORSETP . write ( 0 ) return check_scriptstop () log . debug ( 'Waiting additional time for temperature to stabilize' ) time . sleep ( 60 ) # shim to give time to stabilize check_scriptstop () log . debug ( 'Closing source shutters' ) SetSourceSelectShutters . execute ({}) CONTINUOUS . write ( 'Active' ) SetGuiderFPS . execute ({ 'GuideFPS' : 100 }) for gain in [ 'high' , 'medium' , 'low' ]: log . info ( f 'Collecting { gain } gain cube' ) SetGuiderGain . execute ({ 'GuideCamGain' : gain }) cube_file = TakeGuiderCube . execute ({ 'duration' : 10 }) with open ( output_file , 'a' ) as f : f . write ( f \" { gain : 12s } , { cube_file } \\n \" ) check_scriptstop () time . sleep ( 30 ) # shim to give time to recover after writing cube check_scriptstop () for gain in [ 'high' , 'medium' , 'low' ]: sub_file = kpfguide [ f 'SUB_ { gain . upper () } ' ] . read () kpfguide [ f 'SUB_ { gain . upper () } ' ] . write ( '' ) log . info ( f 'Collecting { gain } gain cube without bias subtraction' ) SetGuiderGain . execute ({ 'GuideCamGain' : gain }) cube_file = TakeGuiderCube . execute ({ 'duration' : 10 }) with open ( output_file , 'a' ) as f : gain_string = f ' { gain } _nosub' f . write ( f \" { gain_string : 12s } , { cube_file } \\n \" ) kpfguide [ f 'SUB_ { gain . upper () } ' ] . write ( sub_file ) check_scriptstop () time . sleep ( 30 ) # shim to give time to recover after writing cube check_scriptstop () except Exception as e : log . error ( 'Error running CollectGuiderDarkCubes' ) log . debug ( e ) log . info ( 'Resetting CRED2 temperature set point to 0' ) SENSORSETP . write ( 0 ) log . debug ( f 'Setting OUTDIR to { original_OUTDIR } ' ) OUTDIR . write ( original_OUTDIR ) clear_script_keywords () @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"ARGS:"},{"location":"scripts/ConfigureFIU/","text":"ConfigureFIU Bases: KPFTranslatorFunction Set the FIU mode (kpffiu.MODE). If the wait option is fale this will retry the move if it fails with a configurable number of retries. Parameters: mode ( str ) \u2013 The desired FIU mode. Allowed values: Stowed, Alignment, Acquisition, Observing, Calibration wait ( bool ) \u2013 Wait for move to complete before returning? (default: True) KTL Keywords Used: kpffiu.MODE Scripts Called: kpf.calbench.ConfigureFIUOnce kpf.calbench.WaitForConfigureFIU Source code in kpf/fiu/ConfigureFIU.py 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class ConfigureFIU ( KPFTranslatorFunction ): '''Set the FIU mode (kpffiu.MODE). If the wait option is fale this will retry the move if it fails with a configurable number of retries. Args: mode (str): The desired FIU mode. Allowed values: Stowed, Alignment, Acquisition, Observing, Calibration wait (bool): Wait for move to complete before returning? (default: True) KTL Keywords Used: - `kpffiu.MODE` Scripts Called: - `kpf.calbench.ConfigureFIUOnce` - `kpf.calbench.WaitForConfigureFIU` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpffiu' , 'MODE' ) allowed_values = list ( keyword . _getEnumerators ()) if 'None' in allowed_values : allowed_values . pop ( allowed_values . index ( 'None' )) check_input ( args , 'mode' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): dest = args . get ( 'mode' ) wait = args . get ( 'wait' , True ) log . info ( f \"Configuring FIU for { dest } \" ) ConfigureFIUOnce . execute ({ 'mode' : dest , 'wait' : wait }) if wait == True : WaitForConfigureFIU . execute ({ 'mode' : dest }) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'mode' , type = str , choices = [ 'Stowed' , 'Alignment' , 'Acquisition' , 'Observing' , 'Calibration' ], help = 'Desired mode (see kpffiu.MODE)' ) parser . add_argument ( \"--nowait\" , dest = \"wait\" , default = True , action = \"store_false\" , help = \"Send move and return immediately?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"ConfigureFIU"},{"location":"scripts/ConfigureFIU/#configurefiu","text":"Bases: KPFTranslatorFunction Set the FIU mode (kpffiu.MODE). If the wait option is fale this will retry the move if it fails with a configurable number of retries. Parameters: mode ( str ) \u2013 The desired FIU mode. Allowed values: Stowed, Alignment, Acquisition, Observing, Calibration wait ( bool ) \u2013 Wait for move to complete before returning? (default: True) KTL Keywords Used: kpffiu.MODE Scripts Called: kpf.calbench.ConfigureFIUOnce kpf.calbench.WaitForConfigureFIU Source code in kpf/fiu/ConfigureFIU.py 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class ConfigureFIU ( KPFTranslatorFunction ): '''Set the FIU mode (kpffiu.MODE). If the wait option is fale this will retry the move if it fails with a configurable number of retries. Args: mode (str): The desired FIU mode. Allowed values: Stowed, Alignment, Acquisition, Observing, Calibration wait (bool): Wait for move to complete before returning? (default: True) KTL Keywords Used: - `kpffiu.MODE` Scripts Called: - `kpf.calbench.ConfigureFIUOnce` - `kpf.calbench.WaitForConfigureFIU` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpffiu' , 'MODE' ) allowed_values = list ( keyword . _getEnumerators ()) if 'None' in allowed_values : allowed_values . pop ( allowed_values . index ( 'None' )) check_input ( args , 'mode' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): dest = args . get ( 'mode' ) wait = args . get ( 'wait' , True ) log . info ( f \"Configuring FIU for { dest } \" ) ConfigureFIUOnce . execute ({ 'mode' : dest , 'wait' : wait }) if wait == True : WaitForConfigureFIU . execute ({ 'mode' : dest }) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'mode' , type = str , choices = [ 'Stowed' , 'Alignment' , 'Acquisition' , 'Observing' , 'Calibration' ], help = 'Desired mode (see kpffiu.MODE)' ) parser . add_argument ( \"--nowait\" , dest = \"wait\" , default = True , action = \"store_false\" , help = \"Send move and return immediately?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"ConfigureFIU"},{"location":"scripts/ConfigureForAcquisition/","text":"ConfigureForAcquisition Bases: KPFTranslatorFunction Script which configures the instrument for Acquisition step. Sets target parameters Sets FIU mode Executes Slew Cal This must have arguments as input, either from a file using the -f command line tool, or passed in from the execution engine. ARGS: :OB: dict A fully specified science observing block (OB). Source code in kpf/scripts/ConfigureForAcquisition.py 22 23 24 25 26 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 class ConfigureForAcquisition ( KPFTranslatorFunction ): '''Script which configures the instrument for Acquisition step. - Sets target parameters - Sets FIU mode - Executes Slew Cal This must have arguments as input, either from a file using the `-f` command line tool, or passed in from the execution engine. ARGS: ===== :OB: `dict` A fully specified science observing block (OB). ''' @classmethod @obey_scriptrun def pre_condition ( cls , OB , logger , cfg ): check_input ( OB , 'Template_Name' , allowed_values = [ 'kpf_sci' ]) check_input ( OB , 'Template_Version' , version_check = True , value_min = '0.5' ) # Check Slewcals kpfconfig = ktl . cache ( 'kpfconfig' ) if kpfconfig [ 'SLEWCALREQ' ] . read ( binary = True ) is True : slewcal_argsfile = Path ( kpfconfig [ 'SLEWCALFILE' ] . read ()) if slewcal_argsfile . exists () is False : raise FailedPreCondition ( f \"Slew cal file { slewcal_argsfile } does not exist\" ) @classmethod def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in OB : if key not in [ 'SEQ_Observations' ]: log . debug ( f \" { key } : { OB [ key ] } \" ) else : log . debug ( f \" { key } :\" ) for entry in OB [ key ]: log . debug ( f \" { entry } \" ) log . info ( '-------------------------' ) kpfconfig = ktl . cache ( 'kpfconfig' ) kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) # Set Octagon kpfconfig = ktl . cache ( 'kpfconfig' ) calsource = kpfconfig [ 'SIMULCALSOURCE' ] . read () octagon = ktl . cache ( 'kpfcal' , 'OCTAGON' ) . read () log . debug ( f \"Current OCTAGON = { octagon } , desired = { calsource } \" ) if octagon != calsource : log . info ( f \"Set CalSource/Octagon: { calsource } \" ) SetCalSource . execute ({ 'CalSource' : calsource , 'wait' : False }) ## Execute Slew Cal if Requested if kpfconfig [ 'SLEWCALREQ' ] . read ( binary = True ) is True : slewcal_argsfile = Path ( kpfconfig [ 'SLEWCALFILE' ] . read ()) log . info ( f \"Beginning Slew Cal\" ) log . debug ( f \"Using: { slewcal_argsfile } \" ) with open ( slewcal_argsfile , 'r' ) as file : slewcal_OB = yaml . safe_load ( file ) slewcal_args = slewcal_OB . get ( 'SEQ_Calibrations' )[ 0 ] slewcal_args [ 'Template_Name' ] = 'kpf_slewcal' slewcal_args [ 'Template_Version' ] = '0.5' slewcal_args [ 'TriggerCaHK' ] = OB [ 'TriggerCaHK' ] slewcal_args [ 'TriggerGreen' ] = OB [ 'TriggerGreen' ] slewcal_args [ 'TriggerRed' ] = OB [ 'TriggerRed' ] ExecuteSlewCal . execute ( slewcal_args ) log . info ( 'Slew cal complete. Resetting SLEWCALREQ' ) kpfconfig [ 'SLEWCALREQ' ] . write ( 'No' ) # Set FIU Mode log . info ( 'Setting FIU mode to Observing' ) ConfigureFIU . execute ({ 'mode' : 'Observing' , 'wait' : False }) # Set Target Parameters from OB SetTargetInfo . execute ( OB ) @classmethod def post_condition ( cls , OB , logger , cfg ): pass","title":"ConfigureForAcquisition"},{"location":"scripts/ConfigureForAcquisition/#configureforacquisition","text":"Bases: KPFTranslatorFunction Script which configures the instrument for Acquisition step. Sets target parameters Sets FIU mode Executes Slew Cal This must have arguments as input, either from a file using the -f command line tool, or passed in from the execution engine.","title":"ConfigureForAcquisition"},{"location":"scripts/ConfigureForAcquisition/#kpf.scripts.ConfigureForAcquisition.ConfigureForAcquisition--args","text":":OB: dict A fully specified science observing block (OB). Source code in kpf/scripts/ConfigureForAcquisition.py 22 23 24 25 26 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 class ConfigureForAcquisition ( KPFTranslatorFunction ): '''Script which configures the instrument for Acquisition step. - Sets target parameters - Sets FIU mode - Executes Slew Cal This must have arguments as input, either from a file using the `-f` command line tool, or passed in from the execution engine. ARGS: ===== :OB: `dict` A fully specified science observing block (OB). ''' @classmethod @obey_scriptrun def pre_condition ( cls , OB , logger , cfg ): check_input ( OB , 'Template_Name' , allowed_values = [ 'kpf_sci' ]) check_input ( OB , 'Template_Version' , version_check = True , value_min = '0.5' ) # Check Slewcals kpfconfig = ktl . cache ( 'kpfconfig' ) if kpfconfig [ 'SLEWCALREQ' ] . read ( binary = True ) is True : slewcal_argsfile = Path ( kpfconfig [ 'SLEWCALFILE' ] . read ()) if slewcal_argsfile . exists () is False : raise FailedPreCondition ( f \"Slew cal file { slewcal_argsfile } does not exist\" ) @classmethod def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in OB : if key not in [ 'SEQ_Observations' ]: log . debug ( f \" { key } : { OB [ key ] } \" ) else : log . debug ( f \" { key } :\" ) for entry in OB [ key ]: log . debug ( f \" { entry } \" ) log . info ( '-------------------------' ) kpfconfig = ktl . cache ( 'kpfconfig' ) kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) # Set Octagon kpfconfig = ktl . cache ( 'kpfconfig' ) calsource = kpfconfig [ 'SIMULCALSOURCE' ] . read () octagon = ktl . cache ( 'kpfcal' , 'OCTAGON' ) . read () log . debug ( f \"Current OCTAGON = { octagon } , desired = { calsource } \" ) if octagon != calsource : log . info ( f \"Set CalSource/Octagon: { calsource } \" ) SetCalSource . execute ({ 'CalSource' : calsource , 'wait' : False }) ## Execute Slew Cal if Requested if kpfconfig [ 'SLEWCALREQ' ] . read ( binary = True ) is True : slewcal_argsfile = Path ( kpfconfig [ 'SLEWCALFILE' ] . read ()) log . info ( f \"Beginning Slew Cal\" ) log . debug ( f \"Using: { slewcal_argsfile } \" ) with open ( slewcal_argsfile , 'r' ) as file : slewcal_OB = yaml . safe_load ( file ) slewcal_args = slewcal_OB . get ( 'SEQ_Calibrations' )[ 0 ] slewcal_args [ 'Template_Name' ] = 'kpf_slewcal' slewcal_args [ 'Template_Version' ] = '0.5' slewcal_args [ 'TriggerCaHK' ] = OB [ 'TriggerCaHK' ] slewcal_args [ 'TriggerGreen' ] = OB [ 'TriggerGreen' ] slewcal_args [ 'TriggerRed' ] = OB [ 'TriggerRed' ] ExecuteSlewCal . execute ( slewcal_args ) log . info ( 'Slew cal complete. Resetting SLEWCALREQ' ) kpfconfig [ 'SLEWCALREQ' ] . write ( 'No' ) # Set FIU Mode log . info ( 'Setting FIU mode to Observing' ) ConfigureFIU . execute ({ 'mode' : 'Observing' , 'wait' : False }) # Set Target Parameters from OB SetTargetInfo . execute ( OB ) @classmethod def post_condition ( cls , OB , logger , cfg ): pass","title":"ARGS:"},{"location":"scripts/ConfigureForCalibrations/","text":"ConfigureForCalibrations Bases: KPFTranslatorFunction Script which configures the instrument for Cal OBs. This must have arguments as input, either from a file using the -f command line tool, or passed in from the execution engine. Can be called by ddoi_script_functions.configure_for_science . ARGS: :OB: dict A fully specified calibration observing block (OB). Source code in kpf/scripts/ConfigureForCalibrations.py 21 22 23 24 25 26 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 class ConfigureForCalibrations ( KPFTranslatorFunction ): '''Script which configures the instrument for Cal OBs. This must have arguments as input, either from a file using the `-f` command line tool, or passed in from the execution engine. Can be called by `ddoi_script_functions.configure_for_science`. ARGS: ===== :OB: `dict` A fully specified calibration observing block (OB). ''' @classmethod @obey_scriptrun def pre_condition ( cls , OB , logger , cfg ): check_input ( OB , 'Template_Name' , allowed_values = [ 'kpf_cal' ]) check_input ( OB , 'Template_Version' , version_check = True , value_min = '0.5' ) @classmethod def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in OB : if key not in [ 'SEQ_Darks' , 'SEQ_Calibrations' ]: log . debug ( f \" { key } : { OB [ key ] } \" ) else : log . debug ( f \" { key } :\" ) for entry in OB [ key ]: log . debug ( f \" { entry } \" ) log . info ( '-------------------------' ) check_scriptstop () # Power up needed lamps sequence = OB . get ( 'SEQ_Calibrations' , None ) lamps = set ([ x [ 'CalSource' ] for x in sequence if x [ 'CalSource' ] != 'Home' ]) \\ if sequence is not None else [] for lamp in lamps : if IsCalSourceEnabled . execute ({ 'CalSource' : lamp }) == True : if lamp in [ 'Th_daily' , 'Th_gold' , 'U_daily' , 'U_gold' , 'BrdbandFiber' , 'WideFlat' ]: CalLampPower . execute ({ 'lamp' : lamp , 'power' : 'on' }) log . debug ( f \"Ensuring back illumination LEDs are off\" ) CalLampPower . execute ({ 'lamp' : 'ExpMeterLED' , 'power' : 'off' }) CalLampPower . execute ({ 'lamp' : 'CaHKLED' , 'power' : 'off' }) CalLampPower . execute ({ 'lamp' : 'SciLED' , 'power' : 'off' }) CalLampPower . execute ({ 'lamp' : 'SkyLED' , 'power' : 'off' }) log . info ( f \"Configuring FIU\" ) ConfigureFIU . execute ({ 'mode' : 'Calibration' }) log . info ( f \"Set Detector List\" ) WaitForReady . execute ({}) SetTriggeredDetectors . execute ( OB ) @classmethod def post_condition ( cls , OB , logger , cfg ): pass","title":"ConfigureForCalibrations"},{"location":"scripts/ConfigureForCalibrations/#configureforcalibrations","text":"Bases: KPFTranslatorFunction Script which configures the instrument for Cal OBs. This must have arguments as input, either from a file using the -f command line tool, or passed in from the execution engine. Can be called by ddoi_script_functions.configure_for_science .","title":"ConfigureForCalibrations"},{"location":"scripts/ConfigureForCalibrations/#kpf.scripts.ConfigureForCalibrations.ConfigureForCalibrations--args","text":":OB: dict A fully specified calibration observing block (OB). Source code in kpf/scripts/ConfigureForCalibrations.py 21 22 23 24 25 26 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 class ConfigureForCalibrations ( KPFTranslatorFunction ): '''Script which configures the instrument for Cal OBs. This must have arguments as input, either from a file using the `-f` command line tool, or passed in from the execution engine. Can be called by `ddoi_script_functions.configure_for_science`. ARGS: ===== :OB: `dict` A fully specified calibration observing block (OB). ''' @classmethod @obey_scriptrun def pre_condition ( cls , OB , logger , cfg ): check_input ( OB , 'Template_Name' , allowed_values = [ 'kpf_cal' ]) check_input ( OB , 'Template_Version' , version_check = True , value_min = '0.5' ) @classmethod def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in OB : if key not in [ 'SEQ_Darks' , 'SEQ_Calibrations' ]: log . debug ( f \" { key } : { OB [ key ] } \" ) else : log . debug ( f \" { key } :\" ) for entry in OB [ key ]: log . debug ( f \" { entry } \" ) log . info ( '-------------------------' ) check_scriptstop () # Power up needed lamps sequence = OB . get ( 'SEQ_Calibrations' , None ) lamps = set ([ x [ 'CalSource' ] for x in sequence if x [ 'CalSource' ] != 'Home' ]) \\ if sequence is not None else [] for lamp in lamps : if IsCalSourceEnabled . execute ({ 'CalSource' : lamp }) == True : if lamp in [ 'Th_daily' , 'Th_gold' , 'U_daily' , 'U_gold' , 'BrdbandFiber' , 'WideFlat' ]: CalLampPower . execute ({ 'lamp' : lamp , 'power' : 'on' }) log . debug ( f \"Ensuring back illumination LEDs are off\" ) CalLampPower . execute ({ 'lamp' : 'ExpMeterLED' , 'power' : 'off' }) CalLampPower . execute ({ 'lamp' : 'CaHKLED' , 'power' : 'off' }) CalLampPower . execute ({ 'lamp' : 'SciLED' , 'power' : 'off' }) CalLampPower . execute ({ 'lamp' : 'SkyLED' , 'power' : 'off' }) log . info ( f \"Configuring FIU\" ) ConfigureFIU . execute ({ 'mode' : 'Calibration' }) log . info ( f \"Set Detector List\" ) WaitForReady . execute ({}) SetTriggeredDetectors . execute ( OB ) @classmethod def post_condition ( cls , OB , logger , cfg ): pass","title":"ARGS:"},{"location":"scripts/ConfigureForScience/","text":"ConfigureForScience Bases: KPFTranslatorFunction Script which configures the instrument for Science observations. Sets octagon / simulcal source Sets source select shutters Set triggered detectors This must have arguments as input, either from a file using the -f command line tool, or passed in from the execution engine. Can be called by ddoi_script_functions.configure_for_science . ARGS: :OB: dict A fully specified science observing block (OB). Source code in kpf/scripts/ConfigureForScience.py 24 25 26 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 class ConfigureForScience ( KPFTranslatorFunction ): '''Script which configures the instrument for Science observations. - Sets octagon / simulcal source - Sets source select shutters - Set triggered detectors This must have arguments as input, either from a file using the `-f` command line tool, or passed in from the execution engine. Can be called by `ddoi_script_functions.configure_for_science`. ARGS: ===== :OB: `dict` A fully specified science observing block (OB). ''' @classmethod @obey_scriptrun def pre_condition ( cls , OB , logger , cfg ): check_input ( OB , 'Template_Name' , allowed_values = [ 'kpf_sci' ]) check_input ( OB , 'Template_Version' , version_check = True , value_min = '0.5' ) return True @classmethod def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in OB : if key not in [ 'SEQ_Observations' ]: log . debug ( f \" { key } : { OB [ key ] } \" ) else : log . debug ( f \" { key } :\" ) for entry in OB [ key ]: log . debug ( f \" { entry } \" ) log . info ( '-------------------------' ) check_scriptstop () matched_PO = VerifyCurrentBase . execute ({}) if matched_PO == False : # Check with user log . debug ( 'Asking for user input' ) print () print ( \"#####################################################\" ) print ( \"The dcs.PONAME value is incosistent with CURRENT_BASE\" ) print ( \"Please double check that the target object is where you\" ) print ( \"want it to be before proceeding.\" ) print () print ( \"Do you wish to continue executing this OB?\" ) print ( \"(y/n) [y]:\" ) print ( \"#####################################################\" ) print () user_input = input () log . debug ( f 'response: \" { user_input } \"' ) if user_input . lower () . strip () in [ 'n' , 'no' , 'a' , 'abort' , 'q' , 'quit' ]: raise KPFException ( \"User chose to halt execution\" ) check_scriptstop () # Set Octagon kpfconfig = ktl . cache ( 'kpfconfig' ) calsource = kpfconfig [ 'SIMULCALSOURCE' ] . read () octagon = ktl . cache ( 'kpfcal' , 'OCTAGON' ) . read () log . debug ( f \"Current OCTAGON = { octagon } , desired = { calsource } \" ) if octagon != calsource : log . info ( f \"Set CalSource/Octagon: { calsource } \" ) SetCalSource . execute ({ 'CalSource' : calsource , 'wait' : False }) check_scriptstop () exposestatus = ktl . cache ( 'kpfexpose' , 'EXPOSE' ) if exposestatus . read () != 'Ready' : log . info ( f \"Waiting for kpfexpose to be Ready\" ) WaitForReady . execute ({}) log . debug ( f \"kpfexpose is Ready\" ) # Set source select shutters log . info ( f \"Set Source Select Shutters\" ) SetSourceSelectShutters . execute ({ 'SSS_Science' : True , 'SSS_Sky' : not OB . get ( 'BlockSky' , False ), 'SSS_SoCalSci' : False , 'SSS_SoCalCal' : False , 'SSS_CalSciSky' : False }) # Set Triggered Detectors OB [ 'TriggerGuide' ] = True SetTriggeredDetectors . execute ( OB ) check_scriptstop () @classmethod def post_condition ( cls , OB , logger , cfg ): pass","title":"ConfigureForScience"},{"location":"scripts/ConfigureForScience/#configureforscience","text":"Bases: KPFTranslatorFunction Script which configures the instrument for Science observations. Sets octagon / simulcal source Sets source select shutters Set triggered detectors This must have arguments as input, either from a file using the -f command line tool, or passed in from the execution engine. Can be called by ddoi_script_functions.configure_for_science .","title":"ConfigureForScience"},{"location":"scripts/ConfigureForScience/#kpf.scripts.ConfigureForScience.ConfigureForScience--args","text":":OB: dict A fully specified science observing block (OB). Source code in kpf/scripts/ConfigureForScience.py 24 25 26 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 class ConfigureForScience ( KPFTranslatorFunction ): '''Script which configures the instrument for Science observations. - Sets octagon / simulcal source - Sets source select shutters - Set triggered detectors This must have arguments as input, either from a file using the `-f` command line tool, or passed in from the execution engine. Can be called by `ddoi_script_functions.configure_for_science`. ARGS: ===== :OB: `dict` A fully specified science observing block (OB). ''' @classmethod @obey_scriptrun def pre_condition ( cls , OB , logger , cfg ): check_input ( OB , 'Template_Name' , allowed_values = [ 'kpf_sci' ]) check_input ( OB , 'Template_Version' , version_check = True , value_min = '0.5' ) return True @classmethod def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in OB : if key not in [ 'SEQ_Observations' ]: log . debug ( f \" { key } : { OB [ key ] } \" ) else : log . debug ( f \" { key } :\" ) for entry in OB [ key ]: log . debug ( f \" { entry } \" ) log . info ( '-------------------------' ) check_scriptstop () matched_PO = VerifyCurrentBase . execute ({}) if matched_PO == False : # Check with user log . debug ( 'Asking for user input' ) print () print ( \"#####################################################\" ) print ( \"The dcs.PONAME value is incosistent with CURRENT_BASE\" ) print ( \"Please double check that the target object is where you\" ) print ( \"want it to be before proceeding.\" ) print () print ( \"Do you wish to continue executing this OB?\" ) print ( \"(y/n) [y]:\" ) print ( \"#####################################################\" ) print () user_input = input () log . debug ( f 'response: \" { user_input } \"' ) if user_input . lower () . strip () in [ 'n' , 'no' , 'a' , 'abort' , 'q' , 'quit' ]: raise KPFException ( \"User chose to halt execution\" ) check_scriptstop () # Set Octagon kpfconfig = ktl . cache ( 'kpfconfig' ) calsource = kpfconfig [ 'SIMULCALSOURCE' ] . read () octagon = ktl . cache ( 'kpfcal' , 'OCTAGON' ) . read () log . debug ( f \"Current OCTAGON = { octagon } , desired = { calsource } \" ) if octagon != calsource : log . info ( f \"Set CalSource/Octagon: { calsource } \" ) SetCalSource . execute ({ 'CalSource' : calsource , 'wait' : False }) check_scriptstop () exposestatus = ktl . cache ( 'kpfexpose' , 'EXPOSE' ) if exposestatus . read () != 'Ready' : log . info ( f \"Waiting for kpfexpose to be Ready\" ) WaitForReady . execute ({}) log . debug ( f \"kpfexpose is Ready\" ) # Set source select shutters log . info ( f \"Set Source Select Shutters\" ) SetSourceSelectShutters . execute ({ 'SSS_Science' : True , 'SSS_Sky' : not OB . get ( 'BlockSky' , False ), 'SSS_SoCalSci' : False , 'SSS_SoCalCal' : False , 'SSS_CalSciSky' : False }) # Set Triggered Detectors OB [ 'TriggerGuide' ] = True SetTriggeredDetectors . execute ( OB ) check_scriptstop () @classmethod def post_condition ( cls , OB , logger , cfg ): pass","title":"ARGS:"},{"location":"scripts/ControlAOHatch/","text":"ControlAOHatch Bases: KPFTranslatorFunction Command the AO Hatch to open or close. Parameters: destination ( str ) \u2013 The destination position. Allowed Values: 'open' or 'close'. KTL Keywords Used: ao.AOHATCHCMD ao.AOHATCHSTS Source code in kpf/ao/ControlAOHatch.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class ControlAOHatch ( KPFTranslatorFunction ): '''Command the AO Hatch to open or close. Args: destination (str): The destination position. Allowed Values: 'open' or 'close'. KTL Keywords Used: - `ao.AOHATCHCMD` - `ao.AOHATCHSTS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'destination' , allowed_values = [ 'close' , 'closed' , 'open' ]) @classmethod def perform ( cls , args , logger , cfg ): destination = args . get ( 'destination' , '' ) . strip () ao = ktl . cache ( 'ao' ) log . debug ( f \"Setting AO Hatch to { destination } \" ) cmd = { 'close' : 1 , 'closed' : 1 , 'open' : 0 }[ destination ] ao [ 'aohatchcmd' ] . write ( cmd ) @classmethod def post_condition ( cls , args , logger , cfg ): destination = args . get ( 'destination' , '' ) . strip () final_dest = { 'close' : 'closed' , 'closed' : 'closed' , 'open' : 'open' }[ destination ] aohatchsts = ktl . cache ( 'ao' , 'AOHATCHSTS' ) success = aohatchsts . waitfor ( f \"== ' { final_dest } '\" , timeout = 30 ) if success is not True : raise FailedToReachDestination ( aohatchsts . read (), final_dest ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'destination' , type = str , choices = [ 'open' , 'close' ], help = 'Desired hatch position' ) return super () . add_cmdline_args ( parser , cfg )","title":"ControlAOHatch"},{"location":"scripts/ControlAOHatch/#controlaohatch","text":"Bases: KPFTranslatorFunction Command the AO Hatch to open or close. Parameters: destination ( str ) \u2013 The destination position. Allowed Values: 'open' or 'close'. KTL Keywords Used: ao.AOHATCHCMD ao.AOHATCHSTS Source code in kpf/ao/ControlAOHatch.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class ControlAOHatch ( KPFTranslatorFunction ): '''Command the AO Hatch to open or close. Args: destination (str): The destination position. Allowed Values: 'open' or 'close'. KTL Keywords Used: - `ao.AOHATCHCMD` - `ao.AOHATCHSTS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'destination' , allowed_values = [ 'close' , 'closed' , 'open' ]) @classmethod def perform ( cls , args , logger , cfg ): destination = args . get ( 'destination' , '' ) . strip () ao = ktl . cache ( 'ao' ) log . debug ( f \"Setting AO Hatch to { destination } \" ) cmd = { 'close' : 1 , 'closed' : 1 , 'open' : 0 }[ destination ] ao [ 'aohatchcmd' ] . write ( cmd ) @classmethod def post_condition ( cls , args , logger , cfg ): destination = args . get ( 'destination' , '' ) . strip () final_dest = { 'close' : 'closed' , 'closed' : 'closed' , 'open' : 'open' }[ destination ] aohatchsts = ktl . cache ( 'ao' , 'AOHATCHSTS' ) success = aohatchsts . waitfor ( f \"== ' { final_dest } '\" , timeout = 30 ) if success is not True : raise FailedToReachDestination ( aohatchsts . read (), final_dest ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'destination' , type = str , choices = [ 'open' , 'close' ], help = 'Desired hatch position' ) return super () . add_cmdline_args ( parser , cfg )","title":"ControlAOHatch"},{"location":"scripts/ControlFoldMirror/","text":"ControlFoldMirror Bases: KPFTranslatorFunction Insert or remove the FIU Cal Fold Mirror from the beam. Parameters: destination ( str ) \u2013 The desired FIU fold mirror position name. Allowed values: in, out wait ( bool ) \u2013 Wait for move to complete before returning? (default: True) KTL Keywords Used: kpffiu.FOLDNAM Source code in kpf/fiu/ControlFoldMirror.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class ControlFoldMirror ( KPFTranslatorFunction ): '''Insert or remove the FIU Cal Fold Mirror from the beam. Args: destination (str): The desired FIU fold mirror position name. Allowed values: in, out wait (bool): Wait for move to complete before returning? (default: True) KTL Keywords Used: - `kpffiu.FOLDNAM` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): destination = args . get ( 'destination' , '' ) . strip () if destination . lower () not in [ 'in' , 'out' ]: raise FailedPreCondition ( f \"Requested state { destination } is invalid\" ) @classmethod def perform ( cls , args , logger , cfg ): destination = args . get ( 'destination' , '' ) . strip () kpffiu = ktl . cache ( 'kpffiu' ) kpffiu [ 'FOLDNAM' ] . write ( destination ) @classmethod def post_condition ( cls , args , logger , cfg ): destination = args . get ( 'destination' , '' ) . strip () timeout = cfg . getfloat ( 'times' , 'fiu_fold_mirror_move_time' , fallback = 5 ) success = ktl . waitFor ( f '($kpffiu.foldnam == { destination } )' , timeout = timeout ) if success is not True : foldnam = ktl . cache ( 'kpffiu' , 'FOLDNAM' ) raise FailedToReachDestination ( foldnam . read (), destination ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'destination' , type = str , choices = [ 'in' , 'out' ], help = 'Desired fold mirror position' ) return super () . add_cmdline_args ( parser , cfg )","title":"ControlFoldMirror"},{"location":"scripts/ControlFoldMirror/#controlfoldmirror","text":"Bases: KPFTranslatorFunction Insert or remove the FIU Cal Fold Mirror from the beam. Parameters: destination ( str ) \u2013 The desired FIU fold mirror position name. Allowed values: in, out wait ( bool ) \u2013 Wait for move to complete before returning? (default: True) KTL Keywords Used: kpffiu.FOLDNAM Source code in kpf/fiu/ControlFoldMirror.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class ControlFoldMirror ( KPFTranslatorFunction ): '''Insert or remove the FIU Cal Fold Mirror from the beam. Args: destination (str): The desired FIU fold mirror position name. Allowed values: in, out wait (bool): Wait for move to complete before returning? (default: True) KTL Keywords Used: - `kpffiu.FOLDNAM` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): destination = args . get ( 'destination' , '' ) . strip () if destination . lower () not in [ 'in' , 'out' ]: raise FailedPreCondition ( f \"Requested state { destination } is invalid\" ) @classmethod def perform ( cls , args , logger , cfg ): destination = args . get ( 'destination' , '' ) . strip () kpffiu = ktl . cache ( 'kpffiu' ) kpffiu [ 'FOLDNAM' ] . write ( destination ) @classmethod def post_condition ( cls , args , logger , cfg ): destination = args . get ( 'destination' , '' ) . strip () timeout = cfg . getfloat ( 'times' , 'fiu_fold_mirror_move_time' , fallback = 5 ) success = ktl . waitFor ( f '($kpffiu.foldnam == { destination } )' , timeout = timeout ) if success is not True : foldnam = ktl . cache ( 'kpffiu' , 'FOLDNAM' ) raise FailedToReachDestination ( foldnam . read (), destination ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'destination' , type = str , choices = [ 'in' , 'out' ], help = 'Desired fold mirror position' ) return super () . add_cmdline_args ( parser , cfg )","title":"ControlFoldMirror"},{"location":"scripts/ControlHatch/","text":"ControlHatch Bases: KPFTranslatorFunction Open or close the FIU hatch Parameters: destination ( str ) \u2013 The desired FIU hatch position name. Allowed values: closed, open KTL Keywords Used: kpffiu.HATCH Source code in kpf/fiu/ControlHatch.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 class ControlHatch ( KPFTranslatorFunction ): '''Open or close the FIU hatch Args: destination (str): The desired FIU hatch position name. Allowed values: closed, open KTL Keywords Used: - `kpffiu.HATCH` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'destination' , allowed_values = [ 'closed' , 'open' ]) @classmethod def perform ( cls , args , logger , cfg ): destination = args . get ( 'destination' , '' ) . strip () kpffiu = ktl . cache ( 'kpffiu' ) kpffiu [ 'HATCH' ] . write ( destination ) @classmethod def post_condition ( cls , args , logger , cfg ): destination = args . get ( 'destination' , '' ) . strip () timeout = cfg . getfloat ( 'times' , 'fiu_hatch_move_time' , fallback = 1 ) success = ktl . waitFor ( f '($kpffiu.hatch == { destination } )' , timeout = timeout ) if success is not True : hatch = ktl . cache ( 'kpffiu' , 'HATCH' ) raise FailedToReachDestination ( hatch . read (), destination ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'destination' , type = str , choices = [ 'open' , 'closed' ], help = 'Desired hatch position' ) return super () . add_cmdline_args ( parser , cfg )","title":"ControlHatch"},{"location":"scripts/ControlHatch/#controlhatch","text":"Bases: KPFTranslatorFunction Open or close the FIU hatch Parameters: destination ( str ) \u2013 The desired FIU hatch position name. Allowed values: closed, open KTL Keywords Used: kpffiu.HATCH Source code in kpf/fiu/ControlHatch.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 class ControlHatch ( KPFTranslatorFunction ): '''Open or close the FIU hatch Args: destination (str): The desired FIU hatch position name. Allowed values: closed, open KTL Keywords Used: - `kpffiu.HATCH` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'destination' , allowed_values = [ 'closed' , 'open' ]) @classmethod def perform ( cls , args , logger , cfg ): destination = args . get ( 'destination' , '' ) . strip () kpffiu = ktl . cache ( 'kpffiu' ) kpffiu [ 'HATCH' ] . write ( destination ) @classmethod def post_condition ( cls , args , logger , cfg ): destination = args . get ( 'destination' , '' ) . strip () timeout = cfg . getfloat ( 'times' , 'fiu_hatch_move_time' , fallback = 1 ) success = ktl . waitFor ( f '($kpffiu.hatch == { destination } )' , timeout = timeout ) if success is not True : hatch = ktl . cache ( 'kpffiu' , 'HATCH' ) raise FailedToReachDestination ( hatch . read (), destination ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'destination' , type = str , choices = [ 'open' , 'closed' ], help = 'Desired hatch position' ) return super () . add_cmdline_args ( parser , cfg )","title":"ControlHatch"},{"location":"scripts/CorrectDAR/","text":"CorrectDAR Bases: KPFTranslatorFunction Modify the CURRENT_BASE keyword based upon the calculated differential atmospheric refraction value. This is NOT the recommended method for doing this as it is now done automatically in the kpfguide keyword service. This script predates full functionality of kpfguide and is being left in place only for emergency use. Calculation from Filippenko 1982 (PASP, 94:715-721, August 1982) ARGS: :EL: float Elevation of the telescope. Source code in kpf/utils/CorrectDAR.py 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class CorrectDAR ( KPFTranslatorFunction ): '''Modify the CURRENT_BASE keyword based upon the calculated differential atmospheric refraction value. This is NOT the recommended method for doing this as it is now done automatically in the `kpfguide` keyword service. This script predates full functionality of `kpfguide` and is being left in place only for emergency use. Calculation from Filippenko 1982 (PASP, 94:715-721, August 1982) ARGS: ===== :EL: `float` Elevation of the telescope. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) dcs = ktl . cache ( 'dcs1' ) EL = dcs [ 'EL' ] . read ( binary = True ) * 180 / np . pi DARarcsec = calculate_DAR_arcsec ( EL ) log . info ( f \"DAR is { DARarcsec : .3f } arcseconds\" ) dx , dy = calculate_DAR_pix ( DARarcsec ) total_pix = ( dx ** 2 + dy ** 2 ) ** 0.5 log . info ( f \"Pixel shift is { dx : .1f } , { dy : .1f } = { total_pix : .1f } \" ) base_names = { 'KPF' : 'SCIENCE_BASE' , 'SKY' : 'SKY_BASE' } POname = dcs [ 'PONAME' ] . read () base_name = base_names . get ( POname , None ) if base_name is None : log . error ( f \"dcs.PONAME= { POname } is not recognized\" ) log . error ( \"Leaving CURRENT_BASE unmodified\" ) return # log.error(f\"Using SCIENCE_BASE for testing\") # base_name = 'SCIENCE_BASE' # Set CURRENT_BASE log . info ( f \"dcs.PONAME is { POname } , using { base_name } as reference pixel\" ) reference_pix = list ( kpfguide [ base_name ] . read ( binary = True )) log . debug ( f \"Initial CURRENT_BASE = { reference_pix [ 0 ] : .1f } { reference_pix [ 1 ] : .1f } \" ) final_pixel = [ reference_pix [ 0 ] + dx , reference_pix [ 1 ] + dy ] final_pixel_string = f \" { final_pixel [ 0 ] : .2f } { final_pixel [ 1 ] : .2f } \" log . debug ( f \"Final Pixel = { final_pixel_string } \" ) min_x_pixel = cfg . getint ( 'guider' , 'min_x_pixel' , fallback = 0 ) max_x_pixel = cfg . getint ( 'guider' , 'max_x_pixel' , fallback = 640 ) min_y_pixel = cfg . getint ( 'guider' , 'min_y_pixel' , fallback = 0 ) max_y_pixel = cfg . getint ( 'guider' , 'max_y_pixel' , fallback = 512 ) if final_pixel [ 0 ] < min_x_pixel or final_pixel [ 0 ] > max_x_pixel or \\ final_pixel [ 1 ] < min_y_pixel or final_pixel [ 1 ] > max_y_pixel : log . error ( f \"Target pixel ( { final_pixel_string } ) is not on guide camera\" ) log . error ( \"Leaving CURRENT_BASE unmodified\" ) else : log . info ( f \"Writing new CURRENT_BASE = { final_pixel_string } \" ) kpfguide [ 'CURRENT_BASE' ] . write ( final_pixel ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"CorrectDAR"},{"location":"scripts/CorrectDAR/#correctdar","text":"Bases: KPFTranslatorFunction Modify the CURRENT_BASE keyword based upon the calculated differential atmospheric refraction value. This is NOT the recommended method for doing this as it is now done automatically in the kpfguide keyword service. This script predates full functionality of kpfguide and is being left in place only for emergency use. Calculation from Filippenko 1982 (PASP, 94:715-721, August 1982)","title":"CorrectDAR"},{"location":"scripts/CorrectDAR/#kpf.utils.CorrectDAR.CorrectDAR--args","text":":EL: float Elevation of the telescope. Source code in kpf/utils/CorrectDAR.py 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class CorrectDAR ( KPFTranslatorFunction ): '''Modify the CURRENT_BASE keyword based upon the calculated differential atmospheric refraction value. This is NOT the recommended method for doing this as it is now done automatically in the `kpfguide` keyword service. This script predates full functionality of `kpfguide` and is being left in place only for emergency use. Calculation from Filippenko 1982 (PASP, 94:715-721, August 1982) ARGS: ===== :EL: `float` Elevation of the telescope. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) dcs = ktl . cache ( 'dcs1' ) EL = dcs [ 'EL' ] . read ( binary = True ) * 180 / np . pi DARarcsec = calculate_DAR_arcsec ( EL ) log . info ( f \"DAR is { DARarcsec : .3f } arcseconds\" ) dx , dy = calculate_DAR_pix ( DARarcsec ) total_pix = ( dx ** 2 + dy ** 2 ) ** 0.5 log . info ( f \"Pixel shift is { dx : .1f } , { dy : .1f } = { total_pix : .1f } \" ) base_names = { 'KPF' : 'SCIENCE_BASE' , 'SKY' : 'SKY_BASE' } POname = dcs [ 'PONAME' ] . read () base_name = base_names . get ( POname , None ) if base_name is None : log . error ( f \"dcs.PONAME= { POname } is not recognized\" ) log . error ( \"Leaving CURRENT_BASE unmodified\" ) return # log.error(f\"Using SCIENCE_BASE for testing\") # base_name = 'SCIENCE_BASE' # Set CURRENT_BASE log . info ( f \"dcs.PONAME is { POname } , using { base_name } as reference pixel\" ) reference_pix = list ( kpfguide [ base_name ] . read ( binary = True )) log . debug ( f \"Initial CURRENT_BASE = { reference_pix [ 0 ] : .1f } { reference_pix [ 1 ] : .1f } \" ) final_pixel = [ reference_pix [ 0 ] + dx , reference_pix [ 1 ] + dy ] final_pixel_string = f \" { final_pixel [ 0 ] : .2f } { final_pixel [ 1 ] : .2f } \" log . debug ( f \"Final Pixel = { final_pixel_string } \" ) min_x_pixel = cfg . getint ( 'guider' , 'min_x_pixel' , fallback = 0 ) max_x_pixel = cfg . getint ( 'guider' , 'max_x_pixel' , fallback = 640 ) min_y_pixel = cfg . getint ( 'guider' , 'min_y_pixel' , fallback = 0 ) max_y_pixel = cfg . getint ( 'guider' , 'max_y_pixel' , fallback = 512 ) if final_pixel [ 0 ] < min_x_pixel or final_pixel [ 0 ] > max_x_pixel or \\ final_pixel [ 1 ] < min_y_pixel or final_pixel [ 1 ] > max_y_pixel : log . error ( f \"Target pixel ( { final_pixel_string } ) is not on guide camera\" ) log . error ( \"Leaving CURRENT_BASE unmodified\" ) else : log . info ( f \"Writing new CURRENT_BASE = { final_pixel_string } \" ) kpfguide [ 'CURRENT_BASE' ] . write ( final_pixel ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"ARGS:"},{"location":"scripts/CountCameraErrors/","text":"CountCameraErrors Bases: KPFTranslatorFunction Description Parameters Source code in kpf/engineering/analysis/CountCameraErrors.py 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 class CountCameraErrors ( KPFTranslatorFunction ): '''# Description # Parameters ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): output_file = Path ( '/s/sdata1701/KPFTranslator_logs/camera_errors.txt' ) if output_file . exists (): output_file . unlink () date = datetime . strptime ( '2023-06-01' , '%Y-%m- %d ' ) total_green_errors = 0 total_green_starts = 0 total_red_errors = 0 total_red_starts = 0 print ( f \"From { date . strftime ( '%Y-%m- %d ' ) } \" ) dates = [] green_errs = [] red_errs = [] green_starts = [] red_starts = [] with open ( output_file , 'w' ) as f : while date < datetime . utcnow () - timedelta ( days = 1 ): date_str = date . strftime ( '%Y-%m- %d ' ) ng_starts , nr_starts = count_start_state_instances ( date = date_str ) ng_errs , nr_errs = count_start_state_errors ( date = date_str ) dates . append ( date ) green_errs . append ( ng_errs ) red_errs . append ( nr_errs ) green_starts . append ( ng_starts ) red_starts . append ( nr_starts ) total_green_errors += ng_errs total_green_starts += ng_starts total_red_errors += nr_errs total_red_starts += nr_starts line = f \" { date_str } , { ng_errs } , { ng_starts } , { nr_errs } , { nr_starts } \" # print(line) f . write ( f \" { line } \\n \" ) date += timedelta ( days = 1 ) print ( f \"Through { date . strftime ( '%Y-%m- %d ' ) } \" ) green_error_rate = total_green_errors / total_green_starts print ( f \"Green error rate = { green_error_rate : .2% } ( { total_green_errors } / { total_green_starts } )\" ) red_error_rate = total_red_errors / total_red_starts print ( f \"Red error rate = { red_error_rate : .2% } ( { total_red_errors } / { total_red_starts } )\" ) plt . figure ( figsize = ( 12 , 8 )) plt . subplot ( 2 , 1 , 1 ) plt . title ( f \"Number of start errors per day\" ) plt . bar ( dates , green_errs , color = 'g' , alpha = 0.5 , width = 0.4 , align = 'edge' ) plt . bar ( dates , red_errs , color = 'r' , alpha = 0.5 , width =- 0.4 , align = 'edge' ) plt . ylabel ( 'N Errors' ) plt . subplot ( 2 , 1 , 2 ) plt . title ( f \"Rate of start errors per day\" ) plt . plot ( dates , np . array ( green_errs ) / np . array ( green_starts ) * 100 , 'go-' ) plt . plot ( dates , np . array ( red_errs ) / np . array ( red_starts ) * 100 , 'ro-' ) plt . ylabel ( ' % E rrors' ) plt . xlabel ( 'Date' ) plt . grid () plt . show () @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"CountCameraErrors"},{"location":"scripts/CountCameraErrors/#countcameraerrors","text":"Bases: KPFTranslatorFunction","title":"CountCameraErrors"},{"location":"scripts/CountCameraErrors/#kpf.engineering.analysis.CountCameraErrors.CountCameraErrors--description","text":"","title":"Description"},{"location":"scripts/CountCameraErrors/#kpf.engineering.analysis.CountCameraErrors.CountCameraErrors--parameters","text":"Source code in kpf/engineering/analysis/CountCameraErrors.py 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 class CountCameraErrors ( KPFTranslatorFunction ): '''# Description # Parameters ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): output_file = Path ( '/s/sdata1701/KPFTranslator_logs/camera_errors.txt' ) if output_file . exists (): output_file . unlink () date = datetime . strptime ( '2023-06-01' , '%Y-%m- %d ' ) total_green_errors = 0 total_green_starts = 0 total_red_errors = 0 total_red_starts = 0 print ( f \"From { date . strftime ( '%Y-%m- %d ' ) } \" ) dates = [] green_errs = [] red_errs = [] green_starts = [] red_starts = [] with open ( output_file , 'w' ) as f : while date < datetime . utcnow () - timedelta ( days = 1 ): date_str = date . strftime ( '%Y-%m- %d ' ) ng_starts , nr_starts = count_start_state_instances ( date = date_str ) ng_errs , nr_errs = count_start_state_errors ( date = date_str ) dates . append ( date ) green_errs . append ( ng_errs ) red_errs . append ( nr_errs ) green_starts . append ( ng_starts ) red_starts . append ( nr_starts ) total_green_errors += ng_errs total_green_starts += ng_starts total_red_errors += nr_errs total_red_starts += nr_starts line = f \" { date_str } , { ng_errs } , { ng_starts } , { nr_errs } , { nr_starts } \" # print(line) f . write ( f \" { line } \\n \" ) date += timedelta ( days = 1 ) print ( f \"Through { date . strftime ( '%Y-%m- %d ' ) } \" ) green_error_rate = total_green_errors / total_green_starts print ( f \"Green error rate = { green_error_rate : .2% } ( { total_green_errors } / { total_green_starts } )\" ) red_error_rate = total_red_errors / total_red_starts print ( f \"Red error rate = { red_error_rate : .2% } ( { total_red_errors } / { total_red_starts } )\" ) plt . figure ( figsize = ( 12 , 8 )) plt . subplot ( 2 , 1 , 1 ) plt . title ( f \"Number of start errors per day\" ) plt . bar ( dates , green_errs , color = 'g' , alpha = 0.5 , width = 0.4 , align = 'edge' ) plt . bar ( dates , red_errs , color = 'r' , alpha = 0.5 , width =- 0.4 , align = 'edge' ) plt . ylabel ( 'N Errors' ) plt . subplot ( 2 , 1 , 2 ) plt . title ( f \"Rate of start errors per day\" ) plt . plot ( dates , np . array ( green_errs ) / np . array ( green_starts ) * 100 , 'go-' ) plt . plot ( dates , np . array ( red_errs ) / np . array ( red_starts ) * 100 , 'ro-' ) plt . ylabel ( ' % E rrors' ) plt . xlabel ( 'Date' ) plt . grid () plt . show () @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"Parameters"},{"location":"scripts/DisableSoCal/","text":"DisableSoCal Bases: KPFTranslatorFunction Disables SoCal by setting kpfsocal.CAN_OPEN to No. ARGS: None Source code in kpf/socal/DisableSoCal.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class DisableSoCal ( KPFTranslatorFunction ): '''Disables SoCal by setting kpfsocal.CAN_OPEN to No. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): CAN_OPEN = ktl . cache ( 'kpfsocal' , 'CAN_OPEN' ) log . info ( 'Setting kpfsocal.CAN_OPEN = 0' ) CAN_OPEN . write ( 0 ) @classmethod def post_condition ( cls , args , logger , cfg ): CAN_OPEN = ktl . cache ( 'kpfsocal' , 'CAN_OPEN' ) success = CAN_OPEN . waitFor ( \"==0\" , timeout = 1 ) if success is False : raise FailedToReachDestination ( 'kpfsocal.CAN_OPEN is not 0' )","title":"DisableSoCal"},{"location":"scripts/DisableSoCal/#disablesocal","text":"Bases: KPFTranslatorFunction Disables SoCal by setting kpfsocal.CAN_OPEN to No.","title":"DisableSoCal"},{"location":"scripts/DisableSoCal/#kpf.socal.DisableSoCal.DisableSoCal--args","text":"None Source code in kpf/socal/DisableSoCal.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class DisableSoCal ( KPFTranslatorFunction ): '''Disables SoCal by setting kpfsocal.CAN_OPEN to No. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): CAN_OPEN = ktl . cache ( 'kpfsocal' , 'CAN_OPEN' ) log . info ( 'Setting kpfsocal.CAN_OPEN = 0' ) CAN_OPEN . write ( 0 ) @classmethod def post_condition ( cls , args , logger , cfg ): CAN_OPEN = ktl . cache ( 'kpfsocal' , 'CAN_OPEN' ) success = CAN_OPEN . waitFor ( \"==0\" , timeout = 1 ) if success is False : raise FailedToReachDestination ( 'kpfsocal.CAN_OPEN is not 0' )","title":"ARGS:"},{"location":"scripts/DisplayGuiderContinuous/","text":"DisplayGuiderContinuous Bases: KPFTranslatorFunction Continuously display latest guider images to ds9 using xpaset . KTL Keywords Used: kpfguide.LASTFILE Source code in kpf/guider/DisplayGuiderContinuous.py 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 class DisplayGuiderContinuous ( KPFTranslatorFunction ): '''Continuously display latest guider images to ds9 using `xpaset`. KTL Keywords Used: - `kpfguide.LASTFILE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): display_name = cfg . get ( 'display' , 'guider_xpa_target' , fallback = 'CRED2' ) lastfile = ktl . cache ( 'kpfguide' , 'LASTFILE' ) initial_lastfile = lastfile . read () while True : expr = f \"($kpfguide.LASTFILE != ' { initial_lastfile } ')\" is_there_a_newfile = ktl . waitFor ( expr , timeout = 10 ) if is_there_a_newfile is True : initial_lastfile = lastfile . read () print ( f \"Displaying { initial_lastfile } \" ) ds9cmd = [ 'xpaset' , display_name , 'fits' , f \" { initial_lastfile } \" , '<' , f \" { initial_lastfile } \" ] # log.debug(f\"Running: {' '.join(ds9cmd)}\") subprocess . call ( ' ' . join ( ds9cmd ), shell = True ) regfile = Path ( f '/home/kpfeng/fibers_on_cred2.reg' ) if regfile . exists () is True : overlaycmd = [ 'xpaset' , '-p' , display_name , 'regions' , 'file' , f \" { regfile } \" ] # log.debug(f\"Running: {' '.join(overlaycmd)}\") subprocess . call ( ' ' . join ( overlaycmd ), shell = True ) time . sleep ( 0.5 ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"DisplayGuiderContinuous"},{"location":"scripts/DisplayGuiderContinuous/#displayguidercontinuous","text":"Bases: KPFTranslatorFunction Continuously display latest guider images to ds9 using xpaset . KTL Keywords Used: kpfguide.LASTFILE Source code in kpf/guider/DisplayGuiderContinuous.py 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 class DisplayGuiderContinuous ( KPFTranslatorFunction ): '''Continuously display latest guider images to ds9 using `xpaset`. KTL Keywords Used: - `kpfguide.LASTFILE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): display_name = cfg . get ( 'display' , 'guider_xpa_target' , fallback = 'CRED2' ) lastfile = ktl . cache ( 'kpfguide' , 'LASTFILE' ) initial_lastfile = lastfile . read () while True : expr = f \"($kpfguide.LASTFILE != ' { initial_lastfile } ')\" is_there_a_newfile = ktl . waitFor ( expr , timeout = 10 ) if is_there_a_newfile is True : initial_lastfile = lastfile . read () print ( f \"Displaying { initial_lastfile } \" ) ds9cmd = [ 'xpaset' , display_name , 'fits' , f \" { initial_lastfile } \" , '<' , f \" { initial_lastfile } \" ] # log.debug(f\"Running: {' '.join(ds9cmd)}\") subprocess . call ( ' ' . join ( ds9cmd ), shell = True ) regfile = Path ( f '/home/kpfeng/fibers_on_cred2.reg' ) if regfile . exists () is True : overlaycmd = [ 'xpaset' , '-p' , display_name , 'regions' , 'file' , f \" { regfile } \" ] # log.debug(f\"Running: {' '.join(overlaycmd)}\") subprocess . call ( ' ' . join ( overlaycmd ), shell = True ) time . sleep ( 0.5 ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"DisplayGuiderContinuous"},{"location":"scripts/EnableSoCal/","text":"EnableSoCal Bases: KPFTranslatorFunction Enables SoCal by setting kpfsocal.CAN_OPEN to Yes. ARGS: None Source code in kpf/socal/EnableSoCal.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class EnableSoCal ( KPFTranslatorFunction ): '''Enables SoCal by setting kpfsocal.CAN_OPEN to Yes. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): CAN_OPEN = ktl . cache ( 'kpfsocal' , 'CAN_OPEN' ) log . info ( 'Setting kpfsocal.CAN_OPEN = 1' ) CAN_OPEN . write ( 1 ) @classmethod def post_condition ( cls , args , logger , cfg ): CAN_OPEN = ktl . cache ( 'kpfsocal' , 'CAN_OPEN' ) success = CAN_OPEN . waitFor ( \"==1\" , timeout = 1 ) if success is False : raise FailedToReachDestination ( 'kpfsocal.CAN_OPEN is not 1' )","title":"EnableSoCal"},{"location":"scripts/EnableSoCal/#enablesocal","text":"Bases: KPFTranslatorFunction Enables SoCal by setting kpfsocal.CAN_OPEN to Yes.","title":"EnableSoCal"},{"location":"scripts/EnableSoCal/#kpf.socal.EnableSoCal.EnableSoCal--args","text":"None Source code in kpf/socal/EnableSoCal.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class EnableSoCal ( KPFTranslatorFunction ): '''Enables SoCal by setting kpfsocal.CAN_OPEN to Yes. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): CAN_OPEN = ktl . cache ( 'kpfsocal' , 'CAN_OPEN' ) log . info ( 'Setting kpfsocal.CAN_OPEN = 1' ) CAN_OPEN . write ( 1 ) @classmethod def post_condition ( cls , args , logger , cfg ): CAN_OPEN = ktl . cache ( 'kpfsocal' , 'CAN_OPEN' ) success = CAN_OPEN . waitFor ( \"==1\" , timeout = 1 ) if success is False : raise FailedToReachDestination ( 'kpfsocal.CAN_OPEN is not 1' )","title":"ARGS:"},{"location":"scripts/EndOfNight/","text":"EndOfNight Bases: KPFTranslatorFunction 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) Source code in kpf/scripts/EndOfNight.py 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 class EndOfNight ( KPFTranslatorFunction ): '''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 , logger , cfg ): pass @classmethod @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , args , logger , cfg ): StopTipTilt . execute ({}) StopAgitator . execute ({}) # Start FIU stow log . info ( 'Setting FIU mode to Stowed' ) ConfigureFIU . execute ({ 'mode' : 'Stowed' , 'wait' : False }) # --------------------------------- # User Verification for AO Shutdown # --------------------------------- 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 , logger , cfg ): pass","title":"EndOfNight"},{"location":"scripts/EndOfNight/#endofnight","text":"Bases: KPFTranslatorFunction 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","title":"EndOfNight"},{"location":"scripts/EndOfNight/#kpf.scripts.EndOfNight.EndOfNight--args","text":":AO: (bool) Close AO hatch, home PCU, and turn on HEPA? (default=True) Source code in kpf/scripts/EndOfNight.py 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 class EndOfNight ( KPFTranslatorFunction ): '''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 , logger , cfg ): pass @classmethod @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , args , logger , cfg ): StopTipTilt . execute ({}) StopAgitator . execute ({}) # Start FIU stow log . info ( 'Setting FIU mode to Stowed' ) ConfigureFIU . execute ({ 'mode' : 'Stowed' , 'wait' : False }) # --------------------------------- # User Verification for AO Shutdown # --------------------------------- 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 , logger , cfg ): pass","title":"ARGS:"},{"location":"scripts/EnterLowPowerMode/","text":"EnterLowPowerMode Bases: KPFTranslatorFunction Set KPF to a low power mode. This is intended for use during power outages. This reduces power use in the AO electronics room. We do not currently recommend any changes in the basement due to the sensitivity of the spectrograph to thermal changes. Procedure: - If a script is running exit or terminate it (depending on --force arg) - Disable HK detector - Stop HK cooling - Power off HK systems: J1, J2, J5 - Stop CRED2 exposures (CONTINUOUS and SAVE) - Stop CRED2 cooling (if on) - Power off CRED2 (K2, K3) Source code in kpf/scripts/EnterLowPowerMode.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class EnterLowPowerMode ( KPFTranslatorFunction ): '''Set KPF to a low power mode. This is intended for use during power outages. This reduces power use in the AO electronics room. We do not currently recommend any changes in the basement due to the sensitivity of the spectrograph to thermal changes. Procedure: - If a script is running exit or terminate it (depending on --force arg) - Disable HK detector - Stop HK cooling - Power off HK systems: J1, J2, J5 - Stop CRED2 exposures (CONTINUOUS and SAVE) - Stop CRED2 cooling (if on) - Power off CRED2 (K2, K3) ''' @classmethod def pre_condition ( cls , args , logger , cfg ): log . info ( 'Configuring KPF for Low Power Mode' ) force = args . get ( 'force' , False ) SCRIPTNAME = ktl . cache ( 'kpfconfig' , 'SCRIPTNAME' ) SCRIPTNAME . monitor () if SCRIPTNAME not in [ 'None' , '' ]: log . warning ( f 'A script ( { SCRIPTNAME } ) is running' ) if force is True : log . warning ( f 'Requesting script stop' ) kpfconfig [ 'SCRIPTSTOP' ] . write ( 'Yes' ) no_script_running = SCRIPTNAME . waitFor ( \"==''\" , timeout = 120 ) if no_script_running is False : log . error ( 'Script failed to stop' ) raise FailedToReachDestination ( f ' { SCRIPTNAME . read () } ' , '' ) else : raise FailedPreCondition ( 'A script is running, not setting Low Power Mode' ) @classmethod def perform ( cls , args , logger , cfg ): kpfconfig = ktl . cache ( 'kpfconfig' ) kpfpower = ktl . cache ( 'kpfpower' ) # Power down Ca HK detector systems kpf_hk = ktl . cache ( 'kpf_hk' ) log . info ( 'Disabling Ca HK detector' ) kpfconfig [ 'CA_HK_ENABLED' ] . write ( 'No' ) log . info ( 'Turning Ca HK detector cooling off' ) kpf_hk [ 'COOLING' ] . write ( 'off' ) time . sleep ( 3 ) log . info ( 'Powering off Ca HK detector systems' ) log . debug ( f \"Powering off { kpfpower [ 'OUTLET_J1_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_J1' ] . write ( 'Off' ) log . debug ( f \"Powering off { kpfpower [ 'OUTLET_J2_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_J2' ] . write ( 'Off' ) log . debug ( f \"Powering off { kpfpower [ 'OUTLET_J5_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_J5' ] . write ( 'Off' ) # Power down CRED2 detector systems kpfguide = ktl . cache ( 'kpfguide' ) log . info ( 'Powering off CRED2 detector systems' ) kpfguide [ 'CONTINUOUS' ] . write ( 'Inactive' ) kpfguide [ 'SAVE' ] . write ( 'Inactive' ) time . sleep ( 2 ) log . debug ( f \"Powering off { kpfpower [ 'OUTLET_K2_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_K2' ] . write ( 'Off' ) log . debug ( f \"Powering off { kpfpower [ 'OUTLET_K3_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_K3' ] . write ( 'Off' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--force\" , dest = \"force\" , default = False , action = \"store_true\" , help = \"Force change? This will terminate any running scripts.\" ) return super () . add_cmdline_args ( parser , cfg )","title":"EnterLowPowerMode"},{"location":"scripts/EnterLowPowerMode/#enterlowpowermode","text":"Bases: KPFTranslatorFunction Set KPF to a low power mode. This is intended for use during power outages. This reduces power use in the AO electronics room. We do not currently recommend any changes in the basement due to the sensitivity of the spectrograph to thermal changes. Procedure: - If a script is running exit or terminate it (depending on --force arg) - Disable HK detector - Stop HK cooling - Power off HK systems: J1, J2, J5 - Stop CRED2 exposures (CONTINUOUS and SAVE) - Stop CRED2 cooling (if on) - Power off CRED2 (K2, K3) Source code in kpf/scripts/EnterLowPowerMode.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class EnterLowPowerMode ( KPFTranslatorFunction ): '''Set KPF to a low power mode. This is intended for use during power outages. This reduces power use in the AO electronics room. We do not currently recommend any changes in the basement due to the sensitivity of the spectrograph to thermal changes. Procedure: - If a script is running exit or terminate it (depending on --force arg) - Disable HK detector - Stop HK cooling - Power off HK systems: J1, J2, J5 - Stop CRED2 exposures (CONTINUOUS and SAVE) - Stop CRED2 cooling (if on) - Power off CRED2 (K2, K3) ''' @classmethod def pre_condition ( cls , args , logger , cfg ): log . info ( 'Configuring KPF for Low Power Mode' ) force = args . get ( 'force' , False ) SCRIPTNAME = ktl . cache ( 'kpfconfig' , 'SCRIPTNAME' ) SCRIPTNAME . monitor () if SCRIPTNAME not in [ 'None' , '' ]: log . warning ( f 'A script ( { SCRIPTNAME } ) is running' ) if force is True : log . warning ( f 'Requesting script stop' ) kpfconfig [ 'SCRIPTSTOP' ] . write ( 'Yes' ) no_script_running = SCRIPTNAME . waitFor ( \"==''\" , timeout = 120 ) if no_script_running is False : log . error ( 'Script failed to stop' ) raise FailedToReachDestination ( f ' { SCRIPTNAME . read () } ' , '' ) else : raise FailedPreCondition ( 'A script is running, not setting Low Power Mode' ) @classmethod def perform ( cls , args , logger , cfg ): kpfconfig = ktl . cache ( 'kpfconfig' ) kpfpower = ktl . cache ( 'kpfpower' ) # Power down Ca HK detector systems kpf_hk = ktl . cache ( 'kpf_hk' ) log . info ( 'Disabling Ca HK detector' ) kpfconfig [ 'CA_HK_ENABLED' ] . write ( 'No' ) log . info ( 'Turning Ca HK detector cooling off' ) kpf_hk [ 'COOLING' ] . write ( 'off' ) time . sleep ( 3 ) log . info ( 'Powering off Ca HK detector systems' ) log . debug ( f \"Powering off { kpfpower [ 'OUTLET_J1_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_J1' ] . write ( 'Off' ) log . debug ( f \"Powering off { kpfpower [ 'OUTLET_J2_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_J2' ] . write ( 'Off' ) log . debug ( f \"Powering off { kpfpower [ 'OUTLET_J5_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_J5' ] . write ( 'Off' ) # Power down CRED2 detector systems kpfguide = ktl . cache ( 'kpfguide' ) log . info ( 'Powering off CRED2 detector systems' ) kpfguide [ 'CONTINUOUS' ] . write ( 'Inactive' ) kpfguide [ 'SAVE' ] . write ( 'Inactive' ) time . sleep ( 2 ) log . debug ( f \"Powering off { kpfpower [ 'OUTLET_K2_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_K2' ] . write ( 'Off' ) log . debug ( f \"Powering off { kpfpower [ 'OUTLET_K3_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_K3' ] . write ( 'Off' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--force\" , dest = \"force\" , default = False , action = \"store_true\" , help = \"Force change? This will terminate any running scripts.\" ) return super () . add_cmdline_args ( parser , cfg )","title":"EnterLowPowerMode"},{"location":"scripts/EstimateOBDuration/","text":"EstimateOBDuration Bases: KPFTranslatorFunction Estimate the duration of the input OB. This script will determine the OB type (science or calibration) and invoke either EstimateCalOBDuration or EstimateSciOBDuration ARGS: :OB: dict A fully specified observing block (OB). Source code in kpf/utils/EstimateOBDuration.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 class EstimateOBDuration ( KPFTranslatorFunction ): '''Estimate the duration of the input OB. This script will determine the OB type (science or calibration) and invoke either `EstimateCalOBDuration` or `EstimateSciOBDuration` ARGS: ===== :OB: `dict` A fully specified observing block (OB). ''' @classmethod def pre_condition ( cls , OB , logger , cfg ): pass @classmethod def perform ( cls , OB , logger , cfg ): if OB [ 'Template_Name' ] == 'kpf_cal' : return EstimateCalOBDuration . execute ( OB ) elif OB [ 'Template_Name' ] == 'kpf_sci' : return EstimateSciOBDuration . execute ( OB ) else : print ( f \"Time estimate not supported for { OB [ 'Template_Name' ] } type\" ) @classmethod def post_condition ( cls , OB , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( '--fast' , '--fastread' , dest = \"fast\" , default = False , action = \"store_true\" , help = 'Use fast readout mode times for estimate?' ) return super () . add_cmdline_args ( parser , cfg )","title":"EstimateOBDuration"},{"location":"scripts/EstimateOBDuration/#estimateobduration","text":"Bases: KPFTranslatorFunction Estimate the duration of the input OB. This script will determine the OB type (science or calibration) and invoke either EstimateCalOBDuration or EstimateSciOBDuration","title":"EstimateOBDuration"},{"location":"scripts/EstimateOBDuration/#kpf.utils.EstimateOBDuration.EstimateOBDuration--args","text":":OB: dict A fully specified observing block (OB). Source code in kpf/utils/EstimateOBDuration.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 class EstimateOBDuration ( KPFTranslatorFunction ): '''Estimate the duration of the input OB. This script will determine the OB type (science or calibration) and invoke either `EstimateCalOBDuration` or `EstimateSciOBDuration` ARGS: ===== :OB: `dict` A fully specified observing block (OB). ''' @classmethod def pre_condition ( cls , OB , logger , cfg ): pass @classmethod def perform ( cls , OB , logger , cfg ): if OB [ 'Template_Name' ] == 'kpf_cal' : return EstimateCalOBDuration . execute ( OB ) elif OB [ 'Template_Name' ] == 'kpf_sci' : return EstimateSciOBDuration . execute ( OB ) else : print ( f \"Time estimate not supported for { OB [ 'Template_Name' ] } type\" ) @classmethod def post_condition ( cls , OB , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( '--fast' , '--fastread' , dest = \"fast\" , default = False , action = \"store_true\" , help = 'Use fast readout mode times for estimate?' ) return super () . add_cmdline_args ( parser , cfg )","title":"ARGS:"},{"location":"scripts/ExecuteSlewCal/","text":"ExecuteSlewCal Bases: KPFTranslatorFunction Script which executes the observations of a Slew Cal This must have arguments as input, either from a file using the -f command line tool, or passed in from the execution engine. ARGS: :OB: dict A fully specified slew cal observing block (OB). Source code in kpf/scripts/ExecuteSlewCal.py 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 class ExecuteSlewCal ( KPFTranslatorFunction ): '''Script which executes the observations of a Slew Cal This must have arguments as input, either from a file using the `-f` command line tool, or passed in from the execution engine. ARGS: ===== :OB: `dict` A fully specified slew cal observing block (OB). ''' abortable = True @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'Template_Name' , allowed_values = [ 'kpf_slewcal' ]) check_input ( args , 'Template_Version' , version_check = True , value_min = '0.4' ) @classmethod def perform ( cls , args , logger , cfg ): set_script_keywords ( Path ( __file__ ) . name , os . getpid ()) log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in args : log . debug ( f \" { key } : { args [ key ] } \" ) log . info ( '-------------------------' ) kpfconfig = ktl . cache ( 'kpfconfig' ) calsource = kpfconfig [ 'SIMULCALSOURCE' ] . read () runagitator = kpfconfig [ 'USEAGITATOR' ] . read ( binary = True ) fast_read_mode = QueryFastReadMode . execute ({}) # Fill in args in case this is not called by configure for acquisition if args . get ( 'TriggerCaHK' , None ) is None : args [ 'TriggerCaHK' ] = False if args . get ( 'TriggerGreen' , None ) is None : args [ 'TriggerGreen' ] = True if args . get ( 'TriggerRed' , None ) is None : args [ 'TriggerRed' ] = True # Skip this lamp if it is not enabled if IsCalSourceEnabled . execute ({ 'CalSource' : calsource }) == False : return # Set Octagon calsource = kpfconfig [ 'SIMULCALSOURCE' ] . read () octagon = ktl . cache ( 'kpfcal' , 'OCTAGON' ) . read () log . debug ( f \"Current OCTAGON = { octagon } , desired = { calsource } \" ) if octagon != calsource : log . info ( f \"Set CalSource/Octagon: { calsource } \" ) SetCalSource . execute ({ 'CalSource' : calsource , 'wait' : False }) progname = ktl . cache ( 'kpfexpose' , 'PROGNAME' ) original_progname = progname . read () ## ---------------------------------------------------------------- ## First, configure lamps and cal bench (may happen during readout) ## ---------------------------------------------------------------- log . info ( f \"Configuring FIU\" ) ConfigureFIU . execute ({ 'mode' : 'Calibration' , 'wait' : False }) check_scriptstop () # Stop here if requested # Configure Cal Bench nd1 = args . get ( 'CalND1' ) nd2 = args . get ( 'CalND2' ) log . info ( f \"Set ND1, ND2 Filter Wheels: { nd1 } , { nd2 } \" ) SetND1 . execute ({ 'CalND1' : nd1 , 'wait' : False }) SetND2 . execute ({ 'CalND2' : nd2 , 'wait' : False }) log . info ( f \"Waiting for Octagon/CalSource, ND1, ND2, FIU\" ) WaitForND1 . execute ( args ) WaitForND2 . execute ( args ) WaitForCalSource . execute ({ 'CalSource' : calsource }) WaitForConfigureFIU . execute ({ 'mode' : 'Calibration' }) check_scriptstop () # Stop here if requested ## ---------------------------------------------------------------- ## Second, configure kpfexpose (may not happen during readout) ## ---------------------------------------------------------------- # Wait for current exposure to readout exposestatus = ktl . cache ( 'kpfexpose' , 'EXPOSE' ) if exposestatus . read () != 'Ready' : log . info ( f \"Waiting for kpfexpose to be Ready\" ) WaitForReady . execute ({}) log . info ( f \"Readout complete\" ) check_scriptstop () # Stop here if requested log . info ( f \"Set Detector List\" ) SetTriggeredDetectors . execute ( args ) log . info ( f \"Set Source Select Shutters\" ) SetSourceSelectShutters . execute ({ 'SSS_Science' : True , 'SSS_Sky' : True , 'SSS_SoCalSci' : False , 'SSS_SoCalCal' : False , 'SSS_CalSciSky' : True }) log . info ( f \"Set exposure time: { args . get ( 'ExpTime' ) : .3f } \" ) SetExpTime . execute ( args ) # No need to specify TimedShutter_Scrambler args [ 'TimedShutter_Scrambler' ] = True log . debug ( f \"Automatically setting TimedShutter_Scrambler: { args [ 'TimedShutter_Scrambler' ] } \" ) # No need to specify TimedShutter_CaHK args [ 'TimedShutter_CaHK' ] = args . get ( 'TriggerCaHK' , False ) log . debug ( f \"Automatically setting TimedShutter_CaHK: { args [ 'TimedShutter_CaHK' ] } \" ) # No need to specify TimedShutter_FlatField args [ 'TimedShutter_FlatField' ] = False log . debug ( f \"Automatically setting TimedShutter_FlatField: { args [ 'TimedShutter_FlatField' ] } \" ) # Set TimedShutter_SimulCal args [ 'TimedShutter_SimulCal' ] = args [ 'TakeSimulCal' ] log . debug ( f \"Automatically setting TimedShutter_SimulCal: { args [ 'TimedShutter_SimulCal' ] } \" ) log . info ( f \"Setting timed shutters\" ) SetTimedShutters . execute ( args ) log . info ( f \"Setting OBJECT: { args . get ( 'Object' ) } \" ) SetObject . execute ( args ) log . info ( f \"Clearing stellar parameters\" ) SetTargetInfo . execute ({}) SetProgram . execute ({ 'progname' : 'ENG' }) ## ---------------------------------------------------------------- ## Third, take actual exposures ## ---------------------------------------------------------------- nexp = args . get ( 'nExp' , 1 ) # If we are in fast read mode, turn on agitator once if runagitator and fast_read_mode : StartAgitator . execute ({}) for j in range ( nexp ): check_scriptstop () # Stop here if requested # Wait for current exposure to readout if exposestatus . read () != 'Ready' : log . info ( f \"Waiting for kpfexpose to be Ready\" ) WaitForReady . execute ({}) log . info ( f \"Readout complete\" ) check_scriptstop () # Stop here if requested # Start next exposure if runagitator and not fast_read_mode : StartAgitator . execute ({}) log . info ( f \"Starting expoure { j + 1 } / { nexp } ( { args . get ( 'Object' ) } )\" ) StartExposure . execute ({}) WaitForReadout . execute ({}) log . info ( f \"Readout has begun\" ) if runagitator and not fast_read_mode : StopAgitator . execute ({}) ZeroOutSlewCalTime . execute ({}) # If we are in fast read mode, turn off agitator at end if runagitator and fast_read_mode : StopAgitator . execute ({}) # Set FIU Mode log . info ( 'Setting FIU mode to Observing' ) ConfigureFIU . execute ({ 'mode' : 'Observing' , 'wait' : False }) # Set PROGNAME log . info ( f 'Setting PROGNAME back to { original_progname } ' ) SetProgram . execute ({ 'progname' : original_progname }) clear_script_keywords () @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"ExecuteSlewCal"},{"location":"scripts/ExecuteSlewCal/#executeslewcal","text":"Bases: KPFTranslatorFunction Script which executes the observations of a Slew Cal This must have arguments as input, either from a file using the -f command line tool, or passed in from the execution engine.","title":"ExecuteSlewCal"},{"location":"scripts/ExecuteSlewCal/#kpf.scripts.ExecuteSlewCal.ExecuteSlewCal--args","text":":OB: dict A fully specified slew cal observing block (OB). Source code in kpf/scripts/ExecuteSlewCal.py 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 class ExecuteSlewCal ( KPFTranslatorFunction ): '''Script which executes the observations of a Slew Cal This must have arguments as input, either from a file using the `-f` command line tool, or passed in from the execution engine. ARGS: ===== :OB: `dict` A fully specified slew cal observing block (OB). ''' abortable = True @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'Template_Name' , allowed_values = [ 'kpf_slewcal' ]) check_input ( args , 'Template_Version' , version_check = True , value_min = '0.4' ) @classmethod def perform ( cls , args , logger , cfg ): set_script_keywords ( Path ( __file__ ) . name , os . getpid ()) log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in args : log . debug ( f \" { key } : { args [ key ] } \" ) log . info ( '-------------------------' ) kpfconfig = ktl . cache ( 'kpfconfig' ) calsource = kpfconfig [ 'SIMULCALSOURCE' ] . read () runagitator = kpfconfig [ 'USEAGITATOR' ] . read ( binary = True ) fast_read_mode = QueryFastReadMode . execute ({}) # Fill in args in case this is not called by configure for acquisition if args . get ( 'TriggerCaHK' , None ) is None : args [ 'TriggerCaHK' ] = False if args . get ( 'TriggerGreen' , None ) is None : args [ 'TriggerGreen' ] = True if args . get ( 'TriggerRed' , None ) is None : args [ 'TriggerRed' ] = True # Skip this lamp if it is not enabled if IsCalSourceEnabled . execute ({ 'CalSource' : calsource }) == False : return # Set Octagon calsource = kpfconfig [ 'SIMULCALSOURCE' ] . read () octagon = ktl . cache ( 'kpfcal' , 'OCTAGON' ) . read () log . debug ( f \"Current OCTAGON = { octagon } , desired = { calsource } \" ) if octagon != calsource : log . info ( f \"Set CalSource/Octagon: { calsource } \" ) SetCalSource . execute ({ 'CalSource' : calsource , 'wait' : False }) progname = ktl . cache ( 'kpfexpose' , 'PROGNAME' ) original_progname = progname . read () ## ---------------------------------------------------------------- ## First, configure lamps and cal bench (may happen during readout) ## ---------------------------------------------------------------- log . info ( f \"Configuring FIU\" ) ConfigureFIU . execute ({ 'mode' : 'Calibration' , 'wait' : False }) check_scriptstop () # Stop here if requested # Configure Cal Bench nd1 = args . get ( 'CalND1' ) nd2 = args . get ( 'CalND2' ) log . info ( f \"Set ND1, ND2 Filter Wheels: { nd1 } , { nd2 } \" ) SetND1 . execute ({ 'CalND1' : nd1 , 'wait' : False }) SetND2 . execute ({ 'CalND2' : nd2 , 'wait' : False }) log . info ( f \"Waiting for Octagon/CalSource, ND1, ND2, FIU\" ) WaitForND1 . execute ( args ) WaitForND2 . execute ( args ) WaitForCalSource . execute ({ 'CalSource' : calsource }) WaitForConfigureFIU . execute ({ 'mode' : 'Calibration' }) check_scriptstop () # Stop here if requested ## ---------------------------------------------------------------- ## Second, configure kpfexpose (may not happen during readout) ## ---------------------------------------------------------------- # Wait for current exposure to readout exposestatus = ktl . cache ( 'kpfexpose' , 'EXPOSE' ) if exposestatus . read () != 'Ready' : log . info ( f \"Waiting for kpfexpose to be Ready\" ) WaitForReady . execute ({}) log . info ( f \"Readout complete\" ) check_scriptstop () # Stop here if requested log . info ( f \"Set Detector List\" ) SetTriggeredDetectors . execute ( args ) log . info ( f \"Set Source Select Shutters\" ) SetSourceSelectShutters . execute ({ 'SSS_Science' : True , 'SSS_Sky' : True , 'SSS_SoCalSci' : False , 'SSS_SoCalCal' : False , 'SSS_CalSciSky' : True }) log . info ( f \"Set exposure time: { args . get ( 'ExpTime' ) : .3f } \" ) SetExpTime . execute ( args ) # No need to specify TimedShutter_Scrambler args [ 'TimedShutter_Scrambler' ] = True log . debug ( f \"Automatically setting TimedShutter_Scrambler: { args [ 'TimedShutter_Scrambler' ] } \" ) # No need to specify TimedShutter_CaHK args [ 'TimedShutter_CaHK' ] = args . get ( 'TriggerCaHK' , False ) log . debug ( f \"Automatically setting TimedShutter_CaHK: { args [ 'TimedShutter_CaHK' ] } \" ) # No need to specify TimedShutter_FlatField args [ 'TimedShutter_FlatField' ] = False log . debug ( f \"Automatically setting TimedShutter_FlatField: { args [ 'TimedShutter_FlatField' ] } \" ) # Set TimedShutter_SimulCal args [ 'TimedShutter_SimulCal' ] = args [ 'TakeSimulCal' ] log . debug ( f \"Automatically setting TimedShutter_SimulCal: { args [ 'TimedShutter_SimulCal' ] } \" ) log . info ( f \"Setting timed shutters\" ) SetTimedShutters . execute ( args ) log . info ( f \"Setting OBJECT: { args . get ( 'Object' ) } \" ) SetObject . execute ( args ) log . info ( f \"Clearing stellar parameters\" ) SetTargetInfo . execute ({}) SetProgram . execute ({ 'progname' : 'ENG' }) ## ---------------------------------------------------------------- ## Third, take actual exposures ## ---------------------------------------------------------------- nexp = args . get ( 'nExp' , 1 ) # If we are in fast read mode, turn on agitator once if runagitator and fast_read_mode : StartAgitator . execute ({}) for j in range ( nexp ): check_scriptstop () # Stop here if requested # Wait for current exposure to readout if exposestatus . read () != 'Ready' : log . info ( f \"Waiting for kpfexpose to be Ready\" ) WaitForReady . execute ({}) log . info ( f \"Readout complete\" ) check_scriptstop () # Stop here if requested # Start next exposure if runagitator and not fast_read_mode : StartAgitator . execute ({}) log . info ( f \"Starting expoure { j + 1 } / { nexp } ( { args . get ( 'Object' ) } )\" ) StartExposure . execute ({}) WaitForReadout . execute ({}) log . info ( f \"Readout has begun\" ) if runagitator and not fast_read_mode : StopAgitator . execute ({}) ZeroOutSlewCalTime . execute ({}) # If we are in fast read mode, turn off agitator at end if runagitator and fast_read_mode : StopAgitator . execute ({}) # Set FIU Mode log . info ( 'Setting FIU mode to Observing' ) ConfigureFIU . execute ({ 'mode' : 'Observing' , 'wait' : False }) # Set PROGNAME log . info ( f 'Setting PROGNAME back to { original_progname } ' ) SetProgram . execute ({ 'progname' : original_progname }) clear_script_keywords () @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"ARGS:"},{"location":"scripts/FVCPower/","text":"FVCPower Bases: KPFTranslatorFunction Turn on or off the power for the specified FVC camera. Parameters: camera ( str ) \u2013 Which FVC camera? Allowed values: SCI, CAHK, EXT, CAL power ( str ) \u2013 The desired state. Allowed values: on or off KTL Keywords Used: kpfpower.KPFFVC1 kpfpower.KPFFVC2 kpfpower.KPFFVC3 Source code in kpf/fvc/FVCPower.py 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class FVCPower ( KPFTranslatorFunction ): '''Turn on or off the power for the specified FVC camera. Args: camera (str): Which FVC camera? Allowed values: SCI, CAHK, EXT, CAL power (str): The desired state. Allowed values: on or off KTL Keywords Used: - `kpfpower.KPFFVC1` - `kpfpower.KPFFVC2` - `kpfpower.KPFFVC3` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'camera' , allowed_values = [ 'SCI' , 'CAHK' , 'CAL' ]) @classmethod def perform ( cls , args , logger , cfg ): camera = args . get ( 'camera' ) camnum = { 'SCI' : 1 , 'CAHK' : 2 , 'CAL' : 3 }[ camera ] powerkw = ktl . cache ( 'kpfpower' , f 'KPFFVC { camnum } ' ) dest = args . get ( 'power' ) if powerkw . read () . lower () != dest . lower (): log . info ( f \"Turning { dest } { camera } FVC\" ) powerkw . write ( args . get ( 'power' )) shim = cfg . getfloat ( 'times' , 'fvc_command_timeshim' , fallback = 2 ) time . sleep ( shim ) @classmethod def post_condition ( cls , args , logger , cfg ): camera = args . get ( 'camera' ) camnum = { 'SCI' : 1 , 'CAHK' : 2 , 'CAL' : 3 }[ camera ] powerkw = ktl . cache ( 'kpfpower' , f 'KPFFVC { camnum } ' ) timeout = cfg . getfloat ( 'times' , 'fvc_command_timeout' , fallback = 1 ) dest = args . get ( 'power' ) success = powerkw . waitFor ( f \"== ' { dest } '\" , timeout = timeout ) if success is False : raise FailedToReachDestination ( powerkw . read (), dest ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'camera' , type = str , choices = [ 'SCI' , 'CAHK' , 'CAL' ], help = 'The FVC camera' ) parser . add_argument ( 'power' , type = str , choices = [ 'on' , 'off' ], help = 'Desired power state: \"on\" or \"off\"' ) return super () . add_cmdline_args ( parser , cfg )","title":"FVCPower"},{"location":"scripts/FVCPower/#fvcpower","text":"Bases: KPFTranslatorFunction Turn on or off the power for the specified FVC camera. Parameters: camera ( str ) \u2013 Which FVC camera? Allowed values: SCI, CAHK, EXT, CAL power ( str ) \u2013 The desired state. Allowed values: on or off KTL Keywords Used: kpfpower.KPFFVC1 kpfpower.KPFFVC2 kpfpower.KPFFVC3 Source code in kpf/fvc/FVCPower.py 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class FVCPower ( KPFTranslatorFunction ): '''Turn on or off the power for the specified FVC camera. Args: camera (str): Which FVC camera? Allowed values: SCI, CAHK, EXT, CAL power (str): The desired state. Allowed values: on or off KTL Keywords Used: - `kpfpower.KPFFVC1` - `kpfpower.KPFFVC2` - `kpfpower.KPFFVC3` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'camera' , allowed_values = [ 'SCI' , 'CAHK' , 'CAL' ]) @classmethod def perform ( cls , args , logger , cfg ): camera = args . get ( 'camera' ) camnum = { 'SCI' : 1 , 'CAHK' : 2 , 'CAL' : 3 }[ camera ] powerkw = ktl . cache ( 'kpfpower' , f 'KPFFVC { camnum } ' ) dest = args . get ( 'power' ) if powerkw . read () . lower () != dest . lower (): log . info ( f \"Turning { dest } { camera } FVC\" ) powerkw . write ( args . get ( 'power' )) shim = cfg . getfloat ( 'times' , 'fvc_command_timeshim' , fallback = 2 ) time . sleep ( shim ) @classmethod def post_condition ( cls , args , logger , cfg ): camera = args . get ( 'camera' ) camnum = { 'SCI' : 1 , 'CAHK' : 2 , 'CAL' : 3 }[ camera ] powerkw = ktl . cache ( 'kpfpower' , f 'KPFFVC { camnum } ' ) timeout = cfg . getfloat ( 'times' , 'fvc_command_timeout' , fallback = 1 ) dest = args . get ( 'power' ) success = powerkw . waitFor ( f \"== ' { dest } '\" , timeout = timeout ) if success is False : raise FailedToReachDestination ( powerkw . read (), dest ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'camera' , type = str , choices = [ 'SCI' , 'CAHK' , 'CAL' ], help = 'The FVC camera' ) parser . add_argument ( 'power' , type = str , choices = [ 'on' , 'off' ], help = 'Desired power state: \"on\" or \"off\"' ) return super () . add_cmdline_args ( parser , cfg )","title":"FVCPower"},{"location":"scripts/Fit2DGridSearch/","text":"Fit2DGridSearch Bases: KPFTranslatorFunction Description Take two 1D grid search runs (one in X and one in Y) ... Parameters None Source code in kpf/engineering/analysis/Fit2DGridSearch.py 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 class Fit2DGridSearch ( KPFTranslatorFunction ): '''# Description Take two 1D grid search runs (one in X and one in Y) ... # Parameters None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # 20240718at140930_GridSearch.log # TipTilt20240718at140930_GridSearch.fits log_file_x = Path ( args . get ( 'logfileX' )) fgs_cube_fileX = log_file_x . parent / Path ( f 'TipTilt { log_file_x . stem } .fits' ) log_file_y = Path ( args . get ( 'logfileY' )) fgs_cube_fileY = log_file_y . parent / Path ( f 'TipTilt { log_file_y . stem } .fits' ) # Try to determine targname/comment try : with open ( log_file_x ) as FO : lines = FO . readlines () for line in lines [: 60 ]: m_comment = re . search ( \"comment: (.*)\" , line ) if m_comment is not None : comment = m_comment . groups ()[ 0 ] . strip ( ' \\n ' ) log . info ( f \" Log Comment: { comment } \" ) except : comment = '' fit_2D_fiber_center ( fgs_cube_fileX , fgs_cube_fileY , xcent = args . get ( 'xfit' ), ycent = args . get ( 'yfit' ), targname = comment ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'logfileX' , type = str , help = \"The GridSearch log file for the X pixel scan\" ) parser . add_argument ( 'logfileY' , type = str , help = \"The GridSearch log file for the Y pixel scan\" ) parser . add_argument ( \"--xfit\" , dest = \"xfit\" , type = float , default = 335.5 , help = \"The X pixel position to use as the center when overlaying the model.\" ) parser . add_argument ( \"--yfit\" , dest = \"yfit\" , type = float , default = 258 , help = \"The X pixel position to use as the center when overlaying the model.\" ) return super () . add_cmdline_args ( parser , cfg )","title":"Fit2DGridSearch"},{"location":"scripts/Fit2DGridSearch/#fit2dgridsearch","text":"Bases: KPFTranslatorFunction","title":"Fit2DGridSearch"},{"location":"scripts/Fit2DGridSearch/#kpf.engineering.analysis.Fit2DGridSearch.Fit2DGridSearch--description","text":"Take two 1D grid search runs (one in X and one in Y) ...","title":"Description"},{"location":"scripts/Fit2DGridSearch/#kpf.engineering.analysis.Fit2DGridSearch.Fit2DGridSearch--parameters","text":"None Source code in kpf/engineering/analysis/Fit2DGridSearch.py 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 class Fit2DGridSearch ( KPFTranslatorFunction ): '''# Description Take two 1D grid search runs (one in X and one in Y) ... # Parameters None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # 20240718at140930_GridSearch.log # TipTilt20240718at140930_GridSearch.fits log_file_x = Path ( args . get ( 'logfileX' )) fgs_cube_fileX = log_file_x . parent / Path ( f 'TipTilt { log_file_x . stem } .fits' ) log_file_y = Path ( args . get ( 'logfileY' )) fgs_cube_fileY = log_file_y . parent / Path ( f 'TipTilt { log_file_y . stem } .fits' ) # Try to determine targname/comment try : with open ( log_file_x ) as FO : lines = FO . readlines () for line in lines [: 60 ]: m_comment = re . search ( \"comment: (.*)\" , line ) if m_comment is not None : comment = m_comment . groups ()[ 0 ] . strip ( ' \\n ' ) log . info ( f \" Log Comment: { comment } \" ) except : comment = '' fit_2D_fiber_center ( fgs_cube_fileX , fgs_cube_fileY , xcent = args . get ( 'xfit' ), ycent = args . get ( 'yfit' ), targname = comment ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'logfileX' , type = str , help = \"The GridSearch log file for the X pixel scan\" ) parser . add_argument ( 'logfileY' , type = str , help = \"The GridSearch log file for the Y pixel scan\" ) parser . add_argument ( \"--xfit\" , dest = \"xfit\" , type = float , default = 335.5 , help = \"The X pixel position to use as the center when overlaying the model.\" ) parser . add_argument ( \"--yfit\" , dest = \"yfit\" , type = float , default = 258 , help = \"The X pixel position to use as the center when overlaying the model.\" ) return super () . add_cmdline_args ( parser , cfg )","title":"Parameters"},{"location":"scripts/GetGaiaStars/","text":"GetGaiaStars Bases: KPFTranslatorFunction Build a ds9 region file of Gaia catalog stars which ought to be present in the specified guider image. Parameters: file ( str ) \u2013 The file to retrieve stars for. Source code in kpf/guider/GetGaiaStars.py 20 21 22 23 24 25 26 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 class GetGaiaStars ( KPFTranslatorFunction ): '''Build a ds9 region file of Gaia catalog stars which ought to be present in the specified guider image. Args: file (str): The file to retrieve stars for. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): if Vizier is None : raise FailedPreCondition ( 'Unable to import astroquery.vizier' ) file = Path ( args . get ( 'file' , '/tmp/CRED2.fits' )) . expanduser () . absolute () if file . exists () is False : raise FailedPreCondition ( f 'Fould not find input file: { file } ' ) @classmethod def perform ( cls , args , logger , cfg ): catalog_id = cfg . get ( 'stellar_catalog' , 'catalog_id' , fallback = 'I/345/gaia2' ) search_radius = cfg . getfloat ( 'stellar_catalog' , 'search_radius' , fallback = 28 ) ds9_color = cfg . get ( 'stellar_catalog' , 'ds9_color' , fallback = 'cyan' ) ds9_font = cfg . get ( 'stellar_catalog' , 'ds9_font' , fallback = 'helvetica 10 normal roman' ) requery_threshold = cfg . getfloat ( 'stellar_catalog' , 'requery_threshold' , fallback = 5 ) region_file = Path ( '~/.CRED2_auto_regions.reg' ) . expanduser () cntr_file = Path ( '~/.CRED2_auto_regions.cntr' ) . expanduser () file = Path ( args . get ( 'file' , './junk.fits' )) . expanduser () . absolute () # hdul = fits.open(file) header = fits . getheader ( file ) w = WCS ( header ) # cntr = w.pixel_to_world(hdul[0].data.shape[0]/2, hdul[0].data.shape[1]/2) cntr = w . pixel_to_world ( int ( header . get ( 'NAXIS2' )) / 2 , int ( header . get ( 'NAXIS1' )) / 2 ) if cntr_file . exists () is False : with open ( cntr_file , 'w' ) as FO : FO . write ( cntr . to_string ( 'hmsdms' , precision = 2 )) else : with open ( cntr_file , 'r' ) as FO : cntr_file_string = FO . readlines () file_cntr = SkyCoord ( cntr_file_string , unit = ( u . hourangle , u . deg ), frame = 'icrs' ) sep = file_cntr . separation ( cntr ) # If we're in a new position, query for a new catalog of stars and # write a new region file if sep [ 0 ] . to ( u . arcsec ) . value > requery_threshold : print ( f 'Querying for catalog: { cntr . to_string ( \"hmsdms\" , precision = 2 ) } ' ) gaia = Vizier . query_region ( cntr , radius = search_radius * u . arcsec , catalog = catalog_id )[ 0 ] regions = [ f '# Region file format: DS9 version 4.1' , f 'global color= { ds9_color } dashlist=8 3 width=1 font=\" { ds9_font } \"' , ] for star in gaia : sc = SkyCoord ( star [ 'RA_ICRS' ], star [ 'DE_ICRS' ], unit = ( u . deg , u . deg ), frame = 'icrs' ) coord_string = sc . to_string ( 'hmsdms' , sep = ':' , precision = 2 ) . replace ( ' ' , ',' ) newline = f \"circle( { coord_string } ,0.5 \\\" )\" # \\# text=\\{\"#\\}\" newline += \" # text={\" newline += f \" { star [ 'RPmag' ] : .1f } \" newline += \"}\" regions . append ( newline ) if region_file . exists (): region_file . unlink () with open ( region_file , 'w' ) as FO : for line in regions : FO . write ( line + ' \\n ' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'file' , type = str , help = 'The CRED2 file to retrieve stars for' ) return super () . add_cmdline_args ( parser , cfg )","title":"GetGaiaStars"},{"location":"scripts/GetGaiaStars/#getgaiastars","text":"Bases: KPFTranslatorFunction Build a ds9 region file of Gaia catalog stars which ought to be present in the specified guider image. Parameters: file ( str ) \u2013 The file to retrieve stars for. Source code in kpf/guider/GetGaiaStars.py 20 21 22 23 24 25 26 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 class GetGaiaStars ( KPFTranslatorFunction ): '''Build a ds9 region file of Gaia catalog stars which ought to be present in the specified guider image. Args: file (str): The file to retrieve stars for. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): if Vizier is None : raise FailedPreCondition ( 'Unable to import astroquery.vizier' ) file = Path ( args . get ( 'file' , '/tmp/CRED2.fits' )) . expanduser () . absolute () if file . exists () is False : raise FailedPreCondition ( f 'Fould not find input file: { file } ' ) @classmethod def perform ( cls , args , logger , cfg ): catalog_id = cfg . get ( 'stellar_catalog' , 'catalog_id' , fallback = 'I/345/gaia2' ) search_radius = cfg . getfloat ( 'stellar_catalog' , 'search_radius' , fallback = 28 ) ds9_color = cfg . get ( 'stellar_catalog' , 'ds9_color' , fallback = 'cyan' ) ds9_font = cfg . get ( 'stellar_catalog' , 'ds9_font' , fallback = 'helvetica 10 normal roman' ) requery_threshold = cfg . getfloat ( 'stellar_catalog' , 'requery_threshold' , fallback = 5 ) region_file = Path ( '~/.CRED2_auto_regions.reg' ) . expanduser () cntr_file = Path ( '~/.CRED2_auto_regions.cntr' ) . expanduser () file = Path ( args . get ( 'file' , './junk.fits' )) . expanduser () . absolute () # hdul = fits.open(file) header = fits . getheader ( file ) w = WCS ( header ) # cntr = w.pixel_to_world(hdul[0].data.shape[0]/2, hdul[0].data.shape[1]/2) cntr = w . pixel_to_world ( int ( header . get ( 'NAXIS2' )) / 2 , int ( header . get ( 'NAXIS1' )) / 2 ) if cntr_file . exists () is False : with open ( cntr_file , 'w' ) as FO : FO . write ( cntr . to_string ( 'hmsdms' , precision = 2 )) else : with open ( cntr_file , 'r' ) as FO : cntr_file_string = FO . readlines () file_cntr = SkyCoord ( cntr_file_string , unit = ( u . hourangle , u . deg ), frame = 'icrs' ) sep = file_cntr . separation ( cntr ) # If we're in a new position, query for a new catalog of stars and # write a new region file if sep [ 0 ] . to ( u . arcsec ) . value > requery_threshold : print ( f 'Querying for catalog: { cntr . to_string ( \"hmsdms\" , precision = 2 ) } ' ) gaia = Vizier . query_region ( cntr , radius = search_radius * u . arcsec , catalog = catalog_id )[ 0 ] regions = [ f '# Region file format: DS9 version 4.1' , f 'global color= { ds9_color } dashlist=8 3 width=1 font=\" { ds9_font } \"' , ] for star in gaia : sc = SkyCoord ( star [ 'RA_ICRS' ], star [ 'DE_ICRS' ], unit = ( u . deg , u . deg ), frame = 'icrs' ) coord_string = sc . to_string ( 'hmsdms' , sep = ':' , precision = 2 ) . replace ( ' ' , ',' ) newline = f \"circle( { coord_string } ,0.5 \\\" )\" # \\# text=\\{\"#\\}\" newline += \" # text={\" newline += f \" { star [ 'RPmag' ] : .1f } \" newline += \"}\" regions . append ( newline ) if region_file . exists (): region_file . unlink () with open ( region_file , 'w' ) as FO : for line in regions : FO . write ( line + ' \\n ' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'file' , type = str , help = 'The CRED2 file to retrieve stars for' ) return super () . add_cmdline_args ( parser , cfg )","title":"GetGaiaStars"},{"location":"scripts/GridSearch/","text":"GridSearch Bases: KPFTranslatorFunction Executes an engineering grid search OB. This must have arguments as input, either from a file using the -f command line tool, or passed in from the execution engine. ARGS: None Source code in kpf/engineering/GridSearch.py 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 class GridSearch ( KPFTranslatorFunction ): '''Executes an engineering grid search OB. This must have arguments as input, either from a file using the `-f` command line tool, or passed in from the execution engine. ARGS: ===== None ''' abortable = True @classmethod @obey_scriptrun def pre_condition ( cls , OB , logger , cfg ): check_input ( OB , 'Template_Name' , allowed_values = [ 'kpf_eng_grid' ]) check_input ( OB , 'Template_Version' , version_check = True , value_min = '0.4' ) check_input ( OB , 'Grid' , allowed_values = [ 'TipTilt' , 'SciADC' ]) check_input ( OB , 'nx' ) check_input ( OB , 'ny' ) check_input ( OB , 'dx' ) check_input ( OB , 'dy' ) check_input ( OB , 'ExpMeter_exptime' ) FVCs = OB . get ( 'FVCs' , '' ) . split ( ',' ) for FVC in FVCs : if FVC not in [ 'SCI' , 'CAHK' , 'EXT' , '' ]: raise FailedPreCondition ( f \"FVC { FVC } not supported\" ) @classmethod @register_script ( Path ( __file__ ) . name , os . getpid ()) @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in OB : log . debug ( f \" { key } : { OB [ key ] } \" ) log . info ( '-------------------------' ) grid = OB . get ( 'Grid' ) this_file_name = Path ( __file__ ) . name . replace ( '.py' , '' ) utnow = datetime . utcnow () now_str = utnow . strftime ( '%Y%m %d at%H%M%S' ) date_str = ( utnow - timedelta ( days = 1 )) . strftime ( '%Y%b %d ' ) . lower () log_path = Path ( f '/s/sdata1701/KPFTranslator_logs/ { date_str } ' ) images_file = log_path / Path ( f ' { grid }{ this_file_name } _images_ { now_str } .txt' ) fluxes_file = log_path / Path ( f ' { grid }{ this_file_name } _fluxes_ { now_str } .txt' ) images = Table ( names = ( 'file' , 'camera' , 'x' , 'y' ), dtype = ( 'a90' , 'a10' , 'f4' , 'f4' )) expmeter_flux = Table ( names = ( 'i' , 'j' , 'x' , 'y' , 'bck1' , 'bck2' , 'bck3' , 'bck4' , 'cur1' , 'cur2' , 'cur3' , 'cur4' , 'raw1' , 'raw2' , 'raw3' , 'raw4' , 'nimages' ), dtype = ( 'i4' , 'i4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'i4' )) FVCs = OB . get ( 'FVCs' , '' ) . split ( ',' ) nx = OB . get ( 'nx' ) ny = OB . get ( 'ny' ) dx = OB . get ( 'dx' ) dy = OB . get ( 'dy' ) xis = [ xi for xi in range ( int ( - nx / 2 ), int (( nx + 1 ) / 2 ), 1 )] yis = [ yi for yi in range ( int ( - ny / 2 ), int (( ny + 1 ) / 2 ), 1 )] xindicies = [ ind for ind in range ( nx )] yindicies = [ ind for ind in range ( ny )] xs = [ xi * dx for xi in xis ] ys = [ yi * dy for yi in yis ] # Set up guider (assume parameters set during acquisition of star) kpfguide = ktl . cache ( 'kpfguide' ) log . info ( 'Setting TRIGCUBE Inactive' ) kpfguide [ 'TRIGCUBE' ] . write ( 'Inactive' ) if grid == 'TipTilt' : log . info ( f \"DAR_ENABLE = { kpfguide [ 'DAR_ENABLE' ] . read () } \" ) dar_offset = kpfguide [ 'DAR_OFFSET' ] . read ( binary = True ) log . info ( f \"DAR_OFFSET = { dar_offset [ 0 ] : .2f } { dar_offset [ 1 ] : .2f } \" ) xpix0 , ypix0 = kpfguide [ 'PIX_TARGET' ] . read ( binary = True ) log . info ( f \"PIX_TARGET is { xpix0 : .2f } , { ypix0 : .2f } \" ) basex , basey = kpfguide [ 'CURRENT_BASE' ] . read ( binary = True ) log . info ( f \"CURRENT_BASE is { basex : .2f } , { basey : .2f } \" ) # Pixel targets must be in absolute coordinates xs = [ basex + xpix for xpix in xs ] ys = [ basey + ypix for ypix in ys ] elif grid == 'SciADC' : kpffiu = ktl . cache ( 'kpffiu' ) kpffiu [ 'ADCTRACK' ] . write ( 'Off' ) nominalx , nominaly = kpffiu [ 'ADCPRISMS' ] . read ( binary = True ) x0 = OB . get ( 'ADC1Position' ) if str ( x0 ) . lower () == 'nominal' : x0 = nominalx else : x0 = float ( OB . get ( 'ADC1Position' )) y0 = OB . get ( 'ADC2Position' ) if str ( y0 ) . lower () == 'nominal' : y0 = nominaly else : y0 = float ( OB . get ( 'ADC2Position' )) log . info ( f \"ADC starting position: { x0 : .1f } { y0 : .1f } \" ) # Apply reverse rotation if requested if OB . get ( 'ADC1Reverse' , False ) is True : x0 = - x0 if OB . get ( 'ADC2Reverse' , False ) is True : y0 = - y0 log . info ( f \"ADC reverse nominal position: { x0 : .1f } { y0 : .1f } \" ) # Apply flip if requested if OB . get ( 'ADC1Flip' , False ) is True : x0 += 180 if OB . get ( 'ADC2Flip' , False ) is True : y0 += 180 log . info ( f \"ADC flip nominal position: { x0 : .1f } { y0 : .1f } \" ) xs = [ x + x0 for x in xs ] ys = [ y + y0 for y in ys ] # Set up kpfexpose kpfexpose = ktl . cache ( 'kpfexpose' ) SetSourceSelectShutters . execute ( OB ) OB [ 'TimedShutter_Scrambler' ] = True OB [ 'TimedShutter_CaHK' ] = OB . get ( 'TriggerCaHK' , False ) SetTimedShutters . execute ( OB ) SetTriggeredDetectors . execute ( OB ) total_exptime = OB . get ( 'TimeOnPosition' ) SetExpTime . execute ({ 'ExpTime' : total_exptime }) # Configure Exposure Meter kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) ExpMeter_exptime = OB . get ( 'ExpMeter_exptime' ) log . info ( f \"Setting kpf_expmeter.EXPOSURE = { ExpMeter_exptime : .2f } s\" ) kpf_expmeter [ 'EXPOSURE' ] . write ( ExpMeter_exptime ) # Set up FVCs kpffvc = ktl . cache ( 'kpffvc' ) for FVC in [ 'SCI' , 'CAHK' , 'EXT' ]: if FVC in FVCs and OB . get ( f ' { FVC } FVC_exptime' , None ) != None : exptime = OB . get ( f ' { FVC } FVC_exptime' ) log . info ( f \"Setting { FVC } FVC ExpTime = { exptime : .2f } s\" ) SetFVCExpTime . execute ({ 'camera' : FVC , 'exptime' : exptime }) for i in xindicies : yindicies . reverse () for j in yindicies : check_scriptstop () if grid == 'TipTilt' : ##------------------------------------------------------ ## Tip Tilt ##------------------------------------------------------ log . info ( f \"Adjusting CURRENT_BASE to ( { xs [ i ] : .2f } , { ys [ j ] : .2f } ) ( { xis [ i ] } , { yis [ j ] } )\" ) max_move = 3 precisison = 0.01 current_base = ktl . cache ( 'kpfguide' , 'CURRENT_BASE' ) current_cb = current_base . read ( binary = True ) delta_cb = ( xs [ i ] - current_cb [ 0 ], ys [ j ] - current_cb [ 1 ]) while abs ( delta_cb [ 0 ]) > precisison or abs ( delta_cb [ 1 ]) > precisison : # Calc X move new_X_target = current_cb [ 0 ] if abs ( delta_cb [ 0 ]) > precisison : move_sign_X = delta_cb [ 0 ] / abs ( delta_cb [ 0 ]) move_mag_X = min ([ max_move , abs ( delta_cb [ 0 ])]) new_X_target += move_sign_X * move_mag_X # Calc Y move new_Y_target = current_cb [ 1 ] if abs ( delta_cb [ 1 ]) > precisison : move_sign_Y = delta_cb [ 1 ] / abs ( delta_cb [ 1 ]) move_mag_Y = min ([ max_move , abs ( delta_cb [ 1 ])]) new_Y_target += move_sign_Y * move_mag_Y log . info ( f \" Setting CURRENT_BASE to { new_X_target : .2f } , { new_Y_target : .2f } \" ) SetTipTiltTargetPixel . execute ({ 'x' : new_X_target , 'y' : new_Y_target }) success = ktl . waitFor ( \"$kpfguide.TIPTILT_PHASE == 'Tracking'\" , timeout = 5 ) current_cb = current_base . read ( binary = True ) delta_cb = ( xs [ i ] - current_cb [ 0 ], ys [ j ] - current_cb [ 1 ]) xpix , ypix = kpfguide [ 'PIX_TARGET' ] . read ( binary = True ) log . info ( f \"PIX_TARGET is { xpix : .2f } , { ypix : .2f } \" ) # Check for lost star obj_choice = kpfguide [ 'OBJECT_CHOICE' ] . read () if obj_choice in [ None , 'None' ]: log . error ( f \" --> Lost star <--\" ) log . info ( f \"Stopping tip tilt\" ) StopTipTilt . execute ({}) time . sleep ( 1 ) log . info ( f \"Starting tip tilt\" ) StartTipTilt . execute ({}) time . sleep ( 5 ) # Check for lost star obj_choice = kpfguide [ 'OBJECT_CHOICE' ] . read () if obj_choice in [ None , 'None' ]: log . error ( f \" --> Lost star <--\" ) subprocess . call ([ 'kpf' , 'restart' , 'kpfguide2' ]) time . sleep ( 5 ) log . info ( f \"Starting tip tilt\" ) StartTipTilt . execute ({}) time . sleep ( 5 ) obj_choice = kpfguide [ 'OBJECT_CHOICE' ] . read () if obj_choice in [ None , 'None' ]: log . error ( f \" --> Lost star <--\" ) raise KPFException ( 'Lost Star' ) elif grid == 'SciADC' : ##------------------------------------------------------ ## Science ADC ##------------------------------------------------------ log . info ( f \"Offsetting to ( { xs [ i ] : .2f } , { ys [ j ] : .2f } ) ( { xis [ i ] } , { yis [ j ] } )\" ) kpffiu [ 'ADC1VAL' ] . write ( xs [ i ]) kpffiu [ 'ADC2VAL' ] . write ( ys [ j ]) log . info ( f \"Absolute position: { xs [ i ] : .1f } { ys [ j ] : .1f } \" ) expr = '($kpffiu.ADC1STA == Ready) and ($kpffiu.ADC2STA == Ready)' success = ktl . waitFor ( expr , timeout = 2 * max ([ dx * nx , dy * ny ]) / 5 ) if success is not True : ADC1STA = kpffiu [ 'ADC1STA' ] . read () ADC2STA = kpffiu [ 'ADC2STA' ] . read () msg = f 'Timed out waiting for ADCs: ADC1STA= { ADC1STA } ADC2STA= { ADC2STA } ' raise KPFException ( msg ) WaitForReady . execute ({}) check_scriptstop () # Stop here if requested # Start Exposure Meter and Science Cameras kpfexpose [ 'OBJECT' ] . write ( f 'Grid search { xs [ i ] } , { ys [ j ] } ' ) log . info ( f \"Starting kpfexpose cameras\" ) StartExposure . execute ({}) # Begin timestamp for history retrieval begin = time . time () # Take CRED2 image if OB . get ( 'UseCRED2' , True ) is True : log . info ( 'Starting guider Trigger file' ) initial_last_cube = kpfguide [ 'LASTTRIGFILE' ] . read () StartTriggerFile . execute ({}) # Start FVC Exposures initial_lastfile = {} failedFVCs = [] for FVC in [ 'SCI' , 'CAHK' , 'EXT' ]: if FVC in FVCs : initial_lastfile [ FVC ] = kpffvc [ f \" { FVC } LASTFILE\" ] . read () log . debug ( f \" Initial lastfile for { FVC } = { initial_lastfile [ FVC ] } \" ) log . info ( f \" Starting { FVC } FVC exposure\" ) try : TakeFVCExposure . execute ({ 'camera' : FVC , 'wait' : False }) except : log . error ( 'Starting FVC image failed' ) failedFVCs . append ( FVC ) check_scriptstop () # Collect files for FVC exposures for FVC in [ 'SCI' , 'CAHK' , 'EXT' ]: if FVC in FVCs and FVC not in failedFVCs : log . info ( f \" Looking for output file for { FVC } \" ) expr = f '($kpffvc. { FVC } LASTFILE != \" { initial_lastfile [ FVC ] } \")' log . debug ( f \" Waiting for: { expr } \" ) if ktl . waitFor ( expr , timeout = 20 ) is False : lastfile = kpffvc [ f ' { FVC } LASTFILE' ] . read () log . error ( 'No new FVC file found' ) log . error ( f \" kpffvc. { FVC } LASTFILE = { lastfile } \" ) else : lastfile = kpffvc [ f ' { FVC } LASTFILE' ] . read () log . debug ( f \"Found { lastfile } \" ) row = { 'file' : lastfile , 'camera' : FVC , 'x' : xs [ i ], 'y' : ys [ j ]} images . add_row ( row ) check_scriptstop () # Here's where we wait for the remainder of the TimeOnPosition log . info ( f \" Waiting for kpfexpose to be ready\" ) WaitForReady . execute ({}) # Collect CRED2 File if OB . get ( 'UseCRED2' , True ) is True : StopTriggerFile . execute ({}) WaitForTriggerFile . execute ({ 'initial_lastfile' : initial_last_cube }) last_cube = kpfguide [ 'LASTTRIGFILE' ] . read () row = { 'file' : last_cube , 'camera' : 'CRED2' , 'x' : xs [ i ], 'y' : ys [ j ]} images . add_row ( row ) # Stop Exposure Meter log . info ( f \" Waiting for ExpMeter to be Ready\" ) EMsuccess = ktl . waitFor ( '$kpf_expmeter.EXPSTATE == Ready' , timeout = 5 ) time . sleep ( 0.5 ) # Time shim because paranoia if EMsuccess is True : lastfile = kpf_expmeter [ 'FITSFILE' ] . read () else : lastfile = 'failed' log . debug ( f ' Done. FITSFILE= { lastfile } ' ) row = { 'file' : lastfile , 'camera' : 'ExpMeter' , 'x' : xs [ i ], 'y' : ys [ j ]} images . add_row ( row ) if EMsuccess is True : loutfile = kpf_expmeter [ 'LOUTFILE' ] . read () else : loutfile = 'failed' log . debug ( f ' Done. LOUTFILE= { loutfile } ' ) row = { 'file' : loutfile , 'camera' : 'ExpMeter_1Dspec' , 'x' : xs [ i ], 'y' : ys [ j ]} images . add_row ( row ) # Retrieve keyword history end = time . time () expmeter_data = { 'x' : xs [ i ], 'y' : ys [ j ], 'i' : i , 'j' : j , } log . info ( f \" Retrieving keyword history\" ) for counts_kw in [ 'CUR_COUNTS' , 'RAW_COUNTS' , 'BCK_COUNTS' ]: log . debug ( f \" Retrieving keyword history for { counts_kw } \" ) kws = { 'kpf_expmeter' : [ counts_kw ]} counts_history = keygrabber . retrieve ( kws , begin = begin , end = end ) # Extract counts and save to table (initial style output) fluxes = np . zeros (( len ( counts_history ) - 2 , 4 )) for k , entry in enumerate ( counts_history ): if k != 0 and k != len ( counts_history ) - 1 : value_floats = [ float ( v ) for v in entry [ 'ascvalue' ] . split ()] ts = datetime . fromtimestamp ( entry [ 'time' ]) . strftime ( '%Y-%m- %d %H:%M:%S' ) log . debug ( f \" { ts } : { value_floats } \" ) fluxes [ k - 1 ] = value_floats avg_fluxes = np . mean ( fluxes , axis = 0 ) expmeter_data [ f \" { counts_kw [: 3 ] . lower () } 1\" ] = avg_fluxes [ 0 ] expmeter_data [ f \" { counts_kw [: 3 ] . lower () } 2\" ] = avg_fluxes [ 1 ] expmeter_data [ f \" { counts_kw [: 3 ] . lower () } 3\" ] = avg_fluxes [ 2 ] expmeter_data [ f \" { counts_kw [: 3 ] . lower () } 4\" ] = avg_fluxes [ 3 ] expmeter_data [ 'nimages' ] = len ( counts_history ) expmeter_flux . add_row ( expmeter_data ) if images_file . exists (): images_file . unlink () images . write ( images_file , format = 'ascii.csv' ) if fluxes_file . exists (): fluxes_file . unlink () expmeter_flux . write ( fluxes_file , format = 'ascii.csv' ) if images_file . exists (): images_file . unlink () images . write ( images_file , format = 'ascii.csv' ) if fluxes_file . exists (): fluxes_file . unlink () expmeter_flux . write ( fluxes_file , format = 'ascii.csv' ) if grid == 'TipTilt' : SetTipTiltTargetPixel . execute ({ 'x' : basex , 'y' : basey }) StopTipTilt . execute ({}) elif grid == 'SciADC' : kpffiu [ 'ADC1NAM' ] . write ( 'Null' ) kpffiu [ 'ADC2NAM' ] . write ( 'Null' ) # kpffiu['ADCTRACK'].write('On') @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"GridSearch"},{"location":"scripts/GridSearch/#gridsearch","text":"Bases: KPFTranslatorFunction Executes an engineering grid search OB. This must have arguments as input, either from a file using the -f command line tool, or passed in from the execution engine.","title":"GridSearch"},{"location":"scripts/GridSearch/#kpf.engineering.GridSearch.GridSearch--args","text":"None Source code in kpf/engineering/GridSearch.py 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 class GridSearch ( KPFTranslatorFunction ): '''Executes an engineering grid search OB. This must have arguments as input, either from a file using the `-f` command line tool, or passed in from the execution engine. ARGS: ===== None ''' abortable = True @classmethod @obey_scriptrun def pre_condition ( cls , OB , logger , cfg ): check_input ( OB , 'Template_Name' , allowed_values = [ 'kpf_eng_grid' ]) check_input ( OB , 'Template_Version' , version_check = True , value_min = '0.4' ) check_input ( OB , 'Grid' , allowed_values = [ 'TipTilt' , 'SciADC' ]) check_input ( OB , 'nx' ) check_input ( OB , 'ny' ) check_input ( OB , 'dx' ) check_input ( OB , 'dy' ) check_input ( OB , 'ExpMeter_exptime' ) FVCs = OB . get ( 'FVCs' , '' ) . split ( ',' ) for FVC in FVCs : if FVC not in [ 'SCI' , 'CAHK' , 'EXT' , '' ]: raise FailedPreCondition ( f \"FVC { FVC } not supported\" ) @classmethod @register_script ( Path ( __file__ ) . name , os . getpid ()) @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in OB : log . debug ( f \" { key } : { OB [ key ] } \" ) log . info ( '-------------------------' ) grid = OB . get ( 'Grid' ) this_file_name = Path ( __file__ ) . name . replace ( '.py' , '' ) utnow = datetime . utcnow () now_str = utnow . strftime ( '%Y%m %d at%H%M%S' ) date_str = ( utnow - timedelta ( days = 1 )) . strftime ( '%Y%b %d ' ) . lower () log_path = Path ( f '/s/sdata1701/KPFTranslator_logs/ { date_str } ' ) images_file = log_path / Path ( f ' { grid }{ this_file_name } _images_ { now_str } .txt' ) fluxes_file = log_path / Path ( f ' { grid }{ this_file_name } _fluxes_ { now_str } .txt' ) images = Table ( names = ( 'file' , 'camera' , 'x' , 'y' ), dtype = ( 'a90' , 'a10' , 'f4' , 'f4' )) expmeter_flux = Table ( names = ( 'i' , 'j' , 'x' , 'y' , 'bck1' , 'bck2' , 'bck3' , 'bck4' , 'cur1' , 'cur2' , 'cur3' , 'cur4' , 'raw1' , 'raw2' , 'raw3' , 'raw4' , 'nimages' ), dtype = ( 'i4' , 'i4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'f4' , 'i4' )) FVCs = OB . get ( 'FVCs' , '' ) . split ( ',' ) nx = OB . get ( 'nx' ) ny = OB . get ( 'ny' ) dx = OB . get ( 'dx' ) dy = OB . get ( 'dy' ) xis = [ xi for xi in range ( int ( - nx / 2 ), int (( nx + 1 ) / 2 ), 1 )] yis = [ yi for yi in range ( int ( - ny / 2 ), int (( ny + 1 ) / 2 ), 1 )] xindicies = [ ind for ind in range ( nx )] yindicies = [ ind for ind in range ( ny )] xs = [ xi * dx for xi in xis ] ys = [ yi * dy for yi in yis ] # Set up guider (assume parameters set during acquisition of star) kpfguide = ktl . cache ( 'kpfguide' ) log . info ( 'Setting TRIGCUBE Inactive' ) kpfguide [ 'TRIGCUBE' ] . write ( 'Inactive' ) if grid == 'TipTilt' : log . info ( f \"DAR_ENABLE = { kpfguide [ 'DAR_ENABLE' ] . read () } \" ) dar_offset = kpfguide [ 'DAR_OFFSET' ] . read ( binary = True ) log . info ( f \"DAR_OFFSET = { dar_offset [ 0 ] : .2f } { dar_offset [ 1 ] : .2f } \" ) xpix0 , ypix0 = kpfguide [ 'PIX_TARGET' ] . read ( binary = True ) log . info ( f \"PIX_TARGET is { xpix0 : .2f } , { ypix0 : .2f } \" ) basex , basey = kpfguide [ 'CURRENT_BASE' ] . read ( binary = True ) log . info ( f \"CURRENT_BASE is { basex : .2f } , { basey : .2f } \" ) # Pixel targets must be in absolute coordinates xs = [ basex + xpix for xpix in xs ] ys = [ basey + ypix for ypix in ys ] elif grid == 'SciADC' : kpffiu = ktl . cache ( 'kpffiu' ) kpffiu [ 'ADCTRACK' ] . write ( 'Off' ) nominalx , nominaly = kpffiu [ 'ADCPRISMS' ] . read ( binary = True ) x0 = OB . get ( 'ADC1Position' ) if str ( x0 ) . lower () == 'nominal' : x0 = nominalx else : x0 = float ( OB . get ( 'ADC1Position' )) y0 = OB . get ( 'ADC2Position' ) if str ( y0 ) . lower () == 'nominal' : y0 = nominaly else : y0 = float ( OB . get ( 'ADC2Position' )) log . info ( f \"ADC starting position: { x0 : .1f } { y0 : .1f } \" ) # Apply reverse rotation if requested if OB . get ( 'ADC1Reverse' , False ) is True : x0 = - x0 if OB . get ( 'ADC2Reverse' , False ) is True : y0 = - y0 log . info ( f \"ADC reverse nominal position: { x0 : .1f } { y0 : .1f } \" ) # Apply flip if requested if OB . get ( 'ADC1Flip' , False ) is True : x0 += 180 if OB . get ( 'ADC2Flip' , False ) is True : y0 += 180 log . info ( f \"ADC flip nominal position: { x0 : .1f } { y0 : .1f } \" ) xs = [ x + x0 for x in xs ] ys = [ y + y0 for y in ys ] # Set up kpfexpose kpfexpose = ktl . cache ( 'kpfexpose' ) SetSourceSelectShutters . execute ( OB ) OB [ 'TimedShutter_Scrambler' ] = True OB [ 'TimedShutter_CaHK' ] = OB . get ( 'TriggerCaHK' , False ) SetTimedShutters . execute ( OB ) SetTriggeredDetectors . execute ( OB ) total_exptime = OB . get ( 'TimeOnPosition' ) SetExpTime . execute ({ 'ExpTime' : total_exptime }) # Configure Exposure Meter kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) ExpMeter_exptime = OB . get ( 'ExpMeter_exptime' ) log . info ( f \"Setting kpf_expmeter.EXPOSURE = { ExpMeter_exptime : .2f } s\" ) kpf_expmeter [ 'EXPOSURE' ] . write ( ExpMeter_exptime ) # Set up FVCs kpffvc = ktl . cache ( 'kpffvc' ) for FVC in [ 'SCI' , 'CAHK' , 'EXT' ]: if FVC in FVCs and OB . get ( f ' { FVC } FVC_exptime' , None ) != None : exptime = OB . get ( f ' { FVC } FVC_exptime' ) log . info ( f \"Setting { FVC } FVC ExpTime = { exptime : .2f } s\" ) SetFVCExpTime . execute ({ 'camera' : FVC , 'exptime' : exptime }) for i in xindicies : yindicies . reverse () for j in yindicies : check_scriptstop () if grid == 'TipTilt' : ##------------------------------------------------------ ## Tip Tilt ##------------------------------------------------------ log . info ( f \"Adjusting CURRENT_BASE to ( { xs [ i ] : .2f } , { ys [ j ] : .2f } ) ( { xis [ i ] } , { yis [ j ] } )\" ) max_move = 3 precisison = 0.01 current_base = ktl . cache ( 'kpfguide' , 'CURRENT_BASE' ) current_cb = current_base . read ( binary = True ) delta_cb = ( xs [ i ] - current_cb [ 0 ], ys [ j ] - current_cb [ 1 ]) while abs ( delta_cb [ 0 ]) > precisison or abs ( delta_cb [ 1 ]) > precisison : # Calc X move new_X_target = current_cb [ 0 ] if abs ( delta_cb [ 0 ]) > precisison : move_sign_X = delta_cb [ 0 ] / abs ( delta_cb [ 0 ]) move_mag_X = min ([ max_move , abs ( delta_cb [ 0 ])]) new_X_target += move_sign_X * move_mag_X # Calc Y move new_Y_target = current_cb [ 1 ] if abs ( delta_cb [ 1 ]) > precisison : move_sign_Y = delta_cb [ 1 ] / abs ( delta_cb [ 1 ]) move_mag_Y = min ([ max_move , abs ( delta_cb [ 1 ])]) new_Y_target += move_sign_Y * move_mag_Y log . info ( f \" Setting CURRENT_BASE to { new_X_target : .2f } , { new_Y_target : .2f } \" ) SetTipTiltTargetPixel . execute ({ 'x' : new_X_target , 'y' : new_Y_target }) success = ktl . waitFor ( \"$kpfguide.TIPTILT_PHASE == 'Tracking'\" , timeout = 5 ) current_cb = current_base . read ( binary = True ) delta_cb = ( xs [ i ] - current_cb [ 0 ], ys [ j ] - current_cb [ 1 ]) xpix , ypix = kpfguide [ 'PIX_TARGET' ] . read ( binary = True ) log . info ( f \"PIX_TARGET is { xpix : .2f } , { ypix : .2f } \" ) # Check for lost star obj_choice = kpfguide [ 'OBJECT_CHOICE' ] . read () if obj_choice in [ None , 'None' ]: log . error ( f \" --> Lost star <--\" ) log . info ( f \"Stopping tip tilt\" ) StopTipTilt . execute ({}) time . sleep ( 1 ) log . info ( f \"Starting tip tilt\" ) StartTipTilt . execute ({}) time . sleep ( 5 ) # Check for lost star obj_choice = kpfguide [ 'OBJECT_CHOICE' ] . read () if obj_choice in [ None , 'None' ]: log . error ( f \" --> Lost star <--\" ) subprocess . call ([ 'kpf' , 'restart' , 'kpfguide2' ]) time . sleep ( 5 ) log . info ( f \"Starting tip tilt\" ) StartTipTilt . execute ({}) time . sleep ( 5 ) obj_choice = kpfguide [ 'OBJECT_CHOICE' ] . read () if obj_choice in [ None , 'None' ]: log . error ( f \" --> Lost star <--\" ) raise KPFException ( 'Lost Star' ) elif grid == 'SciADC' : ##------------------------------------------------------ ## Science ADC ##------------------------------------------------------ log . info ( f \"Offsetting to ( { xs [ i ] : .2f } , { ys [ j ] : .2f } ) ( { xis [ i ] } , { yis [ j ] } )\" ) kpffiu [ 'ADC1VAL' ] . write ( xs [ i ]) kpffiu [ 'ADC2VAL' ] . write ( ys [ j ]) log . info ( f \"Absolute position: { xs [ i ] : .1f } { ys [ j ] : .1f } \" ) expr = '($kpffiu.ADC1STA == Ready) and ($kpffiu.ADC2STA == Ready)' success = ktl . waitFor ( expr , timeout = 2 * max ([ dx * nx , dy * ny ]) / 5 ) if success is not True : ADC1STA = kpffiu [ 'ADC1STA' ] . read () ADC2STA = kpffiu [ 'ADC2STA' ] . read () msg = f 'Timed out waiting for ADCs: ADC1STA= { ADC1STA } ADC2STA= { ADC2STA } ' raise KPFException ( msg ) WaitForReady . execute ({}) check_scriptstop () # Stop here if requested # Start Exposure Meter and Science Cameras kpfexpose [ 'OBJECT' ] . write ( f 'Grid search { xs [ i ] } , { ys [ j ] } ' ) log . info ( f \"Starting kpfexpose cameras\" ) StartExposure . execute ({}) # Begin timestamp for history retrieval begin = time . time () # Take CRED2 image if OB . get ( 'UseCRED2' , True ) is True : log . info ( 'Starting guider Trigger file' ) initial_last_cube = kpfguide [ 'LASTTRIGFILE' ] . read () StartTriggerFile . execute ({}) # Start FVC Exposures initial_lastfile = {} failedFVCs = [] for FVC in [ 'SCI' , 'CAHK' , 'EXT' ]: if FVC in FVCs : initial_lastfile [ FVC ] = kpffvc [ f \" { FVC } LASTFILE\" ] . read () log . debug ( f \" Initial lastfile for { FVC } = { initial_lastfile [ FVC ] } \" ) log . info ( f \" Starting { FVC } FVC exposure\" ) try : TakeFVCExposure . execute ({ 'camera' : FVC , 'wait' : False }) except : log . error ( 'Starting FVC image failed' ) failedFVCs . append ( FVC ) check_scriptstop () # Collect files for FVC exposures for FVC in [ 'SCI' , 'CAHK' , 'EXT' ]: if FVC in FVCs and FVC not in failedFVCs : log . info ( f \" Looking for output file for { FVC } \" ) expr = f '($kpffvc. { FVC } LASTFILE != \" { initial_lastfile [ FVC ] } \")' log . debug ( f \" Waiting for: { expr } \" ) if ktl . waitFor ( expr , timeout = 20 ) is False : lastfile = kpffvc [ f ' { FVC } LASTFILE' ] . read () log . error ( 'No new FVC file found' ) log . error ( f \" kpffvc. { FVC } LASTFILE = { lastfile } \" ) else : lastfile = kpffvc [ f ' { FVC } LASTFILE' ] . read () log . debug ( f \"Found { lastfile } \" ) row = { 'file' : lastfile , 'camera' : FVC , 'x' : xs [ i ], 'y' : ys [ j ]} images . add_row ( row ) check_scriptstop () # Here's where we wait for the remainder of the TimeOnPosition log . info ( f \" Waiting for kpfexpose to be ready\" ) WaitForReady . execute ({}) # Collect CRED2 File if OB . get ( 'UseCRED2' , True ) is True : StopTriggerFile . execute ({}) WaitForTriggerFile . execute ({ 'initial_lastfile' : initial_last_cube }) last_cube = kpfguide [ 'LASTTRIGFILE' ] . read () row = { 'file' : last_cube , 'camera' : 'CRED2' , 'x' : xs [ i ], 'y' : ys [ j ]} images . add_row ( row ) # Stop Exposure Meter log . info ( f \" Waiting for ExpMeter to be Ready\" ) EMsuccess = ktl . waitFor ( '$kpf_expmeter.EXPSTATE == Ready' , timeout = 5 ) time . sleep ( 0.5 ) # Time shim because paranoia if EMsuccess is True : lastfile = kpf_expmeter [ 'FITSFILE' ] . read () else : lastfile = 'failed' log . debug ( f ' Done. FITSFILE= { lastfile } ' ) row = { 'file' : lastfile , 'camera' : 'ExpMeter' , 'x' : xs [ i ], 'y' : ys [ j ]} images . add_row ( row ) if EMsuccess is True : loutfile = kpf_expmeter [ 'LOUTFILE' ] . read () else : loutfile = 'failed' log . debug ( f ' Done. LOUTFILE= { loutfile } ' ) row = { 'file' : loutfile , 'camera' : 'ExpMeter_1Dspec' , 'x' : xs [ i ], 'y' : ys [ j ]} images . add_row ( row ) # Retrieve keyword history end = time . time () expmeter_data = { 'x' : xs [ i ], 'y' : ys [ j ], 'i' : i , 'j' : j , } log . info ( f \" Retrieving keyword history\" ) for counts_kw in [ 'CUR_COUNTS' , 'RAW_COUNTS' , 'BCK_COUNTS' ]: log . debug ( f \" Retrieving keyword history for { counts_kw } \" ) kws = { 'kpf_expmeter' : [ counts_kw ]} counts_history = keygrabber . retrieve ( kws , begin = begin , end = end ) # Extract counts and save to table (initial style output) fluxes = np . zeros (( len ( counts_history ) - 2 , 4 )) for k , entry in enumerate ( counts_history ): if k != 0 and k != len ( counts_history ) - 1 : value_floats = [ float ( v ) for v in entry [ 'ascvalue' ] . split ()] ts = datetime . fromtimestamp ( entry [ 'time' ]) . strftime ( '%Y-%m- %d %H:%M:%S' ) log . debug ( f \" { ts } : { value_floats } \" ) fluxes [ k - 1 ] = value_floats avg_fluxes = np . mean ( fluxes , axis = 0 ) expmeter_data [ f \" { counts_kw [: 3 ] . lower () } 1\" ] = avg_fluxes [ 0 ] expmeter_data [ f \" { counts_kw [: 3 ] . lower () } 2\" ] = avg_fluxes [ 1 ] expmeter_data [ f \" { counts_kw [: 3 ] . lower () } 3\" ] = avg_fluxes [ 2 ] expmeter_data [ f \" { counts_kw [: 3 ] . lower () } 4\" ] = avg_fluxes [ 3 ] expmeter_data [ 'nimages' ] = len ( counts_history ) expmeter_flux . add_row ( expmeter_data ) if images_file . exists (): images_file . unlink () images . write ( images_file , format = 'ascii.csv' ) if fluxes_file . exists (): fluxes_file . unlink () expmeter_flux . write ( fluxes_file , format = 'ascii.csv' ) if images_file . exists (): images_file . unlink () images . write ( images_file , format = 'ascii.csv' ) if fluxes_file . exists (): fluxes_file . unlink () expmeter_flux . write ( fluxes_file , format = 'ascii.csv' ) if grid == 'TipTilt' : SetTipTiltTargetPixel . execute ({ 'x' : basex , 'y' : basey }) StopTipTilt . execute ({}) elif grid == 'SciADC' : kpffiu [ 'ADC1NAM' ] . write ( 'Null' ) kpffiu [ 'ADC2NAM' ] . write ( 'Null' ) # kpffiu['ADCTRACK'].write('On') @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"ARGS:"},{"location":"scripts/GuiderLastfile/","text":"GuiderLastfile Bases: KPFTranslatorFunction Print the value of the kpfguide.LASTFILE keyword to STDOUT Parameters: wait ( bool ) \u2013 Return only after lastfile is updated? (default = False) KTL Keywords Used: kpfguide.LASTFILE Source code in kpf/guider/GuiderLastfile.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class GuiderLastfile ( KPFTranslatorFunction ): '''Print the value of the kpfguide.LASTFILE keyword to STDOUT Args: wait (bool): Return only after lastfile is updated? (default = False) KTL Keywords Used: - `kpfguide.LASTFILE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) if args . get ( 'wait' , True ) is True : exptime = kpfguide [ 'EXPTIME' ] . read ( binary = True ) initial_lastfile = kpfguide [ 'LASTFILE' ] . read () timeout = cfg . getfloat ( 'times' , 'kpfguide_shim_time' , fallback = 0.01 ) expr = f \"($kpfguide.LASTFILE != ' { initial_lastfile } ')\" ktl . waitFor ( expr , timeout = exptime + timeout ) lastfile = kpfguide [ 'LASTFILE' ] . read () print ( lastfile ) return lastfile @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--nowait\" , dest = \"wait\" , default = True , action = \"store_false\" , help = \"Send exposure command and return immediately?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"GuiderLastfile"},{"location":"scripts/GuiderLastfile/#guiderlastfile","text":"Bases: KPFTranslatorFunction Print the value of the kpfguide.LASTFILE keyword to STDOUT Parameters: wait ( bool ) \u2013 Return only after lastfile is updated? (default = False) KTL Keywords Used: kpfguide.LASTFILE Source code in kpf/guider/GuiderLastfile.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class GuiderLastfile ( KPFTranslatorFunction ): '''Print the value of the kpfguide.LASTFILE keyword to STDOUT Args: wait (bool): Return only after lastfile is updated? (default = False) KTL Keywords Used: - `kpfguide.LASTFILE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) if args . get ( 'wait' , True ) is True : exptime = kpfguide [ 'EXPTIME' ] . read ( binary = True ) initial_lastfile = kpfguide [ 'LASTFILE' ] . read () timeout = cfg . getfloat ( 'times' , 'kpfguide_shim_time' , fallback = 0.01 ) expr = f \"($kpfguide.LASTFILE != ' { initial_lastfile } ')\" ktl . waitFor ( expr , timeout = exptime + timeout ) lastfile = kpfguide [ 'LASTFILE' ] . read () print ( lastfile ) return lastfile @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--nowait\" , dest = \"wait\" , default = True , action = \"store_false\" , help = \"Send exposure command and return immediately?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"GuiderLastfile"},{"location":"scripts/GuiderOutdir/","text":"GuiderOutdir Bases: KPFTranslatorFunction Print the value of the kpfguide.OUTDIR keyword to STDOUT KTL Keywords Used: kpfguide.OUTDIR Source code in kpf/guider/GuiderOutdir.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class GuiderOutdir ( KPFTranslatorFunction ): '''Print the value of the kpfguide.OUTDIR keyword to STDOUT KTL Keywords Used: - `kpfguide.OUTDIR` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) outdir = kpfguide [ 'OUTDIR' ] . read () print ( outdir ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"GuiderOutdir"},{"location":"scripts/GuiderOutdir/#guideroutdir","text":"Bases: KPFTranslatorFunction Print the value of the kpfguide.OUTDIR keyword to STDOUT KTL Keywords Used: kpfguide.OUTDIR Source code in kpf/guider/GuiderOutdir.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class GuiderOutdir ( KPFTranslatorFunction ): '''Print the value of the kpfguide.OUTDIR keyword to STDOUT KTL Keywords Used: - `kpfguide.OUTDIR` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) outdir = kpfguide [ 'OUTDIR' ] . read () print ( outdir ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"GuiderOutdir"},{"location":"scripts/ImageBackIlluminatedFibers/","text":"ImageBackIlluminatedFibers Bases: KPFTranslatorFunction Take images of the back illuminated fibers using the FVCs Source code in kpf/engineering/ImageBackIlluminatedFibers.py 20 21 22 23 24 25 26 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 class ImageBackIlluminatedFibers ( KPFTranslatorFunction ): '''Take images of the back illuminated fibers using the FVCs ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): this_file_name = Path ( __file__ ) . name . replace ( '.py' , '' ) log_path = Path ( f '/s/sdata1701/KPFTranslator_logs/' ) images_file = log_path / Path ( f ' { this_file_name } _images.txt' ) hstnow = datetime . now () now_str = hstnow . strftime ( '%Y-%m- %d %H:%M:%S' ) LEDoutlets = { 'Science' : 'E7' , 'Sky' : 'E8' , 'CaHK' : 'J7' , 'ExpMeter' : 'H1' } LEDnames = { 'Science' : 'Science Back-Illumination LED' , 'Sky' : 'Sky Back-Illumination LED' , 'CaHK' : 'HK Back-Illumination LED' , 'ExpMeter' : 'Exp Meter Back Illum LED' } exptimes = { 'SCI' : { 'Science' : 0.1 , 'Sky' : 1 , 'ExpMeter' : 2 }, 'CAHK' : { 'CaHK' : 5 } } kpffvc = ktl . cache ( 'kpffvc' ) kpfpower = ktl . cache ( 'kpfpower' ) kpffiu = ktl . cache ( 'kpffiu' ) def take_back_illuminated_image ( camera , LEDname ): log . info ( f \"Taking back illuminated image of { LEDname } fiber with { camera } FVC\" ) camnum = { 'SCI' : 1 , 'CAHK' : 2 }[ camera ] powerkw = ktl . cache ( 'kpfpower' , f 'KPFFVC { camnum } ' ) if powerkw . read () == 'Off' : FVCPower . execute ({ 'camera' : camera , 'power' : 'on' }) # Time shim to let FVC service connect to camera after power up time . sleep ( 10 ) # Set ADC to Null if camera == 'SCI' : kpffiu [ 'ADC1NAM' ] . write ( 'Null' ) kpffiu [ 'ADC2NAM' ] . write ( 'Null' ) success1 = kpffiu [ 'ADC1NAM' ] . waitFor ( \"=='Null'\" , timeout = 30 ) success2 = kpffiu [ 'ADC2NAM' ] . waitFor ( \"=='Null'\" , timeout = 30 ) if success1 is False or success2 is False : raise KPFException ( 'Failed to reach Null position on science ADC' ) elif camera == 'CAHK' : kpffiu [ 'HKXNAM' ] . write ( 'Null' ) kpffiu [ 'HKYNAM' ] . write ( 'Null' ) success1 = kpffiu [ 'HKXNAM' ] . waitFor ( \"=='Null'\" , timeout = 30 ) success2 = kpffiu [ 'HKYNAM' ] . waitFor ( \"=='Null'\" , timeout = 30 ) if success1 is False or success2 is False : raise KPFException ( 'Failed to reach Null position on HK ADC' ) # Turn LED on outlet = LEDoutlets [ LEDname ] if LEDnames [ LEDname ] != kpfpower [ f \"OUTLET_ { outlet } _NAME\" ] . read (): raise KPFException ( f \"Expected outlet { outlet } to have name { LEDnames [ LEDname ] } \" ) log . debug ( 'Turning LED on' ) kpfpower [ f \"OUTLET_ { outlet } \" ] . write ( 'On' ) # Take FVC Image SetFVCExpTime . execute ({ 'camera' : camera , 'exptime' : exptimes [ camera ][ LEDname ]}) lastfile = TakeFVCExposure . execute ({ 'camera' : camera }) log . info ( f ' LASTFILE: { lastfile } ' ) log . debug ( 'Turning LED off' ) kpfpower [ f \"OUTLET_ { outlet } \" ] . write ( 'Off' ) # Append to images file if images_file . exists () is False : # Write header line header = f \"# HST date, camera, LED, file \\n \" with open ( images_file , 'w' ) as f : f . write ( header ) row = f \" { now_str } , { camera : 4s } , { LEDname : 8s } , { lastfile } \\n \" with open ( images_file , 'a' ) as f : f . write ( row ) if args . get ( 'SCI' , False ) is True : take_back_illuminated_image ( 'SCI' , 'Science' ) take_back_illuminated_image ( 'SCI' , 'Sky' ) take_back_illuminated_image ( 'SCI' , 'ExpMeter' ) if args . get ( 'CAHK' , False ) is True : take_back_illuminated_image ( 'CAHK' , 'CaHK' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--Science\" , \"--Sci\" , \"--science\" , \"--sci\" , \"--SCI\" , dest = \"SCI\" , default = False , action = \"store_true\" , help = \"Image science and sky fibers with science FVC?\" ) parser . add_argument ( \"--CaHK\" , \"--HK\" , \"--cahk\" , \"--hk\" , \"--CAHK\" , dest = \"CAHK\" , default = False , action = \"store_true\" , help = \"Image CaHK fiber with CaHK FVC?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"ImageBackIlluminatedFibers"},{"location":"scripts/ImageBackIlluminatedFibers/#imagebackilluminatedfibers","text":"Bases: KPFTranslatorFunction Take images of the back illuminated fibers using the FVCs Source code in kpf/engineering/ImageBackIlluminatedFibers.py 20 21 22 23 24 25 26 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 class ImageBackIlluminatedFibers ( KPFTranslatorFunction ): '''Take images of the back illuminated fibers using the FVCs ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): this_file_name = Path ( __file__ ) . name . replace ( '.py' , '' ) log_path = Path ( f '/s/sdata1701/KPFTranslator_logs/' ) images_file = log_path / Path ( f ' { this_file_name } _images.txt' ) hstnow = datetime . now () now_str = hstnow . strftime ( '%Y-%m- %d %H:%M:%S' ) LEDoutlets = { 'Science' : 'E7' , 'Sky' : 'E8' , 'CaHK' : 'J7' , 'ExpMeter' : 'H1' } LEDnames = { 'Science' : 'Science Back-Illumination LED' , 'Sky' : 'Sky Back-Illumination LED' , 'CaHK' : 'HK Back-Illumination LED' , 'ExpMeter' : 'Exp Meter Back Illum LED' } exptimes = { 'SCI' : { 'Science' : 0.1 , 'Sky' : 1 , 'ExpMeter' : 2 }, 'CAHK' : { 'CaHK' : 5 } } kpffvc = ktl . cache ( 'kpffvc' ) kpfpower = ktl . cache ( 'kpfpower' ) kpffiu = ktl . cache ( 'kpffiu' ) def take_back_illuminated_image ( camera , LEDname ): log . info ( f \"Taking back illuminated image of { LEDname } fiber with { camera } FVC\" ) camnum = { 'SCI' : 1 , 'CAHK' : 2 }[ camera ] powerkw = ktl . cache ( 'kpfpower' , f 'KPFFVC { camnum } ' ) if powerkw . read () == 'Off' : FVCPower . execute ({ 'camera' : camera , 'power' : 'on' }) # Time shim to let FVC service connect to camera after power up time . sleep ( 10 ) # Set ADC to Null if camera == 'SCI' : kpffiu [ 'ADC1NAM' ] . write ( 'Null' ) kpffiu [ 'ADC2NAM' ] . write ( 'Null' ) success1 = kpffiu [ 'ADC1NAM' ] . waitFor ( \"=='Null'\" , timeout = 30 ) success2 = kpffiu [ 'ADC2NAM' ] . waitFor ( \"=='Null'\" , timeout = 30 ) if success1 is False or success2 is False : raise KPFException ( 'Failed to reach Null position on science ADC' ) elif camera == 'CAHK' : kpffiu [ 'HKXNAM' ] . write ( 'Null' ) kpffiu [ 'HKYNAM' ] . write ( 'Null' ) success1 = kpffiu [ 'HKXNAM' ] . waitFor ( \"=='Null'\" , timeout = 30 ) success2 = kpffiu [ 'HKYNAM' ] . waitFor ( \"=='Null'\" , timeout = 30 ) if success1 is False or success2 is False : raise KPFException ( 'Failed to reach Null position on HK ADC' ) # Turn LED on outlet = LEDoutlets [ LEDname ] if LEDnames [ LEDname ] != kpfpower [ f \"OUTLET_ { outlet } _NAME\" ] . read (): raise KPFException ( f \"Expected outlet { outlet } to have name { LEDnames [ LEDname ] } \" ) log . debug ( 'Turning LED on' ) kpfpower [ f \"OUTLET_ { outlet } \" ] . write ( 'On' ) # Take FVC Image SetFVCExpTime . execute ({ 'camera' : camera , 'exptime' : exptimes [ camera ][ LEDname ]}) lastfile = TakeFVCExposure . execute ({ 'camera' : camera }) log . info ( f ' LASTFILE: { lastfile } ' ) log . debug ( 'Turning LED off' ) kpfpower [ f \"OUTLET_ { outlet } \" ] . write ( 'Off' ) # Append to images file if images_file . exists () is False : # Write header line header = f \"# HST date, camera, LED, file \\n \" with open ( images_file , 'w' ) as f : f . write ( header ) row = f \" { now_str } , { camera : 4s } , { LEDname : 8s } , { lastfile } \\n \" with open ( images_file , 'a' ) as f : f . write ( row ) if args . get ( 'SCI' , False ) is True : take_back_illuminated_image ( 'SCI' , 'Science' ) take_back_illuminated_image ( 'SCI' , 'Sky' ) take_back_illuminated_image ( 'SCI' , 'ExpMeter' ) if args . get ( 'CAHK' , False ) is True : take_back_illuminated_image ( 'CAHK' , 'CaHK' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--Science\" , \"--Sci\" , \"--science\" , \"--sci\" , \"--SCI\" , dest = \"SCI\" , default = False , action = \"store_true\" , help = \"Image science and sky fibers with science FVC?\" ) parser . add_argument ( \"--CaHK\" , \"--HK\" , \"--cahk\" , \"--hk\" , \"--CAHK\" , dest = \"CAHK\" , default = False , action = \"store_true\" , help = \"Image CaHK fiber with CaHK FVC?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"ImageBackIlluminatedFibers"},{"location":"scripts/InitializeTipTilt/","text":"InitializeTipTilt Bases: KPFTranslatorFunction Initialize the tip tilt system by setting the control mode to closed loop and setting the target values in X and Y to 0. KTL Keywords Used: kpfguide.TIPTILT_HOME kpffiu.TTXSRV kpffiu.TTYSRV kpffiu.TTXVAX kpffiu.TTYVAX Source code in kpf/fiu/InitializeTipTilt.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class InitializeTipTilt ( KPFTranslatorFunction ): '''Initialize the tip tilt system by setting the control mode to closed loop and setting the target values in X and Y to 0. KTL Keywords Used: - `kpfguide.TIPTILT_HOME` - `kpffiu.TTXSRV` - `kpffiu.TTYSRV` - `kpffiu.TTXVAX` - `kpffiu.TTYVAX` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): log . debug ( f \"Initializing tip tilt mirror\" ) kpffiu = ktl . cache ( 'kpffiu' ) tthome = ktl . cache ( 'kpfguide' , 'TIPTILT_HOME' ) home = tthome . read ( binary = True ) kpffiu [ 'TTXSRV' ] . write ( 'closed' ) kpffiu [ 'TTYSRV' ] . write ( 'closed' ) time . sleep ( 1 ) log . debug ( f 'Sending Tip tilt mirror to home: { home [ 0 ] } { home [ 1 ] } ' ) kpffiu [ 'TTXVAX' ] . write ( home [ 0 ]) kpffiu [ 'TTYVAX' ] . write ( home [ 1 ]) @classmethod def post_condition ( cls , args , logger , cfg ): kpffiu = ktl . cache ( 'kpffiu' ) tthome = ktl . cache ( 'kpfguide' , 'TIPTILT_HOME' ) home = tthome . read ( binary = True ) movetime = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) timeout = 1000 * movetime tol = cfg . getfloat ( 'tolerances' , 'tip_tilt_move_tolerance' , fallback = 0.1 ) if not ktl . waitFor ( '($kpffiu.TTXSRV == closed)' , timeout = timeout ): raise FailedToReachDestination ( kpffiu [ 'TTXSRV' ] . read (), 'closed' ) if not ktl . waitFor ( '($kpffiu.TTYSRV == closed)' , timeout = timeout ): raise FailedToReachDestination ( kpffiu [ 'TTYSRV' ] . read (), 'closed' ) expr = ( f '($kpffiu.TTXVAX >= { home [ 0 ] - tol } ) and ' \\ f '($kpffiu.TTXVAX <= { home [ 0 ] + tol } )' ) if not ktl . waitFor ( expr , timeout = timeout ): raise FailedToReachDestination ( kpffiu [ 'TTXVAX' ] . read (), f \" { home [ 0 ] } \" ) expr = ( f '($kpffiu.TTYVAX >= { home [ 1 ] - tol } ) and ' \\ f '($kpffiu.TTYVAX <= { home [ 1 ] + tol } )' ) if not ktl . waitFor ( expr , timeout = timeout ): raise FailedToReachDestination ( kpffiu [ 'TTYVAX' ] . read (), f \" { home [ 1 ] } \" )","title":"InitializeTipTilt"},{"location":"scripts/InitializeTipTilt/#initializetiptilt","text":"Bases: KPFTranslatorFunction Initialize the tip tilt system by setting the control mode to closed loop and setting the target values in X and Y to 0. KTL Keywords Used: kpfguide.TIPTILT_HOME kpffiu.TTXSRV kpffiu.TTYSRV kpffiu.TTXVAX kpffiu.TTYVAX Source code in kpf/fiu/InitializeTipTilt.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class InitializeTipTilt ( KPFTranslatorFunction ): '''Initialize the tip tilt system by setting the control mode to closed loop and setting the target values in X and Y to 0. KTL Keywords Used: - `kpfguide.TIPTILT_HOME` - `kpffiu.TTXSRV` - `kpffiu.TTYSRV` - `kpffiu.TTXVAX` - `kpffiu.TTYVAX` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): log . debug ( f \"Initializing tip tilt mirror\" ) kpffiu = ktl . cache ( 'kpffiu' ) tthome = ktl . cache ( 'kpfguide' , 'TIPTILT_HOME' ) home = tthome . read ( binary = True ) kpffiu [ 'TTXSRV' ] . write ( 'closed' ) kpffiu [ 'TTYSRV' ] . write ( 'closed' ) time . sleep ( 1 ) log . debug ( f 'Sending Tip tilt mirror to home: { home [ 0 ] } { home [ 1 ] } ' ) kpffiu [ 'TTXVAX' ] . write ( home [ 0 ]) kpffiu [ 'TTYVAX' ] . write ( home [ 1 ]) @classmethod def post_condition ( cls , args , logger , cfg ): kpffiu = ktl . cache ( 'kpffiu' ) tthome = ktl . cache ( 'kpfguide' , 'TIPTILT_HOME' ) home = tthome . read ( binary = True ) movetime = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) timeout = 1000 * movetime tol = cfg . getfloat ( 'tolerances' , 'tip_tilt_move_tolerance' , fallback = 0.1 ) if not ktl . waitFor ( '($kpffiu.TTXSRV == closed)' , timeout = timeout ): raise FailedToReachDestination ( kpffiu [ 'TTXSRV' ] . read (), 'closed' ) if not ktl . waitFor ( '($kpffiu.TTYSRV == closed)' , timeout = timeout ): raise FailedToReachDestination ( kpffiu [ 'TTYSRV' ] . read (), 'closed' ) expr = ( f '($kpffiu.TTXVAX >= { home [ 0 ] - tol } ) and ' \\ f '($kpffiu.TTXVAX <= { home [ 0 ] + tol } )' ) if not ktl . waitFor ( expr , timeout = timeout ): raise FailedToReachDestination ( kpffiu [ 'TTXVAX' ] . read (), f \" { home [ 0 ] } \" ) expr = ( f '($kpffiu.TTYVAX >= { home [ 1 ] - tol } ) and ' \\ f '($kpffiu.TTYVAX <= { home [ 1 ] + tol } )' ) if not ktl . waitFor ( expr , timeout = timeout ): raise FailedToReachDestination ( kpffiu [ 'TTYVAX' ] . read (), f \" { home [ 1 ] } \" )","title":"InitializeTipTilt"},{"location":"scripts/IsCalSourceEnabled/","text":"IsCalSourceEnabled Bases: KPFTranslatorFunction Return a boolean indicating whether the input CalSource is enabled as reported by the kpfconfig.%_ENABLED keywords. Parameters: CalSource ( str ) \u2013 Which lamp to check? Allowed Values: EtalonFiber, BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, SoCal-CalFib, LFCFiber, SoCal-SciSky, WideFlat Returns: \u2013 The return value. True for enabled, False for disabled. KTL Keywords Used: kpfcal.OCTAGON kpfconfig.BRDBANDFIBER_ENABLED kpfconfig.U_GOLD_ENABLED kpfconfig.U_DAILY_ENABLED kpfconfig.TH_DAILY_ENABLED kpfconfig.TH_GOLD_ENABLED kpfconfig.FF_FIBER_ENABLED kpfconfig.EXPMLED_ENABLED kpfconfig.HKLED_ENABLED kpfconfig.SCILED_ENABLED kpfconfig.SKYLED_ENABLED Source code in kpf/calbench/IsCalSourceEnabled.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class IsCalSourceEnabled ( KPFTranslatorFunction ): '''Return a boolean indicating whether the input CalSource is enabled as reported by the kpfconfig.%_ENABLED keywords. Args: CalSource (str): Which lamp to check? Allowed Values: EtalonFiber, BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, SoCal-CalFib, LFCFiber, SoCal-SciSky, WideFlat Returns: The return value. True for enabled, False for disabled. KTL Keywords Used: - `kpfcal.OCTAGON` - `kpfconfig.BRDBANDFIBER_ENABLED` - `kpfconfig.U_GOLD_ENABLED` - `kpfconfig.U_DAILY_ENABLED` - `kpfconfig.TH_DAILY_ENABLED` - `kpfconfig.TH_GOLD_ENABLED` - `kpfconfig.FF_FIBER_ENABLED` - `kpfconfig.EXPMLED_ENABLED` - `kpfconfig.HKLED_ENABLED` - `kpfconfig.SCILED_ENABLED` - `kpfconfig.SKYLED_ENABLED` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'OCTAGON' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) allowed_values . append ( 'SoCal-SciSky' ) allowed_values . append ( 'WideFlat' ) check_input ( args , 'CalSource' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): calsource = args . get ( 'CalSource' ) if calsource in [ 'BrdbandFiber' , 'WideFlat' , 'Th_daily' , 'Th_gold' , 'U_daily' , 'U_gold' ]: lamp_name = standardize_lamp_name ( calsource ) elif calsource in [ 'LFCFiber' , 'EtalonFiber' ]: lamp_name = calsource . upper () elif calsource in [ 'SoCal-CalFib' , 'SoCal-SciSky' ]: lamp_name = calsource . replace ( '-' , '_' ) . replace ( 'Sky' , 'FIB' ) else : log . warning ( f \"IsCalSourceEnabled does not recognize ' { calsource } '\" ) return True lamp_enabledkw = ktl . cache ( 'kpfconfig' , f ' { lamp_name } _ENABLED' ) lamp_enabled = lamp_enabledkw . read ( binary = True ) if lamp_enabled is True : log . debug ( f \"Cal source { calsource } is enabled\" ) else : log . warning ( f \"Cal source { calsource } is disabled\" ) return lamp_enabled @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalSource' , type = str , choices = [ 'BrdbandFiber' , 'WideFlat' , 'Th_daily' , 'Th_gold' , 'U_daily' , 'U_gold' , 'LFCFiber' , 'EtalonFiber' , 'SoCal-CalFib' , 'SoCal-SciSky' ], help = 'Which lamp to check?' ) return super () . add_cmdline_args ( parser , cfg )","title":"IsCalSourceEnabled"},{"location":"scripts/IsCalSourceEnabled/#iscalsourceenabled","text":"Bases: KPFTranslatorFunction Return a boolean indicating whether the input CalSource is enabled as reported by the kpfconfig.%_ENABLED keywords. Parameters: CalSource ( str ) \u2013 Which lamp to check? Allowed Values: EtalonFiber, BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, SoCal-CalFib, LFCFiber, SoCal-SciSky, WideFlat Returns: \u2013 The return value. True for enabled, False for disabled. KTL Keywords Used: kpfcal.OCTAGON kpfconfig.BRDBANDFIBER_ENABLED kpfconfig.U_GOLD_ENABLED kpfconfig.U_DAILY_ENABLED kpfconfig.TH_DAILY_ENABLED kpfconfig.TH_GOLD_ENABLED kpfconfig.FF_FIBER_ENABLED kpfconfig.EXPMLED_ENABLED kpfconfig.HKLED_ENABLED kpfconfig.SCILED_ENABLED kpfconfig.SKYLED_ENABLED Source code in kpf/calbench/IsCalSourceEnabled.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class IsCalSourceEnabled ( KPFTranslatorFunction ): '''Return a boolean indicating whether the input CalSource is enabled as reported by the kpfconfig.%_ENABLED keywords. Args: CalSource (str): Which lamp to check? Allowed Values: EtalonFiber, BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, SoCal-CalFib, LFCFiber, SoCal-SciSky, WideFlat Returns: The return value. True for enabled, False for disabled. KTL Keywords Used: - `kpfcal.OCTAGON` - `kpfconfig.BRDBANDFIBER_ENABLED` - `kpfconfig.U_GOLD_ENABLED` - `kpfconfig.U_DAILY_ENABLED` - `kpfconfig.TH_DAILY_ENABLED` - `kpfconfig.TH_GOLD_ENABLED` - `kpfconfig.FF_FIBER_ENABLED` - `kpfconfig.EXPMLED_ENABLED` - `kpfconfig.HKLED_ENABLED` - `kpfconfig.SCILED_ENABLED` - `kpfconfig.SKYLED_ENABLED` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'OCTAGON' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) allowed_values . append ( 'SoCal-SciSky' ) allowed_values . append ( 'WideFlat' ) check_input ( args , 'CalSource' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): calsource = args . get ( 'CalSource' ) if calsource in [ 'BrdbandFiber' , 'WideFlat' , 'Th_daily' , 'Th_gold' , 'U_daily' , 'U_gold' ]: lamp_name = standardize_lamp_name ( calsource ) elif calsource in [ 'LFCFiber' , 'EtalonFiber' ]: lamp_name = calsource . upper () elif calsource in [ 'SoCal-CalFib' , 'SoCal-SciSky' ]: lamp_name = calsource . replace ( '-' , '_' ) . replace ( 'Sky' , 'FIB' ) else : log . warning ( f \"IsCalSourceEnabled does not recognize ' { calsource } '\" ) return True lamp_enabledkw = ktl . cache ( 'kpfconfig' , f ' { lamp_name } _ENABLED' ) lamp_enabled = lamp_enabledkw . read ( binary = True ) if lamp_enabled is True : log . debug ( f \"Cal source { calsource } is enabled\" ) else : log . warning ( f \"Cal source { calsource } is disabled\" ) return lamp_enabled @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalSource' , type = str , choices = [ 'BrdbandFiber' , 'WideFlat' , 'Th_daily' , 'Th_gold' , 'U_daily' , 'U_gold' , 'LFCFiber' , 'EtalonFiber' , 'SoCal-CalFib' , 'SoCal-SciSky' ], help = 'Which lamp to check?' ) return super () . add_cmdline_args ( parser , cfg )","title":"IsCalSourceEnabled"},{"location":"scripts/IsSoCalClosed/","text":"IsSoCalClosed Bases: KPFTranslatorFunction Returns True if SoCal enclsoure is closed. ARGS: None Source code in kpf/socal/IsSoCalClosed.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class IsSoCalClosed ( KPFTranslatorFunction ): '''Returns True if SoCal enclsoure is closed. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'SoCal' , 'enclosure_status_time' , fallback = 10 ) ENCSTA = ktl . cache ( 'kpfsocal' , 'ENCSTA' ) is_closed = ENCSTA . waitFor ( \"==1\" , timeout = timeout ) msg = { True : 'SoCal is Closed' , False : 'SoCal is NOT Closed' }[ is_closed ] print ( msg ) return is_closed @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"IsSoCalClosed"},{"location":"scripts/IsSoCalClosed/#issocalclosed","text":"Bases: KPFTranslatorFunction Returns True if SoCal enclsoure is closed.","title":"IsSoCalClosed"},{"location":"scripts/IsSoCalClosed/#kpf.socal.IsSoCalClosed.IsSoCalClosed--args","text":"None Source code in kpf/socal/IsSoCalClosed.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class IsSoCalClosed ( KPFTranslatorFunction ): '''Returns True if SoCal enclsoure is closed. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'SoCal' , 'enclosure_status_time' , fallback = 10 ) ENCSTA = ktl . cache ( 'kpfsocal' , 'ENCSTA' ) is_closed = ENCSTA . waitFor ( \"==1\" , timeout = timeout ) msg = { True : 'SoCal is Closed' , False : 'SoCal is NOT Closed' }[ is_closed ] print ( msg ) return is_closed @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"ARGS:"},{"location":"scripts/IsSoCalOpen/","text":"IsSoCalOpen Bases: KPFTranslatorFunction Returns True if SoCal enclsoure is open. ARGS: None Source code in kpf/socal/IsSoCalOpen.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class IsSoCalOpen ( KPFTranslatorFunction ): '''Returns True if SoCal enclsoure is open. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'SoCal' , 'enclosure_status_time' , fallback = 10 ) ENCSTA = ktl . cache ( 'kpfsocal' , 'ENCSTA' ) is_open = ENCSTA . waitFor ( \"==0\" , timeout = timeout ) msg = { True : 'SoCal is Open' , False : 'SoCal is NOT Open' }[ is_open ] print ( msg ) return is_open @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"IsSoCalOpen"},{"location":"scripts/IsSoCalOpen/#issocalopen","text":"Bases: KPFTranslatorFunction Returns True if SoCal enclsoure is open.","title":"IsSoCalOpen"},{"location":"scripts/IsSoCalOpen/#kpf.socal.IsSoCalOpen.IsSoCalOpen--args","text":"None Source code in kpf/socal/IsSoCalOpen.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class IsSoCalOpen ( KPFTranslatorFunction ): '''Returns True if SoCal enclsoure is open. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'SoCal' , 'enclosure_status_time' , fallback = 10 ) ENCSTA = ktl . cache ( 'kpfsocal' , 'ENCSTA' ) is_open = ENCSTA . waitFor ( \"==0\" , timeout = timeout ) msg = { True : 'SoCal is Open' , False : 'SoCal is NOT Open' }[ is_open ] print ( msg ) return is_open @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"ARGS:"},{"location":"scripts/IsSoCalShutDown/","text":"IsSoCalShutDown Bases: KPFTranslatorFunction Returns True if SoCal enclosure is closed and tracker is parked. ARGS: None Source code in kpf/socal/IsSoCalShutDown.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class IsSoCalShutDown ( KPFTranslatorFunction ): '''Returns True if SoCal enclosure is closed and tracker is parked. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # Enclosure timeout = cfg . getfloat ( 'SoCal' , 'enclosure_status_time' , fallback = 10 ) ENCSTA = ktl . cache ( 'kpfsocal' , 'ENCSTA' ) is_closed = ENCSTA . waitFor ( \"==1\" , timeout = timeout ) EKOHOME = ktl . cache ( 'kpfsocal' , 'EKOHOME' ) is_home = EKOHOME . waitFor ( \"==1\" , timeout = timeout ) closedstr = { True : '' , False : 'NOT ' }[ is_closed ] parkedstr = { True : '' , False : 'NOT ' }[ is_home ] msg = f 'SoCal is { closedstr } closed and { parkedstr } parked' print ( msg ) shutdown = is_closed and is_home if not shutdown and args . get ( 'email' , False ) is True : try : SendEmail . execute ({ 'Subject' : f 'KPF SoCal is not shut down properly' , 'Message' : msg }) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) return shutdown @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( '--email' , dest = \"email\" , default = False , action = \"store_true\" , help = 'Send email if SoCal is not shut down?' ) return super () . add_cmdline_args ( parser , cfg )","title":"IsSoCalShutDown"},{"location":"scripts/IsSoCalShutDown/#issocalshutdown","text":"Bases: KPFTranslatorFunction Returns True if SoCal enclosure is closed and tracker is parked.","title":"IsSoCalShutDown"},{"location":"scripts/IsSoCalShutDown/#kpf.socal.IsSoCalShutDown.IsSoCalShutDown--args","text":"None Source code in kpf/socal/IsSoCalShutDown.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class IsSoCalShutDown ( KPFTranslatorFunction ): '''Returns True if SoCal enclosure is closed and tracker is parked. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # Enclosure timeout = cfg . getfloat ( 'SoCal' , 'enclosure_status_time' , fallback = 10 ) ENCSTA = ktl . cache ( 'kpfsocal' , 'ENCSTA' ) is_closed = ENCSTA . waitFor ( \"==1\" , timeout = timeout ) EKOHOME = ktl . cache ( 'kpfsocal' , 'EKOHOME' ) is_home = EKOHOME . waitFor ( \"==1\" , timeout = timeout ) closedstr = { True : '' , False : 'NOT ' }[ is_closed ] parkedstr = { True : '' , False : 'NOT ' }[ is_home ] msg = f 'SoCal is { closedstr } closed and { parkedstr } parked' print ( msg ) shutdown = is_closed and is_home if not shutdown and args . get ( 'email' , False ) is True : try : SendEmail . execute ({ 'Subject' : f 'KPF SoCal is not shut down properly' , 'Message' : msg }) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) return shutdown @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( '--email' , dest = \"email\" , default = False , action = \"store_true\" , help = 'Send email if SoCal is not shut down?' ) return super () . add_cmdline_args ( parser , cfg )","title":"ARGS:"},{"location":"scripts/LockFIU/","text":"LockFIU Bases: KPFTranslatorFunction Lock the FIU mechanisms Parameters: comment ( str ) \u2013 A comment (must not be empty) designating why the mechanisms are locked. KTL Keywords Used: kpffiu.ADC1LCK kpffiu.ADC2LCK kpffiu.FOLDLCK kpffiu.HKXLCK kpffiu.HKYLCK kpffiu.TTXLCK kpffiu.TTYLCK Source code in kpf/fiu/LockFIU.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 class LockFIU ( KPFTranslatorFunction ): '''Lock the FIU mechanisms Args: comment (str): A comment (must not be empty) designating why the mechanisms are locked. KTL Keywords Used: - `kpffiu.ADC1LCK` - `kpffiu.ADC2LCK` - `kpffiu.FOLDLCK` - `kpffiu.HKXLCK` - `kpffiu.HKYLCK` - `kpffiu.TTXLCK` - `kpffiu.TTYLCK` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): comment = args . get ( 'comment' , 'locked' ) . strip () kpffiu = ktl . cache ( 'kpffiu' ) kpffiu [ 'adc1lck' ] . write ( comment ) kpffiu [ 'adc2lck' ] . write ( comment ) kpffiu [ 'foldlck' ] . write ( comment ) kpffiu [ 'hkxlck' ] . write ( comment ) kpffiu [ 'hkylck' ] . write ( comment ) kpffiu [ 'ttxlck' ] . write ( comment ) kpffiu [ 'ttylck' ] . write ( comment ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'comment' , type = str , help = 'Comment for lock keywords' ) return super () . add_cmdline_args ( parser , cfg )","title":"LockFIU"},{"location":"scripts/LockFIU/#lockfiu","text":"Bases: KPFTranslatorFunction Lock the FIU mechanisms Parameters: comment ( str ) \u2013 A comment (must not be empty) designating why the mechanisms are locked. KTL Keywords Used: kpffiu.ADC1LCK kpffiu.ADC2LCK kpffiu.FOLDLCK kpffiu.HKXLCK kpffiu.HKYLCK kpffiu.TTXLCK kpffiu.TTYLCK Source code in kpf/fiu/LockFIU.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 class LockFIU ( KPFTranslatorFunction ): '''Lock the FIU mechanisms Args: comment (str): A comment (must not be empty) designating why the mechanisms are locked. KTL Keywords Used: - `kpffiu.ADC1LCK` - `kpffiu.ADC2LCK` - `kpffiu.FOLDLCK` - `kpffiu.HKXLCK` - `kpffiu.HKYLCK` - `kpffiu.TTXLCK` - `kpffiu.TTYLCK` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): comment = args . get ( 'comment' , 'locked' ) . strip () kpffiu = ktl . cache ( 'kpffiu' ) kpffiu [ 'adc1lck' ] . write ( comment ) kpffiu [ 'adc2lck' ] . write ( comment ) kpffiu [ 'foldlck' ] . write ( comment ) kpffiu [ 'hkxlck' ] . write ( comment ) kpffiu [ 'hkylck' ] . write ( comment ) kpffiu [ 'ttxlck' ] . write ( comment ) kpffiu [ 'ttylck' ] . write ( comment ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'comment' , type = str , help = 'Comment for lock keywords' ) return super () . add_cmdline_args ( parser , cfg )","title":"LockFIU"},{"location":"scripts/MeasureTipTiltMirrorRange/","text":"MeasureTipTiltMirrorRange Bases: KPFTranslatorFunction Measure the range of the tip tilt mirror. Prints to screen the keyword modify commands to update the range parameters. KTL Keywords Used: kpffiu.TTXVAX kpffiu.TTYVAX kpffiu.TTXMEX kpffiu.TTYMEX kpffiu.TTXMED kpffiu.TTYMED kpfguide.TIPTILT_HOME Scripts Called: kpf.fiu.InitializeTipTilt kpf.fiu.ShutdownTipTilt Source code in kpf/fiu/MeasureTipTiltMirrorRange.py 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 class MeasureTipTiltMirrorRange ( KPFTranslatorFunction ): '''Measure the range of the tip tilt mirror. Prints to screen the keyword modify commands to update the range parameters. KTL Keywords Used: - `kpffiu.TTXVAX` - `kpffiu.TTYVAX` - `kpffiu.TTXMEX` - `kpffiu.TTYMEX` - `kpffiu.TTXMED` - `kpffiu.TTYMED` - `kpfguide.TIPTILT_HOME` Scripts Called: - `kpf.fiu.InitializeTipTilt` - `kpf.fiu.ShutdownTipTilt` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # Measure tip tilt ranges log . info ( 'Beginning MeasureTipTiltMirrorRange' ) InitializeTipTilt . execute ({}) sleeptime = 10 # Set by the 5 second time in the %MEX and %MEV keywords # Need to account for worst case tol = cfg . getfloat ( 'tolerances' , 'tip_tilt_move_tolerance' , fallback = 0.1 ) n = args . get ( 'repeats' ) kpffiu = ktl . cache ( 'kpffiu' ) kpfguide = ktl . cache ( 'kpfguide' ) measured_range = {} axis = [ 'X' , 'Y' ] rawvals = {} update_ax = { 'X' : False , 'Y' : False } for i , ax in enumerate ( axis ): nominal_range = { 'X' : 15.9 , 'Y' : 24.6 }[ ax ] home = 0 measured_range [ ax ] = [ - nominal_range , nominal_range ] rawvals [ ax ] = [ None , None ] # Negative side commanded_position = home - nominal_range new_limit = find_new_limit ( ax , commanded_position , sleeptime = sleeptime , tol = tol , n = n ) if new_limit is not None : update_ax [ ax ] = True measured_range [ ax ][ 0 ] = new_limit # Positive side commanded_position = home + nominal_range new_limit = find_new_limit ( ax , commanded_position , sleeptime = sleeptime , tol = tol , n = n ) if new_limit is not None : update_ax [ ax ] = True measured_range [ ax ][ 1 ] = new_limit time . sleep ( sleeptime ) InitializeTipTilt . execute ({}) time . sleep ( sleeptime ) log . info ( f \"Measured X range: { measured_range [ 'X' ] } \" ) log . info ( f \"Measured Y range: { measured_range [ 'Y' ] } \" ) new_home = [ np . mean ( measured_range [ 'X' ]), np . mean ( measured_range [ 'Y' ])] current_home = kpfguide [ 'TIPTILT_HOME' ] . read ( binary = True ) if np . isclose ( current_home [ 0 ], new_home [ 0 ]) and np . isclose ( current_home [ 1 ], new_home [ 1 ]): print ( f 'TIPTILT_HOME OK: gshow -s kpfguide TIPTILT_HOME matches { new_home } ' ) else : print ( f \"modify -s kpfguide TIPTILT_HOME=' { new_home [ 0 ] : .1f } { new_home [ 1 ] : .1f } '\" ) for i , ax in enumerate ( axis ): print () range = ( max ( measured_range [ ax ]) - min ( measured_range [ ax ])) / 2 print ( f \"modify -s kpfguide TIPTILT_ { ax } RANGE= { range : .1f } \" ) print ( f \" Sending { ax } to home\" ) kpffiu [ f 'TT { ax } VAX' ] . write ( new_home [ i ]) time . sleep ( sleeptime ) new_RON = kpffiu [ f 'TT { ax } MED' ] . read () print ( f \"modify -s kpffiu TT { ax } RON='| { new_RON } |0|Home'\" ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( '--repeats' , type = int , default = 1 , help = \"The number of iterations to use in the calculation\" ) return super () . add_cmdline_args ( parser , cfg )","title":"MeasureTipTiltMirrorRange"},{"location":"scripts/MeasureTipTiltMirrorRange/#measuretiptiltmirrorrange","text":"Bases: KPFTranslatorFunction Measure the range of the tip tilt mirror. Prints to screen the keyword modify commands to update the range parameters. KTL Keywords Used: kpffiu.TTXVAX kpffiu.TTYVAX kpffiu.TTXMEX kpffiu.TTYMEX kpffiu.TTXMED kpffiu.TTYMED kpfguide.TIPTILT_HOME Scripts Called: kpf.fiu.InitializeTipTilt kpf.fiu.ShutdownTipTilt Source code in kpf/fiu/MeasureTipTiltMirrorRange.py 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 class MeasureTipTiltMirrorRange ( KPFTranslatorFunction ): '''Measure the range of the tip tilt mirror. Prints to screen the keyword modify commands to update the range parameters. KTL Keywords Used: - `kpffiu.TTXVAX` - `kpffiu.TTYVAX` - `kpffiu.TTXMEX` - `kpffiu.TTYMEX` - `kpffiu.TTXMED` - `kpffiu.TTYMED` - `kpfguide.TIPTILT_HOME` Scripts Called: - `kpf.fiu.InitializeTipTilt` - `kpf.fiu.ShutdownTipTilt` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # Measure tip tilt ranges log . info ( 'Beginning MeasureTipTiltMirrorRange' ) InitializeTipTilt . execute ({}) sleeptime = 10 # Set by the 5 second time in the %MEX and %MEV keywords # Need to account for worst case tol = cfg . getfloat ( 'tolerances' , 'tip_tilt_move_tolerance' , fallback = 0.1 ) n = args . get ( 'repeats' ) kpffiu = ktl . cache ( 'kpffiu' ) kpfguide = ktl . cache ( 'kpfguide' ) measured_range = {} axis = [ 'X' , 'Y' ] rawvals = {} update_ax = { 'X' : False , 'Y' : False } for i , ax in enumerate ( axis ): nominal_range = { 'X' : 15.9 , 'Y' : 24.6 }[ ax ] home = 0 measured_range [ ax ] = [ - nominal_range , nominal_range ] rawvals [ ax ] = [ None , None ] # Negative side commanded_position = home - nominal_range new_limit = find_new_limit ( ax , commanded_position , sleeptime = sleeptime , tol = tol , n = n ) if new_limit is not None : update_ax [ ax ] = True measured_range [ ax ][ 0 ] = new_limit # Positive side commanded_position = home + nominal_range new_limit = find_new_limit ( ax , commanded_position , sleeptime = sleeptime , tol = tol , n = n ) if new_limit is not None : update_ax [ ax ] = True measured_range [ ax ][ 1 ] = new_limit time . sleep ( sleeptime ) InitializeTipTilt . execute ({}) time . sleep ( sleeptime ) log . info ( f \"Measured X range: { measured_range [ 'X' ] } \" ) log . info ( f \"Measured Y range: { measured_range [ 'Y' ] } \" ) new_home = [ np . mean ( measured_range [ 'X' ]), np . mean ( measured_range [ 'Y' ])] current_home = kpfguide [ 'TIPTILT_HOME' ] . read ( binary = True ) if np . isclose ( current_home [ 0 ], new_home [ 0 ]) and np . isclose ( current_home [ 1 ], new_home [ 1 ]): print ( f 'TIPTILT_HOME OK: gshow -s kpfguide TIPTILT_HOME matches { new_home } ' ) else : print ( f \"modify -s kpfguide TIPTILT_HOME=' { new_home [ 0 ] : .1f } { new_home [ 1 ] : .1f } '\" ) for i , ax in enumerate ( axis ): print () range = ( max ( measured_range [ ax ]) - min ( measured_range [ ax ])) / 2 print ( f \"modify -s kpfguide TIPTILT_ { ax } RANGE= { range : .1f } \" ) print ( f \" Sending { ax } to home\" ) kpffiu [ f 'TT { ax } VAX' ] . write ( new_home [ i ]) time . sleep ( sleeptime ) new_RON = kpffiu [ f 'TT { ax } MED' ] . read () print ( f \"modify -s kpffiu TT { ax } RON='| { new_RON } |0|Home'\" ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( '--repeats' , type = int , default = 1 , help = \"The number of iterations to use in the calculation\" ) return super () . add_cmdline_args ( parser , cfg )","title":"MeasureTipTiltMirrorRange"},{"location":"scripts/ParkSoCal/","text":"ParkSoCal Bases: KPFTranslatorFunction Parks SoCal. This includes setting AUTONOMOUS to \"Manual\", closing the enclosure, and parking the solar tracker. ARGS: None Source code in kpf/socal/ParkSoCal.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 class ParkSoCal ( KPFTranslatorFunction ): '''Parks SoCal. This includes setting AUTONOMOUS to \"Manual\", closing the enclosure, and parking the solar tracker. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): SoCalStopAutonomous . execute ({}) log . info ( 'Parking SoCal' ) kpfsocal = ktl . cache ( 'kpfsocal' ) kpfsocal [ 'ENCCMD' ] . write ( 'close' ) kpfsocal [ 'EKOSLEW' ] . write ( 0 ) kpfsocal [ 'EKOTARGALT' ] . write ( 0 ) kpfsocal [ 'EKOTARGAZ' ] . write ( 0 ) kpfsocal [ 'EKOMODE' ] . write ( 0 ) kpfsocal [ 'EKOSLEW' ] . write ( 1 ) kpfsocal [ 'EKOSLEW' ] . write ( 0 ) @classmethod def post_condition ( cls , args , logger , cfg ): kpfsocal = ktl . cache ( 'kpfsocal' ) timeout = cfg . getfloat ( 'SoCal' , 'park_time' , fallback = 300 ) expr = '($kpfsocal.ENCSTA == 1) ' expr += 'and ($kpfsocal.EKOHOME == 1)' success = ktl . waitFor ( expr , timeout = timeout ) if success is False : raise FailedToReachDestination ( 'SoCal failed to park completely' )","title":"ParkSoCal"},{"location":"scripts/ParkSoCal/#parksocal","text":"Bases: KPFTranslatorFunction Parks SoCal. This includes setting AUTONOMOUS to \"Manual\", closing the enclosure, and parking the solar tracker.","title":"ParkSoCal"},{"location":"scripts/ParkSoCal/#kpf.socal.ParkSoCal.ParkSoCal--args","text":"None Source code in kpf/socal/ParkSoCal.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 class ParkSoCal ( KPFTranslatorFunction ): '''Parks SoCal. This includes setting AUTONOMOUS to \"Manual\", closing the enclosure, and parking the solar tracker. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): SoCalStopAutonomous . execute ({}) log . info ( 'Parking SoCal' ) kpfsocal = ktl . cache ( 'kpfsocal' ) kpfsocal [ 'ENCCMD' ] . write ( 'close' ) kpfsocal [ 'EKOSLEW' ] . write ( 0 ) kpfsocal [ 'EKOTARGALT' ] . write ( 0 ) kpfsocal [ 'EKOTARGAZ' ] . write ( 0 ) kpfsocal [ 'EKOMODE' ] . write ( 0 ) kpfsocal [ 'EKOSLEW' ] . write ( 1 ) kpfsocal [ 'EKOSLEW' ] . write ( 0 ) @classmethod def post_condition ( cls , args , logger , cfg ): kpfsocal = ktl . cache ( 'kpfsocal' ) timeout = cfg . getfloat ( 'SoCal' , 'park_time' , fallback = 300 ) expr = '($kpfsocal.ENCSTA == 1) ' expr += 'and ($kpfsocal.EKOHOME == 1)' success = ktl . waitFor ( expr , timeout = timeout ) if success is False : raise FailedToReachDestination ( 'SoCal failed to park completely' )","title":"ARGS:"},{"location":"scripts/PowerCycleCaHK/","text":"PowerCycleCaHK Bases: KPFTranslatorFunction Script which will power cycle the Ca HK detector control system and restart the services. Use as a last resort measure after other troubleshooting measures such as resetting the detector and restarting software have already failed. KTL Keywords Used: kpfpower.OUTLET_J1% kpfpower.OUTLET_J2% kpfpower.OUTLET_J5% Scripts Called: - kpf start/stop/status/restart kpfexpose2 - kpf start/stop/status/restart kpf_hk Source code in kpf/cahk/PowerCycleCaHK.py 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class PowerCycleCaHK ( KPFTranslatorFunction ): '''Script which will power cycle the Ca HK detector control system and restart the services. Use as a last resort measure after other troubleshooting measures such as resetting the detector and restarting software have already failed. KTL Keywords Used: - `kpfpower.OUTLET_J1%` - `kpfpower.OUTLET_J2%` - `kpfpower.OUTLET_J5%` Scripts Called: -`kpf start/stop/status/restart kpfexpose2` -`kpf start/stop/status/restart kpf_hk` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): kpfpower = ktl . cache ( 'kpfpower' ) outlets = [( 'J1' , 'kpfexpose2 Galil RIO controller' ), ( 'J2' , 'kpfexpose2 Galil output bank' ), ( 'J5' , 'Andor Newton PS' ), ] for outlet_id , outlet_name in outlets : name = kpfpower [ f 'OUTLET_ { outlet_id } _NAME' ] . read () if name . find ( outlet_name ) < 0 : raise FailedPreCondition ( f \"Outlet name: { outlet_id } != ' { outlet_name } '\" ) @classmethod def perform ( cls , args , logger , cfg ): log . warning ( 'Stopping kpfexpose2 dispatcher' ) cmd = [ 'kpf' , 'stop' , 'kpfexpose2' ] result = subprocess . run ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) log . debug ( f \" args: { result . args } \" ) log . debug ( f \" rtncode: { result . returncode } \" ) log . debug ( f \" STDOUT: { result . stdout . decode () } \" ) log . debug ( f \" STDERR: { result . stderr . decode () } \" ) if result . returncode != 0 : raise FailedPostCondition ( f \"The kpf stop kpfexpose2 command appears to have failed\" ) time . sleep ( 2 ) log . warning ( 'Stopping kpf_hk keyword service' ) cmd = [ 'kpf' , 'stop' , 'kpf_hk' ] result = subprocess . run ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) log . debug ( f \" args: { result . args } \" ) log . debug ( f \" rtncode: { result . returncode } \" ) log . debug ( f \" STDOUT: { result . stdout . decode () } \" ) log . debug ( f \" STDERR: { result . stderr . decode () } \" ) if result . returncode != 0 : raise FailedPostCondition ( f \"The kpf stop kpf_hk command appears to have failed\" ) time . sleep ( 2 ) # Get status response for log cmd = [ 'kpf' , 'status' , 'kpf_hk' ] result = subprocess . run ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) log . debug ( f \" args: { result . args } \" ) log . debug ( f \" rtncode: { result . returncode } \" ) log . debug ( f \" STDOUT: { result . stdout . decode () } \" ) log . debug ( f \" STDERR: { result . stderr . decode () } \" ) log . warning ( 'Power cycling the Ca HK detector system' ) kpfpower = ktl . cache ( 'kpfpower' ) outlets = [( 'J5' , 'Andor Newton PS' ), ( 'J1' , 'kpfexpose2 Galil RIO controller' ), ( 'J2' , 'kpfexpose2 Galil output bank' ), ] for outlet_id , outlet_name in outlets : log . info ( f \"Powering off { outlet_id } : { outlet_name } \" ) kpfpower [ f 'OUTLET_ { outlet_id } ' ] . write ( 'Off' ) time . sleep ( 10 ) for outlet_id , outlet_name in outlets : log . info ( f \"Powering on { outlet_id } : { outlet_name } \" ) kpfpower [ f 'OUTLET_ { outlet_id } ' ] . write ( 'On' ) time . sleep ( 10 ) log . warning ( 'Restarting kpf_hk keyword service' ) cmd = [ 'kpf' , 'restart' , 'kpf_hk' ] result = subprocess . run ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) log . debug ( f \" args: { result . args } \" ) log . debug ( f \" rtncode: { result . returncode } \" ) log . debug ( f \" STDOUT: { result . stdout . decode () } \" ) log . debug ( f \" STDERR: { result . stderr . decode () } \" ) if result . returncode != 0 : raise FailedPostCondition ( f \"The kpf restart kpf_hk command appears to have failed\" ) time . sleep ( 10 ) # Get status response for log cmd = [ 'kpf' , 'status' , 'kpf_hk' ] result = subprocess . run ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) log . debug ( f \" args: { result . args } \" ) log . debug ( f \" rtncode: { result . returncode } \" ) log . debug ( f \" STDOUT: { result . stdout . decode () } \" ) log . debug ( f \" STDERR: { result . stderr . decode () } \" ) log . warning ( 'Restarting kpfexpose2 keyword service' ) cmd = [ 'kpf' , 'restart' , 'kpfexpose2' ] result = subprocess . run ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) log . debug ( f \" args: { result . args } \" ) log . debug ( f \" rtncode: { result . returncode } \" ) log . debug ( f \" STDOUT: { result . stdout . decode () } \" ) log . debug ( f \" STDERR: { result . stderr . decode () } \" ) if result . returncode != 0 : raise FailedPostCondition ( f \"The kpf restart kpfexpose2 command appears to have failed\" ) time . sleep ( 10 ) # Get status response for log cmd = [ 'kpf' , 'status' , 'kpfexpose2' ] result = subprocess . run ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) log . debug ( f \" args: { result . args } \" ) log . debug ( f \" rtncode: { result . returncode } \" ) log . debug ( f \" STDOUT: { result . stdout . decode () } \" ) log . debug ( f \" STDERR: { result . stderr . decode () } \" ) log . warning ( 'Resetting Ca HK' ) ResetCaHKDetector . execute ({}) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"PowerCycleCaHK"},{"location":"scripts/PowerCycleCaHK/#powercyclecahk","text":"Bases: KPFTranslatorFunction Script which will power cycle the Ca HK detector control system and restart the services. Use as a last resort measure after other troubleshooting measures such as resetting the detector and restarting software have already failed. KTL Keywords Used: kpfpower.OUTLET_J1% kpfpower.OUTLET_J2% kpfpower.OUTLET_J5% Scripts Called: - kpf start/stop/status/restart kpfexpose2 - kpf start/stop/status/restart kpf_hk Source code in kpf/cahk/PowerCycleCaHK.py 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class PowerCycleCaHK ( KPFTranslatorFunction ): '''Script which will power cycle the Ca HK detector control system and restart the services. Use as a last resort measure after other troubleshooting measures such as resetting the detector and restarting software have already failed. KTL Keywords Used: - `kpfpower.OUTLET_J1%` - `kpfpower.OUTLET_J2%` - `kpfpower.OUTLET_J5%` Scripts Called: -`kpf start/stop/status/restart kpfexpose2` -`kpf start/stop/status/restart kpf_hk` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): kpfpower = ktl . cache ( 'kpfpower' ) outlets = [( 'J1' , 'kpfexpose2 Galil RIO controller' ), ( 'J2' , 'kpfexpose2 Galil output bank' ), ( 'J5' , 'Andor Newton PS' ), ] for outlet_id , outlet_name in outlets : name = kpfpower [ f 'OUTLET_ { outlet_id } _NAME' ] . read () if name . find ( outlet_name ) < 0 : raise FailedPreCondition ( f \"Outlet name: { outlet_id } != ' { outlet_name } '\" ) @classmethod def perform ( cls , args , logger , cfg ): log . warning ( 'Stopping kpfexpose2 dispatcher' ) cmd = [ 'kpf' , 'stop' , 'kpfexpose2' ] result = subprocess . run ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) log . debug ( f \" args: { result . args } \" ) log . debug ( f \" rtncode: { result . returncode } \" ) log . debug ( f \" STDOUT: { result . stdout . decode () } \" ) log . debug ( f \" STDERR: { result . stderr . decode () } \" ) if result . returncode != 0 : raise FailedPostCondition ( f \"The kpf stop kpfexpose2 command appears to have failed\" ) time . sleep ( 2 ) log . warning ( 'Stopping kpf_hk keyword service' ) cmd = [ 'kpf' , 'stop' , 'kpf_hk' ] result = subprocess . run ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) log . debug ( f \" args: { result . args } \" ) log . debug ( f \" rtncode: { result . returncode } \" ) log . debug ( f \" STDOUT: { result . stdout . decode () } \" ) log . debug ( f \" STDERR: { result . stderr . decode () } \" ) if result . returncode != 0 : raise FailedPostCondition ( f \"The kpf stop kpf_hk command appears to have failed\" ) time . sleep ( 2 ) # Get status response for log cmd = [ 'kpf' , 'status' , 'kpf_hk' ] result = subprocess . run ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) log . debug ( f \" args: { result . args } \" ) log . debug ( f \" rtncode: { result . returncode } \" ) log . debug ( f \" STDOUT: { result . stdout . decode () } \" ) log . debug ( f \" STDERR: { result . stderr . decode () } \" ) log . warning ( 'Power cycling the Ca HK detector system' ) kpfpower = ktl . cache ( 'kpfpower' ) outlets = [( 'J5' , 'Andor Newton PS' ), ( 'J1' , 'kpfexpose2 Galil RIO controller' ), ( 'J2' , 'kpfexpose2 Galil output bank' ), ] for outlet_id , outlet_name in outlets : log . info ( f \"Powering off { outlet_id } : { outlet_name } \" ) kpfpower [ f 'OUTLET_ { outlet_id } ' ] . write ( 'Off' ) time . sleep ( 10 ) for outlet_id , outlet_name in outlets : log . info ( f \"Powering on { outlet_id } : { outlet_name } \" ) kpfpower [ f 'OUTLET_ { outlet_id } ' ] . write ( 'On' ) time . sleep ( 10 ) log . warning ( 'Restarting kpf_hk keyword service' ) cmd = [ 'kpf' , 'restart' , 'kpf_hk' ] result = subprocess . run ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) log . debug ( f \" args: { result . args } \" ) log . debug ( f \" rtncode: { result . returncode } \" ) log . debug ( f \" STDOUT: { result . stdout . decode () } \" ) log . debug ( f \" STDERR: { result . stderr . decode () } \" ) if result . returncode != 0 : raise FailedPostCondition ( f \"The kpf restart kpf_hk command appears to have failed\" ) time . sleep ( 10 ) # Get status response for log cmd = [ 'kpf' , 'status' , 'kpf_hk' ] result = subprocess . run ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) log . debug ( f \" args: { result . args } \" ) log . debug ( f \" rtncode: { result . returncode } \" ) log . debug ( f \" STDOUT: { result . stdout . decode () } \" ) log . debug ( f \" STDERR: { result . stderr . decode () } \" ) log . warning ( 'Restarting kpfexpose2 keyword service' ) cmd = [ 'kpf' , 'restart' , 'kpfexpose2' ] result = subprocess . run ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) log . debug ( f \" args: { result . args } \" ) log . debug ( f \" rtncode: { result . returncode } \" ) log . debug ( f \" STDOUT: { result . stdout . decode () } \" ) log . debug ( f \" STDERR: { result . stderr . decode () } \" ) if result . returncode != 0 : raise FailedPostCondition ( f \"The kpf restart kpfexpose2 command appears to have failed\" ) time . sleep ( 10 ) # Get status response for log cmd = [ 'kpf' , 'status' , 'kpfexpose2' ] result = subprocess . run ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) log . debug ( f \" args: { result . args } \" ) log . debug ( f \" rtncode: { result . returncode } \" ) log . debug ( f \" STDOUT: { result . stdout . decode () } \" ) log . debug ( f \" STDERR: { result . stderr . decode () } \" ) log . warning ( 'Resetting Ca HK' ) ResetCaHKDetector . execute ({}) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"PowerCycleCaHK"},{"location":"scripts/PredictExpMeterParameters/","text":"PredictExpMeterParameters Bases: KPFTranslatorFunction Estimate the proper exposure meter exposure time given the stellar Gmag. Parameters: Gmag ( float ) \u2013 The Gaia g magnitude of the target. Source code in kpf/expmeter/PredictExpMeterParameters.py 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 class PredictExpMeterParameters ( KPFTranslatorFunction ): '''Estimate the proper exposure meter exposure time given the stellar Gmag. Args: Gmag (float): The Gaia g magnitude of the target. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'Gmag' , allowed_types = [ int , float ]) @classmethod def perform ( cls , args , logger , cfg ): Gmag = args . get ( 'Gmag' ) if Gmag < 4.0 : exptime = 0.5 elif Gmag < 9.0 : exptime = 1.0 elif Gmag < 11.0 : exptime = 2.0 elif Gmag < 13.0 : exptime = 4.0 elif Gmag < 15.0 : exptime = 8.0 else : exptime = 16.0 log . info ( f \"Predicted ExpMeterExpTime = { exptime : .1f } s\" ) return { 'ExpMeterExpTime' : exptime } @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'Gmag' , type = float , help = \"The Gaia g magnitude of the target\" ) return super () . add_cmdline_args ( parser , cfg )","title":"PredictExpMeterParameters"},{"location":"scripts/PredictExpMeterParameters/#predictexpmeterparameters","text":"Bases: KPFTranslatorFunction Estimate the proper exposure meter exposure time given the stellar Gmag. Parameters: Gmag ( float ) \u2013 The Gaia g magnitude of the target. Source code in kpf/expmeter/PredictExpMeterParameters.py 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 class PredictExpMeterParameters ( KPFTranslatorFunction ): '''Estimate the proper exposure meter exposure time given the stellar Gmag. Args: Gmag (float): The Gaia g magnitude of the target. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'Gmag' , allowed_types = [ int , float ]) @classmethod def perform ( cls , args , logger , cfg ): Gmag = args . get ( 'Gmag' ) if Gmag < 4.0 : exptime = 0.5 elif Gmag < 9.0 : exptime = 1.0 elif Gmag < 11.0 : exptime = 2.0 elif Gmag < 13.0 : exptime = 4.0 elif Gmag < 15.0 : exptime = 8.0 else : exptime = 16.0 log . info ( f \"Predicted ExpMeterExpTime = { exptime : .1f } s\" ) return { 'ExpMeterExpTime' : exptime } @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'Gmag' , type = float , help = \"The Gaia g magnitude of the target\" ) return super () . add_cmdline_args ( parser , cfg )","title":"PredictExpMeterParameters"},{"location":"scripts/PredictFVCParameters/","text":"PredictFVCParameters Bases: KPFTranslatorFunction Estimate the exposure time given the stellar Gmag and which camera. Based on scaling from a single, poorly measured data point: For Vmag ~ 4, the SCIFVC_exptime = 1 and CAHKFVC_exptime = 15 Parameters: Gmag ( float ) \u2013 The G magnitude of the target. Source code in kpf/fvc/PredictFVCParameters.py 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class PredictFVCParameters ( KPFTranslatorFunction ): '''Estimate the exposure time given the stellar Gmag and which camera. Based on scaling from a single, poorly measured data point: For Vmag ~ 4, the SCIFVC_exptime = 1 and CAHKFVC_exptime = 15 Args: Gmag (float): The G magnitude of the target. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'Gmag' , allowed_types = [ int , float ]) @classmethod def perform ( cls , args , logger , cfg ): Gmag = args . get ( 'Gmag' ) delta_mag = 4 - Gmag flux_ratio = 10 ** ( delta_mag / 2.5 ) if flux_ratio > 10 : exptime = { 'SCI' : 0.1 , 'CAHK' : 1.5 } elif flux_ratio > 5 : exptime = { 'SCI' : 0.2 , 'CAHK' : 3 } elif flux_ratio > 2 : exptime = { 'SCI' : 0.5 , 'CAHK' : 8 } elif flux_ratio > 0.5 : exptime = { 'SCI' : 1 , 'CAHK' : 15 } elif flux_ratio > 0.2 : exptime = { 'SCI' : 5 , 'CAHK' : 15 } elif flux_ratio > 0.05 : exptime = { 'SCI' : 10 , 'CAHK' : 15 } result = { 'SCIFVC_exptime' : exptime [ 'SCI' ], 'CAHKFVC_exptime' : exptime [ 'CAHK' ]} print ( result ) if args . get ( 'set' , False ): SetFVCExpTime . execute ({ 'camera' : 'SCI' , 'exptime' : exptime [ 'SCI' ]}) SetFVCExpTime . execute ({ 'camera' : 'CAHK' , 'exptime' : exptime [ 'CAHK' ]}) return result @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'Gmag' , type = float , help = \"The G magnitude of the target\" ) parser . add_argument ( \"--set\" , dest = \"set\" , default = False , action = \"store_true\" , help = \"Set these values after calculating?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"PredictFVCParameters"},{"location":"scripts/PredictFVCParameters/#predictfvcparameters","text":"Bases: KPFTranslatorFunction Estimate the exposure time given the stellar Gmag and which camera. Based on scaling from a single, poorly measured data point: For Vmag ~ 4, the SCIFVC_exptime = 1 and CAHKFVC_exptime = 15 Parameters: Gmag ( float ) \u2013 The G magnitude of the target. Source code in kpf/fvc/PredictFVCParameters.py 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class PredictFVCParameters ( KPFTranslatorFunction ): '''Estimate the exposure time given the stellar Gmag and which camera. Based on scaling from a single, poorly measured data point: For Vmag ~ 4, the SCIFVC_exptime = 1 and CAHKFVC_exptime = 15 Args: Gmag (float): The G magnitude of the target. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'Gmag' , allowed_types = [ int , float ]) @classmethod def perform ( cls , args , logger , cfg ): Gmag = args . get ( 'Gmag' ) delta_mag = 4 - Gmag flux_ratio = 10 ** ( delta_mag / 2.5 ) if flux_ratio > 10 : exptime = { 'SCI' : 0.1 , 'CAHK' : 1.5 } elif flux_ratio > 5 : exptime = { 'SCI' : 0.2 , 'CAHK' : 3 } elif flux_ratio > 2 : exptime = { 'SCI' : 0.5 , 'CAHK' : 8 } elif flux_ratio > 0.5 : exptime = { 'SCI' : 1 , 'CAHK' : 15 } elif flux_ratio > 0.2 : exptime = { 'SCI' : 5 , 'CAHK' : 15 } elif flux_ratio > 0.05 : exptime = { 'SCI' : 10 , 'CAHK' : 15 } result = { 'SCIFVC_exptime' : exptime [ 'SCI' ], 'CAHKFVC_exptime' : exptime [ 'CAHK' ]} print ( result ) if args . get ( 'set' , False ): SetFVCExpTime . execute ({ 'camera' : 'SCI' , 'exptime' : exptime [ 'SCI' ]}) SetFVCExpTime . execute ({ 'camera' : 'CAHK' , 'exptime' : exptime [ 'CAHK' ]}) return result @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'Gmag' , type = float , help = \"The G magnitude of the target\" ) parser . add_argument ( \"--set\" , dest = \"set\" , default = False , action = \"store_true\" , help = \"Set these values after calculating?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"PredictFVCParameters"},{"location":"scripts/PredictGuiderParameters/","text":"PredictGuiderParameters Bases: KPFTranslatorFunction Estimate the proper gain and FPS given the stellar Jmag. Parameters: Jmag ( float ) \u2013 The J magnitude of the target. Scripts Called: kpf.guider.SetGuiderGain kpf.guider.SetGuiderFPS Source code in kpf/guider/PredictGuiderParameters.py 26 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 class PredictGuiderParameters ( KPFTranslatorFunction ): '''Estimate the proper gain and FPS given the stellar Jmag. Args: Jmag (float): The J magnitude of the target. Scripts Called: - `kpf.guider.SetGuiderGain` - `kpf.guider.SetGuiderFPS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'Jmag' , allowed_types = [ int , float ]) @classmethod def perform ( cls , args , logger , cfg ): Jmag = args . get ( 'Jmag' ) if Jmag < 5.5 : gain = 'Low' fps = 100 elif Jmag < 8.0 : gain = 'Medium' fps = 100 elif Jmag < 12.0 : gain = 'High' fps = 100 elif Jmag < 12.8 : gain = 'High' fps = 50 elif Jmag < 13.8 : gain = 'High' fps = 20 elif Jmag < 14.5 : gain = 'High' fps = 10 elif Jmag < 17.0 : gain = 'high' fps = 1 else : gain = 'high' fps = 1 log . info ( f \"Predicted GuideCamGain = { gain } \" ) log . info ( f \"Predicted GuideFPS = { fps : d } \" ) result = { 'GuideCamGain' : gain , 'GuideFPS' : fps } if args . get ( 'set' , False ): SetGuiderGain . execute ( result ) SetGuiderFPS . execute ( result ) return result @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'Jmag' , type = float , help = \"The J magnitude of the target\" ) parser . add_argument ( \"--set\" , dest = \"set\" , default = False , action = \"store_true\" , help = \"Set these values after calculating?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"PredictGuiderParameters"},{"location":"scripts/PredictGuiderParameters/#predictguiderparameters","text":"Bases: KPFTranslatorFunction Estimate the proper gain and FPS given the stellar Jmag. Parameters: Jmag ( float ) \u2013 The J magnitude of the target. Scripts Called: kpf.guider.SetGuiderGain kpf.guider.SetGuiderFPS Source code in kpf/guider/PredictGuiderParameters.py 26 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 class PredictGuiderParameters ( KPFTranslatorFunction ): '''Estimate the proper gain and FPS given the stellar Jmag. Args: Jmag (float): The J magnitude of the target. Scripts Called: - `kpf.guider.SetGuiderGain` - `kpf.guider.SetGuiderFPS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'Jmag' , allowed_types = [ int , float ]) @classmethod def perform ( cls , args , logger , cfg ): Jmag = args . get ( 'Jmag' ) if Jmag < 5.5 : gain = 'Low' fps = 100 elif Jmag < 8.0 : gain = 'Medium' fps = 100 elif Jmag < 12.0 : gain = 'High' fps = 100 elif Jmag < 12.8 : gain = 'High' fps = 50 elif Jmag < 13.8 : gain = 'High' fps = 20 elif Jmag < 14.5 : gain = 'High' fps = 10 elif Jmag < 17.0 : gain = 'high' fps = 1 else : gain = 'high' fps = 1 log . info ( f \"Predicted GuideCamGain = { gain } \" ) log . info ( f \"Predicted GuideFPS = { fps : d } \" ) result = { 'GuideCamGain' : gain , 'GuideFPS' : fps } if args . get ( 'set' , False ): SetGuiderGain . execute ( result ) SetGuiderFPS . execute ( result ) return result @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'Jmag' , type = float , help = \"The J magnitude of the target\" ) parser . add_argument ( \"--set\" , dest = \"set\" , default = False , action = \"store_true\" , help = \"Set these values after calculating?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"PredictGuiderParameters"},{"location":"scripts/PredictNDFilters/","text":"PredictNDFilters Bases: KPFTranslatorFunction Predict which ND filters should be used for simultaneous calibrations. Parameters: ? ( float ) \u2013 Scripts Called: kpf.calbench.SetND Source code in kpf/calbench/PredictNDFilters.py 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 class PredictNDFilters ( KPFTranslatorFunction ): '''Predict which ND filters should be used for simultaneous calibrations. Args: ? (float): Scripts Called: - `kpf.calbench.SetND` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'Gmag' , allowed_types = [ int , float ]) check_input ( args , 'Teff' , allowed_types = [ int , float ]) check_input ( args , 'ExpTime' , allowed_types = [ int , float ]) @classmethod def perform ( cls , args , logger , cfg ): tick = datetime . datetime . now () gmag = args . get ( 'Gmag' ) teff = args . get ( 'Teff' ) log . debug ( 'Estimating Vmag from Gmag:' ) vmag = gmag - get_GminusV ( teff ) log . debug ( f ' Gmag= { gmag : .2f } --> Vmag= { vmag : .2f } ' ) obs_exp_time = args . get ( 'ExpTime' ) # reference calibration file to scale up/down #cal_file = 'KP.20240529.80736.43_L1.fits' # reference etalon L1 file data_dir = Path ( __file__ ) . parent . parent . parent / 'data' cal_file = data_dir / 'KP.20240529.80736.43_L1.fits' # Filter wheel populations for both wheels # od_arr_scical = [0.1, 0.3, 0.5, 0.8, 1.0, 4.0] # od_arr_cal = [0.1, 1.0, 1.3, 2., 3., 4.] # od_arr_scical = [0.1, 1.0, 1.3, 2., 3., 4.] # od_arr_cal = [0.1, 0.3, 0.5, 0.8, 1.0, 4.0] ND1POS = ktl . cache ( 'kpfcal' , 'ND1POS' ) ND1POS_allowed_values = list ( ND1POS . _getEnumerators ()) if 'Unknown' in ND1POS_allowed_values : ND1POS_allowed_values . pop ( ND1POS_allowed_values . index ( 'Unknown' )) od_arr_scical = [ float ( pos [ 3 :]) for pos in ND1POS_allowed_values ] ND2POS = ktl . cache ( 'kpfcal' , 'ND2POS' ) ND2POS_allowed_values = list ( ND2POS . _getEnumerators ()) if 'Unknown' in ND2POS_allowed_values : ND2POS_allowed_values . pop ( ND2POS_allowed_values . index ( 'Unknown' )) od_arr_cal = [ float ( pos [ 3 :]) for pos in ND2POS_allowed_values ] od_vals_all , filter_configs_all = all_possible_sums_with_indices_sorted ( od_arr_scical , od_arr_cal ) od , nd_config = get_simulcal_od ( vmag , teff , obs_exp_time , cal_file , ref_wave = 5500 , od_values = od_vals_all , filter_configs = filter_configs_all ) result = { 'CalND1' : f 'OD { nd_config [ 0 ] } ' , 'CalND2' : f 'OD { nd_config [ 1 ] } ' } log . info ( f \"Predicted ND1 = { result [ 'CalND1' ] } \" ) log . info ( f \"Predicted ND2 = { result [ 'CalND2' ] } \" ) tock = datetime . datetime . now () elapsed = ( tock - tick ) . total_seconds () log . debug ( f 'ND filter calculation took { elapsed : .1f } s' ) if args . get ( 'set' , False ): SetND . execute ( result ) return result @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'Gmag' , type = float , help = \"The gaia G magnitude of the target\" ) parser . add_argument ( 'Teff' , type = float , help = \"The effective temperature of the target\" ) parser . add_argument ( 'ExpTime' , type = float , help = \"The exposure time on target\" ) parser . add_argument ( \"--set\" , dest = \"set\" , default = False , action = \"store_true\" , help = \"Set these values after calculating?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"PredictNDFilters"},{"location":"scripts/PredictNDFilters/#predictndfilters","text":"Bases: KPFTranslatorFunction Predict which ND filters should be used for simultaneous calibrations. Parameters: ? ( float ) \u2013 Scripts Called: kpf.calbench.SetND Source code in kpf/calbench/PredictNDFilters.py 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 class PredictNDFilters ( KPFTranslatorFunction ): '''Predict which ND filters should be used for simultaneous calibrations. Args: ? (float): Scripts Called: - `kpf.calbench.SetND` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'Gmag' , allowed_types = [ int , float ]) check_input ( args , 'Teff' , allowed_types = [ int , float ]) check_input ( args , 'ExpTime' , allowed_types = [ int , float ]) @classmethod def perform ( cls , args , logger , cfg ): tick = datetime . datetime . now () gmag = args . get ( 'Gmag' ) teff = args . get ( 'Teff' ) log . debug ( 'Estimating Vmag from Gmag:' ) vmag = gmag - get_GminusV ( teff ) log . debug ( f ' Gmag= { gmag : .2f } --> Vmag= { vmag : .2f } ' ) obs_exp_time = args . get ( 'ExpTime' ) # reference calibration file to scale up/down #cal_file = 'KP.20240529.80736.43_L1.fits' # reference etalon L1 file data_dir = Path ( __file__ ) . parent . parent . parent / 'data' cal_file = data_dir / 'KP.20240529.80736.43_L1.fits' # Filter wheel populations for both wheels # od_arr_scical = [0.1, 0.3, 0.5, 0.8, 1.0, 4.0] # od_arr_cal = [0.1, 1.0, 1.3, 2., 3., 4.] # od_arr_scical = [0.1, 1.0, 1.3, 2., 3., 4.] # od_arr_cal = [0.1, 0.3, 0.5, 0.8, 1.0, 4.0] ND1POS = ktl . cache ( 'kpfcal' , 'ND1POS' ) ND1POS_allowed_values = list ( ND1POS . _getEnumerators ()) if 'Unknown' in ND1POS_allowed_values : ND1POS_allowed_values . pop ( ND1POS_allowed_values . index ( 'Unknown' )) od_arr_scical = [ float ( pos [ 3 :]) for pos in ND1POS_allowed_values ] ND2POS = ktl . cache ( 'kpfcal' , 'ND2POS' ) ND2POS_allowed_values = list ( ND2POS . _getEnumerators ()) if 'Unknown' in ND2POS_allowed_values : ND2POS_allowed_values . pop ( ND2POS_allowed_values . index ( 'Unknown' )) od_arr_cal = [ float ( pos [ 3 :]) for pos in ND2POS_allowed_values ] od_vals_all , filter_configs_all = all_possible_sums_with_indices_sorted ( od_arr_scical , od_arr_cal ) od , nd_config = get_simulcal_od ( vmag , teff , obs_exp_time , cal_file , ref_wave = 5500 , od_values = od_vals_all , filter_configs = filter_configs_all ) result = { 'CalND1' : f 'OD { nd_config [ 0 ] } ' , 'CalND2' : f 'OD { nd_config [ 1 ] } ' } log . info ( f \"Predicted ND1 = { result [ 'CalND1' ] } \" ) log . info ( f \"Predicted ND2 = { result [ 'CalND2' ] } \" ) tock = datetime . datetime . now () elapsed = ( tock - tick ) . total_seconds () log . debug ( f 'ND filter calculation took { elapsed : .1f } s' ) if args . get ( 'set' , False ): SetND . execute ( result ) return result @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'Gmag' , type = float , help = \"The gaia G magnitude of the target\" ) parser . add_argument ( 'Teff' , type = float , help = \"The effective temperature of the target\" ) parser . add_argument ( 'ExpTime' , type = float , help = \"The exposure time on target\" ) parser . add_argument ( \"--set\" , dest = \"set\" , default = False , action = \"store_true\" , help = \"Set these values after calculating?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"PredictNDFilters"},{"location":"scripts/QueryFastReadMode/","text":"QueryFastReadMode Bases: KPFTranslatorFunction Returns True if both ACF files are consistent with fast read mode. Source code in kpf/spectrograph/QueryFastReadMode.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class QueryFastReadMode ( KPFTranslatorFunction ): '''Returns True if both ACF files are consistent with fast read mode. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): green_mode , red_mode = QueryReadMode . execute ({}) return ( green_mode == 'fast' ) and ( red_mode == 'fast' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"QueryFastReadMode"},{"location":"scripts/QueryFastReadMode/#queryfastreadmode","text":"Bases: KPFTranslatorFunction Returns True if both ACF files are consistent with fast read mode. Source code in kpf/spectrograph/QueryFastReadMode.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class QueryFastReadMode ( KPFTranslatorFunction ): '''Returns True if both ACF files are consistent with fast read mode. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): green_mode , red_mode = QueryReadMode . execute ({}) return ( green_mode == 'fast' ) and ( red_mode == 'fast' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"QueryFastReadMode"},{"location":"scripts/QueryReadMode/","text":"QueryReadMode Bases: KPFTranslatorFunction Returns string describing the read mode. Source code in kpf/spectrograph/QueryReadMode.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 class QueryReadMode ( KPFTranslatorFunction ): '''Returns string describing the read mode. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfgreen = ktl . cache ( 'kpfgreen' ) green_normal_file = cfg . get ( 'acf_files' , 'green_normal' ) green_fast_file = cfg . get ( 'acf_files' , 'green_fast' ) green_ACFFILE = Path ( kpfgreen [ 'ACFFILE' ] . read ()) . stem if green_ACFFILE == green_normal_file : green_mode = 'normal' elif green_ACFFILE == green_fast_file : green_mode = 'fast' else : green_mode = 'unknown' kpfred = ktl . cache ( 'kpfred' ) red_normal_file = cfg . get ( 'acf_files' , 'red_normal' ) red_fast_file = cfg . get ( 'acf_files' , 'red_fast' ) red_ACFFILE = Path ( kpfred [ 'ACFFILE' ] . read ()) . stem if red_ACFFILE == red_normal_file : red_mode = 'normal' elif red_ACFFILE == red_fast_file : red_mode = 'fast' else : red_mode = 'unknown' log . debug ( f \"Green read mode: { green_mode } , Red read mode: { red_mode } \" ) print ( f \"Green read mode: { green_mode } \" ) print ( f \"Red read mode: { red_mode } \" ) return green_mode , red_mode @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"QueryReadMode"},{"location":"scripts/QueryReadMode/#queryreadmode","text":"Bases: KPFTranslatorFunction Returns string describing the read mode. Source code in kpf/spectrograph/QueryReadMode.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 class QueryReadMode ( KPFTranslatorFunction ): '''Returns string describing the read mode. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfgreen = ktl . cache ( 'kpfgreen' ) green_normal_file = cfg . get ( 'acf_files' , 'green_normal' ) green_fast_file = cfg . get ( 'acf_files' , 'green_fast' ) green_ACFFILE = Path ( kpfgreen [ 'ACFFILE' ] . read ()) . stem if green_ACFFILE == green_normal_file : green_mode = 'normal' elif green_ACFFILE == green_fast_file : green_mode = 'fast' else : green_mode = 'unknown' kpfred = ktl . cache ( 'kpfred' ) red_normal_file = cfg . get ( 'acf_files' , 'red_normal' ) red_fast_file = cfg . get ( 'acf_files' , 'red_fast' ) red_ACFFILE = Path ( kpfred [ 'ACFFILE' ] . read ()) . stem if red_ACFFILE == red_normal_file : red_mode = 'normal' elif red_ACFFILE == red_fast_file : red_mode = 'fast' else : red_mode = 'unknown' log . debug ( f \"Green read mode: { green_mode } , Red read mode: { red_mode } \" ) print ( f \"Green read mode: { green_mode } \" ) print ( f \"Red read mode: { red_mode } \" ) return green_mode , red_mode @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"QueryReadMode"},{"location":"scripts/RecoverDetectors/","text":"RecoverDetectors Bases: KPFTranslatorFunction Try to examine the state of all detectors an run the appropriate recovery ARGS: None Source code in kpf/spectrograph/ResetDetectors.py 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 class RecoverDetectors ( KPFTranslatorFunction ): '''Try to examine the state of all detectors an run the appropriate recovery ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): log . warning ( 'Attempting a detector recovery' ) timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) kpfmon = ktl . cache ( 'kpfmon' ) camera_status = kpfmon [ 'CAMSTATESTA' ] . read () if camera_status == 'OK' : log . warning ( 'No camera error state detected by kpfmon' ) explainnr = ktl . cache ( 'kpfexpose' , 'EXPLAINNR' ) explainnr_str = explainnr . read () if explainnr_str . find ( 'hk:' ) >= 0 : log . warning ( 'kpfexpose.EXPLAINNR contains hk' ) ResetCaHKDetector . execute ({}) elif camera_status == 'ERROR' : if kpfmon [ 'G_STATESTA' ] . read () == 'ERROR' : ResetGreenDetector . execute ({}) if kpfmon [ 'R_STATESTA' ] . read () == 'ERROR' : ResetRedDetector . execute ({}) if kpfmon [ 'H_STATESTA' ] . read () == 'ERROR' : ResetCaHKDetector . execute ({}) if kpfmon [ 'E_STATESTA' ] . read () == 'ERROR' : ResetExpMeterDetector . execute ({}) else : log . warning ( f 'kpfmon.CAMSTATESTA= { camera_status } . No action taken.' ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) log . debug ( f 'Waiting { timeout : .1f } s for EXPOSE to be Readout or Ready' ) expr = f \"($kpfexpose.EXPOSE == 'Ready') or ($kpfexpose.EXPOSE == 'Readout')\" log . warning ( f \"Waiting for kpfexpose to be Ready or Readout\" ) success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : kpfexposeexpose = ktl . cache ( 'kpfexpose' , 'EXPOSE' ) raise FailedToReachDestination ( kpfexposeexpose . read (), 'Ready or Readout' ) else : kpfexpose = ktl . cache ( 'kpfexpose' ) log . info ( f \"Reset detectors done\" ) log . info ( f \"kpfexpose.EXPOSE = { kpfexpose [ 'EXPOSE' ] . read () } \" ) log . info ( f \"kpfexpose.EXPLAINR = { kpfexpose [ 'EXPLAINR' ] . read () } \" ) log . info ( f \"kpfexpose.EXPLAINNR = { kpfexpose [ 'EXPLAINNR' ] . read () } \" )","title":"RecoverDetectors"},{"location":"scripts/RecoverDetectors/#recoverdetectors","text":"Bases: KPFTranslatorFunction Try to examine the state of all detectors an run the appropriate recovery","title":"RecoverDetectors"},{"location":"scripts/RecoverDetectors/#kpf.spectrograph.ResetDetectors.RecoverDetectors--args","text":"None Source code in kpf/spectrograph/ResetDetectors.py 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 class RecoverDetectors ( KPFTranslatorFunction ): '''Try to examine the state of all detectors an run the appropriate recovery ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): log . warning ( 'Attempting a detector recovery' ) timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) kpfmon = ktl . cache ( 'kpfmon' ) camera_status = kpfmon [ 'CAMSTATESTA' ] . read () if camera_status == 'OK' : log . warning ( 'No camera error state detected by kpfmon' ) explainnr = ktl . cache ( 'kpfexpose' , 'EXPLAINNR' ) explainnr_str = explainnr . read () if explainnr_str . find ( 'hk:' ) >= 0 : log . warning ( 'kpfexpose.EXPLAINNR contains hk' ) ResetCaHKDetector . execute ({}) elif camera_status == 'ERROR' : if kpfmon [ 'G_STATESTA' ] . read () == 'ERROR' : ResetGreenDetector . execute ({}) if kpfmon [ 'R_STATESTA' ] . read () == 'ERROR' : ResetRedDetector . execute ({}) if kpfmon [ 'H_STATESTA' ] . read () == 'ERROR' : ResetCaHKDetector . execute ({}) if kpfmon [ 'E_STATESTA' ] . read () == 'ERROR' : ResetExpMeterDetector . execute ({}) else : log . warning ( f 'kpfmon.CAMSTATESTA= { camera_status } . No action taken.' ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) log . debug ( f 'Waiting { timeout : .1f } s for EXPOSE to be Readout or Ready' ) expr = f \"($kpfexpose.EXPOSE == 'Ready') or ($kpfexpose.EXPOSE == 'Readout')\" log . warning ( f \"Waiting for kpfexpose to be Ready or Readout\" ) success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : kpfexposeexpose = ktl . cache ( 'kpfexpose' , 'EXPOSE' ) raise FailedToReachDestination ( kpfexposeexpose . read (), 'Ready or Readout' ) else : kpfexpose = ktl . cache ( 'kpfexpose' ) log . info ( f \"Reset detectors done\" ) log . info ( f \"kpfexpose.EXPOSE = { kpfexpose [ 'EXPOSE' ] . read () } \" ) log . info ( f \"kpfexpose.EXPLAINR = { kpfexpose [ 'EXPLAINR' ] . read () } \" ) log . info ( f \"kpfexpose.EXPLAINNR = { kpfexpose [ 'EXPLAINNR' ] . read () } \" )","title":"ARGS:"},{"location":"scripts/RecoverFromLowPowerMode/","text":"RecoverFromLowPowerMode Bases: KPFTranslatorFunction Recover from low power mode. Power on the Ca HK systems Restore cooling to Ca HK detector Re-enable Ca HK detector Power on CRED2 systems Source code in kpf/scripts/RecoverFromLowPowerMode.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class RecoverFromLowPowerMode ( KPFTranslatorFunction ): '''Recover from low power mode. - Power on the Ca HK systems - Restore cooling to Ca HK detector - Re-enable Ca HK detector - Power on CRED2 systems ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfconfig = ktl . cache ( 'kpfconfig' ) kpfpower = ktl . cache ( 'kpfpower' ) # Power up Ca HK detector systems kpf_hk = ktl . cache ( 'kpf_hk' ) log . info ( 'Powering on Ca HK detector systems' ) log . debug ( f \"Powering on { kpfpower [ 'OUTLET_J1_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_J1' ] . write ( 'On' ) log . debug ( f \"Powering on { kpfpower [ 'OUTLET_J2_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_J2' ] . write ( 'On' ) log . debug ( f \"Powering on { kpfpower [ 'OUTLET_J5_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_J5' ] . write ( 'On' ) time . sleep ( 10 ) log . info ( 'Turning Ca HK detector cooling on' ) kpf_hk [ 'COOLING' ] . write ( 'On' ) kpf_hk [ 'COOLTARG' ] . write ( - 60 ) log . info ( 'Enabling Ca HK detector' ) kpfconfig [ 'CA_HK_ENABLED' ] . write ( 'Yes' ) # Power up CRED2 detector systems log . info ( 'Powering on CRED2 detector systems' ) log . debug ( f \"Powering on { kpfpower [ 'OUTLET_K2_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_K2' ] . write ( 'On' ) log . debug ( f \"Powering on { kpfpower [ 'OUTLET_K3_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_K3' ] . write ( 'On' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--force\" , dest = \"force\" , default = False , action = \"store_true\" , help = \"Force change? This will terminate any running scripts.\" ) return super () . add_cmdline_args ( parser , cfg )","title":"RecoverFromLowPowerMode"},{"location":"scripts/RecoverFromLowPowerMode/#recoverfromlowpowermode","text":"Bases: KPFTranslatorFunction Recover from low power mode. Power on the Ca HK systems Restore cooling to Ca HK detector Re-enable Ca HK detector Power on CRED2 systems Source code in kpf/scripts/RecoverFromLowPowerMode.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class RecoverFromLowPowerMode ( KPFTranslatorFunction ): '''Recover from low power mode. - Power on the Ca HK systems - Restore cooling to Ca HK detector - Re-enable Ca HK detector - Power on CRED2 systems ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfconfig = ktl . cache ( 'kpfconfig' ) kpfpower = ktl . cache ( 'kpfpower' ) # Power up Ca HK detector systems kpf_hk = ktl . cache ( 'kpf_hk' ) log . info ( 'Powering on Ca HK detector systems' ) log . debug ( f \"Powering on { kpfpower [ 'OUTLET_J1_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_J1' ] . write ( 'On' ) log . debug ( f \"Powering on { kpfpower [ 'OUTLET_J2_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_J2' ] . write ( 'On' ) log . debug ( f \"Powering on { kpfpower [ 'OUTLET_J5_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_J5' ] . write ( 'On' ) time . sleep ( 10 ) log . info ( 'Turning Ca HK detector cooling on' ) kpf_hk [ 'COOLING' ] . write ( 'On' ) kpf_hk [ 'COOLTARG' ] . write ( - 60 ) log . info ( 'Enabling Ca HK detector' ) kpfconfig [ 'CA_HK_ENABLED' ] . write ( 'Yes' ) # Power up CRED2 detector systems log . info ( 'Powering on CRED2 detector systems' ) log . debug ( f \"Powering on { kpfpower [ 'OUTLET_K2_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_K2' ] . write ( 'On' ) log . debug ( f \"Powering on { kpfpower [ 'OUTLET_K3_NAME' ] . read () } \" ) kpfpower [ 'OUTLET_K3' ] . write ( 'On' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--force\" , dest = \"force\" , default = False , action = \"store_true\" , help = \"Force change? This will terminate any running scripts.\" ) return super () . add_cmdline_args ( parser , cfg )","title":"RecoverFromLowPowerMode"},{"location":"scripts/ResetCaHKDetector/","text":"ResetCaHKDetector Bases: KPFTranslatorFunction Resets the Ca HK detector by aborting the exposure ARGS: None Source code in kpf/spectrograph/ResetDetectors.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class ResetCaHKDetector ( KPFTranslatorFunction ): '''Resets the Ca HK detector by aborting the exposure ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): expose = ktl . cache ( 'kpf_hk' , 'EXPOSE' ) log . warning ( f \"Resetting/Aborting: kpf_hk.EXPOSE = abort\" ) expose . write ( 'abort' ) log . debug ( 'Reset/abort command sent' ) @classmethod def post_condition ( cls , args , logger , cfg ): expstate = ktl . cache ( 'kpf_hk' , 'EXPSTATE' ) timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) log . warning ( f \"Waiting for kpf_hk to be Ready\" ) success = expstate . waitFor ( '==\"Ready\"' , timeout = timeout ) if success is not True : raise FailedToReachDestination ( expstate . read (), 'Ready' )","title":"ResetCaHKDetector"},{"location":"scripts/ResetCaHKDetector/#resetcahkdetector","text":"Bases: KPFTranslatorFunction Resets the Ca HK detector by aborting the exposure","title":"ResetCaHKDetector"},{"location":"scripts/ResetCaHKDetector/#kpf.spectrograph.ResetDetectors.ResetCaHKDetector--args","text":"None Source code in kpf/spectrograph/ResetDetectors.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class ResetCaHKDetector ( KPFTranslatorFunction ): '''Resets the Ca HK detector by aborting the exposure ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): expose = ktl . cache ( 'kpf_hk' , 'EXPOSE' ) log . warning ( f \"Resetting/Aborting: kpf_hk.EXPOSE = abort\" ) expose . write ( 'abort' ) log . debug ( 'Reset/abort command sent' ) @classmethod def post_condition ( cls , args , logger , cfg ): expstate = ktl . cache ( 'kpf_hk' , 'EXPSTATE' ) timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) log . warning ( f \"Waiting for kpf_hk to be Ready\" ) success = expstate . waitFor ( '==\"Ready\"' , timeout = timeout ) if success is not True : raise FailedToReachDestination ( expstate . read (), 'Ready' )","title":"ARGS:"},{"location":"scripts/ResetDetectors/","text":"ResetDetectors Bases: KPFTranslatorFunction Resets the kpfexpose service by setting kpfexpose.EXPOSE = Reset Description from Will Deich: This sets EXPOSE=Reset for the appropriate service. For the ktlcamerad services, that just means, \u201ceven though you\u2019ve not received (from camerad) the normal sequence of messages for a completed exposure, pretend everything is fine for starting a new exposure.\u201d ARGS: None Source code in kpf/spectrograph/ResetDetectors.py 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 class ResetDetectors ( KPFTranslatorFunction ): '''Resets the kpfexpose service by setting kpfexpose.EXPOSE = Reset Description from Will Deich: This sets EXPOSE=Reset for the appropriate service. For the ktlcamerad services, that just means, \u201ceven though you\u2019ve not received (from camerad) the normal sequence of messages for a completed exposure, pretend everything is fine for starting a new exposure.\u201d ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) log . warning ( f \"Resetting: kpfexpose.EXPOSE = Reset\" ) kpfexpose [ 'EXPOSE' ] . write ( 'Reset' ) log . debug ( 'Reset command sent' ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) log . debug ( f 'Waiting { timeout : .1f } s for EXPOSE to be Readout or Ready' ) expr = f \"($kpfexpose.EXPOSE == 'Ready') or ($kpfexpose.EXPOSE == 'Readout')\" log . warning ( f \"Waiting for kpfexpose to be Ready or Readout\" ) success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : kpfexposeexpose = ktl . cache ( 'kpfexpose' , 'EXPOSE' ) raise FailedToReachDestination ( kpfexposeexpose . read (), 'Ready or Readout' ) else : kpfexpose = ktl . cache ( 'kpfexpose' ) log . info ( f \"Reset detectors done\" ) log . info ( f \"kpfexpose.EXPOSE = { kpfexpose [ 'EXPOSE' ] . read () } \" ) log . info ( f \"kpfexpose.EXPLAINR = { kpfexpose [ 'EXPLAINR' ] . read () } \" ) log . info ( f \"kpfexpose.EXPLAINNR = { kpfexpose [ 'EXPLAINNR' ] . read () } \" )","title":"ResetDetectors"},{"location":"scripts/ResetDetectors/#resetdetectors","text":"Bases: KPFTranslatorFunction Resets the kpfexpose service by setting kpfexpose.EXPOSE = Reset Description from Will Deich: This sets EXPOSE=Reset for the appropriate service. For the ktlcamerad services, that just means, \u201ceven though you\u2019ve not received (from camerad) the normal sequence of messages for a completed exposure, pretend everything is fine for starting a new exposure.\u201d","title":"ResetDetectors"},{"location":"scripts/ResetDetectors/#kpf.spectrograph.ResetDetectors.ResetDetectors--args","text":"None Source code in kpf/spectrograph/ResetDetectors.py 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 class ResetDetectors ( KPFTranslatorFunction ): '''Resets the kpfexpose service by setting kpfexpose.EXPOSE = Reset Description from Will Deich: This sets EXPOSE=Reset for the appropriate service. For the ktlcamerad services, that just means, \u201ceven though you\u2019ve not received (from camerad) the normal sequence of messages for a completed exposure, pretend everything is fine for starting a new exposure.\u201d ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) log . warning ( f \"Resetting: kpfexpose.EXPOSE = Reset\" ) kpfexpose [ 'EXPOSE' ] . write ( 'Reset' ) log . debug ( 'Reset command sent' ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) log . debug ( f 'Waiting { timeout : .1f } s for EXPOSE to be Readout or Ready' ) expr = f \"($kpfexpose.EXPOSE == 'Ready') or ($kpfexpose.EXPOSE == 'Readout')\" log . warning ( f \"Waiting for kpfexpose to be Ready or Readout\" ) success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : kpfexposeexpose = ktl . cache ( 'kpfexpose' , 'EXPOSE' ) raise FailedToReachDestination ( kpfexposeexpose . read (), 'Ready or Readout' ) else : kpfexpose = ktl . cache ( 'kpfexpose' ) log . info ( f \"Reset detectors done\" ) log . info ( f \"kpfexpose.EXPOSE = { kpfexpose [ 'EXPOSE' ] . read () } \" ) log . info ( f \"kpfexpose.EXPLAINR = { kpfexpose [ 'EXPLAINR' ] . read () } \" ) log . info ( f \"kpfexpose.EXPLAINNR = { kpfexpose [ 'EXPLAINNR' ] . read () } \" )","title":"ARGS:"},{"location":"scripts/ResetExpMeterDetector/","text":"ResetExpMeterDetector Bases: KPFTranslatorFunction Resets the exposure meter detector ARGS: None Source code in kpf/spectrograph/ResetDetectors.py 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 class ResetExpMeterDetector ( KPFTranslatorFunction ): '''Resets the exposure meter detector ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): expose = ktl . cache ( 'kpf_expmeter' , 'EXPOSE' ) log . warning ( f \"Resetting: kpf_expmeter.EXPOSE = abort\" ) expose . write ( 'Reset' ) log . debug ( 'Reset command sent' ) @classmethod def post_condition ( cls , args , logger , cfg ): expstate = ktl . cache ( 'kpf_expmeter' , 'EXPSTATE' ) timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) log . warning ( f \"Waiting for kpf_expmeter to be Ready\" ) success = expstate . waitFor ( '==\"Ready\"' , timeout = timeout ) if success is not True : raise FailedToReachDestination ( expstate . read (), 'Ready' )","title":"ResetExpMeterDetector"},{"location":"scripts/ResetExpMeterDetector/#resetexpmeterdetector","text":"Bases: KPFTranslatorFunction Resets the exposure meter detector","title":"ResetExpMeterDetector"},{"location":"scripts/ResetExpMeterDetector/#kpf.spectrograph.ResetDetectors.ResetExpMeterDetector--args","text":"None Source code in kpf/spectrograph/ResetDetectors.py 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 class ResetExpMeterDetector ( KPFTranslatorFunction ): '''Resets the exposure meter detector ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): expose = ktl . cache ( 'kpf_expmeter' , 'EXPOSE' ) log . warning ( f \"Resetting: kpf_expmeter.EXPOSE = abort\" ) expose . write ( 'Reset' ) log . debug ( 'Reset command sent' ) @classmethod def post_condition ( cls , args , logger , cfg ): expstate = ktl . cache ( 'kpf_expmeter' , 'EXPSTATE' ) timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) log . warning ( f \"Waiting for kpf_expmeter to be Ready\" ) success = expstate . waitFor ( '==\"Ready\"' , timeout = timeout ) if success is not True : raise FailedToReachDestination ( expstate . read (), 'Ready' )","title":"ARGS:"},{"location":"scripts/ResetGreenDetector/","text":"ResetGreenDetector Bases: KPFTranslatorFunction Resets the kpfgreen detector ARGS: None Source code in kpf/spectrograph/ResetDetectors.py 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 class ResetGreenDetector ( KPFTranslatorFunction ): '''Resets the kpfgreen detector ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # Check if the auto reset is already doing this current_expstate = ktl . cache ( 'kpfgreen' , 'EXPSTATE' ) current_expstate . read () if current_expstate == 'Resetting' : return elif current_expstate == 'Exposing' : log . warning ( 'Can not send reset during exposure' ) return # Send the reset expose = ktl . cache ( 'kpfgreen' , 'EXPOSE' ) log . warning ( f \"Resetting: kpfgreen.EXPOSE = Reset\" ) expose . write ( 'Reset' ) log . debug ( 'Reset command sent' ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) log . warning ( f \"Waiting for kpfgreen to be Readout or Ready\" ) expr = f \"($kpfgreen.EXPOSE == 'Ready') or ($kpfgreen.EXPOSE == 'Readout')\" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : expose = ktl . cache ( 'kpfgreen' , 'EXPOSE' ) raise FailedToReachDestination ( expose . read (), 'Ready or Readout' ) else : kpfexpose = ktl . cache ( 'kpfexpose' ) log . info ( f \"ResetGreenDetector done\" ) log . info ( f \"kpfexpose.EXPOSE = { kpfexpose [ 'EXPOSE' ] . read () } \" ) log . info ( f \"kpfexpose.EXPLAINR = { kpfexpose [ 'EXPLAINR' ] . read () } \" ) log . info ( f \"kpfexpose.EXPLAINNR = { kpfexpose [ 'EXPLAINNR' ] . read () } \" )","title":"ResetGreenDetector"},{"location":"scripts/ResetGreenDetector/#resetgreendetector","text":"Bases: KPFTranslatorFunction Resets the kpfgreen detector","title":"ResetGreenDetector"},{"location":"scripts/ResetGreenDetector/#kpf.spectrograph.ResetDetectors.ResetGreenDetector--args","text":"None Source code in kpf/spectrograph/ResetDetectors.py 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 class ResetGreenDetector ( KPFTranslatorFunction ): '''Resets the kpfgreen detector ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # Check if the auto reset is already doing this current_expstate = ktl . cache ( 'kpfgreen' , 'EXPSTATE' ) current_expstate . read () if current_expstate == 'Resetting' : return elif current_expstate == 'Exposing' : log . warning ( 'Can not send reset during exposure' ) return # Send the reset expose = ktl . cache ( 'kpfgreen' , 'EXPOSE' ) log . warning ( f \"Resetting: kpfgreen.EXPOSE = Reset\" ) expose . write ( 'Reset' ) log . debug ( 'Reset command sent' ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) log . warning ( f \"Waiting for kpfgreen to be Readout or Ready\" ) expr = f \"($kpfgreen.EXPOSE == 'Ready') or ($kpfgreen.EXPOSE == 'Readout')\" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : expose = ktl . cache ( 'kpfgreen' , 'EXPOSE' ) raise FailedToReachDestination ( expose . read (), 'Ready or Readout' ) else : kpfexpose = ktl . cache ( 'kpfexpose' ) log . info ( f \"ResetGreenDetector done\" ) log . info ( f \"kpfexpose.EXPOSE = { kpfexpose [ 'EXPOSE' ] . read () } \" ) log . info ( f \"kpfexpose.EXPLAINR = { kpfexpose [ 'EXPLAINR' ] . read () } \" ) log . info ( f \"kpfexpose.EXPLAINNR = { kpfexpose [ 'EXPLAINNR' ] . read () } \" )","title":"ARGS:"},{"location":"scripts/ResetRedDetector/","text":"ResetRedDetector Bases: KPFTranslatorFunction Resets the kpfred detector ARGS: None Source code in kpf/spectrograph/ResetDetectors.py 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 class ResetRedDetector ( KPFTranslatorFunction ): '''Resets the kpfred detector ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # Check if the auto reset is already doing this current_expstate = ktl . cache ( 'kpfred' , 'EXPSTATE' ) current_expstate . read () if current_expstate == 'Resetting' : return elif current_expstate == 'Exposing' : log . warning ( 'Can not send reset during exposure' ) return # Send the reset expose = ktl . cache ( 'kpfred' , 'EXPOSE' ) log . warning ( f \"Resetting: kpfred.EXPOSE = Reset\" ) expose . write ( 'Reset' ) log . debug ( 'Reset command sent' ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) log . warning ( f \"Waiting for kpfred to be Readout or Ready\" ) expr = f \"($kpfred.EXPOSE == 'Ready') or ($kpfred.EXPOSE == 'Readout')\" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : expose = ktl . cache ( 'kpfred' , 'EXPOSE' ) raise FailedToReachDestination ( expose . read (), 'Ready or Readout' ) else : kpfexpose = ktl . cache ( 'kpfexpose' ) log . info ( f \"ResetRedDetector done\" ) log . info ( f \"kpfexpose.EXPOSE = { kpfexpose [ 'EXPOSE' ] . read () } \" ) log . info ( f \"kpfexpose.EXPLAINR = { kpfexpose [ 'EXPLAINR' ] . read () } \" ) log . info ( f \"kpfexpose.EXPLAINNR = { kpfexpose [ 'EXPLAINNR' ] . read () } \" )","title":"ResetRedDetector"},{"location":"scripts/ResetRedDetector/#resetreddetector","text":"Bases: KPFTranslatorFunction Resets the kpfred detector","title":"ResetRedDetector"},{"location":"scripts/ResetRedDetector/#kpf.spectrograph.ResetDetectors.ResetRedDetector--args","text":"None Source code in kpf/spectrograph/ResetDetectors.py 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 class ResetRedDetector ( KPFTranslatorFunction ): '''Resets the kpfred detector ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # Check if the auto reset is already doing this current_expstate = ktl . cache ( 'kpfred' , 'EXPSTATE' ) current_expstate . read () if current_expstate == 'Resetting' : return elif current_expstate == 'Exposing' : log . warning ( 'Can not send reset during exposure' ) return # Send the reset expose = ktl . cache ( 'kpfred' , 'EXPOSE' ) log . warning ( f \"Resetting: kpfred.EXPOSE = Reset\" ) expose . write ( 'Reset' ) log . debug ( 'Reset command sent' ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) log . warning ( f \"Waiting for kpfred to be Readout or Ready\" ) expr = f \"($kpfred.EXPOSE == 'Ready') or ($kpfred.EXPOSE == 'Readout')\" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : expose = ktl . cache ( 'kpfred' , 'EXPOSE' ) raise FailedToReachDestination ( expose . read (), 'Ready or Readout' ) else : kpfexpose = ktl . cache ( 'kpfexpose' ) log . info ( f \"ResetRedDetector done\" ) log . info ( f \"kpfexpose.EXPOSE = { kpfexpose [ 'EXPOSE' ] . read () } \" ) log . info ( f \"kpfexpose.EXPLAINR = { kpfexpose [ 'EXPLAINR' ] . read () } \" ) log . info ( f \"kpfexpose.EXPLAINNR = { kpfexpose [ 'EXPLAINNR' ] . read () } \" )","title":"ARGS:"},{"location":"scripts/Run2DGridSearch/","text":"Run2DGridSearch Bases: KPFTranslatorFunction Source code in kpf/engineering/Run2DGridSearch.py 16 17 18 19 20 21 22 23 24 25 26 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 class Run2DGridSearch ( KPFTranslatorFunction ): ''' ''' @classmethod @obey_scriptrun def pre_condition ( cls , OB , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): n = args . get ( 'n' ) d = args . get ( 'd' ) Gmag = args . get ( 'Gmag' ) time_on_position = args . get ( 'time_on_position' ) comment = args . get ( 'comment' , '' ) em_parameters = PredictExpMeterParameters . execute ({ 'Gmag' : Gmag }) # Check if FVCs are on, if so, use them FVCs_that_are_on = [] for camera in [ 'SCI' , 'CAHK' ]: camnum = { 'SCI' : 1 , 'CAHK' : 2 }[ camera ] powerkw = ktl . cache ( 'kpfpower' , f 'KPFFVC { camnum } ' ) if powerkw . read () . lower () == 'on' : FVCs_that_are_on . append ( camera ) FVCstring = ',' . join ( FVCs_that_are_on ) if len ( FVCs_that_are_on ) > 0 : fvc_parameters = PredictFVCParameters . execute ({ 'Gmag' : Gmag }) print ( f \"Predicted FVC parameters:\" ) print ( fvc_parameters ) print ( 'Set the FVC parameters manually and press enter to continue' ) user_input = input () dcs = ktl . cache ( 'dcs1' ) targname = dcs [ 'TARGNAME' ] . read () args = { 'Template_Name' : 'kpf_eng_grid' , 'Template_Version' : 0.4 , 'Grid' : 'TipTilt' , 'dx' : d , 'dy' : d , 'TimeOnPosition' : time_on_position , 'TriggerCaHK' : False , 'TriggerGreen' : False , 'TriggerRed' : False , 'TriggerExpMeter' : True , 'UseCRED2' : True , 'SSS_Science' : True , 'SSS_Sky' : True , 'SSS_CalSciSky' : False , 'ExpMeter_exptime' : em_parameters [ 'ExpMeterExpTime' ], 'FVCs' : FVCstring , } x_args = { 'comment' : f '1D in X { targname } (G= { Gmag : .1f } ) { comment } ' , 'nx' : n , 'ny' : 1 , } args . update ( x_args ) GridSearch . execute ( args ) y_args = { 'comment' : f '1D in Y { targname } (G= { Gmag : .1f } ) { comment } ' , 'nx' : 1 , 'ny' : n , } args . update ( y_args ) GridSearch . execute ( args ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'd' , type = float , help = \"Separation between positions (in guder pix)\" ) parser . add_argument ( 'n' , type = int , help = \"Number of position samples in each axis\" ) parser . add_argument ( 'Gmag' , type = float , help = \"The G magnitude of the target\" ) parser . add_argument ( \"--comment\" , dest = \"comment\" , type = str , default = '' , help = \"Additional comment text\" ) parser . add_argument ( \"--time\" , dest = \"time_on_position\" , type = float , default = 15 , help = \"Dwell time at each position (s)\" ) return super () . add_cmdline_args ( parser , cfg )","title":"Run2DGridSearch"},{"location":"scripts/Run2DGridSearch/#run2dgridsearch","text":"Bases: KPFTranslatorFunction Source code in kpf/engineering/Run2DGridSearch.py 16 17 18 19 20 21 22 23 24 25 26 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 class Run2DGridSearch ( KPFTranslatorFunction ): ''' ''' @classmethod @obey_scriptrun def pre_condition ( cls , OB , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): n = args . get ( 'n' ) d = args . get ( 'd' ) Gmag = args . get ( 'Gmag' ) time_on_position = args . get ( 'time_on_position' ) comment = args . get ( 'comment' , '' ) em_parameters = PredictExpMeterParameters . execute ({ 'Gmag' : Gmag }) # Check if FVCs are on, if so, use them FVCs_that_are_on = [] for camera in [ 'SCI' , 'CAHK' ]: camnum = { 'SCI' : 1 , 'CAHK' : 2 }[ camera ] powerkw = ktl . cache ( 'kpfpower' , f 'KPFFVC { camnum } ' ) if powerkw . read () . lower () == 'on' : FVCs_that_are_on . append ( camera ) FVCstring = ',' . join ( FVCs_that_are_on ) if len ( FVCs_that_are_on ) > 0 : fvc_parameters = PredictFVCParameters . execute ({ 'Gmag' : Gmag }) print ( f \"Predicted FVC parameters:\" ) print ( fvc_parameters ) print ( 'Set the FVC parameters manually and press enter to continue' ) user_input = input () dcs = ktl . cache ( 'dcs1' ) targname = dcs [ 'TARGNAME' ] . read () args = { 'Template_Name' : 'kpf_eng_grid' , 'Template_Version' : 0.4 , 'Grid' : 'TipTilt' , 'dx' : d , 'dy' : d , 'TimeOnPosition' : time_on_position , 'TriggerCaHK' : False , 'TriggerGreen' : False , 'TriggerRed' : False , 'TriggerExpMeter' : True , 'UseCRED2' : True , 'SSS_Science' : True , 'SSS_Sky' : True , 'SSS_CalSciSky' : False , 'ExpMeter_exptime' : em_parameters [ 'ExpMeterExpTime' ], 'FVCs' : FVCstring , } x_args = { 'comment' : f '1D in X { targname } (G= { Gmag : .1f } ) { comment } ' , 'nx' : n , 'ny' : 1 , } args . update ( x_args ) GridSearch . execute ( args ) y_args = { 'comment' : f '1D in Y { targname } (G= { Gmag : .1f } ) { comment } ' , 'nx' : 1 , 'ny' : n , } args . update ( y_args ) GridSearch . execute ( args ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'd' , type = float , help = \"Separation between positions (in guder pix)\" ) parser . add_argument ( 'n' , type = int , help = \"Number of position samples in each axis\" ) parser . add_argument ( 'Gmag' , type = float , help = \"The G magnitude of the target\" ) parser . add_argument ( \"--comment\" , dest = \"comment\" , type = str , default = '' , help = \"Additional comment text\" ) parser . add_argument ( \"--time\" , dest = \"time_on_position\" , type = float , default = 15 , help = \"Dwell time at each position (s)\" ) return super () . add_cmdline_args ( parser , cfg )","title":"Run2DGridSearch"},{"location":"scripts/RunCalOB/","text":"RunCalOB Bases: KPFTranslatorFunction Script to run a full Calibration OB from the command line. This must have arguments as input, typically from a file using the -f command line tool. This script is abortable. When .abort_execution() is invoked, the kpconfig.SCRIPTSTOP is set to Yes. This script checked for this value at various locations in the script. As a result, the script will not stop immediately, but will stop when it reaches a breakpoint. ARGS: OB - dict A fully specified observing block (OB). Source code in kpf/scripts/RunCalOB.py 26 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 class RunCalOB ( KPFTranslatorFunction ): '''Script to run a full Calibration OB from the command line. This must have arguments as input, typically from a file using the `-f` command line tool. This script is abortable. When `.abort_execution()` is invoked, the `kpconfig.SCRIPTSTOP` is set to Yes. This script checked for this value at various locations in the script. As a result, the script will not stop immediately, but will stop when it reaches a breakpoint. ARGS: ===== * __OB__ - `dict` A fully specified observing block (OB). ''' abortable = True @classmethod def pre_condition ( cls , OB , logger , cfg ): check_input ( OB , 'Template_Name' , allowed_values = [ 'kpf_cal' ]) check_input ( OB , 'Template_Version' , version_check = True , value_min = '0.5' ) @classmethod @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in OB : if key not in [ 'SEQ_Darks' , 'SEQ_Calibrations' ]: log . debug ( f \" { key } : { OB [ key ] } \" ) else : log . debug ( f \" { key } :\" ) for entry in OB [ key ]: log . debug ( f \" { entry } \" ) log . info ( '-------------------------' ) # Configure: Turn on Lamps try : ConfigureForCalibrations . execute ( OB ) except ExistingScriptRunning as e : log . error ( 'ExistingScriptRunning' ) sys . exit ( 1 ) except Exception as e : log . error ( 'ConfigureForCalibrations Failed' ) log . error ( e ) traceback_text = traceback . format_exc () log . error ( traceback_text ) # Email error to kpf_info if not isinstance ( e , ScriptStopTriggered ): try : msg = [ f ' { type ( e ) } ' , f ' { traceback_text } ' , '' , f ' { OB } ' ] SendEmail . execute ({ 'Subject' : 'ConfigureForCalibrations Failed' , 'Message' : ' \\n ' . join ( msg )}) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) log . error ( 'Running CleanupAfterCalibrations and exiting' ) CleanupAfterCalibrations . execute ( OB ) raise e check_script_running () set_script_keywords ( Path ( __file__ ) . name , os . getpid ()) # Execute the Dark Sequence try : darks = OB . get ( 'SEQ_Darks' , []) if len ( darks ) > 0 : log . info ( f \"Setting source select shutters\" ) SetSourceSelectShutters . execute ({}) # No args defaults all to false log . info ( f \"Setting timed shutters\" ) SetTimedShutters . execute ({}) # No args defaults all to false log . info ( f \"Setting OCTAGON to Home position\" ) SetCalSource . execute ({ 'CalSource' : 'Home' }) log . info ( f \"Setting FlatField Fiber position to 'Blank'\" ) SetFlatFieldFiberPos . execute ({ 'FF_FiberPos' : 'Blank' }) for dark in darks : # Wrap in try/except so that cleanup happens dark [ 'Template_Name' ] = 'kpf_dark' dark [ 'Template_Version' ] = OB [ 'Template_Version' ] ExecuteDark . execute ( dark ) except Exception as e : log . error ( \"ExecuteDarks failed:\" ) log . error ( e ) traceback_text = traceback . format_exc () log . error ( traceback_text ) # Email error to kpf_info if not isinstance ( e , ScriptStopTriggered ): try : msg = [ f ' { type ( e ) } ' , f ' { traceback_text } ' , '' , f ' { OB } ' ] SendEmail . execute ({ 'Subject' : 'ExecuteDarks Failed' , 'Message' : ' \\n ' . join ( msg )}) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) # Cleanup log . error ( 'Running CleanupAfterCalibrations and exiting' ) CleanupAfterCalibrations . execute ( OB ) sys . exit ( 1 ) # Execute the Cal Sequence try : cals = OB . get ( 'SEQ_Calibrations' , []) for cal in cals : cal [ 'TriggerCaHK' ] = OB [ 'TriggerCaHK' ] cal [ 'TriggerGreen' ] = OB [ 'TriggerGreen' ] cal [ 'TriggerRed' ] = OB [ 'TriggerRed' ] # No need to specify TimedShutter_CaHK in OB/calibration cal [ 'TimedShutter_CaHK' ] = OB . get ( 'TriggerCaHK' , False ) log . debug ( f \"Automatically setting TimedShutter_CaHK: { cal [ 'TimedShutter_CaHK' ] } \" ) cal [ 'Template_Name' ] = 'kpf_lamp' cal [ 'Template_Version' ] = OB [ 'Template_Version' ] cal [ 'nointensemon' ] = OB . get ( 'nointensemon' , False ) cal [ 'leave_lamps_on' ] = OB . get ( 'leave_lamps_on' , False ) # Only needed for LFC ExecuteCal . execute ( cal ) except Exception as e : log . error ( \"ExecuteCal failed:\" ) log . error ( e ) traceback_text = traceback . format_exc () log . error ( traceback_text ) # Email error to kpf_info if not isinstance ( e , ScriptStopTriggered ): try : msg = [ f ' { type ( e ) } ' , f ' { traceback . format_exc () } ' , '' , f ' { OB } ' ] SendEmail . execute ({ 'Subject' : 'ExecuteCals Failed' , 'Message' : ' \\n ' . join ( msg )}) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) # Cleanup log . error ( 'Running CleanupAfterCalibrations and exiting' ) CleanupAfterCalibrations . execute ( OB ) sys . exit ( 1 ) # Cleanup: Turn off lamps try : CleanupAfterCalibrations . execute ( OB ) except Exception as e : log . error ( \"CleanupAfterCalibrations failed:\" ) log . error ( e ) traceback_text = traceback . format_exc () log . error ( traceback_text ) clear_script_keywords () # Email error to kpf_info try : msg = [ f ' { type ( e ) } ' , f ' { traceback_text } ' , '' , f ' { OB } ' ] SendEmail . execute ({ 'Subject' : 'CleanupAfterCalibrations Failed' , 'Message' : ' \\n ' . join ( msg )}) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) @classmethod def post_condition ( cls , OB , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( '--leave_lamps_on' , dest = \"leave_lamps_on\" , default = False , action = \"store_true\" , help = 'Leave the lamps on after cleanup phase?' ) parser . add_argument ( '--nointensemon' , dest = \"nointensemon\" , default = False , action = \"store_true\" , help = 'Skip the intensity monitor measurement?' ) return super () . add_cmdline_args ( parser , cfg )","title":"RunCalOB"},{"location":"scripts/RunCalOB/#runcalob","text":"Bases: KPFTranslatorFunction Script to run a full Calibration OB from the command line. This must have arguments as input, typically from a file using the -f command line tool. This script is abortable. When .abort_execution() is invoked, the kpconfig.SCRIPTSTOP is set to Yes. This script checked for this value at various locations in the script. As a result, the script will not stop immediately, but will stop when it reaches a breakpoint.","title":"RunCalOB"},{"location":"scripts/RunCalOB/#kpf.scripts.RunCalOB.RunCalOB--args","text":"OB - dict A fully specified observing block (OB). Source code in kpf/scripts/RunCalOB.py 26 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 class RunCalOB ( KPFTranslatorFunction ): '''Script to run a full Calibration OB from the command line. This must have arguments as input, typically from a file using the `-f` command line tool. This script is abortable. When `.abort_execution()` is invoked, the `kpconfig.SCRIPTSTOP` is set to Yes. This script checked for this value at various locations in the script. As a result, the script will not stop immediately, but will stop when it reaches a breakpoint. ARGS: ===== * __OB__ - `dict` A fully specified observing block (OB). ''' abortable = True @classmethod def pre_condition ( cls , OB , logger , cfg ): check_input ( OB , 'Template_Name' , allowed_values = [ 'kpf_cal' ]) check_input ( OB , 'Template_Version' , version_check = True , value_min = '0.5' ) @classmethod @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in OB : if key not in [ 'SEQ_Darks' , 'SEQ_Calibrations' ]: log . debug ( f \" { key } : { OB [ key ] } \" ) else : log . debug ( f \" { key } :\" ) for entry in OB [ key ]: log . debug ( f \" { entry } \" ) log . info ( '-------------------------' ) # Configure: Turn on Lamps try : ConfigureForCalibrations . execute ( OB ) except ExistingScriptRunning as e : log . error ( 'ExistingScriptRunning' ) sys . exit ( 1 ) except Exception as e : log . error ( 'ConfigureForCalibrations Failed' ) log . error ( e ) traceback_text = traceback . format_exc () log . error ( traceback_text ) # Email error to kpf_info if not isinstance ( e , ScriptStopTriggered ): try : msg = [ f ' { type ( e ) } ' , f ' { traceback_text } ' , '' , f ' { OB } ' ] SendEmail . execute ({ 'Subject' : 'ConfigureForCalibrations Failed' , 'Message' : ' \\n ' . join ( msg )}) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) log . error ( 'Running CleanupAfterCalibrations and exiting' ) CleanupAfterCalibrations . execute ( OB ) raise e check_script_running () set_script_keywords ( Path ( __file__ ) . name , os . getpid ()) # Execute the Dark Sequence try : darks = OB . get ( 'SEQ_Darks' , []) if len ( darks ) > 0 : log . info ( f \"Setting source select shutters\" ) SetSourceSelectShutters . execute ({}) # No args defaults all to false log . info ( f \"Setting timed shutters\" ) SetTimedShutters . execute ({}) # No args defaults all to false log . info ( f \"Setting OCTAGON to Home position\" ) SetCalSource . execute ({ 'CalSource' : 'Home' }) log . info ( f \"Setting FlatField Fiber position to 'Blank'\" ) SetFlatFieldFiberPos . execute ({ 'FF_FiberPos' : 'Blank' }) for dark in darks : # Wrap in try/except so that cleanup happens dark [ 'Template_Name' ] = 'kpf_dark' dark [ 'Template_Version' ] = OB [ 'Template_Version' ] ExecuteDark . execute ( dark ) except Exception as e : log . error ( \"ExecuteDarks failed:\" ) log . error ( e ) traceback_text = traceback . format_exc () log . error ( traceback_text ) # Email error to kpf_info if not isinstance ( e , ScriptStopTriggered ): try : msg = [ f ' { type ( e ) } ' , f ' { traceback_text } ' , '' , f ' { OB } ' ] SendEmail . execute ({ 'Subject' : 'ExecuteDarks Failed' , 'Message' : ' \\n ' . join ( msg )}) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) # Cleanup log . error ( 'Running CleanupAfterCalibrations and exiting' ) CleanupAfterCalibrations . execute ( OB ) sys . exit ( 1 ) # Execute the Cal Sequence try : cals = OB . get ( 'SEQ_Calibrations' , []) for cal in cals : cal [ 'TriggerCaHK' ] = OB [ 'TriggerCaHK' ] cal [ 'TriggerGreen' ] = OB [ 'TriggerGreen' ] cal [ 'TriggerRed' ] = OB [ 'TriggerRed' ] # No need to specify TimedShutter_CaHK in OB/calibration cal [ 'TimedShutter_CaHK' ] = OB . get ( 'TriggerCaHK' , False ) log . debug ( f \"Automatically setting TimedShutter_CaHK: { cal [ 'TimedShutter_CaHK' ] } \" ) cal [ 'Template_Name' ] = 'kpf_lamp' cal [ 'Template_Version' ] = OB [ 'Template_Version' ] cal [ 'nointensemon' ] = OB . get ( 'nointensemon' , False ) cal [ 'leave_lamps_on' ] = OB . get ( 'leave_lamps_on' , False ) # Only needed for LFC ExecuteCal . execute ( cal ) except Exception as e : log . error ( \"ExecuteCal failed:\" ) log . error ( e ) traceback_text = traceback . format_exc () log . error ( traceback_text ) # Email error to kpf_info if not isinstance ( e , ScriptStopTriggered ): try : msg = [ f ' { type ( e ) } ' , f ' { traceback . format_exc () } ' , '' , f ' { OB } ' ] SendEmail . execute ({ 'Subject' : 'ExecuteCals Failed' , 'Message' : ' \\n ' . join ( msg )}) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) # Cleanup log . error ( 'Running CleanupAfterCalibrations and exiting' ) CleanupAfterCalibrations . execute ( OB ) sys . exit ( 1 ) # Cleanup: Turn off lamps try : CleanupAfterCalibrations . execute ( OB ) except Exception as e : log . error ( \"CleanupAfterCalibrations failed:\" ) log . error ( e ) traceback_text = traceback . format_exc () log . error ( traceback_text ) clear_script_keywords () # Email error to kpf_info try : msg = [ f ' { type ( e ) } ' , f ' { traceback_text } ' , '' , f ' { OB } ' ] SendEmail . execute ({ 'Subject' : 'CleanupAfterCalibrations Failed' , 'Message' : ' \\n ' . join ( msg )}) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) @classmethod def post_condition ( cls , OB , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( '--leave_lamps_on' , dest = \"leave_lamps_on\" , default = False , action = \"store_true\" , help = 'Leave the lamps on after cleanup phase?' ) parser . add_argument ( '--nointensemon' , dest = \"nointensemon\" , default = False , action = \"store_true\" , help = 'Skip the intensity monitor measurement?' ) return super () . add_cmdline_args ( parser , cfg )","title":"ARGS:"},{"location":"scripts/RunSciOB/","text":"RunSciOB Bases: KPFTranslatorFunction Script to run a full Science OB from the command line. This must have arguments as input, typically from a file using the -f command line tool. This script is abortable. When .abort_execution() is invoked, the kpconfig.SCRIPTSTOP is set to Yes. This script checked for this value at various locations in the script. As a result, the script will not stop immediately, but will stop when it reaches a breakpoint. ARGS: OB - dict A fully specified observing block (OB). Source code in kpf/scripts/RunSciOB.py 23 24 25 26 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 class RunSciOB ( KPFTranslatorFunction ): '''Script to run a full Science OB from the command line. This must have arguments as input, typically from a file using the `-f` command line tool. This script is abortable. When `.abort_execution()` is invoked, the `kpconfig.SCRIPTSTOP` is set to Yes. This script checked for this value at various locations in the script. As a result, the script will not stop immediately, but will stop when it reaches a breakpoint. ARGS: ===== * __OB__ - `dict` A fully specified observing block (OB). ''' abortable = True @classmethod def pre_condition ( cls , OB , logger , cfg ): check_input ( OB , 'Template_Name' , allowed_values = [ 'kpf_sci' ]) check_input ( OB , 'Template_Version' , version_check = True , value_min = '0.5' ) @classmethod @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) log . info ( '-------------------------' ) check_scriptstop () # Configure: log . info ( f \"Configuring for Acquisition\" ) ConfigureForAcquisition . execute ( OB ) WaitForConfigureAcquisition . execute ( OB ) check_scriptstop () log . debug ( 'Asking for user input' ) print () print ( \"###############################################################\" ) print ( \" Before continuing, please ensure that the OA has placed\" ) print ( \" the star on the KPF PO and they have initiated tip tilt\" ) print ( \" corrections (if desired).\" ) print () print ( \" Press 'Enter' to begin exposure(s) or 'a' to abort script\" ) print ( \"###############################################################\" ) print () user_input = input () log . debug ( f 'response: \" { user_input } \"' ) if user_input . lower () in [ 'a' , 'abort' , 'q' , 'quit' ]: raise KPFException ( \"User chose to halt execution\" ) check_scriptstop () log . info ( f \"Configuring for Science\" ) ConfigureForScience . execute ( OB ) WaitForConfigureScience . execute ( OB ) check_script_running () set_script_keywords ( Path ( __file__ ) . name , os . getpid ()) # Execute the Cal Sequence # Wrap in try/except so that cleanup happens observations = OB . get ( 'SEQ_Observations' , []) for observation in observations : observation [ 'Template_Name' ] = 'kpf_sci' observation [ 'Template_Version' ] = OB [ 'Template_Version' ] log . debug ( f \"Automatically setting TimedShutter_CaHK: { OB [ 'TriggerCaHK' ] } \" ) observation [ 'TimedShutter_CaHK' ] = OB [ 'TriggerCaHK' ] observation [ 'TriggerCaHK' ] = OB [ 'TriggerCaHK' ] observation [ 'TriggerGreen' ] = OB [ 'TriggerGreen' ] observation [ 'TriggerRed' ] = OB [ 'TriggerRed' ] # Note: pyyaml resolver currently converts off string to False boolean observation [ 'TriggerGuide' ] = True observation [ 'Gmag' ] = OB [ 'Gmag' ] try : ExecuteSci . execute ( observation ) except Exception as e : log . error ( \"ExecuteSci failed:\" ) log . error ( e ) traceback_text = traceback . format_exc () log . error ( traceback_text ) # Cleanup clear_script_keywords () log . error ( 'Running CleanupAfterScience and exiting' ) CleanupAfterScience . execute ( OB ) sys . exit ( 1 ) # Cleanup CleanupAfterScience . execute ( OB ) @classmethod def post_condition ( cls , OB , logger , cfg ): pass","title":"RunSciOB"},{"location":"scripts/RunSciOB/#runsciob","text":"Bases: KPFTranslatorFunction Script to run a full Science OB from the command line. This must have arguments as input, typically from a file using the -f command line tool. This script is abortable. When .abort_execution() is invoked, the kpconfig.SCRIPTSTOP is set to Yes. This script checked for this value at various locations in the script. As a result, the script will not stop immediately, but will stop when it reaches a breakpoint.","title":"RunSciOB"},{"location":"scripts/RunSciOB/#kpf.scripts.RunSciOB.RunSciOB--args","text":"OB - dict A fully specified observing block (OB). Source code in kpf/scripts/RunSciOB.py 23 24 25 26 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 class RunSciOB ( KPFTranslatorFunction ): '''Script to run a full Science OB from the command line. This must have arguments as input, typically from a file using the `-f` command line tool. This script is abortable. When `.abort_execution()` is invoked, the `kpconfig.SCRIPTSTOP` is set to Yes. This script checked for this value at various locations in the script. As a result, the script will not stop immediately, but will stop when it reaches a breakpoint. ARGS: ===== * __OB__ - `dict` A fully specified observing block (OB). ''' abortable = True @classmethod def pre_condition ( cls , OB , logger , cfg ): check_input ( OB , 'Template_Name' , allowed_values = [ 'kpf_sci' ]) check_input ( OB , 'Template_Version' , version_check = True , value_min = '0.5' ) @classmethod @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) log . info ( '-------------------------' ) check_scriptstop () # Configure: log . info ( f \"Configuring for Acquisition\" ) ConfigureForAcquisition . execute ( OB ) WaitForConfigureAcquisition . execute ( OB ) check_scriptstop () log . debug ( 'Asking for user input' ) print () print ( \"###############################################################\" ) print ( \" Before continuing, please ensure that the OA has placed\" ) print ( \" the star on the KPF PO and they have initiated tip tilt\" ) print ( \" corrections (if desired).\" ) print () print ( \" Press 'Enter' to begin exposure(s) or 'a' to abort script\" ) print ( \"###############################################################\" ) print () user_input = input () log . debug ( f 'response: \" { user_input } \"' ) if user_input . lower () in [ 'a' , 'abort' , 'q' , 'quit' ]: raise KPFException ( \"User chose to halt execution\" ) check_scriptstop () log . info ( f \"Configuring for Science\" ) ConfigureForScience . execute ( OB ) WaitForConfigureScience . execute ( OB ) check_script_running () set_script_keywords ( Path ( __file__ ) . name , os . getpid ()) # Execute the Cal Sequence # Wrap in try/except so that cleanup happens observations = OB . get ( 'SEQ_Observations' , []) for observation in observations : observation [ 'Template_Name' ] = 'kpf_sci' observation [ 'Template_Version' ] = OB [ 'Template_Version' ] log . debug ( f \"Automatically setting TimedShutter_CaHK: { OB [ 'TriggerCaHK' ] } \" ) observation [ 'TimedShutter_CaHK' ] = OB [ 'TriggerCaHK' ] observation [ 'TriggerCaHK' ] = OB [ 'TriggerCaHK' ] observation [ 'TriggerGreen' ] = OB [ 'TriggerGreen' ] observation [ 'TriggerRed' ] = OB [ 'TriggerRed' ] # Note: pyyaml resolver currently converts off string to False boolean observation [ 'TriggerGuide' ] = True observation [ 'Gmag' ] = OB [ 'Gmag' ] try : ExecuteSci . execute ( observation ) except Exception as e : log . error ( \"ExecuteSci failed:\" ) log . error ( e ) traceback_text = traceback . format_exc () log . error ( traceback_text ) # Cleanup clear_script_keywords () log . error ( 'Running CleanupAfterScience and exiting' ) CleanupAfterScience . execute ( OB ) sys . exit ( 1 ) # Cleanup CleanupAfterScience . execute ( OB ) @classmethod def post_condition ( cls , OB , logger , cfg ): pass","title":"ARGS:"},{"location":"scripts/RunSoCalObservingLoop/","text":"RunSoCalObservingLoop Bases: KPFTranslatorFunction This script runs a control loop to execute SoCal observations. When the script is invoked, it puts SoCal in AUTONOMOUS mode. This means that the SoCal dispatcher number 4 will handle opening the enclosure, acquiring and tracking the Sun, and will perform a weather safety shutdown if needed. The AUTONOMOUS mode will respect the CAN_OPEN keyword as well, so that keyword will lock out SoCal motions if that is desired. The script takes two required inputs: a start and end time in decimal hours (in HST). The start time can be after the invocation of this script. This is in fact the recommended operational strategy as the SoCal AUTONOMOUS mode will then have time to open and acquire the Sun before observations start. If needed, the script will wait until the start time before taking further actions (beyond setting AUTONOMOUS). Once the start time has passed, the script will check the kpfconfig.SCRIPT% keywords to see if something is currently running. If so, it will wait for the script keywords to clear before starting operations. Next the script will try to determine if SoCal is successfully observing the Sun by invoking the WaitForSoCalOnTarget script. If SoCal is on target, then a short observation of the Sun is performed. Some of the parameters can be modified in the KPFTranslator configuration file ( kpf_inst_config.ini ). This observation, as currently configured, takes about 15 minutes to complete. If SoCal is not on target (according to the WaitForSoCalOnTarget script), then an Etalon calibration set is taken. This is a way to make use of time that would otherwise be unproductive. This etalon script also takes around 15 minutes or a bit less to complete. Once either of the two observations above has completed, the script repeats the loop as long as there is enough time before the end time to complete a SoCal observation. Once the end time has passed, the system will perform basic cleanup of KPF, then it will park SoCal using ParkSoCal if the park flag is set. Arguments StartTimeHST - float The time (in decimal hours HST) to begin observing. EndTimeHST - float The time (in decimal hours HST) to end observing. park - bool If True, the script will park SoCal when complete. scheduled - bool If True, the script will not run if the keyword kpfconfig.ALLOWSCHEDULEDCALS is \"No\". Source code in kpf/scripts/RunSoCalObservingLoop.py 23 24 25 26 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 class RunSoCalObservingLoop ( KPFTranslatorFunction ): '''This script runs a control loop to execute SoCal observations. When the script is invoked, it puts SoCal in AUTONOMOUS mode. This means that the SoCal dispatcher number 4 will handle opening the enclosure, acquiring and tracking the Sun, and will perform a weather safety shutdown if needed. The AUTONOMOUS mode will respect the CAN_OPEN keyword as well, so that keyword will lock out SoCal motions if that is desired. The script takes two required inputs: a start and end time in decimal hours (in HST). The start time can be after the invocation of this script. This is in fact the recommended operational strategy as the SoCal AUTONOMOUS mode will then have time to open and acquire the Sun before observations start. If needed, the script will wait until the start time before taking further actions (beyond setting AUTONOMOUS). Once the start time has passed, the script will check the `kpfconfig.SCRIPT%` keywords to see if something is currently running. If so, it will wait for the script keywords to clear before starting operations. Next the script will try to determine if SoCal is successfully observing the Sun by invoking the `WaitForSoCalOnTarget` script. If SoCal is on target, then a short observation of the Sun is performed. Some of the parameters can be modified in the `KPFTranslator` configuration file (`kpf_inst_config.ini`). This observation, as currently configured, takes about 15 minutes to complete. If SoCal is not on target (according to the `WaitForSoCalOnTarget` script), then an Etalon calibration set is taken. This is a way to make use of time that would otherwise be unproductive. This etalon script also takes around 15 minutes or a bit less to complete. Once either of the two observations above has completed, the script repeats the loop as long as there is enough time before the end time to complete a SoCal observation. Once the end time has passed, the system will perform basic cleanup of KPF, then it will park SoCal using `ParkSoCal` if the park flag is set. ## Arguments * __StartTimeHST__ - `float` The time (in decimal hours HST) to begin observing. * __EndTimeHST__ - `float` The time (in decimal hours HST) to end observing. * __park__ - `bool` If True, the script will park SoCal when complete. * __scheduled__ - `bool` If True, the script will not run if the keyword `kpfconfig.ALLOWSCHEDULEDCALS` is \"No\". ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , args , logger , cfg ): # Check the ALLOWSCHEDULEDCALS value if args . get ( 'scheduled' , True ) is True : ALLOWSCHEDULED = ktl . cache ( 'kpfconfig' , 'ALLOWSCHEDULEDCALS' ) . read () if ALLOWSCHEDULED == 'No' : return log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) log . info ( '-------------------------' ) # Prepare SoCal parameters to pass to ExecuteCal socal_ND1 = cfg . get ( 'SoCal' , 'ND1' , fallback = 'OD 0.1' ) socal_ND2 = cfg . get ( 'SoCal' , 'ND2' , fallback = 'OD 0.1' ) socal_ExpTime = cfg . getfloat ( 'SoCal' , 'ExpTime' , fallback = 12 ) SoCal_observation = { 'Template_Name' : 'kpf_lamp' , 'Template_Version' : '1.0' , 'TargetName' : 'Sun' , 'TriggerCaHK' : False , 'TimedShutter_CaHK' : False , 'TriggerGreen' : True , 'TriggerRed' : True , 'TriggerExpMeter' : False , 'RunAgitator' : True , 'CalSource' : 'SoCal-SciSky' , 'Object' : 'SoCal' , 'CalND1' : socal_ND1 , 'CalND2' : socal_ND2 , 'ExpTime' : socal_ExpTime , 'nExp' : 15 , 'SSS_Science' : True , 'SSS_Sky' : True , 'TakeSimulCal' : True , 'nointensemon' : True , } readout_red = cfg . getfloat ( 'time_estimates' , f 'readout_red' , fallback = 60 ) readout_green = cfg . getfloat ( 'time_estimates' , f 'readout_green' , fallback = 60 ) readout_cahk = cfg . getfloat ( 'time_estimates' , 'readout_cahk' , fallback = 1 ) archon_time_shim = cfg . getfloat ( 'times' , 'archon_temperature_time_shim' , fallback = 2 ) readout = max ([ readout_red , readout_green , readout_cahk ]) SoCal_duration = int ( SoCal_observation [ 'nExp' ]) * max ([ float ( SoCal_observation [ 'ExpTime' ]), archon_time_shim ]) SoCal_duration += int ( SoCal_observation [ 'nExp' ]) * readout log . debug ( f \"Estimated SoCal observation time = { SoCal_duration } \" ) # Prepare Etalon parameters to pass to ExecuteCal Etalon_ND1 = cfg . get ( 'SoCal' , 'EtalonND1' , fallback = 'OD 0.1' ) Etalon_ND2 = cfg . get ( 'SoCal' , 'EtalonND2' , fallback = 'OD 0.1' ) Etalon_ExpTime = cfg . getfloat ( 'SoCal' , 'EtalonExpTime' , fallback = 60 ) Etalon_observation = { 'Template_Name' : 'kpf_lamp' , 'Template_Version' : '1.0' , 'TriggerCaHK' : True , 'TimedShutter_CaHK' : True , 'TriggerGreen' : True , 'TriggerRed' : True , 'TriggerExpMeter' : False , 'RunAgitator' : True , 'CalSource' : 'EtalonFiber' , 'Object' : 'slewcal' , 'CalND1' : Etalon_ND1 , 'CalND2' : Etalon_ND2 , 'ExpTime' : Etalon_ExpTime , 'nExp' : 8 , 'SSS_Science' : True , 'SSS_Sky' : True , 'TakeSimulCal' : True , 'nointensemon' : True , } Etalon_duration = int ( Etalon_observation [ 'nExp' ]) * max ([ float ( Etalon_observation [ 'ExpTime' ]), archon_time_shim ]) Etalon_duration += int ( Etalon_observation [ 'nExp' ]) * readout log . debug ( f \"Estimated Etalon observation time = { Etalon_duration } \" ) # Start SoCal in autonomous mode SoCalStartAutonomous . execute ({}) # Start Loop max_wait_per_iteration = 60 start_time = args . get ( 'StartTimeHST' , 9 ) end_time = args . get ( 'EndTimeHST' , 12 ) - SoCal_duration / 3600 - 0.05 now = datetime . datetime . now () now_decimal = ( now . hour + now . minute / 60 + now . second / 3600 ) if now_decimal < start_time : wait = ( start_time - now_decimal ) * 3600 log . info ( f 'Waiting { wait : .0f } s for SoCal window start time' ) time . sleep ( wait ) elif now_decimal > end_time : log . info ( \"End time for today's SoCal window has passed\" ) return SCRIPTPID = ktl . cache ( 'kpfconfig' , 'SCRIPTPID' ) if SCRIPTPID . read ( binary = True ) >= 0 : SCRIPTNAME = ktl . cache ( 'kpfconfig' , 'SCRIPTNAME' ) . read () waittime = ( end_time - now_decimal ) * 3600 - SoCal_duration - 180 log . warning ( f 'Script is currently running: { SCRIPTNAME } ' ) if waittime > 0 : log . info ( f 'Waiting up to { waittime : .0f } s for running script to end' ) SCRIPTPID . waitFor ( \"==-1\" , timeout = waittime ) time . sleep ( 10 ) # time shim check_script_running () set_script_keywords ( Path ( __file__ ) . name , os . getpid ()) log . info ( f 'Starting SoCal observation loop' ) log . info ( f 'Start time: { start_time : .2f } HST' ) log . info ( f 'End Time: { end_time : .2f } HST' ) check_scriptstop () nSoCalObs = 0 nEtalonObs = 0 now = datetime . datetime . now () now_decimal = ( now . hour + now . minute / 60 + now . second / 3600 ) while now_decimal >= start_time and now_decimal < end_time : log . debug ( 'Checking if SoCal is on the Sun' ) on_target = WaitForSoCalOnTarget . execute ({ 'timeout' : max_wait_per_iteration }) observation = { True : SoCal_observation , False : Etalon_observation }[ on_target ] log . info ( f 'SoCal on target: { on_target } ' ) log . info ( f \"Executing { observation [ 'Object' ] } \" ) try : check_scriptstop () ExecuteCal . execute ( observation ) if on_target == True : nSoCalObs += 1 else : nEtalonObs += 1 except ScriptStopTriggered as e : raise e except Exception as e : log . error ( \"ExecuteCal failed:\" ) log . error ( e ) traceback_text = traceback . format_exc () log . error ( traceback_text ) # Email error to kpf_info if not isinstance ( e , ScriptStopTriggered ): try : msg = [ f ' { type ( e ) } ' , f ' { traceback . format_exc () } ' , '' , f ' { OB } ' ] SendEmail . execute ({ 'Subject' : 'ExecuteCals Failed' , 'Message' : ' \\n ' . join ( msg )}) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) check_scriptstop () # Update loop inputs now = datetime . datetime . now () now_decimal = ( now . hour + now . minute / 60 + now . second / 3600 ) log . info ( 'SoCal observation loop completed' ) log . info ( f 'Executed { nSoCalObs } SoCal sequences' ) log . info ( f 'Executed { nEtalonObs } Etalon sequences' ) # Cleanup try : CleanupAfterCalibrations . execute ( Etalon_observation ) except Exception as e : log . error ( \"CleanupAfterCalibrations failed:\" ) log . error ( e ) traceback_text = traceback . format_exc () log . error ( traceback_text ) clear_script_keywords () # Email error to kpf_info try : msg = [ f ' { type ( e ) } ' , f ' { traceback_text } ' , '' , f ' { OB } ' ] SendEmail . execute ({ 'Subject' : 'CleanupAfterCalibrations Failed' , 'Message' : ' \\n ' . join ( msg )}) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) # Park SoCal? if args . get ( 'park' , False ) == True : ParkSoCal . execute ({}) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'StartTimeHST' , type = float , help = 'Start of daily observing window in decimal hours HST.' ) parser . add_argument ( 'EndTimeHST' , type = float , help = 'End of daily observing window in decimal hours HST.' ) parser . add_argument ( \"--park\" , dest = \"park\" , default = False , action = \"store_true\" , help = \"Close and park SoCal when done?\" ) parser . add_argument ( \"--notscheduled\" , dest = \"scheduled\" , default = True , action = \"store_false\" , help = \"Do not respect the kpfconfig.ALLOWSCHEDULEDCALS flag.\" ) return super () . add_cmdline_args ( parser , cfg )","title":"RunSoCalObservingLoop"},{"location":"scripts/RunSoCalObservingLoop/#runsocalobservingloop","text":"Bases: KPFTranslatorFunction This script runs a control loop to execute SoCal observations. When the script is invoked, it puts SoCal in AUTONOMOUS mode. This means that the SoCal dispatcher number 4 will handle opening the enclosure, acquiring and tracking the Sun, and will perform a weather safety shutdown if needed. The AUTONOMOUS mode will respect the CAN_OPEN keyword as well, so that keyword will lock out SoCal motions if that is desired. The script takes two required inputs: a start and end time in decimal hours (in HST). The start time can be after the invocation of this script. This is in fact the recommended operational strategy as the SoCal AUTONOMOUS mode will then have time to open and acquire the Sun before observations start. If needed, the script will wait until the start time before taking further actions (beyond setting AUTONOMOUS). Once the start time has passed, the script will check the kpfconfig.SCRIPT% keywords to see if something is currently running. If so, it will wait for the script keywords to clear before starting operations. Next the script will try to determine if SoCal is successfully observing the Sun by invoking the WaitForSoCalOnTarget script. If SoCal is on target, then a short observation of the Sun is performed. Some of the parameters can be modified in the KPFTranslator configuration file ( kpf_inst_config.ini ). This observation, as currently configured, takes about 15 minutes to complete. If SoCal is not on target (according to the WaitForSoCalOnTarget script), then an Etalon calibration set is taken. This is a way to make use of time that would otherwise be unproductive. This etalon script also takes around 15 minutes or a bit less to complete. Once either of the two observations above has completed, the script repeats the loop as long as there is enough time before the end time to complete a SoCal observation. Once the end time has passed, the system will perform basic cleanup of KPF, then it will park SoCal using ParkSoCal if the park flag is set.","title":"RunSoCalObservingLoop"},{"location":"scripts/RunSoCalObservingLoop/#kpf.scripts.RunSoCalObservingLoop.RunSoCalObservingLoop--arguments","text":"StartTimeHST - float The time (in decimal hours HST) to begin observing. EndTimeHST - float The time (in decimal hours HST) to end observing. park - bool If True, the script will park SoCal when complete. scheduled - bool If True, the script will not run if the keyword kpfconfig.ALLOWSCHEDULEDCALS is \"No\". Source code in kpf/scripts/RunSoCalObservingLoop.py 23 24 25 26 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 class RunSoCalObservingLoop ( KPFTranslatorFunction ): '''This script runs a control loop to execute SoCal observations. When the script is invoked, it puts SoCal in AUTONOMOUS mode. This means that the SoCal dispatcher number 4 will handle opening the enclosure, acquiring and tracking the Sun, and will perform a weather safety shutdown if needed. The AUTONOMOUS mode will respect the CAN_OPEN keyword as well, so that keyword will lock out SoCal motions if that is desired. The script takes two required inputs: a start and end time in decimal hours (in HST). The start time can be after the invocation of this script. This is in fact the recommended operational strategy as the SoCal AUTONOMOUS mode will then have time to open and acquire the Sun before observations start. If needed, the script will wait until the start time before taking further actions (beyond setting AUTONOMOUS). Once the start time has passed, the script will check the `kpfconfig.SCRIPT%` keywords to see if something is currently running. If so, it will wait for the script keywords to clear before starting operations. Next the script will try to determine if SoCal is successfully observing the Sun by invoking the `WaitForSoCalOnTarget` script. If SoCal is on target, then a short observation of the Sun is performed. Some of the parameters can be modified in the `KPFTranslator` configuration file (`kpf_inst_config.ini`). This observation, as currently configured, takes about 15 minutes to complete. If SoCal is not on target (according to the `WaitForSoCalOnTarget` script), then an Etalon calibration set is taken. This is a way to make use of time that would otherwise be unproductive. This etalon script also takes around 15 minutes or a bit less to complete. Once either of the two observations above has completed, the script repeats the loop as long as there is enough time before the end time to complete a SoCal observation. Once the end time has passed, the system will perform basic cleanup of KPF, then it will park SoCal using `ParkSoCal` if the park flag is set. ## Arguments * __StartTimeHST__ - `float` The time (in decimal hours HST) to begin observing. * __EndTimeHST__ - `float` The time (in decimal hours HST) to end observing. * __park__ - `bool` If True, the script will park SoCal when complete. * __scheduled__ - `bool` If True, the script will not run if the keyword `kpfconfig.ALLOWSCHEDULEDCALS` is \"No\". ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , args , logger , cfg ): # Check the ALLOWSCHEDULEDCALS value if args . get ( 'scheduled' , True ) is True : ALLOWSCHEDULED = ktl . cache ( 'kpfconfig' , 'ALLOWSCHEDULEDCALS' ) . read () if ALLOWSCHEDULED == 'No' : return log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) log . info ( '-------------------------' ) # Prepare SoCal parameters to pass to ExecuteCal socal_ND1 = cfg . get ( 'SoCal' , 'ND1' , fallback = 'OD 0.1' ) socal_ND2 = cfg . get ( 'SoCal' , 'ND2' , fallback = 'OD 0.1' ) socal_ExpTime = cfg . getfloat ( 'SoCal' , 'ExpTime' , fallback = 12 ) SoCal_observation = { 'Template_Name' : 'kpf_lamp' , 'Template_Version' : '1.0' , 'TargetName' : 'Sun' , 'TriggerCaHK' : False , 'TimedShutter_CaHK' : False , 'TriggerGreen' : True , 'TriggerRed' : True , 'TriggerExpMeter' : False , 'RunAgitator' : True , 'CalSource' : 'SoCal-SciSky' , 'Object' : 'SoCal' , 'CalND1' : socal_ND1 , 'CalND2' : socal_ND2 , 'ExpTime' : socal_ExpTime , 'nExp' : 15 , 'SSS_Science' : True , 'SSS_Sky' : True , 'TakeSimulCal' : True , 'nointensemon' : True , } readout_red = cfg . getfloat ( 'time_estimates' , f 'readout_red' , fallback = 60 ) readout_green = cfg . getfloat ( 'time_estimates' , f 'readout_green' , fallback = 60 ) readout_cahk = cfg . getfloat ( 'time_estimates' , 'readout_cahk' , fallback = 1 ) archon_time_shim = cfg . getfloat ( 'times' , 'archon_temperature_time_shim' , fallback = 2 ) readout = max ([ readout_red , readout_green , readout_cahk ]) SoCal_duration = int ( SoCal_observation [ 'nExp' ]) * max ([ float ( SoCal_observation [ 'ExpTime' ]), archon_time_shim ]) SoCal_duration += int ( SoCal_observation [ 'nExp' ]) * readout log . debug ( f \"Estimated SoCal observation time = { SoCal_duration } \" ) # Prepare Etalon parameters to pass to ExecuteCal Etalon_ND1 = cfg . get ( 'SoCal' , 'EtalonND1' , fallback = 'OD 0.1' ) Etalon_ND2 = cfg . get ( 'SoCal' , 'EtalonND2' , fallback = 'OD 0.1' ) Etalon_ExpTime = cfg . getfloat ( 'SoCal' , 'EtalonExpTime' , fallback = 60 ) Etalon_observation = { 'Template_Name' : 'kpf_lamp' , 'Template_Version' : '1.0' , 'TriggerCaHK' : True , 'TimedShutter_CaHK' : True , 'TriggerGreen' : True , 'TriggerRed' : True , 'TriggerExpMeter' : False , 'RunAgitator' : True , 'CalSource' : 'EtalonFiber' , 'Object' : 'slewcal' , 'CalND1' : Etalon_ND1 , 'CalND2' : Etalon_ND2 , 'ExpTime' : Etalon_ExpTime , 'nExp' : 8 , 'SSS_Science' : True , 'SSS_Sky' : True , 'TakeSimulCal' : True , 'nointensemon' : True , } Etalon_duration = int ( Etalon_observation [ 'nExp' ]) * max ([ float ( Etalon_observation [ 'ExpTime' ]), archon_time_shim ]) Etalon_duration += int ( Etalon_observation [ 'nExp' ]) * readout log . debug ( f \"Estimated Etalon observation time = { Etalon_duration } \" ) # Start SoCal in autonomous mode SoCalStartAutonomous . execute ({}) # Start Loop max_wait_per_iteration = 60 start_time = args . get ( 'StartTimeHST' , 9 ) end_time = args . get ( 'EndTimeHST' , 12 ) - SoCal_duration / 3600 - 0.05 now = datetime . datetime . now () now_decimal = ( now . hour + now . minute / 60 + now . second / 3600 ) if now_decimal < start_time : wait = ( start_time - now_decimal ) * 3600 log . info ( f 'Waiting { wait : .0f } s for SoCal window start time' ) time . sleep ( wait ) elif now_decimal > end_time : log . info ( \"End time for today's SoCal window has passed\" ) return SCRIPTPID = ktl . cache ( 'kpfconfig' , 'SCRIPTPID' ) if SCRIPTPID . read ( binary = True ) >= 0 : SCRIPTNAME = ktl . cache ( 'kpfconfig' , 'SCRIPTNAME' ) . read () waittime = ( end_time - now_decimal ) * 3600 - SoCal_duration - 180 log . warning ( f 'Script is currently running: { SCRIPTNAME } ' ) if waittime > 0 : log . info ( f 'Waiting up to { waittime : .0f } s for running script to end' ) SCRIPTPID . waitFor ( \"==-1\" , timeout = waittime ) time . sleep ( 10 ) # time shim check_script_running () set_script_keywords ( Path ( __file__ ) . name , os . getpid ()) log . info ( f 'Starting SoCal observation loop' ) log . info ( f 'Start time: { start_time : .2f } HST' ) log . info ( f 'End Time: { end_time : .2f } HST' ) check_scriptstop () nSoCalObs = 0 nEtalonObs = 0 now = datetime . datetime . now () now_decimal = ( now . hour + now . minute / 60 + now . second / 3600 ) while now_decimal >= start_time and now_decimal < end_time : log . debug ( 'Checking if SoCal is on the Sun' ) on_target = WaitForSoCalOnTarget . execute ({ 'timeout' : max_wait_per_iteration }) observation = { True : SoCal_observation , False : Etalon_observation }[ on_target ] log . info ( f 'SoCal on target: { on_target } ' ) log . info ( f \"Executing { observation [ 'Object' ] } \" ) try : check_scriptstop () ExecuteCal . execute ( observation ) if on_target == True : nSoCalObs += 1 else : nEtalonObs += 1 except ScriptStopTriggered as e : raise e except Exception as e : log . error ( \"ExecuteCal failed:\" ) log . error ( e ) traceback_text = traceback . format_exc () log . error ( traceback_text ) # Email error to kpf_info if not isinstance ( e , ScriptStopTriggered ): try : msg = [ f ' { type ( e ) } ' , f ' { traceback . format_exc () } ' , '' , f ' { OB } ' ] SendEmail . execute ({ 'Subject' : 'ExecuteCals Failed' , 'Message' : ' \\n ' . join ( msg )}) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) check_scriptstop () # Update loop inputs now = datetime . datetime . now () now_decimal = ( now . hour + now . minute / 60 + now . second / 3600 ) log . info ( 'SoCal observation loop completed' ) log . info ( f 'Executed { nSoCalObs } SoCal sequences' ) log . info ( f 'Executed { nEtalonObs } Etalon sequences' ) # Cleanup try : CleanupAfterCalibrations . execute ( Etalon_observation ) except Exception as e : log . error ( \"CleanupAfterCalibrations failed:\" ) log . error ( e ) traceback_text = traceback . format_exc () log . error ( traceback_text ) clear_script_keywords () # Email error to kpf_info try : msg = [ f ' { type ( e ) } ' , f ' { traceback_text } ' , '' , f ' { OB } ' ] SendEmail . execute ({ 'Subject' : 'CleanupAfterCalibrations Failed' , 'Message' : ' \\n ' . join ( msg )}) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) # Park SoCal? if args . get ( 'park' , False ) == True : ParkSoCal . execute ({}) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'StartTimeHST' , type = float , help = 'Start of daily observing window in decimal hours HST.' ) parser . add_argument ( 'EndTimeHST' , type = float , help = 'End of daily observing window in decimal hours HST.' ) parser . add_argument ( \"--park\" , dest = \"park\" , default = False , action = \"store_true\" , help = \"Close and park SoCal when done?\" ) parser . add_argument ( \"--notscheduled\" , dest = \"scheduled\" , default = True , action = \"store_false\" , help = \"Do not respect the kpfconfig.ALLOWSCHEDULEDCALS flag.\" ) return super () . add_cmdline_args ( parser , cfg )","title":"Arguments"},{"location":"scripts/RunTwilightRVStandard/","text":"RunTwilightRVStandard Bases: KPFTranslatorFunction Executes a twilight observation of one a selected RV standard star. This script performs all necessary instrument actions from sart up to shut down. Sequence of Actions (and who performs them) once this script is invoked: - (Script): run StartOfNight - (Script): Start Sci OB + Slew Cal - (OA): Slew to target - (OA): Perform autofoc - (Script): Obtain science data - (OA): Release to regular use, OA can park or do other tasks - (Script): run EndOfNight - (Script): run Calibration Source code in kpf/scripts/RunTwilightRVStandard.py 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 class RunTwilightRVStandard ( KPFTranslatorFunction ): '''Executes a twilight observation of one a selected RV standard star. This script performs all necessary instrument actions from sart up to shut down. Sequence of Actions (and who performs them) once this script is invoked: - (Script): run StartOfNight - (Script): Start Sci OB + Slew Cal - (OA): Slew to target - (OA): Perform autofoc - (Script): Obtain science data - (OA): Release to regular use, OA can park or do other tasks - (Script): run EndOfNight - (Script): run Calibration ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , args , logger , cfg ): # --------------------------------- # Select Target # --------------------------------- horizon = 30 * u . deg starlist_file = Path ( f '/s/sdata1701/OBs/kpftwilight/starlist.txt' ) all_targets = rank_targets ( starlist_file , horizon = horizon ) if len ( all_targets ) == 0 : log . error ( f 'No targets available above horizon ( { horizon : .1f } )' ) return targname = all_targets [ 0 ] . targname sciOBfile = starlist_file . parent / f ' { targname } .yaml' with open ( sciOBfile , 'r' ) as f : sciOB = yaml . safe_load ( f ) calOBfile = Path ( '/s/sdata1701/OBs/kpftwilight/twilight_program_cal.yaml' ) if calOBfile . exists () is False : log . error ( f \"Could not load OB file: { calOBfile } \" ) return with open ( calOBfile , 'r' ) as f : calOB = yaml . safe_load ( f ) log_string = f \"Selected: { targname } at { all_targets [ 0 ] . alt () : .1f } , \" \\ f \"priority= { all_targets [ 0 ] . priority } \" log . debug ( log_string ) if args . get ( 'test_only' , False ) is True : print ( log_string ) return # --------------------------------- # Start Of Night # --------------------------------- msg = [ \"\" , \"-------------------------------------------------------------\" , \"Thank you for executing a KPF Twilight Stability Measurement.\" , \"If you encounter urgent problems or questions contact one of\" , \"the KPF SAs. Contact info:\" , \" Josh Walawender: 808-990-4294 (cell)\" , \"\" , \"Please load the starlist at\" , f \" { starlist_file } \" , \"\" , f \"Our target will be:\" , f \" { targname } \" , \"\" , \"If the instrument has not been in use, you will presumably\" , \"need to run the Start Of Night script. This will open the AO\" , \"hatch and configure AO and KPF for observing. This is not\" , \"needed if KPF has been observing immediately prior to this.\" , \"Do you wish to run the Start Of Night Script? [Y/n]\" , \"-------------------------------------------------------------\" , \"\" , ] for line in msg : print ( line ) user_input = input () if user_input . lower () in [ 'n' , 'no' , 'cancel' ]: log . warning ( 'User opted to skip Start Of Night script' ) else : StartOfNight . execute ({}) SetProgram . execute ({ 'progname' : 'K444' }) SetObserver . execute ({ 'observer' : 'OA' }) # Wrap operations in try/except to ensure we get to end of night try : log . info ( f \"Configuring for Acquisition\" ) ConfigureForAcquisition . execute ( sciOB ) # --------------------------------- # OA Focus # --------------------------------- msg = [ \"\" , \"-------------------------------------------------------------\" , \"The instrument is being configured now, please begin slewing\" , \"to the target. Once you are on target:\" , \" - Focus on target using autfoc\" , \" - Then place the target on the KPF PO\" , \"When those steps are done, press Enter to continue.\" , \"-------------------------------------------------------------\" , \"\" , ] for line in msg : print ( line ) user_input = input () # Open an xshow for exposure status cmd = [ 'xshow' , '-s' , 'kpfexpose' , 'EXPOSE' , 'ELAPSED' , 'EXPOSURE' ] xshow_proc = subprocess . Popen ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) # --------------------------------- # Execute Observation # --------------------------------- WaitForConfigureAcquisition . execute ( sciOB ) log . info ( f \"Configuring for Science\" ) ConfigureForScience . execute ( sciOB ) WaitForConfigureScience . execute ( sciOB ) # Execute Sequences check_script_running () set_script_keywords ( Path ( __file__ ) . name , os . getpid ()) # Execute the Cal Sequence observations = sciOB . get ( 'SEQ_Observations' , []) for observation in observations : observation [ 'Template_Name' ] = 'kpf_sci' observation [ 'Template_Version' ] = sciOB [ 'Template_Version' ] observation [ 'Gmag' ] = sciOB [ 'Gmag' ] log . debug ( f \"Automatically setting TimedShutter_CaHK: { sciOB [ 'TriggerCaHK' ] } \" ) observation [ 'TimedShutter_CaHK' ] = sciOB [ 'TriggerCaHK' ] observation [ 'TriggerCaHK' ] = sciOB [ 'TriggerCaHK' ] observation [ 'TriggerGreen' ] = sciOB [ 'TriggerGreen' ] observation [ 'TriggerRed' ] = sciOB [ 'TriggerRed' ] observation [ 'TriggerGuide' ] = ( sciOB . get ( 'GuideMode' , 'off' ) != 'off' ) # Wrap in try/except so that cleanup happens try : ExecuteSci . execute ( observation ) except Exception as e : log . error ( \"ExecuteSci failed:\" ) log . error ( e ) clear_script_keywords () except Exception as e : log . error ( f 'Encountered exception during operations' ) log . error ( e ) log . error ( traceback . format_exc ()) # Cleanup CleanupAfterScience . execute ( sciOB ) # Close xshow xshow_proc . terminate () # --------------------------------- # Done with telescope # --------------------------------- log . debug ( 'Observations complete. Alerting OA.' ) msg = [ \"\" , \"-------------------------------------------------------------\" , \"Observation complete. Do you wish to run end of night and\" , \"perform a calibration set? Please answer yes if this is a\" , \"morning twilight or if some other instrument will be observing.\" , \"\" , \"Regardless of the choice below, you may perform other tasks as\" , \"needed after answering.\" , \"\" , \"Run End of Night and then start calibrations? [Y/n]\" , \"-------------------------------------------------------------\" , \"\" , ] for line in msg : print ( line ) user_input = input () if user_input . lower () in [ 'y' , 'yes' ]: EndOfNight . execute ({}) RunCalOB . execute ( calOB ) # Send email email = { 'To' : 'kpf_info@keck.hawaii.edu,ahoward@caltech.edu,sphalverson@gmail.com' , # 'To': 'jwalawender@keck.hawaii.edu', 'Subject' : 'KPF Twilight Program Completed' , 'Message' : 'A KPF twilight observation has been completed.' } SendEmail . execute ( email ) print () print ( 'Script complete.' ) time . sleep ( 120 ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( '--test' , dest = \"test_only\" , default = False , action = \"store_true\" , help = 'Only execute the target selection code' ) return super () . add_cmdline_args ( parser , cfg )","title":"RunTwilightRVStandard"},{"location":"scripts/RunTwilightRVStandard/#runtwilightrvstandard","text":"Bases: KPFTranslatorFunction Executes a twilight observation of one a selected RV standard star. This script performs all necessary instrument actions from sart up to shut down. Sequence of Actions (and who performs them) once this script is invoked: - (Script): run StartOfNight - (Script): Start Sci OB + Slew Cal - (OA): Slew to target - (OA): Perform autofoc - (Script): Obtain science data - (OA): Release to regular use, OA can park or do other tasks - (Script): run EndOfNight - (Script): run Calibration Source code in kpf/scripts/RunTwilightRVStandard.py 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 class RunTwilightRVStandard ( KPFTranslatorFunction ): '''Executes a twilight observation of one a selected RV standard star. This script performs all necessary instrument actions from sart up to shut down. Sequence of Actions (and who performs them) once this script is invoked: - (Script): run StartOfNight - (Script): Start Sci OB + Slew Cal - (OA): Slew to target - (OA): Perform autofoc - (Script): Obtain science data - (OA): Release to regular use, OA can park or do other tasks - (Script): run EndOfNight - (Script): run Calibration ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , args , logger , cfg ): # --------------------------------- # Select Target # --------------------------------- horizon = 30 * u . deg starlist_file = Path ( f '/s/sdata1701/OBs/kpftwilight/starlist.txt' ) all_targets = rank_targets ( starlist_file , horizon = horizon ) if len ( all_targets ) == 0 : log . error ( f 'No targets available above horizon ( { horizon : .1f } )' ) return targname = all_targets [ 0 ] . targname sciOBfile = starlist_file . parent / f ' { targname } .yaml' with open ( sciOBfile , 'r' ) as f : sciOB = yaml . safe_load ( f ) calOBfile = Path ( '/s/sdata1701/OBs/kpftwilight/twilight_program_cal.yaml' ) if calOBfile . exists () is False : log . error ( f \"Could not load OB file: { calOBfile } \" ) return with open ( calOBfile , 'r' ) as f : calOB = yaml . safe_load ( f ) log_string = f \"Selected: { targname } at { all_targets [ 0 ] . alt () : .1f } , \" \\ f \"priority= { all_targets [ 0 ] . priority } \" log . debug ( log_string ) if args . get ( 'test_only' , False ) is True : print ( log_string ) return # --------------------------------- # Start Of Night # --------------------------------- msg = [ \"\" , \"-------------------------------------------------------------\" , \"Thank you for executing a KPF Twilight Stability Measurement.\" , \"If you encounter urgent problems or questions contact one of\" , \"the KPF SAs. Contact info:\" , \" Josh Walawender: 808-990-4294 (cell)\" , \"\" , \"Please load the starlist at\" , f \" { starlist_file } \" , \"\" , f \"Our target will be:\" , f \" { targname } \" , \"\" , \"If the instrument has not been in use, you will presumably\" , \"need to run the Start Of Night script. This will open the AO\" , \"hatch and configure AO and KPF for observing. This is not\" , \"needed if KPF has been observing immediately prior to this.\" , \"Do you wish to run the Start Of Night Script? [Y/n]\" , \"-------------------------------------------------------------\" , \"\" , ] for line in msg : print ( line ) user_input = input () if user_input . lower () in [ 'n' , 'no' , 'cancel' ]: log . warning ( 'User opted to skip Start Of Night script' ) else : StartOfNight . execute ({}) SetProgram . execute ({ 'progname' : 'K444' }) SetObserver . execute ({ 'observer' : 'OA' }) # Wrap operations in try/except to ensure we get to end of night try : log . info ( f \"Configuring for Acquisition\" ) ConfigureForAcquisition . execute ( sciOB ) # --------------------------------- # OA Focus # --------------------------------- msg = [ \"\" , \"-------------------------------------------------------------\" , \"The instrument is being configured now, please begin slewing\" , \"to the target. Once you are on target:\" , \" - Focus on target using autfoc\" , \" - Then place the target on the KPF PO\" , \"When those steps are done, press Enter to continue.\" , \"-------------------------------------------------------------\" , \"\" , ] for line in msg : print ( line ) user_input = input () # Open an xshow for exposure status cmd = [ 'xshow' , '-s' , 'kpfexpose' , 'EXPOSE' , 'ELAPSED' , 'EXPOSURE' ] xshow_proc = subprocess . Popen ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) # --------------------------------- # Execute Observation # --------------------------------- WaitForConfigureAcquisition . execute ( sciOB ) log . info ( f \"Configuring for Science\" ) ConfigureForScience . execute ( sciOB ) WaitForConfigureScience . execute ( sciOB ) # Execute Sequences check_script_running () set_script_keywords ( Path ( __file__ ) . name , os . getpid ()) # Execute the Cal Sequence observations = sciOB . get ( 'SEQ_Observations' , []) for observation in observations : observation [ 'Template_Name' ] = 'kpf_sci' observation [ 'Template_Version' ] = sciOB [ 'Template_Version' ] observation [ 'Gmag' ] = sciOB [ 'Gmag' ] log . debug ( f \"Automatically setting TimedShutter_CaHK: { sciOB [ 'TriggerCaHK' ] } \" ) observation [ 'TimedShutter_CaHK' ] = sciOB [ 'TriggerCaHK' ] observation [ 'TriggerCaHK' ] = sciOB [ 'TriggerCaHK' ] observation [ 'TriggerGreen' ] = sciOB [ 'TriggerGreen' ] observation [ 'TriggerRed' ] = sciOB [ 'TriggerRed' ] observation [ 'TriggerGuide' ] = ( sciOB . get ( 'GuideMode' , 'off' ) != 'off' ) # Wrap in try/except so that cleanup happens try : ExecuteSci . execute ( observation ) except Exception as e : log . error ( \"ExecuteSci failed:\" ) log . error ( e ) clear_script_keywords () except Exception as e : log . error ( f 'Encountered exception during operations' ) log . error ( e ) log . error ( traceback . format_exc ()) # Cleanup CleanupAfterScience . execute ( sciOB ) # Close xshow xshow_proc . terminate () # --------------------------------- # Done with telescope # --------------------------------- log . debug ( 'Observations complete. Alerting OA.' ) msg = [ \"\" , \"-------------------------------------------------------------\" , \"Observation complete. Do you wish to run end of night and\" , \"perform a calibration set? Please answer yes if this is a\" , \"morning twilight or if some other instrument will be observing.\" , \"\" , \"Regardless of the choice below, you may perform other tasks as\" , \"needed after answering.\" , \"\" , \"Run End of Night and then start calibrations? [Y/n]\" , \"-------------------------------------------------------------\" , \"\" , ] for line in msg : print ( line ) user_input = input () if user_input . lower () in [ 'y' , 'yes' ]: EndOfNight . execute ({}) RunCalOB . execute ( calOB ) # Send email email = { 'To' : 'kpf_info@keck.hawaii.edu,ahoward@caltech.edu,sphalverson@gmail.com' , # 'To': 'jwalawender@keck.hawaii.edu', 'Subject' : 'KPF Twilight Program Completed' , 'Message' : 'A KPF twilight observation has been completed.' } SendEmail . execute ( email ) print () print ( 'Script complete.' ) time . sleep ( 120 ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( '--test' , dest = \"test_only\" , default = False , action = \"store_true\" , help = 'Only execute the target selection code' ) return super () . add_cmdline_args ( parser , cfg )","title":"RunTwilightRVStandard"},{"location":"scripts/SendPCUtoHome/","text":"SendPCUtoHome Bases: KPFTranslatorFunction Send the PCU stage to the \"home\" named position. KTL Keywords Used: ao.PCSFNAME ao.PCSFSTST Source code in kpf/ao/SendPCUtoHome.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 class SendPCUtoHome ( KPFTranslatorFunction ): '''Send the PCU stage to the \"home\" named position. KTL Keywords Used: - `ao.PCSFNAME` - `ao.PCSFSTST` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): PCSFSTST = ktl . cache ( 'ao' , 'PCSFSTST' ) success = PCSFSTST . waitFor ( '!= \"FAULT\"' ) if success is not True : raise FailedPreCondition ( 'PCSFSTST is faulted' ) @classmethod def perform ( cls , args , logger , cfg ): PCSstagekw = ktl . cache ( 'ao' , 'PCSFNAME' ) log . info ( f \"Sending PCU to Home\" ) PCSstagekw . write ( 'home' ) shim_time = cfg . getfloat ( 'times' , 'ao_pcu_shim_time' , fallback = 5 ) time . sleep ( shim_time ) @classmethod def post_condition ( cls , args , logger , cfg ): PCSstagekw = ktl . cache ( 'ao' , 'PCSFSTST' ) timeout = cfg . getfloat ( 'times' , 'ao_pcu_move_time' , fallback = 150 ) success = PCSstagekw . waitfor ( \"== INPOS\" , timeout = timeout ) if success is False : raise FailedToReachDestination ( PCSstagekw . read (), 'home' )","title":"SendPCUtoHome"},{"location":"scripts/SendPCUtoHome/#sendpcutohome","text":"Bases: KPFTranslatorFunction Send the PCU stage to the \"home\" named position. KTL Keywords Used: ao.PCSFNAME ao.PCSFSTST Source code in kpf/ao/SendPCUtoHome.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 class SendPCUtoHome ( KPFTranslatorFunction ): '''Send the PCU stage to the \"home\" named position. KTL Keywords Used: - `ao.PCSFNAME` - `ao.PCSFSTST` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): PCSFSTST = ktl . cache ( 'ao' , 'PCSFSTST' ) success = PCSFSTST . waitFor ( '!= \"FAULT\"' ) if success is not True : raise FailedPreCondition ( 'PCSFSTST is faulted' ) @classmethod def perform ( cls , args , logger , cfg ): PCSstagekw = ktl . cache ( 'ao' , 'PCSFNAME' ) log . info ( f \"Sending PCU to Home\" ) PCSstagekw . write ( 'home' ) shim_time = cfg . getfloat ( 'times' , 'ao_pcu_shim_time' , fallback = 5 ) time . sleep ( shim_time ) @classmethod def post_condition ( cls , args , logger , cfg ): PCSstagekw = ktl . cache ( 'ao' , 'PCSFSTST' ) timeout = cfg . getfloat ( 'times' , 'ao_pcu_move_time' , fallback = 150 ) success = PCSstagekw . waitfor ( \"== INPOS\" , timeout = timeout ) if success is False : raise FailedToReachDestination ( PCSstagekw . read (), 'home' )","title":"SendPCUtoHome"},{"location":"scripts/SendPCUtoKPF/","text":"SendPCUtoKPF Bases: KPFTranslatorFunction Send the PCU stage to the \"kpf\" named position. KTL Keywords Used: ao.PCSFNAME ao.PCSFSTST Source code in kpf/ao/SendPCUtoKPF.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 class SendPCUtoKPF ( KPFTranslatorFunction ): '''Send the PCU stage to the \"kpf\" named position. KTL Keywords Used: - `ao.PCSFNAME` - `ao.PCSFSTST` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) success = ao [ 'PCSFSTST' ] . waitFor ( '!= \"FAULT\"' ) if success is not True : raise FailedPreCondition ( 'PCSFSTST is faulted' ) success = ktl . waitfor ( \"($ao.PCSFSTST == INPOS)\" , timeout = 120 ) if success is False : raise FailedPreCondition ( 'PCU is in motion' ) success = ktl . waitfor ( \"($ao.PCSFNAME == home)\" , timeout = 120 ) if success is False : raise FailedPreCondition ( 'PCU must be at home before moving to KPF' ) @classmethod def perform ( cls , args , logger , cfg ): PCSstagekw = ktl . cache ( 'ao' , 'PCSFNAME' ) log . info ( f \"Sending PCU to KPF\" ) PCSstagekw . write ( 'kpf' ) shim_time = cfg . getfloat ( 'times' , 'ao_pcu_shim_time' , fallback = 5 ) time . sleep ( shim_time ) @classmethod def post_condition ( cls , args , logger , cfg ): PCSstagekw = ktl . cache ( 'ao' , 'PCSFSTST' ) timeout = cfg . getfloat ( 'times' , 'ao_pcu_move_time' , fallback = 150 ) success = PCSstagekw . waitfor ( \"== INPOS\" , timeout = timeout ) if success is False : raise FailedToReachDestination ( PCSstagekw . read (), 'kpf' )","title":"SendPCUtoKPF"},{"location":"scripts/SendPCUtoKPF/#sendpcutokpf","text":"Bases: KPFTranslatorFunction Send the PCU stage to the \"kpf\" named position. KTL Keywords Used: ao.PCSFNAME ao.PCSFSTST Source code in kpf/ao/SendPCUtoKPF.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 class SendPCUtoKPF ( KPFTranslatorFunction ): '''Send the PCU stage to the \"kpf\" named position. KTL Keywords Used: - `ao.PCSFNAME` - `ao.PCSFSTST` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) success = ao [ 'PCSFSTST' ] . waitFor ( '!= \"FAULT\"' ) if success is not True : raise FailedPreCondition ( 'PCSFSTST is faulted' ) success = ktl . waitfor ( \"($ao.PCSFSTST == INPOS)\" , timeout = 120 ) if success is False : raise FailedPreCondition ( 'PCU is in motion' ) success = ktl . waitfor ( \"($ao.PCSFNAME == home)\" , timeout = 120 ) if success is False : raise FailedPreCondition ( 'PCU must be at home before moving to KPF' ) @classmethod def perform ( cls , args , logger , cfg ): PCSstagekw = ktl . cache ( 'ao' , 'PCSFNAME' ) log . info ( f \"Sending PCU to KPF\" ) PCSstagekw . write ( 'kpf' ) shim_time = cfg . getfloat ( 'times' , 'ao_pcu_shim_time' , fallback = 5 ) time . sleep ( shim_time ) @classmethod def post_condition ( cls , args , logger , cfg ): PCSstagekw = ktl . cache ( 'ao' , 'PCSFSTST' ) timeout = cfg . getfloat ( 'times' , 'ao_pcu_move_time' , fallback = 150 ) success = PCSstagekw . waitfor ( \"== INPOS\" , timeout = timeout ) if success is False : raise FailedToReachDestination ( PCSstagekw . read (), 'kpf' )","title":"SendPCUtoKPF"},{"location":"scripts/SetADCAngles/","text":"SetADCAngles Bases: KPFTranslatorFunction Quick and dirty code to manually set ADC angles for a notional NULL position. KTL Keywords Used: kpffiu.ADC1VAL kpffiu.ADC2VAL Source code in kpf/fiu/SetADCAngles.py 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 class SetADCAngles ( KPFTranslatorFunction ): '''Quick and dirty code to manually set ADC angles for a notional NULL position. KTL Keywords Used: - `kpffiu.ADC1VAL` - `kpffiu.ADC2VAL` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpffiu = ktl . cache ( 'kpffiu' ) el = args . get ( 'EL' ) za = 90 - el ADC_delta = calculate_ADC_delta ( za ) log . info ( f \"ADC Hack: za= { za : .1f } , ADC_delta= { ADC_delta : .1f } \" ) # Constants common_angle = 60 ADC1_offset = - 5 ADC2_offset = 5 log . debug ( f \"ADC Hack: common_angle= { common_angle : .1f } \" ) log . debug ( f \"ADC Hack: ADC1_offset= { ADC1_offset : .1f } \" ) log . debug ( f \"ADC Hack: ADC2_offset= { ADC2_offset : .1f } \" ) # Calculations ADC1 = common_angle + ADC1_offset + za - ADC_delta ADC2 = common_angle + ADC2_offset - za - ADC_delta log . info ( f \"ADC Hack: Writing ADC1VAL= { ADC1 : .1f } , ADC2VAL= { ADC2 : .1f } \" ) kpffiu [ 'ADC1VAL' ] . write ( ADC1 ) kpffiu [ 'ADC2VAL' ] . write ( ADC2 ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'EL' , type = float , help = \"The telescope elevation to use in the calculation\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetADCAngles"},{"location":"scripts/SetADCAngles/#setadcangles","text":"Bases: KPFTranslatorFunction Quick and dirty code to manually set ADC angles for a notional NULL position. KTL Keywords Used: kpffiu.ADC1VAL kpffiu.ADC2VAL Source code in kpf/fiu/SetADCAngles.py 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 class SetADCAngles ( KPFTranslatorFunction ): '''Quick and dirty code to manually set ADC angles for a notional NULL position. KTL Keywords Used: - `kpffiu.ADC1VAL` - `kpffiu.ADC2VAL` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpffiu = ktl . cache ( 'kpffiu' ) el = args . get ( 'EL' ) za = 90 - el ADC_delta = calculate_ADC_delta ( za ) log . info ( f \"ADC Hack: za= { za : .1f } , ADC_delta= { ADC_delta : .1f } \" ) # Constants common_angle = 60 ADC1_offset = - 5 ADC2_offset = 5 log . debug ( f \"ADC Hack: common_angle= { common_angle : .1f } \" ) log . debug ( f \"ADC Hack: ADC1_offset= { ADC1_offset : .1f } \" ) log . debug ( f \"ADC Hack: ADC2_offset= { ADC2_offset : .1f } \" ) # Calculations ADC1 = common_angle + ADC1_offset + za - ADC_delta ADC2 = common_angle + ADC2_offset - za - ADC_delta log . info ( f \"ADC Hack: Writing ADC1VAL= { ADC1 : .1f } , ADC2VAL= { ADC2 : .1f } \" ) kpffiu [ 'ADC1VAL' ] . write ( ADC1 ) kpffiu [ 'ADC2VAL' ] . write ( ADC2 ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'EL' , type = float , help = \"The telescope elevation to use in the calculation\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetADCAngles"},{"location":"scripts/SetADCOffsets/","text":"SetADCOffsets Bases: KPFTranslatorFunction Quick and dirty code to manually set ADC angles to prescribed offsets from nominal based on the telescope position. Parameters: ADC1OFF ( float ) \u2013 Offset for ADC1 (in degrees). ADC2OFF ( float ) \u2013 Offset for ADC2 (in degrees). KTL Keywords Used: kpffiu.ADC1VAL kpffiu.ADC2VAL kpffiu.ADCTRACK kpffiu.ADCPRISMS Source code in kpf/fiu/SetADCOffsets.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetADCOffsets ( KPFTranslatorFunction ): '''Quick and dirty code to manually set ADC angles to prescribed offsets from nominal based on the telescope position. Args: ADC1OFF (float): Offset for ADC1 (in degrees). ADC2OFF (float): Offset for ADC2 (in degrees). KTL Keywords Used: - `kpffiu.ADC1VAL` - `kpffiu.ADC2VAL` - `kpffiu.ADCTRACK` - `kpffiu.ADCPRISMS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpffiu = ktl . cache ( 'kpffiu' ) if kpffiu [ 'ADCTRACK' ] . read () == 'On' : log . info ( f 'Setting ADCTRACK to Off' ) kpffiu [ 'ADCTRACK' ] . write ( 'Off' ) time . sleep ( 1 ) ADC1_nominal , ADC2_nominal = kpffiu [ 'ADCPRISMS' ] . read ( binary = True ) ADC1 = ADC1_nominal + args . get ( 'ADC1OFF' ) ADC2 = ADC2_nominal + args . get ( 'ADC2OFF' ) log . info ( f \"Setting ADC to offset angles: ADC1VAL= { ADC1 : .1f } , ADC2VAL= { ADC2 : .1f } \" ) kpffiu [ 'ADC1VAL' ] . write ( ADC1 ) kpffiu [ 'ADC2VAL' ] . write ( ADC2 ) @classmethod def post_condition ( cls , args , logger , cfg ): kpffiu = ktl . cache ( 'kpffiu' ) tol = 0.1 ADC1_nominal , ADC2_nominal = kpffiu [ 'ADCPRISMS' ] . read ( binary = True ) adc1targ = ADC1_nominal + args . get ( 'ADC1OFF' ) adc2targ = ADC2_nominal + args . get ( 'ADC2OFF' ) expr = ( f \"($kpffiu.ADC1VAL > { adc1targ - tol } ) \" f \"and ($kpffiu.ADC1VAL < { adc1targ + tol } ) \" f \"and ($kpffiu.ADC2VAL > { adc2targ - tol } ) \" f \"and ($kpffiu.ADC2VAL < { adc2targ + tol } )\" ) success = ktl . waitFor ( expr , timeout = 20 ) if success is False : raise FailedPostCondition ( 'ADC Prisms did not reach destination angles' ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'ADC1OFF' , type = float , help = \"Offset for ADC1 (in degrees)\" ) parser . add_argument ( 'ADC2OFF' , type = float , help = \"Offset for ADC2 (in degrees)\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetADCOffsets"},{"location":"scripts/SetADCOffsets/#setadcoffsets","text":"Bases: KPFTranslatorFunction Quick and dirty code to manually set ADC angles to prescribed offsets from nominal based on the telescope position. Parameters: ADC1OFF ( float ) \u2013 Offset for ADC1 (in degrees). ADC2OFF ( float ) \u2013 Offset for ADC2 (in degrees). KTL Keywords Used: kpffiu.ADC1VAL kpffiu.ADC2VAL kpffiu.ADCTRACK kpffiu.ADCPRISMS Source code in kpf/fiu/SetADCOffsets.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetADCOffsets ( KPFTranslatorFunction ): '''Quick and dirty code to manually set ADC angles to prescribed offsets from nominal based on the telescope position. Args: ADC1OFF (float): Offset for ADC1 (in degrees). ADC2OFF (float): Offset for ADC2 (in degrees). KTL Keywords Used: - `kpffiu.ADC1VAL` - `kpffiu.ADC2VAL` - `kpffiu.ADCTRACK` - `kpffiu.ADCPRISMS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpffiu = ktl . cache ( 'kpffiu' ) if kpffiu [ 'ADCTRACK' ] . read () == 'On' : log . info ( f 'Setting ADCTRACK to Off' ) kpffiu [ 'ADCTRACK' ] . write ( 'Off' ) time . sleep ( 1 ) ADC1_nominal , ADC2_nominal = kpffiu [ 'ADCPRISMS' ] . read ( binary = True ) ADC1 = ADC1_nominal + args . get ( 'ADC1OFF' ) ADC2 = ADC2_nominal + args . get ( 'ADC2OFF' ) log . info ( f \"Setting ADC to offset angles: ADC1VAL= { ADC1 : .1f } , ADC2VAL= { ADC2 : .1f } \" ) kpffiu [ 'ADC1VAL' ] . write ( ADC1 ) kpffiu [ 'ADC2VAL' ] . write ( ADC2 ) @classmethod def post_condition ( cls , args , logger , cfg ): kpffiu = ktl . cache ( 'kpffiu' ) tol = 0.1 ADC1_nominal , ADC2_nominal = kpffiu [ 'ADCPRISMS' ] . read ( binary = True ) adc1targ = ADC1_nominal + args . get ( 'ADC1OFF' ) adc2targ = ADC2_nominal + args . get ( 'ADC2OFF' ) expr = ( f \"($kpffiu.ADC1VAL > { adc1targ - tol } ) \" f \"and ($kpffiu.ADC1VAL < { adc1targ + tol } ) \" f \"and ($kpffiu.ADC2VAL > { adc2targ - tol } ) \" f \"and ($kpffiu.ADC2VAL < { adc2targ + tol } )\" ) success = ktl . waitFor ( expr , timeout = 20 ) if success is False : raise FailedPostCondition ( 'ADC Prisms did not reach destination angles' ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'ADC1OFF' , type = float , help = \"Offset for ADC1 (in degrees)\" ) parser . add_argument ( 'ADC2OFF' , type = float , help = \"Offset for ADC2 (in degrees)\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetADCOffsets"},{"location":"scripts/SetAFMtoMirror/","text":"SetAFMtoMirror Bases: KPFTranslatorFunction Set AFM to Mirror so ACAM sees light KTL Keywords Used: ao.OBAMNAME ao.OBAMSLEW ao.OBAMSTST Source code in kpf/ao/SetAFMtoMirror.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class SetAFMtoMirror ( KPFTranslatorFunction ): '''Set AFM to Mirror so ACAM sees light KTL Keywords Used: - `ao.OBAMNAME` - `ao.OBAMSLEW` - `ao.OBAMSTST` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) log . debug ( f \"Setting AFM to Mirror\" ) ao [ 'OBAMNAME' ] . write ( 'Mirror' ) ao [ 'OBAMSLEW' ] . write ( '1' ) @classmethod def post_condition ( cls , args , logger , cfg ): expr = '($ao.OBAMSTST == INPOS) and ($ao.OBAMNAME == Mirror)' aoamstst_success = ktl . waitfor ( expr , timeout = 60 ) if not aoamstst_success : ao = ktl . cache ( 'ao' ) FailedToReachDestination ( ao [ 'OBAMNAME' ] . read (), 'Mirror' )","title":"SetAFMtoMirror"},{"location":"scripts/SetAFMtoMirror/#setafmtomirror","text":"Bases: KPFTranslatorFunction Set AFM to Mirror so ACAM sees light KTL Keywords Used: ao.OBAMNAME ao.OBAMSLEW ao.OBAMSTST Source code in kpf/ao/SetAFMtoMirror.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class SetAFMtoMirror ( KPFTranslatorFunction ): '''Set AFM to Mirror so ACAM sees light KTL Keywords Used: - `ao.OBAMNAME` - `ao.OBAMSLEW` - `ao.OBAMSTST` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) log . debug ( f \"Setting AFM to Mirror\" ) ao [ 'OBAMNAME' ] . write ( 'Mirror' ) ao [ 'OBAMSLEW' ] . write ( '1' ) @classmethod def post_condition ( cls , args , logger , cfg ): expr = '($ao.OBAMSTST == INPOS) and ($ao.OBAMNAME == Mirror)' aoamstst_success = ktl . waitfor ( expr , timeout = 60 ) if not aoamstst_success : ao = ktl . cache ( 'ao' ) FailedToReachDestination ( ao [ 'OBAMNAME' ] . read (), 'Mirror' )","title":"SetAFMtoMirror"},{"location":"scripts/SetAFStoNGS/","text":"SetAFStoNGS Bases: KPFTranslatorFunction ACAM should be set to NGS focus. LGS focus will not work for KPF. KTL Keywords Used: ao.OBASNAME ao.OBASSLEW ao.OBASSTST Source code in kpf/ao/SetAFStoNGS.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class SetAFStoNGS ( KPFTranslatorFunction ): '''ACAM should be set to NGS focus. LGS focus will not work for KPF. KTL Keywords Used: - `ao.OBASNAME` - `ao.OBASSLEW` - `ao.OBASSTST` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) log . debug ( f \"Setting AFS to NGS\" ) ao [ 'OBASNAME' ] . write ( 'ngs' ) ao [ 'OBASSLEW' ] . write ( '1' ) @classmethod def post_condition ( cls , args , logger , cfg ): expr = f '($ao.OBASSTST == INPOS) and ($ao.OBASNAME == ngs)' aoamstst_success = ktl . waitfor ( expr , timeout = 60 ) if not aoamstst_success : ao = ktl . cache ( 'ao' ) raise FailedToReachDestination ( ao [ 'OBASNAME' ] . read (), 'ngs' )","title":"SetAFStoNGS"},{"location":"scripts/SetAFStoNGS/#setafstongs","text":"Bases: KPFTranslatorFunction ACAM should be set to NGS focus. LGS focus will not work for KPF. KTL Keywords Used: ao.OBASNAME ao.OBASSLEW ao.OBASSTST Source code in kpf/ao/SetAFStoNGS.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class SetAFStoNGS ( KPFTranslatorFunction ): '''ACAM should be set to NGS focus. LGS focus will not work for KPF. KTL Keywords Used: - `ao.OBASNAME` - `ao.OBASSLEW` - `ao.OBASSTST` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) log . debug ( f \"Setting AFS to NGS\" ) ao [ 'OBASNAME' ] . write ( 'ngs' ) ao [ 'OBASSLEW' ] . write ( '1' ) @classmethod def post_condition ( cls , args , logger , cfg ): expr = f '($ao.OBASSTST == INPOS) and ($ao.OBASNAME == ngs)' aoamstst_success = ktl . waitfor ( expr , timeout = 60 ) if not aoamstst_success : ao = ktl . cache ( 'ao' ) raise FailedToReachDestination ( ao [ 'OBASNAME' ] . read (), 'ngs' )","title":"SetAFStoNGS"},{"location":"scripts/SetAODCStoSIM/","text":"SetAODCStoSIM Bases: KPFTranslatorFunction Set AO in AO DCS sim mode, so AO doesn't communicate with telescope KTL Keywords Used: ao.AODCSSIM ao.AOCOMSIM ao.AODCSSFP Source code in kpf/ao/SetAODCStoSIM.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 class SetAODCStoSIM ( KPFTranslatorFunction ): '''Set AO in AO DCS sim mode, so AO doesn't communicate with telescope KTL Keywords Used: - `ao.AODCSSIM` - `ao.AOCOMSIM` - `ao.AODCSSFP` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) log . debug ( \"Setting AO DCS to Sim\" ) ao [ 'AODCSSIM' ] . write ( '1' ) ao [ 'AOCOMSIM' ] . write ( '1' ) ao [ 'AODCSSFP' ] . write ( '0' ) @classmethod def post_condition ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) aodcssim_success = ktl . waitfor ( '($ao.AODCSSIM == enabled)' , timeout = 3 ) if not aodcssim_success : raise FailedToReachDestination ( ao [ 'AODCSSIM' ] . read (), 'enabled' ) aocomsim_success = ktl . waitfor ( '($ao.AOCOMSIM == enabled)' , timeout = 3 ) if not aocomsim_success : raise FailedToReachDestination ( ao [ 'AOCOMSIM' ] . read (), 'enabled' ) aodcssfp_success = ktl . waitfor ( '($ao.AODCSSFP == disabled)' , timeout = 3 ) if not aodcssfp_success : raise FailedToReachDestination ( ao [ 'AODCSSFP' ] . read (), 'disabled' )","title":"SetAODCStoSIM"},{"location":"scripts/SetAODCStoSIM/#setaodcstosim","text":"Bases: KPFTranslatorFunction Set AO in AO DCS sim mode, so AO doesn't communicate with telescope KTL Keywords Used: ao.AODCSSIM ao.AOCOMSIM ao.AODCSSFP Source code in kpf/ao/SetAODCStoSIM.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 class SetAODCStoSIM ( KPFTranslatorFunction ): '''Set AO in AO DCS sim mode, so AO doesn't communicate with telescope KTL Keywords Used: - `ao.AODCSSIM` - `ao.AOCOMSIM` - `ao.AODCSSFP` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) log . debug ( \"Setting AO DCS to Sim\" ) ao [ 'AODCSSIM' ] . write ( '1' ) ao [ 'AOCOMSIM' ] . write ( '1' ) ao [ 'AODCSSFP' ] . write ( '0' ) @classmethod def post_condition ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) aodcssim_success = ktl . waitfor ( '($ao.AODCSSIM == enabled)' , timeout = 3 ) if not aodcssim_success : raise FailedToReachDestination ( ao [ 'AODCSSIM' ] . read (), 'enabled' ) aocomsim_success = ktl . waitfor ( '($ao.AOCOMSIM == enabled)' , timeout = 3 ) if not aocomsim_success : raise FailedToReachDestination ( ao [ 'AOCOMSIM' ] . read (), 'enabled' ) aodcssfp_success = ktl . waitfor ( '($ao.AODCSSFP == disabled)' , timeout = 3 ) if not aodcssfp_success : raise FailedToReachDestination ( ao [ 'AODCSSFP' ] . read (), 'disabled' )","title":"SetAODCStoSIM"},{"location":"scripts/SetAORotator/","text":"SetAORotator Bases: KPFTranslatorFunction Set the AO rotator destination KTL Keywords Used: ao.AODCSSIM ao.AOCOMSIM ao.AODCSSFP Parameters: dest ( float ) \u2013 Angle in degrees for the physical drive angle of the rotator. Source code in kpf/ao/SetAORotator.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class SetAORotator ( KPFTranslatorFunction ): '''Set the AO rotator destination KTL Keywords Used: - `ao.AODCSSIM` - `ao.AOCOMSIM` - `ao.AODCSSFP` Args: dest (float): Angle in degrees for the physical drive angle of the rotator. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'dest' ) @classmethod def perform ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) dest = args . get ( 'dest' , 0 ) log . debug ( f \"Setting AO Rotator to { dest : .1f } \" ) ao [ 'OBRT' ] . write ( dest ) ao [ 'OBRTMOVE' ] . write ( '1' ) @classmethod def post_condition ( cls , args , logger , cfg ): success = ktl . waitfor ( '($ao.OBRTSTST == INPOS)' , timeout = 180 ) if success is not True : ao = ktl . cache ( 'ao' ) raise FailedToReachDestination ( ao [ 'OBRTSTST' ] . read (), 'INPOS' ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'dest' , type = float , help = \"Desired rotator position\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetAORotator"},{"location":"scripts/SetAORotator/#setaorotator","text":"Bases: KPFTranslatorFunction Set the AO rotator destination KTL Keywords Used: ao.AODCSSIM ao.AOCOMSIM ao.AODCSSFP Parameters: dest ( float ) \u2013 Angle in degrees for the physical drive angle of the rotator. Source code in kpf/ao/SetAORotator.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class SetAORotator ( KPFTranslatorFunction ): '''Set the AO rotator destination KTL Keywords Used: - `ao.AODCSSIM` - `ao.AOCOMSIM` - `ao.AODCSSFP` Args: dest (float): Angle in degrees for the physical drive angle of the rotator. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'dest' ) @classmethod def perform ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) dest = args . get ( 'dest' , 0 ) log . debug ( f \"Setting AO Rotator to { dest : .1f } \" ) ao [ 'OBRT' ] . write ( dest ) ao [ 'OBRTMOVE' ] . write ( '1' ) @classmethod def post_condition ( cls , args , logger , cfg ): success = ktl . waitfor ( '($ao.OBRTSTST == INPOS)' , timeout = 180 ) if success is not True : ao = ktl . cache ( 'ao' ) raise FailedToReachDestination ( ao [ 'OBRTSTST' ] . read (), 'INPOS' ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'dest' , type = float , help = \"Desired rotator position\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetAORotator"},{"location":"scripts/SetAORotatorManual/","text":"SetAORotatorManual Bases: KPFTranslatorFunction AO rotator needs to be in the Manual mode before observing. KTL Keywords Used: ao.OBRTDSRC ao.OBRTMOVE Source code in kpf/ao/SetAORotatorManual.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class SetAORotatorManual ( KPFTranslatorFunction ): '''AO rotator needs to be in the Manual mode before observing. KTL Keywords Used: - `ao.OBRTDSRC` - `ao.OBRTMOVE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) log . debug ( \"Setting AO rotator to manual mode\" ) ao [ 'OBRTDSRC' ] . write ( '0' ) ao [ 'OBRTMOVE' ] . write ( '1' ) @classmethod def post_condition ( cls , args , logger , cfg ): success = ktl . waitfor ( '($ao.OBRTDSRC == manual)' , timeout = 3 ) if success is not True : ao = ktl . cache ( 'ao' ) raise FailedToReachDestination ( ao [ 'OBRTDSRC' ] . read (), 'manual' )","title":"SetAORotatorManual"},{"location":"scripts/SetAORotatorManual/#setaorotatormanual","text":"Bases: KPFTranslatorFunction AO rotator needs to be in the Manual mode before observing. KTL Keywords Used: ao.OBRTDSRC ao.OBRTMOVE Source code in kpf/ao/SetAORotatorManual.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class SetAORotatorManual ( KPFTranslatorFunction ): '''AO rotator needs to be in the Manual mode before observing. KTL Keywords Used: - `ao.OBRTDSRC` - `ao.OBRTMOVE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) log . debug ( \"Setting AO rotator to manual mode\" ) ao [ 'OBRTDSRC' ] . write ( '0' ) ao [ 'OBRTMOVE' ] . write ( '1' ) @classmethod def post_condition ( cls , args , logger , cfg ): success = ktl . waitfor ( '($ao.OBRTDSRC == manual)' , timeout = 3 ) if success is not True : ao = ktl . cache ( 'ao' ) raise FailedToReachDestination ( ao [ 'OBRTDSRC' ] . read (), 'manual' )","title":"SetAORotatorManual"},{"location":"scripts/SetCalSource/","text":"SetCalSource Bases: KPFTranslatorFunction Selects which source is fed from the octagon in to the cal bench via the kpfcal.OCTAGON keyword. Parameters: CalSource ( str ) \u2013 Which lamp to select? Allowed Values: EtalonFiber, BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, SoCal-CalFib, LFCFiber KTL Keywords Used: kpfcal.OCTAGON Source code in kpf/calbench/SetCalSource.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetCalSource ( KPFTranslatorFunction ): '''Selects which source is fed from the octagon in to the cal bench via the `kpfcal.OCTAGON` keyword. Args: CalSource (str): Which lamp to select? Allowed Values: EtalonFiber, BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, SoCal-CalFib, LFCFiber KTL Keywords Used: - `kpfcal.OCTAGON` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'OCTAGON' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) check_input ( args , 'CalSource' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): target = args . get ( 'CalSource' ) kpfcal = ktl . cache ( 'kpfcal' ) log . debug ( f \"Setting Cal Source (Octagon) to { target } \" ) kpfcal [ 'OCTAGON' ] . write ( target , wait = args . get ( 'wait' , True )) @classmethod def post_condition ( cls , args , logger , cfg ): target = args . get ( 'CalSource' ) timeout = cfg . getfloat ( 'times' , 'octagon_move_time' , fallback = 90 ) expr = f \"($kpfcal.OCTAGON == { target } )\" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : kpfcal = ktl . cache ( 'kpfcal' ) raise FailedToReachDestination ( kpfcal [ 'OCTAGON' ] . read (), target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalSource' , type = str , choices = [ 'Home' , 'EtalonFiber' , 'BrdbandFiber' , 'U_gold' , 'U_daily' , 'Th_daily' , 'Th_gold' , 'SoCal-CalFib' , 'LFCFiber' ], help = 'Octagon position to choose?' ) parser . add_argument ( \"--nowait\" , dest = \"wait\" , default = True , action = \"store_false\" , help = \"Send move and return immediately?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetCalSource"},{"location":"scripts/SetCalSource/#setcalsource","text":"Bases: KPFTranslatorFunction Selects which source is fed from the octagon in to the cal bench via the kpfcal.OCTAGON keyword. Parameters: CalSource ( str ) \u2013 Which lamp to select? Allowed Values: EtalonFiber, BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, SoCal-CalFib, LFCFiber KTL Keywords Used: kpfcal.OCTAGON Source code in kpf/calbench/SetCalSource.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetCalSource ( KPFTranslatorFunction ): '''Selects which source is fed from the octagon in to the cal bench via the `kpfcal.OCTAGON` keyword. Args: CalSource (str): Which lamp to select? Allowed Values: EtalonFiber, BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, SoCal-CalFib, LFCFiber KTL Keywords Used: - `kpfcal.OCTAGON` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'OCTAGON' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) check_input ( args , 'CalSource' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): target = args . get ( 'CalSource' ) kpfcal = ktl . cache ( 'kpfcal' ) log . debug ( f \"Setting Cal Source (Octagon) to { target } \" ) kpfcal [ 'OCTAGON' ] . write ( target , wait = args . get ( 'wait' , True )) @classmethod def post_condition ( cls , args , logger , cfg ): target = args . get ( 'CalSource' ) timeout = cfg . getfloat ( 'times' , 'octagon_move_time' , fallback = 90 ) expr = f \"($kpfcal.OCTAGON == { target } )\" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : kpfcal = ktl . cache ( 'kpfcal' ) raise FailedToReachDestination ( kpfcal [ 'OCTAGON' ] . read (), target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalSource' , type = str , choices = [ 'Home' , 'EtalonFiber' , 'BrdbandFiber' , 'U_gold' , 'U_daily' , 'Th_daily' , 'Th_gold' , 'SoCal-CalFib' , 'LFCFiber' ], help = 'Octagon position to choose?' ) parser . add_argument ( \"--nowait\" , dest = \"wait\" , default = True , action = \"store_false\" , help = \"Send move and return immediately?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetCalSource"},{"location":"scripts/SetExpMeterExpTime/","text":"SetExpMeterExpTime Bases: KPFTranslatorFunction Sets the exposure time for the exposure meter Parameters: ExpMeterExpTime ( float ) \u2013 The exposure time in seconds. KTL Keywords Used: kpf_expmeter.EXPOSURE Source code in kpf/expmeter/SetExpMeterExpTime.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 class SetExpMeterExpTime ( KPFTranslatorFunction ): '''Sets the exposure time for the exposure meter Args: ExpMeterExpTime (float): The exposure time in seconds. KTL Keywords Used: - `kpf_expmeter.EXPOSURE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'ExpMeterExpTime' , allowed_types = [ int , float ]) @classmethod def perform ( cls , args , logger , cfg ): kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) exptime = args . get ( 'ExpMeterExpTime' ) log . debug ( f \"Setting exposure time to { exptime : .3f } \" ) kpf_expmeter [ 'EXPOSURE' ] . write ( exptime ) @classmethod def post_condition ( cls , args , logger , cfg ): log . debug ( \"Checking for success\" ) exptime = args . get ( 'ExpMeterExpTime' ) tol = cfg . getfloat ( 'tolerances' , 'kpfexpose_exptime_tolerance' , fallback = 0.01 ) timeout = cfg . getfloat ( 'times' , 'kpfexpose_response_time' , fallback = 1 ) expr = ( f \"($kpf_expmeter.EXPOSURE >= { exptime - tol } ) and \" f \"($kpf_expmeter.EXPOSURE <= { exptime + tol } )\" ) log . debug ( expr ) success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : exposure = ktl . cache ( 'kpf_expmeter' , 'EXPOSURE' ) raise FailedToReachDestination ( exposure . read (), exptime ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'ExpMeterExpTime' , type = float , help = \"The exposure time in seconds\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetExpMeterExpTime"},{"location":"scripts/SetExpMeterExpTime/#setexpmeterexptime","text":"Bases: KPFTranslatorFunction Sets the exposure time for the exposure meter Parameters: ExpMeterExpTime ( float ) \u2013 The exposure time in seconds. KTL Keywords Used: kpf_expmeter.EXPOSURE Source code in kpf/expmeter/SetExpMeterExpTime.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 class SetExpMeterExpTime ( KPFTranslatorFunction ): '''Sets the exposure time for the exposure meter Args: ExpMeterExpTime (float): The exposure time in seconds. KTL Keywords Used: - `kpf_expmeter.EXPOSURE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'ExpMeterExpTime' , allowed_types = [ int , float ]) @classmethod def perform ( cls , args , logger , cfg ): kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) exptime = args . get ( 'ExpMeterExpTime' ) log . debug ( f \"Setting exposure time to { exptime : .3f } \" ) kpf_expmeter [ 'EXPOSURE' ] . write ( exptime ) @classmethod def post_condition ( cls , args , logger , cfg ): log . debug ( \"Checking for success\" ) exptime = args . get ( 'ExpMeterExpTime' ) tol = cfg . getfloat ( 'tolerances' , 'kpfexpose_exptime_tolerance' , fallback = 0.01 ) timeout = cfg . getfloat ( 'times' , 'kpfexpose_response_time' , fallback = 1 ) expr = ( f \"($kpf_expmeter.EXPOSURE >= { exptime - tol } ) and \" f \"($kpf_expmeter.EXPOSURE <= { exptime + tol } )\" ) log . debug ( expr ) success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : exposure = ktl . cache ( 'kpf_expmeter' , 'EXPOSURE' ) raise FailedToReachDestination ( exposure . read (), exptime ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'ExpMeterExpTime' , type = float , help = \"The exposure time in seconds\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetExpMeterExpTime"},{"location":"scripts/SetExpMeterTerminationParameters/","text":"SetExpMeterTerminationParameters Bases: KPFTranslatorFunction Sets the exposure meter exposure termination control parameters Parameters: Band ( int ) \u2013 Which of the 4 exposure meter bands to use? 0=All, 1=498nm, 2=604nm, 3=711nm, 4=817nm (from kpf_expmeter.THRESHOLDBIN). Flux ( float ) \u2013 The target flux (e/nm) in the science spectrum. KTL Keywords Used: kpf_expmeter.THRESHOLDBIN kpf_expmeter.THRESHOLD kpf_expmeter.USETHRESHOLD Source code in kpf/expmeter/SetExpMeterTerminationParameters.py 18 19 20 21 22 23 24 25 26 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 class SetExpMeterTerminationParameters ( KPFTranslatorFunction ): '''Sets the exposure meter exposure termination control parameters Args: Band (int): Which of the 4 exposure meter bands to use? 0=All, 1=498nm, 2=604nm, 3=711nm, 4=817nm (from kpf_expmeter.THRESHOLDBIN). Flux (float): The target flux (e/nm) in the science spectrum. KTL Keywords Used: - `kpf_expmeter.THRESHOLDBIN` - `kpf_expmeter.THRESHOLD` - `kpf_expmeter.USETHRESHOLD` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'ExpMeterThreshold' , allowed_types = [ int , float ], value_min = 0 ) check_input ( args , 'ExpMeterBin' ) # Manually check ExpMeterBin inputs band = args . get ( 'ExpMeterBin' ) tbin = ktl . cache ( 'kpf_expmeter' , 'THRESHOLDBIN' ) allowed_values = list ( tbin . _getEnumerators ()) if isinstance ( band , float ): band = str ( band ) if isinstance ( band , str ): if band not in allowed_values : raise FailedPreCondition ( f \"ExpMeterBin ' { band } ' not in { allowed_values } \" ) else : raise FailedPreCondition ( f \"ExpMeterBin ' { band } ' could not be parsed\" ) @classmethod def perform ( cls , args , logger , cfg ): band = str ( args . get ( 'ExpMeterBin' )) spectrograph_flux = args . get ( 'ExpMeterThreshold' ) expmeter_flux = expeter_flux_target ( spectrograph_flux , band ) kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) kpf_expmeter [ 'THRESHOLDBIN' ] . write ( band ) kpf_expmeter [ 'THRESHOLD' ] . write ( expmeter_flux ) kpf_expmeter [ 'USETHRESHOLD' ] . write ( 'Yes' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'ExpMeterBin' , type = int , choices = [ 1 , 2 , 3 , 4 ], help = \"Which exposure meter band to use (1, 2, 3, or 4)\" ) parser . add_argument ( 'ExpMeterThreshold' , type = float , help = \"Threshold flux in e-/nm in the main spectrograph\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetExpMeterTerminationParameters"},{"location":"scripts/SetExpMeterTerminationParameters/#setexpmeterterminationparameters","text":"Bases: KPFTranslatorFunction Sets the exposure meter exposure termination control parameters Parameters: Band ( int ) \u2013 Which of the 4 exposure meter bands to use? 0=All, 1=498nm, 2=604nm, 3=711nm, 4=817nm (from kpf_expmeter.THRESHOLDBIN). Flux ( float ) \u2013 The target flux (e/nm) in the science spectrum. KTL Keywords Used: kpf_expmeter.THRESHOLDBIN kpf_expmeter.THRESHOLD kpf_expmeter.USETHRESHOLD Source code in kpf/expmeter/SetExpMeterTerminationParameters.py 18 19 20 21 22 23 24 25 26 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 class SetExpMeterTerminationParameters ( KPFTranslatorFunction ): '''Sets the exposure meter exposure termination control parameters Args: Band (int): Which of the 4 exposure meter bands to use? 0=All, 1=498nm, 2=604nm, 3=711nm, 4=817nm (from kpf_expmeter.THRESHOLDBIN). Flux (float): The target flux (e/nm) in the science spectrum. KTL Keywords Used: - `kpf_expmeter.THRESHOLDBIN` - `kpf_expmeter.THRESHOLD` - `kpf_expmeter.USETHRESHOLD` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'ExpMeterThreshold' , allowed_types = [ int , float ], value_min = 0 ) check_input ( args , 'ExpMeterBin' ) # Manually check ExpMeterBin inputs band = args . get ( 'ExpMeterBin' ) tbin = ktl . cache ( 'kpf_expmeter' , 'THRESHOLDBIN' ) allowed_values = list ( tbin . _getEnumerators ()) if isinstance ( band , float ): band = str ( band ) if isinstance ( band , str ): if band not in allowed_values : raise FailedPreCondition ( f \"ExpMeterBin ' { band } ' not in { allowed_values } \" ) else : raise FailedPreCondition ( f \"ExpMeterBin ' { band } ' could not be parsed\" ) @classmethod def perform ( cls , args , logger , cfg ): band = str ( args . get ( 'ExpMeterBin' )) spectrograph_flux = args . get ( 'ExpMeterThreshold' ) expmeter_flux = expeter_flux_target ( spectrograph_flux , band ) kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) kpf_expmeter [ 'THRESHOLDBIN' ] . write ( band ) kpf_expmeter [ 'THRESHOLD' ] . write ( expmeter_flux ) kpf_expmeter [ 'USETHRESHOLD' ] . write ( 'Yes' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'ExpMeterBin' , type = int , choices = [ 1 , 2 , 3 , 4 ], help = \"Which exposure meter band to use (1, 2, 3, or 4)\" ) parser . add_argument ( 'ExpMeterThreshold' , type = float , help = \"Threshold flux in e-/nm in the main spectrograph\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetExpMeterTerminationParameters"},{"location":"scripts/SetExpTime/","text":"SetExpTime Bases: KPFTranslatorFunction Sets the exposure time for the science detectors in the kpfexpose keyword service. ARGS: :ExpTime: float The exposure time in seconds Source code in kpf/spectrograph/SetExpTime.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class SetExpTime ( KPFTranslatorFunction ): '''Sets the exposure time for the science detectors in the kpfexpose keyword service. ARGS: ===== :ExpTime: `float` The exposure time in seconds ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'ExpTime' , allowed_types = [ int , float ]) @classmethod def perform ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) exptime = args . get ( 'ExpTime' ) log . debug ( f \"Setting exposure time to { exptime : .3f } \" ) kpfexpose [ 'EXPOSURE' ] . write ( exptime ) @classmethod def post_condition ( cls , args , logger , cfg ): log . debug ( \"Checking for success\" ) exptime = args . get ( 'ExpTime' ) tol = cfg . getfloat ( 'tolerances' , 'kpfexpose_exptime_tolerance' , fallback = 0.01 ) timeout = cfg . getfloat ( 'times' , 'kpfexpose_response_time' , fallback = 1 ) expr = ( f \"($kpfexpose.EXPOSURE >= { exptime - tol } ) and \" f \"($kpfexpose.EXPOSURE <= { exptime + tol } )\" ) log . debug ( expr ) success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : exposure = ktl . cache ( 'kpfexpose' , 'EXPOSURE' ) raise FailedToReachDestination ( exposure . read (), exptime ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'ExpTime' , type = float , help = 'The exposure time in seconds' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetExpTime"},{"location":"scripts/SetExpTime/#setexptime","text":"Bases: KPFTranslatorFunction Sets the exposure time for the science detectors in the kpfexpose keyword service.","title":"SetExpTime"},{"location":"scripts/SetExpTime/#kpf.spectrograph.SetExpTime.SetExpTime--args","text":":ExpTime: float The exposure time in seconds Source code in kpf/spectrograph/SetExpTime.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class SetExpTime ( KPFTranslatorFunction ): '''Sets the exposure time for the science detectors in the kpfexpose keyword service. ARGS: ===== :ExpTime: `float` The exposure time in seconds ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'ExpTime' , allowed_types = [ int , float ]) @classmethod def perform ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) exptime = args . get ( 'ExpTime' ) log . debug ( f \"Setting exposure time to { exptime : .3f } \" ) kpfexpose [ 'EXPOSURE' ] . write ( exptime ) @classmethod def post_condition ( cls , args , logger , cfg ): log . debug ( \"Checking for success\" ) exptime = args . get ( 'ExpTime' ) tol = cfg . getfloat ( 'tolerances' , 'kpfexpose_exptime_tolerance' , fallback = 0.01 ) timeout = cfg . getfloat ( 'times' , 'kpfexpose_response_time' , fallback = 1 ) expr = ( f \"($kpfexpose.EXPOSURE >= { exptime - tol } ) and \" f \"($kpfexpose.EXPOSURE <= { exptime + tol } )\" ) log . debug ( expr ) success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : exposure = ktl . cache ( 'kpfexpose' , 'EXPOSURE' ) raise FailedToReachDestination ( exposure . read (), exptime ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'ExpTime' , type = float , help = 'The exposure time in seconds' ) return super () . add_cmdline_args ( parser , cfg )","title":"ARGS:"},{"location":"scripts/SetFVCExpTime/","text":"SetFVCExpTime Bases: KPFTranslatorFunction Set the exposure time of the specified fiber viewing camera Parameters: camera ( str ) \u2013 Which FVC camera? Allowed values: SCI, CAHK, EXT, CAL exptime ( float ) \u2013 The exposure time in seconds. KTL Keywords Used: kpffvc.SCIEXPTIME kpffvc.CAHKEXPTIME kpffvc.EXTEXPTIME kpffvc.CALEXPTIME kpfpower.KPFFVC1 kpfpower.KPFFVC2 kpfpower.KPFFVC3 Source code in kpf/fvc/SetFVCExpTime.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetFVCExpTime ( KPFTranslatorFunction ): '''Set the exposure time of the specified fiber viewing camera Args: camera (str): Which FVC camera? Allowed values: SCI, CAHK, EXT, CAL exptime (float): The exposure time in seconds. KTL Keywords Used: - `kpffvc.SCIEXPTIME` - `kpffvc.CAHKEXPTIME` - `kpffvc.EXTEXPTIME` - `kpffvc.CALEXPTIME` - `kpfpower.KPFFVC1` - `kpfpower.KPFFVC2` - `kpfpower.KPFFVC3` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'camera' , allowed_values = [ 'SCI' , 'CAHK' , 'CAL' , 'EXT' ]) check_input ( args , 'exptime' , value_min = 0.005 , value_max = 60 ) # Check if power is on camera = args . get ( 'camera' ) camnum = { 'SCI' : 1 , 'CAHK' : 2 , 'CAL' : 3 , 'EXT' : None }[ camera ] if camnum is not None : powerkw = ktl . cache ( 'kpfpower' , f \"KPFFVC { camnum } \" ) if powerkw . read () != 'On' : raise FailedPreCondition ( f \" { camera } FVC power is not On\" ) @classmethod def perform ( cls , args , logger , cfg ): camera = args . get ( 'camera' ) kpffvc = ktl . cache ( 'kpffvc' ) exptime = args . get ( 'exptime' ) log . debug ( f \"Setting { camera } FVC exposure time to { exptime : .3f } s\" ) kpffvc [ f ' { camera } EXPTIME' ] . write ( exptime ) @classmethod def post_condition ( cls , args , logger , cfg ): camera = args . get ( 'camera' ) exptime = args . get ( 'exptime' ) timeout = cfg . getfloat ( 'times' , 'fvc_command_timeout' , fallback = 5 ) tol = cfg . getfloat ( 'tolerances' , 'guider_exptime_tolerance' , fallback = 0.01 ) expr = ( f '($kpffvc. { camera } EXPTIME > { exptime } - { tol } ) ' \\ f 'and ($kpffvc. { camera } EXPTIME < { exptime } + { tol } )' ) success = ktl . waitfor ( expr , timeout = timeout ) if success is not True : exptimekw = ktl . cache ( 'kpffvc' , f \" { camera } EXPTIME\" ) raise FailedToReachDestination ( exptimekw . read (), exptime ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'camera' , type = str , choices = [ 'SCI' , 'CAHK' , 'CAL' , 'EXT' ], help = 'The FVC camera' ) parser . add_argument ( 'exptime' , type = float , help = 'The exposure time in seconds' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetFVCExpTime"},{"location":"scripts/SetFVCExpTime/#setfvcexptime","text":"Bases: KPFTranslatorFunction Set the exposure time of the specified fiber viewing camera Parameters: camera ( str ) \u2013 Which FVC camera? Allowed values: SCI, CAHK, EXT, CAL exptime ( float ) \u2013 The exposure time in seconds. KTL Keywords Used: kpffvc.SCIEXPTIME kpffvc.CAHKEXPTIME kpffvc.EXTEXPTIME kpffvc.CALEXPTIME kpfpower.KPFFVC1 kpfpower.KPFFVC2 kpfpower.KPFFVC3 Source code in kpf/fvc/SetFVCExpTime.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetFVCExpTime ( KPFTranslatorFunction ): '''Set the exposure time of the specified fiber viewing camera Args: camera (str): Which FVC camera? Allowed values: SCI, CAHK, EXT, CAL exptime (float): The exposure time in seconds. KTL Keywords Used: - `kpffvc.SCIEXPTIME` - `kpffvc.CAHKEXPTIME` - `kpffvc.EXTEXPTIME` - `kpffvc.CALEXPTIME` - `kpfpower.KPFFVC1` - `kpfpower.KPFFVC2` - `kpfpower.KPFFVC3` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'camera' , allowed_values = [ 'SCI' , 'CAHK' , 'CAL' , 'EXT' ]) check_input ( args , 'exptime' , value_min = 0.005 , value_max = 60 ) # Check if power is on camera = args . get ( 'camera' ) camnum = { 'SCI' : 1 , 'CAHK' : 2 , 'CAL' : 3 , 'EXT' : None }[ camera ] if camnum is not None : powerkw = ktl . cache ( 'kpfpower' , f \"KPFFVC { camnum } \" ) if powerkw . read () != 'On' : raise FailedPreCondition ( f \" { camera } FVC power is not On\" ) @classmethod def perform ( cls , args , logger , cfg ): camera = args . get ( 'camera' ) kpffvc = ktl . cache ( 'kpffvc' ) exptime = args . get ( 'exptime' ) log . debug ( f \"Setting { camera } FVC exposure time to { exptime : .3f } s\" ) kpffvc [ f ' { camera } EXPTIME' ] . write ( exptime ) @classmethod def post_condition ( cls , args , logger , cfg ): camera = args . get ( 'camera' ) exptime = args . get ( 'exptime' ) timeout = cfg . getfloat ( 'times' , 'fvc_command_timeout' , fallback = 5 ) tol = cfg . getfloat ( 'tolerances' , 'guider_exptime_tolerance' , fallback = 0.01 ) expr = ( f '($kpffvc. { camera } EXPTIME > { exptime } - { tol } ) ' \\ f 'and ($kpffvc. { camera } EXPTIME < { exptime } + { tol } )' ) success = ktl . waitfor ( expr , timeout = timeout ) if success is not True : exptimekw = ktl . cache ( 'kpffvc' , f \" { camera } EXPTIME\" ) raise FailedToReachDestination ( exptimekw . read (), exptime ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'camera' , type = str , choices = [ 'SCI' , 'CAHK' , 'CAL' , 'EXT' ], help = 'The FVC camera' ) parser . add_argument ( 'exptime' , type = float , help = 'The exposure time in seconds' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetFVCExpTime"},{"location":"scripts/SetFlatFieldFiberPos/","text":"SetFlatFieldFiberPos Bases: KPFTranslatorFunction Description Set the flat field fiber aperture via the kpfcal.FF_FIBERPOS keyword. Parameters: FF_FiberPos ( str ) \u2013 The name of the flat field fiber position desired. Allowed Values: \"Blank\", \"6 mm f/5\", \"7.5 mm f/4\", \"10 mm f/3\", \"13.2 mm f/2.3\", \"Open\". wait ( bool ) \u2013 Wait for move to complete before returning? default: True KTL Keywords Used kpfcal.FF_FIBERPOS Source code in kpf/calbench/SetFlatFieldFiberPos.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetFlatFieldFiberPos ( KPFTranslatorFunction ): '''# Description Set the flat field fiber aperture via the `kpfcal.FF_FIBERPOS` keyword. Args: FF_FiberPos (str): The name of the flat field fiber position desired. Allowed Values: \"Blank\", \"6 mm f/5\", \"7.5 mm f/4\", \"10 mm f/3\", \"13.2 mm f/2.3\", \"Open\". wait (bool): Wait for move to complete before returning? default: True ## KTL Keywords Used - `kpfcal.FF_FIBERPOS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'FF_FiberPos' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) check_input ( args , 'FF_FiberPos' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): target = args . get ( 'FF_FiberPos' ) log . debug ( f \"Setting FF_FiberPos to { target } \" ) kpfcal = ktl . cache ( 'kpfcal' ) kpfcal [ 'FF_FiberPos' ] . write ( target , wait = args . get ( 'wait' , True )) @classmethod def post_condition ( cls , args , logger , cfg ): target = args . get ( 'FF_FiberPos' ) timeout = cfg . getfloat ( 'times' , 'nd_move_time' , fallback = 20 ) expr = f \"($kpfcal.FF_FiberPos == ' { target } ')\" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : kpfcal = ktl . cache ( 'kpfcal' ) raise FailedToReachDestination ( kpfcal [ 'FF_FiberPos' ] . read (), target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'FF_FiberPos' , type = str , choices = [ \"Blank\" , \"6 mm f/5\" , \"7.5 mm f/4\" , \"10 mm f/3\" , \"13.2 mm f/2.3\" , \"Open\" ], help = 'Wide flat aperture to use.' ) parser . add_argument ( \"--nowait\" , dest = \"wait\" , default = True , action = \"store_false\" , help = \"Send move and return immediately?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetFlatFieldFiberPos"},{"location":"scripts/SetFlatFieldFiberPos/#setflatfieldfiberpos","text":"Bases: KPFTranslatorFunction","title":"SetFlatFieldFiberPos"},{"location":"scripts/SetFlatFieldFiberPos/#kpf.calbench.SetFlatFieldFiberPos.SetFlatFieldFiberPos--description","text":"Set the flat field fiber aperture via the kpfcal.FF_FIBERPOS keyword. Parameters: FF_FiberPos ( str ) \u2013 The name of the flat field fiber position desired. Allowed Values: \"Blank\", \"6 mm f/5\", \"7.5 mm f/4\", \"10 mm f/3\", \"13.2 mm f/2.3\", \"Open\". wait ( bool ) \u2013 Wait for move to complete before returning? default: True","title":"Description"},{"location":"scripts/SetFlatFieldFiberPos/#kpf.calbench.SetFlatFieldFiberPos.SetFlatFieldFiberPos--ktl-keywords-used","text":"kpfcal.FF_FIBERPOS Source code in kpf/calbench/SetFlatFieldFiberPos.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetFlatFieldFiberPos ( KPFTranslatorFunction ): '''# Description Set the flat field fiber aperture via the `kpfcal.FF_FIBERPOS` keyword. Args: FF_FiberPos (str): The name of the flat field fiber position desired. Allowed Values: \"Blank\", \"6 mm f/5\", \"7.5 mm f/4\", \"10 mm f/3\", \"13.2 mm f/2.3\", \"Open\". wait (bool): Wait for move to complete before returning? default: True ## KTL Keywords Used - `kpfcal.FF_FIBERPOS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'FF_FiberPos' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) check_input ( args , 'FF_FiberPos' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): target = args . get ( 'FF_FiberPos' ) log . debug ( f \"Setting FF_FiberPos to { target } \" ) kpfcal = ktl . cache ( 'kpfcal' ) kpfcal [ 'FF_FiberPos' ] . write ( target , wait = args . get ( 'wait' , True )) @classmethod def post_condition ( cls , args , logger , cfg ): target = args . get ( 'FF_FiberPos' ) timeout = cfg . getfloat ( 'times' , 'nd_move_time' , fallback = 20 ) expr = f \"($kpfcal.FF_FiberPos == ' { target } ')\" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : kpfcal = ktl . cache ( 'kpfcal' ) raise FailedToReachDestination ( kpfcal [ 'FF_FiberPos' ] . read (), target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'FF_FiberPos' , type = str , choices = [ \"Blank\" , \"6 mm f/5\" , \"7.5 mm f/4\" , \"10 mm f/3\" , \"13.2 mm f/2.3\" , \"Open\" ], help = 'Wide flat aperture to use.' ) parser . add_argument ( \"--nowait\" , dest = \"wait\" , default = True , action = \"store_false\" , help = \"Send move and return immediately?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"KTL Keywords Used"},{"location":"scripts/SetGuiderExpTime/","text":"SetGuiderExpTime Bases: KPFTranslatorFunction Set the guider exposure time (in seconds) via the kpfguide.EXPTIME keyword. The guider exposure time is governed by several factors. The exposure time controlled here is generated by stacking (averaging) multiple frames as needed to obtain the specified exposure time. Those individual frames are controlled by the FPS, AVERAGE, STACK, and EXPTIME keywords. From Kyle: If you want to tweak an exposure setting, I recommend MAGIQ use the EXPTIME keyword as its preferred knob. This will translate to changing the number of frames averaged together. You can also choose to stack frames, but I doubt that will be necessary. Notice how EXPTIME remains unchanged when I change the STACK keyword: [klanclos@kpffiuserver ~]$ gshow -s kpfguide fps average stack exptime FPS = 100.0000 frames/second AVERAGE = 100 frames STACK = 1 averaged frames EXPTIME = 1.000000 seconds [klanclos@kpffiuserver ~]$ modify -s kpfguide stack=2 setting stack = 2 (wait) [klanclos@kpffiuserver ~]$ gshow -s kpfguide fps average stack exptime FPS = 100.0000 frames/second AVERAGE = 50 frames STACK = 2 averaged frames EXPTIME = 1.000000 seconds ...but if I change AVERAGE, EXPTIME reflects the change: [klanclos@kpffiuserver ~]$ modify -s kpfguide average=20 setting average = 20 (wait) [klanclos@kpffiuserver ~]$ gshow -s kpfguide fps average stack exptime FPS = 100.0000 frames/second AVERAGE = 20 frames STACK = 1 averaged frames EXPTIME = 0.200000 seconds Stick to changing EXPTIME and you won't have to worry about it. Changing the frames per second is not recommended, because the tip/tilt system will be consuming this image stream, and it needs to retain full control of what an individual frame looks like. Parameters: exptime ( float ) \u2013 The exposure time in seconds. KTL Keywords Used: kpfguide.EXPTIME Source code in kpf/guider/SetGuiderExpTime.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetGuiderExpTime ( KPFTranslatorFunction ): '''Set the guider exposure time (in seconds) via the kpfguide.EXPTIME keyword. The guider exposure time is governed by several factors. The exposure time controlled here is generated by stacking (averaging) multiple frames as needed to obtain the specified exposure time. Those individual frames are controlled by the FPS, AVERAGE, STACK, and EXPTIME keywords. From Kyle: If you want to tweak an exposure setting, I recommend MAGIQ use the EXPTIME keyword as its preferred knob. This will translate to changing the number of frames averaged together. You can also choose to stack frames, but I doubt that will be necessary. Notice how EXPTIME remains unchanged when I change the STACK keyword: [klanclos@kpffiuserver ~]$ gshow -s kpfguide fps average stack exptime FPS = 100.0000 frames/second AVERAGE = 100 frames STACK = 1 averaged frames EXPTIME = 1.000000 seconds [klanclos@kpffiuserver ~]$ modify -s kpfguide stack=2 setting stack = 2 (wait) [klanclos@kpffiuserver ~]$ gshow -s kpfguide fps average stack exptime FPS = 100.0000 frames/second AVERAGE = 50 frames STACK = 2 averaged frames EXPTIME = 1.000000 seconds ...but if I change AVERAGE, EXPTIME reflects the change: [klanclos@kpffiuserver ~]$ modify -s kpfguide average=20 setting average = 20 (wait) [klanclos@kpffiuserver ~]$ gshow -s kpfguide fps average stack exptime FPS = 100.0000 frames/second AVERAGE = 20 frames STACK = 1 averaged frames EXPTIME = 0.200000 seconds Stick to changing EXPTIME and you won't have to worry about it. Changing the frames per second is not recommended, because the tip/tilt system will be consuming this image stream, and it needs to retain full control of what an individual frame looks like. Args: exptime (float): The exposure time in seconds. KTL Keywords Used: - `kpfguide.EXPTIME` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'exptime' , value_min = 0 ) @classmethod def perform ( cls , args , logger , cfg ): exptimekw = ktl . cache ( 'kpfguide' , 'EXPTIME' ) exptime = args . get ( 'exptime' ) exptimekw . write ( exptime ) @classmethod def post_condition ( cls , args , logger , cfg ): exptol = cfg . getfloat ( 'tolerances' , 'guider_exptime_tolerance' , fallback = 0.01 ) exptimekw = ktl . cache ( 'kpfguide' , 'EXPTIME' ) exptimeread = exptimekw . read ( binary = True ) exptime = args . get ( 'exptime' ) expr = ( f '($kpfguide.EXPTIME >= { exptime - exptol } ) and ' \\ f '($kpfguide.EXPTIME <= { exptime + exptol } )' ) success = ktl . waitFor ( expr , timeout = exptimeread + 1 ) if not success : raise FailedToReachDestination ( exptimekw . read (), exptime ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'exptime' , type = float , help = 'The exposure time in seconds' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetGuiderExpTime"},{"location":"scripts/SetGuiderExpTime/#setguiderexptime","text":"Bases: KPFTranslatorFunction Set the guider exposure time (in seconds) via the kpfguide.EXPTIME keyword. The guider exposure time is governed by several factors. The exposure time controlled here is generated by stacking (averaging) multiple frames as needed to obtain the specified exposure time. Those individual frames are controlled by the FPS, AVERAGE, STACK, and EXPTIME keywords. From Kyle: If you want to tweak an exposure setting, I recommend MAGIQ use the EXPTIME keyword as its preferred knob. This will translate to changing the number of frames averaged together. You can also choose to stack frames, but I doubt that will be necessary. Notice how EXPTIME remains unchanged when I change the STACK keyword: [klanclos@kpffiuserver ~]$ gshow -s kpfguide fps average stack exptime FPS = 100.0000 frames/second AVERAGE = 100 frames STACK = 1 averaged frames EXPTIME = 1.000000 seconds [klanclos@kpffiuserver ~]$ modify -s kpfguide stack=2 setting stack = 2 (wait) [klanclos@kpffiuserver ~]$ gshow -s kpfguide fps average stack exptime FPS = 100.0000 frames/second AVERAGE = 50 frames STACK = 2 averaged frames EXPTIME = 1.000000 seconds ...but if I change AVERAGE, EXPTIME reflects the change: [klanclos@kpffiuserver ~]$ modify -s kpfguide average=20 setting average = 20 (wait) [klanclos@kpffiuserver ~]$ gshow -s kpfguide fps average stack exptime FPS = 100.0000 frames/second AVERAGE = 20 frames STACK = 1 averaged frames EXPTIME = 0.200000 seconds Stick to changing EXPTIME and you won't have to worry about it. Changing the frames per second is not recommended, because the tip/tilt system will be consuming this image stream, and it needs to retain full control of what an individual frame looks like. Parameters: exptime ( float ) \u2013 The exposure time in seconds. KTL Keywords Used: kpfguide.EXPTIME Source code in kpf/guider/SetGuiderExpTime.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetGuiderExpTime ( KPFTranslatorFunction ): '''Set the guider exposure time (in seconds) via the kpfguide.EXPTIME keyword. The guider exposure time is governed by several factors. The exposure time controlled here is generated by stacking (averaging) multiple frames as needed to obtain the specified exposure time. Those individual frames are controlled by the FPS, AVERAGE, STACK, and EXPTIME keywords. From Kyle: If you want to tweak an exposure setting, I recommend MAGIQ use the EXPTIME keyword as its preferred knob. This will translate to changing the number of frames averaged together. You can also choose to stack frames, but I doubt that will be necessary. Notice how EXPTIME remains unchanged when I change the STACK keyword: [klanclos@kpffiuserver ~]$ gshow -s kpfguide fps average stack exptime FPS = 100.0000 frames/second AVERAGE = 100 frames STACK = 1 averaged frames EXPTIME = 1.000000 seconds [klanclos@kpffiuserver ~]$ modify -s kpfguide stack=2 setting stack = 2 (wait) [klanclos@kpffiuserver ~]$ gshow -s kpfguide fps average stack exptime FPS = 100.0000 frames/second AVERAGE = 50 frames STACK = 2 averaged frames EXPTIME = 1.000000 seconds ...but if I change AVERAGE, EXPTIME reflects the change: [klanclos@kpffiuserver ~]$ modify -s kpfguide average=20 setting average = 20 (wait) [klanclos@kpffiuserver ~]$ gshow -s kpfguide fps average stack exptime FPS = 100.0000 frames/second AVERAGE = 20 frames STACK = 1 averaged frames EXPTIME = 0.200000 seconds Stick to changing EXPTIME and you won't have to worry about it. Changing the frames per second is not recommended, because the tip/tilt system will be consuming this image stream, and it needs to retain full control of what an individual frame looks like. Args: exptime (float): The exposure time in seconds. KTL Keywords Used: - `kpfguide.EXPTIME` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'exptime' , value_min = 0 ) @classmethod def perform ( cls , args , logger , cfg ): exptimekw = ktl . cache ( 'kpfguide' , 'EXPTIME' ) exptime = args . get ( 'exptime' ) exptimekw . write ( exptime ) @classmethod def post_condition ( cls , args , logger , cfg ): exptol = cfg . getfloat ( 'tolerances' , 'guider_exptime_tolerance' , fallback = 0.01 ) exptimekw = ktl . cache ( 'kpfguide' , 'EXPTIME' ) exptimeread = exptimekw . read ( binary = True ) exptime = args . get ( 'exptime' ) expr = ( f '($kpfguide.EXPTIME >= { exptime - exptol } ) and ' \\ f '($kpfguide.EXPTIME <= { exptime + exptol } )' ) success = ktl . waitFor ( expr , timeout = exptimeread + 1 ) if not success : raise FailedToReachDestination ( exptimekw . read (), exptime ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'exptime' , type = float , help = 'The exposure time in seconds' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetGuiderExpTime"},{"location":"scripts/SetGuiderFPS/","text":"SetGuiderFPS Bases: KPFTranslatorFunction Set the guider FPS (frames per second) via the kpfguide.FPS keyword. Parameters: GuideFPS ( float ) \u2013 Number of frames per second. KTL Keywords Used: kpfguide.FPS Source code in kpf/guider/SetGuiderFPS.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class SetGuiderFPS ( KPFTranslatorFunction ): '''Set the guider FPS (frames per second) via the kpfguide.FPS keyword. Args: GuideFPS (float): Number of frames per second. KTL Keywords Used: - `kpfguide.FPS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'GuideFPS' , value_min = 0.0001 , value_max = 400 ) return True @classmethod def perform ( cls , args , logger , cfg ): fpskw = ktl . cache ( 'kpfguide' , 'FPS' ) fps = args . get ( 'GuideFPS' ) log . debug ( f 'Setting guider FPS to { fps } ' ) fpskw . write ( fps ) @classmethod def post_condition ( cls , args , logger , cfg ): fpstol = cfg . getfloat ( 'tolerances' , 'guider_fps_tolerance' , fallback = 0.01 ) fpskw = ktl . cache ( 'kpfguide' , 'FPS' ) fps = args . get ( 'GuideFPS' ) expr = ( f '($kpfguide.FPS >= { fps - fpstol } ) and ' \\ f '($kpfguide.FPS <= { fps + fpstol } )' ) success = ktl . waitFor ( expr , timeout = 1 ) if not success : raise FailedToReachDestination ( fpskw . read (), fps ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'GuideFPS' , type = float , help = 'The frames per second (FPS)' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetGuiderFPS"},{"location":"scripts/SetGuiderFPS/#setguiderfps","text":"Bases: KPFTranslatorFunction Set the guider FPS (frames per second) via the kpfguide.FPS keyword. Parameters: GuideFPS ( float ) \u2013 Number of frames per second. KTL Keywords Used: kpfguide.FPS Source code in kpf/guider/SetGuiderFPS.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class SetGuiderFPS ( KPFTranslatorFunction ): '''Set the guider FPS (frames per second) via the kpfguide.FPS keyword. Args: GuideFPS (float): Number of frames per second. KTL Keywords Used: - `kpfguide.FPS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'GuideFPS' , value_min = 0.0001 , value_max = 400 ) return True @classmethod def perform ( cls , args , logger , cfg ): fpskw = ktl . cache ( 'kpfguide' , 'FPS' ) fps = args . get ( 'GuideFPS' ) log . debug ( f 'Setting guider FPS to { fps } ' ) fpskw . write ( fps ) @classmethod def post_condition ( cls , args , logger , cfg ): fpstol = cfg . getfloat ( 'tolerances' , 'guider_fps_tolerance' , fallback = 0.01 ) fpskw = ktl . cache ( 'kpfguide' , 'FPS' ) fps = args . get ( 'GuideFPS' ) expr = ( f '($kpfguide.FPS >= { fps - fpstol } ) and ' \\ f '($kpfguide.FPS <= { fps + fpstol } )' ) success = ktl . waitFor ( expr , timeout = 1 ) if not success : raise FailedToReachDestination ( fpskw . read (), fps ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'GuideFPS' , type = float , help = 'The frames per second (FPS)' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetGuiderFPS"},{"location":"scripts/SetGuiderGain/","text":"SetGuiderGain Bases: KPFTranslatorFunction Set the guider gain via the kpfguide.GAIN keyword. Parameters: GuideCamGain ( str ) \u2013 The desired gain. Allowed values: high, medium, or low. KTL Keywords Used: kpfguide.GAIN Source code in kpf/guider/SetGuiderGain.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 class SetGuiderGain ( KPFTranslatorFunction ): '''Set the guider gain via the kpfguide.GAIN keyword. Args: GuideCamGain (str): The desired gain. Allowed values: high, medium, or low. KTL Keywords Used: - `kpfguide.GAIN` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'GuideCamGain' , allowed_values = [ 'high' , 'medium' , 'low' ]) @classmethod def perform ( cls , args , logger , cfg ): gainkw = ktl . cache ( 'kpfguide' , 'GAIN' ) gain = args . get ( 'GuideCamGain' ) log . debug ( f 'Setting guider gain to { gain } ' ) gainkw . write ( gain ) @classmethod def post_condition ( cls , args , logger , cfg ): gainkw = ktl . cache ( 'kpfguide' , 'GAIN' ) gain = args . get ( 'GuideCamGain' ) expr = ( f \"($kpfguide.GAIN == ' { gain } ')\" ) success = ktl . waitFor ( expr , timeout = 1 ) if not success : raise FailedToReachDestination ( gainkw . read (), gain ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'GuideCamGain' , type = str , choices = [ 'high' , 'medium' , 'low' ], help = 'The gain' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetGuiderGain"},{"location":"scripts/SetGuiderGain/#setguidergain","text":"Bases: KPFTranslatorFunction Set the guider gain via the kpfguide.GAIN keyword. Parameters: GuideCamGain ( str ) \u2013 The desired gain. Allowed values: high, medium, or low. KTL Keywords Used: kpfguide.GAIN Source code in kpf/guider/SetGuiderGain.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 class SetGuiderGain ( KPFTranslatorFunction ): '''Set the guider gain via the kpfguide.GAIN keyword. Args: GuideCamGain (str): The desired gain. Allowed values: high, medium, or low. KTL Keywords Used: - `kpfguide.GAIN` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'GuideCamGain' , allowed_values = [ 'high' , 'medium' , 'low' ]) @classmethod def perform ( cls , args , logger , cfg ): gainkw = ktl . cache ( 'kpfguide' , 'GAIN' ) gain = args . get ( 'GuideCamGain' ) log . debug ( f 'Setting guider gain to { gain } ' ) gainkw . write ( gain ) @classmethod def post_condition ( cls , args , logger , cfg ): gainkw = ktl . cache ( 'kpfguide' , 'GAIN' ) gain = args . get ( 'GuideCamGain' ) expr = ( f \"($kpfguide.GAIN == ' { gain } ')\" ) success = ktl . waitFor ( expr , timeout = 1 ) if not success : raise FailedToReachDestination ( gainkw . read (), gain ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'GuideCamGain' , type = str , choices = [ 'high' , 'medium' , 'low' ], help = 'The gain' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetGuiderGain"},{"location":"scripts/SetGuiderOutdir/","text":"SetGuiderOutdir Bases: KPFTranslatorFunction Set the value of the kpfguide.OUTDIR keyword Parameters: outdir ( str ) \u2013 The desired output path. KTL Keywords Used: kpfguide.OUTDIR Source code in kpf/guider/SetGuiderOutdir.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 class SetGuiderOutdir ( KPFTranslatorFunction ): '''Set the value of the kpfguide.OUTDIR keyword Args: outdir (str): The desired output path. KTL Keywords Used: - `kpfguide.OUTDIR` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'outdir' ) @classmethod def perform ( cls , args , logger , cfg ): newoutdir = Path ( args . get ( 'outdir' )) . expanduser () . absolute () kpfguide = ktl . cache ( 'kpfguide' ) kpfguide [ 'OUTDIR' ] . write ( f \" { newoutdir } \" ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'outdir' , type = str , help = 'The desired output path' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetGuiderOutdir"},{"location":"scripts/SetGuiderOutdir/#setguideroutdir","text":"Bases: KPFTranslatorFunction Set the value of the kpfguide.OUTDIR keyword Parameters: outdir ( str ) \u2013 The desired output path. KTL Keywords Used: kpfguide.OUTDIR Source code in kpf/guider/SetGuiderOutdir.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 class SetGuiderOutdir ( KPFTranslatorFunction ): '''Set the value of the kpfguide.OUTDIR keyword Args: outdir (str): The desired output path. KTL Keywords Used: - `kpfguide.OUTDIR` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'outdir' ) @classmethod def perform ( cls , args , logger , cfg ): newoutdir = Path ( args . get ( 'outdir' )) . expanduser () . absolute () kpfguide = ktl . cache ( 'kpfguide' ) kpfguide [ 'OUTDIR' ] . write ( f \" { newoutdir } \" ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'outdir' , type = str , help = 'The desired output path' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetGuiderOutdir"},{"location":"scripts/SetLFCtoAstroComb/","text":"SetLFCtoAstroComb Bases: KPFTranslatorFunction Set the Laser Frequency Comb (LFC) to \"AstroComb\" mode. This should be used during operation of the LFC. KTL Keywords Used: kpfcal.OPERATIONMODE kpfmon.HB_MENLOSTA Scripts Called: kpf.calbench.WaitForLFCReady Source code in kpf/calbench/SetLFCtoAstroComb.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class SetLFCtoAstroComb ( KPFTranslatorFunction ): '''Set the Laser Frequency Comb (LFC) to \"AstroComb\" mode. This should be used during operation of the LFC. KTL Keywords Used: - `kpfcal.OPERATIONMODE` - `kpfmon.HB_MENLOSTA` Scripts Called: - `kpf.calbench.WaitForLFCReady` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): heartbeat = ktl . cache ( 'kpfmon' , 'HB_MENLOSTA' ) hb_success = heartbeat . waitFor ( '== \"OK\"' , timeout = 3 ) if hb_success is False : raise FailedPreCondition ( f \"Menlo heartbeat is not OK: { heartbeat . read () } \" ) lfc_mode = ktl . cache ( 'kpfcal' , 'OPERATIONMODE' ) . read () if lfc_mode not in [ 'AstroComb' , 'StandbyHigh' ]: raise FailedPreCondition ( f \"LFC must be in AstroComb or StandbyHigh: { lfc_mode } \" ) @classmethod def perform ( cls , args , logger , cfg ): lfc_mode = ktl . cache ( 'kpfcal' , 'OPERATIONMODE' ) log . info ( 'Setting LFC to AstroComb' ) lfc_mode . write ( 'AstroComb' ) time_shim = cfg . getfloat ( 'times' , 'LFC_shim_time' , fallback = 10 ) time . sleep ( time_shim ) @classmethod def post_condition ( cls , args , logger , cfg ): success = WaitForLFCReady . execute ({}) if success is not True : raise FailedPostCondition ( 'LFC did not reach expected state' )","title":"SetLFCtoAstroComb"},{"location":"scripts/SetLFCtoAstroComb/#setlfctoastrocomb","text":"Bases: KPFTranslatorFunction Set the Laser Frequency Comb (LFC) to \"AstroComb\" mode. This should be used during operation of the LFC. KTL Keywords Used: kpfcal.OPERATIONMODE kpfmon.HB_MENLOSTA Scripts Called: kpf.calbench.WaitForLFCReady Source code in kpf/calbench/SetLFCtoAstroComb.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class SetLFCtoAstroComb ( KPFTranslatorFunction ): '''Set the Laser Frequency Comb (LFC) to \"AstroComb\" mode. This should be used during operation of the LFC. KTL Keywords Used: - `kpfcal.OPERATIONMODE` - `kpfmon.HB_MENLOSTA` Scripts Called: - `kpf.calbench.WaitForLFCReady` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): heartbeat = ktl . cache ( 'kpfmon' , 'HB_MENLOSTA' ) hb_success = heartbeat . waitFor ( '== \"OK\"' , timeout = 3 ) if hb_success is False : raise FailedPreCondition ( f \"Menlo heartbeat is not OK: { heartbeat . read () } \" ) lfc_mode = ktl . cache ( 'kpfcal' , 'OPERATIONMODE' ) . read () if lfc_mode not in [ 'AstroComb' , 'StandbyHigh' ]: raise FailedPreCondition ( f \"LFC must be in AstroComb or StandbyHigh: { lfc_mode } \" ) @classmethod def perform ( cls , args , logger , cfg ): lfc_mode = ktl . cache ( 'kpfcal' , 'OPERATIONMODE' ) log . info ( 'Setting LFC to AstroComb' ) lfc_mode . write ( 'AstroComb' ) time_shim = cfg . getfloat ( 'times' , 'LFC_shim_time' , fallback = 10 ) time . sleep ( time_shim ) @classmethod def post_condition ( cls , args , logger , cfg ): success = WaitForLFCReady . execute ({}) if success is not True : raise FailedPostCondition ( 'LFC did not reach expected state' )","title":"SetLFCtoAstroComb"},{"location":"scripts/SetLFCtoStandbyHigh/","text":"SetLFCtoStandbyHigh Bases: KPFTranslatorFunction Set the Laser Frequency Comb (LFC) to \"StandbyHigh\" mode. This is the mode which should be set after operation of the LFC for science is complete. KTL Keywords Used: kpfcal.OPERATIONMODE kpfmon.HB_MENLOSTA kpfmon.LFCREADYSTA Source code in kpf/calbench/SetLFCtoStandbyHigh.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 class SetLFCtoStandbyHigh ( KPFTranslatorFunction ): '''Set the Laser Frequency Comb (LFC) to \"StandbyHigh\" mode. This is the mode which should be set after operation of the LFC for science is complete. KTL Keywords Used: - `kpfcal.OPERATIONMODE` - `kpfmon.HB_MENLOSTA` - `kpfmon.LFCREADYSTA` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): heartbeat = ktl . cache ( 'kpfmon' , 'HB_MENLOSTA' ) success = heartbeat . waitFor ( '== \"OK\"' , timeout = 3 ) if success is False : raise FailedPreCondition ( f \"Menlo heartbeat is not OK: { heartbeat . read () } \" ) lfc_mode = ktl . cache ( 'kpfcal' , 'OPERATIONMODE' ) . read () if lfc_mode not in [ 'AstroComb' , 'StandbyHigh' ]: raise FailedPreCondition ( f \"LFC must be in AstroComb: { lfc_mode } \" ) @classmethod def perform ( cls , args , logger , cfg ): lfc_mode = ktl . cache ( 'kpfcal' , 'OPERATIONMODE' ) log . info ( 'Setting LFC to StandbyHigh' ) lfc_mode . write ( 'StandbyHigh' ) time_shim = cfg . getfloat ( 'times' , 'LFC_shim_time' , fallback = 10 ) time . sleep ( time_shim ) @classmethod def post_condition ( cls , args , logger , cfg ): LFCready = ktl . cache ( 'kpfmon' , 'LFCREADYSTA' ) timeout = cfg . getfloat ( 'times' , 'LFC_startup_time' , fallback = 60 ) success = LFCready . waitFor ( '== \"OK\"' , timeout = timeout ) if success is not True : raise FailedPostCondition ( 'kpfmon.LFCREADYSTA is not OK' )","title":"SetLFCtoStandbyHigh"},{"location":"scripts/SetLFCtoStandbyHigh/#setlfctostandbyhigh","text":"Bases: KPFTranslatorFunction Set the Laser Frequency Comb (LFC) to \"StandbyHigh\" mode. This is the mode which should be set after operation of the LFC for science is complete. KTL Keywords Used: kpfcal.OPERATIONMODE kpfmon.HB_MENLOSTA kpfmon.LFCREADYSTA Source code in kpf/calbench/SetLFCtoStandbyHigh.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 class SetLFCtoStandbyHigh ( KPFTranslatorFunction ): '''Set the Laser Frequency Comb (LFC) to \"StandbyHigh\" mode. This is the mode which should be set after operation of the LFC for science is complete. KTL Keywords Used: - `kpfcal.OPERATIONMODE` - `kpfmon.HB_MENLOSTA` - `kpfmon.LFCREADYSTA` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): heartbeat = ktl . cache ( 'kpfmon' , 'HB_MENLOSTA' ) success = heartbeat . waitFor ( '== \"OK\"' , timeout = 3 ) if success is False : raise FailedPreCondition ( f \"Menlo heartbeat is not OK: { heartbeat . read () } \" ) lfc_mode = ktl . cache ( 'kpfcal' , 'OPERATIONMODE' ) . read () if lfc_mode not in [ 'AstroComb' , 'StandbyHigh' ]: raise FailedPreCondition ( f \"LFC must be in AstroComb: { lfc_mode } \" ) @classmethod def perform ( cls , args , logger , cfg ): lfc_mode = ktl . cache ( 'kpfcal' , 'OPERATIONMODE' ) log . info ( 'Setting LFC to StandbyHigh' ) lfc_mode . write ( 'StandbyHigh' ) time_shim = cfg . getfloat ( 'times' , 'LFC_shim_time' , fallback = 10 ) time . sleep ( time_shim ) @classmethod def post_condition ( cls , args , logger , cfg ): LFCready = ktl . cache ( 'kpfmon' , 'LFCREADYSTA' ) timeout = cfg . getfloat ( 'times' , 'LFC_startup_time' , fallback = 60 ) success = LFCready . waitFor ( '== \"OK\"' , timeout = timeout ) if success is not True : raise FailedPostCondition ( 'kpfmon.LFCREADYSTA is not OK' )","title":"SetLFCtoStandbyHigh"},{"location":"scripts/SetMasterBiasToDefault/","text":"SetMasterBiasToDefault Bases: KPFTranslatorFunction Sets the master bias file for the exposure meter to the default value KTL Keywords Used: kpf_expmeter.BIAS_FILE Source code in kpf/expmeter/SetMasterBiasToDefault.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class SetMasterBiasToDefault ( KPFTranslatorFunction ): '''Sets the master bias file for the exposure meter to the default value KTL Keywords Used: - `kpf_expmeter.BIAS_FILE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) default_file = '/kroot/rel/default/data/kpf_expmeter/full_bias.fits' log . debug ( f \"Setting master bias file to { default_file } \" ) kpf_expmeter [ 'BIAS_FILE' ] . write ( default_file ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"SetMasterBiasToDefault"},{"location":"scripts/SetMasterBiasToDefault/#setmasterbiastodefault","text":"Bases: KPFTranslatorFunction Sets the master bias file for the exposure meter to the default value KTL Keywords Used: kpf_expmeter.BIAS_FILE Source code in kpf/expmeter/SetMasterBiasToDefault.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class SetMasterBiasToDefault ( KPFTranslatorFunction ): '''Sets the master bias file for the exposure meter to the default value KTL Keywords Used: - `kpf_expmeter.BIAS_FILE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) default_file = '/kroot/rel/default/data/kpf_expmeter/full_bias.fits' log . debug ( f \"Setting master bias file to { default_file } \" ) kpf_expmeter [ 'BIAS_FILE' ] . write ( default_file ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"SetMasterBiasToDefault"},{"location":"scripts/SetND/","text":"SetND Bases: KPFTranslatorFunction Set the filter in the ND1 & ND2 filter wheels via the kpfcal.ND1POS and kpfcal.ND2POS keywords. Parameters: CalND1 ( str ) \u2013 The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: OD 0.1 , OD 1.0 , OD 1.3 , OD 2.0 , OD 3.0 , OD 4.0 CalND2 ( str ) \u2013 The neutral density filter to put in the first filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: OD 0.1 , OD 0.3 , OD 0.5 , OD 0.8 , OD 1.0 , OD 4.0 wait ( bool ) \u2013 Wait for move to complete before returning? default: True Scripts Called: kpf.calbench.SetND1 kpf.calbench.SetND2 Source code in kpf/calbench/SetND.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetND ( KPFTranslatorFunction ): '''Set the filter in the ND1 & ND2 filter wheels via the `kpfcal.ND1POS` and `kpfcal.ND2POS` keywords. Args: CalND1 (str): The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: `OD 0.1`, `OD 1.0`, `OD 1.3`, `OD 2.0`, `OD 3.0`, `OD 4.0` CalND2 (str): The neutral density filter to put in the first filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: `OD 0.1`, `OD 0.3`, `OD 0.5`, `OD 0.8`, `OD 1.0`, `OD 4.0` wait (bool): Wait for move to complete before returning? default: True Scripts Called: - `kpf.calbench.SetND1` - `kpf.calbench.SetND2` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): SetND1 . execute ( args ) SetND2 . execute ( args ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalND1' , type = str , choices = [ \"OD 0.1\" , \"OD 1.0\" , \"OD 1.3\" , \"OD 2.0\" , \"OD 3.0\" , \"OD 4.0\" ], help = 'ND1 Filter to use.' ) parser . add_argument ( 'CalND2' , type = str , choices = [ \"OD 0.1\" , \"OD 0.3\" , \"OD 0.5\" , \"OD 0.8\" , \"OD 1.0\" , \"OD 4.0\" ], help = 'ND2 Filter to use.' ) parser . add_argument ( \"--nowait\" , dest = \"wait\" , default = True , action = \"store_false\" , help = \"Send move and return immediately?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetND"},{"location":"scripts/SetND/#setnd","text":"Bases: KPFTranslatorFunction Set the filter in the ND1 & ND2 filter wheels via the kpfcal.ND1POS and kpfcal.ND2POS keywords. Parameters: CalND1 ( str ) \u2013 The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: OD 0.1 , OD 1.0 , OD 1.3 , OD 2.0 , OD 3.0 , OD 4.0 CalND2 ( str ) \u2013 The neutral density filter to put in the first filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: OD 0.1 , OD 0.3 , OD 0.5 , OD 0.8 , OD 1.0 , OD 4.0 wait ( bool ) \u2013 Wait for move to complete before returning? default: True Scripts Called: kpf.calbench.SetND1 kpf.calbench.SetND2 Source code in kpf/calbench/SetND.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetND ( KPFTranslatorFunction ): '''Set the filter in the ND1 & ND2 filter wheels via the `kpfcal.ND1POS` and `kpfcal.ND2POS` keywords. Args: CalND1 (str): The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: `OD 0.1`, `OD 1.0`, `OD 1.3`, `OD 2.0`, `OD 3.0`, `OD 4.0` CalND2 (str): The neutral density filter to put in the first filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: `OD 0.1`, `OD 0.3`, `OD 0.5`, `OD 0.8`, `OD 1.0`, `OD 4.0` wait (bool): Wait for move to complete before returning? default: True Scripts Called: - `kpf.calbench.SetND1` - `kpf.calbench.SetND2` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): SetND1 . execute ( args ) SetND2 . execute ( args ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalND1' , type = str , choices = [ \"OD 0.1\" , \"OD 1.0\" , \"OD 1.3\" , \"OD 2.0\" , \"OD 3.0\" , \"OD 4.0\" ], help = 'ND1 Filter to use.' ) parser . add_argument ( 'CalND2' , type = str , choices = [ \"OD 0.1\" , \"OD 0.3\" , \"OD 0.5\" , \"OD 0.8\" , \"OD 1.0\" , \"OD 4.0\" ], help = 'ND2 Filter to use.' ) parser . add_argument ( \"--nowait\" , dest = \"wait\" , default = True , action = \"store_false\" , help = \"Send move and return immediately?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetND"},{"location":"scripts/SetND1/","text":"SetND1 Bases: KPFTranslatorFunction Set the filter in the ND1 filter wheel (the one at the output of the octagon) via the kpfcal.ND1POS keyword. Parameters: CalND1 ( str ) \u2013 The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: OD 0.1 , OD 1.0 , OD 1.3 , OD 2.0 , OD 3.0 , OD 4.0 wait ( bool ) \u2013 Wait for move to complete before returning? default: True KTL Keywords Used: kpfcal.ND1POS Source code in kpf/calbench/SetND1.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetND1 ( KPFTranslatorFunction ): '''Set the filter in the ND1 filter wheel (the one at the output of the octagon) via the `kpfcal.ND1POS` keyword. Args: CalND1 (str): The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: `OD 0.1`, `OD 1.0`, `OD 1.3`, `OD 2.0`, `OD 3.0`, `OD 4.0` wait (bool): Wait for move to complete before returning? default: True KTL Keywords Used: - `kpfcal.ND1POS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'ND1POS' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) check_input ( args , 'CalND1' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): target = args . get ( 'CalND1' ) log . debug ( f \"Setting ND1POS to { target } \" ) kpfcal = ktl . cache ( 'kpfcal' ) kpfcal [ 'ND1POS' ] . write ( target , wait = args . get ( 'wait' , True )) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'nd_move_time' , fallback = 20 ) ND1target = args . get ( 'CalND1' ) ND1POS = ktl . cache ( 'kpfcal' , 'ND1POS' ) if ND1POS . waitFor ( f \"== ' { ND1target } '\" , timeout = timeout ) == False : raise FailedToReachDestination ( ND1POS . read (), ND1target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalND1' , type = str , choices = [ \"OD 0.1\" , \"OD 1.0\" , \"OD 1.3\" , \"OD 2.0\" , \"OD 3.0\" , \"OD 4.0\" ], help = 'ND1 Filter to use.' ) parser . add_argument ( \"--nowait\" , dest = \"wait\" , default = True , action = \"store_false\" , help = \"Send move and return immediately?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetND1"},{"location":"scripts/SetND1/#setnd1","text":"Bases: KPFTranslatorFunction Set the filter in the ND1 filter wheel (the one at the output of the octagon) via the kpfcal.ND1POS keyword. Parameters: CalND1 ( str ) \u2013 The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: OD 0.1 , OD 1.0 , OD 1.3 , OD 2.0 , OD 3.0 , OD 4.0 wait ( bool ) \u2013 Wait for move to complete before returning? default: True KTL Keywords Used: kpfcal.ND1POS Source code in kpf/calbench/SetND1.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetND1 ( KPFTranslatorFunction ): '''Set the filter in the ND1 filter wheel (the one at the output of the octagon) via the `kpfcal.ND1POS` keyword. Args: CalND1 (str): The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: `OD 0.1`, `OD 1.0`, `OD 1.3`, `OD 2.0`, `OD 3.0`, `OD 4.0` wait (bool): Wait for move to complete before returning? default: True KTL Keywords Used: - `kpfcal.ND1POS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'ND1POS' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) check_input ( args , 'CalND1' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): target = args . get ( 'CalND1' ) log . debug ( f \"Setting ND1POS to { target } \" ) kpfcal = ktl . cache ( 'kpfcal' ) kpfcal [ 'ND1POS' ] . write ( target , wait = args . get ( 'wait' , True )) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'nd_move_time' , fallback = 20 ) ND1target = args . get ( 'CalND1' ) ND1POS = ktl . cache ( 'kpfcal' , 'ND1POS' ) if ND1POS . waitFor ( f \"== ' { ND1target } '\" , timeout = timeout ) == False : raise FailedToReachDestination ( ND1POS . read (), ND1target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalND1' , type = str , choices = [ \"OD 0.1\" , \"OD 1.0\" , \"OD 1.3\" , \"OD 2.0\" , \"OD 3.0\" , \"OD 4.0\" ], help = 'ND1 Filter to use.' ) parser . add_argument ( \"--nowait\" , dest = \"wait\" , default = True , action = \"store_false\" , help = \"Send move and return immediately?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetND1"},{"location":"scripts/SetND2/","text":"SetND2 Bases: KPFTranslatorFunction Set the filter in the ND2 filter wheel (the one at the output of the octagon) via the kpfcal.ND2POS keyword. Parameters: CalND2 ( str ) \u2013 The neutral density filter to put in the first filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: OD 0.1 , OD 0.3 , OD 0.5 , OD 0.8 , OD 1.0 , OD 4.0 wait ( bool ) \u2013 Wait for move to complete before returning? default: True KTL Keywords Used: kpfcal.ND2POS Source code in kpf/calbench/SetND2.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetND2 ( KPFTranslatorFunction ): '''Set the filter in the ND2 filter wheel (the one at the output of the octagon) via the `kpfcal.ND2POS` keyword. Args: CalND2 (str): The neutral density filter to put in the first filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: `OD 0.1`, `OD 0.3`, `OD 0.5`, `OD 0.8`, `OD 1.0`, `OD 4.0` wait (bool): Wait for move to complete before returning? default: True KTL Keywords Used: - `kpfcal.ND2POS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'ND2POS' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) check_input ( args , 'CalND2' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): target = args . get ( 'CalND2' ) log . debug ( f \"Setting ND2POS to { target } \" ) kpfcal = ktl . cache ( 'kpfcal' ) kpfcal [ 'ND2POS' ] . write ( target , wait = args . get ( 'wait' , True )) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'nd_move_time' , fallback = 20 ) ND2target = args . get ( 'CalND2' ) ND2POS = ktl . cache ( 'kpfcal' , 'ND2POS' ) if ND2POS . waitFor ( f \"== ' { ND2target } '\" , timeout = timeout ) == False : raise FailedToReachDestination ( ND2POS . read (), ND2target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalND2' , type = str , choices = [ \"OD 0.1\" , \"OD 0.3\" , \"OD 0.5\" , \"OD 0.8\" , \"OD 1.0\" , \"OD 4.0\" ], help = 'ND2 Filter to use.' ) parser . add_argument ( \"--nowait\" , dest = \"wait\" , default = True , action = \"store_false\" , help = \"Send move and return immediately?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetND2"},{"location":"scripts/SetND2/#setnd2","text":"Bases: KPFTranslatorFunction Set the filter in the ND2 filter wheel (the one at the output of the octagon) via the kpfcal.ND2POS keyword. Parameters: CalND2 ( str ) \u2013 The neutral density filter to put in the first filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: OD 0.1 , OD 0.3 , OD 0.5 , OD 0.8 , OD 1.0 , OD 4.0 wait ( bool ) \u2013 Wait for move to complete before returning? default: True KTL Keywords Used: kpfcal.ND2POS Source code in kpf/calbench/SetND2.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetND2 ( KPFTranslatorFunction ): '''Set the filter in the ND2 filter wheel (the one at the output of the octagon) via the `kpfcal.ND2POS` keyword. Args: CalND2 (str): The neutral density filter to put in the first filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: `OD 0.1`, `OD 0.3`, `OD 0.5`, `OD 0.8`, `OD 1.0`, `OD 4.0` wait (bool): Wait for move to complete before returning? default: True KTL Keywords Used: - `kpfcal.ND2POS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'ND2POS' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) check_input ( args , 'CalND2' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): target = args . get ( 'CalND2' ) log . debug ( f \"Setting ND2POS to { target } \" ) kpfcal = ktl . cache ( 'kpfcal' ) kpfcal [ 'ND2POS' ] . write ( target , wait = args . get ( 'wait' , True )) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'nd_move_time' , fallback = 20 ) ND2target = args . get ( 'CalND2' ) ND2POS = ktl . cache ( 'kpfcal' , 'ND2POS' ) if ND2POS . waitFor ( f \"== ' { ND2target } '\" , timeout = timeout ) == False : raise FailedToReachDestination ( ND2POS . read (), ND2target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalND2' , type = str , choices = [ \"OD 0.1\" , \"OD 0.3\" , \"OD 0.5\" , \"OD 0.8\" , \"OD 1.0\" , \"OD 4.0\" ], help = 'ND2 Filter to use.' ) parser . add_argument ( \"--nowait\" , dest = \"wait\" , default = True , action = \"store_false\" , help = \"Send move and return immediately?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetND2"},{"location":"scripts/SetObject/","text":"SetObject Bases: KPFTranslatorFunction Sets the OBJECT keyword for the science detectors in the kpfexpose keyword service. ARGS: :Object: str The desired object keyword value. Source code in kpf/spectrograph/SetObject.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 class SetObject ( KPFTranslatorFunction ): '''Sets the OBJECT keyword for the science detectors in the kpfexpose keyword service. ARGS: ===== :Object: `str` The desired object keyword value. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) obj = args . get ( 'Object' , '' ) if obj is None : obj = '' log . debug ( f \"Setting OBJECT to ' { obj } '\" ) kpfexpose [ 'OBJECT' ] . write ( obj ) time_shim = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.1 ) time . sleep ( time_shim ) @classmethod def post_condition ( cls , args , logger , cfg ): obj = args . get ( 'Object' , '' ) if obj is None : obj = '' timeout = cfg . getfloat ( 'times' , 'kpfexpose_response_time' , fallback = 1 ) expr = f \"($kpfexpose.OBJECT == ' { obj } ')\" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : objectkw = ktl . cache ( 'kpfexpose' , 'OBJECT' ) raise FailedToReachDestination ( objectkw . read (), obj ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'Object' , type = str , help = 'The OBJECT keyword' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetObject"},{"location":"scripts/SetObject/#setobject","text":"Bases: KPFTranslatorFunction Sets the OBJECT keyword for the science detectors in the kpfexpose keyword service.","title":"SetObject"},{"location":"scripts/SetObject/#kpf.spectrograph.SetObject.SetObject--args","text":":Object: str The desired object keyword value. Source code in kpf/spectrograph/SetObject.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 class SetObject ( KPFTranslatorFunction ): '''Sets the OBJECT keyword for the science detectors in the kpfexpose keyword service. ARGS: ===== :Object: `str` The desired object keyword value. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) obj = args . get ( 'Object' , '' ) if obj is None : obj = '' log . debug ( f \"Setting OBJECT to ' { obj } '\" ) kpfexpose [ 'OBJECT' ] . write ( obj ) time_shim = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.1 ) time . sleep ( time_shim ) @classmethod def post_condition ( cls , args , logger , cfg ): obj = args . get ( 'Object' , '' ) if obj is None : obj = '' timeout = cfg . getfloat ( 'times' , 'kpfexpose_response_time' , fallback = 1 ) expr = f \"($kpfexpose.OBJECT == ' { obj } ')\" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : objectkw = ktl . cache ( 'kpfexpose' , 'OBJECT' ) raise FailedToReachDestination ( objectkw . read (), obj ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'Object' , type = str , help = 'The OBJECT keyword' ) return super () . add_cmdline_args ( parser , cfg )","title":"ARGS:"},{"location":"scripts/SetObserver/","text":"SetObserver Bases: KPFTranslatorFunction Sets the OBSERVER keyword for the science detectors in the kpfexpose keyword service. ARGS: :observer: str The desired value of the OBSERVER keyword. Source code in kpf/spectrograph/SetObserver.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class SetObserver ( KPFTranslatorFunction ): '''Sets the OBSERVER keyword for the science detectors in the kpfexpose keyword service. ARGS: ===== :observer: `str` The desired value of the OBSERVER keyword. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'observer' ) @classmethod def perform ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) observer = args . get ( 'observer' ) log . info ( f \"Setting OBSERVER to { observer } \" ) kpfexpose [ 'OBSERVER' ] . write ( observer ) time_shim = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.1 ) time . sleep ( time_shim ) @classmethod def post_condition ( cls , args , logger , cfg ): observer = args . get ( 'observer' ) timeout = cfg . getfloat ( 'times' , 'kpfexpose_response_time' , fallback = 1 ) expr = f '($kpfexpose.OBSERVER == \" { observer } \")' success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : observerkw = ktl . cache ( 'kpfexpose' , 'OBSERVER' ) raise FailedToReachDestination ( observerkw . read () . strip (), observer . strip ()) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'observer' , type = str , help = 'The OBSERVER keyword' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetObserver"},{"location":"scripts/SetObserver/#setobserver","text":"Bases: KPFTranslatorFunction Sets the OBSERVER keyword for the science detectors in the kpfexpose keyword service.","title":"SetObserver"},{"location":"scripts/SetObserver/#kpf.spectrograph.SetObserver.SetObserver--args","text":":observer: str The desired value of the OBSERVER keyword. Source code in kpf/spectrograph/SetObserver.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class SetObserver ( KPFTranslatorFunction ): '''Sets the OBSERVER keyword for the science detectors in the kpfexpose keyword service. ARGS: ===== :observer: `str` The desired value of the OBSERVER keyword. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'observer' ) @classmethod def perform ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) observer = args . get ( 'observer' ) log . info ( f \"Setting OBSERVER to { observer } \" ) kpfexpose [ 'OBSERVER' ] . write ( observer ) time_shim = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.1 ) time . sleep ( time_shim ) @classmethod def post_condition ( cls , args , logger , cfg ): observer = args . get ( 'observer' ) timeout = cfg . getfloat ( 'times' , 'kpfexpose_response_time' , fallback = 1 ) expr = f '($kpfexpose.OBSERVER == \" { observer } \")' success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : observerkw = ktl . cache ( 'kpfexpose' , 'OBSERVER' ) raise FailedToReachDestination ( observerkw . read () . strip (), observer . strip ()) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'observer' , type = str , help = 'The OBSERVER keyword' ) return super () . add_cmdline_args ( parser , cfg )","title":"ARGS:"},{"location":"scripts/SetObserverFromSchedule/","text":"SetObserverFromSchedule Bases: KPFTranslatorFunction Look up the telescope schedule and try to determine the observer names based on the current date and the scheduled programs. If only one KPF program is on the schedule, the script will use that to set the observer names. If multiple programs are on the schedule, it will use the progname input (see below) or query the user if no progname is given. ARGS: :progname: str The program name to set if a choice is needed. Source code in kpf/utils/SetObserverFromSchedule.py 17 18 19 20 21 22 23 24 25 26 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 class SetObserverFromSchedule ( KPFTranslatorFunction ): '''Look up the telescope schedule and try to determine the observer names based on the current date and the scheduled programs. If only one KPF program is on the schedule, the script will use that to set the observer names. If multiple programs are on the schedule, it will use the progname input (see below) or query the user if no progname is given. ARGS: ===== :progname: `str` The program name to set if a choice is needed. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): utnow = datetime . utcnow () date = utnow - timedelta ( days = 1 ) date_str = date . strftime ( '%Y-%m- %d ' ) KPF_programs = [ s for s in get_schedule ( date_str , 1 ) if s [ 'Instrument' ] == 'KPF' ] nKPFprograms = len ( KPF_programs ) log . debug ( f \"Found { nKPFprograms } KPF programs in schedule for tonight\" ) project_codes = [ p [ 'ProjCode' ] for p in KPF_programs ] # Look at the schedule to find programs scheduled for tonight if nKPFprograms == 0 : log . warning ( f \"No KPF programs found on schedule\" ) progname = None elif nKPFprograms == 1 : progname = KPF_programs [ 0 ][ 'ProjCode' ] elif nKPFprograms > 1 : progname = args . get ( 'progname' , None ) if progname is None : print () print ( f \"########################################\" ) print ( f \" Found { nKPFprograms } KPF programs for tonight:\" ) for project_code in project_codes : print ( f \" { project_code } \" ) print ( f \" Please enter the program ID for your observations:\" ) print ( f \"########################################\" ) print () progname = input () if progname . strip () not in project_codes : log . warning ( f \"Project code { progname } not on schedule\" ) # Set the program if progname is None : time . sleep ( 0.5 ) # try time shim for log line print () print ( f \" Please enter the program ID for your observations:\" ) print () progname = input () if progname == '' : log . info ( 'No progname specified' ) else : SetProgram . execute ({ 'progname' : progname }) # Set Observers this_program = [ p for p in KPF_programs if p [ 'ProjCode' ] == progname ] if len ( this_program ) > 0 : observers = this_program [ 0 ][ 'Observers' ] else : print () print ( f \" Please enter the observer names:\" ) print () observers = input () log . info ( f \"Setting observer list: { observers } \" ) SetObserver . execute ({ 'observer' : observers }) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"SetObserverFromSchedule"},{"location":"scripts/SetObserverFromSchedule/#setobserverfromschedule","text":"Bases: KPFTranslatorFunction Look up the telescope schedule and try to determine the observer names based on the current date and the scheduled programs. If only one KPF program is on the schedule, the script will use that to set the observer names. If multiple programs are on the schedule, it will use the progname input (see below) or query the user if no progname is given.","title":"SetObserverFromSchedule"},{"location":"scripts/SetObserverFromSchedule/#kpf.utils.SetObserverFromSchedule.SetObserverFromSchedule--args","text":":progname: str The program name to set if a choice is needed. Source code in kpf/utils/SetObserverFromSchedule.py 17 18 19 20 21 22 23 24 25 26 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 class SetObserverFromSchedule ( KPFTranslatorFunction ): '''Look up the telescope schedule and try to determine the observer names based on the current date and the scheduled programs. If only one KPF program is on the schedule, the script will use that to set the observer names. If multiple programs are on the schedule, it will use the progname input (see below) or query the user if no progname is given. ARGS: ===== :progname: `str` The program name to set if a choice is needed. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): utnow = datetime . utcnow () date = utnow - timedelta ( days = 1 ) date_str = date . strftime ( '%Y-%m- %d ' ) KPF_programs = [ s for s in get_schedule ( date_str , 1 ) if s [ 'Instrument' ] == 'KPF' ] nKPFprograms = len ( KPF_programs ) log . debug ( f \"Found { nKPFprograms } KPF programs in schedule for tonight\" ) project_codes = [ p [ 'ProjCode' ] for p in KPF_programs ] # Look at the schedule to find programs scheduled for tonight if nKPFprograms == 0 : log . warning ( f \"No KPF programs found on schedule\" ) progname = None elif nKPFprograms == 1 : progname = KPF_programs [ 0 ][ 'ProjCode' ] elif nKPFprograms > 1 : progname = args . get ( 'progname' , None ) if progname is None : print () print ( f \"########################################\" ) print ( f \" Found { nKPFprograms } KPF programs for tonight:\" ) for project_code in project_codes : print ( f \" { project_code } \" ) print ( f \" Please enter the program ID for your observations:\" ) print ( f \"########################################\" ) print () progname = input () if progname . strip () not in project_codes : log . warning ( f \"Project code { progname } not on schedule\" ) # Set the program if progname is None : time . sleep ( 0.5 ) # try time shim for log line print () print ( f \" Please enter the program ID for your observations:\" ) print () progname = input () if progname == '' : log . info ( 'No progname specified' ) else : SetProgram . execute ({ 'progname' : progname }) # Set Observers this_program = [ p for p in KPF_programs if p [ 'ProjCode' ] == progname ] if len ( this_program ) > 0 : observers = this_program [ 0 ][ 'Observers' ] else : print () print ( f \" Please enter the observer names:\" ) print () observers = input () log . info ( f \"Setting observer list: { observers } \" ) SetObserver . execute ({ 'observer' : observers }) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"ARGS:"},{"location":"scripts/SetOutdirs/","text":"SetOutdirs Bases: KPFTranslatorFunction Set output directories for all detectors based on the current date. ARGS: None Source code in kpf/utils/SetOutdirs.py 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 class SetOutdirs ( KPFTranslatorFunction ): '''Set output directories for all detectors based on the current date. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): log . info ( f \"SetOutdirs invoked\" ) utnow = datetime . utcnow () date = utnow - timedelta ( days = 1 ) date_str = date . strftime ( '%Y%b %d ' ) . lower () outdir = Path ( f \"/s/sdata1701/ { os . getlogin () } / { date_str } \" ) magiq_outdir = Path ( f \"/s/sdata1701/kpfguide/ { date_str } \" ) log . debug ( f \"base outdir: { outdir } \" ) log . debug ( f \"magiq outdir: { magiq_outdir } \" ) if args . get ( 'CRED2' , True ) is True : log . info ( f \"Setting guider OUTDIR to { magiq_outdir } \" ) guide_outdir = ktl . cache ( 'kpfguide' , 'OUTDIR' ) try : guide_outdir . write ( f \" { magiq_outdir } \" ) except Exception as e : log . error ( f \"ERROR setting guider outdir\" ) log . error ( e ) log . info ( f \"Setting guider TRIGOUTDIR to { outdir / 'CRED2' } \" ) trig_outdir = ktl . cache ( 'kpfguide' , 'TRIGOUTDIR' ) try : trig_outdir . write ( f \" { outdir / 'CRED2' } \" ) except Exception as e : log . error ( f \"ERROR setting guider TRIGOUTDIR\" ) log . error ( e ) kpffvc = ktl . cache ( 'kpffvc' ) if args . get ( 'FVC1' , True ) is True : log . info ( f \"Setting FVC1 OUTDIR to { outdir / 'FVC1' } \" ) try : kpffvc [ 'SCIOUTDIR' ] . write ( f \" { outdir / 'FVC1' } \" ) except Exception as e : log . error ( f \"ERROR setting SCI FVC outdir\" ) log . error ( e ) if args . get ( 'FVC2' , True ) is True : log . info ( f \"Setting FVC2 OUTDIR to { outdir / 'FVC2' } \" ) try : kpffvc [ 'CAHKOUTDIR' ] . write ( f \" { outdir / 'FVC2' } \" ) except Exception as e : log . error ( f \"ERROR setting CAHK FVC outdir\" ) log . error ( e ) if args . get ( 'FVC3' , True ) is True : log . info ( f \"Setting FVC3 OUTDIR to { outdir / 'FVC3' } \" ) try : kpffvc [ 'CALOUTDIR' ] . write ( f \" { outdir / 'FVC3' } \" ) except Exception as e : log . error ( f \"ERROR setting CAL FVC outdir\" ) log . error ( e ) if args . get ( 'FVC4' , True ) is True : log . info ( f \"Setting FVC4 OUTDIR to { outdir / 'FVC4' } \" ) try : kpffvc [ 'EXTOUTDIR' ] . write ( f \" { outdir / 'FVC4' } \" ) except Exception as e : log . error ( f \"ERROR setting EXT FVC outdir\" ) log . error ( e ) if args . get ( 'ExpMeter' , True ) is True : expmeter_outdir = outdir / 'ExpMeter' log . info ( f \"Setting exposure meter DATADIR to { expmeter_outdir } \" ) kpf_expmeter_outdir = ktl . cache ( 'kpf_expmeter' , 'DATADIR' ) try : kpf_expmeter_outdir . write ( f \" { expmeter_outdir } \" ) except Exception as e : log . error ( f \"ERROR setting ExpMeter outdir\" ) log . error ( e ) if args . get ( 'CaHK' , True ) is True : cahk_outdir = outdir / 'CaHK' log . info ( f \"Setting CaHK RECORDDIR to { cahk_outdir } \" ) kpf_hk_outdir = ktl . cache ( 'kpf_hk' , 'RECORDDIR' ) try : kpf_hk_outdir . write ( f \" { cahk_outdir } \" ) except Exception as e : log . error ( f \"ERROR setting CaHK outdir\" ) log . error ( e ) if args . get ( 'Green' , True ) is True : green_outdir = outdir / 'Green' log . info ( f \"Setting Green FITSDIR to { green_outdir } \" ) kpfgreen_outdir = ktl . cache ( 'kpfgreen' , 'FITSDIR' ) try : kpfgreen_outdir . write ( f \" { green_outdir } \" ) except Exception as e : log . error ( f \"ERROR setting Green outdir\" ) log . error ( e ) if args . get ( 'Red' , True ) is True : red_outdir = outdir / 'Red' log . info ( f \"Setting Red FITSDIR to { red_outdir } \" ) kpfred_outdir = ktl . cache ( 'kpfred' , 'FITSDIR' ) try : kpfred_outdir . write ( f \" { red_outdir } \" ) except Exception as e : log . error ( f \"ERROR setting Red outdir\" ) log . error ( e ) if args . get ( 'L0' , True ) is True : L0_outdir = outdir / 'L0' log . info ( f \"Setting kpfasemble OUTDIR to { L0_outdir } \" ) kpfassemble_outdir = ktl . cache ( 'kpfassemble' , 'OUTDIR' ) try : kpfassemble_outdir . write ( f \" { L0_outdir } \" ) except Exception as e : log . error ( f \"ERROR setting kpfasemble outdir\" ) log . error ( e ) @classmethod def post_condition ( cls , args , logger , cfg ): utnow = datetime . utcnow () date = utnow - timedelta ( days = 1 ) date_str = date . strftime ( '%Y%b %d ' ) . lower () outdir = Path ( f \"/s/sdata1701/ { os . getlogin () } / { date_str } \" ) tests = [] if args . get ( 'CRED2' , True ) is True : expr = f \"$kpfguide.OUTDIR == '/s/sdata1701/kpfguide'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'CRED2' , True ) is True : expr = f \"$kpfguide.TRIGOUTDIR == ' { outdir } /CRED2'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'FVC1' , True ) is True : expr = f \"$kpffvc.SCIOUTDIR == ' { outdir } /FVC1'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'FVC2' , True ) is True : expr = f \"$kpffvc.CAHKOUTDIR == ' { outdir } /FVC2'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'FVC3' , True ) is True : expr = f \"$kpffvc.CALOUTDIR == ' { outdir } /FVC3'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'FVC4' , False ) is True : expr = f \"$kpffvc.EXTOUTDIR == ' { outdir } /FVC4'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'ExpMeter' , True ) is True : expr = f \"$kpf_expmeter.DATADIR == ' { outdir } /ExpMeter'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'CaHK' , True ) is True : expr = f \"$kpf_hk.RECORDDIR == ' { outdir } /CaHK'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'Green' , True ) is True : expr = f \"$kpfgreen.FITSDIR == ' { outdir } /Green'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'Red' , True ) is True : expr = f \"$kpfred.FITSDIR == ' { outdir } /Red'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'L0' , True ) is True : expr = f \"$kpfassemble.OUTDIR == ' { outdir } /L0'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) return np . all ( np . array ( tests )) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser = cls . _add_bool_arg ( parser , 'CRED2' , 'Set CRED2 OUTDIR (kpfguide.OUTDIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'FVC1' , 'Set FVC1 OUTDIR (kpffvc.SCIOUTDIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'FVC2' , 'Set FVC2 OUTDIR (kpffvc.CAHKOUTDIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'FVC3' , 'Set FVC3 OUTDIR (kpffvc.CALOUTDIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'FVC4' , 'Set FVC4 OUTDIR (kpffvc.EXTOUTDIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'ExpMeter' , 'Set ExpMeter OUTDIR (kpf_expmeter.DATADIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'CaHK' , 'Set CaHK OUTDIR (kpf_hk.RECORDDIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'Green' , 'Set Green OUTDIR (kpfgreen.FITSDIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'Red' , 'Set Red OUTDIR (kpfred.FITSDIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'L0' , 'Set Red OUTDIR (kpfassemble.OUTDIR)?' , default = True ) return super () . add_cmdline_args ( parser , cfg )","title":"SetOutdirs"},{"location":"scripts/SetOutdirs/#setoutdirs","text":"Bases: KPFTranslatorFunction Set output directories for all detectors based on the current date.","title":"SetOutdirs"},{"location":"scripts/SetOutdirs/#kpf.utils.SetOutdirs.SetOutdirs--args","text":"None Source code in kpf/utils/SetOutdirs.py 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 class SetOutdirs ( KPFTranslatorFunction ): '''Set output directories for all detectors based on the current date. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): log . info ( f \"SetOutdirs invoked\" ) utnow = datetime . utcnow () date = utnow - timedelta ( days = 1 ) date_str = date . strftime ( '%Y%b %d ' ) . lower () outdir = Path ( f \"/s/sdata1701/ { os . getlogin () } / { date_str } \" ) magiq_outdir = Path ( f \"/s/sdata1701/kpfguide/ { date_str } \" ) log . debug ( f \"base outdir: { outdir } \" ) log . debug ( f \"magiq outdir: { magiq_outdir } \" ) if args . get ( 'CRED2' , True ) is True : log . info ( f \"Setting guider OUTDIR to { magiq_outdir } \" ) guide_outdir = ktl . cache ( 'kpfguide' , 'OUTDIR' ) try : guide_outdir . write ( f \" { magiq_outdir } \" ) except Exception as e : log . error ( f \"ERROR setting guider outdir\" ) log . error ( e ) log . info ( f \"Setting guider TRIGOUTDIR to { outdir / 'CRED2' } \" ) trig_outdir = ktl . cache ( 'kpfguide' , 'TRIGOUTDIR' ) try : trig_outdir . write ( f \" { outdir / 'CRED2' } \" ) except Exception as e : log . error ( f \"ERROR setting guider TRIGOUTDIR\" ) log . error ( e ) kpffvc = ktl . cache ( 'kpffvc' ) if args . get ( 'FVC1' , True ) is True : log . info ( f \"Setting FVC1 OUTDIR to { outdir / 'FVC1' } \" ) try : kpffvc [ 'SCIOUTDIR' ] . write ( f \" { outdir / 'FVC1' } \" ) except Exception as e : log . error ( f \"ERROR setting SCI FVC outdir\" ) log . error ( e ) if args . get ( 'FVC2' , True ) is True : log . info ( f \"Setting FVC2 OUTDIR to { outdir / 'FVC2' } \" ) try : kpffvc [ 'CAHKOUTDIR' ] . write ( f \" { outdir / 'FVC2' } \" ) except Exception as e : log . error ( f \"ERROR setting CAHK FVC outdir\" ) log . error ( e ) if args . get ( 'FVC3' , True ) is True : log . info ( f \"Setting FVC3 OUTDIR to { outdir / 'FVC3' } \" ) try : kpffvc [ 'CALOUTDIR' ] . write ( f \" { outdir / 'FVC3' } \" ) except Exception as e : log . error ( f \"ERROR setting CAL FVC outdir\" ) log . error ( e ) if args . get ( 'FVC4' , True ) is True : log . info ( f \"Setting FVC4 OUTDIR to { outdir / 'FVC4' } \" ) try : kpffvc [ 'EXTOUTDIR' ] . write ( f \" { outdir / 'FVC4' } \" ) except Exception as e : log . error ( f \"ERROR setting EXT FVC outdir\" ) log . error ( e ) if args . get ( 'ExpMeter' , True ) is True : expmeter_outdir = outdir / 'ExpMeter' log . info ( f \"Setting exposure meter DATADIR to { expmeter_outdir } \" ) kpf_expmeter_outdir = ktl . cache ( 'kpf_expmeter' , 'DATADIR' ) try : kpf_expmeter_outdir . write ( f \" { expmeter_outdir } \" ) except Exception as e : log . error ( f \"ERROR setting ExpMeter outdir\" ) log . error ( e ) if args . get ( 'CaHK' , True ) is True : cahk_outdir = outdir / 'CaHK' log . info ( f \"Setting CaHK RECORDDIR to { cahk_outdir } \" ) kpf_hk_outdir = ktl . cache ( 'kpf_hk' , 'RECORDDIR' ) try : kpf_hk_outdir . write ( f \" { cahk_outdir } \" ) except Exception as e : log . error ( f \"ERROR setting CaHK outdir\" ) log . error ( e ) if args . get ( 'Green' , True ) is True : green_outdir = outdir / 'Green' log . info ( f \"Setting Green FITSDIR to { green_outdir } \" ) kpfgreen_outdir = ktl . cache ( 'kpfgreen' , 'FITSDIR' ) try : kpfgreen_outdir . write ( f \" { green_outdir } \" ) except Exception as e : log . error ( f \"ERROR setting Green outdir\" ) log . error ( e ) if args . get ( 'Red' , True ) is True : red_outdir = outdir / 'Red' log . info ( f \"Setting Red FITSDIR to { red_outdir } \" ) kpfred_outdir = ktl . cache ( 'kpfred' , 'FITSDIR' ) try : kpfred_outdir . write ( f \" { red_outdir } \" ) except Exception as e : log . error ( f \"ERROR setting Red outdir\" ) log . error ( e ) if args . get ( 'L0' , True ) is True : L0_outdir = outdir / 'L0' log . info ( f \"Setting kpfasemble OUTDIR to { L0_outdir } \" ) kpfassemble_outdir = ktl . cache ( 'kpfassemble' , 'OUTDIR' ) try : kpfassemble_outdir . write ( f \" { L0_outdir } \" ) except Exception as e : log . error ( f \"ERROR setting kpfasemble outdir\" ) log . error ( e ) @classmethod def post_condition ( cls , args , logger , cfg ): utnow = datetime . utcnow () date = utnow - timedelta ( days = 1 ) date_str = date . strftime ( '%Y%b %d ' ) . lower () outdir = Path ( f \"/s/sdata1701/ { os . getlogin () } / { date_str } \" ) tests = [] if args . get ( 'CRED2' , True ) is True : expr = f \"$kpfguide.OUTDIR == '/s/sdata1701/kpfguide'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'CRED2' , True ) is True : expr = f \"$kpfguide.TRIGOUTDIR == ' { outdir } /CRED2'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'FVC1' , True ) is True : expr = f \"$kpffvc.SCIOUTDIR == ' { outdir } /FVC1'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'FVC2' , True ) is True : expr = f \"$kpffvc.CAHKOUTDIR == ' { outdir } /FVC2'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'FVC3' , True ) is True : expr = f \"$kpffvc.CALOUTDIR == ' { outdir } /FVC3'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'FVC4' , False ) is True : expr = f \"$kpffvc.EXTOUTDIR == ' { outdir } /FVC4'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'ExpMeter' , True ) is True : expr = f \"$kpf_expmeter.DATADIR == ' { outdir } /ExpMeter'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'CaHK' , True ) is True : expr = f \"$kpf_hk.RECORDDIR == ' { outdir } /CaHK'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'Green' , True ) is True : expr = f \"$kpfgreen.FITSDIR == ' { outdir } /Green'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'Red' , True ) is True : expr = f \"$kpfred.FITSDIR == ' { outdir } /Red'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) if args . get ( 'L0' , True ) is True : expr = f \"$kpfassemble.OUTDIR == ' { outdir } /L0'\" success = ktl . waitFor ( expr , timeout = 5 ) tests . append ( success ) return np . all ( np . array ( tests )) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser = cls . _add_bool_arg ( parser , 'CRED2' , 'Set CRED2 OUTDIR (kpfguide.OUTDIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'FVC1' , 'Set FVC1 OUTDIR (kpffvc.SCIOUTDIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'FVC2' , 'Set FVC2 OUTDIR (kpffvc.CAHKOUTDIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'FVC3' , 'Set FVC3 OUTDIR (kpffvc.CALOUTDIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'FVC4' , 'Set FVC4 OUTDIR (kpffvc.EXTOUTDIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'ExpMeter' , 'Set ExpMeter OUTDIR (kpf_expmeter.DATADIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'CaHK' , 'Set CaHK OUTDIR (kpf_hk.RECORDDIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'Green' , 'Set Green OUTDIR (kpfgreen.FITSDIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'Red' , 'Set Red OUTDIR (kpfred.FITSDIR)?' , default = True ) parser = cls . _add_bool_arg ( parser , 'L0' , 'Set Red OUTDIR (kpfassemble.OUTDIR)?' , default = True ) return super () . add_cmdline_args ( parser , cfg )","title":"ARGS:"},{"location":"scripts/SetProgram/","text":"SetProgram Bases: KPFTranslatorFunction Sets the PROGNAME keyword for the science detectors in the kpfexpose keyword service. ARGS: :progname: str The program ID to set. Source code in kpf/spectrograph/SetProgram.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 class SetProgram ( KPFTranslatorFunction ): '''Sets the PROGNAME keyword for the science detectors in the kpfexpose keyword service. ARGS: ===== :progname: `str` The program ID to set. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'progname' ) @classmethod def perform ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) progname = args . get ( 'progname' ) log . debug ( 'Waiting for kpfexpose to be ready' ) WaitForReady . execute ({}) log . info ( f \"Setting PROGNAME to ' { progname } '\" ) kpfexpose [ 'PROGNAME' ] . write ( progname ) time_shim = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.1 ) time . sleep ( time_shim ) @classmethod def post_condition ( cls , args , logger , cfg ): progname = args . get ( 'progname' ) timeout = cfg . getfloat ( 'times' , 'kpfexpose_response_time' , fallback = 1 ) expr = f \"($kpfexpose.PROGNAME == ' { progname } ')\" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : prognamekw = ktl . cache ( 'kpfexpose' , 'PROGNAME' ) raise FailedToReachDestination ( prognamekw . read (), progname ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'progname' , type = str , help = 'The PROGNAME keyword' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetProgram"},{"location":"scripts/SetProgram/#setprogram","text":"Bases: KPFTranslatorFunction Sets the PROGNAME keyword for the science detectors in the kpfexpose keyword service.","title":"SetProgram"},{"location":"scripts/SetProgram/#kpf.spectrograph.SetProgram.SetProgram--args","text":":progname: str The program ID to set. Source code in kpf/spectrograph/SetProgram.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 class SetProgram ( KPFTranslatorFunction ): '''Sets the PROGNAME keyword for the science detectors in the kpfexpose keyword service. ARGS: ===== :progname: `str` The program ID to set. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'progname' ) @classmethod def perform ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) progname = args . get ( 'progname' ) log . debug ( 'Waiting for kpfexpose to be ready' ) WaitForReady . execute ({}) log . info ( f \"Setting PROGNAME to ' { progname } '\" ) kpfexpose [ 'PROGNAME' ] . write ( progname ) time_shim = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.1 ) time . sleep ( time_shim ) @classmethod def post_condition ( cls , args , logger , cfg ): progname = args . get ( 'progname' ) timeout = cfg . getfloat ( 'times' , 'kpfexpose_response_time' , fallback = 1 ) expr = f \"($kpfexpose.PROGNAME == ' { progname } ')\" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : prognamekw = ktl . cache ( 'kpfexpose' , 'PROGNAME' ) raise FailedToReachDestination ( prognamekw . read (), progname ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'progname' , type = str , help = 'The PROGNAME keyword' ) return super () . add_cmdline_args ( parser , cfg )","title":"ARGS:"},{"location":"scripts/SetReadModeFast/","text":"SetReadModeFast Bases: KPFTranslatorFunction Configure both detectors to fast read mode by changing the ACF files they are using. ARGS: None Source code in kpf/spectrograph/SetReadModeFast.py 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetReadModeFast ( KPFTranslatorFunction ): '''Configure both detectors to fast read mode by changing the ACF files they are using. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): green_mode , red_mode = QueryReadMode . execute ({}) if green_mode != 'fast' : msg = f 'Setting Green CCD read mode fast' log . info ( msg ) # Email to kpf_info try : SendEmail . execute ({ 'Subject' : msg , 'Message' : msg }) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) kpfgreen = ktl . cache ( 'kpfgreen' ) green_fast_file = cfg . get ( 'acf_files' , 'green_fast' ) green_ACFFILE = Path ( kpfgreen [ 'ACFFILE' ] . read ()) . stem if green_ACFFILE != green_fast_file : kpfgreen [ 'ACF' ] . write ( green_fast_file ) time . sleep ( 1 ) if red_mode != 'fast' : msg = f 'Setting Red CCD read mode fast' log . info ( msg ) # Email to kpf_info try : SendEmail . execute ({ 'Subject' : msg , 'Message' : msg }) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) kpfred = ktl . cache ( 'kpfred' ) red_fast_file = cfg . get ( 'acf_files' , 'red_fast' ) red_ACFFILE = Path ( kpfred [ 'ACFFILE' ] . read ()) . stem if red_ACFFILE != red_fast_file : kpfred [ 'ACF' ] . write ( red_fast_file ) time . sleep ( 1 ) @classmethod def post_condition ( cls , args , logger , cfg ): green_mode , red_mode = QueryReadMode . execute ({}) if green_mode != 'fast' or red_mode != 'fast' : raise FailedPostCondition ( f \"Read mode change failed\" )","title":"SetReadModeFast"},{"location":"scripts/SetReadModeFast/#setreadmodefast","text":"Bases: KPFTranslatorFunction Configure both detectors to fast read mode by changing the ACF files they are using.","title":"SetReadModeFast"},{"location":"scripts/SetReadModeFast/#kpf.spectrograph.SetReadModeFast.SetReadModeFast--args","text":"None Source code in kpf/spectrograph/SetReadModeFast.py 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetReadModeFast ( KPFTranslatorFunction ): '''Configure both detectors to fast read mode by changing the ACF files they are using. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): green_mode , red_mode = QueryReadMode . execute ({}) if green_mode != 'fast' : msg = f 'Setting Green CCD read mode fast' log . info ( msg ) # Email to kpf_info try : SendEmail . execute ({ 'Subject' : msg , 'Message' : msg }) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) kpfgreen = ktl . cache ( 'kpfgreen' ) green_fast_file = cfg . get ( 'acf_files' , 'green_fast' ) green_ACFFILE = Path ( kpfgreen [ 'ACFFILE' ] . read ()) . stem if green_ACFFILE != green_fast_file : kpfgreen [ 'ACF' ] . write ( green_fast_file ) time . sleep ( 1 ) if red_mode != 'fast' : msg = f 'Setting Red CCD read mode fast' log . info ( msg ) # Email to kpf_info try : SendEmail . execute ({ 'Subject' : msg , 'Message' : msg }) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) kpfred = ktl . cache ( 'kpfred' ) red_fast_file = cfg . get ( 'acf_files' , 'red_fast' ) red_ACFFILE = Path ( kpfred [ 'ACFFILE' ] . read ()) . stem if red_ACFFILE != red_fast_file : kpfred [ 'ACF' ] . write ( red_fast_file ) time . sleep ( 1 ) @classmethod def post_condition ( cls , args , logger , cfg ): green_mode , red_mode = QueryReadMode . execute ({}) if green_mode != 'fast' or red_mode != 'fast' : raise FailedPostCondition ( f \"Read mode change failed\" )","title":"ARGS:"},{"location":"scripts/SetReadModeNormal/","text":"SetReadModeNormal Bases: KPFTranslatorFunction Configure both detectors to normal read mode by changing the ACF files they are using. ARGS: None Source code in kpf/spectrograph/SetReadModeNormal.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetReadModeNormal ( KPFTranslatorFunction ): '''Configure both detectors to normal read mode by changing the ACF files they are using. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): green_mode , red_mode = QueryReadMode . execute ({}) if green_mode != 'normal' : msg = f 'Setting Green CCD read mode normal' log . info ( msg ) # Email to kpf_info try : SendEmail . execute ({ 'Subject' : msg , 'Message' : msg }) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) kpfgreen = ktl . cache ( 'kpfgreen' ) green_normal_file = cfg . get ( 'acf_files' , 'green_normal' ) green_ACFFILE = Path ( kpfgreen [ 'ACFFILE' ] . read ()) . stem if green_ACFFILE != green_normal_file : kpfgreen [ 'ACF' ] . write ( green_normal_file ) time . sleep ( 1 ) if red_mode != 'normal' : msg = f 'Setting Red CCD read mode normal' log . info ( msg ) # Email to kpf_info try : SendEmail . execute ({ 'Subject' : msg , 'Message' : msg }) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) kpfred = ktl . cache ( 'kpfred' ) red_normal_file = cfg . get ( 'acf_files' , 'red_normal' ) red_ACFFILE = Path ( kpfred [ 'ACFFILE' ] . read ()) . stem if red_ACFFILE != red_normal_file : kpfred [ 'ACF' ] . write ( red_normal_file ) time . sleep ( 1 ) @classmethod def post_condition ( cls , args , logger , cfg ): green_mode , red_mode = QueryReadMode . execute ({}) if green_mode != 'normal' or red_mode != 'normal' : raise FailedPostCondition ( f \"Read mode change failed\" )","title":"SetReadModeNormal"},{"location":"scripts/SetReadModeNormal/#setreadmodenormal","text":"Bases: KPFTranslatorFunction Configure both detectors to normal read mode by changing the ACF files they are using.","title":"SetReadModeNormal"},{"location":"scripts/SetReadModeNormal/#kpf.spectrograph.SetReadModeNormal.SetReadModeNormal--args","text":"None Source code in kpf/spectrograph/SetReadModeNormal.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetReadModeNormal ( KPFTranslatorFunction ): '''Configure both detectors to normal read mode by changing the ACF files they are using. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): green_mode , red_mode = QueryReadMode . execute ({}) if green_mode != 'normal' : msg = f 'Setting Green CCD read mode normal' log . info ( msg ) # Email to kpf_info try : SendEmail . execute ({ 'Subject' : msg , 'Message' : msg }) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) kpfgreen = ktl . cache ( 'kpfgreen' ) green_normal_file = cfg . get ( 'acf_files' , 'green_normal' ) green_ACFFILE = Path ( kpfgreen [ 'ACFFILE' ] . read ()) . stem if green_ACFFILE != green_normal_file : kpfgreen [ 'ACF' ] . write ( green_normal_file ) time . sleep ( 1 ) if red_mode != 'normal' : msg = f 'Setting Red CCD read mode normal' log . info ( msg ) # Email to kpf_info try : SendEmail . execute ({ 'Subject' : msg , 'Message' : msg }) except Exception as email_err : log . error ( f 'Sending email failed' ) log . error ( email_err ) kpfred = ktl . cache ( 'kpfred' ) red_normal_file = cfg . get ( 'acf_files' , 'red_normal' ) red_ACFFILE = Path ( kpfred [ 'ACFFILE' ] . read ()) . stem if red_ACFFILE != red_normal_file : kpfred [ 'ACF' ] . write ( red_normal_file ) time . sleep ( 1 ) @classmethod def post_condition ( cls , args , logger , cfg ): green_mode , red_mode = QueryReadMode . execute ({}) if green_mode != 'normal' or red_mode != 'normal' : raise FailedPostCondition ( f \"Read mode change failed\" )","title":"ARGS:"},{"location":"scripts/SetSimulCalSource/","text":"SetSimulCalSource Bases: KPFTranslatorFunction Set the slew cal and simultaneous calibration source. Valid names: EtalonFiber, U_gold, U_daily, Th_daily, Th_gold, LFCFiber ARGS: :calsource: The calibration source to use (must be one of Etalon, LFC, Th_daily, Th_gold, U_daily, U_gold). Source code in kpf/utils/SetSimulCalSource.py 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetSimulCalSource ( KPFTranslatorFunction ): '''Set the slew cal and simultaneous calibration source. Valid names: EtalonFiber, U_gold, U_daily, Th_daily, Th_gold, LFCFiber ARGS: ===== :calsource: The calibration source to use (must be one of Etalon, LFC, Th_daily, Th_gold, U_daily, U_gold). ''' @classmethod def pre_condition ( cls , args , logger , cfg ): valid_names = [ 'EtalonFiber' , 'U_gold' , 'U_daily' , 'Th_daily' , 'Th_gold' , 'LFCFiber' ] if args . get ( 'CalSource' , None ) not in valid_names : raise FailedPreCondition ( f \"calsource ' { calsource } ' must be one of { valid_names } \" ) @classmethod def perform ( cls , args , logger , cfg ): log . info ( f \"Setting simul cal / slew cal source\" ) calsource = args . get ( 'CalSource' ) kpfconfig = ktl . cache ( 'kpfconfig' ) slew_cal_file = Path ( f '/kroot/rel/default/data/obs/kpf/SlewCal_ { calsource } .yaml' ) if slew_cal_file . exists () is False : raise KPFException ( f 'The slew cal file for { calsource } does not exist' ) else : log . info ( f 'Writing kpfconfig.SIMULCALSOURCE = { calsource } ' ) kpfconfig [ 'SIMULCALSOURCE' ] . write ( calsource ) log . info ( f 'Writing kpfconfig.SLEWCALFILE = { slew_cal_file } ' ) kpfconfig [ 'SLEWCALFILE' ] . write ( f \" { slew_cal_file } \" ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalSource' , type = str , choices = [ 'EtalonFiber' , 'U_gold' , 'U_daily' , 'Th_daily' , 'Th_gold' , 'LFCFiber' ], help = 'Which lamp to use for simultaneous calibration and slew cals' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetSimulCalSource"},{"location":"scripts/SetSimulCalSource/#setsimulcalsource","text":"Bases: KPFTranslatorFunction Set the slew cal and simultaneous calibration source. Valid names: EtalonFiber, U_gold, U_daily, Th_daily, Th_gold, LFCFiber","title":"SetSimulCalSource"},{"location":"scripts/SetSimulCalSource/#kpf.utils.SetSimulCalSource.SetSimulCalSource--args","text":":calsource: The calibration source to use (must be one of Etalon, LFC, Th_daily, Th_gold, U_daily, U_gold). Source code in kpf/utils/SetSimulCalSource.py 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetSimulCalSource ( KPFTranslatorFunction ): '''Set the slew cal and simultaneous calibration source. Valid names: EtalonFiber, U_gold, U_daily, Th_daily, Th_gold, LFCFiber ARGS: ===== :calsource: The calibration source to use (must be one of Etalon, LFC, Th_daily, Th_gold, U_daily, U_gold). ''' @classmethod def pre_condition ( cls , args , logger , cfg ): valid_names = [ 'EtalonFiber' , 'U_gold' , 'U_daily' , 'Th_daily' , 'Th_gold' , 'LFCFiber' ] if args . get ( 'CalSource' , None ) not in valid_names : raise FailedPreCondition ( f \"calsource ' { calsource } ' must be one of { valid_names } \" ) @classmethod def perform ( cls , args , logger , cfg ): log . info ( f \"Setting simul cal / slew cal source\" ) calsource = args . get ( 'CalSource' ) kpfconfig = ktl . cache ( 'kpfconfig' ) slew_cal_file = Path ( f '/kroot/rel/default/data/obs/kpf/SlewCal_ { calsource } .yaml' ) if slew_cal_file . exists () is False : raise KPFException ( f 'The slew cal file for { calsource } does not exist' ) else : log . info ( f 'Writing kpfconfig.SIMULCALSOURCE = { calsource } ' ) kpfconfig [ 'SIMULCALSOURCE' ] . write ( calsource ) log . info ( f 'Writing kpfconfig.SLEWCALFILE = { slew_cal_file } ' ) kpfconfig [ 'SLEWCALFILE' ] . write ( f \" { slew_cal_file } \" ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalSource' , type = str , choices = [ 'EtalonFiber' , 'U_gold' , 'U_daily' , 'Th_daily' , 'Th_gold' , 'LFCFiber' ], help = 'Which lamp to use for simultaneous calibration and slew cals' ) return super () . add_cmdline_args ( parser , cfg )","title":"ARGS:"},{"location":"scripts/SetSourceSelectShutters/","text":"SetSourceSelectShutters Bases: KPFTranslatorFunction Opens and closes the source select shutters via the kpfexpose.SRC_SHUTTERS keyword. ARGS: :SSS_Science: bool Open the SciSelect shutter? (default=False) :SSS_Sky: bool Open the SkySelect shutter? (default=False) :SSS_CalSciSky: bool Open the Cal_SciSky shutter? (default=False) :SSS_SoCalSci: bool Open the SoCalSci shutter? (default=False) :SSS_SoCalCal: bool Open the SoCalCal shutter? (default=False) Source code in kpf/spectrograph/SetSourceSelectShutters.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetSourceSelectShutters ( KPFTranslatorFunction ): '''Opens and closes the source select shutters via the `kpfexpose.SRC_SHUTTERS` keyword. ARGS: ===== :SSS_Science: `bool` Open the SciSelect shutter? (default=False) :SSS_Sky: `bool` Open the SkySelect shutter? (default=False) :SSS_CalSciSky: `bool` Open the Cal_SciSky shutter? (default=False) :SSS_SoCalSci: `bool` Open the SoCalSci shutter? (default=False) :SSS_SoCalCal: `bool` Open the SoCalCal shutter? (default=False) ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): shutter_list = [] if args . get ( 'SSS_Science' , False ) is True : shutter_list . append ( 'SciSelect' ) if args . get ( 'SSS_Sky' , False ) is True : shutter_list . append ( 'SkySelect' ) if args . get ( 'SSS_SoCalSci' , False ) is True : shutter_list . append ( 'SoCalSci' ) if args . get ( 'SSS_SoCalCal' , False ) is True : shutter_list . append ( 'SoCalCal' ) if args . get ( 'SSS_CalSciSky' , False ) is True : shutter_list . append ( 'Cal_SciSky' ) shutters_string = ',' . join ( shutter_list ) log . debug ( f \"Setting source select shutters to ' { shutters_string } '\" ) kpfexpose = ktl . cache ( 'kpfexpose' ) kpfexpose [ 'SRC_SHUTTERS' ] . write ( shutters_string ) shim_time = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.1 ) sleep ( shim_time ) @classmethod def post_condition ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) timeshim = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.01 ) sleep ( timeshim ) shutters = kpfexpose [ 'SRC_SHUTTERS' ] . read () shutter_list = shutters . split ( ',' ) shutter_names = [( 'SciSelect' , 'SSS_Science' ), ( 'SkySelect' , 'SSS_Sky' ), ( 'SoCalSci' , 'SSS_SoCalSci' ), ( 'SoCalCal' , 'SSS_SoCalCal' ), ( 'Cal_SciSky' , 'SSS_CalSciSky' )] for shutter in shutter_names : shutter_status = shutter [ 0 ] in shutter_list shutter_target = args . get ( shutter [ 1 ], False ) if shutter_target != shutter_status : raise FailedToReachDestination ( shutter_status , shutter_target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--Science\" , \"--Sci\" , \"--science\" , \"--sci\" , dest = \"SSS_Science\" , default = False , action = \"store_true\" , help = \"Open the SciSelect shutter?\" ) parser . add_argument ( \"--Sky\" , \"--sky\" , dest = \"SSS_Sky\" , default = False , action = \"store_true\" , help = \"Open the SkySelect shutter?\" ) parser . add_argument ( \"--CalSciSky\" , dest = \"SSS_CalSciSky\" , default = False , action = \"store_true\" , help = \"Open the Cal_SciSky shutter?\" ) parser . add_argument ( \"--SoCalSci\" , dest = \"SSS_SoCalSci\" , default = False , action = \"store_true\" , help = \"Open the SoCalSci shutter?\" ) parser . add_argument ( \"--SoCalCal\" , dest = \"SSS_SoCalCal\" , default = False , action = \"store_true\" , help = \"Open the SoCalCal shutter?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetSourceSelectShutters"},{"location":"scripts/SetSourceSelectShutters/#setsourceselectshutters","text":"Bases: KPFTranslatorFunction Opens and closes the source select shutters via the kpfexpose.SRC_SHUTTERS keyword.","title":"SetSourceSelectShutters"},{"location":"scripts/SetSourceSelectShutters/#kpf.spectrograph.SetSourceSelectShutters.SetSourceSelectShutters--args","text":":SSS_Science: bool Open the SciSelect shutter? (default=False) :SSS_Sky: bool Open the SkySelect shutter? (default=False) :SSS_CalSciSky: bool Open the Cal_SciSky shutter? (default=False) :SSS_SoCalSci: bool Open the SoCalSci shutter? (default=False) :SSS_SoCalCal: bool Open the SoCalCal shutter? (default=False) Source code in kpf/spectrograph/SetSourceSelectShutters.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetSourceSelectShutters ( KPFTranslatorFunction ): '''Opens and closes the source select shutters via the `kpfexpose.SRC_SHUTTERS` keyword. ARGS: ===== :SSS_Science: `bool` Open the SciSelect shutter? (default=False) :SSS_Sky: `bool` Open the SkySelect shutter? (default=False) :SSS_CalSciSky: `bool` Open the Cal_SciSky shutter? (default=False) :SSS_SoCalSci: `bool` Open the SoCalSci shutter? (default=False) :SSS_SoCalCal: `bool` Open the SoCalCal shutter? (default=False) ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): shutter_list = [] if args . get ( 'SSS_Science' , False ) is True : shutter_list . append ( 'SciSelect' ) if args . get ( 'SSS_Sky' , False ) is True : shutter_list . append ( 'SkySelect' ) if args . get ( 'SSS_SoCalSci' , False ) is True : shutter_list . append ( 'SoCalSci' ) if args . get ( 'SSS_SoCalCal' , False ) is True : shutter_list . append ( 'SoCalCal' ) if args . get ( 'SSS_CalSciSky' , False ) is True : shutter_list . append ( 'Cal_SciSky' ) shutters_string = ',' . join ( shutter_list ) log . debug ( f \"Setting source select shutters to ' { shutters_string } '\" ) kpfexpose = ktl . cache ( 'kpfexpose' ) kpfexpose [ 'SRC_SHUTTERS' ] . write ( shutters_string ) shim_time = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.1 ) sleep ( shim_time ) @classmethod def post_condition ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) timeshim = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.01 ) sleep ( timeshim ) shutters = kpfexpose [ 'SRC_SHUTTERS' ] . read () shutter_list = shutters . split ( ',' ) shutter_names = [( 'SciSelect' , 'SSS_Science' ), ( 'SkySelect' , 'SSS_Sky' ), ( 'SoCalSci' , 'SSS_SoCalSci' ), ( 'SoCalCal' , 'SSS_SoCalCal' ), ( 'Cal_SciSky' , 'SSS_CalSciSky' )] for shutter in shutter_names : shutter_status = shutter [ 0 ] in shutter_list shutter_target = args . get ( shutter [ 1 ], False ) if shutter_target != shutter_status : raise FailedToReachDestination ( shutter_status , shutter_target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--Science\" , \"--Sci\" , \"--science\" , \"--sci\" , dest = \"SSS_Science\" , default = False , action = \"store_true\" , help = \"Open the SciSelect shutter?\" ) parser . add_argument ( \"--Sky\" , \"--sky\" , dest = \"SSS_Sky\" , default = False , action = \"store_true\" , help = \"Open the SkySelect shutter?\" ) parser . add_argument ( \"--CalSciSky\" , dest = \"SSS_CalSciSky\" , default = False , action = \"store_true\" , help = \"Open the Cal_SciSky shutter?\" ) parser . add_argument ( \"--SoCalSci\" , dest = \"SSS_SoCalSci\" , default = False , action = \"store_true\" , help = \"Open the SoCalSci shutter?\" ) parser . add_argument ( \"--SoCalCal\" , dest = \"SSS_SoCalCal\" , default = False , action = \"store_true\" , help = \"Open the SoCalCal shutter?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"ARGS:"},{"location":"scripts/SetTargetInfo/","text":"SetTargetInfo Bases: KPFTranslatorFunction Set the target info keywords based on the target information in the OB. ARGS OB : ( dict ) A fully specified observing block (OB) or at least the target components of an OB. Source code in kpf/utils/SetTargetInfo.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetTargetInfo ( KPFTranslatorFunction ): '''Set the target info keywords based on the target information in the OB. ### ARGS **OB**: (`dict`) A fully specified observing block (OB) or at least the target components of an OB. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , OB , logger , cfg ): log . info ( f \"Setting target parameters\" ) kpfconfig = ktl . cache ( 'kpfconfig' ) kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) dcs = ktl . cache ( 'dcs1' ) kpfconfig [ 'TARGET_NAME' ] . write ( OB . get ( 'TargetName' , '' )) kpfconfig [ 'TARGET_GAIA' ] . write ( OB . get ( 'GaiaID' , '' )) kpfconfig [ 'TARGET_2MASS' ] . write ( OB . get ( '2MASSID' , '' )) kpfconfig [ 'TARGET_GMAG' ] . write ( OB . get ( 'Gmag' , '' )) kpfconfig [ 'TARGET_JMAG' ] . write ( OB . get ( 'Jmag' , '' )) TARGET_TEFF = OB . get ( 'Teff' , 45000 ) try : kpf_expmeter [ 'TARGET_TEFF' ] . write ( float ( TARGET_TEFF )) except : log . warning ( f \"Unable to set kpf_expmeter.TARGET_TEFF to { TARGET_TEFF } ( { type ( TARGET_TEFF ) } )\" ) TARGPLAX = OB . get ( 'Parallax' , 0 ) try : dcs [ 'TARGPLAX' ] . write ( float ( TARGPLAX )) except : log . warning ( f \"Unable to set dcs.TARGPLAX to { TARGPLAX } ( { type ( TARGPLAX ) } )\" ) TARGRADV = OB . get ( 'RadialVelocity' , 0 ) try : dcs [ 'TARGRADV' ] . write ( float ( TARGRADV )) except : log . warning ( f \"Unable to set dcs.TARGRADV to { TARGRADV } ( { type ( TARGRADV ) } )\" ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"SetTargetInfo"},{"location":"scripts/SetTargetInfo/#settargetinfo","text":"Bases: KPFTranslatorFunction Set the target info keywords based on the target information in the OB.","title":"SetTargetInfo"},{"location":"scripts/SetTargetInfo/#kpf.utils.SetTargetInfo.SetTargetInfo--args","text":"OB : ( dict ) A fully specified observing block (OB) or at least the target components of an OB. Source code in kpf/utils/SetTargetInfo.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetTargetInfo ( KPFTranslatorFunction ): '''Set the target info keywords based on the target information in the OB. ### ARGS **OB**: (`dict`) A fully specified observing block (OB) or at least the target components of an OB. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , OB , logger , cfg ): log . info ( f \"Setting target parameters\" ) kpfconfig = ktl . cache ( 'kpfconfig' ) kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) dcs = ktl . cache ( 'dcs1' ) kpfconfig [ 'TARGET_NAME' ] . write ( OB . get ( 'TargetName' , '' )) kpfconfig [ 'TARGET_GAIA' ] . write ( OB . get ( 'GaiaID' , '' )) kpfconfig [ 'TARGET_2MASS' ] . write ( OB . get ( '2MASSID' , '' )) kpfconfig [ 'TARGET_GMAG' ] . write ( OB . get ( 'Gmag' , '' )) kpfconfig [ 'TARGET_JMAG' ] . write ( OB . get ( 'Jmag' , '' )) TARGET_TEFF = OB . get ( 'Teff' , 45000 ) try : kpf_expmeter [ 'TARGET_TEFF' ] . write ( float ( TARGET_TEFF )) except : log . warning ( f \"Unable to set kpf_expmeter.TARGET_TEFF to { TARGET_TEFF } ( { type ( TARGET_TEFF ) } )\" ) TARGPLAX = OB . get ( 'Parallax' , 0 ) try : dcs [ 'TARGPLAX' ] . write ( float ( TARGPLAX )) except : log . warning ( f \"Unable to set dcs.TARGPLAX to { TARGPLAX } ( { type ( TARGPLAX ) } )\" ) TARGRADV = OB . get ( 'RadialVelocity' , 0 ) try : dcs [ 'TARGRADV' ] . write ( float ( TARGRADV )) except : log . warning ( f \"Unable to set dcs.TARGRADV to { TARGRADV } ( { type ( TARGRADV ) } )\" ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"ARGS"},{"location":"scripts/SetTimedShutters/","text":"SetTimedShutters Bases: KPFTranslatorFunction Selects which timed shutters will be triggered by setting the kpfexpose.TIMED_SHUTTERS keyword value. ARGS: :TimedShutter_Scrambler: bool Open the TimedShutter_Scrambler shutter? (default=False) :TimedShutter_SimulCal: bool Open the TimedShutter_SimulCal shutter? (default=False) :TimedShutter_CaHK: bool Open the TimedShutter_CaHK shutter? (default=False) :TimedShutter_FlatField: bool Open the TimedShutter_FlatField shutter? (default=False) Source code in kpf/spectrograph/SetTimedShutters.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetTimedShutters ( KPFTranslatorFunction ): '''Selects which timed shutters will be triggered by setting the `kpfexpose.TIMED_SHUTTERS` keyword value. ARGS: ===== :TimedShutter_Scrambler: `bool` Open the TimedShutter_Scrambler shutter? (default=False) :TimedShutter_SimulCal: `bool` Open the TimedShutter_SimulCal shutter? (default=False) :TimedShutter_CaHK: `bool` Open the TimedShutter_CaHK shutter? (default=False) :TimedShutter_FlatField: `bool` Open the TimedShutter_FlatField shutter? (default=False) ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # Scrambler 2 SimulCal 3 FF_Fiber 4 Ca_HK timed_shutters_list = [] if args . get ( 'TimedShutter_Scrambler' , False ) is True : timed_shutters_list . append ( 'Scrambler' ) if args . get ( 'TimedShutter_SimulCal' , False ) is True : timed_shutters_list . append ( 'SimulCal' ) if args . get ( 'TimedShutter_FlatField' , False ) is True : timed_shutters_list . append ( 'FF_Fiber' ) if args . get ( 'TimedShutter_CaHK' , False ) is True : timed_shutters_list . append ( 'Ca_HK' ) timed_shutters_string = ',' . join ( timed_shutters_list ) log . debug ( f \"Setting timed shutters to ' { timed_shutters_string } '\" ) kpfexpose = ktl . cache ( 'kpfexpose' ) kpfexpose [ 'TIMED_TARG' ] . write ( timed_shutters_string ) shim_time = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.1 ) sleep ( shim_time ) @classmethod def post_condition ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) timeshim = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.01 ) sleep ( timeshim ) shutters = kpfexpose [ 'TIMED_TARG' ] . read () log . debug ( f \"TIMED_TARG: { shutters } \" ) shutter_list = shutters . split ( ',' ) shutter_names = [( 'Scrambler' , 'TimedShutter_Scrambler' ), ( 'SimulCal' , 'TimedShutter_SimulCal' ), ( 'FF_Fiber' , 'TimedShutter_FlatField' ), ( 'Ca_HK' , 'TimedShutter_CaHK' )] for shutter in shutter_names : shutter_status = shutter [ 0 ] in shutter_list shutter_target = args . get ( shutter [ 1 ], False ) if shutter_target != shutter_status : raise FailedToReachDestination ( shutter_status , shutter_target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--Scrambler\" , \"--scrambler\" , dest = \"TimedShutter_Scrambler\" , default = False , action = \"store_true\" , help = \"Open the Scrambler Timed Shutter during exposure?\" ) parser . add_argument ( \"--SimulCal\" , \"--simulcal\" , dest = \"TimedShutter_SimulCal\" , default = False , action = \"store_true\" , help = \"Open the SimulCal Timed Shutter during exposure?\" ) parser . add_argument ( \"--CaHK\" , \"--HK\" , \"--cahk\" , \"--hk\" , dest = \"TimedShutter_CaHK\" , default = False , action = \"store_true\" , help = \"Open the CaHK Timed Shutter during exposure?\" ) parser . add_argument ( \"--FlatField\" , \"--flatfield\" , dest = \"TimedShutter_FlatField\" , default = False , action = \"store_true\" , help = \"Open the FlatField Timed Shutter during exposure?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetTimedShutters"},{"location":"scripts/SetTimedShutters/#settimedshutters","text":"Bases: KPFTranslatorFunction Selects which timed shutters will be triggered by setting the kpfexpose.TIMED_SHUTTERS keyword value.","title":"SetTimedShutters"},{"location":"scripts/SetTimedShutters/#kpf.spectrograph.SetTimedShutters.SetTimedShutters--args","text":":TimedShutter_Scrambler: bool Open the TimedShutter_Scrambler shutter? (default=False) :TimedShutter_SimulCal: bool Open the TimedShutter_SimulCal shutter? (default=False) :TimedShutter_CaHK: bool Open the TimedShutter_CaHK shutter? (default=False) :TimedShutter_FlatField: bool Open the TimedShutter_FlatField shutter? (default=False) Source code in kpf/spectrograph/SetTimedShutters.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetTimedShutters ( KPFTranslatorFunction ): '''Selects which timed shutters will be triggered by setting the `kpfexpose.TIMED_SHUTTERS` keyword value. ARGS: ===== :TimedShutter_Scrambler: `bool` Open the TimedShutter_Scrambler shutter? (default=False) :TimedShutter_SimulCal: `bool` Open the TimedShutter_SimulCal shutter? (default=False) :TimedShutter_CaHK: `bool` Open the TimedShutter_CaHK shutter? (default=False) :TimedShutter_FlatField: `bool` Open the TimedShutter_FlatField shutter? (default=False) ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # Scrambler 2 SimulCal 3 FF_Fiber 4 Ca_HK timed_shutters_list = [] if args . get ( 'TimedShutter_Scrambler' , False ) is True : timed_shutters_list . append ( 'Scrambler' ) if args . get ( 'TimedShutter_SimulCal' , False ) is True : timed_shutters_list . append ( 'SimulCal' ) if args . get ( 'TimedShutter_FlatField' , False ) is True : timed_shutters_list . append ( 'FF_Fiber' ) if args . get ( 'TimedShutter_CaHK' , False ) is True : timed_shutters_list . append ( 'Ca_HK' ) timed_shutters_string = ',' . join ( timed_shutters_list ) log . debug ( f \"Setting timed shutters to ' { timed_shutters_string } '\" ) kpfexpose = ktl . cache ( 'kpfexpose' ) kpfexpose [ 'TIMED_TARG' ] . write ( timed_shutters_string ) shim_time = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.1 ) sleep ( shim_time ) @classmethod def post_condition ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) timeshim = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.01 ) sleep ( timeshim ) shutters = kpfexpose [ 'TIMED_TARG' ] . read () log . debug ( f \"TIMED_TARG: { shutters } \" ) shutter_list = shutters . split ( ',' ) shutter_names = [( 'Scrambler' , 'TimedShutter_Scrambler' ), ( 'SimulCal' , 'TimedShutter_SimulCal' ), ( 'FF_Fiber' , 'TimedShutter_FlatField' ), ( 'Ca_HK' , 'TimedShutter_CaHK' )] for shutter in shutter_names : shutter_status = shutter [ 0 ] in shutter_list shutter_target = args . get ( shutter [ 1 ], False ) if shutter_target != shutter_status : raise FailedToReachDestination ( shutter_status , shutter_target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--Scrambler\" , \"--scrambler\" , dest = \"TimedShutter_Scrambler\" , default = False , action = \"store_true\" , help = \"Open the Scrambler Timed Shutter during exposure?\" ) parser . add_argument ( \"--SimulCal\" , \"--simulcal\" , dest = \"TimedShutter_SimulCal\" , default = False , action = \"store_true\" , help = \"Open the SimulCal Timed Shutter during exposure?\" ) parser . add_argument ( \"--CaHK\" , \"--HK\" , \"--cahk\" , \"--hk\" , dest = \"TimedShutter_CaHK\" , default = False , action = \"store_true\" , help = \"Open the CaHK Timed Shutter during exposure?\" ) parser . add_argument ( \"--FlatField\" , \"--flatfield\" , dest = \"TimedShutter_FlatField\" , default = False , action = \"store_true\" , help = \"Open the FlatField Timed Shutter during exposure?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"ARGS:"},{"location":"scripts/SetTipTiltCalculations/","text":"SetTipTiltCalculations Bases: KPFTranslatorFunction Turn the tip tilt calculation software on or off. Parameters: calculations ( str ) \u2013 The desired state of the calculations. Allowed values: Active or Inactive KTL Keywords Used: kpfguide.TIPTILT_CALC Source code in kpf/fiu/SetTipTiltCalculations.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class SetTipTiltCalculations ( KPFTranslatorFunction ): '''Turn the tip tilt calculation software on or off. Args: calculations (str): The desired state of the calculations. Allowed values: Active or Inactive KTL Keywords Used: - `kpfguide.TIPTILT_CALC` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): allowed_values = [ 'Active' , 'Inactive' , '1' , '0' , 1 , 0 ] check_input ( args , 'calculations' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): calculations = args . get ( 'calculations' ) tiptiltcalc = ktl . cache ( 'kpfguide' , 'TIPTILT_CALC' ) tiptiltcalc . write ( calculations ) @classmethod def post_condition ( cls , args , logger , cfg ): calculations = args . get ( 'calculations' ) timeout = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) expr = f \"($kpfguide.TIPTILT_CALC == { calculations } ) \" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : tiptilt = ktl . cache ( 'kpfguide' , 'TIPTILT_CALC' ) raise FailedToReachDestination ( tiptilt . read (), calculations ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'calculations' , type = str , choices = [ 'Active' , 'Inactive' ], help = 'Calulations \"Active\" or \"Inactive\"' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetTipTiltCalculations"},{"location":"scripts/SetTipTiltCalculations/#settiptiltcalculations","text":"Bases: KPFTranslatorFunction Turn the tip tilt calculation software on or off. Parameters: calculations ( str ) \u2013 The desired state of the calculations. Allowed values: Active or Inactive KTL Keywords Used: kpfguide.TIPTILT_CALC Source code in kpf/fiu/SetTipTiltCalculations.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class SetTipTiltCalculations ( KPFTranslatorFunction ): '''Turn the tip tilt calculation software on or off. Args: calculations (str): The desired state of the calculations. Allowed values: Active or Inactive KTL Keywords Used: - `kpfguide.TIPTILT_CALC` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): allowed_values = [ 'Active' , 'Inactive' , '1' , '0' , 1 , 0 ] check_input ( args , 'calculations' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): calculations = args . get ( 'calculations' ) tiptiltcalc = ktl . cache ( 'kpfguide' , 'TIPTILT_CALC' ) tiptiltcalc . write ( calculations ) @classmethod def post_condition ( cls , args , logger , cfg ): calculations = args . get ( 'calculations' ) timeout = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) expr = f \"($kpfguide.TIPTILT_CALC == { calculations } ) \" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : tiptilt = ktl . cache ( 'kpfguide' , 'TIPTILT_CALC' ) raise FailedToReachDestination ( tiptilt . read (), calculations ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'calculations' , type = str , choices = [ 'Active' , 'Inactive' ], help = 'Calulations \"Active\" or \"Inactive\"' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetTipTiltCalculations"},{"location":"scripts/SetTipTiltControl/","text":"SetTipTiltControl Bases: KPFTranslatorFunction Turn the tip tilt control software on or off. Parameters: control ( str ) \u2013 The desired state of the control. Allowed values: Active or Inactive KTL Keywords Used: kpfguide.TIPTILT_CONTROL Source code in kpf/fiu/SetTipTiltControl.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class SetTipTiltControl ( KPFTranslatorFunction ): '''Turn the tip tilt control software on or off. Args: control (str): The desired state of the control. Allowed values: Active or Inactive KTL Keywords Used: - `kpfguide.TIPTILT_CONTROL` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): allowed_values = [ 'Active' , 'Inactive' , '1' , '0' , 1 , 0 ] check_input ( args , 'control' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): control = args . get ( 'control' ) tiptiltcontrol = ktl . cache ( 'kpfguide' , 'TIPTILT_CONTROL' ) tiptiltcontrol . write ( control ) @classmethod def post_condition ( cls , args , logger , cfg ): control = args . get ( 'control' ) timeout = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) expr = f \"($kpfguide.TIPTILT_CONTROL == { calculations } ) \" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : tiptiltcontrol = ktl . cache ( 'kpfguide' , 'TIPTILT_CONTROL' ) raise FailedToReachDestination ( tiptiltcontrol . read (), control ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'control' , type = str , choices = [ 'Active' , 'Inactive' ], help = 'Control \"Active\" or \"Inactive\"' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetTipTiltControl"},{"location":"scripts/SetTipTiltControl/#settiptiltcontrol","text":"Bases: KPFTranslatorFunction Turn the tip tilt control software on or off. Parameters: control ( str ) \u2013 The desired state of the control. Allowed values: Active or Inactive KTL Keywords Used: kpfguide.TIPTILT_CONTROL Source code in kpf/fiu/SetTipTiltControl.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class SetTipTiltControl ( KPFTranslatorFunction ): '''Turn the tip tilt control software on or off. Args: control (str): The desired state of the control. Allowed values: Active or Inactive KTL Keywords Used: - `kpfguide.TIPTILT_CONTROL` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): allowed_values = [ 'Active' , 'Inactive' , '1' , '0' , 1 , 0 ] check_input ( args , 'control' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): control = args . get ( 'control' ) tiptiltcontrol = ktl . cache ( 'kpfguide' , 'TIPTILT_CONTROL' ) tiptiltcontrol . write ( control ) @classmethod def post_condition ( cls , args , logger , cfg ): control = args . get ( 'control' ) timeout = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) expr = f \"($kpfguide.TIPTILT_CONTROL == { calculations } ) \" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : tiptiltcontrol = ktl . cache ( 'kpfguide' , 'TIPTILT_CONTROL' ) raise FailedToReachDestination ( tiptiltcontrol . read (), control ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'control' , type = str , choices = [ 'Active' , 'Inactive' ], help = 'Control \"Active\" or \"Inactive\"' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetTipTiltControl"},{"location":"scripts/SetTipTiltGain/","text":"SetTipTiltGain Bases: KPFTranslatorFunction Set the guide loop gain. Parameters: GuideLoopGain ( float ) \u2013 The desired gain value. KTL Keywords Used: kpfguide.TIPTILT_GAIN Source code in kpf/fiu/SetTipTiltGain.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 class SetTipTiltGain ( KPFTranslatorFunction ): '''Set the guide loop gain. Args: GuideLoopGain (float): The desired gain value. KTL Keywords Used: - `kpfguide.TIPTILT_GAIN` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'GuideLoopGain' , value_min = 0 , value_max = 1 ) @classmethod def perform ( cls , args , logger , cfg ): gain = float ( args . get ( 'GuideLoopGain' )) tiptiltgain = ktl . cache ( 'kpfguide' , 'TIPTILT_GAIN' ) tiptiltgain . write ( gain ) @classmethod def post_condition ( cls , args , logger , cfg ): gain = float ( args . get ( 'GuideLoopGain' )) timeout = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) tol = cfg . getfloat ( 'tolerances' , 'tip_tilt_gain_tolerance' , fallback = 0.001 ) expr = ( f \"($kpfguide.TIPTILT_GAIN >= { gain - tol } ) and \" f \"($kpfguide.TIPTILT_GAIN <= { gain + tol } )\" ) success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : tiptiltgain = ktl . cache ( 'kpfguide' , 'TIPTILT_GAIN' ) raise FailedToReachDestination ( tiptiltgain . read (), gain ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'GuideLoopGain' , type = float , help = \"Tip tilt control loop gain\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetTipTiltGain"},{"location":"scripts/SetTipTiltGain/#settiptiltgain","text":"Bases: KPFTranslatorFunction Set the guide loop gain. Parameters: GuideLoopGain ( float ) \u2013 The desired gain value. KTL Keywords Used: kpfguide.TIPTILT_GAIN Source code in kpf/fiu/SetTipTiltGain.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 class SetTipTiltGain ( KPFTranslatorFunction ): '''Set the guide loop gain. Args: GuideLoopGain (float): The desired gain value. KTL Keywords Used: - `kpfguide.TIPTILT_GAIN` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'GuideLoopGain' , value_min = 0 , value_max = 1 ) @classmethod def perform ( cls , args , logger , cfg ): gain = float ( args . get ( 'GuideLoopGain' )) tiptiltgain = ktl . cache ( 'kpfguide' , 'TIPTILT_GAIN' ) tiptiltgain . write ( gain ) @classmethod def post_condition ( cls , args , logger , cfg ): gain = float ( args . get ( 'GuideLoopGain' )) timeout = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) tol = cfg . getfloat ( 'tolerances' , 'tip_tilt_gain_tolerance' , fallback = 0.001 ) expr = ( f \"($kpfguide.TIPTILT_GAIN >= { gain - tol } ) and \" f \"($kpfguide.TIPTILT_GAIN <= { gain + tol } )\" ) success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : tiptiltgain = ktl . cache ( 'kpfguide' , 'TIPTILT_GAIN' ) raise FailedToReachDestination ( tiptiltgain . read (), gain ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'GuideLoopGain' , type = float , help = \"Tip tilt control loop gain\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetTipTiltGain"},{"location":"scripts/SetTipTiltPosition/","text":"SetTipTiltPosition Bases: KPFTranslatorFunction Set the position of the tip tilt mirror. This should only be used in an engineering context. To control the position of a star, set the CURRENT_BASE or PIX_TARGET keywords as appropriate, e.g. via the kpf.fiu.SetTipTiltTargetPixel translator module function. Parameters: x ( float ) \u2013 The desired X position (TTXVAX). y ( float ) \u2013 The desired Y position (TTYVAX). KTL Keywords Used: kpffiu.TTXVAX kpffiu.TTYVAX Source code in kpf/fiu/SetTipTiltPosition.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetTipTiltPosition ( KPFTranslatorFunction ): '''Set the position of the tip tilt mirror. This should only be used in an engineering context. To control the position of a star, set the CURRENT_BASE or PIX_TARGET keywords as appropriate, e.g. via the `kpf.fiu.SetTipTiltTargetPixel` translator module function. Args: x (float): The desired X position (TTXVAX). y (float): The desired Y position (TTYVAX). KTL Keywords Used: - `kpffiu.TTXVAX` - `kpffiu.TTYVAX` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'x' ) check_input ( args , 'y' ) @classmethod def perform ( cls , args , logger , cfg ): kpffiu = ktl . cache ( 'kpffiu' ) kpffiu [ 'TTXVAX' ] . write ( args . get ( 'x' )) kpffiu [ 'TTYVAX' ] . write ( args . get ( 'y' )) time_shim = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) time . sleep ( time_shim ) @classmethod def post_condition ( cls , args , logger , cfg ): kpffiu = ktl . cache ( 'kpffiu' ) timeout = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) tol = cfg . getfloat ( 'tolerances' , 'tip_tilt_move_tolerance' , fallback = 0.1 ) xdest = args . get ( 'x' ) ydest = args . get ( 'y' ) expr = ( f '($kpffiu.TTXVAX > { xdest - tol } ) and ' \\ f '($kpffiu.TTXVAX < { xdest + tol } )' ) successx = ktl . waitFor ( expr , timeout = timeout ) if successx is not True : raise FailedToReachDestination ( kpffiu [ 'TTXVAX' ] . read (), xdest ) expr = ( f '($kpffiu.TTYVAX > { ydest - tol } ) and ' \\ f '($kpffiu.TTYVAX < { ydest + tol } )' ) successy = ktl . waitFor ( expr , timeout = timeout ) if successy is not True : raise FailedToReachDestination ( kpffiu [ 'TTYVAX' ] . read (), ydest ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'x' , type = float , help = \"X position of the tip tilt mirror (TTXVAX)\" ) parser . add_argument ( 'y' , type = float , help = \"X position of the tip tilt mirror (TTYVAX)\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetTipTiltPosition"},{"location":"scripts/SetTipTiltPosition/#settiptiltposition","text":"Bases: KPFTranslatorFunction Set the position of the tip tilt mirror. This should only be used in an engineering context. To control the position of a star, set the CURRENT_BASE or PIX_TARGET keywords as appropriate, e.g. via the kpf.fiu.SetTipTiltTargetPixel translator module function. Parameters: x ( float ) \u2013 The desired X position (TTXVAX). y ( float ) \u2013 The desired Y position (TTYVAX). KTL Keywords Used: kpffiu.TTXVAX kpffiu.TTYVAX Source code in kpf/fiu/SetTipTiltPosition.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetTipTiltPosition ( KPFTranslatorFunction ): '''Set the position of the tip tilt mirror. This should only be used in an engineering context. To control the position of a star, set the CURRENT_BASE or PIX_TARGET keywords as appropriate, e.g. via the `kpf.fiu.SetTipTiltTargetPixel` translator module function. Args: x (float): The desired X position (TTXVAX). y (float): The desired Y position (TTYVAX). KTL Keywords Used: - `kpffiu.TTXVAX` - `kpffiu.TTYVAX` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'x' ) check_input ( args , 'y' ) @classmethod def perform ( cls , args , logger , cfg ): kpffiu = ktl . cache ( 'kpffiu' ) kpffiu [ 'TTXVAX' ] . write ( args . get ( 'x' )) kpffiu [ 'TTYVAX' ] . write ( args . get ( 'y' )) time_shim = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) time . sleep ( time_shim ) @classmethod def post_condition ( cls , args , logger , cfg ): kpffiu = ktl . cache ( 'kpffiu' ) timeout = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) tol = cfg . getfloat ( 'tolerances' , 'tip_tilt_move_tolerance' , fallback = 0.1 ) xdest = args . get ( 'x' ) ydest = args . get ( 'y' ) expr = ( f '($kpffiu.TTXVAX > { xdest - tol } ) and ' \\ f '($kpffiu.TTXVAX < { xdest + tol } )' ) successx = ktl . waitFor ( expr , timeout = timeout ) if successx is not True : raise FailedToReachDestination ( kpffiu [ 'TTXVAX' ] . read (), xdest ) expr = ( f '($kpffiu.TTYVAX > { ydest - tol } ) and ' \\ f '($kpffiu.TTYVAX < { ydest + tol } )' ) successy = ktl . waitFor ( expr , timeout = timeout ) if successy is not True : raise FailedToReachDestination ( kpffiu [ 'TTYVAX' ] . read (), ydest ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'x' , type = float , help = \"X position of the tip tilt mirror (TTXVAX)\" ) parser . add_argument ( 'y' , type = float , help = \"X position of the tip tilt mirror (TTYVAX)\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetTipTiltPosition"},{"location":"scripts/SetTipTiltTargetPixel/","text":"SetTipTiltTargetPixel Bases: KPFTranslatorFunction Set the target pixel of the tip tilt mirror. This sets the CURRENT_BASE keyword. Parameters: x ( float ) \u2013 The desired X target pixel. y ( float ) \u2013 The desired Y target pixel. KTL Keywords Used: kpfguide.CURRENT_BASE Source code in kpf/fiu/SetTipTiltTargetPixel.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 class SetTipTiltTargetPixel ( KPFTranslatorFunction ): '''Set the target pixel of the tip tilt mirror. This sets the CURRENT_BASE keyword. Args: x (float): The desired X target pixel. y (float): The desired Y target pixel. KTL Keywords Used: - `kpfguide.CURRENT_BASE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): min_x_pixel = cfg . getint ( 'guider' , 'min_x_pixel' , fallback = 0 ) max_x_pixel = cfg . getint ( 'guider' , 'max_x_pixel' , fallback = 640 ) min_y_pixel = cfg . getint ( 'guider' , 'min_y_pixel' , fallback = 0 ) max_y_pixel = cfg . getint ( 'guider' , 'max_y_pixel' , fallback = 512 ) check_input ( args , 'x' , value_min = min_x_pixel , value_max = max_x_pixel ) check_input ( args , 'y' , value_min = min_y_pixel , value_max = max_y_pixel ) @classmethod def perform ( cls , args , logger , cfg ): x = args . get ( 'x' ) y = args . get ( 'y' ) pixtarget = ktl . cache ( 'kpfguide' , 'CURRENT_BASE' ) pixtarget . write (( x , y )) time_shim = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.01 ) time . sleep ( time_shim ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'x' , type = float , help = \"X pixel target (CURRENT_BASE)\" ) parser . add_argument ( 'y' , type = float , help = \"Y pixel target (CURRENT_BASE)\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetTipTiltTargetPixel"},{"location":"scripts/SetTipTiltTargetPixel/#settiptilttargetpixel","text":"Bases: KPFTranslatorFunction Set the target pixel of the tip tilt mirror. This sets the CURRENT_BASE keyword. Parameters: x ( float ) \u2013 The desired X target pixel. y ( float ) \u2013 The desired Y target pixel. KTL Keywords Used: kpfguide.CURRENT_BASE Source code in kpf/fiu/SetTipTiltTargetPixel.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 class SetTipTiltTargetPixel ( KPFTranslatorFunction ): '''Set the target pixel of the tip tilt mirror. This sets the CURRENT_BASE keyword. Args: x (float): The desired X target pixel. y (float): The desired Y target pixel. KTL Keywords Used: - `kpfguide.CURRENT_BASE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): min_x_pixel = cfg . getint ( 'guider' , 'min_x_pixel' , fallback = 0 ) max_x_pixel = cfg . getint ( 'guider' , 'max_x_pixel' , fallback = 640 ) min_y_pixel = cfg . getint ( 'guider' , 'min_y_pixel' , fallback = 0 ) max_y_pixel = cfg . getint ( 'guider' , 'max_y_pixel' , fallback = 512 ) check_input ( args , 'x' , value_min = min_x_pixel , value_max = max_x_pixel ) check_input ( args , 'y' , value_min = min_y_pixel , value_max = max_y_pixel ) @classmethod def perform ( cls , args , logger , cfg ): x = args . get ( 'x' ) y = args . get ( 'y' ) pixtarget = ktl . cache ( 'kpfguide' , 'CURRENT_BASE' ) pixtarget . write (( x , y )) time_shim = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.01 ) time . sleep ( time_shim ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'x' , type = float , help = \"X pixel target (CURRENT_BASE)\" ) parser . add_argument ( 'y' , type = float , help = \"Y pixel target (CURRENT_BASE)\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetTipTiltTargetPixel"},{"location":"scripts/SetTriggeredDetectors/","text":"SetTriggeredDetectors Bases: KPFTranslatorFunction Selects which cameras will be triggered by setting the kpfexpose.TRIG_TARG keyword value. ARGS: :TriggerRed: bool Trigger the Red detector? (default=False) :TriggerGreen: bool Trigger the Green detector? (default=False) :TriggerCaHK: bool Trigger the CaH&K detector? (default=False) :TriggerExpMeter: bool Trigger the ExpMeter detector? (default=False) Source code in kpf/spectrograph/SetTriggeredDetectors.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetTriggeredDetectors ( KPFTranslatorFunction ): '''Selects which cameras will be triggered by setting the `kpfexpose.TRIG_TARG` keyword value. ARGS: ===== :TriggerRed: `bool` Trigger the Red detector? (default=False) :TriggerGreen: `bool` Trigger the Green detector? (default=False) :TriggerCaHK: `bool` Trigger the CaH&K detector? (default=False) :TriggerExpMeter: `bool` Trigger the ExpMeter detector? (default=False) ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfconfig = ktl . cache ( 'kpfconfig' ) detector_list = [] if args . get ( 'TriggerRed' , False ) is True : if kpfconfig [ 'RED_ENABLED' ] . read ( binary = True ) == False : log . warning ( f 'Red detector is not enabled' ) else : detector_list . append ( 'Red' ) if args . get ( 'TriggerGreen' , False ) is True : if kpfconfig [ 'GREEN_ENABLED' ] . read ( binary = True ) == False : log . warning ( f 'Green detector is not enabled' ) else : detector_list . append ( 'Green' ) if args . get ( 'TriggerCaHK' , False ) is True : if kpfconfig [ 'CA_HK_ENABLED' ] . read ( binary = True ) == False : log . warning ( f 'Ca HK detector is not enabled' ) else : detector_list . append ( 'Ca_HK' ) if args . get ( 'TriggerExpMeter' , False ) is True : if kpfconfig [ 'EXPMETER_ENABLED' ] . read ( binary = True ) == False : log . warning ( f 'ExpMeter detector is not enabled' ) else : detector_list . append ( 'ExpMeter' ) if args . get ( 'TriggerGuide' , False ) is True : detector_list . append ( 'Guide' ) detectors_string = ',' . join ( detector_list ) log . debug ( f \"Setting triggered detectors to ' { detectors_string } '\" ) kpfexpose = ktl . cache ( 'kpfexpose' ) kpfexpose [ 'TRIG_TARG' ] . write ( detectors_string ) shim_time = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.1 ) sleep ( shim_time ) @classmethod def post_condition ( cls , args , logger , cfg ): kpfconfig = ktl . cache ( 'kpfconfig' ) kpfexpose = ktl . cache ( 'kpfexpose' ) timeshim = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.1 ) sleep ( timeshim ) detectors = kpfexpose [ 'TRIG_TARG' ] . read () detector_list = detectors . split ( ',' ) detector_names = [( 'Red' , 'TriggerRed' ), ( 'Green' , 'TriggerGreen' ), ( 'Ca_HK' , 'TriggerCaHK' ), ( 'ExpMeter' , 'TriggerExpMeter' ), # ('Guide', 'TriggerGuide'), ] # Don't check on guide because there is no enabled keyword for it for detector in detector_names : detector_status = detector [ 0 ] in detector_list enabled = kpfconfig [ f ' { detector [ 0 ] . upper () } _ENABLED' ] . read ( binary = True ) detector_target = args . get ( detector [ 1 ], False ) and enabled if detector_target != detector_status : raise FailedToReachDestination ( detector_status , detector_target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--Red\" , \"--red\" , \"-r\" , dest = \"TriggerRed\" , default = False , action = \"store_true\" , help = \"Trigger the Red detector during exposure?\" ) parser . add_argument ( \"--Green\" , \"--green\" , \"-g\" , dest = \"TriggerGreen\" , default = False , action = \"store_true\" , help = \"Trigger the Green detector during exposure?\" ) parser . add_argument ( \"--CaHK\" , \"--HK\" , \"--cahk\" , \"--hk\" , dest = \"TriggerCaHK\" , default = False , action = \"store_true\" , help = \"Trigger the CaHK detector during exposure?\" ) parser . add_argument ( \"--ExpMeter\" , \"--expmeter\" , \"--EM\" , \"--em\" , dest = \"TriggerExpMeter\" , default = False , action = \"store_true\" , help = \"Trigger the ExpMeter detector during exposure?\" ) parser . add_argument ( \"--Guide\" , \"--Guider\" , \"--guide\" , \"--guider\" , \"--CRED2\" , dest = \"TriggerGuide\" , default = False , action = \"store_true\" , help = \"Trigger the Guider detector during exposure?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"SetTriggeredDetectors"},{"location":"scripts/SetTriggeredDetectors/#settriggereddetectors","text":"Bases: KPFTranslatorFunction Selects which cameras will be triggered by setting the kpfexpose.TRIG_TARG keyword value.","title":"SetTriggeredDetectors"},{"location":"scripts/SetTriggeredDetectors/#kpf.spectrograph.SetTriggeredDetectors.SetTriggeredDetectors--args","text":":TriggerRed: bool Trigger the Red detector? (default=False) :TriggerGreen: bool Trigger the Green detector? (default=False) :TriggerCaHK: bool Trigger the CaH&K detector? (default=False) :TriggerExpMeter: bool Trigger the ExpMeter detector? (default=False) Source code in kpf/spectrograph/SetTriggeredDetectors.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetTriggeredDetectors ( KPFTranslatorFunction ): '''Selects which cameras will be triggered by setting the `kpfexpose.TRIG_TARG` keyword value. ARGS: ===== :TriggerRed: `bool` Trigger the Red detector? (default=False) :TriggerGreen: `bool` Trigger the Green detector? (default=False) :TriggerCaHK: `bool` Trigger the CaH&K detector? (default=False) :TriggerExpMeter: `bool` Trigger the ExpMeter detector? (default=False) ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfconfig = ktl . cache ( 'kpfconfig' ) detector_list = [] if args . get ( 'TriggerRed' , False ) is True : if kpfconfig [ 'RED_ENABLED' ] . read ( binary = True ) == False : log . warning ( f 'Red detector is not enabled' ) else : detector_list . append ( 'Red' ) if args . get ( 'TriggerGreen' , False ) is True : if kpfconfig [ 'GREEN_ENABLED' ] . read ( binary = True ) == False : log . warning ( f 'Green detector is not enabled' ) else : detector_list . append ( 'Green' ) if args . get ( 'TriggerCaHK' , False ) is True : if kpfconfig [ 'CA_HK_ENABLED' ] . read ( binary = True ) == False : log . warning ( f 'Ca HK detector is not enabled' ) else : detector_list . append ( 'Ca_HK' ) if args . get ( 'TriggerExpMeter' , False ) is True : if kpfconfig [ 'EXPMETER_ENABLED' ] . read ( binary = True ) == False : log . warning ( f 'ExpMeter detector is not enabled' ) else : detector_list . append ( 'ExpMeter' ) if args . get ( 'TriggerGuide' , False ) is True : detector_list . append ( 'Guide' ) detectors_string = ',' . join ( detector_list ) log . debug ( f \"Setting triggered detectors to ' { detectors_string } '\" ) kpfexpose = ktl . cache ( 'kpfexpose' ) kpfexpose [ 'TRIG_TARG' ] . write ( detectors_string ) shim_time = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.1 ) sleep ( shim_time ) @classmethod def post_condition ( cls , args , logger , cfg ): kpfconfig = ktl . cache ( 'kpfconfig' ) kpfexpose = ktl . cache ( 'kpfexpose' ) timeshim = cfg . getfloat ( 'times' , 'kpfexpose_shim_time' , fallback = 0.1 ) sleep ( timeshim ) detectors = kpfexpose [ 'TRIG_TARG' ] . read () detector_list = detectors . split ( ',' ) detector_names = [( 'Red' , 'TriggerRed' ), ( 'Green' , 'TriggerGreen' ), ( 'Ca_HK' , 'TriggerCaHK' ), ( 'ExpMeter' , 'TriggerExpMeter' ), # ('Guide', 'TriggerGuide'), ] # Don't check on guide because there is no enabled keyword for it for detector in detector_names : detector_status = detector [ 0 ] in detector_list enabled = kpfconfig [ f ' { detector [ 0 ] . upper () } _ENABLED' ] . read ( binary = True ) detector_target = args . get ( detector [ 1 ], False ) and enabled if detector_target != detector_status : raise FailedToReachDestination ( detector_status , detector_target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--Red\" , \"--red\" , \"-r\" , dest = \"TriggerRed\" , default = False , action = \"store_true\" , help = \"Trigger the Red detector during exposure?\" ) parser . add_argument ( \"--Green\" , \"--green\" , \"-g\" , dest = \"TriggerGreen\" , default = False , action = \"store_true\" , help = \"Trigger the Green detector during exposure?\" ) parser . add_argument ( \"--CaHK\" , \"--HK\" , \"--cahk\" , \"--hk\" , dest = \"TriggerCaHK\" , default = False , action = \"store_true\" , help = \"Trigger the CaHK detector during exposure?\" ) parser . add_argument ( \"--ExpMeter\" , \"--expmeter\" , \"--EM\" , \"--em\" , dest = \"TriggerExpMeter\" , default = False , action = \"store_true\" , help = \"Trigger the ExpMeter detector during exposure?\" ) parser . add_argument ( \"--Guide\" , \"--Guider\" , \"--guide\" , \"--guider\" , \"--CRED2\" , dest = \"TriggerGuide\" , default = False , action = \"store_true\" , help = \"Trigger the Guider detector during exposure?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"ARGS:"},{"location":"scripts/SetupAOforACAM/","text":"SetupAOforACAM Bases: KPFTranslatorFunction Set up AO in the safe mode for ACAM operation to assist KPF acquisition Scripts Called: kpf.ao.SetAFMtoMirror kpf.ao.SetAFStoNGS Source code in kpf/ao/SetupAOforACAM.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class SetupAOforACAM ( KPFTranslatorFunction ): '''Set up AO in the safe mode for ACAM operation to assist KPF acquisition Scripts Called: - `kpf.ao.SetAFMtoMirror` - `kpf.ao.SetAFStoNGS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): log . info ( 'Set AFM to Mirror' ) SetAFMtoMirror . execute ({}) log . info ( 'Set AFS to NGS' ) SetAFStoNGS . execute ({}) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"SetupAOforACAM"},{"location":"scripts/SetupAOforACAM/#setupaoforacam","text":"Bases: KPFTranslatorFunction Set up AO in the safe mode for ACAM operation to assist KPF acquisition Scripts Called: kpf.ao.SetAFMtoMirror kpf.ao.SetAFStoNGS Source code in kpf/ao/SetupAOforACAM.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class SetupAOforACAM ( KPFTranslatorFunction ): '''Set up AO in the safe mode for ACAM operation to assist KPF acquisition Scripts Called: - `kpf.ao.SetAFMtoMirror` - `kpf.ao.SetAFStoNGS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): log . info ( 'Set AFM to Mirror' ) SetAFMtoMirror . execute ({}) log . info ( 'Set AFS to NGS' ) SetAFStoNGS . execute ({}) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"SetupAOforACAM"},{"location":"scripts/SetupAOforKPF/","text":"SetupAOforKPF Bases: KPFTranslatorFunction Set up AO in the safe mode for KPF operation Set AO roator in Manual mode Set AO rotator to 0 deg Turn off HEPA Set AO in DCS sim mode Home PCU Move PCU to the KPF position Open AO hatch KTL Keywords Used: ao.PCSFNAME Scripts Called: kpf.ao.SetAORotatorManual kpf.ao.SetAORotator kpf.ao.TurnHepaOff kpf.ao.SetAODCStoSIM kpf.ao.TurnLightSourceOff kpf.ao.SendPCUtoHome kpf.ao.SendPCUtoKPF Source code in kpf/ao/SetupAOforKPF.py 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetupAOforKPF ( KPFTranslatorFunction ): '''Set up AO in the safe mode for KPF operation - Set AO roator in Manual mode - Set AO rotator to 0 deg - Turn off HEPA - Set AO in DCS sim mode - Home PCU - Move PCU to the KPF position - Open AO hatch KTL Keywords Used: - `ao.PCSFNAME` Scripts Called: - `kpf.ao.SetAORotatorManual` - `kpf.ao.SetAORotator` - `kpf.ao.TurnHepaOff` - `kpf.ao.SetAODCStoSIM` - `kpf.ao.TurnLightSourceOff` - `kpf.ao.SendPCUtoHome` - `kpf.ao.SendPCUtoKPF` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): log . info ( 'Set AO rotator to Manual' ) SetAORotatorManual . execute ({}) log . info ( 'Set AO rotator to 0 deg' ) SetAORotator . execute ({ 'dest' : 0 }) log . info ( 'Turn off HEPA' ) TurnHepaOff . execute ({}) log . info ( 'Set AO in DCS sim mode' ) SetAODCStoSIM . execute ({}) log . info ( 'Turn K1 AO light source off' ) TurnLightSourceOff . execute ({}) PCSstagekw = ktl . cache ( 'ao' , 'PCSFNAME' ) if PCSstagekw . read () != 'kpf' : log . info ( 'Move PCU to Home' ) SendPCUtoHome . execute ({}) log . info ( 'Move PCU to KPF' ) SendPCUtoKPF . execute ({}) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"SetupAOforKPF"},{"location":"scripts/SetupAOforKPF/#setupaoforkpf","text":"Bases: KPFTranslatorFunction Set up AO in the safe mode for KPF operation Set AO roator in Manual mode Set AO rotator to 0 deg Turn off HEPA Set AO in DCS sim mode Home PCU Move PCU to the KPF position Open AO hatch KTL Keywords Used: ao.PCSFNAME Scripts Called: kpf.ao.SetAORotatorManual kpf.ao.SetAORotator kpf.ao.TurnHepaOff kpf.ao.SetAODCStoSIM kpf.ao.TurnLightSourceOff kpf.ao.SendPCUtoHome kpf.ao.SendPCUtoKPF Source code in kpf/ao/SetupAOforKPF.py 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetupAOforKPF ( KPFTranslatorFunction ): '''Set up AO in the safe mode for KPF operation - Set AO roator in Manual mode - Set AO rotator to 0 deg - Turn off HEPA - Set AO in DCS sim mode - Home PCU - Move PCU to the KPF position - Open AO hatch KTL Keywords Used: - `ao.PCSFNAME` Scripts Called: - `kpf.ao.SetAORotatorManual` - `kpf.ao.SetAORotator` - `kpf.ao.TurnHepaOff` - `kpf.ao.SetAODCStoSIM` - `kpf.ao.TurnLightSourceOff` - `kpf.ao.SendPCUtoHome` - `kpf.ao.SendPCUtoKPF` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): log . info ( 'Set AO rotator to Manual' ) SetAORotatorManual . execute ({}) log . info ( 'Set AO rotator to 0 deg' ) SetAORotator . execute ({ 'dest' : 0 }) log . info ( 'Turn off HEPA' ) TurnHepaOff . execute ({}) log . info ( 'Set AO in DCS sim mode' ) SetAODCStoSIM . execute ({}) log . info ( 'Turn K1 AO light source off' ) TurnLightSourceOff . execute ({}) PCSstagekw = ktl . cache ( 'ao' , 'PCSFNAME' ) if PCSstagekw . read () != 'kpf' : log . info ( 'Move PCU to Home' ) SendPCUtoHome . execute ({}) log . info ( 'Move PCU to KPF' ) SendPCUtoKPF . execute ({}) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"SetupAOforKPF"},{"location":"scripts/SetupExpMeter/","text":"SetupExpMeter Bases: KPFTranslatorFunction Configure the exposure meter using the given OB arguments. Parameters: ExpMeterMode ( str ) \u2013 See Science OB definition. TriggerExpMeter ( bool ) \u2013 See Science OB definition. KTL Keywords Used: kpf_expmeter.USETHRESHOLD kpfconfig.EXPMETER_ENABLED Scripts Called: kpf.expmeter.SetExpMeterTerminationParameters Source code in kpf/expmeter/SetupExpMeter.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetupExpMeter ( KPFTranslatorFunction ): '''Configure the exposure meter using the given OB arguments. Args: ExpMeterMode (str): See Science OB definition. TriggerExpMeter (bool): See Science OB definition. KTL Keywords Used: - `kpf_expmeter.USETHRESHOLD` - `kpfconfig.EXPMETER_ENABLED` Scripts Called: - `kpf.expmeter.SetExpMeterTerminationParameters` ''' abortable = False @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'Template_Name' , allowed_values = [ 'kpf_lamp' , 'kpf_sci' ]) check_input ( args , 'Template_Version' , version_check = True , value_min = '0.5' ) @classmethod def perform ( cls , args , logger , cfg ): kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) kpfconfig = ktl . cache ( 'kpfconfig' ) ## ---------------------------------------------------------------- ## Configure exposure meter ## ---------------------------------------------------------------- log . debug ( 'Setting up exposure meter using SetupExpMeter' ) EM_mode = args . get ( 'ExpMeterMode' , 'off' ) EM_enabled = kpfconfig [ 'EXPMETER_ENABLED' ] . read () == 'Yes' if EM_mode == 'monitor' and EM_enabled : kpf_expmeter [ 'USETHRESHOLD' ] . write ( 'No' ) args [ 'TriggerExpMeter' ] = True elif EM_mode == 'control' and EM_enabled : args [ 'TriggerExpMeter' ] = True try : SetExpMeterTerminationParameters . execute ( args ) except Exception as e : log . error ( 'SetExpMeterTerminationParameters failed' ) log . error ( e ) traceback_text = traceback . format_exc () log . error ( traceback_text ) kpf_expmeter [ 'USETHRESHOLD' ] . write ( 'No' ) elif EM_mode in [ 'off' , False ]: # pyyaml converts 'off' to False, so handle both args [ 'TriggerExpMeter' ] = False elif EM_enabled == False : log . warning ( 'ExpMeter is disabled' ) else : log . warning ( f \"ExpMeterMode { EM_mode } is not available\" ) kpf_expmeter [ 'USETHRESHOLD' ] . write ( 'No' ) # Must return args as we have edited them return args @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( '--nointensemon' , dest = \"nointensemon\" , default = False , action = \"store_true\" , help = 'Skip the intensity monitor measurement?' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetupExpMeter"},{"location":"scripts/SetupExpMeter/#setupexpmeter","text":"Bases: KPFTranslatorFunction Configure the exposure meter using the given OB arguments. Parameters: ExpMeterMode ( str ) \u2013 See Science OB definition. TriggerExpMeter ( bool ) \u2013 See Science OB definition. KTL Keywords Used: kpf_expmeter.USETHRESHOLD kpfconfig.EXPMETER_ENABLED Scripts Called: kpf.expmeter.SetExpMeterTerminationParameters Source code in kpf/expmeter/SetupExpMeter.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class SetupExpMeter ( KPFTranslatorFunction ): '''Configure the exposure meter using the given OB arguments. Args: ExpMeterMode (str): See Science OB definition. TriggerExpMeter (bool): See Science OB definition. KTL Keywords Used: - `kpf_expmeter.USETHRESHOLD` - `kpfconfig.EXPMETER_ENABLED` Scripts Called: - `kpf.expmeter.SetExpMeterTerminationParameters` ''' abortable = False @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'Template_Name' , allowed_values = [ 'kpf_lamp' , 'kpf_sci' ]) check_input ( args , 'Template_Version' , version_check = True , value_min = '0.5' ) @classmethod def perform ( cls , args , logger , cfg ): kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) kpfconfig = ktl . cache ( 'kpfconfig' ) ## ---------------------------------------------------------------- ## Configure exposure meter ## ---------------------------------------------------------------- log . debug ( 'Setting up exposure meter using SetupExpMeter' ) EM_mode = args . get ( 'ExpMeterMode' , 'off' ) EM_enabled = kpfconfig [ 'EXPMETER_ENABLED' ] . read () == 'Yes' if EM_mode == 'monitor' and EM_enabled : kpf_expmeter [ 'USETHRESHOLD' ] . write ( 'No' ) args [ 'TriggerExpMeter' ] = True elif EM_mode == 'control' and EM_enabled : args [ 'TriggerExpMeter' ] = True try : SetExpMeterTerminationParameters . execute ( args ) except Exception as e : log . error ( 'SetExpMeterTerminationParameters failed' ) log . error ( e ) traceback_text = traceback . format_exc () log . error ( traceback_text ) kpf_expmeter [ 'USETHRESHOLD' ] . write ( 'No' ) elif EM_mode in [ 'off' , False ]: # pyyaml converts 'off' to False, so handle both args [ 'TriggerExpMeter' ] = False elif EM_enabled == False : log . warning ( 'ExpMeter is disabled' ) else : log . warning ( f \"ExpMeterMode { EM_mode } is not available\" ) kpf_expmeter [ 'USETHRESHOLD' ] . write ( 'No' ) # Must return args as we have edited them return args @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( '--nointensemon' , dest = \"nointensemon\" , default = False , action = \"store_true\" , help = 'Skip the intensity monitor measurement?' ) return super () . add_cmdline_args ( parser , cfg )","title":"SetupExpMeter"},{"location":"scripts/ShutdownTipTilt/","text":"ShutdownTipTilt Bases: KPFTranslatorFunction Shutdown the tip tilt system by setting the control mode to open loop and setting the target values in X and Y to 0. KTL Keywords Used: kpffiu.TTXSRV kpffiu.TTYSRV kpffiu.TTXVAX kpffiu.TTYVAX kpfguide.TIPTILT_CONTROL kpfguide.TIPTILT_CALC kpfguide.TIPTILT_HOME Source code in kpf/fiu/ShutdownTipTilt.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class ShutdownTipTilt ( KPFTranslatorFunction ): '''Shutdown the tip tilt system by setting the control mode to open loop and setting the target values in X and Y to 0. KTL Keywords Used: - `kpffiu.TTXSRV` - `kpffiu.TTYSRV` - `kpffiu.TTXVAX` - `kpffiu.TTYVAX` - `kpfguide.TIPTILT_CONTROL` - `kpfguide.TIPTILT_CALC` - `kpfguide.TIPTILT_HOME` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) kpffiu = ktl . cache ( 'kpffiu' ) xopen = kpffiu [ 'TTXSRV' ] . read () == 'Open' yopen = kpffiu [ 'TTYSRV' ] . read () == 'Open' if xopen and yopen : # No actions needed return elif xopen == False and yopen == False : # Both axis are in closed loop mode # Shut down tip tilt activity and park mirror before opening loops kpfguide [ 'TIPTILT_CONTROL' ] . write ( 'Inactive' ) kpfguide [ 'TIPTILT_CALC' ] . write ( 'Inactive' ) tthome = ktl . cache ( 'kpfguide' , 'TIPTILT_HOME' ) home = tthome . read ( binary = True ) log . debug ( f 'Sending Tip tilt mirror to home: { home [ 0 ] } { home [ 1 ] } ' ) kpffiu [ 'TTXVAX' ] . write ( home [ 0 ]) kpffiu [ 'TTYVAX' ] . write ( home [ 1 ]) log . debug ( 'Opening tip tilt mirror servo loops' ) kpffiu [ 'TTXSRV' ] . write ( 'open' ) kpffiu [ 'TTYSRV' ] . write ( 'open' ) else : # We're in a mixed state, just open the loops log . debug ( 'Opening tip tilt mirror servo loops' ) kpffiu [ 'TTXSRV' ] . write ( 'open' ) kpffiu [ 'TTYSRV' ] . write ( 'open' ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) success1 = ktl . waitFor ( '($kpffiu.TTXSRV == open)' , timeout = timeout ) success2 = ktl . waitFor ( '($kpffiu.TTYSRV == open)' , timeout = timeout ) if success1 == False or success2 == False : raise FailedPostCondition ( f 'TT[X and/or Y]SRV did not open' )","title":"ShutdownTipTilt"},{"location":"scripts/ShutdownTipTilt/#shutdowntiptilt","text":"Bases: KPFTranslatorFunction Shutdown the tip tilt system by setting the control mode to open loop and setting the target values in X and Y to 0. KTL Keywords Used: kpffiu.TTXSRV kpffiu.TTYSRV kpffiu.TTXVAX kpffiu.TTYVAX kpfguide.TIPTILT_CONTROL kpfguide.TIPTILT_CALC kpfguide.TIPTILT_HOME Source code in kpf/fiu/ShutdownTipTilt.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class ShutdownTipTilt ( KPFTranslatorFunction ): '''Shutdown the tip tilt system by setting the control mode to open loop and setting the target values in X and Y to 0. KTL Keywords Used: - `kpffiu.TTXSRV` - `kpffiu.TTYSRV` - `kpffiu.TTXVAX` - `kpffiu.TTYVAX` - `kpfguide.TIPTILT_CONTROL` - `kpfguide.TIPTILT_CALC` - `kpfguide.TIPTILT_HOME` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) kpffiu = ktl . cache ( 'kpffiu' ) xopen = kpffiu [ 'TTXSRV' ] . read () == 'Open' yopen = kpffiu [ 'TTYSRV' ] . read () == 'Open' if xopen and yopen : # No actions needed return elif xopen == False and yopen == False : # Both axis are in closed loop mode # Shut down tip tilt activity and park mirror before opening loops kpfguide [ 'TIPTILT_CONTROL' ] . write ( 'Inactive' ) kpfguide [ 'TIPTILT_CALC' ] . write ( 'Inactive' ) tthome = ktl . cache ( 'kpfguide' , 'TIPTILT_HOME' ) home = tthome . read ( binary = True ) log . debug ( f 'Sending Tip tilt mirror to home: { home [ 0 ] } { home [ 1 ] } ' ) kpffiu [ 'TTXVAX' ] . write ( home [ 0 ]) kpffiu [ 'TTYVAX' ] . write ( home [ 1 ]) log . debug ( 'Opening tip tilt mirror servo loops' ) kpffiu [ 'TTXSRV' ] . write ( 'open' ) kpffiu [ 'TTYSRV' ] . write ( 'open' ) else : # We're in a mixed state, just open the loops log . debug ( 'Opening tip tilt mirror servo loops' ) kpffiu [ 'TTXSRV' ] . write ( 'open' ) kpffiu [ 'TTYSRV' ] . write ( 'open' ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) success1 = ktl . waitFor ( '($kpffiu.TTXSRV == open)' , timeout = timeout ) success2 = ktl . waitFor ( '($kpffiu.TTYSRV == open)' , timeout = timeout ) if success1 == False or success2 == False : raise FailedPostCondition ( f 'TT[X and/or Y]SRV did not open' )","title":"ShutdownTipTilt"},{"location":"scripts/SoCalStartAutonomous/","text":"SoCalStartAutonomous Bases: KPFTranslatorFunction Start SoCal's AUTONOMOUS mode by setting AUTONOMOUS=1 ARGS: None Source code in kpf/socal/SoCalStartAutonomous.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class SoCalStartAutonomous ( KPFTranslatorFunction ): '''Start SoCal's AUTONOMOUS mode by setting AUTONOMOUS=1 ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): AUTONOMOUS = ktl . cache ( 'kpfsocal' , 'AUTONOMOUS' ) log . info ( 'Setting kpfsocal.AUTONOMOUS = 1' ) AUTONOMOUS . write ( 1 ) @classmethod def post_condition ( cls , args , logger , cfg ): AUTONOMOUS = ktl . cache ( 'kpfsocal' , 'AUTONOMOUS' ) success = AUTONOMOUS . waitFor ( \"==1\" , timeout = 1 ) if success is False : raise FailedToReachDestination ( 'kpfsocal.AUTONOMOUS is not 1' )","title":"SoCalStartAutonomous"},{"location":"scripts/SoCalStartAutonomous/#socalstartautonomous","text":"Bases: KPFTranslatorFunction Start SoCal's AUTONOMOUS mode by setting AUTONOMOUS=1","title":"SoCalStartAutonomous"},{"location":"scripts/SoCalStartAutonomous/#kpf.socal.SoCalStartAutonomous.SoCalStartAutonomous--args","text":"None Source code in kpf/socal/SoCalStartAutonomous.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class SoCalStartAutonomous ( KPFTranslatorFunction ): '''Start SoCal's AUTONOMOUS mode by setting AUTONOMOUS=1 ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): AUTONOMOUS = ktl . cache ( 'kpfsocal' , 'AUTONOMOUS' ) log . info ( 'Setting kpfsocal.AUTONOMOUS = 1' ) AUTONOMOUS . write ( 1 ) @classmethod def post_condition ( cls , args , logger , cfg ): AUTONOMOUS = ktl . cache ( 'kpfsocal' , 'AUTONOMOUS' ) success = AUTONOMOUS . waitFor ( \"==1\" , timeout = 1 ) if success is False : raise FailedToReachDestination ( 'kpfsocal.AUTONOMOUS is not 1' )","title":"ARGS:"},{"location":"scripts/SoCalStopAutonomous/","text":"SoCalStopAutonomous Bases: KPFTranslatorFunction Stop SoCal's AUTONOMOUS mode by setting AUTONOMOUS=0 ARGS: None Source code in kpf/socal/SoCalStopAutonomous.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class SoCalStopAutonomous ( KPFTranslatorFunction ): '''Stop SoCal's AUTONOMOUS mode by setting AUTONOMOUS=0 ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): AUTONOMOUS = ktl . cache ( 'kpfsocal' , 'AUTONOMOUS' ) log . info ( 'Setting kpfsocal.AUTONOMOUS = 0' ) AUTONOMOUS . write ( 0 ) @classmethod def post_condition ( cls , args , logger , cfg ): AUTONOMOUS = ktl . cache ( 'kpfsocal' , 'AUTONOMOUS' ) success = AUTONOMOUS . waitFor ( \"==0\" , timeout = 1 ) if success is False : raise FailedToReachDestination ( 'kpfsocal.AUTONOMOUS is not 0' )","title":"SoCalStopAutonomous"},{"location":"scripts/SoCalStopAutonomous/#socalstopautonomous","text":"Bases: KPFTranslatorFunction Stop SoCal's AUTONOMOUS mode by setting AUTONOMOUS=0","title":"SoCalStopAutonomous"},{"location":"scripts/SoCalStopAutonomous/#kpf.socal.SoCalStopAutonomous.SoCalStopAutonomous--args","text":"None Source code in kpf/socal/SoCalStopAutonomous.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class SoCalStopAutonomous ( KPFTranslatorFunction ): '''Stop SoCal's AUTONOMOUS mode by setting AUTONOMOUS=0 ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): AUTONOMOUS = ktl . cache ( 'kpfsocal' , 'AUTONOMOUS' ) log . info ( 'Setting kpfsocal.AUTONOMOUS = 0' ) AUTONOMOUS . write ( 0 ) @classmethod def post_condition ( cls , args , logger , cfg ): AUTONOMOUS = ktl . cache ( 'kpfsocal' , 'AUTONOMOUS' ) success = AUTONOMOUS . waitFor ( \"==0\" , timeout = 1 ) if success is False : raise FailedToReachDestination ( 'kpfsocal.AUTONOMOUS is not 0' )","title":"ARGS:"},{"location":"scripts/StartAgitator/","text":"StartAgitator Bases: KPFTranslatorFunction Start the agitator motion and wait the appropriate startup time before returning. ARGS: None Source code in kpf/spectrograph/StartAgitator.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class StartAgitator ( KPFTranslatorFunction ): '''Start the agitator motion and wait the appropriate startup time before returning. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): agitator = ktl . cache ( 'kpfmot' , 'AGITATOR' ) if agitator . read () == 'Running' : log . debug ( 'Agitator is running' ) else : startup = cfg . getfloat ( 'times' , 'agitator_startup_time' , fallback = 0.325 ) log . debug ( 'Starting agitator motion' ) try : agitator . write ( 'Run' ) except Exception as e : log . warning ( 'Write to kpfmot.AGITATOR failed' ) log . debug ( e ) log . warning ( 'Retrying' ) time . sleep ( 1 ) agitator . write ( 'Run' ) time . sleep ( startup ) @classmethod def post_condition ( cls , args , logger , cfg ): startup = cfg . getfloat ( 'times' , 'agitator_startup_time' , fallback = 0.325 ) success = ktl . waitFor ( '$kpfmot.AGITATOR == Running' , timeout = 5 * startup ) if success is not True : agitator = ktl . cache ( 'kpfmot' , 'AGITATOR' ) raise FailedToReachDestination ( agitator . read (), 'Running' )","title":"StartAgitator"},{"location":"scripts/StartAgitator/#startagitator","text":"Bases: KPFTranslatorFunction Start the agitator motion and wait the appropriate startup time before returning.","title":"StartAgitator"},{"location":"scripts/StartAgitator/#kpf.spectrograph.StartAgitator.StartAgitator--args","text":"None Source code in kpf/spectrograph/StartAgitator.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class StartAgitator ( KPFTranslatorFunction ): '''Start the agitator motion and wait the appropriate startup time before returning. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): agitator = ktl . cache ( 'kpfmot' , 'AGITATOR' ) if agitator . read () == 'Running' : log . debug ( 'Agitator is running' ) else : startup = cfg . getfloat ( 'times' , 'agitator_startup_time' , fallback = 0.325 ) log . debug ( 'Starting agitator motion' ) try : agitator . write ( 'Run' ) except Exception as e : log . warning ( 'Write to kpfmot.AGITATOR failed' ) log . debug ( e ) log . warning ( 'Retrying' ) time . sleep ( 1 ) agitator . write ( 'Run' ) time . sleep ( startup ) @classmethod def post_condition ( cls , args , logger , cfg ): startup = cfg . getfloat ( 'times' , 'agitator_startup_time' , fallback = 0.325 ) success = ktl . waitFor ( '$kpfmot.AGITATOR == Running' , timeout = 5 * startup ) if success is not True : agitator = ktl . cache ( 'kpfmot' , 'AGITATOR' ) raise FailedToReachDestination ( agitator . read (), 'Running' )","title":"ARGS:"},{"location":"scripts/StartExposure/","text":"StartExposure Bases: KPFTranslatorFunction Begins an triggered exposure by setting the kpfexpose.EXPOSE keyword to Start. This will return immediately after. Use commands like WaitForReadout or WaitForReady to determine when an exposure is done. ARGS: None Source code in kpf/spectrograph/StartExposure.py 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class StartExposure ( KPFTranslatorFunction ): '''Begins an triggered exposure by setting the `kpfexpose.EXPOSE` keyword to Start. This will return immediately after. Use commands like WaitForReadout or WaitForReady to determine when an exposure is done. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): expose = ktl . cache ( 'kpfexpose' , 'EXPOSE' ) WaitForReady . execute ({}) log . debug ( f \"Beginning Exposure\" ) expose . write ( 'Start' ) @classmethod def post_condition ( cls , args , logger , cfg ): expr = f \"(kpfexpose.EXPOSE != Start)\" kpfexpose = ktl . cache ( 'kpfexpose' ) is_GREEN_ENABLED = ktl . cache ( 'kpfconfig' , 'GREEN_ENABLED' ) . read () == 'Yes' is_RED_ENABLED = ktl . cache ( 'kpfconfig' , 'RED_ENABLED' ) . read () == 'Yes' is_CA_HK_ENABLED = ktl . cache ( 'kpfconfig' , 'CA_HK_ENABLED' ) . read () == 'Yes' trig_targ = kpfexpose [ 'TRIG_TARG' ] . read () . split ( ',' ) if 'Green' in trig_targ and is_GREEN_ENABLED : expr += ' and ($kpfgreen.EXPSTATE != Start)' if 'Red' in trig_targ and is_RED_ENABLED : expr += ' and ($kpfred.EXPSTATE != Start)' if 'Ca_HK' in trig_targ and is_CA_HK_ENABLED : expr += ' and ($kpf_hk.EXPSTATE != Start)' exptime = kpfexpose [ 'EXPOSURE' ] . read ( binary = True ) timeout = 6 left_start_state = ktl . waitFor ( expr , timeout = timeout ) if left_start_state is False : log . error ( f 'We are still in start state after { timeout } s' ) # Figure out which detector is stuck in the start state? if is_GREEN_ENABLED : green_expstate = ktl . cache ( 'kpfgreen' , 'EXPSTATE' ) . read () log . debug ( f 'kpfgreen.EXPSTATE = { green_expstate } ' ) if is_RED_ENABLED : red_expstate = ktl . cache ( 'kpfred' , 'EXPSTATE' ) . read () log . debug ( f 'kpfred.EXPSTATE = { red_expstate } ' ) if is_CA_HK_ENABLED : cahk_expstate = ktl . cache ( 'kpf_hk' , 'EXPSTATE' ) . read () log . debug ( f 'kpf_hk.EXPSTATE = { cahk_expstate } ' ) # Abort the current exposure elapsed = kpfexpose [ 'ELAPSED' ] . read ( binary = True ) remaining = exptime - elapsed if remaining <= 10 : # Don't stop exposure, just wait it out log . debug ( f 'Waiting out remaining { remaining } s of exposure' ) time . sleep ( remaining + 2 ) else : log . warning ( 'Stopping current exposure (with read out)' ) kpfexpose [ 'EXPOSE' ] . write ( 'End' ) time . sleep ( 2 ) # Time shim, this time is a WAG # Now reset the offending detector if is_GREEN_ENABLED : if green_expstate == 'Start' : ResetGreenDetector . execute ({}) if is_RED_ENABLED : if red_expstate == 'Start' : ResetRedDetector . execute ({}) if is_CA_HK_ENABLED : if cahk_expstate == 'Start' : ResetCaHKDetector . execute ({}) # Now start a fresh exposure WaitForReady . execute ({}) time . sleep ( 1.0 ) # This time shim and the WaitForReady are hacks to catch if the WaitForReady . execute ({}) # reset detector went in to readout, but we didn't know. log . warning ( 'Restarting exposure' ) StartExposure . execute ( args )","title":"StartExposure"},{"location":"scripts/StartExposure/#startexposure","text":"Bases: KPFTranslatorFunction Begins an triggered exposure by setting the kpfexpose.EXPOSE keyword to Start. This will return immediately after. Use commands like WaitForReadout or WaitForReady to determine when an exposure is done.","title":"StartExposure"},{"location":"scripts/StartExposure/#kpf.spectrograph.StartExposure.StartExposure--args","text":"None Source code in kpf/spectrograph/StartExposure.py 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class StartExposure ( KPFTranslatorFunction ): '''Begins an triggered exposure by setting the `kpfexpose.EXPOSE` keyword to Start. This will return immediately after. Use commands like WaitForReadout or WaitForReady to determine when an exposure is done. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): expose = ktl . cache ( 'kpfexpose' , 'EXPOSE' ) WaitForReady . execute ({}) log . debug ( f \"Beginning Exposure\" ) expose . write ( 'Start' ) @classmethod def post_condition ( cls , args , logger , cfg ): expr = f \"(kpfexpose.EXPOSE != Start)\" kpfexpose = ktl . cache ( 'kpfexpose' ) is_GREEN_ENABLED = ktl . cache ( 'kpfconfig' , 'GREEN_ENABLED' ) . read () == 'Yes' is_RED_ENABLED = ktl . cache ( 'kpfconfig' , 'RED_ENABLED' ) . read () == 'Yes' is_CA_HK_ENABLED = ktl . cache ( 'kpfconfig' , 'CA_HK_ENABLED' ) . read () == 'Yes' trig_targ = kpfexpose [ 'TRIG_TARG' ] . read () . split ( ',' ) if 'Green' in trig_targ and is_GREEN_ENABLED : expr += ' and ($kpfgreen.EXPSTATE != Start)' if 'Red' in trig_targ and is_RED_ENABLED : expr += ' and ($kpfred.EXPSTATE != Start)' if 'Ca_HK' in trig_targ and is_CA_HK_ENABLED : expr += ' and ($kpf_hk.EXPSTATE != Start)' exptime = kpfexpose [ 'EXPOSURE' ] . read ( binary = True ) timeout = 6 left_start_state = ktl . waitFor ( expr , timeout = timeout ) if left_start_state is False : log . error ( f 'We are still in start state after { timeout } s' ) # Figure out which detector is stuck in the start state? if is_GREEN_ENABLED : green_expstate = ktl . cache ( 'kpfgreen' , 'EXPSTATE' ) . read () log . debug ( f 'kpfgreen.EXPSTATE = { green_expstate } ' ) if is_RED_ENABLED : red_expstate = ktl . cache ( 'kpfred' , 'EXPSTATE' ) . read () log . debug ( f 'kpfred.EXPSTATE = { red_expstate } ' ) if is_CA_HK_ENABLED : cahk_expstate = ktl . cache ( 'kpf_hk' , 'EXPSTATE' ) . read () log . debug ( f 'kpf_hk.EXPSTATE = { cahk_expstate } ' ) # Abort the current exposure elapsed = kpfexpose [ 'ELAPSED' ] . read ( binary = True ) remaining = exptime - elapsed if remaining <= 10 : # Don't stop exposure, just wait it out log . debug ( f 'Waiting out remaining { remaining } s of exposure' ) time . sleep ( remaining + 2 ) else : log . warning ( 'Stopping current exposure (with read out)' ) kpfexpose [ 'EXPOSE' ] . write ( 'End' ) time . sleep ( 2 ) # Time shim, this time is a WAG # Now reset the offending detector if is_GREEN_ENABLED : if green_expstate == 'Start' : ResetGreenDetector . execute ({}) if is_RED_ENABLED : if red_expstate == 'Start' : ResetRedDetector . execute ({}) if is_CA_HK_ENABLED : if cahk_expstate == 'Start' : ResetCaHKDetector . execute ({}) # Now start a fresh exposure WaitForReady . execute ({}) time . sleep ( 1.0 ) # This time shim and the WaitForReady are hacks to catch if the WaitForReady . execute ({}) # reset detector went in to readout, but we didn't know. log . warning ( 'Restarting exposure' ) StartExposure . execute ( args )","title":"ARGS:"},{"location":"scripts/StartGUIs/","text":"StartGUIs Bases: KPFTranslatorFunction Start KPF GUIs ARGS None Source code in kpf/utils/StartGUIs.py 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 class StartGUIs ( KPFTranslatorFunction ): '''Start KPF GUIs ### ARGS None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # Get DISPLAY varibales env = os . environ uidisp = {} # for dispno in [0, 1, 2, 3]: # uidisp_proc = subprocess.run(['uidisp', f'{dispno}'], env=env, # stdout=subprocess.PIPE) # uidisp[dispno] = uidisp_proc.stdout.decode().strip('\\n') kvncstatus_proc = subprocess . run ([ 'kvncstatus' ], env = env , stdout = subprocess . PIPE ) kvncstatus = Table . read ( kvncstatus_proc . stdout . decode (), format = 'ascii' ) username = os . getlogin () display = { 'control0' : kvncstatus [ kvncstatus [ 'Desktop' ] == f 'kpf- { username } -control0' ][ 'Display' ][ 0 ], 'control1' : kvncstatus [ kvncstatus [ 'Desktop' ] == f 'kpf- { username } -control1' ][ 'Display' ][ 0 ], 'control2' : kvncstatus [ kvncstatus [ 'Desktop' ] == f 'kpf- { username } -control2' ][ 'Display' ][ 0 ], 'telstatus' : kvncstatus [ kvncstatus [ 'Desktop' ] == f 'kpf- { username } -telstatus' ][ 'Display' ][ 0 ], } # Start GUIs if needed for GUI in GUI_list : # Find out of GUIs are Running log . debug ( f \"Setting DISPLAY to kpf { display [ GUI [ 'display' ]] } \" ) env [ 'DISPLAY' ] = f \"kpf { display [ GUI [ 'display' ]] } \" window_names = get_window_list ( env = env ) GUIname = GUI [ 'name' ] if GUIname not in window_names and args . get ( 'position_only' , False ) is False : instrume = ktl . cache ( 'dcs1' , 'INSTRUME' ) if GUIname == 'MAGIQ - Observer UI: KPF on Keck1' and instrume . read () != 'KPF' : log . info ( f 'Selected instrument is not KPF, not starting magiq' ) success = False else : log . info ( f \"Starting ' { GUIname } ' GUI\" ) gui_proc = subprocess . Popen ( GUI [ 'cmd' ], env = env , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) success = waitfor_window_to_appear ( GUIname , env = env ) if success is False : log . error ( f ' { GUIname } did not come up' ) stdout , stderr = gui_proc . communicate () log . error ( f \"STDERR: { stderr . decode () } \" ) log . error ( f \"STDOUT: { stdout . decode () } \" ) else : log . info ( f \"Existing ' { GUIname } ' window found\" ) success = True time . sleep ( 2 ) if GUI . get ( 'position' , None ) is not None and success is True : log . info ( f \"Positioning ' { GUIname } ' GUI\" ) wmctrl_cmd = [ 'wmctrl' , '-r' , f '\" { GUIname } \"' , '-e' , GUI [ 'position' ]] log . debug ( f \" Running: { ' ' . join ( wmctrl_cmd ) } \" ) wmctrl_proc = subprocess . run ( ' ' . join ( wmctrl_cmd ), env = env , shell = True ) if GUI [ 'cmd' ][ 0 ] == 'xterm' : xterm_title = GUI [ 'cmd' ][ 2 ] success = waitfor_window_to_appear ( xterm_title , env = env ) log . info ( f \"Minimizing ' { xterm_title } '\" ) wmctrl_cmd = [ 'wmctrl' , '-r' , xterm_title , '-b' , 'add,hidden' ] wmctrl_proc = subprocess . run ( ' ' . join ( wmctrl_cmd ), env = env , shell = True ) if GUIname == 'SAOImage kpfds9' : # Configure ds9 initial color maps and scaling cmaps = { '1' : 'cool' , '2' : 'green' , '3' : 'heat' } for frameno in cmaps . keys (): xpaset_cmds = [[ 'xpaset' , '-p' , 'kpfds9' , 'frame' , 'frameno' , f ' { frameno } ' ], [ 'xpaset' , '-p' , 'kpfds9' , 'cmap' , f ' { cmaps [ frameno ] } ' ], [ 'xpaset' , '-p' , 'kpfds9' , 'scale' , '99.5' ]] for xpaset_cmd in xpaset_cmds : xpa_proc = subprocess . Popen ( xpaset_cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) time . sleep ( 1 ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--position\" , \"-p\" , dest = \"position_only\" , default = False , action = \"store_true\" , help = \"Only position the GUIs, do not start\" ) return super () . add_cmdline_args ( parser , cfg )","title":"StartGUIs"},{"location":"scripts/StartGUIs/#startguis","text":"Bases: KPFTranslatorFunction Start KPF GUIs","title":"StartGUIs"},{"location":"scripts/StartGUIs/#kpf.utils.StartGUIs.StartGUIs--args","text":"None Source code in kpf/utils/StartGUIs.py 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 class StartGUIs ( KPFTranslatorFunction ): '''Start KPF GUIs ### ARGS None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # Get DISPLAY varibales env = os . environ uidisp = {} # for dispno in [0, 1, 2, 3]: # uidisp_proc = subprocess.run(['uidisp', f'{dispno}'], env=env, # stdout=subprocess.PIPE) # uidisp[dispno] = uidisp_proc.stdout.decode().strip('\\n') kvncstatus_proc = subprocess . run ([ 'kvncstatus' ], env = env , stdout = subprocess . PIPE ) kvncstatus = Table . read ( kvncstatus_proc . stdout . decode (), format = 'ascii' ) username = os . getlogin () display = { 'control0' : kvncstatus [ kvncstatus [ 'Desktop' ] == f 'kpf- { username } -control0' ][ 'Display' ][ 0 ], 'control1' : kvncstatus [ kvncstatus [ 'Desktop' ] == f 'kpf- { username } -control1' ][ 'Display' ][ 0 ], 'control2' : kvncstatus [ kvncstatus [ 'Desktop' ] == f 'kpf- { username } -control2' ][ 'Display' ][ 0 ], 'telstatus' : kvncstatus [ kvncstatus [ 'Desktop' ] == f 'kpf- { username } -telstatus' ][ 'Display' ][ 0 ], } # Start GUIs if needed for GUI in GUI_list : # Find out of GUIs are Running log . debug ( f \"Setting DISPLAY to kpf { display [ GUI [ 'display' ]] } \" ) env [ 'DISPLAY' ] = f \"kpf { display [ GUI [ 'display' ]] } \" window_names = get_window_list ( env = env ) GUIname = GUI [ 'name' ] if GUIname not in window_names and args . get ( 'position_only' , False ) is False : instrume = ktl . cache ( 'dcs1' , 'INSTRUME' ) if GUIname == 'MAGIQ - Observer UI: KPF on Keck1' and instrume . read () != 'KPF' : log . info ( f 'Selected instrument is not KPF, not starting magiq' ) success = False else : log . info ( f \"Starting ' { GUIname } ' GUI\" ) gui_proc = subprocess . Popen ( GUI [ 'cmd' ], env = env , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) success = waitfor_window_to_appear ( GUIname , env = env ) if success is False : log . error ( f ' { GUIname } did not come up' ) stdout , stderr = gui_proc . communicate () log . error ( f \"STDERR: { stderr . decode () } \" ) log . error ( f \"STDOUT: { stdout . decode () } \" ) else : log . info ( f \"Existing ' { GUIname } ' window found\" ) success = True time . sleep ( 2 ) if GUI . get ( 'position' , None ) is not None and success is True : log . info ( f \"Positioning ' { GUIname } ' GUI\" ) wmctrl_cmd = [ 'wmctrl' , '-r' , f '\" { GUIname } \"' , '-e' , GUI [ 'position' ]] log . debug ( f \" Running: { ' ' . join ( wmctrl_cmd ) } \" ) wmctrl_proc = subprocess . run ( ' ' . join ( wmctrl_cmd ), env = env , shell = True ) if GUI [ 'cmd' ][ 0 ] == 'xterm' : xterm_title = GUI [ 'cmd' ][ 2 ] success = waitfor_window_to_appear ( xterm_title , env = env ) log . info ( f \"Minimizing ' { xterm_title } '\" ) wmctrl_cmd = [ 'wmctrl' , '-r' , xterm_title , '-b' , 'add,hidden' ] wmctrl_proc = subprocess . run ( ' ' . join ( wmctrl_cmd ), env = env , shell = True ) if GUIname == 'SAOImage kpfds9' : # Configure ds9 initial color maps and scaling cmaps = { '1' : 'cool' , '2' : 'green' , '3' : 'heat' } for frameno in cmaps . keys (): xpaset_cmds = [[ 'xpaset' , '-p' , 'kpfds9' , 'frame' , 'frameno' , f ' { frameno } ' ], [ 'xpaset' , '-p' , 'kpfds9' , 'cmap' , f ' { cmaps [ frameno ] } ' ], [ 'xpaset' , '-p' , 'kpfds9' , 'scale' , '99.5' ]] for xpaset_cmd in xpaset_cmds : xpa_proc = subprocess . Popen ( xpaset_cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) time . sleep ( 1 ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--position\" , \"-p\" , dest = \"position_only\" , default = False , action = \"store_true\" , help = \"Only position the GUIs, do not start\" ) return super () . add_cmdline_args ( parser , cfg )","title":"ARGS"},{"location":"scripts/StartGuiderContinuous/","text":"StartGuiderContinuous Bases: KPFTranslatorFunction Put the guider in to continuous exposure mode and set images to be saved. KTL Keywords Used: kpfguide.CONTINUOUS kpfguide.SAVE Source code in kpf/guider/StartGuiderContinuous.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class StartGuiderContinuous ( KPFTranslatorFunction ): '''Put the guider in to continuous exposure mode and set images to be saved. KTL Keywords Used: - `kpfguide.CONTINUOUS` - `kpfguide.SAVE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) kpfguide [ 'CONTINUOUS' ] . write ( 'active' ) kpfguide [ 'SAVE' ] . write ( 'active' ) @classmethod def post_condition ( cls , args , logger , cfg ): if guider_is_active () == False : raise FailedPostCondition ( 'Guider is not active' ) if guider_is_saving () == False : raise FailedPostCondition ( 'Guider is not saving' )","title":"StartGuiderContinuous"},{"location":"scripts/StartGuiderContinuous/#startguidercontinuous","text":"Bases: KPFTranslatorFunction Put the guider in to continuous exposure mode and set images to be saved. KTL Keywords Used: kpfguide.CONTINUOUS kpfguide.SAVE Source code in kpf/guider/StartGuiderContinuous.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class StartGuiderContinuous ( KPFTranslatorFunction ): '''Put the guider in to continuous exposure mode and set images to be saved. KTL Keywords Used: - `kpfguide.CONTINUOUS` - `kpfguide.SAVE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) kpfguide [ 'CONTINUOUS' ] . write ( 'active' ) kpfguide [ 'SAVE' ] . write ( 'active' ) @classmethod def post_condition ( cls , args , logger , cfg ): if guider_is_active () == False : raise FailedPostCondition ( 'Guider is not active' ) if guider_is_saving () == False : raise FailedPostCondition ( 'Guider is not saving' )","title":"StartGuiderContinuous"},{"location":"scripts/StartOfNight/","text":"StartOfNight Bases: KPFTranslatorFunction Send KPF in to a reasonable starting configuration set FIU mode to observing Setup AO for KPF Configure DCS (ROTDEST and ROTMODE) ARGS: AO - bool Open AO hatch, send PCU to KPF, and turn on HEPA? (default=True) Source code in kpf/scripts/StartOfNight.py 24 25 26 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 class StartOfNight ( KPFTranslatorFunction ): '''Send KPF in to a reasonable starting configuration - set FIU mode to observing - Setup AO for KPF - Configure DCS (ROTDEST and ROTMODE) ARGS: ===== * __AO__ - `bool` Open AO hatch, send PCU to KPF, and turn on HEPA? (default=True) ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , args , logger , cfg ): log . info ( f \"Running KPF Start of Night script\" ) # Check Scripts kpfconfig = ktl . cache ( 'kpfconfig' ) expose = ktl . cache ( 'kpfexpose' , 'EXPOSE' ) scriptname = kpfconfig [ 'SCRIPTNAME' ] . read () pid = kpfconfig [ 'SCRIPTPID' ] . read ( binary = True ) if scriptname not in [ '' , 'None' , None ] or pid >= 0 : # --------------------------------- # User Verification # --------------------------------- msg = [ \"\" , \"--------------------------------------------------------------\" , f \"A script ( { scriptname } , { pid } ) is currently running. \" , \"\" , \"Depending on when you are seeing this, it may be a scheduled\" , \"nighttime calibration which can and should be interrupted to\" , \"enable observing.\" , \"\" , \"Do you wish to end the current exposure and request a script\" , \"stop in order to proceed with running StartOfNight?\" , \"\" , \"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 Start 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 () # --------------------------------- # Remaining non-AO Actions # --------------------------------- # Disallow cron job calibration scripts log . info ( 'Set ALLOWSCHEDULEDCALS to No' ) kpfconfig = ktl . cache ( 'kpfconfig' ) kpfconfig [ 'ALLOWSCHEDULEDCALS' ] . write ( 'No' ) # Configure FIU log . info ( 'Configure FIU for \"Observing\"' ) ConfigureFIU . execute ({ 'mode' : 'Observing' }) # Set DCS rotator parameters dcs = ktl . cache ( 'dcs1' ) inst = dcs [ 'INSTRUME' ] . read () if inst == 'KPF' : log . info ( f \"Setting dcs.ROTDEST = 0\" ) dcs [ 'ROTDEST' ] . write ( 0 ) log . info ( f \"Setting dcs.ROTMODE = stationary\" ) dcs [ 'ROTMODE' ] . write ( 'stationary' ) else : log . warning ( f \"Instrument is { inst } , not configuring DCS\" ) # Report Agitator status runagitator = kpfconfig [ 'USEAGITATOR' ] . read ( binary = True ) if runagitator is True : log . info ( f \"Agitator use is enabled\" ) else : log . warning ( f \"Agitator use is disabled for tonight\" ) # Pre-configure cal source calsource = kpfconfig [ 'SIMULCALSOURCE' ] . read () log . info ( f \"Setting simultaneous CalSource/Octagon: { calsource } \" ) SetCalSource . execute ({ 'CalSource' : calsource , 'wait' : True }) # Power on Simulcal lamp if needed if calsource in [ 'U_gold' , 'U_daily' , 'Th_daily' , 'Th_gold' ]: CalLampPower . execute ({ 'lamp' : calsource , 'power' : 'on' }) # Set tip tilt loop gain to default value kpfguide = ktl . cache ( 'kpfguide' ) tip_tilt_gain = cfg . getfloat ( 'tiptilt' , 'tiptilt_loop_gain' , fallback = 0.3 ) log . info ( f \"Setting default tip tilt loop gain of { tip_tilt_gain } \" ) SetTipTiltGain . execute ({ 'GuideLoopGain' : tip_tilt_gain }) # Set tip tilt loop detection threshold to default value detect_snr = cfg . getfloat ( 'tiptilt' , 'detect_snr' , fallback = 7 ) log . info ( f \"Setting default tip tilt detection SNR of { detect_snr } \" ) kpfguide [ 'OBJECT_INTENSITY' ] . write ( detect_snr ) # Set tip tilt loop detection area to default value detect_area = cfg . getfloat ( 'tiptilt' , 'detect_area' , fallback = 100 ) log . info ( f \"Setting default tip tilt detection area of { detect_area } \" ) kpfguide [ 'OBJECT_AREA' ] . write ( detect_area ) # Set tip tilt loop deblend parameter to default value deblend = cfg . getfloat ( 'tiptilt' , 'deblend' , fallback = 1 ) log . info ( f \"Setting default tip tilt deblending parameter of { deblend } \" ) kpfguide [ 'OBJECT_DBCONT' ] . write ( 1.0 ) # Set DAR parameter to default value log . info ( f \"Ensuring DAR correction is on\" ) kpfguide [ 'DAR_ENABLE' ] . write ( 'Yes' ) # Set Outdirs if expose . read () != 'Ready' : log . info ( 'Waiting for kpfexpose to be Ready' ) WaitForReady . execute ({}) SetOutdirs . execute ({}) # Set guider gain to high for initial acquisition and focus SetGuiderGain . execute ({ 'GuideCamGain' : 'high' }) # Set progname and observer SetObserverFromSchedule . execute ({}) # Summarize Detector Disabled States cahk_enabled = kpfconfig [ 'CA_HK_ENABLED' ] . read ( binary = True ) if cahk_enabled is False : log . warning ( f \"The CA_HK detector is disabled tonight\" ) green_enabled = kpfconfig [ 'GREEN_ENABLED' ] . read ( binary = True ) if green_enabled is False : log . warning ( f \"The Green detector is disabled tonight\" ) red_enabled = kpfconfig [ 'RED_ENABLED' ] . read ( binary = True ) if red_enabled is False : log . warning ( f \"The Red detector is disabled tonight\" ) expmeter_enabled = kpfconfig [ 'EXPMETER_ENABLED' ] . read ( binary = True ) if expmeter_enabled is False : log . warning ( f \"The ExpMeter detector is disabled tonight\" ) # Setup AO if args . get ( 'AO' , True ) is True : # --------------------------------- # User Verification # --------------------------------- msg = [ \"\" , \"--------------------------------------------------------------\" , \"This script will configure the FIU and AO bench for observing.\" , \"The AO bench area should be clear of personnel before proceeding.\" , \"Do you wish to to continue?\" , \"(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 Start Of Night' ) return else : SetupAOforKPF . execute ({}) log . info ( 'Open AO hatch' ) try : ControlAOHatch . execute ({ 'destination' : 'open' }) except FailedToReachDestination : log . error ( f \"AO hatch did not move successfully\" ) print () print ( '----------------------------------------------------------' ) print ( 'AO hatch reported problems moving. Make sure stars are' ) print ( 'visible on guide camera before proceeding.' ) print ( '----------------------------------------------------------' ) print () @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--noAO\" , dest = \"AO\" , default = True , action = \"store_false\" , help = \"Skip configuring AO?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"StartOfNight"},{"location":"scripts/StartOfNight/#startofnight","text":"Bases: KPFTranslatorFunction Send KPF in to a reasonable starting configuration set FIU mode to observing Setup AO for KPF Configure DCS (ROTDEST and ROTMODE)","title":"StartOfNight"},{"location":"scripts/StartOfNight/#kpf.scripts.StartOfNight.StartOfNight--args","text":"AO - bool Open AO hatch, send PCU to KPF, and turn on HEPA? (default=True) Source code in kpf/scripts/StartOfNight.py 24 25 26 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 class StartOfNight ( KPFTranslatorFunction ): '''Send KPF in to a reasonable starting configuration - set FIU mode to observing - Setup AO for KPF - Configure DCS (ROTDEST and ROTMODE) ARGS: ===== * __AO__ - `bool` Open AO hatch, send PCU to KPF, and turn on HEPA? (default=True) ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , args , logger , cfg ): log . info ( f \"Running KPF Start of Night script\" ) # Check Scripts kpfconfig = ktl . cache ( 'kpfconfig' ) expose = ktl . cache ( 'kpfexpose' , 'EXPOSE' ) scriptname = kpfconfig [ 'SCRIPTNAME' ] . read () pid = kpfconfig [ 'SCRIPTPID' ] . read ( binary = True ) if scriptname not in [ '' , 'None' , None ] or pid >= 0 : # --------------------------------- # User Verification # --------------------------------- msg = [ \"\" , \"--------------------------------------------------------------\" , f \"A script ( { scriptname } , { pid } ) is currently running. \" , \"\" , \"Depending on when you are seeing this, it may be a scheduled\" , \"nighttime calibration which can and should be interrupted to\" , \"enable observing.\" , \"\" , \"Do you wish to end the current exposure and request a script\" , \"stop in order to proceed with running StartOfNight?\" , \"\" , \"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 Start 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 () # --------------------------------- # Remaining non-AO Actions # --------------------------------- # Disallow cron job calibration scripts log . info ( 'Set ALLOWSCHEDULEDCALS to No' ) kpfconfig = ktl . cache ( 'kpfconfig' ) kpfconfig [ 'ALLOWSCHEDULEDCALS' ] . write ( 'No' ) # Configure FIU log . info ( 'Configure FIU for \"Observing\"' ) ConfigureFIU . execute ({ 'mode' : 'Observing' }) # Set DCS rotator parameters dcs = ktl . cache ( 'dcs1' ) inst = dcs [ 'INSTRUME' ] . read () if inst == 'KPF' : log . info ( f \"Setting dcs.ROTDEST = 0\" ) dcs [ 'ROTDEST' ] . write ( 0 ) log . info ( f \"Setting dcs.ROTMODE = stationary\" ) dcs [ 'ROTMODE' ] . write ( 'stationary' ) else : log . warning ( f \"Instrument is { inst } , not configuring DCS\" ) # Report Agitator status runagitator = kpfconfig [ 'USEAGITATOR' ] . read ( binary = True ) if runagitator is True : log . info ( f \"Agitator use is enabled\" ) else : log . warning ( f \"Agitator use is disabled for tonight\" ) # Pre-configure cal source calsource = kpfconfig [ 'SIMULCALSOURCE' ] . read () log . info ( f \"Setting simultaneous CalSource/Octagon: { calsource } \" ) SetCalSource . execute ({ 'CalSource' : calsource , 'wait' : True }) # Power on Simulcal lamp if needed if calsource in [ 'U_gold' , 'U_daily' , 'Th_daily' , 'Th_gold' ]: CalLampPower . execute ({ 'lamp' : calsource , 'power' : 'on' }) # Set tip tilt loop gain to default value kpfguide = ktl . cache ( 'kpfguide' ) tip_tilt_gain = cfg . getfloat ( 'tiptilt' , 'tiptilt_loop_gain' , fallback = 0.3 ) log . info ( f \"Setting default tip tilt loop gain of { tip_tilt_gain } \" ) SetTipTiltGain . execute ({ 'GuideLoopGain' : tip_tilt_gain }) # Set tip tilt loop detection threshold to default value detect_snr = cfg . getfloat ( 'tiptilt' , 'detect_snr' , fallback = 7 ) log . info ( f \"Setting default tip tilt detection SNR of { detect_snr } \" ) kpfguide [ 'OBJECT_INTENSITY' ] . write ( detect_snr ) # Set tip tilt loop detection area to default value detect_area = cfg . getfloat ( 'tiptilt' , 'detect_area' , fallback = 100 ) log . info ( f \"Setting default tip tilt detection area of { detect_area } \" ) kpfguide [ 'OBJECT_AREA' ] . write ( detect_area ) # Set tip tilt loop deblend parameter to default value deblend = cfg . getfloat ( 'tiptilt' , 'deblend' , fallback = 1 ) log . info ( f \"Setting default tip tilt deblending parameter of { deblend } \" ) kpfguide [ 'OBJECT_DBCONT' ] . write ( 1.0 ) # Set DAR parameter to default value log . info ( f \"Ensuring DAR correction is on\" ) kpfguide [ 'DAR_ENABLE' ] . write ( 'Yes' ) # Set Outdirs if expose . read () != 'Ready' : log . info ( 'Waiting for kpfexpose to be Ready' ) WaitForReady . execute ({}) SetOutdirs . execute ({}) # Set guider gain to high for initial acquisition and focus SetGuiderGain . execute ({ 'GuideCamGain' : 'high' }) # Set progname and observer SetObserverFromSchedule . execute ({}) # Summarize Detector Disabled States cahk_enabled = kpfconfig [ 'CA_HK_ENABLED' ] . read ( binary = True ) if cahk_enabled is False : log . warning ( f \"The CA_HK detector is disabled tonight\" ) green_enabled = kpfconfig [ 'GREEN_ENABLED' ] . read ( binary = True ) if green_enabled is False : log . warning ( f \"The Green detector is disabled tonight\" ) red_enabled = kpfconfig [ 'RED_ENABLED' ] . read ( binary = True ) if red_enabled is False : log . warning ( f \"The Red detector is disabled tonight\" ) expmeter_enabled = kpfconfig [ 'EXPMETER_ENABLED' ] . read ( binary = True ) if expmeter_enabled is False : log . warning ( f \"The ExpMeter detector is disabled tonight\" ) # Setup AO if args . get ( 'AO' , True ) is True : # --------------------------------- # User Verification # --------------------------------- msg = [ \"\" , \"--------------------------------------------------------------\" , \"This script will configure the FIU and AO bench for observing.\" , \"The AO bench area should be clear of personnel before proceeding.\" , \"Do you wish to to continue?\" , \"(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 Start Of Night' ) return else : SetupAOforKPF . execute ({}) log . info ( 'Open AO hatch' ) try : ControlAOHatch . execute ({ 'destination' : 'open' }) except FailedToReachDestination : log . error ( f \"AO hatch did not move successfully\" ) print () print ( '----------------------------------------------------------' ) print ( 'AO hatch reported problems moving. Make sure stars are' ) print ( 'visible on guide camera before proceeding.' ) print ( '----------------------------------------------------------' ) print () @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( \"--noAO\" , dest = \"AO\" , default = True , action = \"store_false\" , help = \"Skip configuring AO?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"ARGS:"},{"location":"scripts/StartTipTilt/","text":"StartTipTilt Bases: KPFTranslatorFunction Start the tip tilt control loop. This uses the ALL_LOOPS keyword to start all functions including DAR (via DAR_ENABLE), tip tilt calculations (via TIPTILT_CALC), tip tilt control (via TIPTILT_CONTROL), offloading to the telescope (via OFFLOAD_DCS and OFFLOAD). KTL Keywords Used: kpffiu.TTXSRV kpffiu.TTYSRV kpfguide.DAR_ENABLE kpfguide.ALL_LOOPS Source code in kpf/fiu/StartTipTilt.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class StartTipTilt ( KPFTranslatorFunction ): '''Start the tip tilt control loop. This uses the ALL_LOOPS keyword to start all functions including DAR (via DAR_ENABLE), tip tilt calculations (via TIPTILT_CALC), tip tilt control (via TIPTILT_CONTROL), offloading to the telescope (via OFFLOAD_DCS and OFFLOAD). KTL Keywords Used: - `kpffiu.TTXSRV` - `kpffiu.TTYSRV` - `kpfguide.DAR_ENABLE` - `kpfguide.ALL_LOOPS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): expr = \"($kpffiu.TTXSRV == 'Closed') and ($kpffiu.TTYSRV == 'Closed')\" servo_loops_closed = ktl . waitFor ( expr , timeout = 0.5 ) if not servo_loops_closed : kpffiu = ktl . cache ( 'kpffiu' ) log . info ( 'Closing servo loops' ) kpffiu [ 'TTXSRV' ] . write ( 'Closed' ) kpffiu [ 'TTYSRV' ] . write ( 'Closed' ) movetime = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) time . sleep ( 10 * movetime ) kpfguide = ktl . cache ( 'kpfguide' ) log . info ( 'Turning kpfguide.ALL_LOOPS on' ) kpfguide [ 'ALL_LOOPS' ] . write ( 'Active' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"StartTipTilt"},{"location":"scripts/StartTipTilt/#starttiptilt","text":"Bases: KPFTranslatorFunction Start the tip tilt control loop. This uses the ALL_LOOPS keyword to start all functions including DAR (via DAR_ENABLE), tip tilt calculations (via TIPTILT_CALC), tip tilt control (via TIPTILT_CONTROL), offloading to the telescope (via OFFLOAD_DCS and OFFLOAD). KTL Keywords Used: kpffiu.TTXSRV kpffiu.TTYSRV kpfguide.DAR_ENABLE kpfguide.ALL_LOOPS Source code in kpf/fiu/StartTipTilt.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class StartTipTilt ( KPFTranslatorFunction ): '''Start the tip tilt control loop. This uses the ALL_LOOPS keyword to start all functions including DAR (via DAR_ENABLE), tip tilt calculations (via TIPTILT_CALC), tip tilt control (via TIPTILT_CONTROL), offloading to the telescope (via OFFLOAD_DCS and OFFLOAD). KTL Keywords Used: - `kpffiu.TTXSRV` - `kpffiu.TTYSRV` - `kpfguide.DAR_ENABLE` - `kpfguide.ALL_LOOPS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): expr = \"($kpffiu.TTXSRV == 'Closed') and ($kpffiu.TTYSRV == 'Closed')\" servo_loops_closed = ktl . waitFor ( expr , timeout = 0.5 ) if not servo_loops_closed : kpffiu = ktl . cache ( 'kpffiu' ) log . info ( 'Closing servo loops' ) kpffiu [ 'TTXSRV' ] . write ( 'Closed' ) kpffiu [ 'TTYSRV' ] . write ( 'Closed' ) movetime = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) time . sleep ( 10 * movetime ) kpfguide = ktl . cache ( 'kpfguide' ) log . info ( 'Turning kpfguide.ALL_LOOPS on' ) kpfguide [ 'ALL_LOOPS' ] . write ( 'Active' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"StartTipTilt"},{"location":"scripts/StartTriggerFile/","text":"StartTriggerFile Bases: KPFTranslatorFunction Start a \"trigger file\" from the guide camera. KTL Keywords Used: kpfguide.TRIGCUBE kpfguide.TRIGGER Source code in kpf/guider/StartTriggerFile.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class StartTriggerFile ( KPFTranslatorFunction ): '''Start a \"trigger file\" from the guide camera. KTL Keywords Used: - `kpfguide.TRIGCUBE` - `kpfguide.TRIGGER` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) cube = kpfguide [ 'TRIGCUBE' ] . read () log . info ( f \"Start guider trigger file data collection: TRIGCUBE= { cube } \" ) kpfguide [ 'TRIGGER' ] . write ( 'Active' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"StartTriggerFile"},{"location":"scripts/StartTriggerFile/#starttriggerfile","text":"Bases: KPFTranslatorFunction Start a \"trigger file\" from the guide camera. KTL Keywords Used: kpfguide.TRIGCUBE kpfguide.TRIGGER Source code in kpf/guider/StartTriggerFile.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class StartTriggerFile ( KPFTranslatorFunction ): '''Start a \"trigger file\" from the guide camera. KTL Keywords Used: - `kpfguide.TRIGCUBE` - `kpfguide.TRIGGER` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) cube = kpfguide [ 'TRIGCUBE' ] . read () log . info ( f \"Start guider trigger file data collection: TRIGCUBE= { cube } \" ) kpfguide [ 'TRIGGER' ] . write ( 'Active' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"StartTriggerFile"},{"location":"scripts/StartUp/","text":"StartUp Bases: KPFTranslatorFunction Start KPF software for afternoon setup. ARGS: None Source code in kpf/scripts/StartUp.py 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class StartUp ( KPFTranslatorFunction ): '''Start KPF software for afternoon setup. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # Start GUIs StartGUIs . execute ({}) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"StartUp"},{"location":"scripts/StartUp/#startup","text":"Bases: KPFTranslatorFunction Start KPF software for afternoon setup.","title":"StartUp"},{"location":"scripts/StartUp/#kpf.scripts.StartUp.StartUp--args","text":"None Source code in kpf/scripts/StartUp.py 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class StartUp ( KPFTranslatorFunction ): '''Start KPF software for afternoon setup. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # Start GUIs StartGUIs . execute ({}) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"ARGS:"},{"location":"scripts/StopAgitator/","text":"StopAgitator Bases: KPFTranslatorFunction Stop the agitator motion. ARGS: None Source code in kpf/spectrograph/StopAgitator.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 class StopAgitator ( KPFTranslatorFunction ): '''Stop the agitator motion. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): agitator = ktl . cache ( 'kpfmot' , 'AGITATOR' ) if agitator . read () == 'Stopped' : log . debug ( 'Agitator is stopped' ) else : log . debug ( 'Stopping agitator' ) try : agitator . write ( 'Stop' ) except Exception as e : log . warning ( 'Write to kpfmot.AGITATOR failed' ) log . debug ( e ) log . warning ( 'Retrying' ) time . sleep ( 1 ) agitator . write ( 'Stop' ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'agitator_startup_time' , fallback = 0.325 ) success = ktl . waitFor ( '$kpfmot.AGITATOR == Stopped' , timeout = 5 * timeout ) if success is not True : agitator = ktl . cache ( 'kpfmot' , 'AGITATOR' ) raise FailedToReachDestination ( agitator . read (), 'Stopped' )","title":"StopAgitator"},{"location":"scripts/StopAgitator/#stopagitator","text":"Bases: KPFTranslatorFunction Stop the agitator motion.","title":"StopAgitator"},{"location":"scripts/StopAgitator/#kpf.spectrograph.StopAgitator.StopAgitator--args","text":"None Source code in kpf/spectrograph/StopAgitator.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 class StopAgitator ( KPFTranslatorFunction ): '''Stop the agitator motion. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): agitator = ktl . cache ( 'kpfmot' , 'AGITATOR' ) if agitator . read () == 'Stopped' : log . debug ( 'Agitator is stopped' ) else : log . debug ( 'Stopping agitator' ) try : agitator . write ( 'Stop' ) except Exception as e : log . warning ( 'Write to kpfmot.AGITATOR failed' ) log . debug ( e ) log . warning ( 'Retrying' ) time . sleep ( 1 ) agitator . write ( 'Stop' ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'agitator_startup_time' , fallback = 0.325 ) success = ktl . waitFor ( '$kpfmot.AGITATOR == Stopped' , timeout = 5 * timeout ) if success is not True : agitator = ktl . cache ( 'kpfmot' , 'AGITATOR' ) raise FailedToReachDestination ( agitator . read (), 'Stopped' )","title":"ARGS:"},{"location":"scripts/StopGUIs/","text":"StopGUIs Bases: KPFTranslatorFunction Stop KPF GUIs ARGS None Source code in kpf/utils/StopGUIs.py 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 class StopGUIs ( KPFTranslatorFunction ): '''Stop KPF GUIs ### ARGS None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): for GUI in GUI_list : GUIname = GUI [ 'name' ] if GUI [ 'cmd' ][ 0 ] == 'kpf' : GUIscriptname = GUI [ 'cmd' ][ 2 ] status_cmd = GUI [ 'cmd' ] status_cmd [ 1 ] = 'status' log . info ( f \"Getting status of ' { GUIname } ' GUI\" ) gui_proc = subprocess . run ( status_cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) stdout = gui_proc . stdout . decode () . strip () is_running = re . search ( 'is running on' , stdout ) if is_running is not None : stop_cmd = GUI [ 'cmd' ] stop_cmd [ 1 ] = 'stop' log . info ( f \"Stopping ' { GUIname } ' GUI\" ) stopout = subprocess . run ( stop_cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) log . debug ( f \" { stopout . returncode } \" ) log . debug ( f \" { stopout . stdout . decode () } \" ) log . debug ( f \" { stopout . stderr . decode () } \" ) else : log . info ( f \" { GUIname } is not running\" ) log . debug ( f \" { stdout } \" ) elif GUIname == 'MAGIQ - Observer UI' : log . info ( f \"Stopping ' { GUIname } ' GUI\" ) stop_cmd = GUI [ 'cmd' ] stop_cmd [ 4 ] = 'stop' gui_proc = subprocess . Popen ( stop_cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) else : log . info ( f \"Stopping ' { GUIname } ' GUI\" ) kill_process ( GUI [ 'cmd' ], server = 'kpf' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"StopGUIs"},{"location":"scripts/StopGUIs/#stopguis","text":"Bases: KPFTranslatorFunction Stop KPF GUIs","title":"StopGUIs"},{"location":"scripts/StopGUIs/#kpf.utils.StopGUIs.StopGUIs--args","text":"None Source code in kpf/utils/StopGUIs.py 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 class StopGUIs ( KPFTranslatorFunction ): '''Stop KPF GUIs ### ARGS None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): for GUI in GUI_list : GUIname = GUI [ 'name' ] if GUI [ 'cmd' ][ 0 ] == 'kpf' : GUIscriptname = GUI [ 'cmd' ][ 2 ] status_cmd = GUI [ 'cmd' ] status_cmd [ 1 ] = 'status' log . info ( f \"Getting status of ' { GUIname } ' GUI\" ) gui_proc = subprocess . run ( status_cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) stdout = gui_proc . stdout . decode () . strip () is_running = re . search ( 'is running on' , stdout ) if is_running is not None : stop_cmd = GUI [ 'cmd' ] stop_cmd [ 1 ] = 'stop' log . info ( f \"Stopping ' { GUIname } ' GUI\" ) stopout = subprocess . run ( stop_cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) log . debug ( f \" { stopout . returncode } \" ) log . debug ( f \" { stopout . stdout . decode () } \" ) log . debug ( f \" { stopout . stderr . decode () } \" ) else : log . info ( f \" { GUIname } is not running\" ) log . debug ( f \" { stdout } \" ) elif GUIname == 'MAGIQ - Observer UI' : log . info ( f \"Stopping ' { GUIname } ' GUI\" ) stop_cmd = GUI [ 'cmd' ] stop_cmd [ 4 ] = 'stop' gui_proc = subprocess . Popen ( stop_cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ) else : log . info ( f \"Stopping ' { GUIname } ' GUI\" ) kill_process ( GUI [ 'cmd' ], server = 'kpf' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"ARGS"},{"location":"scripts/StopGuiderContinuous/","text":"StopGuiderContinuous Bases: KPFTranslatorFunction Stop the guider's continuous exposure mode and stop saving images. KTL Keywords Used: kpfguide.CONTINUOUS kpfguide.SAVE Source code in kpf/guider/StopGuiderContinuous.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class StopGuiderContinuous ( KPFTranslatorFunction ): '''Stop the guider's continuous exposure mode and stop saving images. KTL Keywords Used: - `kpfguide.CONTINUOUS` - `kpfguide.SAVE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) kpfguide [ 'CONTINUOUS' ] . write ( 'inactive' ) kpfguide [ 'SAVE' ] . write ( 'inactive' ) @classmethod def post_condition ( cls , args , logger , cfg ): if guider_is_active () != False : raise FailedPostCondition ( 'Guider is not inactive' ) if guider_is_saving () != False : raise FailedPostCondition ( 'Guider is still saving' )","title":"StopGuiderContinuous"},{"location":"scripts/StopGuiderContinuous/#stopguidercontinuous","text":"Bases: KPFTranslatorFunction Stop the guider's continuous exposure mode and stop saving images. KTL Keywords Used: kpfguide.CONTINUOUS kpfguide.SAVE Source code in kpf/guider/StopGuiderContinuous.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class StopGuiderContinuous ( KPFTranslatorFunction ): '''Stop the guider's continuous exposure mode and stop saving images. KTL Keywords Used: - `kpfguide.CONTINUOUS` - `kpfguide.SAVE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) kpfguide [ 'CONTINUOUS' ] . write ( 'inactive' ) kpfguide [ 'SAVE' ] . write ( 'inactive' ) @classmethod def post_condition ( cls , args , logger , cfg ): if guider_is_active () != False : raise FailedPostCondition ( 'Guider is not inactive' ) if guider_is_saving () != False : raise FailedPostCondition ( 'Guider is still saving' )","title":"StopGuiderContinuous"},{"location":"scripts/StopTipTilt/","text":"StopTipTilt Bases: KPFTranslatorFunction Stop the tip tilt control loop. This uses the ALL_LOOPS keyword to stop all functions including DAR (via DAR_ENABLE), tip tilt calculations (via TIPTILT_CALC), tip tilt control (via TIPTILT_CONTROL), offloading to the telescope (via OFFLOAD_DCS and OFFLOAD). KTL Keywords Used: kpfguide.TIPTILT_CALC kpfguide.TIPTILT_CONTROL kpfguide.OFFLOAD kpfguide.ALL_LOOPS Source code in kpf/fiu/StopTipTilt.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 class StopTipTilt ( KPFTranslatorFunction ): '''Stop the tip tilt control loop. This uses the ALL_LOOPS keyword to stop all functions including DAR (via DAR_ENABLE), tip tilt calculations (via TIPTILT_CALC), tip tilt control (via TIPTILT_CONTROL), offloading to the telescope (via OFFLOAD_DCS and OFFLOAD). KTL Keywords Used: - `kpfguide.TIPTILT_CALC` - `kpfguide.TIPTILT_CONTROL` - `kpfguide.OFFLOAD` - `kpfguide.ALL_LOOPS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) kpfguide [ 'ALL_LOOPS' ] . write ( 'Inactive' ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) TIPTILT_CALC = ktl . cache ( 'kpfguide' , 'TIPTILT_CALC' ) success = TIPTILT_CALC . waitFor ( \"== 'Inactive'\" ) if success is False : raise FailedToReachDestination ( TIPTILT_CALC . read (), 'Inactive' ) TIPTILT_CONTROL = ktl . cache ( 'kpfguide' , 'TIPTILT_CONTROL' ) success = TIPTILT_CONTROL . waitFor ( \"== 'Inactive'\" ) if success is False : raise FailedToReachDestination ( TIPTILT_CONTROL . read (), 'Inactive' ) OFFLOAD = ktl . cache ( 'kpfguide' , 'OFFLOAD' ) success = OFFLOAD . waitFor ( \"== 'Inactive'\" ) if success is False : raise FailedToReachDestination ( OFFLOAD . read (), 'Inactive' )","title":"StopTipTilt"},{"location":"scripts/StopTipTilt/#stoptiptilt","text":"Bases: KPFTranslatorFunction Stop the tip tilt control loop. This uses the ALL_LOOPS keyword to stop all functions including DAR (via DAR_ENABLE), tip tilt calculations (via TIPTILT_CALC), tip tilt control (via TIPTILT_CONTROL), offloading to the telescope (via OFFLOAD_DCS and OFFLOAD). KTL Keywords Used: kpfguide.TIPTILT_CALC kpfguide.TIPTILT_CONTROL kpfguide.OFFLOAD kpfguide.ALL_LOOPS Source code in kpf/fiu/StopTipTilt.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 class StopTipTilt ( KPFTranslatorFunction ): '''Stop the tip tilt control loop. This uses the ALL_LOOPS keyword to stop all functions including DAR (via DAR_ENABLE), tip tilt calculations (via TIPTILT_CALC), tip tilt control (via TIPTILT_CONTROL), offloading to the telescope (via OFFLOAD_DCS and OFFLOAD). KTL Keywords Used: - `kpfguide.TIPTILT_CALC` - `kpfguide.TIPTILT_CONTROL` - `kpfguide.OFFLOAD` - `kpfguide.ALL_LOOPS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) kpfguide [ 'ALL_LOOPS' ] . write ( 'Inactive' ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) TIPTILT_CALC = ktl . cache ( 'kpfguide' , 'TIPTILT_CALC' ) success = TIPTILT_CALC . waitFor ( \"== 'Inactive'\" ) if success is False : raise FailedToReachDestination ( TIPTILT_CALC . read (), 'Inactive' ) TIPTILT_CONTROL = ktl . cache ( 'kpfguide' , 'TIPTILT_CONTROL' ) success = TIPTILT_CONTROL . waitFor ( \"== 'Inactive'\" ) if success is False : raise FailedToReachDestination ( TIPTILT_CONTROL . read (), 'Inactive' ) OFFLOAD = ktl . cache ( 'kpfguide' , 'OFFLOAD' ) success = OFFLOAD . waitFor ( \"== 'Inactive'\" ) if success is False : raise FailedToReachDestination ( OFFLOAD . read (), 'Inactive' )","title":"StopTipTilt"},{"location":"scripts/StopTriggerFile/","text":"StopTriggerFile Bases: KPFTranslatorFunction Stop a \"trigger file\" from the guide camera. KTL Keywords Used: kpfguide.TRIGGER Source code in kpf/guider/StopTriggerFile.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class StopTriggerFile ( KPFTranslatorFunction ): '''Stop a \"trigger file\" from the guide camera. KTL Keywords Used: - `kpfguide.TRIGGER` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) log . info ( f \"Stopping guider trigger file data collection\" ) kpfguide [ 'TRIGGER' ] . write ( 'Inactive' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"StopTriggerFile"},{"location":"scripts/StopTriggerFile/#stoptriggerfile","text":"Bases: KPFTranslatorFunction Stop a \"trigger file\" from the guide camera. KTL Keywords Used: kpfguide.TRIGGER Source code in kpf/guider/StopTriggerFile.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class StopTriggerFile ( KPFTranslatorFunction ): '''Stop a \"trigger file\" from the guide camera. KTL Keywords Used: - `kpfguide.TRIGGER` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) log . info ( f \"Stopping guider trigger file data collection\" ) kpfguide [ 'TRIGGER' ] . write ( 'Inactive' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"StopTriggerFile"},{"location":"scripts/TakeADCGridData/","text":"TakeADCGridData Bases: KPFTranslatorFunction Source code in kpf/engineering/TakeADCGridData.py 18 19 20 21 22 23 24 25 26 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 class TakeADCGridData ( KPFTranslatorFunction ): ''' ''' @classmethod def pre_condition ( cls , OB , logger , cfg ): pass @classmethod @register_script ( Path ( __file__ ) . name , os . getpid ()) @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , args , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in args : log . debug ( f \" { key } : { args [ key ] } \" ) log . info ( '-------------------------' ) adc1min = args . get ( 'ADC1MIN' , 60 ) adc1max = args . get ( 'ADC1MAX' , 70 ) adc2min = args . get ( 'ADC2MIN' , 60 ) adc2max = args . get ( 'ADC2MAX' , 70 ) adcstep = args . get ( 'ADCSTEP' , 1 ) adc1vals = np . arange ( adc1min , adc1max + adcstep , adcstep ) adc2vals = np . arange ( adc2min , adc2max + adcstep , adcstep ) adcsleeptime = 1 fvcsleeptime = 0.25 ADC1VAL = ktl . cache ( 'kpffiu' , 'ADC1VAL' ) ADC1VAL . monitor () ADC2VAL = ktl . cache ( 'kpffiu' , 'ADC2VAL' ) ADC2VAL . monitor () LASTFILE = ktl . cache ( 'kpffvc' , 'EXTLASTFILE' ) LASTFILE . monitor () this_file_name = Path ( __file__ ) . name . replace ( '.py' , '' ) utnow = datetime . utcnow () now_str = utnow . strftime ( '%Y%m %d at%H%M%S' ) date_str = ( utnow - timedelta ( days = 1 )) . strftime ( '%Y%b %d ' ) . lower () log_path = Path ( f '/s/sdata1701/KPFTranslator_logs/ { date_str } ' ) images_file = log_path / Path ( f ' { this_file_name } _ { now_str } .txt' ) images = Table ( names = ( 'file' , 'ADC1VAL' , 'ADC2VAL' ), dtype = ( 'a90' , 'f4' , 'f4' )) for i , adc1 in enumerate ( adc1vals ): for j , adc2 in enumerate ( adc2vals ): log . info ( f 'Moving ADC1 to { adc1 : .1f } , ADC2 to { adc2 : .1f } ' ) ADC1VAL . write ( f \" { adc1 : .1f } \" ) ADC2VAL . write ( f \" { adc2 : .1f } \" ) time . sleep ( adcsleeptime ) log . info ( 'Taking EXT FVC exposure' ) TakeFVCExposure . execute ({ 'camera' : 'EXT' }) time . sleep ( fvcsleeptime ) row = { 'file' : str ( LASTFILE ), 'ADC1VAL' : str ( ADC1VAL ), 'ADC2VAL' : str ( ADC2VAL )} log . info ( f ' { row [ \"file\" ] } ' ) images . add_row ( row ) if images_file . exists (): images_file . unlink () images . write ( images_file , format = 'ascii.csv' ) log . info ( 'Done' ) @classmethod def post_condition ( cls , OB , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'ADC1MIN' , type = float , help = \"Starting ADC1 angle\" ) parser . add_argument ( 'ADC1MAX' , type = float , help = \"Ending ADC1 angle\" ) parser . add_argument ( 'ADC2MIN' , type = float , help = \"Starting ADC2 angle\" ) parser . add_argument ( 'ADC2MAX' , type = float , help = \"Ending ADC2 angle\" ) parser . add_argument ( 'ADCSTEP' , type = float , help = \"Anglular step size\" ) return super () . add_cmdline_args ( parser , cfg )","title":"TakeADCGridData"},{"location":"scripts/TakeADCGridData/#takeadcgriddata","text":"Bases: KPFTranslatorFunction Source code in kpf/engineering/TakeADCGridData.py 18 19 20 21 22 23 24 25 26 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 class TakeADCGridData ( KPFTranslatorFunction ): ''' ''' @classmethod def pre_condition ( cls , OB , logger , cfg ): pass @classmethod @register_script ( Path ( __file__ ) . name , os . getpid ()) @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , args , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in args : log . debug ( f \" { key } : { args [ key ] } \" ) log . info ( '-------------------------' ) adc1min = args . get ( 'ADC1MIN' , 60 ) adc1max = args . get ( 'ADC1MAX' , 70 ) adc2min = args . get ( 'ADC2MIN' , 60 ) adc2max = args . get ( 'ADC2MAX' , 70 ) adcstep = args . get ( 'ADCSTEP' , 1 ) adc1vals = np . arange ( adc1min , adc1max + adcstep , adcstep ) adc2vals = np . arange ( adc2min , adc2max + adcstep , adcstep ) adcsleeptime = 1 fvcsleeptime = 0.25 ADC1VAL = ktl . cache ( 'kpffiu' , 'ADC1VAL' ) ADC1VAL . monitor () ADC2VAL = ktl . cache ( 'kpffiu' , 'ADC2VAL' ) ADC2VAL . monitor () LASTFILE = ktl . cache ( 'kpffvc' , 'EXTLASTFILE' ) LASTFILE . monitor () this_file_name = Path ( __file__ ) . name . replace ( '.py' , '' ) utnow = datetime . utcnow () now_str = utnow . strftime ( '%Y%m %d at%H%M%S' ) date_str = ( utnow - timedelta ( days = 1 )) . strftime ( '%Y%b %d ' ) . lower () log_path = Path ( f '/s/sdata1701/KPFTranslator_logs/ { date_str } ' ) images_file = log_path / Path ( f ' { this_file_name } _ { now_str } .txt' ) images = Table ( names = ( 'file' , 'ADC1VAL' , 'ADC2VAL' ), dtype = ( 'a90' , 'f4' , 'f4' )) for i , adc1 in enumerate ( adc1vals ): for j , adc2 in enumerate ( adc2vals ): log . info ( f 'Moving ADC1 to { adc1 : .1f } , ADC2 to { adc2 : .1f } ' ) ADC1VAL . write ( f \" { adc1 : .1f } \" ) ADC2VAL . write ( f \" { adc2 : .1f } \" ) time . sleep ( adcsleeptime ) log . info ( 'Taking EXT FVC exposure' ) TakeFVCExposure . execute ({ 'camera' : 'EXT' }) time . sleep ( fvcsleeptime ) row = { 'file' : str ( LASTFILE ), 'ADC1VAL' : str ( ADC1VAL ), 'ADC2VAL' : str ( ADC2VAL )} log . info ( f ' { row [ \"file\" ] } ' ) images . add_row ( row ) if images_file . exists (): images_file . unlink () images . write ( images_file , format = 'ascii.csv' ) log . info ( 'Done' ) @classmethod def post_condition ( cls , OB , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'ADC1MIN' , type = float , help = \"Starting ADC1 angle\" ) parser . add_argument ( 'ADC1MAX' , type = float , help = \"Ending ADC1 angle\" ) parser . add_argument ( 'ADC2MIN' , type = float , help = \"Starting ADC2 angle\" ) parser . add_argument ( 'ADC2MAX' , type = float , help = \"Ending ADC2 angle\" ) parser . add_argument ( 'ADCSTEP' , type = float , help = \"Anglular step size\" ) return super () . add_cmdline_args ( parser , cfg )","title":"TakeADCGridData"},{"location":"scripts/TakeADCOffsetGridData/","text":"TakeADCOffsetGridData Bases: KPFTranslatorFunction Source code in kpf/engineering/TakeADCOffsetGridData.py 18 19 20 21 22 23 24 25 26 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 class TakeADCOffsetGridData ( KPFTranslatorFunction ): ''' ''' @classmethod def pre_condition ( cls , OB , logger , cfg ): pass @classmethod @register_script ( Path ( __file__ ) . name , os . getpid ()) @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , args , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in args : log . debug ( f \" { key } : { args [ key ] } \" ) log . info ( '-------------------------' ) adc1delta = args . get ( 'ADC1DELTA' , 5 ) adc2delta = args . get ( 'ADC2DELTA' , 5 ) adcstep = args . get ( 'ADCSTEP' , 1 ) adc1deltas = np . arange ( - adc1delta , adc1delta , adcstep ) adc2deltas = np . arange ( - adc2delta , adc2delta , adcstep ) fvcsleeptime = 0.25 ADCPRISMS = ktl . cache ( 'kpffiu' , 'ADCPRISMS' ) ADCPRISMS . monitor () ADC1VAL = ktl . cache ( 'kpffiu' , 'ADC1VAL' ) ADC1VAL . monitor () ADC2VAL = ktl . cache ( 'kpffiu' , 'ADC2VAL' ) ADC2VAL . monitor () LASTFILE = ktl . cache ( 'kpffvc' , 'EXTLASTFILE' ) LASTFILE . monitor () this_file_name = Path ( __file__ ) . name . replace ( '.py' , '' ) utnow = datetime . utcnow () now_str = utnow . strftime ( '%Y%m %d at%H%M%S' ) date_str = ( utnow - timedelta ( days = 1 )) . strftime ( '%Y%b %d ' ) . lower () log_path = Path ( f '/s/sdata1701/KPFTranslator_logs/ { date_str } ' ) images_file = log_path / Path ( f ' { this_file_name } _ { now_str } .txt' ) images = Table ( names = ( 'file' , 'DELTA1' , 'DELTA2' , 'ADC1VAL' , 'ADC2VAL' ), dtype = ( 'a90' , 'f4' , 'f4' , 'f4' , 'f4' )) for i , delta1 in enumerate ( adc1deltas ): for j , delta2 in enumerate ( adc2deltas ): log . info ( f 'Moving ADCs to offset positions: { delta1 : .1f } , { delta2 : .1f } ' ) SetADCOffsets . execute ({ 'ADC1OFF' : delta1 , 'ADC2OFF' : delta2 }) log . info ( 'Taking EXT FVC exposure' ) TakeFVCExposure . execute ({ 'camera' : 'EXT' }) time . sleep ( fvcsleeptime ) row = { 'file' : str ( LASTFILE ), 'DELTA1' : delta1 , 'DELTA2' : delta2 , 'ADC1VAL' : str ( ADC1VAL ), 'ADC2VAL' : str ( ADC2VAL )} log . info ( f ' { row [ \"file\" ] } ' ) images . add_row ( row ) if images_file . exists (): images_file . unlink () images . write ( images_file , format = 'ascii.csv' ) log . info ( 'Done' ) @classmethod def post_condition ( cls , OB , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'ADC1DELTA' , type = float , help = \"Maximum ADC1 offset from nominal\" ) parser . add_argument ( 'ADC2DELTA' , type = float , help = \"Maximum ADC2 offset from nominal\" ) parser . add_argument ( 'ADCSTEP' , type = float , help = \"Anglular step size\" ) return super () . add_cmdline_args ( parser , cfg )","title":"TakeADCOffsetGridData"},{"location":"scripts/TakeADCOffsetGridData/#takeadcoffsetgriddata","text":"Bases: KPFTranslatorFunction Source code in kpf/engineering/TakeADCOffsetGridData.py 18 19 20 21 22 23 24 25 26 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 class TakeADCOffsetGridData ( KPFTranslatorFunction ): ''' ''' @classmethod def pre_condition ( cls , OB , logger , cfg ): pass @classmethod @register_script ( Path ( __file__ ) . name , os . getpid ()) @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , args , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in args : log . debug ( f \" { key } : { args [ key ] } \" ) log . info ( '-------------------------' ) adc1delta = args . get ( 'ADC1DELTA' , 5 ) adc2delta = args . get ( 'ADC2DELTA' , 5 ) adcstep = args . get ( 'ADCSTEP' , 1 ) adc1deltas = np . arange ( - adc1delta , adc1delta , adcstep ) adc2deltas = np . arange ( - adc2delta , adc2delta , adcstep ) fvcsleeptime = 0.25 ADCPRISMS = ktl . cache ( 'kpffiu' , 'ADCPRISMS' ) ADCPRISMS . monitor () ADC1VAL = ktl . cache ( 'kpffiu' , 'ADC1VAL' ) ADC1VAL . monitor () ADC2VAL = ktl . cache ( 'kpffiu' , 'ADC2VAL' ) ADC2VAL . monitor () LASTFILE = ktl . cache ( 'kpffvc' , 'EXTLASTFILE' ) LASTFILE . monitor () this_file_name = Path ( __file__ ) . name . replace ( '.py' , '' ) utnow = datetime . utcnow () now_str = utnow . strftime ( '%Y%m %d at%H%M%S' ) date_str = ( utnow - timedelta ( days = 1 )) . strftime ( '%Y%b %d ' ) . lower () log_path = Path ( f '/s/sdata1701/KPFTranslator_logs/ { date_str } ' ) images_file = log_path / Path ( f ' { this_file_name } _ { now_str } .txt' ) images = Table ( names = ( 'file' , 'DELTA1' , 'DELTA2' , 'ADC1VAL' , 'ADC2VAL' ), dtype = ( 'a90' , 'f4' , 'f4' , 'f4' , 'f4' )) for i , delta1 in enumerate ( adc1deltas ): for j , delta2 in enumerate ( adc2deltas ): log . info ( f 'Moving ADCs to offset positions: { delta1 : .1f } , { delta2 : .1f } ' ) SetADCOffsets . execute ({ 'ADC1OFF' : delta1 , 'ADC2OFF' : delta2 }) log . info ( 'Taking EXT FVC exposure' ) TakeFVCExposure . execute ({ 'camera' : 'EXT' }) time . sleep ( fvcsleeptime ) row = { 'file' : str ( LASTFILE ), 'DELTA1' : delta1 , 'DELTA2' : delta2 , 'ADC1VAL' : str ( ADC1VAL ), 'ADC2VAL' : str ( ADC2VAL )} log . info ( f ' { row [ \"file\" ] } ' ) images . add_row ( row ) if images_file . exists (): images_file . unlink () images . write ( images_file , format = 'ascii.csv' ) log . info ( 'Done' ) @classmethod def post_condition ( cls , OB , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'ADC1DELTA' , type = float , help = \"Maximum ADC1 offset from nominal\" ) parser . add_argument ( 'ADC2DELTA' , type = float , help = \"Maximum ADC2 offset from nominal\" ) parser . add_argument ( 'ADCSTEP' , type = float , help = \"Anglular step size\" ) return super () . add_cmdline_args ( parser , cfg )","title":"TakeADCOffsetGridData"},{"location":"scripts/TakeExpMeterBiases/","text":"TakeExpMeterBiases Bases: KPFTranslatorFunction Take a set of bias frames for the exposure meter. Obeys kpfconfig.ALLOWSCHEDULEDCALS (will not run if that is set to No) Parameters: nExp ( int ) \u2013 The number of frames to take. combine ( bool ) \u2013 Combine the files in to a master bias? output ( str ) \u2013 The output combined bias file. update ( bool ) \u2013 Update the bias file in use with the newly generated file? (only used if combine is True). KTL Keywords Used: kpfconfig.EXPMETER_ENABLED kpfconfig.ALLOWSCHEDULEDCALS kpf_expmeter.COOLING kpf_expmeter.COOLTARG kpf_expmeter.COOLTEMP kpf_expmeter.BINX kpf_expmeter.BINY kpf_expmeter.TOP kpf_expmeter.LEFT kpf_expmeter.WIDTH kpf_expmeter.HEIGHT kpf_expmeter.EXPOSURE kpf_expmeter.OBJECT kpf_expmeter.OBSERVER kpf_expmeter.EXPMODE kpf_expmeter.EXPSTATE kpf_expmeter.EXPOSE kpf_expmeter.SEQNUM kpf_expmeter.FITSFILE kpfexpose.TRIG_TARG Scripts Called: kpf.calbench.SetCalSource kpf.calbench.WaitForCalSource kpf.spectrograph.WaitForReady kpf.spectrograph.SetSourceSelectShutters kpf.expmeter.BuildMasterBias kpf.spectrograph.ResetDetectors.ResetExpMeterDetector Source code in kpf/expmeter/TakeExpMeterBiases.py 20 21 22 23 24 25 26 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 class TakeExpMeterBiases ( KPFTranslatorFunction ): '''Take a set of bias frames for the exposure meter. Obeys kpfconfig.ALLOWSCHEDULEDCALS (will not run if that is set to No) Args: nExp (int): The number of frames to take. combine (bool): Combine the files in to a master bias? output (str): The output combined bias file. update (bool): Update the bias file in use with the newly generated file? (only used if combine is True). KTL Keywords Used: - `kpfconfig.EXPMETER_ENABLED` - `kpfconfig.ALLOWSCHEDULEDCALS` - `kpf_expmeter.COOLING` - `kpf_expmeter.COOLTARG` - `kpf_expmeter.COOLTEMP` - `kpf_expmeter.BINX` - `kpf_expmeter.BINY` - `kpf_expmeter.TOP` - `kpf_expmeter.LEFT` - `kpf_expmeter.WIDTH` - `kpf_expmeter.HEIGHT` - `kpf_expmeter.EXPOSURE` - `kpf_expmeter.OBJECT` - `kpf_expmeter.OBSERVER` - `kpf_expmeter.EXPMODE` - `kpf_expmeter.EXPSTATE` - `kpf_expmeter.EXPOSE` - `kpf_expmeter.SEQNUM` - `kpf_expmeter.FITSFILE` - `kpfexpose.TRIG_TARG` Scripts Called: - `kpf.calbench.SetCalSource` - `kpf.calbench.WaitForCalSource` - `kpf.spectrograph.WaitForReady` - `kpf.spectrograph.SetSourceSelectShutters` - `kpf.expmeter.BuildMasterBias` - `kpf.spectrograph.ResetDetectors.ResetExpMeterDetector` ''' @classmethod @obey_scriptrun def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'nExp' , allowed_types = [ int ]) kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) # Check exposure meter enabled kpfconfig = ktl . cache ( 'kpfconfig' ) EM_enabled = kpfconfig [ 'EXPMETER_ENABLED' ] . read () == 'Yes' if EM_enabled == False : raise FailedPreCondition ( 'Exposure meter is not enabled' ) # Check on exposure meter detector status if kpf_expmeter [ 'COOLING' ] . read ( binary = True ) != True : raise FailedPreCondition ( 'Exposure meter cooling is not On' ) cooltarg = kpf_expmeter [ 'COOLTARG' ] . read ( binary = True ) currtemp = kpf_expmeter [ 'CURRTEMP' ] . read ( binary = True ) deltaT = abs ( currtemp - cooltarg ) deltaT_threshold = cfg . getfloat ( 'tolerances' , 'expmeter_detector_temperature_tolerance' , fallback = 0.5 ) if deltaT > deltaT_threshold : raise FailedPreCondition ( 'Exposure meter not near target temperature' ) @classmethod @register_script ( Path ( __file__ ) . name , os . getpid ()) @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , args , logger , cfg ): # Check if we're ok to take data allowscheduledcals = ktl . cache ( 'kpfconfig' , 'ALLOWSCHEDULEDCALS' ) if allowscheduledcals . read ( binary = True ) == False : log . warning ( f 'kpfconfig.ALLOWSCHEDULEDCALS=No. Not taking biases.' ) return [] # Proceed with taking biases nExp = int ( args . get ( 'nExp' )) log . info ( f \"Taking { nExp } exposure meter bias frames\" ) kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) # Set exposure meter to full frame to take biases log . info ( f \"Setting exposure meter to full frame for biases\" ) kpf_expmeter [ 'BINX' ] . write ( 1 ) kpf_expmeter [ 'BINY' ] . write ( 1 ) kpf_expmeter [ 'TOP' ] . write ( 0 ) kpf_expmeter [ 'LEFT' ] . write ( 0 ) kpf_expmeter [ 'WIDTH' ] . write ( 1072 ) kpf_expmeter [ 'HEIGHT' ] . write ( 1024 ) kpf_expmeter [ 'EXPOSURE' ] . write ( 0.12 ) kpf_expmeter [ 'OBJECT' ] . write ( 'bias' ) kpf_expmeter [ 'OBSERVER' ] . write ( 'TakeExpMeterBiases' ) kpf_expmeter [ 'EXPMODE' ] . write ( 'Continuous' ) log . debug ( 'Set Octagon to Home and close all source select shutters' ) SetCalSource . execute ({ 'CalSource' : 'Home' }) WaitForReady . execute ({}) SetSourceSelectShutters . execute ({}) WaitForCalSource . execute ({ 'CalSource' : 'Home' }) # Set TRIG_TARG to None, so that kpfassemble doesn't try # to pick up this data set trig_targ = ktl . cache ( 'kpfexpose' , 'TRIG_TARG' ) trig_targ . write ( 'None' ) ready = kpf_expmeter [ 'EXPSTATE' ] . waitFor ( \"== 'Ready'\" , timeout = 60 ) if ready is not True : raise KPFException ( f \"Exposure Meter did not reach ready state\" ) # Start continuous exposures log . info ( f \"Starting continuous exposures\" ) kpf_expmeter [ 'EXPOSE' ] . write ( 'Start' ) started = kpf_expmeter [ 'EXPSTATE' ] . waitFor ( \"!= 'Ready'\" , timeout = 5 ) if started is not True : raise KPFException ( f \"Exposure Meter did not start exposures\" ) got_frames = kpf_expmeter [ 'SEQNUM' ] . waitFor ( f \"== { nExp } \" , timeout = 2 * nExp ) if got_frames is not True : raise KPFException ( f \"Exposure Meter did not get all exposures\" ) log . info ( f \"Stopping continuous exposures\" ) kpf_expmeter [ 'EXPOSE' ] . write ( 'End' ) # Arbitrary wait to let file writing and DRP finish time . sleep ( 2 ) # Get FITSFILE lastfile = Path ( kpf_expmeter [ 'FITSFILE' ] . read ()) if lastfile . exists () is False : raise KPFException ( f \"Could not find file: { lastfile } \" ) filename_parts = lastfile . name . split ( '.' ) filename_parts [ 1 ] = '*' biases = [ f for f in lastfile . parent . glob ( '.' . join ( filename_parts ))] # Set exposure meter back to operations settings log . info ( f \"Setting exposure meter to operational windowing\" ) kpf_expmeter [ 'BINX' ] . write ( 1 ) kpf_expmeter [ 'BINY' ] . write ( 1 ) kpf_expmeter [ 'TOP' ] . write ( 0 ) kpf_expmeter [ 'LEFT' ] . write ( 1 ) kpf_expmeter [ 'WIDTH' ] . write ( 651 ) kpf_expmeter [ 'HEIGHT' ] . write ( 300 ) kpf_expmeter [ 'OBJECT' ] . write ( '' ) if args . get ( 'combine' , False ) is True : BuildMasterBias . execute ({ 'files' : biases , 'output' : args . get ( 'output' ), 'update' : args . get ( 'update' )}) return biases @classmethod def post_condition ( cls , args , logger , cfg ): expstate = ktl . cache ( 'kpf_expmeter' , 'EXPSTATE' ) expstate . monitor () timeout = 60 ready = expstate . waitFor ( \"== 'Ready'\" , timeout = timeout ) if ready is not True : log . error ( f 'ExpMeter is not Ready after { timeout } s' ) log . warning ( f 'ExpMeter is { expstate . ascii } . Resetting.' ) ResetExpMeterDetector . execute ({}) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'nExp' , type = int , help = \"The number of frames to take\" ) parser . add_argument ( \"-c\" , \"--combine\" , dest = \"combine\" , default = False , action = \"store_true\" , help = \"Combine the files in to a master bias?\" ) parser . add_argument ( \"--update\" , dest = \"update\" , default = False , action = \"store_true\" , help = \"Update the bias file in use with the newly generated file? (only used if --combine is used)\" ) parser . add_argument ( \"--output\" , dest = \"output\" , type = str , default = '' , help = \"The output combined bias file.\" ) return super () . add_cmdline_args ( parser , cfg )","title":"TakeExpMeterBiases"},{"location":"scripts/TakeExpMeterBiases/#takeexpmeterbiases","text":"Bases: KPFTranslatorFunction Take a set of bias frames for the exposure meter. Obeys kpfconfig.ALLOWSCHEDULEDCALS (will not run if that is set to No) Parameters: nExp ( int ) \u2013 The number of frames to take. combine ( bool ) \u2013 Combine the files in to a master bias? output ( str ) \u2013 The output combined bias file. update ( bool ) \u2013 Update the bias file in use with the newly generated file? (only used if combine is True). KTL Keywords Used: kpfconfig.EXPMETER_ENABLED kpfconfig.ALLOWSCHEDULEDCALS kpf_expmeter.COOLING kpf_expmeter.COOLTARG kpf_expmeter.COOLTEMP kpf_expmeter.BINX kpf_expmeter.BINY kpf_expmeter.TOP kpf_expmeter.LEFT kpf_expmeter.WIDTH kpf_expmeter.HEIGHT kpf_expmeter.EXPOSURE kpf_expmeter.OBJECT kpf_expmeter.OBSERVER kpf_expmeter.EXPMODE kpf_expmeter.EXPSTATE kpf_expmeter.EXPOSE kpf_expmeter.SEQNUM kpf_expmeter.FITSFILE kpfexpose.TRIG_TARG Scripts Called: kpf.calbench.SetCalSource kpf.calbench.WaitForCalSource kpf.spectrograph.WaitForReady kpf.spectrograph.SetSourceSelectShutters kpf.expmeter.BuildMasterBias kpf.spectrograph.ResetDetectors.ResetExpMeterDetector Source code in kpf/expmeter/TakeExpMeterBiases.py 20 21 22 23 24 25 26 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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 class TakeExpMeterBiases ( KPFTranslatorFunction ): '''Take a set of bias frames for the exposure meter. Obeys kpfconfig.ALLOWSCHEDULEDCALS (will not run if that is set to No) Args: nExp (int): The number of frames to take. combine (bool): Combine the files in to a master bias? output (str): The output combined bias file. update (bool): Update the bias file in use with the newly generated file? (only used if combine is True). KTL Keywords Used: - `kpfconfig.EXPMETER_ENABLED` - `kpfconfig.ALLOWSCHEDULEDCALS` - `kpf_expmeter.COOLING` - `kpf_expmeter.COOLTARG` - `kpf_expmeter.COOLTEMP` - `kpf_expmeter.BINX` - `kpf_expmeter.BINY` - `kpf_expmeter.TOP` - `kpf_expmeter.LEFT` - `kpf_expmeter.WIDTH` - `kpf_expmeter.HEIGHT` - `kpf_expmeter.EXPOSURE` - `kpf_expmeter.OBJECT` - `kpf_expmeter.OBSERVER` - `kpf_expmeter.EXPMODE` - `kpf_expmeter.EXPSTATE` - `kpf_expmeter.EXPOSE` - `kpf_expmeter.SEQNUM` - `kpf_expmeter.FITSFILE` - `kpfexpose.TRIG_TARG` Scripts Called: - `kpf.calbench.SetCalSource` - `kpf.calbench.WaitForCalSource` - `kpf.spectrograph.WaitForReady` - `kpf.spectrograph.SetSourceSelectShutters` - `kpf.expmeter.BuildMasterBias` - `kpf.spectrograph.ResetDetectors.ResetExpMeterDetector` ''' @classmethod @obey_scriptrun def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'nExp' , allowed_types = [ int ]) kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) # Check exposure meter enabled kpfconfig = ktl . cache ( 'kpfconfig' ) EM_enabled = kpfconfig [ 'EXPMETER_ENABLED' ] . read () == 'Yes' if EM_enabled == False : raise FailedPreCondition ( 'Exposure meter is not enabled' ) # Check on exposure meter detector status if kpf_expmeter [ 'COOLING' ] . read ( binary = True ) != True : raise FailedPreCondition ( 'Exposure meter cooling is not On' ) cooltarg = kpf_expmeter [ 'COOLTARG' ] . read ( binary = True ) currtemp = kpf_expmeter [ 'CURRTEMP' ] . read ( binary = True ) deltaT = abs ( currtemp - cooltarg ) deltaT_threshold = cfg . getfloat ( 'tolerances' , 'expmeter_detector_temperature_tolerance' , fallback = 0.5 ) if deltaT > deltaT_threshold : raise FailedPreCondition ( 'Exposure meter not near target temperature' ) @classmethod @register_script ( Path ( __file__ ) . name , os . getpid ()) @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , args , logger , cfg ): # Check if we're ok to take data allowscheduledcals = ktl . cache ( 'kpfconfig' , 'ALLOWSCHEDULEDCALS' ) if allowscheduledcals . read ( binary = True ) == False : log . warning ( f 'kpfconfig.ALLOWSCHEDULEDCALS=No. Not taking biases.' ) return [] # Proceed with taking biases nExp = int ( args . get ( 'nExp' )) log . info ( f \"Taking { nExp } exposure meter bias frames\" ) kpf_expmeter = ktl . cache ( 'kpf_expmeter' ) # Set exposure meter to full frame to take biases log . info ( f \"Setting exposure meter to full frame for biases\" ) kpf_expmeter [ 'BINX' ] . write ( 1 ) kpf_expmeter [ 'BINY' ] . write ( 1 ) kpf_expmeter [ 'TOP' ] . write ( 0 ) kpf_expmeter [ 'LEFT' ] . write ( 0 ) kpf_expmeter [ 'WIDTH' ] . write ( 1072 ) kpf_expmeter [ 'HEIGHT' ] . write ( 1024 ) kpf_expmeter [ 'EXPOSURE' ] . write ( 0.12 ) kpf_expmeter [ 'OBJECT' ] . write ( 'bias' ) kpf_expmeter [ 'OBSERVER' ] . write ( 'TakeExpMeterBiases' ) kpf_expmeter [ 'EXPMODE' ] . write ( 'Continuous' ) log . debug ( 'Set Octagon to Home and close all source select shutters' ) SetCalSource . execute ({ 'CalSource' : 'Home' }) WaitForReady . execute ({}) SetSourceSelectShutters . execute ({}) WaitForCalSource . execute ({ 'CalSource' : 'Home' }) # Set TRIG_TARG to None, so that kpfassemble doesn't try # to pick up this data set trig_targ = ktl . cache ( 'kpfexpose' , 'TRIG_TARG' ) trig_targ . write ( 'None' ) ready = kpf_expmeter [ 'EXPSTATE' ] . waitFor ( \"== 'Ready'\" , timeout = 60 ) if ready is not True : raise KPFException ( f \"Exposure Meter did not reach ready state\" ) # Start continuous exposures log . info ( f \"Starting continuous exposures\" ) kpf_expmeter [ 'EXPOSE' ] . write ( 'Start' ) started = kpf_expmeter [ 'EXPSTATE' ] . waitFor ( \"!= 'Ready'\" , timeout = 5 ) if started is not True : raise KPFException ( f \"Exposure Meter did not start exposures\" ) got_frames = kpf_expmeter [ 'SEQNUM' ] . waitFor ( f \"== { nExp } \" , timeout = 2 * nExp ) if got_frames is not True : raise KPFException ( f \"Exposure Meter did not get all exposures\" ) log . info ( f \"Stopping continuous exposures\" ) kpf_expmeter [ 'EXPOSE' ] . write ( 'End' ) # Arbitrary wait to let file writing and DRP finish time . sleep ( 2 ) # Get FITSFILE lastfile = Path ( kpf_expmeter [ 'FITSFILE' ] . read ()) if lastfile . exists () is False : raise KPFException ( f \"Could not find file: { lastfile } \" ) filename_parts = lastfile . name . split ( '.' ) filename_parts [ 1 ] = '*' biases = [ f for f in lastfile . parent . glob ( '.' . join ( filename_parts ))] # Set exposure meter back to operations settings log . info ( f \"Setting exposure meter to operational windowing\" ) kpf_expmeter [ 'BINX' ] . write ( 1 ) kpf_expmeter [ 'BINY' ] . write ( 1 ) kpf_expmeter [ 'TOP' ] . write ( 0 ) kpf_expmeter [ 'LEFT' ] . write ( 1 ) kpf_expmeter [ 'WIDTH' ] . write ( 651 ) kpf_expmeter [ 'HEIGHT' ] . write ( 300 ) kpf_expmeter [ 'OBJECT' ] . write ( '' ) if args . get ( 'combine' , False ) is True : BuildMasterBias . execute ({ 'files' : biases , 'output' : args . get ( 'output' ), 'update' : args . get ( 'update' )}) return biases @classmethod def post_condition ( cls , args , logger , cfg ): expstate = ktl . cache ( 'kpf_expmeter' , 'EXPSTATE' ) expstate . monitor () timeout = 60 ready = expstate . waitFor ( \"== 'Ready'\" , timeout = timeout ) if ready is not True : log . error ( f 'ExpMeter is not Ready after { timeout } s' ) log . warning ( f 'ExpMeter is { expstate . ascii } . Resetting.' ) ResetExpMeterDetector . execute ({}) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'nExp' , type = int , help = \"The number of frames to take\" ) parser . add_argument ( \"-c\" , \"--combine\" , dest = \"combine\" , default = False , action = \"store_true\" , help = \"Combine the files in to a master bias?\" ) parser . add_argument ( \"--update\" , dest = \"update\" , default = False , action = \"store_true\" , help = \"Update the bias file in use with the newly generated file? (only used if --combine is used)\" ) parser . add_argument ( \"--output\" , dest = \"output\" , type = str , default = '' , help = \"The output combined bias file.\" ) return super () . add_cmdline_args ( parser , cfg )","title":"TakeExpMeterBiases"},{"location":"scripts/TakeFVCContinuous/","text":"TakeFVCContinuous Bases: KPFTranslatorFunction Take exposures with the specified FVC continuously and display to ds9. Parameters: camera ( str ) \u2013 Which FVC camera? Allowed values: SCI, CAHK, EXT, CAL exptime ( float ) \u2013 The exposure time in seconds. KTL Keywords Used: kpffvc.SCIEXPTIME kpffvc.CAHKEXPTIME kpffvc.EXTEXPTIME kpffvc.CALEXPTIME kpfpower.KPFFVC1 kpfpower.KPFFVC2 kpfpower.KPFFVC3 Source code in kpf/fvc/TakeFVCContinuous.py 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class TakeFVCContinuous ( KPFTranslatorFunction ): '''Take exposures with the specified FVC continuously and display to ds9. Args: camera (str): Which FVC camera? Allowed values: SCI, CAHK, EXT, CAL exptime (float): The exposure time in seconds. KTL Keywords Used: - `kpffvc.SCIEXPTIME` - `kpffvc.CAHKEXPTIME` - `kpffvc.EXTEXPTIME` - `kpffvc.CALEXPTIME` - `kpfpower.KPFFVC1` - `kpfpower.KPFFVC2` - `kpfpower.KPFFVC3` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'camera' , allowed_values = [ 'SCI' , 'CAHK' , 'CAL' , 'EXT' ]) # Check if power is on camera = args . get ( 'camera' ) camnum = { 'SCI' : 1 , 'CAHK' : 2 , 'CAL' : 3 }[ camera ] powerkw = ktl . cache ( 'kpfpower' , f \"KPFFVC { camnum } \" ) if powerkw . read () != 'On' : raise FailedPreCondition ( f \" { camera } FVC power is not On\" ) @classmethod def perform ( cls , args , logger , cfg ): camera = args . get ( 'camera' ) exptime = args . get ( 'exptime' ) SetFVCExpTime . execute ( args ) while True : TakeFVCExposure . execute ({ 'camera' : camera , 'display' : True }) time . sleep ( 0.5 ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'camera' , type = str , choices = [ 'SCI' , 'CAHK' , 'CAL' , 'EXT' ], help = 'The FVC camera' ) parser . add_argument ( 'exptime' , type = float , help = 'The exposure time in seconds' ) return super () . add_cmdline_args ( parser , cfg )","title":"TakeFVCContinuous"},{"location":"scripts/TakeFVCContinuous/#takefvccontinuous","text":"Bases: KPFTranslatorFunction Take exposures with the specified FVC continuously and display to ds9. Parameters: camera ( str ) \u2013 Which FVC camera? Allowed values: SCI, CAHK, EXT, CAL exptime ( float ) \u2013 The exposure time in seconds. KTL Keywords Used: kpffvc.SCIEXPTIME kpffvc.CAHKEXPTIME kpffvc.EXTEXPTIME kpffvc.CALEXPTIME kpfpower.KPFFVC1 kpfpower.KPFFVC2 kpfpower.KPFFVC3 Source code in kpf/fvc/TakeFVCContinuous.py 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class TakeFVCContinuous ( KPFTranslatorFunction ): '''Take exposures with the specified FVC continuously and display to ds9. Args: camera (str): Which FVC camera? Allowed values: SCI, CAHK, EXT, CAL exptime (float): The exposure time in seconds. KTL Keywords Used: - `kpffvc.SCIEXPTIME` - `kpffvc.CAHKEXPTIME` - `kpffvc.EXTEXPTIME` - `kpffvc.CALEXPTIME` - `kpfpower.KPFFVC1` - `kpfpower.KPFFVC2` - `kpfpower.KPFFVC3` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'camera' , allowed_values = [ 'SCI' , 'CAHK' , 'CAL' , 'EXT' ]) # Check if power is on camera = args . get ( 'camera' ) camnum = { 'SCI' : 1 , 'CAHK' : 2 , 'CAL' : 3 }[ camera ] powerkw = ktl . cache ( 'kpfpower' , f \"KPFFVC { camnum } \" ) if powerkw . read () != 'On' : raise FailedPreCondition ( f \" { camera } FVC power is not On\" ) @classmethod def perform ( cls , args , logger , cfg ): camera = args . get ( 'camera' ) exptime = args . get ( 'exptime' ) SetFVCExpTime . execute ( args ) while True : TakeFVCExposure . execute ({ 'camera' : camera , 'display' : True }) time . sleep ( 0.5 ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'camera' , type = str , choices = [ 'SCI' , 'CAHK' , 'CAL' , 'EXT' ], help = 'The FVC camera' ) parser . add_argument ( 'exptime' , type = float , help = 'The exposure time in seconds' ) return super () . add_cmdline_args ( parser , cfg )","title":"TakeFVCContinuous"},{"location":"scripts/TakeFVCExposure/","text":"TakeFVCExposure Bases: KPFTranslatorFunction Take an exposure with the specified fiber viewing camera Parameters: camera ( str ) \u2013 Which FVC camera? Allowed values: SCI, CAHK, EXT, CAL wait ( bool ) \u2013 Wait for image to complete before returning? (default: True) display ( bool ) \u2013 Display the resulting image to the engineering ds9 instance for FVCs using XPA? KTL Keywords Used: kpffvc.SCIEXPTIME kpffvc.CAHKEXPTIME kpffvc.EXTEXPTIME kpffvc.CALEXPTIME kpffvc.SCILASTFILE kpffvc.CALLASTFILE kpffvc.EXTLASTFILE kpffvc.CAHKLASTFILE kpffvc.SCIEXPOSE kpffvc.CALEXPOSE kpffvc.EXTEXPOSE kpffvc.CAHKEXPOSE kpfpower.KPFFVC1 kpfpower.KPFFVC2 kpfpower.KPFFVC3 Source code in kpf/fvc/TakeFVCExposure.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class TakeFVCExposure ( KPFTranslatorFunction ): '''Take an exposure with the specified fiber viewing camera Args: camera (str): Which FVC camera? Allowed values: SCI, CAHK, EXT, CAL wait (bool): Wait for image to complete before returning? (default: True) display (bool): Display the resulting image to the engineering ds9 instance for FVCs using XPA? KTL Keywords Used: - `kpffvc.SCIEXPTIME` - `kpffvc.CAHKEXPTIME` - `kpffvc.EXTEXPTIME` - `kpffvc.CALEXPTIME` - `kpffvc.SCILASTFILE` - `kpffvc.CALLASTFILE` - `kpffvc.EXTLASTFILE` - `kpffvc.CAHKLASTFILE` - `kpffvc.SCIEXPOSE` - `kpffvc.CALEXPOSE` - `kpffvc.EXTEXPOSE` - `kpffvc.CAHKEXPOSE` - `kpfpower.KPFFVC1` - `kpfpower.KPFFVC2` - `kpfpower.KPFFVC3` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'camera' , allowed_values = [ 'SCI' , 'CAHK' , 'CAL' , 'EXT' ]) # Check if power is on camera = args . get ( 'camera' ) camnum = { 'SCI' : 1 , 'CAHK' : 2 , 'CAL' : 3 , 'EXT' : None }[ camera ] if camnum is not None : powerkw = ktl . cache ( 'kpfpower' , f \"KPFFVC { camnum } \" ) if powerkw . read () != 'On' : raise FailedPreCondition ( f \" { camera } FVC power is not On\" ) @classmethod def perform ( cls , args , logger , cfg ): camera = args . get ( 'camera' ) kpffvc = ktl . cache ( 'kpffvc' ) exptime = kpffvc [ f ' { camera } EXPTIME' ] . read ( binary = True ) lastfile = kpffvc [ f ' { camera } LASTFILE' ] initial_lastfile = lastfile . read () wait = args . get ( 'wait' , True ) kpffvc [ f ' { camera } EXPOSE' ] . write ( 'yes' , wait = wait ) if wait is True : timeout = cfg . getfloat ( 'times' , 'fvc_command_timeout' , fallback = 5 ) expr = f \"($kpffvc. { camera } LASTFILE != ' { initial_lastfile } ')\" ktl . waitFor ( expr , timeout = exptime + timeout ) if wait is True and args . get ( 'display' , False ) is True : display_name = cfg . get ( 'display' , 'fvc_xpa_target' , fallback = 'FVC' ) ds9cmd = [ 'xpaset' , display_name , 'fits' , f \" { lastfile . read () } \" , '<' , f \" { lastfile . read () } \" ] log . debug ( f \"Running: { ' ' . join ( ds9cmd ) } \" ) subprocess . call ( ' ' . join ( ds9cmd ), shell = True ) regfile = Path ( f '/home/kpfeng/fibers_on_ { camera . lower () } fvc.reg' ) if regfile . exists () is True : overlaycmd = [ 'xpaset' , '-p' , display_name , 'regions' , 'file' , f \" { regfile } \" ] log . debug ( f \"Running: { ' ' . join ( overlaycmd ) } \" ) subprocess . call ( ' ' . join ( overlaycmd ), shell = True ) return kpffvc [ f \" { camera } LASTFILE\" ] . read () @classmethod def post_condition ( cls , args , logger , cfg ): camera = args . get ( 'camera' , 'SCI' ) kpffvc = ktl . cache ( 'kpffvc' ) lastfile = kpffvc [ f ' { camera } LASTFILE' ] lastfile . monitor () new_file = Path ( f \" { lastfile } \" ) log . debug ( f \" { camera } FVC LASTFILE: { new_file } \" ) if new_file . exists () == False : raise FailedPostCondition ( f 'Output file not found: { new_file } ' ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'camera' , type = str , choices = [ 'SCI' , 'CAHK' , 'CAL' , 'EXT' ], help = 'The FVC camera' ) parser . add_argument ( \"--nowait\" , dest = \"wait\" , default = True , action = \"store_false\" , help = \"Send exposure command and return immediately?\" ) parser . add_argument ( \"--display\" , dest = \"display\" , default = False , action = \"store_true\" , help = \"Display image via engineering ds9?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"TakeFVCExposure"},{"location":"scripts/TakeFVCExposure/#takefvcexposure","text":"Bases: KPFTranslatorFunction Take an exposure with the specified fiber viewing camera Parameters: camera ( str ) \u2013 Which FVC camera? Allowed values: SCI, CAHK, EXT, CAL wait ( bool ) \u2013 Wait for image to complete before returning? (default: True) display ( bool ) \u2013 Display the resulting image to the engineering ds9 instance for FVCs using XPA? KTL Keywords Used: kpffvc.SCIEXPTIME kpffvc.CAHKEXPTIME kpffvc.EXTEXPTIME kpffvc.CALEXPTIME kpffvc.SCILASTFILE kpffvc.CALLASTFILE kpffvc.EXTLASTFILE kpffvc.CAHKLASTFILE kpffvc.SCIEXPOSE kpffvc.CALEXPOSE kpffvc.EXTEXPOSE kpffvc.CAHKEXPOSE kpfpower.KPFFVC1 kpfpower.KPFFVC2 kpfpower.KPFFVC3 Source code in kpf/fvc/TakeFVCExposure.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class TakeFVCExposure ( KPFTranslatorFunction ): '''Take an exposure with the specified fiber viewing camera Args: camera (str): Which FVC camera? Allowed values: SCI, CAHK, EXT, CAL wait (bool): Wait for image to complete before returning? (default: True) display (bool): Display the resulting image to the engineering ds9 instance for FVCs using XPA? KTL Keywords Used: - `kpffvc.SCIEXPTIME` - `kpffvc.CAHKEXPTIME` - `kpffvc.EXTEXPTIME` - `kpffvc.CALEXPTIME` - `kpffvc.SCILASTFILE` - `kpffvc.CALLASTFILE` - `kpffvc.EXTLASTFILE` - `kpffvc.CAHKLASTFILE` - `kpffvc.SCIEXPOSE` - `kpffvc.CALEXPOSE` - `kpffvc.EXTEXPOSE` - `kpffvc.CAHKEXPOSE` - `kpfpower.KPFFVC1` - `kpfpower.KPFFVC2` - `kpfpower.KPFFVC3` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'camera' , allowed_values = [ 'SCI' , 'CAHK' , 'CAL' , 'EXT' ]) # Check if power is on camera = args . get ( 'camera' ) camnum = { 'SCI' : 1 , 'CAHK' : 2 , 'CAL' : 3 , 'EXT' : None }[ camera ] if camnum is not None : powerkw = ktl . cache ( 'kpfpower' , f \"KPFFVC { camnum } \" ) if powerkw . read () != 'On' : raise FailedPreCondition ( f \" { camera } FVC power is not On\" ) @classmethod def perform ( cls , args , logger , cfg ): camera = args . get ( 'camera' ) kpffvc = ktl . cache ( 'kpffvc' ) exptime = kpffvc [ f ' { camera } EXPTIME' ] . read ( binary = True ) lastfile = kpffvc [ f ' { camera } LASTFILE' ] initial_lastfile = lastfile . read () wait = args . get ( 'wait' , True ) kpffvc [ f ' { camera } EXPOSE' ] . write ( 'yes' , wait = wait ) if wait is True : timeout = cfg . getfloat ( 'times' , 'fvc_command_timeout' , fallback = 5 ) expr = f \"($kpffvc. { camera } LASTFILE != ' { initial_lastfile } ')\" ktl . waitFor ( expr , timeout = exptime + timeout ) if wait is True and args . get ( 'display' , False ) is True : display_name = cfg . get ( 'display' , 'fvc_xpa_target' , fallback = 'FVC' ) ds9cmd = [ 'xpaset' , display_name , 'fits' , f \" { lastfile . read () } \" , '<' , f \" { lastfile . read () } \" ] log . debug ( f \"Running: { ' ' . join ( ds9cmd ) } \" ) subprocess . call ( ' ' . join ( ds9cmd ), shell = True ) regfile = Path ( f '/home/kpfeng/fibers_on_ { camera . lower () } fvc.reg' ) if regfile . exists () is True : overlaycmd = [ 'xpaset' , '-p' , display_name , 'regions' , 'file' , f \" { regfile } \" ] log . debug ( f \"Running: { ' ' . join ( overlaycmd ) } \" ) subprocess . call ( ' ' . join ( overlaycmd ), shell = True ) return kpffvc [ f \" { camera } LASTFILE\" ] . read () @classmethod def post_condition ( cls , args , logger , cfg ): camera = args . get ( 'camera' , 'SCI' ) kpffvc = ktl . cache ( 'kpffvc' ) lastfile = kpffvc [ f ' { camera } LASTFILE' ] lastfile . monitor () new_file = Path ( f \" { lastfile } \" ) log . debug ( f \" { camera } FVC LASTFILE: { new_file } \" ) if new_file . exists () == False : raise FailedPostCondition ( f 'Output file not found: { new_file } ' ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'camera' , type = str , choices = [ 'SCI' , 'CAHK' , 'CAL' , 'EXT' ], help = 'The FVC camera' ) parser . add_argument ( \"--nowait\" , dest = \"wait\" , default = True , action = \"store_false\" , help = \"Send exposure command and return immediately?\" ) parser . add_argument ( \"--display\" , dest = \"display\" , default = False , action = \"store_true\" , help = \"Display image via engineering ds9?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"TakeFVCExposure"},{"location":"scripts/TakeGuiderCube/","text":"TakeGuiderCube Bases: KPFTranslatorFunction Take a \"trigger file\" from the guide camera of a given duration. Parameters: duration ( float ) \u2013 The duration in seconds of the image set. ImageCube ( bool ) \u2013 Collect the full cube of images? (default True) This will slow down file write considerably. KTL Keywords Used: kpfguide.TRIGCUBE kpfguide.LASTTRIGFILE kpfguide.ALL_LOOPS Scripts Called: kpf.guider.StartTriggerFile kpf.guider.StopTriggerFile kpf.guider.WaitForTriggerFile Source code in kpf/guider/TakeGuiderCube.py 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class TakeGuiderCube ( KPFTranslatorFunction ): '''Take a \"trigger file\" from the guide camera of a given duration. Args: duration (float): The duration in seconds of the image set. ImageCube (bool): Collect the full cube of images? (default True) This will slow down file write considerably. KTL Keywords Used: - `kpfguide.TRIGCUBE` - `kpfguide.LASTTRIGFILE` - `kpfguide.ALL_LOOPS` Scripts Called: - `kpf.guider.StartTriggerFile` - `kpf.guider.StopTriggerFile` - `kpf.guider.WaitForTriggerFile` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'duration' , value_min = 0 ) @classmethod def perform ( cls , args , logger , cfg ): duration = float ( args . get ( 'duration' )) kpfguide = ktl . cache ( 'kpfguide' ) # Read initial conditions, so we can set them back at the end initial_trigcube = kpfguide [ 'TRIGCUBE' ] . read () initial_lastfile = kpfguide [ 'LASTTRIGFILE' ] . read () initial_all_loops = kpfguide [ 'ALL_LOOPS' ] . read () # Do we want to take the image cube? collect_image_cube = args . get ( 'ImageCube' , True ) set_trigcube = { True : 'Active' , False : 'Inactive' }[ collect_image_cube ] kpfguide [ 'TRIGCUBE' ] . write ( set_trigcube ) # Trigger data collection log . info ( f \"Starting guider cube data collection, duration = { duration : .1f } s\" ) StartTriggerFile . execute ({}) time . sleep ( duration ) StopTriggerFile . execute ({}) # Stop all loops if we're writing out a full image cube # if initial_all_loops == 'Active' and collect_image_cube == True: # kpfguide['ALL_LOOPS'].write('Inactive', wait=False) cube_file = WaitForTriggerFile . execute ({ 'initial_lastfile' : initial_lastfile }) # Reset TRIGCUBE kpfguide [ 'TRIGCUBE' ] . write ( initial_trigcube ) # Reset ALL_LOOPS to initial values # if initial_all_loops == 'Active' and collect_image_cube == True: # kpfguide['ALL_LOOPS'].write(initial_all_loops) return cube_file @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'duration' , type = float , help = 'The duration in seconds' ) parser . add_argument ( \"--noTRIGCUBE\" , dest = \"ImageCube\" , default = True , action = \"store_false\" , help = \"Collect the full image cube?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"TakeGuiderCube"},{"location":"scripts/TakeGuiderCube/#takeguidercube","text":"Bases: KPFTranslatorFunction Take a \"trigger file\" from the guide camera of a given duration. Parameters: duration ( float ) \u2013 The duration in seconds of the image set. ImageCube ( bool ) \u2013 Collect the full cube of images? (default True) This will slow down file write considerably. KTL Keywords Used: kpfguide.TRIGCUBE kpfguide.LASTTRIGFILE kpfguide.ALL_LOOPS Scripts Called: kpf.guider.StartTriggerFile kpf.guider.StopTriggerFile kpf.guider.WaitForTriggerFile Source code in kpf/guider/TakeGuiderCube.py 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class TakeGuiderCube ( KPFTranslatorFunction ): '''Take a \"trigger file\" from the guide camera of a given duration. Args: duration (float): The duration in seconds of the image set. ImageCube (bool): Collect the full cube of images? (default True) This will slow down file write considerably. KTL Keywords Used: - `kpfguide.TRIGCUBE` - `kpfguide.LASTTRIGFILE` - `kpfguide.ALL_LOOPS` Scripts Called: - `kpf.guider.StartTriggerFile` - `kpf.guider.StopTriggerFile` - `kpf.guider.WaitForTriggerFile` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'duration' , value_min = 0 ) @classmethod def perform ( cls , args , logger , cfg ): duration = float ( args . get ( 'duration' )) kpfguide = ktl . cache ( 'kpfguide' ) # Read initial conditions, so we can set them back at the end initial_trigcube = kpfguide [ 'TRIGCUBE' ] . read () initial_lastfile = kpfguide [ 'LASTTRIGFILE' ] . read () initial_all_loops = kpfguide [ 'ALL_LOOPS' ] . read () # Do we want to take the image cube? collect_image_cube = args . get ( 'ImageCube' , True ) set_trigcube = { True : 'Active' , False : 'Inactive' }[ collect_image_cube ] kpfguide [ 'TRIGCUBE' ] . write ( set_trigcube ) # Trigger data collection log . info ( f \"Starting guider cube data collection, duration = { duration : .1f } s\" ) StartTriggerFile . execute ({}) time . sleep ( duration ) StopTriggerFile . execute ({}) # Stop all loops if we're writing out a full image cube # if initial_all_loops == 'Active' and collect_image_cube == True: # kpfguide['ALL_LOOPS'].write('Inactive', wait=False) cube_file = WaitForTriggerFile . execute ({ 'initial_lastfile' : initial_lastfile }) # Reset TRIGCUBE kpfguide [ 'TRIGCUBE' ] . write ( initial_trigcube ) # Reset ALL_LOOPS to initial values # if initial_all_loops == 'Active' and collect_image_cube == True: # kpfguide['ALL_LOOPS'].write(initial_all_loops) return cube_file @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'duration' , type = float , help = 'The duration in seconds' ) parser . add_argument ( \"--noTRIGCUBE\" , dest = \"ImageCube\" , default = True , action = \"store_false\" , help = \"Collect the full image cube?\" ) return super () . add_cmdline_args ( parser , cfg )","title":"TakeGuiderCube"},{"location":"scripts/TakeGuiderExposure/","text":"TakeGuiderExposure Bases: KPFTranslatorFunction Depending on whether the guide camera is running in continuous mode or not, this will either grab the next exposure (if in continuous mode) or trigger a new exposure. KTL Keywords Used: kpfguide.EXPTIME kpfguide.LASTFILE Scripts Called: kpf.guider.TriggerSingleGuiderExposure kpf.guider.GrabGuiderExposure Source code in kpf/guider/TakeGuiderExposure.py 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class TakeGuiderExposure ( KPFTranslatorFunction ): '''Depending on whether the guide camera is running in continuous mode or not, this will either grab the next exposure (if in continuous mode) or trigger a new exposure. KTL Keywords Used: - `kpfguide.EXPTIME` - `kpfguide.LASTFILE` Scripts Called: - `kpf.guider.TriggerSingleGuiderExposure` - `kpf.guider.GrabGuiderExposure` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) exptime = kpfguide [ 'EXPTIME' ] . read ( binary = True ) lastfile = kpfguide [ 'LASTFILE' ] if guider_is_active (): if guider_is_saving (): GrabGuiderExposure . execute ({}) else : # not sure what right action is here log . warning ( 'Guider is active, but not saving. No image saved.' ) else : TriggerSingleGuiderExposure . execute ({}) lastfile . monitor () lastfile . wait ( timeout = exptime * 2 + 1 ) # Wait for update which signals a new file @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"TakeGuiderExposure"},{"location":"scripts/TakeGuiderExposure/#takeguiderexposure","text":"Bases: KPFTranslatorFunction Depending on whether the guide camera is running in continuous mode or not, this will either grab the next exposure (if in continuous mode) or trigger a new exposure. KTL Keywords Used: kpfguide.EXPTIME kpfguide.LASTFILE Scripts Called: kpf.guider.TriggerSingleGuiderExposure kpf.guider.GrabGuiderExposure Source code in kpf/guider/TakeGuiderExposure.py 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class TakeGuiderExposure ( KPFTranslatorFunction ): '''Depending on whether the guide camera is running in continuous mode or not, this will either grab the next exposure (if in continuous mode) or trigger a new exposure. KTL Keywords Used: - `kpfguide.EXPTIME` - `kpfguide.LASTFILE` Scripts Called: - `kpf.guider.TriggerSingleGuiderExposure` - `kpf.guider.GrabGuiderExposure` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfguide = ktl . cache ( 'kpfguide' ) exptime = kpfguide [ 'EXPTIME' ] . read ( binary = True ) lastfile = kpfguide [ 'LASTFILE' ] if guider_is_active (): if guider_is_saving (): GrabGuiderExposure . execute ({}) else : # not sure what right action is here log . warning ( 'Guider is active, but not saving. No image saved.' ) else : TriggerSingleGuiderExposure . execute ({}) lastfile . monitor () lastfile . wait ( timeout = exptime * 2 + 1 ) # Wait for update which signals a new file @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"TakeGuiderExposure"},{"location":"scripts/TakeGuiderSensitivityData/","text":"TakeGuiderSensitivityData Bases: KPFTranslatorFunction Source code in kpf/engineering/TakeGuiderSensitivityData.py 19 20 21 22 23 24 25 26 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 class TakeGuiderSensitivityData ( KPFTranslatorFunction ): ''' ''' @classmethod @obey_scriptrun def pre_condition ( cls , OB , logger , cfg ): check_input ( OB , 'Template_Name' , allowed_values = [ 'kpf_eng_tgsd' ]) check_input ( OB , 'Template_Version' , version_check = True , value_min = '0.3' ) check_input ( OB , 'FPSvalues' ) @classmethod @register_script ( Path ( __file__ ) . name , os . getpid ()) @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in OB : log . debug ( f \" { key } : { OB [ key ] } \" ) log . info ( '-------------------------' ) images_file = log_dir / Path ( f ' { this_file_name } _images_ { now_str } .txt' ) images = Table ( names = ( 'cube file' , 'fps' ), dtype = ( 'a90' , 'f4' )) kpfguide = ktl . cache ( 'kpfguide' ) log . info ( f \"Guider gain is { kpfguide [ 'GAIN' ] . read () } \" ) log . info ( f \"Ensuring TRIGCUBE is Active\" ) kpfguide [ 'TRIGCUBE' ] . write ( 'Active' ) all_loops = kpfguide [ 'ALL_LOOPS' ] . read ( binary = True ) cube_duration = OB . get ( 'cube_duration' ) for FPS in OB . get ( 'FPSvalues' ): log . info ( f \"Setting FPS to { FPS } \" ) SetGuiderFPS . execute ({ 'GuideFPS' : FPS }) # Start cube collection log . info ( f 'Starting data collection for { cube_duration } s' ) initial_lastfile = kpfguide [ 'LASTTRIGFILE' ] . read () kpfguide [ 'TRIGGER' ] . write ( 'Active' ) log . debug ( f \"Sleeping { cube_duration } s\" ) time . sleep ( cube_duration ) # End cube collection kpfguide [ 'TRIGGER' ] . write ( 'Inactive' , wait = False ) kpfguide [ 'ALL_LOOPS' ] . write ( 'Inactive' ) # Wait for cube file to be updated ktl . waitFor ( f \"$kpfguide.LASTTRIGFILE != ' { initial_lastfile } '\" ) cube_file = kpfguide [ 'LASTTRIGFILE' ] . read () log . info ( f \" cube file: { cube_file } \" ) if all_loops == 1 : kpfguide [ 'ALL_LOOPS' ] . write ( 1 ) row = { 'cube file' : cube_file , 'fps' : FPS } images . add_row ( row ) if images_file . exists (): images_file . unlink () images . write ( images_file , format = 'ascii.csv' ) @classmethod def post_condition ( cls , OB , logger , cfg ): pass","title":"TakeGuiderSensitivityData"},{"location":"scripts/TakeGuiderSensitivityData/#takeguidersensitivitydata","text":"Bases: KPFTranslatorFunction Source code in kpf/engineering/TakeGuiderSensitivityData.py 19 20 21 22 23 24 25 26 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 class TakeGuiderSensitivityData ( KPFTranslatorFunction ): ''' ''' @classmethod @obey_scriptrun def pre_condition ( cls , OB , logger , cfg ): check_input ( OB , 'Template_Name' , allowed_values = [ 'kpf_eng_tgsd' ]) check_input ( OB , 'Template_Version' , version_check = True , value_min = '0.3' ) check_input ( OB , 'FPSvalues' ) @classmethod @register_script ( Path ( __file__ ) . name , os . getpid ()) @add_script_log ( Path ( __file__ ) . name . replace ( \".py\" , \"\" )) def perform ( cls , OB , logger , cfg ): log . info ( '-------------------------' ) log . info ( f \"Running { cls . __name__ } \" ) for key in OB : log . debug ( f \" { key } : { OB [ key ] } \" ) log . info ( '-------------------------' ) images_file = log_dir / Path ( f ' { this_file_name } _images_ { now_str } .txt' ) images = Table ( names = ( 'cube file' , 'fps' ), dtype = ( 'a90' , 'f4' )) kpfguide = ktl . cache ( 'kpfguide' ) log . info ( f \"Guider gain is { kpfguide [ 'GAIN' ] . read () } \" ) log . info ( f \"Ensuring TRIGCUBE is Active\" ) kpfguide [ 'TRIGCUBE' ] . write ( 'Active' ) all_loops = kpfguide [ 'ALL_LOOPS' ] . read ( binary = True ) cube_duration = OB . get ( 'cube_duration' ) for FPS in OB . get ( 'FPSvalues' ): log . info ( f \"Setting FPS to { FPS } \" ) SetGuiderFPS . execute ({ 'GuideFPS' : FPS }) # Start cube collection log . info ( f 'Starting data collection for { cube_duration } s' ) initial_lastfile = kpfguide [ 'LASTTRIGFILE' ] . read () kpfguide [ 'TRIGGER' ] . write ( 'Active' ) log . debug ( f \"Sleeping { cube_duration } s\" ) time . sleep ( cube_duration ) # End cube collection kpfguide [ 'TRIGGER' ] . write ( 'Inactive' , wait = False ) kpfguide [ 'ALL_LOOPS' ] . write ( 'Inactive' ) # Wait for cube file to be updated ktl . waitFor ( f \"$kpfguide.LASTTRIGFILE != ' { initial_lastfile } '\" ) cube_file = kpfguide [ 'LASTTRIGFILE' ] . read () log . info ( f \" cube file: { cube_file } \" ) if all_loops == 1 : kpfguide [ 'ALL_LOOPS' ] . write ( 1 ) row = { 'cube file' : cube_file , 'fps' : FPS } images . add_row ( row ) if images_file . exists (): images_file . unlink () images . write ( images_file , format = 'ascii.csv' ) @classmethod def post_condition ( cls , OB , logger , cfg ): pass","title":"TakeGuiderSensitivityData"},{"location":"scripts/TakeIntensityReading/","text":"TakeIntensityReading Bases: KPFTranslatorFunction Insert the intensity monitor (aka \"cal diode\") in to the beam and record a measurement of the cal lamp intensity. KTL Keywords Used: kpflamps.INTENSEMON kpfcal.SERIALCONN kpfcal.INTENMON kpfcal.NAVG kpfcal.AVG kpfcal.MEASURING Scripts Called: kpf.utils.SendEmail Source code in kpf/calbench/TakeIntensityReading.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class TakeIntensityReading ( KPFTranslatorFunction ): '''Insert the intensity monitor (aka \"cal diode\") in to the beam and record a measurement of the cal lamp intensity. KTL Keywords Used: - `kpflamps.INTENSEMON` - `kpfcal.SERIALCONN` - `kpfcal.INTENMON` - `kpfcal.NAVG` - `kpfcal.AVG` - `kpfcal.MEASURING` Scripts Called: - `kpf.utils.SendEmail` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfcal = ktl . cache ( 'kpfcal' ) intensemon = ktl . cache ( 'kpflamps' , 'INTENSEMON' ) # Turn on intensity monitor if intensemon . read () == 'Off' : log . debug ( 'Turning kpflamps.INTENSEMON on' ) intensemon . write ( 'On' ) boottime = cfg . getfloat ( 'times' , 'intenmon_boot_time' , fallback = 5 ) time . sleep ( boottime ) # Verify serial connection is active if kpfcal [ 'SERIALCONN' ] . read () == 'Off' : log . debug ( 'Initiating serial connection' ) kpfcal [ 'SERIALCONN' ] . write ( 'On' ) expr = f \"($kpfcal.SERIALCONN == 'On')\" boottime = cfg . getfloat ( 'times' , 'intenmon_boot_time' , fallback = 5 ) success = ktl . waitFor ( expr , timeout = boottime ) if success is False : msg = f 'Intensity monitor serial connection is Off' log . error ( msg ) SendEmail . execute ({ 'Subject' : 'TakeIntensityReading Failed' , 'Message' : f ' { msg } ' }) # Move sensor in to beam log . info ( 'Moving Intensity Monitor in to beam' ) kpfcal [ 'INTENMON' ] . write ( 'Boresight' ) # Set averaging navg = cfg . getfloat ( 'times' , 'intenmon_avg_time' , fallback = 60 ) log . info ( f 'Starting measurement: NAVG= { navg } ' ) kpfcal [ 'NAVG' ] . write ( navg ) kpfcal [ 'AVG' ] . write ( 'On' ) # Check whether measuring is taking place expr = f \"($kpfcal.MEASURING == 'Yes')\" success = ktl . waitFor ( expr , timeout = 5 ) if success is False : msg = f 'Intensity monitor is not measuring' log . error ( msg ) SendEmail . execute ({ 'Subject' : 'TakeIntensityReading Failed' , 'Message' : f ' { msg } ' }) # Wait for readings to be complete expr = f \"($kpfcal.AVG == 'Off')\" success = ktl . waitFor ( expr , timeout = navg + 10 ) if success is False : msg = f 'Intensity monitor measurement timed out' log . error ( msg ) SendEmail . execute ({ 'Subject' : 'TakeIntensityReading Failed' , 'Message' : f ' { msg } ' }) # Move sensor out of beam log . info ( 'Moving Intensity Monitor out of beam' ) kpfcal [ 'INTENMON' ] . write ( 'Out' ) # Turn off intensity monitor log . debug ( 'Turning kpflamps.INTENSEMON off' ) intensemon . write ( 'Off' ) log . debug ( 'Turning kpfcal.SERIALCONN off' ) kpfcal [ 'SERIALCONN' ] . write ( 'Off' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"TakeIntensityReading"},{"location":"scripts/TakeIntensityReading/#takeintensityreading","text":"Bases: KPFTranslatorFunction Insert the intensity monitor (aka \"cal diode\") in to the beam and record a measurement of the cal lamp intensity. KTL Keywords Used: kpflamps.INTENSEMON kpfcal.SERIALCONN kpfcal.INTENMON kpfcal.NAVG kpfcal.AVG kpfcal.MEASURING Scripts Called: kpf.utils.SendEmail Source code in kpf/calbench/TakeIntensityReading.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class TakeIntensityReading ( KPFTranslatorFunction ): '''Insert the intensity monitor (aka \"cal diode\") in to the beam and record a measurement of the cal lamp intensity. KTL Keywords Used: - `kpflamps.INTENSEMON` - `kpfcal.SERIALCONN` - `kpfcal.INTENMON` - `kpfcal.NAVG` - `kpfcal.AVG` - `kpfcal.MEASURING` Scripts Called: - `kpf.utils.SendEmail` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfcal = ktl . cache ( 'kpfcal' ) intensemon = ktl . cache ( 'kpflamps' , 'INTENSEMON' ) # Turn on intensity monitor if intensemon . read () == 'Off' : log . debug ( 'Turning kpflamps.INTENSEMON on' ) intensemon . write ( 'On' ) boottime = cfg . getfloat ( 'times' , 'intenmon_boot_time' , fallback = 5 ) time . sleep ( boottime ) # Verify serial connection is active if kpfcal [ 'SERIALCONN' ] . read () == 'Off' : log . debug ( 'Initiating serial connection' ) kpfcal [ 'SERIALCONN' ] . write ( 'On' ) expr = f \"($kpfcal.SERIALCONN == 'On')\" boottime = cfg . getfloat ( 'times' , 'intenmon_boot_time' , fallback = 5 ) success = ktl . waitFor ( expr , timeout = boottime ) if success is False : msg = f 'Intensity monitor serial connection is Off' log . error ( msg ) SendEmail . execute ({ 'Subject' : 'TakeIntensityReading Failed' , 'Message' : f ' { msg } ' }) # Move sensor in to beam log . info ( 'Moving Intensity Monitor in to beam' ) kpfcal [ 'INTENMON' ] . write ( 'Boresight' ) # Set averaging navg = cfg . getfloat ( 'times' , 'intenmon_avg_time' , fallback = 60 ) log . info ( f 'Starting measurement: NAVG= { navg } ' ) kpfcal [ 'NAVG' ] . write ( navg ) kpfcal [ 'AVG' ] . write ( 'On' ) # Check whether measuring is taking place expr = f \"($kpfcal.MEASURING == 'Yes')\" success = ktl . waitFor ( expr , timeout = 5 ) if success is False : msg = f 'Intensity monitor is not measuring' log . error ( msg ) SendEmail . execute ({ 'Subject' : 'TakeIntensityReading Failed' , 'Message' : f ' { msg } ' }) # Wait for readings to be complete expr = f \"($kpfcal.AVG == 'Off')\" success = ktl . waitFor ( expr , timeout = navg + 10 ) if success is False : msg = f 'Intensity monitor measurement timed out' log . error ( msg ) SendEmail . execute ({ 'Subject' : 'TakeIntensityReading Failed' , 'Message' : f ' { msg } ' }) # Move sensor out of beam log . info ( 'Moving Intensity Monitor out of beam' ) kpfcal [ 'INTENMON' ] . write ( 'Out' ) # Turn off intensity monitor log . debug ( 'Turning kpflamps.INTENSEMON off' ) intensemon . write ( 'Off' ) log . debug ( 'Turning kpfcal.SERIALCONN off' ) kpfcal [ 'SERIALCONN' ] . write ( 'Off' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"TakeIntensityReading"},{"location":"scripts/TestTipTiltMirrorRange/","text":"TestTipTiltMirrorRange Bases: KPFTranslatorFunction Verify if the tip tilt system is reaching the nominal range. Output is only via log messages. KTL Keywords Used: kpffiu.TTXVAX kpffiu.TTYVAX kpfguide.TIPTILT_HOME kpfguide.TIPTILT_XRANGE kpfguide.TIPTILT_YRANGE Scripts Called: kpf.fiu.InitializeTipTilt kpf.fiu.ShutdownTipTilt Source code in kpf/fiu/TestTipTiltMirrorRange.py 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class TestTipTiltMirrorRange ( KPFTranslatorFunction ): '''Verify if the tip tilt system is reaching the nominal range. Output is only via log messages. KTL Keywords Used: - `kpffiu.TTXVAX` - `kpffiu.TTYVAX` - `kpfguide.TIPTILT_HOME` - `kpfguide.TIPTILT_XRANGE` - `kpfguide.TIPTILT_YRANGE` Scripts Called: - `kpf.fiu.InitializeTipTilt` - `kpf.fiu.ShutdownTipTilt` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # Measure tip tilt ranges log . info ( 'Beginning TestTipTiltMirrorRange' ) InitializeTipTilt . execute ({}) movetime = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) tol = cfg . getfloat ( 'tolerances' , 'tip_tilt_move_tolerance' , fallback = 0.1 ) kpffiu = ktl . cache ( 'kpffiu' ) kpfguide = ktl . cache ( 'kpfguide' ) axis = [ 'X' , 'Y' ] for i , ax in enumerate ( axis ): nominal_range = kpfguide [ f 'TIPTILT_ { ax } RANGE' ] . read ( binary = True ) home = kpfguide [ 'TIPTILT_HOME' ] . read ( binary = True )[ i ] commanded_position = home - nominal_range log . info ( f \"Sending TT { ax } VAX to { commanded_position } \" ) kpffiu [ f 'TT { ax } VAX' ] . write ( commanded_position ) time . sleep ( movetime * 100 ) current_position = kpffiu [ f 'TT { ax } VAX' ] . read ( binary = True ) if abs ( current_position - commanded_position ) < tol : log . info ( f \" { ax } reached nominal range: { commanded_position } \" ) else : log . error ( f \" { ax } failed to reach { commanded_position } : { current_position } \" ) commanded_position = home + nominal_range log . info ( f \"Sending TT { ax } VAX to { commanded_position } \" ) kpffiu [ f 'TT { ax } VAX' ] . write ( commanded_position ) time . sleep ( movetime * 100 ) current_position = kpffiu [ f 'TT { ax } VAX' ] . read ( binary = True ) if abs ( current_position - commanded_position ) < tol : log . info ( f \" { ax } reached nominal range: { commanded_position } \" ) else : log . error ( f \" { ax } failed to reach { commanded_position } : { current_position } \" ) time . sleep ( movetime * 100 ) InitializeTipTilt . execute ({}) time . sleep ( movetime * 100 ) ShutdownTipTilt . execute ({}) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"TestTipTiltMirrorRange"},{"location":"scripts/TestTipTiltMirrorRange/#testtiptiltmirrorrange","text":"Bases: KPFTranslatorFunction Verify if the tip tilt system is reaching the nominal range. Output is only via log messages. KTL Keywords Used: kpffiu.TTXVAX kpffiu.TTYVAX kpfguide.TIPTILT_HOME kpfguide.TIPTILT_XRANGE kpfguide.TIPTILT_YRANGE Scripts Called: kpf.fiu.InitializeTipTilt kpf.fiu.ShutdownTipTilt Source code in kpf/fiu/TestTipTiltMirrorRange.py 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class TestTipTiltMirrorRange ( KPFTranslatorFunction ): '''Verify if the tip tilt system is reaching the nominal range. Output is only via log messages. KTL Keywords Used: - `kpffiu.TTXVAX` - `kpffiu.TTYVAX` - `kpfguide.TIPTILT_HOME` - `kpfguide.TIPTILT_XRANGE` - `kpfguide.TIPTILT_YRANGE` Scripts Called: - `kpf.fiu.InitializeTipTilt` - `kpf.fiu.ShutdownTipTilt` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): # Measure tip tilt ranges log . info ( 'Beginning TestTipTiltMirrorRange' ) InitializeTipTilt . execute ({}) movetime = cfg . getfloat ( 'times' , 'tip_tilt_move_time' , fallback = 0.1 ) tol = cfg . getfloat ( 'tolerances' , 'tip_tilt_move_tolerance' , fallback = 0.1 ) kpffiu = ktl . cache ( 'kpffiu' ) kpfguide = ktl . cache ( 'kpfguide' ) axis = [ 'X' , 'Y' ] for i , ax in enumerate ( axis ): nominal_range = kpfguide [ f 'TIPTILT_ { ax } RANGE' ] . read ( binary = True ) home = kpfguide [ 'TIPTILT_HOME' ] . read ( binary = True )[ i ] commanded_position = home - nominal_range log . info ( f \"Sending TT { ax } VAX to { commanded_position } \" ) kpffiu [ f 'TT { ax } VAX' ] . write ( commanded_position ) time . sleep ( movetime * 100 ) current_position = kpffiu [ f 'TT { ax } VAX' ] . read ( binary = True ) if abs ( current_position - commanded_position ) < tol : log . info ( f \" { ax } reached nominal range: { commanded_position } \" ) else : log . error ( f \" { ax } failed to reach { commanded_position } : { current_position } \" ) commanded_position = home + nominal_range log . info ( f \"Sending TT { ax } VAX to { commanded_position } \" ) kpffiu [ f 'TT { ax } VAX' ] . write ( commanded_position ) time . sleep ( movetime * 100 ) current_position = kpffiu [ f 'TT { ax } VAX' ] . read ( binary = True ) if abs ( current_position - commanded_position ) < tol : log . info ( f \" { ax } reached nominal range: { commanded_position } \" ) else : log . error ( f \" { ax } failed to reach { commanded_position } : { current_position } \" ) time . sleep ( movetime * 100 ) InitializeTipTilt . execute ({}) time . sleep ( movetime * 100 ) ShutdownTipTilt . execute ({}) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"TestTipTiltMirrorRange"},{"location":"scripts/TriggerGreenMiniFill/","text":"TriggerGreenMiniFill Bases: KPFTranslatorFunction I really hope this is not necessary in the long term. Source code in kpf/engineering/TriggerGreenMiniFill.py 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class TriggerGreenMiniFill ( KPFTranslatorFunction ): '''I really hope this is not necessary in the long term. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): kpffill = ktl . cache ( 'kpffill' ) if kpffill [ 'GREENFILLIP' ] . read () == 'True' : raise FailedPreCondition ( 'Green fill already in progress' ) @classmethod def perform ( cls , args , logger , cfg ): kpffill = ktl . cache ( 'kpffill' ) # Start fill log . warning ( f 'Starting green mini fill' ) kpffill [ 'GREENSTART' ] . write ( 1 ) # Wait sleep_time = args . get ( 'duration' , 240 ) log . debug ( f 'Sleeping { sleep_time : .0f } s' ) time . sleep ( sleep_time ) # Stop fill if kpffill [ 'GREENFILLIP' ] . read () == 'True' : log . warning ( f 'Stopping green mini fill' ) kpffill [ 'GREENSTOP' ] . write ( 1 ) time . sleep ( 5 ) else : msg = 'Expected green mini fill to be in progress.' SendEmail . execute ({ 'Subject' : 'TriggerGreenMiniFill Failed' , 'Message' : f ' { msg } ' }) raise KPFException ( msg ) @classmethod def post_condition ( cls , args , logger , cfg ): kpffill = ktl . cache ( 'kpffill' ) if kpffill [ 'GREENFILLIP' ] . read () == 'True' : msg = 'Green still in progress, should be stopped!' SendEmail . execute ({ 'Subject' : 'TriggerGreenMiniFill Failed' , 'Message' : f ' { msg } ' }) raise FailedPostCondition ( msg ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'duration' , type = float , help = 'The duration of the fill in seconds (240 recommended)' ) return super () . add_cmdline_args ( parser , cfg )","title":"TriggerGreenMiniFill"},{"location":"scripts/TriggerGreenMiniFill/#triggergreenminifill","text":"Bases: KPFTranslatorFunction I really hope this is not necessary in the long term. Source code in kpf/engineering/TriggerGreenMiniFill.py 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class TriggerGreenMiniFill ( KPFTranslatorFunction ): '''I really hope this is not necessary in the long term. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): kpffill = ktl . cache ( 'kpffill' ) if kpffill [ 'GREENFILLIP' ] . read () == 'True' : raise FailedPreCondition ( 'Green fill already in progress' ) @classmethod def perform ( cls , args , logger , cfg ): kpffill = ktl . cache ( 'kpffill' ) # Start fill log . warning ( f 'Starting green mini fill' ) kpffill [ 'GREENSTART' ] . write ( 1 ) # Wait sleep_time = args . get ( 'duration' , 240 ) log . debug ( f 'Sleeping { sleep_time : .0f } s' ) time . sleep ( sleep_time ) # Stop fill if kpffill [ 'GREENFILLIP' ] . read () == 'True' : log . warning ( f 'Stopping green mini fill' ) kpffill [ 'GREENSTOP' ] . write ( 1 ) time . sleep ( 5 ) else : msg = 'Expected green mini fill to be in progress.' SendEmail . execute ({ 'Subject' : 'TriggerGreenMiniFill Failed' , 'Message' : f ' { msg } ' }) raise KPFException ( msg ) @classmethod def post_condition ( cls , args , logger , cfg ): kpffill = ktl . cache ( 'kpffill' ) if kpffill [ 'GREENFILLIP' ] . read () == 'True' : msg = 'Green still in progress, should be stopped!' SendEmail . execute ({ 'Subject' : 'TriggerGreenMiniFill Failed' , 'Message' : f ' { msg } ' }) raise FailedPostCondition ( msg ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'duration' , type = float , help = 'The duration of the fill in seconds (240 recommended)' ) return super () . add_cmdline_args ( parser , cfg )","title":"TriggerGreenMiniFill"},{"location":"scripts/TriggerRedMiniFill/","text":"TriggerRedMiniFill Bases: KPFTranslatorFunction I really hope this is not necessary in the long term. Source code in kpf/engineering/TriggerRedMiniFill.py 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class TriggerRedMiniFill ( KPFTranslatorFunction ): '''I really hope this is not necessary in the long term. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): kpffill = ktl . cache ( 'kpffill' ) if kpffill [ 'REDFILLIP' ] . read () == 'True' : raise FailedPreCondition ( 'Red fill already in progress' ) @classmethod def perform ( cls , args , logger , cfg ): kpffill = ktl . cache ( 'kpffill' ) # Start fill log . warning ( f 'Starting Red mini fill' ) kpffill [ 'REDSTART' ] . write ( 1 ) # Wait sleep_time = args . get ( 'duration' , 240 ) log . debug ( f 'Sleeping { sleep_time : .0f } s' ) time . sleep ( sleep_time ) # Stop fill if kpffill [ 'REDFILLIP' ] . read () == 'True' : log . warning ( f 'Stopping Red mini fill' ) kpffill [ 'REDSTOP' ] . write ( 1 ) time . sleep ( 5 ) else : msg = 'Expected Red mini fill to be in progress.' SendEmail . execute ({ 'Subject' : 'TriggerRedMiniFill Failed' , 'Message' : f ' { msg } ' }) raise KPFException ( msg ) @classmethod def post_condition ( cls , args , logger , cfg ): kpffill = ktl . cache ( 'kpffill' ) if kpffill [ 'RedFILLIP' ] . read () == 'True' : msg = 'Red still in progress, should be stopped!' SendEmail . execute ({ 'Subject' : 'TriggerRedMiniFill Failed' , 'Message' : f ' { msg } ' }) raise FailedPostCondition ( msg ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'duration' , type = float , help = 'The duration of the fill in seconds (240 recommended)' ) return super () . add_cmdline_args ( parser , cfg )","title":"TriggerRedMiniFill"},{"location":"scripts/TriggerRedMiniFill/#triggerredminifill","text":"Bases: KPFTranslatorFunction I really hope this is not necessary in the long term. Source code in kpf/engineering/TriggerRedMiniFill.py 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class TriggerRedMiniFill ( KPFTranslatorFunction ): '''I really hope this is not necessary in the long term. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): kpffill = ktl . cache ( 'kpffill' ) if kpffill [ 'REDFILLIP' ] . read () == 'True' : raise FailedPreCondition ( 'Red fill already in progress' ) @classmethod def perform ( cls , args , logger , cfg ): kpffill = ktl . cache ( 'kpffill' ) # Start fill log . warning ( f 'Starting Red mini fill' ) kpffill [ 'REDSTART' ] . write ( 1 ) # Wait sleep_time = args . get ( 'duration' , 240 ) log . debug ( f 'Sleeping { sleep_time : .0f } s' ) time . sleep ( sleep_time ) # Stop fill if kpffill [ 'REDFILLIP' ] . read () == 'True' : log . warning ( f 'Stopping Red mini fill' ) kpffill [ 'REDSTOP' ] . write ( 1 ) time . sleep ( 5 ) else : msg = 'Expected Red mini fill to be in progress.' SendEmail . execute ({ 'Subject' : 'TriggerRedMiniFill Failed' , 'Message' : f ' { msg } ' }) raise KPFException ( msg ) @classmethod def post_condition ( cls , args , logger , cfg ): kpffill = ktl . cache ( 'kpffill' ) if kpffill [ 'RedFILLIP' ] . read () == 'True' : msg = 'Red still in progress, should be stopped!' SendEmail . execute ({ 'Subject' : 'TriggerRedMiniFill Failed' , 'Message' : f ' { msg } ' }) raise FailedPostCondition ( msg ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'duration' , type = float , help = 'The duration of the fill in seconds (240 recommended)' ) return super () . add_cmdline_args ( parser , cfg )","title":"TriggerRedMiniFill"},{"location":"scripts/TurnHepaOff/","text":"TurnHepaOff Bases: KPFTranslatorFunction Turn HEPA Filter system off KTL Keywords Used: ao.OBHPAON ao.OBHPASTA Source code in kpf/ao/TurnHepaOff.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class TurnHepaOff ( KPFTranslatorFunction ): '''Turn HEPA Filter system off KTL Keywords Used: - `ao.OBHPAON` - `ao.OBHPASTA` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) log . debug ( 'Setting AO HEPA filter to off' ) ao [ 'OBHPAON' ] . write ( 0 ) @classmethod def post_condition ( cls , args , logger , cfg ): success = ktl . waitfor ( '($ao.OBHPASTA == off)' , timeout = 3 ) if success is not True : ao = ktl . cache ( 'ao' ) raise FailedToReachDestination ( ao [ 'OBHPASTA' ] . read (), 'off' )","title":"TurnHepaOff"},{"location":"scripts/TurnHepaOff/#turnhepaoff","text":"Bases: KPFTranslatorFunction Turn HEPA Filter system off KTL Keywords Used: ao.OBHPAON ao.OBHPASTA Source code in kpf/ao/TurnHepaOff.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class TurnHepaOff ( KPFTranslatorFunction ): '''Turn HEPA Filter system off KTL Keywords Used: - `ao.OBHPAON` - `ao.OBHPASTA` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) log . debug ( 'Setting AO HEPA filter to off' ) ao [ 'OBHPAON' ] . write ( 0 ) @classmethod def post_condition ( cls , args , logger , cfg ): success = ktl . waitfor ( '($ao.OBHPASTA == off)' , timeout = 3 ) if success is not True : ao = ktl . cache ( 'ao' ) raise FailedToReachDestination ( ao [ 'OBHPASTA' ] . read (), 'off' )","title":"TurnHepaOff"},{"location":"scripts/TurnHepaOn/","text":"TurnHepaOn Bases: KPFTranslatorFunction Turn HEPA Filter system on KTL Keywords Used: ao.OBHPAON ao.OBHPASTA Source code in kpf/ao/TurnHepaOn.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class TurnHepaOn ( KPFTranslatorFunction ): '''Turn HEPA Filter system on KTL Keywords Used: - `ao.OBHPAON` - `ao.OBHPASTA` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) log . debug ( 'Setting AO HEPA filter to on' ) ao [ 'OBHPAON' ] . write ( 1 ) @classmethod def post_condition ( cls , args , logger , cfg ): success = ktl . waitfor ( '($ao.OBHPASTA == on)' , timeout = 3 ) if success is not True : ao = ktl . cache ( 'ao' ) raise FailedToReachDestination ( ao [ 'OBHPASTA' ] . read (), 'on' )","title":"TurnHepaOn"},{"location":"scripts/TurnHepaOn/#turnhepaon","text":"Bases: KPFTranslatorFunction Turn HEPA Filter system on KTL Keywords Used: ao.OBHPAON ao.OBHPASTA Source code in kpf/ao/TurnHepaOn.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class TurnHepaOn ( KPFTranslatorFunction ): '''Turn HEPA Filter system on KTL Keywords Used: - `ao.OBHPAON` - `ao.OBHPASTA` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) log . debug ( 'Setting AO HEPA filter to on' ) ao [ 'OBHPAON' ] . write ( 1 ) @classmethod def post_condition ( cls , args , logger , cfg ): success = ktl . waitfor ( '($ao.OBHPASTA == on)' , timeout = 3 ) if success is not True : ao = ktl . cache ( 'ao' ) raise FailedToReachDestination ( ao [ 'OBHPASTA' ] . read (), 'on' )","title":"TurnHepaOn"},{"location":"scripts/TurnLightSourceOff/","text":"TurnLightSourceOff Bases: KPFTranslatorFunction Turn K1 AO light source off KTL Keywords Used: ao.OBSWON ao.OBSWSTA Source code in kpf/ao/TurnLightSourceOff.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class TurnLightSourceOff ( KPFTranslatorFunction ): '''Turn K1 AO light source off KTL Keywords Used: - `ao.OBSWON` - `ao.OBSWSTA` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) log . debug ( 'Turning AO light source off' ) ao [ 'OBSWON' ] . write ( 0 ) @classmethod def post_condition ( cls , args , logger , cfg ): success = ktl . waitfor ( '($ao.OBSWSTA == off)' , timeout = 3 ) if success is not True : ao = ktl . cache ( 'ao' ) raise FailedToReachDestination ( ao [ 'OBSWSTA' ] . read (), 'off' )","title":"TurnLightSourceOff"},{"location":"scripts/TurnLightSourceOff/#turnlightsourceoff","text":"Bases: KPFTranslatorFunction Turn K1 AO light source off KTL Keywords Used: ao.OBSWON ao.OBSWSTA Source code in kpf/ao/TurnLightSourceOff.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class TurnLightSourceOff ( KPFTranslatorFunction ): '''Turn K1 AO light source off KTL Keywords Used: - `ao.OBSWON` - `ao.OBSWSTA` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): ao = ktl . cache ( 'ao' ) log . debug ( 'Turning AO light source off' ) ao [ 'OBSWON' ] . write ( 0 ) @classmethod def post_condition ( cls , args , logger , cfg ): success = ktl . waitfor ( '($ao.OBSWSTA == off)' , timeout = 3 ) if success is not True : ao = ktl . cache ( 'ao' ) raise FailedToReachDestination ( ao [ 'OBSWSTA' ] . read (), 'off' )","title":"TurnLightSourceOff"},{"location":"scripts/UnlockFIU/","text":"UnlockFIU Bases: KPFTranslatorFunction Unlock the FIU mechanisms KTL Keywords Used: kpffiu.ADC1LCK kpffiu.ADC2LCK kpffiu.FOLDLCK kpffiu.HKXLCK kpffiu.HKYLCK kpffiu.TTXLCK kpffiu.TTYLCK Source code in kpf/fiu/UnlockFIU.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 class UnlockFIU ( KPFTranslatorFunction ): '''Unlock the FIU mechanisms KTL Keywords Used: - `kpffiu.ADC1LCK` - `kpffiu.ADC2LCK` - `kpffiu.FOLDLCK` - `kpffiu.HKXLCK` - `kpffiu.HKYLCK` - `kpffiu.TTXLCK` - `kpffiu.TTYLCK` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpffiu = ktl . cache ( 'kpffiu' ) kpffiu [ 'adc1lck' ] . write ( '' ) kpffiu [ 'adc2lck' ] . write ( '' ) kpffiu [ 'foldlck' ] . write ( '' ) kpffiu [ 'hkxlck' ] . write ( '' ) kpffiu [ 'hkylck' ] . write ( '' ) kpffiu [ 'ttxlck' ] . write ( '' ) kpffiu [ 'ttylck' ] . write ( '' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"UnlockFIU"},{"location":"scripts/UnlockFIU/#unlockfiu","text":"Bases: KPFTranslatorFunction Unlock the FIU mechanisms KTL Keywords Used: kpffiu.ADC1LCK kpffiu.ADC2LCK kpffiu.FOLDLCK kpffiu.HKXLCK kpffiu.HKYLCK kpffiu.TTXLCK kpffiu.TTYLCK Source code in kpf/fiu/UnlockFIU.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 class UnlockFIU ( KPFTranslatorFunction ): '''Unlock the FIU mechanisms KTL Keywords Used: - `kpffiu.ADC1LCK` - `kpffiu.ADC2LCK` - `kpffiu.FOLDLCK` - `kpffiu.HKXLCK` - `kpffiu.HKYLCK` - `kpffiu.TTXLCK` - `kpffiu.TTYLCK` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpffiu = ktl . cache ( 'kpffiu' ) kpffiu [ 'adc1lck' ] . write ( '' ) kpffiu [ 'adc2lck' ] . write ( '' ) kpffiu [ 'foldlck' ] . write ( '' ) kpffiu [ 'hkxlck' ] . write ( '' ) kpffiu [ 'hkylck' ] . write ( '' ) kpffiu [ 'ttxlck' ] . write ( '' ) kpffiu [ 'ttylck' ] . write ( '' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"UnlockFIU"},{"location":"scripts/VerifyCurrentBase/","text":"VerifyCurrentBase Bases: KPFTranslatorFunction Check whether the tip tilt system's target pixel (kpffiu.CURRENT_BASE) is consistent with the selected pointing origin (dcs.PONAME) KTL Keywords Used: dcs1.PONAME kpfguide.CURRENT_BASE kpfguide.SCIENCE_BASE kpfguide.SKY_BASE Source code in kpf/fiu/VerifyCurrentBase.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class VerifyCurrentBase ( KPFTranslatorFunction ): '''Check whether the tip tilt system's target pixel (kpffiu.CURRENT_BASE) is consistent with the selected pointing origin (dcs.PONAME) KTL Keywords Used: - `dcs1.PONAME` - `kpfguide.CURRENT_BASE` - `kpfguide.SCIENCE_BASE` - `kpfguide.SKY_BASE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): ponamekw = ktl . cache ( 'dcs1' , 'PONAME' ) poname = ponamekw . read () . upper () kpfguide = ktl . cache ( 'kpfguide' ) current_base = kpfguide [ 'CURRENT_BASE' ] . read ( binary = True ) science_base = kpfguide [ 'SCIENCE_BASE' ] . read ( binary = True ) sky_base = kpfguide [ 'SKY_BASE' ] . read ( binary = True ) science_match = np . all ( np . isclose ( current_base , science_base , atol = 0.01 )) sky_match = np . all ( np . isclose ( current_base , sky_base , atol = 0.01 )) msg = f \"CURRENT_BASE=\" if science_match : log . debug ( f \"CURRENT_BASE is science fiber, PO = { poname } \" ) msg += 'SCIENCE_BASE' elif sky_match : log . debug ( f \"CURRENT_BASE is sky fiber, PO = { poname } \" ) msg += 'SKY_BASE' else : log . debug ( f \"CURRENT_BASE is { current_base } , PO = { poname } \" ) msg += 'custom' poname_match = ( science_match and poname == 'KPF' ) \\ or ( sky_match and poname == 'SKY' ) if poname_match : msg += f \" which is consistent with PONAME= { poname } \" log . debug ( msg ) else : msg += f \" which is NOT consistent with PONAME= { poname } \" log . error ( msg ) print ( msg ) return poname_match @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"VerifyCurrentBase"},{"location":"scripts/VerifyCurrentBase/#verifycurrentbase","text":"Bases: KPFTranslatorFunction Check whether the tip tilt system's target pixel (kpffiu.CURRENT_BASE) is consistent with the selected pointing origin (dcs.PONAME) KTL Keywords Used: dcs1.PONAME kpfguide.CURRENT_BASE kpfguide.SCIENCE_BASE kpfguide.SKY_BASE Source code in kpf/fiu/VerifyCurrentBase.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class VerifyCurrentBase ( KPFTranslatorFunction ): '''Check whether the tip tilt system's target pixel (kpffiu.CURRENT_BASE) is consistent with the selected pointing origin (dcs.PONAME) KTL Keywords Used: - `dcs1.PONAME` - `kpfguide.CURRENT_BASE` - `kpfguide.SCIENCE_BASE` - `kpfguide.SKY_BASE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): ponamekw = ktl . cache ( 'dcs1' , 'PONAME' ) poname = ponamekw . read () . upper () kpfguide = ktl . cache ( 'kpfguide' ) current_base = kpfguide [ 'CURRENT_BASE' ] . read ( binary = True ) science_base = kpfguide [ 'SCIENCE_BASE' ] . read ( binary = True ) sky_base = kpfguide [ 'SKY_BASE' ] . read ( binary = True ) science_match = np . all ( np . isclose ( current_base , science_base , atol = 0.01 )) sky_match = np . all ( np . isclose ( current_base , sky_base , atol = 0.01 )) msg = f \"CURRENT_BASE=\" if science_match : log . debug ( f \"CURRENT_BASE is science fiber, PO = { poname } \" ) msg += 'SCIENCE_BASE' elif sky_match : log . debug ( f \"CURRENT_BASE is sky fiber, PO = { poname } \" ) msg += 'SKY_BASE' else : log . debug ( f \"CURRENT_BASE is { current_base } , PO = { poname } \" ) msg += 'custom' poname_match = ( science_match and poname == 'KPF' ) \\ or ( sky_match and poname == 'SKY' ) if poname_match : msg += f \" which is consistent with PONAME= { poname } \" log . debug ( msg ) else : msg += f \" which is NOT consistent with PONAME= { poname } \" log . error ( msg ) print ( msg ) return poname_match @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"VerifyCurrentBase"},{"location":"scripts/WaitForCalSource/","text":"WaitForCalSource Bases: KPFTranslatorFunction Wait for the move to a cal source is complete (kpfcal.OCTAGON keyword). Parameters: CalSource ( str ) \u2013 Which lamp to select? Allowed Values: EtalonFiber, BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, SoCal-CalFib, LFCFiber KTL Keywords Used: kpfcal.OCTAGON Source code in kpf/calbench/WaitForCalSource.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class WaitForCalSource ( KPFTranslatorFunction ): '''Wait for the move to a cal source is complete (kpfcal.OCTAGON keyword). Args: CalSource (str): Which lamp to select? Allowed Values: EtalonFiber, BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, SoCal-CalFib, LFCFiber KTL Keywords Used: - `kpfcal.OCTAGON` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'OCTAGON' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) check_input ( args , 'CalSource' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): target = args . get ( 'CalSource' ) timeout = cfg . getfloat ( 'times' , 'octagon_move_time' , fallback = 60 ) expr = f \"($kpfcal.OCTAGON == { target } )\" success = ktl . waitFor ( expr , timeout = timeout ) if success is False : log . error ( f \"Timed out waiting for octagon\" ) @classmethod def post_condition ( cls , args , logger , cfg ): target = args . get ( 'CalSource' ) timeout = cfg . getfloat ( 'times' , 'octagon_move_time' , fallback = 60 ) expr = f \"($kpfcal.OCTAGON == { target } )\" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : kpfcal = ktl . cache ( 'kpfcal' ) raise FailedToReachDestination ( kpfcal [ 'OCTAGON' ] . read (), target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalSource' , type = str , choices = [ 'Home' , 'EtalonFiber' , 'BrdbandFiber' , 'U_gold' , 'U_daily' , 'Th_daily' , 'Th_gold' , 'SoCal-CalFib' , 'LFCFiber' ], help = 'Octagon position to choose?' ) return super () . add_cmdline_args ( parser , cfg )","title":"WaitForCalSource"},{"location":"scripts/WaitForCalSource/#waitforcalsource","text":"Bases: KPFTranslatorFunction Wait for the move to a cal source is complete (kpfcal.OCTAGON keyword). Parameters: CalSource ( str ) \u2013 Which lamp to select? Allowed Values: EtalonFiber, BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, SoCal-CalFib, LFCFiber KTL Keywords Used: kpfcal.OCTAGON Source code in kpf/calbench/WaitForCalSource.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class WaitForCalSource ( KPFTranslatorFunction ): '''Wait for the move to a cal source is complete (kpfcal.OCTAGON keyword). Args: CalSource (str): Which lamp to select? Allowed Values: EtalonFiber, BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, SoCal-CalFib, LFCFiber KTL Keywords Used: - `kpfcal.OCTAGON` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'OCTAGON' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) check_input ( args , 'CalSource' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): target = args . get ( 'CalSource' ) timeout = cfg . getfloat ( 'times' , 'octagon_move_time' , fallback = 60 ) expr = f \"($kpfcal.OCTAGON == { target } )\" success = ktl . waitFor ( expr , timeout = timeout ) if success is False : log . error ( f \"Timed out waiting for octagon\" ) @classmethod def post_condition ( cls , args , logger , cfg ): target = args . get ( 'CalSource' ) timeout = cfg . getfloat ( 'times' , 'octagon_move_time' , fallback = 60 ) expr = f \"($kpfcal.OCTAGON == { target } )\" success = ktl . waitFor ( expr , timeout = timeout ) if success is not True : kpfcal = ktl . cache ( 'kpfcal' ) raise FailedToReachDestination ( kpfcal [ 'OCTAGON' ] . read (), target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalSource' , type = str , choices = [ 'Home' , 'EtalonFiber' , 'BrdbandFiber' , 'U_gold' , 'U_daily' , 'Th_daily' , 'Th_gold' , 'SoCal-CalFib' , 'LFCFiber' ], help = 'Octagon position to choose?' ) return super () . add_cmdline_args ( parser , cfg )","title":"WaitForCalSource"},{"location":"scripts/WaitForConfigureCalibrations/","text":"WaitForConfigureCalibrations Bases: KPFTranslatorFunction Script which waits for the instrument to be configured for calibrations. ARGS: None Source code in kpf/scripts/WaitForConfigureCalibrations.py 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 class WaitForConfigureCalibrations ( KPFTranslatorFunction ): '''Script which waits for the instrument to be configured for calibrations. ARGS: ===== None ''' @classmethod def pre_condition ( cls , OB , logger , cfg ): check_input ( OB , 'Template_Name' , allowed_values = [ 'kpf_cal' ]) check_input ( OB , 'Template_Version' , version_check = True , value_min = '0.5' ) @classmethod def perform ( cls , OB , logger , cfg ): WaitForCalSource . execute ( OB ) WaitForConfigureFIU . execute ({ 'mode' : 'Calibration' }) WaitForReady . execute ({}) @classmethod def post_condition ( cls , OB , logger , cfg ): pass","title":"WaitForConfigureCalibrations"},{"location":"scripts/WaitForConfigureCalibrations/#waitforconfigurecalibrations","text":"Bases: KPFTranslatorFunction Script which waits for the instrument to be configured for calibrations.","title":"WaitForConfigureCalibrations"},{"location":"scripts/WaitForConfigureCalibrations/#kpf.scripts.WaitForConfigureCalibrations.WaitForConfigureCalibrations--args","text":"None Source code in kpf/scripts/WaitForConfigureCalibrations.py 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 class WaitForConfigureCalibrations ( KPFTranslatorFunction ): '''Script which waits for the instrument to be configured for calibrations. ARGS: ===== None ''' @classmethod def pre_condition ( cls , OB , logger , cfg ): check_input ( OB , 'Template_Name' , allowed_values = [ 'kpf_cal' ]) check_input ( OB , 'Template_Version' , version_check = True , value_min = '0.5' ) @classmethod def perform ( cls , OB , logger , cfg ): WaitForCalSource . execute ( OB ) WaitForConfigureFIU . execute ({ 'mode' : 'Calibration' }) WaitForReady . execute ({}) @classmethod def post_condition ( cls , OB , logger , cfg ): pass","title":"ARGS:"},{"location":"scripts/WaitForConfigureFIU/","text":"WaitForConfigureFIU Bases: KPFTranslatorFunction Wait for the FIU to reach specified mode (kpffiu.MODE). This will retry the configure command if the system fails to reach its destination. Parameters: mode ( str ) \u2013 The desired FIU mode. Allowed values: Stowed, Alignment, Acquisition, Observing, Calibration KTL Keywords Used: kpffiu.MODE Scripts Called: kpf.calbench.ConfigureFIUOnce Source code in kpf/fiu/WaitForConfigureFIU.py 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 class WaitForConfigureFIU ( KPFTranslatorFunction ): '''Wait for the FIU to reach specified mode (kpffiu.MODE). This will retry the configure command if the system fails to reach its destination. Args: mode (str): The desired FIU mode. Allowed values: Stowed, Alignment, Acquisition, Observing, Calibration KTL Keywords Used: - `kpffiu.MODE` Scripts Called: - `kpf.calbench.ConfigureFIUOnce` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpffiu' , 'MODE' ) allowed_values = list ( keyword . _getEnumerators ()) if 'None' in allowed_values : allowed_values . pop ( allowed_values . index ( 'None' )) check_input ( args , 'mode' , allowed_values = allowed_values ) return True @classmethod def perform ( cls , args , logger , cfg ): dest = args . get ( 'mode' ) ntries = cfg . getint ( 'retries' , 'fiu_mode_tries' , fallback = 2 ) shim_time = cfg . getfloat ( 'times' , 'fiu_mode_shim_time' , fallback = 2 ) for i in range ( ntries ): ok = WaitForConfigureFIUOnce . execute ({ 'mode' : dest }) if ok is False : log . warning ( f 'FIU move failed on attempt { i + 1 } of { ntries } ' ) time . sleep ( shim_time ) ConfigureFIUOnce . execute ({ 'mode' : dest , 'wait' : True }) else : break @classmethod def post_condition ( cls , args , logger , cfg ): dest = args . get ( 'mode' ) kpffiu = ktl . cache ( 'kpffiu' ) modes = kpffiu [ 'MODE' ] . read () if dest . lower () not in modes . lower () . split ( ',' ): raise FailedToReachDestination ( modes , dest ) else : log . info ( f \"FIU mode is now { dest } \" ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'mode' , type = str , choices = [ 'Stowed' , 'Alignment' , 'Acquisition' , 'Observing' , 'Calibration' ], help = 'Desired mode (see kpffiu.MODE)' ) return super () . add_cmdline_args ( parser , cfg )","title":"WaitForConfigureFIU"},{"location":"scripts/WaitForConfigureFIU/#waitforconfigurefiu","text":"Bases: KPFTranslatorFunction Wait for the FIU to reach specified mode (kpffiu.MODE). This will retry the configure command if the system fails to reach its destination. Parameters: mode ( str ) \u2013 The desired FIU mode. Allowed values: Stowed, Alignment, Acquisition, Observing, Calibration KTL Keywords Used: kpffiu.MODE Scripts Called: kpf.calbench.ConfigureFIUOnce Source code in kpf/fiu/WaitForConfigureFIU.py 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 class WaitForConfigureFIU ( KPFTranslatorFunction ): '''Wait for the FIU to reach specified mode (kpffiu.MODE). This will retry the configure command if the system fails to reach its destination. Args: mode (str): The desired FIU mode. Allowed values: Stowed, Alignment, Acquisition, Observing, Calibration KTL Keywords Used: - `kpffiu.MODE` Scripts Called: - `kpf.calbench.ConfigureFIUOnce` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpffiu' , 'MODE' ) allowed_values = list ( keyword . _getEnumerators ()) if 'None' in allowed_values : allowed_values . pop ( allowed_values . index ( 'None' )) check_input ( args , 'mode' , allowed_values = allowed_values ) return True @classmethod def perform ( cls , args , logger , cfg ): dest = args . get ( 'mode' ) ntries = cfg . getint ( 'retries' , 'fiu_mode_tries' , fallback = 2 ) shim_time = cfg . getfloat ( 'times' , 'fiu_mode_shim_time' , fallback = 2 ) for i in range ( ntries ): ok = WaitForConfigureFIUOnce . execute ({ 'mode' : dest }) if ok is False : log . warning ( f 'FIU move failed on attempt { i + 1 } of { ntries } ' ) time . sleep ( shim_time ) ConfigureFIUOnce . execute ({ 'mode' : dest , 'wait' : True }) else : break @classmethod def post_condition ( cls , args , logger , cfg ): dest = args . get ( 'mode' ) kpffiu = ktl . cache ( 'kpffiu' ) modes = kpffiu [ 'MODE' ] . read () if dest . lower () not in modes . lower () . split ( ',' ): raise FailedToReachDestination ( modes , dest ) else : log . info ( f \"FIU mode is now { dest } \" ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'mode' , type = str , choices = [ 'Stowed' , 'Alignment' , 'Acquisition' , 'Observing' , 'Calibration' ], help = 'Desired mode (see kpffiu.MODE)' ) return super () . add_cmdline_args ( parser , cfg )","title":"WaitForConfigureFIU"},{"location":"scripts/WaitForFlatFieldFiberPos/","text":"WaitForFlatFieldFiberPos Bases: KPFTranslatorFunction Wait for the flat field fiber aperture via the kpfcal.FF_FIBERPOS keyword. Parameters: FF_FiberPos ( str ) \u2013 The name of the flat field fiber position desired. Allowed Values: \"Blank\", \"6 mm f/5\", \"7.5 mm f/4\", \"10 mm f/3\", \"13.2 mm f/2.3\", \"Open\". wait ( bool ) \u2013 Wait for move to complete before returning? default: True KTL Keywords Used kpfcal.FF_FIBERPOS Source code in kpf/calbench/WaitForFlatFieldFiberPos.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class WaitForFlatFieldFiberPos ( KPFTranslatorFunction ): '''Wait for the flat field fiber aperture via the `kpfcal.FF_FIBERPOS` keyword. Args: FF_FiberPos (str): The name of the flat field fiber position desired. Allowed Values: \"Blank\", \"6 mm f/5\", \"7.5 mm f/4\", \"10 mm f/3\", \"13.2 mm f/2.3\", \"Open\". wait (bool): Wait for move to complete before returning? default: True ## KTL Keywords Used - `kpfcal.FF_FIBERPOS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'FF_FiberPos' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) check_input ( args , 'FF_FiberPos' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): target = args . get ( 'FF_FiberPos' ) timeout = cfg . getfloat ( 'times' , 'nd_move_time' , fallback = 20 ) expr = f \"($kpfcal.FF_FiberPos == ' { target } ')\" success = ktl . waitFor ( expr , timeout = timeout ) if success is False : log . error ( f \"Timed out waiting for FF_FiberPos filter wheel\" ) @classmethod def post_condition ( cls , args , logger , cfg ): target = args . get ( 'FF_FiberPos' ) expr = f \"($kpfcal.FF_FiberPos == ' { target } ')\" success = ktl . waitFor ( expr , timeout = 0.1 ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'FF_FiberPos' , type = str , choices = [ \"Blank\" , \"6 mm f/5\" , \"7.5 mm f/4\" , \"10 mm f/3\" , \"13.2 mm f/2.3\" , \"Open\" ], help = 'Wide flat aperture to use.' ) return super () . add_cmdline_args ( parser , cfg )","title":"WaitForFlatFieldFiberPos"},{"location":"scripts/WaitForFlatFieldFiberPos/#waitforflatfieldfiberpos","text":"Bases: KPFTranslatorFunction Wait for the flat field fiber aperture via the kpfcal.FF_FIBERPOS keyword. Parameters: FF_FiberPos ( str ) \u2013 The name of the flat field fiber position desired. Allowed Values: \"Blank\", \"6 mm f/5\", \"7.5 mm f/4\", \"10 mm f/3\", \"13.2 mm f/2.3\", \"Open\". wait ( bool ) \u2013 Wait for move to complete before returning? default: True","title":"WaitForFlatFieldFiberPos"},{"location":"scripts/WaitForFlatFieldFiberPos/#kpf.calbench.WaitForFlatFieldFiberPos.WaitForFlatFieldFiberPos--ktl-keywords-used","text":"kpfcal.FF_FIBERPOS Source code in kpf/calbench/WaitForFlatFieldFiberPos.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class WaitForFlatFieldFiberPos ( KPFTranslatorFunction ): '''Wait for the flat field fiber aperture via the `kpfcal.FF_FIBERPOS` keyword. Args: FF_FiberPos (str): The name of the flat field fiber position desired. Allowed Values: \"Blank\", \"6 mm f/5\", \"7.5 mm f/4\", \"10 mm f/3\", \"13.2 mm f/2.3\", \"Open\". wait (bool): Wait for move to complete before returning? default: True ## KTL Keywords Used - `kpfcal.FF_FIBERPOS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'FF_FiberPos' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) check_input ( args , 'FF_FiberPos' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): target = args . get ( 'FF_FiberPos' ) timeout = cfg . getfloat ( 'times' , 'nd_move_time' , fallback = 20 ) expr = f \"($kpfcal.FF_FiberPos == ' { target } ')\" success = ktl . waitFor ( expr , timeout = timeout ) if success is False : log . error ( f \"Timed out waiting for FF_FiberPos filter wheel\" ) @classmethod def post_condition ( cls , args , logger , cfg ): target = args . get ( 'FF_FiberPos' ) expr = f \"($kpfcal.FF_FiberPos == ' { target } ')\" success = ktl . waitFor ( expr , timeout = 0.1 ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'FF_FiberPos' , type = str , choices = [ \"Blank\" , \"6 mm f/5\" , \"7.5 mm f/4\" , \"10 mm f/3\" , \"13.2 mm f/2.3\" , \"Open\" ], help = 'Wide flat aperture to use.' ) return super () . add_cmdline_args ( parser , cfg )","title":"KTL Keywords Used"},{"location":"scripts/WaitForL0File/","text":"WaitForL0File Bases: KPFTranslatorFunction Wait a short time to see if kpfassemble writes a new L0 file. If it does, print a log line with that file name. KTL Keywords Used: kpfassemble.LOUTFILE Source code in kpf/spectrograph/WaitForL0File.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 class WaitForL0File ( KPFTranslatorFunction ): '''Wait a short time to see if `kpfassemble` writes a new L0 file. If it does, print a log line with that file name. KTL Keywords Used: - `kpfassemble.LOUTFILE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): LOUTFILE = ktl . cache ( 'kpfassemble' , 'LOUTFILE' ) initial_LOUTFILE = LOUTFILE . read () timeout = 10 found_new_file = LOUTFILE . waitFor ( f '!=\" { initial_LOUTFILE } \"' , timeout = timeout ) if found_new_file is True : log . info ( f 'kpfassemble wrote { LOUTFILE . read () } ' ) else : log . debug ( 'WaitForL0File did not find new file' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"WaitForL0File"},{"location":"scripts/WaitForL0File/#waitforl0file","text":"Bases: KPFTranslatorFunction Wait a short time to see if kpfassemble writes a new L0 file. If it does, print a log line with that file name. KTL Keywords Used: kpfassemble.LOUTFILE Source code in kpf/spectrograph/WaitForL0File.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 class WaitForL0File ( KPFTranslatorFunction ): '''Wait a short time to see if `kpfassemble` writes a new L0 file. If it does, print a log line with that file name. KTL Keywords Used: - `kpfassemble.LOUTFILE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): LOUTFILE = ktl . cache ( 'kpfassemble' , 'LOUTFILE' ) initial_LOUTFILE = LOUTFILE . read () timeout = 10 found_new_file = LOUTFILE . waitFor ( f '!=\" { initial_LOUTFILE } \"' , timeout = timeout ) if found_new_file is True : log . info ( f 'kpfassemble wrote { LOUTFILE . read () } ' ) else : log . debug ( 'WaitForL0File did not find new file' ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"WaitForL0File"},{"location":"scripts/WaitForLFCReady/","text":"WaitForLFCReady Bases: KPFTranslatorFunction Wait for the Laser Frequency Comb (LFC) to be ready and in \"AstroComb\" mode KTL Keywords Used: kpfmon.HB_MENLOSTA kpfmon.LFCREADYSTA kpfcal.WOBBLE kpfcal.OPERATIONMODE kpfcal.SPECFLAT Source code in kpf/calbench/WaitForLFCReady.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 class WaitForLFCReady ( KPFTranslatorFunction ): '''Wait for the Laser Frequency Comb (LFC) to be ready and in \"AstroComb\" mode KTL Keywords Used: - `kpfmon.HB_MENLOSTA` - `kpfmon.LFCREADYSTA` - `kpfcal.WOBBLE` - `kpfcal.OPERATIONMODE` - `kpfcal.SPECFLAT` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): expr = f \"($kpfmon.HB_MENLOSTA == 'OK')\" expr += f \"and ($kpfmon.LFCREADYSTA == 'OK')\" expr += f \"and ($kpfcal.WOBBLE == 'False')\" expr += f \"and ($kpfcal.OPERATIONMODE == 'AstroComb')\" expr += f \"and ($kpfcal.SPECFLAT == 'True')\" timeout = cfg . getfloat ( 'times' , 'LFC_startup_time' , fallback = 300 ) success = ktl . waitFor ( expr , timeout = timeout ) return success @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"WaitForLFCReady"},{"location":"scripts/WaitForLFCReady/#waitforlfcready","text":"Bases: KPFTranslatorFunction Wait for the Laser Frequency Comb (LFC) to be ready and in \"AstroComb\" mode KTL Keywords Used: kpfmon.HB_MENLOSTA kpfmon.LFCREADYSTA kpfcal.WOBBLE kpfcal.OPERATIONMODE kpfcal.SPECFLAT Source code in kpf/calbench/WaitForLFCReady.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 class WaitForLFCReady ( KPFTranslatorFunction ): '''Wait for the Laser Frequency Comb (LFC) to be ready and in \"AstroComb\" mode KTL Keywords Used: - `kpfmon.HB_MENLOSTA` - `kpfmon.LFCREADYSTA` - `kpfcal.WOBBLE` - `kpfcal.OPERATIONMODE` - `kpfcal.SPECFLAT` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): expr = f \"($kpfmon.HB_MENLOSTA == 'OK')\" expr += f \"and ($kpfmon.LFCREADYSTA == 'OK')\" expr += f \"and ($kpfcal.WOBBLE == 'False')\" expr += f \"and ($kpfcal.OPERATIONMODE == 'AstroComb')\" expr += f \"and ($kpfcal.SPECFLAT == 'True')\" timeout = cfg . getfloat ( 'times' , 'LFC_startup_time' , fallback = 300 ) success = ktl . waitFor ( expr , timeout = timeout ) return success @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"WaitForLFCReady"},{"location":"scripts/WaitForLampWarm/","text":"WaitForLampWarm Bases: KPFTranslatorFunction Wait for the specified lamp to be warm. Parameters: CalSource ( str ) \u2013 Which lamp to wait for. Allowed Values: BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, WideFlat KTL Keywords Used: kpflamps.FF_FIBER_STATUS kpflamps.FF_FIBER_TIMEON kpflamps.FF_FIBER_THRESHOLD kpflamps.BRDBANDFIBER_STATUS kpflamps.BRDBANDFIBER_TIMEON kpflamps.BRDBANDFIBER_THRESHOLD kpflamps.TH_DAILY_STATUS kpflamps.TH_DAILY_TIMEON kpflamps.TH_DAILY_THRESHOLD kpflamps.TH_GOLD_STATUS kpflamps.TH_GOLD_TIMEON kpflamps.TH_GOLD_THRESHOLD kpflamps.U_DAILY_STATUS kpflamps.U_DAILY_TIMEON kpflamps.U_DAILY_THRESHOLD kpflamps.U_GOLD_STATUS kpflamps.U_GOLD_TIMEON kpflamps.U_GOLD_THRESHOLD Scripts Called: kpf.calbench.CalLampPower Source code in kpf/calbench/WaitForLampWarm.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class WaitForLampWarm ( KPFTranslatorFunction ): '''Wait for the specified lamp to be warm. Args: CalSource (str): Which lamp to wait for. Allowed Values: BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, WideFlat KTL Keywords Used: - `kpflamps.FF_FIBER_STATUS` - `kpflamps.FF_FIBER_TIMEON` - `kpflamps.FF_FIBER_THRESHOLD` - `kpflamps.BRDBANDFIBER_STATUS` - `kpflamps.BRDBANDFIBER_TIMEON` - `kpflamps.BRDBANDFIBER_THRESHOLD` - `kpflamps.TH_DAILY_STATUS` - `kpflamps.TH_DAILY_TIMEON` - `kpflamps.TH_DAILY_THRESHOLD` - `kpflamps.TH_GOLD_STATUS` - `kpflamps.TH_GOLD_TIMEON` - `kpflamps.TH_GOLD_THRESHOLD` - `kpflamps.U_DAILY_STATUS` - `kpflamps.U_DAILY_TIMEON` - `kpflamps.U_DAILY_THRESHOLD` - `kpflamps.U_GOLD_STATUS` - `kpflamps.U_GOLD_TIMEON` - `kpflamps.U_GOLD_THRESHOLD` Scripts Called: - `kpf.calbench.CalLampPower` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'CalSource' ) @classmethod def perform ( cls , args , logger , cfg ): lamp = standardize_lamp_name ( args . get ( 'CalSource' )) lamps_that_need_warmup = [ 'FF_FIBER' , 'BRDBANDFIBER' , 'TH_DAILY' , 'TH_GOLD' , 'U_DAILY' , 'U_GOLD' ] if lamp in lamps_that_need_warmup : kpflamps = ktl . cache ( 'kpflamps' ) log . debug ( f 'Lamp { lamp } does need to be warmed up before use' ) # Check that lamp is actually on lamp = standardize_lamp_name ( args . get ( 'CalSource' )) lamp_statuskw = ktl . cache ( 'kpflamps' , f ' { lamp } _STATUS' ) lamp_status = lamp_statuskw . read () if lamp_status == 'Off' : log . warning ( f \"Lamp { lamp } is not on: { lamp_status } \" ) CalLampPower . execute ({ 'lamp' : args . get ( 'CalSource' ), 'power' : 'on' }) lamp_status = lamp_statuskw . read () if lamp_status == 'Off' : raise KPFException ( f \"Lamp { lamp } should be on: { lamp_status } \" ) elif lamp_status == 'Warm' : log . debug ( f \"Lamp { lamp } is warm\" ) elif lamp_status == 'Warming' : lamp_timeon = kpflamps [ f ' { lamp } _TIMEON' ] . read ( binary = True ) lamp_threshold = kpflamps [ f ' { lamp } _THRESHOLD' ] . read ( binary = True ) time_to_wait = lamp_threshold - lamp_timeon log . info ( f \"Lamp { lamp } is warming\" ) log . info ( f \"Estimated time remaining = { time_to_wait : .0f } s\" ) while lamp_statuskw . read () != 'Warm' : # Check if scriptstop has been activated check_scriptstop () log . debug ( f 'Waiting for { lamp } _STATUS == Warm' ) expr = f \"($kpflamps. { lamp } _STATUS == 'Warm')\" warm = ktl . waitFor ( expr , timeout = 30 ) if warm is False : new_lamp_timeton = kpflamps [ f ' { lamp } _TIMEON' ] . read ( binary = True ) if new_lamp_timeton <= lamp_timeon : break lamp_timeon = new_lamp_timeton @classmethod def post_condition ( cls , args , logger , cfg ): lamp = standardize_lamp_name ( args . get ( 'CalSource' )) lamps_that_need_warmup = [ 'FF_FIBER' , 'BRDBANDFIBER' , 'TH_DAILY' , 'TH_GOLD' , 'U_DAILY' , 'U_GOLD' ] if lamp in lamps_that_need_warmup : lamp_statuskw = ktl . cache ( 'kpflamps' , f ' { lamp } _STATUS' ) lamp_status = lamp_statuskw . read () if lamp_status != 'Warm' : raise FailedPostCondition ( f \"Lamp { lamp } should be warm: { lamp_status } \" ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'lamp' , type = str , choices = [ 'BrdbandFiber' , 'U_gold' , 'U_daily' , 'Th_daily' , 'Th_gold' , 'WideFlat' ], help = 'Which lamp are we waiting on?' ) return super () . add_cmdline_args ( parser , cfg )","title":"WaitForLampWarm"},{"location":"scripts/WaitForLampWarm/#waitforlampwarm","text":"Bases: KPFTranslatorFunction Wait for the specified lamp to be warm. Parameters: CalSource ( str ) \u2013 Which lamp to wait for. Allowed Values: BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, WideFlat KTL Keywords Used: kpflamps.FF_FIBER_STATUS kpflamps.FF_FIBER_TIMEON kpflamps.FF_FIBER_THRESHOLD kpflamps.BRDBANDFIBER_STATUS kpflamps.BRDBANDFIBER_TIMEON kpflamps.BRDBANDFIBER_THRESHOLD kpflamps.TH_DAILY_STATUS kpflamps.TH_DAILY_TIMEON kpflamps.TH_DAILY_THRESHOLD kpflamps.TH_GOLD_STATUS kpflamps.TH_GOLD_TIMEON kpflamps.TH_GOLD_THRESHOLD kpflamps.U_DAILY_STATUS kpflamps.U_DAILY_TIMEON kpflamps.U_DAILY_THRESHOLD kpflamps.U_GOLD_STATUS kpflamps.U_GOLD_TIMEON kpflamps.U_GOLD_THRESHOLD Scripts Called: kpf.calbench.CalLampPower Source code in kpf/calbench/WaitForLampWarm.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class WaitForLampWarm ( KPFTranslatorFunction ): '''Wait for the specified lamp to be warm. Args: CalSource (str): Which lamp to wait for. Allowed Values: BrdbandFiber, U_gold, U_daily, Th_daily, Th_gold, WideFlat KTL Keywords Used: - `kpflamps.FF_FIBER_STATUS` - `kpflamps.FF_FIBER_TIMEON` - `kpflamps.FF_FIBER_THRESHOLD` - `kpflamps.BRDBANDFIBER_STATUS` - `kpflamps.BRDBANDFIBER_TIMEON` - `kpflamps.BRDBANDFIBER_THRESHOLD` - `kpflamps.TH_DAILY_STATUS` - `kpflamps.TH_DAILY_TIMEON` - `kpflamps.TH_DAILY_THRESHOLD` - `kpflamps.TH_GOLD_STATUS` - `kpflamps.TH_GOLD_TIMEON` - `kpflamps.TH_GOLD_THRESHOLD` - `kpflamps.U_DAILY_STATUS` - `kpflamps.U_DAILY_TIMEON` - `kpflamps.U_DAILY_THRESHOLD` - `kpflamps.U_GOLD_STATUS` - `kpflamps.U_GOLD_TIMEON` - `kpflamps.U_GOLD_THRESHOLD` Scripts Called: - `kpf.calbench.CalLampPower` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'CalSource' ) @classmethod def perform ( cls , args , logger , cfg ): lamp = standardize_lamp_name ( args . get ( 'CalSource' )) lamps_that_need_warmup = [ 'FF_FIBER' , 'BRDBANDFIBER' , 'TH_DAILY' , 'TH_GOLD' , 'U_DAILY' , 'U_GOLD' ] if lamp in lamps_that_need_warmup : kpflamps = ktl . cache ( 'kpflamps' ) log . debug ( f 'Lamp { lamp } does need to be warmed up before use' ) # Check that lamp is actually on lamp = standardize_lamp_name ( args . get ( 'CalSource' )) lamp_statuskw = ktl . cache ( 'kpflamps' , f ' { lamp } _STATUS' ) lamp_status = lamp_statuskw . read () if lamp_status == 'Off' : log . warning ( f \"Lamp { lamp } is not on: { lamp_status } \" ) CalLampPower . execute ({ 'lamp' : args . get ( 'CalSource' ), 'power' : 'on' }) lamp_status = lamp_statuskw . read () if lamp_status == 'Off' : raise KPFException ( f \"Lamp { lamp } should be on: { lamp_status } \" ) elif lamp_status == 'Warm' : log . debug ( f \"Lamp { lamp } is warm\" ) elif lamp_status == 'Warming' : lamp_timeon = kpflamps [ f ' { lamp } _TIMEON' ] . read ( binary = True ) lamp_threshold = kpflamps [ f ' { lamp } _THRESHOLD' ] . read ( binary = True ) time_to_wait = lamp_threshold - lamp_timeon log . info ( f \"Lamp { lamp } is warming\" ) log . info ( f \"Estimated time remaining = { time_to_wait : .0f } s\" ) while lamp_statuskw . read () != 'Warm' : # Check if scriptstop has been activated check_scriptstop () log . debug ( f 'Waiting for { lamp } _STATUS == Warm' ) expr = f \"($kpflamps. { lamp } _STATUS == 'Warm')\" warm = ktl . waitFor ( expr , timeout = 30 ) if warm is False : new_lamp_timeton = kpflamps [ f ' { lamp } _TIMEON' ] . read ( binary = True ) if new_lamp_timeton <= lamp_timeon : break lamp_timeon = new_lamp_timeton @classmethod def post_condition ( cls , args , logger , cfg ): lamp = standardize_lamp_name ( args . get ( 'CalSource' )) lamps_that_need_warmup = [ 'FF_FIBER' , 'BRDBANDFIBER' , 'TH_DAILY' , 'TH_GOLD' , 'U_DAILY' , 'U_GOLD' ] if lamp in lamps_that_need_warmup : lamp_statuskw = ktl . cache ( 'kpflamps' , f ' { lamp } _STATUS' ) lamp_status = lamp_statuskw . read () if lamp_status != 'Warm' : raise FailedPostCondition ( f \"Lamp { lamp } should be warm: { lamp_status } \" ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'lamp' , type = str , choices = [ 'BrdbandFiber' , 'U_gold' , 'U_daily' , 'Th_daily' , 'Th_gold' , 'WideFlat' ], help = 'Which lamp are we waiting on?' ) return super () . add_cmdline_args ( parser , cfg )","title":"WaitForLampWarm"},{"location":"scripts/WaitForND/","text":"WaitForND Bases: KPFTranslatorFunction Wait for both ND filter wheels. Parameters: CalND1 ( str ) \u2013 The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: OD 0.1 , OD 1.0 , OD 1.3 , OD 2.0 , OD 3.0 , OD 4.0 CalND2 ( str ) \u2013 The neutral density filter to put in the first filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: OD 0.1 , OD 0.3 , OD 0.5 , OD 0.8 , OD 1.0 , OD 4.0 Scripts Called: kpf.calbench.WaitForND1 kpf.calbench.WaitForND2 Source code in kpf/calbench/WaitForND.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 class WaitForND ( KPFTranslatorFunction ): '''Wait for both ND filter wheels. Args: CalND1 (str): The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: `OD 0.1`, `OD 1.0`, `OD 1.3`, `OD 2.0`, `OD 3.0`, `OD 4.0` CalND2 (str): The neutral density filter to put in the first filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: `OD 0.1`, `OD 0.3`, `OD 0.5`, `OD 0.8`, `OD 1.0`, `OD 4.0` Scripts Called: - `kpf.calbench.WaitForND1` - `kpf.calbench.WaitForND2` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): WaitForND1 . execute ( args ) WaitForND2 . execute ( args ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalND1' , type = str , choices = [ \"OD 0.1\" , \"OD 1.0\" , \"OD 1.3\" , \"OD 2.0\" , \"OD 3.0\" , \"OD 4.0\" ], help = 'ND1 Filter to use.' ) parser . add_argument ( 'CalND2' , type = str , help = 'ND2 Filter to use.' ) return super () . add_cmdline_args ( parser , cfg )","title":"WaitForND"},{"location":"scripts/WaitForND/#waitfornd","text":"Bases: KPFTranslatorFunction Wait for both ND filter wheels. Parameters: CalND1 ( str ) \u2013 The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: OD 0.1 , OD 1.0 , OD 1.3 , OD 2.0 , OD 3.0 , OD 4.0 CalND2 ( str ) \u2013 The neutral density filter to put in the first filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: OD 0.1 , OD 0.3 , OD 0.5 , OD 0.8 , OD 1.0 , OD 4.0 Scripts Called: kpf.calbench.WaitForND1 kpf.calbench.WaitForND2 Source code in kpf/calbench/WaitForND.py 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 class WaitForND ( KPFTranslatorFunction ): '''Wait for both ND filter wheels. Args: CalND1 (str): The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: `OD 0.1`, `OD 1.0`, `OD 1.3`, `OD 2.0`, `OD 3.0`, `OD 4.0` CalND2 (str): The neutral density filter to put in the first filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: `OD 0.1`, `OD 0.3`, `OD 0.5`, `OD 0.8`, `OD 1.0`, `OD 4.0` Scripts Called: - `kpf.calbench.WaitForND1` - `kpf.calbench.WaitForND2` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): WaitForND1 . execute ( args ) WaitForND2 . execute ( args ) @classmethod def post_condition ( cls , args , logger , cfg ): pass @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalND1' , type = str , choices = [ \"OD 0.1\" , \"OD 1.0\" , \"OD 1.3\" , \"OD 2.0\" , \"OD 3.0\" , \"OD 4.0\" ], help = 'ND1 Filter to use.' ) parser . add_argument ( 'CalND2' , type = str , help = 'ND2 Filter to use.' ) return super () . add_cmdline_args ( parser , cfg )","title":"WaitForND"},{"location":"scripts/WaitForND1/","text":"WaitForND1 Bases: KPFTranslatorFunction Wait for the ND1 filter wheel (the one at the output of the octagon) via the kpfcal.ND1POS keyword. Parameters: CalND1 ( str ) \u2013 The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: OD 0.1 , OD 1.0 , OD 1.3 , OD 2.0 , OD 3.0 , OD 4.0 KTL Keywords Used: kpfcal.ND1POS Source code in kpf/calbench/WaitForND1.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class WaitForND1 ( KPFTranslatorFunction ): '''Wait for the ND1 filter wheel (the one at the output of the octagon) via the `kpfcal.ND1POS` keyword. Args: CalND1 (str): The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: `OD 0.1`, `OD 1.0`, `OD 1.3`, `OD 2.0`, `OD 3.0`, `OD 4.0` KTL Keywords Used: - `kpfcal.ND1POS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'ND1POS' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) check_input ( args , 'CalND1' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): target = args . get ( 'CalND1' ) timeout = cfg . getfloat ( 'times' , 'nd_move_time' , fallback = 20 ) expr = f \"($kpfcal.ND1POS == ' { target } ')\" success = ktl . waitFor ( expr , timeout = timeout ) if success is False : log . error ( f \"Timed out waiting for ND1 filter wheel\" ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'nd_move_time' , fallback = 20 ) ND1target = args . get ( 'CalND1' ) ND1POS = ktl . cache ( 'kpfcal' , 'ND1POS' ) if ND1POS . waitFor ( f \"== ' { ND1target } '\" , timeout = timeout ) == False : raise FailedToReachDestination ( ND1POS . read (), ND1target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalND1' , type = str , choices = [ \"OD 0.1\" , \"OD 1.0\" , \"OD 1.3\" , \"OD 2.0\" , \"OD 3.0\" , \"OD 4.0\" ], help = 'ND1 Filter to use.' ) return super () . add_cmdline_args ( parser , cfg )","title":"WaitForND1"},{"location":"scripts/WaitForND1/#waitfornd1","text":"Bases: KPFTranslatorFunction Wait for the ND1 filter wheel (the one at the output of the octagon) via the kpfcal.ND1POS keyword. Parameters: CalND1 ( str ) \u2013 The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: OD 0.1 , OD 1.0 , OD 1.3 , OD 2.0 , OD 3.0 , OD 4.0 KTL Keywords Used: kpfcal.ND1POS Source code in kpf/calbench/WaitForND1.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class WaitForND1 ( KPFTranslatorFunction ): '''Wait for the ND1 filter wheel (the one at the output of the octagon) via the `kpfcal.ND1POS` keyword. Args: CalND1 (str): The neutral density filter to put in the first filter wheel. This affects both the simultaneous calibration light and light which can be routed through the FIU to the science and sky fibers. Allowed Values: `OD 0.1`, `OD 1.0`, `OD 1.3`, `OD 2.0`, `OD 3.0`, `OD 4.0` KTL Keywords Used: - `kpfcal.ND1POS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'ND1POS' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) check_input ( args , 'CalND1' , allowed_values = allowed_values ) @classmethod def perform ( cls , args , logger , cfg ): target = args . get ( 'CalND1' ) timeout = cfg . getfloat ( 'times' , 'nd_move_time' , fallback = 20 ) expr = f \"($kpfcal.ND1POS == ' { target } ')\" success = ktl . waitFor ( expr , timeout = timeout ) if success is False : log . error ( f \"Timed out waiting for ND1 filter wheel\" ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'nd_move_time' , fallback = 20 ) ND1target = args . get ( 'CalND1' ) ND1POS = ktl . cache ( 'kpfcal' , 'ND1POS' ) if ND1POS . waitFor ( f \"== ' { ND1target } '\" , timeout = timeout ) == False : raise FailedToReachDestination ( ND1POS . read (), ND1target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalND1' , type = str , choices = [ \"OD 0.1\" , \"OD 1.0\" , \"OD 1.3\" , \"OD 2.0\" , \"OD 3.0\" , \"OD 4.0\" ], help = 'ND1 Filter to use.' ) return super () . add_cmdline_args ( parser , cfg )","title":"WaitForND1"},{"location":"scripts/WaitForND2/","text":"WaitForND2 Bases: KPFTranslatorFunction Description Set the filter in the ND2 filter wheel (the one at the output of the octagon) via the kpfcal.ND2POS keyword. Parameters: CalND2 ( str ) \u2013 The neutral density filter to put in the first filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: OD 0.1 , OD 0.3 , OD 0.5 , OD 0.8 , OD 1.0 , OD 4.0 KTL Keywords Used: kpfcal.ND2POS Source code in kpf/calbench/WaitForND2.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class WaitForND2 ( KPFTranslatorFunction ): '''# Description Set the filter in the ND2 filter wheel (the one at the output of the octagon) via the `kpfcal.ND2POS` keyword. Args: CalND2 (str): The neutral density filter to put in the first filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: `OD 0.1`, `OD 0.3`, `OD 0.5`, `OD 0.8`, `OD 1.0`, `OD 4.0` KTL Keywords Used: - `kpfcal.ND2POS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'ND2POS' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) check_input ( args , 'CalND2' , allowed_values = allowed_values ) return True @classmethod def perform ( cls , args , logger , cfg ): target = args . get ( 'CalND2' ) timeout = cfg . getfloat ( 'times' , 'nd_move_time' , fallback = 20 ) expr = f \"($kpfcal.ND2POS == ' { target } ')\" success = ktl . waitFor ( expr , timeout = timeout ) if success is False : log . error ( f \"Timed out waiting for ND2 filter wheel\" ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'nd_move_time' , fallback = 20 ) ND2target = args . get ( 'CalND2' ) ND2POS = ktl . cache ( 'kpfcal' , 'ND2POS' ) if ND2POS . waitFor ( f \"== ' { ND2target } '\" , timeout = timeout ) == False : raise FailedToReachDestination ( ND2POS . read (), ND2target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalND2' , type = str , choices = [ \"OD 0.1\" , \"OD 0.3\" , \"OD 0.5\" , \"OD 0.8\" , \"OD 1.0\" , \"OD 4.0\" ], help = 'ND2 Filter to use.' ) return super () . add_cmdline_args ( parser , cfg )","title":"WaitForND2"},{"location":"scripts/WaitForND2/#waitfornd2","text":"Bases: KPFTranslatorFunction","title":"WaitForND2"},{"location":"scripts/WaitForND2/#kpf.calbench.WaitForND2.WaitForND2--description","text":"Set the filter in the ND2 filter wheel (the one at the output of the octagon) via the kpfcal.ND2POS keyword. Parameters: CalND2 ( str ) \u2013 The neutral density filter to put in the first filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: OD 0.1 , OD 0.3 , OD 0.5 , OD 0.8 , OD 1.0 , OD 4.0 KTL Keywords Used: kpfcal.ND2POS Source code in kpf/calbench/WaitForND2.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class WaitForND2 ( KPFTranslatorFunction ): '''# Description Set the filter in the ND2 filter wheel (the one at the output of the octagon) via the `kpfcal.ND2POS` keyword. Args: CalND2 (str): The neutral density filter to put in the first filter wheel. This affects only the light injected in to the simultaneous calibration fiber. Allowed Values: `OD 0.1`, `OD 0.3`, `OD 0.5`, `OD 0.8`, `OD 1.0`, `OD 4.0` KTL Keywords Used: - `kpfcal.ND2POS` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): keyword = ktl . cache ( 'kpfcal' , 'ND2POS' ) allowed_values = list ( keyword . _getEnumerators ()) if 'Unknown' in allowed_values : allowed_values . pop ( allowed_values . index ( 'Unknown' )) check_input ( args , 'CalND2' , allowed_values = allowed_values ) return True @classmethod def perform ( cls , args , logger , cfg ): target = args . get ( 'CalND2' ) timeout = cfg . getfloat ( 'times' , 'nd_move_time' , fallback = 20 ) expr = f \"($kpfcal.ND2POS == ' { target } ')\" success = ktl . waitFor ( expr , timeout = timeout ) if success is False : log . error ( f \"Timed out waiting for ND2 filter wheel\" ) @classmethod def post_condition ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'times' , 'nd_move_time' , fallback = 20 ) ND2target = args . get ( 'CalND2' ) ND2POS = ktl . cache ( 'kpfcal' , 'ND2POS' ) if ND2POS . waitFor ( f \"== ' { ND2target } '\" , timeout = timeout ) == False : raise FailedToReachDestination ( ND2POS . read (), ND2target ) @classmethod def add_cmdline_args ( cls , parser , cfg = None ): parser . add_argument ( 'CalND2' , type = str , choices = [ \"OD 0.1\" , \"OD 0.3\" , \"OD 0.5\" , \"OD 0.8\" , \"OD 1.0\" , \"OD 4.0\" ], help = 'ND2 Filter to use.' ) return super () . add_cmdline_args ( parser , cfg )","title":"Description"},{"location":"scripts/WaitForReadout/","text":"WaitForReadout Bases: KPFTranslatorFunction Waits for the kpfexpose.EXPOSE keyword to be \"Readout\". This will block until the camera enters the readout state. ARGS: None Source code in kpf/spectrograph/WaitForReadout.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class WaitForReadout ( KPFTranslatorFunction ): '''Waits for the `kpfexpose.EXPOSE` keyword to be \"Readout\". This will block until the camera enters the readout state. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) exptime = kpfexpose [ 'EXPOSURE' ] . read ( binary = True ) starting_status = kpfexpose [ 'EXPOSE' ] . read ( binary = True ) detectors = kpfexpose [ 'TRIG_TARG' ] . read () detector_list = detectors . split ( ',' ) buffer_time = cfg . getfloat ( 'times' , 'readout_buffer_time' , fallback = 10 ) wait_time = exptime + buffer_time if starting_status < 3 else buffer_time wait_logic_steps = [ '($kpfexpose.EXPOSE == 4)' ] if 'Green' in detector_list : wait_logic_steps . append ( \"($kpfgreen.EXPSTATE == 4)\" ) if 'Red' in detector_list : wait_logic_steps . append ( \"($kpfred.EXPSTATE == 4)\" ) if 'Ca_HK' in detector_list : wait_logic_steps . append ( \"($kpf_hk.EXPSTATE == 4)\" ) wait_logic = ' and ' . join ( wait_logic_steps ) log . debug ( f \"Waiting ( { wait_time : .0f } s max) for readout to begin\" ) success = ktl . waitFor ( wait_logic , timeout = wait_time ) if success is True : log . debug ( f 'kpfexpose is { kpfexpose [ \"EXPOSE\" ] . read () } ' ) if 'Green' in detector_list : nextfile = ktl . cache ( 'kpfgreen' , 'NEXTFILE' ) log . debug ( f \"Green nextfile: { nextfile . read () } \" ) if 'Red' in detector_list : nextfile = ktl . cache ( 'kpfred' , 'NEXTFILE' ) log . debug ( f \"Red nextfile: { nextfile . read () } \" ) else : log . warning ( 'WaitForReadout failed to reach expected state' ) log . debug ( f 'kpfexpose is { kpfexpose [ \"EXPOSE\" ] . read () } ' ) log . debug ( f 'kpfexpose EXPLAINR = { kpfexpose [ \"EXPLAINR\" ] . read () } ' ) log . debug ( f 'kpfexpose EXPLAINNR = { kpfexpose [ \"EXPLAINNR\" ] . read () } ' ) RecoverDetectors . execute ({}) @classmethod def post_condition ( cls , args , logger , cfg ): expr = \"($kpfexpose.EXPOSE == 'Ready') or ($kpfexpose.EXPOSE == 'Readout')\" timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) ok = ktl . waitFor ( expr , timeout = timeout ) if ok is not True : expose = ktl . cache ( 'kpfexpose' , 'EXPOSE' ) raise FailedPostCondition ( f \"kpfexpose.EXPOSE= { expose . read () } is not Ready or Readout\" )","title":"WaitForReadout"},{"location":"scripts/WaitForReadout/#waitforreadout","text":"Bases: KPFTranslatorFunction Waits for the kpfexpose.EXPOSE keyword to be \"Readout\". This will block until the camera enters the readout state.","title":"WaitForReadout"},{"location":"scripts/WaitForReadout/#kpf.spectrograph.WaitForReadout.WaitForReadout--args","text":"None Source code in kpf/spectrograph/WaitForReadout.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class WaitForReadout ( KPFTranslatorFunction ): '''Waits for the `kpfexpose.EXPOSE` keyword to be \"Readout\". This will block until the camera enters the readout state. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) exptime = kpfexpose [ 'EXPOSURE' ] . read ( binary = True ) starting_status = kpfexpose [ 'EXPOSE' ] . read ( binary = True ) detectors = kpfexpose [ 'TRIG_TARG' ] . read () detector_list = detectors . split ( ',' ) buffer_time = cfg . getfloat ( 'times' , 'readout_buffer_time' , fallback = 10 ) wait_time = exptime + buffer_time if starting_status < 3 else buffer_time wait_logic_steps = [ '($kpfexpose.EXPOSE == 4)' ] if 'Green' in detector_list : wait_logic_steps . append ( \"($kpfgreen.EXPSTATE == 4)\" ) if 'Red' in detector_list : wait_logic_steps . append ( \"($kpfred.EXPSTATE == 4)\" ) if 'Ca_HK' in detector_list : wait_logic_steps . append ( \"($kpf_hk.EXPSTATE == 4)\" ) wait_logic = ' and ' . join ( wait_logic_steps ) log . debug ( f \"Waiting ( { wait_time : .0f } s max) for readout to begin\" ) success = ktl . waitFor ( wait_logic , timeout = wait_time ) if success is True : log . debug ( f 'kpfexpose is { kpfexpose [ \"EXPOSE\" ] . read () } ' ) if 'Green' in detector_list : nextfile = ktl . cache ( 'kpfgreen' , 'NEXTFILE' ) log . debug ( f \"Green nextfile: { nextfile . read () } \" ) if 'Red' in detector_list : nextfile = ktl . cache ( 'kpfred' , 'NEXTFILE' ) log . debug ( f \"Red nextfile: { nextfile . read () } \" ) else : log . warning ( 'WaitForReadout failed to reach expected state' ) log . debug ( f 'kpfexpose is { kpfexpose [ \"EXPOSE\" ] . read () } ' ) log . debug ( f 'kpfexpose EXPLAINR = { kpfexpose [ \"EXPLAINR\" ] . read () } ' ) log . debug ( f 'kpfexpose EXPLAINNR = { kpfexpose [ \"EXPLAINNR\" ] . read () } ' ) RecoverDetectors . execute ({}) @classmethod def post_condition ( cls , args , logger , cfg ): expr = \"($kpfexpose.EXPOSE == 'Ready') or ($kpfexpose.EXPOSE == 'Readout')\" timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) ok = ktl . waitFor ( expr , timeout = timeout ) if ok is not True : expose = ktl . cache ( 'kpfexpose' , 'EXPOSE' ) raise FailedPostCondition ( f \"kpfexpose.EXPOSE= { expose . read () } is not Ready or Readout\" )","title":"ARGS:"},{"location":"scripts/WaitForReady/","text":"WaitForReady Bases: KPFTranslatorFunction Waits for the kpfexpose.EXPOSE keyword to be \"Ready\". This will block until the camera is ready for another exposure. Times out after waiting for exposure time plus a set buffer time. ARGS: None Source code in kpf/spectrograph/WaitForReady.py 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class WaitForReady ( KPFTranslatorFunction ): '''Waits for the `kpfexpose.EXPOSE` keyword to be \"Ready\". This will block until the camera is ready for another exposure. Times out after waiting for exposure time plus a set buffer time. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) exptime = kpfexpose [ 'EXPOSURE' ] . read ( binary = True ) starting_status = kpfexpose [ 'EXPOSE' ] . read ( binary = True ) detectors = kpfexpose [ 'TRIG_TARG' ] . read () detector_list = detectors . split ( ',' ) buffer_time = cfg . getfloat ( 'times' , 'readout_buffer_time' , fallback = 10 ) read_times = [ cfg . getfloat ( 'time_estimates' , 'readout_red' , fallback = 60 ), cfg . getfloat ( 'time_estimates' , 'readout_green' , fallback = 60 ), cfg . getfloat ( 'time_estimates' , 'readout_cahk' , fallback = 1 ), cfg . getfloat ( 'time_estimates' , 'readout_expmeter' , fallback = 1 ), ] slowest_read = max ( read_times ) wait_time = exptime + slowest_read + buffer_time if starting_status < 3 else slowest_read + buffer_time wait_logic_steps = [ '($kpfexpose.EXPOSE == 0)' ] if 'Green' in detector_list : wait_logic_steps . append ( \"($kpfgreen.EXPSTATE == 0)\" ) if 'Red' in detector_list : wait_logic_steps . append ( \"($kpfred.EXPSTATE == 0)\" ) if 'Ca_HK' in detector_list : wait_logic_steps . append ( \"($kpf_hk.EXPSTATE == 0)\" ) wait_logic = ' and ' . join ( wait_logic_steps ) log . debug ( f \"Waiting ( { wait_time : .0f } s max) for detectors to be ready\" ) success = ktl . waitFor ( wait_logic , timeout = wait_time ) if success is True : log . debug ( f 'kpfexpose is { kpfexpose [ \"EXPOSE\" ] . read () } ' ) else : log . warning ( 'WaitForReady failed to reach expected state' ) log . debug ( f 'kpfexpose is { kpfexpose [ \"EXPOSE\" ] . read () } ' ) log . debug ( f 'kpfexpose EXPLAINR = { kpfexpose [ \"EXPLAINR\" ] . read () } ' ) log . debug ( f 'kpfexpose EXPLAINNR = { kpfexpose [ \"EXPLAINNR\" ] . read () } ' ) if kpfexpose [ 'EXPOSE' ] . read () == 'Readout' : # Readout errors are handled in kpfred and kpfgreen services. # Just wait some extra time for that to recover the system. success = ktl . waitFor ( wait_logic , timeout = wait_time ) else : RecoverDetectors . execute ({}) @classmethod def post_condition ( cls , args , logger , cfg ): expr = \"($kpfexpose.EXPOSE == 'Ready')\" timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) ok = ktl . waitFor ( expr , timeout = timeout ) if ok is not True : expose = ktl . cache ( 'kpfexpose' , 'EXPOSE' ) raise FailedPostCondition ( f \"kpfexpose.EXPOSE= { expose . read () } is not Ready\" )","title":"WaitForReady"},{"location":"scripts/WaitForReady/#waitforready","text":"Bases: KPFTranslatorFunction Waits for the kpfexpose.EXPOSE keyword to be \"Ready\". This will block until the camera is ready for another exposure. Times out after waiting for exposure time plus a set buffer time.","title":"WaitForReady"},{"location":"scripts/WaitForReady/#kpf.spectrograph.WaitForReady.WaitForReady--args","text":"None Source code in kpf/spectrograph/WaitForReady.py 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class WaitForReady ( KPFTranslatorFunction ): '''Waits for the `kpfexpose.EXPOSE` keyword to be \"Ready\". This will block until the camera is ready for another exposure. Times out after waiting for exposure time plus a set buffer time. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): kpfexpose = ktl . cache ( 'kpfexpose' ) exptime = kpfexpose [ 'EXPOSURE' ] . read ( binary = True ) starting_status = kpfexpose [ 'EXPOSE' ] . read ( binary = True ) detectors = kpfexpose [ 'TRIG_TARG' ] . read () detector_list = detectors . split ( ',' ) buffer_time = cfg . getfloat ( 'times' , 'readout_buffer_time' , fallback = 10 ) read_times = [ cfg . getfloat ( 'time_estimates' , 'readout_red' , fallback = 60 ), cfg . getfloat ( 'time_estimates' , 'readout_green' , fallback = 60 ), cfg . getfloat ( 'time_estimates' , 'readout_cahk' , fallback = 1 ), cfg . getfloat ( 'time_estimates' , 'readout_expmeter' , fallback = 1 ), ] slowest_read = max ( read_times ) wait_time = exptime + slowest_read + buffer_time if starting_status < 3 else slowest_read + buffer_time wait_logic_steps = [ '($kpfexpose.EXPOSE == 0)' ] if 'Green' in detector_list : wait_logic_steps . append ( \"($kpfgreen.EXPSTATE == 0)\" ) if 'Red' in detector_list : wait_logic_steps . append ( \"($kpfred.EXPSTATE == 0)\" ) if 'Ca_HK' in detector_list : wait_logic_steps . append ( \"($kpf_hk.EXPSTATE == 0)\" ) wait_logic = ' and ' . join ( wait_logic_steps ) log . debug ( f \"Waiting ( { wait_time : .0f } s max) for detectors to be ready\" ) success = ktl . waitFor ( wait_logic , timeout = wait_time ) if success is True : log . debug ( f 'kpfexpose is { kpfexpose [ \"EXPOSE\" ] . read () } ' ) else : log . warning ( 'WaitForReady failed to reach expected state' ) log . debug ( f 'kpfexpose is { kpfexpose [ \"EXPOSE\" ] . read () } ' ) log . debug ( f 'kpfexpose EXPLAINR = { kpfexpose [ \"EXPLAINR\" ] . read () } ' ) log . debug ( f 'kpfexpose EXPLAINNR = { kpfexpose [ \"EXPLAINNR\" ] . read () } ' ) if kpfexpose [ 'EXPOSE' ] . read () == 'Readout' : # Readout errors are handled in kpfred and kpfgreen services. # Just wait some extra time for that to recover the system. success = ktl . waitFor ( wait_logic , timeout = wait_time ) else : RecoverDetectors . execute ({}) @classmethod def post_condition ( cls , args , logger , cfg ): expr = \"($kpfexpose.EXPOSE == 'Ready')\" timeout = cfg . getfloat ( 'times' , 'kpfexpose_reset_time' , fallback = 10 ) ok = ktl . waitFor ( expr , timeout = timeout ) if ok is not True : expose = ktl . cache ( 'kpfexpose' , 'EXPOSE' ) raise FailedPostCondition ( f \"kpfexpose.EXPOSE= { expose . read () } is not Ready\" )","title":"ARGS:"},{"location":"scripts/WaitForSoCalOnTarget/","text":"WaitForSoCalOnTarget Bases: KPFTranslatorFunction Returns True if, within a set timeout, a set of conditions which suggest that SoCal is on the Sun accurately evaluate to True. ARGS: None Source code in kpf/socal/WaitForSoCalOnTarget.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class WaitForSoCalOnTarget ( KPFTranslatorFunction ): '''Returns True if, within a set timeout, a set of conditions which suggest that SoCal is on the Sun accurately evaluate to True. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'SoCal' , 'enclosure_status_time' , fallback = 10 ) pyrirrad_threshold = cfg . getfloat ( 'SoCal' , 'pyrirrad_threshold' , fallback = 1000 ) expr = '($kpfsocal.ENCSTA == 0) ' expr += 'and ($kpfsocal.EKOONLINE == Online)' expr += 'and ($kpfsocal.EKOMODE == 3)' expr += f 'and ($kpfsocal.PYRIRRAD > { pyrirrad_threshold } )' expr += 'and ($kpfsocal.AUTONOMOUS == 1)' expr += 'and ($kpfsocal.CAN_OPEN == True)' expr += 'and ($kpfsocal.IS_OPEN == True)' expr += 'and ($kpfsocal.IS_TRACKING == True)' expr += 'and ($kpfsocal.ONLINE == True)' expr += 'and ($kpfsocal.STATE == Tracking)' on_target = ktl . waitFor ( expr , timeout = timeout ) msg = { True : 'On Target' , False : 'NOT On Target' }[ on_target ] print ( msg ) if on_target == False : kpfsocal = ktl . cache ( 'kpfsocal' ) if kpfsocal [ 'ENCSTA' ] . read ( binary = True ) != 0 : log . debug ( f 'ENCSTA != 0' ) if kpfsocal [ 'EKOONLINE' ] . read () != 'Online' : log . debug ( f 'EKOONLINE != Online' ) if kpfsocal [ 'EKOMODE' ] . read ( binary = True ) != 3 : log . debug ( f 'EKOMODE != 3' ) if kpfsocal [ 'PYRIRRAD' ] . read ( binary = True ) < pyrirrad_threshold : log . debug ( f 'PYRIRRAD < { pyrirrad_threshold } ' ) if kpfsocal [ 'AUTONOMOUS' ] . read ( binary = True ) != 1 : log . debug ( f 'AUTONOMOUS != 1' ) if kpfsocal [ 'IS_OPEN' ] . read ( binary = True ) != True : log . debug ( f 'IS_OPEN != True' ) if kpfsocal [ 'IS_TRACKING' ] . read ( binary = True ) != True : log . debug ( f 'IS_TRACKING != True' ) if kpfsocal [ 'ONLINE' ] . read ( binary = True ) != True : log . debug ( f 'ONLINE != True' ) if kpfsocal [ 'STATE' ] . read () != 'Tracking' : log . debug ( f 'STATE != Tracking' ) return on_target @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"WaitForSoCalOnTarget"},{"location":"scripts/WaitForSoCalOnTarget/#waitforsocalontarget","text":"Bases: KPFTranslatorFunction Returns True if, within a set timeout, a set of conditions which suggest that SoCal is on the Sun accurately evaluate to True.","title":"WaitForSoCalOnTarget"},{"location":"scripts/WaitForSoCalOnTarget/#kpf.socal.WaitForSoCalOnTarget.WaitForSoCalOnTarget--args","text":"None Source code in kpf/socal/WaitForSoCalOnTarget.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 class WaitForSoCalOnTarget ( KPFTranslatorFunction ): '''Returns True if, within a set timeout, a set of conditions which suggest that SoCal is on the Sun accurately evaluate to True. ARGS: ===== None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): timeout = cfg . getfloat ( 'SoCal' , 'enclosure_status_time' , fallback = 10 ) pyrirrad_threshold = cfg . getfloat ( 'SoCal' , 'pyrirrad_threshold' , fallback = 1000 ) expr = '($kpfsocal.ENCSTA == 0) ' expr += 'and ($kpfsocal.EKOONLINE == Online)' expr += 'and ($kpfsocal.EKOMODE == 3)' expr += f 'and ($kpfsocal.PYRIRRAD > { pyrirrad_threshold } )' expr += 'and ($kpfsocal.AUTONOMOUS == 1)' expr += 'and ($kpfsocal.CAN_OPEN == True)' expr += 'and ($kpfsocal.IS_OPEN == True)' expr += 'and ($kpfsocal.IS_TRACKING == True)' expr += 'and ($kpfsocal.ONLINE == True)' expr += 'and ($kpfsocal.STATE == Tracking)' on_target = ktl . waitFor ( expr , timeout = timeout ) msg = { True : 'On Target' , False : 'NOT On Target' }[ on_target ] print ( msg ) if on_target == False : kpfsocal = ktl . cache ( 'kpfsocal' ) if kpfsocal [ 'ENCSTA' ] . read ( binary = True ) != 0 : log . debug ( f 'ENCSTA != 0' ) if kpfsocal [ 'EKOONLINE' ] . read () != 'Online' : log . debug ( f 'EKOONLINE != Online' ) if kpfsocal [ 'EKOMODE' ] . read ( binary = True ) != 3 : log . debug ( f 'EKOMODE != 3' ) if kpfsocal [ 'PYRIRRAD' ] . read ( binary = True ) < pyrirrad_threshold : log . debug ( f 'PYRIRRAD < { pyrirrad_threshold } ' ) if kpfsocal [ 'AUTONOMOUS' ] . read ( binary = True ) != 1 : log . debug ( f 'AUTONOMOUS != 1' ) if kpfsocal [ 'IS_OPEN' ] . read ( binary = True ) != True : log . debug ( f 'IS_OPEN != True' ) if kpfsocal [ 'IS_TRACKING' ] . read ( binary = True ) != True : log . debug ( f 'IS_TRACKING != True' ) if kpfsocal [ 'ONLINE' ] . read ( binary = True ) != True : log . debug ( f 'ONLINE != True' ) if kpfsocal [ 'STATE' ] . read () != 'Tracking' : log . debug ( f 'STATE != Tracking' ) return on_target @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"ARGS:"},{"location":"scripts/WaitForTipTilt/","text":"WaitForTipTilt Bases: KPFTranslatorFunction Dumb versions which simply waits for a few seconds. Source code in kpf/fiu/WaitForTipTilt.py 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class WaitForTipTilt ( KPFTranslatorFunction ): '''Dumb versions which simply waits for a few seconds. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): loop_close_time = cfg . getfloat ( 'times' , 'tip_tilt_close_time' , fallback = 3 ) time . sleep ( loop_close_time ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"WaitForTipTilt"},{"location":"scripts/WaitForTipTilt/#waitfortiptilt","text":"Bases: KPFTranslatorFunction Dumb versions which simply waits for a few seconds. Source code in kpf/fiu/WaitForTipTilt.py 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class WaitForTipTilt ( KPFTranslatorFunction ): '''Dumb versions which simply waits for a few seconds. ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): loop_close_time = cfg . getfloat ( 'times' , 'tip_tilt_close_time' , fallback = 3 ) time . sleep ( loop_close_time ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"WaitForTipTilt"},{"location":"scripts/WaitForTriggerFile/","text":"WaitForTriggerFile Bases: KPFTranslatorFunction Wait for a trigger file in progress to finish being collected. KTL Keywords Used: kpfguide.LASTTRIGFILE Source code in kpf/guider/WaitForTriggerFile.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 class WaitForTriggerFile ( KPFTranslatorFunction ): '''Wait for a trigger file in progress to finish being collected. KTL Keywords Used: - `kpfguide.LASTTRIGFILE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'initial_lastfile' ) @classmethod def perform ( cls , args , logger , cfg ): initial_lastfile = args . get ( 'initial_lastfile' , False ) kpfguide = ktl . cache ( 'kpfguide' ) log . debug ( f \"Waiting for guider trigger file to be written out\" ) # Wait for cube file to be updated expr = f \"$kpfguide.LASTTRIGFILE != ' { initial_lastfile } '\" success = ktl . waitFor ( expr , timeout = 20 ) cube_file = kpfguide [ 'LASTTRIGFILE' ] . read () log . info ( f \"New cube file: { cube_file } \" ) return cube_file @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"WaitForTriggerFile"},{"location":"scripts/WaitForTriggerFile/#waitfortriggerfile","text":"Bases: KPFTranslatorFunction Wait for a trigger file in progress to finish being collected. KTL Keywords Used: kpfguide.LASTTRIGFILE Source code in kpf/guider/WaitForTriggerFile.py 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 class WaitForTriggerFile ( KPFTranslatorFunction ): '''Wait for a trigger file in progress to finish being collected. KTL Keywords Used: - `kpfguide.LASTTRIGFILE` ''' @classmethod def pre_condition ( cls , args , logger , cfg ): check_input ( args , 'initial_lastfile' ) @classmethod def perform ( cls , args , logger , cfg ): initial_lastfile = args . get ( 'initial_lastfile' , False ) kpfguide = ktl . cache ( 'kpfguide' ) log . debug ( f \"Waiting for guider trigger file to be written out\" ) # Wait for cube file to be updated expr = f \"$kpfguide.LASTTRIGFILE != ' { initial_lastfile } '\" success = ktl . waitFor ( expr , timeout = 20 ) cube_file = kpfguide [ 'LASTTRIGFILE' ] . read () log . info ( f \"New cube file: { cube_file } \" ) return cube_file @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"WaitForTriggerFile"},{"location":"scripts/ZeroOutSlewCalTime/","text":"ZeroOutSlewCalTime Bases: KPFTranslatorFunction Zero out the slew cal timer by setting it to the current timestamp. ARGS None Source code in kpf/utils/ZeroOutSlewCalTime.py 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class ZeroOutSlewCalTime ( KPFTranslatorFunction ): '''Zero out the slew cal timer by setting it to the current timestamp. ### ARGS None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): log . debug ( 'Updating LASTSLEWCAL time stamp to reset slew cal timer' ) ktl . write ( 'kpfconfig' , 'LASTSLEWCAL' , time . time (), binary = True ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"ZeroOutSlewCalTime"},{"location":"scripts/ZeroOutSlewCalTime/#zerooutslewcaltime","text":"Bases: KPFTranslatorFunction Zero out the slew cal timer by setting it to the current timestamp.","title":"ZeroOutSlewCalTime"},{"location":"scripts/ZeroOutSlewCalTime/#kpf.utils.ZeroOutSlewCalTime.ZeroOutSlewCalTime--args","text":"None Source code in kpf/utils/ZeroOutSlewCalTime.py 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class ZeroOutSlewCalTime ( KPFTranslatorFunction ): '''Zero out the slew cal timer by setting it to the current timestamp. ### ARGS None ''' @classmethod def pre_condition ( cls , args , logger , cfg ): pass @classmethod def perform ( cls , args , logger , cfg ): log . debug ( 'Updating LASTSLEWCAL time stamp to reset slew cal timer' ) ktl . write ( 'kpfconfig' , 'LASTSLEWCAL' , time . time (), binary = True ) @classmethod def post_condition ( cls , args , logger , cfg ): pass","title":"ARGS"},{"location":"scripts/scripts/","text":"Scripts kpf.ao ControlAOHatch SendPCUtoHome SendPCUtoKPF SetAFMtoMirror SetAFStoNGS SetAODCStoSIM SetAORotator SetAORotatorManual SetupAOforACAM SetupAOforKPF TurnHepaOff TurnHepaOn TurnLightSourceOff kpf.cahk PowerCycleCaHK kpf.calbench CalLampPower IsCalSourceEnabled PredictNDFilters SetCalSource SetFlatFieldFiberPos SetLFCtoAstroComb SetLFCtoStandbyHigh SetND SetND1 SetND2 TakeIntensityReading WaitForCalSource WaitForFlatFieldFiberPos WaitForLampWarm WaitForLFCReady WaitForND WaitForND1 WaitForND2 kpf.engineering GridSearch ImageBackIlluminatedFibers Run2DGridSearch TakeADCGridData TakeADCOffsetGridData TakeGuiderSensitivityData TriggerGreenMiniFill TriggerRedMiniFill AnalyzeGridSearch AnalyzeTipTiltPerformance Fit2DGridSearch CountCameraErrors kpf.expmeter BuildMasterBias SetExpMeterExpTime SetExpMeterTerminationParameters PredictExpMeterParameters SetMasterBiasToDefault SetupExpMeter TakeExpMeterBiases kpf.fiu ConfigureFIU ControlFoldMirror ControlHatch InitializeTipTilt LockFIU UnlockFIU MeasureTipTiltMirrorRange SetADCAngles SetADCOffsets SetTipTiltCalculations SetTipTiltControl SetTipTiltGain SetTipTiltPosition SetTipTiltTargetPixel ShutdownTipTilt StartTipTilt StopTipTilt TestTipTiltMirrorRange VerifyCurrentBase WaitForConfigureFIU WaitForTipTilt kpf.fvc FVCPower PredictFVCParameters TakeFVCContinuous TakeFVCExposure SetFVCExpTime kpf.guider DisplayGuiderContinuous GetGaiaStars GuiderLastfile GuiderOutdir PredictGuiderParameters SetGuiderExpTime SetGuiderFPS SetGuiderGain SetGuiderOutdir StartGuiderContinuous StartTriggerFile StopGuiderContinuous StopTriggerFile TakeGuiderCube TakeGuiderExposure WaitForTriggerFile kpf.scripts CleanupAfterCalibrations CleanupAfterScience CollectGuiderDarkCubes ConfigureForAcquisition ConfigureForCalibrations ConfigureForScience EndOfNight EnterLowPowerMode ExecuteSlewCal RecoverFromLowPowerMode RunCalOB RunSciOB RunSoCalObservingLoop RunTwilightRVStandard StartOfNight StartUp WaitForConfigureCalibrations kpf.socal DisableSoCal EnableSoCal IsSoCalClosed IsSoCalOpen IsSoCalShutDown ParkSoCal SoCalStartAutonomous SoCalStopAutonomous WaitForSoCalOnTarget kpf.spectrograph QueryReadMode QueryFastReadMode RecoverDetectors ResetCaHKDetector ResetExpMeterDetector ResetGreenDetector ResetRedDetector ResetDetectors SetExpTime SetObject SetObserver SetProgram SetReadModeFast SetReadModeNormal SetSourceSelectShutters SetTimedShutters SetTriggeredDetectors StartAgitator StartExposure StopAgitator WaitForL0File WaitForReadout WaitForReady kpf.utils BuildOBfromQuery CalculateDAR CheckDewarWeights CorrectDAR EstimateOBDuration SetObserverFromSchedule SetOutdirs SetSimulCalSource SetTargetInfo StartGUIs StopGUIs ZeroOutSlewCalTime","title":"Operations Scripts"},{"location":"scripts/scripts/#scripts","text":"kpf.ao ControlAOHatch SendPCUtoHome SendPCUtoKPF SetAFMtoMirror SetAFStoNGS SetAODCStoSIM SetAORotator SetAORotatorManual SetupAOforACAM SetupAOforKPF TurnHepaOff TurnHepaOn TurnLightSourceOff kpf.cahk PowerCycleCaHK kpf.calbench CalLampPower IsCalSourceEnabled PredictNDFilters SetCalSource SetFlatFieldFiberPos SetLFCtoAstroComb SetLFCtoStandbyHigh SetND SetND1 SetND2 TakeIntensityReading WaitForCalSource WaitForFlatFieldFiberPos WaitForLampWarm WaitForLFCReady WaitForND WaitForND1 WaitForND2 kpf.engineering GridSearch ImageBackIlluminatedFibers Run2DGridSearch TakeADCGridData TakeADCOffsetGridData TakeGuiderSensitivityData TriggerGreenMiniFill TriggerRedMiniFill AnalyzeGridSearch AnalyzeTipTiltPerformance Fit2DGridSearch CountCameraErrors kpf.expmeter BuildMasterBias SetExpMeterExpTime SetExpMeterTerminationParameters PredictExpMeterParameters SetMasterBiasToDefault SetupExpMeter TakeExpMeterBiases kpf.fiu ConfigureFIU ControlFoldMirror ControlHatch InitializeTipTilt LockFIU UnlockFIU MeasureTipTiltMirrorRange SetADCAngles SetADCOffsets SetTipTiltCalculations SetTipTiltControl SetTipTiltGain SetTipTiltPosition SetTipTiltTargetPixel ShutdownTipTilt StartTipTilt StopTipTilt TestTipTiltMirrorRange VerifyCurrentBase WaitForConfigureFIU WaitForTipTilt kpf.fvc FVCPower PredictFVCParameters TakeFVCContinuous TakeFVCExposure SetFVCExpTime kpf.guider DisplayGuiderContinuous GetGaiaStars GuiderLastfile GuiderOutdir PredictGuiderParameters SetGuiderExpTime SetGuiderFPS SetGuiderGain SetGuiderOutdir StartGuiderContinuous StartTriggerFile StopGuiderContinuous StopTriggerFile TakeGuiderCube TakeGuiderExposure WaitForTriggerFile kpf.scripts CleanupAfterCalibrations CleanupAfterScience CollectGuiderDarkCubes ConfigureForAcquisition ConfigureForCalibrations ConfigureForScience EndOfNight EnterLowPowerMode ExecuteSlewCal RecoverFromLowPowerMode RunCalOB RunSciOB RunSoCalObservingLoop RunTwilightRVStandard StartOfNight StartUp WaitForConfigureCalibrations kpf.socal DisableSoCal EnableSoCal IsSoCalClosed IsSoCalOpen IsSoCalShutDown ParkSoCal SoCalStartAutonomous SoCalStopAutonomous WaitForSoCalOnTarget kpf.spectrograph QueryReadMode QueryFastReadMode RecoverDetectors ResetCaHKDetector ResetExpMeterDetector ResetGreenDetector ResetRedDetector ResetDetectors SetExpTime SetObject SetObserver SetProgram SetReadModeFast SetReadModeNormal SetSourceSelectShutters SetTimedShutters SetTriggeredDetectors StartAgitator StartExposure StopAgitator WaitForL0File WaitForReadout WaitForReady kpf.utils BuildOBfromQuery CalculateDAR CheckDewarWeights CorrectDAR EstimateOBDuration SetObserverFromSchedule SetOutdirs SetSimulCalSource SetTargetInfo StartGUIs StopGUIs ZeroOutSlewCalTime","title":"Scripts"}]} \ No newline at end of file diff --git a/status/index.html b/status/index.html index 03f4b889..a8067c81 100644 --- a/status/index.html +++ b/status/index.html @@ -225,18 +225,18 @@

Instrument Status

KPF has been commissioned on sky, and is available for use. Many aspects of the instrument are still being optimized and the long term stability is still under evaluation. Short term stability looks excellent (exceeding the 50 cm/s target spec within a night) and we expect measures of the long term RV precision to become available as the DRP evolves.

A detailed summary of the instrument status was presented at the September 2023 Keck Science Meeting. The slides from that presentation are available in PDF format.

-

Important Notice: KPF will have a lengthy “servicing mission” during 24B to perform several upgrades. This will involve warm up of the optical bench. The expected timeline is to do this in November 2024. Details are still being worked out.

+

Important Notice: KPF will have a lengthy “servicing mission” during 24B to perform several upgrades. This will involve warm up of the detectors. The work is expected to commence around Oct 27 and be complete before Nov 24.

Subsystem Status

This is an attempt to summarize the status of various sub-systems of the instrument. Each sub-system name is color coded to indicate the status at a glance: green means functioning normally, orange means mostly normal, but with some caveats or minor issues, and red means the sub-system is compromised in some way.