Source code for pyEDITH.cli

from pyEDITH import AstrophysicalScene, Observation, Observatory
from pyEDITH import calculate_exposure_time_or_snr, parse_input
from argparse import ArgumentParser
import numpy as np
from .units import *
import sys
from . import set_verbosity
import os
import logging

logger = logging.getLogger("pyEDITH")

# Declare the environment variable
# os.environ["SCI_ENG_DIR"] = "/path/to/Sci-Eng-Interface/hwo_sci_eng"


[docs] def main(): """ Main entry point for the py-E.D.I.T.H. command-line interface. This function sets up the argument parser and handles the execution of different subcommands: etc (Exposure Time Calculator), snr (Signal-to-Noise Ratio), and etc2snr (Exposure Time to Signal-to-Noise Ratio). The function reads configuration from .edith files and calls the appropriate calculation functions based on the subcommand. Raises ------ SyntaxError If required command-line arguments are missing TypeError If multiple wavelengths are provided for primary lambda in etc2snr mode ValueError If secondary parameters are not specified in etc2snr mode or if the returned exposure time is infinity """ parent_parser = ArgumentParser(add_help=False) parent_parser.add_argument( "-v", "--verbose", action="count", default=0, help="Increase verbosity: -v for INFO, -vv for DEBUG logs with detailed output", ) parent_parser.add_argument( "-q", "--quiet", action="store_true", help="Quiet mode, only show errors" ) parser = ArgumentParser( description="Available command line arguments for E.D.I.T.H.", ) parser.add_argument( "-v", "--verbose", action="count", default=0, help="Increase verbosity: -v for INFO, -vv for DEBUG logs with detailed output", ) parser.add_argument( "-q", "--quiet", action="store_true", help="Quiet mode, only show errors" ) subparsers = parser.add_subparsers( dest="subfunction", help="Subfunction to execute" ) parser_a = subparsers.add_parser( "etc", help="Exposure Time Calculator for a specific lambda (in .edith file)" ) parser_a.add_argument("--edith", type=str, help="an .edith file") parser_b = subparsers.add_parser( "snr", help="SNR calculator for a specific lambda (in .edith file) and for a given \ exposure time (argument, in seconds)", ) parser_b.add_argument("--edith", type=str, help="an .edith file") parser_b.add_argument( "--time", type=float, help="the desired observing time in seconds" ) parser_c = subparsers.add_parser( "etc2snr", help="SNR calculator for a secondary lambda based on an exposure file \ calculated on a primary lambda (in .edith file)", ) parser_c.add_argument("--edith", type=str, help="an .edith file") args = parser.parse_args() if args.quiet: set_verbosity("error") elif args.verbose == 0: set_verbosity("warning") # Default elif args.verbose == 1: set_verbosity("info") # -v else: # args.verbose >= 2 set_verbosity("debug") # -vv, -vvv, etc. if args.subfunction == "etc": if not args.edith: raise SyntaxError("--edith argument is required for etc subfunction.") parameters, _ = parse_input.read_configuration(args.edith) texp, _ = calculate_texp(parameters) print(texp) elif args.subfunction == "snr": if not args.edith or args.time is None: raise SyntaxError( "Both --edith and --time arguments are required for snr subfunction." ) parameters, _ = parse_input.read_configuration(args.edith) texp = args.time * TIME snr, _ = calculate_snr(parameters, texp) print(snr) elif args.subfunction == "etc2snr": if not args.edith: raise SyntaxError("--edith argument is required for etc2snr subfunction.") parameters, secondary_parameters = parse_input.read_configuration( args.edith, secondary_flag=True ) if not secondary_parameters: raise ValueError("The secondary parameters are not specified.") if len(parameters["wavelength"]) > 1: raise TypeError("Cannot accept multiple lambdas as primary lambda") else: for key in parameters: if key not in secondary_parameters: secondary_parameters[key] = parameters[key] logger.info("Calculating texp from primary lambda") logger.info(parameters.keys()) texp, _ = calculate_texp(parameters) print("Reference exposure time: ", texp) if np.isfinite(texp).all(): logger.info("Calculating snr on secondary lambda") snr, _ = calculate_snr(secondary_parameters, texp) print("SNR at the secondary lambda: ", snr) else: raise ValueError("Returned exposure time is infinity.") else: parser.print_help()
[docs] def calculate_texp(parameters: dict, ETC_validation: bool = False) -> np.array: """ Calculate exposure time for a planet observation with specified parameters. This function initializes Observation, AstrophysicalScene, and Observatory objects with the provided parameters, then calculates the required exposure time to achieve the specified signal-to-noise ratio at each wavelength. Parameters ---------- parameters : dict Dictionary containing all input parameters for the calculation ETC_validation : bool, optional If True, use specific parameter values for validation against the ETC, default is False Returns ------- tuple A tuple containing: observation.exptime : numpy.ndarray Exposure time in hours for each wavelength observation.validation_variables : dict Validation variables containing intermediate calculation results """ # Define Observation and load relevant parameters observation = Observation() observation.load_configuration(parameters) observation.set_output_arrays() observation.validate_configuration() # Define Astrophysical Scene and load relevant parameters, # then calculate zodi/exozodi scene = AstrophysicalScene() scene.load_configuration(parameters) scene.calculate_zodi_exozodi(parameters) scene.validate_configuration() if ( parameters["observing_mode"] == "IFS" and parameters["regrid_wavelength"] is True ): scene.regrid_spectra(parameters, observation) # Create and configure Observatory observatory_config = parse_input.get_observatory_config(parameters) observatory = Observatory() observatory.create_observatory(observatory_config) observatory.load_configuration(parameters, observation, scene) observatory.validate_configuration() # EXPOSURE TIME CALCULATION calculate_exposure_time_or_snr( observation, scene, observatory, ETC_validation=ETC_validation, mode="exposure_time", ) return observation.exptime, observation.validation_variables
[docs] def calculate_snr(parameters: dict, reference_texp: float): """ Calculate signal-to-noise ratio for a given exposure time. This function initializes Observation, AstrophysicalScene, and Observatory objects with the provided parameters, then calculates the achievable signal-to-noise ratio for the specified exposure time at each wavelength. Parameters ---------- parameters : dict Dictionary containing all input parameters for the calculation reference_texp : float Reference exposure time in seconds Returns ------- tuple A tuple containing: observation.fullsnr : numpy.ndarray Signal-to-noise ratio for each wavelength observation.validation_variables : dict Validation variables containing intermediate calculation results """ # Define Observation and load relevant parameters observation = Observation() observation.load_configuration(parameters) observation.set_output_arrays() # Define Astrophysical Scene and load relevant parameters, # then calculate zodi/exozodi scene = AstrophysicalScene() scene.load_configuration(parameters) scene.calculate_zodi_exozodi(parameters) if ( parameters["observing_mode"] == "IFS" and parameters["regrid_wavelength"] is True ): scene.regrid_spectra(parameters, observation) # Create and configure Observatory observatory_config = parse_input.get_observatory_config(parameters) observatory = Observatory() observatory.create_observatory(observatory_config) observatory.load_configuration(parameters, observation, scene) observatory.validate_configuration() # SNR CALCULATION observation.obstime = reference_texp calculate_exposure_time_or_snr( observation, scene, observatory, mode="signal_to_noise" ) return observation.fullsnr, observation.validation_variables