Ejemplo n.º 1
0
/*
 * Read an ASCII file as a 2-dimensional array of floating point numbers.
 * The number of columns is determined by the number of entries on the
 * first non-comment line.  Missing values are set to zero.
 * Comment lines (preceded with a hash mark) are ignored.
 * The returned matrix is in row-major order, and as such is
 * addressed as (*ppData)[iRow*NCols+iCol].
 * If the data array is empty, it should be passed with the value ppData = NULL.
 *
 * Return IO_GOOD if the file exists, and IO_BAD otherwise.
 */
int asciifile_read_rowmajor
  (char     pFileName[],
   int      numColsMax,
   int   *  pNRows,
   int   *  pNCols,
   float ** ppData)
{
   int      fileNum;
   int      iCol;
   int      nValues;
   int      qExist;
   const int numAddRows = 10;
   MEMSZ    memSize;
   MEMSZ    newMemSize;
   char  *  iq;
   float *  pValues;
   float *  pData;
   char     pPrivR[] = "r\0";

   *pNCols = 0;
   *pNRows = 0;

   qExist = inoutput_open_file(&fileNum, pFileName, pPrivR);

   if (qExist == IO_GOOD) {

      /* Allocate a starting block of memory for the data array */
      /* Start with enough memory for numAddRows rows */
      memSize = numAddRows * sizeof(float) * numColsMax;
      /* SHOULD BE ABLE TO USE REALLOC BELOW !!!??? */
      ccalloc_(&memSize, (void **)ppData);
      pData = *ppData;

      /* Allocate the temporary memory for each line of values */
      pValues = ccvector_build_(numColsMax);

      /* Read the first line, which determines the # of cols for all lines */
      iq = asciifile_read_line(fileNum, numColsMax, pNCols, pData);

      /* Read the remaining lines if a first line was read successfully */
      if (iq != NULL) {
         *pNRows=1;

         while ((iq = asciifile_read_line(fileNum, numColsMax,
          &nValues, pValues)) != NULL) {

            /* Allocate more memory for the data array if necessary */
            /* Always keep enough memory for at least one more row */
            newMemSize = sizeof(float) * (*pNRows + 1) * (*pNCols);
            if (newMemSize > memSize) {
               newMemSize = newMemSize + sizeof(float)*(numAddRows);
               ccalloc_resize_(&memSize, &newMemSize, (void **)ppData);
               pData = *ppData;
               memSize = newMemSize;
            }
   
            /* Case where the line contained fewer values than allowed */
            if (nValues < *pNCols) {
               for (iCol=0; iCol<nValues; iCol++)
                  pData[iCol+(*pNCols)*(*pNRows)] = pValues[iCol];
               for (iCol=nValues; iCol < *pNCols; iCol++)
                  pData[iCol+(*pNCols)*(*pNRows)] = 0;

            /* Case where line contained as many or more values than allowed */
            } else {
               for (iCol=0; iCol < *pNCols; iCol++)
                  pData[iCol+(*pNCols)*(*pNRows)] = pValues[iCol];
            }

            (*pNRows)++;
         }
      }

      inoutput_close_file(fileNum);
      ccvector_free_(pValues);
   }

   return qExist;
}
Ejemplo n.º 2
0
void main
  (int      argc,
   char  *  ppArgv[],
   char  *  ppEnvp[])
{
   int      ic;
   int      qInterp;
   int      qVerbose;
   int      qNoloop;
   int      iGal;
   int      nGal;
   int      nCol;
   float    tmpl;
   float    tmpb;
   float *  pGall = NULL;
   float *  pGalb = NULL;
   float *  pNu = NULL;
   float *  pInu;
   float *  pData;

   FILE  *  pFILEout;
   static char pPrivW[] = "w";

   /* Declarations for keyword input values */
   int      ienv;
   int      nkey;
   int      modelNum;
   float    nuval = 0.0;
   char  *  pTemp;
   char  *  pKeyname;
   char  *  pKeyval;
   char  *  pResName;
   char  *  pUnitsName;
   char  *  pInFile = NULL;
   char  *  pOutName = NULL;
   char  *  pIPath   = NULL;
   char     pString1[13];
   char     pDefPath[] = "./";
   char     pDefRes[] = "I4096";
   const char pDUST_DIR[] = "DUST_DIR";
   const char     pEq[] = "=";
   const char pText_mapdir[] = "/maps/";

   /* Declarations for command-line keyword names */
   const char pText_ipath[] = "ipath";
   const char pText_infile[] = "infile";
   const char pText_outfile[] = "outfile";
   const char pText_model[] = "model";
   const char pText_nu[] = "nu";
   const char pText_resolution[] = "resolution";
   const char pText_units[] = "units";
   const char pText_interp[] = "interp";
   const char pText_noloop[] = "noloop";
   const char pText_verbose[] = "verbose";
   char     pText_MJy[] = "MJy";

   /* Set defaults */
   pIPath = pDefPath;
   pResName = pDefRes;
   pUnitsName = pText_MJy;
   modelNum = 8; /* default to our best-fit model */
   qInterp = 0; /* no interpolation */
   qVerbose = 0; /* not verbose */
   qNoloop = 0; /* do not read entire image into memory */

   /* Override default path by value in the environment variable DUST_DIR */
   for (ienv=0; ppEnvp[ienv] != 0; ienv++) {
      if (strcmp(pDUST_DIR,strtok(ppEnvp[ienv],pEq))==0 ) {
         pIPath = strcat( strtok(NULL,pEq), pText_mapdir );
      }
   }

   nkey = 0;
   for (ic=1; ic < argc; ic++) {
      /* Check if this argument is a keyword */
      if ((pTemp=strchr(ppArgv[ic],'=')) != NULL) {
         nkey++;
         pKeyname = ppArgv[ic];
         pKeyval = pTemp + 1;
         pTemp[0] = '\0'; /* replace equals with NULL to terminate string */

         if (strcmp(pKeyname,pText_nu) == 0)
          sscanf(pKeyval, "%f", &nuval);

         if (strcmp(pKeyname,pText_infile) == 0) pInFile = pKeyval;

         if (strcmp(pKeyname,pText_outfile) == 0) pOutName = pKeyval;

         if (strcmp(pKeyname,pText_model) == 0)
          sscanf(pKeyval, "%d", &modelNum);

         if (strcmp(pKeyname,pText_resolution) == 0) pResName = pKeyval;

         if (strcmp(pKeyname,pText_units) == 0) pUnitsName = pKeyval;

         if (strcmp(pKeyname,pText_ipath) == 0) pIPath = pKeyval;

         if (strcmp(pKeyname,pText_interp) == 0) {
            if (strchr(pKeyval,'y') != NULL || strchr(pKeyval,'Y') != NULL)
             qInterp = 1; /* do interpolation */
         }

         if (strcmp(pKeyname,pText_noloop) == 0) {
            if (strchr(pKeyval,'y') != NULL || strchr(pKeyval,'Y') != NULL)
             qNoloop=1; /* read entire image into memory */
         }

         if (strcmp(pKeyname,pText_verbose) == 0) {
            if (strchr(pKeyval,'y') != NULL || strchr(pKeyval,'Y') != NULL)
             qVerbose = 1; /* do interpolation */
         }

      }
   }

   /* If no input coordinate file, then read coordinates from either
    * the command line or by query */
   if (pInFile != NULL) {
      if (nuval == 0.0) {
         asciifile_read_colmajor(pInFile, 3, &nGal, &nCol, &pData);
         pGall = pData;
         pGalb = pData + nGal;
         pNu = pData + 2*nGal;
         if (pNu[0] == 0.0) pNu = NULL;
      } else {
         asciifile_read_colmajor(pInFile, 2, &nGal, &nCol, &pData);
         pGall = pData;
         pGalb = pData + nGal;
      }
   } else {
      if (argc-nkey > 2) {
         sscanf(ppArgv[1], "%f", &tmpl);
         sscanf(ppArgv[2], "%f", &tmpb);
      } else {
         printf("Galactic longitude (degrees):\n");
         scanf("%f", &tmpl);
         printf("Galactic latitude (degrees):\n");
         scanf("%f", &tmpb);
      }
      nGal = 1;
      pGall = ccvector_build_(nGal);
      pGalb = ccvector_build_(nGal);
      pGall[0] = tmpl;
      pGalb[0] = tmpb;
   }

   /* Query for the frequency if not specified on the command line or
    * in the input file.
    */
   if (nuval == 0.0 && pNu == NULL) {
      printf("Frequency (GHz):\n");
      scanf("%f", &nuval);
   }

   /* If "nu" was specified on the command line, then set frequency of
      all points to this value; this will supersede any in an input file. */
   if (nuval != 0.0) {
      if (pNu == NULL) pNu = ccvector_build_(nGal);
      for (iGal=0; iGal < nGal; iGal++) pNu[iGal] = nuval;
   }

   pInu = predict_thermal(nGal, pGall, pGalb, pNu, pIPath, pResName,
    pUnitsName, modelNum, qInterp, qNoloop, qVerbose);

   /* If no output file, then output to screen */
   if (pOutName != NULL) pFILEout = fopen(pOutName, pPrivW);
   else pFILEout = stdout;
   sprintf(pString1, "Inu(%s)", pUnitsName);
   fprintf(pFILEout, " l(deg)  b(deg)  nu(GHz)      %-12.12s\n", pString1);
   fprintf(pFILEout, " ------- ------- ------------ ------------\n");
   for (iGal=0; iGal < nGal; iGal++) {
      fprintf(pFILEout, "%8.3f %7.3f %12.5e %12.5e\n",
       pGall[iGal], pGalb[iGal], pNu[iGal], pInu[iGal]);
   }
   if (pOutName != NULL) fclose(pFILEout);

   if (pInFile != NULL) {
      ccfree_((void **)&pData);
   } else {
      ccfree_((void **)&pGall);
      ccfree_((void **)&pGalb);
   }
}
Ejemplo n.º 3
0
float * predict_thermal
  (long     nGal,
   float *  pGall,
   float *  pGalb,
   float *  pNu,
   char  *  pIPath,
   char  *  pResName,
   char  *  pUnitsName,
   int      modelNum,
   int      qInterp,
   int      qNoloop,
   int      qVerbose)
{
   int      ii;
   int      im;
   int      iz1 = -1; /* crash if Zindx not tabulated for alpha1 */
   int      iz2 = -1; /* crash if Zindx not tabulated for alpha2 */
   int      imap;
   int      iGal;
   float *  pI100;
   float *  pRmapval;
   float *  pInu;
   float    alpha1;
   float    alpha2;
   float    f1;
   float    q1q2;
   float    RfitA[6];
   float    lnR;
   float    lnRpow;
   float    T1;
   float    T2;
   float    lnT1;
   float    lnT2;
   float    tcoeff;
   const float nu100 = 2997.92458; /* Frequency in GHz for 100-microns */
   const float h_Pl = 6.6261e-27; /* cm^2 g s^-1 */
   const float k_B = 1.3806e-16;  /* erg K^-1 */

   /* Declarations for command-line keyword names */
   char pText_MJy[] = "MJy";
   char pText_microK[] = "microK";
   char pText_thermo[] = "thermo";

   /* Declarations for data file names */
   char     pFileN[MAX_FILE_NAME_LEN];
   char     pFileS[MAX_FILE_NAME_LEN];
   struct   mapParms {
      char *   pName;
      char *   pFile1;
      char *   pFile2;
   } ppMapAll[] = {
     { "D1024", "SFD_d100_1024_ngp.fits", "SFD_d100_1024_sgp.fits" },
     { "I1024", "SFD_i100_1024_ngp.fits", "SFD_i100_1024_sgp.fits" },
     { "I2048", "SFD_i100_2048_ngp.fits", "SFD_i100_2048_sgp.fits" },
     { "I4096", "SFD_i100_4096_ngp.fits", "SFD_i100_4096_sgp.fits" }
   };
   const int nmap = sizeof(ppMapAll) / sizeof(ppMapAll[0]);
   char * ppRmapFile[] =
     { "FINK_Rmap_ngp.fits" , "FINK_Rmap_sgp.fits" };

   /* Set model parameters */
   const float alpha1vec[] = {1.50, 1.70, 2.00, 2.20, 1.50, 2.00, 1.50, 1.67};
   const float alpha2vec[] = {0.00, 0.00, 0.00, 0.00, 2.60, 2.00, 2.60, 2.70};
   const float f1vec[]     = {1.00, 1.00, 1.00, 1.00, 0.25, 0.00261, 0.0309, 0.0363};
   const float q1q2vec[]   = {1.00, 1.00, 1.00, 1.00, 0.61, 2480.0, 11.2, 13.0};
   /* const int N_MODEL = sizeof(alpha1vec) / sizeof(alpha1vec[0]); */
 
   /* Rfita contains fit coefficients for T2_of_R */
   const float RfitAarr[][6] =
    {{2.9268E+00, 3.8419E-01, 5.0233E-02, 1.0852E-02, 3.0738E-03, 5.0595E-04},
     {2.8483E+00, 3.8044E-01, 4.6584E-02, 9.0938E-03, 2.7038E-03, 5.4664E-04},
     {2.7334E+00, 3.7537E-01, 4.1712E-02, 6.8839E-03, 2.0316E-03, 6.0311E-04},
     {2.6556E+00, 3.7377E-01, 3.9898E-02, 5.7662E-03, 1.4638E-03, 6.3723E-04},
     {2.9206E+00, 2.3254E-01, 2.3506E-02, 4.0781E-03, 1.0048E-03, 1.2004E-04},
     {2.9900E+00, 2.5041E-01, 2.9688E-02, 6.5641E-03, 1.5688E-03, 1.6542E-04},
     {2.8874E+00, 2.4172E-01, 2.9369E-02, 4.7867E-03, 9.7237E-04, 1.1410E-04},
     {2.8723E+00, 2.4071E-01, 2.9625E-02, 4.7196E-03, 9.3207E-04, 1.1099E-04} };
 
   /* Zeta integrals for alpha=[1.50, 1.67, 1.70, 2.00, 2.20, 2.60, 2.70]
      from equn (15) of Finkbeiner et al. */
   const float Zindx[] = {1.50, 1.67, 1.70, 2.00, 2.20, 2.60, 2.70};
   const float Zintegral[] = {5.3662E+01, 7.0562E+01, 7.4100E+01, 1.2208E+02,
    1.7194E+02, 3.4855E+02, 4.1770E+02};
   const int N_ZINDEX = sizeof(Zindx) / sizeof(Zindx[0]);

   /* Test that inputs are valid */
   if (nGal == 0 || pGall == NULL || pGalb == NULL || pNu == NULL) {
      printf("ERROR: Must specify coordinates and frequencies.\n");
      return NULL;
   }

   /* Select parameters for this model */
   alpha1 = alpha1vec[modelNum-1];
   alpha2 = alpha2vec[modelNum-1];
   f1 = f1vec[modelNum-1];
   q1q2 = q1q2vec[modelNum-1];
   for (ii=0; ii < 6; ii++) RfitA[ii] = RfitAarr[modelNum-1][ii];

   /* Determine the file names to use */
   for (imap=0; imap < nmap; imap++) {
      if (strcmp(pResName,ppMapAll[imap].pName) == 0) {
         sprintf(pFileN, "%s/%s", pIPath, ppMapAll[imap].pFile1);
         sprintf(pFileS, "%s/%s", pIPath, ppMapAll[imap].pFile2);
      }
   }

   /* Read the 100-micron map */
   pI100 = lambert_getval(pFileN, pFileS, nGal, pGall, pGalb,
    qInterp, qNoloop, qVerbose);

   /* Read the I100/240 ratio map */
   sprintf(pFileN, "%s/%s", pIPath, ppRmapFile[0]);
   sprintf(pFileS, "%s/%s", pIPath, ppRmapFile[1]);
   pRmapval = lambert_getval(pFileN, pFileS, nGal, pGall, pGalb,
    qInterp, qNoloop, qVerbose);

   /* Allocate memory for output array */
   pInu = ccvector_build_(nGal);

   if (modelNum <=4) {
      /* SINGLE-COMPONENT MODEL: Evaluate equn (1) from Finkbeiner et al */
      for (iGal=0; iGal < nGal; iGal++) {

         /* Compute ln(T1) from ln(Rmap) */
         lnR = log(pRmapval[iGal]);
         lnRpow = 1.0;
         lnT1 = RfitA[0];
         for (ii=1; ii < 6; ii++) {
            lnRpow *= lnR;
            lnT1 += RfitA[ii] * lnRpow;
         }
         T1 = exp(lnT1);

         pInu[iGal] =
          pI100[iGal] * pow(pNu[iGal]/nu100,alpha1) * planck(T1,pNu[iGal]) /
          ( planck(T1,nu100) * kfactor(alpha1,T1) );
      }
   } else {
      /* TWO-COMPONENT MODEL: Evaluate equn (6) from Finkbeiner et al */

      /* Find Zintegral index for the model values of "alpha" */
      for (im=0; im < N_ZINDEX; im++) {
         if (fabs(Zindx[im] - alpha1) < 1.e-4) iz1 = im;
         if (fabs(Zindx[im] - alpha2) < 1.e-4) iz2 = im;
      }
      tcoeff = pow( (Zintegral[iz2] / (q1q2*Zintegral[iz1]))
       * pow(h_Pl*nu100*1.e+9/k_B,alpha1-alpha2), 1./(4.+alpha1) );

      for (iGal=0; iGal < nGal; iGal++) {

         /* Compute ln(T2) from ln(Rmap) */
         lnR = log(pRmapval[iGal]);
         lnRpow = 1.0;
         lnT2 = RfitA[0];
         for (ii=1; ii < 6; ii++) {
            lnRpow *= lnR;
            lnT2 += RfitA[ii] * lnRpow;
         }
         T2 = exp(lnT2);

         /* Compute T1 as a function of T2; equn (13) of Finkbeiner et al. */
         T1 = tcoeff * pow( T2, ((4+alpha2)/(4+alpha1)) );

         pInu[iGal] = pI100[iGal] *
          ( f1 * q1q2 * pow(pNu[iGal]/nu100,alpha1) * planck(T1,pNu[iGal])
             + (1-f1) * pow(pNu[iGal]/nu100,alpha2) * planck(T2,pNu[iGal]) ) / 
          ( f1 * q1q2 * planck(T1,nu100) * kfactor(alpha1,T1)
          + (1-f1) * planck(T2,nu100) * kfactor(alpha2,T2) );
      }
   }

   /* Convert units */
   if (strcmp(pUnitsName,pText_MJy) == 0) {
      /* MJy/sr */
   } else if (strcmp(pUnitsName,pText_microK) == 0) {
      /* brightness temp micro-K */
      for (iGal=0; iGal < nGal; iGal++)
       pInu[iGal] *= fac_flux2temp(pNu[iGal]);
   } else if (strcmp(pUnitsName,pText_thermo) == 0) {
      /* thermodynamic micro-K */
      for (iGal=0; iGal < nGal; iGal++)
       pInu[iGal] *= fac_flux2temp(pNu[iGal]) * planckcorr(pNu[iGal]);
   } else {
      printf("ERROR: Invalid units name.\n");
      for (iGal=0; iGal < nGal; iGal++)
       pInu[iGal] = 0.0;
   }

   ccvector_free_(pI100);
   ccvector_free_(pRmapval);

   return pInu;
}
Ejemplo n.º 4
0
float * predict_sync
  (long     nGal,
   float *  pGall,
   float *  pGalb,
   float *  pNu,
   char  *  pIPath,
   char  *  pUnitsName,
   int      qInterp,
   int      qNoloop,
   int      qVerbose)
{
   int      iGal;
   float *  pAmap;
   float *  pBmap;
   float *  pInu;

   /* Declarations for command-line keyword names */
   char pText_MJy[] = "MJy";
   char pText_microK[] = "microK";
   char pText_thermo[] = "thermo";

   /* Declarations for data file names */
   char     pFileN[MAX_FILE_NAME_LEN];
   char     pFileS[MAX_FILE_NAME_LEN];
   char * ppHaslamFile[] =
     { "Haslam_clean_ngp.fits" , "Haslam_clean_sgp.fits" };
   char * ppBetaFile[] =
     { "Synch_Beta_ngp.fits" , "Synch_Beta_sgp.fits" };

   /* Test that inputs are valid */
   if (nGal == 0 || pGall == NULL || pGalb == NULL || pNu == NULL) {
      printf("ERROR: Must specify coordinates and frequencies.\n");
      return NULL;
   }

   /* Read the Haslam map */
   sprintf(pFileN, "%s/%s", pIPath, ppHaslamFile[0]);
   sprintf(pFileS, "%s/%s", pIPath, ppHaslamFile[1]);
   pAmap = lambert_getval(pFileN, pFileS, nGal, pGall, pGalb,
    qInterp, qNoloop, qVerbose);

   /* Read the Beta ratio map */
   sprintf(pFileN, "%s/%s", pIPath, ppBetaFile[0]);
   sprintf(pFileS, "%s/%s", pIPath, ppBetaFile[1]);
   pBmap = lambert_getval(pFileN, pFileS, nGal, pGall, pGalb,
    qInterp, qNoloop, qVerbose);

   /* Allocate memory for output array */
   pInu = ccvector_build_(nGal);

   /* microK brightness temp (Beta map is actually negative of spectral
    * index, and ranges from roughly 2.5 < beta < 3.0)
    */
   for (iGal=0; iGal < nGal; iGal++) {
      pInu[iGal] = 1.0e6 * pAmap[iGal] * pow(0.408/pNu[iGal], pBmap[iGal]);
   }

   /* Convert units */
   if (strcmp(pUnitsName,pText_MJy) == 0) {
      /* MJy/sr */
      for (iGal=0; iGal < nGal; iGal++)
       pInu[iGal] /= fac_flux2temp(pNu[iGal]);
   } else if (strcmp(pUnitsName,pText_microK) == 0) {
      /* brightness temp micro-K */
   } else if (strcmp(pUnitsName,pText_thermo) == 0) {
      /* thermodynamic micro-K */
      for (iGal=0; iGal < nGal; iGal++)
       pInu[iGal] *= planckcorr(pNu[iGal]);
   } else {
      printf("ERROR: Invalid units name.\n");
      for (iGal=0; iGal < nGal; iGal++)
       pInu[iGal] = 0.0;
   }

   return pInu;
}
Ejemplo n.º 5
0
/* Read one value at a time from NGP+SGP polar projections.
 * Set qInterp=1 to interpolate, or =0 otherwise.
 * Set qVerbose=1 to for verbose output, or =0 otherwise.
 */
