spalipy


Namespalipy JSON
Version 3.5.3 PyPI version JSON
download
home_pagehttps://github.com/Lyalpha/spalipy
SummaryDetection-based astrononmical image registration
upload_time2024-01-24 16:13:32
maintainer
docs_urlNone
authorJoe Lyman
requires_python
license
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # spalipy

Detection-based astronomical image registration.

Initially built from the algorithm of
[alipy2.0](https://obswww.unige.ch/~tewes/alipy/), `spalipy` includes an
optional additional warping of the affine transformation via splines to
achieve accurate registration in the case of non-homogeneous coordinate
transforms. This is particularly useful in the case of optically distorted
or wide field-of-view images.

## Install

#### From PyPI
```
pip install spalipy
```

#### From source
```
git clone https://github.com/Lyalpha/spalipy
cd spalipy
pip install .
```

## Quick run

If you have (geometrically) well-behaved images with a significant
overlap, then good results can usually be obtained with a call such
as:
```
align-fits-simple source.fits source_aligned.fits template.fits
```
Where `source.fits` is the image to be aligned to the supplied `template.fits`,
and `source_aligned.fits` is where the result should be written.

To take advantage of all the dials and sliders to tweak the alignment,
take a look at the entire parameter descriptions via:
```
align-fits -h
```

Alternatively, one can pass lower level objects to perform an alignment
interactively or within an external script, see running `spalipy`
[interactively](#interactively).

## Description

A `source` image is transformed to the pixel-coordinate system of a
`template` image using their respective detections as tie-points.

Matching [quads](https://arxiv.org/abs/0910.2233) of detections between
the two catalogues are used to match corresponding detections in the two
images. An initial affine transformation is calculated from a quad match,
and is applied to `source` image detections. Following this, cross-matching
is performed within some tolerance to find corresponding detections across
the image. The remaining residuals between the matched detection coordinates
are used to construct 2D spline surfaces that represent the spatially-varying
residuals in `x` and `y` axes. These surfaces are used to calculate the
correction needed to properly register the images even in the face of
non-homogeneous coordinate transformation between the images. Flux
conservation is relatively robust so long as the pixel scale between `source`
and `template` is the same. Proper investigation with different pixel scales
has not been performed.

*__Note:__ the affine transformation uses `scipy.interpolation.affine_transform`
which doesn't handle nans properly, therefore replace all nan values
in the `source` image prior to running `spalipy`.*


## Examples

`spalipy` can be run in two modes - via the command-line scripts or
interactively. The second big choice is to either provide your own detection
catalogues or let `spalipy` perform its own detection. Each of these scenarios
is shown below.

### via the command-line

##### Using the internal detection routine

When using the internal detection routines, there are two command-line
scripts: `align-fits` and `align-fits-simple`. For narrow field-of-view
images without significant distortions, `align-fits-simple` is probabably
entirely sufficient to get a good alignment. (`align-fits-simple` has
a significantly reduced parameter list and sets some automatically,
for example it will always switch off spline fitting and does not
allow the user to pass existing detection catalogues.)

```
align-fits-simple source.fits source_aligned.fits template.fits
```
or
```
align-fits source.fits source_aligned.fits -tf template.fits
```
Take notice of the `-tf` argument in the second example, this is because
`align-fits` offers multiple ways to provide detections, as shown in the next
section.

##### Passing existing SExtractor detection catalogues

If one already has detection catalogues from a SExtractor run, then these can
be used to save repetition.

e.g. create two `SExtractor` catalogues for the image:
```
sex -c /path/to/my/sex.config source.fits -CATALOG_NAME source.cat
sex -c /path/to/my/sex.config template.fits -CATALOG_NAME template.cat
```
*__Note:__ At a minimum, the `SExtractor` catalogues __must__ contain the
columns `X_IMAGE, Y_IMAGE, FLUX, FWHM_IMAGE, FLAGS`.*

We must use `align-fits` here since `align-fits-simple` does not allow us to
pass catalogues:

```
align-fits source.fits source_aligned.fits -sc source.cat -tc template.cat
```

### Interactively

##### Using the internal detection routine

```python
from astropy.io import fits
from spalipy import Spalipy

source_data = fits.getdata("source.fits")
template_data = fits.getdata("template.fits")

sp = Spalipy(source_data, template_data=template_data)
sp.align()
fits.writeto("source_aligned.fits", data=sp.aligned_data)
```

##### Passing existing detection tables

Analagously to [passing `SExtractor` catalogues](#passing-existing-sextractor-detection-catalogues),
one can pass existing `astropy.Table` objects when calling `spalipy` interactively, for examples
as the output of a prior `sep.extract()` call.

*__Note:__ At a minimum, the detection tables __must__ contain the
columns `x, y, flux, fwhm, flag`.*

```python
import sep
from astropy.io import fits
from astropy.table import Table
from spalipy import Spalipy

source_data = fits.getdata("source.fits")
template_data = fits.getdata("template.fits")
# Run sep on each set of data
# ...
# source_extracted = sep.extract(...)
# template_extracted = sep.extract(...)
source_det = Table(source_extracted)
template_det = Table(template_extracted)

sp = Spalipy(source_data, source_det=source_det, template_det=template_det)
sp.align()
fits.writeto("source_aligned.fits", data=sp.aligned_data)
```

### Logging

When running interactively, all information is output in logging. To see these
one can do
```python
import logging
logging.getLogger().setLevel(logging.INFO)  # or logging.DEBUG for more messages
```
prior to any of the [interactive example calls](#interactively).

Statistics for the transformation goodness can also be accessed via:
```python
sp.log_transform_stats()
```

### Parameter tuning

Several parameters should have the main focus of attention if an acceptable
alignment is not being found.

* If you have a small number of detections in your image overlap then
`min_n_match` will need to be lowered from its default of `100`, but it is
also worth raising `n_det` so that the alignment uses all of your sources.
See `n_det` docstring on its float vs int format, but it is safe/easy to just
set to some overly large value such that it won't limit your detection tables,
e.g. `n_det=10000`.
* `sub_tile` at a default of `2` will effectively fit an affine transformation
in each quart of the image. On extremely distorted images even this may not be
enough and so it can be raised to `3` (or even `4`). It is a balancing act
that there must still be sufficient detections in each image in each sub tile
region from which to make a fit. If you have a low number of detections,
or detections are spread strongly unevenly, this should be set to `1`.
* `spline_order` should generally only be lowered from its default of `3`.
Setting it to zero might actually be preferable for simple alignment tasks.
Also, with a low number of detections, and particularly with regions of low
number of detections, the splines may misbehave.
* `max_match_dist` is the tolerance in pixels when considering a `source`
and `template` detection as matched after the affine transform. One may
increase this in the case of poorly centred detections. Note that this
has an indirect impact on `min_sep` (set to `2 * max_match_dist` by
default) - when raising `max_match_dist` then `min_sep` correspondingly
increases, offering some guard against ambguous cross-matching in crowded
regions. However, raising it too high may mean that too few detections
pass the `min_sep` criterion. In crowded fields and with well-behaved
detection centres, reducing `max_match_dist` may be advisable.

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/Lyalpha/spalipy",
    "name": "spalipy",
    "maintainer": "",
    "docs_url": null,
    "requires_python": "",
    "maintainer_email": "",
    "keywords": "",
    "author": "Joe Lyman",
    "author_email": "joedlyman@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/a9/d1/74416e10efa62c2ea541ab950d6be57aefc455a95c8f3c3cf499065fa8e1/spalipy-3.5.3.tar.gz",
    "platform": null,
    "description": "# spalipy\n\nDetection-based astronomical image registration.\n\nInitially built from the algorithm of\n[alipy2.0](https://obswww.unige.ch/~tewes/alipy/), `spalipy` includes an\noptional additional warping of the affine transformation via splines to\nachieve accurate registration in the case of non-homogeneous coordinate\ntransforms. This is particularly useful in the case of optically distorted\nor wide field-of-view images.\n\n## Install\n\n#### From PyPI\n```\npip install spalipy\n```\n\n#### From source\n```\ngit clone https://github.com/Lyalpha/spalipy\ncd spalipy\npip install .\n```\n\n## Quick run\n\nIf you have (geometrically) well-behaved images with a significant\noverlap, then good results can usually be obtained with a call such\nas:\n```\nalign-fits-simple source.fits source_aligned.fits template.fits\n```\nWhere `source.fits` is the image to be aligned to the supplied `template.fits`,\nand `source_aligned.fits` is where the result should be written.\n\nTo take advantage of all the dials and sliders to tweak the alignment,\ntake a look at the entire parameter descriptions via:\n```\nalign-fits -h\n```\n\nAlternatively, one can pass lower level objects to perform an alignment\ninteractively or within an external script, see running `spalipy`\n[interactively](#interactively).\n\n## Description\n\nA `source` image is transformed to the pixel-coordinate system of a\n`template` image using their respective detections as tie-points.\n\nMatching [quads](https://arxiv.org/abs/0910.2233) of detections between\nthe two catalogues are used to match corresponding detections in the two\nimages. An initial affine transformation is calculated from a quad match,\nand is applied to `source` image detections. Following this, cross-matching\nis performed within some tolerance to find corresponding detections across\nthe image. The remaining residuals between the matched detection coordinates\nare used to construct 2D spline surfaces that represent the spatially-varying\nresiduals in `x` and `y` axes. These surfaces are used to calculate the\ncorrection needed to properly register the images even in the face of\nnon-homogeneous coordinate transformation between the images. Flux\nconservation is relatively robust so long as the pixel scale between `source`\nand `template` is the same. Proper investigation with different pixel scales\nhas not been performed.\n\n*__Note:__ the affine transformation uses `scipy.interpolation.affine_transform`\nwhich doesn't handle nans properly, therefore replace all nan values\nin the `source` image prior to running `spalipy`.*\n\n\n## Examples\n\n`spalipy` can be run in two modes - via the command-line scripts or\ninteractively. The second big choice is to either provide your own detection\ncatalogues or let `spalipy` perform its own detection. Each of these scenarios\nis shown below.\n\n### via the command-line\n\n##### Using the internal detection routine\n\nWhen using the internal detection routines, there are two command-line\nscripts: `align-fits` and `align-fits-simple`. For narrow field-of-view\nimages without significant distortions, `align-fits-simple` is probabably\nentirely sufficient to get a good alignment. (`align-fits-simple` has\na significantly reduced parameter list and sets some automatically,\nfor example it will always switch off spline fitting and does not\nallow the user to pass existing detection catalogues.)\n\n```\nalign-fits-simple source.fits source_aligned.fits template.fits\n```\nor\n```\nalign-fits source.fits source_aligned.fits -tf template.fits\n```\nTake notice of the `-tf` argument in the second example, this is because\n`align-fits` offers multiple ways to provide detections, as shown in the next\nsection.\n\n##### Passing existing SExtractor detection catalogues\n\nIf one already has detection catalogues from a SExtractor run, then these can\nbe used to save repetition.\n\ne.g. create two `SExtractor` catalogues for the image:\n```\nsex -c /path/to/my/sex.config source.fits -CATALOG_NAME source.cat\nsex -c /path/to/my/sex.config template.fits -CATALOG_NAME template.cat\n```\n*__Note:__ At a minimum, the `SExtractor` catalogues __must__ contain the\ncolumns `X_IMAGE, Y_IMAGE, FLUX, FWHM_IMAGE, FLAGS`.*\n\nWe must use `align-fits` here since `align-fits-simple` does not allow us to\npass catalogues:\n\n```\nalign-fits source.fits source_aligned.fits -sc source.cat -tc template.cat\n```\n\n### Interactively\n\n##### Using the internal detection routine\n\n```python\nfrom astropy.io import fits\nfrom spalipy import Spalipy\n\nsource_data = fits.getdata(\"source.fits\")\ntemplate_data = fits.getdata(\"template.fits\")\n\nsp = Spalipy(source_data, template_data=template_data)\nsp.align()\nfits.writeto(\"source_aligned.fits\", data=sp.aligned_data)\n```\n\n##### Passing existing detection tables\n\nAnalagously to [passing `SExtractor` catalogues](#passing-existing-sextractor-detection-catalogues),\none can pass existing `astropy.Table` objects when calling `spalipy` interactively, for examples\nas the output of a prior `sep.extract()` call.\n\n*__Note:__ At a minimum, the detection tables __must__ contain the\ncolumns `x, y, flux, fwhm, flag`.*\n\n```python\nimport sep\nfrom astropy.io import fits\nfrom astropy.table import Table\nfrom spalipy import Spalipy\n\nsource_data = fits.getdata(\"source.fits\")\ntemplate_data = fits.getdata(\"template.fits\")\n# Run sep on each set of data\n# ...\n# source_extracted = sep.extract(...)\n# template_extracted = sep.extract(...)\nsource_det = Table(source_extracted)\ntemplate_det = Table(template_extracted)\n\nsp = Spalipy(source_data, source_det=source_det, template_det=template_det)\nsp.align()\nfits.writeto(\"source_aligned.fits\", data=sp.aligned_data)\n```\n\n### Logging\n\nWhen running interactively, all information is output in logging. To see these\none can do\n```python\nimport logging\nlogging.getLogger().setLevel(logging.INFO)  # or logging.DEBUG for more messages\n```\nprior to any of the [interactive example calls](#interactively).\n\nStatistics for the transformation goodness can also be accessed via:\n```python\nsp.log_transform_stats()\n```\n\n### Parameter tuning\n\nSeveral parameters should have the main focus of attention if an acceptable\nalignment is not being found.\n\n* If you have a small number of detections in your image overlap then\n`min_n_match` will need to be lowered from its default of `100`, but it is\nalso worth raising `n_det` so that the alignment uses all of your sources.\nSee `n_det` docstring on its float vs int format, but it is safe/easy to just\nset to some overly large value such that it won't limit your detection tables,\ne.g. `n_det=10000`.\n* `sub_tile` at a default of `2` will effectively fit an affine transformation\nin each quart of the image. On extremely distorted images even this may not be\nenough and so it can be raised to `3` (or even `4`). It is a balancing act\nthat there must still be sufficient detections in each image in each sub tile\nregion from which to make a fit. If you have a low number of detections,\nor detections are spread strongly unevenly, this should be set to `1`.\n* `spline_order` should generally only be lowered from its default of `3`.\nSetting it to zero might actually be preferable for simple alignment tasks.\nAlso, with a low number of detections, and particularly with regions of low\nnumber of detections, the splines may misbehave.\n* `max_match_dist` is the tolerance in pixels when considering a `source`\nand `template` detection as matched after the affine transform. One may\nincrease this in the case of poorly centred detections. Note that this\nhas an indirect impact on `min_sep` (set to `2 * max_match_dist` by\ndefault) - when raising `max_match_dist` then `min_sep` correspondingly\nincreases, offering some guard against ambguous cross-matching in crowded\nregions. However, raising it too high may mean that too few detections\npass the `min_sep` criterion. In crowded fields and with well-behaved\ndetection centres, reducing `max_match_dist` may be advisable.\n",
    "bugtrack_url": null,
    "license": "",
    "summary": "Detection-based astrononmical image registration",
    "version": "3.5.3",
    "project_urls": {
        "Homepage": "https://github.com/Lyalpha/spalipy"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "868ed45c4936eec1b5081025ae30d97e8db8f212686a4371e2690649a0b74c0c",
                "md5": "613c49cb6fb1026ac24e8933bc35e18f",
                "sha256": "1963f5d61842c9cebc4ef7fa974637f159aab8cba408c0d89a9e4b127ebba8d0"
            },
            "downloads": -1,
            "filename": "spalipy-3.5.3-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "613c49cb6fb1026ac24e8933bc35e18f",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 36812,
            "upload_time": "2024-01-24T16:13:30",
            "upload_time_iso_8601": "2024-01-24T16:13:30.941424Z",
            "url": "https://files.pythonhosted.org/packages/86/8e/d45c4936eec1b5081025ae30d97e8db8f212686a4371e2690649a0b74c0c/spalipy-3.5.3-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "a9d174416e10efa62c2ea541ab950d6be57aefc455a95c8f3c3cf499065fa8e1",
                "md5": "8baa9de05eacf17d9bf11401b2fd14d7",
                "sha256": "06bcc9648bea792b773efc5cbe8680f24644244f50e88fc7373595ae9b9bab7f"
            },
            "downloads": -1,
            "filename": "spalipy-3.5.3.tar.gz",
            "has_sig": false,
            "md5_digest": "8baa9de05eacf17d9bf11401b2fd14d7",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 38596,
            "upload_time": "2024-01-24T16:13:32",
            "upload_time_iso_8601": "2024-01-24T16:13:32.087368Z",
            "url": "https://files.pythonhosted.org/packages/a9/d1/74416e10efa62c2ea541ab950d6be57aefc455a95c8f3c3cf499065fa8e1/spalipy-3.5.3.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-01-24 16:13:32",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "Lyalpha",
    "github_project": "spalipy",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [],
    "lcname": "spalipy"
}
        
Elapsed time: 0.17683s