|
181 | 181 | "\n", |
182 | 182 | "A Bounding Box is useful for defining boundaries of images (either of the parent tract, the `deep_coadd` itself, or to make a subset from an image). This section will retrieve an image from the Butler and demonstrate how to define a bounding box (`bbox`) for a subset that is centered on pixel coordinate x,y and is 1000 pixels wide and 1000 pixels high.\n", |
183 | 183 | "\n", |
184 | | - "First, query the Butler for images that overlap the sky region defined above. " |
| 184 | + "### 2.1. Identify deep_coadds\n", |
| 185 | + "\n", |
| 186 | + "First, query the Butler for r-band images that overlap the sky region defined above. " |
185 | 187 | ] |
186 | 188 | }, |
187 | 189 | { |
|
224 | 226 | "id": "dd5a65f3-2048-4bbb-806e-f869dff354b2", |
225 | 227 | "metadata": {}, |
226 | 228 | "source": [ |
227 | | - "### 2.1. Local vs parent coordinates\n", |
| 229 | + "### 2.2. Define image boundaries\n", |
228 | 230 | "\n", |
229 | | - "To retrieve the bounding box that defines the full deep_coadd, use the getBBox method. By default, `getBBox` returns pixel coordinates in the parent coordinate system of the entire image tract. " |
| 231 | + "To retrieve the bounding box that defines the full `deep_coadd`, use the `getBBox` method. By default, `getBBox` returns pixel coordinates in the parent coordinate system of the entire image tract. " |
230 | 232 | ] |
231 | 233 | }, |
232 | 234 | { |
|
237 | 239 | "outputs": [], |
238 | 240 | "source": [ |
239 | 241 | "bbox = coadd.getBBox()\n", |
240 | | - "print(\"x pixel values range between\", bbox.beginX, bbox.endX)\n", |
241 | | - "print(\"y pixel values range between\", bbox.beginY, bbox.endY)\n" |
| 242 | + "print(f\"X-pixel range: [{bbox.beginX}, {bbox.endX}]\")\n", |
| 243 | + "print(f\"Y-pixel range: [{bbox.beginY}, {bbox.endY}]\")" |
242 | 244 | ] |
243 | 245 | }, |
244 | 246 | { |
|
257 | 259 | "outputs": [], |
258 | 260 | "source": [ |
259 | 261 | "bbox_local = coadd.getBBox(LOCAL)\n", |
260 | | - "print(\"x pixel values range between\", bbox_local.beginX, bbox_local.endX)\n", |
261 | | - "print(\"y pixel values range between\", bbox_local.beginY, bbox_local.endY)\n" |
| 262 | + "print(f\"X-pixel range: [{bbox_local.beginX}, {bbox_local.endX}]\")\n", |
| 263 | + "print(f\"Y-pixel range: [{bbox_local.beginY}, {bbox_local.endY}]\")" |
262 | 264 | ] |
263 | 265 | }, |
264 | 266 | { |
265 | 267 | "cell_type": "markdown", |
266 | 268 | "id": "6a16aab2-19ee-4a8a-92da-d8069e44458d", |
267 | 269 | "metadata": {}, |
268 | 270 | "source": [ |
269 | | - "Values of interest to defining the subset, including the origin and dimensions of the bounding box can be accessed through the getXY0, getDimensions, getMin and getMax methods." |
| 271 | + "Values of interest to defining the subset, including the origin and dimensions of the bounding box can be accessed through the `getDimensions`, `getMin` and `getMax` methods." |
270 | 272 | ] |
271 | 273 | }, |
272 | 274 | { |
|
277 | 279 | "outputs": [], |
278 | 280 | "source": [ |
279 | 281 | "print(\"The pixel dimensions of the coadd is \", bbox.getDimensions())\n", |
280 | | - "print(\"The minimum pixel values of the coadd are \", bbox.getMin())\n", |
281 | | - "print(\"The maximum pixel values of the coadd are \", bbox.getMax())\n" |
| 282 | + "print(\"The minimum pixel coordinates of the coadd are \", bbox.getMin())\n", |
| 283 | + "print(\"The maximum pixel coordinates of the coadd are \", bbox.getMax())" |
282 | 284 | ] |
283 | 285 | }, |
284 | 286 | { |
285 | 287 | "cell_type": "markdown", |
286 | 288 | "id": "1e47abf1-2d10-4f06-899e-b3f0f01636cb", |
287 | 289 | "metadata": {}, |
288 | 290 | "source": [ |
289 | | - "### 2.2. Use Box2I to define subset\n", |
| 291 | + "### 2.3. Use Box2I to define subset\n", |
290 | 292 | "\n", |
291 | | - "The `lsst.geom.Box2I` (2D Integer Bounding Box) object can be used to define a bounding box for the subset. First, use the bounding box previously defined in the parent coordinate system (this can also be done by specifying `PARENT`). For these examples, use definitions of the bounding box based on pixel coordinates. Sky coordinates are demonstrated below in section 2.2.3." |
| 293 | + "The `Box2I` (2D Integer Bounding Box) object can be used to define a bounding box for the subset. First, use the bounding box previously defined in the parent coordinate system (this can also be done by specifying `PARENT`). For these examples, use definitions of the bounding box based on pixel coordinates. Sky coordinates are demonstrated below in section 2.2.3." |
292 | 294 | ] |
293 | 295 | }, |
294 | 296 | { |
295 | 297 | "cell_type": "markdown", |
296 | 298 | "id": "a506b75b-11e7-4a0b-8415-531bb968e946", |
297 | 299 | "metadata": {}, |
298 | 300 | "source": [ |
299 | | - "#### 2.2.1. Use edge corners to define box\n", |
| 301 | + "#### 2.3.1. Use edge corners to define box\n", |
300 | 302 | "\n", |
301 | 303 | "Now, define a bounding box for the subset `subset_box` specified above using the `Box2I` function. Use the values returned by these methods to define the subset bounding box in pixel coordinates for a subset with edge size 1000 pixels.\n", |
302 | 304 | "\n", |
|
337 | 339 | "id": "6376abd5-216e-4ab2-9c36-b3df5eba3dcd", |
338 | 340 | "metadata": {}, |
339 | 341 | "source": [ |
340 | | - "#### 2.2.2. Use Point2I to define box\n", |
| 342 | + "#### 2.3.2. Use Point2I to define box\n", |
341 | 343 | "\n", |
342 | | - "A more compact alternative statement to create the same bounding box is using the `Point2I` to define the starting x and y coordinates, and the `Extent2I` to define the width and height. Note that 2I refers to integer pixels.\n" |
| 344 | + "A more compact alternative statement to create the same bounding box is using `Point2I` to define the starting x and y coordinates, and `Extent2I` to define the width and height. Note that `2I` refers to integer pixels.\n" |
343 | 345 | ] |
344 | 346 | }, |
345 | 347 | { |
|
351 | 353 | "source": [ |
352 | 354 | "w = subset_pixsize\n", |
353 | 355 | "h = subset_pixsize\n", |
354 | | - "subset_box = geom.Box2I(geom.Point2I(subset_xmin, subset_ymin), geom.Extent2I(w, h))\n" |
| 356 | + "subset_box = Box2I(Point2I(subset_xmin, subset_ymin), Extent2I(w, h))\n" |
355 | 357 | ] |
356 | 358 | }, |
357 | 359 | { |
358 | 360 | "cell_type": "markdown", |
359 | 361 | "id": "e9ef9dd0-d3bc-49c0-bff8-ec63603b9153", |
360 | 362 | "metadata": {}, |
361 | 363 | "source": [ |
362 | | - "#### 2.2.3. Use sky coordinates\n", |
| 364 | + "#### 2.3.3. Use sky coordinates\n", |
363 | 365 | "\n", |
364 | 366 | "The bounding box can also be defined starting with sky coordinates (converted to pixels) in the following way. Retrieving the world coordinate system (WCS) of the `deep_coadd` enables converting an ra, dec and spatial extent in (60 arcseconds) to pixel coordinates to define the bounding box." |
365 | 367 | ] |
|
375 | 377 | "\n", |
376 | 378 | "wcs = butler.get('deep_coadd.wcs', dataId=dataId)\n", |
377 | 379 | "\n", |
378 | | - "xy = geom.Point2I(wcs.skyToPixel(point))\n", |
| 380 | + "xy = Point2I(wcs.skyToPixel(point))\n", |
379 | 381 | "\n", |
380 | 382 | "pixel_scale_arcsec = wcs.getPixelScale().asArcseconds()\n", |
381 | 383 | "subset_side_arcsec = 60.0\n", |
382 | 384 | "subset_side_pixels = int(subset_side_arcsec / pixel_scale_arcsec)\n", |
383 | 385 | "half_size = subset_side_pixels // 2\n", |
384 | 386 | "\n", |
385 | | - "subset_box_sky = geom.Box2I(xy - geom.Extent2I(half_size, half_size),\n", |
386 | | - " geom.Extent2I(subset_side_pixels, subset_side_pixels))\n" |
| 387 | + "subset_box_sky = Box2I(xy - Extent2I(half_size, half_size),\n", |
| 388 | + " Extent2I(subset_side_pixels, subset_side_pixels))\n" |
387 | 389 | ] |
388 | 390 | }, |
389 | 391 | { |
|
393 | 395 | "source": [ |
394 | 396 | "## 3. Retrieve subset from the butler\n", |
395 | 397 | "\n", |
396 | | - "Several methods exist for extracting subsets from the butler. A few are demonstrated below, including passing the bounding box directly to the butler (3.1), retrieving the full deep_coadd and using the subset method (Section 3.2) and passing the bounding box to the full `deep_coadd` via `ExposureF` (Section 3.3). \n", |
| 398 | + "Several methods exist for extracting subsets from the butler. A few are demonstrated below, including passing the bounding box directly to the butler (Section 3.1), retrieving the full deep_coadd and using the subset method (Section 3.2) and passing the bounding box to the full `deep_coadd` via `ExposureF` (Section 3.3). \n", |
397 | 399 | "\n", |
398 | 400 | "### 3.1. Pass bounding box to the Butler\n", |
399 | 401 | "\n", |
|
415 | 417 | "id": "00f06747-8fd3-4f97-b937-3b2fe7e63ca1", |
416 | 418 | "metadata": {}, |
417 | 419 | "source": [ |
418 | | - "Next, pass the bounding box to the bulter in the parameters dictionary directly. This saves memory and time by only loading the requested pixels. Some properties of the subset can be accessed with methods such as `.shape`, and image extensions using `.image` or `.variance`" |
| 420 | + "Next, pass the bounding box to the butler in the parameters dictionary directly. This saves memory and time by only loading the requested pixels. Some properties of the subset can be accessed with methods such as `.shape`, and image extensions using `.image` or `.variance`" |
419 | 421 | ] |
420 | 422 | }, |
421 | 423 | { |
|
599 | 601 | "\n", |
600 | 602 | "This section demonstrates an efficient way to retrieve multiple subsets from the butler. Instead of first retrieving the deep_coadd image into memory (which is many gigabytes is size), an alternative is to use the `butler.getDeferred()` method. This identifies the images on the remote server and returns a lightweight \"pointer\" or \"handle\" (specifically, a `DeferredDatasetHandle`) instead of the actual data. `getDeferred` is fast and uses nearly no memory, while queuing up a bunch of subsets to retrieve at a later time all at once without transferring the `deep_coadd`(s) themselves. The call `handle.get(parameters=params)` moves the subsets to the local disk. Passing the bbox parameter enables the butler to transfer only the pixels inside the bounding box.\n", |
601 | 603 | "\n", |
602 | | - "Since the galaxies may not be centered in the middle of pixels, use the `geom.Point2D` to convert the ra and dec to floating point pixel coordinates, rather than rounded integer types returned by `Point2I`. The example below will use the `geom.Box2I.makeCenteredBox` method, which will take as input the subset center and subset edge size, rather than the bottom left coordinate of the subset. This simplifies the bounding box definition for this example.\n", |
| 604 | + "Since the galaxies may not be centered in the middle of pixels, use the `Point2D` to convert the ra and dec to floating point pixel coordinates, rather than rounded integer types returned by `Point2I`. The example below will use the `Box2I.makeCenteredBox` method, which will take as input the subset center and subset edge size, rather than the bottom left coordinate of the subset. This simplifies the bounding box definition for this example.\n", |
603 | 605 | "\n", |
604 | 606 | "First, define a list of targets in a dictionary containing bright (V band magnitude < 22) variability selected galaxies hosting active galactic nuclei (AGN) in the ECDFS field from <a href=\"https://ui.adsabs.harvard.edu/abs/2009A%26A...497...81B/abstract\">Boutsia et al. 2009</a>." |
605 | 607 | ] |
|
703 | 705 | "for idx, (target, handle) in enumerate(deferred_handles):\n", |
704 | 706 | "\n", |
705 | 707 | " radec = geom.SpherePoint(target['ra'], target['dec'], geom.degrees)\n", |
706 | | - " xy = geom.Point2D(wcs.skyToPixel(radec))\n", |
| 708 | + " xy = Point2D(wcs.skyToPixel(radec))\n", |
707 | 709 | "\n", |
708 | | - " selection_bbox = geom.Box2I.makeCenteredBox(xy, geom.Extent2I(subset_size, subset_size))\n", |
| 710 | + " selection_bbox = Box2I.makeCenteredBox(xy, Extent2I(subset_size, subset_size))\n", |
709 | 711 | " params = {'bbox': selection_bbox}\n", |
710 | 712 | " \n", |
711 | 713 | " subset = handle.get(parameters=params)\n", |
|
716 | 718 | " vmin, vmax = zscale.get_limits(img_array)\n", |
717 | 719 | " ax = axes[idx]\n", |
718 | 720 | "\n", |
719 | | - " ax.imshow(img_array, origin='lower')#, vmin=vmin, vmax=vmax)#, cmap='gray')\n", |
| 721 | + " ax.imshow(img_array, origin='lower')\n", |
720 | 722 | " ax.set_title(f\"{target['id']}\")\n", |
721 | 723 | "\n", |
722 | 724 | "for i in range(len(targets), len(axes)):\n", |
|
0 commit comments