168 def run(self, input_images: Iterable[tuple[NDArray, SkyWcs, Box2I]], healpix_id) -> Struct:
169 """Main execution method for generating HealPix tiles.
173 input_images : Iterable[tuple[NDArray, SkyWcs, Box2I]]
174 Iterable of tuples containing image data, WCS, and bounding box information.
176 The HealPix order 8 ID to process.
181 Output structure containing the processed HealPix order 8 tile.
182 This has been downsampled to 256x256 corresponding to a quarter of a healpix
188 target_wcs = makeHpxWcs(8, healpix_id, 12,
False)
193 output_array_hpx = np.zeros((4096, 4096, 3), dtype=np.float32)
194 output_array_hpx[:, :, :] = np.nan
196 self.log.info(
"Warping input exposures and populating hpx8 super tile.")
199 for input_image, in_wcs, in_box
in input_images:
200 tmp_image = ImageF(in_box)
201 in_image: NDArray = input_image
204 match in_image.dtype:
206 in_image = in_image.astype(np.float32) / 255.0
208 in_image = in_image.astype(np.float32) / 65535
210 in_image = in_image.astype(np.float32)
213 for channel
in ColorChannel:
215 existing = output_array_hpx[..., channel.value]
218 channel_array = in_image[..., channel.value]
219 tmp_image.array[:, :] = channel_array
222 warpped = self.
warper.warpImage(target_wcs, tmp_image, in_wcs, maxBBox=exp_bbox)
223 warpped_box_slices = warpped.getBBox().slices
226 are_warpped = np.isfinite(warpped.array)
227 existing[warpped_box_slices][are_warpped] = warpped.array[are_warpped]
230 output_array_hpx[np.isnan(output_array_hpx)] = 0
233 output_array_hpx = output_array_hpx[::-1, :, :]
246 for zoom, hips_level, factor
in zip((0, 2, 4, 8), (11, 10, 9, 8), (3, 2, 1, 0)):
247 self.log.info(
"Generating tiles for hxp level %d", hips_level)
250 binned_array = cv2.resize(output_array_hpx, (size, size), interpolation=cv2.INTER_LANCZOS4)
252 binned_array = output_array_hpx
262 tmp_pixels = np.array([[healpix_id]])
263 for _
in range(factor):
264 tmp_array = np.zeros(np.array(tmp_pixels.shape) * 2)
265 for ii
in range(tmp_pixels.shape[0]):
266 for jj
in range(tmp_pixels.shape[1]):
267 tmp_array_view = tmp_array[ii * 2 : ii * 2 + 2, jj * 2 : jj * 2 + 2]
268 tmp_range_set = RangeSet(int(tmp_pixels[ii, jj]))
269 tmp_array_view[:, :] = (
270 np.array([x
for x
in range(*tmp_range_set.scaled(4)[0])], dtype=int)[[0, 2, 1, 3]]
272 tmp_pixels = tmp_array
275 hpx_id_array = tmp_pixels
276 for i
in range(binned_array.shape[0] // 512):
277 for j
in range(binned_array.shape[1] // 512):
278 pixel_id = int(hpx_id_array[i, j])
279 sub_pixel = binned_array[i * 512 : i * 512 + 512, j * 512 : j * 512 + 512, :]
280 self.log.info(f
"writing sub_pixel {pixel_id}")
286 self.config.file_extension,
287 self.config.array_type,
292 zoomed = cv2.resize(output_array_hpx, (256, 256), interpolation=cv2.INTER_LANCZOS4)
294 return Struct(output_hpx=zoomed)
297 self, tract_patch: dict[int, Iterable[tuple[DeferredDatasetHandle, SkyWcs, Box2I]]], patch_grow: int
298 ) -> list[tuple[NDArray, SkyWcs, Box2I]]:
299 """Assemble all the patches in each tract into images.
301 This function takes in an input keyed by tract, with values
302 corresponding the patches in that tract that overlap the quatum's
303 healpix value. It assembles each of these into a single image such
304 that the return values is a list of images (and metadata) one element
305 for each input tract.
309 tract_patch : `dict` of `int` to `iterable` of `tuple` of
310 `DeferredDatasetHandle`, `SkyWcs` and `Box2I`
311 Input images and metadata organized into corresponding tracts.
313 Amount to grow patches by
317 output_list : `list` of `tuple` of `NDArray` `SkyWcs` and `Box2I`
318 List of assembled images and metadata, one element for each tract
323 for _, iterable
in tract_patch.items():
326 for _, _, bbox
in iterable:
327 new_box.include(bbox)
329 new_array = np.zeros((new_box.getHeight(), new_box.getWidth(), 3), dtype=np.float32)
330 for handle, skyWcs, box
in iterable:
333 localOrigin = box.getBegin() - new_box.getBegin()
335 x=int(np.floor(localOrigin.x)),
336 y=int(np.floor(localOrigin.y)),
340 x=int(np.floor(box.getWidth())),
341 y=int(np.floor(box.getHeight())),
343 tmpBox =
Box2I(localOrigin, localExtent)
347 mosaic_maker.add_to_image(new_array, image.array, tmp_new_box, tmpBox, reverse=
False)
348 boxes.append((new_array, skyWcs, new_box))
353 butlerQC: QuantumContext,
354 inputRefs: InputQuantizedConnection,
355 outputRefs: OutputQuantizedConnection,
358 healpix_id = butlerQC.quantum.dataId[
"healpix8"]
361 skymap: BaseSkyMap = butlerQC.get(inputRefs.skymap)
366 for input_image_ref
in inputRefs.input_images:
367 tract = input_image_ref.dataId[
"tract"]
368 patch = input_image_ref.dataId[
"patch"]
371 imageWcs = skymap[tract][patch].getWcs()
372 box = skymap[tract][patch].getOuterBBox()
373 patch_grow = skymap[tract][patch].getCellInnerDimensions().getX()
374 imageHandle = butlerQC.get(input_image_ref)
375 container = inputs_by_tract.setdefault(tract, list())
376 container.append((imageHandle, imageWcs, box))
380 outputs = self.
run(input_images, healpix_id)
381 butlerQC.put(outputs, outputRefs)