Skip to content
This repository was archived by the owner on Apr 28, 2025. It is now read-only.

Commit 10219d7

Browse files
committed
a few mods to the last section
1 parent 189cb8f commit 10219d7

1 file changed

Lines changed: 71 additions & 41 deletions

File tree

04_Intro_to_Butler.ipynb

Lines changed: 71 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
"metadata": {},
66
"source": [
77
"<img align=\"left\" src = https://project.lsst.org/sites/default/files/Rubin-O-Logo_0.png width=250> \n",
8-
"<b>Introduction to the LSST data Butler</b> <br>\n",
9-
"Last verified to run on <b>TBD</b> with LSST Science Pipelines release <b>TBD</b> <br>\n",
8+
"<b>Introduction to the LSST Data Butler</b> <br>\n",
9+
"Last verified to run on <b>2020-06-10</b> with LSST Science Pipelines release <b>w_2020_20</b> <br>\n",
1010
"Contact author: Alex Drlica-Wagner <br>\n",
1111
"Credit: Originally developed by Alex Drlica-Wagner in the context of the LSST Stack Club <br>\n",
1212
"Target audience: All DP0 delegates. <br>\n",
@@ -22,8 +22,8 @@
2222
"The goals of this notebook are to:<br>\n",
2323
"1. create an instance of the Butler<br>\n",
2424
"2. explore the DP0.1 data repository<br>\n",
25-
"3. retrive and display some image and catalog data<br>\n",
26-
"4. create in image cutout at a user-specified coordinate<br>\n",
25+
"3. retrieve and display some image and catalog data<br>\n",
26+
"4. create an image cutout at a specific location<br>\n",
2727
"5. retrieve and plot catalog data \n",
2828
"\n",
2929
"\n",
@@ -58,6 +58,7 @@
5858
"source": [
5959
"# Generic imports\n",
6060
"import os,glob\n",
61+
"import numpy as np\n",
6162
"import pylab as plt\n",
6263
"plt.rcParams['figure.figsize'] = (8.0, 8.0)"
6364
]
@@ -67,9 +68,7 @@
6768
"metadata": {},
6869
"source": [
6970
"We import several packages from the LSST Science Pipelines. \n",
70-
"The first import gives us access to the Butler, while the second provides tools for displaying data.\n",
71-
"\n",
72-
"More details and techniques regarding image display can be found in the `rubin-dp0` GitHub Organization's [tutorial-notebooks](https://github.com/rubin-dp0/tutorial-notebooks) repository."
71+
"The first import gives us access to the Butler, while the second provides tools for displaying data. More details about image display can be found in the `rubin-dp0` GitHub Organization's [tutorial-notebooks](https://github.com/rubin-dp0/tutorial-notebooks) repository."
7372
]
7473
},
7574
{
@@ -88,7 +87,7 @@
8887
"cell_type": "markdown",
8988
"metadata": {},
9089
"source": [
91-
"To create the Butler, we need to provide it with a path to the data set, which is called a \"data repository\". Butler repositories can be remote (i.e., pointing to an S3 bucket) or local (i.e., pointing to a directory on the local file system). In this case, we point to an S3 bucket."
90+
"To create the Butler, we need to provide it with a path to the data set, which is called a \"data repository\". The Butler can access repositories that are remote (e.g., pointing to an S3 bucket) or local (e.g., pointing to a path on the local file system). In this case, we point to an S3 bucket."
9291
]
9392
},
9493
{
@@ -101,6 +100,23 @@
101100
"butler = dafButler.Butler(repo)"
102101
]
103102
},
103+
{
104+
"cell_type": "markdown",
105+
"metadata": {},
106+
"source": [
107+
"We now have an instance of the Butler that we can explore with the Python `help` function."
108+
]
109+
},
110+
{
111+
"cell_type": "code",
112+
"execution_count": null,
113+
"metadata": {},
114+
"outputs": [],
115+
"source": [
116+
"# Uncomment the following line to see the Butler help documentation\n",
117+
"#help(butler)"
118+
]
119+
},
104120
{
105121
"cell_type": "markdown",
106122
"metadata": {},
@@ -118,7 +134,7 @@
118134
"source": [
119135
"registry = butler.registry\n",
120136
"\n",
121-
"# We can examine the registry with\n",
137+
"# We can also examine the registry\n",
122138
"#help(registry)"
123139
]
124140
},
@@ -143,15 +159,15 @@
143159
"cell_type": "markdown",
144160
"metadata": {},
145161
"source": [
146-
"This is our first glimpse at the data contained in the repository, but it doesn't teach us *which* collection we are actually interested in. The names do give us some hints though...\n",
162+
"This is our first glimpse at the data sets contained in the repository, but it doesn't teach us *which* collection we are actually interested in. The names do give us some hints though...\n",
147163
"\n",
148-
"* `2.2i` - refers to the processing run of the LSST DESC DC2 data (the `i` stands for `imSim`)\n",
164+
"* `2.2i` - refers to the processing run of the LSST DESC DC2 data (the `i` stands the `imSim` tool that was used to simulate the images)\n",
149165
"* `calib` - refers to calibration products that are used for instrument signature removal\n",
150166
"* `runs` - refers to processed data products\n",
151167
"* `refcats` - refers to the reference catalogs used for astrometric and photometric calibration\n",
152168
"* `skymaps` - are the geometric representations of the sky coverage\n",
153169
"\n",
154-
"Collections can be nested, so we can access to everything for DC2 Run 2.2i (the primary DP0.1 data set) by selecting the collection `2.2i/runs/DP0.1`. This is a pointer to other collections that expand out recursively... More on collections can be found here: https://pipelines.lsst.io/v/weekly/modules/lsst.daf.butler/organizing.html#collections"
170+
"Collections can be nested, so we can access to everything for DC2 Run 2.2i (the primary DP0.1 data set) by selecting the collection `2.2i/runs/DP0.1`. This is a pointer to other collections that expand out recursively... More on collections can be found [here](https://pipelines.lsst.io/v/weekly/modules/lsst.daf.butler/organizing.html#collections)."
155171
]
156172
},
157173
{
@@ -171,7 +187,7 @@
171187
"cell_type": "markdown",
172188
"metadata": {},
173189
"source": [
174-
"We now create a new Butler instance specifying that we are specifically interested in the `2.2i/runs/DP0.1` data collection. For most uses, this will be the line you will use to create a Butler to work on DP0.1, since you now know that this collection exists."
190+
"We now create a new Butler instance specifying that we are specifically interested in the `2.2i/runs/DP0.1` data collection. For most uses, this will be the line you will use to create a Butler to work on DP0.1."
175191
]
176192
},
177193
{
@@ -213,20 +229,20 @@
213229
"- `src` - refers the the catalog of sources\n",
214230
"- `skyMap` - refers to geometric representations of the sky coverage\n",
215231
"\n",
232+
"You can look up these and other LSST terms in the searchable [LSST Glossary](https://www.lsst.org/scientists/glossary-acronyms).\n",
233+
"\n",
216234
"<b> Which data sets are most appropriate for DP0.1? </b><br>\n",
217235
"Most DP0.1 delegates will only be interested in data sets with types `ExposureF` or `SourceCatalog`. \n",
218236
"For images, stick to the `calexp` (processed visit images, or PVIs) and `deepCoadd` (stacked PVIs).\n",
219-
"For catalogs, the `src` should be used with the `calexp` images, and the `deepCoadd_forced_src` are the most appropriate to be used with the `coadds`.\n",
220-
"More information can be found in the DP0.1 Data Products Definitions Document (DPDD) at [dp0-1.lsst.io](http://dp0-1.lsst.io).\n",
221-
"\n",
222-
"<br>\n"
237+
"For catalogs, the `src` table should be used with the `calexp` images, and the `deepCoadd_forced_src` table are the most appropriate to be used with the `deepCoadd`.\n",
238+
"More information can be found in the DP0.1 Data Products Definitions Document (DPDD) at [dp0-1.lsst.io](http://dp0-1.lsst.io)."
223239
]
224240
},
225241
{
226242
"cell_type": "markdown",
227243
"metadata": {},
228244
"source": [
229-
"We access specific data sets through a set of specifications known as a data identifier (`dataId`). Each `DatasetType` can be identified with a different set of properties, so it is important to be able to determine what properties need to be specified to access data of a specific type. It is possible to get all `DatasetRef` (which include the `dataId`) for a specific `datasetType` in a specific collection with a query like this. Note that this doesn't necessarily guarentee that the specific data set exists, so we include a check that the data set has a valid Uniform Resource Identifier (URI)."
245+
"We access specific data sets through a set of specifications known as a data identifier (`dataId`). Each `DatasetType` can be identified with a different set of properties, so it is important to be able to determine what properties need to be specified to access data of a specific type. It is possible to get all `DatasetRef` (which include the `dataId`) for a specific `datasetType` in a specific collection with a query like this. Note that this doesn't necessarily guarentee that the specific data set exists, so we include a check that the data set has a valid ."
230246
]
231247
},
232248
{
@@ -247,7 +263,7 @@
247263
"cell_type": "markdown",
248264
"metadata": {},
249265
"source": [
250-
"We can get the path from the URI that is returned by `butler.getURI`. Note that this URI does not refer to a local path on the filesystem. We do not need to know exactly where the data live in order to access it. That's the power of the Butler."
266+
"In the code above we were accessing the Uniform Resource Identifier (URI) for each data product from `butler.getURI`. Note that in this case, the URI is pointing to an S3 bucket and not a local path on the filesystem. We do not need to know exactly where the data live in order to access it. That's the power of the Butler."
251267
]
252268
},
253269
{
@@ -266,7 +282,7 @@
266282
"cell_type": "markdown",
267283
"metadata": {},
268284
"source": [
269-
"Now say we want to restrict our selection to datasets associated with a specific filter. We can add that constraint to our query, but first we need to figure out what the filters are called... Looking at the dataId object, we see the attributes `physical_filter` and `band` look promising."
285+
"Now say we want to restrict our selection to images that were taken in a specific optical filter. We can add that constraint to our query, but first we need to figure out what the LSST filters are called... Looking at the `dataId`, we see that the attribute `band` looks promising."
270286
]
271287
},
272288
{
@@ -284,7 +300,6 @@
284300
"metadata": {},
285301
"outputs": [],
286302
"source": [
287-
"print(f\"physical_filter = {ref.dataId['physical_filter']}\")\n",
288303
"print(f\"band = {ref.dataId['band']}\")"
289304
]
290305
},
@@ -335,7 +350,7 @@
335350
"# We could pass the datasetRef that we found above, but since the query may \n",
336351
"# return results in a different order we define the dataId explicitly for reproducibility. \n",
337352
"dataId = {'visit': '703697', 'detector': 80, 'band':'g'}\n",
338-
"calexp = butler.get('calexp',dataId=dataId)\n",
353+
"calexp = butler.get('calexp', dataId=dataId)\n",
339354
"\n",
340355
"# This will print a warning related to the gen2 to gen3 Butler conversion that was performed on DP0.1"
341356
]
@@ -344,7 +359,7 @@
344359
"cell_type": "markdown",
345360
"metadata": {},
346361
"source": [
347-
"The `calexp` is a calibrated CCD from a single exposure. We'll use the afwDisplay interface to show the pixel values and mask plane (more on afwDisplay can be found in other notebooks)."
362+
"The `calexp`, also known as a \"Processed Visit Image\" (PVI), is a calibrated CCD from a single exposure. We'll use the afwDisplay interface to show the pixel values and mask plane (more on afwDisplay can be found in other notebooks)."
348363
]
349364
},
350365
{
@@ -373,10 +388,9 @@
373388
"metadata": {},
374389
"outputs": [],
375390
"source": [
376-
"# We could get the src table using the dataId as we did above for the calexp, \n",
377-
"# but this would require the butler to perform another query of the database. \n",
378-
"# Instead, we can just pass the ref itself directly to butler.get\n",
379-
"src = butler.get('src',dataId)\n",
391+
"# We can get the src table using the dataId as we did above for the calexp\n",
392+
"# (note that it is also possible to pass the data ref)\n",
393+
"src = butler.get('src',dataId=dataId)\n",
380394
"src = src.copy(True)\n",
381395
"src.asAstropy()"
382396
]
@@ -385,7 +399,7 @@
385399
"cell_type": "markdown",
386400
"metadata": {},
387401
"source": [
388-
"We can now plot the `calexp` with the `src` catalog overlaid. We leave an investigation of this image as an exercise to the user :)"
402+
"We can now plot the `calexp` with the `src` catalog overlaid. We'll leave further investigation of this image as an exercise to the user :)"
389403
]
390404
},
391405
{
@@ -413,7 +427,7 @@
413427
"source": [
414428
"### 4. How to query for multiple data sets\n",
415429
"\n",
416-
"In the case above, both the `calexp` and `src` can be found by the registry, but this will not always necessarily be the case. The `queryDimensions` method provides a more flexible way to query for multiple datasets (requiring an instance of all datasets to be available for that dataId) or ask for different dataId keys than what is used to identify the dataset (which invokes various built-in relationships). An example of this is provided below:"
430+
"In the case above, both the `calexp` and `src` can be found by the registry, but this will not always necessarily be the case. The `queryDimensions` method provides a more flexible way to query for multiple datasets (requiring an instance of all datasets to be available for that `dataId`) or ask for different `dataId` keys than what is used to identify the dataset (which invokes various built-in relationships). An example of this is provided below:"
417431
]
418432
},
419433
{
@@ -469,7 +483,7 @@
469483
"source": [
470484
"### 5. Generate an Image Cutout\n",
471485
"\n",
472-
"Say we want to grab a cutout of the DP0.1 coadded images at a specific location. In order to do this, we need a few other packages from the LSST Science Pipelines. In particular, access to the geometry and coordinate packages."
486+
"Now say we want to grab a cutout of the DP0.1 coadded images at a specific location. In order to do this, we need a few other packages from the LSST Science Pipelines. In particular, access to the geometry and coordinate packages."
473487
]
474488
},
475489
{
@@ -482,6 +496,13 @@
482496
"import lsst.afw.coord as afwCoord"
483497
]
484498
},
499+
{
500+
"cell_type": "markdown",
501+
"metadata": {},
502+
"source": [
503+
"Next we define a `cutout_coadd` function to query an instance of the Butler for a cutout image at a specific location, band, and size."
504+
]
505+
},
485506
{
486507
"cell_type": "code",
487508
"execution_count": null,
@@ -565,11 +586,11 @@
565586
"cell_type": "markdown",
566587
"metadata": {},
567588
"source": [
568-
"### 6. Retrieve and plot catalog data from the Butler\n",
589+
"### 6. Exploring and retrieving catalog data from the Butler\n",
569590
"\n",
570-
"The TAP service is the recommended way to retrieve DP0.1 catalog data for a notebook, and there are several other tutuorials that demonstrate how to use the TAP service.\n",
591+
"The TAP service is the recommended way to retrieve DP0.1 catalog data for a notebook, and there are several other [tutuorials](https://github.com/rubin-dp0/tutorial-notebooks) that demonstrate how to use the TAP service.\n",
571592
"\n",
572-
"But if Butler access to catalog data is needed, an easy way to start is by retrieving only the schema data set for a Butler catalog, which can be done without specifying the ``dataId``. "
593+
"However, as we saw above, the Butler can also be used to access to catalog data. We can investigate the table schema for a specific source catalog by Butler appending `_schema` to the `datasetType`. Note that this does not require you to specify the ``dataId``. "
573594
]
574595
},
575596
{
@@ -586,7 +607,7 @@
586607
"cell_type": "markdown",
587608
"metadata": {},
588609
"source": [
589-
"Each of the following lines will print the schema to the screen in different ways."
610+
"The table `schema` stores information about the columns stored in the table. Each of the following lines will print the schema to the screen in different ways."
590611
]
591612
},
592613
{
@@ -643,7 +664,8 @@
643664
"# Print the associated docstring for each of the named columns of interest\n",
644665
"for name in ['base_SdssShape_psf_xx','base_SdssShape_psf_yy','base_SdssShape_psf_xy']:\n",
645666
" doc = schema_dict[name].getField().getDoc()\n",
646-
" print(name, ' = ', doc)"
667+
" units = schema_dict[name].getField().getUnits()\n",
668+
" print(name, '[%s]'%units, ' = ', doc)"
647669
]
648670
},
649671
{
@@ -658,7 +680,7 @@
658680
"metadata": {},
659681
"source": [
660682
"<br>\n",
661-
"The catalogs are very large and it is not feasible to try and retrieve it in its entirety.\n",
683+
"The full catalogs are very large and it is not feasible to try and retrieve them in their entirety.\n",
662684
"Instead, in this example we identify the tract and patch of interest and retrieve only catalog data for a small region of sky.\n",
663685
"Use the same ra and dec coordinates as above to find the patch and tract."
664686
]
@@ -684,7 +706,7 @@
684706
"coaddId = {'tract': tract, 'patch': patch, 'band':'i'}\n",
685707
"\n",
686708
"coadd_src = butler.get('deepCoadd_forced_src',coaddId)\n",
687-
"coadd_src = src.copy(True)"
709+
"coadd_src = coadd_src.copy(True)"
688710
]
689711
},
690712
{
@@ -748,7 +770,7 @@
748770
"cell_type": "markdown",
749771
"metadata": {},
750772
"source": [
751-
"Plot the locations of sources in the patch."
773+
"Plot the locations of sources in the patch as well as the ra,dec that we requested. Note that the `coord_ra` and `coord_dec` are in radians, so we need to convert them to degrees."
752774
]
753775
},
754776
{
@@ -758,11 +780,19 @@
758780
"outputs": [],
759781
"source": [
760782
"fig = plt.figure()\n",
761-
"plt.plot( data['coord_ra'].values, data['coord_dec'].values, 'o', ms=2, alpha=0.5 )\n",
762-
"plt.xlabel('RA')\n",
763-
"plt.ylabel('Dec')\n",
783+
"plt.plot(np.degrees(data['coord_ra'].values), np.degrees(data['coord_dec'].values), 'o', ms=2, alpha=0.5 )\n",
784+
"plt.plot(ra,dec,'*',ms=25, mec='k')\n",
785+
"plt.xlabel('RA (deg)')\n",
786+
"plt.ylabel('Dec (deg)')\n",
764787
"plt.title('Butler coadd_forced_src objects in tract 4638 patch 43')"
765788
]
789+
},
790+
{
791+
"cell_type": "code",
792+
"execution_count": null,
793+
"metadata": {},
794+
"outputs": [],
795+
"source": []
766796
}
767797
],
768798
"metadata": {

0 commit comments

Comments
 (0)