Coverage for middlelayer / ngect / cli.py: 28.57%

42 statements  

« prev     ^ index     » next       coverage.py v7.13.4, created at 2026-03-16 06:04 +0000

1# -*- coding: utf-8 -*- 

2# Copyright 2023 Associated Universities, Inc. 

3# 

4# This file is part of ngVLA Exposure Calculator Tool (ngECT). 

5# 

6# ngECT is free software: you can redistribute it and/or modify 

7# it under the terms of the GNU General Public License as published by 

8# the Free Software Foundation, either version 3 of the License, or 

9# any later version. 

10# 

11# ngECT is distributed in the hope that it will be useful, 

12# but WITHOUT ANY WARRANTY; without even the implied warranty of 

13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

14# GNU General Public License for more details. 

15# 

16# You should have received a copy of the GNU General Public License 

17# along with ngECT. If not, see <https://www.gnu.org/licenses/>. 

18 

19"""ngect cli interface. adapted from the ngVLA subarray sensitivity and key performance metric calculator by V. Rosero.""" 

20 

21import argparse 

22import logging 

23import pickle 

24import sys 

25import textwrap 

26from pprint import pformat 

27 

28import numpy as np 

29from astropy import units as u 

30 

31from . import __version__, engine, system 

32 

33logger = logging.getLogger(__name__) 

34 

35 

36def cli_run(): 

37 """Entry point for the ngECT command-line interface. 

38 

39 Parses CLI arguments and delegates to :func:`calculate_sensitivity` to 

40 compute exposure metrics. This mirrors the historical 

41 ``ngVLA_sensitivity_calculator.py`` workflow for comparison purposes. 

42 

43 Examples 

44 -------- 

45 From a shell, compute sensitivities for a given setup: 

46 

47 >>> # doctest: +SKIP 

48 ... ngect_cli main+long 24.5 1 --t_obs 4 --delta_v 2e3 

49 """ 

50 

51 description = r""" 

52 ngect cli user interface, adapted from the ngVLA subarray sensitivity and key performance metric calculator by V. Rosero. 

53 

54 A comparison example: 

55 $ ngect_cli main+long 24.5 1 

56 vs. 

57 $ ./ngVLA_sensitivity_calculator.py main+long 24.5 1 

58 

59 They should give similar results. 

60 """ 

61 

62 subarray_help = ( 

63 r"""name of array (string): sba, core, spiral, mid, long, main, main+long, spiral+mid, spiral+core, mid+long""" 

64 ) 

65 

66 freq_help = r"""frequency in GHz(float): e.g., 24.5""" 

67 

68 theta_help = r"""resolution in arcsec(float or -1): e.g., 0.5. 

69 theta = -1 will calculate native resolution (natural, no taper)""" 

70 

71 t_obs_help = r"""on-source time in hours(float): e.g., 4. Default: 1""" 

72 

73 delta_v_help = r"""channel width in m/s(float): e.g., 2e3. Default: 10e3""" 

74 

75 parser = argparse.ArgumentParser( 

76 description=textwrap.dedent(description), formatter_class=argparse.RawDescriptionHelpFormatter 

77 ) 

78 parser.add_argument("subarray", type=str, help=subarray_help) 

79 parser.add_argument("frequency", type=float, help=freq_help) 

80 parser.add_argument("theta", type=float, help=theta_help) 

81 parser.add_argument("--t_obs", type=float, default=1.0, help=t_obs_help) 

82 parser.add_argument("--delta_v", type=float, default=10e3, help=delta_v_help) 

83 parser.add_argument("-v", "--verbose", help="increase output verbosity", action="store_true") 

84 args = parser.parse_args() 

85 

86 calculate_sensitivity(args.subarray, args.frequency, args.theta, args.t_obs, args.delta_v, args.verbose) 

87 

88 

89def calculate_sensitivity(subarray, freq=-1, theta=-1, t_obs=1, delta_v=10e3, verbose=True): 

90 """Calculate sensitivities for a given observing setup. 

91 

92 Parameters 

93 ---------- 

94 subarray : str 

95 Subarray name (e.g., ``"sba"``, ``"core"``, ``"main+long"``). 

96 freq : float, optional 

97 Representative frequency in GHz. Default is ``-1`` (uses engine logic). 

98 theta : float, optional 

99 Target resolution in arcsec (use ``-1`` for native resolution). Default ``-1``. 

100 t_obs : float, optional 

101 On-source time in hours. Default ``1``. 

102 delta_v : float, optional 

103 Channel width in m/s. Default ``1e4``. 

104 verbose : bool, optional 

105 If ``True``, log a human-readable report to the logger. Default ``True``. 

106 

107 Returns 

108 ------- 

109 dict 

110 A result mapping from :meth:`ngect.engine.ArrayPerformance.ect` containing 

111 sensitivities and configuration details for the last processed specmode. 

112 

113 Notes 

114 ----- 

115 This function evaluates both continuum (``cont``) and spectral line (``line``) 

116 modes in sequence, logging their results. The returned dictionary corresponds 

117 to the last evaluated mode. 

118 """ 

119 

120 ap = engine.ArrayPerformance() 

121 

122 for specmode in ["cont", "line"]: 

123 input_dict = { 

124 "freq": freq * u.GHz, 

125 "theta": theta * u.arcsec, 

126 "subarray": subarray, 

127 "specmode": specmode, 

128 "chanwidth": delta_v * u.m / u.s, 

129 "npol": 2, 

130 "tos": t_obs * u.hr, 

131 "elevation": 45 * u.degree, 

132 "ectmode": "tos2rms", 

133 "pwv": "6 mm", 

134 } 

135 output_dict = ap.ect(input_dict) 

136 

137 logger.info("") 

138 if specmode == "cont": 

139 logger.info("Continuum Mode:") 

140 if specmode == "line": 

141 logger.info("Spectral-Line Mode:") 

142 

143 str1 = f'{subarray} array, {input_dict["tos"]} at frequency {output_dict["freq"]} ({output_dict["rx_name"]}) with resolution of {output_dict["theta"]} (eta_w = {output_dict["eta_W"]})' 

144 logger.info(str1) 

145 logger.info("-" * len(str1)) 

146 logger.info(f'continuum point source sensitivity: {output_dict["sigma_fl"]}') 

147 logger.info(f'continuum brightness sensitivity: {output_dict["sigma_tb"]}') 

148 return output_dict 

149 

150 

151if __name__ == "__main__": 

152 cli_run()