diff --git a/Basic DM AFW Introduction.ipynb b/Basic DM AFW Introduction.ipynb index d51bcf9..410207d 100644 --- a/Basic DM AFW Introduction.ipynb +++ b/Basic DM AFW Introduction.ipynb @@ -1,670 +1,699 @@ { - "metadata": { - "name": "" - }, - "nbformat": 3, - "nbformat_minor": 0, - "worksheets": [ + "cells": [ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#Introduction to the DM AFW packages\n", - "#### Written by Chris Walter of Duke University for the LSST Dark Energy Science Collaboration. Last Updated 10/2013.\n", - "\n", - "This IPython notebook is an introduction to the LSST DM stack with a focus on the AFW (applications framework) package used for dealing with image data." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Don't forget to the load LSST setup files and then \"setup\" before you start.\n", - "For this notebook running 'setup pipe_tasks' should load what you need.\n", - "\n", - "Start by importing the packages we are going to use." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "import lsst.afw.math as math\n", - "import lsst.afw.table as afwTable\n", - "import lsst.afw.image as afwImg\n", - "import lsst.afw.detection as afwDetect\n", - "\n", - "import lsst.meas.algorithms as measAlg\n", - "\n", - "from matplotlib.colors import LogNorm" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 5 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now create an exposure by reading a PhoSim output file (you should have created this seperately and copied the eimage file to somewhere you can use it). A exposure contains a MaskedImage (image, mask and variance image), Meta-data and optional WCS and PSF information. The mask and variances will be empty. The Psf returns nothing now." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "exposure = afwImg.ExposureF('lsst_e_99999999_f2_R22_S11_E000.fits.gz')\n", - "\n", - "maskedImage = exposure.getMaskedImage()\n", - "\n", - "# These three are held in the maskedImage\n", - "image = maskedImage.getImage()\n", - "mask = maskedImage.getMask()\n", - "variance = maskedImage.getVariance()\n", - "\n", - "wcs = exposure.getWcs()\n", - "metaData = exposure.getMetadata()\n", - "psf = exposure.getPsf()" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 6 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Plot the CCD data (there should be a star in the middle) and also print out the mask and variance data." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "imshow(image.getArray(),norm=LogNorm());" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "display_data", - "png": "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\npaVFMzMzmpmZUXNzs+rq6lRVVaVdu3aps7NToVBI7733niSpvLxcu3btUnl5uQoKCnTs2DHvZc+x\nY8f04osv6vr163ruuee0ffv23K8OQF74/vNnoCXD5/NpiZ0S8EjK5nONT7YCcEZIADgjJACcERIA\nzggJAGeEBIAzQgLAGSEB4IyQAHBGSAA4IyQAnBESAM4ICQBnhASAM0ICwBkhAeCMkABwRkgAOCMk\nAJwREgDOCAkAZ4QEgDNCAsAZIQHgjJAAcEZIADgjJACcERIAzggJAGeEBIAzQgLAGSEB4IyQAHBG\nSAA4IyQAnBESAM4ICQBnhASAM0ICwBkhAeCMkABwRkgAOCMkAJwREgDOCAkAZw8UkunpaVVVVemF\nF16QJF26dEn19fUqLS3Vtm3bdOXKFe+xbW1tikQiKisr0+nTp73tAwMDqqysVCQS0YEDB7K8DACL\n6YFCcvToUZWXl8vn80mS2tvbVV9fr48//lh1dXVqb2+XJA0NDendd9/V0NCQ+vr69Morr8jMJEn7\n9u1TZ2enhoeHNTw8rL6+vhwtCUC+zRuSVCqlU6dO6eWXX/ai0NPTo5aWFklSS0uLTp48KUnq7u5W\nU1OTCgsLFQqFVFJSokQioUwmo4mJCVVXV0uS9uzZ4+0DYPmbNyQ/+tGP9POf/1wrVvz/Q8fHx+X3\n+yVJfr9f4+PjkqTR0VEFg0HvccFgUOl0+q7tgUBA6XQ6a4sAsLjuG5Lf/e53KioqUlVVlXc1cief\nz+e95AHweCq43zc//PBD9fT06NSpU7px44Y+++wzNTc3y+/3a2xsTMXFxcpkMioqKpL0xZXGyMiI\nt38qlVIwGFQgEFAqlZq1PRAIzDm3tbXV+7q2tla1tbULXN79xePxnB17MWflex5rWx6z4vG44vF4\nbg5uDygej9u3vvUtMzM7ePCgtbe3m5lZW1ubHTp0yMzMLly4YNFo1G7evGmffPKJrVu3zmZmZszM\nrLq62j766CObmZmxhoYG6+3tveechzglZ2+88cYjOSvf81jb8ptllt3n2n2vSO506yXMT37yE+3a\ntUudnZ0KhUJ67733JEnl5eXatWuXysvLVVBQoGPHjnn7HDt2TC+++KKuX7+u5557Ttu3b89qEAEs\nngcOyZYtW7RlyxZJ0tNPP60zZ87c83Gvv/66Xn/99bu2f/WrX9Xf/va3BZ4mgKXM959LnCUjFovp\nL3/5y2KfBvDI27JlS9beM1lyIQGw/HCvDQBnhASAsyUTkr6+PpWVlSkSiaijoyMrxwyFQnrmmWdU\nVVXlfTx/ITcczuWll16S3+9XZWWlty1XNzTea1Zra6uCwaCqqqpUVVWl3t7erMwaGRnR1q1btXHj\nRlVUVOitt97K6drmmpeL9d24cUM1NTWKxWIqLy/Xa6+9lrO1zTUrVz+3WxblJtus/SHZwb///W8L\nh8OWTCZtcnLSotGoDQ0NOR83FArZxYsXZ207ePCgdXR0mJlZe3v7XZ+BmZyctGQyaeFw2Kanp+97\n/A8++MD+/Oc/W0VFxYKOf+szNps2bbJEImFmNudnbO41q7W11d588827Hus6K5PJ2ODgoJmZTUxM\nWGlpqQ0NDeVsbXPNy9X6rl27ZmZmU1NTVlNTY/39/Tlb271m5Wpdt7z55pv2ve99z1544QUzy93/\nydstiSuSs2fPqqSkRKFQSIWFhdq9e7e6u7uzcmy7473kh7nh8OzZs/c99ubNm7V69eoFH/9hbmi8\n16x7rS8bs4qLixWLxSRJK1eu1IYNG5ROp3O2trnm5Wp9TzzxhCRpcnJS09PTWr16dc7Wdq9ZuVqX\ntHg32S6JkKTTaa1du9b7962b/Vz5fD5985vf1Ne+9jX95je/kfTwNxw+rHzf0PjLX/5S0WhUe/fu\n9S5Zsznr008/1eDgoGpqavKytlvzvv71r+dsfTMzM4rFYvL7/d5Lqlyt7V6zcrUuafFusl0SIcnV\nTX9/+tOfNDg4qN7eXv36179Wf3//XXPvN9v1vHJ9Q+O+ffuUTCZ1/vx5rVmzRj/+8Y+zevyrV69q\n586dOnr0qJ588slZ38vF2q5evarvfve7Onr0qFauXJmz9a1YsULnz59XKpXSBx98oPfff3/W97O5\ntjtnxePxnK1rMW+yXRIhufNmv5GRkVlFXKg1a9ZIkr785S/rO9/5js6ePevdcChp3hsO73dj4Vwe\n5vgLuaHxdkVFRd5/jJdfftl7KZaNWVNTU9q5c6eam5u1Y8eOnK/t1rzvf//73rxcrk+SnnrqKT3/\n/PMaGBjI+c/t1qxz587lbF23brL9yle+oqamJv3xj3+cdZNtrtYmaWm82To1NWXr1q2zZDJpN2/e\nzMqbrdeuXbPPPvvMzMyuXr1q3/jGN+z3v//9gm44vJ9kMnnXm625uqHxzlmjo6Pe17/4xS+sqakp\nK7NmZmasubnZXn311Vnbc7W2ueblYn3/+Mc/7PLly2Zm9vnnn9vmzZvtzJkzOVnbXLMymUxOfm63\ny9dNtrcsiZCYmZ06dcpKS0stHA7bT3/6U+fjffLJJxaNRi0ajdrGjRu9Y168eNHq6uosEolYfX29\n94M2Mzty5IiFw2Fbv3699fX1zTtj9+7dtmbNGissLLRgMGhvv/32go5/7tw5q6iosHA4bPv373+g\nWZ2dndbc3GyVlZX2zDPP2Le//W0bGxvLyqz+/n7z+XwWjUYtFotZLBaz3t7enK3tXvNOnTqVk/X9\n9a9/taqqKotGo1ZZWWk/+9nPzGxh/y8WOitXP7fbxeNx7682ufq53Y6PyANwtiTeIwGwvBESAM4I\nCQBnhASAM0ICwBkhAeCMkABwRkgAOPs/sFOSlUo2GzEAAAAASUVORK5CYII=\n", - "text": [ - "" - ] - } - ], - "prompt_number": 7 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "mask.getArray()" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 8, - "text": [ - "array([[0, 0, 0, ..., 0, 0, 0],\n", - " [0, 0, 0, ..., 0, 0, 0],\n", - " [0, 0, 0, ..., 0, 0, 0],\n", - " ..., \n", - " [0, 0, 0, ..., 0, 0, 0],\n", - " [0, 0, 0, ..., 0, 0, 0],\n", - " [0, 0, 0, ..., 0, 0, 0]], dtype=uint16)" - ] - } - ], - "prompt_number": 8 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "variance.getArray()" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 9, - "text": [ - "array([[ 0., 0., 0., ..., 0., 0., 0.],\n", - " [ 0., 0., 0., ..., 0., 0., 0.],\n", - " [ 0., 0., 0., ..., 0., 0., 0.],\n", - " ..., \n", - " [ 0., 0., 0., ..., 0., 0., 0.],\n", - " [ 0., 0., 0., ..., 0., 0., 0.],\n", - " [ 0., 0., 0., ..., 0., 0., 0.]], dtype=float32)" - ] - } - ], - "prompt_number": 9 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Printout the WCS and FITS Header metaData keys." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "metaWCS = wcs.getFitsMetadata()\n", - "metaWCS.getOrderedNames() #print them out" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 10, - "text": [ - "('NAXIS',\n", - " 'EQUINOX',\n", - " 'RADESYS',\n", - " 'CRPIX1',\n", - " 'CRPIX2',\n", - " 'CD1_1',\n", - " 'CD1_2',\n", - " 'CD2_1',\n", - " 'CD2_2',\n", - " 'CRVAL1',\n", - " 'CRVAL2',\n", - " 'CUNIT1',\n", - " 'CUNIT2',\n", - " 'CTYPE1',\n", - " 'CTYPE2')" - ] - } - ], - "prompt_number": 10 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "print \"There are \", metaData.nameCount(), \"items.\"\n", - "print \"The first 20 names are\", metaData.names()[:20]" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "There are 322 items.\n", - "The first 20 names are ('VERSION', 'CREATOR', 'QEVAR', 'OVRDEP', 'SF', 'NB', 'NBULK', 'CHPANG', 'MAXY', 'MINY', 'MAXX', 'MINX', 'FPFILE', 'NF', 'PAIRID', 'PIXSIZE', 'DOMESEE', 'LASCPR', 'AERIND', 'H2OPRESS')\n" - ] - } - ], - "prompt_number": 11 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's retrieve one of the header members and see who made this FITS file." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "print metaData.get('CREATOR')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "PHOSIM\n" - ] - } - ], - "prompt_number": 12 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now let's look at statistics of the image. In a bit we will see what using a mask can do. First set up the statistics flag:" - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "statFlags = math.NPOINT | math.MEAN | math.STDEV | math.MAX | math.MIN | math.ERRORS\n", - "print \"The statistics flags are set to %s.\"%bin(statFlags)\n", - "print \"Errors will be calculated.\"" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "The statistics flags are set to 0b110000001111.\n", - "Errors will be calculated.\n" - ] - } - ], - "prompt_number": 13 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "First let's set individual pixel (0,0) to 65,000. This will saturate a single pixel and screw up our overall statitics. Later we will see how to mask it out." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "image.set(0, 0, 65000)" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 14 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "*VERY IMPORTANT*: If you want to use a mask, you need to make a control object and tell the statistics routines which planes to pay attention to. Also: unlike what is says in some documentation 0 will *ignore* all of the mask layers not use all of them. Here I will tell AFW to use the saturation (SAT) plane. Note I have't actually set any saturated bits yet. I will do that later." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "control = math.StatisticsControl()\n", - "SAT = afwImg.MaskU_getPlaneBitMask(\"SAT\")\n", - "control.setAndMask(SAT); #pixels with this mask bit set will be ignored." - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 15 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now let's do the statistics on the sensor. The saturated pixel will screw things up." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "imageStatistics = math.makeStatistics(maskedImage, statFlags, control)\n", - "numBins = imageStatistics.getResult(math.NPOINT)[0]\n", - "mean = imageStatistics.getResult(math.MEAN)[0]\n", - "\n", - "print \"The image has dimensions %i x %i pixels\" %(maskedImage.getWidth(), maskedImage.getHeight())\n", - "print \"Number of analyzed bins in image is %i\" %numBins\n", - "print \"Max = %9d\" %imageStatistics.getResult(math.MAX)[0]\n", - "print \"Min = %9d\" %imageStatistics.getResult(math.MIN)[0]\n", - "print \"Mean = %9.8f +- %3.1f\" %imageStatistics.getResult(math.MEAN)\n", - "print \"StdDev = %9.2f\" %imageStatistics.getResult(math.STDEV)[0]" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "The image has dimensions 4000 x 4072 pixels\n", - "Number of analyzed bins in image is 16288000\n", - "Max = 65000\n", - "Min = 0\n", - "Mean = 0.00555734 +- 0.0\n", - "StdDev = 16.13\n" - ] - } - ], - "prompt_number": 16 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now also set the mask bit to SAT (Saturated) for that pixel. This should cause the builtin statistics routines to igrore this pixel as earlier we told them to pay attention to the SAT mask layer." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "saturationBit = mask.getPlaneBitMask('SAT')\n", - "mask.set (0, 0, saturationBit)" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 17 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now the let's try the same thing again." - ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "imageStatistics = math.makeStatistics(maskedImage, statFlags, control)\n", - "numBins = imageStatistics.getResult(math.NPOINT)[0]\n", - "mean = imageStatistics.getResult(math.MEAN)[0]\n", - "\n", - "print \"The image has dimensions %i x %i pixels\" %(maskedImage.getWidth(), maskedImage.getHeight())\n", - "print \"Number of analyzed bins in image is %i\" %numBins\n", - "print \"Max = %9d\" %imageStatistics.getResult(math.MAX)[0]\n", - "print \"Min = %9d\" %imageStatistics.getResult(math.MIN)[0]\n", - "print \"Mean = %9.8f +- %3.1f\" %imageStatistics.getResult(math.MEAN)\n", - "print \"StdDev = %9.2f\" %imageStatistics.getResult(math.STDEV)[0]\n" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "The image has dimensions 4000 x 4072 pixels\n", - "Number of analyzed bins in image is 16287999\n", - "Max = 1103\n", - "Min = 0\n", - "Mean = 0.00156667 +- 0.0\n", - "StdDev = 0.87\n" - ] - } - ], - "prompt_number": 18 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As we can see one less pixel was considered and now the saturated pixel was ignored." + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#Introduction to the DM AFW packages\n", + "#### Written by Chris Walter of Duke University for the LSST Dark Energy Science Collaboration. Last Updated 5/2015 by Will Dawson using LSST Stack v10_0.\n", + "\n", + "This IPython notebook is an introduction to the LSST DM stack with a focus on the AFW (applications framework) package used for dealing with image data." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Don't forget to the load LSST setup files and then \"setup\" before you start.\n", + "For this notebook running 'setup pipe_tasks' should load what you need. So before runing `ipython notebook` run the following in the terminal:\n", + "\n", + "```\n", + "cd \\path\\to\\lsst\\\n", + "source loadLSST.bash\n", + "setup pipe_tasks -T v10_0\n", + "ipython notebook\n", + "```\n", + "\n", + "If you followed the default LSST DM pipeline installation instructions then \\path\\to\\lsst\\ is ~\\lsst. Change the suffix of the `source loadLSST.bash` command to match your shell.\n", + "\n", + "Start by importing the packages we are going to use." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import lsst.afw.math as math\n", + "import lsst.afw.table as afwTable\n", + "import lsst.afw.image as afwImg\n", + "import lsst.afw.detection as afwDetect\n", + "import lsst.meas.algorithms as measAlg\n", + "\n", + "%matplotlib inline\n", + "from matplotlib.colors import LogNorm\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Exposure Creation and Exploration\n", + "Now create an exposure by reading a PhoSim output file (you should have created this seperately and copied the eimage file to somewhere you can use it). A exposure contains a MaskedImage (image, mask and variance image), Meta-data and optional WCS and PSF information. The mask and variances will be empty. The Psf returns nothing now." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "exposure = afwImg.ExposureF('lsst_e_99999999_f2_R22_S11_E000.fits.gz')\n", + "\n", + "maskedImage = exposure.getMaskedImage()\n", + "\n", + "# These three are held in the maskedImage\n", + "image = maskedImage.getImage()\n", + "mask = maskedImage.getMask()\n", + "variance = maskedImage.getVariance()\n", + "\n", + "wcs = exposure.getWcs()\n", + "metaData = exposure.getMetadata()\n", + "psf = exposure.getPsf()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Plot the CCD data (there should be a star in the middle) and also print out the mask and variance data." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAARIAAAEACAYAAAB/KfmzAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAADpJJREFUeJzt3G+s3mV9x/H3hz+NOJmkMWn50wUelIQuWzBd6LLhKJtj\nxSxAlgX0gSHa7AluGE2c1Cyjj9SYLI49gD2YjsK2mmZmDCMqlVA1S6T7Q6VSK5TZxJ7Zw4zMPzHL\nSvzuwX0d++NwTs9pr/u+T0/7fiUnvX7X/ftd39/F6f3p7y+pKiSpxwUrvQOSVj+DRFI3g0RSN4NE\nUjeDRFI3g0RSt6kHSZJtSQ4neTHJh6ddX9L4ZZrPkSS5EPg28HZgBvhX4F1V9a2p7YSksZv2EckN\nwJGqOlpVJ4DPALdPeR8kjdm0g+RK4LuD5WOtT9IqNu0g8Xl86Rx00ZTrzQAbBssbGB2V/FwSw0aa\nkqrKuAaa2g+j4HoJuBpYAxwArpu3Tk1xf3aei7Wcm7WWWa/GNdZUj0iq6tUkfwx8CbgQ+FR5x0Za\n9aZ9akNVfQH4wrTrSpqc8/3J1n3naK1p15tmrWnXO1drjdVUH0hbjiRV47oAJGlR4/yune9HJJLG\nwCCR1M0gkdTNIJHUzSCR1M0gkdTNIJHUzSCR1M0gkdTNIJHUzSCR1M0gkdTNIJHUzSCR1M0gkdTN\nIJHUzSCR1M0gkdTNIJHUzSCR1M0gkdTNIJHUzSCR1M0gkdTNIJHUzSCR1M0gkdTNIJHUzSCR1M0g\nkdTNIJHUzSCR1M0gkdTNIJHUzSCR1M0gkdTNIJHUzSCR1M0gkdTNIJHUzSCR1M0gkdTNIJHUzSCR\n1G3JIEny6SSzSQ4O+tYm2ZvkhSRPJrls8NmOJC8mOZzklkH/5iQH22cPjH8qklbKco5I/hbYNq/v\nPmBvVV0LPNWWSbIJuAvY1LZ5MEnaNg8B26tqI7AxyfwxJa1SSwZJVX0NeGVe923ArtbeBdzR2rcD\nu6vqRFUdBY4AW5JcDlxaVfvbeo8MtpG0yp3pNZJ1VTXb2rPAuta+Ajg2WO8YcOUC/TOtX9I54KLe\nAaqqktQ4dmZOkp2DxX1VtW+c40vnoyRbga2TGPtMg2Q2yfqqOt5OW15u/TPAhsF6VzE6Eplp7WH/\nzGKDV9XOM9wvSYto/yDvm1tOcv+4xj7TU5vHgbtb+27gsUH/O5OsSXINsBHYX1XHgR8l2dIuvr57\nsI2kVW7JI5Iku4GbgLck+S7w58DHgT1JtgNHgTsBqupQkj3AIeBV4J6qmjvtuQd4GLgEeKKqvjje\nqUhaKTn5PT87JKmqytJrSuoxzu+aT7ZK6maQSOpmkEjqZpBI6maQSOpmkEjqZpBI6maQSOpmkEjq\nZpBI6maQSOpmkEjqZpBI6maQSOpmkEjqZpBI6maQSOpmkEjqZpBI6maQSOpmkEjqZpBI6maQSOpm\nkEjqZpBI6maQSOpmkEjqZpBI6maQSOpmkEjqZpBI6maQSOpmkEjqZpBI6maQSOpmkEjqZpBI6maQ\nSOpmkEjqZpBI6maQSOpmkGjqkmu2rvQ+aLxSVSu9D6+RpKoqK70f0rlunN81j0gkdTNIJHUzSCR1\nWzJIkmxI8nSS55N8M8m9rX9tkr1JXkjyZJLLBtvsSPJiksNJbhn0b05ysH32wGSmJGnalnNEcgL4\nQFX9MvDrwPuSXAfcB+ytqmuBp9oySTYBdwGbgG3Ag0nmLug8BGyvqo3AxiTbxjobSStiySCpquNV\ndaC1fwJ8C7gSuA3Y1VbbBdzR2rcDu6vqRFUdBY4AW5JcDlxaVfvbeo8MtpG0ip3WNZIkVwNvBZ4B\n1lXVbPtoFljX2lcAxwabHWMUPPP7Z1q/pFXuouWumORNwGeB91fVj0+erUBVVZKxPZCSZOdgcV9V\n7RvX2NL5KslWYOskxl5WkCS5mFGIPFpVj7Xu2STrq+p4O215ufXPABsGm1/F6EhkprWH/TML1auq\nncuegVZc1vxz8eZLv8r3//A9VT/4z5XeHy2s/YO8b245yf3jGns5d20CfAo4VFV/OfjoceDu1r4b\neGzQ/84ka5JcA2wE9lfVceBHSba0Md892Ear2Yk/exfff+iv4bo/WOld0cpY8hH5JDcCXwWeA+ZW\n3gHsB/YAvwQcBe6sqv9p23wEeC/wKqNToS+1/s3Aw8AlwBNVde8C9XxEXpqCcX7XfNdGOk/5ro2k\ns4pBIqmbQSKpm0EiqZtBIqmbQSKpm0EiqZtBIqmbQSKpm0EiqZtBIqmbQSKpm0EiqZtBIqmbQSKp\nm0EiqZtBIqmbQSKpm0EiqZtBIqmbQSKpm0EiqZtBIqmbQSKpm0EiqZtBIqmbQSKpm0EiqZtBIqmb\nQSKpm0EiqZtBIqmbQSKpm0EiqZtBIqmbQSKpm0EiqZtBIqmbQSKpm0EiqZtBIqmbQSKpm0EiqZtB\nIqmbQSKpm0EiqdspgyTJG5I8k+RAkkNJPtb61ybZm+SFJE8muWywzY4kLyY5nOSWQf/mJAfbZw9M\nbkqSpu2UQVJV/wvcXFXXA78K3JzkRuA+YG9VXQs81ZZJsgm4C9gEbAMeTJI23EPA9qraCGxMsm0S\nE5I0fUue2lTVT1tzDXAh8ApwG7Cr9e8C7mjt24HdVXWiqo4CR4AtSS4HLq2q/W29RwbbSFrllgyS\nJBckOQDMAk9X1fPAuqqabavMAuta+wrg2GDzY8CVC/TPtH5J54CLllqhqn4GXJ/kzcCXktw87/NK\nUuPcqSQ7B4v7qmrfOMeXzkdJtgJbJzH2kkEyp6p+mOTzwGZgNsn6qjreTltebqvNABsGm13F6Ehk\nprWH/TOnqLVzufslaXnaP8j75paT3D+usZe6a/OWuTsySS4Bfhd4FngcuLutdjfwWGs/DrwzyZok\n1wAbgf1VdRz4UZIt7eLruwfbSFrlljoiuRzYleQCRqHzaFU9leRZYE+S7cBR4E6AqjqUZA9wCHgV\nuKeq5k577gEeBi4BnqiqL457MpJWRk5+z88OSaqqsvSaknqM87vmk62SuhkkkroZJJK6GSSSuhkk\nkroZJJK6GSSSuhkkkroZJJK6GSSSuhkkkroZJJK6GSSSuhkkkroZJJK6GSSSuhkkkroZJJK6GSSS\nuhkkkroZJJK6GSSSuhkkkroZJJK6GSSSuhkkkroZJJK6GSSSuhkkkroZJJK6GSSSuhkkkroZJJK6\nGSSSuhkkkroZJJK6GSSSuhkkkroZJJK6GSSSuhkkkroZJJK6GSSSuhkkkroZJJK6LStIklyY5Nkk\nn2vLa5PsTfJCkieTXDZYd0eSF5McTnLLoH9zkoPtswfGPxVJK2W5RyTvBw4B1ZbvA/ZW1bXAU22Z\nJJuAu4BNwDbgwSRp2zwEbK+qjcDGJNvGMwVJK23JIElyFfAO4G+AuVC4DdjV2ruAO1r7dmB3VZ2o\nqqPAEWBLksuBS6tqf1vvkcE2kla55RyRfBL4EPCzQd+6qppt7VlgXWtfARwbrHcMuHKB/pnWL+kc\ncMogSfL7wMtV9Swnj0Zeo6qKk6c8ks5DFy3x+W8AtyV5B/AG4BeTPArMJllfVcfbacvLbf0ZYMNg\n+6sYHYnMtPawf2axokl2Dhb3VdW+ZczltCXZOqmxV7LWtOs5t9VRK8lWYOtEBq+qZf0ANwGfa+1P\nAB9u7fuAj7f2JuAAsAa4BngJSPvsGWALoyObJ4Bti9Sp5e5T7w+w81ys5dystcx6Na6xljoieV3u\ntD8/DuxJsh04CtzZ9upQkj2M7vC8CtxTbY+Be4CHgUuAJ6rqi6dZW9JZatlBUlVfAb7S2j8A3r7I\neh8FPrpA/78Dv3JmuynpbJaTBwxnhyRn1w5J57CqWvAmyuk664JE0urjuzaSuhkkkvpN83bTErei\ntgGHgRdpt5bHMOZR4DngWWB/61sL7AVeAJ4ELhusv6PVPwzcsozxP83oyd6Dg77THh/YDBxsnz1w\nGrV2MnpO59n2c+uYam0AngaeB74J3DvhuS1Wb+zzY/Q81DOMHlM4BHxsUnM7Ra2J/N4G617Yxv3c\npOb2uprTCIllfCEvZPReztXAxe0//HVjGPc7wNp5fZ8A/rS1P8zrn4G5uO3HEeCCJcZ/G/BWXvvl\nPp3x565R7QduaO0Fn7FZpNb9wAcXWLe31nrg+tZ+E/Bt4LoJzm2xepOa3xvbnxcBXwdunODcFqo1\nkXkNxvkg8PfA45P8Ozn8OVtObW4AjlTV0ao6AXyG0QuA4zD/qvTpvHB4w6kGrqqvAa90jL/sFxoX\nqbXQ/MZR63hVHWjtnwDfYvRu1KTmtli9Sc3vp625htE/Yq9McG4L1ZrIvGDlXrI9W4LkSuC7g+W5\nl/16FfDlJP+W5I9a3+m+cHi6pv1C458k+UaSTw3+vzBjq5XkakZHQs8whbkN6n19UvNLckGSA20O\nT1fV85Oa2yK1JjKvZkVesj1bgmRS96B/s6reCtwKvC/J215TdHTcdqraXfu1jPF7PcToVYTrge8B\nfzHOwZO8Cfgs8P6q+vHws0nMrdX7x1bvJ0xoflX1s6q6ntE7X7+V5OZ5n49tbgvU2sqE5rWSL9me\nLUEy/2W/Dbw2Ec9IVX2v/fnfwD8xOlWZTbIeYBkvHC76YuEpnM74p/1C41BVvVwNo0PZuVOx7lpJ\nLmYUIo9W1WOTntug3t/N1Zvk/Nr4PwQ+z+jC4kR/b4NavzbBec29ZPsdYDfw28OXbCc1t7kJrvgP\nowtRLzG64LOGMVxsBd7I6DwP4BeAfwFu4QxeOFyiztW8/mLrpF5onF/r8kH7A8A/jKNW++wR4JPz\n+icyt1PUG/v8gLfQ7loweu/rq8DvTGJup6i1fhK/t3m1b2IKL9n+vN5Kh8hg4rcyulp/BNgxhvGu\naf+RDjC6pbij9a8FvszCt8I+0uofBn5vGTV2A/8F/B+jazzvOZPxOXmr7QjwV8us9V5GX77ngG8A\njzE6Fx5HrRsZnWMf4OQtym0TnNtC9W6dxPwYve/1H63Wc8CHzvTvRUetifze5tW+iZN3bSbyexv+\n+Ii8pG5nyzUSSauYQSKpm0EiqZtBIqmbQSKpm0EiqZtBIqmbQSKp2/8DGvC7Q10t8Z0AAAAASUVO\nRK5CYII=\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.imshow(image.getArray(),norm=LogNorm());" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[0, 0, 0, ..., 0, 0, 0],\n", + " [0, 0, 0, ..., 0, 0, 0],\n", + " [0, 0, 0, ..., 0, 0, 0],\n", + " ..., \n", + " [0, 0, 0, ..., 0, 0, 0],\n", + " [0, 0, 0, ..., 0, 0, 0],\n", + " [0, 0, 0, ..., 0, 0, 0]], dtype=uint16)" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "mask.getArray()" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 0., 0., 0., ..., 0., 0., 0.],\n", + " [ 0., 0., 0., ..., 0., 0., 0.],\n", + " [ 0., 0., 0., ..., 0., 0., 0.],\n", + " ..., \n", + " [ 0., 0., 0., ..., 0., 0., 0.],\n", + " [ 0., 0., 0., ..., 0., 0., 0.],\n", + " [ 0., 0., 0., ..., 0., 0., 0.]], dtype=float32)" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "variance.getArray()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Printout the WCS and FITS Header metaData keys." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "('NAXIS',\n", + " 'EQUINOX',\n", + " 'RADESYS',\n", + " 'CRPIX1',\n", + " 'CRPIX2',\n", + " 'CD1_1',\n", + " 'CD1_2',\n", + " 'CD2_1',\n", + " 'CD2_2',\n", + " 'CRVAL1',\n", + " 'CRVAL2',\n", + " 'CUNIT1',\n", + " 'CUNIT2',\n", + " 'CTYPE1',\n", + " 'CTYPE2')" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "metaWCS = wcs.getFitsMetadata()\n", + "metaWCS.getOrderedNames() #print them out" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "There are 322 items.\n", + "The first 20 names are ('VERSION', 'CREATOR', 'QEVAR', 'OVRDEP', 'SF', 'NB', 'NBULK', 'CHPANG', 'MAXY', 'MINY', 'MAXX', 'MINX', 'FPFILE', 'NF', 'PAIRID', 'PIXSIZE', 'DOMESEE', 'LASCPR', 'AERIND', 'H2OPRESS')\n" ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now let's try to find the peak. No backgound subtraction will be done because there is no background in this simulated image. This first step finds a \"footprint\" of connected pixels including its center. \n", - "\n", - "I am going to start by running these algorithms for detection and measurment \"manually\" so we can see the proper way to call them. Later I will call routines that will call them for me." + } + ], + "source": [ + "print \"There are \", metaData.nameCount(), \"items.\"\n", + "print \"The first 20 names are\", metaData.names()[:20]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's retrieve one of the header members and see who made this FITS file." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "PHOSIM\n" ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "thresholdValue = 50\n", - "npixMin = 5 \n", - "grow = 1\n", - "isotropic = False\n", - "\n", - "threshold = afwDetect.Threshold(thresholdValue, afwDetect.Threshold.VALUE)\n", - "footPrintSet = afwDetect.FootprintSet(maskedImage, threshold, \"DETECTED\", npixMin)\n", - "footPrintSet = afwDetect.FootprintSet(footPrintSet, grow, isotropic)\n", - "\n", - "footPrints = footPrintSet.getFootprints()\n", - "\n", - "footPrintSet.setMask(maskedImage.getMask(), \"DETECTED\")" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 19 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, let's print out the peak we found." + } + ], + "source": [ + "print metaData.get('CREATOR')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Statistics without a mask\n", + "Now let's look at statistics of the image. In a bit we will see what using a mask can do. First set up the statistics flag:" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The statistics flags are set to 0b110000001111.\n", + "Errors will be calculated.\n" ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "print \"I found \", footPrints.size(), \"footPrint(s)\"\n", - "print\n", - "\n", - "for i in range(0,footPrints.size()):\n", - " print \"Footprint:\",i\n", - " \n", - " peak = footPrints[i].getPeaks()[0]\n", - " print \"A peak of value\", peak.getPeakValue()\n", - " print \"was found at X =\", peak.getFx(),\"Y =\",peak.getFy()\n" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "I found 1 footPrint(s)\n", - "\n", - "Footprint: 0\n", - "A peak of value" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - " 1103.0\n", - "was found at X = 2000.0 Y = 2032.0\n" - ] - } - ], - "prompt_number": 20 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We found our star!" + } + ], + "source": [ + "statFlags = math.NPOINT | math.MEAN | math.STDEV | math.MAX | math.MIN | math.ERRORS\n", + "print \"The statistics flags are set to %s.\"%bin(statFlags)\n", + "print \"Errors will be calculated.\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First let's set individual pixel (0,0) to 65,000. This will saturate a single pixel and screw up our overall statitics. Later we will see how to mask it out." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "image.set(0, 0, 65000)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "*VERY IMPORTANT*: If you want to use a mask, you need to make a control object and tell the statistics routines which planes to pay attention to. Also: unlike what is says in some documentation 0 will *ignore* all of the mask layers not use all of them. Here I will tell AFW to use the saturation (SAT) plane. Note I have't actually set any saturated bits yet. I will do that later." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "control = math.StatisticsControl()\n", + "SAT = afwImg.MaskU_getPlaneBitMask(\"SAT\")\n", + "control.setAndMask(SAT); #pixels with this mask bit set will be ignored." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now let's do the statistics on the sensor. The saturated pixel will screw things up." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The image has dimensions 4000 x 4072 pixels\n", + "Number of analyzed bins in image is 16288000\n", + "Max = 65000\n", + "Min = 0\n", + "Mean = 0.00555734 +- 0.0\n", + "StdDev = 16.13\n" ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now let's take that peak and try to measure it with one of the alogorithms. We will use some of the infrastructure and also reduce the list of algorithms to apply to only one. \n", - "\n", - "To do this I will also reset some \"aliases\" so that they don't point to algorithms that we aren't going to use (the default code uses several). The aliases are pointers into records in the output table. They names of these pointers are independent of the algorithms. So I can point them at the alogorithm results I want and then just ask for a output variable through an access function and it will get the correct one. This way, you can switch which algorithm you want to look at the output for, but not change how you access the answer.\n", - "\n", - "Note: This example uses tables and catalogs. If you don't understand those you should also look at the short notebook which introduces them." + } + ], + "source": [ + "imageStatistics = math.makeStatistics(maskedImage, statFlags, control)\n", + "numBins = imageStatistics.getResult(math.NPOINT)[0]\n", + "mean = imageStatistics.getResult(math.MEAN)[0]\n", + "\n", + "print \"The image has dimensions %i x %i pixels\" %(maskedImage.getWidth(), maskedImage.getHeight())\n", + "print \"Number of analyzed bins in image is %i\" %numBins\n", + "print \"Max = %9d\" %imageStatistics.getResult(math.MAX)[0]\n", + "print \"Min = %9d\" %imageStatistics.getResult(math.MIN)[0]\n", + "print \"Mean = %9.8f +- %3.1f\" %imageStatistics.getResult(math.MEAN)\n", + "print \"StdDev = %9.2f\" %imageStatistics.getResult(math.STDEV)[0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Statistics with a mask\n", + "Now also set the mask bit to SAT (Saturated) for that pixel. This should cause the builtin statistics routines to igrore this pixel as earlier we told them to pay attention to the SAT mask layer." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "saturationBit = mask.getPlaneBitMask('SAT')\n", + "mask.set (0, 0, saturationBit)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now the let's try the same thing again." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The image has dimensions 4000 x 4072 pixels\n", + "Number of analyzed bins in image is 16287999\n", + "Max = 1103\n", + "Min = 0\n", + "Mean = 0.00156667 +- 0.0\n", + "StdDev = 0.87\n" ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "# Make a Schema which is a list of columns for a table. The object below store things in a table. \n", - "# The Schema is a describption of what is in each column. It can be added to by algorithms later.\n", - "schema = afwTable.SourceTable.makeMinimalSchema()\n", - "\n", - "# Make an object which we are going to use to configure the algorithms\n", - "# Decide which algorithms to include (meas_algorithms/../tests/measure.py) is a good reference\n", - "# Note: the pre-centroid fit is set seperately (it is set by default to 'centroid.sdss')\n", - "measureSourcesConfig = measAlg.SourceMeasurementConfig()\n", - "\n", - "measureSourcesConfig.algorithms.names = ['shape.sdss']\n", - "\n", - "#Aliases only\n", - "measureSourcesConfig.slots.psfFlux = None\n", - "measureSourcesConfig.slots.apFlux = None\n", - "measureSourcesConfig.slots.modelFlux = None\n", - "measureSourcesConfig.slots.instFlux = None\n", - "measureSourcesConfig.validate()\n", - "\n", - "# Now make the object which includes list the algorithms we want to use\n", - "# using the measureSourcesConfig object I made before.\n", - "# It also adds output places for those algorithms to the schema.\n", - "# This object can apply it's algorithms to images given a list of sources.\n", - "measureSources = measureSourcesConfig.makeMeasureSources(schema)\n", - "\n", - "# First make a catalog. Then, setup the aliases in the table so that it agrees with \n", - "# our rules above (where we set the aliases to None).\n", - "catalog = afwTable.SourceCatalog(schema)\n", - "measureSourcesConfig.slots.setupTable(catalog.getTable())\n", - "\n", - "# Take the set of footPrints (areas around the detected objects) we found when \n", - "# we did the detection and then put them in the catalog.\n", - "footPrintSet.makeSources(catalog)\n", + } + ], + "source": [ + "imageStatistics = math.makeStatistics(maskedImage, statFlags, control)\n", + "numBins = imageStatistics.getResult(math.NPOINT)[0]\n", + "mean = imageStatistics.getResult(math.MEAN)[0]\n", + "\n", + "print \"The image has dimensions %i x %i pixels\" %(maskedImage.getWidth(), maskedImage.getHeight())\n", + "print \"Number of analyzed bins in image is %i\" %numBins\n", + "print \"Max = %9d\" %imageStatistics.getResult(math.MAX)[0]\n", + "print \"Min = %9d\" %imageStatistics.getResult(math.MIN)[0]\n", + "print \"Mean = %9.8f +- %3.1f\" %imageStatistics.getResult(math.MEAN)\n", + "print \"StdDev = %9.2f\" %imageStatistics.getResult(math.STDEV)[0]\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As we can see one less pixel was considered and now the saturated pixel was ignored." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Source Detection\n", + "Now let's try to find the peak. No backgound subtraction will be done because there is no background in this simulated image. This first step finds a \"footprint\" of connected pixels including its center. \n", + "\n", + "I am going to start by running these algorithms for detection and measurment \"manually\" so we can see the proper way to call them. Later I will call routines that will call them for me." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "thresholdValue = 50\n", + "npixMin = 5 \n", + "grow = 1\n", + "isotropic = False\n", + "\n", + "threshold = afwDetect.Threshold(thresholdValue, afwDetect.Threshold.VALUE)\n", + "footPrintSet = afwDetect.FootprintSet(maskedImage, threshold, \"DETECTED\", npixMin)\n", + "footPrintSet = afwDetect.FootprintSet(footPrintSet, grow, isotropic)\n", + "\n", + "footPrints = footPrintSet.getFootprints()\n", + "\n", + "footPrintSet.setMask(maskedImage.getMask(), \"DETECTED\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let's print out the peak we found." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "I found 1 footPrint(s)\n", "\n", - "# Loop over all of the sources in the catalog. For each source apply our measurement algorithms to it.\n", - "# It uses the data in the exposure for the calculation. After the algorithim is run, print the centroid\n", - "# of the source as found by the algorithm. We access it throgh an alias.\n", - "for i, source in enumerate(catalog):\n", - " print i\n", - " measureSources.apply(source, exposure)\n", - " print source.getCentroid()" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "0\n", - "(1999.5, 2032.5)" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "\n" - ] - } - ], - "prompt_number": 21 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now let's do both steps again (detection and measurement) in a simpler way. We will use the tasks that were setup to help us do these jobs. This is the recomended interface. Internally it is doing a lot of what we did in the previous examples but being more comprehensive. We can configure them how we want. Doing it this way is more compact, flexible and it is easier to understand since the steps pretty much make sense. BTW, you can still restrict the algorithms as I showed above etc in the same way. Here I use all of the default algorithms." + "Footprint: 0\n", + "A peak of value 1103.0\n", + "was found at X = 2000.0 Y = 2032.0\n" ] - }, - { - "cell_type": "code", - "collapsed": true, - "input": [ - "# Configure the detection and measurement algorithms\n", - "schema = afwTable.SourceTable.makeMinimalSchema()\n", - "detectSourcesConfig = measAlg.SourceDetectionConfig(thresholdType='value')\n", - "measureSourcesConfig = measAlg.SourceMeasurementConfig()\n", - "\n", - "# Setup the detection and measurement tasks\n", - "detect = measAlg.SourceDetectionTask (config=detectSourcesConfig, schema=schema)\n", - "measure = measAlg.SourceMeasurementTask(config=measureSourcesConfig, schema=schema)\n", - "\n", - "# Detect the sources,then put them into a catalog (the table is where the catalog atually stores stuff)\n", - "table = afwTable.SourceTable.make(schema)\n", - "catalog = detect.makeSourceCatalog(table, exposure, sigma=5)\n", - "\n", - "# Get the sources out of the catalog\n", - "sources = catalog.sources\n", - "\n", - "# Apply the measurement routines to the exposure using the sources as input\n", - "measure.run(exposure, sources)\n", - "\n", - "# Now let's look at the output from some of the measurment algorithms.\n", - "fields = ['centroid.sdss', 'shape.sdss', 'shape.sdss.centroid','flux.gaussian']\n", - "keys = [schema.find(f).key for f in fields]\n", - "\n", - "for source in sources:\n", - " print source.getCentroid() #This uses one of the aliases\n", - "\n", - " # Now loop through the keys we want\n", - " for f,k in zip(fields, keys):\n", - " print ' ', f, source.get(k)" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "(1999.5, 2032.5)\n", - " centroid.sdss (1999.5, 2032.5)\n", - " shape.sdss (ixx=2.88751926897, iyy=3.05814257946, ixy=-0.133327694904)\n", - " shape.sdss.centroid (1999.5, 2032.5)\n", - " flux.gaussian 21410.8483803\n" - ] - } - ], - "prompt_number": 22 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can also use the DS9 program to display our results. This will overlay the footprint and the source measured centroid to the sensor data. This is commented out by default in case you don't have ds9 installed." + } + ], + "source": [ + "print \"I found \", footPrints.size(), \"footPrint(s)\"\n", + "print\n", + "\n", + "for i in range(0,footPrints.size()):\n", + " print \"Footprint:\",i\n", + " \n", + " peak = footPrints[i].getPeaks()[0]\n", + " print \"A peak of value\", peak.getPeakValue()\n", + " print \"was found at X =\", peak.getFx(),\"Y =\",peak.getFy()\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We found our star!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Source Measurement\n", + "Now let's take that peak and try to measure it with one of the alogorithms. We will use some of the infrastructure and also reduce the list of algorithms to apply to only one. \n", + "\n", + "To do this I will also reset some \"aliases\" so that they don't point to algorithms that we aren't going to use (the default code uses several). The aliases are pointers into records in the output table. The names of these pointers are independent of the algorithms. So I can point them at the alogorithm results I want and then just ask for an output variable through an access function and it will get the correct one. This way, you can switch which algorithm generates the output, but not change how you access the answer.\n", + "\n", + "Note: This example uses tables and catalogs. If you don't understand those you should also look at the short notebook which introduces them." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "(1999.5, 2032.5)\n" ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "#import lsst.afw.display.ds9 as ds9\n", - "##ds9.setMaskPlaneVisibility(\"DETECTED\",False)\n", - "#ds9.setMaskTransparency(75)\n", - "\n", - "#ds9.mtv(maskedImage)\n", - "#ds9.dot(\"+\", source.getX(), source.getY())" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 25 - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next we can take the code in this tutorial and turn it into a single program. Then, we can learn how to make it into a commandLine Task and use some framework code that will take care of some more things I did in the last step for us automatically. I do that in the next notebook." + } + ], + "source": [ + "# Make a Schema which is a list of columns for a table. The object below store things in a table. \n", + "# The Schema is a describption of what is in each column. It can be added to by algorithms later.\n", + "schema = afwTable.SourceTable.makeMinimalSchema()\n", + "\n", + "# Make an object which we are going to use to configure the algorithms\n", + "# Decide which algorithms to include (meas_algorithms/../tests/measure.py) is a good reference\n", + "# Note: the pre-centroid fit is set seperately (it is set by default to 'centroid.sdss')\n", + "measureSourcesConfig = measAlg.SourceMeasurementConfig()\n", + "\n", + "measureSourcesConfig.algorithms.names = ['shape.sdss']\n", + "\n", + "#Aliases only\n", + "measureSourcesConfig.slots.psfFlux = None\n", + "measureSourcesConfig.slots.apFlux = None\n", + "measureSourcesConfig.slots.modelFlux = None\n", + "measureSourcesConfig.slots.instFlux = None\n", + "measureSourcesConfig.validate()\n", + "\n", + "# Now make the object which includes list the algorithms we want to use\n", + "# using the measureSourcesConfig object I made before.\n", + "# It also adds output places for those algorithms to the schema.\n", + "# This object can apply it's algorithms to images given a list of sources.\n", + "measureSources = measureSourcesConfig.makeMeasureSources(schema)\n", + "\n", + "# First make a catalog. Then, setup the aliases in the table so that it agrees with \n", + "# our rules above (where we set the aliases to None).\n", + "catalog = afwTable.SourceCatalog(schema)\n", + "measureSourcesConfig.slots.setupTable(catalog.getTable())\n", + "\n", + "# Take the set of footPrints (areas around the detected objects) we found when \n", + "# we did the detection and then put them in the catalog.\n", + "footPrintSet.makeSources(catalog)\n", + "\n", + "# Loop over all of the sources in the catalog. For each source apply our measurement algorithms to it.\n", + "# It uses the data in the exposure for the calculation. After the algorithim is run, print the centroid\n", + "# of the source as found by the algorithm. We access it throgh an alias.\n", + "for i, source in enumerate(catalog):\n", + " print i\n", + " measureSources.apply(source, exposure)\n", + " print source.getCentroid()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Source Detection and Measurement (the effecient coding way)\n", + "Now let's do both steps again (detection and measurement) in a simpler way. We will use the tasks that were setup to help us do these jobs. This is the recomended interface. Internally it is doing a lot of what we did in the previous examples but being more comprehensive. We can configure them how we want. Doing it this way is more compact, flexible and it is easier to understand since the steps pretty much make sense. BTW, you can still restrict the algorithms as I showed above etc in the same way. Here I use all of the default algorithms." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(1999.5, 2032.5)\n", + " centroid.sdss (1999.5, 2032.5)\n", + " shape.sdss (ixx=2.88751926897, iyy=3.05814257946, ixy=-0.133327694904)\n", + " shape.sdss.centroid (1999.5, 2032.5)\n", + " flux.gaussian 21410.8483803\n" ] } ], - "metadata": {} + "source": [ + "# Configure the detection and measurement algorithms\n", + "schema = afwTable.SourceTable.makeMinimalSchema()\n", + "detectSourcesConfig = measAlg.SourceDetectionConfig(thresholdType='value')\n", + "measureSourcesConfig = measAlg.SourceMeasurementConfig()\n", + "\n", + "# Setup the detection and measurement tasks\n", + "detect = measAlg.SourceDetectionTask (config=detectSourcesConfig, schema=schema)\n", + "measure = measAlg.SourceMeasurementTask(config=measureSourcesConfig, schema=schema)\n", + "\n", + "# Set flux aliases to None; a hack for an incompatability between makeMinimalSchema() and the\n", + "# default SourceMeasurementConfig() options.\n", + "measureSourcesConfig.slots.psfFlux = None\n", + "measureSourcesConfig.slots.apFlux = None\n", + "measureSourcesConfig.slots.modelFlux = None\n", + "measureSourcesConfig.slots.instFlux = None\n", + "measureSourcesConfig.validate()\n", + "\n", + "# Detect the sources,then put them into a catalog (the table is where the catalog atually stores stuff)\n", + "table = afwTable.SourceTable.make(schema)\n", + "catalog = detect.makeSourceCatalog(table, exposure, sigma=5)\n", + "\n", + "# Get the sources out of the catalog\n", + "sources = catalog.sources\n", + "\n", + "# Apply the measurement routines to the exposure using the sources as input\n", + "measure.run(exposure, sources)\n", + "\n", + "# Now let's look at the output from some of the measurment algorithms.\n", + "fields = ['centroid.sdss', 'shape.sdss', 'shape.sdss.centroid','flux.gaussian']\n", + "keys = [schema.find(f).key for f in fields]\n", + "\n", + "for source in sources:\n", + " print source.getCentroid() #This uses one of the aliases\n", + "\n", + " # Now loop through the keys we want\n", + " for f,k in zip(fields, keys):\n", + " print ' ', f, source.get(k)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can also use the DS9 program to display our results. This will overlay the footprint and the source measured centroid to the sensor data. This is commented out by default in case you don't have ds9 installed." + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "#import lsst.afw.display.ds9 as ds9\n", + "##ds9.setMaskPlaneVisibility(\"DETECTED\",False)\n", + "#ds9.setMaskTransparency(75)\n", + "\n", + "#ds9.mtv(maskedImage)\n", + "#ds9.dot(\"+\", source.getX(), source.getY())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next we can take the code in this tutorial and turn it into a single program. Then, we can learn how to make it into a commandLine Task and use some framework code that will take care of some more things I did in the last step for us automatically. I do that in the next notebook." + ] } - ] -} \ No newline at end of file + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.9" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/lsst_e_99999999_f2_R22_S11_E000.fits.gz b/lsst_e_99999999_f2_R22_S11_E000.fits.gz new file mode 100644 index 0000000..38b55ab Binary files /dev/null and b/lsst_e_99999999_f2_R22_S11_E000.fits.gz differ