float * lambert_getval
  (char  *  pFileN,
   char  *  pFileS,
   long     nGal,
   float *  pGall,
   float *  pGalb,
   int      qInterp,
   int      qNoloop,
   int      qVerbose)
{
   int      iloop;
   int      iGal;
   int      ii;
   int      jj;
   int   *  pNS; /* 0 for NGP, 1 for SGP */
   int      nIndx;
   int   *  pIndx;
   int   *  pXPix;
   int   *  pYPix;
   int      xPix;
   int      yPix;
   int      xsize;
   DSIZE    pStart[2];
   DSIZE    pEnd[2];
   DSIZE    nSubimg;
   float *  pSubimg;
   float    dx;
   float    dy;
   float    xr;
   float    yr;
   float    pWeight[4];
   float    mapval;
   float *  pOutput;
   float *  pDX = NULL;
   float *  pDY = NULL;

   /* Variables for FITS files */
   int      qRead;
   int      numAxes;
   DSIZE *  pNaxis;
   char  *  pFileIn = NULL;
   HSIZE    nHead;
   uchar *  pHead;

   /* Allocate output data array */
   pNS = ccivector_build_(nGal);
   pOutput = ccvector_build_(nGal);

   /* Decide if each point should be read from the NGP or SGP projection */
   for (iGal=0; iGal < nGal; iGal++)
    pNS[iGal] = (pGalb[iGal] >= 0.0) ? 0 : 1; /* ==0 for NGP, ==1 for SGP */

   if (qNoloop == 0) {  /* LOOP THROUGH ONE POINT AT A TIME */

      /* Loop through first NGP then SGP */
      for (iloop=0; iloop < 2; iloop++) {
         qRead = 0;

         /* Loop through each data point */
         for (iGal=0; iGal < nGal; iGal++) {
            if (pNS[iGal] == iloop) {

               /* Read FITS header for this projection if not yet read */
               if (qRead == 0) {
                  if (iloop == 0) pFileIn = pFileN; else pFileIn = pFileS;
                  fits_read_file_fits_header_only_(pFileIn, &nHead, &pHead);
                  qRead = 1;
               }

               if (qInterp == 0) {  /* NEAREST PIXELS */

                  /* Determine the nearest pixel coordinates */
                  lambert_lb2pix(pGall[iGal], pGalb[iGal], nHead, pHead,
                   &xPix, &yPix);

                  pStart[0] = xPix;
                  pStart[1] = yPix;

                  /* Read one pixel value from data file */
                  fits_read_point_(pFileIn, nHead, pHead, pStart, &mapval);
                  pOutput[iGal] = mapval;

                  if (qVerbose != 0)
                   printf("%8.3f %7.3f %1d %8d %8d %12.5e\n",
                   pGall[iGal], pGalb[iGal], iloop, xPix, yPix, mapval);

               } else {  /* INTERPOLATE */

                  fits_compute_axes_(&nHead, &pHead, &numAxes, &pNaxis);

                  /* Determine the fractional pixel coordinates */
                  lambert_lb2fpix(pGall[iGal], pGalb[iGal], nHead, pHead,
                   &xr, &yr);
/* The following 4 lines introduced an erroneous 1/2-pixel shift
   (DJS 18-Mar-1999).
                  xPix = (int)(xr-0.5);
                  yPix = (int)(yr-0.5);
                  dx = xPix - xr + 1.5;
                  dy = yPix - yr + 1.5;
 */
                  xPix = (int)(xr);
                  yPix = (int)(yr);
                  dx = xPix - xr + 1.0;
                  dy = yPix - yr + 1.0;

                  /* Force pixel values to fall within the image boundaries */
                  if (xPix < 0) { xPix = 0; dx = 1.0; }
                  if (yPix < 0) { yPix = 0; dy = 1.0; }
                  if (xPix >= pNaxis[0]-1) { xPix = pNaxis[0]-2; dx = 0.0; }
                  if (yPix >= pNaxis[1]-1) { yPix = pNaxis[1]-2; dy = 0.0; }

                  pStart[0] = xPix;
                  pStart[1] = yPix;
                  pEnd[0] = xPix + 1;
                  pEnd[1] = yPix + 1;

                  /* Create array of weights */
                  pWeight[0] =    dx  *    dy  ;
                  pWeight[1] = (1-dx) *    dy  ;
                  pWeight[2] =    dx  * (1-dy) ;
                  pWeight[3] = (1-dx) * (1-dy) ;

                  /* Read 2x2 array from data file */
                  fits_read_subimg_(pFileIn, nHead, pHead, pStart, pEnd,
                   &nSubimg, &pSubimg);

                  pOutput[iGal] = 0.0;
                  for (jj=0; jj < 4; jj++)
                   pOutput[iGal] += pWeight[jj] * pSubimg[jj];

                  fits_free_axes_(&numAxes, &pNaxis);
                  ccfree_((void **)&pSubimg);

                  if (qVerbose != 0)
                   printf("%8.3f %7.3f %1d %9.3f %9.3f %12.5e\n",
                   pGall[iGal], pGalb[iGal], iloop, xr, yr, pOutput[iGal]);

               }  /* -- END NEAREST PIXEL OR INTERPOLATE -- */
            }
         }
      }

   } else {  /* READ FULL IMAGE */

      pIndx = ccivector_build_(nGal);
      pXPix = ccivector_build_(nGal);
      pYPix = ccivector_build_(nGal);
      if (qInterp != 0) {
         pDX = ccvector_build_(nGal);
         pDY = ccvector_build_(nGal);
      }

      /* Loop through first NGP then SGP */
      for (iloop=0; iloop < 2; iloop++) {

         /* Determine the indices of data points in this hemisphere */
         nIndx = 0;
         for (iGal=0; iGal < nGal; iGal++) {
            if (pNS[iGal] == iloop) {
               pIndx[nIndx] = iGal;
               nIndx++;
            }
         }

         /* Do not continue if no data points in this hemisphere */
         if (nIndx > 0) {

            /* Read FITS header for this projection */
            if (iloop == 0) pFileIn = pFileN; else pFileIn = pFileS;
            fits_read_file_fits_header_only_(pFileIn, &nHead, &pHead);

            if (qInterp == 0) {  /* NEAREST PIXELS */

               /* Determine the nearest pixel coordinates */
               for (ii=0; ii < nIndx; ii++) {
                  lambert_lb2pix(pGall[pIndx[ii]], pGalb[pIndx[ii]],
                   nHead, pHead, &pXPix[ii], &pYPix[ii]);
               }

               pStart[0] = ivector_minimum(nIndx, pXPix);
               pEnd[0] = ivector_maximum(nIndx, pXPix);
               pStart[1] = ivector_minimum(nIndx, pYPix);
               pEnd[1] = ivector_maximum(nIndx, pYPix);

               /* Read smallest subimage containing all points in this hemi */
               fits_read_subimg_(pFileIn, nHead, pHead, pStart, pEnd,
                &nSubimg, &pSubimg);
               xsize = pEnd[0] - pStart[0] + 1;

               /* Determine data values */
               for (ii=0; ii < nIndx; ii++) {
                  pOutput[pIndx[ii]] = pSubimg[ pXPix[ii]-pStart[0] +
                   (pYPix[ii]-pStart[1]) * xsize ];

               }

               ccfree_((void **)&pSubimg);

            } else {  /* INTERPOLATE */

               fits_compute_axes_(&nHead, &pHead, &numAxes, &pNaxis);

               /* Determine the fractional pixel coordinates */
               for (ii=0; ii < nIndx; ii++) {
                  lambert_lb2fpix(pGall[pIndx[ii]], pGalb[pIndx[ii]],
                   nHead, pHead, &xr, &yr);
/* The following 4 lines introduced an erroneous 1/2-pixel shift
   (DJS 03-Mar-2004).
                  pXPix[ii] = (int)(xr-0.5);
                  pYPix[ii] = (int)(yr-0.5);
                  pDX[ii] = pXPix[ii] - xr + 1.5;
                  pDY[ii] = pYPix[ii] - yr + 1.5;
*/
                  pXPix[ii] = (int)(xr);
                  pYPix[ii] = (int)(yr);
                  pDX[ii] = pXPix[ii] - xr + 1.0;
                  pDY[ii] = pYPix[ii] - yr + 1.0;

                  /* Force pixel values to fall within the image boundaries */
                  if (pXPix[ii] < 0) { pXPix[ii] = 0; pDX[ii] = 1.0; }
                  if (pYPix[ii] < 0) { pYPix[ii] = 0; pDY[ii] = 1.0; }
                  if (pXPix[ii] >= pNaxis[0]-1)
                   { pXPix[ii] = pNaxis[0]-2; pDX[ii] = 0.0; }
                  if (pYPix[ii] >= pNaxis[1]-1)
                   { pYPix[ii] = pNaxis[1]-2; pDY[ii] = 0.0; }

               }

               pStart[0] = ivector_minimum(nIndx, pXPix);
               pEnd[0] = ivector_maximum(nIndx, pXPix) + 1;
               pStart[1] = ivector_minimum(nIndx, pYPix);
               pEnd[1] = ivector_maximum(nIndx, pYPix) + 1;

               /* Read smallest subimage containing all points in this hemi */
               fits_read_subimg_(pFileIn, nHead, pHead, pStart, pEnd,
                &nSubimg, &pSubimg);
               xsize = pEnd[0] - pStart[0] + 1;

               /* Determine data values */
               for (ii=0; ii < nIndx; ii++) {
                  /* Create array of weights */
                  pWeight[0] =    pDX[ii]  *    pDY[ii]  ;
                  pWeight[1] = (1-pDX[ii]) *    pDY[ii]  ;
                  pWeight[2] =    pDX[ii]  * (1-pDY[ii]) ;
                  pWeight[3] = (1-pDX[ii]) * (1-pDY[ii]) ;

                  pOutput[pIndx[ii]] =
                    pWeight[0] * pSubimg[
                     pXPix[ii]-pStart[0]   + (pYPix[ii]-pStart[1]  )*xsize ]
                   +pWeight[1] * pSubimg[
                     pXPix[ii]-pStart[0]+1 + (pYPix[ii]-pStart[1]  )*xsize ]
                   +pWeight[2] * pSubimg[
                     pXPix[ii]-pStart[0]   + (pYPix[ii]-pStart[1]+1)*xsize ]
                   +pWeight[3] * pSubimg[
                     pXPix[ii]-pStart[0]+1 + (pYPix[ii]-pStart[1]+1)*xsize ] ;

               }

               fits_free_axes_(&numAxes, &pNaxis);
               ccfree_((void **)&pSubimg);

            }  /* -- END NEAREST PIXEL OR INTERPOLATE -- */
         }

      }

      ccivector_free_(pIndx);
      ccivector_free_(pXPix);
      ccivector_free_(pYPix);
      if (qInterp != 0) {
         ccvector_free_(pDX);
         ccvector_free_(pDY);
      }
   }

   /* Free the memory allocated for the FITS header 
      (Moved outside previous brace by Chris Stoughton 19-Jan-1999) */
   fits_dispose_array_(&pHead);

   /* Deallocate output data array */
   ccivector_free_(pNS);

   return pOutput;
}