├── figures ├── plot_G29.png ├── plot_SgrB2.png └── my_emission_1_1.png ├── .gitmodules ├── contpy ├── tests │ ├── setup_package.py │ ├── __init__.py │ └── coveragerc ├── __init__.py ├── conftest.py ├── fits_cutout.py ├── _astropy_init.py └── contpy.py ├── statcont ├── tests │ ├── setup_package.py │ ├── __init__.py │ └── coveragerc ├── __init__.py ├── conftest.py ├── _astropy_init.py ├── fits_utils.py ├── statcont.py └── cont_finding.py ├── docs ├── _templates │ └── autosummary │ │ ├── base.rst │ │ ├── class.rst │ │ └── module.rst ├── index.rst ├── Makefile ├── make.bat └── conf.py ├── pyproject.toml ├── .gitignore ├── tests ├── include_noise.py ├── include_slope.py └── noise │ ├── my_narrow-range_n06.dat │ └── my_narrow-range_n17.dat ├── MANIFEST.in ├── setup.cfg ├── .travis.yml ├── ez_setup.py └── README.md /figures/plot_G29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radio-astro-tools/statcont/HEAD/figures/plot_G29.png -------------------------------------------------------------------------------- /figures/plot_SgrB2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radio-astro-tools/statcont/HEAD/figures/plot_SgrB2.png -------------------------------------------------------------------------------- /figures/my_emission_1_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radio-astro-tools/statcont/HEAD/figures/my_emission_1_1.png -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "astropy_helpers"] 2 | path = astropy_helpers 3 | url = https://github.com/astropy/astropy-helpers.git 4 | -------------------------------------------------------------------------------- /contpy/tests/setup_package.py: -------------------------------------------------------------------------------- 1 | def get_package_data(): 2 | return { 3 | _ASTROPY_PACKAGE_NAME_ + '.tests': ['coveragerc']} 4 | -------------------------------------------------------------------------------- /statcont/tests/setup_package.py: -------------------------------------------------------------------------------- 1 | def get_package_data(): 2 | return { 3 | _ASTROPY_PACKAGE_NAME_ + '.tests': ['coveragerc']} 4 | -------------------------------------------------------------------------------- /contpy/tests/__init__.py: -------------------------------------------------------------------------------- 1 | # Licensed under a 3-clause BSD style license - see LICENSE.rst 2 | """ 3 | This packages contains affiliated package tests. 4 | """ 5 | -------------------------------------------------------------------------------- /statcont/tests/__init__.py: -------------------------------------------------------------------------------- 1 | # Licensed under a 3-clause BSD style license - see LICENSE.rst 2 | """ 3 | This packages contains affiliated package tests. 4 | """ 5 | -------------------------------------------------------------------------------- /docs/_templates/autosummary/base.rst: -------------------------------------------------------------------------------- 1 | {% extends "autosummary_core/base.rst" %} 2 | {# The template this is inherited from is in astropy/sphinx/ext/templates/autosummary_core. If you want to modify this template, it is strongly recommended that you still inherit from the astropy template. #} -------------------------------------------------------------------------------- /docs/_templates/autosummary/class.rst: -------------------------------------------------------------------------------- 1 | {% extends "autosummary_core/class.rst" %} 2 | {# The template this is inherited from is in astropy/sphinx/ext/templates/autosummary_core. If you want to modify this template, it is strongly recommended that you still inherit from the astropy template. #} -------------------------------------------------------------------------------- /docs/_templates/autosummary/module.rst: -------------------------------------------------------------------------------- 1 | {% extends "autosummary_core/module.rst" %} 2 | {# The template this is inherited from is in astropy/sphinx/ext/templates/autosummary_core. If you want to modify this template, it is strongly recommended that you still inherit from the astropy template. #} -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools", 3 | "setuptools_scm", 4 | "wheel"] 5 | build-backend = 'setuptools.build_meta' 6 | 7 | [tool.setuptools] 8 | py-modules = ['statcont'] 9 | packages = ['statcont'] 10 | 11 | [project] 12 | name = "statcont" 13 | dynamic = ['version', 'authors', 'dependencies', 'readme', 'description', 'requires-python', 'optional-dependencies', 'license'] 14 | 15 | [project.scripts] 16 | statcont = "statcont:main" -------------------------------------------------------------------------------- /contpy/__init__.py: -------------------------------------------------------------------------------- 1 | # Licensed under a 3-clause BSD style license - see LICENSE.rst 2 | 3 | """ 4 | This is an Astropy affiliated package. 5 | """ 6 | 7 | # Affiliated packages may add whatever they like to this file, but 8 | # should keep this content at the top. 9 | # ---------------------------------------------------------------------------- 10 | from ._astropy_init import * 11 | # ---------------------------------------------------------------------------- 12 | 13 | # For egg_info test builds to pass, put package imports here. 14 | if not _ASTROPY_SETUP_: 15 | from .contpy import * 16 | -------------------------------------------------------------------------------- /statcont/__init__.py: -------------------------------------------------------------------------------- 1 | # Licensed under a 3-clause BSD style license - see LICENSE.rst 2 | 3 | """ 4 | This is an Astropy affiliated package. 5 | """ 6 | 7 | # Affiliated packages may add whatever they like to this file, but 8 | # should keep this content at the top. 9 | # ---------------------------------------------------------------------------- 10 | from ._astropy_init import * 11 | # ---------------------------------------------------------------------------- 12 | 13 | # For egg_info test builds to pass, put package imports here. 14 | if not _ASTROPY_SETUP_: 15 | from .statcont import * 16 | -------------------------------------------------------------------------------- /contpy/tests/coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | source = {packagename} 3 | omit = 4 | {packagename}/_astropy_init* 5 | {packagename}/conftest* 6 | {packagename}/cython_version* 7 | {packagename}/setup_package* 8 | {packagename}/*/setup_package* 9 | {packagename}/*/*/setup_package* 10 | {packagename}/tests/* 11 | {packagename}/*/tests/* 12 | {packagename}/*/*/tests/* 13 | {packagename}/version* 14 | 15 | [report] 16 | exclude_lines = 17 | # Have to re-enable the standard pragma 18 | pragma: no cover 19 | 20 | # Don't complain about packages we have installed 21 | except ImportError 22 | 23 | # Don't complain if tests don't hit assertions 24 | raise AssertionError 25 | raise NotImplementedError 26 | 27 | # Don't complain about script hooks 28 | def main\(.*\): 29 | 30 | # Ignore branches that don't pertain to this version of Python 31 | pragma: py{ignore_python_version} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled files 2 | *.py[cod] 3 | *.a 4 | *.o 5 | *.so 6 | __pycache__ 7 | 8 | # Ignore .c files by default to avoid including generated code. If you want to 9 | # add a non-generated .c extension, use `git add -f filename.c`. 10 | *.c 11 | 12 | # Other generated files 13 | */version.py 14 | */cython_version.py 15 | htmlcov 16 | .coverage 17 | MANIFEST 18 | .ipynb_checkpoints 19 | 20 | # Sphinx 21 | docs/api 22 | docs/_build 23 | 24 | # Eclipse editor project files 25 | .project 26 | .pydevproject 27 | .settings 28 | 29 | # Pycharm editor project files 30 | .idea 31 | 32 | # Packages/installer info 33 | *.egg 34 | *.egg-info 35 | dist 36 | build 37 | eggs 38 | parts 39 | bin 40 | var 41 | sdist 42 | develop-eggs 43 | .installed.cfg 44 | distribute-*.tar.gz 45 | 46 | # Other 47 | .cache 48 | .tox 49 | .*.sw[op] 50 | *~ 51 | .project 52 | .pydevproject 53 | .settings 54 | 55 | # Mac OSX 56 | .DS_Store 57 | -------------------------------------------------------------------------------- /statcont/tests/coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | source = {packagename} 3 | omit = 4 | {packagename}/_astropy_init* 5 | {packagename}/conftest* 6 | {packagename}/cython_version* 7 | {packagename}/setup_package* 8 | {packagename}/*/setup_package* 9 | {packagename}/*/*/setup_package* 10 | {packagename}/tests/* 11 | {packagename}/*/tests/* 12 | {packagename}/*/*/tests/* 13 | {packagename}/version* 14 | 15 | [report] 16 | exclude_lines = 17 | # Have to re-enable the standard pragma 18 | pragma: no cover 19 | 20 | # Don't complain about packages we have installed 21 | except ImportError 22 | 23 | # Don't complain if tests don't hit assertions 24 | raise AssertionError 25 | raise NotImplementedError 26 | 27 | # Don't complain about script hooks 28 | def main\(.*\): 29 | 30 | # Ignore branches that don't pertain to this version of Python 31 | pragma: py{ignore_python_version} -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | STATCONT documentation 2 | ---------------------- 3 | 4 | To be implemented. For now, just see the readme. 5 | 6 | 7 | The web page (https://hera.ph1.uni-koeln.de/~sanchez/statcont) includes 8 | more complete instructions. 9 | 10 | Test data are available `here 11 | `_ 12 | 13 | 14 | Interactive Example 15 | ------------------- 16 | 17 | To reproduce something like figure 13 in `the paper 18 | `_, you can do the 19 | following (which is based off of the ``test_cases`` data linked above): 20 | 21 | .. code:: python 22 | 23 | from astropy.io import fits 24 | from statcont import cont_finding 25 | 26 | data = fits.getdata('SYNTHETIC_cube.fits') 27 | sigmaclip_flux_prev, sigmaclip_flux, sigmaclip_noise, filtered_data = cont_finding.c_sigmaclip(data, 1.5, 0) 28 | 29 | import pylab as pl 30 | pl.plot(data[:,28,43], 'k') 31 | pl.plot(filtered_data[:,28,43], 'r') 32 | 33 | which will show the "filtered data", i.e., the data used for the continuum 34 | measurement, in red overlaid on the black spectrum. 35 | -------------------------------------------------------------------------------- /tests/include_noise.py: -------------------------------------------------------------------------------- 1 | #!/usr/bni/env python 2 | 3 | import os 4 | import numpy as np 5 | import astropy.io.ascii as ascii 6 | 7 | inpfiles = ['my_few-lines', 'my_emission', 'my_absorption', 'my_absorption_emission', 'my_narrow-range', 'my_broad-lines', 'my_extragalactic'] 8 | inpnoises = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25] 9 | 10 | for inpnoise in inpnoises: 11 | 12 | for inpfile in inpfiles: 13 | 14 | f = open(inpfile+'.dat', 'r') 15 | 16 | lflux = [] 17 | freqs = [] 18 | counter = 0 19 | for line in f: 20 | counter = counter+1 21 | freqs.append(float(line.split()[0])) 22 | lflux.append(float(line.split()[1])) 23 | flux = np.array(lflux) 24 | freq = np.array(freqs) 25 | noise = np.random.normal(loc=0.0, scale=inpnoise, size=counter) 26 | 27 | 28 | if (inpnoise < 10): 29 | ascii.write((freqs, flux+noise), output='noise/'+inpfile+'_n0'+str(inpnoise)+'.dat', format='no_header') 30 | if (inpnoise >= 10): 31 | ascii.write((freqs, flux+noise), output='noise/'+inpfile+'_n'+str(inpnoise)+'.dat', format='no_header') 32 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.rst 2 | include CHANGES.rst 3 | 4 | include ez_setup.py 5 | include ah_bootstrap.py 6 | include setup.cfg 7 | 8 | recursive-include packagename *.pyx *.c *.pxd 9 | recursive-include docs * 10 | recursive-include licenses * 11 | recursive-include cextern * 12 | recursive-include scripts * 13 | 14 | prune build 15 | prune docs/_build 16 | prune docs/api 17 | 18 | 19 | # the next few stanzas are for astropy_helpers. It's derived from the 20 | # astropy_helpers/MANIFEST.in, but requires additional includes for the actual 21 | # package directory and egg-info. 22 | 23 | include astropy_helpers/README.rst 24 | include astropy_helpers/CHANGES.rst 25 | include astropy_helpers/LICENSE.rst 26 | recursive-include astropy_helpers/licenses * 27 | 28 | include astropy_helpers/ez_setup.py 29 | include astropy_helpers/ah_bootstrap.py 30 | 31 | recursive-include astropy_helpers/astropy_helpers *.py *.pyx *.c *.h 32 | recursive-include astropy_helpers/astropy_helpers.egg-info * 33 | # include the sphinx stuff with "*" because there are css/html/rst/etc. 34 | recursive-include astropy_helpers/astropy_helpers/sphinx * 35 | 36 | prune astropy_helpers/build 37 | prune astropy_helpers/astropy_helpers/tests 38 | 39 | 40 | global-exclude *.pyc *.o 41 | -------------------------------------------------------------------------------- /tests/include_slope.py: -------------------------------------------------------------------------------- 1 | #!/usr/bni/env python 2 | 3 | import os 4 | import numpy as np 5 | import astropy.io.ascii as ascii 6 | 7 | inpfiles = ['my_few-lines', 'my_emission', 'my_absorption', 'my_absorption_emission', 'my_narrow-range', 'my_broad-lines', 'my_extragalactic'] 8 | inpnoises = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25] 9 | 10 | #inpfiles = ['my_few-lines'] 11 | #inpnoises = [1] 12 | 13 | my_slope = 10.0 14 | 15 | for inpnoise in inpnoises: 16 | 17 | for inpfile in inpfiles: 18 | 19 | f = open(inpfile+'.dat', 'r') 20 | 21 | lflux = [] 22 | freqs = [] 23 | counter = 0 24 | for line in f: 25 | counter = counter+1 26 | freqs.append(float(line.split()[0])) 27 | lflux.append(float(line.split()[1])) 28 | flux = np.array(lflux) 29 | freq = np.array(freqs) 30 | for ival in range(0,len(freq)): 31 | flux[ival] = flux[ival]+(my_slope*freq[ival]-my_slope*freq[0]) 32 | noise = np.random.normal(loc=0.0, scale=inpnoise, size=counter) 33 | 34 | 35 | if (inpnoise < 10): 36 | ascii.write((freqs, flux+noise), output='slope/'+inpfile+'_n0'+str(inpnoise)+'_slope.dat', format='no_header', overwrite=True) 37 | if (inpnoise >= 10): 38 | ascii.write((freqs, flux+noise), output='slope/'+inpfile+'_n'+str(inpnoise)+'_slope.dat', format='no_header', overwrite=True) 39 | -------------------------------------------------------------------------------- /contpy/conftest.py: -------------------------------------------------------------------------------- 1 | # this contains imports plugins that configure py.test for astropy tests. 2 | # by importing them here in conftest.py they are discoverable by py.test 3 | # no matter how it is invoked within the source tree. 4 | 5 | from astropy.tests.pytest_plugins import * 6 | 7 | ## Uncomment the following line to treat all DeprecationWarnings as 8 | ## exceptions 9 | # enable_deprecations_as_exceptions() 10 | 11 | ## Uncomment and customize the following lines to add/remove entries from 12 | ## the list of packages for which version numbers are displayed when running 13 | ## the tests. Making it pass for KeyError is essential in some cases when 14 | ## the package uses other astropy affiliated packages. 15 | # try: 16 | # PYTEST_HEADER_MODULES['Astropy'] = 'astropy' 17 | # PYTEST_HEADER_MODULES['scikit-image'] = 'skimage' 18 | # del PYTEST_HEADER_MODULES['h5py'] 19 | # except (NameError, KeyError): # NameError is needed to support Astropy < 1.0 20 | # pass 21 | 22 | ## Uncomment the following lines to display the version number of the 23 | ## package rather than the version number of Astropy in the top line when 24 | ## running the tests. 25 | # import os 26 | # 27 | ## This is to figure out the affiliated package version, rather than 28 | ## using Astropy's 29 | # try: 30 | # from .version import version 31 | # except ImportError: 32 | # version = 'dev' 33 | # 34 | # try: 35 | # packagename = os.path.basename(os.path.dirname(__file__)) 36 | # TESTED_VERSIONS[packagename] = version 37 | # except NameError: # Needed to support Astropy <= 1.0.0 38 | # pass 39 | -------------------------------------------------------------------------------- /statcont/conftest.py: -------------------------------------------------------------------------------- 1 | # this contains imports plugins that configure py.test for astropy tests. 2 | # by importing them here in conftest.py they are discoverable by py.test 3 | # no matter how it is invoked within the source tree. 4 | 5 | from astropy.tests.pytest_plugins import * 6 | 7 | ## Uncomment the following line to treat all DeprecationWarnings as 8 | ## exceptions 9 | # enable_deprecations_as_exceptions() 10 | 11 | ## Uncomment and customize the following lines to add/remove entries from 12 | ## the list of packages for which version numbers are displayed when running 13 | ## the tests. Making it pass for KeyError is essential in some cases when 14 | ## the package uses other astropy affiliated packages. 15 | # try: 16 | # PYTEST_HEADER_MODULES['Astropy'] = 'astropy' 17 | # PYTEST_HEADER_MODULES['scikit-image'] = 'skimage' 18 | # del PYTEST_HEADER_MODULES['h5py'] 19 | # except (NameError, KeyError): # NameError is needed to support Astropy < 1.0 20 | # pass 21 | 22 | ## Uncomment the following lines to display the version number of the 23 | ## package rather than the version number of Astropy in the top line when 24 | ## running the tests. 25 | # import os 26 | # 27 | ## This is to figure out the affiliated package version, rather than 28 | ## using Astropy's 29 | # try: 30 | # from .version import version 31 | # except ImportError: 32 | # version = 'dev' 33 | # 34 | # try: 35 | # packagename = os.path.basename(os.path.dirname(__file__)) 36 | # TESTED_VERSIONS[packagename] = version 37 | # except NameError: # Needed to support Astropy <= 1.0.0 38 | # pass 39 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | name = statcont 3 | version = 0.0.dev 4 | description = Statistical continuum level determination for line-rich sources 5 | long_description = Statistical continuum level determination for line-rich sources 6 | author = Alvaro Sanchez-Monge 7 | author_email = betacygni@gmail.com 8 | license = BSD 9 | url = https://hera.ph1.uni-koeln.de/~sanchez/statcont 10 | edit_on_github = False 11 | github_project = radio-astro-tools/statcont 12 | install_requires = astropy scipy 13 | 14 | [build_docs] 15 | source-dir = docs 16 | build-dir = docs/_build 17 | all_files = 1 18 | 19 | [build_sphinx] 20 | source-dir = docs 21 | build-dir = docs/_build 22 | all_files = 1 23 | 24 | [upload_docs] 25 | upload-dir = docs/_build/html 26 | show-response = 1 27 | 28 | [tool:pytest] 29 | minversion = 6.0 30 | norecursedirs = build docs/_build 31 | testpaths = statcont docs 32 | doctest_plus = enabled 33 | astropy_header = true 34 | text_file_format = rst 35 | xfail_strict = true 36 | remote_data_strict = true 37 | addopts = --color=yes --doctest-rst --doctest-continue-on-failure 38 | filterwarnings = 39 | error 40 | 41 | [pycodestyle] 42 | 43 | # E402 module level import not at top of file 44 | # We need to ignore this as the .conf has to be set in the __init__.py 45 | # before the modules are imported. 46 | ignore = E402 47 | 48 | # Excluding files that are directly copied from the package template or 49 | # generated 50 | exclude = _astropy_init.py,version.py 51 | 52 | # E226 missing whitespace around operators 53 | # E402 module level import not at top of file 54 | # W503 line break before operator 55 | # Stricter settings for people who use flake8 in their editors 56 | [flake8] 57 | max-line-length = 120 58 | ignore = E226,E402,W503 59 | exclude = _astropy_init.py,version.py 60 | 61 | [coverage:run] 62 | omit = 63 | statcont/*_init* 64 | statcont/**/tests/* 65 | statcont/*setup* 66 | statcont/version* 67 | */statcont/*_init* 68 | */statcont/**/tests/* 69 | */statcont/*setup* 70 | */statcont/version* 71 | 72 | [entry_points] 73 | 74 | [options] 75 | 76 | python_requires = >=3.9 77 | 78 | install_requires= 79 | numpy>=1.20 80 | astropy>=5.0 81 | scipy 82 | matplotlib 83 | tests_require = 84 | pytest-doctestplus>=0.13 85 | pytest-astropy 86 | 87 | [options.extras_require] 88 | test= 89 | pytest-astropy 90 | matplotlib 91 | pytest-dependency 92 | pytest-rerunfailures 93 | docs= 94 | matplotlib 95 | sphinx-astropy>=1.5 96 | scipy 97 | -------------------------------------------------------------------------------- /contpy/fits_cutout.py: -------------------------------------------------------------------------------- 1 | import os 2 | import numpy 3 | import warnings 4 | import astropy.io 5 | 6 | ##===================================================================================================================== 7 | def cutout(filename, xc, yc, size, outfile): 8 | 9 | """ 10 | Inputs: 11 | filename - .fits filename 12 | xc,yc - x and y center coordinates in the fits files' coordinate system (CTYPE) 13 | size - size of the cutout in pixel 14 | outfile - output file 15 | """ 16 | 17 | if isinstance(filename, str): 18 | fitsfile = astropy.io.fits.open(filename) 19 | opened = True 20 | 21 | #get header information 22 | head = fitsfile[0].header.copy() 23 | ndim = head.get('NAXIS') 24 | cdelt1 = head.get('CDELT1') 25 | cdelt2 = head.get('CDELT2') 26 | nmax = head.get('NAXIS3') 27 | 28 | if cdelt1 is None or cdelt2 is None: 29 | raise Exception("Missing CD or CDELT keywords in header") 30 | 31 | xmin, xmax = numpy.max([0, xc - size / 2]), numpy.min([head['NAXIS1'], xc + size / 2]) 32 | ymin, ymax = numpy.max([0, yc - size / 2]), numpy.min([head['NAXIS2'], yc + size / 2]) 33 | 34 | if xmax < 0 or ymax < 0: 35 | raise ValueError("Max Coordinate is outside of map: %f, %f." % (xmax, ymax)) 36 | 37 | if ymin >= head.get('NAXIS2') or xmin >= head.get('NAXIS1'): 38 | raise ValueError("Min Coordinate is outside of map: %f, %f." % (xmin, ymin)) 39 | 40 | head['CRPIX1'] -= xmin 41 | head['CRPIX2'] -= ymin 42 | head['NAXIS1'] = int(xmax - xmin) 43 | head['NAXIS2'] = int(ymax - ymin) 44 | head['NAXIS3'] = 1 45 | 46 | if head.get('NAXIS1') == 0 or head.get('NAXIS2') == 0: 47 | raise ValueError("Map has a 0 dimension: %i, %i." % (head.get('NAXIS1'), head.get('NAXIS2'))) 48 | 49 | # copy data 50 | 51 | if ndim == 4: 52 | img = fitsfile[0].data[0:1, 0:nmax, ymin:ymax, xmin:xmax] 53 | if ndim == 3: 54 | img = fitsfile[0].data[0:nmax, ymin:ymax, xmin:xmax] 55 | newfile = astropy.io.fits.PrimaryHDU(data=img, header=head) 56 | ###ASM print 'Cut image %s with dims %s to %s. xrange: %f:%f, yrange: %f:%f' % (filename, fitsfile[0].data.shape, img.shape, xmin, xmax, ymin, ymax) 57 | ###ASM print 'New outputfile is %s' % outfile 58 | 59 | # output 60 | if isinstance(outfile, str): 61 | 62 | with warnings.catch_warnings(): 63 | warnings.simplefilter('ignore') 64 | 65 | newfile.writeto(outfile, clobber=True) 66 | 67 | if opened: 68 | fitsfile.close() 69 | 70 | ###ASM # export outfile to MIRIAD format; remove any existing file 71 | ###ASM os.system('rm -rf %s' % outfile.replace('.fits', '')) 72 | ###ASM os.system('fits op=xyin in=%s out=%s' % (outfile, outfile.replace('.fits', ''))) 73 | 74 | return newfile 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = _build 9 | 10 | # Internal variables. 11 | PAPEROPT_a4 = -D latex_paper_size=a4 12 | PAPEROPT_letter = -D latex_paper_size=letter 13 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 14 | 15 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest 16 | 17 | #This is needed with git because git doesn't create a dir if it's empty 18 | $(shell [ -d "_static" ] || mkdir -p _static) 19 | 20 | help: 21 | @echo "Please use \`make ' where is one of" 22 | @echo " html to make standalone HTML files" 23 | @echo " dirhtml to make HTML files named index.html in directories" 24 | @echo " singlehtml to make a single large HTML file" 25 | @echo " pickle to make pickle files" 26 | @echo " json to make JSON files" 27 | @echo " htmlhelp to make HTML files and a HTML help project" 28 | @echo " qthelp to make HTML files and a qthelp project" 29 | @echo " devhelp to make HTML files and a Devhelp project" 30 | @echo " epub to make an epub" 31 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 32 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 33 | @echo " text to make text files" 34 | @echo " man to make manual pages" 35 | @echo " changes to make an overview of all changed/added/deprecated items" 36 | @echo " linkcheck to check all external links for integrity" 37 | 38 | clean: 39 | -rm -rf $(BUILDDIR) 40 | -rm -rf api 41 | -rm -rf generated 42 | 43 | html: 44 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 45 | @echo 46 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 47 | 48 | dirhtml: 49 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 50 | @echo 51 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 52 | 53 | singlehtml: 54 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 55 | @echo 56 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 57 | 58 | pickle: 59 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 60 | @echo 61 | @echo "Build finished; now you can process the pickle files." 62 | 63 | json: 64 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 65 | @echo 66 | @echo "Build finished; now you can process the JSON files." 67 | 68 | htmlhelp: 69 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 70 | @echo 71 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 72 | ".hhp project file in $(BUILDDIR)/htmlhelp." 73 | 74 | qthelp: 75 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 76 | @echo 77 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 78 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 79 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Astropy.qhcp" 80 | @echo "To view the help file:" 81 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Astropy.qhc" 82 | 83 | devhelp: 84 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 85 | @echo 86 | @echo "Build finished." 87 | @echo "To view the help file:" 88 | @echo "# mkdir -p $$HOME/.local/share/devhelp/Astropy" 89 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Astropy" 90 | @echo "# devhelp" 91 | 92 | epub: 93 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 94 | @echo 95 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 96 | 97 | latex: 98 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 99 | @echo 100 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 101 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 102 | "(use \`make latexpdf' here to do that automatically)." 103 | 104 | latexpdf: 105 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 106 | @echo "Running LaTeX files through pdflatex..." 107 | make -C $(BUILDDIR)/latex all-pdf 108 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 109 | 110 | text: 111 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 112 | @echo 113 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 114 | 115 | man: 116 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 117 | @echo 118 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 119 | 120 | changes: 121 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 122 | @echo 123 | @echo "The overview file is in $(BUILDDIR)/changes." 124 | 125 | linkcheck: 126 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 127 | @echo 128 | @echo "Link check complete; look for any errors in the above output " \ 129 | "or in $(BUILDDIR)/linkcheck/output.txt." 130 | 131 | doctest: 132 | @echo "Run 'python setup.py test' in the root directory to run doctests " \ 133 | @echo "in the documentation." 134 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | REM Command file for Sphinx documentation 4 | 5 | if "%SPHINXBUILD%" == "" ( 6 | set SPHINXBUILD=sphinx-build 7 | ) 8 | set BUILDDIR=_build 9 | set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . 10 | if NOT "%PAPER%" == "" ( 11 | set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% 12 | ) 13 | 14 | if "%1" == "" goto help 15 | 16 | if "%1" == "help" ( 17 | :help 18 | echo.Please use `make ^` where ^ is one of 19 | echo. html to make standalone HTML files 20 | echo. dirhtml to make HTML files named index.html in directories 21 | echo. singlehtml to make a single large HTML file 22 | echo. pickle to make pickle files 23 | echo. json to make JSON files 24 | echo. htmlhelp to make HTML files and a HTML help project 25 | echo. qthelp to make HTML files and a qthelp project 26 | echo. devhelp to make HTML files and a Devhelp project 27 | echo. epub to make an epub 28 | echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter 29 | echo. text to make text files 30 | echo. man to make manual pages 31 | echo. changes to make an overview over all changed/added/deprecated items 32 | echo. linkcheck to check all external links for integrity 33 | echo. doctest to run all doctests embedded in the documentation if enabled 34 | goto end 35 | ) 36 | 37 | if "%1" == "clean" ( 38 | for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i 39 | del /q /s %BUILDDIR%\* 40 | goto end 41 | ) 42 | 43 | if "%1" == "html" ( 44 | %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html 45 | if errorlevel 1 exit /b 1 46 | echo. 47 | echo.Build finished. The HTML pages are in %BUILDDIR%/html. 48 | goto end 49 | ) 50 | 51 | if "%1" == "dirhtml" ( 52 | %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml 53 | if errorlevel 1 exit /b 1 54 | echo. 55 | echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. 56 | goto end 57 | ) 58 | 59 | if "%1" == "singlehtml" ( 60 | %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml 61 | if errorlevel 1 exit /b 1 62 | echo. 63 | echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. 64 | goto end 65 | ) 66 | 67 | if "%1" == "pickle" ( 68 | %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle 69 | if errorlevel 1 exit /b 1 70 | echo. 71 | echo.Build finished; now you can process the pickle files. 72 | goto end 73 | ) 74 | 75 | if "%1" == "json" ( 76 | %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json 77 | if errorlevel 1 exit /b 1 78 | echo. 79 | echo.Build finished; now you can process the JSON files. 80 | goto end 81 | ) 82 | 83 | if "%1" == "htmlhelp" ( 84 | %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp 85 | if errorlevel 1 exit /b 1 86 | echo. 87 | echo.Build finished; now you can run HTML Help Workshop with the ^ 88 | .hhp project file in %BUILDDIR%/htmlhelp. 89 | goto end 90 | ) 91 | 92 | if "%1" == "qthelp" ( 93 | %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp 94 | if errorlevel 1 exit /b 1 95 | echo. 96 | echo.Build finished; now you can run "qcollectiongenerator" with the ^ 97 | .qhcp project file in %BUILDDIR%/qthelp, like this: 98 | echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Astropy.qhcp 99 | echo.To view the help file: 100 | echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Astropy.ghc 101 | goto end 102 | ) 103 | 104 | if "%1" == "devhelp" ( 105 | %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp 106 | if errorlevel 1 exit /b 1 107 | echo. 108 | echo.Build finished. 109 | goto end 110 | ) 111 | 112 | if "%1" == "epub" ( 113 | %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub 114 | if errorlevel 1 exit /b 1 115 | echo. 116 | echo.Build finished. The epub file is in %BUILDDIR%/epub. 117 | goto end 118 | ) 119 | 120 | if "%1" == "latex" ( 121 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 122 | if errorlevel 1 exit /b 1 123 | echo. 124 | echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. 125 | goto end 126 | ) 127 | 128 | if "%1" == "text" ( 129 | %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text 130 | if errorlevel 1 exit /b 1 131 | echo. 132 | echo.Build finished. The text files are in %BUILDDIR%/text. 133 | goto end 134 | ) 135 | 136 | if "%1" == "man" ( 137 | %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man 138 | if errorlevel 1 exit /b 1 139 | echo. 140 | echo.Build finished. The manual pages are in %BUILDDIR%/man. 141 | goto end 142 | ) 143 | 144 | if "%1" == "changes" ( 145 | %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes 146 | if errorlevel 1 exit /b 1 147 | echo. 148 | echo.The overview file is in %BUILDDIR%/changes. 149 | goto end 150 | ) 151 | 152 | if "%1" == "linkcheck" ( 153 | %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck 154 | if errorlevel 1 exit /b 1 155 | echo. 156 | echo.Link check complete; look for any errors in the above output ^ 157 | or in %BUILDDIR%/linkcheck/output.txt. 158 | goto end 159 | ) 160 | 161 | if "%1" == "doctest" ( 162 | %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest 163 | if errorlevel 1 exit /b 1 164 | echo. 165 | echo.Testing of doctests in the sources finished, look at the ^ 166 | results in %BUILDDIR%/doctest/output.txt. 167 | goto end 168 | ) 169 | 170 | :end 171 | -------------------------------------------------------------------------------- /contpy/_astropy_init.py: -------------------------------------------------------------------------------- 1 | # Licensed under a 3-clause BSD style license - see LICENSE.rst 2 | 3 | __all__ = ['__version__', '__githash__', 'test'] 4 | 5 | # this indicates whether or not we are in the package's setup.py 6 | try: 7 | _ASTROPY_SETUP_ 8 | except NameError: 9 | from sys import version_info 10 | if version_info[0] >= 3: 11 | import builtins 12 | else: 13 | import __builtin__ as builtins 14 | builtins._ASTROPY_SETUP_ = False 15 | 16 | try: 17 | from .version import version as __version__ 18 | except ImportError: 19 | __version__ = '' 20 | try: 21 | from .version import githash as __githash__ 22 | except ImportError: 23 | __githash__ = '' 24 | 25 | # set up the test command 26 | def _get_test_runner(): 27 | import os 28 | from astropy.tests.helper import TestRunner 29 | return TestRunner(os.path.dirname(__file__)) 30 | 31 | def test(package=None, test_path=None, args=None, plugins=None, 32 | verbose=False, pastebin=None, remote_data=False, pep8=False, 33 | pdb=False, coverage=False, open_files=False, **kwargs): 34 | """ 35 | Run the tests using `py.test `__. A proper set 36 | of arguments is constructed and passed to `pytest.main`_. 37 | 38 | .. _py.test: http://pytest.org/latest/ 39 | .. _pytest.main: http://pytest.org/latest/builtin.html#pytest.main 40 | 41 | Parameters 42 | ---------- 43 | package : str, optional 44 | The name of a specific package to test, e.g. 'io.fits' or 'utils'. 45 | If nothing is specified all default tests are run. 46 | 47 | test_path : str, optional 48 | Specify location to test by path. May be a single file or 49 | directory. Must be specified absolutely or relative to the 50 | calling directory. 51 | 52 | args : str, optional 53 | Additional arguments to be passed to pytest.main_ in the ``args`` 54 | keyword argument. 55 | 56 | plugins : list, optional 57 | Plugins to be passed to pytest.main_ in the ``plugins`` keyword 58 | argument. 59 | 60 | verbose : bool, optional 61 | Convenience option to turn on verbose output from py.test_. Passing 62 | True is the same as specifying ``'-v'`` in ``args``. 63 | 64 | pastebin : {'failed','all',None}, optional 65 | Convenience option for turning on py.test_ pastebin output. Set to 66 | ``'failed'`` to upload info for failed tests, or ``'all'`` to upload 67 | info for all tests. 68 | 69 | remote_data : bool, optional 70 | Controls whether to run tests marked with @remote_data. These 71 | tests use online data and are not run by default. Set to True to 72 | run these tests. 73 | 74 | pep8 : bool, optional 75 | Turn on PEP8 checking via the `pytest-pep8 plugin 76 | `_ and disable normal 77 | tests. Same as specifying ``'--pep8 -k pep8'`` in ``args``. 78 | 79 | pdb : bool, optional 80 | Turn on PDB post-mortem analysis for failing tests. Same as 81 | specifying ``'--pdb'`` in ``args``. 82 | 83 | coverage : bool, optional 84 | Generate a test coverage report. The result will be placed in 85 | the directory htmlcov. 86 | 87 | open_files : bool, optional 88 | Fail when any tests leave files open. Off by default, because 89 | this adds extra run time to the test suite. Requires the 90 | `psutil `_ package. 91 | 92 | parallel : int, optional 93 | When provided, run the tests in parallel on the specified 94 | number of CPUs. If parallel is negative, it will use the all 95 | the cores on the machine. Requires the 96 | `pytest-xdist `_ plugin 97 | installed. Only available when using Astropy 0.3 or later. 98 | 99 | kwargs 100 | Any additional keywords passed into this function will be passed 101 | on to the astropy test runner. This allows use of test-related 102 | functionality implemented in later versions of astropy without 103 | explicitly updating the package template. 104 | 105 | """ 106 | test_runner = _get_test_runner() 107 | return test_runner.run_tests( 108 | package=package, test_path=test_path, args=args, 109 | plugins=plugins, verbose=verbose, pastebin=pastebin, 110 | remote_data=remote_data, pep8=pep8, pdb=pdb, 111 | coverage=coverage, open_files=open_files, **kwargs) 112 | 113 | if not _ASTROPY_SETUP_: 114 | import os 115 | from warnings import warn 116 | from astropy import config 117 | 118 | # add these here so we only need to cleanup the namespace at the end 119 | config_dir = None 120 | 121 | if not os.environ.get('ASTROPY_SKIP_CONFIG_UPDATE', False): 122 | config_dir = os.path.dirname(__file__) 123 | config_template = os.path.join(config_dir, __package__ + ".cfg") 124 | if os.path.isfile(config_template): 125 | try: 126 | config.configuration.update_default_config( 127 | __package__, config_dir, version=__version__) 128 | except TypeError as orig_error: 129 | try: 130 | config.configuration.update_default_config( 131 | __package__, config_dir) 132 | except config.configuration.ConfigurationDefaultMissingError as e: 133 | wmsg = (e.args[0] + " Cannot install default profile. If you are " 134 | "importing from source, this is expected.") 135 | warn(config.configuration.ConfigurationDefaultMissingWarning(wmsg)) 136 | del e 137 | except: 138 | raise orig_error 139 | -------------------------------------------------------------------------------- /statcont/_astropy_init.py: -------------------------------------------------------------------------------- 1 | # Licensed under a 3-clause BSD style license - see LICENSE.rst 2 | 3 | __all__ = ['__version__', '__githash__', 'test'] 4 | 5 | # this indicates whether or not we are in the package's setup.py 6 | try: 7 | _ASTROPY_SETUP_ 8 | except NameError: 9 | from sys import version_info 10 | if version_info[0] >= 3: 11 | import builtins 12 | else: 13 | import __builtin__ as builtins 14 | builtins._ASTROPY_SETUP_ = False 15 | 16 | try: 17 | from .version import version as __version__ 18 | except ImportError: 19 | __version__ = '' 20 | try: 21 | from .version import githash as __githash__ 22 | except ImportError: 23 | __githash__ = '' 24 | 25 | # set up the test command 26 | def _get_test_runner(): 27 | import os 28 | from astropy.tests.helper import TestRunner 29 | return TestRunner(os.path.dirname(__file__)) 30 | 31 | def test(package=None, test_path=None, args=None, plugins=None, 32 | verbose=False, pastebin=None, remote_data=False, pep8=False, 33 | pdb=False, coverage=False, open_files=False, **kwargs): 34 | """ 35 | Run the tests using `py.test `__. A proper set 36 | of arguments is constructed and passed to `pytest.main`_. 37 | 38 | .. _py.test: http://pytest.org/latest/ 39 | .. _pytest.main: http://pytest.org/latest/builtin.html#pytest.main 40 | 41 | Parameters 42 | ---------- 43 | package : str, optional 44 | The name of a specific package to test, e.g. 'io.fits' or 'utils'. 45 | If nothing is specified all default tests are run. 46 | 47 | test_path : str, optional 48 | Specify location to test by path. May be a single file or 49 | directory. Must be specified absolutely or relative to the 50 | calling directory. 51 | 52 | args : str, optional 53 | Additional arguments to be passed to pytest.main_ in the ``args`` 54 | keyword argument. 55 | 56 | plugins : list, optional 57 | Plugins to be passed to pytest.main_ in the ``plugins`` keyword 58 | argument. 59 | 60 | verbose : bool, optional 61 | Convenience option to turn on verbose output from py.test_. Passing 62 | True is the same as specifying ``'-v'`` in ``args``. 63 | 64 | pastebin : {'failed','all',None}, optional 65 | Convenience option for turning on py.test_ pastebin output. Set to 66 | ``'failed'`` to upload info for failed tests, or ``'all'`` to upload 67 | info for all tests. 68 | 69 | remote_data : bool, optional 70 | Controls whether to run tests marked with @remote_data. These 71 | tests use online data and are not run by default. Set to True to 72 | run these tests. 73 | 74 | pep8 : bool, optional 75 | Turn on PEP8 checking via the `pytest-pep8 plugin 76 | `_ and disable normal 77 | tests. Same as specifying ``'--pep8 -k pep8'`` in ``args``. 78 | 79 | pdb : bool, optional 80 | Turn on PDB post-mortem analysis for failing tests. Same as 81 | specifying ``'--pdb'`` in ``args``. 82 | 83 | coverage : bool, optional 84 | Generate a test coverage report. The result will be placed in 85 | the directory htmlcov. 86 | 87 | open_files : bool, optional 88 | Fail when any tests leave files open. Off by default, because 89 | this adds extra run time to the test suite. Requires the 90 | `psutil `_ package. 91 | 92 | parallel : int, optional 93 | When provided, run the tests in parallel on the specified 94 | number of CPUs. If parallel is negative, it will use the all 95 | the cores on the machine. Requires the 96 | `pytest-xdist `_ plugin 97 | installed. Only available when using Astropy 0.3 or later. 98 | 99 | kwargs 100 | Any additional keywords passed into this function will be passed 101 | on to the astropy test runner. This allows use of test-related 102 | functionality implemented in later versions of astropy without 103 | explicitly updating the package template. 104 | 105 | """ 106 | test_runner = _get_test_runner() 107 | return test_runner.run_tests( 108 | package=package, test_path=test_path, args=args, 109 | plugins=plugins, verbose=verbose, pastebin=pastebin, 110 | remote_data=remote_data, pep8=pep8, pdb=pdb, 111 | coverage=coverage, open_files=open_files, **kwargs) 112 | 113 | if not _ASTROPY_SETUP_: 114 | import os 115 | from warnings import warn 116 | from astropy import config 117 | 118 | # add these here so we only need to cleanup the namespace at the end 119 | config_dir = None 120 | 121 | if not os.environ.get('ASTROPY_SKIP_CONFIG_UPDATE', False): 122 | config_dir = os.path.dirname(__file__) 123 | config_template = os.path.join(config_dir, __package__ + ".cfg") 124 | if os.path.isfile(config_template): 125 | try: 126 | config.configuration.update_default_config( 127 | __package__, config_dir, version=__version__) 128 | except TypeError as orig_error: 129 | try: 130 | config.configuration.update_default_config( 131 | __package__, config_dir) 132 | except config.configuration.ConfigurationDefaultMissingError as e: 133 | wmsg = (e.args[0] + " Cannot install default profile. If you are " 134 | "importing from source, this is expected.") 135 | warn(config.configuration.ConfigurationDefaultMissingWarning(wmsg)) 136 | del e 137 | except: 138 | raise orig_error 139 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | 3 | python: 4 | - 2.7 5 | - 3.4 6 | - 3.5 7 | - 3.6 8 | 9 | # Setting sudo to false opts in to Travis-CI container-based builds. 10 | sudo: false 11 | 12 | # The apt packages below are needed for sphinx builds. A full list of packages 13 | # that can be included can be found here: 14 | # 15 | # https://github.com/travis-ci/apt-package-whitelist/blob/master/ubuntu-precise 16 | 17 | addons: 18 | apt: 19 | packages: 20 | - graphviz 21 | - texlive-latex-extra 22 | - dvipng 23 | 24 | env: 25 | global: 26 | 27 | # The following versions are the 'default' for tests, unless 28 | # overridden underneath. They are defined here in order to save having 29 | # to repeat them for all configurations. 30 | - NUMPY_VERSION=stable 31 | - ASTROPY_VERSION=stable 32 | - MAIN_CMD='python setup.py' 33 | - SETUP_CMD='test' 34 | - PIP_DEPENDENCIES='' 35 | 36 | # For this package-template, we include examples of Cython modules, 37 | # so Cython is required for testing. If your package does not include 38 | # Cython code, you can set CONDA_DEPENDENCIES='' 39 | - CONDA_DEPENDENCIES='Cython' 40 | 41 | # Conda packages for affiliated packages are hosted in channel 42 | # "astropy" while builds for astropy LTS with recent numpy versions 43 | # are in astropy-ci-extras. If your package uses either of these, 44 | # add the channels to CONDA_CHANNELS along with any other channels 45 | # you want to use. 46 | - CONDA_CHANNELS='astropy-ci-extras astropy' 47 | 48 | # If there are matplotlib or other GUI tests, uncomment the following 49 | # line to use the X virtual framebuffer. 50 | # - SETUP_XVFB=True 51 | 52 | matrix: 53 | # Make sure that egg_info works without dependencies 54 | - SETUP_CMD='egg_info' 55 | # Try all python versions with the latest numpy 56 | - SETUP_CMD='test' 57 | 58 | matrix: 59 | 60 | # Don't wait for allowed failures 61 | fast_finish: true 62 | 63 | include: 64 | 65 | # Do a coverage test in Python 2. 66 | - python: 2.7 67 | env: SETUP_CMD='test --coverage' 68 | 69 | # Check for sphinx doc build warnings - we do this first because it 70 | # may run for a long time 71 | - python: 2.7 72 | env: SETUP_CMD='build_sphinx -w' 73 | 74 | # Try Astropy development version 75 | - python: 2.7 76 | env: ASTROPY_VERSION=development 77 | - python: 3.5 78 | env: ASTROPY_VERSION=development 79 | - python: 2.7 80 | env: ASTROPY_VERSION=lts 81 | - python: 3.5 82 | env: ASTROPY_VERSION=lts 83 | 84 | # Python 3.3 doesn't have numpy 1.10 in conda, but can be put 85 | # back into the main matrix once the numpy build is available in the 86 | # astropy-ci-extras channel (or in the one provided in the 87 | # CONDA_CHANNELS environmental variable). 88 | 89 | - python: 3.3 90 | env: SETUP_CMD='egg_info' 91 | - python: 3.3 92 | env: SETUP_CMD='test' NUMPY_VERSION=1.9 93 | 94 | # Try older numpy versions 95 | - python: 2.7 96 | env: NUMPY_VERSION=1.10 97 | - python: 2.7 98 | env: NUMPY_VERSION=1.9 99 | - python: 2.7 100 | env: NUMPY_VERSION=1.8 101 | - python: 2.7 102 | env: NUMPY_VERSION=1.7 103 | 104 | # Try numpy pre-release 105 | - python: 3.5 106 | env: NUMPY_VERSION=prerelease 107 | 108 | # Do a PEP8 test with pycodestyle 109 | - python: 3.5 110 | env: MAIN_CMD='pycodestyle packagename --count' SETUP_CMD='' 111 | 112 | allow_failures: 113 | # Do a PEP8 test with pycodestyle 114 | # (allow to fail unless your code completely compliant) 115 | - python: 3.5 116 | env: MAIN_CMD='pycodestyle packagename --count' SETUP_CMD='' 117 | 118 | install: 119 | 120 | # We now use the ci-helpers package to set up our testing environment. 121 | # This is done by using Miniconda and then using conda and pip to install 122 | # dependencies. Which dependencies are installed using conda and pip is 123 | # determined by the CONDA_DEPENDENCIES and PIP_DEPENDENCIES variables, 124 | # which should be space-delimited lists of package names. See the README 125 | # in https://github.com/astropy/ci-helpers for information about the full 126 | # list of environment variables that can be used to customize your 127 | # environment. In some cases, ci-helpers may not offer enough flexibility 128 | # in how to install a package, in which case you can have additional 129 | # commands in the install: section below. 130 | 131 | - git clone git://github.com/astropy/ci-helpers.git 132 | - source ci-helpers/travis/setup_conda_$TRAVIS_OS_NAME.sh 133 | 134 | # As described above, using ci-helpers, you should be able to set up an 135 | # environment with dependencies installed using conda and pip, but in some 136 | # cases this may not provide enough flexibility in how to install a 137 | # specific dependency (and it will not be able to install non-Python 138 | # dependencies). Therefore, you can also include commands below (as 139 | # well as at the start of the install section or in the before_install 140 | # section if they are needed before setting up conda) to install any 141 | # other dependencies. 142 | 143 | script: 144 | - $MAIN_CMD $SETUP_CMD 145 | 146 | after_success: 147 | # If coveralls.io is set up for this package, uncomment the line 148 | # below and replace "packagename" with the name of your package. 149 | # The coveragerc file may be customized as needed for your package. 150 | # - if [[ $SETUP_CMD == 'test --coverage' ]]; then coveralls --rcfile='packagename/tests/coveragerc'; fi 151 | -------------------------------------------------------------------------------- /statcont/fits_utils.py: -------------------------------------------------------------------------------- 1 | import os 2 | import warnings 3 | import astropy.io 4 | from astropy.io import fits 5 | import numpy as np 6 | 7 | ##====================================================================== 8 | def fits_cutout(filename, xc, yc, size, outfile): 9 | 10 | """ 11 | Create a cutout of a larger FITS file 12 | 13 | Parameters 14 | ---------- 15 | filename : string 16 | Name of the FITS file 17 | xc : float 18 | yc : float 19 | X and Y coordinates of the central pixel of the cutout image 20 | size : float 21 | Size of the cutout image in pixels 22 | outfile : string 23 | Name of the output FITS file 24 | 25 | Returns 26 | ------- 27 | outfile : string 28 | Name of the output FITS file 29 | """ 30 | 31 | if isinstance(filename, str): 32 | fitsfile = astropy.io.fits.open(filename) 33 | opened = True 34 | 35 | # Get header information 36 | head = fitsfile[0].header.copy() 37 | ndim = head.get('NAXIS') 38 | cdelt1 = head.get('CDELT1') 39 | cdelt2 = head.get('CDELT2') 40 | nmax = head.get('NAXIS3') 41 | 42 | if cdelt1 is None or cdelt2 is None: 43 | raise Exception("Missing CD or CDELT keywords in header") 44 | 45 | xmin, xmax = np.max([0, xc - size / 2]), np.min([head['NAXIS1'], xc + size / 2]) 46 | ymin, ymax = np.max([0, yc - size / 2]), np.min([head['NAXIS2'], yc + size / 2]) 47 | 48 | xmin = int(xmin) 49 | xmax = int(xmax) 50 | ymin = int(ymin) 51 | ymax = int(ymax) 52 | 53 | if xmax < 0 or ymax < 0: 54 | raise ValueError("Max Coordinate is outside of map: %f, %f." % (xmax, ymax)) 55 | 56 | if ymin >= head.get('NAXIS2') or xmin >= head.get('NAXIS1'): 57 | raise ValueError("Min Coordinate is outside of map: %f, %f." % (xmin, ymin)) 58 | 59 | head['CRPIX1'] -= xmin 60 | head['CRPIX2'] -= ymin 61 | head['NAXIS1'] = int(xmax - xmin) 62 | head['NAXIS2'] = int(ymax - ymin) 63 | head['NAXIS3'] = 1 64 | 65 | if head.get('NAXIS1') == 0 or head.get('NAXIS2') == 0: 66 | raise ValueError("Map has a 0 dimension: %i, %i." % (head.get('NAXIS1'), head.get('NAXIS2'))) 67 | 68 | # Copy data 69 | if ndim == 4: 70 | img = fitsfile[0].data[0:1, 0:nmax, ymin:ymax, xmin:xmax] 71 | if ndim == 3: 72 | img = fitsfile[0].data[0:nmax, ymin:ymax, xmin:xmax] 73 | newfile = astropy.io.fits.PrimaryHDU(data=img, header=head) 74 | 75 | # Output 76 | if isinstance(outfile, str): 77 | 78 | with warnings.catch_warnings(): 79 | warnings.simplefilter('ignore') 80 | 81 | newfile.writeto(outfile, clobber=True) 82 | 83 | if opened: 84 | fitsfile.close() 85 | 86 | return newfile 87 | 88 | ##====================================================================== 89 | def fits_merge(tmp_files, tmp_path, extension, merged_file_name, merged_path): 90 | """ 91 | Merge files to be processed into one single output merged file 92 | 93 | Parameters 94 | ---------- 95 | tmp_files : np.ndarray 96 | tmp_path : string 97 | One-dimension array with the names of the files to be merged 98 | and path where the files are saved 99 | extension : string 100 | Extension of the input files, either .fits or .dat 101 | merged_file_name : string 102 | merged_path : string 103 | Strings with the name of the output merged file and the 104 | path to this file 105 | 106 | Returns 107 | ------- 108 | tmp_files : np.ndarray 109 | One-dimension array with the name of the merged file 110 | tmp_path : np.ndarray 111 | One-dimension array with the path to the merged file 112 | unmerged_files : np.ndarray 113 | One-dimension array with the names of the individual files 114 | that were merged 115 | unmerged_path : np.ndarray 116 | One-dimension array with the path to the individual files 117 | """ 118 | 119 | merged_file = merged_path + merged_file_name + extension 120 | print (merged_file) 121 | 122 | if extension=='.dat': 123 | filenames = [] 124 | for tmp_file in tmp_files: 125 | filenames.append(tmp_path+tmp_file+extension) 126 | with open(merged_file, 'w') as outfile: 127 | for fname in filenames: 128 | with open(fname) as infile: 129 | for line in infile: 130 | outfile.write(line) 131 | 132 | if extension=='.fits': 133 | # Define ranges for channels, to combine all the files 134 | ninterval = len(tmp_files) 135 | bnchan = np.empty([ninterval]) 136 | enchan = np.empty([ninterval]) 137 | 138 | # Determine the total number of channels (icount) of the merged file 139 | icount = 0 140 | for tmp_file in tmp_files: 141 | 142 | header = fits.getheader(tmp_path + tmp_file + extension) 143 | ndim = header.get('NAXIS') 144 | nxpix = header.get('NAXIS1') 145 | nypix = header.get('NAXIS2') 146 | nchan = header.get('NAXIS3') 147 | npolz = header.get('NAXIS4') 148 | 149 | if icount == 0: 150 | bnchan[icount] = 0 151 | enchan[icount] = int(nchan) 152 | else: 153 | jcount = icount-1 154 | bnchan[icount] = int(enchan[jcount]) 155 | enchan[icount] = int(nchan+enchan[jcount]) 156 | 157 | icount = icount + 1 158 | 159 | # Create output merged file 160 | merged_data = np.empty([npolz,int(enchan[icount-1]),nypix,nxpix]) 161 | 162 | # Write data to the new merged file 163 | icount = 0 164 | for tmp_file in tmp_files: 165 | data = fits.getdata(tmp_path + tmp_file + extension) 166 | merged_data[0,int(bnchan[icount]):int(enchan[icount]),:,:] = data 167 | icount = icount + 1 168 | 169 | os.system('rm -rf ' + merged_file) 170 | fits.writeto(merged_file, np.float32(merged_data), header=header, clobber=True) 171 | 172 | # Keep track of the individual file names, and the merged file 173 | unmerged_files = tmp_files 174 | unmerged_path = tmp_path 175 | tmp_files = [] 176 | tmp_files.append(merged_file_name) 177 | tmp_path = merged_path 178 | 179 | return tmp_files, tmp_path, unmerged_files, unmerged_path 180 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Licensed under a 3-clause BSD style license - see LICENSE.rst 3 | # 4 | # Astropy documentation build configuration file. 5 | # 6 | # This file is execfile()d with the current directory set to its containing dir. 7 | # 8 | # Note that not all possible configuration values are present in this file. 9 | # 10 | # All configuration values have a default. Some values are defined in 11 | # the global Astropy configuration which is loaded here before anything else. 12 | # See astropy.sphinx.conf for which values are set there. 13 | 14 | # If extensions (or modules to document with autodoc) are in another directory, 15 | # add these directories to sys.path here. If the directory is relative to the 16 | # documentation root, use os.path.abspath to make it absolute, like shown here. 17 | # sys.path.insert(0, os.path.abspath('..')) 18 | # IMPORTANT: the above commented section was generated by sphinx-quickstart, but 19 | # is *NOT* appropriate for astropy or Astropy affiliated packages. It is left 20 | # commented out with this explanation to make it clear why this should not be 21 | # done. If the sys.path entry above is added, when the astropy.sphinx.conf 22 | # import occurs, it will import the *source* version of astropy instead of the 23 | # version installed (if invoked as "make html" or directly with sphinx), or the 24 | # version in the build directory (if "python setup.py build_sphinx" is used). 25 | # Thus, any C-extensions that are needed to build the documentation will *not* 26 | # be accessible, and the documentation will not build correctly. 27 | 28 | import datetime 29 | import os 30 | import sys 31 | 32 | try: 33 | import astropy_helpers 34 | except ImportError: 35 | # Building from inside the docs/ directory? 36 | if os.path.basename(os.getcwd()) == 'docs': 37 | a_h_path = os.path.abspath(os.path.join('..', 'astropy_helpers')) 38 | if os.path.isdir(a_h_path): 39 | sys.path.insert(1, a_h_path) 40 | 41 | # Load all of the global Astropy configuration 42 | from astropy_helpers.sphinx.conf import * 43 | 44 | # Get configuration information from setup.cfg 45 | try: 46 | from ConfigParser import ConfigParser 47 | except ImportError: 48 | from configparser import ConfigParser 49 | conf = ConfigParser() 50 | 51 | conf.read([os.path.join(os.path.dirname(__file__), '..', 'setup.cfg')]) 52 | setup_cfg = dict(conf.items('metadata')) 53 | 54 | # -- General configuration ---------------------------------------------------- 55 | 56 | # If your documentation needs a minimal Sphinx version, state it here. 57 | #needs_sphinx = '1.2' 58 | 59 | # To perform a Sphinx version check that needs to be more specific than 60 | # major.minor, call `check_sphinx_version("x.y.z")` here. 61 | # check_sphinx_version("1.2.1") 62 | 63 | # List of patterns, relative to source directory, that match files and 64 | # directories to ignore when looking for source files. 65 | exclude_patterns.append('_templates') 66 | 67 | # This is added to the end of RST files - a good place to put substitutions to 68 | # be used globally. 69 | rst_epilog += """ 70 | """ 71 | 72 | # -- Project information ------------------------------------------------------ 73 | 74 | # This does not *have* to match the package name, but typically does 75 | project = setup_cfg['package_name'] 76 | author = setup_cfg['author'] 77 | copyright = '{0}, {1}'.format( 78 | datetime.datetime.now().year, setup_cfg['author']) 79 | 80 | # The version info for the project you're documenting, acts as replacement for 81 | # |version| and |release|, also used in various other places throughout the 82 | # built documents. 83 | 84 | __import__(setup_cfg['package_name']) 85 | package = sys.modules[setup_cfg['package_name']] 86 | 87 | # The short X.Y version. 88 | version = package.__version__.split('-', 1)[0] 89 | # The full version, including alpha/beta/rc tags. 90 | release = package.__version__ 91 | 92 | 93 | # -- Options for HTML output -------------------------------------------------- 94 | 95 | # A NOTE ON HTML THEMES 96 | # The global astropy configuration uses a custom theme, 'bootstrap-astropy', 97 | # which is installed along with astropy. A different theme can be used or 98 | # the options for this theme can be modified by overriding some of the 99 | # variables set in the global configuration. The variables set in the 100 | # global configuration are listed below, commented out. 101 | 102 | 103 | # Please update these texts to match the name of your package. 104 | html_theme_options = { 105 | 'logotext1': 'package', # white, semi-bold 106 | 'logotext2': '-template', # orange, light 107 | 'logotext3': ':docs' # white, light 108 | } 109 | 110 | # Add any paths that contain custom themes here, relative to this directory. 111 | # To use a different custom theme, add the directory containing the theme. 112 | #html_theme_path = [] 113 | 114 | # The theme to use for HTML and HTML Help pages. See the documentation for 115 | # a list of builtin themes. To override the custom theme, set this to the 116 | # name of a builtin theme or the name of a custom theme in html_theme_path. 117 | #html_theme = None 118 | 119 | # Custom sidebar templates, maps document names to template names. 120 | #html_sidebars = {} 121 | 122 | # The name of an image file (within the static path) to use as favicon of the 123 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 124 | # pixels large. 125 | #html_favicon = '' 126 | 127 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 128 | # using the given strftime format. 129 | #html_last_updated_fmt = '' 130 | 131 | # The name for this set of Sphinx documents. If None, it defaults to 132 | # " v documentation". 133 | html_title = '{0} v{1}'.format(project, release) 134 | 135 | # Output file base name for HTML help builder. 136 | htmlhelp_basename = project + 'doc' 137 | 138 | 139 | # -- Options for LaTeX output ------------------------------------------------- 140 | 141 | # Grouping the document tree into LaTeX files. List of tuples 142 | # (source start file, target name, title, author, documentclass [howto/manual]). 143 | latex_documents = [('index', project + '.tex', project + u' Documentation', 144 | author, 'manual')] 145 | 146 | 147 | # -- Options for manual page output ------------------------------------------- 148 | 149 | # One entry per manual page. List of tuples 150 | # (source start file, name, description, authors, manual section). 151 | man_pages = [('index', project.lower(), project + u' Documentation', 152 | [author], 1)] 153 | 154 | 155 | # -- Options for the edit_on_github extension --------------------------------- 156 | 157 | if eval(setup_cfg.get('edit_on_github')): 158 | extensions += ['astropy_helpers.sphinx.ext.edit_on_github'] 159 | 160 | versionmod = __import__(setup_cfg['package_name'] + '.version') 161 | edit_on_github_project = setup_cfg['github_project'] 162 | if versionmod.version.release: 163 | edit_on_github_branch = "v" + versionmod.version.version 164 | else: 165 | edit_on_github_branch = "master" 166 | 167 | edit_on_github_source_root = "" 168 | edit_on_github_doc_root = "docs" 169 | 170 | # -- Resolving issue number to links in changelog ----------------------------- 171 | github_issues_url = 'https://github.com/{0}/issues/'.format(setup_cfg['github_project']) 172 | 173 | -------------------------------------------------------------------------------- /contpy/contpy.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # See http://docs.astropy.org/en/stable/development/scripts.html 4 | 5 | from __future__ import print_function 6 | import argparse 7 | 8 | from .contpy_main import process_files 9 | 10 | def main(args=None): 11 | 12 | # Creating the list of options 13 | pars = argparse.ArgumentParser(description="CONTPY : continuum emission level determination") 14 | grou = pars.add_mutually_exclusive_group() 15 | grou.add_argument('-i', '--iname', nargs='*', 16 | help='NECESSARY: unless parameters -f or -s are considered. \ 17 | One or more FITS files, stored in the directory --path \ 18 | Name of the files without the extension [ .fits ]') 19 | grou.add_argument('-f', '--ifile', nargs=1, 20 | help='NECESSARY: unless parameters -i or -s are considered. \ 21 | File containing a 1-column list with the file names. \ 22 | Name of the files without the extension [ .fits ]') 23 | grou.add_argument('-s', '--ispec', nargs='*', 24 | help='NECESSARY: unless parameters -i or -f are considered. \ 25 | One single ASCII-format file with two columns: \ 26 | frequency (c.1) and intensity (c.2), and no header. \ 27 | Name of the files without the extension [ .dat ]') 28 | pars.add_argument('-m', '--imerge', nargs=1, 29 | help='OPTIONAL: All the files in --iname are merged \ 30 | The argument is the output name for the merged file') 31 | pars.add_argument('-p', '--ipath', nargs=1, 32 | help='OPTIONAL: Specify the PATH where there original files \ 33 | are saved, within the DATA directory') 34 | pars.add_argument('-n', '--noise', nargs=1, type=float, 35 | help='NECESSARY: RMS noise level of the observataions') 36 | pars.add_argument('--continuum', action='store_true', 37 | help='OPTIONAL: Determination of the continuum level \ 38 | Method SIGMACLIP (--csigmaclip) is used by default\ 39 | Subtraction of continuum to line data (--cfree)') 40 | pars.add_argument('--cmax', action='store_true', 41 | help='OPTIONAL: Continuum from the MAXIMUM of the histogram') 42 | pars.add_argument('--cmean', action='store_true', 43 | help='OPTIOANL: Continuum from the MEAN of the intensties') 44 | pars.add_argument('--cmedian', action='store_true', 45 | help='OPTIONAL: Continuum from the MEDIAN of the intensities') 46 | pars.add_argument('--cpercent', action='store_true', 47 | help='OPTIONAL: Continuum from the 25th and 75th PERCENTILE') 48 | pars.add_argument('--cKDEmax', action='store_true', 49 | help='OPTIONAL: Continuum from the maximum of the KDE') 50 | pars.add_argument('--cGaussian', action='store_true', 51 | help='OPTIONAL: Continuum from a Gaussian fit to the histogram') 52 | pars.add_argument('--csigmaclip', action='store_true', 53 | help='OPTIONAL: Continuum from the SIGMA-CLIPPING algorithm') 54 | pars.add_argument('--call', action='store_true', 55 | help='OPTIONAL: Continuum using ALL the methods') 56 | pars.add_argument('--cfree', action='store_true', 57 | help='OPTIONAL: Remove the continuum to the original datacube') 58 | pars.add_argument('--nooffset', action='store_true', 59 | help='OPTIONAL: Search for and remove a general continuum offset') 60 | pars.add_argument('--spindex', action='store_true', 61 | help='OPTIONAL: Determine the spectral index (ALPHA), as \ 62 | a linear function: Flux = FACTOR * frequency ^ (ALPHA) \ 63 | Provide a list of files to be processed, for which \ 64 | the continuum needs to be created (--continuum)') 65 | pars.add_argument('--model', action='store_true', 66 | help='OPTIONAL: Create a continuum model using information \ 67 | from --spindex, and a line+continuum(model) cube') 68 | pars.add_argument('--cutout', nargs=3, type=int, 69 | help='OPTIONAL: Create a cutout image of the original file. \ 70 | Three integer numbers are required for this option: \ 71 | xcen: x coordinate of the central pixel of the cutout \ 72 | ycen: y coordinate of the central pixel of the cutout \ 73 | size: size (in pixels) of the cutout') 74 | pars.add_argument('--plots', action='store_true', 75 | help='OPTIONAL: Create plots on a pixel-by-pixel basis \ 76 | Spectrum with continuum (and noise) levels indicated \ 77 | (computing time increases considerably)') 78 | pars.add_argument('--verbose', action='store_true', 79 | help='OPTIONAL: Increase output verbosity') 80 | op = pars.parse_args(args) 81 | 82 | # Select all continuum determination methods when --call is used 83 | if op.call: 84 | op.cmax = True 85 | op.cmean = True 86 | op.cmedian = True 87 | op.cpercent = True 88 | op.cKDEmax = True 89 | op.cGaussian = True 90 | op.csigmaclip = True 91 | 92 | # Use SIGMA-CLIPPING to obtain a value to compare with when using other methods 93 | if op.cmax or op.cmean or op.cmedian or op.cpercent or op.cKDEmax or op.cGaussian: 94 | op.csigmaclip = True 95 | 96 | # Use the SIGMA-CLIPPING method and subtract continuum to line, if --continuum is used 97 | if op.continuum: 98 | op.csigmaclip = True 99 | op.cfree = True 100 | 101 | # Activate the main code for continuum determination when using any method 102 | if op.cmax or op.cmean or op.cmedian or op.cpercent or op.cKDEmax or op.cGaussian or op.csigmaclip: 103 | op.continuum = True 104 | 105 | # Activate the subtraction of the continuum --cfree, if the general offset wants to be removed 106 | if op.nooffset: 107 | op.cfree = True 108 | 109 | # Activate the determination of the spectral index --spindex, if the model wants to be created 110 | if op.model: 111 | op.spindex = True 112 | 113 | # Noise level of your data cubes (in units of the FITS file) 114 | rms_noise = op.noise[0] 115 | 116 | process_files(iname=op.iname, 117 | ifile=op.ifile, 118 | ispec=op.ispec, 119 | imerge=op.imerge, 120 | ipath=op.ipath, 121 | rms_noise=rms_noise, 122 | continuum=op.continuum, 123 | cmax=op.cmax, 124 | cmean=op.cmean, 125 | cmedian=op.cmedian, 126 | cpercent=op.cpercent, 127 | cKDEmax=op.cKDEmax, 128 | cGaussian=op.cGaussian, 129 | csigmaclip=op.csigmaclip, 130 | cfree=op.cfree, 131 | nooffset=op.nooffset, 132 | spindex=op.spindex, 133 | model=op.model, 134 | plots=op.plots, 135 | cutout=op.cutout, 136 | verbose=op.verbose) 137 | -------------------------------------------------------------------------------- /statcont/statcont.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # See http://docs.astropy.org/en/stable/development/scripts.html 4 | 5 | """ Description: 6 | 7 | ----------------------------------------------------------------- 8 | STATCONT: A statistical continuum level determination method for 9 | line-rich sources" 10 | 11 | Sanchez-Monge et al (2018, A&A,609, A101) 12 | Details in https://hera.ph1.uni-koeln.de/~sanchez/statcont 13 | version 1.5 14 | 15 | """ 16 | 17 | from __future__ import print_function 18 | import argparse 19 | 20 | from .statcont_main import process_files 21 | 22 | def main(args=None): 23 | 24 | # Creating the list of options 25 | pars = argparse.ArgumentParser(description="+++ ----------------------------------------------------------------------- \ 26 | +++ STATCONT : A statistical continuum level determination method (v 1.5) - \ 27 | +++ please refer to Sanchez-Monge et al. (2018, A&A, 609, A101)") 28 | grou = pars.add_mutually_exclusive_group() 29 | grou.add_argument('-i', '--iname', nargs='*', 30 | help='NECESSARY: unless parameters -f or -s are considered. \ 31 | One or more FITS files, stored in the directory --path \ 32 | Name of the files without the extension [ .fits ]') 33 | grou.add_argument('-f', '--ifile', nargs=1, 34 | help='NECESSARY: unless parameters -i or -s are considered. \ 35 | File containing a 1-column list with the file names. \ 36 | Name of the files without the extension [ .fits ]') 37 | grou.add_argument('-s', '--ispec', nargs='*', 38 | help='NECESSARY: unless parameters -i or -f are considered. \ 39 | One single ASCII-format file with two columns: \ 40 | frequency (c.1) and intensity (c.2), and no header. \ 41 | Name of the files without the extension [ .dat ]') 42 | grou.add_argument('-l', '--ilist', nargs=1, 43 | help='NECESSARY: unless parameters -i or -s are considered. \ 44 | File containing a 1-column list with the file names. \ 45 | Name of the files without the extension [ .dat ]') 46 | pars.add_argument('-m', '--imerge', nargs=1, 47 | help='OPTIONAL: All the files in --iname are merged \ 48 | The argument is the output name for the merged file') 49 | pars.add_argument('-p', '--ipath', nargs=1, 50 | help='OPTIONAL: Specify the PATH where there original files \ 51 | are saved, within the DATA directory') 52 | pars.add_argument('-n', '--noise', nargs=1, type=float, 53 | help='NECESSARY: RMS noise level of the observataions') 54 | pars.add_argument('--continuum', action='store_true', 55 | help='OPTIONAL: Determination of the continuum (and noise) \ 56 | Method corrected SIGMACLIP (fast) is used by default\ 57 | Subtraction of continuum to line data (--cfree)') 58 | pars.add_argument('--cmax', action='store_true', 59 | help='OPTIONAL: Continuum from the MAXIMUM of the histogram') 60 | pars.add_argument('--cmean', action='store_true', 61 | help='OPTIOANL: Continuum from the MEAN of the intensties') 62 | pars.add_argument('--cmedian', action='store_true', 63 | help='OPTIONAL: Continuum from the MEDIAN of the intensities') 64 | pars.add_argument('--cpercent', action='store_true', 65 | help='OPTIONAL: Continuum from the 25th and 75th PERCENTILE') 66 | pars.add_argument('--cKDEmax', action='store_true', 67 | help='OPTIONAL: Continuum from the maximum of the KDE') 68 | pars.add_argument('--cGaussian', action='store_true', 69 | help='OPTIONAL: Continuum from a Gaussian fit to the histogram') 70 | pars.add_argument('--csigmaclip', action='store_true', 71 | help='OPTIONAL: Continuum from the SIGMA-CLIPPING algorithm') 72 | pars.add_argument('--call', action='store_true', 73 | help='OPTIONAL: Continuum using ALL the methods') 74 | pars.add_argument('--cfree', action='store_true', 75 | help='OPTIONAL: Remove the continuum to the original datacube') 76 | pars.add_argument('--nooffset', action='store_true', 77 | help='OPTIONAL: Search for and remove a general continuum offset') 78 | pars.add_argument('--spindex', action='store_true', 79 | help='OPTIONAL: Determine the spectral index (ALPHA), as \ 80 | a linear function: Flux = FACTOR * frequency ^ (ALPHA) \ 81 | Provide a list of files to be processed, for which \ 82 | the continuum needs to be created (--continuum)') 83 | pars.add_argument('--model', action='store_true', 84 | help='OPTIONAL: Create a continuum model using information \ 85 | from --spindex, and a line+continuum(model) cube') 86 | pars.add_argument('--cutout', nargs=3, type=int, 87 | help='OPTIONAL: Create a cutout image of the original file. \ 88 | Three integer numbers are required for this option: \ 89 | xcen: x coordinate of the central pixel of the cutout \ 90 | ycen: y coordinate of the central pixel of the cutout \ 91 | size: size (in pixels) of the cutout') 92 | pars.add_argument('--plots', action='store_true', 93 | help='OPTIONAL: Create plots on a pixel-by-pixel basis \ 94 | Spectrum with continuum (and noise) levels indicated \ 95 | (computing time increases considerably)') 96 | pars.add_argument('--verbose', nargs='?', type=int, const=1, default=2, 97 | help='OPTIONAL: Modify level of output verbosity (default 2) \ 98 | 0: Switch off from terminal all message communications \ 99 | 1: Only important messages are displayed in terminal \ 100 | 2: Standard level of output verbosity (default value) \ 101 | 3: Increase level of output verbosity (more details) \ 102 | 4: Switch on all messages (for developers)') 103 | pars.add_argument('--localdir', action='store_true', 104 | help='Data and product files stored in working directory') 105 | pars.add_argument('--betaversion', action='store_true', 106 | help='DEVELOPERS: For developers and testing') 107 | op = pars.parse_args(args) 108 | 109 | # Modify level of output verbosity 110 | verbose = op.verbose 111 | 112 | # Activate level 2 of verbosity for ASCII spectra 113 | # Can be overwritten by specifying the verbosity output level 114 | if op.ispec and verbose == 2: 115 | verbose = 3 116 | if op.ilist and verbose == 2: 117 | verbose = 3 118 | 119 | # For developers, activate maximum verbosity 120 | # Can be overwritten by specifying the verbosity output level 121 | if op.betaversion and verbose == 2: 122 | verbose = 4 123 | 124 | # Select all continuum determination methods when --call is used 125 | if op.call: 126 | op.cmax = True 127 | op.cmean = True 128 | op.cmedian = True 129 | op.cpercent = True 130 | op.cKDEmax = True 131 | op.cGaussian = True 132 | op.csigmaclip = True 133 | 134 | # Activate the main code for continuum determination when using any method 135 | if op.cmax or op.cmean or op.cmedian or op.cpercent or op.cKDEmax or op.cGaussian or op.csigmaclip: 136 | op.continuum = True 137 | 138 | # Use the SIGMA-CLIPPING method and subtract continuum to line, if --continuum is used 139 | if op.continuum: 140 | op.cfree = True 141 | 142 | # Activate the subtraction of the continuum --cfree, if the general offset wants to be removed 143 | if op.nooffset: 144 | op.continuum = True 145 | op.cfree = True 146 | 147 | # Activate the determination of the spectral index --spindex, if the model wants to be created 148 | if op.model: 149 | op.spindex = True 150 | 151 | # Noise level of your data cubes (in units of the FITS file) 152 | rms_noise = op.noise[0] 153 | 154 | process_files(iname=op.iname, 155 | ifile=op.ifile, 156 | ispec=op.ispec, 157 | ilist=op.ilist, 158 | imerge=op.imerge, 159 | ipath=op.ipath, 160 | rms_noise=rms_noise, 161 | continuum=op.continuum, 162 | cmax=op.cmax, 163 | cmean=op.cmean, 164 | cmedian=op.cmedian, 165 | cpercent=op.cpercent, 166 | cKDEmax=op.cKDEmax, 167 | cGaussian=op.cGaussian, 168 | csigmaclip=op.csigmaclip, 169 | cfree=op.cfree, 170 | nooffset=op.nooffset, 171 | spindex=op.spindex, 172 | model=op.model, 173 | plots=op.plots, 174 | cutout=op.cutout, 175 | verbose=verbose, 176 | betaversion=op.betaversion, 177 | localdir=op.localdir) 178 | -------------------------------------------------------------------------------- /ez_setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Setuptools bootstrapping installer. 5 | 6 | Maintained at https://github.com/pypa/setuptools/tree/bootstrap. 7 | 8 | Run this script to install or upgrade setuptools. 9 | """ 10 | 11 | import os 12 | import shutil 13 | import sys 14 | import tempfile 15 | import zipfile 16 | import optparse 17 | import subprocess 18 | import platform 19 | import textwrap 20 | import contextlib 21 | import json 22 | import codecs 23 | 24 | from distutils import log 25 | 26 | try: 27 | from urllib.request import urlopen 28 | from urllib.parse import urljoin 29 | except ImportError: 30 | from urllib2 import urlopen 31 | from urlparse import urljoin 32 | 33 | try: 34 | from site import USER_SITE 35 | except ImportError: 36 | USER_SITE = None 37 | 38 | LATEST = object() 39 | DEFAULT_VERSION = LATEST 40 | DEFAULT_URL = "https://pypi.io/packages/source/s/setuptools/" 41 | DEFAULT_SAVE_DIR = os.curdir 42 | 43 | MEANINGFUL_INVALID_ZIP_ERR_MSG = 'Maybe {0} is corrupted, delete it and try again.' 44 | 45 | 46 | def _python_cmd(*args): 47 | """ 48 | Execute a command. 49 | 50 | Return True if the command succeeded. 51 | """ 52 | args = (sys.executable,) + args 53 | return subprocess.call(args) == 0 54 | 55 | 56 | def _install(archive_filename, install_args=()): 57 | """Install Setuptools.""" 58 | with archive_context(archive_filename): 59 | # installing 60 | log.warn('Installing Setuptools') 61 | if not _python_cmd('setup.py', 'install', *install_args): 62 | log.warn('Something went wrong during the installation.') 63 | log.warn('See the error message above.') 64 | # exitcode will be 2 65 | return 2 66 | 67 | 68 | def _build_egg(egg, archive_filename, to_dir): 69 | """Build Setuptools egg.""" 70 | with archive_context(archive_filename): 71 | # building an egg 72 | log.warn('Building a Setuptools egg in %s', to_dir) 73 | _python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir) 74 | # returning the result 75 | log.warn(egg) 76 | if not os.path.exists(egg): 77 | raise IOError('Could not build the egg.') 78 | 79 | 80 | class ContextualZipFile(zipfile.ZipFile): 81 | 82 | """Supplement ZipFile class to support context manager for Python 2.6.""" 83 | 84 | def __enter__(self): 85 | return self 86 | 87 | def __exit__(self, type, value, traceback): 88 | self.close() 89 | 90 | def __new__(cls, *args, **kwargs): 91 | """Construct a ZipFile or ContextualZipFile as appropriate.""" 92 | if hasattr(zipfile.ZipFile, '__exit__'): 93 | return zipfile.ZipFile(*args, **kwargs) 94 | return super(ContextualZipFile, cls).__new__(cls) 95 | 96 | 97 | @contextlib.contextmanager 98 | def archive_context(filename): 99 | """ 100 | Unzip filename to a temporary directory, set to the cwd. 101 | 102 | The unzipped target is cleaned up after. 103 | """ 104 | tmpdir = tempfile.mkdtemp() 105 | log.warn('Extracting in %s', tmpdir) 106 | old_wd = os.getcwd() 107 | try: 108 | os.chdir(tmpdir) 109 | try: 110 | with ContextualZipFile(filename) as archive: 111 | archive.extractall() 112 | except zipfile.BadZipfile as err: 113 | if not err.args: 114 | err.args = ('', ) 115 | err.args = err.args + ( 116 | MEANINGFUL_INVALID_ZIP_ERR_MSG.format(filename), 117 | ) 118 | raise 119 | 120 | # going in the directory 121 | subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0]) 122 | os.chdir(subdir) 123 | log.warn('Now working in %s', subdir) 124 | yield 125 | 126 | finally: 127 | os.chdir(old_wd) 128 | shutil.rmtree(tmpdir) 129 | 130 | 131 | def _do_download(version, download_base, to_dir, download_delay): 132 | """Download Setuptools.""" 133 | py_desig = 'py{sys.version_info[0]}.{sys.version_info[1]}'.format(sys=sys) 134 | tp = 'setuptools-{version}-{py_desig}.egg' 135 | egg = os.path.join(to_dir, tp.format(**locals())) 136 | if not os.path.exists(egg): 137 | archive = download_setuptools(version, download_base, 138 | to_dir, download_delay) 139 | _build_egg(egg, archive, to_dir) 140 | sys.path.insert(0, egg) 141 | 142 | # Remove previously-imported pkg_resources if present (see 143 | # https://bitbucket.org/pypa/setuptools/pull-request/7/ for details). 144 | if 'pkg_resources' in sys.modules: 145 | _unload_pkg_resources() 146 | 147 | import setuptools 148 | setuptools.bootstrap_install_from = egg 149 | 150 | 151 | def use_setuptools( 152 | version=DEFAULT_VERSION, download_base=DEFAULT_URL, 153 | to_dir=DEFAULT_SAVE_DIR, download_delay=15): 154 | """ 155 | Ensure that a setuptools version is installed. 156 | 157 | Return None. Raise SystemExit if the requested version 158 | or later cannot be installed. 159 | """ 160 | version = _resolve_version(version) 161 | to_dir = os.path.abspath(to_dir) 162 | 163 | # prior to importing, capture the module state for 164 | # representative modules. 165 | rep_modules = 'pkg_resources', 'setuptools' 166 | imported = set(sys.modules).intersection(rep_modules) 167 | 168 | try: 169 | import pkg_resources 170 | pkg_resources.require("setuptools>=" + version) 171 | # a suitable version is already installed 172 | return 173 | except ImportError: 174 | # pkg_resources not available; setuptools is not installed; download 175 | pass 176 | except pkg_resources.DistributionNotFound: 177 | # no version of setuptools was found; allow download 178 | pass 179 | except pkg_resources.VersionConflict as VC_err: 180 | if imported: 181 | _conflict_bail(VC_err, version) 182 | 183 | # otherwise, unload pkg_resources to allow the downloaded version to 184 | # take precedence. 185 | del pkg_resources 186 | _unload_pkg_resources() 187 | 188 | return _do_download(version, download_base, to_dir, download_delay) 189 | 190 | 191 | def _conflict_bail(VC_err, version): 192 | """ 193 | Setuptools was imported prior to invocation, so it is 194 | unsafe to unload it. Bail out. 195 | """ 196 | conflict_tmpl = textwrap.dedent(""" 197 | The required version of setuptools (>={version}) is not available, 198 | and can't be installed while this script is running. Please 199 | install a more recent version first, using 200 | 'easy_install -U setuptools'. 201 | 202 | (Currently using {VC_err.args[0]!r}) 203 | """) 204 | msg = conflict_tmpl.format(**locals()) 205 | sys.stderr.write(msg) 206 | sys.exit(2) 207 | 208 | 209 | def _unload_pkg_resources(): 210 | sys.meta_path = [ 211 | importer 212 | for importer in sys.meta_path 213 | if importer.__class__.__module__ != 'pkg_resources.extern' 214 | ] 215 | del_modules = [ 216 | name for name in sys.modules 217 | if name.startswith('pkg_resources') 218 | ] 219 | for mod_name in del_modules: 220 | del sys.modules[mod_name] 221 | 222 | 223 | def _clean_check(cmd, target): 224 | """ 225 | Run the command to download target. 226 | 227 | If the command fails, clean up before re-raising the error. 228 | """ 229 | try: 230 | subprocess.check_call(cmd) 231 | except subprocess.CalledProcessError: 232 | if os.access(target, os.F_OK): 233 | os.unlink(target) 234 | raise 235 | 236 | 237 | def download_file_powershell(url, target): 238 | """ 239 | Download the file at url to target using Powershell. 240 | 241 | Powershell will validate trust. 242 | Raise an exception if the command cannot complete. 243 | """ 244 | target = os.path.abspath(target) 245 | ps_cmd = ( 246 | "[System.Net.WebRequest]::DefaultWebProxy.Credentials = " 247 | "[System.Net.CredentialCache]::DefaultCredentials; " 248 | '(new-object System.Net.WebClient).DownloadFile("%(url)s", "%(target)s")' 249 | % locals() 250 | ) 251 | cmd = [ 252 | 'powershell', 253 | '-Command', 254 | ps_cmd, 255 | ] 256 | _clean_check(cmd, target) 257 | 258 | 259 | def has_powershell(): 260 | """Determine if Powershell is available.""" 261 | if platform.system() != 'Windows': 262 | return False 263 | cmd = ['powershell', '-Command', 'echo test'] 264 | with open(os.path.devnull, 'wb') as devnull: 265 | try: 266 | subprocess.check_call(cmd, stdout=devnull, stderr=devnull) 267 | except Exception: 268 | return False 269 | return True 270 | download_file_powershell.viable = has_powershell 271 | 272 | 273 | def download_file_curl(url, target): 274 | cmd = ['curl', url, '--location', '--silent', '--output', target] 275 | _clean_check(cmd, target) 276 | 277 | 278 | def has_curl(): 279 | cmd = ['curl', '--version'] 280 | with open(os.path.devnull, 'wb') as devnull: 281 | try: 282 | subprocess.check_call(cmd, stdout=devnull, stderr=devnull) 283 | except Exception: 284 | return False 285 | return True 286 | download_file_curl.viable = has_curl 287 | 288 | 289 | def download_file_wget(url, target): 290 | cmd = ['wget', url, '--quiet', '--output-document', target] 291 | _clean_check(cmd, target) 292 | 293 | 294 | def has_wget(): 295 | cmd = ['wget', '--version'] 296 | with open(os.path.devnull, 'wb') as devnull: 297 | try: 298 | subprocess.check_call(cmd, stdout=devnull, stderr=devnull) 299 | except Exception: 300 | return False 301 | return True 302 | download_file_wget.viable = has_wget 303 | 304 | 305 | def download_file_insecure(url, target): 306 | """Use Python to download the file, without connection authentication.""" 307 | src = urlopen(url) 308 | try: 309 | # Read all the data in one block. 310 | data = src.read() 311 | finally: 312 | src.close() 313 | 314 | # Write all the data in one block to avoid creating a partial file. 315 | with open(target, "wb") as dst: 316 | dst.write(data) 317 | download_file_insecure.viable = lambda: True 318 | 319 | 320 | def get_best_downloader(): 321 | downloaders = ( 322 | download_file_powershell, 323 | download_file_curl, 324 | download_file_wget, 325 | download_file_insecure, 326 | ) 327 | viable_downloaders = (dl for dl in downloaders if dl.viable()) 328 | return next(viable_downloaders, None) 329 | 330 | 331 | def download_setuptools( 332 | version=DEFAULT_VERSION, download_base=DEFAULT_URL, 333 | to_dir=DEFAULT_SAVE_DIR, delay=15, 334 | downloader_factory=get_best_downloader): 335 | """ 336 | Download setuptools from a specified location and return its filename. 337 | 338 | `version` should be a valid setuptools version number that is available 339 | as an sdist for download under the `download_base` URL (which should end 340 | with a '/'). `to_dir` is the directory where the egg will be downloaded. 341 | `delay` is the number of seconds to pause before an actual download 342 | attempt. 343 | 344 | ``downloader_factory`` should be a function taking no arguments and 345 | returning a function for downloading a URL to a target. 346 | """ 347 | version = _resolve_version(version) 348 | # making sure we use the absolute path 349 | to_dir = os.path.abspath(to_dir) 350 | zip_name = "setuptools-%s.zip" % version 351 | url = download_base + zip_name 352 | saveto = os.path.join(to_dir, zip_name) 353 | if not os.path.exists(saveto): # Avoid repeated downloads 354 | log.warn("Downloading %s", url) 355 | downloader = downloader_factory() 356 | downloader(url, saveto) 357 | return os.path.realpath(saveto) 358 | 359 | 360 | def _resolve_version(version): 361 | """ 362 | Resolve LATEST version 363 | """ 364 | if version is not LATEST: 365 | return version 366 | 367 | meta_url = urljoin(DEFAULT_URL, '/pypi/setuptools/json') 368 | resp = urlopen(meta_url) 369 | with contextlib.closing(resp): 370 | try: 371 | charset = resp.info().get_content_charset() 372 | except Exception: 373 | # Python 2 compat; assume UTF-8 374 | charset = 'UTF-8' 375 | reader = codecs.getreader(charset) 376 | doc = json.load(reader(resp)) 377 | 378 | return str(doc['info']['version']) 379 | 380 | 381 | def _build_install_args(options): 382 | """ 383 | Build the arguments to 'python setup.py install' on the setuptools package. 384 | 385 | Returns list of command line arguments. 386 | """ 387 | return ['--user'] if options.user_install else [] 388 | 389 | 390 | def _parse_args(): 391 | """Parse the command line for options.""" 392 | parser = optparse.OptionParser() 393 | parser.add_option( 394 | '--user', dest='user_install', action='store_true', default=False, 395 | help='install in user site package') 396 | parser.add_option( 397 | '--download-base', dest='download_base', metavar="URL", 398 | default=DEFAULT_URL, 399 | help='alternative URL from where to download the setuptools package') 400 | parser.add_option( 401 | '--insecure', dest='downloader_factory', action='store_const', 402 | const=lambda: download_file_insecure, default=get_best_downloader, 403 | help='Use internal, non-validating downloader' 404 | ) 405 | parser.add_option( 406 | '--version', help="Specify which version to download", 407 | default=DEFAULT_VERSION, 408 | ) 409 | parser.add_option( 410 | '--to-dir', 411 | help="Directory to save (and re-use) package", 412 | default=DEFAULT_SAVE_DIR, 413 | ) 414 | options, args = parser.parse_args() 415 | # positional arguments are ignored 416 | return options 417 | 418 | 419 | def _download_args(options): 420 | """Return args for download_setuptools function from cmdline args.""" 421 | return dict( 422 | version=options.version, 423 | download_base=options.download_base, 424 | downloader_factory=options.downloader_factory, 425 | to_dir=options.to_dir, 426 | ) 427 | 428 | 429 | def main(): 430 | """Install or upgrade setuptools and EasyInstall.""" 431 | options = _parse_args() 432 | archive = download_setuptools(**_download_args(options)) 433 | return _install(archive, _build_install_args(options)) 434 | 435 | if __name__ == '__main__': 436 | sys.exit(main()) 437 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | STATCONT - A statistical continuum level determination method for line-rich sources 2 | ----------------------------------------------------------------------------------- 3 | 4 | STATCONT is a python-based tool designed to determine the continuum 5 | emission level in line-rich spectral data. The tool inspects the 6 | intensity distribution of a given spectrum and automatically determines 7 | the continuum level by using differeng statistical approaches. The 8 | different methods included in STATCONT have been tested against 9 | synthetic data. We conclude that the sigma-clipping algorithm provides 10 | the most accurate continuum level determination, together with 11 | information on the uncertainty in its determination. This uncertainty 12 | is used to correct the final continuum emission level, resulting in the 13 | here-called 'corrected sigma-clipping method' or cSCM. The cSCM has 14 | been tested against synthetic data cubes reproducing typical conditions 15 | found in astronomical line-rich sources. In general, we obtain 16 | accuracies of < 10 % in the continuum determination, and < 5 % in most 17 | cases. The main products of STATCONT are the continuum emission level, 18 | together with its uncertainty, and data cubes containing only spectral 19 | line emission, i.e. continuum-subtracted data cubes. STATCONT also 20 | includes the option to estimate the spectral index or variation of the 21 | continuum emission with frequency. 22 | 23 | If you find STATCONT useful, please cite/refer to: 24 | [Sanchez-Monge, Schilke, Ginsburg, Cesaroni and Schmiedeke 2018, A&A, 609, A101](https://ui.adsabs.harvard.edu/abs/2018A%26A...609A.101S/abstract) 25 | Access to the article in [PDF](https://hera.ph1.uni-koeln.de/~sanchez/my_documents/publications/SanchezMonge_etal_2018.pdf) format. 26 | 27 | More information about STATCONT can be found in [http://www.astro.uni-koeln.de/~sanchez/statcont](http://www.astro.uni-koeln.de/~sanchez/statcont) 28 | 29 | This README document is intented to help you install and use STATCONT. In the following you will find: 30 | - [**Installation instructions**](https://github.com/radio-astro-tools/statcont#installation-instructions) 31 | - [**Required Python packages**](https://github.com/radio-astro-tools/statcont#required-python-packages) 32 | - [**Main STATCONT commands and options**](https://github.com/radio-astro-tools/statcont#main-statcont-commands-and-options) 33 | - [**Examples and test cases**](https://github.com/radio-astro-tools/statcont#examples-and-test-cases) 34 | - [**Determining the continuum in single spectrum files (ASCII files)**](https://github.com/radio-astro-tools/statcont/blob/master/README.md#determining-the-continuum-in-single-spectrum-files-ascii-files) 35 | - [**Determining the continuum in a 3D cube file (FITS files)**](https://github.com/radio-astro-tools/statcont/blob/master/README.md#determining-the-continuum-in-a-3d-cube-file-fits-files) 36 | - [**Determining the spectral index from multiple input files**](https://github.com/radio-astro-tools/statcont/blob/master/README.md#determining-the-spectral-index-from-multiple-input-files) 37 | - [**Real data examples**](https://github.com/radio-astro-tools/statcont#real-data-examples) 38 | - [**Publications citing STATCONT**](https://github.com/radio-astro-tools/statcont#publications-citing-statcont) 39 | 40 | ------------------------------------ 41 | Installation instructions 42 | ------------------------------------ 43 | 44 | STATCONT uses the [ASTROPY](https://www.astropy.org/) package-template and is 45 | fully compatible with the ASTROPY ecosystem. It is freely available for download at 46 | the [GitHub](https://github.com/) repository [Radio Astro Tools](http://radio-astro-tools.github.io/), 47 | as well as in this [webpage](http://www.astro.uni-koeln.de/~sanchez/statcont). The only 48 | required software to use STATCONT is Python and Astropy, together with some basic 49 | Python packages that you can find listed [here](https://github.com/radio-astro-tools/statcont#required-python-packages). 50 | 51 | **Installation method 1**
52 | You can clone STATCONT in your computer from the GitHub repository. For 53 | this, create a directory and move there. Then type: 54 | 55 | ``` 56 | git init 57 | git clone https://github.com/radio-astro-tools/statcont 58 | cd statcont 59 | python setup.py install 60 | ``` 61 | 62 | **Installation method 2**
63 | You can also directly install STATCONT by typing in a terminal session in 64 | your computer (you may need sudo permissions depending on the 65 | configuration of your system): 66 | 67 | ``` 68 | pip install https://github.com/radio-astro-tools/statcont/archive/master.zip 69 | ``` 70 | 71 | **Installation method 3**
72 | Alternatively, STATCONT can also be downloaded locally as a zip file 73 | from: [master.zip](https://github.com/radio-astro-tools/statcont/archive/master.zip). 74 | In order to install it, download the file to a directory in your computer: 75 | 76 | ``` 77 | unzip master.zip 78 | cd statcont 79 | python setup.py install 80 | ``` 81 | 82 | **How to solve permission errors**
83 | If you get a permission error, this means that you do not have the required 84 | administrative access to install STATCONT to your Python installation. In 85 | this case you can use the option `--user` when installing the setup.py script. 86 | You can follow these instructions: 87 | 88 | ``` 89 | python setup.py install --user --install-scripts="~/bin/" 90 | export PATH=~/bin/:$PATH 91 | ``` 92 | 93 | **Check your installation**
94 | Following the installation, you have immediate access to STATCONT in 95 | your computer by typing "statcont" in a terminal session. For example, 96 | inspect the help by doing: 97 | 98 | ``` 99 | statcont --help 100 | ``` 101 | 102 | At the beginning of the help message you will see the version of STATCONT. 103 | The current stable release is `version 1.5`. 104 | 105 | --------------------- 106 | Required Python packages 107 | --------------------- 108 | 109 | STATCONT uses the following Python packages: 110 | 111 | - [argparse](https://docs.python.org/3/library/argparse.html) : version >= 1.1 112 | - [astropy](https://www.astropy.org/) : version >= 4.2.1 113 | - [datetime](https://docs.python.org/3/library/datetime.html) 114 | - [math](https://docs.python.org/3/library/math.html) 115 | - [matplotlib](https://matplotlib.org/) : version >= 3.5.0 116 | - [numpy](https://numpy.org/) : version >= 1.21.4 117 | - [os](https://docs.python.org/3/library/os.html) 118 | - [scipy](https://scipy.org/) : version >= 1.7.3 119 | 120 | The versions indicated above have been recently tested, older versions 121 | worked fine in previous tests and are expected to continue working. 122 | 123 | --------------------- 124 | Main STATCONT commands and options 125 | --------------------- 126 | 127 | The following table contains the main commands and options of STATCONT. They can be explored and executed by typing 128 | 129 | ``` 130 | statcont --help 131 | ``` 132 | 133 | 134 | | Command | Necessary? | Description | 135 | | --- | --- | --- | 136 | | `--help` | | Show the help message and all the STATCONT commands | 137 | | `-i` / `--iname` | NECESSARY
(unless `-f`, `-s` or `-l` are used) | Name of the FITS file to be processed (without extension, which should be .fits)
Example: `-i SYNTHETIC_cube`
The file SYNTHETIC_cube.fits has to be stored in the `data` directory | 138 | | `-f` / `--ifile` | NECESSARY
(unless `-i`, `-s` or `-l` are used) | Text file containing a list of FITS files to be processed (files to be processed have to be listed without extension, which should be .fits)
Example: `-f file.txt`
The file file.txt has to be stored in the running directory | 139 | | `-s` / `--ispec` | NECESSARY
(unless `-i`, `-f` or `-l` are used) | Name of the ASCII file to be processed (without extension, which should be .dat)
Example: `-s my_emission`
The file my_emission.dat has to be stored in the `data` directory | 140 | | `-l` / `--ilist` | NECESSARY
(unless `-i`, `-f` or `-s` are used) | Text file containing a list of ASCII files to be processed (files to be processed have to be listed without extension, which should be .dat)
Example: `-l file.txt`
The file file.txt has to be stored in the running directory | 141 | | `-p` / `--ipath` | OPTIONAL | Specify the path/directory there the files to be processed are stored.
This path/directory has to inside the `data` directory | 142 | | `-n` / `--noise` | NECESSARY | Typical RMS noise level of the observations
A value of 1 can be used in most of the cases | 143 | | `--continuum` | OPTIONAL | Determination of the continuum level and create of line-only cube or spectrum | 144 | | `--plots` | OPTIONAL | Create plots on a pixel-by-pixel basis | 145 | | `--cutout` | OPTIONAL | Create a cutout image of the original FITS cube
Three parameters have to be specified (`xcen`, `ycen` and `size`) in pixels | 146 | | `--spindex` | OPTIONAL | Determine the spectral index (ALPHA) defined as flux = FACTOR * frequency^(ALPHA) | 147 | 148 | 149 | --------------------- 150 | Examples and test cases 151 | --------------------- 152 | 153 | In the following we explain how to execute the main tasks of STATCONT. 154 | A set of test cases is provided in this [test_cases.tar.gz](https://hera.ph1.uni-koeln.de/~sanchez/software/STATCONT/test_cases.tar.gz) file. 155 | Download the file to your computer and follow these instructions: 156 | 157 | ``` 158 | gunzip test_cases.tar.gz 159 | tar -xvf test_cases.tar 160 | ``` 161 | 162 | This creates a directory called `statcont-tests`. Inside, you will 163 | find a directory called data that contains three other subdirectories 164 | `MAP_TESTS`, `SPEC_TESTS`, and `SPINDEX` 165 | 166 | STATCONT requires of a directory data where the files to be processed 167 | are stored. By executing STATCONT, another directory called products 168 | will be generated. The files to be processed, can be directly saved in 169 | the data directory or in subdirectories within data. In the examples 170 | provided here, we have a set of single-spectrum files (in ASCII format) 171 | saved in the subdirectories `SPEC_TESTS` and `SPINDEX`, and a FITS cube 172 | in the subdirectory `MAP_TESTS`. 173 | 174 | 175 | Determining the continuum in single spectrum files (ASCII files) 176 | ---------------------------------------------------------------- 177 | 178 | ``` 179 | statcont -p SPEC_TESTS -s my_emission -n 1 180 | ``` 181 | 182 | - The option -p indicates the subdirectory in data that contains 183 | the file to be analyzed 184 | - The option -s indicates the name of the ASCII file to be 185 | analyzed, without the extension [.dat] 186 | - The option -n indicates the rms noise level (in the units of the 187 | data) of the data to be analyzed. In this case, it is 1 K 188 | 189 | If you want to determine the continuum level: 190 | 191 | ``` 192 | statcont -p SPEC_TESTS -s my_emission -n 1 --continuum 193 | ``` 194 | 195 | - The option --continuum makes use of the 'corrected sigma-clipping 196 | algorithm' described in [Sanchez-Monge et al (2018)](https://ui.adsabs.harvard.edu/abs/2018A%26A...609A.101S/abstract), to determine 197 | the continuum level, the error in the continuum level, and to 198 | produce a file that contains only the line emission, i.e. a 199 | continuum-subtracted file 200 | 201 | Using different methods to determine the continuum level. STATCONT 202 | contains a set of different statistical methods that can be used by the 203 | user at his/her convenience. You can select all them like this: 204 | 205 | ``` 206 | statcont -p SPEC_TESTS -s my_emission -n 1 --call 207 | ``` 208 | 209 | Or you can select individual methods like: 210 | 211 | ``` 212 | statcont -p SPEC_TESTS -s my_emission -n 1 --cmax 213 | statcont -p SPEC_TESTS -s my_emission -n 1 --cmean 214 | statcont -p SPEC_TESTS -s my_emission -n 1 --cmedian 215 | statcont -p SPEC_TESTS -s my_emission -n 1 --cpercent 216 | statcont -p SPEC_TESTS -s my_emission -n 1 --cGaussian 217 | statcont -p SPEC_TESTS -s my_emission -n 1 --cKDEmax 218 | statcont -p SPEC_TESTS -s my_emission -n 1 --csigmaclip 219 | ``` 220 | 221 | You can call several methods at once: 222 | 223 | ``` 224 | statcont -p SPEC_TESTS -s my_emission -n 1 --cmax --cGaussian --csigmaclip 225 | ``` 226 | 227 | The different methods are explained in [Sanchez-Monge et al (2018)](https://ui.adsabs.harvard.edu/abs/2018A%26A...609A.101S/abstract) 228 | 229 | If you want to remove the continuum from the original spectrum, in 230 | order to produce a line-only data file, you can use: 231 | 232 | ``` 233 | statcont -p SPEC_TESTS - s my_emission -n 1 --csigmaclip --cfree 234 | ``` 235 | 236 | - The option --cfree uses the 'corrected sigma-clipping algorithm' 237 | to determine the continuum, and removes it from the original 238 | datafile. 239 | 240 | You can use other example files, like for example: 241 | 242 | ``` 243 | statcont -p SPEC_TESTS -s my_absorption -n 1 --continuum 244 | ``` 245 | 246 | And you can select multiple files simultaneously, as long as they are 247 | saved in the same subdirectory, and they are considered to have the 248 | same rms noise level (option -n ): 249 | 250 | ``` 251 | statcont -p SPEC_TESTS -s my_emission my_absorption my_broad-lines -n 1 --continuum 252 | ``` 253 | 254 | The products can be found in products/SPEC_TESTS 255 | You can produce plots of the spectrum analyzed with the continuum 256 | levels by using the option --plots. As an example: 257 | 258 | ``` 259 | statcont -p SPEC_TESTS -s my_emission -n 1 --continuum --plots 260 | ``` 261 | 262 | In this case the plot is saved in products/SPEC_TESTS/plots/my_emission_1_1.png 263 | You can use all the continuum methods and plot them all together, like: 264 | 265 | ``` 266 | statcont -p SPEC_TESTS -s my_emission -n 1 --call --plots 267 | ``` 268 | 269 | Have a look now at the plot products/SPEC_TESTS/plots/my_emission_1_1.png (see image below) 270 | 271 | ![STATCONT all methods](figures/my_emission_1_1.png) 272 | 273 | 274 | Determining the continuum in a 3D cube file (FITS files) 275 | -------------------------------------------------------- 276 | 277 | ``` 278 | statcont -p MAP_TESTS -i SYNTHETIC_cube -n 1 279 | ``` 280 | 281 | - The option -p indicates the subdirectory in data that contains 282 | the file to be analyzed 283 | - The option -i indicates the name of the FITS file to be analyzed, 284 | without the extension [.fits] 285 | - The option -n indicates the rms noise level (in the units of the 286 | data) of the data to be analyzed. In this case, it is 1 K 287 | 288 | If you want to determine the continuum level: 289 | 290 | ``` 291 | statcont -p MAP_TESTS -i SYNTHETIC_cube -n 1 --continuum 292 | ``` 293 | 294 | This process analyzes each individual pixel, determining the continuum 295 | level, and then combines all the pixels to produce a continuum FITS 296 | image with the label "_continuum". Simultaneously, the --csigmaclip 297 | method provides information on the error in the determination of the 298 | continuum that is saved as a FITS image with the label "_noise". 299 | Finally, a line-only FITS datacube is also produced. All these files 300 | are saved in the directory products/MAP_TESTS 301 | 302 | All the other options applicable to the single-spectrum ASCII files are 303 | also available for the FITS images (e.g. different continuum methods, 304 | creation of plots). 305 | 306 | If your original FITS file is too large and you just want to determine 307 | the continuum level of a small portion you can indicate it like this: 308 | 309 | ``` 310 | statcont -p MAP_TESTS -i SYNTHETIC_cube -n 1 --continuum --cutout 25 25 6 311 | ``` 312 | 313 | - The --cutout option allows to select a central pixel (in this case 314 | 25, 25) and the number of pixels in each direction of the final 315 | image (in this case 6). With this option, the products are saved 316 | with the label "_cutout" 317 | 318 | 319 | Determining the spectral index from multiple input files 320 | -------------------------------------------------------- 321 | 322 | If you have multiple ASCII or FITS files at different frequencies, you can use 323 | the option `--spindex` to determine, first, the continuum level of every 324 | single file, and then the spectral index, i.e. the variation of the 325 | continuum emission with frequency. 326 | 327 | The spectral index (ALPHA) is defined as flux = FACTOR * frequency^(ALPHA) 328 | 329 | ``` 330 | statcont -p SPINDEX -l list.txt -n 1 --continuum 331 | statcont -p SPINDEX -l list.txt -n 1 --spindex 332 | ``` 333 | 334 | The first command determines the continuum level for all the files contained in the list.txt file, while the second command determines the spectral index. 335 | 336 | ----------------------------------- 337 | Real data examples 338 | ----------------------------------- 339 | 340 | If you have multiple ASCII or FITS files at different frequencies, you can use 341 | 342 | | ![SgrB2](figures/plot_SgrB2.png) | ![G29.96-0.02](figures/plot_G29.png) | 343 | |:--:|:--:| 344 | | *Example case SgrB2(N) (see [Sanchez-Monge et al 2017](https://ui.adsabs.harvard.edu/abs/2017A%26A...604A...6S/abstract))* | *Example case G29.96-0.02 (see [Cesaroni et al 2017](https://ui.adsabs.harvard.edu/abs/2017A%26A...602A..59C/abstract))* | 345 | 346 | In both examples: (Top-left) Continuum emission map as determined with STATCONT. (Top-right) Continuum emission map determined with the classical approach (search for line-free channels). (Middle-left) Noise map obtained with STATCONT. (Middle-right) Ratio of the STATCONT to classical-approach continuum maps. (Bottom panels) Continuum-subtracted spectra using STATCONT towards two selected positions A and B, shown in the top-left panel. 347 | 348 | 349 | ----------------------------------- 350 | Publications citing STATCONT 351 | ----------------------------------- 352 | 353 | The following is a list with more than 30 publications using STATCONT in their analysis. The publications cover topics of low and high-mass star formation, extragalactic sources and astrochemical studies. 354 | 355 | - *Is There Any Linkage between Interstellar Aldehyde and Alcohol?*
by Mondal et al. 2021, ApJ, 922, 194 ([link](https://ui.adsabs.harvard.edu/abs/2021ApJ...922..194M/abstract)) 356 | 357 | - *A cold accretion flow onto one component of a multiple protostellar system*
by Murillo et al. 2021, accepted for publication in A&A ([link](https://ui.adsabs.harvard.edu/abs/2021arXiv211104039M/abstract)) 358 | 359 | - *Starburst Energy Feedback Seen Through HCO + /HOC + Emission in NGC 253 from ALCHEMI*
by Harada et al. 2021, accepted for publication in ApJ ([link](https://ui.adsabs.harvard.edu/abs/2021arXiv210906476H/abstract)) 360 | 361 | - *The GUAPOS project. II. A comprehensive study of peptide-like bond molecules*
by Colzi et al. 2021, A&A, 653, A129 ([link](https://ui.adsabs.harvard.edu/abs/2021A%26A...653A.129C/abstract)) 362 | 363 | - *ALCHEMI: an ALMA Comprehensive High-resolution Extragalactic Molecular Inventory. Survey presentation and first results from the ACA array*
by Martin et al. 2021, accepted for publication in A&A ([link](https://ui.adsabs.harvard.edu/abs/2021arXiv210908638M/abstract)) 364 | 365 | - *ALMA observations of doubly deuterated water: inheritance of water from the prestellar environment*
by Jensen et al. 2021, A&A, 650, A172 ([link](https://ui.adsabs.harvard.edu/abs/2021A%26A...650A.172J/abstract)) 366 | 367 | - *The ionized heart of a molecular disk. ALMA observations of the hyper-compact HII region G24.78+0.08 A1*
by Moscadelli et al. 2021, A&A, 650, A142 ([link](https://ui.adsabs.harvard.edu/abs/2021A%26A...650A.142M/abstract)) 368 | 369 | - *Star formation in 'the Brick': ALMA reveals an active protocluster in the Galactic centre cloud G0.253+0.016*
by Walker et al. 2021, MNRAS, 503, 77 ([link](https://ui.adsabs.harvard.edu/abs/2021MNRAS.503...77W/abstract)) 370 | 371 | - *Fragmentation in the massive G31.41+0.31 protocluster*
by Beltran et al. 2021, A&A, 648, A100 ([link](https://ui.adsabs.harvard.edu/abs/2021A%26A...648A.100B/abstract)) 372 | 373 | - *Digging into the Interior of Hot Cores with ALMA (DIHCA). I. Dissecting the High-mass Star-forming Core G335.579-0.292 MM1*
by Olguin et al. 2021, ApJ, 909, 199 ([link](https://ui.adsabs.harvard.edu/abs/2021ApJ...909..199O/abstract)) 374 | 375 | - *The prebiotic molecular inventory of Serpens SMM1. I. An investigation of the isomers CH3NCO and HOCH2CN*
by Ligterink et al. 2021, A&A, 647, A87 ([link](https://ui.adsabs.harvard.edu/abs/2021A%26A...647A..87L/abstract)) 376 | 377 | - *Subarcsecond Imaging of the Complex Organic Chemistry in Massive Star-forming Region G10.6-0.4*
by Law et al. 2021, ApJ, 909, 214 ([link](https://ui.adsabs.harvard.edu/abs/2021ApJ...909..214L/abstract)) 378 | 379 | - *The GUAPOS project: G31.41+0.31 Unbiased ALMA sPectral Observational Survey. I. Isomers of C2H4O2*
by Mininni et al. 2020, A&A, 644, A84 ([link](https://ui.adsabs.harvard.edu/abs/2020A%26A...644A..84M/abstract)) 380 | 381 | - *Multidirectional Mass Accretion and Collimated Outflows on Scales of 100-2000 au in Early Stages of High-mass Protostars*
by Goddi et al. 2020, ApJ, 905, 25 ([link](https://ui.adsabs.harvard.edu/abs/2020ApJ...905...25G/abstract)) 382 | 383 | - *Evidence for Dense Gas Heated by the Explosion in Orion KL*
by Li et al. 2020, ApJ, 901, 62 ([link](https://ui.adsabs.harvard.edu/abs/2020ApJ...901...62L/abstract)) 384 | 385 | - *Detection of hydroxyacetone in protostar IRAS 16293-2422 B*
by Zhou et al. 2020, RAA, 20, 125 ([link](https://ui.adsabs.harvard.edu/abs/2020RAA....20..125Z/abstract)) 386 | 387 | - *Constraints of the Formation and Abundances of Methyl Carbamate, a Glycine Isomer, in Hot Corinos*
by Sahu et al. 2020, ApJ, 899, 65 ([link](https://ui.adsabs.harvard.edu/abs/2020ApJ...899...65S/abstract)) 388 | 389 | - *Astrochemistry During the Formation of Stars*
by Jorgensen et al. 2020, ARA&A, 58, 727 ([link](https://ui.adsabs.harvard.edu/abs/2020ARA%26A..58..727J/abstract)) 390 | 391 | - *Exploring the formation pathways of formamide. Near young O-type stars*
by Allen et al. 2020, A&A, 636, A67 ([link](https://ui.adsabs.harvard.edu/abs/2020A%26A...636A..67A/abstract)) 392 | 393 | - *The HI/OH/Recombination line survey of the inner Milky Way (THOR): data release 2 and H I overview*
by Wang et al. 2020, A&A, 634, A83 ([link](https://ui.adsabs.harvard.edu/abs/2020A%26A...634A..83W/abstract)) 394 | 395 | - *Survey Observation of CH 3 NH 2 and Its Formation Process*
by Suzuki et al. 2019, submitted to ApJ ([link](https://ui.adsabs.harvard.edu/abs/2019arXiv190900528S/abstract)) 396 | 397 | - *Molecular analysis of a high-mass prestellar core candidate in W43-MM1*
by Molet et al. 2019, A&A, 626, A132 ([link](https://ui.adsabs.harvard.edu/abs/2019A%26A...626A.132M/abstract)) 398 | 399 | - *The CARMA-NRO Orion Survey. Filamentary structure as seen in C18O emission*
by Suri et al. 2019, A&A, 623, A142 ([link](https://ui.adsabs.harvard.edu/abs/2019A%26A...623A.142S/abstract)) 400 | 401 | - *A 10-M⊙ YSO with a Keplerian disk and a nonthermal radio jet*
by Moscadelli et al. 2019, A&A, 622, A206 ([link](https://ui.adsabs.harvard.edu/abs/2019A%26A...622A.206M/abstract)) 402 | 403 | - *Evidence for the First Extragalactic Hydrogen Recombination Line Maser in NGC 253*
by Baez-Rubio et al. 2018, ApJL, 867, L6 ([link](https://ui.adsabs.harvard.edu/abs/2018ApJ...867L...6B/abstract)) 404 | 405 | - *Chasing discs around O-type (proto)stars. ALMA evidence for an SiO disc and disc wind from G17.64+0.16*
by Maud et al. 2018, A&A, 620, A31 ([link](https://ui.adsabs.harvard.edu/abs/2018A%26A...620A..31M/abstract)) 406 | 407 | - *The Extraordinary Outburst in the Massive Protostellar System NGC 6334I-MM1: Flaring of the Water Masers in a North-South Bipolar Outflow Driven by MM1B*
by Brogan et al. 2018, ApJ, 866, 87 ([link](https://ui.adsabs.harvard.edu/abs/2018ApJ...866...87B/abstract)) 408 | 409 | - *The feedback of an HC HII region on its parental molecular core. The case of core A1 in the star-forming region G24.78+0.08*
by Moscadelli et al. 2018, A&A, 616, A66 ([link](https://ui.adsabs.harvard.edu/abs/2018A%26A...616A..66M/abstract)) 410 | 411 | - *Accelerating infall and rotational spin-up in the hot molecular core G31.41+0.31*
by Beltran et al. 2018, A&A, 615, A141 ([link](https://ui.adsabs.harvard.edu/abs/2018A%26A...615A.141B/abstract)) 412 | 413 | - *The physical and chemical structure of Sagittarius B2 - III. Radiative transfer simulations of the hot core Sgr B2(M) for methyl cyanide*
by Pols et al. 2018, A&A, 614, A123 ([link](https://ui.adsabs.harvard.edu/abs/2018A%26A...614A.123P/abstract)) 414 | 415 | - *Radio outburst from a massive (proto)star. When accretion turns into ejection*
by Cesaroni et al. 2018, A&A, 612, A103 ([link](https://ui.adsabs.harvard.edu/abs/2018A%26A...612A.103C/abstract)) 416 | 417 | - *Distributed Star Formation throughout the Galactic Center Cloud Sgr B2*
by Ginsburg et al. 2018, ApJ, 853, 171 ([link](https://ui.adsabs.harvard.edu/abs/2018ApJ...853..171G/abstract)) 418 | 419 | - *The physical and chemical structure of Sagittarius B2 - II. Continuum millimeter emission of SgrB2(M) and SgrB2(N) with ALMA*
by Sanchez-Monge et al. 2017, A&A, 604, A6 ([link](https://ui.adsabs.harvard.edu/abs/2017A%26A...604A...6S/abstract)) 420 | 421 | - *Chasing disks around O-type (proto)stars: Evidence from ALMA observations*
by Cesaroni et al. 2017, A&A, 602, A59 ([link](https://ui.adsabs.harvard.edu/abs/2017A%26A...602A..59C/abstract)) 422 | -------------------------------------------------------------------------------- /statcont/cont_finding.py: -------------------------------------------------------------------------------- 1 | import astropy 2 | from astropy.stats import sigma_clip 3 | import numpy as np 4 | from scipy import stats 5 | from scipy.optimize import leastsq 6 | import astropy.io.ascii as ascii 7 | 8 | ##====================================================================== 9 | def c_max(flux, rms_noise): 10 | """ 11 | Perform histogram distribution of variable flux, and determine 12 | the flux level of the maximum of the histogram 13 | 14 | Parameters 15 | ---------- 16 | flux : np.ndarray 17 | One-dimension array of flux values 18 | rms_noise : float 19 | The estimated RMS noise level of the data 20 | 21 | Returns 22 | ------- 23 | maximum_flux : float 24 | The measured continuum flux as the maximum of the histogram 25 | """ 26 | 27 | all_bins, all_hist, sel_bins, sel_hist, sel_flux = cont_histo(flux, rms_noise) 28 | 29 | maximum_flux = all_bins[(np.where(all_hist == all_hist.max())[0])[0]] 30 | 31 | return maximum_flux 32 | 33 | ##====================================================================== 34 | def c_mean(flux, rms_noise): 35 | """ 36 | Perform mean of the distribution of variable flux, and determine 37 | the mean of a selected range around the maximum of the histogram 38 | 39 | Parameters 40 | ---------- 41 | flux : np.ndarray 42 | One-dimension array of flux values 43 | rms_noise : float 44 | The estimated RMS noise level of the data 45 | 46 | Returns 47 | ------- 48 | mean_flux : float 49 | The measured continuum flux as the mean of the distribution 50 | meansel_flux : float 51 | The measured continuum flux as the mean of a selected range 52 | around the maximum of the distribution 53 | """ 54 | 55 | all_bins, all_hist, sel_bins, sel_hist, sel_flux = cont_histo(flux, rms_noise) 56 | 57 | mean_flux = np.mean(flux) 58 | meansel_flux = np.mean(sel_flux) 59 | 60 | return mean_flux, meansel_flux 61 | 62 | ##====================================================================== 63 | def c_median(flux, rms_noise): 64 | """ 65 | Perform median of the distribution of variable flux, and determine 66 | the median of a selected range around the maximum of the histogram 67 | 68 | Parameters 69 | ---------- 70 | flux : np.ndarray 71 | One-dimension array of flux values 72 | rms_noise : float 73 | The estimated RMS noise level of the data 74 | 75 | Returns 76 | ------- 77 | median_flux : float 78 | The measured continuum flux as the median of the distribution 79 | mediansel_flux : float 80 | The measured continuum flux as the median of a selected range 81 | around the maximum of the distribution 82 | """ 83 | 84 | all_bins, all_hist, sel_bins, sel_hist, sel_flux = cont_histo(flux, rms_noise) 85 | 86 | median_flux = np.median(flux) 87 | mediansel_flux = np.median(sel_flux) 88 | 89 | return median_flux, mediansel_flux 90 | 91 | ##====================================================================== 92 | def c_percent(flux, percentile): 93 | """ 94 | Perform numpy percentile to determine the level of the selected 95 | percentile 96 | 97 | Parameters 98 | ---------- 99 | flux : np.ndarray 100 | One-dimension array of flux values 101 | percentile : float 102 | The selected percentile 103 | 104 | Returns 105 | ------- 106 | percent_flux : float 107 | The measured continuum flux at the selected percentile 108 | """ 109 | 110 | percent_flux = np.percentile(flux, percentile) 111 | 112 | return percent_flux 113 | 114 | ##====================================================================== 115 | def c_KDEmax(flux, rms_noise, betaversion): 116 | """ 117 | Perform KDE of the distribution and determine the position of the 118 | maximum 119 | 120 | Parameters 121 | ---------- 122 | flux : np.ndarray 123 | One-dimension array of flux values 124 | rms_noise : float 125 | The estimated RMS noise level of the data 126 | betaversion : logic 127 | Activate more functionalities for developers 128 | 129 | Returns 130 | ------- 131 | KDEmax_flux : float 132 | The measured continuum flux as the position of the maximum 133 | of the KDE 134 | """ 135 | 136 | # Definition of the kernel following Silverman's rule 137 | # - width = [4/(3*ndata)]^(1/5)*min(dispersion, IQR/1/.34) 138 | # In SciPy the dispersion is included in the covariance factor 139 | # and therefore we need to divide by this factor 140 | # Following Silverman 1998, Eqs 3.28 and 3.30 141 | # B. W. Silverman, Density Estimation for Statistics and Data Analysis (CRC Press, Boca Raton, 1998) 142 | # 143 | # For manual definition of the kernel width, in SciPy: 144 | # - KDE_bandwidth = rms_noise/np.std(flux) 145 | # with this expression the kernel width equals "rms_noise" 146 | 147 | Silverman_spread = min(np.std(flux), ((np.percentile(flux, 75)-np.percentile(flux, 25))/1.34)) 148 | KDE_bandwidth = ((4./(3.*len(flux)))**(1./5.)*Silverman_spread)/np.std(flux) 149 | scipy_kde = stats.gaussian_kde(flux, bw_method=KDE_bandwidth) 150 | KDExmin, KDExmax = min(flux), max(flux) 151 | KDEx = np.mgrid[KDExmin:KDExmax:5000j] 152 | positions = np.vstack([KDEx.ravel()]) 153 | KDEpos = scipy_kde(positions) 154 | KDEmax_flux = positions.T[np.argmax(KDEpos)] 155 | 156 | # Write out the KDE as ASCII file 157 | if betaversion: 158 | ascii.write((KDEx, KDEpos), output='statcont-developers/STATCONT_KDE_distribution.dat') 159 | 160 | return KDEmax_flux 161 | 162 | ##====================================================================== 163 | def c_Gaussian(flux, rms_noise): 164 | """ 165 | Perform Gaussian fit to the distribution of variable flux, and determine 166 | the center and width of the Gaussian. Similarly, perform the Gaussian 167 | fit to a selected range of the distribution around the maximum of 168 | the histogram, and determine the center and width of the new Gaussian 169 | 170 | Parameters 171 | ---------- 172 | flux : np.ndarray 173 | One-dimension array of flux values 174 | rms_noise : float 175 | The estimated RMS noise level of the data 176 | 177 | Returns 178 | ------- 179 | Gaussian_flux : float 180 | Gaussian_noise : float 181 | The measured continuum flux and estimated 1-sigma noise as the 182 | center and width of the Gaussian fit to the histogram distribution 183 | The estimated 1-sigma per-channel noise around that measurement 184 | GaussNw_flux : float 185 | GaussNw_noise : float 186 | The measured continuum flux and estimated 1-sigma noise as the 187 | center and width of the Gaussian fit to a selected range around 188 | the maximum of the distribution 189 | """ 190 | 191 | fitfunc = lambda p, x: p[0]*np.exp(-0.5*((x-p[1])/p[2])**2.) 192 | errfunc = lambda p, x, y: (y - fitfunc(p, x)) 193 | 194 | all_bins, all_hist, sel_bins, sel_hist, sel_flux = cont_histo(flux, rms_noise) 195 | 196 | meansel_flux = np.mean(sel_flux) 197 | meansel_sigma = np.std(sel_flux) 198 | 199 | init = [all_hist.max(), meansel_flux, meansel_sigma] 200 | out = leastsq(errfunc, init, args=(all_bins, all_hist)) 201 | c = out[0] 202 | Gaussian_flux = c[1] 203 | Gaussian_noise = c[2] 204 | 205 | init = [all_hist.max(), meansel_flux, meansel_sigma] 206 | out = leastsq(errfunc, init, args=(sel_bins, sel_hist)) 207 | d = out[0] 208 | GaussNw_flux = d[1] 209 | GaussNw_noise = d[2] 210 | 211 | return Gaussian_flux, Gaussian_noise, GaussNw_flux, GaussNw_noise 212 | 213 | ##====================================================================== 214 | def c_sigmaclip1D(flux, rms_noise, betaversion, sigma_clip_threshold=2.0): 215 | """ 216 | Perform sigma-clipping to determine the mean flux level, with different 217 | adaptations for emission- and absorption-dominated spectra 218 | It runs on one-dimensional arrays 219 | 220 | Parameters 221 | ---------- 222 | flux : np.ndarray 223 | One-dimension array of flux values 224 | rms_noise : float 225 | The estimated RMS noise level of the data 226 | betaversion : logic 227 | Activate more functionalities for developers 228 | sigma_clip_threshold : float 229 | The threshold in number of sigma above/below which to reject outlier 230 | data 231 | 232 | Returns 233 | ------- 234 | sigmaclip_flux_prev : float 235 | sigmaclip_flux : float 236 | sigmaclip_noise : float 237 | The measured continuum flux and estimated 1-sigma per-channel noise 238 | around that measurement 239 | The variable sigmaclip_flux_prev contains the continuum determined 240 | with the sigma-clipping method without applying the correction 241 | of STATCONT 242 | """ 243 | 244 | # Sigma-clipping method applied to the flux array 245 | if astropy.version.major >= 3: 246 | filtered_data = sigma_clip(flux, sigma=sigma_clip_threshold, 247 | maxiters=None) 248 | elif astropy.version.major >= 1: 249 | filtered_data = sigma_clip(flux, sigma=sigma_clip_threshold, 250 | maxiters=None) 251 | elif astropy.version.major < 1: 252 | filtered_data = sigma_clip(flux, sig=sigma_clip_threshold, maxiters=None) 253 | 254 | sigmaclip_flux_prev = sigmaclip_flux = np.mean(filtered_data) 255 | sigmaclip_noise = sigmaclip_sigma = np.std(filtered_data) 256 | mean_flux = np.mean(flux) 257 | 258 | # Correction of sigma-clip continuum level, making use of the 259 | # presence of emission and/or absorption line features 260 | 261 | # Set up the fraction of channels (in %) that are in emission 262 | fraction_emission = 0 263 | fraction_emission = sum(i > (sigmaclip_flux+1*rms_noise) for i in flux) 264 | fraction_emission = 100*fraction_emission/len(flux) 265 | 266 | # Set up the fraction of channels (in %) that are in absorption 267 | fraction_absorption = 0 268 | fraction_absorption = sum(i < (sigmaclip_flux-1*rms_noise) for i in flux) 269 | fraction_absorption = 100*fraction_absorption/len(flux) 270 | 271 | # Apply correction to continuum level 272 | # see details in Sect. 2.4 of Sanchez-Monge et al. (2017) 273 | if (fraction_emission < 33 and fraction_absorption < 33): 274 | sigmaclip_flux = sigmaclip_flux_prev 275 | elif (fraction_emission >= 33 and fraction_absorption < 33): 276 | if (fraction_emission-fraction_absorption > 25): 277 | sigmaclip_flux = sigmaclip_flux_prev - 1.0*sigmaclip_sigma 278 | if (fraction_emission-fraction_absorption <= 25): 279 | sigmaclip_flux = sigmaclip_flux_prev - 0.5*sigmaclip_sigma 280 | elif (fraction_emission < 33 and fraction_absorption >= 33): 281 | if (fraction_absorption-fraction_emission > 25): 282 | sigmaclip_flux = sigmaclip_flux_prev + 1.0*sigmaclip_sigma 283 | if (fraction_absorption-fraction_emission <= 25): 284 | sigmaclip_flux = sigmaclip_flux_prev + 0.5*sigmaclip_sigma 285 | elif (fraction_emission >= 33 and fraction_absorption >= 33): 286 | if (fraction_emission-fraction_absorption > 25): 287 | sigmaclip_flux = sigmaclip_flux_prev - 1.0*sigmaclip_sigma 288 | if (fraction_absorption-fraction_emission > 25): 289 | sigmaclip_flux = sigmaclip_flux_prev + 1.0*sigmaclip_sigma 290 | if (abs(fraction_absorption-fraction_emission) <= 25): 291 | sigmaclip_flux = sigmaclip_flux_prev 292 | 293 | if betaversion is False: 294 | return sigmaclip_flux_prev, sigmaclip_flux, sigmaclip_noise 295 | 296 | # Write out the original and filtered data as a two-column ASCII file 297 | if betaversion: 298 | ascii.write((flux, filtered_data), output='statcont-developers/STATCONT_sigmaclip_filtered.dat') 299 | 300 | # Determine the numbers of channels above and under the real continuum level, 301 | # for synthetic files with continuum level set to 50.0 302 | # (i.e. how many channels are in emission/absorption with respect to the total) 303 | # 304 | real_fraction_emission = 0 305 | real_fraction_emission = sum(i > (50.0+1*rms_noise) for i in flux) 306 | real_fraction_emission = 100*real_fraction_emission/len(flux) 307 | real_fraction_absorption = 0 308 | real_fraction_absorption = sum(i < (50.0-1*rms_noise) for i in flux) 309 | real_fraction_absorption = 100*real_fraction_absorption/len(flux) 310 | 311 | return sigmaclip_flux_prev, sigmaclip_flux, sigmaclip_noise, real_fraction_emission, fraction_emission, real_fraction_absorption, fraction_absorption 312 | 313 | ### For EMISSION-dominated spectra 314 | ##if (mean_flux-sigmaclip_flux_prev) > (+1.0*rms_noise): 315 | ## sigmaclip_flux = sigmaclip_flux_prev - sigmaclip_sigma 316 | ### For ABSORPTION-dominated spectra 317 | ##elif (mean_flux-sigmaclip_flux_prev) < (-1.0*rms_noise): 318 | ## sigmaclip_flux = sigmaclip_flux_prev + sigmaclip_sigma 319 | 320 | ##====================================================================== 321 | def c_sigmaclip(flux, rms_noise, freq_axis, sigma_clip_threshold=1.8): 322 | """ 323 | Perform sigma-clipping to determine the mean flux level, with different 324 | adaptations for emission- and absorption-dominated spectra 325 | Different to c_sigmaclip1D function, it works directly on arrays 326 | It speeds up the process of continuum determination 327 | 328 | Parameters 329 | ---------- 330 | flux : np.ndarray 331 | Multi-dimension array of flux values 332 | rms_noise : float 333 | The estimated RMS noise level of the data 334 | freq_axis : integer 335 | Python-based dimension for the frequency (usually 0 or 1) 336 | sigma_clip_threshold : float 337 | The threshold in number of sigma above/below which to reject outlier 338 | data 339 | 340 | Returns 341 | ------- 342 | sigmaclip_flux_prev : np.ndarray 343 | sigmaclip_flux : np.ndarray 344 | sigmaclip_noise : np.ndarray 345 | The measured continuum flux and estimated 1-sigma per-channel noise 346 | around that measurement 347 | The variable sigmaclip_flux_prev contains the continuum determined 348 | with the sigma-clipping method without applying the correction 349 | of STATCONT 350 | """ 351 | 352 | # Sigma-clipping method applied to the flux array 353 | if astropy.version.major >= 3: 354 | filtered_data = astropy.stats.sigma_clip(flux, sigma=sigma_clip_threshold, 355 | maxiters=None, axis=freq_axis) 356 | elif astropy.version.major < 3: 357 | filtered_data = astropy.stats.sigma_clip(flux, sigma=sigma_clip_threshold, 358 | iters=None, axis=freq_axis) 359 | 360 | sigmaclip_flux_prev = sigmaclip_flux = np.mean(filtered_data, axis=freq_axis) 361 | sigmaclip_noise = sigmaclip_sigma = np.std(filtered_data, axis=freq_axis) 362 | mean_flux = np.mean(flux) 363 | 364 | # Correction of sigma-clip continuum level, making use of the 365 | # presence of emission and/or absorption line features 366 | 367 | naxis = len(flux.shape) 368 | 369 | # Handle different shapes; Stokes cube, cube, and single spectra 370 | if naxis == 4: 371 | 372 | view1 = [0, slice(None), slice(None), slice(None)] 373 | 374 | if naxis == 3: 375 | 376 | view1 = [slice(None), slice(None), slice(None)] 377 | 378 | if naxis == 1: 379 | 380 | view1 = [slice(None)] 381 | 382 | # Set up the fraction of channels (in %) that are in emission 383 | fraction_emission = (100 * (flux[tuple(view1)] > 384 | (sigmaclip_flux+1*rms_noise)).sum(axis=0) / 385 | flux[tuple(view1)].shape[0]) 386 | 387 | # Set up the fraction of channels (in %) that are in absorption 388 | fraction_absorption = (100 * (flux[tuple(view1)] < 389 | (sigmaclip_flux-1*rms_noise)).sum(axis=0) / 390 | flux[tuple(view1)].shape[0]) 391 | 392 | # Apply correction to continuum level 393 | # see details in Sect. 2.4 of paper Sanchez-Monge et al. (2018) 394 | sigmaclip_flux_case1 = np.where((fraction_emission < 33) & 395 | (fraction_absorption < 33), 396 | sigmaclip_flux_prev, 0.0) 397 | sigmaclip_flux_case2 = np.where((fraction_emission >= 33) & 398 | (fraction_absorption < 33) & 399 | (fraction_emission-fraction_absorption > 400 | 25.0), sigmaclip_flux_prev - 401 | 1.0*sigmaclip_sigma, 0.0) 402 | sigmaclip_flux_case3 = np.where((fraction_emission >= 33) & 403 | (fraction_absorption < 33) & 404 | (fraction_emission-fraction_absorption <= 405 | 25.0), sigmaclip_flux_prev - 406 | 0.5*sigmaclip_sigma, 0.0) 407 | sigmaclip_flux_case4 = np.where((fraction_emission < 33) & 408 | (fraction_absorption >= 33) & 409 | (fraction_emission-fraction_absorption > 410 | 25.0), sigmaclip_flux_prev + 411 | 1.0*sigmaclip_sigma, 0.0) 412 | sigmaclip_flux_case5 = np.where((fraction_emission < 33) & 413 | (fraction_absorption >= 33) & 414 | (fraction_emission-fraction_absorption <= 415 | 25.0), sigmaclip_flux_prev + 416 | 0.5*sigmaclip_sigma, 0.0) 417 | sigmaclip_flux_case6 = np.where((fraction_emission >= 33) & 418 | (fraction_absorption >= 33) & 419 | (fraction_emission-fraction_absorption > 420 | 25.0), sigmaclip_flux_prev - 421 | 1.0*sigmaclip_sigma, 0.0) 422 | sigmaclip_flux_case7 = np.where((fraction_emission >= 33) & 423 | (fraction_absorption >= 33) & 424 | (fraction_absorption-fraction_emission > 425 | 25.0), sigmaclip_flux_prev + 426 | 1.0*sigmaclip_sigma, 0.0) 427 | sigmaclip_flux_case8 = np.where((fraction_emission >= 33) & 428 | (fraction_absorption >= 33) & 429 | (abs(fraction_absorption-fraction_emission) 430 | <= 25.0), sigmaclip_flux_prev, 0.0) 431 | 432 | sigmaclip_flux = (sigmaclip_flux_case1 + sigmaclip_flux_case2 + 433 | sigmaclip_flux_case3 + sigmaclip_flux_case4 + 434 | sigmaclip_flux_case5 + sigmaclip_flux_case6 + 435 | sigmaclip_flux_case7 + sigmaclip_flux_case8) 436 | 437 | # Remove masked values if any 438 | if isinstance(sigmaclip_flux_prev, np.ma.MaskedArray): 439 | sigmaclip_flux_prev = sigmaclip_flux_prev.filled() 440 | if isinstance(sigmaclip_flux, np.ma.MaskedArray): 441 | sigmaclip_flux = sigmaclip_flux.filled() 442 | if isinstance(sigmaclip_noise, np.ma.MaskedArray): 443 | sigmaclip_noise = sigmaclip_noise.filled() 444 | 445 | return sigmaclip_flux_prev, sigmaclip_flux, sigmaclip_noise, filtered_data 446 | 447 | ##====================================================================== 448 | def cont_histo(flux, rms_noise): 449 | """ 450 | Create histogram distribution of the flux data 451 | and select a narrower range around the maximum 452 | of the histogram distribution 453 | 454 | Parameters 455 | ---------- 456 | flux : np.ndarray 457 | One-dimension array of flux values 458 | rms_noise : float 459 | The estimated RMS noise level of the data 460 | 461 | Returns 462 | ------- 463 | all_bins : np.ndarray 464 | One-dimension array with the value of bins of the histogram 465 | all_hist : np.ndarray 466 | One-dimension array with the value of the position of the bins 467 | sel_bins : np.ndarray 468 | One-dimension array with the value of bins of the histogram 469 | for the selected bins around the maximum 470 | sel_hist : np.ndarray 471 | One-dimension array with the value of position of the bins 472 | for the selected bins around the maximum 473 | sel_flux : np.ndarray 474 | One-dimension array of the flux values selected 475 | around the maximum of the histogram 476 | """ 477 | 478 | # 479 | # creating a general histogram of the flux data 480 | # main variables are: 481 | # all_hist - counts in each bin of the histogram 482 | # all_bins - location of the bins (fluxes) 483 | # all_number_* - index of the array 484 | number_bins = int((np.amax(flux)-np.amin(flux))/(1*rms_noise)) 485 | all_hist, all_bin_edges = np.histogram(flux, number_bins) 486 | all_bins = all_bin_edges[0:len(all_bin_edges)-1] 487 | all_bins = [x + (all_bins[1]-all_bins[0])/2. for x in all_bins] 488 | all_number_max_array = (np.where(all_hist == all_hist.max())[0]) 489 | all_number_max = all_number_max_array[0] 490 | all_bins_max = (all_bin_edges[all_number_max] + (all_bins[1]-all_bins[0])/2.) 491 | 492 | # Gaussian fit around the maximum of the distribution 493 | # determining the range to fit the Gaussian function 494 | all_number_left = (np.where(((all_hist == 0) & (all_bins <= all_bins_max)) | (all_bins == all_bins[0]))[0]).max() 495 | all_number_right = (np.where(((all_hist == 0) & (all_bins >= all_bins_max)) | (all_bins == all_bins[number_bins-1]))[0]).min() 496 | all_number_total = abs(all_number_right-all_number_max)+abs(all_number_left-all_number_max) 497 | emission_absorption_ratio = abs(all_number_right-all_number_max)*1.0/(all_number_total*1.0) 498 | if (emission_absorption_ratio >= 0.66): 499 | lower_all_bins = all_bins_max - 8. * (all_bins[1]-all_bins[0]) 500 | upper_all_bins = all_bins_max + 4. * (all_bins[1]-all_bins[0]) 501 | if (emission_absorption_ratio <= 0.33): 502 | lower_all_bins = all_bins_max - 4. * (all_bins[1]-all_bins[0]) 503 | upper_all_bins = all_bins_max + 8. * (all_bins[1]-all_bins[0]) 504 | if ((emission_absorption_ratio > 0.33) and (emission_absorption_ratio < 0.66)): 505 | lower_all_bins = all_bins_max - 5. * (all_bins[1]-all_bins[0]) 506 | upper_all_bins = all_bins_max + 5. * (all_bins[1]-all_bins[0]) 507 | sel_bins_array = np.where((all_bins >= lower_all_bins) & (all_bins <= upper_all_bins))[0] 508 | if (len(sel_bins_array) < 3): 509 | sel_bins_array = [sel_bins_array[0]-2, sel_bins_array[0]-1, sel_bins_array[0], sel_bins_array[0]+1, sel_bins_array[0]+2] 510 | lower_all_bins = all_bins[sel_bins_array[0]] 511 | upper_all_bins = all_bins[sel_bins_array[len(sel_bins_array)-1]] 512 | sel_bins = all_bins[sel_bins_array[0]:sel_bins_array[len(sel_bins_array)-1]+1] 513 | sel_hist = all_hist[sel_bins_array[0]:sel_bins_array[len(sel_bins_array)-1]+1] 514 | sel_flux = flux[(flux >= lower_all_bins) & (flux <= upper_all_bins)] 515 | 516 | return all_bins, all_hist, sel_bins, sel_hist, sel_flux 517 | 518 | def c_sigmaclip_scube(cube, rms_noise, freq_axis=0, sigma_clip_threshold=1.8, 519 | rechunk=[-1, 'auto', 'auto'], 520 | save_to_tmp_dir=True, 521 | verbose=False): 522 | """ 523 | Perform sigma-clipping to determine the mean flux level, with different 524 | adaptations for emission- and absorption-dominated spectra 525 | Different to c_sigmaclip1D function, it works directly on arrays 526 | It speeds up the process of continuum determination 527 | 528 | Parameters 529 | ---------- 530 | flux : np.ndarray 531 | Multi-dimension array of flux values 532 | rms_noise : float 533 | The estimated RMS noise level of the data 534 | freq_axis : integer 535 | Python-based dimension for the frequency (usually 0 or 1) 536 | sigma_clip_threshold : float 537 | The threshold in number of sigma above/below which to reject outlier 538 | data 539 | rechunk : None or list 540 | Shape to rechunk the dask cube to. -1 is to use the whole axis, 541 | 'auto' is to automatically determine it. [-1, 'auto', 'auto'] 542 | chunks into full spectral with automatically-determined spatial 543 | chunk sizes. [-1,1,1] would be chunking each spectrum separately. 544 | save_to_tmp_dir : bool 545 | Save the intermediate calculated ``sigma_clip_spectrally`` result to 546 | a temporary ``zarr`` file before doing subsequent operations? 547 | This may speed up calculations by ~2x. Be sure that your default 548 | temp directory can store the full cube; the tempdir location can be 549 | set with the environmental variable TEMPDIR. 550 | 551 | Returns 552 | ------- 553 | sigmaclip_flux_prev : np.ndarray 554 | sigmaclip_flux : np.ndarray 555 | sigmaclip_noise : np.ndarray 556 | The measured continuum flux and estimated 1-sigma per-channel noise 557 | around that measurement 558 | The variable sigmaclip_flux_prev contains the continuum determined 559 | with the sigma-clipping method without applying the correction 560 | of STATCONT 561 | """ 562 | from astropy import units as u 563 | 564 | # ensure the rms_noise is in the right unit 565 | rms_noise = u.Quantity(rms_noise, cube.unit) 566 | 567 | if rechunk is not None: 568 | try: 569 | # if dask, rechunk to use full spectral axes 570 | cube = cube.rechunk(rechunk) 571 | except AttributeError: 572 | pass 573 | 574 | 575 | # print out the cube to show its chunking dimensions 576 | if verbose: 577 | print(cube) 578 | 579 | # Sigma-clipping method applied to the flux array 580 | try: 581 | filtered_cube = cube.sigma_clip_spectrally(threshold=sigma_clip_threshold, 582 | save_to_tmp_dir=save_to_tmp_dir, 583 | maxiters=None) 584 | except TypeError: 585 | # if the cube is not a dask_spectral_cube 586 | filtered_cube = cube.sigma_clip_spectrally(threshold=sigma_clip_threshold, 587 | maxiters=None) 588 | 589 | sigmaclip_flux_prev = sigmaclip_flux = filtered_cube.mean(axis=freq_axis) 590 | sigmaclip_noise = sigmaclip_sigma = filtered_cube.std(axis=freq_axis) 591 | 592 | # Correction of sigma-clip continuum level, making use of the 593 | # presence of emission and/or absorption line features 594 | 595 | # Set up the fraction of channels (in %) that are in emission 596 | fraction_emission = (100 * (cube > 597 | (sigmaclip_flux+1*rms_noise)).include().sum(axis=freq_axis) / 598 | cube.shape[freq_axis]) 599 | 600 | # Set up the fraction of channels (in %) that are in absorption 601 | fraction_absorption = (100 * (cube < 602 | (sigmaclip_flux-1*rms_noise)).include().sum(axis=freq_axis) / 603 | cube.shape[freq_axis]) 604 | 605 | # Apply correction to continuum level 606 | # see details in Sect. 2.4 of paper Sanchez-Monge et al. (2018) 607 | sigmaclip_flux_case1 = np.where((fraction_emission < 33) & 608 | (fraction_absorption < 33), 609 | sigmaclip_flux_prev, 0.0) 610 | sigmaclip_flux_case2 = np.where((fraction_emission >= 33) & 611 | (fraction_absorption < 33) & 612 | (fraction_emission-fraction_absorption > 613 | 25.0), sigmaclip_flux_prev - 614 | 1.0*sigmaclip_sigma, 0.0) 615 | sigmaclip_flux_case3 = np.where((fraction_emission >= 33) & 616 | (fraction_absorption < 33) & 617 | (fraction_emission-fraction_absorption <= 618 | 25.0), sigmaclip_flux_prev - 619 | 0.5*sigmaclip_sigma, 0.0) 620 | sigmaclip_flux_case4 = np.where((fraction_emission < 33) & 621 | (fraction_absorption >= 33) & 622 | (fraction_emission-fraction_absorption > 623 | 25.0), sigmaclip_flux_prev + 624 | 1.0*sigmaclip_sigma, 0.0) 625 | sigmaclip_flux_case5 = np.where((fraction_emission < 33) & 626 | (fraction_absorption >= 33) & 627 | (fraction_emission-fraction_absorption <= 628 | 25.0), sigmaclip_flux_prev + 629 | 0.5*sigmaclip_sigma, 0.0) 630 | sigmaclip_flux_case6 = np.where((fraction_emission >= 33) & 631 | (fraction_absorption >= 33) & 632 | (fraction_emission-fraction_absorption > 633 | 25.0), sigmaclip_flux_prev - 634 | 1.0*sigmaclip_sigma, 0.0) 635 | sigmaclip_flux_case7 = np.where((fraction_emission >= 33) & 636 | (fraction_absorption >= 33) & 637 | (fraction_absorption-fraction_emission > 638 | 25.0), sigmaclip_flux_prev + 639 | 1.0*sigmaclip_sigma, 0.0) 640 | sigmaclip_flux_case8 = np.where((fraction_emission >= 33) & 641 | (fraction_absorption >= 33) & 642 | (abs(fraction_absorption-fraction_emission) 643 | <= 25.0), sigmaclip_flux_prev, 0.0) 644 | 645 | sigmaclip_flux = (sigmaclip_flux_case1 + sigmaclip_flux_case2 + 646 | sigmaclip_flux_case3 + sigmaclip_flux_case4 + 647 | sigmaclip_flux_case5 + sigmaclip_flux_case6 + 648 | sigmaclip_flux_case7 + sigmaclip_flux_case8) 649 | 650 | # Remove masked values if any 651 | if isinstance(sigmaclip_flux_prev, np.ma.MaskedArray): 652 | sigmaclip_flux_prev = sigmaclip_flux_prev.filled() 653 | if isinstance(sigmaclip_flux, np.ma.MaskedArray): 654 | sigmaclip_flux = sigmaclip_flux.filled() 655 | if isinstance(sigmaclip_noise, np.ma.MaskedArray): 656 | sigmaclip_noise = sigmaclip_noise.filled() 657 | 658 | return sigmaclip_flux_prev, sigmaclip_flux, sigmaclip_noise 659 | -------------------------------------------------------------------------------- /tests/noise/my_narrow-range_n06.dat: -------------------------------------------------------------------------------- 1 | 226.2 60.95698033165329 2 | 226.2003 41.57787435644305 3 | 226.2006 41.27352164911207 4 | 226.2009 52.686837187964116 5 | 226.2012 50.62979600852148 6 | 226.2015 49.25122062680993 7 | 226.2018 53.332503205445406 8 | 226.2021 53.52025926745671 9 | 226.20239999999998 53.46132788311316 10 | 226.20270000000002 43.169079055655395 11 | 226.203 38.1735559526402 12 | 226.20329999999998 53.84482199981497 13 | 226.2036 51.965843213546385 14 | 226.2039 51.86565448766657 15 | 226.20420000000001 65.87522929657857 16 | 226.2045 46.1797016454129 17 | 226.20479999999998 54.13682810157396 18 | 226.20510000000002 47.30568817036081 19 | 226.2054 48.13143173452588 20 | 226.2057 52.39193361271183 21 | 226.206 57.12559684872347 22 | 226.2063 55.705292484001326 23 | 226.2066 54.1103903361945 24 | 226.2069 56.245595306409854 25 | 226.2072 48.26115974177311 26 | 226.2075 52.644657065877006 27 | 226.2078 51.92523783417359 28 | 226.2081 45.33102863940644 29 | 226.20839999999998 47.47494362552323 30 | 226.20870000000002 46.6943359880545 31 | 226.209 50.48349034187504 32 | 226.20929999999998 50.312806651079825 33 | 226.2096 45.00089287159339 34 | 226.2099 56.17264952620672 35 | 226.21020000000001 58.070496429291325 36 | 226.2105 53.463151916926826 37 | 226.21079999999998 49.15526391823055 38 | 226.21110000000002 51.319419818502894 39 | 226.2114 48.076864833009104 40 | 226.2117 49.12210348919388 41 | 226.212 45.54039543740502 42 | 226.2123 62.957339673927464 43 | 226.2126 64.3805198768153 44 | 226.2129 59.71625380305179 45 | 226.2132 55.55958798841916 46 | 226.2135 52.635444524296176 47 | 226.2138 52.42686474394593 48 | 226.2141 53.15580651675177 49 | 226.21439999999998 48.29909765250899 50 | 226.21470000000002 55.85645077386617 51 | 226.215 56.26236207978903 52 | 226.21529999999998 46.4088091057193 53 | 226.2156 58.7446389681682 54 | 226.2159 57.72251154165233 55 | 226.21620000000001 53.50263527769796 56 | 226.2165 66.863409042621 57 | 226.21679999999998 66.75134199261332 58 | 226.21710000000002 67.59526882416455 59 | 226.2174 54.56209973970759 60 | 226.2177 47.31967744006994 61 | 226.218 52.804771505920414 62 | 226.2183 45.466958622065135 63 | 226.2186 55.75976104395632 64 | 226.2189 46.991308121578555 65 | 226.2192 47.197486619249695 66 | 226.2195 55.49763314543209 67 | 226.2198 64.41105383208301 68 | 226.2201 46.92148237726605 69 | 226.22039999999998 56.97412188274706 70 | 226.22070000000002 54.44718517725532 71 | 226.221 46.733169190946285 72 | 226.22129999999999 43.22503721350751 73 | 226.2216 55.91447007005036 74 | 226.2219 60.45001858459037 75 | 226.22220000000002 53.93886958464527 76 | 226.2225 51.53211432703131 77 | 226.22279999999998 45.37836635991504 78 | 226.22310000000002 48.08232866906404 79 | 226.2234 50.08470981725877 80 | 226.2237 54.67889425026975 81 | 226.224 39.530368040960695 82 | 226.2243 55.658899225431185 83 | 226.2246 48.79187503143039 84 | 226.2249 46.132096856175814 85 | 226.2252 50.570475289765106 86 | 226.2255 54.611196773731635 87 | 226.2258 54.55746224897503 88 | 226.2261 46.76796273173387 89 | 226.22639999999998 51.04059332924108 90 | 226.22670000000002 51.82597660716094 91 | 226.227 52.58004477621927 92 | 226.22729999999999 56.537669896042765 93 | 226.2276 51.324842731808666 94 | 226.2279 48.12271454868374 95 | 226.22820000000002 48.99686834010977 96 | 226.2285 46.4776945454159 97 | 226.22879999999998 46.336417442690056 98 | 226.22910000000002 48.03800492851274 99 | 226.2294 59.226279985019616 100 | 226.2297 51.61325730501902 101 | 226.23 44.75061117721854 102 | 226.2303 50.46547881331998 103 | 226.2306 51.44135105196788 104 | 226.2309 54.711136615909695 105 | 226.2312 42.99894973643347 106 | 226.2315 59.5897648007775 107 | 226.2318 58.82281781782325 108 | 226.2321 50.06317956673265 109 | 226.23239999999998 59.09318281432559 110 | 226.23270000000002 46.03146027198665 111 | 226.233 50.134038360934156 112 | 226.23329999999999 49.54500449458949 113 | 226.2336 56.273236028481065 114 | 226.2339 49.52170203783747 115 | 226.23420000000002 54.6482380727053 116 | 226.2345 46.506433893404605 117 | 226.23479999999998 54.90410225708057 118 | 226.23510000000002 60.2322980786103 119 | 226.2354 50.643442185214695 120 | 226.2357 46.11529170470781 121 | 226.236 45.30000440393265 122 | 226.2363 48.22579468667785 123 | 226.2366 49.71459252664681 124 | 226.2369 42.44902913890249 125 | 226.2372 49.14421120435497 126 | 226.2375 51.82887096676125 127 | 226.2378 41.635528189580334 128 | 226.2381 57.89811414841022 129 | 226.23839999999998 48.248636028387764 130 | 226.23870000000002 44.16090681143871 131 | 226.239 51.89459649194999 132 | 226.2393 51.643967553555804 133 | 226.2396 58.85657907966251 134 | 226.2399 50.03885220796067 135 | 226.24020000000002 57.59464918871407 136 | 226.2405 66.1952204633603 137 | 226.24079999999998 65.49960865005819 138 | 226.24110000000002 86.53563489970526 139 | 226.2414 100.77939139903208 140 | 226.2417 117.39237427461019 141 | 226.242 130.1171179181972 142 | 226.2423 149.97237201210257 143 | 226.2426 193.32693869572134 144 | 226.2429 206.20085251850293 145 | 226.2432 255.08467892272358 146 | 226.2435 288.004326176844 147 | 226.2438 324.5681825598642 148 | 226.2441 345.047873367065 149 | 226.24439999999998 361.48961662365247 150 | 226.24470000000002 373.37899769856807 151 | 226.245 392.62474501115446 152 | 226.2453 394.8536561742188 153 | 226.2456 399.8733714551234 154 | 226.2459 399.5208932589597 155 | 226.24620000000002 415.42108297030046 156 | 226.2465 411.1206103481281 157 | 226.24679999999998 395.3137836473106 158 | 226.24710000000002 402.7834427910106 159 | 226.2474 424.2883767658088 160 | 226.2477 415.7752681538975 161 | 226.248 422.8641966855501 162 | 226.2483 424.5923799120552 163 | 226.2486 436.03552968273516 164 | 226.2489 441.3762164619626 165 | 226.2492 465.317017510089 166 | 226.2495 487.96342980454125 167 | 226.2498 509.90163944122713 168 | 226.2501 530.0289507593487 169 | 226.25039999999998 562.0169850124385 170 | 226.25070000000002 598.6069826181075 171 | 226.251 627.0246945441069 172 | 226.2513 684.772027701985 173 | 226.2516 701.5028435525589 174 | 226.2519 733.3902721123815 175 | 226.25220000000002 741.7209788037056 176 | 226.2525 742.2819737083086 177 | 226.25279999999998 751.4832126313851 178 | 226.25310000000002 761.7677394881312 179 | 226.2534 761.2480290545711 180 | 226.2537 737.7124078849014 181 | 226.254 743.190650401362 182 | 226.2543 729.6851408417645 183 | 226.2546 702.7938100657539 184 | 226.2549 677.6867543411676 185 | 226.2552 641.7359252553168 186 | 226.2555 603.2061205036829 187 | 226.2558 571.1305661112328 188 | 226.2561 545.0664324153952 189 | 226.25639999999999 513.7149210446166 190 | 226.25670000000002 491.13677018324506 191 | 226.257 466.645147942657 192 | 226.2573 446.464034378843 193 | 226.2576 443.4782716866532 194 | 226.2579 425.9308899517391 195 | 226.25820000000002 417.21002161590013 196 | 226.2585 413.9716943964333 197 | 226.25879999999998 417.60302481259924 198 | 226.25910000000002 414.66519435863324 199 | 226.2594 421.1352513652882 200 | 226.2597 418.14389143430515 201 | 226.26 408.2678937443487 202 | 226.2603 401.1282682340774 203 | 226.2606 413.99100501837995 204 | 226.2609 404.11363998688466 205 | 226.2612 395.12343704790396 206 | 226.2615 392.3024122629867 207 | 226.2618 368.12892631108434 208 | 226.2621 357.18432922777686 209 | 226.26239999999999 320.3008244349596 210 | 226.26270000000002 292.58098802779926 211 | 226.263 249.0148640736832 212 | 226.2633 221.66453437774732 213 | 226.2636 177.75809926936262 214 | 226.2639 158.01872855989103 215 | 226.26420000000002 133.07503667744996 216 | 226.2645 126.5976284392394 217 | 226.26479999999998 107.6694954684126 218 | 226.26510000000002 102.25809996557734 219 | 226.2654 87.21650904101665 220 | 226.2657 94.1250355801446 221 | 226.266 93.31338492181864 222 | 226.2663 85.65006222984746 223 | 226.2666 101.10239883857932 224 | 226.2669 100.17888572470572 225 | 226.2672 107.87310537448634 226 | 226.2675 123.23867237965906 227 | 226.2678 132.44392437547575 228 | 226.2681 146.97125001674797 229 | 226.26839999999999 151.51022155388353 230 | 226.26870000000002 155.55359356615182 231 | 226.269 166.48648895517056 232 | 226.2693 179.95403390138588 233 | 226.2696 196.61029062190556 234 | 226.2699 201.8910107712319 235 | 226.27020000000002 198.6476485958425 236 | 226.2705 207.12151259308888 237 | 226.27079999999998 203.26610402154176 238 | 226.27110000000002 223.75184004980696 239 | 226.2714 222.87933321262588 240 | 226.2717 217.77943727822907 241 | 226.272 218.88214755544695 242 | 226.2723 228.09413498720932 243 | 226.2726 210.61691493128097 244 | 226.2729 191.88185250065624 245 | 226.2732 190.3881480392364 246 | 226.2735 185.39914817252878 247 | 226.2738 173.5513803157893 248 | 226.2741 176.60391511915228 249 | 226.27439999999999 146.51331099119994 250 | 226.27470000000002 159.7927354956354 251 | 226.275 132.14922309631982 252 | 226.2753 135.2878808496186 253 | 226.2756 112.4676142884128 254 | 226.2759 111.94465296487357 255 | 226.27620000000002 91.13611745212884 256 | 226.2765 99.59267866752415 257 | 226.27679999999998 73.3807517372447 258 | 226.27710000000002 86.71615632107068 259 | 226.2774 64.74610409114753 260 | 226.2777 78.0787333326273 261 | 226.278 53.66096804888562 262 | 226.2783 62.19536196577489 263 | 226.2786 56.23477292136131 264 | 226.2789 65.1371216536773 265 | 226.2792 57.9992140034155 266 | 226.2795 59.239998693155044 267 | 226.2798 60.84121690213732 268 | 226.2801 63.175418443157966 269 | 226.2804 56.23674884342705 270 | 226.28070000000002 59.979626615892016 271 | 226.281 59.1228502542527 272 | 226.2813 43.9335238417969 273 | 226.2816 34.35504044093898 274 | 226.2819 52.91415930085527 275 | 226.28220000000002 41.92187766517897 276 | 226.2825 43.72374879593867 277 | 226.28279999999998 35.62846024216642 278 | 226.28310000000002 46.18870488707645 279 | 226.2834 34.8245123267083 280 | 226.2837 41.37185531151884 281 | 226.284 20.20907690978016 282 | 226.2843 28.965598838689267 283 | 226.2846 43.493769305547275 284 | 226.2849 45.41671985030728 285 | 226.2852 34.237713530774634 286 | 226.2855 22.47079368811837 287 | 226.2858 29.67766621900683 288 | 226.2861 17.19465641972375 289 | 226.2864 26.747329575523313 290 | 226.28670000000002 32.72862600771434 291 | 226.287 20.477913855516377 292 | 226.2873 21.77943024360198 293 | 226.2876 24.802453934437647 294 | 226.2879 27.310239131208498 295 | 226.28820000000002 26.6945804603807 296 | 226.2885 30.739103459060555 297 | 226.28879999999998 30.278164758310538 298 | 226.28910000000002 21.365363201487913 299 | 226.2894 24.77323784212303 300 | 226.2897 31.357757478905025 301 | 226.29 36.50665893096105 302 | 226.2903 35.716773735102706 303 | 226.2906 29.497134164393863 304 | 226.2909 43.30589530794257 305 | 226.2912 44.50701205286918 306 | 226.2915 45.55718425160237 307 | 226.2918 40.54372018718036 308 | 226.2921 48.26048945833405 309 | 226.2924 39.87244874507994 310 | 226.29270000000002 50.71700315020191 311 | 226.293 44.38732377686969 312 | 226.2933 41.48790274316597 313 | 226.2936 52.40161402201111 314 | 226.2939 47.105215467085 315 | 226.29420000000002 44.610744691019484 316 | 226.2945 48.55748365768858 317 | 226.29479999999998 40.79497751191707 318 | 226.29510000000002 36.625428433521535 319 | 226.2954 29.12431919849608 320 | 226.2957 36.439270133151766 321 | 226.296 25.206706985154636 322 | 226.2963 33.91511443559006 323 | 226.2966 40.82552504681905 324 | 226.2969 39.87385203279216 325 | 226.2972 24.966377604472832 326 | 226.2975 26.736815813381032 327 | 226.2978 19.049395535234993 328 | 226.2981 16.053017100282716 329 | 226.2984 24.51433244368212 330 | 226.29870000000003 19.033776523486637 331 | 226.299 26.158201602143443 332 | 226.2993 28.37691535244967 333 | 226.2996 28.751278455723167 334 | 226.2999 20.13487285598665 335 | 226.30020000000002 19.07155834166052 336 | 226.3005 19.776584472336175 337 | 226.30079999999998 36.23886731490276 338 | 226.30110000000002 16.651423856599628 339 | 226.3014 28.565749400435 340 | 226.3017 17.225431609231133 341 | 226.302 12.042504013391019 342 | 226.3023 14.651932491044036 343 | 226.3026 15.875457787783487 344 | 226.3029 27.151063247386773 345 | 226.3032 25.19808495039835 346 | 226.3035 17.026397308318025 347 | 226.3038 19.482484037808483 348 | 226.3041 16.729063707153355 349 | 226.3044 38.06634822505697 350 | 226.30470000000003 39.1294751573573 351 | 226.305 34.79451569751463 352 | 226.3053 20.29577904614852 353 | 226.3056 40.47243894833818 354 | 226.3059 30.84868937061518 355 | 226.30620000000002 39.986632076605375 356 | 226.3065 35.76492884510522 357 | 226.30679999999998 34.324301761142124 358 | 226.30710000000002 31.871095494584303 359 | 226.3074 41.92636278746011 360 | 226.3077 39.01579671060487 361 | 226.308 47.87671186262716 362 | 226.30829999999997 44.873575369119806 363 | 226.3086 36.32626619087258 364 | 226.3089 47.10947454156086 365 | 226.3092 42.71298180397825 366 | 226.3095 37.21256597171931 367 | 226.3098 41.69985961496428 368 | 226.3101 41.23672925194731 369 | 226.3104 39.64654058551974 370 | 226.31070000000003 46.491192610576775 371 | 226.311 43.57632316932898 372 | 226.3113 40.078280434057774 373 | 226.3116 49.591179018277955 374 | 226.31189999999998 43.709911844936535 375 | 226.31220000000002 45.026673937954364 376 | 226.3125 42.03181687303745 377 | 226.31279999999998 54.18439402587387 378 | 226.31310000000002 66.11313484845911 379 | 226.3134 52.973934808805296 380 | 226.3137 60.49430800877764 381 | 226.314 77.09382925297257 382 | 226.31429999999997 83.27174400493577 383 | 226.3146 84.98040514898825 384 | 226.3149 89.5688808678808 385 | 226.3152 95.29115451266412 386 | 226.3155 92.38030869237248 387 | 226.3158 97.487929089381 388 | 226.3161 92.25270121541028 389 | 226.3164 102.37851683887891 390 | 226.31670000000003 94.18791264309733 391 | 226.317 96.87871759524585 392 | 226.3173 91.90055235097735 393 | 226.3176 71.37417514299163 394 | 226.31789999999998 89.93449522809146 395 | 226.31820000000002 87.56860638257237 396 | 226.3185 81.13235299319376 397 | 226.31879999999998 80.9307674096523 398 | 226.3191 78.69277851454069 399 | 226.3194 81.22340096580665 400 | 226.3197 72.93439104992508 401 | 226.32 69.02527482035232 402 | 226.32029999999997 58.70629116717544 403 | 226.3206 58.73734996616581 404 | 226.3209 61.56039760696498 405 | 226.3212 63.31432431080165 406 | 226.3215 53.92618797337989 407 | 226.3218 54.52499981345541 408 | 226.3221 59.82739165863684 409 | 226.3224 50.590748344946604 410 | 226.3227 58.699505955898665 411 | 226.323 53.30035027166861 412 | 226.3233 48.452841208935546 413 | 226.3236 55.689816957571104 414 | 226.32389999999998 48.20960255627638 415 | 226.32420000000002 47.29719725371735 416 | 226.3245 48.97618975374585 417 | 226.32479999999998 53.927179083558514 418 | 226.3251 63.95112415917119 419 | 226.3254 55.113920073763595 420 | 226.3257 47.248893095255994 421 | 226.326 54.65677728231481 422 | 226.32629999999997 39.51131838045514 423 | 226.3266 51.10917305975969 424 | 226.3269 42.36177603686073 425 | 226.3272 46.289638710443185 426 | 226.3275 45.538506558656145 427 | 226.3278 32.87573830466936 428 | 226.3281 28.072415908582933 429 | 226.3284 47.939973443038326 430 | 226.3287 46.66249370293824 431 | 226.329 47.25852885357697 432 | 226.3293 32.110062088686476 433 | 226.3296 30.347646696194225 434 | 226.32989999999998 26.47860815177342 435 | 226.33020000000002 42.0889837883836 436 | 226.3305 25.23997402252228 437 | 226.33079999999998 26.58404867680594 438 | 226.3311 37.44557700752154 439 | 226.3314 42.999196128503456 440 | 226.3317 34.6406200067407 441 | 226.332 21.058010153883096 442 | 226.33229999999998 49.58814452694128 443 | 226.3326 32.27541201207865 444 | 226.3329 37.79930088237931 445 | 226.3332 30.125944259107772 446 | 226.3335 47.34808340139099 447 | 226.3338 49.05348523284522 448 | 226.3341 47.62581291897723 449 | 226.3344 58.68619374929222 450 | 226.3347 83.75836451957703 451 | 226.335 79.41795158849497 452 | 226.3353 96.98107639424943 453 | 226.3356 96.74471286788621 454 | 226.33589999999998 131.8334834141889 455 | 226.33620000000002 130.64088944609293 456 | 226.3365 154.17587148384686 457 | 226.33679999999998 142.16102396426416 458 | 226.3371 171.7212545328598 459 | 226.3374 171.66527267039663 460 | 226.3377 183.15309325903738 461 | 226.338 184.89979538512637 462 | 226.33829999999998 194.83736024561114 463 | 226.3386 204.0541945687638 464 | 226.3389 198.84001507738876 465 | 226.3392 203.43308552722752 466 | 226.3395 205.06363534488582 467 | 226.3398 191.0774767216892 468 | 226.3401 194.24211978290697 469 | 226.3404 201.0760757838968 470 | 226.3407 189.34679989970198 471 | 226.341 185.5191359747594 472 | 226.3413 174.02370056592795 473 | 226.3416 171.59361417363272 474 | 226.34189999999998 182.29959983053067 475 | 226.34220000000002 190.63771596726974 476 | 226.3425 175.05529282445096 477 | 226.34279999999998 172.47778627131297 478 | 226.3431 178.18002971551886 479 | 226.3434 163.6698355065843 480 | 226.3437 173.7240213772263 481 | 226.344 187.12302582893233 482 | 226.34429999999998 179.35229652394034 483 | 226.3446 193.61006483103333 484 | 226.3449 194.68077113103124 485 | 226.3452 194.15069512622568 486 | 226.3455 213.80520433475078 487 | 226.3458 212.10104900014113 488 | 226.3461 211.9516082584957 489 | 226.3464 214.94911154201304 490 | 226.3467 218.69901314158406 491 | 226.347 220.0247400972998 492 | 226.3473 221.26596450506867 493 | 226.3476 222.7300598983829 494 | 226.34789999999998 209.95771745817848 495 | 226.34820000000002 204.4031812319491 496 | 226.3485 201.5320036866919 497 | 226.34879999999998 189.51677914164992 498 | 226.3491 183.68915990039477 499 | 226.3494 173.7999964451088 500 | 226.3497 162.03488556678514 501 | 226.35 150.62621734185151 502 | 226.35029999999998 134.4725145052316 503 | 226.35060000000001 132.25158353419303 504 | 226.3509 126.39705327110728 505 | 226.3512 102.2725554718028 506 | 226.3515 103.572525541848 507 | 226.3518 95.97746193960349 508 | 226.3521 85.22458236951243 509 | 226.3524 77.7471155653797 510 | 226.3527 69.10265275602427 511 | 226.353 66.95509736618773 512 | 226.3533 59.687996240124576 513 | 226.3536 52.5475447824673 514 | 226.35389999999998 36.46880782854281 515 | 226.35420000000002 57.776427199548806 516 | 226.3545 38.77080712324229 517 | 226.35479999999998 29.363067022582783 518 | 226.3551 30.031014611524522 519 | 226.3554 27.821322615964107 520 | 226.3557 35.77701997102646 521 | 226.356 25.356581293701797 522 | 226.35629999999998 34.181027846200664 523 | 226.35660000000001 29.692904589810823 524 | 226.3569 30.932193509314267 525 | 226.3572 34.057967536624474 526 | 226.3575 32.11254640707415 527 | 226.3578 24.926551117495393 528 | 226.3581 33.62471000047455 529 | 226.3584 30.42853541087935 530 | 226.3587 41.904602667749955 531 | 226.359 31.342341883230333 532 | 226.3593 38.385394198312056 533 | 226.3596 42.80138676521391 534 | 226.35989999999998 35.80442371790483 535 | 226.36020000000002 36.58434163402849 536 | 226.3605 24.862705984874438 537 | 226.36079999999998 33.47201665267896 538 | 226.3611 24.972126239032487 539 | 226.3614 41.08816252462171 540 | 226.3617 39.83935338333349 541 | 226.362 26.47771033686348 542 | 226.36229999999998 38.936759301710694 543 | 226.36260000000001 25.59598554614166 544 | 226.3629 29.53255009058827 545 | 226.3632 24.317720746403662 546 | 226.3635 40.122755986574354 547 | 226.3638 26.961387359411276 548 | 226.3641 22.116511662658922 549 | 226.3644 28.740908578385415 550 | 226.3647 25.878402517601497 551 | 226.365 29.555163486667624 552 | 226.3653 42.983874903582084 553 | 226.3656 44.28735656390677 554 | 226.36589999999998 36.55926020158449 555 | 226.36620000000002 40.2395843764072 556 | 226.3665 45.721213385613275 557 | 226.36679999999998 44.055500424762144 558 | 226.3671 43.06222206348452 559 | 226.3674 54.50898511425701 560 | 226.3677 44.98171788907854 561 | 226.368 54.91416632165531 562 | 226.36829999999998 51.258042451638815 563 | 226.36860000000001 52.31460086341568 564 | 226.3689 49.714353299899905 565 | 226.3692 54.540238604747756 566 | 226.3695 54.5879599417286 567 | 226.3698 49.508880042611445 568 | 226.3701 50.25295384163271 569 | 226.3704 50.90979027891179 570 | 226.3707 40.17158648207837 571 | 226.371 50.459361814626675 572 | 226.3713 50.27152550495874 573 | 226.3716 45.25822747863774 574 | 226.37189999999998 47.70389383397134 575 | 226.37220000000002 58.35511608076132 576 | 226.3725 50.35966515075781 577 | 226.37279999999998 57.06083875946512 578 | 226.3731 40.07173953927845 579 | 226.3734 48.74877092494384 580 | 226.3737 50.475990296645385 581 | 226.374 57.76600084234194 582 | 226.37429999999998 49.81100758661884 583 | 226.37460000000002 48.91176851910481 584 | 226.3749 48.739942108257644 585 | 226.3752 47.53932089972081 586 | 226.3755 60.24511614113332 587 | 226.3758 53.76069375405514 588 | 226.3761 44.204505249980784 589 | 226.3764 56.59758293172481 590 | 226.3767 52.91052322498407 591 | 226.377 42.91729334537048 592 | 226.3773 50.72707075629487 593 | 226.3776 66.24807896915809 594 | 226.37789999999998 54.7159343136845 595 | 226.37820000000002 58.20389698162749 596 | 226.3785 63.49355711885982 597 | 226.37879999999998 57.80988321385182 598 | 226.3791 59.66140636070783 599 | 226.3794 60.096621856893464 600 | 226.3797 58.71737643148121 601 | 226.38 75.2500779930626 602 | 226.38029999999998 72.70908828052958 603 | 226.38060000000002 84.41855019142683 604 | 226.3809 76.29088963555526 605 | 226.3812 99.31849254848316 606 | 226.3815 96.38038951678953 607 | 226.3818 93.99498260792977 608 | 226.3821 105.55124685080501 609 | 226.3824 103.17623924296518 610 | 226.3827 112.59571529159041 611 | 226.383 112.50844771614427 612 | 226.3833 125.02487332011488 613 | 226.3836 129.48870638125425 614 | 226.38389999999998 122.06021039896643 615 | 226.38420000000002 131.01526093952853 616 | 226.3845 140.76690010494792 617 | 226.38479999999998 125.0887123308901 618 | 226.3851 134.8349658541142 619 | 226.3854 130.2450870390885 620 | 226.3857 114.61165700420865 621 | 226.386 125.85791390683879 622 | 226.38629999999998 111.67770683637782 623 | 226.38660000000002 118.78102763155151 624 | 226.3869 121.00964261233078 625 | 226.3872 106.08964418499694 626 | 226.3875 106.51189958136332 627 | 226.3878 108.1837950548124 628 | 226.3881 103.90098898638422 629 | 226.3884 125.2377764346696 630 | 226.3887 121.77896808584804 631 | 226.389 111.94296148706509 632 | 226.3893 121.26326920235407 633 | 226.3896 119.24869595497023 634 | 226.38989999999998 135.4933786190907 635 | 226.39020000000002 132.1612058323745 636 | 226.3905 134.34481810463907 637 | 226.39079999999998 146.92845688908685 638 | 226.3911 134.33128311814605 639 | 226.3914 147.55293914451957 640 | 226.39170000000001 144.9750372876046 641 | 226.392 137.0572316963051 642 | 226.39229999999998 135.30978529407906 643 | 226.39260000000002 135.66608747062804 644 | 226.3929 128.90024843452179 645 | 226.3932 130.20621199117267 646 | 226.3935 131.25857567970985 647 | 226.3938 109.63938089193317 648 | 226.3941 113.70772199587978 649 | 226.3944 117.08344315158303 650 | 226.3947 105.64223211078694 651 | 226.395 102.63345215194572 652 | 226.3953 74.7936796544664 653 | 226.3956 75.7848708955082 654 | 226.39589999999998 82.48970584802586 655 | 226.39620000000002 67.39505343532528 656 | 226.3965 77.99341118219377 657 | 226.39679999999998 74.53053936875148 658 | 226.3971 67.39413273683087 659 | 226.3974 63.300999242755886 660 | 226.39770000000001 52.27637903525589 661 | 226.398 65.41693821892558 662 | 226.39829999999998 51.497809304963695 663 | 226.39860000000002 49.1830810432114 664 | 226.3989 51.48703803190581 665 | 226.3992 61.08426593646978 666 | 226.3995 55.75502995723386 667 | 226.3998 69.67489938430538 668 | 226.4001 58.822342408163465 669 | 226.4004 54.58664009200952 670 | 226.4007 49.009639017229965 671 | 226.401 62.33230105329853 672 | 226.4013 55.4631877152246 673 | 226.4016 57.191861803195515 674 | 226.40189999999998 61.973661891519406 675 | 226.40220000000002 60.53687917366976 676 | 226.4025 50.11319393961801 677 | 226.40279999999998 57.24276295255747 678 | 226.4031 53.46729623016696 679 | 226.4034 47.74670972053723 680 | 226.40370000000001 57.29638757097403 681 | 226.404 49.64881146181428 682 | 226.40429999999998 52.70220422504124 683 | 226.40460000000002 61.45661166907426 684 | 226.4049 53.40798041471414 685 | 226.4052 46.61781514183822 686 | 226.4055 57.069250648746696 687 | 226.4058 51.8547008643118 688 | 226.4061 55.80280283211397 689 | 226.4064 48.57160373081299 690 | 226.4067 55.635551863529656 691 | 226.407 44.182036090016666 692 | 226.4073 57.03114845248924 693 | 226.4076 62.60205603686255 694 | 226.40789999999998 48.73417190521587 695 | 226.40820000000002 42.58968404723833 696 | 226.4085 52.221701562632894 697 | 226.40879999999999 55.6341938169154 698 | 226.4091 56.410572956982165 699 | 226.4094 47.505620572864785 700 | 226.40970000000002 46.1375013517806 701 | 226.41 61.4426354439953 702 | 226.41029999999998 60.19286110978563 703 | 226.41060000000002 52.23044013306079 704 | 226.4109 58.86431242830484 705 | 226.4112 53.96755586960825 706 | 226.4115 40.54665147169616 707 | 226.4118 63.302973419310156 708 | 226.4121 75.9609747889889 709 | 226.4124 69.09280027879937 710 | 226.4127 76.99618159955435 711 | 226.413 80.8160210131769 712 | 226.4133 75.72983813338594 713 | 226.4136 68.0752135274303 714 | 226.41389999999998 86.43951213982197 715 | 226.41420000000002 79.28631499111222 716 | 226.4145 95.69663146141859 717 | 226.41479999999999 93.23302198514537 718 | 226.4151 120.30923890008327 719 | 226.4154 101.951705342836 720 | 226.41570000000002 93.06416111537374 721 | 226.416 112.4997727463325 722 | 226.41629999999998 121.4494797187941 723 | 226.41660000000002 120.54787472391035 724 | 226.4169 110.57640580738729 725 | 226.4172 111.51149693173602 726 | 226.4175 133.81427336514838 727 | 226.4178 131.24661140477488 728 | 226.4181 130.242093824787 729 | 226.4184 143.62262323043342 730 | 226.4187 140.66176571107442 731 | 226.419 139.15884326985872 732 | 226.4193 153.15460134152212 733 | 226.4196 141.61448714195748 734 | 226.41989999999998 143.92153646988228 735 | 226.42020000000002 154.39768583316976 736 | 226.4205 146.09976007188874 737 | 226.42079999999999 148.51226644167593 738 | 226.4211 149.81222754950736 739 | 226.4214 134.04554444965868 740 | 226.42170000000002 153.03051858284897 741 | 226.422 142.78117594053273 742 | 226.42229999999998 130.710894747941 743 | 226.42260000000002 117.12460754146672 744 | 226.4229 124.3729043171195 745 | 226.4232 117.53961942428616 746 | 226.4235 123.42177044543494 747 | 226.4238 124.75043876555014 748 | 226.4241 107.34002830515597 749 | 226.4244 106.44173128182722 750 | 226.4247 117.13932664391746 751 | 226.425 100.34487944658605 752 | 226.4253 105.4107807089033 753 | 226.4256 91.95684910864624 754 | 226.42589999999998 89.8060505368653 755 | 226.42620000000002 96.04511655703413 756 | 226.4265 84.72708993501391 757 | 226.4268 89.50961666818924 758 | 226.4271 88.34665839187426 759 | 226.4274 82.20760778788338 760 | 226.42770000000002 85.24912632408127 761 | 226.428 81.47807226168693 762 | 226.42829999999998 86.25214101586106 763 | 226.42860000000002 72.65627245774118 764 | 226.4289 82.26274206985467 765 | 226.4292 73.43693704022334 766 | 226.4295 65.8493933354186 767 | 226.4298 70.09153494203065 768 | 226.4301 70.42460521852949 769 | 226.4304 74.43394820814952 770 | 226.4307 60.55263401489552 771 | 226.431 73.04086151557816 772 | 226.4313 67.95548697053951 773 | 226.4316 75.44127772639011 774 | 226.43189999999998 66.39286746961126 775 | 226.43220000000002 78.81886561514536 776 | 226.4325 65.15633595759107 777 | 226.4328 64.8544903235065 778 | 226.4331 56.31109465456416 779 | 226.4334 65.05295477851122 780 | 226.43370000000002 65.34428291404738 781 | 226.434 64.35854175268904 782 | 226.43429999999998 63.29109582595158 783 | 226.43460000000002 70.45406109939346 784 | 226.4349 81.14722387997242 785 | 226.4352 78.79471832010005 786 | 226.4355 77.48809503224562 787 | 226.4358 72.39099197285863 788 | 226.4361 62.56499556305702 789 | 226.4364 71.38368384720906 790 | 226.4367 79.48675639302422 791 | 226.437 66.45532507126879 792 | 226.4373 74.6130494894134 793 | 226.4376 62.92700274577396 794 | 226.43789999999998 79.36826439894921 795 | 226.43820000000002 65.22485174899828 796 | 226.4385 69.68227631699479 797 | 226.4388 60.996280170676314 798 | 226.4391 68.07231832890614 799 | 226.4394 62.05936963115563 800 | 226.43970000000002 64.9147108918027 801 | 226.44 66.99991197355557 802 | 226.44029999999998 69.21594388957298 803 | 226.44060000000002 68.4033536275197 804 | 226.4409 67.90222784909813 805 | 226.4412 61.16108115642436 806 | 226.4415 64.74979001168826 807 | 226.4418 64.2905480010427 808 | 226.4421 61.984815935010936 809 | 226.4424 68.09053033769521 810 | 226.4427 76.07382557335401 811 | 226.443 71.96518128218929 812 | 226.4433 88.6483048164533 813 | 226.4436 97.23311764068617 814 | 226.44389999999999 104.35375713977422 815 | 226.44420000000002 116.89883222051047 816 | 226.4445 117.6632911137246 817 | 226.4448 137.10800837533577 818 | 226.4451 152.8585702960251 819 | 226.4454 158.29211101851394 820 | 226.44570000000002 188.815835074331 821 | 226.446 217.51581062722778 822 | 226.44629999999998 217.27461828987265 823 | 226.44660000000002 235.72776317537114 824 | 226.4469 240.0986637061704 825 | 226.4472 272.25404592531265 826 | 226.4475 272.3730184530499 827 | 226.4478 278.1888692179591 828 | 226.4481 275.60438887068074 829 | 226.4484 292.1246071145705 830 | 226.4487 290.41565520101113 831 | 226.449 305.08899901413065 832 | 226.4493 281.11741348506604 833 | 226.4496 296.00377273375284 834 | 226.44989999999999 292.6477821794915 835 | 226.45020000000002 281.33064079907587 836 | 226.4505 269.04127316140296 837 | 226.4508 269.2035808008575 838 | 226.4511 257.89916751101237 839 | 226.4514 245.25640051729937 840 | 226.45170000000002 234.47724544169293 841 | 226.452 225.465256505688 842 | 226.45229999999998 204.98253330619508 843 | 226.45260000000002 182.9258608999401 844 | 226.4529 185.87265036058716 845 | 226.4532 154.6566442768389 846 | 226.4535 142.92286362623958 847 | 226.4538 124.0656263739875 848 | 226.4541 129.8010232712829 849 | 226.4544 111.85205783920435 850 | 226.4547 97.51331587561103 851 | 226.455 93.61573432019365 852 | 226.4553 80.29706834976261 853 | 226.4556 87.67831025613582 854 | 226.45589999999999 97.840900177618 855 | 226.45620000000002 88.69698256020212 856 | 226.4565 83.89264761553531 857 | 226.4568 78.20234021220483 858 | 226.4571 73.42841699644117 859 | 226.4574 81.06835749440276 860 | 226.45770000000002 72.06570685888259 861 | 226.458 74.09569135421395 862 | 226.45829999999998 76.7380327235576 863 | 226.45860000000002 76.45287942481114 864 | 226.4589 79.90411921089814 865 | 226.4592 73.7777439647295 866 | 226.4595 78.32188156346747 867 | 226.4598 79.29659387154943 868 | 226.4601 82.26632394777269 869 | 226.4604 75.61235892841204 870 | 226.4607 76.29617588085188 871 | 226.461 76.27549831523442 872 | 226.4613 74.6373921160373 873 | 226.4616 77.75404368007995 874 | 226.46189999999999 77.68837777296856 875 | 226.46220000000002 76.59295593792358 876 | 226.4625 71.59557370930753 877 | 226.4628 76.46674547441609 878 | 226.4631 60.907405079742105 879 | 226.4634 74.41939152398733 880 | 226.46370000000002 66.49529381670138 881 | 226.464 58.30029305905794 882 | 226.46429999999998 61.54610384467403 883 | 226.46460000000002 72.47541337482214 884 | 226.4649 63.80736778672136 885 | 226.4652 64.3311599710378 886 | 226.4655 72.26815603792558 887 | 226.4658 63.215593095384186 888 | 226.4661 61.340701073582046 889 | 226.4664 59.37417744952129 890 | 226.4667 67.40215352600423 891 | 226.467 63.17970629288186 892 | 226.4673 62.62035065343181 893 | 226.4676 62.03489639314355 894 | 226.4679 70.4642465105573 895 | 226.46820000000002 63.60438499513945 896 | 226.4685 54.24040350582719 897 | 226.4688 61.6949614721274 898 | 226.4691 66.16313293850125 899 | 226.4694 69.8804254070454 900 | 226.46970000000002 60.45943829539861 901 | 226.47 67.06157813989513 902 | 226.47029999999998 64.4744272541082 903 | 226.47060000000002 57.90139918753485 904 | 226.4709 61.06083274008483 905 | 226.4712 54.49463745169448 906 | 226.4715 54.255239707053164 907 | 226.4718 38.437214283792756 908 | 226.4721 59.787391350925 909 | 226.4724 46.85533723436987 910 | 226.4727 61.697393622032 911 | 226.473 61.53043434708868 912 | 226.4733 59.16955877408162 913 | 226.4736 49.787392107268246 914 | 226.4739 46.387251216951356 915 | 226.47420000000002 46.46244342235762 916 | 226.4745 49.74819686841377 917 | 226.4748 54.65661622825561 918 | 226.4751 55.26105314667742 919 | 226.4754 46.8340743815655 920 | 226.47570000000002 56.80426607351504 921 | 226.476 49.911410610297395 922 | 226.47629999999998 52.69565672111953 923 | 226.47660000000002 51.379848030146434 924 | 226.4769 50.98225984328078 925 | 226.4772 50.84657998394459 926 | 226.4775 50.97036926499775 927 | 226.4778 60.71751347019082 928 | 226.4781 56.43343792906167 929 | 226.4784 68.16361429109105 930 | 226.4787 62.70289679383027 931 | 226.479 53.41622020009234 932 | 226.4793 66.28659333138835 933 | 226.4796 63.05827496895029 934 | 226.4799 67.09322947998952 935 | 226.48020000000002 63.25596172640539 936 | 226.4805 65.90964824284586 937 | 226.4808 62.52777805388869 938 | 226.4811 89.9463750500092 939 | 226.4814 100.26370527874718 940 | 226.48170000000002 79.34829788043413 941 | 226.482 99.33197140096641 942 | 226.48229999999998 98.71484794803268 943 | 226.48260000000002 84.2652375832593 944 | 226.4829 99.67918476438801 945 | 226.4832 112.56325437848372 946 | 226.4835 107.09061339245953 947 | 226.4838 113.15337424355509 948 | 226.4841 120.84977477823405 949 | 226.4844 118.63389130493853 950 | 226.4847 131.3724976447193 951 | 226.485 123.04165332445345 952 | 226.4853 136.20543024654842 953 | 226.4856 138.08699823736404 954 | 226.4859 151.13056217723042 955 | 226.48620000000003 149.91201681035864 956 | 226.4865 155.72237612221375 957 | 226.4868 165.62960462467618 958 | 226.4871 162.85897555039122 959 | 226.4874 160.80203058271445 960 | 226.48770000000002 165.8864800181685 961 | 226.488 166.314188458332 962 | 226.48829999999998 173.24876883817956 963 | 226.48860000000002 175.21021712832072 964 | 226.4889 172.94415074304808 965 | 226.4892 183.1620740660983 966 | 226.4895 181.8774058033136 967 | 226.4898 173.63465544589124 968 | 226.4901 181.07963989259963 969 | 226.4904 174.3526862548448 970 | 226.4907 182.6905568302586 971 | 226.491 182.37775603920628 972 | 226.4913 174.3956380955878 973 | 226.4916 181.49215785865465 974 | 226.4919 188.1436927357189 975 | 226.49220000000003 185.6885567802376 976 | 226.4925 178.28030988861937 977 | 226.4928 187.6994801033122 978 | 226.4931 181.98513762724752 979 | 226.4934 184.0275421791187 980 | 226.49370000000002 175.51903856261677 981 | 226.494 191.82750220989084 982 | 226.49429999999998 186.47879981244014 983 | 226.49460000000002 186.1186397509239 984 | 226.4949 172.98151165923807 985 | 226.4952 174.12836579836963 986 | 226.4955 176.2996020434847 987 | 226.49579999999997 164.34560488226322 988 | 226.4961 166.44424433628345 989 | 226.4964 162.3002481868937 990 | 226.4967 168.6991828514279 991 | 226.497 154.16740514416557 992 | 226.4973 150.5729787471432 993 | 226.4976 146.51017610226293 994 | 226.4979 150.13285488855044 995 | 226.49820000000003 139.37128040749374 996 | 226.4985 139.66433897128096 997 | 226.4988 130.3442276442715 998 | 226.4991 125.5763232917815 999 | 226.49939999999998 131.8761514938018 1000 | 226.49970000000002 110.2186597524493 1001 | 226.5 114.42146339214354 1002 | -------------------------------------------------------------------------------- /tests/noise/my_narrow-range_n17.dat: -------------------------------------------------------------------------------- 1 | 226.2 33.484927883113244 2 | 226.2003 49.30998126063173 3 | 226.2006 83.30868032175535 4 | 226.2009 34.6863520124774 5 | 226.2012 69.81951155446367 6 | 226.2015 41.12768404769379 7 | 226.2018 54.222522548668344 8 | 226.2021 87.77450496575716 9 | 226.20239999999998 23.10867735474802 10 | 226.20270000000002 61.15496992857182 11 | 226.203 92.48565222495935 12 | 226.20329999999998 23.204857928302587 13 | 226.2036 57.94540091254015 14 | 226.2039 35.405418709567556 15 | 226.20420000000001 66.99158457011471 16 | 226.2045 67.3826739933614 17 | 226.20479999999998 49.46263317974828 18 | 226.20510000000002 47.674483384735545 19 | 226.2054 51.827289380118984 20 | 226.2057 62.4421145994703 21 | 226.206 36.60194502778827 22 | 226.2063 63.252395911210776 23 | 226.2066 70.17583219192798 24 | 226.2069 97.8581560237907 25 | 226.2072 46.26889214391109 26 | 226.2075 65.16616178966066 27 | 226.2078 38.51987098716869 28 | 226.2081 59.646902501328974 29 | 226.20839999999998 50.12608731418259 30 | 226.20870000000002 37.404770542650084 31 | 226.209 39.836895325282164 32 | 226.20929999999998 48.60334284597267 33 | 226.2096 111.21819563056548 34 | 226.2099 60.84900277958989 35 | 226.21020000000001 63.66720818892837 36 | 226.2105 34.52246518240486 37 | 226.21079999999998 15.780856014622024 38 | 226.21110000000002 47.661129327156864 39 | 226.2114 68.42578829654816 40 | 226.2117 40.64562285711405 41 | 226.212 48.62655134455942 42 | 226.2123 54.84476546206249 43 | 226.2126 46.473488535633265 44 | 226.2129 40.30932722968644 45 | 226.2132 47.73050955427872 46 | 226.2135 41.91124996121658 47 | 226.2138 22.20887403529097 48 | 226.2141 59.68367009154217 49 | 226.21439999999998 90.27492327329014 50 | 226.21470000000002 57.00324394839584 51 | 226.215 34.833903410938184 52 | 226.21529999999998 66.42524724296328 53 | 226.2156 25.786771311683886 54 | 226.2159 43.45651168523074 55 | 226.21620000000001 32.97709309708515 56 | 226.2165 57.33599140251989 57 | 226.21679999999998 35.22668119620261 58 | 226.21710000000002 60.72568359929451 59 | 226.2174 34.71030982251749 60 | 226.2177 35.24806976595869 61 | 226.218 58.40907967456259 62 | 226.2183 50.06936820184464 63 | 226.2186 48.56629021306725 64 | 226.2189 47.24638979790768 65 | 226.2192 61.963986894170766 66 | 226.2195 64.4355607616385 67 | 226.2198 52.51512836431665 68 | 226.2201 51.14042153867389 69 | 226.22039999999998 71.90700590953624 70 | 226.22070000000002 47.504509679036445 71 | 226.221 37.21412539795669 72 | 226.22129999999999 66.71101705355285 73 | 226.2216 30.042269058672993 74 | 226.2219 61.64186208854304 75 | 226.22220000000002 84.89205816374587 76 | 226.2225 40.336778357883176 77 | 226.22279999999998 30.991762067991424 78 | 226.22310000000002 80.51905435305973 79 | 226.2234 36.33027999125785 80 | 226.2237 58.436043122688176 81 | 226.224 50.6127076834439 82 | 226.2243 37.34313503690741 83 | 226.2246 69.56084812642902 84 | 226.2249 18.553441476097102 85 | 226.2252 15.63937125630136 86 | 226.2255 51.82511649783958 87 | 226.2258 30.29674938850693 88 | 226.2261 55.32003508490079 89 | 226.22639999999998 76.48399469802737 90 | 226.22670000000002 74.89184823757466 91 | 226.227 69.80381596159293 92 | 226.22729999999999 55.868633441924665 93 | 226.2276 50.69153263283108 94 | 226.2279 41.60983705665697 95 | 226.22820000000002 59.6071247802676 96 | 226.2285 32.77614942958956 97 | 226.22879999999998 61.03385591879452 98 | 226.22910000000002 37.57553278671695 99 | 226.2294 37.41585549143048 100 | 226.2297 30.376182462347717 101 | 226.23 48.95309745252513 102 | 226.2303 67.40652690123154 103 | 226.2306 35.19858445326467 104 | 226.2309 38.8512403878779 105 | 226.2312 52.26268119328526 106 | 226.2315 34.457997338799366 107 | 226.2318 53.77302468154408 108 | 226.2321 63.524681130527924 109 | 226.23239999999998 75.66431335138375 110 | 226.23270000000002 45.009267790052064 111 | 226.233 53.29262901677724 112 | 226.23329999999999 43.739694245092295 113 | 226.2336 56.05937092538111 114 | 226.2339 57.88685877307627 115 | 226.23420000000002 37.73340190473877 116 | 226.2345 73.14674115384119 117 | 226.23479999999998 63.09541909409366 118 | 226.23510000000002 27.891882904518212 119 | 226.2354 66.7228819459025 120 | 226.2357 36.509523865091154 121 | 226.236 56.59820313352637 122 | 226.2363 54.63127203009216 123 | 226.2366 69.62211839962893 124 | 226.2369 60.721274001651885 125 | 226.2372 33.76837824614965 126 | 226.2375 32.810469511224255 127 | 226.2378 52.288852343517554 128 | 226.2381 44.56853347325383 129 | 226.23839999999998 39.58189877035784 130 | 226.23870000000002 98.08376384422601 131 | 226.239 28.007056209424398 132 | 226.2393 43.08784319292627 133 | 226.2396 80.99098368046096 134 | 226.2399 75.8472472548979 135 | 226.24020000000002 46.50431151714794 136 | 226.2405 89.26560189889858 137 | 226.24079999999998 40.25130875617535 138 | 226.24110000000002 76.52665173842588 139 | 226.2414 118.20505228612141 140 | 226.2417 88.99486505204413 141 | 226.242 136.37955342840823 142 | 226.2423 156.4185122913229 143 | 226.2426 185.2616580900189 144 | 226.2429 230.98225452693237 145 | 226.2432 270.78688825035834 146 | 226.2435 293.72272157296686 147 | 226.2438 308.76959161579344 148 | 226.2441 342.5616326922277 149 | 226.24439999999998 349.6155981550896 150 | 226.24470000000002 362.06898202160147 151 | 226.245 378.18621126245506 152 | 226.2453 424.81660442395963 153 | 226.2456 382.4285212737607 154 | 226.2459 386.08717882827864 155 | 226.24620000000002 398.05832052902394 156 | 226.2465 382.24680785425596 157 | 226.24679999999998 433.8560706479252 158 | 226.24710000000002 408.7902673865789 159 | 226.2474 410.6143594922291 160 | 226.2477 408.3767503917103 161 | 226.248 401.1427914985205 162 | 226.2483 438.03508746340896 163 | 226.2486 436.2467932839601 164 | 226.2489 467.79839796771927 165 | 226.2492 447.24552664946305 166 | 226.2495 479.80447391412105 167 | 226.2498 491.75596535232864 168 | 226.2501 536.5711742955156 169 | 226.25039999999998 565.8303830778902 170 | 226.25070000000002 608.2353069406018 171 | 226.251 634.1201069741833 172 | 226.2513 643.6766812334306 173 | 226.2516 669.969057026985 174 | 226.2519 716.5339875340628 175 | 226.25220000000002 779.1756699792585 176 | 226.2525 753.7565868521577 177 | 226.25279999999998 749.5384395619702 178 | 226.25310000000002 773.0044816822942 179 | 226.2534 762.3618034662439 180 | 226.2537 755.6823648639685 181 | 226.254 769.0083183901313 182 | 226.2543 700.597764924919 183 | 226.2546 685.7093580479628 184 | 226.2549 659.7649761045875 185 | 226.2552 654.078904541085 186 | 226.2555 633.7666264302131 187 | 226.2558 589.7429940355365 188 | 226.2561 542.471203702725 189 | 226.25639999999999 529.3588779529795 190 | 226.25670000000002 480.55615311216997 191 | 226.257 464.7955406402633 192 | 226.2573 437.9855850318791 193 | 226.2576 461.4691069684123 194 | 226.2579 430.2571753149875 195 | 226.25820000000002 437.06799194364 196 | 226.2585 447.7292067699399 197 | 226.25879999999998 414.86039110661466 198 | 226.25910000000002 412.2694860917016 199 | 226.2594 379.70183754431287 200 | 226.2597 362.32646992199864 201 | 226.26 416.49818598672886 202 | 226.2603 426.03396230604625 203 | 226.2606 402.8353367512297 204 | 226.2609 449.97056658228934 205 | 226.2612 387.13222761923 206 | 226.2615 399.46489912603965 207 | 226.2618 372.53261116751264 208 | 226.2621 351.92498476383594 209 | 226.26239999999999 341.664275582322 210 | 226.26270000000002 287.90988348571693 211 | 226.263 263.92127648415146 212 | 226.2633 209.0278154911121 213 | 226.2636 157.3729047718609 214 | 226.2639 163.5552344138952 215 | 226.26420000000002 108.91923468597781 216 | 226.2645 120.12835160131866 217 | 226.26479999999998 86.71777566736392 218 | 226.26510000000002 103.25919727278325 219 | 226.2654 88.04849064177519 220 | 226.2657 72.19112300439598 221 | 226.266 80.12284998928699 222 | 226.2663 91.79195819211189 223 | 226.2666 54.9013871046683 224 | 226.2669 73.53495462284488 225 | 226.2672 112.58598525899791 226 | 226.2675 97.80961842861905 227 | 226.2678 138.7696731808472 228 | 226.2681 123.1812551227649 229 | 226.26839999999999 144.6798502166373 230 | 226.26870000000002 151.29587352885596 231 | 226.269 181.5510344956552 232 | 226.2693 172.36097102301946 233 | 226.2696 197.38482783753057 234 | 226.2699 180.96168512539074 235 | 226.27020000000002 217.69829451651185 236 | 226.2705 264.83322599727825 237 | 226.27079999999998 218.06037650708905 238 | 226.27110000000002 221.1999294520865 239 | 226.2714 235.88780307695103 240 | 226.2717 198.73661557867058 241 | 226.272 190.6619231027522 242 | 226.2723 229.18804169239056 243 | 226.2726 178.7301317055477 244 | 226.2729 195.4424772599684 245 | 226.2732 207.4160077442436 246 | 226.2735 163.6485025345714 247 | 226.2738 185.07031412287458 248 | 226.2741 179.13879269791934 249 | 226.27439999999999 115.60527677836305 250 | 226.27470000000002 137.99464314485868 251 | 226.275 121.66684498627231 252 | 226.2753 149.51737017029706 253 | 226.2756 101.22820179675621 254 | 226.2759 84.16591670996795 255 | 226.27620000000002 79.59773312875357 256 | 226.2765 102.29703831348752 257 | 226.27679999999998 48.49131344141167 258 | 226.27710000000002 86.24049555379543 259 | 226.2774 66.82546848987617 260 | 226.2777 62.88732954262156 261 | 226.278 86.29889315395765 262 | 226.2783 74.11741519414912 263 | 226.2786 56.59935701391778 264 | 226.2789 43.57419523188792 265 | 226.2792 79.88190514950765 266 | 226.2795 98.92177050418583 267 | 226.2798 84.53985371928616 268 | 226.2801 59.70959289845305 269 | 226.2804 62.30729158509709 270 | 226.28070000000002 73.60119961986227 271 | 226.281 19.890183911493203 272 | 226.2813 41.16766847595403 273 | 226.2816 63.028933509336426 274 | 226.2819 52.41534557304988 275 | 226.28220000000002 37.832084031768304 276 | 226.2825 38.95190849542 277 | 226.28279999999998 49.373431300942066 278 | 226.28310000000002 47.09665652425109 279 | 226.2834 49.14779000822959 280 | 226.2837 28.565149362340296 281 | 226.284 33.85542657882546 282 | 226.2843 65.13582884611165 283 | 226.2846 69.66885169991541 284 | 226.2849 33.53544666708989 285 | 226.2852 28.384262761947195 286 | 226.2855 13.633729510557593 287 | 226.2858 -6.390626820352367 288 | 226.2861 14.087552283150867 289 | 226.2864 4.9946438764098 290 | 226.28670000000002 10.813721425765838 291 | 226.287 -18.560824694630014 292 | 226.2873 63.490858654458705 293 | 226.2876 21.017933795168215 294 | 226.2879 25.342528211403664 295 | 226.28820000000002 51.78248337166929 296 | 226.2885 18.47523892356392 297 | 226.28879999999998 18.912730486942888 298 | 226.28910000000002 49.81144515980503 299 | 226.2894 22.913853942977568 300 | 226.2897 28.829176023187813 301 | 226.29 71.06796546313001 302 | 226.2903 35.624428991550815 303 | 226.2906 30.68583567816616 304 | 226.2909 49.39967646907612 305 | 226.2912 35.051534667965825 306 | 226.2915 62.3917287115118 307 | 226.2918 60.140246781488855 308 | 226.2921 38.047641974617164 309 | 226.2924 23.565700934994428 310 | 226.29270000000002 53.52916867648652 311 | 226.293 45.464526684935336 312 | 226.2933 6.66945228219727 313 | 226.2936 50.43751998756224 314 | 226.2939 59.022870069399204 315 | 226.29420000000002 10.695637708812484 316 | 226.2945 62.04972290743734 317 | 226.29479999999998 60.62956315094978 318 | 226.29510000000002 25.31587343807379 319 | 226.2954 42.97028167932788 320 | 226.2957 66.07107423993773 321 | 226.296 44.85170581945691 322 | 226.2963 31.70732350358887 323 | 226.2966 19.45536532809063 324 | 226.2969 67.42116875797309 325 | 226.2972 6.66773147275725 326 | 226.2975 21.10079723516761 327 | 226.2978 51.698640306121014 328 | 226.2981 7.880403655224942 329 | 226.2984 11.84506087041073 330 | 226.29870000000003 0.3831212720155328 331 | 226.299 38.10226142512383 332 | 226.2993 25.78411250523913 333 | 226.2996 26.115506835245757 334 | 226.2999 -8.667571614991129 335 | 226.30020000000002 54.19373966198287 336 | 226.3005 42.38682212880785 337 | 226.30079999999998 26.335453692335346 338 | 226.30110000000002 48.342820732340655 339 | 226.3014 -14.722995310723295 340 | 226.3017 37.62575149787991 341 | 226.302 20.76311054852761 342 | 226.3023 28.915122443316093 343 | 226.3026 60.97727437278584 344 | 226.3029 13.0999991663447 345 | 226.3032 5.319658454652519 346 | 226.3035 44.409005977822126 347 | 226.3038 -25.719039400434863 348 | 226.3041 5.0033357554926745 349 | 226.3044 75.6794059883749 350 | 226.30470000000003 15.235734431420221 351 | 226.305 30.99495764033496 352 | 226.3053 14.496804543854418 353 | 226.3056 15.535678574133495 354 | 226.3059 30.74437750647323 355 | 226.30620000000002 37.39059732775621 356 | 226.3065 33.25453192378014 357 | 226.30679999999998 59.49092804076406 358 | 226.30710000000002 37.2358852844671 359 | 226.3074 32.2118194706927 360 | 226.3077 38.34586033467827 361 | 226.308 71.77550561942819 362 | 226.30829999999997 72.24051895068892 363 | 226.3086 21.737489428205404 364 | 226.3089 38.09518256561241 365 | 226.3092 62.92537723131971 366 | 226.3095 23.158767834151355 367 | 226.3098 20.32511915180897 368 | 226.3101 44.85408468304627 369 | 226.3104 35.78742211919621 370 | 226.31070000000003 54.452234945176386 371 | 226.311 31.069769354428388 372 | 226.3113 34.237675251067515 373 | 226.3116 54.211791121344234 374 | 226.31189999999998 57.53504478088878 375 | 226.31220000000002 46.59189909509801 376 | 226.3125 32.93980353057998 377 | 226.31279999999998 80.79742282412141 378 | 226.31310000000002 54.92707247288271 379 | 226.3134 106.79651961122205 380 | 226.3137 64.75129260943282 381 | 226.314 74.79760356566356 382 | 226.31429999999997 99.69339169394651 383 | 226.3146 44.476182830018004 384 | 226.3149 74.33407218506133 385 | 226.3152 71.80098675639255 386 | 226.3155 110.74755695232501 387 | 226.3158 78.06815342013972 388 | 226.3161 77.29783970905004 389 | 226.3164 110.3503709258316 390 | 226.31670000000003 89.63903549643874 391 | 226.317 84.43256155306281 392 | 226.3173 70.04358129354046 393 | 226.3176 97.62039449448957 394 | 226.31789999999998 104.63064463186004 395 | 226.31820000000002 102.24106644272086 396 | 226.3185 111.18650130331746 397 | 226.31879999999998 104.40237405648784 398 | 226.3191 73.68570410897453 399 | 226.3194 50.84392880605233 400 | 226.3197 72.01437024791377 401 | 226.32 68.44820977761961 402 | 226.32029999999997 58.08595443195285 403 | 226.3206 66.64720163389612 404 | 226.3209 56.44921012467263 405 | 226.3212 75.9473356757535 406 | 226.3215 47.92754682232685 407 | 226.3218 88.94452945414238 408 | 226.3221 58.99367040117004 409 | 226.3224 56.87673657174163 410 | 226.3227 62.12219851082741 411 | 226.323 85.98534793190879 412 | 226.3233 48.307108629102046 413 | 226.3236 70.17994822746309 414 | 226.32389999999998 49.14953113777915 415 | 226.32420000000002 48.007510623441874 416 | 226.3245 29.62213572122206 417 | 226.32479999999998 60.967238578935955 418 | 226.3251 76.47945204650037 419 | 226.3254 34.59407837776968 420 | 226.3257 24.332245867146337 421 | 226.326 61.92359646322814 422 | 226.32629999999997 13.513519755248574 423 | 226.3266 32.16349176864951 424 | 226.3269 36.80513530150989 425 | 226.3272 44.55812190632495 426 | 226.3275 48.8092103760478 427 | 226.3278 50.954352413378146 428 | 226.3281 60.50938628340144 429 | 226.3284 63.901516274577205 430 | 226.3287 70.66906913833313 431 | 226.329 22.807801291217547 432 | 226.3293 47.871216237472346 433 | 226.3296 38.49151639008381 434 | 226.32989999999998 23.924604026251238 435 | 226.33020000000002 48.119819576534695 436 | 226.3305 40.12051882120983 437 | 226.33079999999998 35.12147822351829 438 | 226.3311 48.71892989605321 439 | 226.3314 38.67252998736252 440 | 226.3317 24.309004415364868 441 | 226.332 63.2631114610748 442 | 226.33229999999998 31.7362034167869 443 | 226.3326 27.31174998924733 444 | 226.3329 22.821233175289265 445 | 226.3332 34.016965889313184 446 | 226.3335 79.89131874131455 447 | 226.3338 31.72649918047193 448 | 226.3341 80.59020991219842 449 | 226.3344 70.18017740394961 450 | 226.3347 77.20079141270115 451 | 226.335 90.1274730974663 452 | 226.3353 82.41859150008679 453 | 226.3356 112.07728465465503 454 | 226.33589999999998 125.05630993041274 455 | 226.33620000000002 129.82800901760513 456 | 226.3365 137.97375754908109 457 | 226.33679999999998 146.4619451642601 458 | 226.3371 160.88106252149686 459 | 226.3374 215.5784366288982 460 | 226.3377 151.87414555829127 461 | 226.338 164.93443328849926 462 | 226.33829999999998 201.90611998701561 463 | 226.3386 161.69846980287016 464 | 226.3389 217.36045609244687 465 | 226.3392 206.9663564778119 466 | 226.3395 197.67373080150827 467 | 226.3398 216.67860107614862 468 | 226.3401 180.9966394235076 469 | 226.3404 216.71132926928124 470 | 226.3407 222.26074794294962 471 | 226.341 221.6971306460846 472 | 226.3413 229.1337153120888 473 | 226.3416 196.17526536910432 474 | 226.34189999999998 164.7538190207253 475 | 226.34220000000002 177.7176379153463 476 | 226.3425 156.86280250975926 477 | 226.34279999999998 178.95151255757094 478 | 226.3431 158.29915952793914 479 | 226.3434 198.34672330598735 480 | 226.3437 182.30881353569123 481 | 226.344 145.63191244869242 482 | 226.34429999999998 196.5355637337638 483 | 226.3446 217.36307605638294 484 | 226.3449 229.47067506064528 485 | 226.3452 223.20566482830856 486 | 226.3455 226.70880843456322 487 | 226.3458 236.3974017681003 488 | 226.3461 194.7589743961454 489 | 226.3464 208.73709243339567 490 | 226.3467 194.6987557331136 491 | 226.347 218.46672951498846 492 | 226.3473 220.19434781976622 493 | 226.3476 225.2383600665705 494 | 226.34789999999998 211.0115531308419 495 | 226.34820000000002 214.68641924029848 496 | 226.3485 180.8944746721795 497 | 226.34879999999998 217.85668933993142 498 | 226.3491 171.59932086430686 499 | 226.3494 153.1111897614695 500 | 226.3497 193.6248693778953 501 | 226.35 128.03826463202262 502 | 226.35029999999998 136.43190720057933 503 | 226.35060000000001 128.4792469566485 504 | 226.3509 108.05634589216781 505 | 226.3512 118.83131269326553 506 | 226.3515 107.41131425548802 507 | 226.3518 84.70327221102139 508 | 226.3521 97.01580827600127 509 | 226.3524 87.69748084867186 510 | 226.3527 97.79462906553357 511 | 226.353 49.286893253979244 512 | 226.3533 77.54854779481867 513 | 226.3536 54.460340097255184 514 | 226.35389999999998 7.19280356836552 515 | 226.35420000000002 37.153839512268206 516 | 226.3545 66.48821135666988 517 | 226.35479999999998 54.11347573708152 518 | 226.3551 23.35701605951254 519 | 226.3554 10.081211924338032 520 | 226.3557 39.617053037726905 521 | 226.356 47.332093661869784 522 | 226.35629999999998 11.17185555745052 523 | 226.35660000000001 45.110013099650075 524 | 226.3569 23.30923995694242 525 | 226.3572 26.55953248233058 526 | 226.3575 55.48483814161112 527 | 226.3578 22.950526898589032 528 | 226.3581 51.32410999415302 529 | 226.3584 35.20155876821324 530 | 226.3587 56.1687307654382 531 | 226.359 47.16207769748026 532 | 226.3593 42.687104520331914 533 | 226.3596 69.32536139817674 534 | 226.35989999999998 36.35702259858474 535 | 226.36020000000002 8.49915726123405 536 | 226.3605 25.663691930662157 537 | 226.36079999999998 8.904540243130452 538 | 226.3611 28.11604446534073 539 | 226.3614 41.719162604170364 540 | 226.3617 -4.475188724955807 541 | 226.362 38.174297077964944 542 | 226.36229999999998 53.92980044075721 543 | 226.36260000000001 33.71961832698878 544 | 226.3629 17.048611891225086 545 | 226.3632 31.872780299577236 546 | 226.3635 44.82533271425724 547 | 226.3638 38.9586311943186 548 | 226.3641 11.98930148209827 549 | 226.3644 26.1418226858371 550 | 226.3647 51.28590456598067 551 | 226.365 48.31322143212317 552 | 226.3653 40.49778827584918 553 | 226.3656 38.147809305610195 554 | 226.36589999999998 47.495411701480805 555 | 226.36620000000002 71.86574915229863 556 | 226.3665 37.77947321540094 557 | 226.36679999999998 66.73440265081392 558 | 226.3671 51.831275912765186 559 | 226.3674 26.396961520624078 560 | 226.3677 45.93335979727652 561 | 226.368 49.75110229368222 562 | 226.36829999999998 29.00925941307228 563 | 226.36860000000001 47.321090669884676 564 | 226.3689 57.72700917969778 565 | 226.3692 14.94914473996662 566 | 226.3695 52.19662395094024 567 | 226.3698 24.19653113420919 568 | 226.3701 72.76358004803281 569 | 226.3704 60.22263040929739 570 | 226.3707 37.3312122757833 571 | 226.371 57.72543361654029 572 | 226.3713 55.84838442849536 573 | 226.3716 54.6126417125711 574 | 226.37189999999998 56.653817077611336 575 | 226.37220000000002 76.44038425068321 576 | 226.3725 72.70861910928983 577 | 226.37279999999998 36.55757038098665 578 | 226.3731 47.076221769922064 579 | 226.3734 45.870453156649745 580 | 226.3737 58.08015494906705 581 | 226.374 73.60132468575132 582 | 226.37429999999998 55.10170096286584 583 | 226.37460000000002 50.12425245493028 584 | 226.3749 68.30858822632368 585 | 226.3752 81.40331104307916 586 | 226.3755 34.74871371531973 587 | 226.3758 34.23120204522402 588 | 226.3761 62.124794408150976 589 | 226.3764 52.77745405347158 590 | 226.3767 44.11492451027818 591 | 226.377 25.65945651068359 592 | 226.3773 66.80253061279232 593 | 226.3776 76.65141072722318 594 | 226.37789999999998 50.90245027856765 595 | 226.37820000000002 72.83010536133384 596 | 226.3785 73.75747188903117 597 | 226.37879999999998 59.884095861103766 598 | 226.3791 20.156305903008885 599 | 226.3794 57.447620959765665 600 | 226.3797 65.16306762295201 601 | 226.38 83.89055822026025 602 | 226.38029999999998 76.87721753847138 603 | 226.38060000000002 72.103905167188 604 | 226.3809 85.13172046632837 605 | 226.3812 88.94913348213807 606 | 226.3815 96.06109203193284 607 | 226.3818 84.93690068978238 608 | 226.3821 137.78135817312378 609 | 226.3824 94.97301356040819 610 | 226.3827 131.72916724930784 611 | 226.383 132.84792780249063 612 | 226.3833 126.31331594967868 613 | 226.3836 90.00893484309066 614 | 226.38389999999998 114.65524188351786 615 | 226.38420000000002 128.71955401815393 616 | 226.3845 127.45438245149374 617 | 226.38479999999998 118.42636731080067 618 | 226.3851 112.874689193419 619 | 226.3854 127.44739694584372 620 | 226.3857 113.16161581852192 621 | 226.386 150.53438478684023 622 | 226.38629999999998 134.96315980495973 623 | 226.38660000000002 103.53383526012772 624 | 226.3869 115.37104699972119 625 | 226.3872 83.43021575614354 626 | 226.3875 99.69674057783172 627 | 226.3878 95.40679643497573 628 | 226.3881 123.50387873517748 629 | 226.3884 93.60998738197823 630 | 226.3887 110.573794279505 631 | 226.389 102.0571577881607 632 | 226.3893 142.34433502538337 633 | 226.3896 105.27878869845225 634 | 226.38989999999998 156.5497347452795 635 | 226.39020000000002 115.19403938416511 636 | 226.3905 136.0197674237466 637 | 226.39079999999998 147.7418989383437 638 | 226.3911 127.6235993440554 639 | 226.3914 169.1724642912438 640 | 226.39170000000001 145.5200840967873 641 | 226.392 140.31485910611943 642 | 226.39229999999998 120.33044506034881 643 | 226.39260000000002 137.10546162496928 644 | 226.3929 116.19011310384272 645 | 226.3932 151.42268496752104 646 | 226.3935 118.67601761212586 647 | 226.3938 107.98661208202408 648 | 226.3941 136.9093725344135 649 | 226.3944 97.06052714461856 650 | 226.3947 124.86812164904705 651 | 226.395 76.01644832564334 652 | 226.3953 81.20902956887217 653 | 226.3956 90.36616128060358 654 | 226.39589999999998 65.33209719715381 655 | 226.39620000000002 46.11485201638033 656 | 226.3965 53.46357096432204 657 | 226.39679999999998 54.2379825691379 658 | 226.3971 68.95739201513778 659 | 226.3974 50.90221372895382 660 | 226.39770000000001 62.843964638292164 661 | 226.398 82.49359825464101 662 | 226.39829999999998 92.11457127726746 663 | 226.39860000000002 55.064110098424635 664 | 226.3989 48.36526013524302 665 | 226.3992 77.81656104404878 666 | 226.3995 23.7959357643413 667 | 226.3998 52.87790718890066 668 | 226.4001 41.73791886039855 669 | 226.4004 51.221995769662 670 | 226.4007 38.49415997821521 671 | 226.401 33.37748168932292 672 | 226.4013 48.03070018523003 673 | 226.4016 69.05480444921633 674 | 226.40189999999998 82.21043095569419 675 | 226.40220000000002 46.33425158172693 676 | 226.4025 73.38311119882643 677 | 226.40279999999998 36.68780091477845 678 | 226.4031 63.81647766423092 679 | 226.4034 80.39636597546095 680 | 226.40370000000001 43.23686371759141 681 | 226.404 59.65678722004112 682 | 226.40429999999998 65.38262332253602 683 | 226.40460000000002 39.5326084653832 684 | 226.4049 21.15283168200213 685 | 226.4052 65.22301095551003 686 | 226.4055 70.12433192868178 687 | 226.4058 67.84996591232547 688 | 226.4061 58.73647171291161 689 | 226.4064 34.21413039307879 690 | 226.4067 54.25960397020377 691 | 226.407 78.92230250657133 692 | 226.4073 20.78760473242901 693 | 226.4076 32.873900453549446 694 | 226.40789999999998 23.267006216377705 695 | 226.40820000000002 54.197914572522365 696 | 226.4085 61.911893430794095 697 | 226.40879999999999 47.78883681023119 698 | 226.4091 60.213106651638505 699 | 226.4094 65.38366480055271 700 | 226.40970000000002 61.44137307122293 701 | 226.41 45.85325490977543 702 | 226.41029999999998 56.536298517167175 703 | 226.41060000000002 46.54338654060511 704 | 226.4109 50.319616798060416 705 | 226.4112 14.749419708972098 706 | 226.4115 26.938105069736203 707 | 226.4118 60.71232323053425 708 | 226.4121 87.26914816724329 709 | 226.4124 87.86061010363557 710 | 226.4127 75.58002169230676 711 | 226.413 74.32165756445102 712 | 226.4133 100.1437468718572 713 | 226.4136 47.62374148377882 714 | 226.41389999999998 75.43037916935087 715 | 226.41420000000002 62.12324176691847 716 | 226.4145 85.50956165976473 717 | 226.41479999999999 107.74023678902572 718 | 226.4151 123.5362836959596 719 | 226.4154 106.1359331656401 720 | 226.41570000000002 115.430826847556 721 | 226.416 103.22251481531045 722 | 226.41629999999998 114.59411070069045 723 | 226.41660000000002 123.11352858722444 724 | 226.4169 126.90189780330545 725 | 226.4172 125.9216052012693 726 | 226.4175 129.49516136511684 727 | 226.4178 140.4990287408497 728 | 226.4181 175.50048056083017 729 | 226.4184 119.44572444654648 730 | 226.4187 149.0788925137568 731 | 226.419 139.59905716869525 732 | 226.4193 179.38661831154144 733 | 226.4196 117.72213172202254 734 | 226.41989999999998 159.74936223992043 735 | 226.42020000000002 145.0033576963577 736 | 226.4205 154.34287975976162 737 | 226.42079999999999 155.14475345934645 738 | 226.4211 185.4608400769465 739 | 226.4214 185.75854004483955 740 | 226.42170000000002 131.25492346872494 741 | 226.422 104.55954041353306 742 | 226.42229999999998 139.29186824363583 743 | 226.42260000000002 115.56407802557541 744 | 226.4229 125.06740132986205 745 | 226.4232 109.14967925595751 746 | 226.4235 133.00128000805935 747 | 226.4238 99.3866055103235 748 | 226.4241 107.29124223838984 749 | 226.4244 115.1482510871314 750 | 226.4247 109.30312831528052 751 | 226.425 82.92351048329465 752 | 226.4253 75.15815153990714 753 | 226.4256 117.8313442673288 754 | 226.42589999999998 123.20202201916912 755 | 226.42620000000002 86.31867044641311 756 | 226.4265 89.36954007758557 757 | 226.4268 96.80256110149504 758 | 226.4271 82.8293145155118 759 | 226.4274 79.68896850488431 760 | 226.42770000000002 92.58847587561795 761 | 226.428 87.51044422528054 762 | 226.42829999999998 77.16521089242312 763 | 226.42860000000002 84.61228019875222 764 | 226.4289 79.62376147885928 765 | 226.4292 135.9782354165322 766 | 226.4295 75.56622313126923 767 | 226.4298 83.4122351866886 768 | 226.4301 63.987480281430095 769 | 226.4304 100.41048685706136 770 | 226.4307 101.33974102015192 771 | 226.431 51.889537440667446 772 | 226.4313 95.8721406648723 773 | 226.4316 65.64009956518521 774 | 226.43189999999998 46.41339547278601 775 | 226.43220000000002 71.92943708407836 776 | 226.4325 53.63013769383693 777 | 226.4328 5.328404141701839 778 | 226.4331 54.156222981889464 779 | 226.4334 65.13793434867273 780 | 226.43370000000002 86.08259904556999 781 | 226.434 88.89697430516674 782 | 226.43429999999998 77.47177220247939 783 | 226.43460000000002 70.99633012704726 784 | 226.4349 39.721435361387634 785 | 226.4352 61.15795680450632 786 | 226.4355 53.33933578293653 787 | 226.4358 60.20936848780903 788 | 226.4361 63.40347596408407 789 | 226.4364 67.77889504665382 790 | 226.4367 76.87707620496391 791 | 226.437 70.58730852051309 792 | 226.4373 53.601747070187685 793 | 226.4376 97.40234002975455 794 | 226.43789999999998 65.5359142878084 795 | 226.43820000000002 63.5219107536378 796 | 226.4385 62.97970274213892 797 | 226.4388 60.684082178207184 798 | 226.4391 58.15716295287482 799 | 226.4394 44.33403186377011 800 | 226.43970000000002 81.31953499265549 801 | 226.44 54.58484966016021 802 | 226.44029999999998 63.99084705009118 803 | 226.44060000000002 40.076989426129344 804 | 226.4409 42.49446052933852 805 | 226.4412 73.94856998046822 806 | 226.4415 57.76274118455527 807 | 226.4418 45.892462567279395 808 | 226.4421 58.64358190953605 809 | 226.4424 81.85388612563106 810 | 226.4427 81.9088222096135 811 | 226.443 95.71704461003549 812 | 226.4433 73.56505707918875 813 | 226.4436 94.12491277106211 814 | 226.44389999999999 104.99291372463185 815 | 226.44420000000002 119.80798189270357 816 | 226.4445 116.97006759797029 817 | 226.4448 138.25765307608788 818 | 226.4451 171.3369540112473 819 | 226.4454 174.50372220189908 820 | 226.44570000000002 187.85507469885388 821 | 226.446 215.0729569259424 822 | 226.44629999999998 204.0506634812444 823 | 226.44660000000002 244.28156787854687 824 | 226.4469 245.2349389642158 825 | 226.4472 248.285811528598 826 | 226.4475 235.4067853361 827 | 226.4478 253.4267412003727 828 | 226.4481 293.0761996922394 829 | 226.4484 254.04623563047952 830 | 226.4487 290.2648694170916 831 | 226.449 290.93439183592704 832 | 226.4493 284.7457728645396 833 | 226.4496 279.51644192828763 834 | 226.44989999999999 301.4716760900967 835 | 226.45020000000002 320.03667927079454 836 | 226.4505 303.41509077181934 837 | 226.4508 285.82415784650516 838 | 226.4511 263.88268188571953 839 | 226.4514 267.339587509913 840 | 226.45170000000002 225.542739708612 841 | 226.452 211.62441342058403 842 | 226.45229999999998 236.2811654191997 843 | 226.45260000000002 204.90612954754926 844 | 226.4529 182.56823447825016 845 | 226.4532 183.04224806757782 846 | 226.4535 159.7792128420389 847 | 226.4538 150.21165946143117 848 | 226.4541 144.67035363088743 849 | 226.4544 113.78030391583728 850 | 226.4547 90.24603261700584 851 | 226.455 95.09848897510166 852 | 226.4553 80.37171331843982 853 | 226.4556 74.67549654077825 854 | 226.45589999999999 63.77830141174579 855 | 226.45620000000002 72.34995069530962 856 | 226.4565 77.64502730753112 857 | 226.4568 85.29873248852536 858 | 226.4571 66.63859993807715 859 | 226.4574 75.74692876457749 860 | 226.45770000000002 90.27182625999303 861 | 226.458 73.29789359277675 862 | 226.45829999999998 81.18262652317877 863 | 226.45860000000002 82.12554865526833 864 | 226.4589 82.82688214976191 865 | 226.4592 79.98537339148203 866 | 226.4595 103.79317851507446 867 | 226.4598 41.74338938937779 868 | 226.4601 75.52445588754266 869 | 226.4604 71.69523353578725 870 | 226.4607 71.26131387998939 871 | 226.461 31.790203059015056 872 | 226.4613 86.69279583811237 873 | 226.4616 74.83227285429142 874 | 226.46189999999999 84.3494126259323 875 | 226.46220000000002 73.27580981987 876 | 226.4625 69.27650155769521 877 | 226.4628 60.0880609387389 878 | 226.4631 60.77044855955599 879 | 226.4634 61.780500936803286 880 | 226.46370000000002 77.86405465144182 881 | 226.464 58.83193599468376 882 | 226.46429999999998 96.44914912910463 883 | 226.46460000000002 44.861652294847914 884 | 226.4649 53.13887228641113 885 | 226.4652 56.333408917753154 886 | 226.4655 74.37935546151552 887 | 226.4658 81.21669099034713 888 | 226.4661 82.63059468710273 889 | 226.4664 65.8066602420348 890 | 226.4667 82.59218794792842 891 | 226.467 42.558114315508085 892 | 226.4673 106.3982757942457 893 | 226.4676 77.44365800755007 894 | 226.4679 87.85893464823978 895 | 226.46820000000002 73.15738808553219 896 | 226.4685 69.33082054466894 897 | 226.4688 56.53826796593844 898 | 226.4691 52.3630373106791 899 | 226.4694 115.21653386640061 900 | 226.46970000000002 73.05947690173468 901 | 226.47 51.75886388567 902 | 226.47029999999998 49.69025177066091 903 | 226.47060000000002 54.3482772993337 904 | 226.4709 44.17730958833756 905 | 226.4712 39.96721400511391 906 | 226.4715 25.8516463001966 907 | 226.4718 49.7331441741043 908 | 226.4721 53.37489713361057 909 | 226.4724 82.13861181865548 910 | 226.4727 48.86031295878776 911 | 226.473 47.166495669197936 912 | 226.4733 59.11477333584236 913 | 226.4736 65.57753541347448 914 | 226.4739 60.67818980303745 915 | 226.47420000000002 58.64978015272827 916 | 226.4745 39.239797410308256 917 | 226.4748 49.99279882153556 918 | 226.4751 45.371424275309195 919 | 226.4754 75.09713900327712 920 | 226.47570000000002 43.5927022968146 921 | 226.476 30.672911320718157 922 | 226.47629999999998 78.40928143416618 923 | 226.47660000000002 37.81822167538107 924 | 226.4769 41.277925054115194 925 | 226.4772 81.97469040623704 926 | 226.4775 36.39767901360763 927 | 226.4778 54.57670345604792 928 | 226.4781 69.63037307335779 929 | 226.4784 21.523855124637322 930 | 226.4787 33.84706254885327 931 | 226.479 68.35598608717964 932 | 226.4793 79.38139924745431 933 | 226.4796 54.35792884584413 934 | 226.4799 54.14667365667385 935 | 226.48020000000002 82.9981497633007 936 | 226.4805 56.63246972935366 937 | 226.4808 51.35881854662412 938 | 226.4811 79.99597478362 939 | 226.4814 80.33230532944654 940 | 226.48170000000002 103.63670685516149 941 | 226.482 74.24368602926577 942 | 226.48229999999998 89.48214907699565 943 | 226.48260000000002 84.29241886169157 944 | 226.4829 120.23433522526997 945 | 226.4832 125.05847387808547 946 | 226.4835 109.7129851582782 947 | 226.4838 105.24016787427539 948 | 226.4841 116.05351297729062 949 | 226.4844 141.34043919318194 950 | 226.4847 118.8342298638697 951 | 226.485 101.48872738856116 952 | 226.4853 146.01842416546663 953 | 226.4856 138.59498295885433 954 | 226.4859 169.19166225366388 955 | 226.48620000000003 153.94972248021517 956 | 226.4865 178.23291082930797 957 | 226.4868 161.23710188786072 958 | 226.4871 166.84250218782836 959 | 226.4874 161.48691282736567 960 | 226.48770000000002 210.0255342088238 961 | 226.488 170.24392005187133 962 | 226.48829999999998 177.02638713794465 963 | 226.48860000000002 169.8063989613596 964 | 226.4889 175.85298702157607 965 | 226.4892 173.65281392808794 966 | 226.4895 188.1938226516218 967 | 226.4898 184.15476221499347 968 | 226.4901 179.7498406303106 969 | 226.4904 197.50309805817386 970 | 226.4907 183.12208874983727 971 | 226.491 203.50210757559222 972 | 226.4913 172.88353497749446 973 | 226.4916 190.06810122487337 974 | 226.4919 178.59761615438646 975 | 226.49220000000003 187.77269470286504 976 | 226.4925 139.81129063208036 977 | 226.4928 186.1657214057344 978 | 226.4931 192.17773440077644 979 | 226.4934 172.86460842449551 980 | 226.49370000000002 178.6561443046116 981 | 226.494 162.45410139620992 982 | 226.49429999999998 201.50164650562814 983 | 226.49460000000002 149.21519459975602 984 | 226.4949 175.6772462825073 985 | 226.4952 164.89662223471223 986 | 226.4955 185.60669937229426 987 | 226.49579999999997 180.04944204458835 988 | 226.4961 170.56649202502584 989 | 226.4964 167.20333577365398 990 | 226.4967 161.4301560928917 991 | 226.497 157.79642323701884 992 | 226.4973 139.6264032778673 993 | 226.4976 119.22165604618614 994 | 226.4979 154.2529293315348 995 | 226.49820000000003 157.94825528892676 996 | 226.4985 162.3578136744177 997 | 226.4988 133.01476056819632 998 | 226.4991 138.67011613444726 999 | 226.49939999999998 121.36845531689903 1000 | 226.49970000000002 122.74871411764032 1001 | 226.5 96.63078114500699 1002 | --------------------------------------------------------------------------------