From fa080de7afc95aa1c19a6e6fc0e0708ced2eadc4 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Wed, 8 Jul 2015 20:46:52 -0400 Subject: Initial commit --- noao/twodspec/multispec/setsmooth.x | 250 ++++++++++++++++++++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 noao/twodspec/multispec/setsmooth.x (limited to 'noao/twodspec/multispec/setsmooth.x') diff --git a/noao/twodspec/multispec/setsmooth.x b/noao/twodspec/multispec/setsmooth.x new file mode 100644 index 00000000..10740dce --- /dev/null +++ b/noao/twodspec/multispec/setsmooth.x @@ -0,0 +1,250 @@ +include +include "ms.h" + +.help set_smooth Jul84 MULTISPEC +.sh +Procedure set_smooth + + This procedure returns data profiles for the requested image line and model +profiles consisting of the sum of (naverage =) nlines - 1 image line data +profiles surrounding (and excluding) the data image line. + + A buffer of nlines + 1 set of profiles is kept. The first set of profiles +is used to keep the sum of the nlines - 1 profiles which excludes the current +line of data profiles (thus, the number of lines in the sum = nlines - 1). +The remaining sets of profiles (2 to nlines + 1) contain data profiles for all +the lines in the sum plus the current data line. The lines are stored in a +cyclic fashion with the buffer line being related to the data line by + + buffer line = 2 + mod (data line - 1, nlines) + +Each data line is read and converted into a set of profiles and put into the +buffer only if it is not already in the buffer. + + The algorithm first checks the state of the previous profiles buffer. +If it would be unchanged then it returns. Otherwise, it subtracts the profiles +which are not in common with the new set of summation lines from the +sum profiles before replacing those lines in the profiles buffer with new data +profiles. If the number of vector subtractions exceeds the number of vector +additions to readd the common lines to the sum profiles then the common +profiles are readded instead. The new data profiles are then obtained from +the image (with procedure msgprofiles) and added, if needed, to the sum +profiles. Finally, the sum profiles are copied to the model profiles and +the profiles from the profiles buffer corresponding to the requested data +line are copied to the data profiles array. + + This algorithm is maximumally efficient with its imageio. If the model +lines are requested sequentially through the image then each image data line +will be read only once and each new model line will, on average, require only +one image read, two vector additions, and two vector subtractions. The +number of vector additions and subtractions is two because the current data +line is excluded from the sum. +.sh +Procedure msgprofiles + + In order to obtain model profiles based on summing the profiles from +a number of neighboring lines, the profiles from each line must be +shifted to the relative profile centers. The procedure msgprofiles reads +an image line and computes an interpolation function for the line. +The spectra profiles are then extracted using the position interpolation +function to determine the spectra centers in the image line. The +profiles are aligned to the same relative positions in the profiles +array based on the ranges array. +.endhelp + + +# SET_SMOOTH -- Set the SMOOTH model profiles. + +procedure set_smooth (ms, im, line, ranges, profiles, coeff, + len_prof, nspectra, nlines, data, model) + +pointer ms # MULTISPEC data structure +int im # IMIO image descriptor +int line # Image line to be modeled +real ranges[nspectra, LEN_RANGES] # Ranges array +real profiles[len_prof, nspectra, ARB] # Profiles array +real coeff[ARB] # Image interpolator coeffs. +int len_prof # Length of profiles +int nspectra # Number of spectra +int nlines # Number of lines in average +real data[len_prof, nspectra] # Data profiles for line +real model[len_prof, nspectra] # SMOOTH model profiles + +int i, j, navg +int len_profs, last_line, last_start, last_end, line_start, line_end +pointer k + +data len_profs/0/ + +begin + # Initialize + if (len_profs == 0) { + navg = nlines - 1 + len_profs = len_prof * nspectra + last_line = 0 + last_start = -nlines + last_end = 0 + } + + # Determine range of lines for averaging. + + # The following is to use the center of the averaging region. + #line_start = max (1, line - nlines / 2) + + # The following uses the preceeding nlines - 1 lines. + line_start = max (1, line - (nlines - 1)) + + line_start = min (line_start, IM_LEN(im, 2) - nlines) + line_end = line_start + nlines - 1 + + # Return if the same line is the same and the lines used in the + # sum profile are the same. + + if ((line_start == last_start) && (line == last_line)) + return + + # If the number of lines in common with the previous sum profile is + # < nlines / 2 then it is more efficient to clear the sum profile + # and readd the common lines. + + if (abs (line_start - last_start) > nlines / 2) { + call aclrr (profiles[1,1,1], len_profs) + do i = last_start, last_end { + j = i - line_start + + # If the old line i is within the new sum add it to the sum. + # However, if the line is the new data line do not add it. + if ((j >= 0) && (j < nlines) && (i != line)) { + k = 2 + mod (i - 1, nlines) + call aaddr (profiles[1,1,1], profiles[1,1,k], + profiles[1,1,1], len_profs) + } + } + + # If the number in lines in common is >= nlines / 2 then it is more + # efficient to subtract the lines not in common from the sum. + + } else { + do i = last_start, last_end { + j = i - line_start + k = 2 + mod (i - 1, nlines) + + # If the old line i is not within the new sum subtract it. + # Also, if the line is the new data line subtract it. + if ((j < 0) || (j >= nlines) || (i == line)) { + # However, don't subtract the last data line since it was + # not in the previous sum. + if (i != last_line) { + call asubr (profiles[1,1,1], profiles[1,1,k], + profiles[1,1,1], len_profs) + } + + # If the old line is within the new sum but it was the old data + # line then add it to the sum since it was not in the old sum. + } else if (i == last_line) { + call aaddr (profiles[1,1,1], profiles[1,1,k], + profiles[1,1,1], len_profs) + } + } + } + + # Get the new profiles into the profile buffer and the add to the sum. + do i = line_start, line_end { + j = i - last_start + if ((j < 0) || (j >= nlines)) { + k = 2 + mod (i - 1, nlines) + + # Get the data profile for line i and put it in profiles k. + call msgprofiles (ms, im, i, ranges, profiles[1,1,k], coeff, + len_prof, nspectra) + + # If the new line in the buffer is not the data line then + # add it to the sum profile. + if (i != line) { + call aaddr (profiles[1,1,1], profiles[1,1,k], + profiles[1,1,1], len_profs) + } + } + } + + # Record current state of the average. + last_line = line + last_start = line_start + last_end = line_end + + # Set the data profiles and model profiles. The copies are + # made rather than working directly from the profiles buffer so that + # changes can be made in the data and model profiles without affecting + # the buffer. + + k = 2 + mod (line - 1, nlines) + call amovr (profiles[1,1,k], data, len_profs) + call amovr (profiles[1,1,1], model, len_profs) +end + + +# UPDATE_SMOOTH -- Replace an updated data profile in the profiles buffer. + +procedure update_smooth (line, data, profiles, len_prof, nspectra, nlines) + +int line # Data image line +real data[len_prof, nspectra] # Data profiles +real profiles[len_prof, nspectra, ARB] # Profiles buffer +int len_prof # Length of profiles +int nspectra # Number of spectra +int nlines # Number of lines in buffer + +int i + +begin + i = 2 + mod (line - 1, nlines) + call amovr (data, profiles[1,1,i], len_prof * nspectra) +end + + +# MSGPROFILES -- Read image line and extract profiles in standard positions. + +procedure msgprofiles (ms, im, line, ranges, profile, coeff, len_prof, + nspectra) + +pointer ms # MULTISPEC data structure +pointer im # IMIO image descriptor +int line # Image line to be read +real ranges[nspectra, LEN_RANGES] # Ranges array for profiles +real profile[len_prof, nspectra] # Profiles to be obtained +real coeff[ARB] # Image interpolator coeffs. +int len_prof # Length of profiles +int nspectra # Number of spectra + +int i, j +real x +pointer im_buf + +pointer imgl2r() +real cveval(), asival() + +begin + # Read image line. + im_buf = imgl2r (im, line) + + # Fit image interpolation function. + call asifit (Memr[im_buf], IM_LEN(im, 1), coeff) + + # For each spectrum extract the profiles. + do j = 1, nspectra { + + # Determine profile starting point in image coordinates using the + # fit function for the spectrum center. + x = cveval (CV(ms, X0_FIT, j), real (line)) + + ranges[j, DX_START] - 1 + + # For each point in the profile evaluate the image interpolator. + do i = 1, len_prof { + x = x + 1 + if ((x < 1) || (x > IM_LEN(im, 1))) + profile[i, j] = 0. + else + profile[i, j] = asival (x, coeff) + } + } +end -- cgit