Coverage for python / lsst / obs / base / cli / cmd / commands.py: 93%

58 statements  

« prev     ^ index     » next       coverage.py v7.12.0, created at 2025-12-19 22:18 -0800

1# This file is part of obs_base. 

2# 

3# Developed for the LSST Data Management System. 

4# This product includes software developed by the LSST Project 

5# (http://www.lsst.org). 

6# See the COPYRIGHT file at the top-level directory of this distribution 

7# for details of code ownership. 

8# 

9# This program is free software: you can redistribute it and/or modify 

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

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

12# (at your option) any later version. 

13# 

14# This program is distributed in the hope that it will be useful, 

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

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

17# GNU General Public License for more details. 

18# 

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

20# along with this program. If not, see <http://www.gnu.org/licenses/>. 

21 

22import click 

23 

24from lsst.daf.butler.cli.opt import ( 

25 config_file_option, 

26 config_option, 

27 locations_argument, 

28 options_file_option, 

29 processes_option, 

30 regex_option, 

31 repo_argument, 

32 run_option, 

33 transfer_option, 

34 where_option, 

35) 

36from lsst.daf.butler.cli.utils import ButlerCommand, split_commas, typeStrAcceptsMultiple 

37from lsst.pipe.base.cli.opt import instrument_argument 

38 

39from ... import script 

40from ..opt import failfast_option, labels_argument 

41 

42# regular expression that can be used to find supported fits file extensions. 

43fits_re = r"\.fit[s]?\b" 

44 

45 

46@click.command(short_help="Convert a gen2 repo to gen3.", cls=ButlerCommand) 

47@repo_argument( 

48 required=True, 

49 help="REPO is the URI or path to the gen3 repository. Will be created if it does not already exist", 

50) 

51@click.option("--gen2root", required=True, help="Root path of the gen 2 repo to be converted.") 

52@click.option("--skymap-name", help="Name of the new gen3 skymap (e.g. 'discrete/ci_hsc').") 

53@click.option("--skymap-config", help="Path to skymap config file defining the new gen3 skymap.") 

54@click.option( 

55 "--calibs", help="Path to the gen 2 calibration repo. It can be absolute or relative to gen2root." 

56) 

57@click.option( 

58 "--reruns", 

59 multiple=True, 

60 callback=split_commas, 

61 metavar=typeStrAcceptsMultiple, 

62 help=( 

63 "List of rerun paths to convert. Output collection names will be " 

64 "guessed, which can fail if the Gen2 repository paths do not follow a " 

65 "recognized convention. In this case, the command-line interface cannot " 

66 "be used." 

67 ), 

68) 

69@transfer_option(help="Mode to use to transfer files into the new repository.") 

70@processes_option() 

71@config_file_option( 

72 help="Path to a `ConvertRepoConfig` override to be included after the Instrument config " 

73 "overrides are applied." 

74) 

75@options_file_option() 

76def convert(*args, **kwargs): 

77 """Convert one or more Butler gen 2 repositories into a gen 3 repository. 

78 

79 This is a highly simplified interface that should only be used to convert 

80 suites of gen 2 repositories that contain at most one calibration repo and 

81 has no chained reruns. Custom scripts that call ConvertRepoTask should be 

82 used on more complex suites of repositories. 

83 """ 

84 raise RuntimeError( 

85 "Gen2 conversion to Gen3 is no longer supported. " 

86 "Please use version v23.0 of the pipelines code to do legacy conversions." 

87 ) 

88 

89 

90@click.command(short_help="Define visits from exposures.", cls=ButlerCommand) 

91@repo_argument(required=True) 

92@instrument_argument(required=True) 

93@config_file_option( 

94 help="Path to a pex_config override to be included after the Instrument config overrides are applied." 

95) 

96@click.option( 

97 "--collections", 

98 help="The collections to be searched (in order) for camera geometry.", 

99 multiple=True, 

100 callback=split_commas, 

101 metavar=typeStrAcceptsMultiple, 

102) 

103@where_option() 

