7
7
_DEG2RAD = math .pi / 180.0
8
8
9
9
10
- def calc_pixmap (wcs_from , wcs_to , shape = None ):
10
+ def calc_pixmap (wcs_from , wcs_to , shape = None , disable_bbox = "to" ):
11
11
"""
12
12
Calculate a discretized on a grid mapping between the pixels of two images
13
13
using provided WCS of the original ("from") image and the destination ("to")
@@ -35,6 +35,14 @@ def calc_pixmap(wcs_from, wcs_to, shape=None):
35
35
``numpy.ndarray`` order. When provided, it takes precedence over the
36
36
``wcs_from.array_shape`` property.
37
37
38
+ disable_bbox : {"to", "from", "both", "none"}, optional
39
+ Indicates whether to use or not to use the bounding box of either
40
+ (both) ``wcs_from`` or (and) ``wcs_to`` when computing pixel map. When
41
+ ``disable_bbox`` is "none", pixel coordinates outside of the bounding
42
+ box are set to `NaN` only if ``wcs_from`` or (and) ``wcs_to`` sets
43
+ world coordinates to NaN when input pixel coordinates are outside of
44
+ the bounding box.
45
+
38
46
Returns
39
47
-------
40
48
pixmap : numpy.ndarray
@@ -57,35 +65,62 @@ def calc_pixmap(wcs_from, wcs_to, shape=None):
57
65
If ``bounding_box`` is not available, a `ValueError` will be raised.
58
66
59
67
"""
68
+ if (bbox_from := getattr (wcs_from , "bounding_box" , None )) is not None :
69
+ try :
70
+ # to avoid dependency on astropy just to check whether
71
+ # the bounding box is an instance of
72
+ # modeling.bounding_box.ModelBoundingBox, we try to
73
+ # directly use and bounding_box(order='F') and if it fails,
74
+ # fall back to converting the bounding box to a tuple
75
+ # (of intervals):
76
+ bbox_from = bbox_from .bounding_box (order = 'F' )
77
+ except AttributeError :
78
+ bbox_from = tuple (bbox_from )
79
+
80
+ if (bbox_to := getattr (wcs_to , "bounding_box" , None )) is not None :
81
+ try :
82
+ # to avoid dependency on astropy just to check whether
83
+ # the bounding box is an instance of
84
+ # modeling.bounding_box.ModelBoundingBox, we try to
85
+ # directly use and bounding_box(order='F') and if it fails,
86
+ # fall back to converting the bounding box to a tuple
87
+ # (of intervals):
88
+ bbox_to = bbox_to .bounding_box (order = 'F' )
89
+ except AttributeError :
90
+ bbox_to = tuple (bbox_to )
91
+
60
92
if shape is None :
61
93
shape = wcs_from .array_shape
62
- if shape is None :
63
- if (bbox := getattr (wcs_from , "bounding_box" , None )) is not None :
64
- try :
65
- # to avoid dependency on astropy just to check whether
66
- # the bounding box is an instance of
67
- # modeling.bounding_box.ModelBoundingBox, we try to
68
- # directly use and bounding_box(order='F') and if it fails,
69
- # fall back to converting the bounding box to a tuple
70
- # (of intervals):
71
- bbox = bbox .bounding_box (order = 'F' )
72
- except AttributeError :
73
- bbox = tuple (bbox )
74
-
75
- if (nd := np .ndim (bbox )) == 1 :
76
- bbox = (bbox , )
77
- if nd > 1 :
78
- shape = tuple (
79
- int (math .ceil (lim [1 ] + 0.5 )) for lim in bbox [::- 1 ]
80
- )
94
+ if shape is None and bbox_from is not None :
95
+ if (nd := np .ndim (bbox_from )) == 1 :
96
+ bbox_from = (bbox_from , )
97
+ if nd > 1 :
98
+ shape = tuple (
99
+ int (math .ceil (lim [1 ] + 0.5 )) for lim in bbox_from [::- 1 ]
100
+ )
81
101
82
102
if shape is None :
83
103
raise ValueError (
84
104
'The "from" WCS must have pixel_shape property set.'
85
105
)
86
106
87
107
y , x = np .indices (shape , dtype = np .float64 )
88
- x , y = wcs_to .world_to_pixel_values (* wcs_from .pixel_to_world_values (x , y ))
108
+
109
+ # temporarily disable the bounding box for the "from" WCS:
110
+ if disable_bbox in ["from" , "both" ] and bbox_from is not None :
111
+ wcs_from .bounding_box = None
112
+ if disable_bbox in ["to" , "both" ] and bbox_to is not None :
113
+ wcs_to .bounding_box = None
114
+ try :
115
+ x , y = wcs_to .world_to_pixel_values (
116
+ * wcs_from .pixel_to_world_values (x , y )
117
+ )
118
+ finally :
119
+ if bbox_from is not None :
120
+ wcs_from .bounding_box = bbox_from
121
+ if bbox_to is not None :
122
+ wcs_to .bounding_box = bbox_to
123
+
89
124
pixmap = np .dstack ([x , y ])
90
125
return pixmap
91
126
0 commit comments