diff options
author | Joseph Hunkeler <jhunkeler@gmail.com> | 2015-07-08 20:46:52 -0400 |
---|---|---|
committer | Joseph Hunkeler <jhunkeler@gmail.com> | 2015-07-08 20:46:52 -0400 |
commit | fa080de7afc95aa1c19a6e6fc0e0708ced2eadc4 (patch) | |
tree | bdda434976bc09c864f2e4fa6f16ba1952b1e555 /noao/onedspec/t_sarith.x | |
download | iraf-linux-fa080de7afc95aa1c19a6e6fc0e0708ced2eadc4.tar.gz |
Initial commit
Diffstat (limited to 'noao/onedspec/t_sarith.x')
-rw-r--r-- | noao/onedspec/t_sarith.x | 1423 |
1 files changed, 1423 insertions, 0 deletions
diff --git a/noao/onedspec/t_sarith.x b/noao/onedspec/t_sarith.x new file mode 100644 index 00000000..460ebd7a --- /dev/null +++ b/noao/onedspec/t_sarith.x @@ -0,0 +1,1423 @@ +include <error.h> +include <imhdr.h> +include <mach.h> +include <smw.h> + +# Output formats. +define FORMATS "|multispec|onedspec|" + +# Operations. +define OPS "|abs|copy|dex|exp|flam|fnu|inv|ln|log|lum|mag|sqrt\ + |replace|+|-|*|/|^|" +define ABS 1 +define COPY 2 +define DEX 3 +define EXP 4 +define FLAM 5 +define FNU 6 +define INV 7 +define LN 8 +define LOG 9 +define LUM 10 +define MAG 11 +define SQRT 12 + +define REP 13 +define ADD 14 +define SUB 15 +define MUL 16 +define DIV 17 +define POW 18 + + +# T_SARITH -- Arithmetic operations (including copying) on spectra. + +procedure t_sarith() + +int inlist1 # List of input spectra +int op # Operation +int inlist2 # List of input spectra or operands +int outlist # List of output spectra +double w1 # Starting wavelength +double w2 # Ending wavelength +bool rebin # Rebin wavelength region? +int format # Output format +pointer aps # Aperture/col/line list +pointer bands # Band list +pointer beams # Beam list +bool complement # Complement aperture/beam selection +int apmod # Aperture modulus (used with subapertures) +int offset # Add this offset to apertures on output +bool reverse # Reverse order of operands +bool ignoreaps # Ignore apertures? +bool clobber # Clobber existing images? +bool merge # Merge with existing images? +bool renumber # Renumber apertures? +bool verbose # Verbose? +real errval # Error value + +int list1, list2 +pointer sp, input1, opstr, input2, output, ptr + +double clgetd() +int imtopenp(), imtopen(), imtlen(), imtgetim() +int clgwrd(), clgeti() +bool clgetb() +pointer rng_open() +common /sarith/ errval + +begin + call smark (sp) + call salloc (input1, SZ_LINE, TY_CHAR) + call salloc (opstr, SZ_LINE, TY_CHAR) + call salloc (input2, SZ_LINE, TY_CHAR) + call salloc (output, SZ_LINE, TY_CHAR) + + # Get parameters. + inlist1 = imtopenp ("input1") + op = clgwrd ("op", Memc[opstr], SZ_LINE, OPS) + if (op > SQRT) + inlist2 = imtopenp ("input2") + else + inlist2 = imtopen ("") + outlist = imtopenp ("output") + + w1 = clgetd ("w1") + w2 = clgetd ("w2") + if (IS_INDEFD(w1) && IS_INDEFD(w2)) + rebin = false + else + rebin = clgetb ("rebin") + + format = clgwrd ("format", Memc[input1], SZ_LINE, FORMATS) + call clgstr ("apertures", Memc[input1], SZ_LINE) + call clgstr ("bands", Memc[input2], SZ_LINE) + call clgstr ("beams", Memc[output], SZ_LINE) + apmod = clgeti ("apmodulus") + offset = clgeti ("offset") + reverse = clgetb ("reverse") + ignoreaps = clgetb ("ignoreaps") + clobber = clgetb ("clobber") + merge = clgetb ("merge") + renumber = clgetb ("renumber") + verbose = clgetb ("verbose") + errval = clgetd ("errval") + + if (op == 0) + call error (1, "Unknown operation") + + # Decode range strings and set complement if needed + ptr = input1 + complement = false + if (Memc[ptr] == '!') { + complement = true + ptr = ptr + 1 + } + iferr (aps = rng_open (Memc[ptr], INDEF, INDEF, INDEF)) + call error (0, "Bad aperture/column/line list") + + ptr = input2 + if (Memc[ptr] == '!') { + complement = true + ptr = ptr + 1 + } + iferr (bands = rng_open (Memc[ptr], INDEF, INDEF, INDEF)) + call error (0, "Bad band list") + + ptr = output + if (Memc[ptr] == '!') { + complement = true + ptr = ptr + 1 + } + iferr (beams = rng_open (Memc[ptr], INDEF, INDEF, INDEF)) + call error (0, "Bad beam list") + + # Check lists. + if (imtlen (outlist) > 1 && imtlen (outlist) != imtlen (inlist1)) + call error (1, "Input and output image lists don't make sense") + if (op > SQRT && + imtlen (inlist2) > 1 && imtlen (inlist2) != imtlen (inlist1)) + call error (1, "Input operand lists don't make sense") + + # Do the operations. + while (imtgetim (inlist1, Memc[input1], SZ_LINE) != EOF) { + if (imtgetim (inlist2, Memc[output], SZ_LINE) == EOF) + call strcpy (Memc[input2], Memc[output], SZ_LINE) + call strcpy (Memc[output], Memc[input2], SZ_LINE) + + if (imtlen (outlist) > 1) { + list1 = imtopen (Memc[input1]) + list2 = imtopen (Memc[input2]) + } else { + list1 = inlist1 + list2 = inlist2 + } + + switch (format) { + case 1: + if (imtgetim (outlist, Memc[output], SZ_LINE) == EOF) + call strcpy (Memc[input1], Memc[output], SZ_LINE) + call imgimage (Memc[output], Memc[output], SZ_LINE) + call sa_ms (list1, list2, Memc[output], op, Memc[opstr], + w1, w2, rebin, aps, bands, beams, complement, apmod, + offset, reverse, ignoreaps, clobber, merge, renumber, + verbose) + case 2: + call sa_getim (outlist, Memc[input1], Memc[output], SZ_LINE) + call imgimage (Memc[output], Memc[output], SZ_LINE) + call sa_1d (list1, list2, Memc[output], op, Memc[opstr], + w1, w2, rebin, aps, bands, beams, complement, apmod, + offset, reverse, ignoreaps, clobber, renumber, verbose) + } + + if (list1 != inlist1) { + call imtclose (list1) + call imtclose (list2) + } + } + + call rng_close (aps) + call rng_close (bands) + call rng_close (beams) + call imtclose (inlist1) + call imtclose (inlist2) + call imtclose (outlist) + call sfree (sp) +end + + +# SA_MS -- Operate on input list to multispec output + +procedure sa_ms (list1, list2, output, op, opstr, w1, w2, rebin, + aps, bands, beams, complement, apmod, offset, reverse, ignoreaps, + clobber, merge, renumber, verbose) + +int list1 # Input image list +int list2 # Input image list +char output[ARB] # Output image +int op # Operation +char opstr[ARB] # Operation string +double w1 # Starting wavelength +double w2 # Ending wavelength +bool rebin # Rebin wavelength region? +pointer aps # Apertures/columns/lines +pointer bands # Bands +pointer beams # Beams +bool complement # Complement aperture/beam selection +int apmod # Aperture modulus +int offset # Offset to add to output aperture numbers +bool reverse # Reverse order of operands +bool ignoreaps # Ignore apertures? +bool clobber # Clobber existing image? +bool merge # Merge with existing image? +bool renumber # Renumber apertures? +bool verbose # Verbose output? + +bool select, same +real aplow[2], aphigh[2] +double l1, dl, a, b, w, wb, dw, z, p1, p2, p3 +int i, j, k, l, nin +int ap, beam, dtype, nw, err +int ninaps, noutaps, naps, npts, nbands, mwoutdim +int last, op1, axis[3] +pointer ptr, in1, in2, out, outtmp, mwtmp, mwin1, mwin2, mwout +pointer sh1, sh2, shout, const, coeff, inaps, outaps +pointer sp, str, str1, key, input1, input2, temp, ltm1, ltv1, ltm2, ltv2 + +double shdr_lw() +int imaccess(), ctod() +int imtlen(), imtgetim(), imgnfn() +bool strne(), rng_elementi(), fp_equald() +pointer immap() , imgl3r(), impl3r(), imofnlu() +pointer smw_openim(), mw_open() +errchk immap, smw_openim, mw_open, imunmap, imgstr, imdelete +errchk imgl3r, impl3r +errchk shdr_open, sa_sextract +data axis/1,2,3/ + +begin + call smark (sp) + call salloc (str, SZ_LINE, TY_CHAR) + call salloc (str1, SZ_LINE, TY_CHAR) + call salloc (key, SZ_LINE, TY_CHAR) + call salloc (input1, SZ_FNAME, TY_CHAR) + call salloc (input2, SZ_FNAME, TY_CHAR) + call salloc (temp, SZ_FNAME, TY_CHAR) + call salloc (ltm1, 3*3, TY_DOUBLE) + call salloc (ltv1, 3, TY_DOUBLE) + call salloc (ltm2, 3*3, TY_DOUBLE) + call salloc (ltv2, 3, TY_DOUBLE) + call malloc (coeff, 1, TY_CHAR) + const = NULL + + # Initialize. + Memc[input2] = EOS + in1 = NULL; in2 = NULL; out = NULL; outtmp=NULL; mwtmp = NULL + mwin1 = NULL; mwin2 = NULL; mwout = NULL + sh1 = NULL; sh2 = NULL; shout = NULL + ninaps = 0; noutaps = 0; nbands = 0 + l1 = 1.; dl = 1. + err = NO + + iferr { + # Check for existing output image and abort if clobber is not set. + if (imaccess (output, READ_ONLY) == YES) { + if (!clobber) { + call sprintf (Memc[str], SZ_LINE, + "Output spectrum %s already exists") + call pargstr (output) + call error (1, Memc[str]) + } else if (merge) { + # Open the output and check the type. + ptr = immap (output, READ_ONLY, 0); out = ptr + ptr = smw_openim (out); mwout = ptr + if (SMW_FORMAT(mwout) == SMW_ND) { + call sprintf (Memc[str], SZ_LINE, "%s - Wrong format") + call pargstr (output) + call error (1, Memc[str]) + } + + # Determine existing apertures and renumber them if needed + noutaps = SMW_NSPEC(mwout) + nbands = SMW_NBANDS(mwout) + call salloc (outaps, noutaps, TY_INT) + do i = 1, noutaps { + call shdr_open (out, mwout, i, 1, INDEFI, SHHDR, sh2) + if (renumber) + Memi[outaps+i-1] = i + offset + else + Memi[outaps+i-1] = AP(sh2) + } + } + call mktemp ("temp", Memc[temp], SZ_FNAME) + } else + call strcpy (output, Memc[temp], SZ_FNAME) + + # Open input list. Determine the number of final output apertures + # and maximum length in order to set the output dimensions. Check + # also that there is data to copy. + + call imtrew (list1) + nin = imtlen (list1) + npts = 0 + naps = noutaps + while (imtgetim (list1, Memc[input1], SZ_FNAME) != EOF) { + iferr { + in1 = NULL + mwin1 = NULL + + ptr = immap (Memc[input1], READ_ONLY, 0); in1 = ptr + ptr = smw_openim (in1); mwin1 = ptr + + j = 1 + if (SMW_FORMAT(mwin1) != SMW_ND) { + j = 0 + do i = 1, SMW_NBANDS(mwin1) { + select = rng_elementi (bands, i) + if (!select) + next + j = j + 1 + } + if (j == 0) + call error (1, "No bands selected in image") + } + nbands = max (j, nbands) + + do i = 1, SMW_NSPEC(mwin1) { + call shdr_open (in1, mwin1, i, 1, INDEFI, SHHDR, sh1) + ap = AP(sh1) + if (SMW_FORMAT(mwin1) == SMW_ND) { + call smw_mw (mwin1, i, 1, ptr, j, k) + select = rng_elementi (aps, j) && rng_elementi (bands, k) + } else { + j = ap + if (apmod > 1) + j = mod (j, apmod) + select = rng_elementi (aps, j) + } + + select = select && rng_elementi (beams, BEAM(sh1)) + if ((complement && select) || (!complement && !select)) + next + if (renumber) + ap = naps + 1 + ap = ap + offset + for (j=0; j<noutaps && Memi[outaps+j]!=ap; j=j+1) + ; + if (j == noutaps) + naps = naps + 1 + if (ninaps == 0) + call malloc (inaps, 10, TY_INT) + else if (mod (ninaps, 10) == 0) + call realloc (inaps, ninaps+10, TY_INT) + Memi[inaps+ninaps] = ap + + call sa_sextract (sh1, w1, w2, rebin, dtype, w, dw, nw) + if (ninaps == 0) { + l1 = w + dl = dw + same = true + } + if (same && !(fp_equald (w, l1) && fp_equald (dw, dl))) { + l1 = 1. + dl = 1. + same = false + } + + npts = max (npts, nw+NP1(sh1)-1) + ninaps = ninaps + 1 + if (Memc[input2] == EOS) + call strcpy (Memc[input1], Memc[input2], SZ_FNAME) + } + } then + call erract (EA_WARN) + + if (nin > 1) { + call shdr_close (sh1) + call smw_close (mwin1) + if (in1 != NULL) + call imunmap (in1) + } + } + + # Check the selected apertures. + if (ninaps == 0) + call error (1, "No spectra selected") + for (i=0; i<ninaps-1; i=i+1) { + for (j=i+1; j<ninaps; j=j+1) { + if (Memi[inaps+i] == Memi[inaps+j]) { + call error (1, + "Output spectra cannot have the same aperture number.\n\tUse renumber parameter.") + } + } + } + + # Set output image dimensions and WCS. The WCS preserves the + # dispersion axis physical coordinates but resets the aperture + # axis physical coordinates. + + if (out != NULL) { + ptr = immap (Memc[temp], NEW_COPY, out); outtmp = ptr + if (IM_PIXTYPE(outtmp) != TY_DOUBLE) + IM_PIXTYPE(outtmp) = TY_REAL + + IM_LEN(outtmp,1) = max (npts, IM_LEN(out,1)) + IM_LEN(outtmp,2) = naps + IM_LEN(outtmp,3) = max (nbands, IM_LEN(out,3)) + if (nbands > 1) + IM_NDIM(outtmp) = 3 + else if (naps > 1) + IM_NDIM(outtmp) = 2 + else + IM_NDIM(outtmp) = 1 + + l1 = 1. + dl = 1. + i = SMW_PDIM(MW(sh2)) + j = SMW_PAXIS(MW(sh2),1) + mwoutdim = IM_NDIM(outtmp) + + mwtmp = mw_open (NULL, mwoutdim) + call mw_newsystem (mwtmp, "equispec", mwoutdim) + call mw_swattrs (SMW_MW(mwout,0), 0, "sformat", "equispec") + call mw_swtype (mwtmp, axis, mwoutdim, "linear", "") + if (LABEL(sh2) != EOS) + call mw_swattrs (mwtmp, 1, "label", LABEL(sh2)) + if (UNITS(sh2) != EOS) + call mw_swattrs (mwtmp, 1, "units", UNITS(sh2)) + ifnoerr (call mw_gwattrs (SMW_MW(MW(sh2),0), SMW_PAXIS(MW(sh2),1), + "units_display", Memc[str], SZ_LINE)) + call mw_swattrs (mwtmp, 1, "units_display", Memc[str]) + + call mw_gltermd (SMW_MW(mwout,0), Memd[ltm1], Memd[ltv1], i) + call mw_gltermd (mwtmp, Memd[ltm2], Memd[ltv2], mwoutdim) + Memd[ltm2] = dl * Memd[ltm1+(i+1)*(j-1)] + Memd[ltv2] = (Memd[ltv1+(j-1)] - l1) / dl + 1 + call mw_sltermd (mwtmp, Memd[ltm2], Memd[ltv2], mwoutdim) + call smw_open (mwtmp, NULL, outtmp) + + do i = 1, noutaps { + call smw_gwattrs (mwout, i, 1, ap, beam, dtype, + w, dw, nw, z, aplow, aphigh, coeff) + call smw_swattrs (mwtmp, i, 1, Memi[outaps+i-1], beam, dtype, + w, dw, nw, z, aplow, aphigh, Memc[coeff]) + } + + do j = 1, IM_LEN(out,3) { + do i = 1, IM_LEN(out,2) { + ptr = impl3r (outtmp, i, j) + call aclrr (Memr[ptr], IM_LEN(outtmp,1)) + call amovr (Memr[imgl3r(out,i,j)], Memr[ptr], IM_LEN(out,1)) + if (verbose) { + call shdr_open (out, mwout, i, j, INDEFI, SHHDR, sh2) + call shdr_open (outtmp, mwtmp, i, j, INDEFI, + SHHDR, shout) + if (AP(sh2) != AP(shout)) + call sa_verbose (sh2, NULL, shout, output, + COPY, "copy", const, reverse) + } + } + } + do j = 1, IM_LEN(out,3) + do i = IM_LEN(out,2)+1, IM_LEN(outtmp,2) { + ptr = impl3r (outtmp, i, j) + call aclrr (Memr[ptr], IM_LEN(outtmp,1)) + } + do j = IM_LEN(out,3)+1, nbands + do i = 1, IM_LEN(outtmp,2) { + ptr = impl3r (outtmp, i, j) + call aclrr (Memr[ptr], IM_LEN(outtmp,1)) + } + + call shdr_close (shout) + call shdr_close (sh2) + call smw_close (mwout) + mwout = mwtmp + mwtmp = NULL + call imunmap (out) + out = outtmp + outtmp = NULL + + } else { + if (nin > 1) { + ptr = immap (Memc[input2], READ_ONLY, 0); in1 = ptr + ptr = smw_openim (in1); mwin1 = ptr + call shdr_open (in1, mwin1, i, 1, INDEFI, SHDATA, sh1) + } + ptr = immap (Memc[temp], NEW_COPY, in1); out = ptr + if (IM_PIXTYPE(out) != TY_DOUBLE) + IM_PIXTYPE(out) = TY_REAL + ifnoerr (call imgstr (out, "MSTITLE", Memc[str], SZ_LINE)) { + call strcpy (Memc[str], IM_TITLE(out), SZ_IMTITLE) + call imdelf (out, "MSTITLE") + } + + # Set header + IM_LEN(out,1) = npts + IM_LEN(out,2) = naps + IM_LEN(out,3) = nbands + if (nbands > 1) + IM_NDIM(out) = 3 + else if (naps > 1) + IM_NDIM(out) = 2 + else + IM_NDIM(out) = 1 + mwoutdim = IM_NDIM(out) + + j = imofnlu (out, "DISPAXIS,APID*,BANDID*") + while (imgnfn (j, Memc[key], SZ_LINE) != EOF) + call imdelf (out, Memc[key]) + call imcfnl (j) + + i = SMW_PDIM(MW(sh1)) + j = SMW_PAXIS(MW(sh1),1) + + ptr = mw_open (NULL, mwoutdim); mwout = ptr + call mw_newsystem (mwout, "equispec", mwoutdim) + call mw_swattrs (mwout, 0, "sformat", "equispec") + call mw_swtype (mwout, axis, mwoutdim, "linear", "") + if (LABEL(sh1) != EOS) + call mw_swattrs (mwout, 1, "label", LABEL(sh1)) + if (UNITS(sh1) != EOS) + call mw_swattrs (mwout, 1, "units", UNITS(sh1)) + ifnoerr (call mw_gwattrs (SMW_MW(MW(sh1),0), SMW_PAXIS(MW(sh1),1), + "units_display", Memc[str], SZ_LINE)) + call mw_swattrs (mwout, 1, "units_display", Memc[str]) + + call mw_gltermd (SMW_MW(mwin1,0), Memd[ltm1], Memd[ltv1], i) + call mw_gltermd (mwout, Memd[ltm2], Memd[ltv2], mwoutdim) + Memd[ltv2] = (Memd[ltv1+(j-1)] - l1) / dl + 1 + Memd[ltm2] = dl * Memd[ltm1+(i+1)*(j-1)] + call mw_sltermd (mwout, Memd[ltm2], Memd[ltv2], mwoutdim) + call smw_open (mwout, NULL, out) + + if (nin > 1) { + call shdr_close (sh1) + call smw_close (mwin1) + call imunmap (in1) + } + } + + # Now do the actual copy + last = noutaps + call imtrew (list1) + call imtrew (list2) + while (imtgetim (list1, Memc[input1], SZ_FNAME) != EOF) { + i = imtgetim (list2, Memc[input2], SZ_FNAME) + iferr { + if (nin > 1) { + in1 = NULL + mwin1 = NULL + + ptr = immap (Memc[input1], READ_ONLY, 0); in1 = ptr + ptr = smw_openim (in1); mwin1 = ptr + call shdr_open (in1, mwin1, 1, 1, INDEFI, SHHDR, sh1) + } + + # Check dispersion function compatibility + # Nonlinear functions can't be copied to different physical + # coordinate system though the linear dispersion can be + # adjusted. + + call mw_gltermd (SMW_MW(mwout,0), Memd[ltm2], Memd[ltv2], + mwoutdim) + a = Memd[ltv2] + b = Memd[ltm2] + if (DC(sh1) == DCFUNC && !rebin) { + i = SMW_PDIM(mwin1) + j = SMW_PAXIS(mwin1,1) + + call mw_gltermd (SMW_MW(mwin1,0), Memd[ltm1], Memd[ltv1], i) + Memd[ltv1] = (Memd[ltv1+(j-1)] - l1) / dl + 1 + Memd[ltm1] = dl * Memd[ltm1+(i+1)*(j-1)] + if (!fp_equald (a, Memd[ltv1]) || !fp_equald (b, Memd[ltm1])) { + call error (1, + "Physical basis for nonlinear dispersion functions don't match") + } + } + + # Check for second operand + if (op > SQRT) { + ifnoerr (ptr = immap (Memc[input2], READ_ONLY, 0)) { + in2 = ptr + sh2 = NULL + mwin2 = NULL + ptr = smw_openim (in2); mwin2 = ptr + call shdr_open (in2, mwin2, 1, 1, INDEFI, SHHDR, sh2) + } else { + const = NULL + i = 1 + if (ctod (Memc[input2], i, w) <= 0) + call error (1, "Error in second operand") + call malloc (const, IM_LEN(out,1), TY_REAL) + call amovkr (real (w), Memr[const], IM_LEN(out,1)) + } + } + + do i = 1, SMW_NSPEC(mwin1) { + call shdr_open (in1, mwin1, i, 1, INDEFI, SHHDR, sh1) + ap = AP(sh1) + if (SMW_FORMAT(mwin1) == SMW_ND) { + call smw_mw (mwin1, i, 1, ptr, j, k) + select = rng_elementi (aps, j) && rng_elementi (bands, k) + } else { + j = ap + if (apmod > 1) + j = mod (j, apmod) + select = rng_elementi (aps, j) + } + + select = select && rng_elementi (beams, BEAM(sh1)) + if ((complement && select) || (!complement && !select)) + next + if (renumber) + ap = last + 1 + ap = ap + offset + for (j=0; j<noutaps && Memi[outaps+j]!=ap; j=j+1) + ; + if (j < noutaps) + l = j + 1 + else { + l = last + 1 + last = l + } + + call shdr_open (in1, mwin1, i, 1, INDEFI, SHDATA, sh1) + call sa_sextract (sh1, w1, w2, rebin, dtype, w, dw, nw) + + # Copy and adjust dispersion info + call smw_gwattrs (mwin1, i, 1, AP(sh1), beam, + j, w, dw, nw, z, aplow, aphigh, coeff) + + w = shdr_lw (sh1, 1D0) + wb = shdr_lw (sh1, double (SN(sh1))) + if (rebin) + Memc[coeff] = EOS + + p1 = (NP1(sh1) - a) / b + p2 = (NP2(sh1) - a) / b + p3 = (IM_LEN(out,1) - a) / b + nw = nint (min (max (p1, p3), max (p1, p2))) + NP1(sh1) - 1 + + w = w * (1 + z) + wb = wb * (1 + z) + if (dtype == DCLOG) { + w = log10 (w) + wb = log10 (wb) + if (p1 != p2) + dw = (wb - w) / (p2 - p1) + w = w - (p1 - 1) * dw + wb = w + (nw - 1) * dw + w = 10.**w + wb = 10.**wb + dw = (wb - w) / (nw - 1) + } else { + if (p1 != p2) + dw = (wb - w) / (p2 - p1) + w = w - (p1 - 1) * dw + wb = w + (nw - 1) * dw + } + + call smw_swattrs (mwout, l, 1, ap, beam, dtype, + w, dw, nw, z, aplow, aphigh, Memc[coeff]) + + # Copy title + call smw_sapid (mwout, l, 1, TITLE(sh1)) + + # Copy the data + op1 = op + k = 0 + do j = 1, SMW_NBANDS(mwin1) { + if (SMW_FORMAT(mwin1) != SMW_ND) { + select = rng_elementi (bands, j) + if (!select) + next + } + k = k + 1 + if (j != 1) { + call shdr_open (in1, mwin1, i, j, INDEFI, SHDATA, sh1) + call sa_sextract (sh1, w1, w2, rebin, dtype, w, dw,nw) + } + + if (Memc[SID(sh1,1)] != EOS) { + call sprintf (Memc[key], SZ_LINE, "BANDID%d") + call pargi (k) + iferr (call imgstr (out, Memc[key], Memc[str], SZ_LINE)) + call imastr (out, Memc[key], Memc[SID(sh1,1)]) + else { + if (strne (Memc[SID(sh1,1)], Memc[str])) + call eprintf ( + "Warning: Input and output types (BANDID) differ\n") + } + } + + if (sh2 != NULL) { + if (ignoreaps) + call shdr_open (in2, mwin2, i, j, INDEFI, + SHDATA, sh2) + else { + call shdr_open (in2, mwin2, i, j, AP(sh1), + SHDATA, sh2) + if (AP(sh2) != AP(sh1)) + op1 = COPY + } + } + + # For now just copy noise band. + if (STYPE(sh1,1) == SHSIG) + op1 = COPY + + call sa_arith (op1, sh1, sh2, const, reverse, + Memr[SY(sh1)], Memr[impl3r(out,l,k)+NP1(sh1)-1],SN(sh1)) + + if (verbose) { + call shdr_open (out, mwout, l, k, INDEFI, SHHDR, shout) + call sa_verbose (sh1, sh2, shout, output, + op1, opstr, const, reverse) + call shdr_close (shout) + } + } + do j = k+1, IM_LEN(out,3) + call aclrr (Memr[impl3r(out,l,j)], IM_LEN(out,1)) + } + } then + call erract (EA_WARN) + + call shdr_close (shout) + call shdr_close (sh1) + call shdr_close (sh2) + call mfree (const, TY_REAL) + call smw_close (mwin2) + call smw_close (mwin1) + if (in2 != NULL) + call imunmap (in2) + if (in1 != NULL) + call imunmap (in1) + } + } then { + err = YES + call erract (EA_WARN) + } + + # Finish up the output image. + if (mwout != NULL) { + call smw_saveim (mwout, out) + call smw_close (mwout) + } + if (outtmp != NULL) + call imunmap (outtmp) + call smw_close (mwtmp) + if (out != NULL) { + call imunmap (out) + if (strne (Memc[temp], output)) { + if (err == NO) { + call imdelete (output) + call imrename (Memc[temp], output) + } else { + iferr (call imdelete (Memc[temp])) + ; + } + } + } + + call mfree (inaps, TY_INT) + call mfree (coeff, TY_CHAR) + call sfree (sp) +end + + +# SA_1D -- Operate on input list to onedspec output. + +procedure sa_1d (list1, list2, output, op, opstr, w1, w2, rebin, + aps, bands, beams, complement, apmod, offset, reverse, ignoreaps, + clobber, renumber, verbose) + +int list1 # Input image list +int list2 # Input image list +char output[ARB] # Output image +int op # Operation +char opstr[ARB] # Operation string +double w1 # Starting wavelength +double w2 # Ending wavelength +bool rebin # Rebin wavelength region? +pointer aps # Apertures/columns/lines +pointer bands # Bands +pointer beams # Beams +bool complement # Complement aperture/beam selection +int apmod # Aperture modulus +int offset # Offset to add to output aperture numbers +bool reverse # Reverse order of operands +bool ignoreaps # Ignore apertures? +bool clobber # Clobber existing image? +bool renumber # Renumber apertures? +bool verbose # Verbose output? + +bool select +int i, j, k +int ap, band, beam, dtype, nw, naps, op1, err +double w, wb, dw, z, p1, p2, p3 +real aplow[2], aphigh[2] +pointer ptr, in1, in2, out, mwin1, mwin2, mwout, sh1, sh2, shout +pointer sp, str, key, input1, input2, output1, temp +pointer ltm1, ltv1, ltm2, ltv2, coeff, const + +double shdr_lw() +int imaccess(), ctod(), patmake(), patmatch() +int imtgetim(), imgnfn() +bool rng_elementi(), streq() +pointer immap(), impl1r(), imofnlu(), smw_openim(), mw_open() +errchk immap, smw_openim, mw_open, imunmap, impl1r, imdelete +errchk shdr_open, sa_sextract + +begin + call smark (sp) + call salloc (str, SZ_LINE, TY_CHAR) + call salloc (key, SZ_LINE, TY_CHAR) + call salloc (input1, SZ_FNAME, TY_CHAR) + call salloc (input2, SZ_FNAME, TY_CHAR) + call salloc (output1, SZ_FNAME, TY_CHAR) + call salloc (temp, SZ_FNAME, TY_CHAR) + call salloc (ltm1, 3*3, TY_DOUBLE) + call salloc (ltv1, 3, TY_DOUBLE) + call salloc (ltm2, 3*3, TY_DOUBLE) + call salloc (ltv2, 3, TY_DOUBLE) + call malloc (coeff, 1, TY_CHAR) + + # Loop through each spectrum in each input image. + call imtrew (list1) + call imtrew (list2) + sh1 = NULL; sh2 = NULL; shout = NULL + naps = 0 + while (imtgetim (list1, Memc[input1], SZ_FNAME) != EOF) { + i = imtgetim (list2, Memc[input2], SZ_FNAME) + + iferr { + in1 = NULL; in2 = NULL; mwin1 = NULL; mwin2 = NULL + ptr = immap (Memc[input1], READ_ONLY, 0); in1 = ptr + ptr = smw_openim (in1); mwin1 = ptr + + # Check for second operand + if (op > SQRT) { + ifnoerr (ptr = immap (Memc[input2], READ_ONLY, 0)) { + in2 = ptr + sh2 = NULL + mwin2 = NULL + ptr = smw_openim (in2); mwin2 = ptr + call shdr_open (in2, mwin2,1,1,INDEFI,SHHDR,sh2) + } else { + const = NULL + i = 1 + if (ctod (Memc[input2], i, w) <= 0) + call error (1, "Error in second operand") + call malloc (const, IM_LEN(in1,1), TY_REAL) + call amovkr (real (w), Memr[const], IM_LEN(in1,1)) + } + } + + do band = 1, SMW_NBANDS(mwin1) { + if (SMW_FORMAT(mwin1) != SMW_ND) { + select = rng_elementi (bands, band) + if (!select) + next + } + do i = 1, SMW_NSPEC(mwin1) { + call shdr_open (in1, mwin1, i, band, INDEFI, SHHDR, sh1) + + # Check aperture and beam numbers. + ap = AP(sh1) + if (SMW_FORMAT(mwin1) == SMW_ND) { + call smw_mw (mwin1, i, band, ptr, j, k) + select = rng_elementi (aps,j) && rng_elementi (bands,k) + } else { + j = ap + if (apmod > 1) + j = mod (j, apmod) + select = rng_elementi (aps, j) + } + + select = select && rng_elementi (beams, BEAM(sh1)) + if ((complement && select) || (!complement && !select)) + next + if (renumber) { + naps = naps + 1 + ap = naps + } + ap = ap + offset + + iferr { + out = NULL + mwout = NULL + err = NO + + # Open output spectrum + call strcpy (output, Memc[str], SZ_LINE) + j = patmake (".[0-9][0-9][0-9][0-9]$", Memc[key], + SZ_LINE) + j = patmatch (Memc[str], Memc[key]) + if (j > 0) + Memc[str+j-6] = EOS + if (SMW_FORMAT(mwin1) != SMW_ND) { + call sprintf (Memc[output1], SZ_FNAME, + "%s.%d%03d") + call pargstr (Memc[str]) + call pargi (PINDEX(sh1,2)-1) + call pargi (ap) + } else { + call sprintf (Memc[output1], SZ_FNAME, + "%s.%04d") + call pargstr (Memc[str]) + call pargi (ap) + } + if (imaccess (Memc[output1], READ_ONLY) == YES) { + if (clobber) + call mktemp ("temp", Memc[temp], SZ_FNAME) + else { + call sprintf (Memc[str], SZ_LINE, + "Output spectrum %s already exists") + call pargstr (output) + call error (1, Memc[str]) + } + } else + call strcpy (Memc[output1], Memc[temp], + SZ_FNAME) + + # Get data + call shdr_open (in1, mwin1, i, band, INDEFI, SHDATA, + sh1) + + # Set header + ptr = immap (Memc[temp], NEW_COPY, in1); out = ptr + if (IM_PIXTYPE(out) != TY_DOUBLE) + IM_PIXTYPE(out) = TY_REAL + IM_NDIM(out) = 1 + if (!streq (TITLE(sh1), IM_TITLE(out))) { + call imastr (out, "MSTITLE", IM_TITLE(out)) + call strcpy (TITLE(sh1), IM_TITLE(out), + SZ_IMTITLE) + } + j = imofnlu (out, "DISPAXIS,APID*,BANDID*") + while (imgnfn (j, Memc[key], SZ_LINE) != EOF) + call imdelf (out, Memc[key]) + call imcfnl (j) + + if (Memc[SID(sh1,1)] != EOS) + call imastr (out, "BANDID1", Memc[SID(sh1,1)]) + + # Set WCS + j = SMW_PDIM(MW(sh1)) + k = SMW_PAXIS(MW(sh1),1) + ptr = mw_open (NULL, 1); mwout = ptr + call mw_newsystem (mwout, "equispec", 1) + call mw_swattrs (mwout, 0, "sformat", "equispec") + call mw_swtype (mwout, 1, 1, "linear", "") + if (LABEL(sh1) != EOS) + call mw_swattrs (mwout, 1, "label", LABEL(sh1)) + if (UNITS(sh1) != EOS) + call mw_swattrs (mwout, 1, "units", UNITS(sh1)) + ifnoerr (call mw_gwattrs (SMW_MW(MW(sh1),0), + SMW_PAXIS(MW(sh1),1), "units_display", + Memc[str], SZ_LINE)) + call mw_swattrs (mwout, 1, "units_display", Memc[str]) + + call mw_gltermd (SMW_MW(mwin1,0), Memd[ltm1], + Memd[ltv1], j) + call mw_gltermd (mwout, Memd[ltm2], Memd[ltv2], 1) + Memd[ltv2] = Memd[ltv1+(k-1)] + Memd[ltm2] = Memd[ltm1+(j+1)*(k-1)] + call sa_sextract (sh1, w1, w2, rebin, dtype, w, dw, nw) + IM_LEN(out,1) = nw + NP1(sh1) - 1 + Memd[ltv2] = (Memd[ltv1] - w) / dw + 1 + Memd[ltm2] = dw * Memd[ltm1] + call mw_sltermd (mwout, Memd[ltm2], Memd[ltv2], 1) + call smw_open (mwout, NULL, out) + + # Copy and adjust dispersion info + call smw_gwattrs (mwin1, i, band, AP(sh1), + beam, j, w, dw, nw, z, aplow, aphigh, coeff) + w = shdr_lw (sh1, 1D0) + wb = shdr_lw (sh1, double(SN(sh1))) + if (rebin) + Memc[coeff] = EOS + + p1 = (NP1(sh1) - Memd[ltv2]) / Memd[ltm2] + p2 = (NP2(sh1) - Memd[ltv2]) / Memd[ltm2] + p3 = (IM_LEN(out,1) - Memd[ltv2]) / Memd[ltm2] + nw = nint (min (max (p1, p3), max (p1, p2))) + NP1(sh1) - 1 + + w = w * (1 + z) + wb = wb * (1 + z) + if (dtype == DCLOG) { + w = log10 (w) + wb = log10 (wb) + if (p1 != p2) + dw = (wb - w) / (p2 - p1) + w = w - (p1 - 1) * dw + wb = w + (nw - 1) * dw + w = 10.**w + wb = 10.**wb + dw = (wb - w) / (nw - 1) + } else { + if (p1 != p2) + dw = (wb - w) / (p2 - p1) + w = w - (p1 - 1) * dw + wb = w + (nw - 1) * dw + } + + call smw_swattrs (mwout, 1, 1, ap, beam, dtype, + w, dw, nw, z, aplow, aphigh, Memc[coeff]) + + # Copy data + op1 = op + if (sh2 != NULL) { + if (ignoreaps) + call shdr_open (in2, mwin2, i, band, INDEFI, + SHDATA, sh2) + else { + call shdr_open (in2, mwin2, i, band, AP(sh1), + SHDATA, sh2) + if (AP(sh2) != AP(sh1)) + op1 = COPY + } + } + + # For now just copy noise band. + if (STYPE(sh1,1) == SHSIG) + op1 = COPY + + call sa_arith (op1, sh1, sh2, const, reverse, + Memr[SY(sh1)], Memr[impl1r(out)+NP1(sh1)-1], SN(sh1)) + + + if (verbose) { + call shdr_open (out, mwout, 1, 1, INDEFI, SHHDR, shout) + call sa_verbose (sh1, sh2, shout, Memc[output1], + op1, opstr, const, reverse) + } + } then { + err = YES + call erract (EA_WARN) + } + + call shdr_close (shout) + if (mwout != NULL) { + if (err == NO) + call smw_saveim (mwout, out) + call smw_close (mwout) + } + if (out != NULL) { + call imunmap (out) + if (!streq (Memc[output1], Memc[temp])) { + if (err == NO) { + call imgimage (Memc[input1], Memc[str], SZ_LINE) + if (streq (Memc[output1], Memc[str])) + call imunmap (in1) + call imgimage (Memc[input2], Memc[str], SZ_LINE) + if (streq (Memc[output1], Memc[str])) + call imunmap (in2) + call imdelete (Memc[output1]) + call imrename (Memc[temp], Memc[output1]) + } else + call imdelete (Memc[temp]) + } else if (err == YES) + call imdelete (Memc[output1]) + } + } + } + } then + call erract (EA_WARN) + + call shdr_close (sh2) + call shdr_close (sh1) + call smw_close (mwin1) + call smw_close (mwin2) + if (in2 != NULL) + call imunmap (in2) + if (in1 != NULL) + call imunmap (in1) + } + + call mfree (coeff, TY_CHAR) + call sfree (sp) +end + + +# SA_ARITH -- Do arithmetic operation + +procedure sa_arith (op, sh, sh2, const, reverse, in, out, n) + +int op # Operation +pointer sh # Input SHDR pointer +pointer sh2 # Second operand spectrum (NULL if none) +pointer const # Second operand constant (NULL if none) +bool reverse # Reverse order of operands +real in[n] # Input data +real out[n] # Output data +int n # Number of data points + +int i +pointer buf +real sa_errfcn() +extern sa_errfcn() + +begin + if (op > SQRT) { + if (sh2 != NULL) { + call shdr_rebin (sh2, sh) + buf = SY(sh2) + } else + buf = const + } + + switch (op) { + case ABS: + call aabsr (in, out, n) + case COPY: + call amovr (in, out, n) + case DEX: + do i = 1, n + out[i] = 10. ** in[i] + case EXP: + do i = 1, n + out[i] = exp (in[i]) + case FLAM: + buf = SX(sh) + do i = 1, n { + out[i] = in[i] / (Memr[buf] ** 2 / 2.997925e18) + buf = buf + 1 + } + case FNU: + buf = SX(sh) + do i = 1, n { + out[i] = in[i] * (Memr[buf] ** 2 / 2.997925e18) + buf = buf + 1 + } + case INV: + call arczr (1., in, out, n, sa_errfcn) + case LN: + call allnr (in, out, n, sa_errfcn) + case LOG: + call alogr (in, out, n, sa_errfcn) + case LUM: + do i = 1, n + out[i] = 10. ** (-0.4 * in[i]) + case MAG: + do i = 1, n { + if (in[i] <= 0.) + out[i] = sa_errfcn (0.) + else + out[i] = -2.5 * log10 (in[i]) + } + case SQRT: + call asqrr (in, out, n, sa_errfcn) + + case REP: + call amovr (Memr[buf], out, n) + case ADD: + call aaddr (in, Memr[buf], out, n) + case SUB: + if (reverse) + call asubr (Memr[buf], in, out, n) + else + call asubr (in, Memr[buf], out, n) + case MUL: + call amulr (in, Memr[buf], out, n) + case DIV: + if (reverse) + call advzr (Memr[buf], in, out, n, sa_errfcn) + else + call advzr (in, Memr[buf], out, n, sa_errfcn) + case POW: + if (reverse) { + do i = 1, n + out[i] = Memr[buf+i-1] ** in[i] + } else { + do i = 1, n + out[i] = in[i] ** Memr[buf+i-1] + } + } +end + + +# SA_ERRFCN -- SARITH Error Function + +real procedure sa_errfcn (x) + +real x, errval +common /sarith/ errval + +begin + return (errval) +end + + +# SA_VERBOSE -- Print verbose output. + +procedure sa_verbose1 (input1, input2, output, ap1, ap2, apout, op, opstr, + const, reverse) + +char input1[ARB], input2[ARB] # Input spectra +char output[ARB] # Output spectrum +int ap1, ap2 # Input apertures +int apout # Output apertures +int op # Opcode +char opstr[ARB] # Operation string +pointer const # Pointer to constant if used +bool reverse # Reverse operands? + +begin + if (op <= SQRT) { + if (op == COPY) { + call printf ("%s[%d] --> %s") + call pargstr (input1) + call pargi (ap1) + call pargstr (output) + call pargi (apout) + } else { + call printf ("%s[%d] -- %s --> %s") + call pargstr (input1) + call pargi (ap1) + call pargstr (opstr) + call pargstr (output) + call pargi (apout) + } + } else if (const == NULL) { + call printf ("%s[%d] %s %s[%d] --> %s") + if (reverse) { + call pargstr (input2) + call pargi (ap2) + call pargstr (opstr) + call pargstr (input1) + call pargi (ap1) + } else { + call pargstr (input1) + call pargi (ap1) + call pargstr (opstr) + call pargstr (input2) + call pargi (ap2) + } + call pargstr (output) + call pargi (apout) + } else { + if (reverse) { + call printf ("%g %s %s[%d] --> %s") + call pargr (Memr[const]) + call pargstr (opstr) + call pargstr (input1) + call pargi (ap1) + } else { + call printf ("%s[%d] %s %g --> %s") + call pargstr (input1) + call pargi (ap1) + call pargstr (opstr) + call pargr (Memr[const]) + } + } + call pargstr (output) + if (!IS_INDEFI(apout)) { + call printf ("[%d]") + call pargi (apout) + } + call printf ("\n") + call flush (STDOUT) +end + + +# SA_VERBOSE -- Print verbose output. + +procedure sa_verbose (sh1, sh2, shout, output, op, opstr, const, reverse) + +pointer sh1, sh2 # Input spectra +pointer shout # Output spectrum +char output[ARB] # Output image name +int op # Opcode +char opstr[ARB] # Operation string +pointer const # Pointer to constant if used +bool reverse # Reverse operands? + +begin + if (op <= SQRT) { + if (op == COPY) { + call printf ("%s%s(%d) --> %s%s(%d)") + call pargstr (IMNAME(sh1)) + call pargstr (IMSEC(sh1)) + call pargi (AP(sh1)) + } else { + call printf ("%s%s(%d) -- %s --> %s%s(%d)") + call pargstr (IMNAME(sh1)) + call pargstr (IMSEC(sh1)) + call pargi (AP(sh1)) + call pargstr (opstr) + } + } else if (const == NULL) { + call printf ("%s%s(%d) %s %s%s(%d) --> %s%s(%d)") + if (reverse) { + call pargstr (IMNAME(sh2)) + call pargstr (IMSEC(sh2)) + call pargi (AP(sh2)) + call pargstr (opstr) + call pargstr (IMNAME(sh1)) + call pargstr (IMSEC(sh1)) + call pargi (AP(sh1)) + } else { + call pargstr (IMNAME(sh1)) + call pargstr (IMSEC(sh1)) + call pargi (AP(sh1)) + call pargstr (opstr) + call pargstr (IMNAME(sh2)) + call pargstr (IMSEC(sh2)) + call pargi (AP(sh2)) + } + } else { + if (reverse) { + call printf ("%g %s %s%s(%d) --> %s%s(%d)") + call pargr (Memr[const]) + call pargstr (opstr) + call pargstr (IMNAME(sh1)) + call pargstr (IMSEC(sh1)) + call pargi (AP(sh1)) + } else { + call printf ("%s%s(%d) %s %g --> %s%s(%d)") + call pargstr (IMNAME(sh1)) + call pargstr (IMSEC(sh1)) + call pargi (AP(sh1)) + call pargstr (opstr) + call pargr (Memr[const]) + } + } + call pargstr (output) + call pargstr (IMSEC(shout)) + call pargi (AP(shout)) + call printf ("\n") + call flush (STDOUT) +end + + +# SA_GETIM -- Get image from a list with the image kernal extension removed. + +procedure sa_getim (list, defname, image, maxchar) + +int list # Image list +char defname[ARB] # Default image name +char image[maxchar] # Image name +int maxchar # Image name maximum character length + +int i, stat, imtgetim(), strmatch() +pointer sp, str, section + +begin + call smark (sp) + call salloc (str, maxchar, TY_CHAR) + call salloc (section, SZ_FNAME, TY_CHAR) + + stat = imtgetim (list, Memc[str], maxchar) + if (stat == EOF) + call strcpy (defname, Memc[str], maxchar) + + call imgsection (Memc[str], Memc[section], SZ_FNAME) + call imgimage (Memc[str], image, maxchar) + i = strmatch (image, ".??h$") + if (i > 0) + image[i-4] = EOS + call strcat (Memc[section], image, maxchar) + + call sfree (sp) +end + + +# SA_SEXTRACT -- Extract a specific wavelength region + +procedure sa_sextract (sh, w1, w2, rebin, dtype, l1, dl, n) + +pointer sh #U SHDR structure +double w1 #I Starting wavelength +double w2 #I Ending wavelength +bool rebin #I Rebin wavelength region? +int dtype #O Dispersion type +double l1 #O Starting logical pixel +double dl #O Logical pixel increment +int n #O Number of logical pixels + +int i1, i2 +double a, b +bool fp_equald() +double shdr_lw(), shdr_wl() +errchk shdr_wl, shdr_linear, shdr_extract + +begin + if (IS_INDEFD(w1) && IS_INDEFD(w2)) { + l1 = 1. + dl = 1. + n = SN(sh) + dtype = DC(sh) + return + } + + a = w1 + b = w2 + if (IS_INDEFD(a)) + a = shdr_lw (sh, 1.0D0) + if (IS_INDEFD(b)) + b = shdr_lw (sh, double (SN(sh))) + + l1 = shdr_wl (sh, a) + dl = shdr_wl (sh, b) + if (fp_equald(l1,dl) || max(l1,dl) < 1. || min (l1,dl) > SN(sh)) + call error (1, "No pixels to extract") + l1 = max (1D0, min (double (SN(sh)), l1)) + dl = max (1D0, min (double (SN(sh)), dl)) + i1 = nint (l1) + i2 = nint (dl) + n = abs (i2 - i1) + 1 + if (!rebin) { + l1 = i1 + dl = i2 + } + if (n == 1) + dl = 1 + else + dl = (dl - l1) / (n - 1) + + if (SY(sh) != NULL) + call shdr_extract (sh, real(a), real(b), rebin) + dtype = DC(sh) +end |