├── .gitignore ├── LICENSE.txt ├── README.md ├── data ├── N6251_test.fits ├── N6251_test.png ├── fit │ ├── N6251_cart.pkl │ ├── N6251_polar.pkl │ ├── PAPER-snrem_cart.pkl │ └── PAPER-snrem_polar.pkl ├── solve │ ├── N6251_cart.pkl │ ├── N6251_polar.pkl │ ├── PAPER-snrem_cart.pkl │ └── PAPER-snrem_polar.pkl └── zen.2455819.69771.uvcRREM_briggs-dirty.fits ├── scripts ├── fitShapelet.py ├── insertShapelet.py ├── plotCoeffs.py ├── plotImg.py ├── plotShapelets.py ├── profile.py ├── solveShapelet.py └── test_scripts.sh ├── setup.py └── shapelets ├── __init__.py ├── conv.py ├── cshapelet.pyx ├── decomp.py ├── fileio.py ├── fshapelet.py ├── img.py ├── measure.py ├── phs ├── ClassMS.py ├── ModColor.py ├── ModRotate.py ├── README.md ├── __init__.py ├── rad2hmsdms.py └── reformat.py ├── shapelet.py └── tests.py /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | dist 3 | shapelets.egg-info 4 | temp.coeff 5 | 6 | .settings 7 | .project 8 | .pydevproject 9 | *.so 10 | *.pyc 11 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Unless otherwise specified by LICENSE.txt files in individual directories, all code is 2 | 3 | Copyright (c) 2014, Griffin Foster 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 11 | 12 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 15 | 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | shapelets 2 | === 3 | 4 | Contact: griffin.foster@gmail.com 5 | 6 | A python module for fitting and decomposing images (FITS, PNG, JPEG...) into shapelet coefficients, support for Cartesian and polar forms using Hermite and Laguerre polynomials. 7 | 8 | Based on the shapelet framework developed in [Shapelets: I. A Method for Image Analysis](http://arxiv.org/abs/astro-ph/0105178) and the [IDL shapelet software](http://www.astro.caltech.edu/~rjm/shapelets/). 9 | 10 | #### Required Python Modules 11 | 12 | * matplotlib 13 | * numpy 14 | * scipy 15 | * astropy 16 | * json 17 | 18 | #### Optional Python Modules 19 | 20 | * [python-casacore](https://github.com/casacore/python-casacore) 21 | * PIL 22 | 23 | #### Install 24 | 25 | To install the current stable version (0.2) use pip: 26 | 27 | ``` 28 | pip install shapelets 29 | ``` 30 | 31 | While developing it is useful to do a developer install: 32 | 33 | ``` 34 | sudo python setup.py develop 35 | ``` 36 | 37 | Otherwise, the standard install will work: 38 | 39 | ``` 40 | sudo python setup.py install 41 | ``` 42 | 43 | #### Usage 44 | 45 | The scripts directory contains a number scripts for plotting, decomposing, and fitting. 46 | 47 | * plotShapelets.py : plot a grid of shapelet basis functions 48 | * plotImg.py : load a FITS or image file, useful for determing coordinates to apply shapelet decomposition 49 | * plotCoeffs.py : given a shapelet coefficient file, plot the modelled source and coefficients 50 | * solveShapelet.py : given a set of parameters and an image, decompose the image into shapelet coefficients 51 | * fitShapelet.py : fit parameters to minimize the chi^2 difference between shapelet model and image 52 | * insertShapelet.py : insert a shapelet coefficient set into a Measurement Set (requires python-casacore) 53 | 54 | #### Examples 55 | 56 | ``` 57 | plotShapelets.py -n 4 -p -b 1.0,1.0,0.44 58 | 59 | plotImg.py -r 1010,1117,947,1030 ../data/N6251_test.fits 60 | plotImg.py ../data/zen.2455819.69771.uvcRREM_briggs-dirty.fits 61 | 62 | solveShapelet.py -r 1010,1117,947,1030 -N 891,1257,600,840 ../data/N6251_test.fits -n 15 -x 49,52 --beta=6.,2.5 --phi=-0.448243 -m cart 63 | solveShapelet.py -r 489,530,489,527 -N 436,561,405,487 ../data/zen.2455819.69771.uvcRREM_briggs-dirty.fits -n 10 -m cart 64 | 65 | fitShapelet.py -r 1010,1117,947,1030 -N 891,1257,600,840 ../../data/N6251_test.fits -n 8 -x 49,52 --init_beta=6.,2.5 --init_phi=-0.448243 -m cart 66 | fitShapelet.py -r 489,530,489,527 -N 436,561,405,487 ../../data/zen.2455819.69771.uvcRREM_briggs-dirty.fits -n 8 -x 20.,22. --init_beta=2.788068,2.336974 --init_phi=-1.046530 -m cart -B 10 67 | 68 | plotCoeffs.py ../data/solve/N6251_cart.pkl 69 | 70 | ``` 71 | -------------------------------------------------------------------------------- /data/N6251_test.fits: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/griffinfoster/shapelets/b639447a088c53f0030ba27ca90bc7fc07b2e889/data/N6251_test.fits -------------------------------------------------------------------------------- /data/N6251_test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/griffinfoster/shapelets/b639447a088c53f0030ba27ca90bc7fc07b2e889/data/N6251_test.png -------------------------------------------------------------------------------- /data/fit/N6251_cart.pkl: -------------------------------------------------------------------------------- 1 | (dp1 2 | S'norder' 3 | p2 4 | (lp3 5 | I9 6 | aI9 7 | asS'phi' 8 | p4 9 | cnumpy.core.multiarray 10 | scalar 11 | p5 12 | (cnumpy 13 | dtype 14 | p6 15 | (S'f8' 16 | I0 17 | I1 18 | tRp7 19 | (I3 20 | S'<' 21 | NNNI-1 22 | I-1 23 | I0 24 | tbS'\xf4\xa5Qz\xb8U\xda\xbf' 25 | tRp8 26 | sS'xc' 27 | p9 28 | (lp10 29 | g5 30 | (g7 31 | S'PG\x81\xba\xad[K@' 32 | tRp11 33 | ag5 34 | (g7 35 | S'\x804?\x9b\tsF@' 36 | tRp12 37 | asS'ddec' 38 | p13 39 | F0.002833333333333 40 | sS'coeffs' 41 | p14 42 | cnumpy.core.multiarray 43 | _reconstruct 44 | p15 45 | (cnumpy 46 | ndarray 47 | p16 48 | (I0 49 | tS'b' 50 | tRp17 51 | (I1 52 | (I81 53 | tg7 54 | I00 55 | S'w\x87r\xc4r\x1a\x01@~DC\xaeh\xf6\xec\xbf\x9f\x87\xed\x9a\x97\xe0\xf9?\xb6=\xd1\xd0A\x9a\xe2?w\xc6do/\xf6\xdc?\x84\xaf\x10Nm&\xf4?\xc3\xf6\x9b\xb6?\xc2\xe2?\xa8\xacU\x96\xb8\x17\xa0?\xef\xc7`\xc8\xb0\xdd\xd1?D\x13D3\xace\xde\xbf\x004\x9f\x9ej\x9d\xbc?\x14{q\x96\x8c\x17\xda\xbf\xd2\x1f\x00f\xf4u\xcf\xbf\xfeT\xf9Ey\x08\xce\xbf\x9a\x95\xc3y5\xdf\xda\xbf\x82\x8d\xc3G\xd7\x1d\xd1\xbf62\x9d?8\x99\xbd\xbf\x9dLG]\x13\xdb\xbf\xbfA\xb9\xb3\xd3\xe8\xf1\xd9\xbf,r\xd4\xe3\x98\x9c\xcb?\x0e\xc5VN\xf1\x85\xd1\xbf\x98{\x96\xd00\x00\xad\xbf\xa0\x05mo\x17uz\xbf\xd9c\xa0N\xe6F\xc4\xbf\x06\x07\x17\xbd\r$\x9a\xbf\xb4V1\x872v\xb4?\x10\x0e|\xd7\x0f\x8ca?]\xa2X\x06\xaa\x8a\xc5?\xac\xb4e\x83\xce&\xa5\xbf3R\'\xc8\xf3c\xc2?\xf5<~k\t\x02\xb2?b\xda\xbd\xad{,\xaf?\xa0\x8b\xf3nQ`\xbf?VC\xfd\x9d\xbd\xee\xb0?6Mw\x08\xa8\x17\x8c?11\x95#"\xde\x94?\x8d=\xa5\x9cR\xa6\xb9?\x18\x05\tF\xc1\xd8\xa6\xbf\x8em\xa7f9$\xb0?\x98H\x05\x92\x89\xb7\x7f?p\xc4\x80/\xbe\xad\x7f\xbf\x97\xa0\xb3O\xb5\x10\x9e?\xe0~q)z\xa7]?\xb4\xa3\x86\xeb\xadm\x95\xbf\xc8\xe6\x17\x91,\xe9p?\x8a.\xaf\xcd\xdbi\xaf\xbfF\x13\xe6q\xa0\xd3\x8f?+I}\x1f\x1c\xe8\xa6\xbf\x0c\x92\xfe\x07\xdfS\x96\xbf\xa6+RWh\xbb\x95\xbf\x9a\xb8c\xe60\xa0\xa5\xbf|\x19\x08\xb7}\xc5\x93\xbf\xa0\xc9\x85@.\xa7B\xbfl\x89\xad\x87j1\x7f\xbf\xca*9-\xd6\xf0\x91\xbf\xfc\xab\xc3\xe2>\x17\x9e?p\xc6\nP\xb5\xcf\x80\xbf%m\xee;Z.\x7f?,\xfdY \x81^\x85?\x00P\xb0\xb8\xdb.K?\xf6 \xfd\xb0c\x8e\x8d?9u\xe1\x81\xf0u\x89?Vx\x11.\xe9K\x84?\x9f\x1a\xcb\x92\xc5\x07\x90?;\x12$\xe8s\xd3\x83\xbfV\xa0j-\xef\x8e\x8c?\xb0\xb3\xe4cP\'r?\x00\xf8\xd2\xc4f\x8a\x1e?\x8c\xfb\x17\xe3\x88\xb2r?\x00g\x11\xf3f1Z?\xb8N\x9c!\x08xl\xbf\xca\x99^+R\x05q\xbf\xd2\x1a\rR\x8a\xb8|? e\t$\x88\xa9\x80?hI\x06\x1b\nJs?Z\xd8\xf2\xee\x91\xd7q?Pg\xbaG\xf4\x87e?\xe0\xcc~4\x91\xc4Y?\xb0\x8eM\'\xe4\xbew?\x10?G\x03\xc3]h?\x00\xa7\t\xbf\xe9\x87u?' 56 | tbsS'beta' 57 | p18 58 | (lp19 59 | g5 60 | (g7 61 | S',#\xe2\x05\xbf\x18\x08@' 62 | tRp20 63 | ag5 64 | (g7 65 | S'd\xe5\x0b\xe1\xce\x83\x15@' 66 | tRp21 67 | asS'size' 68 | p22 69 | (I83 70 | I107 71 | tp23 72 | sS'info' 73 | p24 74 | S'../../data/N6251_test.fits' 75 | p25 76 | sS'ra' 77 | p26 78 | g5 79 | (g7 80 | S'\x9ci\x9e\xbd\xbe\xc5m@' 81 | tRp27 82 | sS'dra' 83 | p28 84 | F-0.002833333333333 85 | sS'dec' 86 | p29 87 | g5 88 | (g7 89 | S'\x06\x97\x052bXV@' 90 | tRp30 91 | sS'mode' 92 | p31 93 | S'hermite' 94 | p32 95 | s. -------------------------------------------------------------------------------- /data/fit/N6251_polar.pkl: -------------------------------------------------------------------------------- 1 | (dp1 2 | S'norder' 3 | p2 4 | (lp3 5 | I14 6 | aI14 7 | asS'phi' 8 | p4 9 | cnumpy.core.multiarray 10 | scalar 11 | p5 12 | (cnumpy 13 | dtype 14 | p6 15 | (S'f8' 16 | I0 17 | I1 18 | tRp7 19 | (I3 20 | S'<' 21 | NNNI-1 22 | I-1 23 | I0 24 | tbS'\xc7\x87\xce<\x93\xfc\xda\xbf' 25 | tRp8 26 | sS'xc' 27 | p9 28 | (lp10 29 | g5 30 | (g7 31 | S'l,Zc\x9e\x85J@' 32 | tRp11 33 | ag5 34 | (g7 35 | S'\xf7\xb1`\x9d\x10\xf0G@' 36 | tRp12 37 | asS'ddec' 38 | p13 39 | F0.002833333333333 40 | sS'coeffs' 41 | p14 42 | cnumpy.core.multiarray 43 | _reconstruct 44 | p15 45 | (cnumpy 46 | ndarray 47 | p16 48 | (I0 49 | tS'b' 50 | tRp17 51 | (I1 52 | (I105 53 | tg6 54 | (S'c16' 55 | I0 56 | I1 57 | tRp18 58 | (I3 59 | S'<' 60 | NNNI-1 61 | I-1 62 | I0 63 | tbI00 64 | S'\x85)a_D\x1f\xe8?W\\d?^c\xe8;\rL\x85\xff\x8fL\xb1\xbf\xad\x1e\xed\xda\x93\x07\xc3?\x0eL\x85\xff\x8fL\xb1\xbf\xb1\x1e\xed\xda\x93\x07\xc3\xbf\n\xd7\x82e"\r\xe3\xbf\xd3\xee.\xd1\x15\xear\xbf=\x05\x9f\x07F\x8e\xdc?u\x9f\x83\xa8\x1b\xa3\x1a\xbc\n\xd7\x82e"\r\xe3\xbf\xbb\xee.\xd1\x15\xear?aA\x85\x16\x15\x05\xb9?\xcf&U\t\\|\xc0\xbf\xa4\x0b\x90\xdf)\r|\xbf\xeaj\xdd\x1f7b\xb7?\xc0\x0b\x90\xdf)\r|\xbf\xeej\xdd\x1f7b\xb7\xbfeA\x85\x16\x15\x05\xb9?\xce&U\t\\|\xc0?\x1a\x14\xc3\x06\xf7z\xe0?\x9b\x1bL9\xff\xc2s\xbf[.\xaa\x00\x9a\x08\xde\xbf\x1f\x16\xc1YM\x91x?\xdaMlhHz\xe2?k\x8a\xdc\x87,^;\xbc].\xaa\x00\x9a\x08\xde\xbf\x07\x16\xc1YM\x91x\xbf\x1a\x14\xc3\x06\xf7z\xe0?+\x1bL9\xff\xc2s?\xdc/\xb2\xd8\x0c\xdd\xbd\xbfo\xa3N\xec\xe7,\xb5?\xcc\xc3)w?\x8f\xaa?3\xad\x18\xd1\xd5?\xa4\xbf(\xc3K\xe5p\x87\xa2\xbf\r\xca\xd7h\x04=\x9a?,\xc3K\xe5p\x87\xa2\xbf\r\xca\xd7h\x04=\x9a\xbf\xce\xc3)w?\x8f\xaa?3\xad\x18\xd1\xd5?\xa4?\xd5/\xb2\xd8\x0c\xdd\xbd\xbfm\xa3N\xec\xe7,\xb5\xbfd\x0c\xfdh \xa6\xd6\xbf\x89\x11g\xf95\xc0\x89?"fUr1\xac\xd0?D\x11yEe\xea\x93\xbf\x8e\x93\xc4\xfa^>\xd0\xbf\xf2 }\x07\xd1T\x8e?\xac\x16\xd5q\xcd\xb0\xc9?\xf9H\xc9\xb6\x1c\x8f6\xbc\x8e\x93\xc4\xfa^>\xd0\xbf\xf2 }\x07\xd1T\x8e\xbf"fUr1\xac\xd0?@\x11yEe\xea\x93?e\x0c\xfdh \xa6\xd6\xbf\xa1\x11g\xf95\xc0\x89\xbf}\xc4\xcc[-\x08\xba?\xc9J\xc4\xd6~\xd2\xa2\xbf\xa00\xfcRp\xd3\xa4\xbf\xfb\x17H\x85Q9\xa1\xbf>\x81\xf7M\xa7\xfc\x9d?\xa8\xd7\x8d\xa6\x9d\xac\xb0?\xa2[\\\x05\t=\x07\xbf\xdd\xc1\xe4\n\xe61\xba\xbf\xa4\\\\\x05\t=\x07\xbf\xe0\xc1\xe4\n\xe61\xba?C\x81\xf7M\xa7\xfc\x9d?\xa4\xd7\x8d\xa6\x9d\xac\xb0\xbf\xa60\xfcRp\xd3\xa4\xbf\xf9\x17H\x85Q9\xa1?\x81\xc4\xcc[-\x08\xba?\xc0J\xc4\xd6~\xd2\xa2?~\x12\x07FE]\xc9?\xfc^\xb7\xd0\xf7<\x97\xbf\x12=\x06\xdeul\xb2\xbf\xf7\x9d\xd2\xd5T\xff\x9e?\x13\xe0I}\x89\x88\xa4?\x8aZY\xddB=\x99\xbf\xc5\xad\xeb\xf7\x95\xecQ\xbf9\x114\xfbk\xf9\x92?\x87\xd3\xe7zW\xf0\x96?(\x8ae\xbd+\xc9L<%\xad\xeb\xf7\x95\xecQ\xbf8\x114\xfbk\xf9\x92\xbf\x17\xe0I}\x89\x88\xa4?\x8bZY\xddB=\x99?\x13=\x06\xdeul\xb2\xbf\xff\x9d\xd2\xd5T\xff\x9e\xbf\x80\x12\x07FE]\xc9?\x00_\xb7\xd0\xf7<\x97?\xa9\\W"s\xb2\xb2\xbf\x19\xcd\x18\xe3\xe9\xe5w?\xd6N\x96\xbc\xbb9\x94?CL\x86&\xd1\xc4\xac?\x9bp\xdd\x81\\v\x84\xbfm\x1cg\xe3(\xc5\xb2\xbf\x88\xe7]\xe9i\x11u?\xa0\x14\x0eF\xe9\xca\xb4?\xec(\x86\x7fp\x80\x84\xbf\xe3\xad\xe7\xad\x9c\xeb\xb5\xbf\xf2(\x86\x7fp\x80\x84\xbf\xe3\xad\xe7\xad\x9c\xeb\xb5?\x9e\xe7]\xe9i\x11u?\xa0\x14\x0eF\xe9\xca\xb4\xbf\x95p\xdd\x81\\v\x84\xbfm\x1cg\xe3(\xc5\xb2?\xdaN\x96\xbc\xbb9\x94?=L\x86&\xd1\xc4\xac\xbf\xa3\\W"s\xb2\xb2\xbfI\xcd\x18\xe3\xe9\xe5w\xbf\xde\x8f\x1b\xcf\x0b\x18\xb8\xbf\xf1\xe7\x13\xce\xbd\x02\x98?E\xb3=\xfb<\x8f\x88\xbf*\xd6\x08\x9d\xac\xcb\x9f\xbf\x99\xec\x90))\xa6\x86?\xf5@\x89@\xfc[\x98?5\\\x0c\x0c}\x91\x80\xbf\x96s"\xc7\xf0]\x8a\xbf\xde*\x95F\xb19\x88\xbf\xd01\xdf%\xdd\x91\x83?\xe8\x8d\xcd\x7fF\xf5\x87?\xf5\xbdk\xbf\xc3&P\x96\xd5\xeb\x8e?R|\x17I\xbeF\x80\xbf\xae\xe2\xcc\xcf)\xb3G?\xa4H\x85\x18X\xec~?b\xe6B\xecOh\x81\xbfM\x91\xfdg\x84\xfbn\xbf\xbe%a`\xcf\xc5u?P\xb7\xd7_C?h?\xf1T\xcdo\x13Tp?r\x84\xa92?\x01\x7f\xbf\x02*W\x93\x19\xb9\x92\xbfx\x84\xa92?\x01\x7f\xbf\xf5)W\x93\x19\xb9\x92?>\xb7\xd7_C?h?\xe4T\xcdo\x13Tp\xbfN\x91\xfdg\x84\xfbn\xbf\xa1%a`\xcf\xc5u\xbf\xa2H\x85\x18X\xec~?f\xe6B\xecOh\x81?R|\x17I\xbeF\x80\xbf\x96\xe1\xcc\xcf)\xb3G\xbfN:z>\xf5\xbdk\xbf\xbf&P\x96\xd5\xeb\x8e\xbfw\xae\xac(\x04\x13\x9a\xbfv\xb7\xb6{\x93%j?' 65 | tbsS'beta' 66 | p19 67 | (lp20 68 | g5 69 | (g7 70 | S'.\xf64\xfd}\x13\x05@' 71 | tRp21 72 | ag5 73 | (g7 74 | S'ac\x0b\xdb\x07\xe2\x18@' 75 | tRp22 76 | asS'size' 77 | p23 78 | (I83 79 | I107 80 | tp24 81 | sS'info' 82 | p25 83 | S'../../data/N6251_test.fits' 84 | p26 85 | sS'ra' 86 | p27 87 | g5 88 | (g7 89 | S'\x18*-\xca$\xcfm@' 90 | tRp28 91 | sS'dra' 92 | p29 93 | F-0.002833333333333 94 | sS'dec' 95 | p30 96 | g5 97 | (g7 98 | S'\xd0Hv\x0f\xf8XV@' 99 | tRp31 100 | sS'mode' 101 | p32 102 | S'lageurre' 103 | p33 104 | s. -------------------------------------------------------------------------------- /data/fit/PAPER-snrem_cart.pkl: -------------------------------------------------------------------------------- 1 | (dp1 2 | S'norder' 3 | p2 4 | (lp3 5 | I9 6 | aI9 7 | asS'phi' 8 | p4 9 | cnumpy.core.multiarray 10 | scalar 11 | p5 12 | (cnumpy 13 | dtype 14 | p6 15 | (S'f8' 16 | I0 17 | I1 18 | tRp7 19 | (I3 20 | S'<' 21 | NNNI-1 22 | I-1 23 | I0 24 | tbS'`\xb4|\xc1Vq\xf1\xbf' 25 | tRp8 26 | sS'xc' 27 | p9 28 | (lp10 29 | g5 30 | (g7 31 | S'P\xf3\xb7\xef\xf3[6@' 32 | tRp11 33 | ag5 34 | (g7 35 | S'4\xf7\x9e\xc0\xa2\x1e4@' 36 | tRp12 37 | asS'ddec' 38 | p13 39 | F0.11 40 | sS'coeffs' 41 | p14 42 | cnumpy.core.multiarray 43 | _reconstruct 44 | p15 45 | (cnumpy 46 | ndarray 47 | p16 48 | (I0 49 | tS'b' 50 | tRp17 51 | (I1 52 | (I81 53 | tg7 54 | I00 55 | S'N\x7f\x13\x93Rb\xe2@<\xfc\xd1\x9b\x0f\x9b\xd2@\xec\x8eT[\xe6\x81\xc6\xc0H\x04\xfd\x9d\x8a\xa1\xae\xc0\xf8\xc6\xc61\xc5!\xb7@\x83#G\x9c=E\xa6\xc0\xf4"\xa8\xe3\xe0\x19\xb4\xc0\xf0\x8f\xad\xb1Z\xea\xa9@\xcf\x93\x8a\xe6/\x07\xbf@\xa62I\xc0N\xee\xb5@\xb5\x98(!\xee\xd8\x94@\xbc@%\xcd\x18\xf9\xa4@vA\xcaZ&\x14\xa4@W{\x02\xd3NM\xb2\xc0#K\xbb\xd5?9\xa6\xc0\xddA\xe7\x06\xf49}\xc0}\xe7u9\xd7\xaf\xb1@\xe7\xb9{\xb2l;\x91@\x9f:\x97@\x93t\xc0\xc0\x0cbx\xd0\xa5\x9c\x85\xc0g|\x8c\xb6\x10\x8a\x9e\xc0\x1e\x93\xb5p\xf9>\x86\xc0\x7f\xcb(\xc1\xd6\xf5\x9c@\xbaR\xa9>\xec\x83\xa2@\xe0\x9f\xab1\xee\xef[\xc0\xcbb\xb5\xe5!\x16\x8a@\x00\x1cCb\x98\x02r\xc0\xa1\x00&\xc3\x95\xdb\xc8@R\xc1\xf1\xa8i\xc9\xbd@\xddO\xcc_\xd70\xa8\xc0\xc6\xfc\x14\x9c\x99R\xa0\xc0\x12\xeb\xda\xfe\xfbK\x80@\xd2\x8c\x13\xedy\t\x94@\xb4]\x12\xfc\xfe\xbcq@\x01\x00\xf0\x02\xa4\xd0\x89@\xfc/\x17k\xbf.\xa0@NC\xe4\xce\x99\xfc\xaf\xc0\xc9\x93\x1b7s/\xb0@\xd3\x1c\x93\xa7\x05\xda\x92@ \xee\xa5\xaez[\xc06/\xe9\x10\xf4w\x8d\xc0<\xc5\xa3\xa8\xc7P\x9b@\x9a\xb6d\xa7\x9f\xd2\x92@=\xdfXR;O\x8c@\xd0\xfd|\xd8\xc50\x80@C\xe1\xeft\x95H\xb5\xc0(\xf7\xcc\x93\xdeB{\xc0\xa0\'+s@#\xa2@c\xbd\xf2\x1d\x00\xb5\x92\xc0\x0f\xd6\x9c5\xa5\x807@!\xcc^8=\x19g\xc0\xd4\xdasx\x160R\xc0\x1a\xe8\x12\xdc\tC\x83\xc0\x0c\xa7\xea\xc4\x01KY@\xa5\x95\xad6\x89\xdf\xb0\xc0\xefx\xd2\xca\x80\xc9\x80\xc0\xf01|B\xa2\x0c\x99\xc0\'\xfca\xd2\x01p\xa4@\xd9:&\xc4<\xbe\x8b\xc07\xe0[\xee\xf5\x01\x98@u\'\x97\x9f\xd1%f\xc0\'\xc5\xb15\x9e\xb5\x84@Z\x86\x90G\xd2W\x7f\xc0\xdf4r]*\xeb\xb2\xc0j\xe2\x1f\xfc\xe9\xf6\x89\xc0\xf2\xa5-\x1c6\xed\x91@\x1ad\xbc/\x03vy\xc0N0NV\xbdEk@^V\xe6\xa8\x95\x1cK\xc0N\x80\xbd4\x1e\xbd\x98@\x9d\xbf\xd0L%?\x96\xc0\xfa\x15\xa0a\x04\xa7|@\xd2\xa5&\xed\xb2\x06\xac\xc0n0h\xb8n\x16k\xc0!\x9bm\x9et\xf3\x9e\xc0\xd5}\xcc\xc0\x89\x8f\x9f@\xa6\xcb\r\x90\xab\xfch@\xb6\x8f\xd0\xd8\x1e\xddo@\xc2\xb9\x18\x8b\xfe\xdbS\xc0vPs9\xf3/`\xc0JK\xf1\xeb\xb3\xe4\x8a\xc0' 56 | tbsS'beta' 57 | p18 58 | (lp19 59 | g5 60 | (g7 61 | S'vy\x9dx=\x9c\x00@' 62 | tRp20 63 | ag5 64 | (g7 65 | S'\xf2\x1d7\x08@\xb3\r@' 66 | tRp21 67 | asS'size' 68 | p22 69 | (I38 70 | I41 71 | tp23 72 | sS'info' 73 | p24 74 | S'../../data/zen.2455819.69771.uvcRREM_briggs-dirty.fits' 75 | p25 76 | sS'ra' 77 | p26 78 | g5 79 | (g7 80 | S'\xf1\xdf]\xb8\xd3{_@' 81 | tRp27 82 | sS'dra' 83 | p28 84 | F-0.11 85 | sS'dec' 86 | p29 87 | g5 88 | (g7 89 | S'U\x1f\x8d\x18k\x9cE\xc0' 90 | tRp30 91 | sS'mode' 92 | p31 93 | S'hermite' 94 | p32 95 | s. -------------------------------------------------------------------------------- /data/fit/PAPER-snrem_polar.pkl: -------------------------------------------------------------------------------- 1 | (dp1 2 | S'norder' 3 | p2 4 | (lp3 5 | I9 6 | aI9 7 | asS'phi' 8 | p4 9 | cnumpy.core.multiarray 10 | scalar 11 | p5 12 | (cnumpy 13 | dtype 14 | p6 15 | (S'f8' 16 | I0 17 | I1 18 | tRp7 19 | (I3 20 | S'<' 21 | NNNI-1 22 | I-1 23 | I0 24 | tbS'\x84\xc5\xfc\x89\x9e\xc3\xf0\xbf' 25 | tRp8 26 | sS'xc' 27 | p9 28 | (lp10 29 | g5 30 | (g7 31 | S'\xaaB\xdcXi\xe18@' 32 | tRp11 33 | ag5 34 | (g7 35 | S'\x18v\x1e\x02I<5@' 36 | tRp12 37 | asS'ddec' 38 | p13 39 | F0.11 40 | sS'coeffs' 41 | p14 42 | cnumpy.core.multiarray 43 | _reconstruct 44 | p15 45 | (cnumpy 46 | ndarray 47 | p16 48 | (I0 49 | tS'b' 50 | tRp17 51 | (I1 52 | (I45 53 | tg6 54 | (S'c16' 55 | I0 56 | I1 57 | tRp18 58 | (I3 59 | S'<' 60 | NNNI-1 61 | I-1 62 | I0 63 | tbI00 64 | S"\x96\x059rU\xe2\xc7@\x0c\x0f\x88\x92(\xcdl\xbb,m0\xfe'u\xbb\xc0\xbd\xdf\x87\xe8I\x05\xc5\xc0,m0\xfe'u\xbb\xc0\xbd\xdf\x87\xe8I\x05\xc5@\xac\xbc~\x9d7\x9c\xa2\xc0\x85\x1bq\xed\x12\x04\xba@k\x0b8\xb1\xba\xf6\xa3@\x16\xbe\xdf\x9c\xdcy\xde\xbb\xac\xbc~\x9d7\x9c\xa2\xc0\x86\x1bq\xed\x12\x04\xba\xc0\n;4\x87x\x17\x95@)\x06\xb8\x94\xe8\xcb\xa5\xc0\x85\tb\xbb#0\x95\xc091p\xb5\xaf\xd4\xa6\xc0\x86\tb\xbb#0\x95\xc0:1p\xb5\xaf\xd4\xa6@\n;4\x87x\x17\x95@)\x06\xb8\x94\xe8\xcb\xa5@h\x1f\xf2\xd0E_\x97\xc0r\x00\xec\xbc\xe5]\x91@\xb2\xd64_\xe0K\xb6\xc0D\xf1r\xa2\xd3i\x8f@\x99\xe2DW\x98`\x91\xc0\xaa(\x04\xf5\x82L\xf2\xbb\xb1\xd64_\xe0K\xb6\xc0H\xf1r\xa2\xd3i\x8f\xc0g\x1f\xf2\xd0E_\x97\xc0t\x00\xec\xbc\xe5]\x91\xc0o@C\x8b\xee?!\xc9\x82@5\\\x92\xebe\x9b\xa3@'F#%j\xf7\xb2@~W\x88\xf4\xeaF\x93@\xf5\x95p\x01\xdeq\x9a\xc0vW\x88\xf4\xeaF\x93@\xf6\x95p\x01\xdeq\x9a@9\\\x92\xebe\x9b\xa3@$F#%j\xf7\xb2\xc0NY\xd5eU>o@G\x8b\xee?!\xc9\x82\xc0?2Yo+A\x90@(_(\x0c8\xe8q@\xf4\x949\x87\x86E\x97@\x8ex\xe5\x89G\x80\xa7\xc08\xed\x8eP\x14\x96\xa1\xc0\x8f\xb2\xab\xfe\x07\xda\x99\xc0\tBY\xbf\x82\x91\xa5\xc04m\xce>\xdcF\xc3\xbb;\xed\x8eP\x14\x96\xa1\xc0\x94\xb2\xab\xfe\x07\xda\x99@\xf6\x949\x87\x86E\x97@\x8cx\xe5\x89G\x80\xa7@>2Yo+A\x90@#_(\x0c8\xe8q\xc0\xfa-\xca\xb7\x8b\xd6r\xc0\x18a\x05\xabX\x9b\x91\xc0\xd7P\xdc\\/F\x9f\xc0\x961L\xf4\xf9M\x80\xc0\xdf6\xbcs\xbcty\xc0q\x8b\x7f\x0b+\x9du@\x08\x83\xf8K4l\x92\xc0S4,\x97'x\x80@\n\x83\xf8K4l\x92\xc0Z4,\x97'x\x80\xc0\xd56\xbcs\xbcty\xc0Z\x8b\x7f\x0b+\x9du\xc0\xdaP\xdc\\/F\x9f\xc0\x981L\xf4\xf9M\x80@\xf5-\xca\xb7\x8b\xd6r\xc0\x16a\x05\xabX\x9b\x91@p\xcb1\x81\xe4M\x94\xc0f\xf8\xf1\x88\xadX\x85@\x1f\xbbP\xbd\xea\x96}@\x18\x14\xa8\xe4\xa9\xf1\x8b@_+\xc34\xe3.x@\x13WD=&;{@he8\xb3\x8a\x1f\x87@\xa9\xd2\xcb\x92\x91\xb2x\xc0\x9d\x1a\xb4\xdd\xe1\xc1\xa2\xc0^zS[\x99Uh\xbcke8\xb3\x8a\x1f\x87@\xae\xd2\xcb\x92\x91\xb2x@j+\xc34\xe3.x@\x0fWD=&;{\xc0\x1e\xbbP\xbd\xea\x96}@\x18\x14\xa8\xe4\xa9\xf1\x8b\xc0q\xcb1\x81\xe4M\x94\xc0i\xf8\xf1\x88\xadX\x85\xc0" 65 | tbsS'beta' 66 | p19 67 | (lp20 68 | g5 69 | (g7 70 | S'^\xf3x\xabk/\x02@' 71 | tRp21 72 | ag5 73 | (g7 74 | S'8!:1\xe6\xfe\x04@' 75 | tRp22 76 | asS'size' 77 | p23 78 | (I38 79 | I41 80 | tp24 81 | sS'info' 82 | p25 83 | S'../../data/zen.2455819.69771.uvcRREM_briggs-dirty.fits' 84 | p26 85 | sS'ra' 86 | p27 87 | g5 88 | (g7 89 | S'A!\xc3\x0c q_@' 90 | tRp28 91 | sS'dra' 92 | p29 93 | F-0.11 94 | sS'dec' 95 | p30 96 | g5 97 | (g7 98 | S'\tJ:\x00\xfc\xbfE\xc0' 99 | tRp31 100 | sS'mode' 101 | p32 102 | S'lageurre' 103 | p33 104 | s. -------------------------------------------------------------------------------- /data/solve/N6251_cart.pkl: -------------------------------------------------------------------------------- 1 | (dp1 2 | S'norder' 3 | p2 4 | (lp3 5 | I16 6 | aI16 7 | asS'phi' 8 | p4 9 | F-0.448243 10 | sS'xc' 11 | p5 12 | (lp6 13 | F52 14 | aF49 15 | asS'ddec' 16 | p7 17 | F0.002833333333333 18 | sS'coeffs' 19 | p8 20 | cnumpy.core.multiarray 21 | _reconstruct 22 | p9 23 | (cnumpy 24 | ndarray 25 | p10 26 | (I0 27 | tS'b' 28 | tRp11 29 | (I1 30 | (I256 31 | tcnumpy 32 | dtype 33 | p12 34 | (S'f8' 35 | I0 36 | I1 37 | tRp13 38 | (I3 39 | S'<' 40 | NNNI-1 41 | I-1 42 | I0 43 | tbI00 44 | S'\x1e\xe7\x9c\x89)\xfb\xff?\x98\xb4\x91S\xd2\xba\xd1\xbfj\xbb\xaf\x97a\x85\x03@N\xbc\x97\xcf\xf9\xff\xd8\xbf\x00\xe4\n\xb8S\x8b\xec?g\xce\x88&xm\xb3\xbf~@\xc2\xcd\xd1,\xe2\xbf3.\xf2\xaf\x06\xc5\xdf?\xb4IAiH\x84\xc4?,\xb0\xf6\xbe\x08\x18\xb1\xbfA\xb7\xc5\xb5\xccW\xd9?K\xfb\xa6\xfa\xdaX\xbd?\xf6m%\xcf\x9e\xbe\xb8\xbf\x92D\x00sg\x1e\xca?_\x05p\t\x14%\xbf?\xec!\xfb\x07\xf0\xb1\xab\xbf\x08\xf7=\xac\xe9\xd8\x9b\xbf\\\x8fn\xea\xe2\x8b\xb2?\xa9P\xd0\xb8{\x11\xbf\xbf\x8a\xcf:\x046%\xa5?L\xe5\x1b|\xea\x98\xbf\xbf\xfcr\x8e\xd4\xb3\x97\xb1\xbf@\x10\x996F\x8fl?\xcak\xa7\x8f^)\xb0\xbfz\xc0\xde\x06Pv\xa0\xbf|\xb9\x9a1R\x08\x9d\xbf\xf0K\xf9\xb0\xa14\xb6\xbfH\xc0\xe2]<)\xb2\xbf\x15\xbdKL\xb0%\xa7\xbf\xec*+u\x94\x1a\xa9\xbf\xf1\xc1=\x0eV\x9d\xa6\xbf~`d\x9b\xc5\xaf\x9a\xbf\xe2hQ\x0e\xd2m\xc8\xbf\xfc\xd8\x18\xa8\xe9\x01\xa8?\xb1X\x13\xa1d\x8c\xcb\xbfh\x9f\x867#\x88\xb1?\xcaL\x08\x9e\xecV\xaa\xbfS\xf6&w]x\xa1?K\xffg\x8a\x0f\xa7\xb6?1\x8e\x0f\xaf\xea,\x91\xbfC/\x13\x8e\xd9\xfd\x97?d\xe9L\xe9G]\xb0?\xd8\x9a\xf2\xdb\xd0:\x8b?\x1d9\xbf&\xd7#\xab?\xfc\\ya\xcc@\xb1?H\x9c\xad\x9bMg\xa5?\x14\xbd-\xad\n\x12\xa7?\xb2\xcaS%y\x8a\xaf?\x00\xe5M\x7f\xc9\xbcS\xbf\xc8\xf1\xad\xbfw}\x88\xbf\xcc\x02\x83%O\xfe\x80?p \x9c\xefI\xf1\x8c\xbfJ>\xd4\xb4\x9a\xbc\x90?\xb0k:n\xb2\xc7h?$m3k@\xb2\x80\xbf\xc4\xfb\x95+cEt\xbf "\xf4\xff\x1a\xba\x8b\xbf9\x19\x7f\x8f\xfd\xbb\x90\xbf[\xd6X\xee\xcec\x84\xbf\'yi3\xfa\xd1\x8b\xbf\xab\x94k$\x17\xc6\x95\xbf\x95_\x15\x9e(Y\x95\xbf\x06\x92\x1b!\xceP\x97\xbf\x02\xd4\xe1\x16\xbe\x1e\x9c\xbf\x05\xa2@\xc76{\xa1?`\x91\xa5\xfdg\xb1k?\x9e[\xb0\x01\xc6g\x9e?\xb8l\xf5(&\xa7j?\xf4\xf2\xa1\x1c/3\x93?\x86E,]8\xdc\x80?\x98F;\r\'\xf2s?\xbak\xc8\xc4\xac\xd9\x94?\x9b\xeex\x96$\xad\x91?\xa0\xaf\xa0P}\x82\x91?\xc0\xa1Sb?\x8a\x96?*^\xd7>\xc9T\x95?&n\xca\x0f8J\x92?\xaa,\x9a\xab:\xd7\x9a?D\x84v\xab\xe8\xee\x98?\xac\xe5\xf9\x9e\xb4F\x9e?\xb7[M\x7f\x08\x0co\xbf&\x9aP>-e\xd6\x19e\xbf\xea\x18\xa7\x80\x94\xb3\x84?\xb0~\xd1O%\x82\x82?\x8e-\xb5\xce\xb8`\x87?\xac\xf6\xf0a\xa0\x0f\x89?\xf0,\xe0\xee\xe4\x87\x88?3\xf5\x8e\xbacO\x91?\\\x88\x0e\x98\xc6\xcc\x8c?5\xe2\x9d\xc2\x88\xc7\x90?\xe6B8z\xe5\x1f\x8f?\xefG\xf4\xb3\xc2\x86\x90?%\xc2\x9a\xdb\x18u\x92?4_\x9be\xdf:\x8f?\x13_\x99&hk\x97?8\xc2+\x80\xeb\xe4e\xbf\x98\x13j\xcb\x9f\x9a\\\xbf\x98\x10"_\xa3\x18b\xbf\xf0\x9c\x11\xbe\xc2$x\xbfcB\x9dS\x9d|e\xbf\xf8a\x05\x97\xae\x1ed\xbf\xfc\xc7\xb3\xc3\x86Zw\xbf\x88\xd9\xca\xb2\r\xb7y\xbf\xfc\xe8R\xd1\xfbev\xbfh\xedjPq\xa7j\xbf\x00\xde\x82\x8aFFm\xbf\xbc\x84]\xfb\x89\x98k\xbf\x0c\xf7N\xf0S"v\xbf\x1e/J\x1bSS\x82\xbf0\xa0e1/\x85{\xbf\x1e\xc3\xa3\xf1\x1a\x8f\x88\xbf\xfeq1/\x01\xfd\x87?\xba\xc7\x10\xbb5\x89\x84?\xf1\xf3\xf3\x05\\\xbf_?N4\xf3l\x9d\x03\x84?U\xec\xb1\x0b!\xe5\x82?|\xd9\x81\x01\xedo\x84?\xb6\x83\x9f\xb3K\xb0\x84?\x1e\xd9\xb5\xe9\x99A\x86?A\xf8J\x0e\xc4\xec\x90?\x92\x1f\xe5\x07\x91\xc6\x88?\xb7\xe4Yg.\x94\x8f?h\x8a\xdd\xd1\xdd}\x8c?4\x8c\xfb\x1e\xe7\x95\x8c?\xefF\x1c]\x01\xb7\x90?O\x11X0\xc7\xae\x87?\x01\xd5\xd6\xc0%^\x92?Qn\x83\xbd\xff\x08i\xbf%\xc8\xaa\xbf.\xe9f\xbf\xbd,Y\xaeE}k\xbf\x81\xcc--p\xc5x\xbf\xba\xd8%I\xfc|m\xbf\xf8\xe52j\xd0qh\xbf\x99\x1d\xa5\xcb[{z\xbf\xc9\xa1\x13D\x04C\x80\xbfW\xf7\xdb\xc0n\x01y\xbf\x00\xc7\xd8\x90+\x08r\xbf\xec\xd5\x8aP\xec\x9fp\xbf\xec\xc4\x16G*\xbfg\xbf\x9cmd\xa4\xa4\x07r\xbf\x12\x151|\x17\xe1}\xbf\x94\x13\x94\xe4\x0cyq\xbf\xfaGt\xbf\x81\xaf)C\xbe\xe5v\xbf\xced\xc4\xb3\xb8bm\xbf\xad(\xd3\xea\x1e\xb7j\xbf\xc6\\\xca\xac\xb2\xeb{\xbfk\xef\xae\n\x1a\x8d\x83\xbfV\x9f \xb4\xa4oy\xbfn\xac\xee&/\xa0w\xbf\x8a\x01\r\xbf\x1e\x17q\xbftI\xd1\'\x84\x1de\xbf\xc00#O\xd6Em\xbf\x01\x10\xb6y.\x90x\xbf\xa0\x95\xb9\xfa\x90\x19f\xbf\x01`EM\x00Yv\xbf\x9e\xb0}&\xe6\xdd\x7f?*nP.\x10\xf5\x85?0\xd8\xdf%&\xcee?\xa5\xdd\xde0l\xb0\x82?\x15?\x91\r\x7f\xe7s?&0\x080\xa8\x16\x82?\xcc\xa4=\xbd\xf5o\x85?&`\xb2\xbf\xcf\xe5\x83?\x9d2\xcck\x92f\x8e?_\x98\xb7C\xd6F\x89?\x9c;\x8aK\xec;\x86?\x18\xe5S\xd9l\n\x88?Q_\xd6\xb4\xb4j\x80?\x99p\xe8b\xbc5\x86?Xw\xf8\xcc\x1d\xb7y?6f8\xa9\x93\xc9\x84?\xf8\x8f\x7f\x08\xc5}l\xbfW\r\xe7y\xf98q\xbf\xe6M87\xca\xd7z\xbf\xb6*\x12\x9e\xa4Wq\xbf\xbc9\xaf\x18\xdf\xf6i\xbf\\\xec\xc1\x10!6i\xbf\xf9\xac\xf7\xd6\xfb{y\xbf\xe2MrY\x0b\xb8\x84\xbf\xdf\x8f\x1a1!Wu\xbfn\xc8\x85\xd4\xd95y\xbf\xba\xed\xf7\x8a\xe0!p\xbf&\xf4\xb6\xf7\xc5\xa1c\xbf4\xa7\x0f5\x87\xdch\xbfl]\xc5\x12Zlv\xbfHs\xe8\xed\xafba\xbf\xe0\x92[\x1a\xf1zq\xbf\xb0\xd7k\x98\x0f\x84{?7\xdf.{\xfdj\x82?Bu\x99\xb7\xf3|c?\x07g\xeah!\x15\x80?I\xf8Z\x85\xa51j?\xfdD\xd95\x0cW\x81?=_\x0f\xe5Y\xf3\x84?\xd2P6\xa1\x89h\x81?\xb9=I$%@\x8b?eTJ:\xa2K\x88?\xa7\x15n\xa8\xf0\x9a\x82?\xf2\xd8\x08\xc3\x9a4\x86?\x13\xdb\x1d0\x19\xe4x?\xd5\xe2t\x12\xbd#\x82?6\xfcr\x0c\xed\x9fu?YT\xaa\x9c\x9f\xca\x80?\\\xf2\x1dY\nNk\xbf\x1a-\xcd\xc3\x0e:s\xbfv\xe6-\xaa\xdb\xf5~\xbf@5\xf9\xb1eud\xbfV\xa4\xf8K\xc1sc\xbfp\xe7\x13Q\xfa\x82e\xbf\xa1\x01b\xf8\xcb\xe0t\xbf\x93\x82F\xf0\x9a\xab\x83\xbf7;\x15\xee\x1dvm\xbfF\x9e\x03\x95C^w\xbfhCt\x89\xf7in\xbf45`\xa6\x0c\x7fd\xbfL\xec\xd6\xcf\x96\x19i\xbf\xc0\xfb\xa1\xa48\x07w\xbf<\xba\xc1QC\xf3b\xbf2u\xf5\xdb\xb1\x0fq\xbf' 45 | tbsS'beta' 46 | p14 47 | (lp15 48 | F2.5 49 | aF6 50 | asS'size' 51 | p16 52 | (I83 53 | I107 54 | tp17 55 | sS'info' 56 | p18 57 | S'../../data/N6251_test.fits' 58 | p19 59 | sS'ra' 60 | p20 61 | cnumpy.core.multiarray 62 | scalar 63 | p21 64 | (g13 65 | S'\x83\x80g\xd8>\xd6m@' 66 | tRp22 67 | sS'dra' 68 | p23 69 | F-0.002833333333333 70 | sS'dec' 71 | p24 72 | g21 73 | (g13 74 | S'\xbe\xe9\xf2\xed3YV@' 75 | tRp25 76 | sS'mode' 77 | p26 78 | S'hermite' 79 | p27 80 | s. -------------------------------------------------------------------------------- /data/solve/N6251_polar.pkl: -------------------------------------------------------------------------------- 1 | (dp1 2 | S'norder' 3 | p2 4 | (lp3 5 | I16 6 | aI16 7 | asS'phi' 8 | p4 9 | F-0.448243 10 | sS'xc' 11 | p5 12 | (lp6 13 | F52 14 | aF49 15 | asS'ddec' 16 | p7 17 | F0.002833333333333 18 | sS'coeffs' 19 | p8 20 | cnumpy.core.multiarray 21 | _reconstruct 22 | p9 23 | (cnumpy 24 | ndarray 25 | p10 26 | (I0 27 | tS'b' 28 | tRp11 29 | (I1 30 | (I136 31 | tcnumpy 32 | dtype 33 | p12 34 | (S'c16' 35 | I0 36 | I1 37 | tRp13 38 | (I3 39 | S'<' 40 | NNNI-1 41 | I-1 42 | I0 43 | tbI00 44 | S'N\x1f[\xdd\x15|\xe6?\xb2\xbe\xa0\xd0\xe2\x96\xd7\xbba\xc1ElZ\x03b\xbf\x87!\xc9\x05\xaa\x84\xa8?A\xc1ElZ\x03b\xbf\x8c!\xc9\x05\xaa\x84\xa8\xbf\n\x01>\xf3\x03\xdb\xe1\xbfdg\x8f\xd4l1\x89\xbf\xce52\xda\x85\xc4\xdb?\x9b\xd0\xc2\x9ek;\xe1\xbb\n\x01>\xf3\x03\xdb\xe1\xbfhg\x8f\xd4l1\x89?\x93w\r\x9ap\r\x82?\xb7,\xfb\xd6\xa0\xc8\x9e\xbf\'cy\x1a\xd5\x15x\xbf\x9a\x8d*\xfbp{~?+cy\x1a\xd5\x15x\xbf\xba\x8d*\xfbp{~\xbf\x9bw\r\x9ap\r\x82?\xc1,\xfb\xd6\xa0\xc8\x9e?\x95\xca\x9c\xdf\xf4\xe2\xde?+#\xc5#Ug\x93?\xcc\xc9\xf4)\'\xf2\xdc\xbf\xdb\x1c\xd2\xce\x14:\x84\xbf\x04\x8d\x18\xe8\xdc\xa8\xe1?\xefs\xeayZy\xe4\xbb\xce\xc9\xf4)\'\xf2\xdc\xbf\xf7\x1c\xd2\xce\x14:\x84?\x94\xca\x9c\xdf\xf4\xe2\xde?3#\xc5#Ug\x93\xbfH\x07\x07\xbex\x82\x94\xbf\xd9\x1f\xaa\x98U~\xae?\x13\xec\xe1\xdd\xc4_\x97?\xf7\xba\x98\xe6u\xd3\xb9\xbf\xa6q\xc6\x10\x13\x89\x87\xbf\xf7\x08\xef\xb7\x0fg\xc1?\xb1q\xc6\x10\x13\x89\x87\xbf\xf8\x08\xef\xb7\x0fg\xc1\xbf\x0f\xec\xe1\xdd\xc4_\x97?\xf9\xba\x98\xe6u\xd3\xb9?<\x07\x07\xbex\x82\x94\xbf\xdd\x1f\xaa\x98U~\xae\xbf6\x8a9\x90q\xe1\xd6\xbf>3\xa9\x1f\x177\x97\xbf\xa0\x00D\xf69\xc1\xd4?=T\x83p\xc8\xb9\x88?\xd2\xa9zI\xc7\xbc\xd6\xbf%\x00\xbcs\xea\xc9j\xbf\xb1\xda\xb4!\xab\x02\xd5?I\x1d/\xcdh\x03\x01\xbc\xd0\xa9zI\xc7\xbc\xd6\xbf\x8d\x00\xbcs\xea\xc9j?\xa1\x00D\xf69\xc1\xd4?ET\x83p\xc8\xb9\x88\xbf6\x8a9\x90q\xe1\xd6\xbfB3\xa9\x1f\x177\x97?\x13\xbd\x86\nI\'\x9c?\x08t\x97h\x99P\xb1\xbf\x13\r\xa8Q?#\x9b\xbf#sS\xe2\xcf\x9f\xb8?\x15\x15l^_W\x92?\xb77\x868\xb4\x07\xbb\xbf\xde\x7f\xf7\xc7\xcb_}\xbf\xb4RG\x8e\x84\xbb\xb4?\xcc\x7f\xf7\xc7\xcb_}\xbf\xafRG\x8e\x84\xbb\xb4\xbf\x1a\x15l^_W\x92?\xb67\x868\xb4\x07\xbb?\x1b\r\xa8Q?#\x9b\xbf\'sS\xe2\xcf\x9f\xb8\xbf\x13\xbd\x86\nI\'\x9c?\tt\x97h\x99P\xb1?!\xac\x93\xa0\xe9i\xcd?=5\xad\x14\xff\xc0\x8d?\x05\xeaq\xf0\xe9\xbc\xc4\xbf\xf9\x0bl\x18HVg\xbf}\x0fH\xc5\xc5\x02\xc3?\x8d\x9bz\x8a rB\xbf8@j\xd2\xa9l\xbc\xbf\x01H\xec\x86ar{?I\xec\\?Q\xe0\xbf?z4\xfd\x14\xdb+\t\xbc5@j\xd2\xa9l\xbc\xbf\xfdG\xec\x86ar{\xbf}\x0fH\xc5\xc5\x02\xc3?\x05\x9bz\x8a rB?\x05\xeaq\xf0\xe9\xbc\xc4\xbf\xa9\x0bl\x18HVg?\x1f\xac\x93\xa0\xe9i\xcd?M5\xad\x14\xff\xc0\x8d\xbf\xd45\xcfR\xbc\x16\x99\xbf\x9b\x9dM\xb3\x16t\xa9?rU\xa0\x00g\x17\x98?\xf3\x95p\x96v\x1d\xa7\xbfj\x93\'\x1a0\x83\x82\xbf]\xdd\xa3A\x88\xa4\x92?Fh\x1a^\xdf\x85z?\x1cT\n\xfc\xae-\x82?\xf5\x11>\xb4qfr\xbf;\xf6\xf7gX;\x9a\xbf\xf6\x11>\xb4qfr\xbf?\xf6\xf7gX;\x9a?;h\x1a^\xdf\x85z?!T\n\xfc\xae-\x82\xbff\x93\'\x1a0\x83\x82\xbf[\xdd\xa3A\x88\xa4\x92\xbfkU\xa0\x00g\x17\x98?\xf2\x95p\x96v\x1d\xa7?\xde5\xcfR\xbc\x16\x99\xbf\x9b\x9dM\xb3\x16t\xa9\xbf\n\xa7\x121\xcf+\xc0\xbf\xff\xe9\xe4\x8a\xb3p~\xbf\x89;_a\xd59\xa7?Ol\xa8\x00\x12\xe0x\xbfV\xf4\xfd\x9d\xab\xfc\x93\xbf_\xf8\xf8\x8a\x95x\x82?\xd6\xf8\x95*\xa5T\x8c\xbfY@i0\xaa\xf0o\xbf\x90\xe5aY\x11\xd1\x94?F\x13C\xea\xef3|?\x80\x04T\xf2|\xe9\x98\xbfw\x8a\x86\x15lU\x1f\xbc\x8a\xe5aY\x11\xd1\x94?@\x13C\xea\xef3|\xbf\xd6\xf8\x95*\xa5T\x8c\xbf/@i0\xaa\xf0o?W\xf4\xfd\x9d\xab\xfc\x93\xbfd\xf8\xf8\x8a\x95x\x82\xbf\x88;_a\xd59\xa7?_l\xa8\x00\x12\xe0x?\x07\xa7\x121\xcf+\xc0\xbf\xcf\xe9\xe4\x8a\xb3p~?EM\x8f\xc4\xce\x8f\x93?\xa94o$\xad\xe9\x9c\xbf\x16\xba\xe7\xa5\xf0\xd8\x82\xbfmT\xdaO\xed\xefp?\xf5MaQ-~t?7f\x82\x0fX)\x97?-\x86\xb4\x80\xc7\xecb?\x8f\xcb]"\xa2\x8b\xa1\xbf\xd5\xb1u\xcb\xcb\xf2K?\x94\xcf)\xc8N\x06\xa2?\xfb~\x12\xa1\xcc3h\xbf\xe0S\xbc\xc5\x0c\xcf\xa6\xbf\x0f\x7f\x12\xa1\xcc3h\xbf\xe3S\xbc\xc5\x0c\xcf\xa6?\xdc\xb1u\xcb\xcb\xf2K?\x93\xcf)\xc8N\x06\xa2\xbf!\x86\xb4\x80\xc7\xecb?\x8e\xcb]"\xa2\x8b\xa1?\xeeMaQ-~t?2f\x82\x0fX)\x97\xbf\x12\xba\xe7\xa5\xf0\xd8\x82\xbf\x8dT\xdaO\xed\xefp\xbfCM\x8f\xc4\xce\x8f\x93?\xa34o$\xad\xe9\x9c?lCwz\xf37\xaf?\xb7\xec<\x10\xbe\x13c?\xd5\xf2w\xea\xfdkf?\xb6r=\xc1+\xe4\x80?\xc3\x85\xe7#S\x87\x8a\xbf^\'\xc6%\xb6\xe8{\xbfk\x7f\x9b1]4\x91?\xe5,\xa9\xd20n~?\xa4\xf2J\xdc\xc9\xbbS\xbf\xf8\xb7\xd5T\x8c@Q\xbfr\xbdt\x95\x96\nz\xbf;P\xe8\xd12us?\xaf\xdb\xf9\xbf\xdfQ\x93?:\xfb\xd1V\x93\xaf\x1a\\\x05a?\x19\xdeG\xfc\xddR\x92?m\xbc\xcd\xcc\xba\x925\xbf\xcd\xc3]E\xf0!\x85\xbft>o\x12\xce\x93o?\x17~\xfaD\xfef\x82?\x13\xf4\xd6\xbcv\xb9t\xbf7w\x94iA9\x8f\xbf\xfd\xf3\xd6\xbcv\xb9t\xbf)w\x94iA9\x8f?v>o\x12\xce\x93o?\x06~\xfaD\xfef\x82\xbfx\xbb\xcd\xcc\xba\x925\xbf\xcb\xc3]E\xf0!\x85?\xe2\x95\x88>\\\x05a?\x15\xdeG\xfc\xddR\x92\xbf\xa6\xd7\x07V\xef\xe9T?\x8a\x7f<\'\x8a\x87\x97?\x07 \x04\x89\xd6Kp?`Wm4\xf9l\x81\xbf\x06Y\xee9Y\xe1\x88\xbf@x\n717\x87\xbfx\xf4\x82\xb1\rr\x9b\xbf\xbf\xae\xba\x00D\xd2T?\xb6j\x12r\x05\x16\x8a\xbf&\xce5\t\xe3\x1a\x7f\xbf\xca\xf54\x98iCg?\xb9\xaf\xb0\xd9l@o?!<\xc6\xba9np?\xa9[`vY\x0ed\xbf\xdd\xcd\x17\xfe\x8e\xe8\x93\xbf\x0e!\xf5W\xe48x?\x8b=-\xad\xe6\xde\x99?bvWZ=\xd6j\xbfD\x10i\'\x9c\xac\x9e\xbf\x93,\xdc\x07!\x18q?*\xbf\x19\xd6\x10i\xa0?X{Y\xff\xd7*n\xbcE\x10i\'\x9c\xac\x9e\xbf\x97,\xdc\x07!\x18q\xbf\x84=-\xad\xe6\xde\x99?&vWZ=\xd6j?\xdc\xcd\x17\xfe\x8e\xe8\x93\xbf\x1b!\xf5W\xe48x\xbfd<\xc6\xba9np?\xff[`vY\x0ed?\xc5\xf54\x98iCg?\x89\xaf\xb0\xd9l@o\xbf\xb4j\x12r\x05\x16\x8a\xbf\x12\xce5\t\xe3\x1a\x7f?w\xf4\x82\xb1\rr\x9b\xbf_\xaf\xba\x00D\xd2T\xbf\xef\x82\xa2F:\xbe~?=\xb1V\xd6IXl\xbf\xee\x80\xac\x91II6\xbf\xc5]\xcb\xc5\xac\x91\x84\xbf\x18H\r\xddd\x04]?\x92\xfc\xbc\xcd#\x1c\x84?\x8am\xa3\x84\x85@j\xbf\x8f\x98d\x83D\xf0t\xbfH\xaa4g\xdd\xaft?\x08\x84\xf1\x99\x90pc?\x08\x9e\xb8\xa6\xcf\xb6n\xbf\xd1/\x14\xda\x9aQu\xbf\xbc\xffb\xea\xc7\ts?\xf4\x9d\x07S4+~?\xd0k\x89\xd9\xbe\xf5w\xbf\x94\xdeJS\x82p\x93\xbf\xd0k\x89\xd9\xbe\xf5w\xbf\x98\xdeJS\x82p\x93?\xb4\xffb\xea\xc7\ts?\xf4\x9d\x07S4+~\xbf\xfe\x9d\xb8\xa6\xcf\xb6n\xbf\xc6/\x14\xda\x9aQu?4\xaa4g\xdd\xaft?N\x84\xf1\x99\x90pc\xbf\xa9m\xa3\x84\x85@j\xbf\x8d\x98d\x83D\xf0t?9H\r\xddd\x04]?\x9d\xfc\xbc\xcd#\x1c\x84\xbf\xec~\xac\x91II6\xbf\xdb]\xcb\xc5\xac\x91\x84?\x13\x83\xa2F:\xbe~?a\xb1V\xd6IXl?' 45 | tbsS'beta' 46 | p14 47 | (lp15 48 | F2.5 49 | aF6 50 | asS'size' 51 | p16 52 | (I83 53 | I107 54 | tp17 55 | sS'info' 56 | p18 57 | S'../../data/N6251_test.fits' 58 | p19 59 | sS'ra' 60 | p20 61 | cnumpy.core.multiarray 62 | scalar 63 | p21 64 | (g12 65 | (S'f8' 66 | I0 67 | I1 68 | tRp22 69 | (I3 70 | S'<' 71 | NNNI-1 72 | I-1 73 | I0 74 | tbS'\x83\x80g\xd8>\xd6m@' 75 | tRp23 76 | sS'dra' 77 | p24 78 | F-0.002833333333333 79 | sS'dec' 80 | p25 81 | g21 82 | (g22 83 | S'\xbe\xe9\xf2\xed3YV@' 84 | tRp26 85 | sS'mode' 86 | p27 87 | S'lageurre' 88 | p28 89 | s. -------------------------------------------------------------------------------- /data/solve/PAPER-snrem_cart.pkl: -------------------------------------------------------------------------------- 1 | (dp1 2 | S'norder' 3 | p2 4 | (lp3 5 | I11 6 | aI11 7 | asS'phi' 8 | p4 9 | cnumpy.core.multiarray 10 | scalar 11 | p5 12 | (cnumpy 13 | dtype 14 | p6 15 | (S'f8' 16 | I0 17 | I1 18 | tRp7 19 | (I3 20 | S'<' 21 | NNNI-1 22 | I-1 23 | I0 24 | tbS'\xc7~1\x03\x96\xbe\xf0\xbf' 25 | tRp8 26 | sS'xc' 27 | p9 28 | (lp10 29 | g5 30 | (g6 31 | (S'i8' 32 | I0 33 | I1 34 | tRp11 35 | (I3 36 | S'<' 37 | NNNI-1 38 | I-1 39 | I0 40 | tbS'\x16\x00\x00\x00\x00\x00\x00\x00' 41 | tRp12 42 | ag5 43 | (g11 44 | S'\x14\x00\x00\x00\x00\x00\x00\x00' 45 | tRp13 46 | asS'ddec' 47 | p14 48 | F0.11 49 | sS'coeffs' 50 | p15 51 | cnumpy.core.multiarray 52 | _reconstruct 53 | p16 54 | (cnumpy 55 | ndarray 56 | p17 57 | (I0 58 | tS'b' 59 | tRp18 60 | (I1 61 | (I121 62 | tg7 63 | I00 64 | S"\x86\xab\x03\xc18\x16\xe3@ \x95\xc1N\xba\xd1\xce@\x9c\x97\xd3\xde.y\xbf\xc0\xa9\xc3K\xb1\x93\x10\xbc@\x9b\x8f\xab\rX\xa2\xb4@\xe50\r\xdf\xe9\x8f\xb9\xc0\x02\xdf\xf1M\x97\xf9\xb5\xc0\x0f\x94\xdd\x0cA\xee\x9c@K\x96\xda<\xd9\x1b\xa2@\xd8\x1b\x10,c\x18\x83@\x7fg\x8f-\x91\x16\x94@\x01J\x01Ao\x8b\xc4@\xf0\xcd\x8cT^\xd0\x9e@\xda\x8b\x15?\\R\xb1@p\xab&\x1fPr\xb0@\xeam\xcf\x843\x00\x90\xc07\xbe+\xc5\xdc\x19\xa9\xc0\xa7\x89\x9dgE\xfa\xa8\xc0\x9e?l\x83=\x1b\x86@\xbf\xf0\xf1\xa2\x0c\xeaR\xc0\x13\x18\x06\x94Vl\x92@x!\x91\x99\xfba\x85\xc0e\xc5:\xca\xd4(\xc8\xc0\xcc\x0e\x8ca\x87D\x91\xc0\x0b\xe1D\xe7>\\\xa3\xc0\x1eE\xbe\x13\xab?\x90\xc0\x9e\x0c\x95\xa5\x02B{\xc0i`x\xdd\xd9\x98v@\xdd\xeb\\\xf0\xd9\x88\x83@\xdb\x0bd\x12\tj\xa7@f\xd0\x05\xdf\xffD\x88@ \xbe\xc7\xb4\x91x\x9a@m\x97\xe1F\xcd\xae\x83\xc0\x0f\x91\x02\x00\xaf\x12\xc2@O\xab\x8a\xdd\x1b\x9f\xb8@\xe8i4^\xe8r\x96\xc0[,x%\xf4\xaa\x82\xc0\x1dp\xa0\xaab\xf4\x87@\xc4}\x93\xd1-\xbf\x90\xc0\xeabW{\xef3j\xc0\xcf\xcfa #\xc0\x91@\xff\x1b(_\xde\x89\x83@\x1cR\x95\xa1\xc9\xbau@\x1e\xa9\xefo#\x15s@\xb5'\xabX\xec\x89u\xc0\xdf8t\t\xb5A\xb0@\xaa\x12\x16\x93\xfb&a\xc02\xca\xe0\xe4\n\xad\x97@\\\xbf\xaf\x1fc\x92\x95\xc0\x88|\xc8\xd4\xe9E\x97@\xe5D\xedE\x9bZ\x8e\xc06\xc2-\xd0\xdc\xa0\x97@\xa9\xd2\xf4]\xa6\xf3t\xc0\x01 \x80AQ\r\x9d@Qah\xfc\x85\xc3x\xc0\x1c\xe5\x19\xc3N#\xc4\xc0\x8d\xc6{\x97i\x9e\x83\xc0z\xe5\xe5!\xcd\x84\x8b@\xf7\xda@~\xa0\xe9\x9c\xc0:e\xa7(\x887\x86@\xdc\xe0\x8e\xf2[\xc1m@6\x82\xdf'\x98K|@iI\tz\x92\xbb\x92\xc0\\\xa8\x94gv\x9fB@\xaay\x03\x93 \xe7\x99\xc0\xa2t\xe5\xe5\xebGf@4\xacz|\x91\xa8\xb5\xc0\xb0\xf8v\xb6\xa2\xd2\xa7\xc0]y\t\xbc\xfc\xbe\x9e\xc0\xee\x9e\x7f{\xf9\xb5\x8f@\xe6C_!\xa0Q\x93\xc0\x11\x0bs%\xa2\xf8\x99@=VO\xc7r6}@\x84\xa0b3\xcf\x15z@\x02A\x01:_\x11_\xc0\xeau\xdd\xf1\x0e\x06\x8c@\x97\xc5\xf8\x8e3\xf2\x8a\xc0\xb6l\x815\xf0\x8b\xa3\xc0\xde\x92\xc3\x165\xf41\xc0ja\x17\x9b\x06\x94\x87\xc0\xeb\x90\xd1\x93\xaf\x97\x8a\xc0\xfe\x7fn?0P\x94\xc0Jt\x03\x9a\xf2\x8d\x8f@\xc9.,\x97\xf0\x8cS@\xea\x89*^\xe2\xcfr@\xe0\xf4\xef\xf3\xc1R|@\rT=\xb0u9W\xc02\x8e\xdf\x9aKZ@@\xb6\xf5\xfe\xc2\xb9\xce\xa5\xc0/\xea[\x7f\xb9\x1f|@[\x99\xb0\x96\xa5\xff\x91\xc0\xa4)\xc3\xf7\x12\x0f\x97@\xc1\x06\xf3\x87\xe61\x88\xc0\x88\xfb\xaa)6\xa8\x95@\x10\x93)\x80\xd2\xd2s@k\x8e\x1cg\x88P\x85\xc0A\xd9\n\xbc~6t@\x95w\x05svOB\xc0\x92z\x9d\xab\xdc\x88`@\xb4=+2\xaf\x0c\x90\xc0\x88\x8a)[\xb0K\x97@\xe3\xf9X\x8b\xdc\x97\x93\xc0\xa7\x7f\xa6 a\x08y\xc0\x80O\xbdly\x9c\x99\xc0\x84\xd6b\x8e:\x0c`\xc0\x00\x087Q\t\x1fq\xc0x\xf51H@~`\xc0\xfd6\xc7\xfc\x1a\xeb\x89@V5\xc8\x17\xa2\xf4\x88\xc0\xb3\x1e\xa1\x8d\x93xG\xc0}\x8f4U\xf9\xb7\x9b\xc0\xfa\xac\x01|\xf7e\x9c@\xe1\xab\xe7?q\xcaO@&\xe4\xaa_\xf4?\x92@\xc0`uU\x91\x91s@\xaa\xdc\xc4\x8fc\x86\x95@\r{\xac\x86N\xfdO\xc0Y\xde\xd1\x1b\x9b?|\xc0\xa2\x05\x96\xf0\x05\xbav@s\x90]H<\xef\x85@J\x08\x9bzvM|@" 65 | tbsS'beta' 66 | p19 67 | g16 68 | (g17 69 | (I0 70 | tS'b' 71 | tRp20 72 | (I1 73 | (I2 74 | tg7 75 | I00 76 | S'S\xa0\xdbV\x1f\xb2\x02@mM\xf4\xc2\xf6M\x06@' 77 | tbsS'size' 78 | p21 79 | (I38 80 | I41 81 | tp22 82 | sS'info' 83 | p23 84 | S'../../data/zen.2455819.69771.uvcRREM_briggs-dirty.fits' 85 | p24 86 | sS'ra' 87 | p25 88 | g5 89 | (g7 90 | S'\x8cZN\xe3\xf6|_@' 91 | tRp26 92 | sS'dra' 93 | p27 94 | F-0.11 95 | sS'dec' 96 | p28 97 | g5 98 | (g7 99 | S'\xad\xfd\xb0!Z\x97E\xc0' 100 | tRp29 101 | sS'mode' 102 | p30 103 | S'hermite' 104 | p31 105 | s. -------------------------------------------------------------------------------- /data/solve/PAPER-snrem_polar.pkl: -------------------------------------------------------------------------------- 1 | (dp1 2 | S'norder' 3 | p2 4 | (lp3 5 | I11 6 | aI11 7 | asS'phi' 8 | p4 9 | cnumpy.core.multiarray 10 | scalar 11 | p5 12 | (cnumpy 13 | dtype 14 | p6 15 | (S'f8' 16 | I0 17 | I1 18 | tRp7 19 | (I3 20 | S'<' 21 | NNNI-1 22 | I-1 23 | I0 24 | tbS'\xc7~1\x03\x96\xbe\xf0\xbf' 25 | tRp8 26 | sS'xc' 27 | p9 28 | (lp10 29 | g5 30 | (g6 31 | (S'i8' 32 | I0 33 | I1 34 | tRp11 35 | (I3 36 | S'<' 37 | NNNI-1 38 | I-1 39 | I0 40 | tbS'\x16\x00\x00\x00\x00\x00\x00\x00' 41 | tRp12 42 | ag5 43 | (g11 44 | S'\x14\x00\x00\x00\x00\x00\x00\x00' 45 | tRp13 46 | asS'ddec' 47 | p14 48 | F0.11 49 | sS'coeffs' 50 | p15 51 | cnumpy.core.multiarray 52 | _reconstruct 53 | p16 54 | (cnumpy 55 | ndarray 56 | p17 57 | (I0 58 | tS'b' 59 | tRp18 60 | (I1 61 | (I66 62 | tg6 63 | (S'c16' 64 | I0 65 | I1 66 | tRp19 67 | (I3 68 | S'<' 69 | NNNI-1 70 | I-1 71 | I0 72 | tbI00 73 | S"\x9b\x8bd\x03\x08S\xd5@Va\x9e\xd30'\x14\xbcE2\xd3\x95\x857\xb1@\xb6\xacD\xe2+\x06\xb7\xc0G2\xd3\x95\x857\xb1@\xb5\xacD\xe2+\x06\xb7@\t\x7f\xa6\xe2h\xb5\xa1\xc0\xe7\x80a\x82m\xab\x8a\xc0\x06\x9a}\x0c\r\x8e\xc0\xc0\xea\xb6\x95fy\xdb\x04\xbc\n\x7f\xa6\xe2h\xb5\xa1\xc0\xdf\x80a\x82m\xab\x8a@\xee\x8a\x91\xbfJ\xeb\x80\xc0W\xdf8\x8c\xa9\x1c\xa3@\xc2G\x88\xd4\xb2\xc9\xa7@\x03\xd2\xf2$^\xb0\xa8\xc0\xc4G\x88\xd4\xb2\xc9\xa7@\x03\xd2\xf2$^\xb0\xa8@\xef\x8a\x91\xbfJ\xeb\x80\xc0V\xdf8\x8c\xa9\x1c\xa3\xc0\x07(\xcaj\xdc@\x9b@\x86A\x9d\xe2\xdaxq\xc0\xe2\x8c\x816\xbdD\x96\xc0\xa8\x8f\xce\x05\xd3\xf1\xa7\xc0u\r\x1d\xc1\xd6\x99\x92@\xcb\x89PY\x7f\xc3\x96<\xe4\x8c\x816\xbdD\x96\xc0\xa6\x8f\xce\x05\xd3\xf1\xa7@\x08(\xcaj\xdc@\x9b@~A\x9d\xe2\xdaxq@>\x04!n2`\x83\xc0\xe1}b\xd5\xb3\xe1\x85\xc0(\xe0\xae\x995\xd9\xa4\xc0G\xac\xc41\x94\x1e\x9e\xc0*\x9f4\x94\x05\xab\xaf\xc0\xf9q\x82\x8bHU\x96@-\x9f4\x94\x05\xab\xaf\xc0\xf7q\x82\x8bHU\x96\xc0'\xe0\xae\x995\xd9\xa4\xc0H\xac\xc41\x94\x1e\x9e@;\x04!n2`\x83\xc0\xe0}b\xd5\xb3\xe1\x85@\xa68\xf4\xec&\xbb~\xc0\xf3K\xc4\xa5\xbb\x8d~@ZouG\x90\xce\x97\xc0\xe0\xfcR\xf5\xa8\xeep\xc0_2p?\xcc5r\xc0\xfcn\xde$\x0b\x1a\x90@\xce\xa72G\xcc\xa0\xad\xc0\\\x1c\xac\x04\x1d3sR('r\xc0<\x7fE\x979\tv@}\xb4\x11[\xa3\xb4\x83\xc0\x88\xa6\x9b\xf1\x02\x15e\xc0\x0c\xe8\xd5c\x87\xabX@x\xa8\xd6\xa9\x04lm\xc07q\x8b\x13\xd8\xf2\x80\xc0_\xc3\x0f%tJ\x85\xc0\xf2<\x97\xa1\x0bE\x94\xc0`\xc3\x0f%tJ\x85\xc0\xf0<\x97\xa1\x0bE\x94@q\xa8\xd6\xa9\x04lm\xc0?q\x8b\x13\xd8\xf2\x80@\x8f\xa6\x9b\xf1\x02\x15e\xc0\x11\xe8\xd5c\x87\xabX\xc08\x7fE\x979\tv@y\xb4\x11[\xa3\xb4\x83@\x143Pz\x11\x95G@\x10S>R('r@\xf2\xceo'\x16\xf5\x04\xc0\x0el\x83\x03'bp\xc0\xfdT\x97\xef\x03\xaa\x82\xc0\x86\xe2\x12\xf3J\x1bs\xc0\xea\x03\xa4\x1f\x87ZQ\xc0\xae\xaa2\x87\x08\x87z\xc0\x8bc-8I\x7fo@\xe7\x91v\xe4\x9bk?@\x90\r\x91W\xacE\x91\xc0\x8e#!\xa1\xd6\x82\x7f\xc0\x07\x1c\xa2\xd5O{\x85\xc0\xd8\xf5@\t\x86\x85\xd1\xbc\x8e\r\x91W\xacE\x91\xc0w#!\xa1\xd6\x82\x7f@\x8ac-8I\x7fo@\xba\x91v\xe4\x9bk?\xc0\xf2\x03\xa4\x1f\x87ZQ\xc0\xa8\xaa2\x87\x08\x87z@\xf8T\x97\xef\x03\xaa\x82\xc0\x88\xe2\x12\xf3J\x1bs@2\xcdo'\x16\xf5\x04\xc0\x0el\x83\x03'bp@" 74 | tbsS'beta' 75 | p20 76 | g16 77 | (g17 78 | (I0 79 | tS'b' 80 | tRp21 81 | (I1 82 | (I2 83 | tg7 84 | I00 85 | S'S\xa0\xdbV\x1f\xb2\x02@mM\xf4\xc2\xf6M\x06@' 86 | tbsS'size' 87 | p22 88 | (I38 89 | I41 90 | tp23 91 | sS'info' 92 | p24 93 | S'../../data/zen.2455819.69771.uvcRREM_briggs-dirty.fits' 94 | p25 95 | sS'ra' 96 | p26 97 | g5 98 | (g7 99 | S'\x8cZN\xe3\xf6|_@' 100 | tRp27 101 | sS'dra' 102 | p28 103 | F-0.11 104 | sS'dec' 105 | p29 106 | g5 107 | (g7 108 | S'\xad\xfd\xb0!Z\x97E\xc0' 109 | tRp30 110 | sS'mode' 111 | p31 112 | S'lageurre' 113 | p32 114 | s. -------------------------------------------------------------------------------- /data/zen.2455819.69771.uvcRREM_briggs-dirty.fits: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/griffinfoster/shapelets/b639447a088c53f0030ba27ca90bc7fc07b2e889/data/zen.2455819.69771.uvcRREM_briggs-dirty.fits -------------------------------------------------------------------------------- /scripts/fitShapelet.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | Fit for shapelet coefficients across beta, xc, phi, and n_max 4 | """ 5 | 6 | import sys 7 | import numpy as np 8 | from scipy import optimize 9 | import shapelets 10 | 11 | if __name__ == '__main__': 12 | from optparse import OptionParser 13 | o = OptionParser() 14 | o.set_usage('%prog [options] FITS_IMAGE') 15 | o.set_description(__doc__) 16 | o.add_option('-r', '--region', dest='region', default=None, 17 | help='Region of image to decompose into shapelets, (xmin,xmax,ymin,ymax), default: None') 18 | o.add_option('-N', '--noise_region', dest='nregion', default=None, 19 | help='Region of image to use to create a noise map, if set to None the entire image is used, this is not used in the script, (xmin,xmax,ymin,ymax), default: None') 20 | o.add_option('-m', '--mode', dest='mode', default='cart', 21 | help='Set the shapelet mode, cartesian or polar, default: cartesian') 22 | o.add_option('-o', '--outfile', dest='ofn', default='shapeletCoeffs.pkl', 23 | help='Coefficients output filename, default: shapeletCoeffs.pkl') 24 | o.add_option('--max', dest='max_pos', action="store_true", default=False, 25 | help='Override centroid position to be the position of max intensity') 26 | o.add_option('-s', '--savefig', dest='savefig', default=None, 27 | help='Save the figure, requires filename') 28 | 29 | o.add_option('-x','--init_xc', dest='init_xc', default=None, 30 | help='Initial parameter: set a x,y pixel position for initial center, if using a region it is based on the relative position, default: centroid of image/region') 31 | o.add_option('--set_xc', dest='set_xc', action='store_true', 32 | help='Set parameter: set init_xc x,y pixel position for center, these parameters will not be fit for if set') 33 | o.add_option('-b', '--init_beta', dest='init_beta', default=None, 34 | help='Initial parameter: initial beta value, can be two values i.e. \'25.0,30.5\', default: None, guess is made based on Gaussian fit') 35 | o.add_option('--set_beta', dest='set_beta', action='store_true', 36 | help='Set parameter: set init_beta beta value, these parameters will not be fit for if set') 37 | o.add_option('-p','--init_phi', dest='init_phi', default=None, 38 | help='Initial parameter: inital rotation angle (radians), only used when beta is manually input, default: 0') 39 | o.add_option('--set_phi', dest='set_phi', action='store_true', 40 | help='Set parameter: set init_phi rotation angle, this parameter will not be fit for if set') 41 | o.add_option('-n', '--nmax', dest='nmax', default='5', 42 | help='Size of coefficient dimensions for minimization fit, can be two values i.e. \'4,5\', default: 5') 43 | 44 | o.add_option('--fitter',dest='fitterMethod', default='Nelder-Mead', 45 | help='Fitting method: Nelder-Mead, Powell, CG, BFGS, see http://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.optimize.minimize.html, default: Nelder-Mead') 46 | o.add_option('--xtol', dest='xtol', default=0.001, type='float', 47 | help='Relative error in parameters acceptable for convergence, default: 0.001') 48 | o.add_option('--ftol', dest='ftol', default=0.001, type='float', 49 | help='Relative error in chi^2 function acceptable for convergence, default: 0.001') 50 | o.add_option('--maxiter', dest='maxiter', default=250, type='int', 51 | help='Maximum number of iterations to perform, default: 250') 52 | o.add_option('-B', '--brute', dest='brute', default=15, type='int', 53 | help='Maximum basis function order to use when running brute force method, default: 15') 54 | 55 | o.add_option('--noplot', dest='noplot', action='store_true', 56 | help='Do no show plots') 57 | opts, args = o.parse_args(sys.argv[1:]) 58 | 59 | #import matplotlib if needed 60 | show_plots = not opts.noplot 61 | if show_plots: 62 | from matplotlib import pyplot as plt 63 | import matplotlib.patches 64 | 65 | ifn=args[0] 66 | im0,hdr=shapelets.fileio.readFITS(ifn,hdr=True) 67 | extent=[0,im0.shape[0],0,im0.shape[1]] 68 | if not (opts.region is None): 69 | extent=map(int, opts.region.split(',')) 70 | im=shapelets.img.selPxRange(im0,[extent[2],extent[3],extent[0],extent[1]]) 71 | else: 72 | im=im0 73 | 74 | #noise map 75 | if opts.nregion is None: 76 | #use the image region for noise estimation 77 | mean,std=shapelets.img.estimateNoise(im0,mode='sample') 78 | nm=shapelets.img.makeNoiseMap(im.shape,mean,std) 79 | else: 80 | #use a specific region for noise estimation 81 | nextent=map(int, opts.nregion.split(',')) 82 | mean,std=shapelets.img.estimateNoise(shapelets.img.selPxRange(im0,[nextent[2],nextent[3],nextent[0],nextent[1]]),mode='basic') 83 | nm=shapelets.img.makeNoiseMap(im.shape,mean,std) 84 | 85 | #determine set parameters 86 | set_xc=opts.set_xc 87 | set_beta=opts.set_beta 88 | set_phi=opts.set_phi 89 | 90 | #select initial beta, phi, and xc 91 | if opts.init_beta==None: 92 | beta0,phi0,nmax0=shapelets.decomp.initParams(im,mode='fit',hdr=hdr) 93 | else: 94 | beta0=map(float,opts.init_beta.split(',')) 95 | if len(beta0)==1: 96 | beta0=[beta0[0],beta0[0]] 97 | else: 98 | beta0=[beta0[1],beta0[0]] #input to numpy flip 99 | 100 | if opts.init_phi==None: 101 | betaTemp,phi0,nmax0=shapelets.decomp.initParams(im,mode='fit',hdr=hdr) 102 | else: 103 | phi0=float(opts.init_phi) 104 | 105 | if opts.init_xc==None: 106 | xc=shapelets.img.centroid(im) 107 | else: 108 | xc=map(float,opts.init_xc.split(',')) 109 | xc=[xc[1],xc[0]] #input to numpy flip 110 | 111 | nmax=opts.nmax.split(',') 112 | if len(nmax)==1: 113 | nmax=[int(nmax[0])+1,int(nmax[0])+1] 114 | else: 115 | nmax=[int(nmax[1])+1,int(nmax[0])+1] #input to numpy flip 116 | 117 | print 'Using beta: (%f,%f) :: \tphi: %f radians :: \tcentre: x,y=(%f,%f) :: \tnmax: (%i,%i)'%(beta0[1],beta0[0],phi0,xc[1],xc[0],nmax[1]-1,nmax[0]-1) 118 | print 'Fitting xc : %r\nFitting beta : %r\nFitting phi : %r'%(not(set_xc),not(set_beta),not(set_phi)) 119 | 120 | if opts.mode.startswith('pol'): 121 | r0,th0=shapelets.shapelet.polarArray(xc,im.shape) 122 | 123 | #scipy-based minimizer 124 | if set_xc: 125 | if set_beta: 126 | if set_phi: 127 | #same as solveShapelets, no minimization 128 | print 'No parameters to minimize, solving for coefficients with input values' 129 | beta1=beta0 130 | phi1=phi0 131 | xc1=xc 132 | else: 133 | print 'Running minimization for phi only...' 134 | res=optimize.minimize(shapelets.decomp.chi2PolarFunc,[phi0],args=(nmax,im,nm,['phi'],beta0,None,xc,r0,th0),method=opts.fitterMethod,options={'xtol':opts.xtol,'ftol':opts.ftol,'maxiter':opts.maxiter}) 135 | print res 136 | beta1=beta0 137 | phi1=res['x'][0] 138 | xc1=xc 139 | else: 140 | if set_phi: 141 | print 'Running minimization for beta only...' 142 | res=optimize.minimize(shapelets.decomp.chi2PolarFunc,[beta0[0], beta0[1]],args=(nmax,im,nm,['beta0','beta1'],[None,None],phi0,xc,r0,th0),method=opts.fitterMethod,options={'xtol':opts.xtol,'ftol':opts.ftol,'maxiter':opts.maxiter}) 143 | print res 144 | beta1=[res['x'][0],res['x'][1]] 145 | phi1=phi0 146 | xc1=xc 147 | else: 148 | print 'Running minimization for beta and phi...' 149 | res=optimize.minimize(shapelets.decomp.chi2PolarFunc,[beta0[0], beta0[1], phi0],args=(nmax,im,nm,['beta0','beta1','phi'],[None,None],None,xc,r0,th0),method=opts.fitterMethod,options={'xtol':opts.xtol,'ftol':opts.ftol,'maxiter':opts.maxiter}) 150 | print res 151 | beta1=[res['x'][0],res['x'][1]] 152 | phi1=res['x'][2] 153 | xc1=xc 154 | else: 155 | if set_beta: 156 | if set_phi: 157 | print 'Running minimization for centroid only...' 158 | res=optimize.minimize(shapelets.decomp.chi2PolarFunc,[xc[0],xc[1]],args=(nmax,im,nm,['yc','xc'],beta0,phi0,[None,None],None,None),method=opts.fitterMethod,options={'xtol':opts.xtol,'ftol':opts.ftol,'maxiter':opts.maxiter}) 159 | print res 160 | beta1=beta0 161 | phi1=phi0 162 | xc1=[res['x'][0],res['x'][1]] 163 | else: 164 | print 'Running minimization for phi and centroid...' 165 | res=optimize.minimize(shapelets.decomp.chi2PolarFunc,[phi0,xc[0],xc[1]],args=(nmax,im,nm,['phi','yc','xc'],beta0,None,[None,None],None,None),method=opts.fitterMethod,options={'xtol':opts.xtol,'ftol':opts.ftol,'maxiter':opts.maxiter}) 166 | print res 167 | beta1=beta0 168 | phi1=res['x'][0] 169 | xc1=[res['x'][1],res['x'][2]] 170 | else: 171 | if set_phi: 172 | print 'Running minimization for beta and centroid...' 173 | res=optimize.minimize(shapelets.decomp.chi2PolarFunc,[beta0[0],beta0[1],xc[0],xc[1]],args=(nmax,im,nm,['beta0','beta1','yc','xc'],[None,None],phi0,[None,None],None,None),method=opts.fitterMethod,options={'xtol':opts.xtol,'ftol':opts.ftol,'maxiter':opts.maxiter}) 174 | print res 175 | beta1=[res['x'][0],res['x'][1]] 176 | phi1=phi0 177 | xc1=[res['x'][2],res['x'][3]] 178 | else: 179 | print 'Running minimization for beta, phi and centroid...' 180 | res=optimize.minimize(shapelets.decomp.chi2PolarFunc,[beta0[0], beta0[1], phi0, xc[0], xc[1]],args=(nmax,im,nm),method=opts.fitterMethod,options={'xtol':opts.xtol,'ftol':opts.ftol,'maxiter':opts.maxiter}) 181 | print res 182 | beta1=[res['x'][0],res['x'][1]] 183 | phi1=res['x'][2] 184 | xc1=[res['x'][3],res['x'][4]] 185 | print '\tDone' 186 | 187 | # Correct if beta is negative 188 | if beta1[0] < 0.: beta1[0] = np.abs(beta1[0]) 189 | if beta1[1] < 0.: beta1[1] = np.abs(beta1[1]) 190 | 191 | #scipy optimize brute force over a range of N values 192 | n0=1 193 | n1=opts.brute+1 194 | print 'Running brute force for size of N on range [%i:%i]...'%(n0,n1-1) 195 | nmax1=optimize.brute(shapelets.decomp.chi2nmaxPolarFunc,[np.s_[n0:n1:1]],args=(im,nm,beta1[0],beta1[1],phi1,xc1),finish=None) 196 | nmax1=[int(nmax1),int(nmax1)] 197 | print 'Using %i x %i coefficients'%(nmax1[1],nmax1[0]) 198 | print '\tDone' 199 | 200 | print 'Solution:' 201 | print '\tbeta: (%f,%f) \tphi: %f rad \tcentroid: (%f, %f) (sub image: %f,%f) pixels \t ncoeffs: %i x %i'%(beta1[1], beta1[0], phi1, xc1[1]+extent[2], xc1[0]+extent[0], xc1[1], xc1[0], nmax1[1],nmax1[0]) 202 | 203 | #plot: data, model, residual: model-data, coeffs 204 | if show_plots: 205 | fig = plt.figure() 206 | ax = fig.add_subplot(221) 207 | plt.title('Image') 208 | plt.imshow(im) 209 | e=matplotlib.patches.Ellipse(xy=[xc[1],xc[0]],width=2.*beta0[1],height=2.*beta0[0],angle=(180.*phi0/np.pi)) 210 | e.set_clip_box(ax.bbox) 211 | e.set_alpha(0.3) 212 | e.set_facecolor('black') 213 | ax.add_artist(e) 214 | plt.text(xc[1],xc[0],'+',horizontalalignment='center',verticalalignment='center') 215 | plt.colorbar() 216 | 217 | plt.subplot(222) 218 | plt.title('Model') 219 | r1,th1=shapelets.shapelet.polarArray(xc1,im.shape) 220 | bvals=shapelets.decomp.genPolarBasisMatrix(beta1,nmax1,phi1,r1,th1) 221 | coeffs=shapelets.decomp.solveCoeffs(bvals,im) 222 | mdl=np.abs(shapelets.img.constructModel(bvals,coeffs,im.shape)) 223 | plt.imshow(mdl) 224 | plt.colorbar() 225 | 226 | plt.subplot(223) 227 | plt.title('Residual') 228 | res=im-mdl 229 | plt.imshow(res) 230 | plt.colorbar() 231 | 232 | plt.subplot(224) 233 | plt.title('Coefficients') 234 | cimR=shapelets.img.polarCoeffImg(coeffs.real,nmax1) 235 | cimI=shapelets.img.polarCoeffImg(coeffs.imag,nmax1) 236 | cimI=np.fliplr(cimI) 237 | cim=np.concatenate((cimR,cimI),axis=1) 238 | #plt.pcolor(cim) 239 | plt.imshow(cim,interpolation='nearest',origin='lower') 240 | plt.colorbar() 241 | else: 242 | r1,th1=shapelets.shapelet.polarArray(xc1,im.shape) 243 | bvals=shapelets.decomp.genPolarBasisMatrix(beta1,nmax1,phi1,r1,th1) 244 | coeffs=shapelets.decomp.solveCoeffs(bvals,im) 245 | 246 | #determine (RA,dec) coordinates for centroid position 247 | if extent is None: 248 | #radec=hdr['wcs'].wcs_pix2sky(np.array([ [xc1[1]+1,xc1[0]+1] ]),1)[0] #unit: degrees, FITS conventions: first pixel is (1,1) 249 | radec=hdr['wcs'].all_pix2world(np.array([ [xc1[1]+1,xc1[0]+1] ]),1)[0] #unit: degrees, FITS conventions: first pixel is (1,1) 250 | else: 251 | #radec=hdr['wcs'].wcs_pix2sky(np.array([ [xc1[1]+extent[0]+1,im0.shape[0]-(extent[2]+xc1[0])] ]),1)[0] #unit: degrees, FITS conventions: first pixel is (1,1) 252 | radec=hdr['wcs'].all_pix2world(np.array([ [xc1[1]+extent[0]+1,im0.shape[0]-(extent[2]+xc1[0])] ]),1)[0] #unit: degrees, FITS conventions: first pixel is (1,1) 253 | 254 | print 'Centroid RA: %f (deg) Dec: %f (deg)'%(radec[0],radec[1]) 255 | 256 | ofn=opts.ofn 257 | print 'Writing to file:',ofn 258 | shapelets.fileio.writeLageurreCoeffs(ofn,coeffs,xc1,im.shape,beta1,phi1,nmax1,info=ifn,pos=[radec[0],radec[1],hdr['dra'],hdr['ddec']]) 259 | 260 | elif opts.mode.startswith('cart'): 261 | ry=np.array(range(0,im.shape[0]),dtype=float)-xc[0] 262 | rx=np.array(range(0,im.shape[1]),dtype=float)-xc[1] 263 | xx0,yy0=shapelets.shapelet.xy2Grid(ry,rx) 264 | 265 | #scipy-based minimizer 266 | if set_xc: 267 | if set_beta: 268 | if set_phi: 269 | #same as solveShapelets, no minimization 270 | print 'No parameters to minimize, solving for coefficients with input values' 271 | beta1=beta0 272 | phi1=phi0 273 | xc1=xc 274 | else: 275 | print 'Running minimization for phi only...' 276 | res=optimize.minimize(shapelets.decomp.chi2Func,[phi0],args=(nmax,im,nm,['phi'],beta0,None,xc,xx0,yy0),method=opts.fitterMethod,options={'xtol':opts.xtol,'ftol':opts.ftol,'maxiter':opts.maxiter}) 277 | print res 278 | beta1=beta0 279 | phi1=res['x'][0] 280 | xc1=xc 281 | else: 282 | if set_phi: 283 | print 'Running minimization for beta only...' 284 | res=optimize.minimize(shapelets.decomp.chi2Func,[beta0[0], beta0[1]],args=(nmax,im,nm,['beta0','beta1'],[None,None],phi0,xc,xx0,yy0),method=opts.fitterMethod,options={'xtol':opts.xtol,'ftol':opts.ftol,'maxiter':opts.maxiter}) 285 | print res 286 | beta1=[res['x'][0],res['x'][1]] 287 | phi1=phi0 288 | xc1=xc 289 | else: 290 | print 'Running minimization for beta and phi...' 291 | res=optimize.minimize(shapelets.decomp.chi2Func,[beta0[0], beta0[1], phi0],args=(nmax,im,nm,['beta0','beta1','phi'],[None,None],None,xc,xx0,yy0),method=opts.fitterMethod,options={'xtol':opts.xtol,'ftol':opts.ftol,'maxiter':opts.maxiter}) 292 | print res 293 | beta1=[res['x'][0],res['x'][1]] 294 | phi1=res['x'][2] 295 | xc1=xc 296 | else: 297 | if set_beta: 298 | if set_phi: 299 | print 'Running minimization for centroid only...' 300 | res=optimize.minimize(shapelets.decomp.chi2Func,[xc[0],xc[1]],args=(nmax,im,nm,['yc','xc'],beta0,phi0,[None,None],None,None),method=opts.fitterMethod,options={'xtol':opts.xtol,'ftol':opts.ftol,'maxiter':opts.maxiter}) 301 | print res 302 | beta1=beta0 303 | phi1=phi0 304 | xc1=[res['x'][0],res['x'][1]] 305 | else: 306 | print 'Running minimization for phi and centroid...' 307 | res=optimize.minimize(shapelets.decomp.chi2Func,[phi0,xc[0],xc[1]],args=(nmax,im,nm,['phi','yc','xc'],beta0,None,[None,None],None,None),method=opts.fitterMethod,options={'xtol':opts.xtol,'ftol':opts.ftol,'maxiter':opts.maxiter}) 308 | print res 309 | beta1=beta0 310 | phi1=res['x'][0] 311 | xc1=[res['x'][1],res['x'][2]] 312 | else: 313 | if set_phi: 314 | print 'Running minimization for beta and centroid...' 315 | res=optimize.minimize(shapelets.decomp.chi2Func,[beta0[0],beta0[1],xc[0],xc[1]],args=(nmax,im,nm,['beta0','beta1','yc','xc'],[None,None],phi0,[None,None],None,None),method=opts.fitterMethod,options={'xtol':opts.xtol,'ftol':opts.ftol,'maxiter':opts.maxiter}) 316 | print res 317 | beta1=[res['x'][0],res['x'][1]] 318 | phi1=phi0 319 | xc1=[res['x'][2],res['x'][3]] 320 | else: 321 | print 'Running minimization for beta, phi and centroid...' 322 | res=optimize.minimize(shapelets.decomp.chi2Func,[beta0[0], beta0[1], phi0, xc[0], xc[1]],args=(nmax,im,nm),method=opts.fitterMethod,options={'xtol':opts.xtol,'ftol':opts.ftol,'maxiter':opts.maxiter}) 323 | print res 324 | beta1=[res['x'][0],res['x'][1]] 325 | phi1=res['x'][2] 326 | xc1=[res['x'][3],res['x'][4]] 327 | print '\tDone' 328 | 329 | # Correct if beta is negative 330 | if beta1[0] < 0.: beta1[0] = np.abs(beta1[0]) 331 | if beta1[1] < 0.: beta1[1] = np.abs(beta1[1]) 332 | 333 | #scipy optimize brute force over a range of N values 334 | n0=1 335 | n1=opts.brute+1 336 | print 'Running brute force for size of N on range [%i:%i]...'%(n0,n1-1) 337 | nmax1=optimize.brute(shapelets.decomp.chi2nmaxFunc,[np.s_[n0:n1:1]],args=(im,nm,beta1[0],beta1[1],phi1,xc1),finish=None) 338 | nmax1=[int(nmax1),int(nmax1)] 339 | print 'Using %i x %i coefficients'%(nmax1[1],nmax1[0]) 340 | print '\tDone' 341 | 342 | print 'Solution:' 343 | print '\tbeta: (%f,%f) \tphi: %f rad \tcentroid: (%f, %f) (sub image: %f,%f) pixels \t ncoeffs: %i x %i'%(beta1[1], beta1[0], phi1, xc1[1]+extent[2], xc1[0]+extent[0], xc1[1], xc1[0], nmax1[1],nmax1[0]) 344 | 345 | #plot: data, model, residual: model-data, coeffs 346 | if show_plots: 347 | fig = plt.figure() 348 | ax = fig.add_subplot(221) 349 | plt.title('Image') 350 | plt.imshow(im) 351 | e=matplotlib.patches.Ellipse(xy=[xc[1],xc[0]],width=2.*beta0[1],height=2.*beta0[0],angle=(180.*phi0/np.pi)) 352 | e.set_clip_box(ax.bbox) 353 | e.set_alpha(0.3) 354 | e.set_facecolor('black') 355 | ax.add_artist(e) 356 | plt.text(xc[1],xc[0],'+',horizontalalignment='center',verticalalignment='center') 357 | plt.colorbar() 358 | 359 | plt.subplot(222) 360 | plt.title('Model') 361 | ry=np.array(range(0,im.shape[0]),dtype=float)-xc1[0] 362 | rx=np.array(range(0,im.shape[1]),dtype=float)-xc1[1] 363 | yy,xx=shapelets.shapelet.xy2Grid(ry,rx) 364 | bvals=shapelets.decomp.genBasisMatrix(beta1,nmax1,phi1,yy,xx) 365 | coeffs=shapelets.decomp.solveCoeffs(bvals,im) 366 | mdl=shapelets.img.constructModel(bvals,coeffs,im.shape) 367 | plt.imshow(mdl) 368 | plt.text(xc1[1],xc1[0],'+',horizontalalignment='center',verticalalignment='center') 369 | plt.colorbar() 370 | 371 | plt.subplot(223) 372 | plt.title('Residual') 373 | res=im-mdl 374 | plt.imshow(res) 375 | plt.colorbar() 376 | 377 | plt.subplot(224) 378 | plt.title('Coefficients') 379 | sqCoeffs=np.reshape(coeffs,nmax1) 380 | #plt.pcolor(sqCoeffs) 381 | plt.imshow(sqCoeffs,interpolation='nearest',origin='lower') 382 | plt.colorbar() 383 | else: 384 | ry=np.array(range(0,im.shape[0]),dtype=float)-xc1[0] 385 | rx=np.array(range(0,im.shape[1]),dtype=float)-xc1[1] 386 | yy,xx=shapelets.shapelet.xy2Grid(ry,rx) 387 | bvals=shapelets.decomp.genBasisMatrix(beta1,nmax1,phi1,yy,xx) 388 | coeffs=shapelets.decomp.solveCoeffs(bvals,im) 389 | 390 | #determine (RA,dec) coordinates for centroid position 391 | if extent is None: 392 | #radec=hdr['wcs'].wcs_pix2sky(np.array([ [xc1[1]+1,xc1[0]+1] ]),1)[0] #unit: degrees, FITS conventions: first pixel is (1,1) 393 | radec=hdr['wcs'].wcs_pix2world(np.array([ [xc1[1]+1,xc1[0]+1] ]),1)[0] #unit: degrees, FITS conventions: first pixel is (1,1) 394 | else: 395 | #radec=hdr['wcs'].wcs_pix2sky(np.array([ [xc1[1]+extent[0]+1,im0.shape[0]-(extent[2]+xc1[0])] ]),1)[0] #unit: degrees, FITS conventions: first pixel is (1,1) 396 | radec=hdr['wcs'].wcs_pix2world(np.array([ [xc1[1]+extent[0]+1,im0.shape[0]-(extent[2]+xc1[0])] ]),1)[0] #unit: degrees, FITS conventions: first pixel is (1,1) 397 | 398 | print 'Centroid RA: %f (deg) Dec: %f (deg)'%(radec[0],radec[1]) 399 | 400 | ofn=opts.ofn 401 | print 'Writing to file:',ofn 402 | shapelets.fileio.writeHermiteCoeffs(ofn,coeffs,xc1,im.shape,beta1,phi1,nmax1,info=ifn,pos=[radec[0],radec[1],hdr['dra'],hdr['ddec']]) 403 | 404 | if show_plots: 405 | if not (opts.savefig is None): 406 | plt.savefig(opts.savefig) 407 | else: plt.show() 408 | 409 | -------------------------------------------------------------------------------- /scripts/insertShapelet.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | Insert a shapelet coefficient file into the visibilities of a measurement set 4 | """ 5 | 6 | import sys 7 | import numpy as np 8 | import scipy.constants 9 | #from matplotlib import pyplot as plt 10 | import shapelets 11 | import shapelets.phs 12 | import casacore.tables as tbls 13 | import distutils.dir_util 14 | 15 | if __name__ == '__main__': 16 | from optparse import OptionParser 17 | o = OptionParser() 18 | o.set_usage('%prog [options] -c COEFF_FILE MS') 19 | o.set_description(__doc__) 20 | o.add_option('-c', '--coeff', dest='cfn', default=None, 21 | help='Shapelet coefficient file, default: None') 22 | o.add_option('-m', '--mode', dest='mode', default='add', 23 | help='\'replace\': Replace the visibilities, \'add\': add to the visibilites, \'subtract\': subtract from visibilites, default: add') 24 | o.add_option('-d', '--data_column', dest='data_column', default='DATA', 25 | help='Data column to take visibilities from/write to default: DATA') 26 | o.add_option('-o', '--outfile', dest='ofn', default=None, 27 | help='Output measurement set name, default: input file name + \'.shape\'') 28 | o.add_option('-X','--over', dest='overwrite', action="store_true", default=False, 29 | help='Over write original visibilities') 30 | o.add_option('-S','--scale',dest='rescale', default=None, 31 | help='A flux scaling factor. This is useful if the model was derived from an averaged wideband image and the coefficients need to be rescaled to reverse the averaging, in this situation the rescaling value should be the number of channels imaged. A value of 1 will cause no rescaling Default: Number of channels in the MS') 32 | 33 | #rephasing options 34 | o.add_option('-p','--phs',dest='phsMode', default='centre', 35 | help='Placement of source by phase rotating the visibilities, options are centre: the model is inserted at the phase centre no phase rotation is performed ; source: visibilities are rotated to make the centroid of the model the phase centre, then rotated back to the original phase centre ; manual: a manually input (RA,dec) is rotated to and the source inserted. default: centre') 36 | o.add_option('--ra', dest='ra', default=None, 37 | help='RA (in radians unless flag set) to phase data to') 38 | o.add_option('--dec', dest='dec', default=None, 39 | help='DEC (in radians unless flag set) to phase data to') 40 | o.add_option('--deg',dest='deg_flag',action='store_true', 41 | help='Use degrees instead of radians') 42 | o.add_option('--str',dest='str_flag', action='store_true', 43 | help='Use hh:mm:ss.sss format for RA and dd:mm:ss.sss format for DEC') 44 | 45 | o.add_option('-b','--beta',dest='beta',default=None, 46 | help='Override beta (in pixels), can be a 1, 2, or 3 comma seperated values') 47 | opts, args = o.parse_args(sys.argv[1:]) 48 | 49 | 50 | #load coefficient file 51 | if opts.cfn is None: 52 | sys.exit('error:missing shapelet coefficient file') 53 | d=shapelets.fileio.readCoeffs(opts.cfn) 54 | 55 | #override beta if input as option 56 | if opts.beta is None: 57 | beta=d['beta'] 58 | phi=d['phi'] 59 | else: 60 | betaList=map(float,opts.beta.split(',')) 61 | if len(betaList)==1: 62 | beta=[betaList[0],betaList[0]] 63 | phi=d['phi'] 64 | elif len(betaList)==2: 65 | beta=betaList 66 | phi=d['phi'] 67 | elif len(betaList)==3: 68 | beta=[betaList[0],betaList[1]] 69 | phi=betaList[2] 70 | 71 | ##scale beta to radians 72 | #rotM=np.matrix([[np.cos(d['phi']),-1.*np.sin(d['phi'])],[np.sin(d['phi']),np.cos(d['phi'])]]) 73 | #temp0=np.dot(rotM,np.array([(np.pi/180.)*d['dra'],0.])) 74 | #temp1=np.dot(rotM,np.array([0.,(np.pi/180.)*d['ddec']])) 75 | #rotDeltas=np.array([np.sqrt(temp0[0,0]**2.+temp0[0,1]**2.), np.sqrt(temp1[0,0]**2.+temp1[0,1]**2.)]) 76 | #betaRad=(2.*np.pi)*rotDeltas*np.array(d['beta']) #there is some mathematical convention issue, something about wavenumber and wavelength...should sort out a clear answer 77 | #phi=d['phi'] 78 | 79 | #scale beta to radians 80 | rotM=np.matrix([[np.cos(phi),-1.*np.sin(phi)],[np.sin(phi),np.cos(phi)]]) 81 | temp0=np.dot(rotM,np.array([(np.pi/180.)*d['dra'],0.])) 82 | temp1=np.dot(rotM,np.array([0.,(np.pi/180.)*d['ddec']])) 83 | rotDeltas=np.array([np.sqrt(temp0[0,0]**2.+temp0[0,1]**2.), np.sqrt(temp1[0,0]**2.+temp1[0,1]**2.)]) 84 | betaRad=(2.*np.pi)*rotDeltas*np.array(beta) #there is some mathematical convention issue, something about wavenumber and wavelength...should sort out a clear answer 85 | 86 | #generate basis functions 87 | print 'generating UV Basis Functions...', 88 | if d['mode'].startswith('herm'): 89 | bfs=shapelets.decomp.genBasisFuncs([betaRad[0],betaRad[1]],d['norder'],phi,fourier=True) 90 | elif d['mode'].startswith('lag'): 91 | bfs=shapelets.decomp.genPolarBasisFuncs([betaRad[0],betaRad[1]],d['norder'],phi,fourier=True) 92 | print len(bfs), 'done' 93 | 94 | #parse where to insert the shapelet model 95 | if opts.phsMode.startswith('manual'): 96 | if opts.ra is None or opts.dec is None: 97 | print 'ERROR: RA or DEC not set' 98 | exit(1) 99 | 100 | if opts.deg_flag: 101 | ra=np.pi*float(opts.ra)/180. 102 | dec=np.pi*float(opts.dec)/180. 103 | elif opts.str_flag: 104 | raArr=map(float,opts.ra.split(':')) 105 | ra=15.*(raArr[0]+raArr[1]/60.+raArr[2]/3600.) 106 | ra=np.pi*ra/180. 107 | decArr=map(float,opts.dec.split(':')) 108 | dec=np.abs(decArr[0])+decArr[1]/60.+decArr[2]/3600. 109 | if decArr[0] < 0.: dec*=-1. 110 | dec=np.pi*dec/180. 111 | else: 112 | ra=float(opts.ra) 113 | dec=float(opts.dec) 114 | phsRotate=True 115 | elif opts.phsMode.startswith('source'): 116 | ra=np.pi*d['ra']/180. 117 | dec=np.pi*d['dec']/180. 118 | phsRotate=True 119 | else: 120 | phsRotate=False 121 | 122 | if phsRotate: 123 | print 'Inserting shapelet model at RA=%f Dec=%f (mode=%s)'%(ra,dec,opts.phsMode) 124 | else: 125 | print 'Inserting shapelet model at phase centre' 126 | 127 | #load MS, get visibilites and u,v,w positions 128 | data_column=opts.data_column.upper() 129 | for fid,fn in enumerate(args): 130 | 131 | if opts.overwrite: 132 | ofn=fn 133 | else: 134 | ofn=fn+'.shape' 135 | distutils.dir_util.copy_tree(fn,ofn) 136 | print 'working on: %s (%i of %i)'%(ofn,fid+1,len(args)) 137 | 138 | #get the initial phase centre 139 | field=pt.table(ofn+'/FIELD') 140 | phaseCentre=field.col('PHASE_DIR').getcol()[0,0] 141 | field.close() 142 | if phsRotate: 143 | print 'Phasing to RA: %1.10f, DEC: %1.10f'%(ra,dec) 144 | MS=shapelets.phs.ClassMS.ClassMS(ofn,Col=data_column) 145 | MS.RotateMS((ra,dec)) 146 | MS.SaveVis(Col=data_column) 147 | print 'done' 148 | 149 | MS=tbls.table(ofn,readonly=True) 150 | uvw=MS.col('UVW').getcol() # [vis id, (u,v,w)] 151 | vis=MS.col(data_column).getcol() #[vis id, freq id, stokes id] 152 | MS.close() 153 | 154 | #gather channel frequency information 155 | SW=tbls.table(ofn+'/SPECTRAL_WINDOW') 156 | freqs=SW.col('CHAN_FREQ').getcol() 157 | cc=scipy.constants.c 158 | uu=uvw[:,0] 159 | vv=uvw[:,1] 160 | uu=np.reshape(uu,(uvw.shape[0],1)) 161 | vv=np.reshape(vv,(uvw.shape[0],1)) 162 | #convert u,v to units of wavelengths 163 | uu=(uu*freqs)/cc 164 | vv=(vv*freqs)/cc 165 | SW.close() 166 | 167 | #rescaling value 168 | #flux scaling is too low if the model was derived form a wideband averaged image, in that case the correct rescaling is the number of channels 169 | if opts.rescale is None: 170 | rescale=float(freqs.shape[1]) 171 | else: rescale=float(opts.rescale) 172 | print 'Rescale factor: %f'%rescale 173 | 174 | #evaulate basis functions at each u,v postion 175 | print 'Evaluating shapelet basis functions for all (u,v) positions' 176 | shapeVis=np.zeros_like(vis[:,:,0]).flatten() #only doing this for Stokes I 177 | for bfid,bf in enumerate(bfs): 178 | #TODO: visibilites seem to be rotated by 90 degrees 179 | #TODO: i think this line is correct, but the rotation and mirroring leads me to use the line below -> shapeVis+=d['coeffs'][bfid]*shapelets.shapelet.computeBasis2d(bf,uu.flatten(),vv.flatten()) 180 | #TODO: this could be at least partially due to the sign of the FITS ddec and dra 181 | shapeVis+=d['coeffs'][bfid]*shapelets.shapelet.computeBasis2d(bf,-1.*vv.flatten(),-1.*uu.flatten()) 182 | #shapeVis+=1.*shapelets.shapelet.computeBasis2d(bfs[1],uu.flatten(),vv.flatten()) 183 | shapeVis=rescale*np.reshape(shapeVis,uu.shape) 184 | print 'done' 185 | 186 | #update visibilites 187 | #TODO: assuming unpolarized source for the moment, this needs to be fixed properly 188 | print 'Updating visibilities (mode:%s)'%opts.mode 189 | if opts.mode.startswith('replace'): 190 | newVis=np.zeros_like(vis) 191 | newVis[:,:,0]=shapeVis/2. #XX 192 | newVis[:,:,3]=shapeVis/2. #YY 193 | elif opts.mode.startswith('add'): 194 | newVis=vis 195 | newVis[:,:,0]+=shapeVis/2. #XX 196 | newVis[:,:,3]+=shapeVis/2. #YY 197 | elif opts.mode.startswith('sub'): 198 | newVis=vis 199 | newVis[:,:,0]-=shapeVis/2. #XX 200 | newVis[:,:,3]-=shapeVis/2. #YY 201 | else: 202 | print 'Unknown MS update mode, the MS will be left unchanged' 203 | print 'done' 204 | 205 | print 'writing to:',ofn 206 | MS=tbls.table(ofn,readonly=False) 207 | MS.putcol(data_column, newVis) 208 | MS.close() 209 | print 'done' 210 | 211 | if phsRotate: 212 | print 'Phase rotating back to original phase centre...' 213 | print 'Phasing to RA: %1.10f, DEC: %1.10f'%(phaseCentre[0],phaseCentre[1]) 214 | MS=shapelets.phs.ClassMS.ClassMS(ofn,Col=data_column) 215 | MS.RotateMS((phaseCentre[0],phaseCentre[1])) 216 | MS.SaveVis(Col=data_column) 217 | print 'done' 218 | 219 | -------------------------------------------------------------------------------- /scripts/plotCoeffs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | Plot a Shaplet coefficient file 4 | """ 5 | 6 | import sys 7 | import numpy as np 8 | from matplotlib import pyplot as plt 9 | import shapelets 10 | import shapelets.phs 11 | import pprint 12 | 13 | if __name__ == '__main__': 14 | from optparse import OptionParser 15 | o = OptionParser() 16 | o.set_usage('%prog [options] COEFF_FILE') 17 | o.set_description(__doc__) 18 | o.add_option('-s', '--savefig', dest='savefig', default=None, 19 | help='Save the figure, requires filename') 20 | o.add_option('-f', '--ft', dest='fourier', action='store_true', 21 | help='Perform a Fourier transform on the basis functions') 22 | opts, args = o.parse_args(sys.argv[1:]) 23 | 24 | ifn=args[0] 25 | d=shapelets.fileio.readCoeffs(ifn) 26 | 27 | ry=np.array(range(0,d['size'][0]),dtype=float)-d['xc'][0] 28 | rx=np.array(range(0,d['size'][1]),dtype=float)-d['xc'][1] 29 | 30 | print 'RA:', shapelets.phs.rad2hmsdms.rad2hmsdms(d['ra'],Type="ra",deg=True) 31 | print 'Dec:', shapelets.phs.rad2hmsdms.rad2hmsdms(d['dec'],Type="dec",deg=True) 32 | 33 | if d['mode'].startswith('herm'): 34 | #model 35 | yy,xx=shapelets.shapelet.xy2Grid(ry,rx) 36 | bvals=shapelets.decomp.genBasisMatrix(d['beta'],d['norder'],d['phi'],yy,xx,fourier=opts.fourier) 37 | mdl=shapelets.img.constructModel(bvals,d['coeffs'],d['size']) 38 | 39 | #coeffs 40 | coeffs=np.reshape(d['coeffs'],d['norder']) 41 | 42 | if opts.fourier: 43 | ptitle='Fourier(Hermite)' 44 | else: 45 | ptitle='Hermite' 46 | 47 | elif d['mode'].startswith('lag'): 48 | #model 49 | r0,th0=shapelets.shapelet.polarArray(d['xc'],d['size']) 50 | bvals=shapelets.decomp.genPolarBasisMatrix(d['beta'],d['norder'],d['phi'],r0,th0,fourier=opts.fourier) 51 | mdl=np.abs(shapelets.img.constructModel(bvals,d['coeffs'],d['size'])) 52 | 53 | #coeffs 54 | coeffs=d['coeffs'] 55 | cimR=shapelets.img.polarCoeffImg(coeffs.real,d['norder']) 56 | cimI=shapelets.img.polarCoeffImg(coeffs.imag,d['norder']) 57 | cimI=np.fliplr(cimI) 58 | coeffs=np.concatenate((cimR,cimI),axis=1) 59 | 60 | if opts.fourier: 61 | ptitle='Fourier(Laguerre)' 62 | else: 63 | ptitle='Laguerre' 64 | 65 | print d['beta'] 66 | 67 | betaRad=shapelets.measure.beta_pix2angle(d['beta'],phi=d['phi'],deltas=[d['dra'],d['ddec']]) #convert beta[pixels] to beta[radians] 68 | pprint.pprint(shapelets.measure.all(d['coeffs'],betaRad,d['norder'],mode=d['mode'])) 69 | 70 | plt.suptitle(ptitle) 71 | plt.subplot(121) 72 | plt.title('Model') 73 | plt.imshow(np.abs(mdl),interpolation='nearest',extent=(rx[0],rx[-1],ry[-1],ry[0])) 74 | plt.text(0,0,'+',horizontalalignment='center',verticalalignment='center') 75 | plt.colorbar() 76 | 77 | plt.subplot(122) 78 | plt.title('Coefficients') 79 | #plt.pcolor(coeffs) 80 | plt.imshow(coeffs,interpolation='nearest',origin='lower') 81 | plt.colorbar() 82 | 83 | if not (opts.savefig is None): 84 | plt.savefig(opts.savefig) 85 | else: plt.show() 86 | 87 | -------------------------------------------------------------------------------- /scripts/plotImg.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | Generic Image Plotter 4 | """ 5 | 6 | import sys 7 | from matplotlib import pyplot as plt 8 | import shapelets 9 | 10 | if __name__ == '__main__': 11 | from optparse import OptionParser 12 | o = OptionParser() 13 | o.set_usage('%prog [options] FITS_IMAGE') 14 | o.set_description(__doc__) 15 | o.add_option('-r', '--region', dest='region', default=None, 16 | help='Region of image plot, (xmin,xmax,ymin,ymax), default: None') 17 | o.add_option('-s', '--savefig', dest='savefig', default=None, 18 | help='Save the figure, requires filename') 19 | opts, args = o.parse_args(sys.argv[1:]) 20 | 21 | def onclick(event): 22 | print 'start: \tx=%d \ty=%d'%(event.xdata, event.ydata) 23 | 24 | def onrelease(event): 25 | print 'end: \tx=%d \ty=%d'%(event.xdata, event.ydata) 26 | print '==================================' 27 | 28 | fn=args[0] 29 | if fn.split('.')[-1].lower() == 'fits': 30 | im,hdr=shapelets.fileio.readFITS(fn,hdr=True) 31 | else: 32 | im=shapelets.fileio.readImg(fn) 33 | if not (opts.region is None): 34 | extent=map(int, opts.region.split(',')) 35 | im=shapelets.img.selPxRange(im,[extent[2],extent[3],extent[0],extent[1]]) #numpy axis flip 36 | 37 | fig = plt.figure() 38 | cid = fig.canvas.mpl_connect('button_press_event', onclick) 39 | cid = fig.canvas.mpl_connect('button_release_event', onrelease) 40 | 41 | plt.title('Image') 42 | plt.imshow(im) 43 | plt.colorbar() 44 | plt.xlabel('X/RA') 45 | plt.ylabel('Y/Dec') 46 | print '==================================' 47 | if not (opts.savefig is None): 48 | plt.savefig(opts.savefig) 49 | else: plt.show() 50 | 51 | -------------------------------------------------------------------------------- /scripts/plotShapelets.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | Plot a set of shapelet basis functions 4 | """ 5 | 6 | import sys 7 | import numpy as np 8 | from matplotlib import pyplot as plt 9 | import shapelets 10 | 11 | if __name__ == '__main__': 12 | from optparse import OptionParser 13 | o = OptionParser() 14 | o.set_usage('%prog [options]') 15 | o.set_description(__doc__) 16 | o.add_option('-n', '--nmax', dest='nmax', default='5', 17 | help='Maximum order of shapelet decomposition basis functions, if using Hermite can use 2 values i.e. \'4,5\', default: 5') 18 | o.add_option('-p', '--polar', dest='polar', action='store_true', 19 | help='Put in polar shapelet mode, default: False (cartesian)') 20 | o.add_option('-b', '--beta', dest='beta', default='1.0', 21 | help='Characteristic shapelet size, can use 1(symetric beta), 2(elliptical beta), 3(elliptical beta with rotation) values i.e. \'2.1,3.5\' default: 1.0') 22 | o.add_option('-s', '--savefig', dest='savefig', default=None, 23 | help='Save the figure, requires filename') 24 | o.add_option('-f', '--ft', dest='fourier', default=None, 25 | help='Perform a Fourier transform on the basis functions, mode: fft (compute 2D Fourer transform). scale (compute the Fourier transform as a rescaling)') 26 | opts, args = o.parse_args(sys.argv[1:]) 27 | 28 | nmax=opts.nmax.split(',') 29 | if len(nmax)==1: nmax=[int(nmax[0])+1,int(nmax[0])+1] 30 | else: nmax=[int(nmax[0])+1,int(nmax[1])+1] 31 | 32 | betaphi=opts.beta.split(',') 33 | if len(betaphi)==1: 34 | beta=[float(betaphi[0]),float(betaphi[0])] 35 | phi=0. 36 | elif len(betaphi)==2: 37 | beta=[float(betaphi[1]),float(betaphi[0])] #x/y flip 38 | phi=0. 39 | else: 40 | beta=[float(betaphi[1]),float(betaphi[0])] #x/y flip 41 | phi=float(betaphi[2]) 42 | 43 | xlim=[-5,5] 44 | ylim=[-5,5] 45 | rx=np.linspace(xlim[0],xlim[1],num=128) 46 | ry=np.linspace(ylim[0],ylim[1],num=128) 47 | 48 | if opts.polar: 49 | nmax=nmax[0] 50 | print 'polar shapelets' 51 | fullImgReal=np.zeros((len(ry)*nmax*2,len(rx)*nmax)) 52 | fullImgImag=np.zeros((len(ry)*nmax*2,len(rx)*nmax)) 53 | yOffset=len(ry)*nmax 54 | r,th=shapelets.shapelet.xy2rthGrid(ry,rx) 55 | for nn in range(nmax): 56 | for mm in np.arange(-1*nn,nn+1): 57 | if (nn%2==0 and mm%2==0) or (nn%2==1 and mm%2==1): 58 | if opts.fourier is None: 59 | bf=shapelets.shapelet.polarDimBasis(nn,mm,beta=beta,phi=phi) 60 | bval=shapelets.shapelet.computeBasisPolar(bf,r,th) 61 | elif opts.fourier.startswith('fft'): 62 | bf=shapelets.shapelet.polarDimBasis(nn,mm,beta=beta,phi=phi) 63 | bval=shapelets.shapelet.computeBasisPolar(bf,r,th) 64 | bval=np.fft.fftshift(np.fft.fft2(np.fft.fftshift(bval))) 65 | elif opts.fourier.startswith('scale'): 66 | bf=shapelets.shapelet.polarDimBasis(nn,mm,beta=beta,phi=phi,fourier=True) 67 | bval=shapelets.shapelet.computeBasisPolar(bf,r,th) 68 | fullImgReal[mm*len(ry)+yOffset:(mm+1)*len(ry)+yOffset,nn*len(rx):(nn+1)*len(rx)]=bval.real 69 | fullImgImag[mm*len(ry)+yOffset:(mm+1)*len(ry)+yOffset,nn*len(rx):(nn+1)*len(rx)]=bval.imag 70 | fig=plt.figure() 71 | fig.subplots_adjust(wspace=0.3) 72 | 73 | plt.subplot(121) 74 | plt.imshow(fullImgReal) 75 | for nn in range(nmax): 76 | for mm in np.arange(-1*nn,nn+1): 77 | if (nn%2==0 and mm%2==0) or (nn%2==1 and mm%2==1): 78 | plt.fill([nn*len(rx),(nn+1)*len(rx),(nn+1)*len(rx),nn*len(rx)],[mm*len(ry)+yOffset,mm*len(ry)+yOffset,(mm+1)*len(ry)+yOffset,(mm+1)*len(ry)+yOffset],fill=False) 79 | plt.xlim(xmin=0,xmax=len(rx)*nmax) 80 | plt.ylim(ymin=len(ry)*nmax*2,ymax=len(ry)) 81 | plt.xticks(np.arange(0,len(rx)*nmax,len(rx))+(len(rx)/2),range(nmax)) 82 | plt.yticks(np.arange(0,len(ry)*(nmax*2+1),len(ry)+1)+(len(ry)/2),nmax-np.arange(nmax*2+1)) 83 | plt.title('Real') 84 | plt.colorbar() 85 | 86 | plt.subplot(122) 87 | plt.imshow(fullImgImag) 88 | for nn in range(nmax): 89 | for mm in np.arange(-1*nn,nn+1): 90 | if (nn%2==0 and mm%2==0) or (nn%2==1 and mm%2==1): 91 | plt.fill([nn*len(rx),(nn+1)*len(rx),(nn+1)*len(rx),nn*len(rx)],[mm*len(ry)+yOffset,mm*len(ry)+yOffset,(mm+1)*len(ry)+yOffset,(mm+1)*len(ry)+yOffset],fill=False) 92 | plt.xlim(xmin=0,xmax=len(rx)*nmax) 93 | plt.ylim(ymin=len(ry)*nmax*2,ymax=len(ry)) 94 | plt.xticks(np.arange(0,len(rx)*nmax,len(rx))+(len(rx)/2),range(nmax)) 95 | plt.yticks(np.arange(0,len(ry)*(nmax*2+1),len(ry)+1)+(len(ry)/2),nmax-np.arange(nmax*2+1)) 96 | plt.title('Imaginary') 97 | plt.colorbar() 98 | 99 | plt.suptitle('Lageurre Basis Functions (Polar)') 100 | 101 | else: 102 | print 'cartesian shapelets' 103 | fig=plt.figure() 104 | fullImg=np.zeros((len(ry)*nmax[1],len(rx)*nmax[0])) 105 | yy,xx=shapelets.shapelet.xy2Grid(ry,rx) 106 | for n0 in range(nmax[1]): 107 | for n1 in range(nmax[0]): 108 | if opts.fourier is None: 109 | bf=shapelets.shapelet.dimBasis2d(n0,n1,beta=beta,phi=phi) 110 | bval=shapelets.shapelet.computeBasis2d(bf,yy,xx) 111 | elif opts.fourier.startswith('fft'): 112 | bf=shapelets.shapelet.dimBasis2d(n0,n1,beta=beta,phi=phi) 113 | bval=shapelets.shapelet.computeBasis2d(bf,yy,xx) 114 | bval=np.abs(np.fft.fftshift(np.fft.fft2(np.fft.fftshift(bval)))) 115 | elif opts.fourier.startswith('scale'): 116 | bf=shapelets.shapelet.dimBasis2d(n0,n1,beta=beta,phi=phi,fourier=True) 117 | bval=shapelets.shapelet.computeBasis2d(bf,yy,xx) 118 | fullImg[n0*len(ry):(n0+1)*len(ry),n1*len(rx):(n1+1)*len(rx)]=bval 119 | 120 | plt.imshow(fullImg) 121 | for n0 in range(nmax[1]): 122 | for n1 in range(nmax[0]): 123 | plt.fill([n1*len(rx),(n1+1)*len(rx),(n1+1)*len(rx),n1*len(rx)],[n0*len(ry),n0*len(ry),(n0+1)*len(ry),(n0+1)*len(ry)],fill=False) 124 | plt.xlim(xmin=0,xmax=len(rx)*nmax[0]) 125 | plt.xticks(np.arange(0,len(rx)*nmax[0],len(rx))+(len(rx)/2),range(nmax[0])) 126 | plt.yticks(np.arange(0,len(ry)*nmax[1],len(ry))+(len(ry)/2),range(nmax[1])) 127 | plt.ylim(ymin=len(ry)*nmax[1],ymax=0) 128 | plt.xlabel('X') 129 | plt.ylabel('Y') 130 | plt.title('Hermite Basis Functions (Cartesian)') 131 | plt.colorbar() 132 | 133 | if not (opts.savefig is None): 134 | plt.savefig(opts.savefig) 135 | else: plt.show() 136 | 137 | -------------------------------------------------------------------------------- /scripts/profile.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | import sys 4 | sys.path.append('../src/') 5 | import matplotlib.pyplot as plt 6 | import numpy as np 7 | from time import time 8 | import cshapelet as csh 9 | import fshapelet as fsh 10 | import shapelet as sh 11 | import decomp 12 | import cProfile, pstats 13 | 14 | USE_PROFILER = True 15 | 16 | n = 16 17 | m = 2 18 | PB_DIM = (1000, 500) 19 | xc = (800, 1300) 20 | beta0 = 100. 21 | mask = None 22 | r, th = sh.polarArray(xc, PB_DIM) 23 | print 'Problem dim:', PB_DIM 24 | 25 | backend_list = {'original': decomp, 26 | 'opt + numexpr': fsh, 27 | 'opt + cython': csh 28 | } 29 | 30 | pr = {} 31 | 32 | for backend, mod in backend_list.iteritems(): 33 | if USE_PROFILER: 34 | pr[backend] = cProfile.Profile() 35 | pr[backend].enable() 36 | t = time() 37 | res0 = mod.genPolarBasisMatrix(beta0, n, r, th), 38 | t = time() - t 39 | if USE_PROFILER: 40 | pr[backend].disable() 41 | print backend,':', t 42 | 43 | 44 | if USE_PROFILER: 45 | for backend in backend_list: 46 | print '='*80 47 | print ' '*30, backend 48 | print '='*80 49 | ps = pstats.Stats(pr[backend]) 50 | ps.sort_stats('cumulative').print_stats(20) 51 | -------------------------------------------------------------------------------- /scripts/solveShapelet.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | Solve for shapelet coefficients based on beta, xc, phi, and n_max 4 | """ 5 | 6 | import sys 7 | import numpy as np 8 | import shapelets 9 | 10 | if __name__ == '__main__': 11 | from optparse import OptionParser 12 | o = OptionParser() 13 | o.set_usage('%prog [options] FITS_IMAGE') 14 | o.set_description(__doc__) 15 | o.add_option('-r', '--region', dest='region', default=None, 16 | help='Region of image to decompose into shapelets, (xmin,xmax,ymin,ymax), default: None') 17 | o.add_option('-N', '--noise_region', dest='nregion', default=None, 18 | help='Region of image to use to create a noise map, if set to None the entire image is used, this is not used in the script, (xmin,xmax,ymin,ymax), default: None') 19 | o.add_option('-x', '--xc', dest='xc', default=None, 20 | help='set a x,y pixel position for shapelet center, if using a region it is based on the relative position, default: centroid of image/region') 21 | o.add_option('-m', '--mode', dest='mode', default='cart', 22 | help='Set the shapelet mode, cartesian or polar, default: cartesian') 23 | o.add_option('-n', '--nmax', dest='nmax', default='5', 24 | help='Size of coefficient dimensions, can be two values i.e. \'4,5\', default: 5') 25 | o.add_option('-b', '--beta', dest='beta', default=None, 26 | help='Beta value, can be two values i.e. \'25.0,30.5\', default: None, guess is made based on Gaussian fit') 27 | o.add_option('-p','--phi', dest='phi', default=0., type='float', 28 | help='Rotation angle (radians), only used when beta is manually input, default: 0') 29 | o.add_option('-o', '--outfile', dest='ofn', default='shapeletCoeffs.pkl', 30 | help='Coefficients output filename, default: shapeletCoeffs.pkl') 31 | o.add_option('--centroid', dest='centroid', action="store_true", default=False, 32 | help='Use the centroid position instead of max intensity position') 33 | o.add_option('-s', '--savefig', dest='savefig', default=None, 34 | help='Save the figure, requires filename') 35 | o.add_option('--noplot', dest='noplot', action='store_true', 36 | help='Do no show plots') 37 | opts, args = o.parse_args(sys.argv[1:]) 38 | 39 | #import matplotlib if needed 40 | show_plots = not opts.noplot 41 | if show_plots: 42 | from matplotlib import pyplot as plt 43 | import matplotlib.patches 44 | 45 | ifn=args[0] 46 | im0,hdr=shapelets.fileio.readFITS(ifn,hdr=True) 47 | extent=[0,im0.shape[0],0,im0.shape[1]] 48 | 49 | if not (opts.region is None): 50 | extent=map(int, opts.region.split(',')) 51 | im=shapelets.img.selPxRange(im0, [extent[2],extent[3],extent[0],extent[1]]) #numpy axis flip) 52 | else: 53 | im=im0 54 | 55 | #noise map 56 | if opts.nregion is None: 57 | #sample the entire image for noise estimation 58 | mean,std=shapelets.img.estimateNoise(im0,mode='sample') 59 | nm=shapelets.img.makeNoiseMap(im.shape,mean,std) 60 | else: 61 | #use a specific region for noise estimation 62 | nextent=map(int, opts.nregion.split(',')) 63 | mean,std=shapelets.img.estimateNoise(shapelets.img.selPxRange(im0,[nextent[2],nextent[3],nextent[0],nextent[1]]),mode='basic') 64 | nm=shapelets.img.makeNoiseMap(im.shape,mean,std) 65 | 66 | #select initial beta, phi, and xc 67 | if opts.beta==None: 68 | beta0,phi0,nmax0=shapelets.decomp.initParams(im,mode='fit',hdr=hdr) 69 | else: 70 | beta0=map(float,opts.beta.split(',')) 71 | phi0=float(opts.phi) 72 | if len(beta0)==1: 73 | beta0=[beta0[0],beta0[0]] 74 | else: 75 | beta0=[beta0[1],beta0[0]] #input to numpy flip 76 | 77 | if opts.centroid: 78 | xc=shapelets.img.centroid(im) 79 | elif opts.xc==None: 80 | xc=shapelets.img.maxPos(im) 81 | else: 82 | xc=map(float,opts.xc.split(',')) 83 | xc=[xc[1],xc[0]] #input to numpy flip 84 | 85 | nmax=opts.nmax.split(',') 86 | if len(nmax)==1: 87 | nmax=[int(nmax[0])+1,int(nmax[0])+1] 88 | else: 89 | nmax=[int(nmax[1])+1,int(nmax[0])+1] #input to numpy flip 90 | 91 | print 'Using beta: (%f,%f) :: \tphi: %f radians :: \tcentre: x,y=(%f,%f) :: \tnmax: (%i,%i)'%(beta0[1],beta0[0],phi0,xc[1],xc[0],nmax[1]-1,nmax[0]-1) 92 | 93 | #determine (RA,dec) coordinates for centroid position 94 | #TODO: this is correct for when the FITS header is delta RA<0 and delta Dec>0, this may need to be generalized 95 | if extent is None: 96 | #radec=hdr['wcs'].wcs_pix2sky(np.array([ [xc[1]+1,xc[0]+1] ]),1)[0] #unit: degrees, FITS conventions: first pixel is (1,1) 97 | radec=hdr['wcs'].all_pix2world(np.array([ [xc[1]+1,xc[0]+1] ]),1)[0] #unit: degrees, FITS conventions: first pixel is (1,1) 98 | else: 99 | #radec=hdr['wcs'].wcs_pix2sky(np.array([ [xc[1]+extent[0]+1,im0.shape[0]-(extent[2]+xc[0])] ]),1)[0] #unit: degrees, FITS conventions: first pixel is (1,1) 100 | radec=hdr['wcs'].all_pix2world(np.array([ [xc[1]+extent[0]+1,im0.shape[0]-(extent[2]+xc[0])] ]),1)[0] #unit: degrees, FITS conventions: first pixel is (1,1) 101 | 102 | print 'Centroid RA: %f (deg) Dec: %f (deg)'%(radec[0],radec[1]) 103 | 104 | if opts.mode.startswith('pol'): 105 | r0,th0=shapelets.shapelet.polarArray(xc,im.shape) 106 | 107 | #plot: data, model, residual: model-data, coeffs 108 | if show_plots: 109 | fig = plt.figure() 110 | ax = fig.add_subplot(221) 111 | plt.title('Image') 112 | plt.imshow(im) 113 | e=matplotlib.patches.Ellipse(xy=[xc[1],xc[0]],width=2.*beta0[1],height=2.*beta0[0],angle=(180.*phi0/np.pi)) #numpy to matplotlib flip 114 | e.set_clip_box(ax.bbox) 115 | e.set_alpha(0.3) 116 | e.set_facecolor('black') 117 | ax.add_artist(e) 118 | plt.text(xc[1],xc[0],'+',horizontalalignment='center',verticalalignment='center') #numpy to matplotlib flip 119 | plt.colorbar() 120 | plt.xlabel('X/RA') 121 | plt.ylabel('Y/Dec') 122 | 123 | plt.subplot(222) 124 | plt.title('Model') 125 | bvals=shapelets.decomp.genPolarBasisMatrix(beta0,nmax,phi0,r0,th0) 126 | coeffs=shapelets.decomp.solveCoeffs(bvals,im) 127 | mdl=np.abs(shapelets.img.constructModel(bvals,coeffs,im.shape)) 128 | plt.imshow(mdl) 129 | plt.text(xc[1],xc[0],'+',horizontalalignment='center',verticalalignment='center') #numpy to matplotlib flip 130 | plt.colorbar() 131 | plt.xlabel('X/RA') 132 | plt.ylabel('Y/Dec') 133 | 134 | plt.subplot(223) 135 | plt.title('Residual') 136 | res=im-mdl 137 | plt.imshow(res) 138 | plt.colorbar() 139 | plt.xlabel('X/RA') 140 | plt.ylabel('Y/Dec') 141 | 142 | plt.subplot(224) 143 | plt.title('Coefficients') 144 | cimR=shapelets.img.polarCoeffImg(coeffs.real,nmax) 145 | cimI=shapelets.img.polarCoeffImg(coeffs.imag,nmax) 146 | cimI=np.fliplr(cimI) 147 | cim=np.concatenate((cimR,cimI),axis=1) 148 | #plt.pcolor(cim) 149 | plt.imshow(cim,interpolation='nearest',origin='lower') 150 | plt.colorbar() 151 | else: 152 | bvals=shapelets.decomp.genPolarBasisMatrix(beta0,nmax,phi0,r0,th0) 153 | coeffs=shapelets.decomp.solveCoeffs(bvals,im) 154 | 155 | ofn=opts.ofn 156 | print 'Writing to file:',ofn 157 | shapelets.fileio.writeLageurreCoeffs(ofn,coeffs,xc,im.shape,beta0,phi0,nmax,info=ifn,pos=[radec[0],radec[1],hdr['dra'],hdr['ddec']]) 158 | 159 | elif opts.mode.startswith('cart'): 160 | 161 | #plot: data, model, residual: model-data, coeffs 162 | if show_plots: 163 | fig = plt.figure() 164 | ax = fig.add_subplot(221) 165 | plt.title('Image') 166 | plt.imshow(im) 167 | e=matplotlib.patches.Ellipse(xy=[xc[1],xc[0]],width=2.*beta0[1],height=2.*beta0[0],angle=(180.*phi0/np.pi)) #numpy to matplotlib flip 168 | e.set_clip_box(ax.bbox) 169 | e.set_alpha(0.3) 170 | e.set_facecolor('black') 171 | ax.add_artist(e) 172 | plt.text(xc[1],xc[0],'+',horizontalalignment='center',verticalalignment='center') #numpy to matplotlib flip 173 | plt.colorbar() 174 | plt.xlabel('X/RA') 175 | plt.ylabel('Y/Dec') 176 | 177 | plt.subplot(222) 178 | plt.title('Model') 179 | ry=np.array(range(0,im.shape[0]),dtype=float)-xc[0] 180 | rx=np.array(range(0,im.shape[1]),dtype=float)-xc[1] 181 | yy,xx=shapelets.shapelet.xy2Grid(ry,rx) 182 | bvals=shapelets.decomp.genBasisMatrix(beta0,nmax,phi0,yy,xx) 183 | coeffs=shapelets.decomp.solveCoeffs(bvals,im) 184 | mdl=shapelets.img.constructModel(bvals,coeffs,im.shape) 185 | plt.imshow(mdl) 186 | plt.text(xc[1],xc[0],'+',horizontalalignment='center',verticalalignment='center') #numpy to matplotlib flip 187 | plt.colorbar() 188 | plt.xlabel('X/RA') 189 | plt.ylabel('Y/Dec') 190 | 191 | plt.subplot(223) 192 | plt.title('Residual') 193 | res=im-mdl 194 | plt.imshow(res) 195 | plt.colorbar() 196 | plt.xlabel('X/RA') 197 | plt.ylabel('Y/Dec') 198 | 199 | plt.subplot(224) 200 | plt.title('Coefficients') 201 | sqCoeffs=np.reshape(coeffs,nmax) 202 | #plt.pcolor(sqCoeffs) 203 | plt.imshow(sqCoeffs,interpolation='nearest',origin='lower') 204 | plt.colorbar() 205 | else: 206 | ry=np.array(range(0,im.shape[0]),dtype=float)-xc[0] 207 | rx=np.array(range(0,im.shape[1]),dtype=float)-xc[1] 208 | yy,xx=shapelets.shapelet.xy2Grid(ry,rx) 209 | bvals=shapelets.decomp.genBasisMatrix(beta0,nmax,phi0,yy,xx) 210 | coeffs=shapelets.decomp.solveCoeffs(bvals,im) 211 | 212 | ofn=opts.ofn 213 | print 'Writing to file:',ofn 214 | shapelets.fileio.writeHermiteCoeffs(ofn,coeffs,xc,im.shape,beta0,phi0,nmax,info=ifn,pos=[radec[0],radec[1],hdr['dra'],hdr['ddec']]) 215 | 216 | if show_plots: 217 | if not (opts.savefig is None): 218 | plt.savefig(opts.savefig) 219 | else: plt.show() 220 | 221 | -------------------------------------------------------------------------------- /scripts/test_scripts.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | plotShapelets.py -n 4 -p -b 1.0,1.0,0.44 4 | 5 | solveShapelet.py ../data/N6251_test.fits -r 1028,1097,1025,1074 -N 967,1067,972,1026 -n 20 -m polar 6 | solveShapelet.py ../data/N6251_test.fits -r 1028,1097,1025,1074 -N 967,1067,972,1026 -n 20 -b 3.,3. -p 0.448266 7 | 8 | fitShapelet.py ../data/N6251_test.fits -r 1028,1097,1025,1074 -N 967,1067,972,1026 -n 8 -m polar -p 0.486636 -b 4.,4. --set_phi --set_xc 9 | fitShapelet.py ../data/N6251_test.fits -r 1028,1097,1025,1074 -N 967,1067,972,1026 -n 8 -p 0.486636 -b 4.,4. --set_phi --set_xc 10 | 11 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | #from Cython.Build import cythonize 3 | import numpy as np 4 | import os, sys, glob 5 | 6 | __version__ = '0.2' #this needs to be kept up to date with shapelets/__init__.py 7 | 8 | setup(name = 'shapelets', 9 | version = __version__, 10 | description = 'Shapelet fitting and plotting', 11 | long_description = 'Shapelet fitting and plotting', 12 | author = 'Griffin Foster', 13 | author_email = 'griffin.foster@gmail.com', 14 | url = 'https://github.com/griffinfoster/shapelets', 15 | platforms = ['*nix'], 16 | license='GPL', 17 | requires = ['distutils', 'numpy', 'astropy', 'scipy', 'matplotlib', 'json'], 18 | provides = ['shapelets', 'shapelets.phs'], 19 | packages = ['shapelets', 'shapelets.phs'], 20 | #ext_modules = cythonize('shapelets/cshapelet.pyx', annotate=True), 21 | include_dirs = [np.get_include()], 22 | #scripts = glob.glob('scripts/*.py'), 23 | scripts = ['scripts/fitShapelet.py', 'scripts/insertShapelet.py', 'scripts/plotCoeffs.py', 'scripts/plotImg.py', 'scripts/plotShapelets.py', 'scripts/solveShapelet.py'], 24 | classifiers = [ 25 | 'Development Status :: 4 - Beta', 26 | 'Environment :: Console', 27 | 'Natural Language :: English', 28 | 'Operating System :: POSIX :: Linux', 29 | 'Programming Language :: Python :: 2.7', 30 | 'Intended Audience :: Science/Research', 31 | 'License :: OSI Approved :: GNU General Public License (GPL)', 32 | 'Topic :: Scientific/Engineering :: Astronomy', 33 | ], 34 | ) 35 | 36 | -------------------------------------------------------------------------------- /shapelets/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | A module interface to shapelet functions 3 | """ 4 | 5 | __version__ = '0.2' #this needs to be kept up to date with setup.py 6 | 7 | import decomp, fileio, img, measure, shapelet 8 | 9 | -------------------------------------------------------------------------------- /shapelets/conv.py: -------------------------------------------------------------------------------- 1 | """ 2 | Functions for shapelet-based convolution 3 | """ 4 | 5 | import sys 6 | import numpy as np 7 | from scipy.misc import factorial 8 | 9 | #TODO: polar version 10 | def psfMatrix(gl,gamma,alpha,beta,lmax,mmax,nmax,mode='hermite'): 11 | """Compute the PSF matrix as defined in Refregier and Bacon 2003 Section 3.2 12 | g: shapelet coefficents of the PSF 13 | gamma, alpha, beta: scale factors (float) 14 | nmax: number of coefficients used to represent the convolved image, 2 element list, if 1 element/integer assume it is square 15 | mmax: number of coefficients used to represent the unconvolved image, 2 element list, if 1 element/integer assume it is square 16 | lmax: number of coefficients used to represent the PSF, 2 element list, if 1 element/integer assume it is square 17 | mode: hermite or laguerre 18 | """ 19 | if mode.startswith('herm'): 20 | if type(nmax)==int: nmax=[nmax,nmax] 21 | if type(mmax)==int: nmax=[mmax,mmax] 22 | if type(lmax)==int: nmax=[lmax,lmax] 23 | C=generate2dClmnTensor(gamma,alpha,beta,lmax,mmax,nmax) #compute convolution tensor [Refregier and Bacon 2003 eq. 6-11] 24 | return np.reshape( np.tensordot(C,gl,axes=[[0,1],[0,1]]), (C.shape[2]*C.shape[3], C.shape[4]*C.shape[5]) ) #return convolution tensor x g [Refregier and Bacon 2003 section 3.2] 25 | 26 | def generateLlmnTensor(a,b,c,lmax,mmax,nmax): 27 | """Generate the recursive relation L tensor [Refregier and Bacon 2003 eq. 11] 28 | a,b,c: scale factors (float) 29 | lmax,mmax,nmax: maximum values for l,m,n (integer) 30 | """ 31 | 32 | L=np.zeros((lmax+1,mmax+1,nmax+1)) 33 | #base cases l+m+n=0 34 | L[0,0,0]=1 35 | #base cases l+m+n=2 36 | L[0,1,1]=2.*b*c 37 | L[1,0,1]=2.*a*c 38 | L[1,1,0]=2.*a*b 39 | L[0,0,2]=-2.+2.*(c**2.) 40 | L[0,2,0]=-2.+2.*(b**2.) 41 | L[2,0,0]=-2.+2.*(a**2.) 42 | 43 | for n in np.arange(nmax): 44 | for m in np.arange(mmax): 45 | for l in np.arange(lmax): 46 | if l+m+n>2: 47 | L[l+1,m,n]=2.*l*((a**2.)-1.)*L[l-1,m,n] + 2.*m*a*b*L[l,m-1,n] + 2.*n*a*c*L[l,m,n-1] 48 | L[l,m+1,n]=2.*l*a*b*L[l-1,m,n] + 2.*m*((b**2.)-1.)*L[l,m-1,n] + 2.*n*b*c*L[l,m,n-1] 49 | L[l,m,n+1]=2.*l*a*c*L[l-1,m,n] + 2.*m*b*c*L[l,m-1,n] + 2.*n*((c**2.)-1.)*L[l,m,n-1] 50 | return L[:lmax,:mmax,:nmax] 51 | 52 | def generateBlmnTensor(a,b,c,lmax,mmax,nmax): 53 | """Generate the B tensor [Refregier and Bacon 2003 eq. 9] 54 | a,b,c: scale factors (float) 55 | lmax,mmax,nmax: maximum values for l,m,n (integer) 56 | """ 57 | nu=(a**(-2.)+b**(-2.)+c**(-2.))**(-0.5) 58 | L=generateLlmnTensor(np.sqrt(2.)*nu/a,np.sqrt(2.)*nu/b,np.sqrt(2.)*nu/c,lmax,mmax,nmax) 59 | 60 | lidx, midx, nidx = np.indices((lmax,mmax,nmax)) 61 | B=nu*(((2.**(lidx+midx+nidx-1.))*np.sqrt(np.pi)*factorial(midx)*factorial(nidx)*factorial(lidx)*a*b*c)**(-0.5))*L 62 | 63 | ##slower for loop 64 | #B=np.zeros((lmax,mmax,nmax)) 65 | #for n in np.arange(nmax): 66 | # for m in np.arange(mmax): 67 | # for l in np.arange(lmax): 68 | # B[l,m,n]=nu*(((2.**(l+m+n-1.))*np.sqrt(np.pi)*factorial(m)*factorial(n)*factorial(l)*a*b*c)**(-0.5))*L[l,m,n] 69 | return B 70 | 71 | def generate1dClmnTensor(a,b,c,lmax,mmax,nmax): 72 | """Generate the 1-dimensional C tensor [Refregier and Bacon 2003 eq. 7] 73 | a,b,c: scale factors (float) 74 | lmax,mmax,nmax: maximum values for l,m,n (integer) 75 | """ 76 | B=generateBlmnTensor(1./a, 1./b, 1./c, lmax,mmax,nmax) 77 | 78 | lidx, midx, nidx = np.indices((lmax,mmax,nmax)) 79 | C=np.sqrt(2.*np.pi)*((-1.)**nidx)*((1j)**(nidx+midx+lidx))*B 80 | 81 | ##slower for loop 82 | #C=np.zeros((lmax,mmax,nmax), dtype=np.complex) 83 | #for n in np.arange(nmax): 84 | # for m in np.arange(mmax): 85 | # for l in np.arange(lmax): 86 | # C[l,m,n]=np.sqrt(2.*np.pi)*((-1.)**n)*((1j)**(n+m+l))*B[l,m,n] 87 | return C 88 | 89 | def generate2dClmnTensor(a,b,c,lmax,mmax,nmax): 90 | """Generate the 2-dimensional C tensor [Refregier and Bacon 2003 eq. 6] 91 | a,b,c: scale factors (float) 92 | lmax,mmax,nmax: maximum values for l,m,n (2 element integer lists) 93 | """ 94 | C1=generate1dClmnTensor(a,b,c,lmax[0],mmax[0],nmax[0]) 95 | C2=generate1dClmnTensor(a,b,c,lmax[1],mmax[1],nmax[1]) 96 | C=np.kron(C1,C2) 97 | return np.reshape(C,(lmax[0],lmax[1],mmax[0],mmax[1],nmax[0],nmax[1])) 98 | 99 | def directInversion(hn,P,mmax): 100 | """Direct inversion method [Refregier and Bacon 2003 eq. 13] 101 | hn: convolved shapelet coefficients 102 | P: PSF matrix 103 | mmax: shape of unconvolved shapelet coefficients 104 | """ 105 | Pinv=np.linalg.pinv(P) 106 | fm=np.reshape(np.dot(Pinv.T,np.ravel(hn)), mmax) 107 | return fm 108 | 109 | if __name__ == "__main__": 110 | 111 | print '============================================' 112 | print 'Testing convolution module:' 113 | print '============================================' 114 | tc=0 115 | te=0 116 | 117 | #generateLlmnTensor(): 118 | tc+=1 119 | try: 120 | L=generateLlmnTensor(1.5,2.5,3.5,6,7,8) 121 | print L.shape 122 | except: 123 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 124 | te+=1 125 | 126 | #generateBlmnTensor(): 127 | tc+=1 128 | try: 129 | B=generateBlmnTensor(1.5,2.5,3.5,6,7,8) 130 | print B.shape 131 | except: 132 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 133 | te+=1 134 | 135 | #generate1dClmnTensor(): 136 | tc+=1 137 | try: 138 | C1=generate1dClmnTensor(1.5,2.5,3.5,6,7,8) 139 | print C1.shape 140 | C2=generate1dClmnTensor(1.5,2.5,3.5,5,4,9) 141 | print C2.shape 142 | except: 143 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 144 | te+=1 145 | 146 | #generate2dClmnTensor(): 147 | tc+=1 148 | try: 149 | C=generate2dClmnTensor(1.5,2.5,3.5,[6,5],[7,4],[8,9]) 150 | print C.shape 151 | except: 152 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 153 | te+=1 154 | 155 | #psfMatrix() 156 | try: 157 | gl=np.random.rand(6,5) 158 | P=psfMatrix(gl,1.5,2.5,3.5,[6,5],[7,4],[8,9],mode='hermite') 159 | print P.shape 160 | except: 161 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 162 | te+=1 163 | 164 | #directInversion(hn,P,mmax) 165 | try: 166 | hn=np.random.rand(8,9) 167 | fm=directInversion(hn,P,(7,4)) 168 | print fm.shape 169 | except: 170 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 171 | te+=1 172 | 173 | print '============================================' 174 | print '%i of %i tests succeeded'%(tc-te,tc) 175 | print '============================================' 176 | 177 | -------------------------------------------------------------------------------- /shapelets/cshapelet.pyx: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | #cython: profile=True 3 | #cython: boundscheck=False 4 | #cython: wraparound=False 5 | #cython: cdivision=True 6 | 7 | import numpy as np 8 | cimport numpy as np 9 | from scipy.special import eval_genlaguerre 10 | from scipy.misc import factorial 11 | 12 | cimport cython 13 | from cython.parallel import parallel, prange 14 | from libc.math cimport exp, cos, sin, abs 15 | import numexpr as ne 16 | 17 | from fshapelet import polar_basis_L 18 | 19 | PI = np.pi 20 | 21 | cdef extern from "complex.h": 22 | double complex cexp(double complex z) nogil 23 | 24 | null_char_array = np.array([[0]], dtype='uint8') 25 | 26 | cpdef polar_basis_Y0(double [:,::1] th, double phs=1., 27 | char [:,::1] mask=null_char_array): 28 | """ 29 | Basically complex exp computations taking into account a mask 30 | """ 31 | cdef int k, l 32 | cdef int N0,N1 33 | cdef char use_mask= mask.size > 1 34 | N0, N1 = th.shape[0], th.shape[1] 35 | 36 | cdef double complex [:,::1] vect=np.empty((N0, N1), dtype='complex128')*np.nan 37 | for k in range(N0): 38 | for l in range(N1): 39 | if use_mask: 40 | if mask[k,l]==0: 41 | continue 42 | vect[k,l] = cexp(-1j*th[k,l]) 43 | 44 | return vect.base 45 | 46 | 47 | cpdef genPolarBasisMatrix(double beta, int nmax,r,th, mask=None): 48 | """Generate the n x k matrix of basis functions(k) for each pixel(n) 49 | beta: characteristic size of the shaeplets 50 | nmax: maximum decomposition order 51 | r: radius matrix of n pixels 52 | th: theta matrix of n pixels 53 | """ 54 | cdef int nn, mm, N0, N1, pos 55 | if mask is None: 56 | mask = null_char_array 57 | # Precompute the values for angular basis 58 | # as the complex exp computations are rather costly 59 | # now Y_{m=-1} can be accessed as Y[-1] or Y[(2*nmax-1) -1] 60 | Y0 = polar_basis_Y0(th, mask=mask) 61 | N0, N1 = Y0.shape[0], Y0.shape[1] 62 | Y_vec = [] 63 | for mm in range(nmax) + range(-1*nmax+1, 0): 64 | Y_vec.append(Y0**mm) 65 | 66 | bvals=np.empty((N0*N1, pvect_len(nmax)), dtype='complex128') 67 | L_vec_tmp = [0]*nmax # initializing an empty list 68 | 69 | pos = 0 70 | for nn in range(nmax): 71 | for mm in range(-1*nn,nn+1): 72 | if (nn%2==0 and abs(mm)%2==0) or (nn%2==1 and abs(mm)%2==1): 73 | Ym = wrap_idx(Y_vec, mm) 74 | # Using the fact that L_{n,-m} = L_{n, m} 75 | if mm <= 0: 76 | Lnm = polar_basis_L(r,nn,mm, beta=beta) 77 | L_vec_tmp[abs(mm)] = Lnm 78 | else: 79 | Lnm = L_vec_tmp[mm] 80 | bvals[:,pos] = (Ym*Lnm).flatten() 81 | pos += 1 82 | 83 | return bvals 84 | 85 | cdef wrap_idx(vect, int idx): 86 | # this part reproduces negative indexing 87 | if idx < 0: 88 | idx = len(vect) + idx 89 | return vect[idx] 90 | 91 | 92 | cdef int pvect_len(int nmax): 93 | return nmax*(nmax+1)/2 94 | -------------------------------------------------------------------------------- /shapelets/decomp.py: -------------------------------------------------------------------------------- 1 | """ 2 | Functions for decomposing an image into basis functions using a Least Squares Estimator(LSE) 3 | 4 | Implementation of "Statistics in Theory and Practice", Lupton, Ch. 11 5 | """ 6 | 7 | import numpy as np 8 | import shapelet,img 9 | from scipy import optimize 10 | from scipy import stats 11 | 12 | def ellipticalGaussian2D(x0=0.,y0=0.,sigmax=1.,sigmay=1.,phi=0.,amp=1.,offset=0.): 13 | """A generalized 2D ellipitical Gaussian function with centre (x0,y0), width (sigmax,sigmay), amplitude amp, offset, and rotation angle phi (radians) 14 | """ 15 | aa=((np.cos(phi))**2.)/(2.*(sigmax**2.)) + ((np.sin(phi))**2.)/(2.*(sigmay**2.)) 16 | bb=(-1.*np.sin(2.*phi))/(4.*(sigmax**2.)) + (np.sin(2.*phi))/(4.*(sigmay**2.)) 17 | cc=((np.sin(phi))**2.)/(2.*(sigmax**2.)) + ((np.cos(phi))**2.)/(2.*(sigmay**2.)) 18 | return lambda x,y: amp * np.exp( -1.*( aa*((x-x0)**2.) - 2.*bb*(x-x0)*(y-y0) + cc*((y-y0)**2.) ) ) + offset 19 | 20 | def initGaussian(im): 21 | """Returns (y0, x0, sigmay, sigmax, phi, amp, offset) 22 | the gaussian parameters of a 2D distribution by calculating its 23 | moments 24 | borrowed from: http://wiki.scipy.org/Cookbook/FittingData""" 25 | #total = im.sum() 26 | #X, Y = np.indices(im.shape) 27 | #y = (Y*im).sum()/total 28 | #x = (X*im).sum()/total 29 | y0, x0 = img.maxPos(im) 30 | col = im[:, int(y0)] 31 | sigmax = np.sqrt(abs((np.arange(col.size)-y0)**2*col).sum()/np.abs(col).sum()) 32 | row = im[int(x0), :] 33 | sigmay = np.sqrt(abs((np.arange(row.size)-x0)**2*row).sum()/np.abs(row).sum()) 34 | offset = np.median(im) 35 | amp = im.max() - offset 36 | phi = 0. # no rotation 37 | return float(x0), float(y0), sigmax, sigmay, phi, amp, offset 38 | 39 | def initParams(im, mode='basic', frac=.2, hdr=None): 40 | """Initial guess for beta, phi, nmax 41 | mode: 42 | basic: beta is determined based on the size of the image and the frac arguement, phi is 0 43 | fit: a 2D Gaussian is fit to the image, parameters derived from fit, does not work well for non-Gaussian sources 44 | Theta_max = fit Gaussian width 45 | Theta_min = PSF FWHM 46 | beta ~ sqrt((Theta_max * Theta_min)) 47 | phi ~ fit Gaussian rotation angle 48 | nmax ~ (Theta_max / Theta_min) + 1 49 | moments: using image moments, works better for non-Gaussian sources 50 | Theta_max = initial Gaussian width 51 | beta ~ sqrt(Theta_max) 52 | phi = derived from second order image moments 53 | name ~ number of pixels in image 54 | frac: fraction of image to use as the initial beta (basic) 55 | hdr: FITS header dictionary with PSF size (fit) 56 | gaussian fitting borrowed from: http://wiki.scipy.org/Cookbook/FittingData 57 | returns: beta, phi, nmax 58 | """ 59 | if mode.startswith('basic'): 60 | return [frac*im.shape[0], frac*im.shape[1]], 0., [int((frac * im.shape[0])-1), int((frac * im.shape[1])-1)] 61 | elif mode.startswith('fit'): 62 | #fit a 2D Gaussian to the image 63 | params = initGaussian(im) 64 | errorfunction = lambda p: np.ravel(ellipticalGaussian2D(*p)(*np.indices(im.shape)) - im) 65 | p0, success = optimize.leastsq(errorfunction, params) 66 | print params 67 | print p0 68 | Theta_max = np.abs(2.3548*np.array([p0[2],p0[3]])) #FWHM, the fitter can return negative values of sigma 69 | 70 | #compute PSF size in pixels 71 | bpa = np.pi * hdr['bpa']/180. 72 | bmaj = np.pi * hdr['bmaj']/180. 73 | bmin = np.pi * hdr['bmin']/180. 74 | dra = np.pi * hdr['dra']/180. 75 | ddec = np.pi * hdr['ddec']/180. 76 | rotM = np.matrix( [[np.cos(bpa), -1.*np.sin(bpa)], [np.sin(bpa), np.cos(bpa)]] ) 77 | 78 | temp0 = np.dot(rotM, np.array([(np.pi/180.) * hdr['dra'], 0.])) 79 | temp1 = np.dot(rotM, np.array([0., (np.pi/180.) * hdr['ddec']])) 80 | rotDeltas = np.array([np.sqrt(temp0[0,0]**2. + temp0[0,1]**2.), np.sqrt(temp1[0,0]**2. + temp1[0,1]**2.)]) 81 | psfPix = (np.array([bmaj, bmin])/rotDeltas) / 2.3548 #go from FWHM to sigma, it is better to error on the side of higher order structure, then to miss it 82 | Theta_min = np.abs(np.array(psfPix).flatten()) 83 | 84 | beta = np.sqrt(Theta_max * Theta_min) 85 | phi = -1. * p0[4] 86 | nmax = [int((Theta_max[0] / Theta_min[0]) + 1),int((Theta_max[1] / Theta_min[1]) + 1)] 87 | return beta, phi, nmax 88 | elif mode.startswith('moments'): 89 | params = initGaussian(im) 90 | # calculate phi by using the second order image moments - https://en.wikipedia.org/wiki/Image_moment 91 | import skimage.measure 92 | moments = skimage.measure.moments(np.array(im, dtype='float64'), order=3) 93 | cr = moments[0, 1] / moments[0, 0] 94 | cc = moments[1, 0] / moments[0, 0] 95 | cmoments = skimage.measure.moments_central(np.array(im, dtype='float64'), cr, cc) 96 | phi = 0.5 * np.arctan2( 2. * cmoments[1, 1] / cmoments[0, 0], (cmoments[2, 0] / cmoments[0, 0]) - (cmoments[0, 2] / cmoments[0, 0]) ) 97 | 98 | Theta_max = np.abs(2.3548 * np.array([params[2], params[3]])) #FWHM, the fitter can return negative values of sigma 99 | beta = np.sqrt(Theta_max) 100 | 101 | return beta, phi, [int((frac * im.shape[0])-1), int((frac * im.shape[1])-1)] 102 | 103 | def initBetaPhi(im,mode='basic',frac=.2,circular=False): 104 | """Depreciated: use initParams 105 | Initial starting point for beta and phi 106 | mode: 107 | basic: beta is determined based on the size of the image and the frac arguement, phi is 0 108 | fit: a 2D Gaussian is fit to the image, parameters derived from fit 109 | frac: fraction of image to use as the initial beta (basic) 110 | circular: if True, return a circular fit parameter using the smallest width 111 | fitting borrowed from: http://wiki.scipy.org/Cookbook/FittingData 112 | """ 113 | if mode.startswith('basic'): 114 | return [frac*im.shape[0],frac*im.shape[1]], 0. 115 | elif mode.startswith('fit'): 116 | params=initGaussian(im) 117 | errorfunction = lambda p: np.ravel(ellipticalGaussian2D(*p)(*np.indices(im.shape)) - im) 118 | p, success = optimize.leastsq(errorfunction, params) 119 | if circular: 120 | width=np.min([p[2],p[3]]) 121 | return [width,width],p[4] 122 | else: return [p[2],p[3]],p[4] 123 | 124 | def genPolarBasisFuncs(beta,nmax,phi,fourier=False): 125 | """Generate a list of basis functions 126 | beta: characteristic size of the shapelets (b_major, b_minor) 127 | nmax: maximum decomposition order 128 | phi: rotation angle 129 | fourier: return a FOurer transformed version of the basis functions 130 | """ 131 | bfs=[] 132 | if type(nmax) is int: nmax=[nmax,nmax] 133 | for nn in range(nmax[0]): 134 | for mm in np.arange(-1*nn,nn+1): 135 | if (nn%2==0 and mm%2==0) or (nn%2==1 and mm%2==1): 136 | bfs.append(shapelet.polarDimBasis(nn,mm,beta=beta,phi=phi,fourier=fourier)) 137 | return bfs 138 | 139 | def genPolarBasisMatrix(beta,nmax,phi,r,th,fourier=False): 140 | """Generate the n x k matrix of basis functions(k) for each pixel(n) 141 | beta: characteristic size of the shapelets (b_major, b_minor) 142 | nmax: maximum decomposition order 143 | phi: rotation angle 144 | r: radius matrix of n pixels 145 | th: theta matrix of n pixels 146 | fourier: return a FOurer transformed version of the basis functions 147 | """ 148 | bvals=[] 149 | if type(nmax) is int: nmax=[nmax,nmax] 150 | for nn in range(nmax[0]): 151 | for mm in np.arange(-1*nn,nn+1): 152 | if (nn%2==0 and mm%2==0) or (nn%2==1 and mm%2==1): 153 | bf=shapelet.polarDimBasis(nn,mm,beta=beta,phi=phi,fourier=fourier) 154 | bvals.append(shapelet.computeBasisPolar(bf,r,th).flatten()) 155 | bm=np.array(bvals) 156 | return bm.transpose() 157 | 158 | def genBasisFuncs(beta,nmax,phi,fourier=False): 159 | """Generate a list of basis functions 160 | beta: characteristic size of the shapelets (b_major, b_minor) 161 | nmax: maximum decomposition order 162 | phi: rotation angle 163 | fourier: return a FOurer transformed version of the basis functions 164 | """ 165 | bfs=[] 166 | if type(nmax) is int: nmax=[nmax,nmax] 167 | for ny in range(nmax[0]): 168 | for nx in range(nmax[1]): 169 | bfs.append(shapelet.dimBasis2d(ny,nx,beta=beta,phi=phi,fourier=fourier)) 170 | return bfs 171 | 172 | def genBasisMatrix(beta,nmax,phi,yy,xx,fourier=False): 173 | """Generate the n x k matrix of basis functions(k) for each pixel(n) 174 | nmax: maximum decompisition order 175 | beta: characteristic size of the shapelet 176 | phi: rotation angle 177 | yy: y values to evaluate basis functions 178 | xx: x values to evaluate basis functions 179 | fourier: return a FOurer transformed version of the basis functions 180 | """ 181 | bvals=[] 182 | if type(nmax) is int: nmax=[nmax,nmax] 183 | for ny in range(nmax[0]): 184 | for nx in range(nmax[1]): 185 | bf=shapelet.dimBasis2d(ny,nx,beta=beta,phi=phi,fourier=fourier) 186 | bvals.append(shapelet.computeBasis2d(bf,yy,xx).flatten()) 187 | bm=np.array(bvals) 188 | return bm.transpose() 189 | 190 | def solveCoeffs(m,im): 191 | """Solve for the basis function coefficients Theta^ using a Least Squares Esimation (Lupton pg. 84) 192 | theta^ = (m^T * m)^-1 * im 193 | n: number of pixels in the image 194 | k: number of basis functions (in all dimensions) 195 | m: n x k matrix of the basis functions for each pixel 196 | im: image of size n pixels 197 | returns theta_hat, a size k array of basis function coefficents""" 198 | #im_flat=np.reshape(im,im.shape[0]*im.shape[1],1) 199 | im_flat=im.flatten() 200 | mTm=np.dot(m.T,m) #matrix multiply m with it's transpose 201 | mTm_inv=np.linalg.inv(mTm) #invert the k x k matrix 202 | mTm_inv_mT=np.dot(mTm_inv,m.T) #matrix multiply the result with the transpose of m 203 | theta_hat=np.dot(mTm_inv_mT,im_flat) #compute the coefficents for the basis functions 204 | return theta_hat 205 | 206 | def chi2PolarFunc(params,nmax,im,nm,order=['beta0','beta1','phi','yc','xc'],set_beta=[None,None],set_phi=None,set_xc=[None,None],r=None,th=None): 207 | """Function which is to be minimized in the chi^2 analysis for Polar shapelets 208 | params = [beta0, beta1, phi, xc, yc] or some subset 209 | beta0: characteristic size of shapelets, fit parameter 210 | beta1: characteristic size of shapelets, fit parameter 211 | phi: rotation angle of shapelets, fit parameter 212 | yc: y centroid of shapelets, fit parameter 213 | xc: x centroid of shapelets, fit parameter 214 | nmax: number of coefficents to use in the Laguerre polynomials 215 | im: observed image 216 | nm: noise map 217 | order: order of parameters 218 | fixed parameters: set_beta, set_phi, set_xc 219 | r: radius from centroid, array of im.shape, not required if xc and yc being fit 220 | th: angle from centroid, array of im.shape, not required if xc and yc being fit 221 | """ 222 | #determine which parameters are being fit for, and which are not 223 | beta0=set_beta[0] 224 | beta1=set_beta[1] 225 | phi=set_phi 226 | yc=set_xc[0] 227 | xc=set_xc[1] 228 | fitParams={'beta':False,'phi':False,'xc':False} 229 | for pid,paramName in enumerate(order): 230 | if paramName=='beta0': 231 | beta0=params[pid] 232 | fitParams['beta']=True 233 | elif paramName=='beta1': 234 | beta1=params[pid] 235 | fitParams['beta']=True 236 | elif paramName=='phi': 237 | phi=params[pid] 238 | fitParams['phi']=True 239 | elif paramName=='xc': 240 | xc=params[pid] 241 | fitParams['xc']=True 242 | elif paramName=='yc': 243 | yc=params[pid] 244 | fitParams['xc']=True 245 | 246 | #if beta0<0.: 247 | # print 'warning: beta going negative, setting to 0.0' 248 | # beta0=0. 249 | #if beta1<0.: 250 | # print 'warning: beta going negative, setting to 0.0' 251 | # beta1=0. 252 | if beta0<0.: 253 | print 'warning: beta going negative, taking absolute value' 254 | beta0 = np.abs(beta0) 255 | if beta1<0.: 256 | print 'warning: beta going negative, taking absolute value' 257 | beta1 = np.abs(beta1) 258 | print 'beta: (%f,%f)\t phi: %f\txc: (%f,%f)'%(beta0,beta1,phi,xc,yc) 259 | 260 | #update noise map 261 | nm=img.makeNoiseMap(nm.shape,np.mean(nm),np.std(nm)) 262 | 263 | size=im.shape 264 | if fitParams['xc'] or r is None: 265 | r,th=shapelet.polarArray([yc,xc],size) #the radius,theta pairs need to updated if fitting for the xc centre or if not using the r,th inputs 266 | bvals=genPolarBasisMatrix([beta0,beta1],nmax,phi,r,th) 267 | coeffs=solveCoeffs(bvals,im) 268 | mdl=np.abs(img.constructModel(bvals,coeffs,size)) 269 | return np.sum((im-mdl)**2 / nm**2)/(size[0]*size[1]) 270 | 271 | def chi2nmaxPolarFunc(params,im,nm,beta0,beta1,phi,xc): 272 | """ 273 | params = [nmax] 274 | nmax: number of coefficents 275 | im: observed image 276 | nm: noise map 277 | beta0: fit beta value 278 | beta1: fit beta value 279 | phi: rotation angle 280 | xc: fit centroid position 281 | """ 282 | #nmax=params[0] 283 | nmax=[params, params] 284 | size=im.shape 285 | r,th=shapelet.polarArray(xc,size) 286 | bvals=genPolarBasisMatrix([beta0,beta1],nmax,phi,r,th) 287 | coeffs=solveCoeffs(bvals,im) 288 | mdl=np.abs(img.constructModel(bvals,coeffs,size)) 289 | return np.sum((im-mdl)**2 / nm**2)/(size[0]*size[1]) 290 | 291 | def chi2Func(params,nmax,im,nm,order=['beta0','beta1','phi','yc','xc'],set_beta=[None,None],set_phi=None,set_xc=[None,None],xx=None,yy=None): 292 | """Function which is to be minimized in the chi^2 analysis for Cartesian shapelets 293 | params = [beta0, beta1, phi, xc, yc] or some subset 294 | beta0: characteristic size of shapelets, fit parameter 295 | beta1: characteristic size of shapelets, fit parameter 296 | phi: rotation angle of shapelets, fit parameter 297 | yc: y centroid of shapelets, fit parameter 298 | xc: x centroid of shapelets, fit parameter 299 | nmax: number of coefficents to use in the Hermite polynomials 300 | im: observed image 301 | nm: noise map 302 | order: order of parameters 303 | fixed parameters: set_beta, set_phi, set_xc 304 | xx: X position grid, array of im.shape, not required if xc and yc being fit 305 | yy: Y position grid, array of im.shape, not required if xc and yc being fit 306 | """ 307 | #determine which parameters are being fit for, and which are not 308 | betaY=set_beta[0] 309 | betaX=set_beta[1] 310 | phi=set_phi 311 | yc=set_xc[0] 312 | xc=set_xc[1] 313 | fitParams={'beta':False,'phi':False,'xc':False} 314 | for pid,paramName in enumerate(order): 315 | if paramName=='beta0': 316 | betaY=params[pid] 317 | fitParams['beta']=True 318 | elif paramName=='beta1': 319 | betaX=params[pid] 320 | fitParams['beta']=True 321 | elif paramName=='phi': 322 | phi=params[pid] 323 | fitParams['phi']=True 324 | elif paramName=='xc': 325 | xc=params[pid] 326 | fitParams['xc']=True 327 | elif paramName=='yc': 328 | yc=params[pid] 329 | fitParams['xc']=True 330 | 331 | #if betaX<0.: 332 | # print 'warning: beta going negative, setting to 0.0' 333 | # betaX=0. 334 | #if betaY<0.: 335 | # print 'warning: beta going negative, setting to 0.0' 336 | # betaY=0. 337 | if betaX<0.: 338 | print 'warning: beta going negative, taking absolute value' 339 | betaX = np.abs(betaY) 340 | if betaY<0.: 341 | print 'warning: beta going negative, taking absolute value' 342 | betaY = np.abs(betaX) 343 | print 'beta: (%f,%f)\t phi: %f\txc: (%f,%f)'%(betaX,betaY,phi,xc,yc) 344 | 345 | #update noise map 346 | nm=img.makeNoiseMap(nm.shape,np.mean(nm),np.std(nm)) 347 | 348 | size=im.shape 349 | if fitParams['xc'] or xx is None: 350 | #shift the (0,0) point to the centroid 351 | ry=np.array(range(0,size[0]),dtype=float)-yc 352 | rx=np.array(range(0,size[1]),dtype=float)-xc 353 | yy,xx=shapelet.xy2Grid(ry,rx) 354 | bvals=genBasisMatrix([betaY,betaX],nmax,phi,yy,xx) 355 | coeffs=solveCoeffs(bvals,im) 356 | mdl=img.constructModel(bvals,coeffs,size) 357 | return np.sum((im-mdl)**2 / nm**2)/(size[0]*size[1]) 358 | 359 | def chi2nmaxFunc(params,im,nm,betaY,betaX,phi,xc): 360 | """ 361 | params = [nmaxX,nmaxY] 362 | nmax: number of coefficents to use in x,y 363 | im: observed image 364 | nm: noise map 365 | betaY: characteristic size of shapelet 366 | betaX: characteristic size of shapelet 367 | phi: rotation angle of shapelets 368 | xc: fit centroid position 369 | """ 370 | nmax=params 371 | size=im.shape 372 | #shift the (0,0) point to the centroid 373 | ry=np.array(range(0,size[0]),dtype=float)-xc[0] 374 | rx=np.array(range(0,size[1]),dtype=float)-xc[1] 375 | yy,xx=shapelet.xy2Grid(ry,rx) 376 | 377 | bvals=genBasisMatrix([betaY,betaX],[nmax,nmax],phi,yy,xx) 378 | coeffs=solveCoeffs(bvals,im) 379 | mdl=img.constructModel(bvals,coeffs,size) 380 | return np.sum((im-mdl)**2 / nm**2)/(size[0]*size[1]) 381 | 382 | if __name__ == "__main__": 383 | 384 | print '============================================' 385 | print 'Testing decomp module:' 386 | print '============================================' 387 | import fileio 388 | import sys 389 | write_files = False #Flag to write coeff files 390 | tc=0 391 | te=0 392 | 393 | im,hdr=fileio.readFITS('../data/N6251_test.fits',hdr=True) 394 | subim=img.selPxRange(im,[1028,1097,1025,1074]) 395 | 396 | #guess beta 397 | #initBeta(im): 398 | tc+=1 399 | try: 400 | beta0,phi0=initBetaPhi(subim,mode='basic') 401 | print beta0, phi0 402 | beta0,phi0=initBetaPhi(subim,mode='fit') 403 | print beta0, phi0 404 | except: 405 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 406 | te+=1 407 | 408 | #genPolarBasisMatrix(beta,nmax,r,th): 409 | #solveCoeffs(m,im): 410 | tc+=1 411 | try: 412 | beta0,phi0=initBetaPhi(subim,mode='fit') 413 | xc=img.maxPos(subim) 414 | r0,th0=shapelet.polarArray(xc,subim.shape) 415 | mPolar=genPolarBasisMatrix(beta0,5,0.,r0,th0) 416 | coeffs=solveCoeffs(mPolar,subim) 417 | print coeffs 418 | if write_files: fileio.writeLageurreCoeffs('testLageurre.pkl',coeffs,xc,subim.shape,beta0,0.,[5,5],pos=[hdr['ra'],hdr['dec'],hdr['dra'],hdr['ddec']],info='Test Lageurre coeff file') 419 | except: 420 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 421 | te+=1 422 | 423 | #genBasisMatrix(beta,nmax,rx,ry): 424 | #solveCoeffs(m,im): 425 | tc+=1 426 | try: 427 | beta0,phi0=initBetaPhi(subim,mode='fit') 428 | xc=img.maxPos(subim) 429 | rx=np.array(range(0,subim.shape[0]),dtype=float)-xc[0] 430 | ry=np.array(range(0,subim.shape[1]),dtype=float)-xc[1] 431 | xx,yy=shapelet.xy2Grid(rx,ry) 432 | mCart=genBasisMatrix(beta0,[5,5],phi0,xx,yy) 433 | coeffs=solveCoeffs(mCart,subim) 434 | print coeffs 435 | if write_files: fileio.writeHermiteCoeffs('testHermite.pkl',coeffs,xc,subim.shape,beta0,0.,5,pos=[hdr['ra'],hdr['dec'],hdr['dra'],hdr['ddec']],info='Test Hermite coeff file') 436 | except: 437 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 438 | te+=1 439 | 440 | beta0,phi0=initBetaPhi(subim,mode='fit') 441 | xc=img.maxPos(subim) 442 | mean,std=img.estimateNoise(subim,mode='basic') 443 | nm=img.makeNoiseMap(subim.shape,mean,std) 444 | nmax=[10,10] 445 | 446 | #chi2PolarFunc(params,nmax,im,nm): 447 | tc+=1 448 | try: 449 | print chi2PolarFunc([beta0[0],beta0[1],phi0,xc[0],xc[1]],nmax,subim,nm,order=['beta0','beta1','phi','xc','yc']) #fit: all 450 | print chi2PolarFunc([beta0[0],beta0[1]],nmax,subim,nm,order=['beta0','beta1'],set_phi=phi0,set_xc=xc) #fit: beta 451 | print chi2PolarFunc([phi0],nmax,subim,nm,order=['phi'],set_beta=beta0,set_xc=xc) #fit: phi 452 | print chi2PolarFunc([xc[0],xc[1]],nmax,subim,nm,order=['xc','yc'],set_beta=beta0,set_phi=phi0) #fit: xc 453 | print chi2PolarFunc([beta0[0],beta0[1],phi0],nmax,subim,nm,order=['beta0','beta1','phi'],set_xc=xc) #fit: beta, phi 454 | print chi2PolarFunc([beta0[0],beta0[1],xc[0],xc[1]],nmax,subim,nm,order=['beta0','beta1','xc','yc'],set_phi=phi0) #fit: beta, xc 455 | print chi2PolarFunc([phi0,xc[0],xc[1]],nmax,subim,nm,order=['phi','xc','yc'],set_beta=beta0) #fit: phi, xc 456 | except: 457 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 458 | te+=1 459 | 460 | #chi2nmaxPolarFunc(params,im,nm,beta,xc): 461 | tc+=1 462 | try: 463 | print chi2nmaxPolarFunc(5,subim,nm,beta0[0],beta0[1],0.,xc) 464 | except: 465 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 466 | te+=1 467 | 468 | #chi2Func(params,nmax,im,nm): 469 | tc+=1 470 | try: 471 | print chi2Func([beta0[0],beta0[1],phi0,xc[0],xc[1]],nmax,subim,nm,order=['beta0','beta1','phi','xc','yc']) #fit: all 472 | print chi2Func([beta0[0],beta0[1]],nmax,subim,nm,order=['beta0','beta1'],set_phi=phi0,set_xc=xc) #fit: beta 473 | print chi2Func([phi0],nmax,subim,nm,order=['phi'],set_beta=beta0,set_xc=xc) #fit: phi 474 | print chi2Func([xc[0],xc[1]],nmax,subim,nm,order=['xc','yc'],set_beta=beta0,set_phi=phi0) #fit: xc 475 | print chi2Func([beta0[0],beta0[1],phi0],nmax,subim,nm,order=['beta0','beta1','phi'],set_xc=xc) #fit: beta, phi 476 | print chi2Func([beta0[0],beta0[1],xc[0],xc[1]],nmax,subim,nm,order=['beta0','beta1','xc','yc'],set_phi=phi0) #fit: beta, xc 477 | print chi2Func([phi0,xc[0],xc[1]],nmax,subim,nm,order=['phi','xc','yc'],set_beta=beta0) #fit: phi, xc 478 | except: 479 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 480 | te+=1 481 | 482 | #chi2nmaxFunc(params,im,nm,beta,xc): 483 | tc+=1 484 | try: 485 | print chi2nmaxFunc(5,subim,nm,beta0[0],beta0[1],0.,xc) 486 | except: 487 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 488 | te+=1 489 | 490 | print '============================================' 491 | print '%i of %i tests succeeded'%(tc-te,tc) 492 | print '============================================' 493 | 494 | -------------------------------------------------------------------------------- /shapelets/fileio.py: -------------------------------------------------------------------------------- 1 | """ 2 | Read various image filetypes: FITS,png,jpeg 3 | Write coeff file 4 | """ 5 | 6 | from astropy.io import fits 7 | import numpy as np 8 | import cPickle as pickle 9 | import sys 10 | import json 11 | import astropy.wcs 12 | 13 | #optional packages: 14 | try: 15 | from PIL import Image 16 | except ImportError: pass 17 | 18 | def readFITS(fn,hdr=False): 19 | """Read a FITS image file and returns a numpy array (only Stokes I or the first Stokes index) 20 | """ 21 | hdulist = fits.open(fn) 22 | im = hdulist[0].data 23 | hdulist.close() 24 | h = getFITSInfo(fn) 25 | if im.ndim==4: #image data format: [frequency, polarization, dec, ra] 26 | im = im[0,0] 27 | #orient the image to the same way it would look in a normal FITS viewer 28 | if h['dra'] > 0: im = np.fliplr(im) 29 | if h['ddec'] > 0: im = np.flipud(im) 30 | if hdr: return im, h 31 | else: return im 32 | 33 | def getFITSInfo(fn): 34 | """Parse the FITS header for pointing and pixel size information 35 | return [RA,DEC], pixel resolution, pixel of [RA,DEC] 36 | generates a WCS instance for converting between sky and pixels 37 | """ 38 | hdulist=fits.open(fn) 39 | hdr=hdulist[0].header 40 | #CTYPE1: RA---[PROJ], projection SIN/TAN/ARC 41 | #CRVAL1: reference RA position in degrees 42 | #CRPIX1: location of reference pixel 43 | #CDELT1: delta RA/pixel size in degrees 44 | #CTYPE2: DEC--[PROJ], projection SIN/TAN/ARC 45 | #CRVAL2: reference DEC position in degrees 46 | #CRPIX2: location of reference pixel 47 | #CDELT2: delta DEC/pixel size in degrees 48 | #BMAJ: major axis of PSF FWHM ellipse (degrees) 49 | #BMIN: minor axis of PSF FWHM ellipse (degrees) 50 | #BPA: rotation angle of PSF FWHM ellipse (degrees) 51 | ra=hdr['CRVAL1'] 52 | dra=hdr['CDELT1'] 53 | raPix=hdr['CRPIX1'] 54 | dec=hdr['CRVAL2'] 55 | ddec=hdr['CDELT2'] 56 | decPix=hdr['CRPIX2'] 57 | 58 | # Try to get the PSF FWHM from th header for an initial size scale 59 | if 'BMAJ' in hdr.keys(): 60 | bmaj = hdr['BMAJ'] 61 | bmin = hdr['BMIN'] 62 | bpa = hdr['BPA'] 63 | else: # BMAJ/BMIN/BPA is optional, if not in header, then replace with 3 * pixel resolution (usually the standard resolution in radio synthesis images) 64 | bmaj = 3. * np.abs(dra) 65 | bmin = 3. * np.abs(ddec) 66 | bpa = 0. 67 | 68 | #Generate a WCS structure, using the normal method creates errors due to header formating 69 | wcs = astropy.wcs.WCS(naxis=2) 70 | wcs.wcs.crval = [ra,dec] 71 | wcs.wcs.crpix = [raPix,decPix] 72 | wcs.wcs.cdelt = [dra,ddec] 73 | wcs.wcs.ctype = ["RA---SIN", "DEC--SIN"] 74 | 75 | hdulist.close() 76 | return {'ra':ra,'dec':dec,'dra':dra,'ddec':ddec,'raPix':raPix,'decPix':decPix, 'wcs':wcs, 'bmaj':bmaj, 'bmin':bmin, 'bpa':bpa} 77 | 78 | def readImg(fn,gs=False): 79 | """Read an image file using PIL libraries and return a numpy array 80 | valid types(tested other may work): png, jpeg 81 | gs: return a greyscale image 82 | """ 83 | im=Image.open(fn) 84 | if gs: im=im.convert("L") 85 | return np.asarray(im) 86 | 87 | def readArrayPkl(fn): 88 | """Read a pickle file, expected format is a NxM numpy array 89 | """ 90 | fh=open(fn,'rb') 91 | im=pickle.load(fh) 92 | fh.close() 93 | return im 94 | 95 | def writeHermiteCoeffs(fn,coeffs,xc,size,beta,phi,norder,pos=[0.,0.,0.,0.],mode='hermite',info='',fmt='pkl'): 96 | """Write hermite coeffs and meta data to a pickle file 97 | fn: output file name 98 | coeffs: set of coefficients for Hermite polynomials 99 | xc: center position 100 | size: size in pixels of image 101 | beta: characteristic beta values 102 | phi: rotation angle 103 | norder: order of polynomials 104 | mode: basis function mode 105 | pos: 4 element array of RA,DEC and scale size from FITS header (degrees) 106 | info: extra metadata space 107 | fmt: output formats supported: pkl (pickle), json 108 | """ 109 | if type(norder) is int: norder=[norder,norder] 110 | d={ 'coeffs':coeffs, 111 | 'mode':'hermite', 112 | 'xc':xc, 113 | 'size':size, 114 | 'beta':beta, 115 | 'phi':phi, 116 | 'norder':norder, 117 | 'ra':pos[0], 118 | 'dec':pos[1], 119 | 'dra':pos[2], 120 | 'ddec':pos[3], 121 | 'info': info } 122 | if fmt.startswith('pkl'): 123 | fh=open(fn,'wb') 124 | pickle.dump(d,fh) 125 | fh.close() 126 | elif fmt.startswith('json'): 127 | d['coeffs']=coeffs.tolist() 128 | fh=open(fn,'w') 129 | json.dump(d,fh,sort_keys=True) 130 | fh.close() 131 | else: 132 | print 'Unknown format, no file written' 133 | 134 | def readHermiteCoeffs(fn): 135 | """Read a binary coeff file and return a dictionary of values 136 | fn: filename to read 137 | """ 138 | if fn.endswith('.pkl'): 139 | fh=open(fn,'rb') 140 | d=pickle.load(fh) 141 | fh.close() 142 | return d 143 | elif fn.endswith('.json'): 144 | fh=open(fn,'r') 145 | d=json.load(fh) 146 | coeffs=np.array(d.pop('coeffs')) 147 | d['coeffs']=coeffs 148 | fh.close() 149 | return d 150 | else: 151 | print 'Unknown file type' 152 | return np.nan 153 | 154 | def writeLageurreCoeffs(fn,coeffs,xc,size,beta,phi,norder,pos=[0.,0.,0.,0.],mode='laguerre',info='',fmt='pkl'): 155 | """Write Lageurre coeffs and meta data to a pickle file 156 | fn: output file name 157 | coeffs: set of coefficients for Lageurre polynomials 158 | xc: center position 159 | size: size in pixels of image 160 | beta: characteristic beta values 161 | phi: rotation angle 162 | norder: max order of polynomials 163 | mode: basis function mode 164 | pos: 4 element array of RA,DEC and scale size from FITS header (degrees) 165 | info: extra metadata space 166 | fmt: output formats supported: pkl (pickle), json 167 | """ 168 | if type(norder) is int: norder=[norder,norder] 169 | d={ 'mode':'lageurre', 170 | 'xc':xc, 171 | 'size':size, 172 | 'beta':beta, 173 | 'phi':phi, 174 | 'norder':norder, 175 | 'ra':pos[0], 176 | 'dec':pos[1], 177 | 'dra':pos[2], 178 | 'ddec':pos[3], 179 | 'info': info } 180 | if fmt.startswith('pkl'): 181 | d['coeffs']=coeffs 182 | fh=open(fn,'wb') 183 | pickle.dump(d,fh) 184 | fh.close() 185 | elif fmt.startswith('json'): 186 | d['rcoeffs']=coeffs.real.tolist() 187 | d['icoeffs']=coeffs.imag.tolist() 188 | fh=open(fn,'w') 189 | json.dump(d,fh,sort_keys=True) 190 | fh.close() 191 | else: 192 | print 'Unknown format, no file written' 193 | 194 | def readLageurreCoeffs(fn): 195 | """Read a binary coeff file and return a dictionary of values 196 | fn: filename to read 197 | """ 198 | if fn.endswith('.pkl'): 199 | fh=open(fn,'rb') 200 | d=pickle.load(fh) 201 | fh.close() 202 | return d 203 | elif fn.endswith('.json'): 204 | fh=open(fn,'r') 205 | d=json.load(fh) 206 | rcoeffs=np.array(d.pop('rcoeffs')) 207 | icoeffs=np.array(d.pop('icoeffs')) 208 | d['coeffs']=rcoeffs + 1j*icoeffs 209 | fh.close() 210 | return d 211 | else: 212 | print 'Unknown file type' 213 | return np.nan 214 | 215 | #TODO: a general coeff file reader 216 | def readCoeffs(fn): 217 | """Determine a coefficient file based on file extension, call the correct reader 218 | """ 219 | if fn.endswith('.pkl'): 220 | fh=open(fn,'rb') 221 | d=pickle.load(fh) 222 | fh.close() 223 | return d 224 | elif fn.endswith('.json'): 225 | fh=open(fn,'r') 226 | d=json.load(fh) 227 | fh.close() 228 | if d['mode'].startswith('hermite'): return readHermiteCoeffs(fn) 229 | elif d['mode'].startswith('lageurre'): return readLageurreCoeffs(fn) 230 | 231 | 232 | if __name__ == "__main__": 233 | 234 | print '============================================' 235 | print 'Testing fileio module:' 236 | print '============================================' 237 | tc=0 238 | te=0 239 | 240 | #read in a FITS file 241 | tc+=1 242 | try: 243 | im,hdr=readFITS('../data/N6251_test.fits',hdr=True) 244 | print 'FITS header:', hdr 245 | print 'FITS image shape:', im.shape 246 | except: 247 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 248 | te+=1 249 | 250 | tc+=1 251 | try: 252 | im,hdr=readFITS('../data/2dFGRSTGN274Z24.fits', hdr=True) 253 | print 'FITS header:', hdr 254 | print 'FITS image shape:', im.shape 255 | except: 256 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 257 | te+=1 258 | 259 | #read in a PNG file 260 | tc+=1 261 | try: 262 | im=readImg('../data/N6251_test.png',gs=True) 263 | print 'PNG shape:', im.shape 264 | except: 265 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 266 | te+=1 267 | 268 | #load pre computed shapelet coeffs (pkl) 269 | #save pre computed shapelet coeffs (pkl) 270 | #load pre computed shapelet coeffs (json) 271 | #save pre computed shapelet coeffs (json) 272 | tc+=1 273 | try: 274 | shapeDict=readHermiteCoeffs('../data/testHermite.pkl') 275 | print shapeDict.keys() 276 | 277 | writeHermiteCoeffs('testWriteHermite.pkl',shapeDict['coeffs'],shapeDict['xc'],shapeDict['size'],shapeDict['beta'],shapeDict['phi'],shapeDict['norder'],pos=[shapeDict['ra'],shapeDict['dec'],shapeDict['dra'],shapeDict['ddec']],info=shapeDict['info'],fmt='pkl') 278 | shapeDict0=readHermiteCoeffs('testWriteHermite.pkl') 279 | print shapeDict0.keys() 280 | 281 | writeHermiteCoeffs('testWriteHermite.json',shapeDict['coeffs'],shapeDict['xc'],shapeDict['size'],shapeDict['beta'],shapeDict['phi'],shapeDict['norder'],pos=[shapeDict['ra'],shapeDict['dec'],shapeDict['dra'],shapeDict['ddec']],info=shapeDict['info'],fmt='json') 282 | shapeDict0=readHermiteCoeffs('testWriteHermite.json') 283 | print shapeDict0.keys() 284 | 285 | shapeDict=readLageurreCoeffs('../data/testLageurre.pkl') 286 | print shapeDict.keys() 287 | 288 | writeLageurreCoeffs('testWriteLageurre.pkl',shapeDict['coeffs'],shapeDict['xc'],shapeDict['size'],shapeDict['beta'],shapeDict['phi'],shapeDict['norder'],pos=[shapeDict['ra'],shapeDict['dec'],shapeDict['dra'],shapeDict['ddec']],info=shapeDict['info'],fmt='pkl') 289 | shapeDict0=readLageurreCoeffs('testWriteLageurre.pkl') 290 | print shapeDict0.keys() 291 | 292 | writeLageurreCoeffs('testWriteLageurre.json',shapeDict['coeffs'],shapeDict['xc'],shapeDict['size'],shapeDict['beta'],shapeDict['phi'],shapeDict['norder'],pos=[shapeDict['ra'],shapeDict['dec'],shapeDict['dra'],shapeDict['ddec']],info=shapeDict['info'],fmt='json') 293 | shapeDict0=readLageurreCoeffs('testWriteLageurre.json') 294 | print shapeDict0.keys() 295 | except: 296 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 297 | te+=1 298 | 299 | print '============================================' 300 | print '%i of %i tests succeeded'%(tc-te,tc) 301 | print '============================================' 302 | 303 | -------------------------------------------------------------------------------- /shapelets/fshapelet.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import numpy as np 3 | from scipy.special import eval_genlaguerre 4 | from scipy.misc import factorial 5 | 6 | from numexpr import evaluate as neval 7 | 8 | PI = np.pi 9 | 10 | def polar_basis_L(r, n0, m0, beta=1.): 11 | """Polar dimensional basis function based on Laguerre polynomials of characteristic size beta 12 | phs: additional phase factor, used in the Fourier Transform""" 13 | m_a = abs(m0) 14 | n_m = (n0 - m_a)/2 15 | n_p = (n0 + m_a)/2 16 | 17 | # 2π is missing here.. 18 | norm = (-1.)**n_m/(beta**(m_a + 1))*(float(factorial(n_m))/factorial(n_p))**.5 19 | 20 | lag = eval_genlaguerre(n_m, m_a, (r/beta)**2) 21 | return neval('norm*lag*r**m_a*exp(-.5*(r/beta)**2)') 22 | 23 | def genPolarBasisMatrix(beta, nmax,r,th): 24 | """Generate the n x k matrix of basis functions(k) for each pixel(n) 25 | beta: characteristic size of the shaeplets 26 | nmax: maximum decomposition order 27 | r: radius matrix of n pixels 28 | th: theta matrix of n pixels 29 | """ 30 | # Precompute the values for angular basis 31 | # as the complex exp computations are rather costly 32 | # now Y_{m=-1} can be accessed as Y[-1] or Y[(2*nmax-1) -1] 33 | Y0 = neval('exp(-1.j*th)') 34 | N0, N1 = Y0.shape[0], Y0.shape[1] 35 | Y_vec = [] 36 | for mm in range(nmax) + range(-1*nmax+1, 0): 37 | Y_vec.append(neval('Y0**mm')) 38 | 39 | bvals=np.empty((N0, N1, pvect_len(nmax)), dtype='complex128') 40 | L_vec_tmp = [0]*nmax # initializing an empty list 41 | 42 | pos = 0 43 | for nn in range(nmax): 44 | for mm in range(-1*nn,nn+1): 45 | if (nn%2==0 and abs(mm)%2==0) or (nn%2==1 and abs(mm)%2==1): 46 | Ym = wrap_idx(Y_vec, mm) 47 | # Using the fact that L_{n,-m} = L_{n, m} 48 | if mm <= 0: 49 | Lnm = polar_basis_L(r,nn,mm, beta=beta) 50 | L_vec_tmp[abs(mm)] = Lnm 51 | else: 52 | Lnm = L_vec_tmp[mm] 53 | bvals[:,:,pos] = (neval('Ym*Lnm')) 54 | pos += 1 55 | 56 | return bvals.reshape((N0*N1,-1)) 57 | 58 | def wrap_idx(vect, idx): 59 | # this part reproduces negative indexing 60 | if idx < 0: 61 | idx = len(vect) + idx 62 | return vect[idx] 63 | 64 | 65 | def pvect_len(nmax): 66 | return nmax*(nmax+1)/2 67 | 68 | 69 | def polarArray(xc,size,rot=0.): 70 | """Return arrays of shape 'size' with radius and theta values centered on xc 71 | rot: radians in which to rotate the shapelet 72 | """ 73 | Y, X = np.indices(size, dtype='float64') 74 | X -= xc[0] 75 | Y -= xc[1] 76 | 77 | r = neval('sqrt(X**2 + Y**2)') 78 | th = neval('arctan2(Y,X)+rot') 79 | return r, th 80 | -------------------------------------------------------------------------------- /shapelets/img.py: -------------------------------------------------------------------------------- 1 | """ 2 | Image manipulation functions 3 | """ 4 | 5 | import sys 6 | import numpy as np 7 | #shapelet functions 8 | import decomp 9 | 10 | def selPxRange(im,extent): 11 | """Select out the subimage within the extent region (xmin,xmax,ymin,ymax) 12 | Note about x,y def'n: in numpy the top left corner is (0,0) and the first index index increases from top to bottom, the second index increases from left to right, so this is a -90 degree rotation to the normal x-y plane 13 | """ 14 | return im[extent[0]:extent[1],extent[2]:extent[3]] 15 | 16 | def flux(im): 17 | """Total flux of the image (M00)""" 18 | return im.sum() 19 | 20 | def centroid(im,region=None): 21 | """Compute centroid of image (M10/M00,M01/M00) (x,y), region: use this region to compute centroid""" 22 | if not(region is None): 23 | im=im[region[0]:region[1],region[2]:region[3]] 24 | offset=[region[0],region[2]] 25 | else: offset=[0,0] 26 | m00=np.sum(im) 27 | m01=np.sum(np.sum(im,axis=1)*np.arange(im.shape[0])) 28 | m10=np.sum(np.sum(im,axis=0)*np.arange(im.shape[1])) 29 | return [m01/m00+offset[0], m10/m00+offset[1]] 30 | 31 | def maxPos(im, region=None): 32 | """Return the position of the maximum in the image, region: use this region to determine the maximum""" 33 | if not(region is None): 34 | im=im[region[0]:region[1],region[2]:region[3]] 35 | offset=[region[0],region[2]] 36 | else: offset=[0,0] 37 | #shift minimum to zero 38 | im=im-im.min() 39 | maxpos=np.argwhere(im==np.max(im))[0] 40 | return [maxpos[0]+offset[0],maxpos[1]+offset[1]] 41 | 42 | def makeNoiseMap(shape,mean=0.,std=1.): 43 | """Return a noise map with a given shape, mean and std of Gaussian noise 44 | """ 45 | return np.random.normal(mean,std,shape) 46 | 47 | #TODO: auto noise estimation perhaps with edge detection and masking out regions? needs to be worked on, for know we assume a good noise region is known or just sample the entire image 48 | def estimateNoise(im,mode='basic'): 49 | """ 50 | Estimate the Gaussian noise statistics for an image 51 | modes: 52 | basic: compute the mean and std from an input image 53 | sample: randomly sample a fraction pixels, works fine for sparse images 54 | """ 55 | if mode.startswith('basic'): 56 | mean=np.mean(im) 57 | std=np.std(im) 58 | print 'Estimated noise: \tmean: %f \tstd: %f'%(mean,std) 59 | return mean,std 60 | if mode.startswith('sample'): 61 | sample=np.random.choice(im.flatten(), size=int(im.size*0.1), replace=True) #randomly sample npix*f pixels 62 | mean=np.mean(sample) 63 | std=np.std(sample) 64 | print 'Estimated noise: \tmean: %f \tstd: %f'%(mean,std) 65 | return mean,std 66 | 67 | def constructModel(bvals,coeffs,size): 68 | """Construct a model image based on the basis functions values, and coeffs on an image 69 | with size dimensions 70 | """ 71 | #return np.reshape(bvals[:,0],size) 72 | model_img=np.dot(bvals,coeffs) 73 | model_img=np.reshape(model_img,size) 74 | return model_img 75 | 76 | def polarCoeffImg(coeffs,nmax): 77 | """Return 2D array of coeffs for Laguerre components for plotting 78 | """ 79 | im=np.zeros((nmax[0]*2,nmax[0])) 80 | cnt=0 81 | for nn in range(nmax[0]): 82 | for mm in np.arange(-1*nn,nn+1): 83 | if nn%2==0 and mm%2==0: 84 | im[mm+nmax-1,nn]=coeffs[cnt] 85 | cnt+=1 86 | elif nn%2==1 and mm%2==1: 87 | im[mm+nmax-1,nn]=coeffs[cnt] 88 | cnt+=1 89 | return im 90 | 91 | def xc2radec(xc,hdr,offset=[0.,0.]): 92 | """Return the RA,DEC position for a centroid (x,y) pair based on FITS header 93 | offset: x,y offset from full image 94 | Notation note: dec is top/bottom direction, ra is left/right direction 95 | """ 96 | ra=(hdr['raPix']-(offset[1]+xc[1]))*hdr['dra']+hdr['ra'] 97 | dec=(hdr['decPix']-(offset[0]+xc[0]))*hdr['ddec']+hdr['dec'] 98 | return ra,dec 99 | 100 | #This has been superseded by measure.beta_pix2angle() 101 | #def beta2size(beta,hdr=None,dra=1.,ddec=1.): 102 | # """Convert a beta pixel size to celestial size 103 | # requires either FITS header (hdr) or the delta RA (dra) and delta DEC (ddec) 104 | # """ 105 | # if type(beta)==list: 106 | # if hdr is None: 107 | # return [np.abs(beta[1]*dra),np.abs(beta[0]*ddec)] 108 | # else: 109 | # return [np.abs(beta[1]*hdr['dra']),np.abs(beta[0]*hdr['ddec'])] 110 | # else: 111 | # if hdr is None: 112 | # return [np.abs(beta*dra),np.abs(beta*ddec)] 113 | # else: 114 | # return [np.abs(beta*hdr['dra']),np.abs(beta*hdr['ddec'])] 115 | 116 | if __name__ == "__main__": 117 | 118 | print '============================================' 119 | print 'Testing img module:' 120 | print '============================================' 121 | tc=0 122 | te=0 123 | 124 | import fileio,shapelet 125 | im,hdr=fileio.readFITS('../data/N6251_test.fits',hdr=True) 126 | 127 | #selPxRange(im,extent): 128 | tc+=1 129 | try: 130 | subim=selPxRange(im,[170,335,195,309]) 131 | print subim.shape 132 | except: 133 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 134 | te+=1 135 | 136 | #flux(im): 137 | tc+=1 138 | try: 139 | print flux(im) 140 | except: 141 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 142 | te+=1 143 | 144 | #centroid(im,region=None): 145 | tc+=1 146 | try: 147 | print centroid(im,region=[170,335,195,309]) 148 | except: 149 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 150 | te+=1 151 | 152 | #maxPos(im, region=None): 153 | tc+=1 154 | try: 155 | print maxPos(im,region=[170,335,195,309]) 156 | except: 157 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 158 | te+=1 159 | 160 | #estimateNoise(im,mode='basic'): 161 | tc+=1 162 | try: 163 | mean,std=estimateNoise(im,mode='basic') 164 | nm=makeNoiseMap(im.shape,mean,std) 165 | print nm.shape 166 | except: 167 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 168 | te+=1 169 | 170 | #constructModel(bvals,coeffs,size): 171 | tc+=1 172 | try: 173 | shapeDict=fileio.readLageurreCoeffs('../data/testHermite.pkl') 174 | rx=np.array(range(0,shapeDict['size'][0]),dtype=float)-shapeDict['xc'][0] 175 | ry=np.array(range(0,shapeDict['size'][1]),dtype=float)-shapeDict['xc'][1] 176 | xx,yy=shapelet.xy2Grid(rx,ry) 177 | bvals=decomp.genBasisMatrix(shapeDict['beta'],shapeDict['norder'],shapeDict['phi'],xx,yy) 178 | mdl=constructModel(bvals,shapeDict['coeffs'],shapeDict['size']) 179 | print mdl.shape 180 | except: 181 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 182 | te+=1 183 | 184 | #polarCoeffImg(coeffs,nmax): 185 | tc+=1 186 | try: 187 | shapeDict=fileio.readLageurreCoeffs('../data/testLageurre.pkl') 188 | cim=polarCoeffImg(shapeDict['coeffs'].real,shapeDict['norder']) 189 | print cim 190 | except: 191 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 192 | te+=1 193 | 194 | #xc2radec(xc,hdr,offset=[0.,0.]): 195 | tc+=1 196 | try: 197 | print xc2radec([10.,5.],hdr) 198 | except: 199 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 200 | te+=1 201 | 202 | ##beta2size 203 | #tc+=1 204 | #try: 205 | # print beta2size([4.5,6.],dra=3.,ddec=4.) 206 | #except: 207 | # print 'Test failed (%i):'%tc, sys.exc_info()[0] 208 | # te+=1 209 | 210 | print '============================================' 211 | print '%i of %i tests succeeded'%(tc-te,tc) 212 | print '============================================' 213 | 214 | -------------------------------------------------------------------------------- /shapelets/measure.py: -------------------------------------------------------------------------------- 1 | """ 2 | Measurement operations 3 | """ 4 | 5 | import numpy as np 6 | import scipy.special 7 | 8 | def beta_pix2angle(beta,phi=0.,hdr=None,deltas=[1.,1.]): 9 | """Convert a beta in units of pixels to angluar size (radians) 10 | """ 11 | rotM=np.matrix([[np.cos(phi),-1.*np.sin(phi)],[np.sin(phi),np.cos(phi)]]) 12 | if hdr is None: 13 | dra=np.abs(deltas[0]) 14 | ddec=np.abs(deltas[1]) 15 | else: 16 | dra=np.abs(hdr['dra']) 17 | ddec=np.abs(hdr['ddec']) 18 | temp0=np.dot(rotM,np.array([(np.pi/180.)*dra,0.])) 19 | temp1=np.dot(rotM,np.array([0.,(np.pi/180.)*ddec])) 20 | rotDeltas=np.array([np.sqrt(temp0[0,0]**2.+temp0[0,1]**2.), np.sqrt(temp1[0,0]**2.+temp1[0,1]**2.)]) 21 | betaRad=(2.*np.pi)*rotDeltas*np.array(beta) #there is some mathematical convention issue, something about wavenumber and wavelength...should sort out a clear answer 22 | return betaRad 23 | 24 | def polarIDs(nmax): 25 | """Given an nmax, convert to (n.m) polar ID pairs 26 | """ 27 | ids=[] 28 | for nn in range(nmax[0]): 29 | for mm in np.arange(-1*nn,nn+1): 30 | if nn%2==0 and mm%2==0: 31 | ids.append([nn,mm]) 32 | elif nn%2==1 and mm%2==1: 33 | ids.append([nn,mm]) 34 | return ids 35 | 36 | def cartIDs(nmax): 37 | """Given an nmax, convert to (n,m) Cartesian ID pairs 38 | """ 39 | ids=[] 40 | if type(nmax) is int: nmax=[nmax,nmax] 41 | for ny in range(nmax[0]): 42 | for nx in range(nmax[1]): 43 | ids.append([ny,nx]) 44 | return ids 45 | 46 | def flux(coeffs,beta,nmax,mode): 47 | """Total flux from Cartesian or polar shapelet coefficients [manual eq. 1.14 and 1.23] 48 | coeffs: shapelet coefficients 49 | beta: two element beta 50 | nmax: coefficient limit 51 | mode: Hermite or Lageurre 52 | """ 53 | if mode.startswith('hermite'): 54 | c0=np.reshape(coeffs,nmax) 55 | flux=0 56 | for ny in range(nmax[0]): 57 | for nx in range(nmax[1]): 58 | if ny%2==0 and nx%2==0: 59 | flux+=(2.**(.5*(2-ny-nx)))*np.sqrt(scipy.special.binom(ny,ny/2))*np.sqrt(scipy.special.binom(nx,nx/2))*c0[ny,nx] 60 | return np.sqrt(np.pi*beta[0]*beta[1])*flux 61 | elif mode.startswith('lageurre'): 62 | ids=polarIDs(nmax) 63 | flux=0 64 | for cnt,i in enumerate(ids): 65 | if i[0]%2==0 and i[1]==0: flux+=coeffs[cnt] 66 | return np.sqrt(4.*np.pi*beta[0]*beta[1])*flux.real 67 | else: 68 | print 'Error: Unknown mode' 69 | return np.nan 70 | 71 | def centroid(coeffs,beta,nmax,mode): 72 | """Centroid position from Cartesian or polar shapelet coefficients [manual eq. 1.15 and 1.24] 73 | coeffs: shapelet coefficients 74 | beta: two element beta 75 | nmax: coefficient limit 76 | mode: Hermite or Lageurre 77 | """ 78 | f=flux(coeffs,beta,nmax,mode) 79 | if mode.startswith('hermite'): 80 | c0=np.reshape(coeffs,nmax) 81 | xc=np.array([0.,0.]) 82 | for ny in range(nmax[0]): 83 | for nx in range(nmax[1]): 84 | if ny%2==1 and nx%2==0: 85 | xc[0]+=np.sqrt(ny+1)*(2**(.5*(2-ny-nx)))*np.sqrt(scipy.special.binom(ny+1,(ny+1)/2))*np.sqrt(scipy.special.binom(nx,nx/2))*c0[ny,nx] 86 | elif ny%2==0 and nx%2==1: 87 | xc[1]+=np.sqrt(nx+1)*(2**(.5*(2-ny-nx)))*np.sqrt(scipy.special.binom(ny,ny/2))*np.sqrt(scipy.special.binom(nx+1,(nx+1)/2))*c0[ny,nx] 88 | return (1./f)*np.sqrt(np.pi)*beta[0]*beta[1]*xc 89 | elif mode.startswith('lageurre'): 90 | ids=polarIDs(nmax) 91 | xc=0 92 | for cnt,i in enumerate(ids): 93 | if i[0]%2==1 and i[1]==1: xc+=np.sqrt(i[0]+1)*coeffs[cnt] 94 | xc=((np.sqrt(8*np.pi)*beta[0]*beta[1])/f)*xc 95 | return np.array([xc.real,xc.imag]) 96 | else: 97 | print 'Error: Unknown mode' 98 | return np.nan 99 | 100 | def quadrupoles(coeffs,beta,nmax,mode='hermite'): 101 | """Quadrupole moments (J11, J12, J21, J22) from Cartesian shapelet coefficients [manual eq. 1.16 and 1.17] 102 | coeffs: shapelet coefficients 103 | beta: two element beta 104 | nmax: coefficient limit 105 | mode: only Hermite supported 106 | """ 107 | jj=np.zeros([2,2]) 108 | f=flux(coeffs,beta,nmax,mode) 109 | if mode.startswith('hermite'): 110 | c0=np.reshape(coeffs,nmax) 111 | xc=np.array([0.,0.]) 112 | for ny in range(nmax[0]): 113 | for nx in range(nmax[1]): 114 | if ny%2==1 and nx%2==1: 115 | jj[0,1]=np.sqrt(ny+1)*np.sqrt(nx+1)*(2.**(.5*(2.-ny-nx)))*np.sqrt(scipy.special.binom(ny+1,(ny+1)/2))*np.sqrt(scipy.special.binom(nx+1,(nx+1)/2))*c0[ny,nx] 116 | jj[1,0]=np.sqrt(ny+1)*np.sqrt(nx+1)*(2.**(.5*(2.-ny-nx)))*np.sqrt(scipy.special.binom(ny+1,(ny+1)/2))*np.sqrt(scipy.special.binom(nx+1,(nx+1)/2))*c0[ny,nx] 117 | elif ny%2==0 and nx%2==0: 118 | jj[0,0]=(2.*ny+1)*(2.**(.5*(2.-ny-nx)))*np.sqrt(scipy.special.binom(ny,ny/2))*np.sqrt(scipy.special.binom(nx,nx/2))*c0[ny,nx] 119 | jj[1,1]=(2.*nx+1)*(2.**(.5*(2.-ny-nx)))*np.sqrt(scipy.special.binom(ny,ny/2))*np.sqrt(scipy.special.binom(nx,nx/2))*c0[ny,nx] 120 | else: 121 | print 'Error: Unknown mode' 122 | return np.nan 123 | return np.sqrt(np.pi*((beta[0]*beta[1])**3.))*(1/f)*jj 124 | 125 | def r2size(coeffs,beta,nmax,mode): 126 | """Object size from Cartesian or polar shapelet coefficients [manual eq. 1.18 and 1.25] 127 | coeffs: shapelet coefficients 128 | beta: two element beta 129 | nmax: coefficient limit 130 | mode: Hermite or Lageurre 131 | """ 132 | f=flux(coeffs,beta,nmax,mode) 133 | if mode.startswith('hermite'): 134 | c0=np.reshape(coeffs,nmax) 135 | r2size=0 136 | for ny in range(nmax[0]): 137 | for nx in range(nmax[1]): 138 | if ny%2==0 and nx%2==0: 139 | r2size+=(2.**(.5*(4.-ny-nx)))*(1.+ny+nx)*np.sqrt(scipy.special.binom(ny,ny/2))*np.sqrt(scipy.special.binom(nx,nx/2))*c0[ny,nx] 140 | return np.sqrt(np.pi*((beta[0]*beta[1])**3.))*(1./f)*r2size 141 | elif mode.startswith('lageurre'): 142 | ids=polarIDs(nmax) 143 | r2size=0 144 | for cnt,i in enumerate(ids): 145 | if i[0]%2==0 and i[1]==0: r2size+=(i[0]+1)*coeffs[cnt] 146 | return np.sqrt(16.*np.pi*((beta[0]*beta[1])**3.))*(1./f)*r2size.real 147 | else: 148 | print 'Error: Unknown mode' 149 | return np.nan 150 | 151 | def ellipticity(coeffs,beta,nmax,mode='lageurre'): 152 | """Object ellipticity from polar shapelet coefficients [manual eq. 1.26] 153 | coeffs: shapelet coefficients 154 | beta: two element beta 155 | nmax: coefficient limit 156 | mode: only Laguerre supported 157 | """ 158 | f=flux(coeffs,beta,nmax,mode) 159 | r2=r2size(coeffs,beta,nmax,mode) 160 | if mode.startswith('lageurre'): 161 | ids=polarIDs(nmax) 162 | ee=0. 163 | for cnt,i in enumerate(ids): 164 | if i[0]%2==0 and i[1]==2: ee+=np.sqrt(i[0]*(i[0]+1.))*coeffs[cnt] 165 | return (np.sqrt(16.*np.pi*((beta[0]*beta[1])**3.))/(f*r2))*ee 166 | else: 167 | print 'Error: Unknown mode' 168 | return np.nan 169 | 170 | def all(coeffs,beta,nmax,mode): 171 | """Comppute all measurements for a set of coefficients 172 | coeffs: shapelet coefficients 173 | beta: two element beta 174 | nmax: coefficient limit 175 | mode: Hermite or Lageurre 176 | """ 177 | if mode.startswith('hermite'): 178 | return {'flux': flux(coeffs,beta,nmax,mode), 179 | 'centroid': centroid(coeffs,beta,nmax,mode), 180 | 'quadrupoles': quadrupoles(coeffs,beta,nmax,mode), 181 | 'r2': r2size(coeffs,beta,nmax,mode) } 182 | elif mode.startswith('lageurre'): 183 | return {'flux': flux(coeffs,beta,nmax,mode), 184 | 'centroid': centroid(coeffs,beta,nmax,mode), 185 | 'r2': r2size(coeffs,beta,nmax,mode), 186 | 'ellipticity': ellipticity(coeffs,beta,nmax,mode)} 187 | else: 188 | print 'Error: Unknown mode' 189 | return np.nan 190 | 191 | if __name__ == "__main__": 192 | 193 | print '============================================' 194 | print 'Testing measure module:' 195 | print '============================================' 196 | import fileio 197 | import sys 198 | tc=0 199 | te=0 200 | 201 | #load precomputed shapelet coeffs (polar and cartesian) 202 | hermDict=fileio.readHermiteCoeffs('../data/testHermite.pkl') 203 | laDict=fileio.readLageurreCoeffs('../data/testLageurre.pkl') 204 | 205 | #polarIDs(nmax): 206 | tc+=1 207 | try: 208 | print polarIDs(5) 209 | print cartIDs(5) 210 | except: 211 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 212 | te+=1 213 | 214 | #compute flux (cartesian) 215 | #compute flux (polar) 216 | tc+=1 217 | try: 218 | print flux(hermDict['coeffs'],hermDict['beta'],hermDict['norder'],mode=hermDict['mode']) 219 | print flux(laDict['coeffs'],laDict['beta'],laDict['norder'][0],mode=laDict['mode']) 220 | except: 221 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 222 | te+=1 223 | 224 | #compute centroid (polar) 225 | #compute centroid (cartesian) 226 | tc+=1 227 | try: 228 | print centroid(hermDict['coeffs'],hermDict['beta'],hermDict['norder'],mode=hermDict['mode']) 229 | print centroid(laDict['coeffs'],laDict['beta'],laDict['norder'][0],mode=laDict['mode']) 230 | except: 231 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 232 | te+=1 233 | 234 | #compute quadrupoles (cartesian J11, J12, J21, J22) 235 | tc+=1 236 | try: 237 | print quadrupoles(hermDict['coeffs'],hermDict['beta'],hermDict['norder']) 238 | except: 239 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 240 | te+=1 241 | 242 | #compute size (cartesian) 243 | #compute size (polar) 244 | tc+=1 245 | try: 246 | print r2size(hermDict['coeffs'],hermDict['beta'],hermDict['norder'],mode=hermDict['mode']) 247 | print r2size(laDict['coeffs'],laDict['beta'],laDict['norder'][0],mode=laDict['mode']) 248 | except: 249 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 250 | te+=1 251 | 252 | #compute ellipticity (polar) 253 | tc+=1 254 | try: 255 | print ellipticity(laDict['coeffs'],laDict['beta'],laDict['norder'][0]) 256 | except: 257 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 258 | te+=1 259 | 260 | tc+=1 261 | try: 262 | print all(hermDict['coeffs'],hermDict['beta'],hermDict['norder'],mode=hermDict['mode']) 263 | print all(laDict['coeffs'],laDict['beta'],laDict['norder'][0],mode=laDict['mode']) 264 | except: 265 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 266 | te+=1 267 | 268 | #print cart2polar(hermDict['coeffs'],hermDict['norder']) 269 | 270 | print '============================================' 271 | print '%i of %i tests succeeded'%(tc-te,tc) 272 | print '============================================' 273 | 274 | -------------------------------------------------------------------------------- /shapelets/phs/ClassMS.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from casacore.tables import table 3 | from rad2hmsdms import rad2hmsdms 4 | import ModColor 5 | import reformat 6 | 7 | class ClassMS(): 8 | def __init__(self,MSname,Col="DATA",zero_flag=True,ReOrder=False,EqualizeFlag=False,DoPrint=True,DoReadData=True, 9 | TimeChunkSize=None,GetBeam=False,RejectAutoCorr=False,SelectSPW=None,DelStationList=None): 10 | 11 | 12 | if MSname=="": exit() 13 | MSname=reformat.reformat(MSname,LastSlash=False) 14 | self.MSName=MSname 15 | self.ColName=Col 16 | self.zero_flag=zero_flag 17 | self.ReOrder=ReOrder 18 | self.EqualizeFlag=EqualizeFlag 19 | self.DoPrint=DoPrint 20 | self.TimeChunkSize=TimeChunkSize 21 | self.RejectAutoCorr=RejectAutoCorr 22 | self.SelectSPW=SelectSPW 23 | self.DelStationList=DelStationList 24 | self.ReadMSInfo(MSname,DoPrint=DoPrint) 25 | 26 | if DoReadData: self.ReadData() 27 | #self.RemoveStation() 28 | 29 | self.SR=None 30 | if GetBeam: 31 | self.LoadSR() 32 | 33 | 34 | 35 | 36 | def LoadSR(self): 37 | if self.SR!=None: return 38 | import lofar.stationresponse as lsr 39 | f=self.ChanFreq.flatten() 40 | if f.shape[0]>1: 41 | t=table(self.MSName+"/SPECTRAL_WINDOW/",readonly=False) 42 | c=t.getcol("CHAN_WIDTH") 43 | c.fill(np.abs((f[0:-1]-f[1::])[0])) 44 | t.putcol("CHAN_WIDTH",c) 45 | t.close() 46 | self.SR = lsr.stationresponse(self.MSName) 47 | self.SR.setDirection(self.rarad,self.decrad) 48 | 49 | 50 | def GiveBeam(self,time,ra,dec): 51 | Beam=np.zeros((ra.shape[0],self.na,1,2,2),dtype=np.complex) 52 | for i in range(ra.shape[0]): 53 | self.SR.setDirection(ra[i],dec[i]) 54 | Beam[i]=self.SR.evaluate(time) 55 | return Beam 56 | 57 | def GiveMappingAnt(self,ListStrSel,(row0,row1)=(None,None),FlagAutoCorr=True): 58 | #ListStrSel=["RT9-RTA", "RTA-RTB", "RTC-RTD", "RT6-RT7", "RT5-RT*"] 59 | 60 | print ModColor.Str(" ... Building BL-mapping for %s"%str(ListStrSel)) 61 | 62 | if row1==None: 63 | row0=0 64 | row1=self.nbl 65 | A0=self.A0[row0:row1] 66 | A1=self.A1[row0:row1] 67 | MapOut=np.ones((self.nbl,),dtype=np.bool) 68 | if FlagAutoCorr: 69 | ind=np.where(A0==A1)[0] 70 | MapOut[ind]=False 71 | 72 | 73 | for blsel in ListStrSel: 74 | if "-" in blsel: 75 | StrA0,StrA1=blsel.split("-") 76 | NumA0=np.where(np.array(self.StationNames)==StrA0)[0] 77 | NumA1=np.where(np.array(self.StationNames)==StrA1)[0] 78 | C0=((A0==NumA0)&(A1==NumA1)) 79 | C1=((A1==NumA0)&(A0==NumA1)) 80 | else: 81 | NumA0=np.where(np.array(self.StationNames)==blsel)[0] 82 | C0=(A0==NumA0) 83 | C1=(A1==NumA0) 84 | ind=np.where(C1|C0)[0] 85 | MapOut[ind]=False 86 | self.MapSelBLs=MapOut 87 | return self.MapSelBLs 88 | 89 | 90 | 91 | 92 | def SelChannel(self,(start,end,step)=(None,None,None),Revert=False): 93 | if start!=None: 94 | if Revert==False: 95 | ind=np.arange(self.Nchan)[start:end:step] 96 | else: 97 | ind=np.array(sorted(list(set(np.arange(self.Nchan).tolist())-set(np.arange(self.Nchan)[start:end:step].tolist())))) 98 | self.data=self.data[:,ind,:] 99 | self.flag_all=self.flag_all[:,ind,:] 100 | shape=self.ChanFreq.shape 101 | self.ChanFreq=self.ChanFreq[ind] 102 | 103 | 104 | def ReadData(self,t0=0,t1=-1,DoPrint=False,ReadWeight=False): 105 | if DoPrint==True: 106 | print " ... Reading MS" 107 | row0=0 108 | row1=self.F_nrows 109 | if t1>t0: 110 | t0=t0*3600.+self.F_tstart 111 | t1=t1*3600.+self.F_tstart 112 | ind0=np.argmin(np.abs(t0-self.F_times)) 113 | ind1=np.argmin(np.abs(t1-self.F_times)) 114 | row0=ind0*self.nbl 115 | row1=ind1*self.nbl 116 | 117 | self.ROW0=row0 118 | self.ROW1=row1 119 | self.nRowRead=row1-row0 120 | nRowRead=self.nRowRead 121 | 122 | table_all=table(self.MSName,ack=False,readonly=False) 123 | self.ColNames=table_all.colnames() 124 | SPW=table_all.getcol('DATA_DESC_ID',row0,nRowRead) 125 | A0=table_all.getcol('ANTENNA1',row0,nRowRead)[SPW==self.ListSPW[0]] 126 | A1=table_all.getcol('ANTENNA2',row0,nRowRead)[SPW==self.ListSPW[0]] 127 | print self.ListSPW[0] 128 | time_all=table_all.getcol("TIME")[SPW==self.ListSPW[0]] 129 | print np.max(time_all)-np.min(time_all) 130 | time_slots_all=np.array(sorted(list(set(time_all)))) 131 | ntimes=time_all.shape[0]/self.nbl 132 | 133 | flag_all=table_all.getcol("FLAG",row0,nRowRead)[SPW==self.ListSPW[0]] 134 | if ReadWeight==True: 135 | self.Weights=table_all.getcol("WEIGHT") 136 | 137 | if self.EqualizeFlag: 138 | for i in range(self.Nchan): 139 | fcol=flag_all[:,i,0]|flag_all[:,i,1]|flag_all[:,i,2]|flag_all[:,i,3] 140 | for pol in range(4): 141 | flag_all[:,i,pol]=fcol 142 | 143 | 144 | self.multidata=(type(self.ColName)==list) 145 | self.ReverseAntOrder=(np.where((A0==0)&(A1==1))[0]).shape[0]>0 146 | self.swapped=False 147 | 148 | uvw=table_all.getcol('UVW',row0,nRowRead)[SPW==self.ListSPW[0]] 149 | 150 | if self.ReOrder: 151 | vis_all=table_all.getcol(self.ColName,row0,nRowRead) 152 | if self.zero_flag: vis_all[flag_all==1]=0. 153 | if self.zero_flag: 154 | noise=(np.random.randn(vis_all.shape[0],vis_all.shape[1],vis_all.shape[2])\ 155 | +1j*np.random.randn(vis_all.shape[0],vis_all.shape[1],vis_all.shape[2]))*1e-6 156 | vis_all[flag_all==1]=noise[flag_all==1] 157 | vis_all[np.isnan(vis_all)]=0. 158 | listDataSPW=[np.swapaxes(vis_all[SPW==i,:,:],0,1) for i in self.ListSPW] 159 | self.data=np.concatenate(listDataSPW)#np.swapaxes(np.concatenate(listDataSPW),0,1) 160 | listFlagSPW=[np.swapaxes(flag_all[SPW==i,:,:],0,1) for i in self.ListSPW] 161 | flag_all=np.concatenate(listFlagSPW)#np.swapaxes(np.concatenate(listDataSPW),0,1) 162 | self.uvw=uvw 163 | self.swapped=True 164 | 165 | 166 | else: 167 | self.uvw=uvw 168 | if self.multidata: 169 | self.data=[] 170 | for colin in self.ColName: 171 | print "... read %s"%colin 172 | vis_all=table_all.getcol(colin,row0,nRowRead)[SPW==self.ListSPW[0]] 173 | print " shape: %s"%str(vis_all.shape) 174 | if self.zero_flag: vis_all[flag_all==1]=0. 175 | vis_all[np.isnan(vis_all)]=0. 176 | self.data.append(vis_all) 177 | else: 178 | vis_all=table_all.getcol(self.ColName,row0,nRowRead) 179 | if self.zero_flag: vis_all[flag_all==1]=0. 180 | vis_all[np.isnan(vis_all)]=0. 181 | self.data=vis_all 182 | 183 | 184 | self.flag_all=flag_all 185 | 186 | if self.RejectAutoCorr: 187 | indGetCorrelation=np.where(A0!=A1)[0] 188 | A0=A0[indGetCorrelation] 189 | A1=A1[indGetCorrelation] 190 | self.uvw=self.uvw[indGetCorrelation,:] 191 | time_all=time_all[indGetCorrelation] 192 | if self.swapped: 193 | self.data=self.data[:,indGetCorrelation,:] 194 | self.flag_all=self.flag_all[:,indGetCorrelation,:] 195 | else: 196 | self.data=self.data[indGetCorrelation,:,:] 197 | self.flag_all=self.flag_all[indGetCorrelation,:,:] 198 | self.nbl=(self.na*(self.na-1))/2 199 | 200 | table_all.close() 201 | if self.DoRevertChans: 202 | self.data=self.data[:,::-1,:] 203 | self.flag_all=self.flag_all[:,::-1,:] 204 | 205 | 206 | self.times_all=time_all 207 | self.times=time_slots_all 208 | self.ntimes=time_slots_all.shape[0] 209 | self.nrows=time_all.shape[0] 210 | 211 | self.IndFlag=np.where(flag_all==True) 212 | 213 | #self.NPol=vis_all.shape[2] 214 | self.A0=A0 215 | self.A1=A1 216 | 217 | 218 | def SaveAllDataStruct(self): 219 | t=table(self.MSName,ack=False,readonly=False) 220 | 221 | t.putcol('ANTENNA1',self.A0) 222 | t.putcol('ANTENNA2',self.A1) 223 | t.putcol("TIME",self.times_all) 224 | t.putcol("TIME_CENTROID",self.times_all) 225 | t.putcol("UVW",self.uvw) 226 | t.putcol("FLAG",self.flag_all) 227 | for icol in range(len(self.ColName)): 228 | t.putcol(self.ColName[icol],self.data[icol]) 229 | t.close() 230 | 231 | def RemoveStation(self): 232 | 233 | DelStationList=self.DelStationList 234 | if DelStationList==None: return 235 | 236 | StationNames=self.StationNames 237 | self.MapStationsKeep=np.arange(len(StationNames)) 238 | DelNumStationList=[] 239 | for Station in DelStationList: 240 | ind=np.where(Station==np.array(StationNames))[0] 241 | self.MapStationsKeep[ind]=-1 242 | DelNumStationList.append(ind) 243 | indRemove=np.where((self.A0!=ind)&(self.A1!=ind))[0] 244 | self.A0=self.A0[indRemove] 245 | self.A1=self.A1[indRemove] 246 | self.data=self.data[indRemove,:,:] 247 | self.flag_all=self.flag_all[indRemove,:,:] 248 | self.times_all=self.times_all[indRemove,:,:] 249 | self.MapStationsKeep=self.MapStationsKeep[self.MapStationsKeep!=-1] 250 | StationNames=(np.array(StationNames)[self.MapStationsKeep]).tolist() 251 | 252 | na=self.MapStationsKeep.shape[0] 253 | self.na=na 254 | self.StationPos=self.StationPos[self.MapStationsKeep,:] 255 | self.nbl=(na*(na-1))/2+na 256 | 257 | 258 | def ReadMSInfo(self,MSname,DoPrint=True): 259 | 260 | ta=table(MSname+'/ANTENNA',ack=False) 261 | StationNames=ta.getcol('NAME') 262 | 263 | na=ta.getcol('POSITION').shape[0] 264 | self.StationPos=ta.getcol('POSITION') 265 | nbl=(na*(na-1))/2+na 266 | #nbl=(na*(na-1))/2 267 | ta.close() 268 | 269 | table_all=table(MSname,ack=False,readonly=False) 270 | SPW=table_all.getcol('DATA_DESC_ID') 271 | if self.SelectSPW!=None: 272 | self.ListSPW=self.SelectSPW 273 | print "dosel" 274 | else: 275 | self.ListSPW=sorted(list(set(SPW))) 276 | self.F_nrows=table_all.getcol("TIME").shape[0] 277 | F_time_all=table_all.getcol("TIME")[SPW==self.ListSPW[0]] 278 | #nbl=(np.where(F_time_all==F_time_all[0])[0]).shape[0] 279 | F_time_slots_all=np.array(sorted(list(set(F_time_all.tolist())))) 280 | F_ntimes=F_time_slots_all.shape[0] 281 | table_all.close() 282 | 283 | ta_spectral=table(MSname+'/SPECTRAL_WINDOW/',ack=False) 284 | reffreq=ta_spectral.getcol('REF_FREQUENCY') 285 | chan_freq=ta_spectral.getcol('CHAN_FREQ') 286 | self.dFreq=ta_spectral.getcol("CHAN_WIDTH").flatten()[0] 287 | if chan_freq.shape[0]>len(self.ListSPW): 288 | print ModColor.Str(" ====================== >> More SPW in headers, modifying that error....") 289 | chan_freq=chan_freq[np.array(self.ListSPW),:] 290 | reffreq=reffreq[np.array(self.ListSPW)] 291 | 292 | 293 | wavelength=299792458./reffreq 294 | NSPW=chan_freq.shape[0] 295 | self.ChanFreq=chan_freq 296 | self.Freq_Mean=np.mean(chan_freq) 297 | wavelength_chan=299792458./chan_freq 298 | 299 | if NSPW>1: 300 | print "Don't deal with multiple SPW yet" 301 | 302 | 303 | Nchan=wavelength_chan.shape[1] 304 | NSPWChan=NSPW*Nchan 305 | ta=table(MSname+'/FIELD/',ack=False) 306 | rarad,decrad=ta.getcol('PHASE_DIR')[0][0] 307 | if rarad<0.: rarad+=2.*np.pi 308 | 309 | radeg=rarad*180./np.pi 310 | decdeg=decrad*180./np.pi 311 | ta.close() 312 | 313 | self.DoRevertChans=False 314 | if Nchan>1: 315 | self.DoRevertChans=(self.ChanFreq.flatten()[0]>self.ChanFreq.flatten()[-1]) 316 | if self.DoRevertChans: 317 | print ModColor.Str(" ====================== >> Revert Channel order!") 318 | wavelength_chan=wavelength_chan[0,::-1] 319 | self.ChanFreq=self.ChanFreq[0,::-1] 320 | 321 | self.na=na 322 | self.Nchan=Nchan 323 | self.NSPW=NSPW 324 | self.NSPWChan=NSPWChan 325 | self.F_tstart=F_time_all[0] 326 | self.F_times_all=F_time_all 327 | self.F_times=F_time_slots_all 328 | self.F_ntimes=F_time_slots_all.shape[0] 329 | self.dt=F_time_slots_all[1]-F_time_slots_all[0] 330 | self.DTs=F_time_slots_all[-1]-F_time_slots_all[0] 331 | self.DTh=self.DTs/3600. 332 | self.radec=(rarad,decrad) 333 | self.rarad=rarad 334 | self.decrad=decrad 335 | self.reffreq=reffreq 336 | self.StationNames=StationNames 337 | self.wavelength_chan=wavelength_chan 338 | self.rac=rarad 339 | self.decc=decrad 340 | self.nbl=nbl 341 | self.StrRA = rad2hmsdms(self.rarad,Type="ra").replace(" ",":") 342 | self.StrDEC = rad2hmsdms(self.decrad,Type="dec").replace(" ",".") 343 | 344 | if DoPrint==True: 345 | print ModColor.Str(" MS PROPERTIES: ") 346 | print " - File Name: %s"%ModColor.Str(self.MSName,col="green") 347 | print " - Column Name: %s"%ModColor.Str(str(self.ColName),col="green") 348 | print " - Pointing center: (ra, dec)=(%s, %s) "%(rad2hmsdms(self.rarad,Type="ra").replace(" ",":")\ 349 | ,rad2hmsdms(self.decrad,Type="dec").replace(" ",".")) 350 | print " - Frequency = %s MHz"%str(reffreq/1e6) 351 | print " - Wavelength = ",wavelength," meters" 352 | print " - Time bin = %4.1f seconds"%(self.dt) 353 | print " - Total Integration time = %6.2f hours"%((F_time_all[-1]-F_time_all[0])/3600.) 354 | print " - Number of antenna = ",na 355 | print " - Number of baseline = ",nbl 356 | print " - Number of SPW = ",NSPW 357 | print " - Number of channels = ",Nchan 358 | print 359 | 360 | 361 | def radec2lm_scalar(self,ra,dec): 362 | l = np.cos(dec) * np.sin(ra - self.rarad) 363 | m = np.sin(dec) * np.cos(self.decrad) - np.cos(dec) * np.sin(self.decrad) * np.cos(ra - self.rarad) 364 | return l,m 365 | 366 | def SaveVis(self,vis=None,Col="CORRECTED_DATA",spw=0,DoPrint=True): 367 | if vis==None: 368 | vis=self.data 369 | if DoPrint: print " Writting data in column %s"%ModColor.Str(Col,col="green") 370 | table_all=table(self.MSName,ack=False,readonly=False) 371 | if self.swapped: 372 | visout=np.swapaxes(vis[spw*self.Nchan:(spw+1)*self.Nchan],0,1) 373 | else: 374 | visout=vis 375 | table_all.putcol(Col,visout,self.ROW0,self.nRowRead) 376 | table_all.close() 377 | 378 | def GiveUvwBL(self,a0,a1): 379 | vecout=self.uvw[(self.A0==a0)&(self.A1==a1),:] 380 | return vecout 381 | 382 | def GiveVisBL(self,a0,a1,col=0,pol=None): 383 | if self.multidata: 384 | vecout=self.data[col][(self.A0==a0)&(self.A1==a1),:,:] 385 | else: 386 | vecout=self.data[(self.A0==a0)&(self.A1==a1),:,:] 387 | if pol!=None: 388 | vecout=vecout[:,:,pol] 389 | return vecout 390 | 391 | def GiveVisBLChan(self,a0,a1,chan,pol=None): 392 | if pol==None: 393 | vecout=(self.data[(self.A0==a0)&(self.A1==a1),chan,0]+self.data[(self.A0==a0)&(self.A1==a1),chan,3])/2. 394 | else: 395 | vecout=self.data[(self.A0==a0)&(self.A1==a1),chan,pol] 396 | return vecout 397 | 398 | def plotBL(self,a0,a1,pol=0): 399 | 400 | import pylab 401 | if self.multidata: 402 | vis0=self.GiveVisBL(a0,a1,col=0,pol=pol) 403 | vis1=self.GiveVisBL(a0,a1,col=1,pol=pol) 404 | pylab.clf() 405 | pylab.subplot(2,1,1) 406 | #pylab.plot(vis0.real) 407 | pylab.plot(np.abs(vis0)) 408 | #pylab.subplot(2,1,2) 409 | #pylab.plot(vis1.real) 410 | pylab.plot(np.abs(vis1),ls=":") 411 | pylab.title("%i-%i"%(a0,a1)) 412 | #pylab.plot(vis1.real-vis0.real) 413 | pylab.subplot(2,1,2) 414 | pylab.plot(np.angle(vis0)) 415 | pylab.plot(np.angle(vis1),ls=":") 416 | pylab.draw() 417 | pylab.show() 418 | else: 419 | pylab.clf() 420 | vis=self.GiveVisBL(a0,a1,col=0,pol=pol) 421 | pylab.subplot(2,1,1) 422 | #pylab.plot(np.abs(vis)) 423 | pylab.plot(np.real(vis)) 424 | pylab.subplot(2,1,2) 425 | #pylab.plot(np.angle(vis)) 426 | pylab.plot(np.imag(vis)) 427 | pylab.draw() 428 | pylab.show() 429 | 430 | def GiveCol(self,ColName): 431 | t=table(self.MSName,readonly=False,ack=False) 432 | col=t.getcol(ColName) 433 | t.close() 434 | return col 435 | 436 | def PutColInData(self,SpwChan,pol,data): 437 | if self.swapped: 438 | self.data[SpwChan,:,pol]=data 439 | else: 440 | self.data[:,SpwChan,pol]=data 441 | 442 | def Restore(self): 443 | backname="CORRECTED_DATA_BACKUP" 444 | backnameFlag="FLAG_BACKUP" 445 | t=table(self.MSName,readonly=False,ack=False) 446 | if backname in t.colnames(): 447 | print " Copying ",backname," to CORRECTED_DATA" 448 | #t.putcol("CORRECTED_DATA",t.getcol(backname)) 449 | self.CopyCol(backname,"CORRECTED_DATA") 450 | print " Copying ",backnameFlag," to FLAG" 451 | self.CopyCol(backnameFlag,"FLAG") 452 | #t.putcol(,t.getcol(backnameFlag)) 453 | t.close() 454 | 455 | def ZeroFlagSave(self,spw=0): 456 | self.flag_all.fill(0) 457 | if self.swapped: 458 | flagout=np.swapaxes(self.flag_all[spw*self.Nchan:(spw+1)*self.Nchan],0,1) 459 | else: 460 | flagout=self.flag_all 461 | t=table(self.MSName,readonly=False,ack=False) 462 | t.putcol("FLAG",flagout) 463 | 464 | t.close() 465 | 466 | def CopyCol(self,Colin,Colout): 467 | t=table(self.MSName,readonly=False,ack=False) 468 | if self.TimeChunkSize==None: 469 | print " ... Copying column %s to %s"%(Colin,Colout) 470 | t.putcol(Colout,t.getcol(Colin)) 471 | else: 472 | print " ... Copying column %s to %s"%(Colin,Colout) 473 | TimesInt=np.arange(0,self.DTh,self.TimeChunkSize).tolist() 474 | if not(self.DTh in TimesInt): TimesInt.append(self.DTh) 475 | for i in range(len(TimesInt)-1): 476 | t0,t1=TimesInt[i],TimesInt[i+1] 477 | print t0,t1 478 | t0=t0*3600.+self.F_tstart 479 | t1=t1*3600.+self.F_tstart 480 | ind0=np.argmin(np.abs(t0-self.F_times)) 481 | ind1=np.argmin(np.abs(t1-self.F_times)) 482 | row0=ind0*self.nbl 483 | row1=ind1*self.nbl 484 | NRow=row1-row0 485 | t.putcol(Colout,t.getcol(Colin,row0,NRow),row0,NRow) 486 | t.close() 487 | 488 | 489 | def PutBackupCol(self,back="CORRECTED_DATA"): 490 | backname="%s_BACKUP"%back 491 | backnameFlag="FLAG_BACKUP" 492 | self.PutCasaCols() 493 | t=table(self.MSName,readonly=False,ack=False) 494 | JustAdded=False 495 | if not(backname in t.colnames()): 496 | print " Putting column ",backname," in MS" 497 | desc=t.getcoldesc("CORRECTED_DATA") 498 | desc["name"]=backname 499 | desc['comment']=desc['comment'].replace(" ","_") 500 | t.addcols(desc) 501 | print " Copying CORRECTED_DATA in CORRECTED_DATA_BACKUP" 502 | self.CopyCol("CORRECTED_DATA",backname) 503 | #t.putcol(backname,t.getcol("CORRECTED_DATA")) 504 | if not(backnameFlag in t.colnames()): 505 | desc=t.getcoldesc("FLAG") 506 | desc["name"]=backnameFlag 507 | desc['comment']=desc['comment'].replace(" ","_") 508 | t.addcols(desc) 509 | self.CopyCol("FLAG",backnameFlag) 510 | #t.putcol(backnameFlag,t.getcol("FLAG")) 511 | JustAdded=True 512 | #else: 513 | #print " Column %s already there..."%backname 514 | t.close() 515 | return JustAdded 516 | 517 | def PutNewCol(self,Name,LikeCol="CORRECTED_DATA"): 518 | if not(Name in self.ColNames): 519 | print " Putting column %s in MS, with format of %s"%(Name,LikeCol) 520 | t=table(self.MSName,readonly=False,ack=False) 521 | desc=t.getcoldesc(LikeCol) 522 | desc["name"]=Name 523 | t.addcols(desc) 524 | t.close() 525 | 526 | def RotateMS(self,radec): 527 | import ModRotate 528 | ModRotate.Rotate(self,radec) 529 | ta=table(self.MSName+'/FIELD/',ack=False,readonly=False) 530 | ra,dec=radec 531 | radec=np.array([[[ra,dec]]]) 532 | ta.putcol("DELAY_DIR",radec) 533 | ta.putcol("PHASE_DIR",radec) 534 | ta.putcol("REFERENCE_DIR",radec) 535 | ta.close() 536 | t=table(self.MSName,ack=False,readonly=False) 537 | t.putcol(self.ColName,self.data) 538 | t.putcol("UVW",self.uvw) 539 | t.close() 540 | 541 | def PutCasaCols(self): 542 | import casacore.tables 543 | casacore.tables.addImagingColumns(self.MSName,ack=False) 544 | #self.PutNewCol("CORRECTED_DATA") 545 | #self.PutNewCol("MODEL_DATA") 546 | -------------------------------------------------------------------------------- /shapelets/phs/ModColor.py: -------------------------------------------------------------------------------- 1 | HEADER = '\033[95m' 2 | OKBLUE = '\033[94m' 3 | OKGREEN = '\033[92m' 4 | WARNING = '\033[93m' 5 | FAIL = '\033[91m' 6 | ENDC = '\033[0m' 7 | bold='\033[1m' 8 | nobold='\033[0m' 9 | Separator="================================%s==================================" 10 | silent=0 11 | 12 | def Str(strin0,col="red",Bold=True): 13 | if silent==1: return strin0 14 | strin=str(strin0) 15 | if col=="red": 16 | ss=FAIL 17 | if col=="green": 18 | ss=OKGREEN 19 | elif col=="yellow": 20 | ss=WARNING 21 | elif col=="blue": 22 | ss=OKBLUE 23 | elif col=="green": 24 | ss=OKGREEN 25 | ss="%s%s%s"%(ss,strin,ENDC) 26 | if Bold: ss="%s%s%s"%(bold,ss,nobold) 27 | return ss 28 | 29 | def Sep(strin=None,D=1): 30 | if D!=1: 31 | return Str(Separator%("="*len(strin))) 32 | else: 33 | return Str(Separator%(strin)) 34 | 35 | def Title(strin,Big=False): 36 | print 37 | print 38 | if Big: print Sep(strin,D=0) 39 | print Sep(strin) 40 | if Big: print Sep(strin,D=0) 41 | print 42 | 43 | def disable(): 44 | HEADER = '' 45 | OKBLUE = '' 46 | OKGREEN = '' 47 | WARNING = '' 48 | FAIL = '' 49 | ENDC = '' -------------------------------------------------------------------------------- /shapelets/phs/ModRotate.py: -------------------------------------------------------------------------------- 1 | from casacore.tables import table 2 | import numpy as np 3 | import os 4 | import gc 5 | import ephem 6 | import re 7 | import casacore.quanta as qa 8 | import casacore.measures as pm 9 | import rad2hmsdms 10 | 11 | 12 | def Rotate(MS,ToRaDec): 13 | 14 | ra, dec = MS.radec 15 | ra1,dec1=ToRaDec 16 | 17 | # preparing rotation matrices (ORIGINAL PHASE DIRECTION) 18 | x = np.sin(ra)*np.cos(dec) 19 | y = np.cos(ra)*np.cos(dec) 20 | z = np.sin(dec) 21 | w = np.array([[x,y,z]]).T 22 | x = -np.sin(ra)*np.sin(dec) 23 | y = -np.cos(ra)*np.sin(dec) 24 | z = np.cos(dec) 25 | v = np.array([[x,y,z]]).T 26 | x = np.cos(ra) 27 | y = -np.sin(ra) 28 | z = 0 29 | u = np.array([[x,y,z]]).T 30 | T = np.concatenate([u,v,w], axis = -1 ) 31 | 32 | 33 | TT=np.identity(3) 34 | x1 = np.sin(ra1)*np.cos(dec1) 35 | y1 = np.cos(ra1)*np.cos(dec1) 36 | z1 = np.sin(dec1) 37 | w1 = np.array([[x1,y1,z1]]).T 38 | x1 = -np.sin(ra1)*np.sin(dec1) 39 | y1 = -np.cos(ra1)*np.sin(dec1) 40 | z1 = np.cos(dec1) 41 | v1 = np.array([[x1,y1,z1]]).T 42 | x1 = np.cos(ra1) 43 | y1 = -np.sin(ra1) 44 | z1 = 0 45 | u1 = np.array([[x1,y1,z1]]).T 46 | 47 | Tshift = np.concatenate([u1,v1,w1], axis=-1) 48 | 49 | TT = np.dot(Tshift.T,T) 50 | 51 | uvw_all = MS.uvw 52 | uvw=uvw_all 53 | 54 | Phase=np.dot(np.dot((w-w1).T, T) , uvw.T) 55 | uvwNew=np.dot(uvw, TT.T) 56 | MS.uvw=uvwNew 57 | 58 | for chan in range(MS.NSPWChan): 59 | wavelength = MS.wavelength_chan.flatten()[chan] 60 | f = np.exp(Phase * 2 * np.pi * 1j/wavelength) 61 | for pol in range(4): 62 | MS.data[:,chan,pol]=MS.data[:,chan,pol] * f.reshape((MS.nrows,)) 63 | 64 | 65 | -------------------------------------------------------------------------------- /shapelets/phs/README.md: -------------------------------------------------------------------------------- 1 | A measurement set interface to perform phase rotation, originally written by Cyril Tasse 2 | 3 | -------------------------------------------------------------------------------- /shapelets/phs/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | A module interface to Measurement Set phase rotation functions 3 | """ 4 | 5 | import imp 6 | 7 | try: 8 | imp.find_module('casacore') 9 | casacore = True 10 | except ImportError: 11 | casacore = False 12 | 13 | if casacore: 14 | import ClassMS, ModRotate # these modules require casacore 15 | 16 | import ModColor, rad2hmsdms, reformat 17 | 18 | -------------------------------------------------------------------------------- /shapelets/phs/rad2hmsdms.py: -------------------------------------------------------------------------------- 1 | 2 | import numpy as np 3 | 4 | def rad2hmsdms(rad,Type="dec",deg=False): 5 | 6 | if deg==False: 7 | deg=rad*180/np.pi 8 | else: 9 | deg=rad 10 | 11 | strsgn="+" 12 | if Type=="ra": 13 | deg/=15. 14 | strsgn="" 15 | 16 | if np.sign(deg)==-1.: strsgn="-" 17 | deg=np.abs(deg) 18 | degd=np.int(deg) 19 | degms=(deg-degd)*60. 20 | degm=np.int(degms) 21 | degs=((degms-degm)*60) 22 | return "%s%2.2i %2.2i %06.3f"%(strsgn,degd,degm,degs) -------------------------------------------------------------------------------- /shapelets/phs/reformat.py: -------------------------------------------------------------------------------- 1 | def reformat(ssin,slash=True,LastSlash=True): 2 | ss=ssin.split("/") 3 | ss=filter (lambda a: a != "", ss) 4 | ss="/".join(ss)+"/" 5 | if ssin[0]=="/": ss="/"+ss 6 | if not(slash): 7 | ss=ss[1:-1] 8 | if not(LastSlash): 9 | if ss[-1]=="/": ss=ss[0:-1] 10 | return ss -------------------------------------------------------------------------------- /shapelets/shapelet.py: -------------------------------------------------------------------------------- 1 | """ 2 | Functions for Shapelet related operations 3 | """ 4 | 5 | import sys 6 | 7 | import numpy as np 8 | from scipy.misc import factorial 9 | from scipy import special 10 | 11 | #TODO: hermite 2d, round gaussian? 12 | #TODO: Fourier transform 13 | ######################################################### 14 | #def polar2cart(): 15 | # """Convert a set of polar coefficients to Cartesian coefficients [manual eq. 1.27] 16 | # """ 17 | 18 | def hermite2d(n0,n1): 19 | """Return a n0 x n1 order 2D Hermite polynomial""" 20 | h0=special.hermite(n0) 21 | h1=special.hermite(n1) 22 | return [h0,h1] 23 | 24 | def laguerre(n0,m0): 25 | """Return a generalized Laguerre polynomial L^(|m|)_((n-|m|)/2)(x)""" 26 | l0=special.genlaguerre(n=(n0-np.abs(m0))/2,alpha=np.abs(m0)) 27 | return l0 28 | 29 | def rotMatrix(phi): 30 | """2D Cartesian rotation matrix (radians)""" 31 | return np.matrix([[np.cos(phi),-1.*np.sin(phi)],[np.sin(phi),np.cos(phi)]]) 32 | 33 | def basis2d(n0,n1,beta=[1.,1.],phi=0.,fourier=False): 34 | """2d dimensionless Cartesian basis function 35 | phi: rotation angle 36 | fourier: return the Fourier transformed version of the function 37 | """ 38 | b=hermite2d(n0,n1) 39 | m=rotMatrix(phi) 40 | phs=[1.,1.] 41 | if fourier: 42 | beta=[1./beta[0],1./beta[1]] 43 | phs=[1j**(n0),1j**(n1)] 44 | b[0]*=((2**n0)*(np.pi**(.5))*factorial(n0))**(-.5)*phs[0] 45 | exp0=lambda x: beta[0] * b[0](x) * np.exp(-.5*(x**2)) 46 | b[1]*=((2**n1)*(np.pi**(.5))*factorial(n1))**(-.5)*phs[1] 47 | exp1=lambda x: beta[1] * b[1](x) * np.exp(-.5*(x**2)) 48 | 49 | return lambda y,x: exp0(m[0,0]*y+m[0,1]*x)*exp1(m[1,0]*y+m[1,1]*x) 50 | 51 | def dimBasis2d(n0,n1,beta=[1.,1.],phi=0.,fourier=False): 52 | """2d dimensional Cartesian basis function of characteristic size beta 53 | phi: rotation angle 54 | fourier: return the Fourier transformed version of the function 55 | """ 56 | b=hermite2d(n0,n1) 57 | m=rotMatrix(phi) 58 | phs=[1.,1.] 59 | if fourier: 60 | beta=[1./beta[0],1./beta[1]] 61 | phs=[1j**(n0),1j**(n1)] 62 | b[0]*=(beta[0]**(-.5))*(((2**n0)*(np.pi**(.5))*factorial(n0))**(-.5))*phs[0] 63 | exp0=lambda x: b[0](x/beta[0]) * np.exp(-.5*((x/beta[0])**2)) 64 | b[1]*=(beta[1]**(-.5))*(((2**n1)*(np.pi**(.5))*factorial(n1))**(-.5))*phs[1] 65 | exp1=lambda x: b[1](x/beta[1]) * np.exp(-.5*((x/beta[1])**2)) 66 | 67 | return lambda y,x: exp0(m[0,0]*y+m[0,1]*x)*exp1(m[1,0]*y+m[1,1]*x) 68 | 69 | #TODO: make into an elliptical form? 70 | #TODO: fourier transform is not quite correct 71 | def polarDimBasis(n0,m0,beta=1.,phi=0.,fourier=False): 72 | """Polar dimensional basis function based on Laguerre polynomials of characteristic size beta 73 | phi: rotation angle 74 | fourier: return the Fourier transformed version of the function 75 | """ 76 | if len(beta)==1: beta=[beta,beta] 77 | phs=1. 78 | if fourier: 79 | beta=[1./beta[0],1./beta[1]] 80 | phs=1j**(n0+m0) 81 | b0=laguerre(n0,m0) 82 | norm=(((-1.)**((n0-np.abs(m0))/2))/np.sqrt(beta[0]**(np.abs(m0)+1)*beta[1]**(np.abs(m0)+1)))*((float(factorial(int((n0-np.abs(m0))/2)))/float(factorial(int((n0+np.abs(m0))/2))))**.5)*phs 83 | exp0=lambda r,th: norm * r**(np.abs(m0)) * b0((r**2.)/(beta[0]*beta[1])) * np.exp(-.5*(r**2.)/(beta[0]*beta[1])) * np.exp(-1j*m0*(th+phi)) 84 | return exp0 85 | 86 | def polarArray(xc,size,rot=0.): 87 | """Return arrays of shape 'size' with radius and theta values centered on xc 88 | rot: radians in which to rotate the shapelet 89 | """ 90 | ry=np.array(range(0,size[0]),dtype=float)-xc[0] 91 | rx=np.array(range(0,size[1]),dtype=float)-xc[1] 92 | yy=np.reshape(np.tile(rx,size[0]),(size[0],size[1])) 93 | xx=np.reshape(np.tile(ry,size[1]),(size[1],size[0])) 94 | rExp = lambda y,x: np.sqrt(np.square(y) + np.square(x)) 95 | thExp = lambda y,x: np.arctan2(y,x)+rot 96 | return rExp(yy,xx.T), thExp(yy,xx.T) 97 | 98 | def cartArray(xc,size): 99 | """Return arrays of shape 'size' with y,x values centered on xc 100 | """ 101 | ry=np.array(range(0,size[0]),dtype=float)-xc[0] 102 | rx=np.array(range(0,size[1]),dtype=float)-xc[1] 103 | yy=np.reshape(np.tile(ry,size[1]),(size[0],size[1])) 104 | xx=np.reshape(np.tile(rx,size[0]),(size[1],size[0])) 105 | return yy.T,xx 106 | 107 | def xy2Grid(ry,rx): 108 | """Convert a range of x and y to a grid of shape (len(x),len(y))""" 109 | yy=np.reshape(np.tile(ry,len(rx)),(len(rx),len(ry))) 110 | xx=np.reshape(np.tile(rx,len(ry)),(len(ry),len(rx))) 111 | return yy.T,xx 112 | 113 | def xy2rthGrid(ry,rx): 114 | """Convert a range of y and x to r,th arrays of shape (len(y),len(x))""" 115 | yy=np.reshape(np.tile(ry,len(rx)),(len(rx),len(ry))) 116 | xx=np.reshape(np.tile(rx,len(ry)),(len(ry),len(rx))) 117 | rExp = lambda y,x: np.sqrt(np.square(y) + np.square(x)) 118 | thExp = lambda y,x: np.arctan2(y,x) 119 | return rExp(yy,xx.T), thExp(yy,xx.T) 120 | 121 | def rth2xy(r,th): 122 | """Convert r,theta array pair to an y,x pair""" 123 | y=r*np.cos(th) 124 | x=r*np.sin(th) 125 | return y,x 126 | 127 | def xyRotate(ry,rx,rot=0.): 128 | """Apply a rotation(radians) to an set of Y,Y coordinates""" 129 | r0,th0=xy2rthGrid(ry,rx) 130 | th0+=rot 131 | return rth2xy(r0,th0) 132 | 133 | def computeBasisPolar(b,r,th): 134 | """Compute the values of a Polar Basis function b over the R and Theta range""" 135 | return b(r,th) 136 | 137 | def computeBasisPolarAtom(b,r,th): 138 | """Compute the polar basis function b in the position (rad,theta)""" 139 | return b(r,th) 140 | 141 | def computeBasis2d(b,yy,xx): 142 | """Compute the values of a 2D Basis function b for (yy,xx)""" 143 | return b(yy,xx) 144 | 145 | def computeBasis2dAtom(b,y,x): 146 | """Compute the basis function b in the position (y,x), x and y can be arrays""" 147 | return b(y,x) 148 | 149 | if __name__ == "__main__": 150 | 151 | print '============================================' 152 | print 'Testing shapelets module:' 153 | print '============================================' 154 | tc=0 155 | te=0 156 | 157 | #hermite2d(n0,n1): 158 | tc+=1 159 | try: 160 | h0,h1=hermite2d(3,4) 161 | print 'hermite:', type(h0), type(h1) 162 | except: 163 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 164 | te+=1 165 | 166 | #laguerre(n0,m0): 167 | tc+=1 168 | try: 169 | l0=laguerre(3,3) 170 | print 'laguerre:', type(l0) 171 | except: 172 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 173 | te+=1 174 | 175 | #rotMatrix(phi): 176 | tc+=1 177 | try: 178 | print rotMatrix(np.pi/4.) 179 | except: 180 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 181 | te+=1 182 | 183 | #xyRotate(rx,ry,rot=0.): 184 | tc+=1 185 | try: 186 | xp,yp=xyRotate(np.array([1.]),np.array([0.]),rot=np.pi/4.) 187 | print xp,yp 188 | except: 189 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 190 | te+=1 191 | 192 | #basis2d(n0,n1,beta=[1.,1.],phi=0.): 193 | tc+=1 194 | try: 195 | b=basis2d(3,4,beta=[1.,1.],phi=np.pi/4.) 196 | print b(2.,3.5) 197 | except: 198 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 199 | te+=1 200 | 201 | #dimBasis2d(n0,n1,beta=[1.,1.],phi=0.): 202 | tc+=1 203 | try: 204 | b=dimBasis2d(3,4,beta=[1.,1.],phi=np.pi/4.) 205 | print b(2.,3.5) 206 | except: 207 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 208 | te+=1 209 | 210 | #polarDimBasis(n0,m0,beta=[1.,1.],phi=0.): 211 | tc+=1 212 | try: 213 | b=polarDimBasis(3,3,beta=[1.,1.],phi=np.pi/4.) 214 | print b(3.5,np.pi/8.) 215 | except: 216 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 217 | te+=1 218 | 219 | #polarArray(xc,size,rot=0.): 220 | tc+=1 221 | try: 222 | r,th=polarArray([0.,0.],[15,20],rot=0.) 223 | print r.shape, th.shape 224 | except: 225 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 226 | te+=1 227 | 228 | #cartArray(xc,size): 229 | tc+=1 230 | try: 231 | x,y=cartArray([6.,7.],[15,20]) 232 | print x.shape, y.shape 233 | except: 234 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 235 | te+=1 236 | 237 | #xy2rthGrid(rx,ry): 238 | tc+=1 239 | try: 240 | r,th=xy2rthGrid(np.arange(10),np.arange(10)) 241 | print r.shape, th.shape 242 | except: 243 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 244 | te+=1 245 | 246 | #rth2xy(r,th): 247 | tc+=1 248 | try: 249 | x,y=rth2xy(np.random.randn(10),2.*np.pi*np.random.rand(10)) 250 | print x.shape,y.shape 251 | except: 252 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 253 | te+=1 254 | 255 | #computeBasisPolar(b,r,th): 256 | tc+=1 257 | try: 258 | r,th=polarArray([0.,0.],[15,20],rot=0.) 259 | b=polarDimBasis(3,3,beta=[1.,1.],phi=np.pi/4.) 260 | bval=computeBasisPolar(b,r,th) 261 | print bval.shape 262 | except: 263 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 264 | te+=1 265 | 266 | #computeBasisPolarAtom(b,r,th): 267 | tc+=1 268 | try: 269 | b=polarDimBasis(3,3,beta=[1.,1.],phi=np.pi/4.) 270 | bval=computeBasisPolar(b,5.,np.pi/8.) 271 | print bval 272 | except: 273 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 274 | te+=1 275 | 276 | #computeBasis2d(b,rx,ry): 277 | tc+=1 278 | try: 279 | rx,ry=cartArray([6.,7.],[15,20]) 280 | b=dimBasis2d(3,4,beta=[1.,1.],phi=np.pi/4.) 281 | bval=computeBasis2d(b,rx,ry) 282 | print bval.shape 283 | except: 284 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 285 | te+=1 286 | 287 | #computeBasis2dAtom(b,x,y): 288 | tc+=1 289 | try: 290 | b=dimBasis2d(3,4,beta=[1.,1.],phi=np.pi/4.) 291 | bval=computeBasis2dAtom(b,np.random.randn(10),np.random.randn(10)) 292 | print bval.shape 293 | except: 294 | print 'Test failed (%i):'%tc, sys.exc_info()[0] 295 | te+=1 296 | 297 | print '============================================' 298 | print '%i of %i tests succeeded'%(tc-te,tc) 299 | print '============================================' 300 | -------------------------------------------------------------------------------- /shapelets/tests.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | import nose 4 | import numpy as np 5 | 6 | from nose.tools import assert_equal, assert_not_equal, assert_raises, raises, \ 7 | assert_almost_equal, assert_true, assert_false, assert_in, assert_less_equal, \ 8 | assert_greater_equal 9 | from numpy.testing import assert_allclose 10 | 11 | import fshapelet as fsh 12 | import shapelet as sh 13 | import cshapelet as csh 14 | import decomp 15 | 16 | 17 | def setup(): 18 | global r, th, xc, beta, PB_DIM 19 | xc = (100, 130) 20 | beta = 100. 21 | PB_DIM = (300, 200) 22 | r, th = sh.polarArray(xc, PB_DIM) 23 | 24 | def test_polar_vectors_numexpr(): 25 | """ Check that the the version with numexpr generates the same output """ 26 | for nn in range(5): 27 | for mm in range(-1*nn,nn+1): 28 | if (nn%2==0 and abs(mm)%2==0) or (nn%2==1 and abs(mm)%2==1): 29 | res0 = fsh.polar_basis_L(r,nn,mm, beta)*np.exp(-1j*th*mm) 30 | res1 = sh.polarDimBasis(nn,mm, beta)(r,th) 31 | yield assert_allclose, res0, res1, 1e-7, 1e-9 32 | 33 | def test_polar_basis_numexpr(): 34 | nmax = 10 35 | res0 = fsh.genPolarBasisMatrix(beta, nmax, r, th) 36 | res1 = decomp.genPolarBasisMatrix(beta, nmax, r, th) 37 | yield assert_allclose, res0, res1, 1e-7, 1e-9 38 | 39 | def test_polar_basis_cython(): 40 | nmax = 10 41 | res0 = csh.genPolarBasisMatrix(beta, nmax, r, th) 42 | res1 = decomp.genPolarBasisMatrix(beta, nmax, r, th) 43 | yield assert_allclose, res0, res1, 1e-7, 1e-9 44 | 45 | def test_polarArray(): 46 | xc = (100., 200.) 47 | res0 = fsh.polarArray(xc, PB_DIM) 48 | res1 = sh.polarArray(xc, PB_DIM) 49 | yield assert_allclose, res0, res1, 1e-7, 1e-9 50 | 51 | 52 | 53 | 54 | 55 | --------------------------------------------------------------------------------