diff --git a/nb/AssocStats.ipynb b/nb/AssocStats.ipynb new file mode 100644 index 0000000..09d4292 --- /dev/null +++ b/nb/AssocStats.ipynb @@ -0,0 +1,500 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "5334840a", + "metadata": {}, + "source": [ + "# Comparision between MultiMatch and NWayMatch\n", + "\n", + "MultiMatch is the current default Multi-catalog matcher in the Rubin DM stack. It performs a series\n", + "of two-way catalog matches, updating the reference catalog as it goes.\n", + "\n", + "NWayMatch is a simple proof-of-concept for multi-catalog matching.\n", + "Rather than do a series of 2-way matches, it clusters sources and then resolves\n", + "the cluster membership to ensure that each input catalog only contributes at most\n", + "one source to any given \"object\".\n", + "\n", + "This example assumes that you:\n", + "\n", + " 1. Have downloaded the data here: https://lsst.ncsa.illinois.edu/~yusra/nway-matcher/\n", + " 2. Are running from the directory you download the data into.\n", + " 3. Have run MultiMatch on those data (using multiMatch.py to generate matchCat.fits)\n", + " 4. Have run NWayMatch on those data (using nway.py to generate out.fits)" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "60918b94", + "metadata": {}, + "outputs": [], + "source": [ + "%matplotlib inline\n", + "import matplotlib.pyplot as plt\n", + "import matplotlib.colors as colors" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "b56436d9", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "from astropy import table\n", + "from astropy.table import Table" + ] + }, + { + "cell_type": "markdown", + "id": "2a252a44", + "metadata": {}, + "source": [ + "#### Read the input tables" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "87504966", + "metadata": {}, + "outputs": [], + "source": [ + "cAssoc = Table.read('out.fits', hdu=1)\n", + "oAssoc = Table.read('out.fits', hdu=2)\n", + "cStats = Table.read('out.fits', hdu=3)\n", + "oStats = Table.read('out.fits', hdu=4)\n", + "mAssoc = Table.read('matchCat.fits')" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "5ce79e7d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "64065" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "(cStats['nObject'] != 1).sum()" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "8b46a7d6", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1050857\n", + "462058\n", + "910162\n", + "367735\n" + ] + } + ], + "source": [ + "print(len(oStats))\n", + "print((oStats['nSrcs'] == 1).sum())\n", + "print(len(cStats))\n", + "print((cStats['nSrcs'] == 1).sum())" + ] + }, + { + "cell_type": "markdown", + "id": "c2cdba66", + "metadata": {}, + "source": [ + "#### Quick check on the input tables.\n", + "\n", + "Note that there are 8636020 total sources in the input catalogs.\n", + "\n", + "Right away we see that MultiMatch is leaving some sources unassociated. This is\n", + "actually b/c of the way that it is removing 'ambiguities', i.e., cases were we\n", + "have multiple sources from a single catalog inside the matching radius." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "42148cf7", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Total number of sources assocaited to NWayMatch Clusters: 8636020\n", + "Total number of sources assocaited to NWayMatch Objects: 8636020\n", + "Total number of sources assocaited to MutliMatch Objects: 7923128\n" + ] + } + ], + "source": [ + "print(\"Total number of sources assocaited to NWayMatch Clusters: %i\" % len(cAssoc))\n", + "print(\"Total number of sources assocaited to NWayMatch Objects: %i\" % len(oAssoc))\n", + "print(\"Total number of sources assocaited to MutliMatch Objects: %i\" % len(mAssoc))" + ] + }, + { + "cell_type": "markdown", + "id": "8bf50dca", + "metadata": {}, + "source": [ + "#### Lets look at the number of sources per cluster and per object in NWayMatch" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "e631e602", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "# This is the number of source per cluster. The high-end tail depends on the cell size\n", + "_ = plt.hist(cStats['nSrcs'], bins=np.linspace(0.5, 90.5, 91))\n", + "plt.yscale('log')" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "04d827ca", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "# This is the number of sources per object. It can not exceed the number of input catalogs\n", + "_ = plt.hist(oStats['nSrcs'], bins=np.linspace(0.5, 35.5, 36))\n", + "plt.yscale('log')" + ] + }, + { + "cell_type": "markdown", + "id": "0d10492d", + "metadata": {}, + "source": [ + "### Now lets compare the number of sources per object from MultiMatch.\n", + "\n", + "We see that NWayMatch is giving slightly more associations. Again, this is b/c of the\n", + "associations that have been removed." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "cef4a887", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "# This is the number of sources per object\n", + "# We are using np.bincount to count the number of times a given object id occurs in the association catalog\n", + "_ = plt.hist(oStats['nSrcs'], bins=np.linspace(0.5, 35.5, 36))\n", + "_ = plt.hist(np.bincount(mAssoc['object']), bins=np.linspace(0.5, 35.5, 36))\n", + "plt.yscale('log')" + ] + }, + { + "cell_type": "markdown", + "id": "22970b08", + "metadata": {}, + "source": [ + "### Now let's make vectors that keep track of how sources are in each object\n", + "\n", + " srcCountC -> Number of sources in each cluster\n", + " srcCountO -> Number of sources in each NWayMatch object\n", + " srcCountM -> Number of sources in each MultiMatch object" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "ad404e14", + "metadata": {}, + "outputs": [], + "source": [ + "srcCountC = np.bincount(cAssoc['object'])\n", + "srcCountM = np.bincount(mAssoc['object'])\n", + "srcCountO = np.bincount(oAssoc['object'])" + ] + }, + { + "cell_type": "markdown", + "id": "868001f8", + "metadata": {}, + "source": [ + "#### Now let's join the tables, using the 'id' column as the matching key\n", + "\n", + "This could take about a minute" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "1ea125ff", + "metadata": {}, + "outputs": [], + "source": [ + "jj = table.join(oAssoc, mAssoc, join_type='outer', keys='id')" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "724203ad", + "metadata": {}, + "outputs": [], + "source": [ + "jc = table.join(cAssoc, mAssoc, join_type='outer', keys='id')" + ] + }, + { + "cell_type": "markdown", + "id": "05c51ab3", + "metadata": {}, + "source": [ + "#### Now we can get parallel arrays, with the number of sources associated to each input source\n", + "\n", + " mo -> number of sources in the associated NWayMatch Object\n", + " mc -> number of sources in the associated NWayMatch Cluster\n", + " mm -> number of sources in the associated MultiMatch Object" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "0d531b5e", + "metadata": {}, + "outputs": [], + "source": [ + "mo = srcCountO[jj['object_1'].data]\n", + "mc = srcCountC[jc['object_1'].data]\n", + "mm = np.where(jj['object_2'].data.mask, 0, srcCountM[jj['object_2'].data])\n", + "mask = mo != mm\n", + "mask2 = mc != mm" + ] + }, + { + "cell_type": "markdown", + "id": "b94f9535", + "metadata": {}, + "source": [ + "Make a density plot of the number of sources in the NWayMatch cluster versus the number of associated sources in MultiMatch. Note that the Clusters can have many more sources than the MultiMatch objects. If the same matching radius is used, and is the same as the cell size, there should never be fewer sources in a cluster than in a MultiMatch object. " + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "690cd81e", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "norm=colors.LogNorm(vmin=0.9, vmax=1e5)\n", + "oo = plt.hist2d(mm[mask2], mc[mask2], bins=[np.linspace(-0.5, 33.5, 35), np.linspace(-0.5, 100.5, 102)], norm=norm)\n", + "cb = plt.colorbar()\n", + "_ = plt.xlabel(\"Associated Sources (Multi-Match)\")\n", + "_ = plt.ylabel(\"Assocaited Sources (Clustering)\")" + ] + }, + { + "cell_type": "markdown", + "id": "40af8016", + "metadata": {}, + "source": [ + "Make a density plot of the number of sources in the NWayMatch objects versus the number of associated sources in MultiMatch. Note that feature where nSrcMultiMatch == 0. These are sources that have had all their associated removed b/c of ambiguities." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "7742580d", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "norm=colors.LogNorm(vmin=0.9, vmax=1e5)\n", + "oo = plt.hist2d(mm[mask], mo[mask], bins=[np.linspace(-0.5, 33.5, 35), np.linspace(-0.5, 33.5, 35)], norm=norm)\n", + "cb = plt.colorbar()\n", + "_ = plt.xlabel(\"Associated Sources (MultiMatch)\")\n", + "_ = plt.ylabel(\"Assocaited Sources (NWayMatch)\")" + ] + }, + { + "cell_type": "markdown", + "id": "0b699bc9", + "metadata": {}, + "source": [ + "Now let's make a histogram of the difference in the number of sources\n", + "associated to any given source. (I.e,. there is one entry per source, and the\n", + "x-axis value is the difference in the number of associated sources as found\n", + "by MultiMatch and NWayMatch) " + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "1920877a", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.yscale('log')\n", + "_ = plt.hist(mm-mo, bins=np.linspace(-33.5, 33.5, 68))\n", + "_ = plt.xlabel(r\"$n_{\\rm assoc, mm} - n_{\\rm assoc, nw}$\")" + ] + }, + { + "cell_type": "markdown", + "id": "2fbd0e8d", + "metadata": {}, + "source": [ + "Now let's make a histogram of the difference in the number of sources\n", + "associated to a cluster as compared to the number associated to a MultiMatch\n", + "object. Really this is just telling us about the cell size and the number of\n", + "sources inside the matching radius." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "794f7050", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.yscale('log')\n", + "_ = plt.hist(mm[mask2]-mc[mask2], bins=np.linspace(-66.5, 33.5, 101))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9b1d8abb", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "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.8.8" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/nb/NWayExample.ipynb b/nb/NWayExample.ipynb new file mode 100644 index 0000000..5570b21 --- /dev/null +++ b/nb/NWayExample.ipynb @@ -0,0 +1,683 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "c39d1178", + "metadata": {}, + "source": [ + "### Example of using NWayMatch\n", + "\n", + "MultiMatch is the current default Multi-catalog matcher in the Rubin DM stack. It performs a series\n", + "of two-way catalog matches, updating the reference catalog as it goes.\n", + "\n", + "NWayMatch is a simple proof-of-concept for multi-catalog matching.\n", + "Rather than do a series of 2-way matches, it clusters sources and then resolves\n", + "the cluster membership to ensure that each input catalog only contributes at most\n", + "one source to any given \"object\".\n", + "\n", + "This example assumes that you:\n", + "\n", + " 1. Have downloaded the data here: https://lsst.ncsa.illinois.edu/~yusra/nway-matcher/\n", + " 2. Are running from the directory you download the data into.\n", + " 3. Have run MultiMatch on those data for comparison (using multiMatch.py to generate matchCat.fits)" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "82931de3", + "metadata": {}, + "outputs": [], + "source": [ + "%matplotlib inline\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "ec4aff3d", + "metadata": {}, + "outputs": [], + "source": [ + "import glob\n", + "import os\n", + "import numpy as np\n", + "from nway import NWayMatch" + ] + }, + { + "cell_type": "markdown", + "id": "4dbe80c9", + "metadata": {}, + "source": [ + "### Define the inputs and the parameters for the map used to cluster the sources" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "882c072e", + "metadata": {}, + "outputs": [], + "source": [ + "DATADIR = \".\"\n", + "SOURCE_TABLEFILES = glob.glob(os.path.join(DATADIR, \"sourceTable-00*.parq\"))\n", + "VISIT_IDS = np.arange(len(SOURCE_TABLEFILES))\n", + "\n", + "REF_DIR = (150., 2.) # RA, DEC in deg\n", + "REGION_SIZE = (3., 3.) # in Deg\n", + "CELL_SIZE = 1. / (3600*2) # in Deg = 0.5\"\n", + "SUBREGION_SIZE = 1350 # in Pixels\n", + "PIXEL_R2CUT = 1." + ] + }, + { + "cell_type": "markdown", + "id": "29ebecf0", + "metadata": {}, + "source": [ + "### Construct a matcher object\n", + "\n", + "This will construct at WCS to grid a 3deg x 3deg region around ra=150, dec=2 at 5e-5 deg resolution\n", + "\n", + "It will also define a set of 1350 cell x 1350 cell sub-regions that will be analyzed independently" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "2a2985d4", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[16. 16.]\n" + ] + } + ], + "source": [ + "nWay = NWayMatch.create(REF_DIR, REGION_SIZE, CELL_SIZE, pixelR2Cut=PIXEL_R2CUT, subRegionSize=SUBREGION_SIZE)\n", + "print(nWay.nSubRegion)" + ] + }, + { + "cell_type": "markdown", + "id": "a3fd7e41", + "metadata": {}, + "source": [ + "### Reduce the input data\n", + "\n", + "This will project the input data into the WCS constructed above" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "6444ae1e", + "metadata": {}, + "outputs": [], + "source": [ + "nWay.reduceData(SOURCE_TABLEFILES, VISIT_IDS)" + ] + }, + { + "cell_type": "markdown", + "id": "ce9ed699", + "metadata": {}, + "source": [ + "### Analyze one of the sub-regions" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "e033efbd", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "oDict = nWay.analyzeSubregion(10, 10, True)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "69f27f14", + "metadata": {}, + "outputs": [], + "source": [ + "srd = oDict['srd']\n", + "cd = srd._clusterDict\n", + "idx = 17009734\n", + "image = oDict['image']\n", + "cluster = cd[idx]" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "4f50e260", + "metadata": {}, + "outputs": [], + "source": [ + "srcIdx = np.hstack([df['sourceId'] for df in srd._data])" + ] + }, + { + "cell_type": "markdown", + "id": "e58a553e", + "metadata": {}, + "source": [ + "### This function will draw a cluster\n", + "\n", + "The background image is the pixels used to do the cluster, the color scale \n", + "shows the number of sources per pixel\n", + "\n", + "The blue dots in the foreground are the positions of the individual sources\n", + "\n", + "The red cross is the cluster centroid" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "4b23afa2", + "metadata": {}, + "outputs": [], + "source": [ + "def showCluster(img, cluster, srd, mask=None):\n", + " extent = (0, cluster._footprint.getBBox().getWidth(),\n", + " 0, cluster._footprint.getBBox().getHeight())\n", + " cluster.extract(srd)\n", + " xOffset = srd._minCell[0] + cluster._footprint.getBBox().getBeginY()\n", + " yOffset = srd._minCell[1] + cluster._footprint.getBBox().getBeginX()\n", + " xOff = cluster.xCell - xOffset\n", + " yOff = cluster.yCell - yOffset\n", + " if mask is not None:\n", + " xOff = xOff[mask]\n", + " yOff = yOff[mask]\n", + " xC = cluster._xCent - xOffset\n", + " yC = cluster._yCent - yOffset\n", + " img = plt.imshow(image[cluster._footprint.getBBox()].array, origin='lower', extent=extent)\n", + " cb = plt.colorbar()\n", + " img.axes.scatter(yOff, xOff)\n", + " img.axes.scatter(yC, xC, marker='+', c='green')\n", + " return img.axes.figure" + ] + }, + { + "cell_type": "markdown", + "id": "c8e69ce7", + "metadata": {}, + "source": [ + "### This function will draw a cluster and show the objects\n", + "\n", + "Same as above, expect the dots are color-coded to show how the cluster way broken down" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "775d2065", + "metadata": {}, + "outputs": [], + "source": [ + "def showObjects(img, cluster, srd):\n", + " extent = (0, cluster._footprint.getBBox().getWidth(),\n", + " 0, cluster._footprint.getBBox().getHeight())\n", + " cluster.extract(srd)\n", + " xOffset = srd._minCell[0] + cluster._footprint.getBBox().getBeginY()\n", + " yOffset = srd._minCell[1] + cluster._footprint.getBBox().getBeginX()\n", + " xOff = cluster.xCell - xOffset\n", + " yOff = cluster.yCell - yOffset\n", + " img = plt.imshow(image[cluster._footprint.getBBox()].array, origin='lower', extent=extent)\n", + " cb = plt.colorbar()\n", + " colors = ['red', 'blue', 'green', 'cyan', 'orange', 'grey']\n", + " for iObj, obj in enumerate(cluster.objects):\n", + " xC = obj._xCent - xOffset\n", + " yC = obj._yCent - yOffset\n", + " img.axes.scatter(yOff[obj._mask], xOff[obj._mask], c=colors[iObj%6])\n", + " img.axes.scatter(yC, xC, marker='+', c=colors[iObj % 6])\n", + " return img.axes.figure" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "cb1c5fb0", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAWAAAADxCAYAAAD1LG0eAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/Z1A+gAAAACXBIWXMAAAsTAAALEwEAmpwYAAAZWklEQVR4nO3dfbBcdX3H8fcnuQFCCOEhsQRCDbWZoNgWMWIpliIqRJohraMz0NFa2yna0daHltaHGZi2U0eHjlofKk2Foq2FWhWhiDyobaNMsYSAmEhSokQNCSaXYBJISLj3fvvH7sJmsw/nnD1nz7k5nxdzJnfPnv3tN4fN9/72e36/31FEYGZmozej7ADMzOrKCdjMrCROwGZmJXECNjMriROwmVlJnIDNzEriBGxmlpKk6yRtl7Suy3N/JikkzR/UjhOwmVl61wPLO3dKOhV4DfDjJI04AZuZpRQRq4GdXZ76KPDnQKIZbmN5BmVmVlUXvXJOPL5zMtGx9z24fz3wdNuuVRGxqt9rJF0CPBoR35WU6H2cgM2sFsZ3TvKdOxYlOnbWwh88HRHLkrYt6WjgA8CFaWJyAjazmggmY6qoxl8AnAa0er+LgLWSzo6Ix3q9yAnYzGohgKlkpdn0bUd8D3he67GkzcCyiBjv9zpfhDOz2phK+N8gkm4A/gdYKmmLpD/IEo97wGZWC0HwTE4liIi4bMDzi5O04wRsZrUQwGRBJYisnIDNrDaKqgFn5QRsZrUQwGTF7gDkBGxmtVHYILSMnIDNrBaCcA3YzKwMEfBMtfKvE7CZ1YWYJNkaDaPiBGxmtRDAlHvAZmblcA/YzKwEjYkYTsBmZiMXwDNRreVvnIDNrBYCMVmx9cecgM2sNqbCJQgzs5FzDdjMrDRismI14GpFY2ZWkMYdMWYk2gaRdJ2k7ZLWte37a0kPSnpA0p2STh7UjhOwmdVChDgQMxNtCVwPLO/Yd3VE/HJEnAncClw5qBGXIMysNqZyqgFHxGpJizv27W57OAcGr/zjBGxmtdC4CFfsl35JfwP8LrALeOWg412CMLOaaFyES7IB8yWtadsuT/IOEfGBiDgV+DzwjkHHuwdsZrXQugiX0HhELBvi7f4V+CpwVb+DnIDNrDYmC5yIIWlJRDzcfHgJsGHQa5yAzawWAvFM5JPyJN0AnE+jVLGFRk/3YklLadz56EfA2wa14wRsZrWQ50W4iLisy+5r07bjBGxmtRCo0BJEFk7AZlYbKS7CjYQTsJnVQgSVWwvCCdjMaqFxES7RNOORcQI2s9rwguxmZiUI5AXZzczK4h6wmVkJApjyRTgzszLItyQyMytD47b0HgVhZjZyEXIJwsysLJ6IYWZWgsZ6wK4Bm5mVoHq3pXcCNrNaaAxDcw/YzGzkqrgWRLX642ZmBZpiRqJtEEnXSdouaV3bvqslbZD0oKSbJB03qB0nYDOrhcZylEq0JXA9sLxj313AiyPil4H/A943qBEnYDOrjalQom2QiFgN7OzYd2dETDQf3gMsGtSOa8BmVguN1dAS9znnS1rT9nhVRKxK8Xa/D/zboIOcgM2sFhpTkRMn4PGIWJblfSR9AJgAPj/oWCdgM6uJ4qciS3ozsAJ4VUTEoOOdgM2sNoqcCSdpOfAXwG9ExN4kr3ECNrNaaI2CyIOkG4DzadSKtwBX0Rj1cCRwlySAeyLibf3acQI2s9rIqwQREZd12X1t2nacgM2sFnxPODOzkgQw4cV4zMzK4QXZzczKkHCW2yg5AZtZLXhBdjOzErkHbGZWAi/IbmZWkkBMTPkinJlZKVwDNjMrQ7gEYWZWCteAzcxK5ARsZlaCQEz6IpyZWTl8Ec7MrARRwYtw1eqPm5kVKEKJtkEkXSdpu6R1bfveIGm9pClJie4n5wRsZjWR7Jb0CXvJ1wPLO/atA14HrE4a0cAE3C3TdzwvSR+XtEnSg5LOSvrmZmajlFcPOCJWAzs79j0UERvTxJOkB3w9h2b6dq8FljS3y4FPpwnAzGwUImBySok2Gvd6W9O2XV5ETAMvwkXEakmL+xyyEvhc8xbM90g6TtLCiNiWV5BmZnlIMQpiPCIS1XGHkccoiFOAn7Q93tLc5wRsZpURkKi8MEp5JOBuf6PoemCjG385wEzNeumcI07M4e2nvyVLnyg7hMr4vwePLjuEytCRR5YdQmXs3v/YeEQsGK6Vw/OOGFuAU9seLwK2djswIlYBqwDmHbUwzln85hzefvq77Y4vlR1CZVx08pllh1AZMxe/oOwQKuOOjR/+UR7tRNeuYXqSbgDOp1Er3gJcReOi3CeABcBXJT0QERf1ayePBHwL8A5JNwIvB3a5/mtmVZRXCSIiLuvx1E1p2hmYgHtk+lnNIK4BbgMuBjYBe4G3pAnAzGwUGqMgqjX1IckoiF6ZvvV8AG/PLSIzs4LkVYLIi9eCMLPaOBxHQZiZVV6QbJbbKDkBm1ltVKwC4QRsZjUREFPuAZuZlcIlCDOzkngUhJlZCQ7XtSDMzKovACdgM7NyuARhZlYKeRSEmVlp3AM2MytB+CKcmVl5KtYDrtbabGZmhVLCbUArXe4WL+kESXdJerj55/GD2nECNrP6mEq4DXY9h94t/r3ANyJiCfCN5uO+nIDNrB5a44CTbIOailhN4xZE7VYCn23+/Fngtwa14xqwmdVGinHA8yWtaXu8qnlPy35+rnU7tojYJul5g97ECdjM6iN5Ah6PiGUFRgK4BGFmdZJTCaKHn0paCND8c/ugFzgBm1ltKJJtGd0CvLn585uBmwe9wCUIM6uHEOQ0FbnH3eI/BHxB0h8APwbeMKgdJ2Azq4+cJmL0uVv8q9K04wRsZvVRsZlwTsBmVh9OwGZmJajgguyJRkFIWi5po6RNkg6ZXifpfEm7JD3Q3K7MP1Qzs+EUPAoitYE9YEkzgU8BrwG2APdKuiUivt9x6LciYkUBMZqZ5WMaliDOBjZFxA8BJN1IY85zZwK2aezmDWdx9d0r2LbneBbOfYIrzr2VlaevLTsss1yNsnebRJISxCnAT9oeb2nu63SOpO9K+pqkM7o1JOlySWskrTkwuTdDuFaEmzecxfu/filb95xAILbuOYH3f/1Sbt5wVtmhmeWr2JlwqSXpAXeLpvP3yFrg+RHxpKSLga8ASw55UWMxi1UA845aWLHfRfXT6vVu3XM8nf+b900cwdV3r3Av2A4fwbQsQWwBTm17vAjY2n5AROxu+/k2SX8vaX5EjOcTpuWt1evdN3FEz2O27Rm4nnSu8Vx99wq2XnE8Y7uf4sTV93HsQ4+M7P2tJqZhAr4XWCLpNOBR4FLgd9oPkHQS8NOICEln0yhtPJ53sJafq+9e0Tf5Aiyc+0SmttPWkw/6ZSCYmHcM25efC+AkbLlSssXWR2ZgAo6ICUnvAO4AZgLXRcR6SW9rPn8N8HrgjyRNAPuASyNSrLxpIzeodzt77ABXnHtr6nY7e9atejLQMwl3+2UQs8Z4/LyXOgFbviqWlRJNxIiI24DbOvZd0/bzJ4FP5huaFWnh3CfYuueELs8EJw8xCqJbMh1UT+71y2Di2Dmp39+sl1GP8U3CM+Ey2HXKAnacsZiJ2Ucytm8/C9ZvZt6jO8oOK5Urzr31kBrw7LEDfPDVNw514a1XMu3X4+71y2Bs91OZ4zDrajrOhLPn7DplAY+9ZAkTRx8FEhNHH8VjL1nCrlMWlB3as27ecBavuPZKXvCxj/KKa6/sOpxs5elr+eCrb+TkuTsRwclzdw6dfKF33bhfPfmKc29l9tiBg/bpmQlOXH3fULGYHSISbiPiHnBKO85YTIzNPGhfjM1kxxmLK9ELTlODXXn62tyHmfXqWferJ7diuPruFWzd/dwoCIBH3vp6Jo6d45ERlguXIKa5idlHpto/allqsHlqT6ZpZtW1fhlcdPKZAOx+4WlsX34uMavxEfXIiIbDofxVmshvFISkdwJ/SGMA/T9GxMeytFPrBJzlwzy2b3+j/NBlfxVkqcHmpXP42UeW/3PmpP/4eS99Nvm21H1kRKv81foG1ip/AU7CSeXQA5b0YhrJ92zgAHC7pK9GxMNp26ptDThrLXfB+s1oYvKgfZqYZMH6zQVGm1yWGmwe8p7O3GsERJ1HRvQrfyW165QFbLrwZWxY+Qo2XfiySl27GIl8asAvBO6JiL0RMQH8N/DbWcKpbQJO+2FufXC3LVsKk5PM2P8MRDC292lOuv/hyvRAul3QyjqmN41+pY8seo2AqOPIiNZnb9jy13S4gFy0FMtRzm+tW9PcLm9rZh1wnqQTJR0NXMzBs4UTq20JIs2HufOrXxx5BExMsnDNxsok3pasNdhu0sxoG1T6uOCWLQB885JFid77xNX3HVQDhnqOjOj87HUzqPzVXmpDBw/DqtIF5IoZj4hl3Z6IiIckfRi4C3gS+C4wkeVNapuA09Ry8xj5kKbePOzSkHmMbkgymqI9zhmaYjIOTRJZSx+tOu/j57201qMgun322g0qfyVJ4FW5gDwS+d2U81rgWgBJH6SxZk5qtU3AC9ZvPuSD2evDnNdXvyQXT7JM5R1Wt4Q/aDRFZ5yN5Bu0r6o2e+wAu+f8KRfcsof/3vY0kK4nfOxDj5SWcHe/8LRKJP+en7EIxvbtZ862x9lxxmK2LVva9Rf7oAQO1bmAXLh8R0E8LyK2S/p54HXAOVnaqW0NeN6jOzjp/ocZ2/v0wFpurw9o0g9umnpz1lpqkskXvV7X7eLZ1gElhe6L+YiZmjxoYgfA/due+3uO752bKK4ytYbATcw7plErbQ6B2/3C00YeS7/P3oL1m9n9/JP61nQHdRKqdAF5JPKbiPElSd8H/gN4e0Rk+qpX2x4wNJJwkhJCmt5yN2l60FmGkQ3Ta+6V8Gdqsm9JoVc8UzGDH7zr3c/GNTn+Dxw/cQT7j2jcSnBy/K9456tvpLGEdHdl9z6rNASu32cvSWmsV6mt1YOu0zhikd9EjIj49TzaqW0POI00veVu+vWUN134soN6q1mGkQ0zAqFXIp2MGX1HUySJM0tcVeh9VmkIXL/PXpJf7L2GTS5cs5FfvPPe2iTfZ1VsKrITcELzHt3BL955LwvXbARg27KlicdRdvtHADz7tbF9vGyWYWTDTL7olUhPnvtE37UiksTZ/v4nHfgQJx340MC4+vU+R6VqQ+Ban73Tb/72QUkzSWls2M7DYSXhELRK3RXZnpN1JlLruV5DgdovbmUZRtZrNbEkIxD6rd3QbzRFkjizxFWF3mfWIXCjLp0kLY11ltraxxXXrQzBdFuQ3Z4zzHC01j+CDStf0fX59l5h2mFkWRbAaX8vyDZueFCcWeIa2/1Uo/zQZf+oZBkCV8baFZ2/2JMk07pPZ/ZiPNNYHgvx9LooMsxU4WEnX3S+vlWjzTrsrX1Y27wjn+KosQP87Ok5ieKqygSMtEPgyrpwl/RCckvVV/MrnBPw9JXHQjzdvjbmMVV4mMkXeY497mzrZ/uPYfbYgcQL80zXCRhVKJ0kUfXV/Ao1Te+KbE3DDkeD7l8bP/i6L5R6+/c8l7DMo60yJ2BkVYXSSRJVX82vaC5BTGNZam692ml/zcr3l5d8Id8lLMtcDrNMVSmdDJJHJ2JacwKe3tLW3KaDYUZRFNnWdDJdSid5dSKmq2l3W3o7/A0ziqLItqab6VI6ORw7EYm4BmxVlOcSlsO0dfOGs3jkra+rdA/Spi/RvlRUNTgBG5DvDTqztNUaPTExr9Fz9j3grBAV6wEnmoosabmkjZI2SXpvl+cl6ePN5x+UlO0+NFZb3UZPjHoKsh3+qjYVeWACljQT+BTwWuBFwGWSXtRx2GuBJc3tcuDTOcdph7leoySqNo7WprlpuBjP2cCmiPhhRBwAbgRWdhyzEvhcNNwDHCdpYc6x2mGs1yiJqo2jtWmsuSB7km1UkiTgU4CftD3e0tyX9hiznrqtrlbFcbQ2zeXUA5b0bknrJa2TdIOkLosuD5bkIly3C4edISY5huadRVt3F91/x8YPr0vw/kWbD4yXGcDMheXH0FRiHJuYMfv2EzRz1qkzjzl+LCYnDkw+ufPRzft27ywnngr8P9lYgRgaqhDH0jwayaO+K+kU4E+AF0XEPklfAC4Frk/bVpIEvIWDb7m8CNia4RgiYhWwCkDSml53HR2lKsRRhRiqEoekNRN7xn0uKhJDVeKQtCaXhvKr744BsyU9AxxNl3yXRJISxL3AEkmnSTqCRqa/peOYW4DfbY6G+FVgV0RsyxKQmVlRUoyCmC9pTdvW+uZORDwK/C3wY2AbjXx3Z5Z4BvaAI2JC0juAO4CZwHURsV7S25rPXwPcBlwMbAL2Am/JEoyZWWGCNAuyj/fq9Us6nsbAg9OAnwH/LumNEfEvaUNKNBEjIm6jkWTb913T9nMAb0/53qtSHl+UKsRRhRigGnFUIQaoRhxViAGqEcfQMeR4U85XA49ExA4ASV8Gfg1InYDVyJ1mZoe3OQtOjdN/6z2Jjl37mffc16cH/HLgOuBlwD4aF9/WRMQn0sbkqchmVhvKocMZEd+R9EVgLTAB3E/GHnrhd0WuwjTmBDGcL2mXpAea25UFxHCdpO2Sug69G9V07gRxjOJcnCrpPyU91BxL+c4uxxR6PhLGMIpzcZSk/5X03WYcf9nlmKLPRZIYCj8XzfeZKel+SYcsnzf0eUg6BjhBjo6IqyLi9Ih4cUS8KSIyrWhfaA9Yz01jfg2NoWr3SrolIr7fdlj7NOaX05jG/PIRxwDwrYhYkdf7dnE98Engcz2eL/Q8pIgDij8XE8CfRsRaSXOB+yTdNcrPRcIYoPhzsR+4ICKelDQL+LakrzVnlLYUfS6SxADFnwuAdwIPAcd2eW7o81C1O2IU3QOuwjTmJDEULiJWA/0mFYxkOneCOAoXEdsiYm3z5z00/sF1zpws9HwkjKFwzb/fk82Hs5pbZ5oo+lwkiaFwkhYBvwl8pschQ5+H6TgVeRhVmMactP1zml/BvibpjBzfP6kqTece2bmQtBh4CfCdjqdGdj76xAAjOBfNr90PANuBuyJi5OciQQxQ/Ln4GPDn9B4sNvx5mIaL8Qwjt2nMBcewFnh+RPwK8AngKzm+f1JFn4ekRnYuJB0DfAl4V0Ts7ny6y0tyPx8DYhjJuYiIyYg4k8YM0rMlvbgzzG4vG3EMhZ4LSSuA7RHRb/GP4c5DwkkYlVqOcki5TWMuMoaI2N36CtYc8zxL0vwcY0ii6POQyKjORbPW+CXg8xHx5S6HFH4+BsUw6s9FRPwM+C9gecdTI/ts9IphBOfiXOASSZtplAkvkNQ5rnb481CzHnAVpjEPjEHSSZLU/PlsGufl8RxjSKIS07lHcS6a7V8LPBQRH+lxWKHnI0kMIzoXCyQd1/x5No1B/hs6Div6XAyMoehzERHvi4hFEbGYxr/Rb0bEGzsOG+o8tCZiVKkHXOgoiCpMY04Yw+uBP5I0QWNg9aWR8wwVSTcA59OYY74FuIrGxY6RTudOEEfh54JGb+dNwPeadUeA9wM/3xZH0ecjSQyjOBcLgc82R+vMAL4QEbeO8t9IwhhGcS4Okfd50FS1hkF4JpyZ1cIxJ5wav3TRuxIde8+Nf9ZzJlyePBPOzGpjlEPMknACNrP6qNgXfidgM6uNqs2EcwI2s3oIoGLXvJyAzaw2XAM2MytBjguy58YJ2MzqIaJyJYjC1wM2M6uKPGbCSVqq59ZFfkDSbknvyhKPe8BmVh85dIAjYiNwJjy73vijwE1Z2nICNrPaKKAG/CrgBxHxoywvdgI2s3oIYDJxBp4vaU3b41UR0e2+b5cCN2QNyQnYzGojRQ94fNBaEM3VFS8B3pc1HidgM6uPfEdBvBZYGxE/zdqAE7CZ1UbONeDLGKL8AB6GZmZ1keNt6SUdTeNO693u5pKYe8BmVgsClPwiXF8RsRc4cdh2nIDNrDZUsZlwTsBmVg8jvuFmEk7AZlYT1VsLwgnYzGrDq6GZmZXFPWAzsxJEfqMg8uIEbGb1Ua386wRsZvXhYWhmZmVxAjYzK0EAvimnmdnoiXAJwsysNFPV6gI7AZtZPbgEYWZWHpcgzMzKUrEE7AXZzawmmovxJNkGkHScpC9K2iDpIUnnZInIPWAzq4d0d0Ue5O+A2yPi9c2bcx6dpREnYDOrjTxqwJKOBc4Dfg8gIg4AB7K05RKEmdVHPiWIXwB2AP8k6X5Jn5E0J0s4TsBmVg8BTEWyDeZLWtO2Xd7W0hhwFvDpiHgJ8BTw3iwhuQRhZjWR6o4Y4xGxrMdzW4AtEfGd5uMvkjEBuwdsZvWRQwkiIh4DfiJpaXPXq4DvZwnHPWAzq4cAJnObCvfHwOebIyB+CLwlSyNOwGZWEwGRTwKOiAeAXiWKxJyAzaw+KjYTzgnYzOqhNQqiQpyAzaw+3AM2MyuJE7CZWQkiYHKy7CgO4gRsZvXhHrCZWUmcgM3MyhAeBWFmVoqAyGkiRl6cgM2sPvKbipwLJ2Azq4cI35bezKw0vghnZlaOcA/YzKwMqRZkHwknYDOrBy/GY2ZWjgDCU5HNzEoQ+S3ILmkzsAeYBCb63D+uLydgM6uNyLcE8cqIGB+mASdgM6uPis2EU1TsqqCZWREk3Q7MT3j4UcDTbY9XRcSqtrYeAZ6gUVr+h/bnUsXkBGxmlo6kkyNiq6TnAXcBfxwRq9O2MyP/0MzMDm8RsbX553bgJuDsLO04AZuZpSBpjqS5rZ+BC4F1WdryRTgzs3R+DrhJEjRy6L9GxO1ZGnIN2MysJC5BmJmVxAnYzKwkTsBmZiVxAjYzK4kTsJlZSZyAzcxK4gRsZlaS/wf/b/8PLnvg1wAAAABJRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "fig = showCluster(image, cluster, srd)" + ] + }, + { + "cell_type": "markdown", + "id": "e9bda0bc", + "metadata": {}, + "source": [ + "#### Pull out the ids of clusters of particular types\n", + "\n", + "split -> at least one of the input catalogs seems to have split the source\n", + "\n", + "singleCell -> all the sources are in a single cell\n", + "\n", + "confused -> there are multiple sources from many input catalogs" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "9b828f43", + "metadata": {}, + "outputs": [], + "source": [ + "split = []\n", + "for k, c in cd.items():\n", + " if c._nSrc == c._nUnique + 1:\n", + " split.append(k)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "abff7667", + "metadata": {}, + "outputs": [], + "source": [ + "confused = []\n", + "for k, c in cd.items():\n", + " if c._nSrc > c._nUnique + 4:\n", + " confused.append(k)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "a5251707", + "metadata": {}, + "outputs": [], + "source": [ + "singleCell = []\n", + "for k, c in cd.items():\n", + " if c._nSrc > 5 and c._footprint.getArea() == 1:\n", + " singleCell.append(k)" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "950da1b0", + "metadata": {}, + "outputs": [], + "source": [ + "twoCell = []\n", + "for k, c in cd.items():\n", + " if c._nSrc > 5 and c._footprint.getArea() == 2:\n", + " twoCell.append(k)" + ] + }, + { + "cell_type": "markdown", + "id": "1faca62d", + "metadata": {}, + "source": [ + "### Draw different types of clusters" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "5fde2aab", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "figTwoCell = showCluster(image, cd[twoCell[2]], srd)" + ] + }, + { + "cell_type": "markdown", + "id": "ef2573f0", + "metadata": {}, + "source": [ + "#### This is a simple split cluster" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "4bfc951f", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAATQAAAD8CAYAAAD5TVjyAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/Z1A+gAAAACXBIWXMAAAsTAAALEwEAmpwYAAAZ3klEQVR4nO3df4xd5X3n8feH8UwcGwNxnYDBTsK23mShCo5r2UROF1BKYiwqN1J2ZSuCbJbIpapXSTdFS/iDVErVRqJNdqOQuNNikVT8ULWBYCGDgShbWlKQjeUAxoZMiLWejonDjzXmpz0z3/3jnEmvr++d+9wzd+4998znJR3Nvec859zncPBXz3OeX4oIzMyq4IxeZ8DMrFMc0MysMhzQzKwyHNDMrDIc0MysMhzQzKwyWgY0Scsl/VjSAUn7JX2xQRpJ+pakEUlPSVpVc2y9pOfyYzd2+gbMrL81izGS/kzSv0ral28bWl6rVT80SUuBpRGxV9Ii4EngDyLi2Zo0G4D/BmwA1gL/KyLWShoAngeuBEaB3cDm2nPNbG5rFmOA/wy8HhF/lXqtliW0iDgSEXvzz8eBA8AFdck2At+PzOPAOXkm1wAjEfFCRJwA7s7TmpkByTEmybx2Ekv6IPBR4Im6QxcAh2u+j+b7Gu1f2+TaW4AtAAMM/M4Czmona9Zj//4jb/Y6C9aGQ4dP8tIrE5rJNT51xcJ4+ZWJpLRPPvXOfuDtml3DETFcn64uxqwDtkq6FtgDfDkiXp3ud5IDmqQzgR8AX4qI1+oPNzglptl/+s7s5oYBztLiWKtPpGbNSmDXrn29zoK1Yc2nDrdO1MJLr0zwxK5lSWkHl/787YhYPV2a+hgj6bvA18hixteAvwb+63TXSApokgbzH7ojIu5pkGQUWF7zfRkwBgw12W9mfS+YiMmOXKlRjImIX9Yc/1vg/lbXSWnlFHAbcCAivtEk2Q7g2ry181LgWEQcIWsEWCHpQklDwKY8rZn1uQAmiaRtOs1iTP4efsqngWda5SmlhLYOuAZ4WtK+fN9NwPsBImIbsJOshXMEeBP4fH5sXNJWYBcwAGyPiP0Jv2lmfWCSjpTQmsWYzZJWksXOQ8AftrpQy4AWEf9M43dhtWkC+OMmx3aSBTwzq5AgONmBKuc0MabtuNFWK6eZ2ZQAJlpUJ7vNAc3MCmv1fqzbHNDMrJAAJko247UDmpkV1plOG53jgGZmhQThd2hmVg0RcLJc8cwBzcyKEhPT9+jqOgc0MyskgEmX0MysKlxCM7NKyDrWOqCZWQUEcDLKtSyJA5qZFRKIiZKts+SAZmaFTYarnGZWAX6HZmYVIib8Ds3MqiCbsdYBzcwqIEKciIFeZ+MUDmhmVthkv71Dk7QduBo4GhG/3eD4DcBna673H4D3RsQrkg4Bx4EJYLzVMlZm1j+yRoFyVTlTcnM7sL7ZwYi4JSJWRsRK4CvAP0bEKzVJrsiPO5iZVUrWKJCydUvKIimP5qsZp9gM3DWjHJlZXyhjo0DHciNpAVlJ7gc1uwN4SNKTkrZ06rfMrBwmQklbt3SyUeD3gcfqqpvrImJM0vuAhyUdjIhHG52cB7wtAPNZ0MFsmdlsCMTJKFe7YifLi5uoq25GxFj+9yhwL7Cm2ckRMRwRqyNi9SDv6mC2zGw2TDUKpGzd0pFfknQ2cBlwX82+hZIWTX0GPknCUu5m1h+CtOpmqaqcku4CLgeWSBoFvgoMAkTEtjzZp4GHIuKNmlPPBe6VNPU7d0bEg53Lupn1WtkaBVJaOTcnpLmdrHtH7b4XgEuKZsyslfsOruKWx67myPH3sHTRq9yw7n42fnhvr7M1Z0TgsZxmnXDfwVXc9Mgm3hofAmDs+GJuemQTgINal2SNAuUa+lSu8GqW6JbHrv51MJvy1vgQtzx2dY9yNDeVrVHAJTTrS0eOv6et/a6edl4gT/Bo1glLF73K2PHFDffXc/V09vTjWE6z0rlh3f28e96JU/a9e94Jblh3/2lpXT2dHdm6nGckbd3iEpr1pamSVUo1st3qqaXyyulmHbPxw3uTqoztVE8tXbaMnVs5zbqqneqppYtQ6aqcDmhWeRs/vJe/+L27OX/RK4jg/EWv8Be/d7cbBDqgE/OhSVou6ceSDkjaL+mL+f7Fkh6W9LP8b8t3BK5y2pyQWj21dNl8aB15hzYOfDki9ubjv5+U9DDwX4AfRcTXJd0I3Aj8j+ku5IBmZgV1Zhm7iDgCHMk/H5d0ALgA2Eg2jhzge8D/wQHNzGZD1m0juYS2RNKemu/DETFcnyifHfujwBPAuXmwIyKO5PMqTssBzcwKaXMs50ut1hWRdCbZjNdfiojX8pl62uKAZmaFdWr6IEmDZMHsjoi4J9/9S0lL89LZUuBoq+u4ldPMCsmmD5r5BI/KimK3AQci4hs1h3YAn8s/f46aCWSbcQnNSs2DysutQ4PT1wHXAE9L2pfvuwn4OvAPkq4D/i/wn1pdyAHNSqubg8rrA+cVFz7Dj3/x2w6k08hm2+hIK+c/Q9P+H59o51oOaFZa0w0q72RwaRQ473jqd5n6N+bZORrLhj6V662VA5qV1kwGlbeqqtYeP0OTTJzWWndqgWE2Amn/60wJrZNa5kbSdklHJTVcsUnS5ZKOSdqXbzfXHFsv6TlJI3lPX7NkzQaPtxpUPlXiGju+mECMHV/Mnzx4Dau+++fcd3DVacdPD2aNeXaO002ipK1bUkpotwPfBr4/TZp/iohTJpeSNADcClwJjAK7Je2IiGcL5tXmmBvW3X9KVRDSBpU3qqqC+H/vnMlNj2xi/rwTDY635tk5TjXVylkmKas+PZr33m3XGmAkX/0JSXeTDWVwQLMk7cx5NuW+g6sYm6Yk9db4EG+NDyb8elBb7fTsHI2VrcrZqXdoH5P0U2AM+NOI2E82FutwTZpRYG2zC0jaAmwBmM+CDmXL+l07g8qnqpLNG8zaIyYJxDnvegMJ/vuD13DLY1e7xTNX1TUF9gIfiIjXJW0AfgisoPH/VdHsIvm4rmGAs7S4aTqzZhpXNU93zrve4I2T8zk5Od3//iIQgxo/Je1Ui+eesQ/O+W4dAYyXrIQ249xExGsR8Xr+eScwKGkJWYlseU3SZWQlOLNZkfLS/t3zTvDVK+5h4eDbSdc8GfNOC3xvjQ9x51O/e0qjw02PbOK+g6sK5bufVW6CR0nn5UMXkLQmv+bLwG5ghaQLJQ0Bm8iGMpjNimYv7Qc0cdrEjsfeWTij34om3TrmlMiqnClbt6R027gL+BfgQ5JGJV0n6XpJ1+dJPgM8k79D+xawKTLjwFZgF3AA+If83ZrZrGg21fZffeoOfv6lP+GGdfdzy2NXs+A783nxXV/p+O/PtW4dUxM89lW3jYjY3OL4t8m6dTQ6thPYWSxrZu1p1ioK8Dvb/pxX314ICIayLgf1LZmNDGocxCnVThGnldBgbnbrqGKjgFlp1LeK1g5renEo69v9zkDWR/zFoayUdt6Jrze4UnB+TUCsH+d5z7OXtt0/rmranOCxKxzQrNJSWz7rLRh8B8i6ajRqxVx9/qE5PwtIIMYny9XK6YBmlVb7XmuqJDZVUmtcMssaEU6Oz/v1Wp6NBqd70ZVMN9+PpShXeDXrsPbfawUTcQYn4/SuGnOuFbOVoP9aOc36WaOWz/NO/CXnnfjLJmeIZg0Fc60Vs5Wpd2gOaGZd0miR4W+u/3vOL9AiORdbMVspW0DzOzSrvGbvu+pn8pjO4Bnjc64Vs5VATLhRwKz36vusNZ7k8d8sHHzbjQANlK1RwAHN5qzaklv9NNz1ZjpUqooi3A/NrJSmAtuf7vpsw5LadO/P5vLKVOGAZlZOU0GonVlyu7kyVfmUbz60cr3RM+uxRq2iUzN0NDLdylRzQYSStm5xCc2sTjujAGayMlW/i4CJSZfQzCqj6MpUVVG26YMc0Kyy7ju4io/fdjO/+T+/ycdvu3lWZpRtNgfbXOizFrjKadYV3XpZX2RlquooX6OAA5pV0nQv6zsdbObyzBtRsuWMHNCskubyy/puKls/tJQ1BbZLOirpmSbHPyvpqXz7iaRLao4dkvS0pH2S9nQy42bTmesv67sha+U8I2nrlpRfuh1YP83xXwCXRcRHgK+Rr61Z44qIWBkRq4tl0ax9c/llfTdFpG3dkrJIyqOSPjjN8Z/UfH2cbP1Ns56a2y/ru6dsVc5Ov0O7Dnig5nsAD0kK4G/y1dEbkrQF2AIwnwUdzpbNRXP5ZX03BN3tkpGiYwFN0hVkAe3jNbvXRcSYpPcBD0s6GBGPNjo/D3bDAGdpccnaTsyskbL9Q+3I2zpJHwH+DtgYES9P7Y+IsfzvUeBeYE0nfs/MSiAgJpW0tdKo8VHSn0n617xRcZ+kDa2uM+OAJun9wD3ANRHxfM3+hZIWTX0GPgk0bCk1s/7UwZECt9O48fGbeaPiynzh8mm1rHJKugu4HFgiaRT4KjCY3UxsA24GfgP4jiSA8bxF81zg3nzfPODOiHiw9X2ZWb/oVAtmq8bHVCmtnJtbHP8C8IUG+18ALjn9DDOrgqmxnImW1PVFHZ6ukbDGVknXAnuAL0fEtB0JPTjdzIoJIJS2wUsRsbpmSwlm3wV+E1gJHAH+utUJHvpkZoXNZqfZiPjl1GdJfwu07BXtgGZmBaW1YBa+urQ0Io7kXz9NQqOiA5qZFdehElqTxsfLJa3Mf+UQ8IetruOAZmbFROeGPjVpfLyt3es4oJlZcSUbKuCAZmYzUNGxnGY2B032OgOnckAzs2Km+qGViAOamRXmNQXMrDoc0MysMlzlNLOqkEtoZlYJIZjFoU9FOKCZWXEuoZlZZTigmVllOKCZWSWUsGNtyxlrG63GUndckr4laUTSU5JW1RxbL+m5/NiNncy4mfWeIm3rlpQpuG+n8WosU64CVuTbFrJpc5E0ANyaH78I2Czpoplk1sxKJhK3LmkZ0PKFgV+ZJslG4PuReRw4R9JSsjU4RyLihYg4AdydpzWziihbCa0T79AuAA7XfB/N9zXav7bZRSRtISvhMV8LGTjrrA5kzbrlU+ev7HUWrA3P/9t64DPTb+/QEjS6o5hmf0MRMTy1IszQGfM7kC0zm1Wp1c0+K6GNAstrvi8DxoChJvvNrCpK1m2jEyW0HcC1eWvnpcCxfKWW3cAKSRdKGgI25WnNrCI0mbZ1S8sSWpPVWAYBImIbsBPYAIwAbwKfz4+NS9oK7AIGgO0RsX8W7sHMeqVkJbSWAa3Jaiy1xwP44ybHdpIFPDOrmG63YKbwSAEzK65krZwOaGZWnEtoZlYVrnKaWTVEd1swUzigmVlxLqGZWWU4oJlZVZTtHVonRgqYmZWCS2hmVlzJSmgOaGZWjFs5zaxSXEIzsyoQ5WsUcEAzs+JKFtDcymlmxSSuJ5BSimu0upykxZIelvSz/O97Wl3HAc3MiptM3Fq7ndNXl7sR+FFErAB+lH+flgOamRXWqRJak9XlNgLfyz9/D/iDVtfxOzQzKy79HdoSSXtqvg9HxHCLc87Np/MnIo5Iel+rH3FAM7Ni2lvR6aWIWD17mckkVTklrZf0nKQRSafVYyXdIGlfvj0jaULS4vzYIUlP58f2nH51M+tXs7zQ8C/zRcvJ/x5tdULLgCZpALgVuAq4CNgs6aLaNBFxS0SsjIiVwFeAf4yI2vrwFfnxWY/QZtZFs7su5w7gc/nnzwH3tTohpYS2BhiJiBci4gRwN9nLumY2A3clXNfM+lynlrHLV5f7F+BDkkYlXQd8HbhS0s+AK/Pv00p5h3YBcLjm+yiwtkmmFpA1vW6t2R3AQ5IC+JtmLwIlbQG2AMzXwoRsmVlPdXBV9GlWl/tEO9dJCWiNlnVpdhu/DzxWV91cFxFjeQvFw5IO5k20p14wC3TDAGfPW1Ky/sdmVk80Dg69lFLlHAWW13xfBow1SbuJuupmRIzlf48C95JVYc2sCmb3HVrbUgLabmCFpAslDZEFrR31iSSdDVxGzYs7SQslLZr6DHwSeKb+XDPrT7Pcytm2lJXTxyVtBXYBA8D2iNgv6fr8+LY86aeBhyLijZrTzwXulTT1W3dGxIOdvAEz66GSvRxK6lgbETuBnXX7ttV9v51sPFbtvheAS2aUQzMrJ0/waGaV0o8lNDOzRjzBo5lVhwOamVWFS2hmVg1B6uSNXeOAZmaFeJEUM6sWBzQzqwpFuSKaA5qZFdPlcZopHNDMrDC/QzOzyvDQJzOrDpfQzKwSujw1UAoHNDMrzgHNzKrAHWvNrFI0Wa6I5oBmZsW4H5qZVUnZum2kLJKCpPWSnpM0IunGBscvl3RM0r58uzn1XDPrYyVb9allCU3SAHAr2crFo8BuSTsi4tm6pP8UEVcXPNfM+lDZGgVSSmhrgJGIeCEiTgB3AxsTrz+Tc82szAKISNu6JCWgXQAcrvk+mu+r9zFJP5X0gKSL2zwXSVsk7ZG058Tk2wnZMrNe02Ta1i0pjQKNVnuvD7l7gQ9ExOuSNgA/BFYknpvtjBgGhgHOnrekZAVZM6tXxn5oKSW0UWB5zfdlwFhtgoh4LSJezz/vBAYlLUk518z6VGp1s2RVzt3ACkkXShoCNgE7ahNIOk/58uiS1uTXfTnlXDPrX4q0rVtaVjkjYlzSVmAXMABsj4j9kq7Pj28DPgP8kaRx4C1gU0QE0PDcWboXM+u2klU5kzrW5tXInXX7ttV8/jbw7dRzzawayvYOzSMFzKyYACbKFdEc0MysMJfQzKw6OtSCKekQcByYAMYjYnWR6zigmVlhHS6hXRERL83kAg5oZlZMCacPSpptw8ysngBNRNIGLJka2phvW+ouF8BDkp5scCyZS2hmVlgbK6e/1OK92LqIGJP0PuBhSQcj4tF28+MSmpkVkzoXWkLMi4ix/O9R4F6ymXra5oBmZgV1ZiynpIWSFk19Bj4JPFMkR65ymllhHWrlPBe4Nx8OPg+4MyIeLHIhBzQzK64D/dAi4gXgkplnxgHNzIoKplowS8MBzcyKK1c8c0Azs+La6LbRFQ5oZlacA5qZVUIAJVto2AHNzAoR4SqnmVXIZLmKaEkjBSStl/ScpBFJNzY4/llJT+XbTyRdUnPskKSnJe2TtKeTmTezHpqqcqZsXdKyhCZpALgVuJJsWbrdknZExLM1yX4BXBYRr0q6imx9zbU1x2c8z5GZlU8/VjnXACN5b14k3Q1sBH4d0CLiJzXpHydbf9PMqq5kAS2lynkBcLjm+2i+r5nrgAdqvndkniMzK5vyLTScUkJTg30NcyjpCrKA9vGa3UnzHOXBbgvAfC1MyJaZ9VQJV31KKaGNAstrvi8DxuoTSfoI8HfAxoh4eWp/6jxHETEcEasjYvXQGfPT78DMekYRSVu3pAS03cAKSRdKGgI2ATtqE0h6P3APcE1EPF+zv2PzHJlZCfVblTMixiVtBXYBA8D2iNgv6fr8+DbgZuA3gO/kcxpNLUPVsXmOzKxkApgsV5UzqWNtROwEdtbt21bz+QvAFxqc17F5jsysbLpb+krhkQJmVpwDmplVQgAT5Rr65IBmZgUFhAOamVWFq5zlcuy3lvGrtRczfuYC5r3+Ju99Yj9nj4z2Oltm5devrZxVdey3lvHiZauIwew/w/iihbx42SoABzWzFCUroc3phYZ/tfbiXwezKTE4j1+tvbhHOTLrM/3WsbbKxs9c0NZ+M6sRARMTvc7FKeZ0CW3e62+2td/M6pSshDanA9p7n9iPTo6fsk8nx3nvE/t7lCOzPlOygDanq5xTL/7dymlWRLiVs2zOHhl1ADMrIiDcsdbMKsNDn8ysEiJKt4ydA5qZFVeyjrUOaGZWWLiEZmbV4AkezawqPDjdzKoigOjHoU+S1kt6TtKIpBsbHJekb+XHn5K0KvVcM+tTkU/wmLK10Kk40TKgSRoAbgWuAi4CNku6qC7ZVcCKfNsCfLeNc82sT8VkJG3T6WScSCmhrQFGIuKFiDgB3A1srEuzEfh+ZB4HzpG0NPFcM+tXnSmhdSxOpLxDuwA4XPN9FFibkOaCxHMBkLSFrHQH8M6uY9uruCDxEuClXmdiFlT1vqC69/ahmV7gOK/ueiT+95LE5PMl7an5PhwRw/nn5DjRSkpAU4N99WXIZmlSzs12Zjc3DCBpT75QcaX4vvpPVe+tLrgUEhHrO5EX2ogTraQEtFFgec33ZcBYYpqhhHPNbG5LiTFJUt6h7QZWSLpQ0hCwCdhRl2YHcG3e2nkpcCwijiSea2ZzW8fiRMsSWkSMS9oK7AIGgO0RsV/S9fnxbcBOYAMwArwJfH66cxPyNdw6SV/yffWfqt5bae5rBnHiNIqSDV0wMytqTk/BbWbV4oBmZpXRs4A2k+FUZZdwb5dLOiZpX77d3It8tkPSdklHJTXsH9jnz6vVvfXd8wKQtFzSjyUdkLRf0hcbpOnb59ZQRHR9I3vx93Pg35F17fgpcFFdmg3AA2R9VC4FnuhFXmfp3i4H7u91Xtu8r/8IrAKeaXK8L59X4r313fPK870UWJV/XgQ8X5V/Z822XpXQZjKcquwqOdwrIh4FXpkmSb8+r5R760sRcSQi9uafjwMHyHrl1+rb59ZIrwJas6FS7aYpo9R8f0zSTyU9IOni7mRtVvXr80rV189L0geBjwJP1B2q1HPr1XxoMxlOVXYp+d4LfCAiXpe0Afgh2Uwl/axfn1eKvn5eks4EfgB8KSJeqz/c4JS+fW69KqHNZDhV2bXMd0S8FhGv5593AoOSUgf5llW/Pq+W+vl5SRokC2Z3RMQ9DZJU6rn1KqDNZDhV2bW8N0nnSVL+eQ3Zc3i56zntrH59Xi316/PK83wbcCAivtEkWaWeW0+qnDGD4VRll3hvnwH+SNI48BawKfImp7KSdBdZa98SSaPAV4FB6O/nBUn31nfPK7cOuAZ4WtK+fN9NwPuh/59bIx76ZGaV4ZECZlYZDmhmVhkOaGZWGQ5oZlYZDmhmVhkOaGZWGQ5oZlYZ/x/kcFq5/ATzmwAAAABJRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "fig2 = showCluster(image, cd[split[4]], srd)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "3f8fe426", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "fig2_o = showObjects(image, cd[split[6]], srd)" + ] + }, + { + "cell_type": "markdown", + "id": "3fe68797", + "metadata": {}, + "source": [ + "#### This is an ideal cluster, where all the sources are in a single cell" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "5915c08d", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "fig3 = showCluster(image, cd[singleCell[0]], srd)" + ] + }, + { + "cell_type": "markdown", + "id": "2a3b18ef", + "metadata": {}, + "source": [ + "#### This is a very confused cluster; several input catalog contribute more than one source" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "2a41ca2a", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "fig4 = showCluster(image, cd[confused[7]], srd)" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "id": "64cfa886", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "fig4_o = showObjects(image, cd[confused[7]], srd)" + ] + }, + { + "cell_type": "markdown", + "id": "ca11f019", + "metadata": {}, + "source": [ + "#### These are some functions to get assocations from the MulitMatch matching catalog" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "f3f10b93", + "metadata": {}, + "outputs": [], + "source": [ + "def getObjectId(assocTable, srcId, idField='id', objField='object'):\n", + " mask = assocTable[idField] == srcId\n", + " return assocTable[mask][objField].data" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "9de2f5e7", + "metadata": {}, + "outputs": [], + "source": [ + "def getSourceIds(assocTable, objId, idField='id', objField='object'):\n", + " mask = assocTable[objField] == objId\n", + " return assocTable[mask][idField].data" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "2066240b", + "metadata": {}, + "outputs": [], + "source": [ + "def getAssociatedSources(cluster, assocTable, idField='id', objField='object'):\n", + " matchObjs = np.unique(np.hstack([getObjectId(mAssoc, sId) for sId in cluster._sourceIds]))\n", + " sIds = [getSourceIds(assocTable, matchObj) for matchObj in matchObjs]\n", + " return sIds" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "7cfa1306", + "metadata": {}, + "outputs": [], + "source": [ + "def showAssociatedObjects(img, cluster, srd, assocTable):\n", + " extent = (0, cluster._footprint.getBBox().getWidth(),\n", + " 0, cluster._footprint.getBBox().getHeight())\n", + " cluster.extract(srd)\n", + " xOffset = srd._minCell[0] + cluster._footprint.getBBox().getBeginY()\n", + " yOffset = srd._minCell[1] + cluster._footprint.getBBox().getBeginX()\n", + " xOff = cluster.xCell - xOffset\n", + " yOff = cluster.yCell - yOffset\n", + " img = plt.imshow(image[cluster._footprint.getBBox()].array, origin='lower', extent=extent)\n", + " cb = plt.colorbar()\n", + " colors = ['red', 'blue', 'green', 'cyan', 'orange', 'grey']\n", + " sIds = getAssociatedSources(cluster, mAssoc)\n", + " for iObj, obj in enumerate(sIds):\n", + " mask = np.in1d(cluster._sourceIds, obj)\n", + " img.axes.scatter(yOff[mask], xOff[mask], c=colors[iObj%6])\n", + " return img.axes.figure" + ] + }, + { + "cell_type": "markdown", + "id": "b529262b", + "metadata": {}, + "source": [ + "#### Read the multimatch matching catalog" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "c1083297", + "metadata": {}, + "outputs": [], + "source": [ + "from astropy.table import Table\n", + "mAssoc = Table.read('matchCat.fits')" + ] + }, + { + "cell_type": "markdown", + "id": "9177318f", + "metadata": {}, + "source": [ + "#### Compare results\n", + "\n", + "Here we show the results of the NWayMatch and then we take all of the input sources add look for associations in the\n", + "MultiMatch catalog. Note that many of the sources do not have any matches in the MultiMatch catalog. This is b/c the \"ambiguous\" sources are being removed. " + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "b5f98d1c", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "fig5_o = showObjects(image, cd[confused[7]], srd)" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "id": "e47969d6", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "fig5_o = showAssociatedObjects(image, cd[split[6]], srd, mAssoc)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a6f3f3f6", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "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.8.8" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/nb/Reproducibility.ipynb b/nb/Reproducibility.ipynb new file mode 100644 index 0000000..2203161 --- /dev/null +++ b/nb/Reproducibility.ipynb @@ -0,0 +1,244 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "16d08b9d", + "metadata": {}, + "source": [ + "# This notebook demostrates the effect of input catalog ordering in NWayMatch and MultiMatch\n", + "\n", + "It assumes that you:\n", + "\n", + " 1. Have downloaded the data here: https://lsst.ncsa.illinois.edu/~yusra/nway-matcher/\n", + " 2. Use the script pq2afw.py to make afw source catalogs for MultiMatch\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "97b14652", + "metadata": {}, + "outputs": [], + "source": [ + "%matplotlib inline\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ad816a25", + "metadata": {}, + "outputs": [], + "source": [ + "import glob\n", + "import os\n", + "import numpy as np\n", + "from nway import NWayMatch" + ] + }, + { + "cell_type": "markdown", + "id": "7809cfac", + "metadata": {}, + "source": [ + "### Set up the inputs" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c901f3d7", + "metadata": {}, + "outputs": [], + "source": [ + "DATADIR = \".\"\n", + "SOURCE_TABLEFILES = glob.glob(os.path.join(DATADIR, \"sourceTable-00*.parq\"))\n", + "SOURCE_CATFILES = glob.glob(os.path.join(DATADIR, \"sourceTable-*.fits\"))\n", + "VISIT_IDS = np.arange(len(SOURCE_TABLEFILES))\n", + "\n", + "REF_DIR = (150., 2.) # RA, DEC in deg\n", + "REGION_SIZE = (3., 3.) # in Deg\n", + "CELL_SIZE = 1. / (3600*2) # in Deg = 0.5\"\n", + "SUBREGION_SIZE = 1350 # in Pixels\n", + "PIXEL_R2CUT = 1." + ] + }, + { + "cell_type": "markdown", + "id": "106d23c7", + "metadata": {}, + "source": [ + "#### Create two NWayMatch matchers\n", + "\n", + "Give the the same data, but reverse the order of the input files in one case" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b6b03b01", + "metadata": {}, + "outputs": [], + "source": [ + "nWay = NWayMatch.create(REF_DIR, REGION_SIZE, CELL_SIZE, pixelR2Cut=PIXEL_R2CUT, subRegionSize=SUBREGION_SIZE)\n", + "nWay2 = NWayMatch.create(REF_DIR, REGION_SIZE, CELL_SIZE, pixelR2Cut=PIXEL_R2CUT, subRegionSize=SUBREGION_SIZE)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0ab6680f", + "metadata": {}, + "outputs": [], + "source": [ + "nWay.reduceData(SOURCE_TABLEFILES, VISIT_IDS)\n", + "nWay2.reduceData(SOURCE_TABLEFILES[::-1], VISIT_IDS[::-1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0d6b2385", + "metadata": {}, + "outputs": [], + "source": [ + "oDict = nWay.analyzeSubregion(10, 10, True)\n", + "oDict2 = nWay2.analyzeSubregion(10, 10, True)" + ] + }, + { + "cell_type": "markdown", + "id": "ad60aace", + "metadata": {}, + "source": [ + "### Show that they have the same number of clusters and objects" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "33e1fb3c", + "metadata": {}, + "outputs": [], + "source": [ + "print(oDict['srd'].nClusters, oDict2['srd'].nClusters) \n", + "print(oDict['srd'].nObjects, oDict2['srd'].nObjects)" + ] + }, + { + "cell_type": "markdown", + "id": "ec94c595", + "metadata": {}, + "source": [ + "### Set up a function to run MultiMatch" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "34d497d9", + "metadata": {}, + "outputs": [], + "source": [ + "import lsst.afw.table as afwTable\n", + "import lsst.geom as geom\n", + "from astropy import table\n", + "from astropy.table import Table\n", + "\n", + "def runMultiMatch(inputCats, outFile):\n", + " match_radius = geom.Angle(0.5, geom.arcseconds)\n", + " \n", + " schema = afwTable.SourceTable.makeMinimalSchema()\n", + " mmatch = afwTable.MultiMatch(schema, dataIdFormat={'iCat': np.int32},\n", + " radius=match_radius,\n", + " RecordClass=afwTable.SimpleRecord)\n", + "\n", + " for i, catFile in enumerate(inputCats):\n", + " print(\"Adding %s\" % catFile)\n", + " cat = afwTable.SourceCatalog.readFits(catFile)\n", + " mmatch.add(catalog=cat, dataId=dict(iCat=i))\n", + "\n", + " matchCat = mmatch.finish()\n", + " matchCat.writeFits(outFile)" + ] + }, + { + "cell_type": "markdown", + "id": "40b35cda", + "metadata": {}, + "source": [ + "#### Run it twice, once with the catalogs in reverse order" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "06d49874", + "metadata": {}, + "outputs": [], + "source": [ + "mm1 = runMultiMatch(SOURCE_CATFILES[0:5], 'mm_orig.fits')\n", + "tt1 = Table.read('mm_orig.fits')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4b7bf04a", + "metadata": {}, + "outputs": [], + "source": [ + "mm2 = runMultiMatch(SOURCE_CATFILES[0:5][::-1], 'mm_revr.fits')\n", + "tt2 = Table.read('mm_revr.fits')" + ] + }, + { + "cell_type": "markdown", + "id": "eaaa6643", + "metadata": {}, + "source": [ + "#### Show that the number of associations changes" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "41420f91", + "metadata": {}, + "outputs": [], + "source": [ + "print(len(tt1), len(tt2))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d2b8bc45", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "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.8.8" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python/nway/__init__.py b/python/nway/__init__.py new file mode 100644 index 0000000..416cf4a --- /dev/null +++ b/python/nway/__init__.py @@ -0,0 +1,3 @@ +""" Matching algorithm for multiple input source catalogs """ + +from .nway import * diff --git a/python/nway/nway.py b/python/nway/nway.py new file mode 100644 index 0000000..08c99cd --- /dev/null +++ b/python/nway/nway.py @@ -0,0 +1,847 @@ +""" Proof of concept for n-way matching using footprint detection + +Some terminology: + +cell : A small area, used to find matches, The size + should be about the same as the maximum match radius. + +source : As per DM, per-catalog detection + +matchWcs : The WCS used to define the cells + +subRegion : A square sub-region of the skymap defined by the matchWcs + +sourceCountsMap : A map of the number of source per cell, made per + subRegion + +Cluster: A set of sources found by running a footprint finding algorithm + on a sourceCountsMap + +""" + +import sys +import os +import glob + +from collections import OrderedDict + +import time +import numpy as np +from astropy import wcs +from astropy.table import Table +from astropy.table import vstack +from astropy.io import fits + +try: + import pyarrow.parquet as pq # noqa +except ImportError: + print("nway requires pyarrrow") + +try: + import lsst.afw.detection as afwDetect + import lsst.afw.image as afwImage +except ImportError: + print("nway requires lsst.afw") + +RECURSE_MAX = 200 +COLUMNS = ['ra', 'decl', 'visit', 'ccd', 'sky_source', 'sourceId', 'PsFlux', 'PsFluxErr', 'Centroid_flag', 'detect_isPrimary'] + +def createGlobalWcs(refDir, cellSize, nCell): + """ Helper function to create the WCS used to project the + sources in a skymap """ + w = wcs.WCS(naxis=2) + w.wcs.cdelt = [-cellSize, cellSize] + w.wcs.crpix = [nCell[0]/2, nCell[1]/2] + w.wcs.crval = [refDir[0], refDir[1]] + return w + +def clusterStats(clusterDict): + """ Helper function to get stats about the clusters + + 'Orphan' means single source clusters (i.e., single detections) + 'Mixed` means there is more that one source from at least one + input catalog + 'Confused' means there are more than four cases of duplication + """ + nOrphan = 0 + nMixed = 0 + nConfused = 0 + for val in clusterDict.values(): + if val.nSrc == 1: + nOrphan += 1 + if val.nSrc != val.nUnique: + nMixed += 1 + if val.nSrc > val.nUnique + 3: + nConfused += 1 + return np.array([len(clusterDict), nOrphan, nMixed, nConfused]) + + +class ClusterData: + """ Class to store data about clusters + + Parameters + ---------- + iCluster : `int` + Cluster ID + origCluster : `int` + Id of the original cluster this cluster was made from + nSrc : `int` + Number of sources in this cluster + nUnique : `int` + Number of catalogs contributing sources to this cluster + catIndices : `np.array`, [`int`] + Indices of the catalogs of sources associated to this cluster + sourcdIds : `np.array`, [`int`] + Sources IDs of the sources associated to this cluster + sourcdIdxs : `np.array`, [`int`] + Indices of the sources with their respective catalogs + xCent : `float` + X-pixel value of cluster centroid (in WCS used to do matching) + yCent : `float` + Y-pixel value of cluster centroid (in WCS used to do matching) + """ + def __init__(self, iCluster, footprint, sources, origCluster=None): + self._iCluster = iCluster + self._footprint = footprint + if origCluster is None: + self._origCluster = self._iCluster + else: + self._origCluster = origCluster + self._catIndices = sources[0] + self._sourceIds = sources[1] + self._sourceIdxs = sources[2] + self._nSrc = self._catIndices.size + self._nUnique = len(np.unique(self._catIndices)) + self._objects = [] + self._xCent = None + self._yCent = None + self._dist2 = None + self._rmsDist = None + self.xCell = None + self.yCell = None + self.snr = None + + def extract(self, subRegionData): + """ Extract the xCell, yCell and snr data from + the sources in this cluster + """ + self.xCell = np.zeros((self._nSrc), np.float32) + self.yCell = np.zeros((self._nSrc), np.float32) + self.snr = np.zeros((self._nSrc), np.float32) + for i, (iCat, srcIdx) in enumerate(zip(self._catIndices, self._sourceIdxs)): + self.xCell[i] = subRegionData.data[iCat]['xcell'].values[srcIdx] + self.yCell[i] = subRegionData.data[iCat]['ycell'].values[srcIdx] + self.snr[i] = subRegionData.data[iCat]['SNR'].values[srcIdx] + + def clearTempData(self): + """ Remove temporary data only used when making objects """ + self.xCell = None + self.yCell = None + self.snr = None + + @property + def iCluster(self): + """ Return the cluster ID """ + return self._iCluster + + @property + def nSrc(self): + """ Return the number of sources associated to the cluster """ + return self._nSrc + + @property + def nUnique(self): + """ Return the number of catalogs contributing sources to the cluster """ + return self._nUnique + + @property + def sourceIds(self): + """ Return the source IDs associated to this cluster """ + return self._sourceIds + + @property + def dist2(self): + """ Return an array with the distance squared (in cells) + between each source and the cluster centroid """ + return self._dist2 + + @property + def objects(self): + """ Return the objects associated with this cluster """ + return self._objects + + def processCluster(self, subRegionData, pixelR2Cut): + """ Function that is called recursively to + split clusters until they: + + 1. Consist only of sources with the match radius of the cluster + centroid. + + 2. Have at most one source per input catalog + """ + self._nSrc = self._catIndices.size + self._nUnique = len(np.unique(self._catIndices)) + if self._nSrc == 0: + print("Empty cluster", self._nSrc, self._nUnique) + return self._objects + self.extract(subRegionData) + if self._nSrc == 1: + self._xCent = self.xCell[0] + self._yCent = self.yCell[0] + self._dist2 = np.zeros((1)) + self._rmsDist = 0. + initialObject = self.addObject(subRegionData) + initialObject.processObject(subRegionData, pixelR2Cut) + self.clearTempData() + return self._objects + + sumSnr = np.sum(self.snr) + self._xCent = np.sum(self.xCell*self.snr) / sumSnr + self._yCent = np.sum(self.yCell*self.snr) / sumSnr + self._dist2 = (self._xCent - self.xCell)**2 + (self._yCent - self.yCell)**2 + self._rmsDist = np.sqrt(np.mean(self._dist2)) + + initialObject = self.addObject(subRegionData) + initialObject.processObject(subRegionData, pixelR2Cut) + self.clearTempData() + return self._objects + + def addObject(self, subRegionData, mask=None): + """ Add a new object to this cluster """ + newObject = subRegionData.addObject(self, mask) + self._objects.append(newObject) + return newObject + + +class ObjectData: + """ Small class to define 'Objects', i.e., sets of associated sources """ + + def __init__(self, cluster, objectId, mask): + """ Build from `ClusterData`, an objectId and mask specifying with sources + in the cluster are part of the object """ + self._parentCluster = cluster + self._objectId = objectId + if mask is None: + self._mask = np.ones((self._parentCluster.nSrc), dtype=bool) + else: + self._mask = mask + self._catIndices = self._parentCluster._catIndices[self._mask] + self._nSrc = self._catIndices.size + self._nUnique = np.unique(self._catIndices).size + self._xCent = None + self._yCent = None + self._dist2 = None + self._rmsDist = None + + @property + def nSrc(self): + """ Return the number of sources associated to the cluster """ + return self._nSrc + + @property + def nUnique(self): + """ Return the number of catalogs contributing sources to the cluster """ + return self._nUnique + + @property + def dist2(self): + """ Return an array with the distance squared (in cells) + between each source and the cluster centroid """ + return self._dist2 + + def updateCatIndices(self): + self._catIndices = self._parentCluster._catIndices[self._mask] + self._nSrc = self._catIndices.size + self._nUnique = np.unique(self._catIndices).size + + def sourceIds(self): + return self._parentCluster.sourceIds[self._mask] + + def processObject(self, subRegionData, pixelR2Cut, recurse=0): + """ Recursively process an object and make sub-objects """ + if recurse > RECURSE_MAX: + print("Recursion limit: ", self._nSrc, self._nUnique) + return + if self._nSrc == 0: + print("Empty object", self._nSrc, self._nUnique, recurse) + return + + xCell = self._parentCluster.xCell[self._mask] + yCell = self._parentCluster.yCell[self._mask] + snr = self._parentCluster.snr[self._mask] + + if self._mask.sum() == 1: + self._xCent = xCell[0] + self._yCent = yCell[0] + self._dist2 = np.zeros((1), float) + self._rmsDist = 0. + return + + sumSnr = np.sum(snr) + self._xCent = np.sum(xCell*snr) / sumSnr + self._yCent = np.sum(yCell*snr) / sumSnr + self._dist2 = np.array((self._xCent - xCell)**2 + (self._yCent - yCell)**2) + self._rmsDist = np.sqrt(np.mean(self._dist2)) + subMask = self._dist2 < pixelR2Cut + if subMask.all(): + if self._nSrc != self._nUnique: + self.splitObject(subRegionData, pixelR2Cut, recurse=recurse+1) + return + + if not subMask.any(): + idx = np.argmax(snr) + self._xCent = xCell[idx] + self._yCent = yCell[idx] + self._dist2 = np.array((self._xCent - xCell)**2 + (self._yCent - yCell)**2) + self._rmsDist = np.sqrt(np.mean(self._dist2)) + subMask = self._dist2 < pixelR2Cut + + newObjMask = self._mask.copy() + newObjMask[newObjMask] *= subMask + + newObject = self._parentCluster.addObject(subRegionData, newObjMask) + newObject.processObject(subRegionData, pixelR2Cut) + + self._mask[self._mask] *= ~subMask + self.updateCatIndices() + self.processObject(subRegionData, pixelR2Cut, recurse=recurse+1) + + + def splitObject(self, subRegionData, pixelR2Cut, recurse=0): + """ Split up a cluster keeping only one source per input + catalog, choosing the one closest to the cluster center """ + sortIdx = np.argsort(self._dist2) + mask = np.ones((self._nSrc), dtype=bool) + usedCats = {} + for iSrc, catIdx in zip(sortIdx, self._catIndices[sortIdx]): + if catIdx not in usedCats: + usedCats[catIdx] = 1 + continue + else: + usedCats[catIdx] += 1 + mask[iSrc] = False + + newObjMask = self._mask.copy() + newObjMask[newObjMask] *= mask + + newObject = self._parentCluster.addObject(subRegionData, newObjMask) + newObject.processObject(subRegionData, pixelR2Cut) + + self._mask[self._mask] *= ~mask + self.updateCatIndices() + self.processObject(subRegionData, pixelR2Cut, recurse=recurse+1) + + +class SubregionData: + """ Class to analyze data for a SubRegion + + Include sub-region boundries, reduced data tables + and clustering results + + Does not store sky maps + + Subregions are square sub-regions of the Skymap + constructed with the WCS + + The subregion covers corner:corner+size + + The sources are projected into an array that extends `buf` cells + beyond the region. + + Parameters + ---------- + _data : `list`, [`Dataframe`] + Reduced dataframes with only sources for this sub-region + + _clusterIds : `list`, [`np.array`] + Matched arrays with the index of the cluster associated to each + source. I.e., these could added to the Dataframes as + additional columns + + _clusterDict : `dict`, [`int` : `ClusterData`] + Dictionary with cluster membership data + + TODO: Add code to filter out clusters centered in the buffer + """ + def __init__(self, matcher, idOffset, corner, size, buf=10): + self._matcher = matcher + self._idOffset = idOffset # Offset used for the Object and Cluster IDs for this region + self._corner = corner # cellX, cellY for corner of region + self._size = size # size of region + self._buf = buf + self._minCell = corner - buf + self._maxCell = corner + size + buf + self._nCells = self._maxCell - self._minCell + self._data = None + self._nSrc = None + self._footprintIds = None + self._clusterDict = OrderedDict() + self._objectDict = OrderedDict() + + def reduceData(self, data): + """ Pull out only the data needed for this sub-region """ + self._data = [self.reduceDataframe(val) for val in data] + self._nSrc = sum([len(df) for df in self._data]) + + @property + def nClusters(self): + """ Return the number of clusters in this region """ + return len(self._clusterDict) + + @property + def nObjects(self): + """ Return the number of objects in this region """ + return len(self._objectDict) + + @property + def data(self): + """ Return the data associated to this region """ + return self._data + + @property + def clusterDist(self): + """ Return a dictionary mapping clusters Ids to clusters """ + return self._clusterDict + + def reduceDataframe(self, dataframe): + """ Filters dataframe to keep only source in the subregion """ + xLocal = dataframe['xcell'] - self._minCell[0] + yLocal = dataframe['ycell'] - self._minCell[1] + filtered = (xLocal >= 0) & (xLocal < self._nCells[0]) & (yLocal >= 0) & (yLocal < self._nCells[1]) + red = dataframe[filtered].copy(deep=True) + red['xlocal'] = xLocal[filtered] + red['ylocal'] = yLocal[filtered] + return red + + def countsMap(self, weightName=None): + """ Fill a map that counts the number of source per cell """ + toFill = np.zeros((self._nCells)) + for df in self._data: + toFill += self.fillSubRegionFromDf(df, weightName=weightName) + return toFill + + def associateSourcesToFootprints(self, clusterKey): + """ Loop through data and associate sources to clusters """ + self._footprintIds = [self.findClusterIds(df, clusterKey) for df in self._data] + + def buildClusterData(self, fpSet, pixelR2Cut=4.): + """ Loop through cluster ids and collect sources into + the ClusterData objects """ + footprints = fpSet.getFootprints() + footprintDict = {} + nMissing = 0 + nFound = 0 + for iCat, (df, footprintIds) in enumerate(zip(self._data, self._footprintIds)): + for srcIdx, (srcId, footprintId) in enumerate(zip(df['sourceId'], footprintIds)): + if footprintId < 0: + nMissing += 1 + continue + if footprintId not in footprintDict: + footprintDict[footprintId] = [(iCat, srcId, srcIdx)] + else: + footprintDict[footprintId].append((iCat, srcId, srcIdx)) + nFound += 1 + for footprintId, sources in footprintDict.items(): + footprint = footprints[footprintId] + iCluster = footprintId+self._idOffset + cluster = ClusterData(iCluster, footprint, np.array(sources).T) + self._clusterDict[iCluster] = cluster + cluster.processCluster(self, pixelR2Cut) + + def analyze(self, weightName=None, pixelR2Cut=4.): + """ Analyze this sub-region + + Note that this returns the counts maps and clustering info, + which can be helpful for debugging. + """ + if self._nSrc == 0: + return None + countsMap = self.countsMap(weightName) + oDict = self.getFootprints(countsMap) + oDict['countsMap'] = countsMap + self.associateSourcesToFootprints(oDict['footprintKey']) + self.buildClusterData(oDict['footprints'], pixelR2Cut) + return oDict + + @staticmethod + def findClusterIds(df, clusterKey): + """ Associate sources to clusters using `clusterkey` + which is a map where any pixel associated to a cluster + has the cluster index as its value """ + return np.array([clusterKey[yLocal,xLocal] for xLocal, yLocal in zip(df['xlocal'], df['ylocal'])]).astype(np.int32) + + def fillSubRegionFromDf(self, df, weightName=None): + """ Fill a source counts map from a reduced dataframe for one input + catalog """ + if weightName is None: + weights = None + else: + weights = df[weightName].values + hist = np.histogram2d(df['xlocal'], df['ylocal'], bins=self._nCells, + range=((0, self._nCells[0]), + (0, self._nCells[1])), + weights=weights) + return hist[0] + + @staticmethod + def filterFootprints(fpSet, buf): + """ Remove footprints within `buf` cells of the region edge """ + region = fpSet.getRegion() + width, height = region.getWidth(), region.getHeight() + outList = [] + maxX = width - buf + maxY = height - buf + for fp in fpSet.getFootprints(): + cent = fp.getCentroid() + xC = cent.getX() + yC = cent.getY() + if xC < buf or xC > maxX or yC < buf or yC > maxY: + continue + outList.append(fp) + fpSetOut = afwDetect.FootprintSet(fpSet.getRegion()) + fpSetOut.setFootprints(outList) + return fpSetOut + + def getFootprints(self, countsMap): + """ Take a source counts map and do clustering using Footprint detection + """ + image = afwImage.ImageF(countsMap.astype(np.float32)) + footprintsOrig = afwDetect.FootprintSet(image, afwDetect.Threshold(0.5)) + footprints = self.filterFootprints(footprintsOrig, self._buf) + footprintKey = afwImage.ImageI(np.full(countsMap.shape, -1, dtype=np.int32)) + for i, footprint in enumerate(footprints.getFootprints()): + footprint.spans.setImage(footprintKey, i, doClip=True) + return dict(image=image, footprints=footprints, footprintKey=footprintKey) + + def getClusterAssociations(self): + """ Convert the clusters to a set of associations """ + clusterIds = [] + sourceIds = [] + distances = [] + for cluster in self._clusterDict.values(): + clusterIds.append(np.full((cluster.nSrc), cluster.iCluster, dtype=int)) + sourceIds.append(cluster.sourceIds) + distances.append(cluster.dist2) + if not distances: + return Table(dict(distance=[], id=np.array([], int), object=np.array([], int))) + distances = np.hstack(distances) + distances = self._matcher.cellToArcsec() * np.sqrt(distances) + data = dict(object=np.hstack(clusterIds), + id=np.hstack(sourceIds), + distance=distances) + return Table(data) + + def getObjectAssociations(self): + clusterIds = [] + objectIds = [] + sourceIds = [] + distances = [] + for obj in self._objectDict.values(): + clusterIds.append(np.full((obj._nSrc), obj._parentCluster.iCluster, dtype=int)) + objectIds.append(np.full((obj._nSrc), obj._objectId, dtype=int)) + sourceIds.append(obj.sourceIds()) + distances.append(obj.dist2) + if not distances: + return Table(dict(object=np.array([], int), + parent=np.array([], int), + id=np.array([], int), + distance=[])) + distances = np.hstack(distances) + distances = self._matcher.cellToArcsec() * np.sqrt(distances) + data = dict(object=np.hstack(objectIds), + parent=np.hstack(clusterIds), + id=np.hstack(sourceIds), + distance=distances) + return Table(data) + + def getClusterStats(self): + """ Convert the clusters to a set of associations """ + nClust = self.nClusters + clusterIds = np.zeros((nClust), dtype=int) + nSrcs = np.zeros((nClust), dtype=int) + nObjects = np.zeros((nClust), dtype=int) + nUniques = np.zeros((nClust), dtype=int) + distRms = np.zeros((nClust), dtype=float) + xCents = np.zeros((nClust), dtype=float) + yCents = np.zeros((nClust), dtype=float) + for idx, cluster in enumerate(self._clusterDict.values()): + clusterIds[idx] = cluster._iCluster + nSrcs[idx] = cluster.nSrc + nObjects[idx] = len(cluster._objects) + nUniques[idx] = cluster.nUnique + distRms[idx] = cluster._rmsDist + xCents[idx] = cluster._xCent + yCents[idx] = cluster._yCent + ra, decl = self._matcher.cellToWorld(xCents, yCents) + distRms *= self._matcher.cellToArcsec() + + data = dict(clusterIds=clusterIds, + nSrcs=nSrcs, + nObject=nObjects, + nUnique=nUniques, + distRms=distRms, + ra=ra, + decl=decl) + + return Table(data) + + def getObjectStats(self): + """ Convert the clusters to a set of associations """ + nObj = self.nObjects + clusterIds = np.zeros((nObj), dtype=int) + objectIds = np.zeros((nObj), dtype=int) + nSrcs = np.zeros((nObj), dtype=int) + distRms = np.zeros((nObj), dtype=float) + xCents = np.zeros((nObj), dtype=float) + yCents = np.zeros((nObj), dtype=float) + for idx, obj in enumerate(self._objectDict.values()): + clusterIds[idx] = obj._parentCluster._iCluster + objectIds[idx] = obj._objectId + nSrcs[idx] = obj.nSrc + distRms[idx] = obj._rmsDist + xCents[idx] = obj._xCent + yCents[idx] = obj._yCent + + ra, decl = self._matcher.cellToWorld(xCents, yCents) + distRms *= self._matcher.cellToArcsec() + + data = dict(clusterIds=clusterIds, + objectIds=objectIds, + nSrcs=nSrcs, + distRms=distRms, + ra=ra, + decl=decl) + + return Table(data) + + def addObject(self, cluster, mask=None): + """ Add an object to this sub-region """ + objectId = self.nObjects + self._idOffset + newObject = ObjectData(cluster, objectId, mask) + self._objectDict[objectId] = newObject + return newObject + + +class NWayMatch: + """ Class to do N-way matching + + Uses a provided WCS to define a Skymap that covers the full region + begin matched. + + Uses that WCS to assign cell locations to all sources in the input catalogs + + Iterates over sub-regions and does source clustering in each sub-region + using Footprint detection on a Skymap of source counts per cell. + + Assigns each input source to a cluster. + + At that stage the clusters are not the final product as they can include + more than one soruce from a given catalog. + + Loops over clusters and processes each cluster to: + + 1. Remove outliers outside the match radius w.r.t. the cluster centroid. + 2. Resolve cases of confusion, where multiple sources from a single + catalog contribute to a cluster. + + Parameters + ---------- + _redData : `list`, [`Dataframe`] + Reduced dataframes with only the columns needed for matching + + _clusters : `OrderedDict`, [`tuple`, `SubregionData`] + Dictionary providing access to subregion data + """ + + def __init__(self, matchWcs, **kwargs): + self._wcs = matchWcs + self._cellSize = self._wcs.wcs.cdelt[1] + self._nCellSide = np.ceil(2*np.array(self._wcs.wcs.crpix)).astype(int) + self._subRegionSize = kwargs.get('subRegionSize', 3000) + self._subRegionBuffer = kwargs.get('subRegionBuffer', 10) + self._subregionMaxObject = kwargs.get('subregionMaxObject', 100000) + self._pixelR2Cut = kwargs.get('pixelR2Cut', 1.0) + self._nSubRegion = np.ceil(self._nCellSide/self._subRegionSize) + self._redData = OrderedDict() + self._clusters = None + + def cellToArcsec(self): + return 3600. * self._cellSize + + def cellToWorld(self, xCell, yCell): + return self._wcs.wcs_pix2world(xCell, yCell, 0) + + @classmethod + def create(cls, refDir, regionSize, cellSize, **kwargs): + """ Make an `NWayMatch` object from inputs """ + nCell = (np.array(regionSize)/cellSize).astype(int) + matchWcs = createGlobalWcs(refDir, cellSize, nCell) + return cls(matchWcs, **kwargs) + + @property + def redData(self): + """ Return the dictionary of reduced data, i.e., just the columns + need for matching """ + return self._redData + + @property + def nSubRegion(self): + """ Return the number of sub-regions in X,Y """ + return self._nSubRegion + + def reduceData(self, inputFiles, visitIds): + """ Read input files and filter out only the columns we need """ + for fName, vid in zip(inputFiles, visitIds): + self._redData[vid] = self.reduceDataFrame(fName) + + def reduceDataFrame(self, fName): + """ Read and reduce a single input file """ + parq = pq.read_pandas(fName, columns=COLUMNS) + df = parq.to_pandas() + df['SNR'] = df['PsFlux']/df['PsFluxErr'] + # select sources that have SNR > 5. + # You may start with 10 or even 50 if you want to start with just the brightest objects + # AND + # Centroid_flag is True if there was a problem fitting the position (centroid) + # AND + # sky_source is True if it is a measurement of blank sky. + # sky_sources should have SNR < 5 or the Centroid_flag set, + # but explicitly filter just to make sure. + # AND + # detect_isPrimary = True to remove duplicate rows from deblending: + # If a source has been deblended, the parent is marked detect_isPrimary=False and its children True. + df_clean = df[(df.SNR > 5) & ~df.Centroid_flag & ~df.sky_source & df.detect_isPrimary] + xcell, ycell = self._wcs.wcs_world2pix(df_clean['ra'].values, df_clean['decl'].values, 0) + df_red = df_clean[["ra", "decl", "SNR", "sourceId"]].copy(deep=True) + df_red['xcell'] = xcell + df_red['ycell'] = ycell + return df_red[["ra", "decl", "SNR", "sourceId", "xcell", "ycell"]] + + def reduceCatalog(self, catalog): + """ Reduce a catalog """ + raise NotImplementedError() + + def add(self, catalog, vid): + """ Add a catalog to the data set being matched """ + self._redData[vid] = self.reduceCatalog(catalog) + + def getIdOffset(self, ix, iy): + """ Get the ID offset to use for a given sub-region """ + subRegionIdx = self._nSubRegion[1]*ix + iy + return int(self._subregionMaxObject * subRegionIdx) + + def analyzeSubregion(self, ix, iy, fullData=False): + """ Analyze a single subregion + + Returns an OrderedDict + + 'srd' : `SubregionData` + The analysis data for the sub-region + + if fullData is True the return dict will include + + 'image' : `afwImage.ImageI` + Image of subregion source counts map + 'countsMap' : `np.array` + Numpy array with same + 'clusters' : `afwDetect.FootprintSet` + Clusters as dectected by finding FootprintSet on source counts map + 'clusterKey' : `afwImage.ImageI` + Map of subregion with pixels filled with index of + associated Footprints + """ + iSubRegion = np.array([ix, iy]) + corner = iSubRegion * self._subRegionSize + idOffset = self.getIdOffset(ix, iy) + srd = SubregionData(self, idOffset, corner, self._subRegionSize, self._subRegionBuffer) + srd.reduceData(self._redData.values()) + oDict = srd.analyze(pixelR2Cut=self._pixelR2Cut) + if oDict is None: + return None + if fullData: + oDict['srd'] = srd + return oDict + if srd.nObjects >= self._subregionMaxObject: + print("Too many object in a subregion", srd.nObjects, elf._subregionMaxObject) + return dict(srd=srd) + + def finish(self): + """ Does clusering for all subregions + + Does not store source counts maps for the counts regions + """ + self._clusters = OrderedDict() + nAssoc = 0 + clusterAssocTables = [] + objectAssocTables = [] + clusterStatsTables = [] + objectStatsTables = [] + + for ix in range(int(self._nSubRegion[0])): + sys.stdout.write("%2i " % ix) + sys.stdout.flush() + for iy in range(int(self._nSubRegion[1])): + sys.stdout.write('.') + sys.stdout.flush() + iSubRegion = (ix, iy) + odict = self.analyzeSubregion(ix, iy) + if odict is None: + continue + subregionData = odict['srd'] + self._clusters[iSubRegion] = subregionData + clusterAssocTables.append(subregionData.getClusterAssociations()) + objectAssocTables.append(subregionData.getObjectAssociations()) + clusterStatsTables.append(subregionData.getClusterStats()) + objectStatsTables.append(subregionData.getObjectStats()) + + sys.stdout.write('!\n') + + sys.stdout.write("Making association vectors\n") + hduList = fits.HDUList([fits.PrimaryHDU(), + fits.table_to_hdu(vstack(clusterAssocTables)), + fits.table_to_hdu(vstack(objectAssocTables)), + fits.table_to_hdu(vstack(clusterStatsTables)), + fits.table_to_hdu(vstack(objectStatsTables))]) + return hduList + + def allStats(self): + """ Helper function to print info about clusters """ + stats = np.zeros((4), int) + for key, srd in self._clusters.items(): + subRegionStats = clusterStats(srd._clusterDict) + print("%3i, %3i: %8i %8i %8i %8i" % (key[0], key[1], subRegionStats[0], subRegionStats[1], subRegionStats[2], subRegionStats[3])) + stats += subRegionStats + return stats + +def main(): + """ Example usage """ + + DATADIR = "." + SOURCE_TABLEFILES = glob.glob(os.path.join(DATADIR, "sourceTable-*.parq")) + VISIT_IDS = np.arange(len(SOURCE_TABLEFILES)) + + REF_DIR = (150., 2.) # RA, DEC in deg + REGION_SIZE = (3., 3.) # in Deg + #CELL_SIZE = 5.0e-5 # in Deg + CELL_SIZE = 1. / (3600*2) # in Deg + #SUBREGION_SIZE = 2700 # in Pixels + SUBREGION_SIZE = 1350 # in Pixels + PIXEL_R2CUT = 1. + + t0 = time.time() + nWay = NWayMatch.create(REF_DIR, REGION_SIZE, CELL_SIZE, pixelR2Cut=PIXEL_R2CUT, subRegionSize=SUBREGION_SIZE) + print("Building clusters in %ix%i sub-regions" % (nWay.nSubRegion[0], nWay.nSubRegion[1])) + nWay.reduceData(SOURCE_TABLEFILES, VISIT_IDS) + outTables = nWay.finish() + t1 = time.time() + print("Reading and clustering took %s s" % (t1-t0)) + + print("Cluster Summaries for sub-regions") + print("Region : nCluster nOrphan nMixed nConf") + stats = nWay.allStats() + print("Total: %8i %8i %8i %8i" % (stats[0], stats[1], stats[2], stats[3])) + + outTables.writeto("out.fits", overwrite=True) + +if __name__ == '__main__': + main() diff --git a/python/nway/version.py b/python/nway/version.py new file mode 100644 index 0000000..f007eef --- /dev/null +++ b/python/nway/version.py @@ -0,0 +1,180 @@ +# -*- coding: utf-8 -*- +# Author: Douglas Creager +# This file is placed into the public domain. + +# Calculates the current version number. If possible, this is the +# output of “git describe”, modified to conform to the versioning +# scheme that setuptools uses. If “git describe” returns an error +# (most likely because we're in an unpacked copy of a release tarball, +# rather than in a git working copy), then we fall back on reading the +# contents of the RELEASE-VERSION file. +# +# To use this script, simply import it your setup.py file, and use the +# results of get_git_version() as your package version: +# +# from version import * +# +# setup( +# version=get_git_version(), +# . +# . +# . +# ) +# +# This will automatically update the RELEASE-VERSION file, if +# necessary. Note that the RELEASE-VERSION file should *not* be +# checked into git; please add it to your top-level .gitignore file. +# +# You'll probably want to distribute the RELEASE-VERSION file in your +# sdist tarballs; to do this, just create a MANIFEST.in file that +# contains the following line: +# +# include RELEASE-VERSION + +import os +import subprocess +from subprocess import check_output + +__all__ = ("get_git_version") + +_refname = '$Format: %D$' +_tree_hash = '$Format: %t$' +_commit_info = '$Format:%cd by %aN$' +_commit_hash = '$Format: %h$' + + +def capture_output(cmd, dirname): + + p = subprocess.Popen(cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + cwd=dirname) + p.stderr.close() + + output = p.stdout.readlines() + + if not output: + return None + else: + return output[0].strip() + + +def render_pep440(vcs): + """Convert git release tag into a form that is PEP440 compliant.""" + + if vcs is None: + return None + + tags = vcs.split('-') + + # Bare version number + if len(tags) == 1: + return tags[0] + else: + return tags[0] + '+' + '.'.join(tags[1:]) + + +def call_git_describe(abbrev=4): + + dirname = os.path.abspath(os.path.dirname(__file__)) + + try: + has_git_tree = capture_output(['git', 'rev-parse', + '--is-inside-work-tree'], dirname) + except: + return None + + if not has_git_tree: + return None + + try: + line = check_output(['git', 'describe', '--abbrev=%d' % abbrev, + '--dirty', '--tags'], cwd=dirname) + + return line.strip().decode('utf-8') + + except: + return None + + +def read_release_keywords(keyword): + + refnames = keyword.strip() + if refnames.startswith("$Format"): + return None + + refs = set([r.strip() for r in refnames.strip("()").split(",")]) + TAG = "tag: " + tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)]) + if not tags: + return None + return sorted(tags)[-1] + + +def read_release_version(): + """Read the release version from ``_version.py``.""" + import re + dirname = os.path.abspath(os.path.dirname(__file__)) + + try: + f = open(os.path.join(dirname, "_version.py"), "rt") + for line in f.readlines(): + + m = re.match("__version__ = '([^']+)'", line) + if m: + ver = m.group(1) + return ver + + except: + return None + + return None + + +def write_release_version(version): + """Write the release version to ``_version.py``.""" + dirname = os.path.abspath(os.path.dirname(__file__)) + f = open(os.path.join(dirname, "_version.py"), "wt") + f.write("__version__ = '%s'\n" % version) + f.close() + + +def get_git_version(abbrev=4): + + # Read in the version that's currently in _version.py. + release_version = read_release_version() + + # First try to get the current version using “git describe”. + git_version = call_git_describe(abbrev) + git_version = render_pep440(git_version) + + # Try to deduce the version from keyword expansion + keyword_version = read_release_keywords(_refname) + keyword_version = render_pep440(keyword_version) + + # If that doesn't work, fall back on the value that's in + # _version.py. + if git_version is not None: + version = git_version + elif release_version is not None: + version = release_version + elif keyword_version is not None: + version = keyword_version + else: + version = 'unknown' + + # If we still don't have anything, that's an error. + if version is None: + raise ValueError("Cannot find the version number!") + + # If the current version is different from what's in the + # _version.py file, update the file to be current. + if version != release_version and version != 'unknown': + write_release_version(version) + + # Finally, return the current version. + return version + + +if __name__ == "__main__": + print(get_git_version()) diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..b69c7ab --- /dev/null +++ b/setup.py @@ -0,0 +1,26 @@ +from setuptools import setup + +from python.nway import version + +setup( + name="nway", + version=version.get_git_version(), + author="", + author_email="", + url = "https://github.com/KIPAC/NWayMatch", + package_dir={"":"python"}, + packages=["nway"], + description="=Matching algorithm for multiple input source catalogs", + long_description=open("README.md").read(), + package_data={"": ["README.md", "LICENSE"]}, + include_package_data=True, + classifiers=[ + "Development Status :: 4 - Beta", + "License :: OSI Approved :: BSD License", + "Intended Audience :: Developers", + "Intended Audience :: Science/Research", + "Operating System :: OS Independent", + "Programming Language :: Python", + ], + install_requires=[], +)