Skip to content

Commit 6f5aba7

Browse files
committed
Add kappa-sigma rejected average to stacking possibilities
1 parent fc0d5e0 commit 6f5aba7

File tree

2 files changed

+76
-6
lines changed

2 files changed

+76
-6
lines changed

bin/halostack_cli.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,10 @@ def halostack_cli(args):
8888
images = args['fname_in']
8989

9090
stacks = []
91-
for stack in args['stacks']:
92-
stacks.append(Stack(stack, len(images), nprocs=args['nprocs']))
91+
for i in range(len(args['stacks'])):
92+
stacks.append(Stack(args['stacks'][i], len(images),
93+
nprocs=args['nprocs'],
94+
kwargs=args['stack_kwargs'][i]))
9395

9496
base_img_fname = images[0]
9597
base_img = Image(fname=base_img_fname, nprocs=args['nprocs'])
@@ -202,6 +204,12 @@ def main():
202204
parser.add_argument("-d", "--median", dest="median_stack_file",
203205
default=None, metavar="FILE",
204206
help="Output filename of the median stack")
207+
parser.add_argument("-S", "--sigma", dest="sigma_stack_file",
208+
default=None, metavar="FILE",
209+
help="Output filename of the kappa-sigma stack")
210+
parser.add_argument("-k", "--kappa-sigma-params", dest="kappa_sigma_params",
211+
default=None, metavar="KAPPA,ITERATIONS",
212+
help="Kappa and iterations for the kappa-sigma stack")
205213
parser.add_argument("-t", "--correlation-threshold",
206214
dest="correlation_threshold",
207215
default=None, metavar="NUM", type=float,
@@ -267,24 +275,40 @@ def main():
267275
# Check which stacks will be made
268276
stacks = []
269277
stack_fnames = []
278+
stack_kwargs = []
270279
if args['min_stack_file']:
271280
stacks.append('min')
272281
stack_fnames.append(args['min_stack_file'])
282+
stack_kwargs.append(None)
273283
LOGGER.debug("Added minimum stack")
274284
if args['max_stack_file']:
275285
stacks.append('max')
276286
stack_fnames.append(args['max_stack_file'])
287+
stack_kwargs.append(None)
277288
LOGGER.debug("Added maximum stack")
278289
if args['avg_stack_file']:
279290
stacks.append('mean')
280291
stack_fnames.append(args['avg_stack_file'])
292+
stack_kwargs.append(None)
281293
LOGGER.debug("Added average stack")
282294
if args['median_stack_file']:
283295
stacks.append('median')
284296
stack_fnames.append(args['median_stack_file'])
297+
stack_kwargs.append(None)
298+
LOGGER.debug("Added median stack")
299+
if args['sigma_stack_file']:
300+
stacks.append('sigma')
301+
stack_fnames.append(args['sigma_stack_file'])
302+
if args['kappa_sigma_params']:
303+
tmp = args['kappa_sigma_params'].split(',')
304+
stack_kwargs.append({'kappa': float(tmp[0]),
305+
'max_iters': int(tmp[1])})
306+
else:
307+
stack_kwargs.append(None)
285308
LOGGER.debug("Added median stack")
286309
args['stacks'] = stacks
287310
args['stack_fnames'] = stack_fnames
311+
args['stack_kwargs'] = stack_kwargs
288312

289313
# Check if there's anything to do
290314
if len(args['stacks']) == 0 and args['save_prefix'] is None or \

halostack/stack.py

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,10 @@ class Stack(object):
4444
'max' - maximum stack
4545
'mean' - average stack
4646
'median' - median stack
47+
'sigma' - kappa-sigma stack
4748
'''
4849

49-
def __init__(self, mode, num, nprocs=1):
50+
def __init__(self, mode, num, nprocs=1, kwargs=None):
5051
LOGGER.debug("Initializing %s stack for %d images.",
5152
mode, num)
5253
self.stack = None
@@ -58,14 +59,15 @@ def __init__(self, mode, num, nprocs=1):
5859
'calc': None},
5960
'mean': {'update': self._update_mean,
6061
'calc': None},
61-
# 'sigma': {'update': self._update_deep,
62-
# 'calc': self._calculate_sigma},
62+
'sigma': {'update': self._update_deep,
63+
'calc': self._calculate_sigma},
6364
'median': {'update': self._update_deep,
6465
'calc': self._calculate_median}}
6566
self._update_func = self._mode_functions[mode]['update']
6667
self._calculate_func = self._mode_functions[mode]['calc']
6768
self.num = num
6869
self._num = 0
70+
self._kwargs = kwargs
6971

7072
def add_image(self, img):
7173
'''Add a frame to the stack.
@@ -178,4 +180,48 @@ def _calculate_sigma(self):
178180
'''Calculate the sigma-reject average of the stack and return
179181
the result as Image(dtype=uint16).
180182
'''
181-
LOGGER.error("Sigma stack not implemented.")
183+
shape = self.stack['R'].shape
184+
img = np.zeros((shape[0], shape[1], 3), dtype=self.stack['R'].dtype)
185+
186+
try:
187+
kappa = self._kwargs["kappa"]
188+
except (TypeError, KeyError):
189+
kappa = 2
190+
try:
191+
max_iters = self._kwargs["max_iters"]
192+
except (TypeError, KeyError):
193+
max_iters = self._num/4
194+
195+
LOGGER.info("Calculating Sigma-Kappa average.")
196+
197+
img[:, :, 0] = _sigma_worker(self.stack['R'], kappa, max_iters)
198+
img[:, :, 1] = _sigma_worker(self.stack['G'], kappa, max_iters)
199+
img[:, :, 2] = _sigma_worker(self.stack['B'], kappa, max_iters)
200+
201+
return Image(img=img, nprocs=self.nprocs)
202+
203+
def _sigma_worker(data, kappa, max_iters):
204+
'''Calculate kappa-sigma mean of the data.'''
205+
206+
shape = data.shape
207+
tile_shape = (shape[-1], 1)
208+
data_out = np.empty((shape[0], shape[1]), dtype=STACK_DTYPE) # data.dtype)
209+
210+
for i in range(shape[0]):
211+
num_it = 0
212+
row = np.ma.masked_equal(data[i, :, :], 0).T
213+
while True:
214+
avgs = np.mean(row, 0)
215+
diffs = np.abs(np.tile(avgs, tile_shape) - row)
216+
stds = np.std(row, 0)
217+
idxs = diffs > kappa * np.tile(stds, tile_shape)
218+
num_it += 1
219+
if np.any(idxs):
220+
row = np.ma.masked_where(idxs, row)
221+
else:
222+
break
223+
if num_it >= max_iters:
224+
break
225+
data_out[i, :] = np.mean(row, 0)
226+
227+
return data_out

0 commit comments

Comments
 (0)