104@click.option( 

105 "--update-records/--no-update-records", 

106 default=False, 

107 help="Use this option to force updates to the visit definition record. " 

108 "Should only be used if you know that there has been a change to the " 

109 "exposure records, such as a change to the metadata translator.", 

110) 

111@click.option( 

112 "--incremental/--no-incremental", 

113 default=False, 

114 help="Use this option to force updates to the visit definition record " 

115 "when multi-snap visits are being ingested incrementally and so you " 

116 "might encounter partial visits. Implies --update-records.", 

117) 

118@options_file_option() 

119def define_visits(*args, **kwargs): 

120 """Define visits from exposures in the butler registry. 

121 

122 The calibration collection containing the camera geometry can not 

123 be specified. 

124 """ 

125 script.defineVisits(*args, **kwargs) 

126 

127 

128@click.command(short_help="Ingest raw frames.", cls=ButlerCommand) 

129@repo_argument(required=True) 

130@locations_argument( 

131 help="LOCATIONS specifies files to ingest and/or locations to search for files.", required=True 

132) 

133@regex_option( 

134 default=fits_re, 

135 help="Regex string used to find files in directories listed in LOCATIONS. " 

136 "Searches for fits files by default.", 

137) 

138@config_option(metavar="TEXT=TEXT", multiple=True) 

139@config_file_option(type=click.Path(exists=True, writable=False, file_okay=True, dir_okay=False)) 

140@run_option(required=False) 

141@transfer_option() 

142@processes_option() 

143@click.option( 

144 "--ingest-task", 

145 default="lsst.obs.base.RawIngestTask", 

146 help="The fully qualified class name of the ingest task to use.", 

147) 

148@click.option( 

149 "--track-file-attrs/--no-track-file-attrs", 

150 default=True, 

151 help="Indicate to the datastore whether file attributes such as file size" 

152 " or checksum should be tracked or not. Whether this parameter is honored" 

153 " depends on the specific datastore implentation.", 

154) 

155@failfast_option() 

156@click.option( 

157 "--update-records/--no-update-records", 

158 default=False, 

159 help="Use this option to force updates to the exposure records. " 

160 "Should only be used if you know that there has been a change to the " 

161 "exposure records, such as a change to the metadata translator.", 

162) 

163@click.option( 

164 "--skip-existing/--no-skip-existing", 

165 default=True, 

166 help="Use this option to control whether a raw file already existing " 

167 "in the Butler repository is an error or not.", 

168) 

169@options_file_option() 

170def ingest_raws(*args, **kwargs): 

171 """Ingest raw frames into from a directory into the butler registry.""" 

172 script.ingestRaws(*args, **kwargs) 

173 

174 

175@click.command(short_help="Add an instrument's curated calibrations.", cls=ButlerCommand) 

176@repo_argument(required=True) 

177@instrument_argument(required=True) 

178@labels_argument() 

179@click.option( 

180 "--collection", 

181 required=False, 

182 help="Name of the calibration collection that associates datasets with validity ranges.", 

183) 

184@click.option( 

185 "--label", 

186 "labels", 

187 multiple=True, 

188 help=( 

189 "Extra strings to include (with automatic delimiters) in all RUN collection names, " 

190 "as well as the calibration collection name if it is not provided via --collection. " 

191 "May be provided as a positional argument instead of or in addition to this option, " 

192 "as long as at least one label is provided. Positional-argument labels appear before " 

193 "those provided by this option." 

194 ), 

195) 

196@click.option( 

197 "--prefix", 

198 required=False, 

199 help=( 

200 "Prefix for the collection name. Default is the instrument name. " 

201 "This is ignored if --collection is passed." 

202 ), 

203) 

204@options_file_option() 

205def write_curated_calibrations(*, repo, instrument, collection, labels, labels_arg, prefix): 

206 """Add an instrument's curated calibrations to the data repository.""" 

207 script.writeCuratedCalibrations( 

208 repo=repo, instrument=instrument, collection=collection, labels=labels_arg + labels, prefix=prefix 

209 )