eye-patch 1.0.0__tar.gz → 1.0.0a0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {eye_patch-1.0.0 → eye_patch-1.0.0a0}/PKG-INFO +71 -5
- eye_patch-1.0.0a0/README.md +92 -0
- eye_patch-1.0.0a0/docs/Makefile +20 -0
- eye_patch-1.0.0a0/docs/_static/multi_scale_erode.jpg +0 -0
- eye_patch-1.0.0a0/docs/_static/open_filter.mp4 +0 -0
- eye_patch-1.0.0a0/docs/conf.py +73 -0
- {eye_patch-1.0.0 → eye_patch-1.0.0a0}/docs/index.md +8 -7
- eye_patch-1.0.0a0/docs/masking.md +214 -0
- {eye_patch-1.0.0 → eye_patch-1.0.0a0}/eye_patch/_version.py +2 -2
- {eye_patch-1.0.0 → eye_patch-1.0.0a0}/pyproject.toml +6 -1
- eye_patch-1.0.0a0/uv.lock +2231 -0
- eye_patch-1.0.0/README.md +0 -26
- eye_patch-1.0.0/docs/conf.py +0 -64
- eye_patch-1.0.0/uv.lock +0 -2074
- {eye_patch-1.0.0 → eye_patch-1.0.0a0}/.copier-answers.yml +0 -0
- {eye_patch-1.0.0 → eye_patch-1.0.0a0}/.git_archival.txt +0 -0
- {eye_patch-1.0.0 → eye_patch-1.0.0a0}/.gitattributes +0 -0
- {eye_patch-1.0.0 → eye_patch-1.0.0a0}/.github/CONTRIBUTING.md +0 -0
- {eye_patch-1.0.0 → eye_patch-1.0.0a0}/.github/dependabot.yml +0 -0
- {eye_patch-1.0.0 → eye_patch-1.0.0a0}/.github/release.yml +0 -0
- {eye_patch-1.0.0 → eye_patch-1.0.0a0}/.github/workflows/cd.yml +0 -0
- {eye_patch-1.0.0 → eye_patch-1.0.0a0}/.github/workflows/ci.yml +0 -0
- {eye_patch-1.0.0 → eye_patch-1.0.0a0}/.gitignore +0 -0
- {eye_patch-1.0.0 → eye_patch-1.0.0a0}/.pre-commit-config.yaml +0 -0
- {eye_patch-1.0.0 → eye_patch-1.0.0a0}/.readthedocs.yaml +0 -0
- {eye_patch-1.0.0 → eye_patch-1.0.0a0}/LICENSE +0 -0
- {eye_patch-1.0.0 → eye_patch-1.0.0a0}/eye_patch/__init__.py +0 -0
- {eye_patch-1.0.0 → eye_patch-1.0.0a0}/eye_patch/_version.pyi +0 -0
- {eye_patch-1.0.0 → eye_patch-1.0.0a0}/eye_patch/masking.py +0 -0
- {eye_patch-1.0.0 → eye_patch-1.0.0a0}/eye_patch/naming.py +0 -0
- {eye_patch-1.0.0 → eye_patch-1.0.0a0}/eye_patch/pixel_utils.py +0 -0
- {eye_patch-1.0.0 → eye_patch-1.0.0a0}/eye_patch/py.typed +0 -0
- {eye_patch-1.0.0 → eye_patch-1.0.0a0}/tests/test_masking.py +0 -0
- {eye_patch-1.0.0 → eye_patch-1.0.0a0}/tests/test_package.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: eye-patch
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.0a0
|
|
4
4
|
Summary: The pirate mask.
|
|
5
5
|
Project-URL: Homepage, https://github.com/flint-crew/eye-patch
|
|
6
6
|
Project-URL: Bug Tracker, https://github.com/flint-crew/eye-patch/issues
|
|
@@ -34,10 +34,6 @@ Description-Content-Type: text/markdown
|
|
|
34
34
|
|
|
35
35
|
# Eye Patch
|
|
36
36
|
|
|
37
|
-
The pirate mask!
|
|
38
|
-
|
|
39
|
-
<img width="256" height="256" alt="image" src="https://github.com/user-attachments/assets/2a8e442c-036b-4d78-8370-180c02588c95" />
|
|
40
|
-
|
|
41
37
|
[![Actions Status][actions-badge]][actions-link]
|
|
42
38
|
[![Documentation Status][rtd-badge]][rtd-link]
|
|
43
39
|
[![PyPI version][pypi-version]][pypi-link]
|
|
@@ -58,3 +54,73 @@ The pirate mask!
|
|
|
58
54
|
[coverage-link]: https://codecov.io/github/flint-crew/eye-patch
|
|
59
55
|
|
|
60
56
|
<!-- prettier-ignore-end -->
|
|
57
|
+
|
|
58
|
+
The pirate mask!
|
|
59
|
+
|
|
60
|
+
A python library and CLI tools for creating masks to assist deconvolution of
|
|
61
|
+
interferometric data.
|
|
62
|
+
|
|
63
|
+
This library was originally the masking module of the
|
|
64
|
+
[Flint](https://github.com/flint-crew/flint) pipeline, but has now been
|
|
65
|
+
separated out for flexible use.
|
|
66
|
+
|
|
67
|
+
<img width="256" height="256" alt="image" src="https://github.com/user-attachments/assets/2a8e442c-036b-4d78-8370-180c02588c95" />
|
|
68
|
+
|
|
69
|
+
## Documentation
|
|
70
|
+
|
|
71
|
+
Full documentation is provided on
|
|
72
|
+
[ReadtheDocs](https://eye-patch.readthedocs.io/).
|
|
73
|
+
|
|
74
|
+
## Installation
|
|
75
|
+
|
|
76
|
+
We publish releases on PyPI:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
# PyPI release
|
|
80
|
+
pip install eye-patch
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
You can also install directly from the git repository:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
# Direct git install (latest push)
|
|
87
|
+
pip install git+https://github.com/flint-crew/eye-patch.git
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Or, from a local clone:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
git clone https://github.com/flint-crew/eye-patch.git
|
|
94
|
+
cd flint
|
|
95
|
+
pip install -e .
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
We highly recommend using [uv](https://docs.astral.sh/uv/) for speedy
|
|
99
|
+
installations. Reproducible builds can be created using `uv sync`:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
git clone https://github.com/flint-crew/eye-patch.git
|
|
103
|
+
uv venv
|
|
104
|
+
uv sync
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Contributions
|
|
108
|
+
|
|
109
|
+
Contributions are welcome! Please do submit a pull-request or issue if you spot
|
|
110
|
+
something you would like to address.
|
|
111
|
+
|
|
112
|
+
The full set of dev tooling can be installed via:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
git clone https://github.com/flint-crew/eye-patch.git
|
|
116
|
+
cd eye-patch
|
|
117
|
+
pip install '.[dev]'
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Or, using `uv`:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
git clone https://github.com/flint-crew/eye-patch.git
|
|
124
|
+
cd flint
|
|
125
|
+
uv sync --group dev
|
|
126
|
+
```
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Eye Patch
|
|
2
|
+
|
|
3
|
+
[![Actions Status][actions-badge]][actions-link]
|
|
4
|
+
[![Documentation Status][rtd-badge]][rtd-link]
|
|
5
|
+
[![PyPI version][pypi-version]][pypi-link]
|
|
6
|
+
[![PyPI platforms][pypi-platforms]][pypi-link]
|
|
7
|
+
[![Coverage][coverage-badge]][coverage-link]
|
|
8
|
+
|
|
9
|
+
<!-- SPHINX-START -->
|
|
10
|
+
|
|
11
|
+
<!-- prettier-ignore-start -->
|
|
12
|
+
[actions-badge]: https://github.com/flint-crew/eye-patch/workflows/CI/badge.svg
|
|
13
|
+
[actions-link]: https://github.com/flint-crew/eye-patch/actions
|
|
14
|
+
[pypi-link]: https://pypi.org/project/eye-patch/
|
|
15
|
+
[pypi-platforms]: https://img.shields.io/pypi/pyversions/eye-patch
|
|
16
|
+
[pypi-version]: https://img.shields.io/pypi/v/eye-patch
|
|
17
|
+
[rtd-badge]: https://readthedocs.org/projects/eye-patch/badge/?version=latest
|
|
18
|
+
[rtd-link]: https://eye-patch.readthedocs.io/en/latest/?badge=latest
|
|
19
|
+
[coverage-badge]: https://codecov.io/github/flint-crew/eye-patch/branch/main/graph/badge.svg
|
|
20
|
+
[coverage-link]: https://codecov.io/github/flint-crew/eye-patch
|
|
21
|
+
|
|
22
|
+
<!-- prettier-ignore-end -->
|
|
23
|
+
|
|
24
|
+
The pirate mask!
|
|
25
|
+
|
|
26
|
+
A python library and CLI tools for creating masks to assist deconvolution of
|
|
27
|
+
interferometric data.
|
|
28
|
+
|
|
29
|
+
This library was originally the masking module of the
|
|
30
|
+
[Flint](https://github.com/flint-crew/flint) pipeline, but has now been
|
|
31
|
+
separated out for flexible use.
|
|
32
|
+
|
|
33
|
+
<img width="256" height="256" alt="image" src="https://github.com/user-attachments/assets/2a8e442c-036b-4d78-8370-180c02588c95" />
|
|
34
|
+
|
|
35
|
+
## Documentation
|
|
36
|
+
|
|
37
|
+
Full documentation is provided on
|
|
38
|
+
[ReadtheDocs](https://eye-patch.readthedocs.io/).
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
We publish releases on PyPI:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# PyPI release
|
|
46
|
+
pip install eye-patch
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
You can also install directly from the git repository:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# Direct git install (latest push)
|
|
53
|
+
pip install git+https://github.com/flint-crew/eye-patch.git
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Or, from a local clone:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
git clone https://github.com/flint-crew/eye-patch.git
|
|
60
|
+
cd flint
|
|
61
|
+
pip install -e .
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
We highly recommend using [uv](https://docs.astral.sh/uv/) for speedy
|
|
65
|
+
installations. Reproducible builds can be created using `uv sync`:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
git clone https://github.com/flint-crew/eye-patch.git
|
|
69
|
+
uv venv
|
|
70
|
+
uv sync
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Contributions
|
|
74
|
+
|
|
75
|
+
Contributions are welcome! Please do submit a pull-request or issue if you spot
|
|
76
|
+
something you would like to address.
|
|
77
|
+
|
|
78
|
+
The full set of dev tooling can be installed via:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
git clone https://github.com/flint-crew/eye-patch.git
|
|
82
|
+
cd eye-patch
|
|
83
|
+
pip install '.[dev]'
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Or, using `uv`:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
git clone https://github.com/flint-crew/eye-patch.git
|
|
90
|
+
cd flint
|
|
91
|
+
uv sync --group dev
|
|
92
|
+
```
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Minimal makefile for Sphinx documentation
|
|
2
|
+
#
|
|
3
|
+
|
|
4
|
+
# You can set these variables from the command line, and also
|
|
5
|
+
# from the environment for the first two.
|
|
6
|
+
SPHINXOPTS ?=
|
|
7
|
+
SPHINXBUILD ?= sphinx-build
|
|
8
|
+
SOURCEDIR = .
|
|
9
|
+
BUILDDIR = _build
|
|
10
|
+
|
|
11
|
+
# Put it first so that "make" without argument is like "make help".
|
|
12
|
+
help:
|
|
13
|
+
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
|
14
|
+
|
|
15
|
+
.PHONY: help Makefile
|
|
16
|
+
|
|
17
|
+
# Catch-all target: route all unknown targets to Sphinx using the new
|
|
18
|
+
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
|
19
|
+
%: Makefile
|
|
20
|
+
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Configuration file for the Sphinx documentation builder.
|
|
2
|
+
#
|
|
3
|
+
# For the full list of built-in configuration values, see the documentation:
|
|
4
|
+
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
|
5
|
+
|
|
6
|
+
# -- Project information -----------------------------------------------------
|
|
7
|
+
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import eye_patch
|
|
11
|
+
|
|
12
|
+
project = "eye-patch"
|
|
13
|
+
copyright = "2025, Tim Galvin"
|
|
14
|
+
author = "Tim Galvin"
|
|
15
|
+
version = release = eye_patch.__version__
|
|
16
|
+
|
|
17
|
+
# -- General configuration ---------------------------------------------------
|
|
18
|
+
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
extensions = [
|
|
22
|
+
"myst_parser",
|
|
23
|
+
"sphinx.ext.autodoc",
|
|
24
|
+
"sphinx_autodoc_typehints",
|
|
25
|
+
"sphinx.ext.doctest",
|
|
26
|
+
"sphinx.ext.intersphinx",
|
|
27
|
+
"sphinx.ext.todo",
|
|
28
|
+
"sphinx.ext.coverage",
|
|
29
|
+
"sphinx.ext.mathjax",
|
|
30
|
+
"sphinx.ext.ifconfig",
|
|
31
|
+
"sphinx.ext.viewcode",
|
|
32
|
+
"sphinx.ext.githubpages",
|
|
33
|
+
"sphinx.ext.napoleon",
|
|
34
|
+
"sphinx_copybutton",
|
|
35
|
+
"autoapi.extension",
|
|
36
|
+
"sphinxarg.ext",
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
myst_enable_extensions = [
|
|
40
|
+
"colon_fence",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
autoapi_type = "python"
|
|
44
|
+
autoapi_dirs = ["../eye_patch"]
|
|
45
|
+
autoapi_member_order = "groupwise"
|
|
46
|
+
autoapi_keep_files = False
|
|
47
|
+
autoapi_root = "autoapi"
|
|
48
|
+
autoapi_add_toctree_entry = True
|
|
49
|
+
|
|
50
|
+
# Napoleon settings
|
|
51
|
+
napoleon_google_docstring = True
|
|
52
|
+
napoleon_numpy_docstring = True
|
|
53
|
+
napoleon_include_init_with_doc = True
|
|
54
|
+
napoleon_include_private_with_doc = True
|
|
55
|
+
napoleon_include_special_with_doc = True
|
|
56
|
+
napoleon_use_admonition_for_examples = False
|
|
57
|
+
napoleon_use_admonition_for_notes = False
|
|
58
|
+
napoleon_use_admonition_for_references = False
|
|
59
|
+
napoleon_use_ivar = False
|
|
60
|
+
napoleon_use_param = True
|
|
61
|
+
napoleon_use_rtype = True
|
|
62
|
+
|
|
63
|
+
source_suffix = [".rst", ".md"]
|
|
64
|
+
templates_path = ["_templates"]
|
|
65
|
+
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
# -- Options for HTML output -------------------------------------------------
|
|
69
|
+
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
|
|
70
|
+
|
|
71
|
+
html_theme = "furo"
|
|
72
|
+
# html_theme = "sphinx_rtd_theme"
|
|
73
|
+
html_static_path = ["_static"]
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
```{toctree}
|
|
4
|
-
:maxdepth: 2
|
|
5
|
-
:hidden:
|
|
6
|
-
|
|
7
|
-
```
|
|
1
|
+
# Eye Patch
|
|
8
2
|
|
|
9
3
|
```{include} ../README.md
|
|
10
4
|
:start-after: <!-- SPHINX-START -->
|
|
11
5
|
```
|
|
12
6
|
|
|
7
|
+
## Table of contents
|
|
8
|
+
|
|
9
|
+
```{toctree}
|
|
10
|
+
:maxdepth: 1
|
|
11
|
+
masking.md
|
|
12
|
+
```
|
|
13
|
+
|
|
13
14
|
## Indices and tables
|
|
14
15
|
|
|
15
16
|
- {ref}`genindex`
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# Creating Clean Masks
|
|
2
|
+
|
|
3
|
+
The imaging performance of CLEAN and its derivatives can be improved through the
|
|
4
|
+
construction of reliable clean mask regions. These regions restrict the set of
|
|
5
|
+
pixels that are involved during the peak finding stage of CLEAN. Here the aim of
|
|
6
|
+
the game is to optimally select pixels that contain genuine emission. Issues
|
|
7
|
+
such as clean bias. sub-optimal self-calibration and clean divergence can be
|
|
8
|
+
minimised or outright eliminated provided a clean mask has been reliable
|
|
9
|
+
constructed.
|
|
10
|
+
|
|
11
|
+
`eye-patch` provides functionality to construct such clean masks, where the
|
|
12
|
+
output is a pixel-wise mask of arbitrary shapes that either allow of deny
|
|
13
|
+
cleaning to occur at certain pixel locations. These are intended to be evaluated
|
|
14
|
+
against a restored FITS image. Pixels in the output clean mask are either `0`
|
|
15
|
+
(cleaning is not allowed here) or `1` (cleaning is allowed here).
|
|
16
|
+
|
|
17
|
+
## Available statistics
|
|
18
|
+
|
|
19
|
+
`eye-patch` currently supports two statistics to identify pixels of significance
|
|
20
|
+
that should be cleaned.
|
|
21
|
+
|
|
22
|
+
### Signal-to-noise (SNR)
|
|
23
|
+
|
|
24
|
+
The obvious method is based on signal-to-noise (SNR). After constructing
|
|
25
|
+
background ({math}`\mu`) and noise ({math}`\sigma`) measures across an image a
|
|
26
|
+
direction-dependent SNR ({math}`\mathrm{SNR}`) across the image
|
|
27
|
+
({math}`\mathrm{img}`) can be expressed:
|
|
28
|
+
|
|
29
|
+
{math}`\mathrm{SNR}(x,y) = \frac{\left(\mathrm{img}-\mu\right)}{\sigma}.`
|
|
30
|
+
|
|
31
|
+
In the simplest case constant values may be set across the extent of the image
|
|
32
|
+
{math}`\mu=0`, and {math}`\sigma=\mathrm{SD}(\mathrm{img})`. These can be
|
|
33
|
+
replaced with more sophisticated schemes that compute position dependent metrics
|
|
34
|
+
that also incorporate iterative outlier clipping (e.g.
|
|
35
|
+
[Background and Noise Estimator](https://github.com/PaulHancock/Aegean)) or
|
|
36
|
+
robust statistics (e.g.
|
|
37
|
+
[Selavy](https://www.atnf.csiro.au/computing/software/askapsoft/sdp/docs/current/analysis/selavy.html)).
|
|
38
|
+
|
|
39
|
+
At their heart these SNR based processes are assuming Gaussian distributed
|
|
40
|
+
zero-mean noise, where pixel intensities that are unlikely to occur by chance
|
|
41
|
+
are assumed to be genuine emission. That is to say, pixels that are
|
|
42
|
+
{math}`\gg5\sigma` are likely to be real and should be included in a mask for
|
|
43
|
+
cleaning.
|
|
44
|
+
|
|
45
|
+
### Minimum absolute clip
|
|
46
|
+
|
|
47
|
+
SNR based measures have a clear statistical foundation when identifying bright
|
|
48
|
+
pixels. However, there are situations when such a metric could be perturbed or
|
|
49
|
+
otherwise corrupted, including:
|
|
50
|
+
|
|
51
|
+
- Calibration errors that produce imaging artefacts,
|
|
52
|
+
- Deconvolution errors that accumulate over minor/major iterations,
|
|
53
|
+
- Mishandling of the w-term so that the 2D Fourier transform approximation
|
|
54
|
+
breaks down,
|
|
55
|
+
- Extended diffuse structures that represents a large fraction of the region
|
|
56
|
+
used to calculate the local {math}`\mu` or {math}`\sigma` quantities,
|
|
57
|
+
- Combinations of the above, or
|
|
58
|
+
- Gremlins lurking around in the data.
|
|
59
|
+
|
|
60
|
+
Ultimately, if the regions being considered in the derivation of the noise do
|
|
61
|
+
not appear Gaussian like, the robustness of methods to calculate the local noise
|
|
62
|
+
level are suspect. Additionally, it is unclear whether an accurate noise
|
|
63
|
+
estimation is even an appropriate basis for such regions. For instance,
|
|
64
|
+
artefacts around a bright sources produced by phase error could be
|
|
65
|
+
{math}`\gg\sigma` if the genuine source is sufficiently bright.
|
|
66
|
+
|
|
67
|
+
We introduce the Minimum Absolute Clip ({math}`\mathrm{MAC}`) as an alternative
|
|
68
|
+
metric. By assuming:
|
|
69
|
+
|
|
70
|
+
1. approximately zero-mean distributed Gaussian noise,
|
|
71
|
+
2. the sky brightness is positive definite, and
|
|
72
|
+
3. should there be a significantly bright negative component there will be a
|
|
73
|
+
positive one of comparable brightness nearby.
|
|
74
|
+
|
|
75
|
+
These assumptions are fair for Stokes-I images. A masking function can therefore
|
|
76
|
+
be constructed, where:
|
|
77
|
+
|
|
78
|
+
{math}`\mathrm{MAC}(x, y) = \mathrm{img} > P \times |\mathrm{RollingMinimum}\left(\mathrm{img}, \mathrm{BoxSize}(\mathrm{img}, x, y)\right)|`
|
|
79
|
+
|
|
80
|
+
where {math}`\mathrm{RollingMinimum}` is a minimum boxcar filter of dimensions
|
|
81
|
+
return by {math}`\mathrm{BoxSize}`pixels, which could be turned in a position
|
|
82
|
+
dependent way. The absolute value of the {math}`\mathrm{RollingMinimum}`
|
|
83
|
+
function is increased by a padding factor {math}`P` to increase the minimum
|
|
84
|
+
positive threshold. The {math}`\mathrm{MAC}` is a simply and efficient statistic
|
|
85
|
+
to compute.
|
|
86
|
+
|
|
87
|
+
The choice of an appropriate boxcar size is an important consideration. A larger
|
|
88
|
+
size enforces more conservative behaviour from the {math}`\mathrm{MAC}` process.
|
|
89
|
+
Should too small a region be supplied than typically large multi-scale features
|
|
90
|
+
are less reliably assessed. Extensions can be made to detect when an the rolling
|
|
91
|
+
box filter size is too small (e.g. by an imbalance of positive to negative
|
|
92
|
+
pixels). A basic implementation of this adaptive boxcar size is implemented via
|
|
93
|
+
the `MaskingOptions.flood_fill_use_mbd_adaptive` parameters.
|
|
94
|
+
|
|
95
|
+
<!-- TODO: Need to include some image here -->
|
|
96
|
+
|
|
97
|
+
## Reverse flood filling
|
|
98
|
+
|
|
99
|
+
Cleaning source with features that are both faint and diffuse is difficult. On a
|
|
100
|
+
per-pixel basis it is often a reality that a minimum signal-to-noise threshold
|
|
101
|
+
is not met. Should the cleaning thresholds (set in either absolute
|
|
102
|
+
{math}`\mathrm{Jy}/\mathrm{beam}` units or in terms of {math}`\sigma` units) be
|
|
103
|
+
too high this diffuse emission is never cleaned. In `eye-patch` we include a
|
|
104
|
+
reverse flood fill procedure that grows islands of pixels above an initial
|
|
105
|
+
criteria out to adjacent pixels that met a secondary lower level. This process
|
|
106
|
+
is often the initial step of most source finders.
|
|
107
|
+
|
|
108
|
+
There are two steps to this process:
|
|
109
|
+
|
|
110
|
+
1. _Initial siginficant island detection_: The statistic of choice (see above)
|
|
111
|
+
is executed and all pixels above the threshold are marketed as pixels to
|
|
112
|
+
clean. We can set this via `MaskingOptions.flood_fill_positive_seed_clip`
|
|
113
|
+
2. _Growing the initial set of islands_; Islands that are identified as
|
|
114
|
+
significant go through a dilation process, where the dilation process is
|
|
115
|
+
restricted to limit it only to pixels above the lower level threshold. This
|
|
116
|
+
lower level clip is set via `MaskingOptions.flood_fill_positive_flood_clip`.
|
|
117
|
+
|
|
118
|
+
Activating the flood fill procedure is 'opt in' and activated via
|
|
119
|
+
`MaskingOptions.flood_fill`. Further, the {math}`\mathrm{MAC}` statistic is only
|
|
120
|
+
exposed when the flood fill is enabled.
|
|
121
|
+
|
|
122
|
+
<!-- TODO: Need to include some other image here -->
|
|
123
|
+
|
|
124
|
+
## Eroding output islands
|
|
125
|
+
|
|
126
|
+
Output binary clean masks are naturally at the resolution of the input image (at
|
|
127
|
+
least in `eye-patch`). All pixels that reside in an island are candidate pixels
|
|
128
|
+
where cleaning is allowed to occur. Consider an unresolved source that is
|
|
129
|
+
perfectly aligned to the discrete pixel grid. In principal its clean component
|
|
130
|
+
should be contained entirely to a single pixel. However, as the source is
|
|
131
|
+
sufficiently bright the resulting mask is made up of many pixels (i.e. the shape
|
|
132
|
+
the restoring beam). Should deep cleaning be employed it is possible that small
|
|
133
|
+
perturbations from the noise underlying a source would also be cleaned.
|
|
134
|
+
|
|
135
|
+
A binary erosion process with the erosision structure set to the shape of the
|
|
136
|
+
restoring beam at a particular power level can be used to 'contract' all pixel
|
|
137
|
+
masks. The output should better reflect where clean components ought to be
|
|
138
|
+
placed. See the `MaskingOptions.beam_shape_erode` and
|
|
139
|
+
`MaskingOptions.beam_shape_erode_minimum_response` options to activate and
|
|
140
|
+
control this process. The minimum response should be set between 0 to 1, where
|
|
141
|
+
numbers closer to 0 represent a larger binary erosion structure shape. That is
|
|
142
|
+
to say islands need to be _larger_ for any pixels to remain as
|
|
143
|
+
`MaskingOptions.beam_shape_erode_minimum_response` approaches 0.
|
|
144
|
+
|
|
145
|
+
### Multi-scale beam erosion
|
|
146
|
+
|
|
147
|
+
basic routines to enable per-scale beam shape erosion are provided via
|
|
148
|
+
`MaskingOptions.beam_shape_eroison_scales`. For each specified scale the
|
|
149
|
+
restoring beam (the base shape in this erosion) is convolved with a circular
|
|
150
|
+
gaussian of the specified scale (each scale is FWHM in pixels). The resulting
|
|
151
|
+
beam is then evaluated in the basic process outlined above, eroding the clean
|
|
152
|
+
islands at the native resolution to the clean islands at the specified scale.
|
|
153
|
+
The clean mask at each scale is stored as 'bitmapped' value - except since these
|
|
154
|
+
are floats the `n`'th scale is stored as `2**n` for each pixel.
|
|
155
|
+
|
|
156
|
+
This is intended to provide a mechanism to ensure cleaning at larger scales
|
|
157
|
+
occurs in well defined regions. An example of the erosion process for
|
|
158
|
+
`0 1 2 4 8 16 32 64 128 256 512 1024 2056` is shown below. Point source islands
|
|
159
|
+
are still in the mask, it is just that since they are at the initial scale
|
|
160
|
+
defined, they are stored as `2**0 = 1` values.
|
|
161
|
+
|
|
162
|
+
```{image} _static/multi_scale_erode.jpg
|
|
163
|
+
:alt: Example of multi-scale beam erode
|
|
164
|
+
:width: 100%
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## `--convolve-first` option
|
|
168
|
+
|
|
169
|
+
Historically for extract galactic fields the reverse flood fill process
|
|
170
|
+
described above using a minimum absolute clip as the threshold statistic
|
|
171
|
+
produced reliable clean masks. A subsequent binary erosion process to attempt to
|
|
172
|
+
characterise per-scale clean masks produced meaningful results. For regions like
|
|
173
|
+
the Galactic Plane, however, the reverse flood fill process would often miss
|
|
174
|
+
diffuse emission that was both extended and below the flood fill clip level.
|
|
175
|
+
Reducing this lower level clip would not consistently capture such faint
|
|
176
|
+
extended structures, and pixels boosted by noise would often leak into the clean
|
|
177
|
+
mask from legitimate islands (flying spaghetti monsters).
|
|
178
|
+
|
|
179
|
+
The `--convol-first` option activates a routine where the base image is first
|
|
180
|
+
put through an `open` filter before being convolved to some desired scale.
|
|
181
|
+
Significance thresholding operations are then applied to this filtered image.
|
|
182
|
+
Importantly, the `open` filter attempts to isolate small structures from larger
|
|
183
|
+
ones. This is implemented through the combined usage of a minimum filter
|
|
184
|
+
followed by a maximum filter (could be considered a high-pass filter).
|
|
185
|
+
|
|
186
|
+
```{raw} html
|
|
187
|
+
<video width="100%" controls>
|
|
188
|
+
<source src="_static/open_filter.mp4" type="video/mp4">
|
|
189
|
+
Your browser does not support the video tag.
|
|
190
|
+
</video>
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Should this option be activated be aware that the seed and flood clipping
|
|
194
|
+
threshold change - it should be possible to use lower limits. For example
|
|
195
|
+
`flood_fill_positive_seed_clip=1.02` and `flood_file_positive_flood_clip=0.15`
|
|
196
|
+
when the minimum absolute clip statistic is used.
|
|
197
|
+
|
|
198
|
+
## Accessing via the CLI
|
|
199
|
+
|
|
200
|
+
The masking utility may be accessed via a CLI entrypoint:
|
|
201
|
+
|
|
202
|
+
```{argparse}
|
|
203
|
+
:ref: eye_patch.masking.get_parser
|
|
204
|
+
:prog: eye_patch_masking
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## The `MaskingOptions` class
|
|
208
|
+
|
|
209
|
+
Embedded below is the `eye-patch` `Options` class used to construct clean masks.
|
|
210
|
+
Input values are validated by `pydantic` to ensure they are appropriately typed.
|
|
211
|
+
|
|
212
|
+
```{literalinclude} ../eye_patch/masking.py
|
|
213
|
+
:pyobject: MaskingOptions
|
|
214
|
+
```
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '1.0.
|
|
22
|
-
__version_tuple__ = version_tuple = (1, 0, 0)
|
|
21
|
+
__version__ = version = '1.0.0a0'
|
|
22
|
+
__version_tuple__ = version_tuple = (1, 0, 0, 'a0')
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -61,11 +61,13 @@ dev = [
|
|
|
61
61
|
"ty>=0.0.13",
|
|
62
62
|
]
|
|
63
63
|
docs = [
|
|
64
|
-
"sphinx
|
|
64
|
+
"sphinx<9",
|
|
65
65
|
"myst_parser>=0.13",
|
|
66
66
|
"sphinx_copybutton",
|
|
67
67
|
"sphinx_autodoc_typehints",
|
|
68
68
|
"furo>=2023.08.17",
|
|
69
|
+
"sphinx-autoapi>=3.8.0",
|
|
70
|
+
"sphinx-argparse>=0.5.2",
|
|
69
71
|
]
|
|
70
72
|
|
|
71
73
|
|
|
@@ -164,3 +166,6 @@ ignore = [
|
|
|
164
166
|
|
|
165
167
|
[tool.ruff.lint.per-file-ignores]
|
|
166
168
|
"tests/**" = ["T20"]
|
|
169
|
+
|
|
170
|
+
[tool.codespell]
|
|
171
|
+
skip = ["uv.lock"]
|