TwoDMeshTest.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="TwoDMeshTestCV">
00021 Author: Creighton, T. D.
00022 $Id: TwoDMeshTest.c,v 1.8 2007/06/08 14:41:52 bema Exp $
00023 **************************************************** </lalVerbatim> */
00024 
00025 /********************************************************** <lalLaTeX>
00026 
00027 \subsection{Program \texttt{TwoDMeshTest.c}}
00028 \label{ss:TwoDMeshTest.c}
00029 
00030 Creates a 2-dimensional template mesh for linearly-changing mismatch
00031 ellipses.
00032 
00033 \subsubsection*{Usage}
00034 \begin{verbatim}
00035 TwoDMeshTest [-o outfile] [-p psfile flags] [-d debug] [-m mismatch nmax cmax]
00036              [-i metricfile rangefile] [-b x1 y1 x2 y2 ] [-e a b c]
00037              [-x dadx dbdx dcdx] [-y dady dbdy dcdy]
00038 \end{verbatim}
00039 
00040 \subsubsection*{Description}
00041 
00042 This test program creates a template mesh for a parameter space with
00043 an arbitrary mismatch metric.  The following option flags are
00044 accepted:
00045 \begin{itemize}
00046 \item[\texttt{-o}] Writes the output mesh list to the file
00047 \verb@outfile@.  If absent, no output is written.
00048 \item[\texttt{-p}] Plots the output mesh in a PostScript file
00049 \verb@psfile@, using plot flags \verb@flags@ (see below).  If absent,
00050 no plot is made.
00051 \item[\texttt{-d}] Sets the debug level to \verb@debug@.  If
00052 absent, a debug level of zero is used.
00053 \item[\texttt{-m}] Sets the maximum mismatch to \verb@mismatch@,
00054 maximum number of mesh points to \verb@nmax@ and the maximum estimated
00055 number of columns to \verb@cmax@.  If \verb@mismatch@ is not in the
00056 range (0,1], it is taken to be 1.  If \verb@nmax@ or \verb@cmax@ is
00057 non-positive, it is ignored (no maximum).  If this option is not
00058 given, \verb@-m 1 0 0@ is assumed.
00059 \item[\texttt{-i}] Determines the metric and the parameter space
00060 boundary from \verb@REAL4Grid@ structures stored in the files
00061 \verb@metricfile@ and \verb@rangefile@, read using the generic parser
00062 \verb@LALSReadGrid()@.  The formats for these grids are discussed
00063 below.  If present, this option \emph{overrides} the \verb@-b@,
00064 \verb@-e@, \verb@-x@, and \verb@-y@ options, below.  If absent, these
00065 options, or their defaults, will be used.
00066 \item[\texttt{-b}] Sets the parameter space boundary to be a
00067 parallelogram defined by the vectors (\verb@x1@,\verb@y1@) and
00068 (\verb@x2@,\verb@y2@) from the origin.  If absent, the region is
00069 taken to be a unit square.
00070 \item[\texttt{-e}] Sets the parameters of the mismatch ellipse at the
00071 origin: its principal axis lengths are \verb@a@ and \verb@b@ units,
00072 and the angle from the $x$-axis to the first principal axis is
00073 \verb@c@ radians.  If absent, \verb@-e 0.1 0.05 1@ is assumed.
00074 \item[\texttt{-x}] Sets the rates of change in the $x$-direction of
00075 \verb@a@, \verb@b@, and \verb@c@ (above) to \verb@dadx@, \verb@dbdx@,
00076 and \verb@dcdx@, respectively.  If absent, the rates are taken to be
00077 zero.
00078 \item[\texttt{-y}] Sets the rates of change in the $y$-direction of
00079 \verb@a@, \verb@b@, and \verb@c@ (above) to \verb@dady@, \verb@dbdy@,
00080 and \verb@dcdy@, respectively.  If absent, the rates are taken to be
00081 zero.
00082 \end{itemize}
00083 
00084 
00085 \subsubsection*{Exit codes}
00086 ****************************************** </lalLaTeX><lalErrTable> */
00087 #define TWODMESHTESTC_ENORM   0
00088 #define TWODMESHTESTC_ESUB    1
00089 #define TWODMESHTESTC_EARG    2
00090 #define TWODMESHTESTC_EBAD    3
00091 #define TWODMESHTESTC_EMEM    4
00092 #define TWODMESHTESTC_EFILE   5
00093 #define TWODMESHTESTC_EMETRIC 6
00094 
00095 #define TWODMESHTESTC_MSGENORM   "Normal exit"
00096 #define TWODMESHTESTC_MSGESUB    "Subroutine failed"
00097 #define TWODMESHTESTC_MSGEARG    "Error parsing arguments"
00098 #define TWODMESHTESTC_MSGEBAD    "Bad argument value"
00099 #define TWODMESHTESTC_MSGEMEM    "Memory allocation error"
00100 #define TWODMESHTESTC_MSGEFILE   "Could not open file"
00101 #define TWODMESHTESTC_MSGEMETRIC "Axis length is zero or negative within specified region"
00102 /******************************************** </lalErrTable><lalLaTeX>
00103 
00104 \subsubsection*{Algorithm}
00105 
00106 The test program reads the input arguments and creates a parameter
00107 structure \verb@*params@ to be passed to \verb@LALCreateTwoDMesh()@.
00108 In particular, it computes the domain of the parameter space, and
00109 defines functions and parameter lists to compute the range in $y$ at
00110 any $x$, and the metric at any point $(x,y)$.  If PostScript output is
00111 requested, it is generated using \verb@LALPlotTwoDMesh()@, using the
00112 value of the command-line number \verb@flags@ to set the plotting
00113 parameters.  Each of these functions is discussed below.
00114 
00115 \paragraph{Metric and range grid files:}  If the \verb@-i@ option was
00116 given, the metric and parameter ranges are read from the files named
00117 by the \verb@metricfile@ and \verb@rangefile@ arguments.  These two
00118 files must be in a format parseable by \verb@LALSReadGrid()@; see the
00119 documentation of that routine for more details.
00120 
00121 The \verb@REAL4Grid@ extracted from \verb@metricfile@ must
00122 have grid dimension 2 and data dimension 3: the grid dimensions refer
00123 to the $(x,y)$ coordinates of the points where the metric is
00124 evaluated, while the third dimension must have length 3, storing the
00125 metric components $g_{xx}$, $g_{yy}$, and $g_{xy}$ (in that order) at
00126 each point.  Within the \verb@TwoDMesh.h@ routines, this metric grid
00127 is interpolated using \verb@LALInterpolateMetricGrid()@.
00128 
00129 The \verb@REAL4Grid@ extracted from \verb@rangefile@ must have grid
00130 dimension 1 and data dimension 2: the grid dimension refers to an $x$
00131 coordinate, and the second dimension must have length 3, storing the
00132 lower and upper boundaries $y_1(x)$ and $y_2(x)$ at each sampled value
00133 of $x$.  Within the \verb@TwoDMesh.h@ routines, this range grid is
00134 interpolated using \verb@LALInterpolateRangeGrid()@.
00135 
00136 If the \verb@-i@ option is \emph{not} given, then the parameter
00137 boundary and metric are determined by internal routines, with default
00138 settings that can be overridden using command-line options \verb@-p@,
00139 \verb@-e@, \verb@-x@, and \verb@-y@.
00140 
00141 \paragraph{Parameter ranges:} The parameter space boundary can be
00142 specified by input parameters \verb@x1@$=x_1$, \verb@x2@$=x_2$,
00143 \verb@y1@$=y_1$, and \verb@y2@$=y_2$.  The parameter space is then
00144 defined to be a parallelogram with one corner on the origin, and two
00145 sides defined by vectors $(x_1,y_1)$ and $(x_2,y_2)$.  Without loss of
00146 generality we assume that $x_1<x_2$.  The functions defining the
00147 boundaries are denoted $y_{a,b}(x)$, and we make no assumption about
00148 their signs or relative order.  The algorithm used then depends on the
00149 signs of $x_1$ and $x_2$.
00150 
00151 \medskip\noindent
00152 If $x_1=x_2=0$, then the parameter space is singular, and no mesh need
00153 be generated.
00154 
00155 \medskip\noindent
00156 If $x_1=0$ and $x_2\neq0$, then the domain is $[0,x_2]$, and the
00157 boundary functions are:
00158 \begin{eqnarray}
00159 y_a(x) & = & y_2x/x_2 \nonumber\\
00160 y_b(x) & = & y_1 + y_2x/x_2 \nonumber
00161 \end{eqnarray}
00162 
00163 \noindent
00164 If $x_2=0$ and $x_1\neq0$, then the domain is $[x_1,0]$, and the above
00165 equations for $y_{a,b}(x)$ simply have 1 and 2 reversed.
00166 
00167 \medskip\noindent
00168 If $x_1$ and $x_2$ have the same sign, then the domain is
00169 $[0,x_1+x_2]$ if $x_1$ and $x_2$ are positive, and $[x_1+x_2,0]$
00170 otherwise.  The boundary functions are:
00171 \begin{eqnarray}
00172 y_a(x) & = & \left\{\begin{array}{c@{\qquad}c}
00173         y_1x/x_1             & x\mathrm{~between~}0\mathrm{~and~}x_1 \\
00174         y_1 + y_2(x-x_1)/x_2 & x\mathrm{~between~}x_1\mathrm{~and~}x_1+x_2
00175         \end{array}\right.\nonumber\\
00176 y_b(x) & = & \left\{\begin{array}{c@{\qquad}c}
00177         y_2x/x_2             & x\mathrm{~between~}0\mathrm{~and~}x_2 \\
00178         y_2 + y_1(x-x_2)/x_1 & x\mathrm{~between~}x_2\mathrm{~and~}x_1+x_2
00179         \end{array}\right.\nonumber
00180 \end{eqnarray}
00181 
00182 \noindent
00183 If $x_1$ and $x_2$ have opposite sign, the domain is $[x_1,x_2]$ if
00184 $x_1<0$, and $[x_2,x_1]$ otherwise.  The boundary functions are:
00185 \begin{eqnarray}
00186 y_a(x) & = & \left\{\begin{array}{c@{\qquad}c}
00187         y_1x/x_1 & x\mathrm{~between~}0\mathrm{~and~}x_1 \\
00188         y_2x/x_2 & x\mathrm{~between~}0\mathrm{~and~}x_2
00189         \end{array}\right.\nonumber\\
00190 y_b(x) & = & \left\{\begin{array}{c@{\qquad}c}
00191         y_1 + y_2(x-x_1)/x_2 & x\mathrm{~between~}x_1\mathrm{~and~}x_1+x_2 \\
00192         y_2 + y1(x-x_2)/x_1  & x\mathrm{~between~}x_2\mathrm{~and~}x_1+x_2
00193         \end{array}\right.\nonumber
00194 \end{eqnarray}
00195 
00196 The main program sorts the input parameters so that $x_1\leq x_2$,
00197 stores them in a 4-dimensional array, and assigns a \verb@void@
00198 pointer to that array.  It also computes the domain.  The routine
00199 \verb@LALTwoDRangeTest()@ takes a value of $x$ and the \verb@void@
00200 pointer, computes the values of $y_a(x)$ and $y_b(x)$ according to the
00201 algorithm above, sorts them, and returns them ordered from lower to
00202 higher.
00203 
00204 \paragraph{Metric values:} The main program takes the input parameters
00205 \verb@a@, \verb@b@, \verb@c@, \verb@dadx@, \verb@dbdx@, and
00206 \verb@dcdx@, stores them in a 9-dimensional array, and assigns a
00207 \verb@void@ pointer to it.  The routine \verb@LALTwoDMetricTest()@
00208 takes a position $(x,y)$ and the \verb@void@ pointer, and computes the
00209 ``local'' value of the principal axis
00210 $a=$\verb@a@$+x\times$\verb@dadx@$+y\times$\verb@dady@, and similarly
00211 for $b$ and $c$.  If that ellipse corresponds to the
00212 $m_\mathrm{thresh}$ mismatch level contour, then the eigenvalues of
00213 the corresponding metric are $\lambda_1=m_\mathrm{thresh}/a^2$ and
00214 $\lambda_2=m_\mathrm{thresh}/b^2$.  The metric components are thus:
00215 \begin{eqnarray}
00216 g_{xx} & = & \lambda_1\cos^2(c) + \lambda_2\sin^2(c) \;,\nonumber\\
00217 g_{yy} & = & \lambda_1\sin^2(c) + \lambda_2\cos^2(c) \;,\nonumber\\
00218 g_{xy} \quad = \quad g_{yx} & = & (\lambda_1-\lambda_2)\cos(c)\sin(c)
00219         \;.\nonumber
00220 \end{eqnarray}
00221 The routine assumes that the values of $a$, $b$, and $c$ refer to an
00222 $m_\mathrm{thresh}=1$ mismatch ellipse.  It computes and returns
00223 $g_{xx}$, $g_{yy}$, and $g_{xy}$ in a 3-dimensional array.
00224 
00225 \paragraph{PostScript flags:} The parameter \verb@flags@ is an
00226 unsigned integer whose lowest-order bits contain parameters to be
00227 passed to \verb@LALPlotTwoDMesh()@.  The bits and their meanings are:
00228 \begin{description}
00229 \item[bit 0:] 1 if mesh points will be plotted, 0 otherwise.
00230 \item[bit 1:] 1 if mesh tiles will be plotted, 0 otherwise.
00231 \item[bit 2:] 1 if mismatch ellipses will be plotted, 0 otherwise.
00232 \item[bit 3:] 1 if the boundary will be plotted, 0 otherwise.
00233 \end{description}
00234 Thus a value of 15 will plot everything, while a value of 9 will just
00235 plot the mesh points and the boundary.  A value of zero suppresses the
00236 plot.
00237 
00238 If mesh points are to be plotted, they will be filled circles $1/72''$
00239 (1~point) in diameter.  The parameter space will be rotated so that
00240 the longer of the diagonals of the parallelogram will be vertical, and
00241 scaled to fit on one $8.5''\times11''$ page.  That is, if
00242 $||(x_1+x_2,y_1+y_2)||\geq||(x_1-x_2,y_1-y_2)||$, the rotation angle
00243 of the coordinate axes will be
00244 $\theta=\pi/2-\arctan\!2(y_1+y_2,x_1+x_2)$, or
00245 $\theta=\pi/2-\arctan\!2(y_2-y_1,x_2-x_1)$ otherwise.  We note that
00246 the function $\arctan\!2(y,x)$ returns the argument of the complex
00247 number $x+iy$ in the range $[-\pi,\pi]$.
00248 
00249 \subsubsection*{Uses}
00250 \begin{verbatim}
00251 lalDebugLevel
00252 LALPrintError()                 LALCheckMemoryLeaks()
00253 LALCreateTwoDMesh()             LALDestroyTwoDMesh()
00254 LALSReadGrid()                  LALSDestroyGrid()
00255 LALPlotTwoDMesh()
00256 \end{verbatim}
00257 
00258 \subsubsection*{Notes}
00259 
00260 \vfill{\footnotesize\input{TwoDMeshTestCV}}
00261 
00262 ******************************************************* </lalLaTeX> */
00263 
00264 #include <math.h>
00265 #include <stdlib.h>
00266 #include <lal/LALStdio.h>
00267 #include <lal/FileIO.h>
00268 #include <lal/LALStdlib.h>
00269 #include <lal/LALConstants.h>
00270 #include <lal/Grid.h>
00271 #include <lal/StreamInput.h>
00272 #include <lal/TwoDMesh.h>
00273 #include "TwoDMeshPlot.h"
00274 
00275 NRCSID( TWODMESHTESTC, "$Id: TwoDMeshTest.c,v 1.8 2007/06/08 14:41:52 bema Exp $" );
00276 
00277 /* Default parameter settings. */
00278 int lalDebugLevel = 0;
00279 #define X1 (1.0)
00280 #define Y1 (0.0)
00281 #define X2 (0.0)
00282 #define Y2 (1.0)
00283 #define A_DEFAULT (0.1)
00284 #define B_DEFAULT (0.05)
00285 #define C_DEFAULT (1.0)
00286 #define DADX (0.0)
00287 #define DBDX (0.0)
00288 #define DCDX (0.0)
00289 #define DADY (0.0)
00290 #define DBDY (0.0)
00291 #define DCDY (0.0)
00292 #define MISMATCH (1.0)
00293 
00294 /* Usage format string. */
00295 #define USAGE "Usage: %s [-o outfile] [-p psfile flags] [-d debug]\n" \
00296 "\t[-m mismatch nmax cmax] [-b x1 y1 x2 y2 ] [-e a b c]\n"        \
00297 "\t[-x dadx dbdx dcdx] [-y dady dbdy dcdy] [-i metricfile rangefile]\n"
00298 
00299 /* Macros for printing errors and testing subroutines. */
00300 #define ERROR( code, msg, statement )                                \
00301 if ( lalDebugLevel & LALERROR )                                      \
00302 {                                                                    \
00303   LALPrintError( "Error[0] %d: program %s, file %s, line %d, %s\n"   \
00304                  "        %s %s\n", (code), *argv, __FILE__,         \
00305                  __LINE__, TWODMESHTESTC, statement ? statement :    \
00306                  "", (msg) );                                        \
00307 }                                                                    \
00308 else (void)(0)
00309 
00310 #define INFO( statement )                                            \
00311 if ( lalDebugLevel & LALINFO )                                       \
00312 {                                                                    \
00313   LALPrintError( "Info[0]: program %s, file %s, line %d, %s\n"       \
00314                  "        %s\n", *argv, __FILE__, __LINE__,          \
00315                  TWODMESHTESTC, (statement) );                       \
00316 }                                                                    \
00317 else (void)(0)
00318 
00319 #define SUB( func, statusptr )                                       \
00320 if ( (func), (statusptr)->statusCode )                               \
00321 {                                                                    \
00322   ERROR( TWODMESHTESTC_ESUB, TWODMESHTESTC_MSGESUB,                  \
00323          "Function call \"" #func "\" failed:" );                    \
00324   return TWODMESHTESTC_ESUB;                                         \
00325 }                                                                    \
00326 else (void)(0)
00327 
00328 /* A global pointer for debugging. */
00329 #ifndef NDEBUG
00330 char *lalWatch;
00331 #endif
00332 
00333 /* Local prototypes. */
00334 void
00335 LALRangeTest( LALStatus *stat, REAL4 range[2], REAL4 x, void *params );
00336 
00337 void
00338 LALMetricTest( LALStatus *stat,
00339                REAL4 metric[3],
00340                REAL4 position[2],
00341                void *params );
00342 
00343 int
00344 main(int argc, char **argv)
00345 {
00346   INT4 arg;                     /* argument counter */
00347   static LALStatus stat;        /* top-level status structure */
00348   REAL4 rangeParams[4];         /* LALRangeTest() params. */
00349   REAL4 metricParams[9];        /* LALMetricTest() params. */
00350   REAL4Grid *metricGrid = NULL; /* LALInterpolateMetric() params. */
00351   REAL4Grid *rangeGrid = NULL;  /* LALInterpolateRangeGrid() params. */
00352   TwoDMeshParamStruc params;    /* LALCreateTwoDMesh() params. */
00353   TwoDMeshNode *mesh = NULL;    /* head of mesh list */
00354 
00355   /* Command-line arguments. */
00356   CHAR *outfile = NULL;                       /* output filename */
00357   CHAR *psfile = NULL;                        /* PostScript filename */
00358   UINT2 flags = 0;                            /* PostScript flags */
00359   CHAR *metricfile = NULL, *rangefile = NULL; /* input filenames */
00360   REAL4 mismatch = MISMATCH;                  /* maximum mismatch */
00361   UINT4 nmax = 0, cmax = 0;                   /* maximum nodes/columns */
00362   REAL4 x1 = X1, y1 = Y1, x2 = X2, y2 = Y2;   /* boundary params. */
00363   REAL4 a = A_DEFAULT, b = B_DEFAULT, c = C_DEFAULT; /* ellipse params. */
00364   REAL4 dadx = DADX, dbdx = DBDX, dcdx = DCDX;       /* ellipse x gradient */
00365   REAL4 dady = DADY, dbdy = DBDY, dcdy = DCDY;       /* ellipse y gradient */
00366 
00367   /******************************************************************
00368    * ARGUMENT PARSING                                               *
00369    ******************************************************************/
00370 
00371   /* Parse argument list.  arg stores the current position. */
00372   arg = 1;
00373   while ( arg < argc ) {
00374     /* Parse output file option. */
00375     if ( !strcmp( argv[arg], "-o" ) ) {
00376       if ( argc > arg + 1 ) {
00377         arg++;
00378         outfile = argv[arg++];
00379       } else {
00380         ERROR( TWODMESHTESTC_EARG, TWODMESHTESTC_MSGEARG, 0 );
00381         LALPrintError( USAGE, *argv );
00382         return TWODMESHTESTC_EARG;
00383       }
00384     }
00385     /* Parse PostScript file option. */
00386     else if ( !strcmp( argv[arg], "-p" ) ) {
00387       if ( argc > arg + 2 ) {
00388         arg++;
00389         psfile = argv[arg++];
00390         flags = atoi( argv[arg++] );
00391       } else {
00392         ERROR( TWODMESHTESTC_EARG, TWODMESHTESTC_MSGEARG, 0 );
00393         LALPrintError( USAGE, *argv );
00394         return TWODMESHTESTC_EARG;
00395       }
00396     }
00397     /* Parse debug level option. */
00398     else if ( !strcmp( argv[arg], "-d" ) ) {
00399       if ( argc > arg + 1 ) {
00400         arg++;
00401         lalDebugLevel = atoi( argv[arg++] );
00402       } else {
00403         ERROR( TWODMESHTESTC_EARG, TWODMESHTESTC_MSGEARG, 0 );
00404         LALPrintError( USAGE, *argv );
00405         return TWODMESHTESTC_EARG;
00406       }
00407     }
00408     /* Parse maximum numbers option. */
00409     else if ( !strcmp( argv[arg], "-m" ) ) {
00410       if ( argc > arg + 2 ) {
00411         arg++;
00412         nmax = atoi( argv[arg++] );
00413         cmax = atoi( argv[arg++] );
00414         mismatch = atof( argv[arg++] );
00415       } else {
00416         ERROR( TWODMESHTESTC_EARG, TWODMESHTESTC_MSGEARG, 0 );
00417         LALPrintError( USAGE, *argv );
00418         return TWODMESHTESTC_EARG;
00419       }
00420     }
00421     /* Parse boundary parameters option. */
00422     else if ( !strcmp( argv[arg], "-b" ) ) {
00423       if ( argc > arg + 4 ) {
00424         arg++;
00425         x1 = atof( argv[arg++] );
00426         y1 = atof( argv[arg++] );
00427         x2 = atof( argv[arg++] );
00428         y2 = atof( argv[arg++] );
00429       } else {
00430         ERROR( TWODMESHTESTC_EARG, TWODMESHTESTC_MSGEARG, 0 );
00431         LALPrintError( USAGE, *argv );
00432         return TWODMESHTESTC_EARG;
00433       }
00434     }
00435     /* Parse ellipse parameters option. */
00436     else if ( !strcmp( argv[arg], "-e" ) ) {
00437       if ( argc > arg + 3 ) {
00438         arg++;
00439         a = atof( argv[arg++] );
00440         b = atof( argv[arg++] );
00441         c = atof( argv[arg++] );
00442       } else {
00443         ERROR( TWODMESHTESTC_EARG, TWODMESHTESTC_MSGEARG, 0 );
00444         LALPrintError( USAGE, *argv );
00445         return TWODMESHTESTC_EARG;
00446       }
00447     }
00448     /* Parse ellipse variation in x option. */
00449     else if ( !strcmp( argv[arg], "-x" ) ) {
00450       if ( argc > arg + 3 ) {
00451         arg++;
00452         dadx = atof( argv[arg++] );
00453         dbdx = atof( argv[arg++] );
00454         dcdx = atof( argv[arg++] );
00455       } else {
00456         ERROR( TWODMESHTESTC_EARG, TWODMESHTESTC_MSGEARG, 0 );
00457         LALPrintError( USAGE, *argv );
00458         return TWODMESHTESTC_EARG;
00459       }
00460     }
00461     /* Parse ellipse variation in y option. */
00462     else if ( !strcmp( argv[arg], "-y" ) ) {
00463       if ( argc > arg + 3 ) {
00464         arg++;
00465         dady = atof( argv[arg++] );
00466         dbdy = atof( argv[arg++] );
00467         dcdy = atof( argv[arg++] );
00468       } else {
00469         ERROR( TWODMESHTESTC_EARG, TWODMESHTESTC_MSGEARG, 0 );
00470         LALPrintError( USAGE, *argv );
00471         return TWODMESHTESTC_EARG;
00472       }
00473     }
00474     /* Parse metric and range grid input option. */
00475     else if ( !strcmp( argv[arg], "-i" ) ) {
00476       if ( argc > arg + 2 ) {
00477         arg++;
00478         metricfile = argv[arg++];
00479         rangefile = argv[arg++];
00480       } else {
00481         ERROR( TWODMESHTESTC_EARG, TWODMESHTESTC_MSGEARG, 0 );
00482         LALPrintError( USAGE, *argv );
00483         return TWODMESHTESTC_EARG;
00484       }
00485     }
00486     /* Check for unrecognized options. */
00487     else if ( argv[arg][0] == '-' ) {
00488       ERROR( TWODMESHTESTC_EARG, TWODMESHTESTC_MSGEARG, 0 );
00489       LALPrintError( USAGE, *argv );
00490       return TWODMESHTESTC_EARG;
00491     }
00492   } /* End of argument parsing loop. */
00493 
00494   /******************************************************************
00495    * SETUP (INTERNAL METRIC/RANGE FUNCTIONS)                        *
00496    ******************************************************************/
00497 
00498   if ( !metricfile ) {
00499     REAL4 axisMin, axisTemp; /* Min. ellipse size, and a temp value */
00500 
00501     /* Set up range function and parameters. */
00502     if ( ( x1 == 0.0 ) && ( x2 == 0.0 ) ) {
00503       ERROR( TWODMESHTESTC_EBAD, TWODMESHTESTC_MSGEBAD,
00504              "x1 = x2 = 0:" );
00505       return TWODMESHTESTC_EBAD;
00506     }
00507     if ( x1 < x2 ) {
00508       rangeParams[0] = x1;
00509       rangeParams[1] = y1;
00510       rangeParams[2] = x2;
00511       rangeParams[3] = y2;
00512     } else {
00513       rangeParams[0] = x2;
00514       rangeParams[1] = y2;
00515       rangeParams[2] = x1;
00516       rangeParams[3] = y1;
00517     }
00518     params.getRange = LALRangeTest;
00519     params.rangeParams = (void *)( rangeParams );
00520     if ( x1*x2 <= 0.0 ) {
00521       if ( x1 < x2 ) {
00522         params.domain[0] = x1;
00523         params.domain[1] = x2;
00524       } else {
00525         params.domain[0] = x2;
00526         params.domain[1] = x1;
00527       }
00528     } else {
00529       if ( x1 < 0.0 ) {
00530         params.domain[0] = x1 + x2;
00531         params.domain[1] = 0.0;
00532       } else {
00533         params.domain[0] = 0.0;
00534         params.domain[1] = x1 + x2;
00535       }
00536     }
00537 
00538     /* Check that metric will be positive everywhere in the region. */
00539     axisMin = a;
00540     axisTemp = a + dadx*x1 + dady*y1;
00541     if ( axisTemp < axisMin ) axisMin = axisTemp;
00542     axisTemp = a + dadx*x2 + dady*y2;
00543     if ( axisTemp < axisMin ) axisMin = axisTemp;
00544     axisTemp = a + dadx*( x1 + x2 ) + dady*( y1 + y2 );
00545     if ( axisTemp < axisMin ) axisMin = axisTemp;
00546     if ( axisMin <= 0.0 ) {
00547       ERROR( TWODMESHTESTC_EMETRIC, TWODMESHTESTC_MSGEMETRIC,
00548              "axis a:" );
00549       return TWODMESHTESTC_EBAD;
00550     }
00551     axisTemp = b;
00552     if ( axisTemp < axisMin ) axisMin = axisTemp;
00553     axisTemp = b + dbdx*x1 + dbdy*y1;
00554     if ( axisTemp < axisMin ) axisMin = axisTemp;
00555     axisTemp = b + dbdx*x2 + dbdy*y2;
00556     if ( axisTemp < axisMin ) axisMin = axisTemp;
00557     axisTemp = b + dbdx*( x1 + x2 ) + dbdy*( y1 + y2 );
00558     if ( axisTemp < axisMin ) axisMin = axisTemp;
00559     if ( axisMin <= 0.0 ) {
00560       ERROR( TWODMESHTESTC_EMETRIC, TWODMESHTESTC_MSGEMETRIC,
00561              "axis b:" );
00562       return TWODMESHTESTC_EBAD;
00563     }
00564 
00565     /* Set up metric function and parameters. */
00566     metricParams[0] = a;
00567     metricParams[1] = b;
00568     metricParams[2] = c;
00569     metricParams[3] = dadx;
00570     metricParams[4] = dbdx;
00571     metricParams[5] = dcdx;
00572     metricParams[6] = dady;
00573     metricParams[7] = dbdy;
00574     metricParams[8] = dcdy;
00575     params.getMetric = LALMetricTest;
00576     params.metricParams = (void *)( metricParams );
00577   }
00578 
00579   /******************************************************************
00580    * SETUP (METRIC/RANGE GRID)                                      *
00581    ******************************************************************/
00582 
00583   else {
00584     FILE *fp = fopen( metricfile, "r" ); /* input file pointer */
00585     if ( !fp ) {
00586       ERROR( TWODMESHTESTC_EFILE, "- " TWODMESHTESTC_MSGEFILE,
00587              metricfile );
00588       return TWODMESHTESTC_EFILE;
00589     }
00590     SUB( LALSReadGrid( &stat, &metricGrid, fp ), &stat );
00591     fclose( fp );
00592     fp = fopen( rangefile, "r" );
00593     if ( !fp ) {
00594       ERROR( TWODMESHTESTC_EFILE, "- " TWODMESHTESTC_MSGEFILE,
00595              rangefile );
00596       return TWODMESHTESTC_EFILE;
00597     }
00598     SUB( LALSReadGrid( &stat, &rangeGrid, fp ), &stat );
00599     fclose( fp );
00600     params.getMetric = LALInterpolateMetricGrid;
00601     params.metricParams = (void *)( metricGrid );
00602     params.getRange = LALInterpolateRangeGrid;
00603     params.rangeParams = (void *)( rangeGrid );
00604     params.domain[0] = rangeGrid->offset->data[0];
00605     params.domain[1] = rangeGrid->offset->data[0]
00606       + rangeGrid->interval->data[0]
00607       *( rangeGrid->data->dimLength->data[0] - 1 );
00608   }
00609 
00610   /******************************************************************
00611    * MESH CREATION AND OUTPUT                                       *
00612    ******************************************************************/
00613 
00614   /* Set up remaining mesh creation parameters. */
00615   params.mThresh = mismatch;
00616   params.widthMaxFac = 0.0;
00617   params.widthRetryFac = 0.0;
00618   params.maxColumns = cmax;
00619   params.nIn = nmax;
00620 
00621   /* Create mesh. */
00622   SUB( LALCreateTwoDMesh( &stat, &mesh, &params ), &stat );
00623 
00624   /* Print mesh list to a file, if requested. */
00625   if ( outfile ) {
00626     FILE *fp = fopen( outfile, "w" ); /* output file pointer */
00627     TwoDMeshNode *here;               /* current node in mesh list */
00628 
00629     if ( !fp ) {
00630       ERROR( TWODMESHTESTC_EFILE, "- " TWODMESHTESTC_MSGEFILE,
00631              outfile );
00632       return TWODMESHTESTC_EFILE;
00633     }
00634     for ( here = mesh; here; here = here->next )
00635       fprintf( fp, "%f %f %f %f %f\n", here->x, here->y, here->dx,
00636                here->dy[0], here->dy[1] );
00637     fclose( fp );
00638   }
00639 
00640   /* Make a PostScript plot of the mesh, if requested. */
00641   if ( psfile && flags ) {
00642     FILE *fp = fopen( psfile, "w" );  /* PostScript file pointer */
00643     INT2 plotPoints = flags & 1;      /* whether to plot mesh points */
00644     BOOLEAN plotTiles = flags & 2;    /* whether to plot mesh tiles */
00645     BOOLEAN plotEllipses = flags & 4; /* whether to plot mesh ellipses */
00646     TwoDMeshPlotStruc plotParams;     /* plotting parameter structure */
00647 
00648     if ( !fp ) {
00649       ERROR( TWODMESHTESTC_EFILE, "- " TWODMESHTESTC_MSGEFILE,
00650              psfile );
00651       return TWODMESHTESTC_EFILE;
00652     }
00653 
00654     /* For a parallelogram region specified on the command line, find
00655        the rotation angle for best fit.  Otherwise, just plot it
00656        straight. */
00657     if ( !metricfile ) {
00658       REAL4 theta1, theta2;
00659       REAL4 xSum = x1 + x2, xDiff = x2 - x1;
00660       REAL4 ySum = y1 + y2, yDiff = y2 - y1;
00661       theta1 = LAL_180_PI*atan2( (REAL4)( TWODMESHPLOTH_YSIZE ),
00662                                  (REAL4)( TWODMESHPLOTH_XSIZE ) );
00663       if ( xSum*xSum + ySum*ySum >= xDiff*xDiff + yDiff*yDiff )
00664         theta1 -= LAL_180_PI*atan2( ySum, xSum );
00665       else
00666         theta1 -= LAL_180_PI*atan2( yDiff, xDiff );
00667       theta2 = theta1 + LAL_180_PI*atan2( y1, x1 );
00668       while ( theta2 < -180.0 ) theta2 += 360.0;
00669       while ( theta2 > 180.0 ) theta2 -= 360.0;
00670       if ( theta2 > 90.0 )
00671         theta1 -= theta2 - 90.0;
00672       else if ( ( -90.0 < theta2 ) && ( theta2 < 0.0 ) )
00673         theta1 -= theta2 + 90.0;
00674       theta2 = theta1 + LAL_180_PI*atan2( y2, x2 );
00675       while ( theta2 < -180.0 ) theta2 += 360.0;
00676       while ( theta2 > 180.0 ) theta2 -= 360.0;
00677       if ( theta2 > 90.0 )
00678         theta1 -= theta2 - 90.0;
00679       else if ( ( -90.0 < theta2 ) && ( theta2 < 0.0 ) )
00680         theta1 -= theta2 + 90.0;
00681       plotParams.theta = theta1;
00682     } else
00683       plotParams.theta = 0.0;
00684 
00685     /* Set remaining parameters, and make the plot. */
00686     plotParams.xScale = plotParams.yScale = 100.0;
00687     plotParams.bBox[0] = 36.0;
00688     plotParams.bBox[1] = 36.0;
00689     plotParams.bBox[2] = 576.0;
00690     plotParams.bBox[3] = 756.0;
00691     plotParams.autoscale = 1;
00692     memset( plotParams.clipBox, 0, 4*sizeof(REAL4) );
00693     plotParams.nLevels = 1;
00694     if ( flags & 8 )
00695       plotParams.nBoundary = 2 +
00696         (UINT4)( ( params.domain[1] - params.domain[0] )/a );
00697     else
00698       plotParams.nBoundary = 0;
00699     plotParams.plotPoints = &plotPoints;
00700     plotParams.plotTiles = &plotTiles;
00701     plotParams.plotEllipses = &plotEllipses;
00702     plotParams.params = &params;
00703     SUB( LALPlotTwoDMesh( &stat, fp, mesh, &plotParams ), &stat );
00704     fclose( fp );
00705   }
00706 
00707   /* Free memory, and exit. */
00708   if ( metricfile ) {
00709     SUB( LALSDestroyGrid( &stat, &metricGrid ), &stat );
00710     SUB( LALSDestroyGrid( &stat, &rangeGrid ), &stat );
00711   }
00712   SUB( LALDestroyTwoDMesh( &stat, &mesh, NULL ), &stat );
00713   LALCheckMemoryLeaks();
00714   INFO( TWODMESHTESTC_MSGENORM );
00715   return TWODMESHTESTC_ENORM;
00716 }
00717 
00718 
00719 void
00720 LALRangeTest( LALStatus *stat, REAL4 range[2], REAL4 x, void *params )
00721 {
00722   REAL4 *xy = (REAL4 *)( params ); /* params recast to its proper type */
00723   REAL4 ya, yb;                    /* unsorted range values */
00724 
00725   /* NOTE: It is assumed and required that xy[0] <= xy[2]. */
00726 
00727   INITSTATUS( stat, "LALRangeTest", TWODMESHTESTC );
00728   ASSERT( range, stat, TWODMESHH_ENUL, TWODMESHH_MSGENUL );
00729   ASSERT( params, stat, TWODMESHH_ENUL, TWODMESHH_MSGENUL );
00730 
00731   /* Case 1: one of the side vectors is vertical. */
00732   if ( xy[0] == 0.0 ) {
00733     ya = xy[3]*( x/xy[2] );
00734     yb = ya + xy[1];
00735   }
00736   else if ( xy[2] == 0.0 ) {
00737     ya = xy[1]*( x/xy[0] );
00738     yb = ya + xy[3];
00739   }
00740 
00741   /* Case 2: Both side vectors point in the same direction (either
00742      left or right). */
00743   else if ( ( xy[0] > 0.0 ) || ( xy[2] < 0.0 ) ) {
00744     if ( fabs( x ) < fabs( xy[0] ) )
00745       ya = xy[1]*( x/xy[0] );
00746     else
00747       ya = xy[1] + xy[3]*( ( x - xy[0] )/xy[2] );
00748     if ( fabs( x ) < fabs( xy[2] ) )
00749       yb = xy[3]*( x/xy[2] );
00750     else
00751       yb = xy[3] + xy[1]*( ( x - xy[2] )/xy[0] );
00752   }
00753 
00754   /* Case 3: The first side vector points left and the second points
00755      right.  (The reverse is impossible, given our assumed ordering.)  */
00756   else {
00757     if ( x < 0.0 )
00758       ya = xy[1]*( x/xy[0] );
00759     else
00760       ya = xy[3]*( x/xy[2] );
00761     if ( x - xy[0] - xy[2] < 0.0 )
00762       yb = xy[1] + xy[3]*( ( x - xy[0] )/xy[2] );
00763     else
00764       yb = xy[3] + xy[1]*( ( x - xy[2] )/xy[0] );
00765   }
00766 
00767   /* Sort and return the range values. */
00768   if ( ya < yb ) {
00769     range[0] = ya;
00770     range[1] = yb;
00771   } else {
00772     range[0] = yb;
00773     range[1] = ya;
00774   }
00775   RETURN( stat );
00776 }
00777 
00778 
00779 void
00780 LALMetricTest( LALStatus *stat,
00781                REAL4 metric[3],
00782                REAL4 position[2],
00783                void *params )
00784 {
00785   REAL4 *abc = (REAL4 *)( params ); /* params recast to proper type */
00786   REAL4 a, b, c;                    /* axis lengths and angle */
00787   REAL4 lambda1, lambda2;           /* metric eigenvalues */
00788   REAL4 cosc, sinc;                 /* cosine and sine of c */
00789 
00790   INITSTATUS( stat, "LALMetricTest", TWODMESHTESTC );
00791   ASSERT( metric, stat, TWODMESHH_ENUL, TWODMESHH_MSGENUL );
00792   ASSERT( position, stat, TWODMESHH_ENUL, TWODMESHH_MSGENUL );
00793   ASSERT( params, stat, TWODMESHH_ENUL, TWODMESHH_MSGENUL );
00794 
00795   /* Compute axis lengths and angle at current position. */
00796   a = abc[0] + position[0]*abc[3] + position[1]*abc[6];
00797   b = abc[1] + position[0]*abc[4] + position[1]*abc[7];
00798   c = abc[2] + position[0]*abc[5] + position[1]*abc[8];
00799   if ( a*b == 0.0 ) {
00800     ABORT( stat, TWODMESHTESTC_EMETRIC, TWODMESHTESTC_MSGEMETRIC );
00801   }
00802 
00803   /* Compute eigenvalues and trigonometric functions. */
00804   lambda1 = MISMATCH/( a*a );
00805   lambda2 = MISMATCH/( b*b );
00806   cosc = cos( c );
00807   sinc = sin( c );
00808 
00809   /* Return metric components. */
00810   metric[0] = lambda1*cosc*cosc + lambda2*sinc*sinc;
00811   metric[1] = lambda1*sinc*sinc + lambda2*cosc*cosc;
00812   metric[2] = ( lambda1 - lambda2 )*cosc*sinc;
00813   RETURN( stat );
00814 }

Generated on Thu Aug 21 03:13:21 2008 for LAL by  doxygen 1.5.2