Coverage for python / lsst / obs / base / cli / cmd / commands.py: 91%
75 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-22 08:58 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-22 08:58 +0000
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/>.
22from collections.abc import Sequence
23from typing import Any
25import click
27from lsst.daf.butler import Butler
28from lsst.daf.butler.cli.opt import (
29 collections_argument,
30 config_file_option,
31 config_option,
32 locations_argument,
33 options_file_option,
34 processes_option,
35 regex_option,
36 repo_argument,
37 run_option,
38 transfer_option,
39 where_option,
40)
41from lsst.daf.butler.cli.utils import ButlerCommand, split_commas, typeStrAcceptsMultiple
42from lsst.pipe.base.cli.opt import instrument_argument
44from ... import script
45from ..opt import failfast_option, labels_argument
47# regular expression that can be used to find supported fits file extensions.
48fits_re = r"\.fit[s]?\b"
51@click.command(short_help="Define visits from exposures.", cls=ButlerCommand)
52@repo_argument(required=True)
53@instrument_argument(required=True)
54@config_file_option(
55 help="Path to a pex_config override to be included after the Instrument config overrides are applied."
56)
57@click.option(
58 "--collections",
59 help="The collections to be searched (in order) for camera geometry.",
60 multiple=True,
61 callback=split_commas,
62 metavar=typeStrAcceptsMultiple,
63)
64@where_option()
65@click.option(
66 "--update-records/--no-update-records",
67 default=False,
68 help="Use this option to force updates to the visit definition record. "
69 "Should only be used if you know that there has been a change to the "
70 "exposure records, such as a change to the metadata translator.",
71)
72@click.option(
73 "--incremental/--no-incremental",
74 default=False,
75 help="Use this option to force updates to the visit definition record "
76 "when multi-snap visits are being ingested incrementally and so you "
77 "might encounter partial visits. Implies --update-records.",
78)
79@click.option(
80 "--skip-conflicting/--no-skip-conflicting",
81 default=False,
82 help="Use this option to skip over any visits that are currently defined "
83 "with a different value and you are not sure whether to accept the new "
84 "value. Ignored if incremental or update mode is enabled.",
85)
86@click.option(
87 "--prefilter/--no-prefilter",
88 default=False,
89 help=(
90 "Whether to filter out exposures that are already associated with a visit before computing "
91 "the visits they would be associated with now. This is incompatible with --update-records and "
92 "--incremental."
93 ),
94)
95@click.option(
96 "--check-detector-regions/--no-check-detector-regions",
97 default=False,
98 help=(
99 "Whether to check that already-defined visits have the full set of detector regions defined, "
100 "in order to insert missing ones."
101 ),
102)
103@options_file_option()
104def define_visits(*args: Any, **kwargs: Any) -> None:
105 """Define visits from exposures in the butler registry.
107 The calibration collection containing the camera geometry can not
108 be specified.
109 """
110 script.defineVisits(*args, **kwargs)
113@click.command(short_help="Ingest raw frames.", cls=ButlerCommand)
114@repo_argument(required=True)
115@locations_argument(
116 help="LOCATIONS specifies files to ingest and/or locations to search for files.", required=True
117)
118@regex_option(
119 default=fits_re,
120 help="Regex string used to find files in directories listed in LOCATIONS. "
121 "Searches for fits files by default.",
122)
123@config_option(metavar="TEXT=TEXT", multiple=True)
124@config_file_option(type=click.Path(exists=True, writable=False, file_okay=True, dir_okay=False))
125@run_option(required=False)
126@transfer_option()
127@processes_option(help="Number of workers to use.")
128@click.option(
129 "--ingest-task",
130 default="lsst.obs.base.RawIngestTask",
131 help="The fully qualified class name of the ingest task to use.",
132)
133@click.option(
134 "--track-file-attrs/--no-track-file-attrs",
135 default=True,
136 help="Indicate to the datastore whether file attributes such as file size"
137 " or checksum should be tracked or not. Whether this parameter is honored"
138 " depends on the specific datastore implentation.",
139)
140@failfast_option()
141@click.option(
142 "--update-records/--no-update-records",
143 default=False,
144 help="Use this option to force updates to the exposure records. "
145 "Should only be used if you know that there has been a change to the "
146 "exposure records, such as a change to the metadata translator.",
147)
148@click.option(
149 "--skip-existing/--no-skip-existing",
150 default=True,
151 help="Use this option to control whether a raw file already existing "
152 "in the Butler repository is an error or not.",
153)
154@click.option(
155 "--search-indexes/--no-search-indexes",
156 default=True,
157 help="By default ingest searches for index files in each directory being "
158 "searched. Turning this off can improve performance if you know for a fact "
159 "you have no indexes and you are using an object store.",
160)
161@options_file_option()
162def ingest_raws(*args: Any, **kwargs: Any) -> None:
163 """Ingest raw frames into from a directory into the butler registry."""
164 script.ingestRaws(*args, **kwargs)
167@click.command(short_help="Add an instrument's curated calibrations.", cls=ButlerCommand)
168@repo_argument(required=True)
169@instrument_argument(required=True)
170@labels_argument()
171@click.option(
172 "--collection",
173 required=False,
174 help="Name of the calibration collection that associates datasets with validity ranges.",
175)
176@click.option(
177 "--label",
178 "labels",
179 multiple=True,
180 help=(
181 "Extra strings to include (with automatic delimiters) in all RUN collection names, "
182 "as well as the calibration collection name if it is not provided via --collection. "
183 "May be provided as a positional argument instead of or in addition to this option, "
184 "as long as at least one label is provided. Positional-argument labels appear before "
185 "those provided by this option."
186 ),
187)
188@click.option(
189 "--prefix",
190 required=False,
191 help=(
192 "Prefix for the collection name. Default is the instrument name. "
193 "This is ignored if --collection is passed."
194 ),
195)
196@options_file_option()
197def write_curated_calibrations(
198 *,
199 repo: str,
200 instrument: str,
201 collection: str,
202 labels: list[str],
203 labels_arg: list[str],
204 prefix: str,
205) -> None:
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 )
212@click.command()
213@repo_argument(required=True)
214@instrument_argument(required=True, help="Name of the instrument to use for updates.")
215@collections_argument(help="Collections to search for visit geometry datasets.")
216@click.option("--dataset-type", default="visit_geometry", help="Name of the visit geometry dataset type.")
217@click.option("--batch-size", default=11, help="Number of visits to process in each transaction.")
218@where_option()
219def update_dimension_regions(
220 *,
221 repo: str,
222 instrument: str,
223 collections: Sequence[str],
224 dataset_type: str,
225 batch_size: int,
226 where: str,
227) -> None:
228 """Update dimension record regions from visit geometry datasets."""
229 from ...visit_geometry import VisitGeometry
231 with Butler.from_config(repo, writeable=True, collections=collections) as butler:
232 VisitGeometry.update_dimension_records(
233 butler, instrument, where, dataset_type=dataset_type, batch_size=batch_size
234 )
237@click.command
238@repo_argument(required=True)
239@instrument_argument(required=True, help="Instrument to use for finding raw datasets.")
240@collections_argument(help="List of collections to search for raws instead of the default.")
241@where_option(
242 help="A string expression to use to query the butler to find raw datasets to use for record updates."
243)
244@failfast_option()
245@config_option(metavar="TEXT=TEXT", multiple=True)
246@config_file_option(type=click.Path(exists=True, writable=False, file_okay=True, dir_okay=False))
247@processes_option()
248@options_file_option()
249def update_exposures_from_raws(*args: Any, **kwargs: Any) -> None:
250 """Update exposure records associated with specific raw datasets."""
251 script.updateExposures(*args, **kwargs)