Skip to content

Commit

Permalink
create reproject notebook (#471)
Browse files Browse the repository at this point in the history
* create reproject notebook

* black formatting

* grammar and text changes
  • Loading branch information
maxwest-uw authored Feb 12, 2024
1 parent 2c49ee0 commit 5d9ef50
Showing 1 changed file with 240 additions and 0 deletions.
240 changes: 240 additions & 0 deletions notebooks/reprojection/reproject_demo.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "b8f82eaa-bed0-4643-927a-e311918afbd4",
"metadata": {},
"source": [
"# Reprojection Demo\n",
"\n",
"A notebook on how to use the `kbmod.reprojection` module to reproject WorkUnits into a common WCS frame of reference."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5ca16b19-27be-4569-b3f8-644e81604895",
"metadata": {},
"outputs": [],
"source": [
"from kbmod.work_unit import WorkUnit\n",
"from kbmod import reprojection\n",
"\n",
"import matplotlib.pyplot as plt\n",
"from astropy.nddata import CCDData\n",
"\n",
"import numpy as np\n",
"from os import path\n",
"\n",
"\n",
"# visualization utility.\n",
"def plot_images(obstimes, image1=None, image2=None, image3=None, image4=None):\n",
" \"\"\"Plot up to four images (`astropy.nddata.CCDData` objects) side by side\"\"\"\n",
"\n",
" min_val = -1.0\n",
" fig = plt.figure(figsize=(10, 10))\n",
" if image1:\n",
" f1 = fig.add_subplot(2, 2, 1, projection=image1.wcs)\n",
" f1.title.set_text(str(obstimes[0]))\n",
" plt.imshow(image1.data, vmin=min_val, origin=\"lower\")\n",
" plt.grid(color=\"white\", ls=\"solid\")\n",
" if image2:\n",
" f2 = fig.add_subplot(2, 2, 2, projection=image2.wcs)\n",
" f2.title.set_text(str(obstimes[1]))\n",
" plt.imshow(image2.data, vmin=min_val, origin=\"lower\")\n",
" plt.grid(color=\"white\", ls=\"solid\")\n",
" if image3:\n",
" f3 = fig.add_subplot(2, 2, 3, projection=image3.wcs)\n",
" f3.title.set_text(str(obstimes[2]))\n",
" plt.imshow(image3.data, vmin=min_val, origin=\"lower\")\n",
" plt.grid(color=\"white\", ls=\"solid\")\n",
" if image4:\n",
" f4 = fig.add_subplot(2, 2, 4, projection=image4.wcs)\n",
" f4.title.set_text(str(obstimes[3]))\n",
" plt.imshow(image4.data, vmin=min_val, origin=\"lower\")\n",
" plt.grid(color=\"white\", ls=\"solid\")"
]
},
{
"cell_type": "markdown",
"id": "5667adeb-7648-4b37-a710-29a4a86f4cc6",
"metadata": {},
"source": [
"## Simple Reproject\n",
"\n",
"This the first and simplest type of reprojection that we do. Given a `kbmod.search.WorkUnit` with images of differing WCSs, choose a common WCS and reproject all the images to it.\n",
"\n",
"First, we'll need a WorkUnit. Let's use the same one we usually use for reprojection testing."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "131104b1-fb07-4e47-8932-1f844db60002",
"metadata": {},
"outputs": [],
"source": [
"project_root_dir = path.abspath((path.dirname(path.dirname(path.abspath(\"\")))))\n",
"fake_data_loc = \"tests/data/shifted_wcs_diff_dimms_tiled.fits\"\n",
"\n",
"wunit = WorkUnit.from_fits(path.join(project_root_dir, fake_data_loc))\n",
"wunit"
]
},
{
"cell_type": "markdown",
"id": "2a90c803-ecf6-43eb-b6b8-79d96c3df305",
"metadata": {},
"source": [
"Let's take a peek into this WorkUnit and see what kind of data we have."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7cab183f-dae2-4349-af9c-f667bc212651",
"metadata": {},
"outputs": [],
"source": [
"original_images = wunit.im_stack.get_images()\n",
"\n",
"o_image0 = CCDData(original_images[0].get_science().image, unit=\"adu\")\n",
"o_image0.wcs = wunit.per_image_wcs[0]\n",
"\n",
"o_image1 = CCDData(original_images[1].get_science().image, unit=\"adu\")\n",
"o_image1.wcs = wunit.per_image_wcs[1]\n",
"\n",
"o_image2 = CCDData(original_images[2].get_science().image, unit=\"adu\")\n",
"o_image2.wcs = wunit.per_image_wcs[2]\n",
"\n",
"o_image3 = CCDData(original_images[3].get_science().image, unit=\"adu\")\n",
"o_image3.wcs = wunit.per_image_wcs[3]\n",
"\n",
"plot_images(wunit.get_all_obstimes(), o_image0, o_image1, o_image2, o_image3)"
]
},
{
"cell_type": "markdown",
"id": "dbd3ff9f-62ef-42c8-820f-ca26214d4214",
"metadata": {},
"source": [
"A couple of important attributes to point ou:\n",
"- Each images has a different WCS. The center ra/dec value shifted up and to the right ~5 pixels in each successive images, except for the last one which is below image 3.\n",
"- The `obstime` is increasing for each one, except for the last one which has the same obstime as image 3.\n",
"- They all have a synthetic object in them, moving across the field of view. The last image has a presumambly different object.\n",
"- Image 3 and 4 are from the same \"observation\", with the same obstime and aligned, to simulate the case where we have multiple tiled detectors from a given observation.\n",
" - This is done mainly to handle the LSST case where observations will have to be built out of many different detectors as everything isn't neatly aligned like in DEEP.\n",
" \n",
"With that, let's reproject the images and see how reprojection behaves.\n",
"\n",
"### Reprojection\n",
"\n",
"we'll define a `common_wcs`, in this case the WCS of the first image in the stack. From there, we can run the original work unit through our reprojection module and get a new WorkUnit, where everything has been reprojected into the provided `common_wcs`."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "20a1450e-a963-4fef-b081-13f9489878ab",
"metadata": {},
"outputs": [],
"source": [
"common = wunit.per_image_wcs[0]\n",
"\n",
"uwunit = reprojection.reproject_work_unit(wunit, common)"
]
},
{
"cell_type": "markdown",
"id": "9243cdb2-0afb-47b7-975f-c5e3f6aaddfa",
"metadata": {},
"source": [
"And now let's take a look at the results."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8a5927ff-16f7-45d3-9ceb-77528ba81009",
"metadata": {},
"outputs": [],
"source": [
"images = uwunit.im_stack.get_images()\n",
"\n",
"image0 = CCDData(images[0].get_science().image, unit=\"adu\")\n",
"image0.wcs = uwunit.wcs\n",
"\n",
"image1 = CCDData(images[1].get_science().image, unit=\"adu\")\n",
"image1.wcs = uwunit.wcs\n",
"\n",
"image2 = CCDData(images[2].get_science().image, unit=\"adu\")\n",
"image2.wcs = uwunit.wcs\n",
"\n",
"plot_images(uwunit.get_all_obstimes(), image0, image1, image2)"
]
},
{
"cell_type": "markdown",
"id": "fa9ace16-f9ec-4354-995b-6bded519528d",
"metadata": {},
"source": [
"All of the images are now in the same WCS, which required some shifting - it's hard to see in this view but along the left edge of the images except for the first have `KB_NO_DATA` for a lot of the pixels now. In addition, there are now only 3 images, as the last two were combined into one image as they had the same obstime. Also note that the first image has had no changes made to it, as we used its WCS, resulting in a no-op.\n",
"\n",
"**Important Note:** We were only able to combine the last two images into one because they weren't overlapping. Current constraints mean that if the two images have the same `obstime` but an overlapping footprint, an error will be thrown.\n",
"\n",
"The reprojection will also change the variance and mask layers of the original `LayeredImage`. See below:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d2dab3ca-e784-4b55-b70a-56ef7eadffea",
"metadata": {},
"outputs": [],
"source": [
"original_img = wunit.im_stack.get_single_image(2)\n",
"o_d = original_img.get_mask().image\n",
"original_image2_mask = CCDData(o_d, unit=\"adu\")\n",
"original_image2_mask.wcs = wunit.per_image_wcs[2]\n",
"\n",
"image2_mask = CCDData(images[2].get_mask().image, unit=\"adu\")\n",
"image2_mask.wcs = uwunit.wcs\n",
"\n",
"plot_images([uwunit.get_all_obstimes()[-1]] * 2, original_image2_mask, image2_mask)"
]
},
{
"cell_type": "markdown",
"id": "da33a533-67c4-4f8d-a945-922edad318e8",
"metadata": {},
"source": [
"Looking at the difference between the original mask and the new one, there was a line in the original mask that transfered over (the one around 02\"). You can also see more clearly the parts with no data in the new image, on the left side as well as the line on the bottom that represents the \"chip gap\" between image 3 and 4 in the original `ImageStack`.\n",
"\n",
"## Barycentric Projection\n",
"\n",
"Coming soon!"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "kbmod",
"language": "python",
"name": "kbmod"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.13"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

0 comments on commit 5d9ef50

Please sign in to comment.