r""" Fitting of multiple spectra using NNLS method. Parameters ---------- data : ndarray(float), 2D array holding multiple observed spectra, shape (K, N), where K is the number of energy points, and N is the number of spectra absorption_refs : ndarray(float), 2
(data, ref_spectra, *, maxiter=100)
| 235 | |
| 236 | |
| 237 | def _fitting_nnls(data, ref_spectra, *, maxiter=100): |
| 238 | r""" |
| 239 | Fitting of multiple spectra using NNLS method. |
| 240 | |
| 241 | Parameters |
| 242 | ---------- |
| 243 | |
| 244 | data : ndarray(float), 2D |
| 245 | array holding multiple observed spectra, shape (K, N), where K is the number of energy points, |
| 246 | and N is the number of spectra |
| 247 | |
| 248 | absorption_refs : ndarray(float), 2D |
| 249 | array of references, shape (K, Q), where Q is the number of references. |
| 250 | |
| 251 | maxiter : int |
| 252 | maximum number of iterations. Optimization may stop prematurely if convergence criteria are met. |
| 253 | |
| 254 | Returns |
| 255 | ------- |
| 256 | |
| 257 | map_data_fitted : ndarray(float), 2D |
| 258 | fitting results, shape (Q, N), where Q is the number of references and N is the number of spectra. |
| 259 | |
| 260 | map_rfactor : ndarray(float), 2D |
| 261 | map that represents R-factor for the fitting, shape (M,N). |
| 262 | |
| 263 | map_residual : ndarray(float), 2D |
| 264 | residual returned by NNLS algorithm |
| 265 | """ |
| 266 | assert data.ndim == 2, "Data array 'data' must have 2 dimensions" |
| 267 | assert ref_spectra.ndim == 2, "Data array 'ref_spectra' must have 2 dimensions" |
| 268 | |
| 269 | n_pts = data.shape[0] |
| 270 | n_pixels = data.shape[1] |
| 271 | n_pts_2 = ref_spectra.shape[0] |
| 272 | n_refs = ref_spectra.shape[1] |
| 273 | |
| 274 | assert ( |
| 275 | n_pts == n_pts_2 |
| 276 | ), f"The number of spectrum points in data ({n_pts}) and references ({n_pts_2}) do not match." |
| 277 | |
| 278 | assert maxiter > 0, f"The parameter 'maxiter' is zero or negative ({maxiter})" |
| 279 | |
| 280 | map_data_fitted = np.zeros(shape=[n_refs, n_pixels]) |
| 281 | map_rfactor = np.zeros(shape=[n_pixels]) |
| 282 | map_residual = np.zeros(shape=[n_pixels]) |
| 283 | for n in range(n_pixels): |
| 284 | map_sel = data[:, n] |
| 285 | result, residual = nnls(ref_spectra, map_sel, maxiter=maxiter) |
| 286 | |
| 287 | rfactor = rfactor_compute(map_sel, result, ref_spectra) |
| 288 | |
| 289 | map_data_fitted[:, n] = result |
| 290 | map_rfactor[n] = rfactor |
| 291 | map_residual[n] = residual |
| 292 | |
| 293 | return map_data_fitted, map_rfactor, map_residual |
| 294 |