# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. include include define MAX_IMAGES 4 define LP_TITLE "Linear polarization image" define LP_IMKEY "POL" # keyword prefix for input images define LP_PBAND 1 define LP_PKEY "POLAR" define LP_PSTR "Band 1 is the percent polarization" define LP_ABAND 2 define LP_AKEY "ANGLE" define LP_ASTR "Band 2 is the polarization angle" define LP_IBAND 3 define LP_IKEY "I-STOKES" define LP_ISTR "Band 3 is the Stokes I parameter" define LP_QBAND 4 define LP_QKEY "Q-STOKES" define LP_QSTR "Band 4 is the Stokes Q parameter" define LP_QSTRN "Band 4 is the normalized Stokes Q parameter" define LP_UBAND 5 define LP_UKEY "U-STOKES" define LP_USTR "Band 5 is the Stokes U parameter" define LP_USTRN "Band 5 is the normalized Stokes U parameter" # LINPOL -- Calculate the percent polarization and the polarization # angle images for the simplest linear polarization cases, 0-45-90 or # 0-45-90-135 polarizer positions. procedure t_linpol () pointer inlist, output, in[MAX_IMAGES], out, key, sp bool dflag, sflag, nflag int len int imtopenp(), imtlen() bool clgetb() errchk lp_map, lp_polarize begin call smark (sp) call salloc (output, SZ_FNAME, TY_CHAR) call salloc (key, SZ_FNAME, TY_CHAR) # get the input image template inlist = imtopenp ("input") len = imtlen (inlist) if (len != 3 && len != 4) { call imtclose (inlist) call sfree (sp) call error (1, "Must supply either three or four images.") } # get the output image stack name call clgstr ("output", Memc[output], SZ_FNAME) sflag = clgetb ("stokes") dflag = clgetb ("degrees") nflag = clgetb ("normalize") # keyword for polarizer angle - UPPERcase for neatness call clgstr ("keyword", Memc[key], SZ_FNAME) call strupr (Memc[key]) iferr { # pass the number of possible frames (4) explicitly in # hopes of later relaxing the 45 degree restriction call lp_map (inlist, in, MAX_IMAGES, Memc[key], Memc[output], out, sflag, nflag) call lp_polarize (in, MAX_IMAGES, out, dflag, sflag, nflag) } then { call lp_unmap (in, MAX_IMAGES, out) call imtclose (inlist) call sfree (sp) call erract (EA_ERROR) } call lp_unmap (in, MAX_IMAGES, out) call imtclose (inlist) call sfree (sp) end # LP_MAP -- map the set of input images. procedure lp_map (inlist, in, nin, key, output, out, sflag, nflag) pointer inlist #I input image template pointer in[nin] #O input image descriptor array int nin #I size of the array (4) char key[ARB] #I keyword for polarizer angle char output[ARB] #I output image name pointer out #O output image descriptor bool sflag #I include stokes frames in output? bool nflag #I normalize the stokes frames? pointer input, im_tmp, sp real pol int i, j, ipol, ndim long axis[IM_MAXDIM] bool firsttime int imtgetim() real imgetr() pointer immap() bool fp_equalr() errchk immap, imgetr, imdelf begin # for graceful error recovery im_tmp = NULL out = NULL do i = 1, nin in[i] = NULL call smark (sp) call salloc (input, SZ_FNAME, TY_CHAR) iferr { while (imtgetim (inlist, Memc[input], SZ_FNAME) != EOF) { im_tmp = immap (Memc[input], READ_ONLY, 0) if (IM_NDIM(im_tmp) > 2) call error (1, "only 1 or 2 dimensional images allowed") pol = imgetr (im_tmp, key) if (pol < 0 || pol > 135 || mod (nint(pol), 45) != 0 || ! fp_equalr (pol, real(nint(pol)))) { call eprintf ("image %s, %s must be 0,45,90,135 degrees\n") call pargstr (Memc[input]) call pargstr (key) call flush (STDERR) call error (1, "task LINPOL") } # index into in pointer array ipol = max (1, min (nin, 1 + int(pol) / 45)) if (in[ipol] == NULL) { in[ipol] = im_tmp im_tmp = NULL } else { call eprintf ("multiple images specified at %d degrees\n") call pargi ((ipol-1) * 45) call flush (STDERR) call error (1, "task JOIN") } } # check dimensionality firsttime = true do i = 1, nin { if (in[i] == NULL) next if (firsttime) { ndim = IM_NDIM(in[i]) do j = 1, IM_MAXDIM axis[j] = IM_LEN(in[i],j) firsttime = false next } if (IM_NDIM(in[i]) != ndim) call error (1, "images are different sizes") do j = 1, ndim if (IM_LEN(in[i],j) != axis[j]) call error (1, "images are different sizes") } # create the output polarization (hyper) cube # just copy header from first image available do i = 1, nin if (in[i] != NULL) { out = immap (output, NEW_COPY, in[i]) break } # increase the image's girth IM_NDIM(out) = ndim + 1 for (i=1; i <= ndim; i=i+1) IM_LEN(out,i) = axis[i] if (sflag) IM_LEN(out,i) = 5 else IM_LEN(out,i) = 2 call strcpy (LP_TITLE, IM_TITLE(out), SZ_IMTITLE) # delete the polarizer angle keyword call imdelf (out, key) # add keywords naming the input images do i = 1, nin { if (in[i] == NULL) next call sprintf (Memc[input], SZ_FNAME, "%s%d") call pargstr (LP_IMKEY) call pargi (45*(i-1)) call imastr (out, Memc[input], IM_HDRFILE(in[i])) } # add keywords to index output frames call imastr (out, LP_PKEY, LP_PSTR) call imastr (out, LP_AKEY, LP_ASTR) if (sflag) { call imastr (out, LP_IKEY, LP_ISTR) if (nflag) { call imastr (out, LP_QKEY, LP_QSTRN) call imastr (out, LP_UKEY, LP_USTRN) } else { call imastr (out, LP_QKEY, LP_QSTR) call imastr (out, LP_UKEY, LP_USTR) } } } then { if (im_tmp != NULL) call imunmap (im_tmp) call sfree (sp) call erract (EA_ERROR) } # start off with a clean slate call imflush (out) call sfree (sp) end # LP_UNMAP -- unmap the set of input images. procedure lp_unmap (in, nin, out) pointer in[nin] #U input image pointer array int nin #I size of the array (4) pointer out #U output image pointer int i begin do i = 1, nin if (in[i] != NULL) call imunmap (in[i]) if (out != NULL) call imunmap (out) end # LP_POLARIZE -- calculate the polarization given at least 3 of the 4 # possible frames taken with the polarizer at 45 degree increments. procedure lp_polarize (in, nin, out, dflag, sflag, nflag) pointer in[nin] #I input image pointer array int nin #I size of the array (4) pointer out #I output image pointer bool dflag #I report the angle in degrees? bool sflag #I include stokes frames in output? bool nflag #I normalize the stokes frames? pointer ibuf, qbuf, ubuf, sp pointer buf1, buf2, buf3, buf4 long v1[IM_MAXDIM], v2[IM_MAXDIM], v3[IM_MAXDIM], v4[IM_MAXDIM] int line, npix, skip, i int imgnlr() begin npix = IM_LEN(out,1) call smark (sp) call salloc (ibuf, npix, TY_REAL) call salloc (qbuf, npix, TY_REAL) call salloc (ubuf, npix, TY_REAL) call amovkl (long(1), v1, IM_MAXDIM) call amovkl (long(1), v2, IM_MAXDIM) call amovkl (long(1), v3, IM_MAXDIM) call amovkl (long(1), v4, IM_MAXDIM) # choose the combining scheme skip = 0 do i = 1, nin if (in[i] == NULL) { skip = i break } # not worth generalizing the method, just duplicate the code... switch (skip) { case 0: # I = (im0 + im45 + im90 + im135) / 4 # Q = (im0 - im90) / 2 # U = (im45 - im135) / 2 while (imgnlr (in[1], buf1, v1) != EOF && imgnlr (in[2], buf2, v2) != EOF && imgnlr (in[3], buf3, v3) != EOF && imgnlr (in[4], buf4, v4) != EOF) { call aaddr (Memr[buf1], Memr[buf2], Memr[ibuf], npix) call aaddr (Memr[buf3], Memr[ibuf], Memr[ibuf], npix) call aaddr (Memr[buf4], Memr[ibuf], Memr[ibuf], npix) call adivkr (Memr[ibuf], 4., Memr[ibuf], npix) call asubr (Memr[buf1], Memr[buf3], Memr[qbuf], npix) call adivkr (Memr[qbuf], 2., Memr[qbuf], npix) call asubr (Memr[buf2], Memr[buf4], Memr[ubuf], npix) call adivkr (Memr[ubuf], 2., Memr[ubuf], npix) line = int(v1[2]) - 1 call lp_stokes (Memr[ibuf], Memr[qbuf], Memr[ubuf], npix, out, line, dflag, sflag, nflag) } case 1: # I = (im45 + im135) / 2 # Q = I - im90 # U = (im45 - im135) / 2 while (imgnlr (in[2], buf2, v2) != EOF && imgnlr (in[3], buf3, v3) != EOF && imgnlr (in[4], buf4, v4) != EOF) { call aaddr (Memr[buf2], Memr[buf4], Memr[ibuf], npix) call adivkr (Memr[ibuf], 2., Memr[ibuf], npix) call asubr (Memr[ibuf], Memr[buf3], Memr[qbuf], npix) call asubr (Memr[buf2], Memr[buf4], Memr[ubuf], npix) call adivkr (Memr[ubuf], 2., Memr[ubuf], npix) line = int(v2[2]) - 1 call lp_stokes (Memr[ibuf], Memr[qbuf], Memr[ubuf], npix, out, line, dflag, sflag, nflag) } case 2: # I = (im0 + im90) / 2 # Q = (im0 - im90) / 2 # U = I - im135 while (imgnlr (in[1], buf1, v1) != EOF && imgnlr (in[3], buf3, v3) != EOF && imgnlr (in[4], buf4, v4) != EOF) { call aaddr (Memr[buf1], Memr[buf3], Memr[ibuf], npix) call adivkr (Memr[ibuf], 2., Memr[ibuf], npix) call asubr (Memr[buf1], Memr[buf3], Memr[qbuf], npix) call adivkr (Memr[qbuf], 2., Memr[qbuf], npix) call asubr (Memr[ibuf], Memr[buf4], Memr[ubuf], npix) line = int(v1[2]) - 1 call lp_stokes (Memr[ibuf], Memr[qbuf], Memr[ubuf], npix, out, line, dflag, sflag, nflag) } case 3: # I = (im45 + im135) / 2 # Q = im0 - I # U = (im45 - im135) / 2 while (imgnlr (in[1], buf1, v1) != EOF && imgnlr (in[2], buf2, v2) != EOF && imgnlr (in[4], buf4, v4) != EOF) { call aaddr (Memr[buf2], Memr[buf4], Memr[ibuf], npix) call adivkr (Memr[ibuf], 2., Memr[ibuf], npix) call asubr (Memr[buf1], Memr[ibuf], Memr[qbuf], npix) call asubr (Memr[buf2], Memr[buf4], Memr[ubuf], npix) call adivkr (Memr[ubuf], 2., Memr[ubuf], npix) line = int(v1[2]) - 1 call lp_stokes (Memr[ibuf], Memr[qbuf], Memr[ubuf], npix, out, line, dflag, sflag, nflag) } case 4: # I = (im0 + im90) / 2 # Q = (im0 - im90) / 2 # U = im45 - I while (imgnlr (in[1], buf1, v1) != EOF && imgnlr (in[2], buf2, v2) != EOF && imgnlr (in[3], buf3, v3) != EOF) { call aaddr (Memr[buf1], Memr[buf3], Memr[ibuf], npix) call adivkr (Memr[ibuf], 2., Memr[ibuf], npix) call asubr (Memr[buf1], Memr[buf3], Memr[qbuf], npix) call adivkr (Memr[qbuf], 2., Memr[qbuf], npix) call asubr (Memr[buf2], Memr[ibuf], Memr[ubuf], npix) line = int(v1[2]) - 1 call lp_stokes (Memr[ibuf], Memr[qbuf], Memr[ubuf], npix, out, line, dflag, sflag, nflag) } } call sfree(sp) end # LP_STOKES -- calculate the fractional polarization and angle for a # specific line (from the stokes parameters) and output the results. procedure lp_stokes (i, q, u, npix, out, line, dflag, sflag, nflag) real i[ARB] #I Stokes I vector real q[ARB] #I Stokes Q vector real u[ARB] #I Stokes U vector int npix #I length of the vectors pointer out #I output image descriptor int line #I line number bool dflag #I convert to degrees? bool sflag #I include stokes frames in output? bool nflag #I normalize the stokes frames? pointer pbuf, abuf, sp pointer impl3r() real lp_errfcn() extern lp_errfcn begin call smark (sp) call salloc (pbuf, npix, TY_REAL) call salloc (abuf, npix, TY_REAL) call lp_pol (i, q, u, Memr[pbuf], npix) call lp_ang (q, u, Memr[abuf], npix, dflag) call amovr (Memr[pbuf], Memr[impl3r (out, line, LP_PBAND)], npix) call amovr (Memr[abuf], Memr[impl3r (out, line, LP_ABAND)], npix) if (sflag) { call amovr (i, Memr[impl3r (out, line, LP_IBAND)], npix) if (nflag) { call advzr (q, i, q, npix, lp_errfcn) call advzr (u, i, u, npix, lp_errfcn) } call amovr (q, Memr[impl3r (out, line, LP_QBAND)], npix) call amovr (u, Memr[impl3r (out, line, LP_UBAND)], npix) } call sfree (sp) end # LP_POL -- calculate the fractional linear polarization for a vector, # given the stokes I, Q, and U vectors. procedure lp_pol (i, q, u, p, npix) real i[ARB] #I Stokes I vector real q[ARB] #I Stokes Q vector real u[ARB] #I Stokes U vector real p[ARB] #O fractional polarization vector int npix #I length of the vectors pointer tmp, sp real lp_errfcn() extern lp_errfcn begin call smark (sp) call salloc (tmp, npix, TY_REAL) call amulr (q, q, p, npix) call amulr (u, u, Memr[tmp], npix) call aaddr (p, Memr[tmp], p, npix) call asqrr (p, p, npix, lp_errfcn) call advzr (p, i, p, npix, lp_errfcn) call sfree (sp) end # LP_ERRFCN -- error function for the square root of negative numbers. real procedure lp_errfcn (x) real x begin return (0.) end # LP_ANG -- calculate the polarization angle, given the Stokes params. procedure lp_ang (q, u, a, npix, dflag) real q[ARB] #I Stokes Q vector real u[ARB] #I Stokes U vector real a[ARB] #O polarization angle vector int npix #I length of the vectors bool dflag #I convert to degrees? define PI 3.14159265358979 define RAD2DEG (180./PI) begin call lp_aatn2r (u, q, a, npix) call adivkr (a, 2., a, npix) if (dflag) call amulkr (a, RAD2DEG, a, npix) end # LP_AATN2R -- calculate the arctangent in the proper quadrant. procedure lp_aatn2r (y, x, a, npix) real y[ARB], x[ARB] #I numerator and denominator, respectively real a[ARB] #O arctangent vector (radians) int npix, i begin do i = 1, npix { a[i] = atan2 (y[i], x[i]) } end