SkyMetricTest.c

Go to the documentation of this file.
00001 /*
00002 *  Copyright (C) 2007 Teviet Creighton
00003 *
00004 *  This program is free software; you can redistribute it and/or modify
00005 *  it under the terms of the GNU General Public License as published by
00006 *  the Free Software Foundation; either version 2 of the License, or
00007 *  (at your option) any later version.
00008 *
00009 *  This program is distributed in the hope that it will be useful,
00010 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 *  GNU General Public License for more details.
00013 *
00014 *  You should have received a copy of the GNU General Public License
00015 *  along with with program; see the file COPYING. If not, write to the
00016 *  Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00017 *  MA  02111-1307  USA
00018 */
00019 
00020 /******************************** <lalVerbatim file="SkyMetricTestCV">
00021 Author: Creighton, T. D.
00022 $Id: SkyMetricTest.c,v 1.3 2007/06/08 14:41:52 bema Exp $
00023 **************************************************** </lalVerbatim> */
00024 
00025 /********************************************************** <lalLaTeX>
00026 
00027 \subsection{Program \texttt{SkyMetricTest.c}}
00028 \label{ss:SkyMetricTest.c}
00029 
00030 Computes the sky-position metric for a coherent or semicoherent pulsar
00031 search.
00032 
00033 \subsubsection*{Usage}
00034 \begin{verbatim}
00035 SkyMetricTest [-o metricfile rangefile] [-p n dt t0 f0] [-l lat lon]
00036               [-r ra1 ra2 dec1 dec2] [-d debuglevel]
00037 \end{verbatim}
00038 
00039 \subsubsection*{Description}
00040 
00041 This test program computes the parameter metric for the
00042 two-dimensional sky-position pulsar stack search, over a grid of
00043 points on the sky.  The following option flags are accepted:
00044 \begin{itemize}
00045 \item[\texttt{-o}] Prints the metric grid and a grid specifying the
00046 parameter ranges to the files \verb@metricfile@ and \verb@rangefile@,
00047 respectively, using the standard formatting routine
00048 \verb@LALSWriteGrid()@ in the \verb@support@ package.  See below for a
00049 description of these two grids.  If absent, the routines are
00050 exercised, but no output is written.
00051 \item[\texttt{-p}] Sets the search parameters: the number of stacks
00052 \verb@n@, the length of each stack \verb@dt@ (in seconds), and the
00053 start time of the first stack \verb@t0@ (in seconds of GPS time), and
00054 the maximum source frequency \verb@f0@ (in Hz).  If absent,
00055 \verb@-t 1 86400 0 1000@ is assumed.
00056 \item[\texttt{-l}] Sets the detector latitude to \verb@lat@ (in
00057 degrees north from the equator) and longitude to \verb@lon@ (in
00058 degrees east of the prime meridian).  If absent,
00059 \verb@-l 52.247 9.822@ (GEO600) is assumed.
00060 \item[\texttt{-r}] Sets the ``box'' on the sky to be covered: with
00061 right ascension in the range [\verb@ra1@,\verb@ra2@] and declination
00062 in the range [\verb@ra1@,\verb@ra2@], in degrees.  If absent,
00063 \verb@-r 188.8594813 196.8594813 23.1282511 31.1282511@ is assumed (an
00064 $8^\circ$ square centred on the Galactic core).
00065 \item[\texttt{-d}] Sets the debug level to \verb@debuglevel@; if
00066 absent, \verb@-d 0@ is assumed.
00067 \end{itemize}
00068 
00069 \paragraph{Grid formats:} The metric grid is stored as a
00070 \verb@REAL4Grid@ with physical dimension 2 and data dimesnion 3: for
00071 each point in the two-dimensional sky grid $(\delta,\alpha)$,
00072 representing declination and right ascension, it stores a 3-element
00073 vector consisting of the three metric components $g_{\delta\delta}$,
00074 $g_{\alpha\alpha}$, and $g_{\alpha\delta}$, in that order.  The
00075 coordinates are given in degrees, and the metric components in
00076 $\mathrm{degrees}^{-2}$.
00077 
00078 The range grid stores the parameter space boundaries as a
00079 \verb@REAL4Grid@ with physical dimension 1 and data dimension 2: for
00080 each grid point in the right ascension, it stores a 2-element vector
00081 consisting of the lower and upper values of declination for that right
00082 ascension.  Both coordinates are given in degrees.
00083 
00084 \subsubsection*{Exit codes}
00085 ****************************************** </lalLaTeX><lalErrTable> */
00086 #define SKYMETRICTESTC_ENORM 0
00087 #define SKYMETRICTESTC_ESUB  1
00088 #define SKYMETRICTESTC_EARG  2
00089 #define SKYMETRICTESTC_EVAL  3
00090 #define SKYMETRICTESTC_EMEM  4
00091 #define SKYMETRICTESTC_ERNG  5
00092 #define SKYMETRICTESTC_EFILE 6
00093 
00094 #define SKYMETRICTESTC_MSGENORM "Normal exit"
00095 #define SKYMETRICTESTC_MSGESUB  "Subroutine failed"
00096 #define SKYMETRICTESTC_MSGEARG  "Error parsing arguments"
00097 #define SKYMETRICTESTC_MSGEVAL  "Input argument out of valid range"
00098 #define SKYMETRICTESTC_MSGEMEM  "Memory allocation error"
00099 #define SKYMETRICTESTC_MSGERNG  "Could not find area with valid metric"
00100 #define SKYMETRICTESTC_MSGEFILE "Could not open file"
00101 /******************************************** </lalErrTable><lalLaTeX>
00102 
00103 \subsubsection*{Algorithm}
00104 
00105 After parsing the command-line inputs, this program defines a grid
00106 covering the desired space, and determines the metric using the
00107 routines \verb@LALStackMetric()@ and \verb@LALProjectMetric()@ with
00108 the canonical time routine \verb@LALDTBaryPtolemaic()@.  These
00109 routines return uncertainties along with their best-estimate
00110 components, so we adopt a (perhaps overly) conservative approach: each
00111 component is adjusted up or down by up to $1\sigma$ of estimated
00112 uncertainty, in such a way as to maximize the metric determinant.
00113 This will tend to give \emph{over}coverage of the parameter space.  If
00114 the uncertainty in a component is larger than the component itself,
00115 then a warning is generated.  If the final metric has non-positive
00116 diagonal components or determinant, then the parameter space range is
00117 shortened to exclude these points.  These degeneracies usually occur
00118 at points near the poles for very short observation times, where there
00119 is almost no modulation of the signal; usually in these cases an
00120 unmodulated template will suffice to cover the excluded regions of the
00121 parameter space.
00122 
00123 The metric and range grids are written to the output file by the
00124 routine \verb@LALSWriteGrid()@, from which they can be read using
00125 \verb@LALSReadGrid()@ in template-placement programs such as
00126 \verb@TwoDMeshTest@.
00127 
00128 \paragraph{Note:} This program, like the \verb@DTBaryPtolemaic()@
00129 phase model it relies on, uses right ascension and declination as its
00130 parameter basis.  Since these are polar coordinates, they will go
00131 singular at the poles regardless of the actual Doppler phase
00132 modulation: specifically, the $g_{\alpha\alpha}$ and
00133 $g_{\alpha\delta}$ metric components will go to zero, leading to
00134 equimatch ellipses that are highly elongated in the $\alpha$
00135 direction.
00136 
00137 This gives rise to problems in template placement using the routines
00138 in \verb@TwoDMesh.h@, \emph{if} columns are arranged along the
00139 declination axis, since ellipse size and shape varies greatly along
00140 the length of a column.  The problems largely go away if the columns
00141 are arranged along the right ascension axis, where ellipse variations
00142 are less severe.  This routine therefore orients the sky parameter
00143 space so that declination runs along the first ($x$) axis and right
00144 ascension along the second ($y$) axis.
00145 
00146 \subsubsection*{Uses}
00147 \begin{verbatim}
00148 lalDebugLevel
00149 LALPrintError()                 LALCheckMemoryLeaks()
00150 LALMalloc()                     LALFree()
00151 LALDCreateVector()              LALDDestroyVector()
00152 LALU4CreateVector()             LALU4DestroyVector()
00153 LALSCreateGrid()                LALSDestroyGrid()
00154 LALSWriteGrid()                 LALSnprintf()
00155 LALStackMetric()                LALProjectMetric()
00156 LALDTBaryPtolemaic()            LALGetEarthTimes()
00157 \end{verbatim}
00158 
00159 \subsubsection*{Notes}
00160 
00161 \vfill{\footnotesize\input{SkyMetricTestCV}}
00162 
00163 ******************************************************* </lalLaTeX> */
00164 
00165 #include <math.h>
00166 #include <stdlib.h>
00167 #include <lal/LALStdlib.h>
00168 #include <lal/LALStdio.h>
00169 #include <lal/LALConstants.h>
00170 #include <lal/AVFactories.h>
00171 #include <lal/Grid.h>
00172 #include <lal/StreamOutput.h>
00173 #include <lal/StackMetric.h>
00174 #include <lal/PulsarTimes.h>
00175 
00176 NRCSID( SKYMETRICTESTC, "$Id: SkyMetricTest.c,v 1.3 2007/06/08 14:41:52 bema Exp $" );
00177 
00178 /* Default parameter settings. */
00179 int lalDebugLevel = 0;
00180 #define NSTACKS 1
00181 #define STACKLENGTH 86400.0 /* arbitrary */
00182 #define STARTTIME 0.0       /* arbitrary */
00183 #define LATITUDE  52.247    /* GEO600 location */
00184 #define LONGITUDE 9.822     /* GEO600 location */
00185 #define FREQUENCY 1000.0    /* arbitrary */
00186 #define RA_MIN 188.8594813  /* Galactic core search */
00187 #define RA_MAX 196.8594813  /* Galactic core search */
00188 #define DEC_MIN 23.1282511  /* Galactic core search */
00189 #define DEC_MAX 31.1282511  /* Galactic core search */
00190 #define MISMATCH 0.25       /* arbitrary but reasonably optimal */
00191 
00192 /* Usage format string. */
00193 #define USAGE "Usage: %s [-o metricfile rangefile] [-p n dt t0 f0]\n" \
00194 "\t[-l lat lon] [-r ra1 ra2 dec1 dec2] [-d debuglevel]\n"
00195 
00196 /* Input error checking: Some accepted parameter ranges. */
00197 #define NMAX  10000 /* 1 <= number of stacks <= NMAX */
00198 #define DTMAX  3e10 /* 1/f_0 < stack length <= DTMAX */
00199 #define F0MAX  1e4  /* 0 < f_0 <= FOMAX */
00200 /* Also: |latitude|  will be restricted to <= LAL_PI,
00201          |longitude| will be restricted to <= LAL_TWOPI
00202          mismatch    will be restricted to (0,1] */
00203 
00204 /* Other internal constants. */
00205 #define SPACING 5.0 /* maximum spacing between grid points (degrees) */
00206 #define MSGLEN 1024 /* maximum warning message length */
00207 
00208 
00209 /* Macros for printing errors and testing subroutines. */
00210 #define ERROR( code, msg, statement )                                \
00211 do                                                                   \
00212 if ( lalDebugLevel & LALERROR )                                      \
00213 {                                                                    \
00214   LALPrintError( "Error[0] %d: program %s, file %s, line %d, %s\n"   \
00215                  "        %s %s\n", (code), *argv, __FILE__,         \
00216                  __LINE__, SKYMETRICTESTC, statement ? statement :   \
00217                  "", (msg) );                                        \
00218 }                                                                    \
00219 while (0)
00220 
00221 #define WARNING( statement )                                         \
00222 do                                                                   \
00223 if ( lalDebugLevel & LALWARNING )                                    \
00224 {                                                                    \
00225   LALPrintError( "Warning[0]: program %s, file %s, line %d, %s\n"    \
00226                  "        %s\n", *argv, __FILE__, __LINE__,          \
00227                  SKYMETRICTESTC, (statement) );                      \
00228 }                                                                    \
00229 while (0)
00230 
00231 #define INFO( statement )                                            \
00232 do                                                                   \
00233 if ( lalDebugLevel & LALINFO )                                       \
00234 {                                                                    \
00235   LALPrintError( "Info[0]: program %s, file %s, line %d, %s\n"       \
00236                  "        %s\n", *argv, __FILE__, __LINE__,          \
00237                  SKYMETRICTESTC, (statement) );                      \
00238 }                                                                    \
00239 while (0)
00240 
00241 #define SUB( func, statusptr )                                       \
00242 do                                                                   \
00243 if ( (func), (statusptr)->statusCode )                               \
00244 {                                                                    \
00245   ERROR( SKYMETRICTESTC_ESUB, SKYMETRICTESTC_MSGESUB,                \
00246          "Function call \"" #func "\" failed:" );                    \
00247   return SKYMETRICTESTC_ESUB;                                        \
00248 }                                                                    \
00249 while (0)
00250 
00251 #define CHECKVAL( val, lower, upper )                                \
00252 do                                                                   \
00253 if ( ( (val) <= (lower) ) || ( (val) > (upper) ) )                   \
00254 {                                                                    \
00255   ERROR( SKYMETRICTESTC_EVAL, SKYMETRICTESTC_MSGESUB,                \
00256          "Value of " #val " out of range:" );                        \
00257   LALPrintError( #val " = %f, range = (%f,%f]\n", (REAL8)(val),      \
00258                  (REAL8)(lower), (REAL8)(upper) );                   \
00259   return SKYMETRICTESTC_EVAL;                                        \
00260 }                                                                    \
00261 while (0)
00262 
00263 /* A global pointer for debugging. */
00264 #ifndef NDEBUG
00265 char *lalWatch;
00266 #endif
00267 
00268 int
00269 main(int argc, char **argv)
00270 {
00271   /* Variables for parsing command-line arguments. */
00272   INT4  arg;               /* argument list counter */
00273   CHAR *metricfile = NULL; /* metric output filename */
00274   CHAR *rangefile = NULL;  /* parameter range output filename */
00275   UINT4 n = NSTACKS;       /* number of stacks */
00276   REAL8 dt = STACKLENGTH;  /* length of each stack (s) */
00277   REAL8 t0 = STARTTIME;    /* start time of first stack (GPS s) */
00278   REAL8 f0 = FREQUENCY;    /* maximum frequency of search */
00279   REAL8 lat = LATITUDE;    /* latitude of detector (degrees N) */
00280   REAL8 lon = LONGITUDE;   /* longitude of detector (degrees E) */
00281   REAL8 ra[2], dec[2];     /* RA and dec ranges (degrees) */
00282 
00283   /* Other variables. */
00284   UINT4 i, j, k;                 /* indecies */
00285   UINT4 nRA, nDec;               /* sizes of metric grid in RA and dec */
00286   REAL8 dRA, dDec;               /* grid intervals in RA and dec */
00287   UINT4 warnings = 0;            /* points with large uncertainties */
00288   UINT4 errors = 0;              /* points with bad metrics */
00289   static LALStatus stat;         /* top-level status structure */
00290   static LIGOTimeGPS start;      /* GPS start time of first stack */
00291   REAL4Grid *metricGrid = NULL;  /* grid of metric values */
00292   REAL4 *gData;                  /* pointer to metricGrid->data->data */
00293   REAL4Grid *rangeGrid = NULL;   /* grid of range delimiters */
00294   REAL4 *rData;                  /* pointer to rangeGrid->data->data */
00295   REAL4 propVol = 0.0;           /* average proper volume element */
00296   UINT4 nVol = 0;                /* number of points used in average */
00297   UINT4Vector *dimLength = NULL; /* used to allocate metricGrid */
00298   REAL8Vector *lambda = NULL;    /* metric parameter space vector */
00299   REAL8Vector *metric = NULL;    /* metric components */
00300   REAL8 *mData;                  /* pointer to metric->data */
00301   INT4 *topRange, *botRange;     /* preliminary grid range limits */
00302   INT4 *topRange2, *botRange2;   /* adjusted grid range limits */
00303   static MetricParamStruc params; /* metric computation parameters */
00304   static PulsarTimesParamStruc baryParams; /* barycentring parameters */
00305 
00306   /* Some more initializations. */
00307   ra[0] = RA_MIN; dec[0] = DEC_MIN;
00308   ra[1] = RA_MAX; dec[1] = DEC_MAX;
00309 
00310   /******************************************************************
00311    * ARGUMENT PARSING                                               *
00312    ******************************************************************/
00313 
00314   /* Parse argument list.  arg stores the current position. */
00315   arg = 1;
00316   while ( arg < argc ) {
00317     /* Parse output file option. */
00318     if ( !strcmp( argv[arg], "-o" ) ) {
00319       if ( argc > arg + 2 ) {
00320         arg++;
00321         metricfile = argv[arg++];
00322         rangefile = argv[arg++];
00323       } else {
00324         ERROR( SKYMETRICTESTC_EARG, SKYMETRICTESTC_MSGEARG, 0 );
00325         LALPrintError( USAGE, *argv );
00326         return SKYMETRICTESTC_EARG;
00327       }
00328     }
00329     /* Parse search parameter option. */
00330     else if ( !strcmp( argv[arg], "-p" ) ) {
00331       if ( argc > arg + 4 ) {
00332         arg++;
00333         n = atoi( argv[arg++] );
00334         dt = atof( argv[arg++] );
00335         t0 = atof( argv[arg++] );
00336         f0 = atof( argv[arg++] );
00337       } else {
00338         ERROR( SKYMETRICTESTC_EARG, SKYMETRICTESTC_MSGEARG, 0 );
00339         LALPrintError( USAGE, *argv );
00340         return SKYMETRICTESTC_EARG;
00341       }
00342     }
00343     /* Parse detector position option. */
00344     else if ( !strcmp( argv[arg], "-l" ) ) {
00345       if ( argc > arg + 2 ) {
00346         arg++;
00347         lat = atof( argv[arg++] );
00348         lon = atof( argv[arg++] );
00349       } else {
00350         ERROR( SKYMETRICTESTC_EARG, SKYMETRICTESTC_MSGEARG, 0 );
00351         LALPrintError( USAGE, *argv );
00352         return SKYMETRICTESTC_EARG;
00353       }
00354     }
00355     /* Parse parameter space range option. */
00356     else if ( !strcmp( argv[arg], "-r" ) ) {
00357       if ( argc > arg + 4 ) {
00358         arg++;
00359         ra[0] = atof( argv[arg++] );
00360         ra[1] = atof( argv[arg++] );
00361         dec[0] = atof( argv[arg++] );
00362         dec[1] = atof( argv[arg++] );
00363       } else {
00364         ERROR( SKYMETRICTESTC_EARG, SKYMETRICTESTC_MSGEARG, 0 );
00365         LALPrintError( USAGE, *argv );
00366         return SKYMETRICTESTC_EARG;
00367       }
00368     }
00369     /* Parse debug level option. */
00370     else if ( !strcmp( argv[arg], "-d" ) ) {
00371       if ( argc > arg + 1 ) {
00372         arg++;
00373         lalDebugLevel = atoi( argv[arg++] );
00374       } else {
00375         ERROR( SKYMETRICTESTC_EARG, SKYMETRICTESTC_MSGEARG, 0 );
00376         LALPrintError( USAGE, *argv );
00377         return SKYMETRICTESTC_EARG;
00378       }
00379     }
00380     /* Check for unrecognized options. */
00381     else if ( argv[arg][0] == '-' ) {
00382       ERROR( SKYMETRICTESTC_EARG, SKYMETRICTESTC_MSGEARG, 0 );
00383       LALPrintError( USAGE, *argv );
00384       return SKYMETRICTESTC_EARG;
00385     }
00386   } /* End of argument parsing loop. */
00387 
00388   /* Do error trapping on input parameters. */
00389   if ( lalDebugLevel & LALERROR ) {
00390     CHECKVAL( n, 0, NMAX );
00391     CHECKVAL( f0, 0.0, F0MAX );
00392     CHECKVAL( dt, 1.0/f0, DTMAX );
00393     CHECKVAL( lat, -90.0, 90.0 );
00394     CHECKVAL( lon, -360.0, 360.0 );
00395   }
00396 
00397   /******************************************************************
00398    * METRIC COMPUTATION                                             *
00399    ******************************************************************/
00400 
00401   /* Set up start time. */
00402   start.gpsSeconds = (INT4)t0;
00403   start.gpsNanoSeconds = (INT4)( 1.0e9*( t0 - start.gpsSeconds ) );
00404   t0 = 0.0;
00405 
00406   /* Set up constant parameters for barycentre transformation. */
00407   baryParams.epoch = start;
00408   baryParams.latitude = LAL_PI_180*lat;
00409   baryParams.longitude = LAL_PI_180*lon;
00410   SUB( LALGetEarthTimes( &stat, &baryParams ), &stat );
00411 
00412   /* Set up constant parameters for metric calculation. */
00413   params.dtCanon = LALDTBaryPtolemaic;
00414   params.constants = &baryParams;
00415   params.start = t0;
00416   params.deltaT = dt;
00417   params.n = n;
00418   params.errors = 1;
00419 
00420   /* Set up the metric vector, metric grid, and parameter vector. */
00421   if ( params.errors )
00422     SUB( LALDCreateVector( &stat, &metric, 12 ), &stat );
00423   else
00424     SUB( LALDCreateVector( &stat, &metric, 6 ), &stat );
00425   mData = metric->data;
00426   SUB( LALU4CreateVector( &stat, &dimLength, 3 ), &stat );
00427   nRA = (UINT4)( ( ra[1] - ra[0] )/SPACING ) + 2;
00428   nDec = (UINT4)( ( dec[1] - dec[0] )/SPACING ) + 2;
00429   dimLength->data[0] = nDec;
00430   dimLength->data[1] = nRA;
00431   dimLength->data[2] = 3;
00432   SUB( LALSCreateGrid( &stat, &metricGrid, dimLength, 2 ), &stat );
00433   SUB( LALU4DestroyVector( &stat, &dimLength ), &stat );
00434   metricGrid->offset->data[0] = dec[0];
00435   metricGrid->offset->data[1] = ra[0];
00436   metricGrid->interval->data[0] = dDec = ( dec[1] - dec[0] )/( nDec - 1.0 );
00437   metricGrid->interval->data[1] = dRA = ( ra[1] - ra[0] )/( nRA - 1.0 );
00438   gData = metricGrid->data->data;
00439   SUB( LALDCreateVector( &stat, &lambda, 3 ), &stat );
00440   lambda->data[0] = f0;
00441 
00442   /* Set up preliminary range delimiters. */
00443   topRange = (INT4 *)LALMalloc( nRA*sizeof( INT4 ) );
00444   botRange = (INT4 *)LALMalloc( nRA*sizeof( INT4 ) );
00445   if ( !topRange || !botRange ) {
00446     ERROR( SKYMETRICTESTC_EMEM, SKYMETRICTESTC_MSGEMEM, 0 );
00447     return SKYMETRICTESTC_EMEM;
00448   }
00449   for ( i = 0; i < nRA; i++ ) {
00450     topRange[i] = 0;
00451     botRange[i] = nRA;
00452   }
00453 
00454   /* Fill the metric grid with the projected metric. */
00455   k = 0;
00456   fprintf( stdout, "Computing metric on %ix%i grid:\n", nDec, nRA );
00457   for ( i = 0; i < nDec; i++ ) {
00458     BOOLEAN bottom = 1, top = 0; /* whether we're at the bottom or top
00459                                     of the grid column */
00460     lambda->data[2] = LAL_PI_180*( dec[0] + i*dDec );
00461     for ( j = 0; j < nRA; j++ ) {
00462       if ( top )
00463         fprintf( stdout, "o" );
00464       else {
00465         REAL4 gxx, gyy, gxy; /* metric components */
00466         lambda->data[1] = LAL_PI_180*( ra[0] + j*dRA );
00467         SUB( LALStackMetric( &stat, metric, lambda, &params ), &stat );
00468         SUB( LALProjectMetric( &stat, metric, params.errors ), &stat );
00469 
00470         /* If uncertainties are given, generate conservative metric. */
00471         if ( params.errors ) {
00472           INT2 sign = 1; /* sign of xy metric component */
00473           gxx = mData[10] + mData[11];
00474           gyy = mData[4] + mData[5];
00475           gxy = mData[8];
00476           if ( gxy < 0.0 )
00477             sign = -1;
00478           if ( fabs( gxy ) <= fabs( mData[9] ) )
00479             gxy = 0.0;
00480           else
00481             gxy = sign*( fabs( gxy ) - fabs( mData[9] ) );
00482           if ( gxx < 0.0 || gyy < 0.0 || gxx*gyy - gxy*gxy < 0.0 ) {
00483             errors++;
00484             fprintf( stdout, "o" );
00485           } else if ( fabs( mData[4]*mData[11] ) +
00486                       fabs( mData[5]*mData[10] ) +
00487                       fabs( mData[8]*mData[9] )*2.0 >=
00488                       mData[4]*mData[10] - mData[8]*mData[8] ) {
00489             warnings++;
00490             fprintf( stdout, "*" );
00491           } else
00492             fprintf( stdout, "+" );
00493         }
00494 
00495         /* If uncertainties are not given, just use best estimate. */
00496         else {
00497           gxx = mData[5];
00498           gxy = mData[4];
00499           gyy = mData[2];
00500           if ( gxx < 0.0 || gyy < 0.0 || gxx*gyy - gxy*gxy < 0.0 ) {
00501             errors++;
00502             fprintf( stdout, "o" );
00503           } else
00504             fprintf( stdout, "+" );
00505         }
00506 
00507         /* See whether we've crossed a range boundary. */
00508         if ( gxx > 0.0 && gyy > 0.0 && gxx*gyy - gxy*gxy > 0.0 ) {
00509           if ( bottom ) {
00510             bottom = 0;
00511             botRange[i] = j - 1;
00512           }
00513           propVol += LAL_PI_180*LAL_PI_180*sqrt( gxx*gyy - gxy*gxy );
00514           nVol++;
00515         } else {
00516           if ( !bottom ) {
00517             top = 1;
00518             topRange[i] = j;
00519           }
00520         }
00521         *(gData++) = LAL_PI_180*LAL_PI_180*gxx;
00522         *(gData++) = LAL_PI_180*LAL_PI_180*gyy;
00523         *(gData++) = LAL_PI_180*LAL_PI_180*gxy;
00524       }
00525       fflush( stdout );
00526     }
00527     if ( !top )
00528       topRange[i] = j;
00529     fprintf( stdout, "\n" );
00530   }
00531 
00532   /* Free memory that's no longer needed. */
00533   SUB( LALDDestroyVector( &stat, &metric ), &stat );
00534   SUB( LALDDestroyVector( &stat, &lambda ), &stat );
00535 
00536   /* Warn if any points had bad values or large uncertainties. */
00537   if ( errors ) {
00538     CHAR msg[MSGLEN];
00539     LALSnprintf( msg, MSGLEN, "%i of %i points had"
00540                  " non-positive-definite metric", warnings,
00541                  nRA*nDec );
00542     WARNING( msg );
00543   }
00544   if ( warnings ) {
00545     CHAR msg[MSGLEN];
00546     LALSnprintf( msg, MSGLEN, "%i of %i points had metric component"
00547                  " errors larger than values", warnings, nRA*nDec );
00548     WARNING( msg );
00549   }
00550 
00551   /* Write the proper volume element. */
00552   fprintf( stdout, "Average proper volume element: %10.3e per square"
00553            " degree\n", propVol /= nVol );
00554 
00555   /******************************************************************
00556    * RANGE COMPUTATION                                              *
00557    ******************************************************************/
00558 
00559   /* Each bad metric point affects the four squares adjoining it, so
00560      top and bottom ranges need to be adjusted down or up one point
00561      based on the adjoining columns. */
00562   topRange2 = (INT4 *)LALMalloc( nDec*sizeof(INT4) );
00563   botRange2 = (INT4 *)LALMalloc( nDec*sizeof(INT4) );
00564   if ( !topRange2 || !botRange2 ) {
00565     ERROR( SKYMETRICTESTC_EMEM, SKYMETRICTESTC_MSGEMEM, 0 );
00566     return SKYMETRICTESTC_EMEM;
00567   }
00568   topRange2[0] = topRange[1] < topRange[0] ?
00569     topRange[1] - 1 : topRange[0] - 1;
00570   botRange2[0] = botRange[1] > botRange[0] ?
00571     botRange[1] + 1 : botRange[0] + 1;
00572   topRange2[nDec-1] = topRange[nDec] < topRange[nDec-1] ?
00573     topRange[nDec] - 1 : topRange[nDec-1] - 1;
00574   botRange2[nDec-1] = botRange[nDec] > botRange[nDec-1] ?
00575     botRange[nDec] + 1 : botRange[nDec-1] + 1;
00576   for ( i = 1; i < nDec - 1; i++ ) {
00577     INT4 topMin = topRange[i-1], botMax = botRange[i-1];
00578     if ( topRange[i] < topMin )
00579       topMin = topRange[i];
00580     if ( topRange[i+1] < topMin )
00581       topMin = topRange[i+1];
00582     if ( botRange[i] > botMax )
00583       botMax = botRange[i];
00584     if ( botRange[i+1] > botMax )
00585       botMax = botRange[i+1];
00586     topRange2[i] = topMin - 1;
00587     botRange2[i] = botMax + 1;
00588   }
00589   LALFree( topRange );
00590   LALFree( botRange );
00591 
00592   /* Determine the contiguous domain with open range intervals. */
00593   if ( topRange2[0] > botRange2[0] && topRange2[1] > botRange2[1] )
00594     i = 0;
00595   else {
00596     i = 1;
00597     while ( i < nDec - 1 && topRange2[i] <= botRange2[i] &&
00598             topRange2[i+1] <= botRange2[i+1] )
00599       i++;
00600   }
00601   j = i;
00602   while ( j < nDec - 1 && topRange2[j+1] > botRange2[j+1] )
00603     j++;
00604   if ( j == i ) {
00605     ERROR( SKYMETRICTESTC_ERNG, SKYMETRICTESTC_MSGERNG, 0 );
00606     return SKYMETRICTESTC_ERNG;
00607   }
00608 
00609   /* Set up range grid. */
00610   j = j - i + 1;
00611   SUB( LALU4CreateVector( &stat, &dimLength, 2 ), &stat );
00612   dimLength->data[0] = j;
00613   dimLength->data[1] = 2;
00614   SUB( LALSCreateGrid( &stat, &rangeGrid, dimLength, 1 ), &stat );
00615   SUB( LALU4DestroyVector( &stat, &dimLength ), &stat );
00616   rangeGrid->offset->data[0] = dec[0] + i*dDec;
00617   rangeGrid->interval->data[0] = dDec;
00618   rData = rangeGrid->data->data;
00619   nVol = 0;
00620   for ( k = 0; k < j; k++ ) {
00621     *(rData++) = ra[0] + botRange2[k]*dRA;
00622     *(rData++) = ra[0] + topRange2[k]*dRA;
00623     nVol += topRange2[k] - botRange2[k] - 1;
00624   }
00625   nVol -= topRange2[j-1] - botRange2[j-1] - 1;
00626   LALFree( topRange2 );
00627   LALFree( botRange2 );
00628 
00629   /* Write the total proper volume of the covered range. */
00630   fprintf( stdout, "Total proper volume:           %10.3e\n",
00631            propVol*nVol*dRA*dDec );
00632 
00633   /******************************************************************
00634    * FINISH                                                         *
00635    ******************************************************************/
00636 
00637   /* Write the output files, if requested. */
00638   if ( metricfile ) {
00639     FILE *fp = fopen( metricfile, "w" ); /* output file pointer */
00640     if ( !fp ) {
00641       ERROR( SKYMETRICTESTC_EFILE, "- " SKYMETRICTESTC_MSGEFILE,
00642              metricfile );
00643       return SKYMETRICTESTC_EFILE;
00644     }
00645     SUB( LALSWriteGrid( &stat, fp, metricGrid ), &stat );
00646     fclose( fp );
00647   }
00648   if ( rangefile ) {
00649     FILE *fp = fopen( rangefile, "w" ); /* output file pointer */
00650     if ( !fp ) {
00651       ERROR( SKYMETRICTESTC_EFILE, "- " SKYMETRICTESTC_MSGEFILE,
00652              rangefile );
00653       return SKYMETRICTESTC_EFILE;
00654     }
00655     SUB( LALSWriteGrid( &stat, fp, rangeGrid ), &stat );
00656     fclose( fp );
00657   }
00658 
00659   /* Clean up and exit. */
00660   SUB( LALSDestroyGrid( &stat, &metricGrid ), &stat );
00661   SUB( LALSDestroyGrid( &stat, &rangeGrid ), &stat );
00662   LALCheckMemoryLeaks();
00663   INFO( SKYMETRICTESTC_MSGENORM );
00664   return SKYMETRICTESTC_ENORM;
00665 }

Generated on Thu Aug 28 03:12:50 2008 for LAL by  doxygen 1.5.2