Example #1
0
File: necorrJ.c Project: pa345/lib
/* interpolate Ne data near time t to latitude qdlat */
double
interp_ne(const time_t t, const double qdlat, const satdata_mag *data)
{
  double t_cdf = satdata_timet2epoch(t);
  double Ne;

  if (t_cdf >= data->t[0] && t_cdf <= data->t[data->n - 1])
    {
      int idx = (int) bsearch_double(data->t, t_cdf, 0, data->n - 1);
      int half_window = 15; /* number of minutes in half time window */
      int idx1 = GSL_MAX(0, idx - half_window*60*2);
      int idx2 = GSL_MIN(data->n - 1, idx + half_window*60*2);
      int qidx;
      
      if (data->qdlat[idx1] < data->qdlat[idx2])
        qidx = (int) bsearch_double(data->qdlat, qdlat, idx1, idx2);
      else
        qidx = (int) bsearch_desc_double(data->qdlat, qdlat, idx1, idx2);

      Ne = interp1d(data->qdlat[qidx], data->qdlat[qidx + 1],
                    data->ne[qidx], data->ne[qidx + 1], qdlat);
    }
  else
    Ne = 0.0;

  return Ne;
}
Example #2
0
static double tempFactor(TdsInfo *tds, double photplam, double temperature) {

/* arguments:
TdsInfo *tds         i: temperature-dependent sensitivity info
double photplam      i: pivot wavelength (Angstroms)
double temperature   i: detector temperature (degrees Celsius)
   function value:
factor                  divide photflam by this factor
*/

	double sensitivity, factor;
	int starti;
	/*int i;*/

	if (temperature >= 0.) {
	    starti = 0;
	    sensitivity = interp1d (photplam, tds->wl, tds->temp_sens,
				    tds->nwl, &starti);
	    factor = 1. + sensitivity * (temperature - tds->ref_temp);
	} else {
	    factor = 1.;
	}

	return factor;
}
Example #3
0
int
fill_dens(magdata *mdata, const satdata_lp *dens_data)
{
  int s = 0;
  size_t i;

  /* initialize ne array */
  for (i = 0; i < mdata->n; ++i)
    mdata->ne[i] = 0.0;

  for (i = 0; i < mdata->n; ++i)
    {
      double t = mdata->t[i];
      size_t idx;
      double dt, ne;
      double t0, t1;

      if (t < dens_data->t[0] || t > dens_data->t[dens_data->n - 1])
        continue;

      idx = bsearch_double(dens_data->t, t, 0, dens_data->n);

      t0 = dens_data->t[idx];
      t1 = dens_data->t[idx + 1];

      dt = t1 - t0;
      dt /= 1000.0; /* convert to s */

      /* check for data gaps in PLP measurements */
      if (fabs(dt) > 30.0)
        continue;

      ne = interp1d(t0, t1, dens_data->ne[idx], dens_data->ne[idx + 1], t);

      mdata->ne[i] = ne;
    }

  return s;
}
Example #4
0
static float QFactor(StisInfo6 *sts, double wl, float width, float gross) {

    /*

      The Q factor is a correction to the error array when more than
      one electron is created per photon.  This effect occurs in the
      CCD at wavelengths shorter than ~3400 Angstroms.  The flux array
      already takes this effect into account via the sensitivity
      array.

                           (S*t + D*w)*g/n + R^2*w
      Q_correction = sqrt(-------------------------)
                          (S*t/Q + D*w)*g/n + R^2*w

      where S are the gross counts, D the mean dark background counts
      per pixel, R the read noise counts per pixel, G the gain, N the
      number of combined exposures, t the exposure time, and w the
      width of the extraction region.

    */

    double Q_wave[]  = {1127.09, 2066.33, 2213.93, 2339.25, 3424.86, 11000.00};
    double Q_value[] = {   3.00,    1.50,    1.35,    1.40,    1.00,     1.00};
    int    Q_num   = 6;
    int    wl_start = 0;

    double S = gross > 0? gross: 0.0;   /* gross counts/row */
    double D = sts->meandark;           /* mean dark counts per pixel */
    double R = sts->readnse;            /* read noise counts per pixel */
    double g = sts->atodgain;           /* electron conversion factor */
    double n = sts->ncombine;           /* number of combined exposures */
    double t = sts->exptime;            /* exposure time */
    double w = width;                   /* width of extraction region */
    double Q = interp1d(wl, Q_wave, Q_value, Q_num, &wl_start);

    return (float) sqrt(((S*t + D*w)*g/n + R*R*w)/((S*t/Q + D*w)*g/n + R*R*w));
}
Example #5
0
static int origTdcCorr (StisInfo1 *sts, double *factor) {

/* arguments:
StisInfo1 *sts          i: calibration switches, etc
double *factor          o: NUV correction factor for dark image
*/
	int status;

	TblInfo tabinfo;	/* pointer to table descriptor, etc */
	TblRow tabrow;		/* values read from a table row */

	int row;		/* loop index */
	int nrows;		/* # of rows */

	double* mjd;		/* values from table are stored here   */
	double* scale;		/* to be fed into the interpolation. */
	double* norm;
	double* tmin;
	double* thermcst;

	double scale0;		/* interpolated values */
	double norm0;
	double tmin0;
	double thermcst0;
	int starti;		/* starting index for interpolation search */

	double interp1d (double, double *, double *, int, int *);

	/* Open table and find columns. */
	if ((status = OpenTdcTab (sts->tdctab.name, &tabinfo)))
	    return status;
	nrows = tabinfo.nrows;

	/* Alloc memory. */

	mjd      = (double *) malloc (nrows * sizeof (double));
	scale    = (double *) malloc (nrows * sizeof (double));
	norm     = (double *) malloc (nrows * sizeof (double));
	tmin     = (double *) malloc (nrows * sizeof (double));
	thermcst = (double *) malloc (nrows * sizeof (double));
	if (mjd      == NULL ||
	    scale    == NULL ||
	    norm     == NULL ||
	    tmin     == NULL ||
	    thermcst == NULL)
	    return (status = OUT_OF_MEMORY);

	/* Read rows into arrays. */

	for (row = 1; row <= tabinfo.nrows; row++) {

	    if ((status = ReadTdcTab (&tabinfo, row, &tabrow)))
		return status;

	    if ((status = RowPedigree (&sts->ccdpar, row,
                    tabinfo.tp, tabinfo.cp_pedigree, tabinfo.cp_descrip)))
		return status;
	    if (sts->tdctab.goodPedigree == DUMMY_PEDIGREE)
		printf ("Warning  Row %d of TDCTAB is DUMMY.\n", row);

	    mjd[row-1]      = tabrow.mjd;
	    scale[row-1]    = tabrow.scale;
	    norm[row-1]     = tabrow.norm;
	    tmin[row-1]     = (double)tabrow.tmin;
	    thermcst[row-1] = (double)tabrow.thermcst;
	}

	starti = tabinfo.nrows - 1;
	scale0    = interp1d (sts->expstart, mjd, scale,    nrows, &starti);
	norm0     = interp1d (sts->expstart, mjd, norm,     nrows, &starti);
	tmin0     = interp1d (sts->expstart, mjd, tmin,     nrows, &starti);
	thermcst0 = interp1d (sts->expstart, mjd, thermcst, nrows, &starti);

	*factor  = NUVFactor (sts->detector_temp, scale0, norm0, tmin0,
	                      thermcst0);

	free (mjd);
	free (scale);
	free (norm);
	free (tmin);
	free (thermcst);

	if ((status = CloseTdcTab (&tabinfo)))
	    return status;

	return 0;
}
Example #6
0
File: track.c Project: pa345/lib
size_t
track_init(satdata_mag *data, msynth_workspace *msynth_p, track_workspace *w)
{
    size_t nflagged = 0;
    size_t i = 0, j;

    w->data = data;

    while (i < data->n - 1)
    {
        int s;
        double lon_eq, t_eq, lt_eq;
        size_t sidx, eidx;
        track_data *tptr;

        s = satdata_mag_find_track(i, &eidx, data);
        if (s)
        {
#if TRACK_DEBUG
            fprintf(stderr, "track_init: no more tracks found in [%zu, %zu]\n", sidx, data->n - 1);
#endif
            break;
        }

        /* update index i for next loop */
        sidx = i;
        i = eidx + 1;

        /* check for equator crossing */
        if (data->latitude[sidx] * data->latitude[eidx] < 0.0)
        {
            size_t idx;
            time_t unix_time;

            /* there is an equator crossing, find time and longitude */

            if (data->latitude[eidx] > data->latitude[sidx])
                idx = bsearch_double(data->latitude, 0.0, sidx, eidx);
            else if (data->latitude[eidx] < data->latitude[sidx])
                idx = bsearch_desc_double(data->latitude, 0.0, sidx, eidx);

            /* sanity check we found equator crossing */
            assert(data->latitude[idx] * data->latitude[idx + 1] < 0.0);

            /* interpolate t, but not longitude due to wrapping effects */
            t_eq = interp1d(data->latitude[idx], data->latitude[idx + 1],
                            data->t[idx], data->t[idx + 1], 0.0);
            lon_eq = data->longitude[idx];

            /* compute local time */
            unix_time = satdata_epoch2timet(t_eq);
            lt_eq = get_localtime(unix_time, lon_eq * M_PI / 180.0);
        }
        else
        {
            /* no equator crossing */

#if TRACK_DEBUG
            fprintf(stderr, "track_init: flagging partial track [%zu, %zu]\n", sidx, eidx);
#endif
            nflagged += track_flag_data(sidx, eidx, data);
            continue;
        }

        /* compute main field along track in data->F_main */
        if (msynth_p)
            track_calc_mf(sidx, eidx, data, msynth_p);

        /* store this track information */
        tptr = &(w->tracks[w->n]);
        tptr->start_idx = sidx;
        tptr->end_idx = eidx;
        tptr->n = eidx - sidx + 1;
        tptr->t_eq = t_eq;
        tptr->lon_eq = lon_eq;
        tptr->lt_eq = lt_eq;
        tptr->nrms_scal = 0;
        tptr->nrms_vec = 0;
        tptr->flags = 0;
        tptr->k_ext = 0.0;
        tptr->meanalt = gsl_stats_mean(&(data->altitude[sidx]), 1, tptr->n);

        /* use index of track center to compute satellite direction */
        tptr->satdir = satdata_mag_satdir(sidx + tptr->n / 2, data);

        for (j = 0; j < 3; ++j)
            tptr->rms[j] = 0.0;

        assert(tptr->n > 0);

        /* compute and store along-track residuals */
        tptr->Bx = malloc(tptr->n * sizeof(double));
        tptr->By = malloc(tptr->n * sizeof(double));
        tptr->Bz = malloc(tptr->n * sizeof(double));
        tptr->Bf = malloc(tptr->n * sizeof(double));

        track_calc_residuals(tptr, data);

        if (++(w->n) >= w->ntot)
        {
            fprintf(stderr, "track_init: ntot not large enough: %zu\n", w->ntot);
            return nflagged;
        }
    }

#if TRACK_DEBUG
    fprintf(stderr, "track_init: found %zu tracks\n", w->n);
#endif

    return nflagged;
} /* track_init() */
Example #7
0
static int FluxToNet (StisInfo6 *sts, IntensArray *inta, int sporder) {

	/* This is used to store information from the fflux file in a
           form suitable for the reference file input routines.
        */
	StisInfo6 fsts;
	ApInfo slit;
	PhotInfo phot;

	IODescPtr im;
	Hdr phdr;
	double photfactor, throughput, response, dispersion;
	double atodgain, readnoise;
	float correction;
	int i, dispc, helc, status;
	int abs_starti, thr_starti;
	int dummy;

	void FreePhot6 (PhotInfo *);
	void FreeThroughput6 (ApInfo *);
	int GetAbsPhot6 (StisInfo6 *, int, PhotInfo *, int, int *);
	int GetApDes6 (StisInfo6 *, ApInfo *);
	int GetApThr6 (StisInfo6 *, ApInfo *);
	int Get_KeyD (Hdr *, char *, int, double, double *);
	int Get_KeyS (Hdr *, char *, int, char *, char *, int);
	int GetSwitch (Hdr *, char *, int *);
	double interp1d (double, double *, double *, int, int *);
	void StisInit6 (StisInfo6 *);

	photfactor = H_PLANCK * C_LIGHT / HST_AREA;

	/* Initialize local data structures. */
	StisInit6 (&fsts);
        InitRefTab (&fsts.phottab);
        InitRefTab (&fsts.apertab);
        InitRefTab (&fsts.apdestab);
	slit.allocated  = 0;
	slit.gac_allocated  = 0;
	phot.allocated  = 0;
	phot.pcorr      = NULL;

	/* Handling the primary header here is not efficient. But keeps
           this new code manageable since everything new is added at a
           single point. In the future we may move this to outside the
           main loop and pass the necessary values as part of the sts
           structure.
        */
	initHdr (&phdr);
	im = openInputImage (sts->pxtab.name, "", 0);
	if (hstio_err())
	    return (OPEN_FAILED);
	getHeader (im, &phdr);
	if (hstio_err())
	    return (OPEN_FAILED);
	closeImage (im);

	/* Abort if both helcorr and dispcorr weren't performed.
           The criterion is: if a keyword is set to either COMPLETE
           or PERFORM, we assume that the operation was performed.
           This is because UpdHdrSwitch in Do1Dx only updates the
           keywords to COMPLETE if they are set to PERFORM in the
           input file.  (note:  UpdHdrSwitch is no longer used)
        */
	if ((status = GetSwitch (&phdr, "DISPCORR", &dispc)))
	    return (status);
	if ((status = GetSwitch (&phdr, "HELCORR", &helc)))
	    return (status);
	if (!((dispc == PERFORM || dispc == COMPLETE) &&
              (helc  == PERFORM || helc  == COMPLETE))) {
	    printf ("ERROR    No DISPCORR/HELCORR in fflux file.\n");
	    return (ERROR_RETURN);
	}

	/* Read header keywords. */
	if ((status = Get_KeyD (&phdr, "READNSE", 1, 0., &readnoise)))
	    return (status);
	if ((status = Get_KeyD (&phdr, "ATODGAIN", 1, 1., &atodgain)))
	    return (status);
	if ((status = Get_KeyS (&phdr, "PHOTTAB", FATAL, "",
                                fsts.phottab.name, STIS_LINE)))
	    return (status);
	if ((status = Get_KeyS (&phdr, "APDESTAB", FATAL, "",
                                fsts.apdestab.name, STIS_LINE)))
	    return (status);
	if ((status = Get_KeyS (&phdr, "APERTAB", FATAL, "",
                                fsts.apertab.name, STIS_LINE)))
	    return (status);

	/* Copy stuff from primary data structure into local one. */
	fsts.x1d_o    = sts->x1d_o;
	fsts.dispcorr = sts->dispcorr;
	fsts.fluxcorr = sts->fluxcorr;
	fsts.pctcorr  = sts->pctcorr;
	fsts.cenwave  = sts->cenwave;
	strcpy (fsts.opt_elem, sts->opt_elem);
	strcpy (fsts.aperture, sts->aperture);

	/* Read the required reference info. */
	dummy = 0;
	if ((status = GetAbsPhot6 (&fsts, sporder, &phot, 0, &dummy)))
	    return (status);
	if ((status = GetApDes6 (&fsts, &slit)))
	    return (status);
        if ((status = GetApThr6 (&fsts, &slit)))
	    return (status);

	abs_starti = 1;				/* initial values */
	thr_starti = 1;

	/* Loop over flux array. */
	for (i = 0;  i < inta->nelem;  i++) {
	    response   = interp1d (inta->wave[i], phot.wl, phot.thru,
                                   phot.nelem, &abs_starti);
	    throughput = interp1d (inta->wave[i], slit.wl, slit.thr,
                                   slit.nelem, &thr_starti);
	    if (i > 0)
	        dispersion = inta->wave[i] - inta->wave[i-1];
	    else
	        dispersion = inta->wave[1] - inta->wave[0];

	    /* This check is provisional; final version awaits IS's words. */
	    if (response   <= 0.0 ||
	        dispersion <= 0.0 ||
	        throughput <= 0.0) {
	        printf ("ERROR    Error in fflux file contents.\n");
	        return (ERROR_RETURN);
	    }

	    correction = (float) (photfactor / (response * throughput *
                         inta->wave[i] * dispersion * atodgain *
                         CM_PER_ANGSTROM));

	    inta->intens[i] = inta->intens[i] / correction;
	}

	FreeThroughput6 (&slit);
	FreePhot6 (&phot);

	freeHdr (&phdr);
	return STIS_OK;
}
Example #8
0
int AbsFlux6 (StisInfo6 *sts, RowContents *out,
              PhotInfo *phot, PhotInfo *photc, ApInfo *slit, TdsInfo *tds,
              CTICorrInfo *cti, double hfactor, double atodgain, int optimal,
              double *pfactor, double *blazeshift)
{

    /* arguments:
       StisInfo6 *sts         i: calibration switches and info
       RowContents *out       io: output data
       PhotInfo *phot         i: photometry info
       PhotInfo *photc        i: for extraction box height correction
       ApInfo *slit           i: slit info (for throughput)
       TdsInfo *tds           i: time-dependent sensitivity info
       double hfactor         i: divide to convert back to observed wavelength
       double atodgain        i: CCD ATODGAIN value
       int optimal            i: is optimal extraction ?
       double *pfactor;       i: flux normalization factor from opt. extr.
                                 profile
       double *blazeshift;    o: blaze shift value actually used
    */

        double wl;              /* observed wavelength at a pixel */
        double response;        /* instrumental response at a wavelength */
        double pct_factor;      /* correction to infinite extr box height */
        double pct_factor2;     /* correction for current extr box height */
        double tds_factor;      /* correction for time-dependent sens. */
        double gac_factor;      /* grating-aperture correction */
        double throughput;      /* factor to correct for slit throughput */
        double photfactor;      /* to get inverse sensitivity */
        double dispersion;      /* dispersion in A/pix */
        float correction;       /* combined correction factor */
        float ecorrection;      /* combined correction factor for the error */
        int i;
        int status;
        int abs_starti;         /* index to begin search in interp1d */
        int pct_starti;
        int thr_starti;
        int gac_starti;
        int tds_starti;
        double hf;
        double *tds_factors;    /* array with time-dependent sensitivity
                                   correction factors */
        double *wl_no_blaze;    /* phot->wl before blaze shift correction */

        void BlazeCorr (PhotInfo *, double, double, int, double, double *,
                        double);
        void TdsCorrection (TdsInfo *, double, double, double *);

        abs_starti = 1;                         /* initial values */
        pct_starti = 1;
        thr_starti = 1;
        gac_starti = 1;
        tds_starti = 1;

        /* Get the CCD halo factor (haloterm), for opt_elem G750L or G750M. */
        cti->allocated = 0;
        if ((status = getHalo (sts,
                out->npts, out->wave, out->net, cti)) != 0) {
            return (status);
        }

        photfactor = H_PLANCK * C_LIGHT / HST_AREA;

        if (sts->heliocorr == PERFORM)
            hf = sts->hfactor;
        else
            hf = 1.0;

        /* Generate time-dependent sensitivity correction factors. */
        if (sts->tdscorr == PERFORM) {
            tds_factors = (double *) malloc (tds->nwl * sizeof (double));
            if (tds_factors == NULL)
                return (OUT_OF_MEMORY);

            TdsCorrection (tds, sts->expstart, sts->detector_temp,
                           tds_factors);
        }

        /* Apply MSM/blaze correction to throughput array. Dispersion
           is required in the case the reference values from the _pht
           table are invalid, AND we are passing a blazeshift value
           thru the command line. In this case, we use the dispersion
           at the mid point in the current spectral order.

           First we have to save the phot->wl array, because when we
           interpolate to get pct_factor we must use wavelengths that
           do not include the blaze shift correction.
        */
        wl_no_blaze = malloc (phot->nelem * sizeof (double));
        if (wl_no_blaze == NULL)
            return (OUT_OF_MEMORY);
        for (i = 0;  i < phot->nelem;  i++)
            wl_no_blaze[i] = phot->wl[i];

        if (phot->wpos != 0.0 || sts->blazeshift != NO_VALUE) {

            i = out->npts / 2;
            dispersion = getDispersion (out, i);
            dispersion /= hf;

            BlazeCorr (phot, sts->expstart, sts->expend, out->sporder,
                       sts->blazeshift, blazeshift, dispersion);
        }

        /* Loop over flux array. */
        for (i = 0; i < out->npts; i++) {

            /* Convert back to observed wavelength. */
            wl = out->wave[i] / hfactor;

            /* Interpolate in the reference tables. */
            response    = extrap1d (wl, phot->wl, phot->thru, phot->nelem,
                                    &abs_starti);
            pct_factor  = interp1d (wl, wl_no_blaze, phot->pcorr, phot->nelem,
                                    &pct_starti);
            pct_factor2 = interp1d (wl, photc->wl, photc->pcorr, photc->nelem,
                                    &pct_starti);
            throughput  = interp1d (wl, slit->wl, slit->thr, slit->nelem,
                                    &thr_starti);
            if (sts->gaccorr == PERFORM) {
                gac_factor = interp1d (wl, slit->gac_wl, slit->gac_thr,
                                slit->gac_nelem, &gac_starti);
            } else {
                gac_factor = 1.;
            }
            if (sts->tdscorr == PERFORM)
                tds_factor  = interp1d (wl, tds->wl, tds_factors,
                                        tds->nwl, &tds_starti);
            else
                tds_factor = 1.;

            /* Check for zeroed throughput (OPR 38749) */
            if (throughput <= 0.0) {
                out->flux[i]  = 0.0F;
                out->error[i] = 0.0F;
                out->dq[i]   |= CALIBDEFECT;
                continue;
            }

            /* Compute dispersion at current pixel. */

            dispersion = getDispersion (out, i);

            if (dispersion <= 0.0) {
                out->flux[i]  = 0.0F;
                out->error[i] = 0.0F;
                out->dq[i]   |= CALIBDEFECT;
                continue;
            }
            dispersion /= hf;

            /* Compute flux. */

            if (response <= 0.0) {
                out->flux[i]  = 0.0F;
                out->error[i] = 0.0F;
                out->dq[i]   |= CALIBDEFECT;
            } else {
                float qfactor = 1.0;
                float net   = out->net[i];

                correction = (float) (photfactor / (response * throughput *
                                      wl * dispersion * CM_PER_ANGSTROM));
                correction *= atodgain;  /* added 9/3/97 (IB) */
                correction *= pct_factor / pct_factor2;
                correction /= gac_factor;
                correction /= tds_factor;
                ecorrection = correction;

                if (sts->detector == CCD_DETECTOR) {
                    qfactor = QFactor(sts, wl, out->extrsize, out->gross[i]);
                    if (sts->ctecorr == PERFORM) {
                        if (out->gross[i] > 0.0) {
                            net = out->gross[i] *
                                CtiCorr(sts, cti, cti->haloterm[i],
                                        out->extrsize, out->extrlocy[i],
                                        out->gross[i], out->back[i])
                                - out->back[i];
                        } else {
                            out->dq[i] |= NOT_CTI_CORR;
                        }
                    }
                }
                if (optimal)
                    correction *= pfactor[i];
                if (ecorrection <= 0.) {
                    out->flux[i]  = 0.0F;
                    out->error[i] = 0.0F;
                    out->dq[i]   |= CALIBDEFECT;
                } else {
                    out->flux[i] = net * correction;
                    out->error[i] *= ecorrection * qfactor;
                    out->net_error[i] *= qfactor;
                }
            }
        }

        if (sts->tdscorr == PERFORM)
            free (tds_factors);

        if (cti->allocated)
            free (cti->haloterm);

        free (wl_no_blaze);

        return (0);
}