int ifft2d (CmplxArray *z) { /* argument: CmplxArray *z io: complex array */ CmplxArray scr; /* scratch space for FT of columns */ int i, j; /* loop indexes */ int nx, ny; /* image size */ int status; nx = z->nx; ny = z->ny; /* Allocate a 1-D array for a column. */ InitCmplxArray (&scr); if ((status = AllocCmplxArray (&scr, ny, 1))) return (status); for (j = 0; j < ny; j++) /* transform each line */ CFFTB (&nx, &(RPIX2D(z,0,j)), z->workx); for (i = 0; i < nx; i++) { /* transform each column */ for (j = 0; j < ny; j++) { RPIX1D (&scr, j) = RPIX2D (z, i, j); IPIX1D (&scr, j) = IPIX2D (z, i, j); } CFFTB (&scr.nx, scr.data, scr.workx); for (j = 0; j < ny; j++) { RPIX2D (z, i, j) = RPIX1D (&scr, j) / (nx * ny); IPIX2D (z, i, j) = IPIX1D (&scr, j) / (nx * ny); } } FreeCmplxArray (&scr); return (0); }
static int MakeFT (Image *iso, Image *psf, ScatterFunctions *scf, CmplxArray *ft, CmplxArray *fto) { /* arguments Image *iso; i: isotropic halo function (1024 x 1024) Image *psf; i: telescope PSF for the aperture (normalized) ScatterFunctions *scf; i: scattering functions CmplxArray *ft; o: FT CmplxArray *fto; o: object (central 11 X 11) FT */ CmplxArray ziso, zpsf; float *hold; int i, j, k, i1, i2, j1, j2, ki, kj, kk; int ki1, ki2, kj1, kj2; int status, wsize; int FFTConvolve (CmplxArray *, CmplxArray *); /* Initialize complex arrays. */ InitCmplxArray (&ziso); InitCmplxArray (&zpsf); /* Copy real into complex arrays. PSF must be copied into larger array so its size matches the halo array size. */ if ((status = AllocCmplxArray (&ziso, iso->nx, iso->ny))) return (status); for (j = 1; j < iso->ny - 1; j++) { for (i = 1; i < iso->nx - 1; i++) RPIX2D (&ziso, i, j) = PPIX (iso, i-1, j-1); } if ((status = AllocCmplxArray (&zpsf, iso->nx, iso->ny))) return (status); /* The following code only works when both axis are simultaneously either even or odd-sized. Half-pixel shifting uses linear interp. (Is that comment correct?) */ if (psf->nx <= iso->nx) { /* this is the normal case */ i1 = (iso->nx - psf->nx) / 2; i2 = i1 + psf->nx; ki1 = 0; ki2 = psf->nx; } else { i1 = 0; i2 = iso->nx; ki1 = (psf->nx - iso->nx) / 2; ki2 = ki1 + iso->nx; } if (psf->ny <= iso->ny) { /* this is the normal case, i.e. a small slit */ j1 = (iso->ny - psf->ny) / 2; j2 = j1 + psf->ny; kj1 = 0; kj2 = psf->ny; } else { /* long slit, greater than about 29 arcsec */ j1 = 0; j2 = iso->ny; kj1 = (psf->ny - iso->ny) / 2; kj2 = kj1 + iso->ny; } /* xxx ... if ((i1 % 2) == 0) { ... xxx */ /* copy psf into zpsf */ for (j = j1, kj = kj1; j < j2 && kj < kj2; j++, kj++) { for (i = i1, ki = ki1; i < i2 && ki < ki2; i++, ki++) RPIX2D (&zpsf, i, j) = PPIX (psf, ki, kj); } /* xxx ... } else { for (j = j1, kj = 1; j < j2 - 1; j++, kj++) { for (i = i1, ki = 1; i < i2 - 1; i++, ki++) { RPIX2D (&zpsf, i, j) = (PPIX (psf, ki, kj) + PPIX (psf, ki-1, kj) + PPIX (psf, ki, kj-1) + PPIX (psf, ki-1, kj-1)) / 4.0; } } } ... xxx */ /* Convolve halo with telescope PSF. */ if ((status = FFTConvolve (&zpsf, &ziso))) return (status); /* Now convolve column-by-column with x-disp scattering function. */ for (i = 0; i < iso->nx; i++) { hold = (float *) calloc (iso->ny, sizeof (float)); if (hold == NULL) return (OUT_OF_MEMORY); for (j = 0; j < iso->ny; j++) { kk = j - scf->nxdisp / 2; for (k = 0; k <scf->nxdisp; k++, kk++) { kk = (kk < 0) ? 0 : kk; kk = (kk >= iso->ny) ? iso->ny - 1 : kk; hold[j] += RPIX2D (&zpsf, i, kk) * scf->xdisp[k]; } } for (j = 0; j < iso->ny; j++) RPIX2D (&zpsf, i, j) = hold[j]; free (hold); } /* Insert array into twice as large array and compute FT. No need to normalize ! */ if ((status = AllocCmplxArray (ft, 2 * iso->nx, 2 * iso->ny))) return (status); /* Only works when both are even-sized. */ i1 = iso->nx / 2; j1 = iso->ny / 2; i2 = i1 + iso->nx; j2 = j1 + iso->ny; for (j = j1, kj = 0; j < j2; j++, kj++) { for (i = i1, ki = 0; i < i2; i++, ki++) RPIX2D (ft, i, j) = RPIX2D (&zpsf, ki, kj); } if ((status = fft2d (ft))) return (status); /* Now build "object" FT (central 11 X 11 portion). No need to normalize ! */ if ((status = AllocCmplxArray (fto, 2 * iso->nx, 2 * iso->ny))) return (status); wsize = 6; i1 = iso->nx - wsize; j1 = iso->ny - wsize; i2 = iso->nx + wsize; j2 = iso->ny + wsize; for (j = j1, kj = iso->ny / 2 - wsize; j <= j2; j++, kj++) { for (i = i1, ki = iso->nx / 2 - wsize; i <= i2; i++, ki++) RPIX2D (fto, i, j) = RPIX2D (&zpsf, ki, kj); } if ((status = fft2d (fto))) return (status); FreeCmplxArray (&ziso); FreeCmplxArray (&zpsf); return (STIS_OK); }
int EchScatRead (Hdr *phdr, double xsize, double ysize, ScatterFunctions *scf, int verbose) { /* arguments Hdr *phdr i: primary header double xsize, ysize; i: aperture size in arcsec ScatterFunctions *scf; o: data structure with scattering functions int verbose; i: verbosity flag */ char fname[STIS_LINE]; /* file names */ Image halo1; /* halo images */ Image halo2; Image halo3; Image psf1; /* psf images */ Image psf2; Image psf3; int no_default = 0; /* missing keyword is fatal error */ int status; void InitImage (Image *); void FreeImage (Image *); InitImage (&halo1); InitImage (&halo2); InitImage (&halo3); InitImage (&psf1); InitImage (&psf2); InitImage (&psf3); /* Get scattering functions. */ if ((status = Get_KeyS (phdr, "ECHSCTAB", no_default, "", fname, STIS_LINE))) { printf ( "WARNING The input file *might* not have the required keywords\n"); printf ( " to run the scattered light correction algorithm.\n"); fflush (stdout); return (status); } if (verbose) { printf ("Reading ECHSCTAB: %s\n", fname); fflush (stdout); } if ((status = GetScatter (fname, scf))) return (status); /* Get echelle x-disp spread function. */ if ((status = Get_KeyS (phdr, "EXSTAB", no_default, "", fname, STIS_LINE))) return (status); if (verbose) { printf ("Reading EXSTAB: %s\n", fname); fflush (stdout); } if ((status = GetEchelleScatter (fname, scf))) return (status); /* Get x-disp function. */ if ((status = Get_KeyS (phdr, "CDSTAB", no_default, "", fname, STIS_LINE))) return (status); if (verbose) { printf ("Reading CDSTAB: %s\n", fname); fflush (stdout); } if ((status = GetXDisp (fname, scf))) return (status); /* Get echelle ripple functions. */ if ((status = Get_KeyS (phdr, "RIPTAB", no_default, "", fname, STIS_LINE))) return (status); if (verbose) { printf ("Reading RIPTAB: %s\n", fname); fflush (stdout); } if ((status = GetRipple (phdr, fname, scf))) return (status); /* Get wavelengths of halo and telescope PSF images. */ if ((status = Get_KeyS (phdr, "SRWTAB", no_default, "", fname, STIS_LINE))) return (status); if (verbose) { printf ("Reading SRWTAB: %s\n", fname); fflush (stdout); } if ((status = GetRefWave (phdr, fname, scf))) return (status); /* Get halo and telescope psf images, and build FTs */ if ((status = Get_KeyS (phdr, "HALOTAB", no_default, "", fname, STIS_LINE))) return (status); if (verbose) { printf ("Reading HALOTAB: %s\n", fname); fflush (stdout); } if ((status = GetHalo (fname, scf, &halo1, &halo2, &halo3))) return (status); if ((status = Get_KeyS (phdr, "TELTAB", no_default, "", fname, STIS_LINE))) return (status); if (verbose) { printf ("Reading TELTAB: %s\n", fname); fflush (stdout); } if ((status = GetPSF (fname, phdr, xsize, ysize, scf, &psf1, &psf2, &psf3))) return (status); InitCmplxArray (&(scf->ft1)); InitCmplxArray (&(scf->ft2)); InitCmplxArray (&(scf->ft3)); InitCmplxArray (&(scf->fto1)); InitCmplxArray (&(scf->fto2)); InitCmplxArray (&(scf->fto3)); if (verbose) { printf ( "Computing Fourier Transforms of kernel at wavelength %g\n", scf->kernw[0]); fflush (stdout); } if ((status = MakeFT (&halo1, &psf1, scf, &(scf->ft1), &(scf->fto1)))) return (status); if (scf->nwave > 1) { if (verbose) { printf ( "Computing Fourier Transforms of kernel at wavelength %g\n", scf->kernw[1]); fflush (stdout); } if ((status = MakeFT (&halo2, &psf2, scf, &(scf->ft2), &(scf->fto2)))) return (status); } if (scf->nwave > 2) { if (verbose) { printf ( "Computing Fourier Transforms of kernel at wavelength %g\n", scf->kernw[2]); fflush (stdout); } if ((status = MakeFT (&halo3, &psf3, scf, &(scf->ft3), &(scf->fto3)))) return (status); } FreeImage (&halo1); FreeImage (&halo2); FreeImage (&halo3); FreeImage (&psf1); FreeImage (&psf2); FreeImage (&psf3); return (STIS_OK); }