Skip to content

Commit 19453ec

Browse files
committed
Added "_is_valid_beam_tuple" to DataAccessor
Added: 1) "_is_valid_beam_tuple" static method to "DataAccessor", should be a safeguard against ill-determined beams. 2) Some type annotation for linters.
1 parent 0a67299 commit 19453ec

1 file changed

Lines changed: 30 additions & 18 deletions

File tree

sourcefinder/accessors/dataaccessor.py

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import logging
22

33
import numpy
4-
import numbers
4+
from numbers import Real
55
from math import degrees, sqrt, sin, pi, cos
66
from dataclasses import dataclass, field
77
from sourcefinder.utility.coordinates import WCS
88
from sourcefinder.config import ImgConf
9-
from typing import Optional
9+
from typing import Optional, cast
1010

1111
logger = logging.getLogger(__name__)
1212

@@ -84,18 +84,25 @@ class DataAccessor:
8484

8585
def __post_init__(self):
8686
if self.conf is not None:
87-
bmaj, bmin, bpa = self.conf.bmaj, self.conf.bmin, self.conf.bpa
88-
if all(isinstance(x, numbers.Real) and x is not None for x in
89-
(bmaj, bmin, bpa)):
87+
beam_tuple = (self.conf.bmaj, self.conf.bmin, self.conf.bpa)
88+
if self._is_valid_beam_tuple(beam_tuple):
9089
deltax, deltay = self.pixelsize
91-
self.beam = DataAccessor.degrees2pixels(bmaj, bmin, bpa,
90+
self.beam = DataAccessor.degrees2pixels(*beam_tuple,
9291
deltax, deltay)
9392
else:
9493
print(("WARNING: Partial beam specification ignored; "
9594
"one or more of (bmaj, bmin, bpa) are not "
9695
"specified."))
9796
self.beam = None
9897

98+
@staticmethod
99+
def _is_valid_beam_tuple(b) -> bool:
100+
return (
101+
isinstance(b, tuple)
102+
and len(b) == 3
103+
and all(isinstance(x, Real) and x is not None for x in b)
104+
)
105+
99106
def extract_metadata(self) -> dict:
100107
"""
101108
Massage the class attributes into a flat dictionary with
@@ -124,16 +131,18 @@ def extract_metadata(self) -> dict:
124131
'deltay': self.pixelsize[1],
125132
}
126133

127-
if self.beam is not None:
134+
135+
if self._is_valid_beam_tuple(self.beam):
136+
beam = cast(tuple[float, float, float], self.beam)
128137
metadata.update({
129-
'beam_smaj_pix': self.beam[0],
130-
'beam_smin_pix': self.beam[1],
131-
'beam_pa_rad': self.beam[2],
138+
'beam_smaj_pix': beam[0],
139+
'beam_smin_pix': beam[1],
140+
'beam_pa_rad': beam[2],
132141
})
133142

134143
return metadata
135144

136-
def parse_pixelsize(self):
145+
def parse_pixelsize(self) -> tuple[float, float]:
137146
"""
138147
Returns
139148
-------
@@ -165,7 +174,8 @@ def parse_pixelsize(self):
165174
return deltax, deltay
166175

167176
@staticmethod
168-
def degrees2pixels(bmaj, bmin, bpa, deltax, deltay):
177+
def degrees2pixels(bmaj, bmin, bpa, deltax, deltay) -> (
178+
tuple)[float, float, float]:
169179
"""
170180
Convert beam in degrees to beam in pixels and radians.
171181
For example, FITS beam parameters are in degrees.
@@ -185,12 +195,14 @@ def degrees2pixels(bmaj, bmin, bpa, deltax, deltay):
185195
186196
Returns
187197
-------
188-
semimaj : float
189-
Beam semi-major axis in pixels.
190-
semimin : float
191-
Beam semi-minor axis in pixels.
192-
theta : float
193-
Beam position angle in radians.
198+
tuple
199+
A tuple containing:
200+
- semimaj : float
201+
Beam semi-major axis in pixels.
202+
- semimin : float
203+
Beam semi-minor axis in pixels.
204+
- theta : float
205+
Beam position angle in radians.
194206
"""
195207
theta = pi * bpa / 180
196208
semimaj = (bmaj / 2.) * (sqrt(

0 commit comments

Comments
 (0)