300 """Find array of tract IDs and patch IDs with vectorized operations
303 If a given sky map does not support vectorized operations, then
304 loops will be called.
309 Array of Right Ascension. Units are radians unless
311 dec : `numpy.ndarray`
312 Array of Declination. Units are radians unless
314 degrees : `bool`, optional
315 Input ra, dec arrays are degrees if `True`.
319 tractId : `numpy.ndarray`
321 patchId : `numpy.ndarray`
322 Array of sequential patch IDs. -1 if there is no appropriate
327 - If coord is equidistant between multiple sky tract centers then one
328 is arbitrarily chosen.
332 If tracts do not cover the whole sky then the returned tract may not
333 include the given ra/dec.
335 from scipy.ndimage
import value_indices
337 _ra = np.atleast_1d(ra)
338 _dec = np.atleast_1d(dec)
341 tractIds = self.
findTractIdArray(_ra.ravel(), _dec.ravel(), degrees=degrees)
344 patchIds = np.zeros(len(tractIds), dtype=np.int32) - 1
346 inds = value_indices(tractIds)
347 for tractId, (indices,)
in inds.items():
348 tract = self[tractId]
350 x, y = wcs.skyToPixelArray(_ra[indices], _dec[indices], degrees=degrees)
351 xInd = np.floor(x).astype(np.int64) // tract.patch_inner_dimensions[0]
352 yInd = np.floor(y).astype(np.int64) // tract.patch_inner_dimensions[1]
353 nx, ny = tract.num_patches
354 patchIds[indices] = nx * yInd + xInd
357 bad = (xInd < 0) | (xInd >= nx) | (yInd < 0) | (yInd >= ny)
359 tractIds[indices[bad]] = -1
360 patchIds[indices[bad]] = -1
362 return (tractIds, patchIds)
386 """Write information about a sky map to supplied log
390 log : `logging.Logger`
391 Log object that information about skymap will be written.
393 log.info(
"sky map has %s tracts" % (len(self),))
394 for tractInfo
in self:
395 wcs = tractInfo.getWcs()
403 skyPosList = [wcs.pixelToSky(pos).getPosition(geom.degrees)
for pos
in pixelPosList]
404 posStrList = [
"(%0.3f, %0.3f)" % tuple(skyPos)
for skyPos
in skyPosList]
405 log.info(
"tract %s has corners %s (RA, Dec deg) and %s x %s patches" %
406 (tractInfo.getId(),
", ".join(posStrList),
407 tractInfo.getNumPatches()[0], tractInfo.getNumPatches()[1]))
453 """Add skymap, tract, and patch Dimension entries to the given Gen3
459 The name of the skymap.
460 butler : `lsst.daf.butler.Butler`
461 The butler to add to.
465 lsst.daf.butler.registry.ConflictingDefinitionError
466 Raised if a different skymap exists with the same name.
470 Registering the same skymap multiple times (with the exact same
471 definition) is safe, but inefficient; most of the work of computing
472 the rows to be inserted must be done first in order to check for
473 consistency between the new skymap and any existing one.
475 Re-registering a skymap with different tract and/or patch definitions
476 but the same summary information may not be detected as a conflict but
477 will never result in updating the skymap; there is intentionally no
478 way to modify a registered skymap (aside from manual administrative
479 operations on the database), as it is hard to guarantee that this can
480 be done without affecting reproducibility.
482 numPatches = [tractInfo.getNumPatches()
for tractInfo
in self]
483 nxMax = max(nn[0]
for nn
in numPatches)
484 nyMax = max(nn[1]
for nn
in numPatches)
489 "tract_max": len(self),
490 "patch_nx_max": nxMax,
491 "patch_ny_max": nyMax,
497 from lsst.daf.butler
import DatasetType
498 from lsst.daf.butler.registry
import ConflictingDefinitionError
499 datasetType = DatasetType(
501 dimensions=[
"skymap"],
502 storageClass=
"SkyMap",
503 universe=butler.dimensions
505 butler.registry.registerDatasetType(datasetType)
506 with butler.transaction():
508 inserted = butler.registry.syncDimensionData(
"skymap", skyMapRecord)
509 except ConflictingDefinitionError
as err:
510 raise ConflictingDefinitionError(
511 f
"SkyMap with hash {self.getSha1().hex()} is already registered with a different name."
514 for tractInfo
in self:
515 tractId = tractInfo.getId()
516 tractRegion = tractInfo.getOuterSkyPolygon()
517 tractWcs = tractInfo.getWcs()
523 butler.registry.insertDimensionData(
"tract", tractRecord)
526 for patchInfo
in tractInfo:
527 xx, yy = patchInfo.getIndex()
532 patch=tractInfo.getSequentialPatchIndex(patchInfo),
535 region=patchInfo.getOuterSkyPolygon(tractWcs),
538 butler.registry.insertDimensionData(
"patch", *patchRecords)