Coverage for src/susi/reduc/fringes/spc_registration.py: 0%
42 statements
« prev ^ index » next coverage.py v7.5.0, created at 2025-06-13 14:15 +0000
« prev ^ index » next coverage.py v7.5.0, created at 2025-06-13 14:15 +0000
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3"""
4Provides registration of SP1 and SP2 cameras
6@author: iglesias
7"""
9import numpy as np
10import logging
11from skimage.transform import warp
13log = logging.getLogger("SUSI")
16class SPCRegistration:
17 """
18 Simultaneously Fits and apply the following transformations to SPC2 to mnimize the int difference wrt SPC1:
19 - Shift in x and y
20 - Rigid rotation
21 - Spectral dispersion
22 """
24 def __init__(self, array):
25 """
26 :param array: numpy array with the image data [row, col]
27 """
28 self.data = array # original image
29 self.result = None # distorted image
30 self.shear = None # shear factor
31 self.coord_off = None # offset to add to the coordinates of the image
32 self.out_roi = slice(None, None), slice(None, None) # output roi
34 def run(self, shear_factor, coord_off=(0, 0)):
35 """
36 shear_factor: float
37 """
38 self.shear = shear_factor
39 self.coord_off = coord_off
40 if self.shear == 0:
41 self.result = self.data
42 self.out_roi = slice(0, self.data.shape[0]), slice(0, self.data.shape[1])
43 else:
44 self.result = self.transform_image()
45 self.result = self.keep_valid_rectangular_roi()
46 return self.result
48 def transform_image(self):
49 transform = ShearDistortion.nl_shear
50 transformed_img = warp(
51 self.data,
52 inverse_map=transform,
53 map_args={"shear_factor": self.shear, "coord_off": self.coord_off},
54 mode="constant",
55 cval=np.NAN,
56 )
57 return transformed_img
59 def keep_valid_rectangular_roi(self):
60 roi = [None, None]
61 is_nan = np.isnan(self.result)
62 y = ~np.all(is_nan, axis=1)
63 x = ~np.all(is_nan, axis=0)
64 roi[0] = slice(np.min(np.where(y)), np.max(np.where(y)))
65 roi[1] = slice(np.min(np.where(x)), np.max(np.where(x)))
66 is_nan = is_nan[y, :][:, x]
67 y = np.all(~is_nan, axis=1)
68 roi[0] = slice(roi[0].start + np.min(np.where(y)), roi[0].start + np.max(np.where(y)))
69 self.out_roi = roi[0], roi[1]
70 return self.result[roi[0], roi[1]]
72 @staticmethod
73 def nl_shear(coords, shear_factor, coord_off):
74 x, y = coords.T
75 y += shear_factor / 1e5 * (y + coord_off[0]) * (x + coord_off[1])
76 return np.column_stack((x, y))