{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# How to Find DM Stack Documentation\n", "\n", "
Author(s): **Phil Marshall** ([@drphilmarshall](https://github.com/LSSTScienceCollaborations/StackClub/issues/new?body=@drphilmarshall))\n", "
Maintainer(s): **Alex Drlica-Wagner** ([@kadrlica](https://github.com/LSSTScienceCollaborations/StackClub/issues/new?body=@kadrlica))\n", "
Level: **Introductory**\n", "
Last Verified to Run: **2021-03-31**\n", "
Verified Stack Release: **21.0.0**\n", "\n", "### Learning Objectives:\n", "\n", "In this notebook we will look at a few different ways to find the documentation on a given DM Stack function or class. \n", "After working through this tutorial you should be able to: \n", "1. Use the jupyter notebook built-in functions to read the docstrings of Stack classes and functions \n", "2. Use the `where_is` Stack Club utility to locate DM Stack web documentation.\n", "\n", "### Logistics\n", "This notebook is intended to be runnable on `lsst-lsp-stable.ncsa.illinois.edu` from a local git clone of https://github.com/LSSTScienceCollaborations/StackClub.\n", "\n", "## Set-up" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "execution": { "iopub.execute_input": "2021-04-23T20:41:47.950602Z", "iopub.status.busy": "2021-04-23T20:41:47.947329Z", "iopub.status.idle": "2021-04-23T20:41:50.162055Z", "shell.execute_reply": "2021-04-23T20:41:50.160797Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "nb-kadrlica-r21-0-0\r\n", "lsst_distrib 21.0.0+973e4c9e85 \tcurrent v21_0_0 setup\r\n" ] } ], "source": [ "# What version of the Stack are we using?\n", "! echo $HOSTNAME\n", "! eups list -s | grep lsst_distrib" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We'll need the `stackclub` package to be installed. If you are not developing this package, and you have permission to write to your base python site-packages, you can install it using `pip`, like this:\n", "```\n", "pip install git+git://github.com/LSSTScienceCollaborations/StackClub.git#egg=stackclub\n", "```\n", "If you are developing the `stackclub` package (eg by adding modules to it to support the Stack Club tutorial that you are writing), you'll need to make a local, editable installation, like this:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "execution": { "iopub.execute_input": "2021-04-23T20:41:50.174478Z", "iopub.status.busy": "2021-04-23T20:41:50.171348Z", "iopub.status.idle": "2021-04-23T20:41:52.212871Z", "shell.execute_reply": "2021-04-23T20:41:52.213991Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "/home/kadrlica/notebooks/.beavis/StackClub/GettingStarted\r\n" ] } ], "source": [ "! cd .. && python setup.py -q develop --user && cd -" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When editing the `stackclub` package files, we want the latest version to be imported when we re-run the import command. To enable this, we need the %autoreload magic command." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "execution": { "iopub.execute_input": "2021-04-23T20:41:52.224786Z", "iopub.status.busy": "2021-04-23T20:41:52.223541Z", "iopub.status.idle": "2021-04-23T20:41:52.254595Z", "shell.execute_reply": "2021-04-23T20:41:52.253509Z" } }, "outputs": [], "source": [ "%load_ext autoreload\n", "%autoreload 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Inline Notebook Help\n", "\n", "Command line tasks have usage information - try running them with no arguments, or `--help`." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "execution": { "iopub.execute_input": "2021-04-23T20:41:52.269758Z", "iopub.status.busy": "2021-04-23T20:41:52.268673Z", "iopub.status.idle": "2021-04-23T20:41:56.132810Z", "shell.execute_reply": "2021-04-23T20:41:56.131486Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "usage: imageDifference.py input [options]\r\n", "\r\n", "positional arguments:\r\n", " input path to input data repository, relative to $PIPE_INPUT_ROOT\r\n", "\r\n", "optional arguments:\r\n", " -h, --help show this help message and exit\r\n", " --calib RAWCALIB path to input calibration repository, relative to $PIPE_CALIB_ROOT\r\n", " --output RAWOUTPUT path to output data repository (need not exist), relative to $PIPE_OUTPUT_ROOT\r\n", " --rerun [INPUT:]OUTPUT\r\n", " rerun name: sets OUTPUT to ROOT/rerun/OUTPUT; optionally sets ROOT to ROOT/rerun/INPUT\r\n", " -c [NAME=VALUE [NAME=VALUE ...]], --config [NAME=VALUE [NAME=VALUE ...]]\r\n", " config override(s), e.g. -c foo=newfoo bar.baz=3\r\n", " -C [CONFIGFILE [CONFIGFILE ...]], --configfile [CONFIGFILE [CONFIGFILE ...]]\r\n", " config override file(s)\r\n", " -L [LEVEL|COMPONENT=LEVEL [LEVEL|COMPONENT=LEVEL ...]], --loglevel [LEVEL|COMPONENT=LEVEL [LEVEL|COMPONENT=LEVEL ...]]\r\n", " logging level; supported levels are [trace|debug|info|warn|error|fatal]\r\n", " --longlog use a more verbose format for the logging\r\n", " --debug enable debugging output?\r\n", " --doraise raise an exception on error (else log a message and continue)?\r\n", " --noExit Do not exit even upon failure (i.e. return a struct to the calling script)\r\n", " --profile PROFILE Dump cProfile statistics to filename\r\n", " --show SHOW [SHOW ...]\r\n", " display the specified information to stdout and quit (unless run is specified); information is\r\n", " (config[=PATTERN]|history=PATTERN|tasks|data|run)\r\n", " -j PROCESSES, --processes PROCESSES\r\n", " Number of processes to use\r\n", " -t TIMEOUT, --timeout TIMEOUT\r\n", " Timeout for multiprocessing; maximum wall time (sec)\r\n", " --clobber-output remove and re-create the output directory if it already exists (safe with -j, but not all other forms of\r\n", " parallel execution)\r\n", " --clobber-config backup and then overwrite existing config files instead of checking them (safe with -j, but not all other\r\n", " forms of parallel execution)\r\n", " --no-backup-config Don't copy config to file~N backup.\r\n", " --clobber-versions backup and then overwrite existing package versions instead of checkingthem (safe with -j, but not all\r\n", " other forms of parallel execution)\r\n", " --no-versions don't check package versions; useful for development\r\n", " --id [KEY=VALUE1[^VALUE2[^VALUE3...] [KEY=VALUE1[^VALUE2[^VALUE3...] ...]]\r\n", " data ID, e.g. --id visit=12345 ccd=1,2\r\n", " --templateId [KEY=VALUE1[^VALUE2[^VALUE3...] [KEY=VALUE1[^VALUE2[^VALUE3...] ...]]\r\n", " Template data ID in case of calexp template, e.g. --templateId visit=6789\r\n", "\r\n", "Notes:\r\n", " * --config, --configfile, --id, --loglevel and @file may appear multiple times;\r\n", " all values are used, in order left to right\r\n", " * @file reads command-line options from the specified file:\r\n", " * data may be distributed among multiple lines (e.g. one option per line)\r\n", " * data after # is treated as a comment and ignored\r\n", " * blank lines and lines starting with # are ignored\r\n", " * To specify multiple values for an option, do not use = after the option name:\r\n", " * right: --configfile foo bar\r\n", " * wrong: --configfile=foo bar\r\n" ] } ], "source": [ "! imageDifference.py --help" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The pipeline task python code also contains useful docstrings, accessible in various ways:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "execution": { "iopub.execute_input": "2021-04-23T20:41:56.143101Z", "iopub.status.busy": "2021-04-23T20:41:56.141804Z", "iopub.status.idle": "2021-04-23T20:41:58.610755Z", "shell.execute_reply": "2021-04-23T20:41:58.609554Z" } }, "outputs": [], "source": [ "from lsst.pipe.tasks.imageDifference import ImageDifferenceTask" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "execution": { "iopub.execute_input": "2021-04-23T20:41:58.617728Z", "iopub.status.busy": "2021-04-23T20:41:58.616468Z", "iopub.status.idle": "2021-04-23T20:41:58.679596Z", "shell.execute_reply": "2021-04-23T20:41:58.680824Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on class ImageDifferenceTask in module lsst.pipe.tasks.imageDifference:\n", "\n", "class ImageDifferenceTask(lsst.pipe.base.cmdLineTask.CmdLineTask, lsst.pipe.base.pipelineTask.PipelineTask)\n", " | ImageDifferenceTask(butler=None, **kwargs)\n", " | \n", " | Subtract an image from a template and measure the result\n", " | \n", " | Method resolution order:\n", " | ImageDifferenceTask\n", " | lsst.pipe.base.cmdLineTask.CmdLineTask\n", " | lsst.pipe.base.pipelineTask.PipelineTask\n", " | lsst.pipe.base.task.Task\n", " | builtins.object\n", " | \n", " | Methods defined here:\n", " | \n", " | __init__(self, butler=None, **kwargs)\n", " | !Construct an ImageDifference Task\n", " | \n", " | @param[in] butler Butler object to use in constructing reference object loaders\n", " | \n", " | fitAstrometry(self, templateSources, templateExposure, selectSources)\n", " | Fit the relative astrometry between templateSources and selectSources\n", " | \n", " | Todo\n", " | ----\n", " | \n", " | Remove this method. It originally fit a new WCS to the template before calling register.run\n", " | because our TAN-SIP fitter behaved badly for points far from CRPIX, but that's been fixed.\n", " | It remains because a subtask overrides it.\n", " | \n", " | getSchemaCatalogs(self)\n", " | Return a dict of empty catalogs for each catalog dataset produced by this task.\n", " | \n", " | run(self, exposure=None, selectSources=None, templateExposure=None, templateSources=None, idFactory=None, calexpBackgroundExposure=None, subtractedExposure=None)\n", " | PSF matches, subtract two images and perform detection on the difference image.\n", " | \n", " | Parameters\n", " | ----------\n", " | exposure : `lsst.afw.image.ExposureF`, optional\n", " | The science exposure, the minuend in the image subtraction.\n", " | Can be None only if ``config.doSubtract==False``.\n", " | selectSources : `lsst.afw.table.SourceCatalog`, optional\n", " | Identified sources on the science exposure. This catalog is used to\n", " | select sources in order to perform the AL PSF matching on stamp images\n", " | around them. The selection steps depend on config options and whether\n", " | ``templateSources`` and ``matchingSources`` specified.\n", " | templateExposure : `lsst.afw.image.ExposureF`, optional\n", " | The template to be subtracted from ``exposure`` in the image subtraction.\n", " | The template exposure should cover the same sky area as the science exposure.\n", " | It is either a stich of patches of a coadd skymap image or a calexp\n", " | of the same pointing as the science exposure. Can be None only\n", " | if ``config.doSubtract==False`` and ``subtractedExposure`` is not None.\n", " | templateSources : `lsst.afw.table.SourceCatalog`, optional\n", " | Identified sources on the template exposure.\n", " | idFactory : `lsst.afw.table.IdFactory`\n", " | Generator object to assign ids to detected sources in the difference image.\n", " | calexpBackgroundExposure : `lsst.afw.image.ExposureF`, optional\n", " | Background exposure to be added back to the science exposure\n", " | if ``config.doAddCalexpBackground==True``\n", " | subtractedExposure : `lsst.afw.image.ExposureF`, optional\n", " | If ``config.doSubtract==False`` and ``config.doDetection==True``,\n", " | performs the post subtraction source detection only on this exposure.\n", " | Otherwise should be None.\n", " | \n", " | Returns\n", " | -------\n", " | results : `lsst.pipe.base.Struct`\n", " | ``subtractedExposure`` : `lsst.afw.image.ExposureF`\n", " | Difference image.\n", " | ``matchedExposure`` : `lsst.afw.image.ExposureF`\n", " | The matched PSF exposure.\n", " | ``subtractRes`` : `lsst.pipe.base.Struct`\n", " | The returned result structure of the ImagePsfMatchTask subtask.\n", " | ``diaSources`` : `lsst.afw.table.SourceCatalog`\n", " | The catalog of detected sources.\n", " | ``selectSources`` : `lsst.afw.table.SourceCatalog`\n", " | The input source catalog with optionally added Qa information.\n", " | \n", " | Notes\n", " | -----\n", " | The following major steps are included:\n", " | \n", " | - warp template coadd to match WCS of image\n", " | - PSF match image to warped template\n", " | - subtract image from PSF-matched, warped template\n", " | - detect sources\n", " | - measure sources\n", " | \n", " | For details about the image subtraction configuration modes\n", " | see `lsst.ip.diffim`.\n", " | \n", " | runDataRef(self, sensorRef, templateIdList=None)\n", " | Subtract an image from a template coadd and measure the result.\n", " | \n", " | Data I/O wrapper around `run` using the butler in Gen2.\n", " | \n", " | Parameters\n", " | ----------\n", " | sensorRef : `lsst.daf.persistence.ButlerDataRef`\n", " | Sensor-level butler data reference, used for the following data products:\n", " | \n", " | Input only:\n", " | - calexp\n", " | - psf\n", " | - ccdExposureId\n", " | - ccdExposureId_bits\n", " | - self.config.coaddName + \"Coadd_skyMap\"\n", " | - self.config.coaddName + \"Coadd\"\n", " | Input or output, depending on config:\n", " | - self.config.coaddName + \"Diff_subtractedExp\"\n", " | Output, depending on config:\n", " | - self.config.coaddName + \"Diff_matchedExp\"\n", " | - self.config.coaddName + \"Diff_src\"\n", " | \n", " | Returns\n", " | -------\n", " | results : `lsst.pipe.base.Struct`\n", " | Returns the Struct by `run`.\n", " | \n", " | runDebug(self, exposure, subtractRes, selectSources, kernelSources, diaSources)\n", " | Make debug plots and displays.\n", " | \n", " | Todo\n", " | ----\n", " | Test and update for current debug display and slot names\n", " | \n", " | runQuantum(self, butlerQC: lsst.pipe.base.butlerQuantumContext.ButlerQuantumContext, inputRefs: lsst.pipe.base.connections.InputQuantizedConnection, outputRefs: lsst.pipe.base.connections.OutputQuantizedConnection)\n", " | Method to do butler IO and or transforms to provide in memory\n", " | objects for tasks run method\n", " | \n", " | Parameters\n", " | ----------\n", " | butlerQC : `ButlerQuantumContext`\n", " | A butler which is specialized to operate in the context of a\n", " | `lsst.daf.butler.Quantum`.\n", " | inputRefs : `InputQuantizedConnection`\n", " | Datastructure whose attribute names are the names that identify\n", " | connections defined in corresponding `PipelineTaskConnections`\n", " | class. The values of these attributes are the\n", " | `lsst.daf.butler.DatasetRef` objects associated with the defined\n", " | input/prerequisite connections.\n", " | outputRefs : `OutputQuantizedConnection`\n", " | Datastructure whose attribute names are the names that identify\n", " | connections defined in corresponding `PipelineTaskConnections`\n", " | class. The values of these attributes are the\n", " | `lsst.daf.butler.DatasetRef` objects associated with the defined\n", " | output connections.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Static methods defined here:\n", " | \n", " | makeIdFactory(expId, expBits)\n", " | Create IdFactory instance for unique 64 bit diaSource id-s.\n", " | \n", " | Parameters\n", " | ----------\n", " | expId : `int`\n", " | Exposure id.\n", " | \n", " | expBits: `int`\n", " | Number of used bits in ``expId``.\n", " | \n", " | Note\n", " | ----\n", " | The diasource id-s consists of the ``expId`` stored fixed in the highest value\n", " | ``expBits`` of the 64-bit integer plus (bitwise or) a generated sequence number in the\n", " | low value end of the integer.\n", " | \n", " | Returns\n", " | -------\n", " | idFactory: `lsst.afw.table.IdFactory`\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes defined here:\n", " | \n", " | ConfigClass = " ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "[`lsst.pipe.tasks.imageDifference`](https://github.com/lsst/pipe_tasks/blob/master/python/lsst/pipe/tasks/imageDifference.py)\n" ] } ], "source": [ "from lsst.pipe.tasks.imageDifference import ImageDifferenceTask\n", "where_is(ImageDifferenceTask)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "By default, `where_is` looks for the named object in the source code on GitHub. You can specify this behavior explitly with the `in_the` kwarg:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "execution": { "iopub.execute_input": "2021-04-23T20:41:58.970929Z", "iopub.status.busy": "2021-04-23T20:41:58.969602Z", "iopub.status.idle": "2021-04-23T20:41:58.996819Z", "shell.execute_reply": "2021-04-23T20:41:58.995756Z" } }, "outputs": [ { "data": { "text/markdown": [ "[`lsst.daf.persistence.butler`](https://github.com/lsst/daf_persistence/blob/master/python/lsst/daf/persistence/butler.py)" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "[`lsst.daf.persistence.butler`](https://github.com/lsst/daf_persistence/blob/master/python/lsst/daf/persistence/butler.py)\n" ] } ], "source": [ "from lsst.daf.persistence import Butler\n", "where_is(Butler.get, in_the='source')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "> In case you're interested in what the `where_is` function is doing, paste the following into a python cell: \n", "```\n", "%load ../stackclub/where_is\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "GitHub search is pretty powerful. Here's an example, using the search string `user:lsst ImageDifferenceTask` and selecting \"Code\" results (in python):\n", "\n", "https://github.com/search?l=Python&q=user%3Alsst+ImageDifferenceTask&type=Code\n", "\n", "You can also generate search strings like this one with `where_is`:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "execution": { "iopub.execute_input": "2021-04-23T20:41:59.002095Z", "iopub.status.busy": "2021-04-23T20:41:59.000905Z", "iopub.status.idle": "2021-04-23T20:41:59.025762Z", "shell.execute_reply": "2021-04-23T20:41:59.026619Z" } }, "outputs": [ { "data": { "text/markdown": [ "[searching for `Butler` in the `lsst` repo](https://github.com/search?l=Python&q=org%3Alsst+Butler&type=Code)" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "[searching for `Butler` in the `lsst` repo](https://github.com/search?l=Python&q=org%3Alsst+Butler&type=Code)\n" ] } ], "source": [ "where_is(Butler, in_the='repo')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally, here's how to generate a search within the LSST DM technotes:" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "execution": { "iopub.execute_input": "2021-04-23T20:41:59.031256Z", "iopub.status.busy": "2021-04-23T20:41:59.030222Z", "iopub.status.idle": "2021-04-23T20:41:59.054950Z", "shell.execute_reply": "2021-04-23T20:41:59.055762Z" } }, "outputs": [ { "data": { "text/markdown": [ "[searching for `ImageDifferenceTask` in the `lsst-dm` technotes](https://github.com/search?l=reStructuredText&q=org%3Alsst-dm+ImageDifferenceTask&type=Code)" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "[searching for `ImageDifferenceTask` in the `lsst-dm` technotes](https://github.com/search?l=reStructuredText&q=org%3Alsst-dm+ImageDifferenceTask&type=Code)\n" ] } ], "source": [ "where_is(ImageDifferenceTask, in_the='technotes')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Summary\n", "In this tutorial we have explored two general ways to read more about the DM Stack code objects: the built-in notebook `help` and magic '?' commands, and the `stackclub.where_is` utility for locating the relevant part of the Stack source code. \n", "\n", "Both of the above methods focus on the python code, which for many purposes will be sufficient. However, to understand the Stack's C++ primitives, we'll need to dig deeper into the DM Stack's [doxygen documentation](http://doxygen.lsst.codes/stack/doxygen/x_masterDoxyDoc/), as linked from https://pipelines.lsst.io. " ] } ], "metadata": { "kernelspec": { "display_name": "LSST", "language": "python", "name": "lsst" }, "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.7.8" } }, "nbformat": 4, "nbformat_minor": 4 }