diff options
Diffstat (limited to 'noao/twodspec/multispec/fitclean.x')
-rw-r--r-- | noao/twodspec/multispec/fitclean.x | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/noao/twodspec/multispec/fitclean.x b/noao/twodspec/multispec/fitclean.x new file mode 100644 index 00000000..548f2cf4 --- /dev/null +++ b/noao/twodspec/multispec/fitclean.x @@ -0,0 +1,257 @@ +include "ms.h" + +# FIT_AND_CLEAN -- Iteratively fit profile scales using banded matrix method +# and remove deviant pixels. +# +# The profile fitting and cleaning are combined in order to minimize +# the calculations in re-evaluating the least squares fit after rejecting +# deviant pixels. +# +# The sigma of the fit is calculated and deviant pixels are those whose +# residual is more than +-sigma_cut * sigma. +# The maximum number of pixels to be replaced is max_replace. +# If max_replace is zero then only the model fitting is performed. +# +# The output of this routine are the cleaned data profiles and the +# least-square fitted model profiles. Return the number of pixels replaced. + + +procedure fit_and_clean (ms, data, model, ranges, profiles, len_line, + len_profile, nspectra, nparams) + +pointer ms # MULTISPEC data structure +real data[len_line] # Input data to be fit +real model[len_line] # Output model line +real ranges[nspectra, LEN_RANGES, 3] # Profile ranges +real profiles[len_profile, nspectra, nparams, 3] # Model profiles +int len_line # Length of data/model line +int len_profile # Length of each profile +int nspectra # Number of spectra +int nparams # Number model parameters + +int max_iterate # Maximum number of iterations +int max_replace # Maximum number of bad pixels +real sigma_cut # Rejection cutoff +int fit_type # Type of I0 fitting +bool ex_model # Extract model? + +bool exmod +int i_max, nmax, option, npts +int i, iteration, n_total, n_reject +real sigma, lower, upper, residual, resid_min, resid_max + +begin + # Initialize the model and I0 parameters to zero. + call aclrr (PARAMETER(ms,I0,1), nspectra) + call aclrr (model, len_line) + + # Loop until no further deviant pixels are found. + n_total = 0 + + do iteration = 1, imax { + # Determine I0 for each profile. + switch (option) { + case 1: + call full_solution (ms, data, model, ranges, profiles, + len_line, len_profile, nspectra, nparams) + case 2: + call quick_solution (ms, data, ranges, profiles, len_line, + len_profile, nspectra) + } + + # Set the model to be used to compare against the data. + call set_model (ms, model, profiles, ranges, len_line, len_profile, + nspectra) + + # If number of pixels to reject is zero then skip below. + n_reject = 0 + if (n_total == nmax) + break + + # Compute sigma of fit. + sigma = 0. + npts = 0 + do i = 1, len_line { + if ((model[i] > 0.) && (!IS_INDEFR (data[i]))) { + sigma = sigma + (data[i] - model[i]) ** 2 + npts = npts + 1 + } + } + sigma = sqrt (sigma / npts) + resid_min = -lower * sigma + resid_max = upper * sigma + + # Compare each pixel against the model and set deviant pixels + # to INDEFR. If the number of pixels replaced is equal to the + # maximum allowed stop cleaning. Ignore points with model <= 0. + # Thus, points outside the spectra will not be cleaned. + # Ignore INDEFR pixels. + do i = 1, len_line { + if (n_total == nmax) + break + if ((model[i] <= 0.) || (IS_INDEFR (data[i]))) + next + + # Determine deviant pixels. + residual = data[i] - model[i] + if ((residual < resid_min) || (residual > resid_max)) { + # Flag deviant pixel. + data[i] = INDEFR + n_total = n_total + 1 + n_reject = n_reject + 1 + } + } + + if (n_reject == 0) + break + } + # Refit model if a model extraction is desired and bad pixels were + # in the last fit. + if (exmod && n_reject != 0) { + switch (option) { + case 1: + call full_solution (ms, data, model, ranges, profiles, + len_line, len_profile, nspectra, nparams) + case 2: + call quick_solution (ms, data, ranges, profiles, len_line, + len_profile, nspectra) + } + } + + # Scale profiles to form model profiles. + do i = 1, nspectra + call amulkr (profiles[1,i,I0_INDEX,1], PARAMETER(ms,I0,i), + profiles[1,i,I0_INDEX,1], len_profile) + + # Replace deviant or INDEF pixels by model values. + # Even if no cleaning was done there may have been some INDEF points + # in the input data line. + + do i = 1, len_line { + if (IS_INDEFR (data[i])) + data[i] = model[i] + } + + # Print the number of pixels replaced and return. + call ex_prnt3 (n_total) + return + +# SET_FIT_AND_CLEAN -- Set the fitting and cleaning parameters. + +entry set_fit_and_clean (max_iterate, max_replace, sigma_cut, fit_type, + ex_model) + + imax = max_iterate + nmax = max_replace + lower = sigma_cut + upper = sigma_cut + option = fit_type + exmod = ex_model + return +end + + +procedure full_solution (ms, data, model, ranges, profiles, len_line, + len_profile, nspectra, nparams) + +pointer ms # MULTISPEC data structure +real data[len_line] # Input data to be fit +real model[len_line] # Output model line +real ranges[nspectra, LEN_RANGES, 3] # Profile ranges +real profiles[len_profile, nspectra, nparams, 3] # Model profiles +int len_line # Length of data/model line +int len_profile # Length of each profile +int nspectra # Number of spectra +int nparams # Number model parameters + +real rnorm +pointer sp, fitparams, solution, offset + +begin + # Initialize fitparams and ranges arrays. + call smark (sp) + call salloc (fitparams, nspectra * nparams, TY_REAL) + call salloc (solution, nspectra * nparams, TY_REAL) + + offset = (I0_INDEX - 1) * nspectra + call amovki (NO, Memr[fitparams], nspectra * nparams) + call amovki (YES, Memr[fitparams + offset], nspectra) + + # Do least squares banded matrix solution for I0 parameters. + # The solution vector contains the least square fit values which + # must be copied to the I0 parameter vector. + call solve (ms, data, model, Memr[fitparams], profiles, ranges, + len_line, len_profile, nspectra, nparams, Memr[solution], rnorm) + call aaddr (PARAMETER(ms, I0, 1), Memr[solution + offset], + PARAMETER(ms, I0, 1), nspectra) + + call sfree (sp) +end + + +# QUICK_SOLUTION -- Quick determination of profile scaling parameters. + +procedure quick_solution (ms, data, ranges, profiles, len_line, len_profile, + nspectra) + +pointer ms # MULTISPEC data structure +real data[len_line] # Input data to be fit +real ranges[nspectra, LEN_RANGES] # Profile ranges +real profiles[len_profile, nspectra, ARB] # Model profiles +int len_line # Length of data/model line +int len_profile # Length of each profile +int nspectra # Number of spectra + +int i, ic, j, n, spectrum, xc +real i0[3] + +begin + ic = len_profile / 2 + + # Determine a value for I0 for each spectrum which is in the image. + do spectrum = 1, nspectra { + n = 0 + + # Check each profile point from ic on until n = 2. + do i = ic, len_profile - 1 { + xc = ranges[spectrum, X_START] + i + if ((xc < 1) || (xc > len_line)) + next + if (IS_INDEFR (data[xc])) + next + j = i + 1 + if (profiles[j, spectrum, I0_INDEX] <= 0) + next + n = n + 1 + i0[n] = data[xc] / profiles[j, spectrum, I0_INDEX] + if (n >= 2) + break + } + + # Check each profile point from ic - 1 and less until n = 3. + do i = ic - 1, 0, -1 { + xc = ranges[spectrum, X_START] + i + if ((xc < 1) || (xc > len_line)) + next + if (IS_INDEFR (data[xc])) + next + j = i + 1 + if (profiles[j, spectrum, I0_INDEX] <= 0) + next + n = n + 1 + i0[n] = data[xc] / profiles[j, spectrum, I0_INDEX] + break + } + + # Determine I0. + switch (n) { + case 3: # Use median I0 + call asrtr (i0, i0, n) + PARAMETER(ms, I0, spectrum) = i0[2] + case 2: # Use mean I0 + PARAMETER(ms, I0, spectrum) = (i0[1] + i0[2]) / 2 + case 1: # Use only value + PARAMETER(ms, I0, spectrum) = i0[1] + } + } +end |