diff options
Diffstat (limited to 'noao/twodspec/longslit/illumination.x')
-rw-r--r-- | noao/twodspec/longslit/illumination.x | 414 |
1 files changed, 414 insertions, 0 deletions
diff --git a/noao/twodspec/longslit/illumination.x b/noao/twodspec/longslit/illumination.x new file mode 100644 index 00000000..c291d6f4 --- /dev/null +++ b/noao/twodspec/longslit/illumination.x @@ -0,0 +1,414 @@ +include <imhdr.h> +include <error.h> +include <math/iminterp.h> +include <pkg/gtools.h> +include <pkg/rg.h> +include <pkg/xtanswer.h> + +# T_ILLUMINATION -- Determine the illumination function for longslit spectra. +# +# The calibration image is binned in wavelength. Each wavelength bin is +# then smoothed by curve fitting and normalized to the middle point. +# Finally the binned image is interpolated back to the original image +# dimension. The binning and curve fitting may be performed interactively. +# A illumination function is determined for each input images. Image +# sections in the input image allow only parts of the illumination function +# to be created. Thus, multiple slits in the same image may have +# independent illumination functions on the same illumination image. + +# CL callable procedure. +# +# The input and output images are given by image templates. The +# number of output images must match the number of input images. +# Input image sections are allowed. + +procedure t_illumination () + +pointer image1 +pointer image2 +int list1 # Calibration image list +int list2 # Illumination image list +int interactive # Interactive? +int naverage # Sample averaging size +int order # Order of curve fitting function +real low_reject, high_reject # Rejection thresholds +int niterate # Number of rejection iterations +real grow # Rejection growing radius + +int answer +char history[SZ_LINE] +pointer in, out, ic, gt, sp, str + +int clgeti(), imtopen(), imtgetim(), imtlen(), gt_init() +bool clgetb() +real clgetr() +errchk il_make + +begin + call smark (sp) + call salloc (image1, SZ_LINE, TY_CHAR) + call salloc (image2, SZ_LINE, TY_CHAR) + call salloc (str, SZ_LINE, TY_CHAR) + + # Get calibration and illumination image template lists. + + call clgstr ("images", Memc[image1], SZ_LINE) + call clgstr ("illuminations", Memc[image2], SZ_LINE) + + # Check that the number of illumination calibration images are the same. + + list1 = imtopen (Memc[image1]) + list2 = imtopen (Memc[image2]) + if (imtlen (list1) != imtlen (list2)) { + call imtclose (list1) + call imtclose (list2) + call error (0, + "The number of input and output images are not the same.") + } + + # Get other parameters and initialize the curve fitting package. + + if (clgetb ("interactive")) + interactive = YES + else + interactive = ALWAYSNO + + call clgstr ("sample", Memc[image1], SZ_LINE) + naverage = clgeti ("naverage") + call clgstr ("function", Memc[str], SZ_LINE) + order = clgeti ("order") + low_reject = clgetr ("low_reject") + high_reject = clgetr ("high_reject") + niterate = clgeti ("niterate") + grow = clgetr ("grow") + + # Set the ICFIT pointer structure. + call ic_open (ic) + call ic_pstr (ic, "sample", Memc[image1]) + call ic_puti (ic, "naverage", naverage) + call ic_pstr (ic, "function", Memc[str]) + call ic_puti (ic, "order", order) + call ic_putr (ic, "low", low_reject) + call ic_putr (ic, "high", high_reject) + call ic_puti (ic, "niterate", niterate) + call ic_putr (ic, "grow", grow) + call ic_pstr (ic, "ylabel", "") + + gt = gt_init() + call gt_sets (gt, GTTYPE, "line") + + # Create an illumination image for each calibration image + while ((imtgetim (list1, Memc[image1], SZ_LINE) != EOF) && + (imtgetim (list2, Memc[image2], SZ_LINE) != EOF)) { + + call ls_immap (Memc[image1], Memc[image2], in, out) + + call sprintf (Memc[str], SZ_LINE, + "Determine illumination interactively for %s") + call pargstr (Memc[image1]) + call xt_answer (Memc[str], interactive) + answer = interactive + + iferr { + call il_make (in, out, ic, gt, Memc[str], answer) + + call imaddr (out, "ccdmean", 1.) + call sprintf (history, SZ_LINE, + "Illumination correction determined from %s.") + call pargstr (Memc[image1]) + call imastr (out, "mkillum", history) + call imunmap (in) + call imunmap (out) + } then { + call erract (EA_WARN) + call imunmap (in) + call imunmap (out) + call imdelete (Memc[image2]) + } + } + + call ic_closer (ic) + call gt_free (gt) + call imtclose (list1) + call imtclose (list2) + call sfree (sp) +end + + +# IL_MAKE -- Given the calibration and illumination image descriptors +# make the illumination function. + +procedure il_make (in, out, ic, gt, title, interactive) + +pointer in # Calibration IMIO pointer +pointer out # Illumination IMIO pointer +pointer ic # ICFIT pointer +pointer gt # GTOOLS pointer +char title[ARB] # Title +int interactive # Interactive? + +char graphics[SZ_FNAME] # Graphics output device +int i, laxis, paxis, axis, npts, nbins, len_title +pointer bins, cv, gp, sp, x, y, z, z1, wts + +pointer gopen() +int strlen() +errchk get_daxis + +begin + # Determine the slit axis and set the axis labels. + call get_daxis (in, laxis, paxis) + if (laxis == 1) + axis = 2 + else + axis = 1 + + switch (axis) { + case 1: + call ic_pstr (ic, "xlabel", "Column") + case 2: + call ic_pstr (ic, "xlabel", "Line") + } + + # Set the bins and bin the calibration image. + + switch (axis) { + case 1: + call il_setbins (in, 2, interactive, bins) + case 2: + call il_setbins (in, 1, interactive, bins) + } + + call il_binimage (in, axis, bins, x, y, z, npts, nbins) + call rg_free (bins) + + # Allocate memory for the fit. + + call smark (sp) + call salloc (wts, npts, TY_REAL) + call amovkr (1., Memr[wts], npts) + + # Smooth each bin. + + call ic_putr (ic, "xmin", Memr[x]) + call ic_putr (ic, "xmax", Memr[x+npts-1]) + + len_title = strlen (title) + z1 = z + + do i = 1, nbins { + title[len_title + 1] = EOS + call sprintf (title, SZ_LINE, "%s at bin %d") + call pargstr (title) + call pargi (i) + call xt_answer (title, interactive) + + if ((interactive == YES) || (interactive == ALWAYSYES)) { + call sprintf (title, SZ_LINE, "%s\n%s") + call pargstr (title) + call pargstr (IM_TITLE(in)) + call gt_sets (gt, GTTITLE, title) + + call clgstr ("graphics", graphics, SZ_FNAME) + gp = gopen (graphics, NEW_FILE, STDGRAPH) + call icg_fit (ic, gp, "cursor", gt, cv, Memr[x], Memr[z1], + Memr[wts], npts) + call amovkr (1., Memr[wts], npts) + call gclose (gp) + } else { + call ic_fit (ic, cv, Memr[x], Memr[z1], Memr[wts], npts, + YES, YES, YES, YES) + } + + call cvvector (cv, Memr[x], Memr[z1], npts) + z1 = z1 + npts + } + call cvfree (cv) + + # Compute the illumination image by linear interpolation. + + call il_expand (out, axis, Memr[x], Memr[y], Memr[z], npts, nbins) + + # Free allocated memory. + + call mfree (x, TY_REAL) + call mfree (y, TY_REAL) + call mfree (z, TY_REAL) + call sfree (sp) +end + + +# IL_BINIMAGE -- Read the calibration image and bin it. + +procedure il_binimage (im, axis, bins, x, y, z, npts, nbins) + +pointer im # Calibration IMIO pointer +int axis # Slit axis +pointer bins # Bins +pointer x # Slit positions +pointer y # Dispersion positions of bins +pointer z # Binned image +int npts # Number of points per bin +int nbins # Number of bins + +int i, y1, y2 +pointer z1 + +begin + # Allocate memory. + + npts = IM_LEN (im, axis) + nbins = RG_NRGS (bins) + call malloc (y, nbins, TY_REAL) + call malloc (z, npts * nbins, TY_REAL) + + # Bin the image data. + + x = NULL + do i = 1, nbins { + y1 = RG_X1 (bins, i) + y2 = RG_X2 (bins, i) + Memr[y+i-1] = (y1 + y2) / 2 + + call mfree (x, TY_REAL) + switch (axis) { + case 1: + call ls_aimavg (im, axis, 1, IM_LEN(im, 1), y1, y2, x, z1, npts) + case 2: + call ls_aimavg (im, axis, y1, y2, 1, IM_LEN(im, 2), x, z1, npts) + } + call amovr (Memr[z1], Memr[z+(i-1)*npts], npts) + call mfree (z1, TY_REAL) + } +end + + +# IL_EXPAND -- Expand the reduced illumination back to the original size. +# This procedure request the interpolation type. + +procedure il_expand (im, axis, x, y, z, nx, ny) + +pointer im # Illumination image pointer +int axis # Slit axis +real x[nx] # Slit coordinates +real y[ny] # Dispersion coordinates +real z[nx, ny] # Slit profile +int nx # Number of points per slit profile +int ny # Number of slit profiles + +char dummy[7] +int nyout, ncols, nlines +int i, j, y1, y2 +real dy +pointer msi, sp, out, yout + +int clgwrd() +pointer impl2r() + +int msitypes[5] +data msitypes/II_BINEAREST,II_BILINEAR,II_BIPOLY3,II_BIPOLY5,II_BISPLINE3/ +string msinames "|nearest|linear|poly3|poly5|spline3|" + +begin + ncols = IM_LEN (im, 1) + nlines = IM_LEN (im, 2) + + # Normalize illumination to the center of each slit. + + i = nx / 2 - 1 + do j = 1, ny { + dy = z[i, j] + call adivkr (z[1, j], dy, z[1, j], nx) + } + + # If there is only one slit profile then copy the profile to each + # image line or column. + + if (ny == 1) { + switch (axis) { + case 1: + do i = 1, nlines + call amovr (z, Memr[impl2r (im, i)], ncols) + case 2: + do i = 1, nlines + call amovkr (z[i, 1], Memr[impl2r (im, i)], ncols) + } + + return + } + + # If there is more than one slit profile fit a 2D interpolator. + + i = clgwrd ("interpolator", dummy, 7, msinames) + if (i == 0) + i = II_BILINEAR + else + i = msitypes[i] + + switch (i) { + case II_POLY3, II_SPLINE3: + if (ny < 4) + i = II_BILINEAR + case II_POLY5: + if (ny < 6) { + if (ny < 4) + i = II_BILINEAR + else + i = II_POLY3 + } + } + + call msiinit (msi, i) + call msifit (msi, z, nx, ny, nx) + + # Set the output grid in terms of the interpolation surface. + + switch (axis) { + case 1: + nyout = IM_LEN (im, 2) + case 2: + nyout = IM_LEN (im, 1) + } + + call smark (sp) + call salloc (yout, nyout, TY_REAL) + + y1 = 1 + y2 = y[1] + do i = y1, y2 + Memr[yout+i-1] = 1 + do j = 2, ny { + y1 = y2 + 1 + y2 = y[j] + dy = 1. / (y2 - y1) + do i = y1, y2 + Memr[yout+i-1] = j - 1 + (i - y1) * dy + } + y1 = y2 + 1 + y2 = nyout + do i = y1, y2 + Memr[yout+i-1] = ny + + # Evaluate the interpolation surface on the output grid. + + ncols = IM_LEN (im, 1) + nlines = IM_LEN (im, 2) + call salloc (out, ncols, TY_REAL) + + switch (axis) { + case 1: + do i = 1, nlines { + call amovkr (Memr[yout+i-1], Memr[out], ncols) + call msivector (msi, x, Memr[out], Memr[impl2r (im, i)], + ncols) + } + case 2: + do i = 1, nlines { + call amovkr (x[i], Memr[out], ncols) + call msivector (msi, Memr[out], Memr[yout], Memr[impl2r(im, i)], + ncols) + } + } + + call sfree (sp) +end |