Loading [MathJax]/extensions/TeX/AMSsymbols.js
LALPulsar 7.1.1.1-8a6b96f
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
TwoDMeshTest.c
Go to the documentation of this file.
1/*
2* Copyright (C) 2007 Teviet Creighton
3*
4* This program is free software; you can redistribute it and/or modify
5* it under the terms of the GNU General Public License as published by
6* the Free Software Foundation; either version 2 of the License, or
7* (at your option) any later version.
8*
9* This program is distributed in the hope that it will be useful,
10* but WITHOUT ANY WARRANTY; without even the implied warranty of
11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12* GNU General Public License for more details.
13*
14* You should have received a copy of the GNU General Public License
15* along with with program; see the file COPYING. If not, write to the
16* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17* MA 02110-1301 USA
18*/
19
20/**
21 * \author Creighton, T. D.
22 * \file
23 * \ingroup TwoDMeshPlot_h
24 * \brief Creates a 2-dimensional template mesh for linearly-changing mismatch ellipses.
25 *
26 * ### Usage ###
27 *
28 * \code
29 * TwoDMeshTest [-o outfile] [-p psfile flags] [-d debug] [-m mismatch nmax cmax]
30 * [-b x1 y1 x2 y2 ] [-e a b c]
31 * [-x dadx dbdx dcdx] [-y dady dbdy dcdy]
32 * \endcode
33 *
34 * ### Description ###
35 *
36 * This test program creates a template mesh for a parameter space with
37 * an arbitrary mismatch metric. The following option flags are
38 * accepted:
39 * <ul>
40 * <li><b>-o</b> Writes the output mesh list to the file
41 * \c outfile. If absent, no output is written.</li>
42 * <li><b>-p</b> Plots the output mesh in a PostScript file
43 * \c psfile, using plot flags \c flags (see below). If absent,
44 * no plot is made.</li>
45 * <li><b>-d</b> Sets the debug level to \c debug. If
46 * absent, a debug level of zero is used.</li>
47 * <li><b>-m</b> Sets the maximum mismatch to \c mismatch,
48 * maximum number of mesh points to \c nmax and the maximum estimated
49 * number of columns to \c cmax. If \c mismatch is not in the
50 * range (0,1], it is taken to be 1. If \c nmax or \c cmax is
51 * non-positive, it is ignored (no maximum). If this option is not
52 * given, <b>-m 1 0 0</b> is assumed.</li>
53 * <li><b>-b</b> Sets the parameter space boundary to be a
54 * parallelogram defined by the vectors (\c x1,\c y1) and
55 * (\c x2,\c y2) from the origin. If absent, the region is
56 * taken to be a unit square.</li>
57 * <li><b>-e</b> Sets the parameters of the mismatch ellipse at the
58 * origin: its principal axis lengths are \c a and \c b units,
59 * and the angle from the \f$ x \f$ -axis to the first principal axis is
60 * \c c radians. If absent, <b>-e 0.1 0.05 1</b> is assumed.</li>
61 * <li><b>-x</b> Sets the rates of change in the \f$ x \f$ -direction of
62 * \c a, \c b, and \c c (above) to \c dadx, \c dbdx,
63 * and \c dcdx, respectively. If absent, the rates are taken to be
64 * zero.</li>
65 * <li><b>-y</b> Sets the rates of change in the \f$ y \f$ -direction of
66 * \c a, \c b, and \c c (above) to \c dady, \c dbdy,
67 * and \c dcdy, respectively. If absent, the rates are taken to be
68 * zero.</li>
69 * </ul>
70 *
71 * ### Algorithm ###
72 *
73 * The test program reads the input arguments and creates a parameter
74 * structure <tt>*params</tt> to be passed to LALCreateTwoDMesh().
75 * In particular, it computes the domain of the parameter space, and
76 * defines functions and parameter lists to compute the range in \f$ y \f$ at
77 * any \f$ x \f$ , and the metric at any point \f$ (x,y) \f$ . If PostScript output is
78 * requested, it is generated using LALPlotTwoDMesh(), using the
79 * value of the command-line number \c flags to set the plotting
80 * parameters. Each of these functions is discussed below.
81 *
82 * \par Parameter ranges:
83 * The parameter space boundary can be
84 * specified by input parameters \c x1 \f$ =x_1 \f$ , \c x2 \f$ =x_2 \f$ ,
85 * \c y1 \f$ =y_1 \f$ , and \c y2 \f$ =y_2 \f$ . The parameter space is then
86 * defined to be a parallelogram with one corner on the origin, and two
87 * sides defined by vectors \f$ (x_1,y_1) \f$ and \f$ (x_2,y_2) \f$ . Without loss of
88 * generality we assume that \f$ x_1<x_2 \f$ . The functions defining the
89 * boundaries are denoted \f$ y_{a,b}(x) \f$ , and we make no assumption about
90 * their signs or relative order. The algorithm used then depends on the
91 * signs of \f$ x_1 \f$ and \f$ x_2 \f$ .
92 *
93 * If \f$ x_1=x_2=0 \f$ , then the parameter space is singular, and no mesh need
94 * be generated.
95 *
96 * If \f$ x_1=0 \f$ and \f$ x_2\neq0 \f$ , then the domain is \f$ [0,x_2] \f$ , and the
97 * boundary functions are:
98 * \f{eqnarray}{
99 * y_a(x) & = & y_2x/x_2\\
100 * y_b(x) & = & y_1 + y_2x/x_2
101 * \f}
102 *
103 * If \f$ x_2=0 \f$ and \f$ x_1\neq0 \f$ , then the domain is \f$ [x_1,0] \f$ , and the above
104 * equations for \f$ y_{a,b}(x) \f$ simply have 1 and 2 reversed.
105 *
106 * If \f$ x_1 \f$ and \f$ x_2 \f$ have the same sign, then the domain is
107 * \f$ [0,x_1+x_2] \f$ if \f$ x_1 \f$ and \f$ x_2 \f$ are positive, and \f$ [x_1+x_2,0] \f$
108 * otherwise. The boundary functions are:
109 * \f{eqnarray}{
110 * y_a(x) & = & \left\{\begin{array}{c@{\qquad}c}
111 * y_1x/x_1 & x\mathrm{~between~}0\mathrm{~and~}x_1 \\
112 * y_1 + y_2(x-x_1)/x_2 & x\mathrm{~between~}x_1\mathrm{~and~}x_1+x_2
113 * \end{array}\right.\\
114 * y_b(x) & = & \left\{\begin{array}{c@{\qquad}c}
115 * y_2x/x_2 & x\mathrm{~between~}0\mathrm{~and~}x_2 \\
116 * y_2 + y_1(x-x_2)/x_1 & x\mathrm{~between~}x_2\mathrm{~and~}x_1+x_2
117 * \end{array}\right.
118 * \f}
119 *
120 * If \f$ x_1 \f$ and \f$ x_2 \f$ have opposite sign, the domain is \f$ [x_1,x_2] \f$ if
121 * \f$ x_1<0 \f$ , and \f$ [x_2,x_1] \f$ otherwise. The boundary functions are:
122 * \f{eqnarray}{
123 * y_a(x) & = & \left\{\begin{array}{c@{\qquad}c}
124 * y_1x/x_1 & x\mathrm{~between~}0\mathrm{~and~}x_1 \\
125 * y_2x/x_2 & x\mathrm{~between~}0\mathrm{~and~}x_2
126 * \end{array}\right.\\
127 * y_b(x) & = & \left\{\begin{array}{c@{\qquad}c}
128 * y_1 + y_2(x-x_1)/x_2 & x\mathrm{~between~}x_1\mathrm{~and~}x_1+x_2 \\
129 * y_2 + y1(x-x_2)/x_1 & x\mathrm{~between~}x_2\mathrm{~and~}x_1+x_2
130 * \end{array}\right.
131 * \f}
132 *
133 * The main program sorts the input parameters so that \f$ x_1\leq x_2 \f$ ,
134 * stores them in a 4-dimensional array, and assigns a \c void
135 * pointer to that array. It also computes the domain. The routine
136 * LALTwoDRangeTest() takes a value of \f$ x \f$ and the \c void
137 * pointer, computes the values of \f$ y_a(x) \f$ and \f$ y_b(x) \f$ according to the
138 * algorithm above, sorts them, and returns them ordered from lower to
139 * higher.
140 *
141 * \par Metric values:
142 * The main program takes the input parameters
143 * \c a, \c b, \c c, \c dadx, \c dbdx, and
144 * \c dcdx, stores them in a 9-dimensional array, and assigns a
145 * \c void pointer to it. The routine LALTwoDMetricTest()
146 * takes a position \f$ (x,y) \f$ and the \c void pointer, and computes the
147 * ``local'' value of the principal axis
148 * \f$ a= \f$ \c a \f$ +x\times \f$ \c dadx \f$ +y\times \f$ \c dady, and similarly
149 * for \f$ b \f$ and \f$ c \f$ . If that ellipse corresponds to the
150 * \f$ m_\mathrm{thresh} \f$ mismatch level contour, then the eigenvalues of
151 * the corresponding metric are \f$ \lambda_1=m_\mathrm{thresh}/a^2 \f$ and
152 * \f$ \lambda_2=m_\mathrm{thresh}/b^2 \f$ . The metric components are thus:
153 * \f{eqnarray}{
154 * g_{xx} & = & \lambda_1\cos^2(c) + \lambda_2\sin^2(c) \;,\\
155 * g_{yy} & = & \lambda_1\sin^2(c) + \lambda_2\cos^2(c) \;,\\
156 * g_{xy} \quad = \quad g_{yx} & = & (\lambda_1-\lambda_2)\cos(c)\sin(c)
157 * \;.
158 * \f}
159 * The routine assumes that the values of \f$ a \f$ , \f$ b \f$ , and \f$ c \f$ refer to an
160 * \f$ m_\mathrm{thresh}=1 \f$ mismatch ellipse. It computes and returns
161 * \f$ g_{xx} \f$ , \f$ g_{yy} \f$ , and \f$ g_{xy} \f$ in a 3-dimensional array.
162 *
163 * \par PostScript flags:
164 * The parameter \c flags is an
165 * unsigned integer whose lowest-order bits contain parameters to be
166 * passed to LALPlotTwoDMesh(). The bits and their meanings are:
167 * <dl>
168 * <dt>bit 0:</dt><dd> 1 if mesh points will be plotted, 0 otherwise.</dd>
169 * <dt>bit 1:</dt><dd> 1 if mesh tiles will be plotted, 0 otherwise.</dd>
170 * <dt>bit 2:</dt><dd> 1 if mismatch ellipses will be plotted, 0 otherwise.</dd>
171 * <dt>bit 3:</dt><dd> 1 if the boundary will be plotted, 0 otherwise.</dd>
172 * </dl>
173 * Thus a value of 15 will plot everything, while a value of 9 will just
174 * plot the mesh points and the boundary. A value of zero suppresses the
175 * plot.
176 *
177 * If mesh points are to be plotted, they will be filled circles \f$ 1/72'' \f$
178 * (1~point) in diameter. The parameter space will be rotated so that
179 * the longer of the diagonals of the parallelogram will be vertical, and
180 * scaled to fit on one \f$ 8.5''\times11'' \f$ page. That is, if
181 * \f$ ||(x_1+x_2,y_1+y_2)||\geq||(x_1-x_2,y_1-y_2)|| \f$ , the rotation angle
182 * of the coordinate axes will be
183 * \f$ \theta=\pi/2-\arctan\!2(y_1+y_2,x_1+x_2) \f$ , or
184 * \f$ \theta=\pi/2-\arctan\!2(y_2-y_1,x_2-x_1) \f$ otherwise. We note that
185 * the function \f$ \arctan\!2(y,x) \f$ returns the argument of the complex
186 * number \f$ x+iy \f$ in the range \f$ [-\pi,\pi] \f$ .
187 *
188 * ### Uses ###
189 *
190 * \code
191 * lalDebugLevel
192 * LALPrintError() LALCheckMemoryLeaks()
193 * LALCreateTwoDMesh() LALDestroyTwoDMesh()
194 * LALPlotTwoDMesh()
195 * \endcode
196 *
197 * ### Notes ###
198 *
199 */
200
201/** \name Error Codes */ /** @{ */
202#define TWODMESHTESTC_ENORM 0
203#define TWODMESHTESTC_ESUB 1
204#define TWODMESHTESTC_EARG 2
205#define TWODMESHTESTC_EBAD 3
206#define TWODMESHTESTC_EMEM 4
207#define TWODMESHTESTC_EFILE 5
208#define TWODMESHTESTC_EMETRIC 6
209
210#define TWODMESHTESTC_MSGENORM "Normal exit"
211#define TWODMESHTESTC_MSGESUB "Subroutine failed"
212#define TWODMESHTESTC_MSGEARG "Error parsing arguments"
213#define TWODMESHTESTC_MSGEBAD "Bad argument value"
214#define TWODMESHTESTC_MSGEMEM "Memory allocation error"
215#define TWODMESHTESTC_MSGEFILE "Could not open file"
216#define TWODMESHTESTC_MSGEMETRIC "Axis length is zero or negative within specified region"
217/** @} */
218
219#include <math.h>
220#include <stdlib.h>
221#include <lal/LALStdio.h>
222#include <lal/FileIO.h>
223#include <lal/LALStdlib.h>
224#include <lal/LALConstants.h>
225#include <lal/StreamInput.h>
226#include <lal/TwoDMesh.h>
227#include "TwoDMeshPlot.h"
228
229/** \cond DONT_DOXYGEN */
230
231/* Default parameter settings. */
232#define X1 (1.0)
233#define Y1 (0.0)
234#define X2 (0.0)
235#define Y2 (1.0)
236#define A_DEFAULT (0.1)
237#define B_DEFAULT (0.05)
238#define C_DEFAULT (1.0)
239#define DADX (0.0)
240#define DBDX (0.0)
241#define DCDX (0.0)
242#define DADY (0.0)
243#define DBDY (0.0)
244#define DCDY (0.0)
245#define MISMATCH (1.0)
246
247/* Usage format string. */
248#define USAGE "Usage: %s [-o outfile] [-p psfile flags] [-d debug]\n" \
249"\t[-m mismatch nmax cmax] [-b x1 y1 x2 y2 ] [-e a b c]\n" \
250"\t[-x dadx dbdx dcdx] [-y dady dbdy dcdy]\n"
251
252/* Macros for printing errors and testing subroutines. */
253#define ERROR( code, msg, statement ) \
254if ( lalDebugLevel & LALERROR ) \
255{ \
256 XLALPrintError( "Error[0] %d: program %s, file %s, line %d, %s\n" \
257 " %s %s\n", (code), *argv, __FILE__, \
258 __LINE__, "$Id$", statement ? statement : \
259 "", (msg) ); \
260} \
261else (void)(0)
262
263#define INFO( statement ) \
264if ( lalDebugLevel & LALINFO ) \
265{ \
266 XLALPrintError( "Info[0]: program %s, file %s, line %d, %s\n" \
267 " %s\n", *argv, __FILE__, __LINE__, \
268 "$Id$", (statement) ); \
269} \
270else (void)(0)
271
272#define SUB( func, statusptr ) \
273if ( (func), (statusptr)->statusCode ) \
274{ \
275 ERROR( TWODMESHTESTC_ESUB, TWODMESHTESTC_MSGESUB, \
276 "Function call \"" #func "\" failed:" ); \
277 return TWODMESHTESTC_ESUB; \
278} \
279else (void)(0)
280
281/* Local prototypes. */
282void
283LALRangeTest( LALStatus *stat, REAL4 range[2], REAL4 x, void *params );
284
285void
286LALMetricTest( LALStatus *stat,
287 REAL4 metric[3],
288 REAL4 position[2],
289 void *params );
290
291int
292main( int argc, char **argv )
293{
294 INT4 arg; /* argument counter */
295 static LALStatus stat; /* top-level status structure */
296 REAL4 rangeParams[4]; /* LALRangeTest() params. */
297 REAL4 metricParams[9]; /* LALMetricTest() params. */
298 TwoDMeshParamStruc params; /* LALCreateTwoDMesh() params. */
299 TwoDMeshNode *mesh = NULL; /* head of mesh list */
300
301 /* Command-line arguments. */
302 CHAR *outfile = NULL; /* output filename */
303 CHAR *psfile = NULL; /* PostScript filename */
304 UINT2 flags = 0; /* PostScript flags */
305 REAL4 mismatch = MISMATCH; /* maximum mismatch */
306 UINT4 nmax = 0, cmax = 0; /* maximum nodes/columns */
307 REAL4 x_1 = X1, y_1 = Y1, x_2 = X2, y_2 = Y2; /* boundary params. */
308 REAL4 a = A_DEFAULT, b = B_DEFAULT, c = C_DEFAULT; /* ellipse params. */
309 REAL4 dadx = DADX, dbdx = DBDX, dcdx = DCDX; /* ellipse x gradient */
310 REAL4 dady = DADY, dbdy = DBDY, dcdy = DCDY; /* ellipse y gradient */
311
312
313 /******************************************************************
314 * ARGUMENT PARSING *
315 ******************************************************************/
316
317 /* Parse argument list. arg stores the current position. */
318 arg = 1;
319 while ( arg < argc ) {
320 /* Parse output file option. */
321 if ( !strcmp( argv[arg], "-o" ) ) {
322 if ( argc > arg + 1 ) {
323 arg++;
324 outfile = argv[arg++];
325 } else {
327 XLALPrintError( USAGE, *argv );
328 return TWODMESHTESTC_EARG;
329 }
330 }
331 /* Parse PostScript file option. */
332 else if ( !strcmp( argv[arg], "-p" ) ) {
333 if ( argc > arg + 2 ) {
334 arg++;
335 psfile = argv[arg++];
336 flags = atoi( argv[arg++] );
337 } else {
339 XLALPrintError( USAGE, *argv );
340 return TWODMESHTESTC_EARG;
341 }
342 }
343 /* Parse debug level option. */
344 else if ( !strcmp( argv[arg], "-d" ) ) {
345 if ( argc > arg + 1 ) {
346 arg++;
347 } else {
349 XLALPrintError( USAGE, *argv );
350 return TWODMESHTESTC_EARG;
351 }
352 }
353 /* Parse maximum numbers option. */
354 else if ( !strcmp( argv[arg], "-m" ) ) {
355 if ( argc > arg + 2 ) {
356 arg++;
357 nmax = atoi( argv[arg++] );
358 cmax = atoi( argv[arg++] );
359 mismatch = atof( argv[arg++] );
360 } else {
362 XLALPrintError( USAGE, *argv );
363 return TWODMESHTESTC_EARG;
364 }
365 }
366 /* Parse boundary parameters option. */
367 else if ( !strcmp( argv[arg], "-b" ) ) {
368 if ( argc > arg + 4 ) {
369 arg++;
370 x_1 = atof( argv[arg++] );
371 y_1 = atof( argv[arg++] );
372 x_2 = atof( argv[arg++] );
373 y_2 = atof( argv[arg++] );
374 } else {
376 XLALPrintError( USAGE, *argv );
377 return TWODMESHTESTC_EARG;
378 }
379 }
380 /* Parse ellipse parameters option. */
381 else if ( !strcmp( argv[arg], "-e" ) ) {
382 if ( argc > arg + 3 ) {
383 arg++;
384 a = atof( argv[arg++] );
385 b = atof( argv[arg++] );
386 c = atof( argv[arg++] );
387 } else {
389 XLALPrintError( USAGE, *argv );
390 return TWODMESHTESTC_EARG;
391 }
392 }
393 /* Parse ellipse variation in x option. */
394 else if ( !strcmp( argv[arg], "-x" ) ) {
395 if ( argc > arg + 3 ) {
396 arg++;
397 dadx = atof( argv[arg++] );
398 dbdx = atof( argv[arg++] );
399 dcdx = atof( argv[arg++] );
400 } else {
402 XLALPrintError( USAGE, *argv );
403 return TWODMESHTESTC_EARG;
404 }
405 }
406 /* Parse ellipse variation in y option. */
407 else if ( !strcmp( argv[arg], "-y" ) ) {
408 if ( argc > arg + 3 ) {
409 arg++;
410 dady = atof( argv[arg++] );
411 dbdy = atof( argv[arg++] );
412 dcdy = atof( argv[arg++] );
413 } else {
415 XLALPrintError( USAGE, *argv );
416 return TWODMESHTESTC_EARG;
417 }
418 }
419 /* Check for unrecognized options. */
420 else if ( argv[arg][0] == '-' ) {
422 XLALPrintError( USAGE, *argv );
423 return TWODMESHTESTC_EARG;
424 }
425 } /* End of argument parsing loop. */
426
427 /******************************************************************
428 * SETUP (INTERNAL METRIC/RANGE FUNCTIONS) *
429 ******************************************************************/
430
431 {
432 REAL4 axisMin, axisTemp; /* Min. ellipse size, and a temp value */
433
434 /* Set up range function and parameters. */
435 if ( ( x_1 == 0.0 ) && ( x_2 == 0.0 ) ) {
437 "x_1 = x_2 = 0:" );
438 return TWODMESHTESTC_EBAD;
439 }
440 if ( x_1 < x_2 ) {
441 rangeParams[0] = x_1;
442 rangeParams[1] = y_1;
443 rangeParams[2] = x_2;
444 rangeParams[3] = y_2;
445 } else {
446 rangeParams[0] = x_2;
447 rangeParams[1] = y_2;
448 rangeParams[2] = x_1;
449 rangeParams[3] = y_1;
450 }
451 params.getRange = LALRangeTest;
452 params.rangeParams = ( void * )( rangeParams );
453 if ( x_1 * x_2 <= 0.0 ) {
454 if ( x_1 < x_2 ) {
455 params.domain[0] = x_1;
456 params.domain[1] = x_2;
457 } else {
458 params.domain[0] = x_2;
459 params.domain[1] = x_1;
460 }
461 } else {
462 if ( x_1 < 0.0 ) {
463 params.domain[0] = x_1 + x_2;
464 params.domain[1] = 0.0;
465 } else {
466 params.domain[0] = 0.0;
467 params.domain[1] = x_1 + x_2;
468 }
469 }
470
471 /* Check that metric will be positive everywhere in the region. */
472 axisMin = a;
473 axisTemp = a + dadx * x_1 + dady * y_1;
474 if ( axisTemp < axisMin ) {
475 axisMin = axisTemp;
476 }
477 axisTemp = a + dadx * x_2 + dady * y_2;
478 if ( axisTemp < axisMin ) {
479 axisMin = axisTemp;
480 }
481 axisTemp = a + dadx * ( x_1 + x_2 ) + dady * ( y_1 + y_2 );
482 if ( axisTemp < axisMin ) {
483 axisMin = axisTemp;
484 }
485 if ( axisMin <= 0.0 ) {
487 "axis a:" );
488 return TWODMESHTESTC_EBAD;
489 }
490 axisTemp = b;
491 if ( axisTemp < axisMin ) {
492 axisMin = axisTemp;
493 }
494 axisTemp = b + dbdx * x_1 + dbdy * y_1;
495 if ( axisTemp < axisMin ) {
496 axisMin = axisTemp;
497 }
498 axisTemp = b + dbdx * x_2 + dbdy * y_2;
499 if ( axisTemp < axisMin ) {
500 axisMin = axisTemp;
501 }
502 axisTemp = b + dbdx * ( x_1 + x_2 ) + dbdy * ( y_1 + y_2 );
503 if ( axisTemp < axisMin ) {
504 axisMin = axisTemp;
505 }
506 if ( axisMin <= 0.0 ) {
508 "axis b:" );
509 return TWODMESHTESTC_EBAD;
510 }
511
512 /* Set up metric function and parameters. */
513 metricParams[0] = a;
514 metricParams[1] = b;
515 metricParams[2] = c;
516 metricParams[3] = dadx;
517 metricParams[4] = dbdx;
518 metricParams[5] = dcdx;
519 metricParams[6] = dady;
520 metricParams[7] = dbdy;
521 metricParams[8] = dcdy;
522 params.getMetric = LALMetricTest;
523 params.metricParams = ( void * )( metricParams );
524 }
525
526 /******************************************************************
527 * MESH CREATION AND OUTPUT *
528 ******************************************************************/
529
530 /* Set up remaining mesh creation parameters. */
531 params.mThresh = mismatch;
532 params.widthMaxFac = 0.0;
533 params.widthRetryFac = 0.0;
534 params.maxColumns = cmax;
535 params.nIn = nmax;
536
537 /* Create mesh. */
538 SUB( LALCreateTwoDMesh( &stat, &mesh, &params ), &stat );
539
540 /* Print mesh list to a file, if requested. */
541 if ( outfile ) {
542 FILE *fp = fopen( outfile, "w" ); /* output file pointer */
543 TwoDMeshNode *here; /* current node in mesh list */
544
545 if ( !fp ) {
547 outfile );
548 return TWODMESHTESTC_EFILE;
549 }
550 for ( here = mesh; here; here = here->next )
551 fprintf( fp, "%f %f %f %f %f\n", here->x, here->y, here->dx,
552 here->dy[0], here->dy[1] );
553 fclose( fp );
554 }
555
556 /* Make a PostScript plot of the mesh, if requested. */
557 if ( psfile && flags ) {
558 FILE *fp = fopen( psfile, "w" ); /* PostScript file pointer */
559 INT2 plotPoints = flags & 1; /* whether to plot mesh points */
560 BOOLEAN plotTiles = flags & 2; /* whether to plot mesh tiles */
561 BOOLEAN plotEllipses = flags & 4; /* whether to plot mesh ellipses */
562 TwoDMeshPlotStruc plotParams; /* plotting parameter structure */
563
564 if ( !fp ) {
566 psfile );
567 return TWODMESHTESTC_EFILE;
568 }
569
570 /* For a parallelogram region specified on the command line, find
571 the rotation angle for best fit. Otherwise, just plot it
572 straight. */
573 {
575 REAL4 xSum = x_1 + x_2, xDiff = x_2 - x_1;
576 REAL4 ySum = y_1 + y_2, yDiff = y_2 - y_1;
577 theta1 = LAL_180_PI * atan2( ( REAL4 )( TWODMESHPLOTH_YSIZE ),
578 ( REAL4 )( TWODMESHPLOTH_XSIZE ) );
579 if ( xSum * xSum + ySum * ySum >= xDiff * xDiff + yDiff * yDiff ) {
580 theta1 -= LAL_180_PI * atan2( ySum, xSum );
581 } else {
582 theta1 -= LAL_180_PI * atan2( yDiff, xDiff );
583 }
584 theta2 = theta1 + LAL_180_PI * atan2( y_1, x_1 );
585 while ( theta2 < -180.0 ) {
586 theta2 += 360.0;
587 }
588 while ( theta2 > 180.0 ) {
589 theta2 -= 360.0;
590 }
591 if ( theta2 > 90.0 ) {
592 theta1 -= theta2 - 90.0;
593 } else if ( ( -90.0 < theta2 ) && ( theta2 < 0.0 ) ) {
594 theta1 -= theta2 + 90.0;
595 }
596 theta2 = theta1 + LAL_180_PI * atan2( y_2, x_2 );
597 while ( theta2 < -180.0 ) {
598 theta2 += 360.0;
599 }
600 while ( theta2 > 180.0 ) {
601 theta2 -= 360.0;
602 }
603 if ( theta2 > 90.0 ) {
604 theta1 -= theta2 - 90.0;
605 } else if ( ( -90.0 < theta2 ) && ( theta2 < 0.0 ) ) {
606 theta1 -= theta2 + 90.0;
607 }
608 plotParams.theta = theta1;
609 }
610
611 /* Set remaining parameters, and make the plot. */
612 plotParams.xScale = plotParams.yScale = 100.0;
613 plotParams.bBox[0] = 36.0;
614 plotParams.bBox[1] = 36.0;
615 plotParams.bBox[2] = 576.0;
616 plotParams.bBox[3] = 756.0;
617 plotParams.autoscale = 1;
618 memset( plotParams.clipBox, 0, 4 * sizeof( REAL4 ) );
619 plotParams.nLevels = 1;
620 if ( flags & 8 )
621 plotParams.nBoundary = 2 +
622 ( UINT4 )( ( params.domain[1] - params.domain[0] ) / a );
623 else {
624 plotParams.nBoundary = 0;
625 }
626 plotParams.plotPoints = &plotPoints;
627 plotParams.plotTiles = &plotTiles;
628 plotParams.plotEllipses = &plotEllipses;
629 plotParams.params = &params;
630 SUB( LALPlotTwoDMesh( &stat, fp, mesh, &plotParams ), &stat );
631 fclose( fp );
632 }
633
634 /* Free memory, and exit. */
635 SUB( LALDestroyTwoDMesh( &stat, &mesh, NULL ), &stat );
638 return TWODMESHTESTC_ENORM;
639}
640
641
642void
643LALRangeTest( LALStatus *stat, REAL4 range[2], REAL4 x, void *params )
644{
645 REAL4 *xy = ( REAL4 * )( params ); /* params recast to its proper type */
646 REAL4 ya, yb; /* unsorted range values */
647
648 /* NOTE: It is assumed and required that xy[0] <= xy[2]. */
649
650 INITSTATUS( stat );
653
654 /* Case 1: one of the side vectors is vertical. */
655 if ( xy[0] == 0.0 ) {
656 ya = xy[3] * ( x / xy[2] );
657 yb = ya + xy[1];
658 } else if ( xy[2] == 0.0 ) {
659 ya = xy[1] * ( x / xy[0] );
660 yb = ya + xy[3];
661 }
662
663 /* Case 2: Both side vectors point in the same direction (either
664 left or right). */
665 else if ( ( xy[0] > 0.0 ) || ( xy[2] < 0.0 ) ) {
666 if ( fabs( x ) < fabs( xy[0] ) ) {
667 ya = xy[1] * ( x / xy[0] );
668 } else {
669 ya = xy[1] + xy[3] * ( ( x - xy[0] ) / xy[2] );
670 }
671 if ( fabs( x ) < fabs( xy[2] ) ) {
672 yb = xy[3] * ( x / xy[2] );
673 } else {
674 yb = xy[3] + xy[1] * ( ( x - xy[2] ) / xy[0] );
675 }
676 }
677
678 /* Case 3: The first side vector points left and the second points
679 right. (The reverse is impossible, given our assumed ordering.) */
680 else {
681 if ( x < 0.0 ) {
682 ya = xy[1] * ( x / xy[0] );
683 } else {
684 ya = xy[3] * ( x / xy[2] );
685 }
686 if ( x - xy[0] - xy[2] < 0.0 ) {
687 yb = xy[1] + xy[3] * ( ( x - xy[0] ) / xy[2] );
688 } else {
689 yb = xy[3] + xy[1] * ( ( x - xy[2] ) / xy[0] );
690 }
691 }
692
693 /* Sort and return the range values. */
694 if ( ya < yb ) {
695 range[0] = ya;
696 range[1] = yb;
697 } else {
698 range[0] = yb;
699 range[1] = ya;
700 }
701 RETURN( stat );
702}
703
704
705void
706LALMetricTest( LALStatus *stat,
707 REAL4 metric[3],
708 REAL4 position[2],
709 void *params )
710{
711 REAL4 *abc = ( REAL4 * )( params ); /* params recast to proper type */
712 REAL4 a, b, c; /* axis lengths and angle */
713 REAL4 lambda1, lambda2; /* metric eigenvalues */
714 REAL4 cosc, sinc; /* cosine and sine of c */
715
716 INITSTATUS( stat );
720
721 /* Compute axis lengths and angle at current position. */
722 a = abc[0] + position[0] * abc[3] + position[1] * abc[6];
723 b = abc[1] + position[0] * abc[4] + position[1] * abc[7];
724 c = abc[2] + position[0] * abc[5] + position[1] * abc[8];
725 if ( a * b == 0.0 ) {
727 }
728
729 /* Compute eigenvalues and trigonometric functions. */
730 lambda1 = MISMATCH / ( a * a );
731 lambda2 = MISMATCH / ( b * b );
732 cosc = cos( c );
733 sinc = sin( c );
734
735 /* Return metric components. */
736 metric[0] = lambda1 * cosc * cosc + lambda2 * sinc * sinc;
737 metric[1] = lambda1 * sinc * sinc + lambda2 * cosc * cosc;
738 metric[2] = ( lambda1 - lambda2 ) * cosc * sinc;
739 RETURN( stat );
740}
741
742/** \endcond */
#define SUB(func, statusptr)
#define ERROR(code, msg, statement)
#define INFO(statement)
#define MISMATCH
Default for metric grid maximal mismatch value.
void LALCheckMemoryLeaks(void)
#define c
#define ABORT(statusptr, code, mesg)
#define ASSERT(assertion, statusptr, code, mesg)
#define INITSTATUS(statusptr)
#define RETURN(statusptr)
#define fprintf
#define TWODMESHTESTC_MSGEARG
Definition: TwoDMeshTest.c:212
#define TWODMESHTESTC_MSGENORM
Definition: TwoDMeshTest.c:210
#define TWODMESHTESTC_EMETRIC
Definition: TwoDMeshTest.c:208
#define TWODMESHTESTC_EBAD
Definition: TwoDMeshTest.c:205
#define TWODMESHTESTC_ENORM
Definition: TwoDMeshTest.c:202
#define TWODMESHTESTC_EFILE
Definition: TwoDMeshTest.c:207
#define TWODMESHTESTC_MSGEMETRIC
Definition: TwoDMeshTest.c:216
#define TWODMESHTESTC_MSGEBAD
Definition: TwoDMeshTest.c:213
#define TWODMESHTESTC_EARG
Definition: TwoDMeshTest.c:204
#define TWODMESHTESTC_MSGEFILE
Definition: TwoDMeshTest.c:215
int main(int argc, char **argv)
#define LAL_180_PI
unsigned char BOOLEAN
int16_t INT2
uint16_t UINT2
char CHAR
uint32_t UINT4
int32_t INT4
float REAL4
static const INT4 a
#define TWODMESHH_MSGENUL
Definition: TwoDMesh.h:111
#define TWODMESHH_ENUL
Definition: TwoDMesh.h:103
void LALCreateTwoDMesh(LALStatus *stat, TwoDMeshNode **mesh, TwoDMeshParamStruc *params)
Definition: TwoDMesh.c:106
void LALDestroyTwoDMesh(LALStatus *stat, TwoDMeshNode **mesh, UINT4 *nFree)
Definition: TwoDMesh.c:159
#define TWODMESHPLOTH_XSIZE
Horizontal size of plotting area (points = )
Definition: TwoDMeshPlot.h:76
#define TWODMESHPLOTH_YSIZE
Vertical size of plotting area (points)
Definition: TwoDMeshPlot.h:77
void LALPlotTwoDMesh(LALStatus *stat, FILE *stream, TwoDMeshNode *mesh, TwoDMeshPlotStruc *params)
Plots a hierarchical mesh of templates on an 2-dimensional parameter space.
Definition: TwoDMeshPlot.c:97
int XLALPrintError(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
theta2
theta1
lambda1
lambda2
This structure represents a single node in a linked list of mesh points, specified in the coordinate ...
Definition: TwoDMesh.h:124
struct tagTwoDMeshNode * next
The next mesh point in the linked list; NULL if this is the tail.
Definition: TwoDMesh.h:128
REAL4 dx
The half-width of the tile centred on the mesh point.
Definition: TwoDMesh.h:126
REAL4 dy[2]
The heights of the two right-hand corners of the tile, relative to the mesh point.
Definition: TwoDMesh.h:127
REAL4 y
The coordinates of the mesh point.
Definition: TwoDMesh.h:125
This structure stores the parameters required by the two-dimensional mesh placement functions.
Definition: TwoDMesh.h:142
This structure stores parameters specifying how to plot a PostScript diagram of the parameter mesh.
Definition: TwoDMeshPlot.h:85
REAL4 theta
Angle from the horizontal direction of the plot counterclockwise to the -coordinate axis of the mesh...
Definition: TwoDMeshPlot.h:86
REAL4 yScale
Plotting scale of the mesh coordinate axes, in points per unit or (a point is 1/72 of an inch)
Definition: TwoDMeshPlot.h:87
UINT4 nLevels
The number of levels of recursive submeshes to plot.
Definition: TwoDMeshPlot.h:96
INT2 * plotPoints
An array from [0] to [nLevels] indicating how to plot the mesh points at each recursive level: a valu...
Definition: TwoDMeshPlot.h:100
BOOLEAN * plotTiles
An array from [0] to [nLevels] indicating whether to plot the tiles around each mesh point,...
Definition: TwoDMeshPlot.h:104
BOOLEAN autoscale
If true, xScale and yScale will be adjusted so that the drawn figure will lie within the bBox.
Definition: TwoDMeshPlot.h:89
REAL4 bBox[4]
Bounding box surrounding the figure in plot coordinates, measured in points.
Definition: TwoDMeshPlot.h:88
REAL4 clipBox[4]
Four components , , , (in that order) specifying the corners of a box in the - coordinate syste...
Definition: TwoDMeshPlot.h:92
BOOLEAN * plotEllipses
An array from [0] to [nLevels] indicating whether to plot the mismatch ellipses around each mesh poin...
Definition: TwoDMeshPlot.h:107
TwoDMeshParamStruc * params
An array from [0] to [nLevels] of parameter structures used to generate the meshes at each recursive ...
Definition: TwoDMeshPlot.h:110
UINT4 nBoundary
half the number of points to plot along the boundary of the parameter region; at least 4 points are r...
Definition: TwoDMeshPlot.h:97
int domain