fitszoom 0.0.1__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.
- fitszoom-0.0.1/LICENSE +21 -0
- fitszoom-0.0.1/PKG-INFO +9 -0
- fitszoom-0.0.1/README.md +9 -0
- fitszoom-0.0.1/fitszoom/__init__.py +7 -0
- fitszoom-0.0.1/fitszoom/zoom.py +109 -0
- fitszoom-0.0.1/fitszoom.egg-info/PKG-INFO +9 -0
- fitszoom-0.0.1/fitszoom.egg-info/SOURCES.txt +12 -0
- fitszoom-0.0.1/fitszoom.egg-info/dependency_links.txt +1 -0
- fitszoom-0.0.1/fitszoom.egg-info/requires.txt +4 -0
- fitszoom-0.0.1/fitszoom.egg-info/top_level.txt +1 -0
- fitszoom-0.0.1/pyproject.toml +13 -0
- fitszoom-0.0.1/setup.cfg +4 -0
- fitszoom-0.0.1/tests/test_setup.py +13 -0
- fitszoom-0.0.1/tests/test_zoom.py +19 -0
fitszoom-0.0.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) [2026] [Christa DeCoursey, Haille Perkins, Omar Velasco, Toe Oo Wai Yan]
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
fitszoom-0.0.1/PKG-INFO
ADDED
fitszoom-0.0.1/README.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# fitszoom 🌌🔍
|
|
2
|
+
|
|
3
|
+
This package is a Python wrapper for zooming in on your favorite FITS images.
|
|
4
|
+
There are a couple of limitations before you use this package, unfortunately.
|
|
5
|
+
|
|
6
|
+
- Python: 3.10 and above versions
|
|
7
|
+
- FITS image file size: >100 MB
|
|
8
|
+
|
|
9
|
+
With this package, you will be able to obtain a cutout of specified dimensions at a coordinate of your choice!
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
from astropy.io import fits # importing i/o subpackage for reading FITS files
|
|
2
|
+
from astropy.nddata import Cutout2D
|
|
3
|
+
import astropy.units as u # astropy units
|
|
4
|
+
from astropy.wcs import WCS
|
|
5
|
+
|
|
6
|
+
import matplotlib.pyplot as plt
|
|
7
|
+
import numpy as np
|
|
8
|
+
|
|
9
|
+
class FITSZoom(object):
|
|
10
|
+
"""
|
|
11
|
+
Zoom into the given coordinates and create a cutout with the given dimensions
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
def __init__(self, filename, extension=0):
|
|
15
|
+
"""
|
|
16
|
+
Enter your file directory and your file name should be in .fits format in the DATADIR folder defined in __init__.py.
|
|
17
|
+
Args:
|
|
18
|
+
filename (string): your file name -> "{DATADIR}/<<your image>>.fits"
|
|
19
|
+
"""
|
|
20
|
+
self.filename = filename
|
|
21
|
+
self.fits = fits.open(filename) # open the fits file --> this returns as a list of Header and Data units
|
|
22
|
+
self.setup(extension=extension) # pull out the data we need so that they are ready to use right after construction
|
|
23
|
+
|
|
24
|
+
def setup(self, extension=0):
|
|
25
|
+
"""
|
|
26
|
+
Extract the necessary attributes from the fits header
|
|
27
|
+
Print out the recommended image bounds and sky coordinates
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
extension (int): the index where the desired data is within the fits
|
|
31
|
+
alternative_names (dict): dictionary mapping the names of appropriate values
|
|
32
|
+
"""
|
|
33
|
+
self.header = self.fits[extension].header
|
|
34
|
+
self.data = self.fits[extension].data
|
|
35
|
+
self.wcs = WCS(self.header)
|
|
36
|
+
### TO DO ##
|
|
37
|
+
sky1 = self.wcs.pixel_to_world(0,0)
|
|
38
|
+
sky2 = self.wcs.pixel_to_world(-1,-1)
|
|
39
|
+
print("---------- Recommendations ------------")
|
|
40
|
+
print("---------- Use the ra and dec within the following range ------------")
|
|
41
|
+
print(f"ra between {sky1.ra.value:.6f} and {sky2.ra.value:.6f}.")
|
|
42
|
+
print(f"dec between {sky1.dec.value:.6f} and {sky2.dec.value:.6f}.")
|
|
43
|
+
return
|
|
44
|
+
|
|
45
|
+
def zoom(self, coordinates, cutout_dimensions, save=False):
|
|
46
|
+
"""
|
|
47
|
+
Zoom into the given coordinates and create a cutout with the given dimensions
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
coordinates (tuple): ra, dec in decimal degrees
|
|
51
|
+
cutout_dimensions (tuple): dimensions
|
|
52
|
+
|
|
53
|
+
Return:
|
|
54
|
+
axes: plt.plot of the cutout image
|
|
55
|
+
cutout:
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
if cutout_dimensions[0].unit != u.arcsec or cutout_dimensions[1].unit != u.arcsec:
|
|
59
|
+
raise ValueError("please use arcseconds for the dimensions")
|
|
60
|
+
|
|
61
|
+
cutout = Cutout2D(self.data, coordinates, cutout_dimensions, wcs=self.wcs)
|
|
62
|
+
|
|
63
|
+
ax = self.plot(data=cutout.data, save=save)
|
|
64
|
+
|
|
65
|
+
return ax, cutout
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def plot(self, data=None, save=False, **kwargs):
|
|
69
|
+
"""
|
|
70
|
+
Use matplotlib imshow to display the cutout
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
data : data from FITS image
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
axes: the plt axes with the image
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
if data is None:
|
|
80
|
+
data = self.data
|
|
81
|
+
|
|
82
|
+
# set some defaults
|
|
83
|
+
if not kwargs.get('vmin', False):
|
|
84
|
+
kwargs['vmin'] = np.percentile(self.data, 1)
|
|
85
|
+
|
|
86
|
+
if not kwargs.get('vmax', False):
|
|
87
|
+
kwargs['vmax'] = np.percentile(self.data, 99)
|
|
88
|
+
|
|
89
|
+
fig, ax = plt.subplots(1,1, subplot_kw=dict(projection=self.wcs))
|
|
90
|
+
|
|
91
|
+
ax.imshow(data, **kwargs, origin='lower')
|
|
92
|
+
ax.grid(color='white', ls='solid')
|
|
93
|
+
|
|
94
|
+
return plt.gca()
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def save(self, cutout, output_filename):
|
|
98
|
+
"""
|
|
99
|
+
Save a cutout to a new FITS file, without changing the cutout's WCS in the header.
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
new_header = cutout.wcs.to_header()
|
|
103
|
+
|
|
104
|
+
# Wrap the cropped pixel data and the new header into a primary HDU
|
|
105
|
+
hdu = fits.PrimaryHDU(data=cutout.data, header=new_header)
|
|
106
|
+
# Write it out to disk, overwriting any existing file at that path
|
|
107
|
+
hdu.writeto(output_filename, overwrite=True)
|
|
108
|
+
|
|
109
|
+
return output_filename
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
fitszoom/__init__.py
|
|
5
|
+
fitszoom/zoom.py
|
|
6
|
+
fitszoom.egg-info/PKG-INFO
|
|
7
|
+
fitszoom.egg-info/SOURCES.txt
|
|
8
|
+
fitszoom.egg-info/dependency_links.txt
|
|
9
|
+
fitszoom.egg-info/requires.txt
|
|
10
|
+
fitszoom.egg-info/top_level.txt
|
|
11
|
+
tests/test_setup.py
|
|
12
|
+
tests/test_zoom.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
fitszoom
|
fitszoom-0.0.1/setup.cfg
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
def test_setup():
|
|
2
|
+
"""
|
|
3
|
+
Test that the fits image data array shape exceeds 0 for both x and y dimensions
|
|
4
|
+
Test that accessing non-default extensions works
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from fitszoom.zoom import FITSZoom
|
|
8
|
+
|
|
9
|
+
im_with_ext1 = '../fitszoom/images/tr4_F200W_epoch2_cutout.fits'
|
|
10
|
+
|
|
11
|
+
fitszoom_object = FITSZoom(filename=im_with_ext1, extension=1)
|
|
12
|
+
assert fitszoom_object.data.shape[0] > 0, 'array with 0 length!'
|
|
13
|
+
assert fitszoom_object.data.shape[1] > 0, 'array with 0 length!'
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
def test_zoom():
|
|
2
|
+
"""
|
|
3
|
+
Tests that the zoom function cuts out the image at the correct location and with the correct dimensions
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from fitszoom.zoom import FITSZoom
|
|
7
|
+
import astropy.io.fits as fits
|
|
8
|
+
import astropy.units as u
|
|
9
|
+
|
|
10
|
+
test_image = fits.open('../fitszoom/images/whirlpool_vla.fits')
|
|
11
|
+
fz_object = FITSZoom('/Users/christadecoursey/Documents/CodeAstro/fitszoom/fitszoom/images/whirlpool_vla.fits')
|
|
12
|
+
|
|
13
|
+
ra = 202.469575
|
|
14
|
+
dec = 47.195258
|
|
15
|
+
dimensions = (300*u.arcsec, 300*u.arcsec)
|
|
16
|
+
# Zoom in on the galaxy center (RA, Dec in degrees) with a 300x300 pixel cutout
|
|
17
|
+
_, cutout = fz_object.zoom(coordinates=(ra, dec), cutout_dimensions=dimensions)
|
|
18
|
+
|
|
19
|
+
test_zoom()
|