| 904 | return self.op_in_avg, self.op_resid_avg, n_positions |
| 905 | |
| 906 | def feed(self, data, good_mask, st_only): |
| 907 | n_samp = data.shape[1] |
| 908 | pos_data, n_pos = _trans_lims( |
| 909 | self.pos, self.offset, self.offset + data.shape[-1] |
| 910 | )[:2] |
| 911 | self.offset += data.shape[-1] |
| 912 | |
| 913 | # Do movement compensation on the data, with optional smoothing |
| 914 | in_data = resid_data = None |
| 915 | for sl, left, right, l_interp in self.smooth.feed_generator(n_samp): |
| 916 | good_data = data[good_mask, sl] |
| 917 | l_sss, l_in, l_resid = left |
| 918 | assert l_sss.shape[1] == good_data.shape[0] |
| 919 | if in_data is None: |
| 920 | in_data = np.empty((l_in.shape[0], data.shape[1])) |
| 921 | resid_data = np.empty((l_resid.shape[0], data.shape[1])) |
| 922 | r_interp = 1.0 - l_interp if l_interp is not None else None |
| 923 | if not st_only: |
| 924 | data[:, sl] = np.dot(l_sss, good_data) |
| 925 | if l_interp is not None: |
| 926 | data[:, sl] *= l_interp |
| 927 | data[:, sl] += r_interp * np.dot(right[0], good_data) |
| 928 | |
| 929 | # Reconstruct data using original location from external |
| 930 | # and internal spaces and compute residual |
| 931 | in_data[:, sl] = np.dot(l_in, good_data) |
| 932 | resid_data[:, sl] = np.dot(l_resid, good_data) |
| 933 | if l_interp is not None: |
| 934 | in_data[:, sl] *= l_interp |
| 935 | resid_data[:, sl] *= l_interp |
| 936 | in_data[:, sl] += r_interp * np.dot(right[1], good_data) |
| 937 | resid_data[:, sl] += r_interp * np.dot(right[2], good_data) |
| 938 | return data, in_data, resid_data, pos_data, n_pos |
| 939 | |
| 940 | |
| 941 | def _trans_lims(pos, start, stop): |