/usr/share/doc/libcpl-doc/html/group__cpl__ppm.html is in libcpl-doc 6.5-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.6"/>
<title>Common Pipeline Library Reference Manual: Point pattern matching module</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
<link href="cpl.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<td style="padding-left: 0.5em;">
<div id="projectname">Common Pipeline Library Reference Manual
 <span id="projectnumber">6.5</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.6 -->
<div id="navrow1" class="tabs">
<ul class="tablist">
<li><a href="index.html"><span>Main Page</span></a></li>
<li><a href="pages.html"><span>Related Pages</span></a></li>
<li><a href="modules.html"><span>Modules</span></a></li>
<li><a href="annotated.html"><span>Classes</span></a></li>
</ul>
</div>
</div><!-- top -->
<div class="header">
<div class="summary">
<a href="#func-members">Functions</a> </div>
<div class="headertitle">
<div class="title">Point pattern matching module</div> </div>
</div><!--header-->
<div class="contents">
<table class="memberdecls">
<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
Functions</h2></td></tr>
<tr class="memitem:gaccab8c3f2de716c28f89244d4054dd3d"><td class="memItemLeft" align="right" valign="top">cpl_array * </td><td class="memItemRight" valign="bottom"><a class="el" href="group__cpl__ppm.html#gaccab8c3f2de716c28f89244d4054dd3d">cpl_ppm_match_points</a> (const cpl_matrix *data, <a class="el" href="group__cpl__type.html#gacc431432a4fedf19ec6f7668dda3fbf0">cpl_size</a> use_data, double err_data, const cpl_matrix *pattern, <a class="el" href="group__cpl__type.html#gacc431432a4fedf19ec6f7668dda3fbf0">cpl_size</a> use_pattern, double err_pattern, double tolerance, double radius, cpl_matrix **mdata, cpl_matrix **mpattern, double *lin_scale, double *lin_angle)</td></tr>
<tr class="memdesc:gaccab8c3f2de716c28f89244d4054dd3d"><td class="mdescLeft"> </td><td class="mdescRight">Match 2-D distributions of points. <a href="#gaccab8c3f2de716c28f89244d4054dd3d">More...</a><br/></td></tr>
<tr class="separator:gaccab8c3f2de716c28f89244d4054dd3d"><td class="memSeparator" colspan="2"> </td></tr>
<tr class="memitem:gab7a7213433ef92ec70318f6bc3a1456f"><td class="memItemLeft" align="right" valign="top">cpl_bivector * </td><td class="memItemRight" valign="bottom"><a class="el" href="group__cpl__ppm.html#gab7a7213433ef92ec70318f6bc3a1456f">cpl_ppm_match_positions</a> (const cpl_vector *peaks, const cpl_vector *lines, double min_disp, double max_disp, double tolerance, cpl_array **seq_peaks, cpl_array **seq_lines)</td></tr>
<tr class="memdesc:gab7a7213433ef92ec70318f6bc3a1456f"><td class="mdescLeft"> </td><td class="mdescRight">Match 1-D patterns. <a href="#gab7a7213433ef92ec70318f6bc3a1456f">More...</a><br/></td></tr>
<tr class="separator:gab7a7213433ef92ec70318f6bc3a1456f"><td class="memSeparator" colspan="2"> </td></tr>
</table>
<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
<dl class="section user"><dt>Synopsis:</dt><dd><div class="fragment"><div class="line"><span class="preprocessor">#include "cpl_ppm.h"</span></div>
</div><!-- fragment --> </dd></dl>
<h2 class="groupheader">Function Documentation</h2>
<a class="anchor" id="gaccab8c3f2de716c28f89244d4054dd3d"></a>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">cpl_array* cpl_ppm_match_points </td>
<td>(</td>
<td class="paramtype">const cpl_matrix * </td>
<td class="paramname"><em>data</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype"><a class="el" href="group__cpl__type.html#gacc431432a4fedf19ec6f7668dda3fbf0">cpl_size</a> </td>
<td class="paramname"><em>use_data</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">double </td>
<td class="paramname"><em>err_data</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">const cpl_matrix * </td>
<td class="paramname"><em>pattern</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype"><a class="el" href="group__cpl__type.html#gacc431432a4fedf19ec6f7668dda3fbf0">cpl_size</a> </td>
<td class="paramname"><em>use_pattern</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">double </td>
<td class="paramname"><em>err_pattern</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">double </td>
<td class="paramname"><em>tolerance</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">double </td>
<td class="paramname"><em>radius</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">cpl_matrix ** </td>
<td class="paramname"><em>mdata</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">cpl_matrix ** </td>
<td class="paramname"><em>mpattern</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">double * </td>
<td class="paramname"><em>lin_scale</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">double * </td>
<td class="paramname"><em>lin_angle</em> </td>
</tr>
<tr>
<td></td>
<td>)</td>
<td></td><td></td>
</tr>
</table>
</div><div class="memdoc">
<p>Match 2-D distributions of points. </p>
<dl class="params"><dt>Parameters</dt><dd>
<table class="params">
<tr><td class="paramname">data</td><td>List of data points (e.g., detected stars positions). </td></tr>
<tr><td class="paramname">use_data</td><td>Number of <em>data</em> points used for preliminary match. </td></tr>
<tr><td class="paramname">err_data</td><td>Error on <em>data</em> points positions. </td></tr>
<tr><td class="paramname">pattern</td><td>List of pattern points (e.g., expected stars positions). </td></tr>
<tr><td class="paramname">use_pattern</td><td>Number of <em>pattern</em> points used for preliminary match. </td></tr>
<tr><td class="paramname">err_pattern</td><td>Error on <em>pattern</em> points positions. </td></tr>
<tr><td class="paramname">tolerance</td><td>Max relative difference of angles and scales from their median value for match acceptance. </td></tr>
<tr><td class="paramname">radius</td><td>Search radius applied in final matching (<em>data</em> units). </td></tr>
<tr><td class="paramname">mdata</td><td>List of identified <em>data</em> points. </td></tr>
<tr><td class="paramname">mpattern</td><td>List of matching <em>pattern</em> points. </td></tr>
<tr><td class="paramname">lin_scale</td><td>Linear transformation scale factor. </td></tr>
<tr><td class="paramname">lin_angle</td><td>Linear transformation rotation angle.</td></tr>
</table>
</dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd>Indexes of identified data points (pattern-to-data).</dd></dl>
<p>A point is described here by its coordinates on a cartesian plane. The input matrices <em>data</em> and <em>pattern</em> must have 2 rows, as their column vectors are the points coordinates.</p>
<p>This function attemps to associate points in <em>data</em> to points in <em>pattern</em>, under the assumption that a transformation limited to scaling, rotation, and translation, would convert positions in <em>pattern</em> into positions in <em>data</em>. Association between points is also indicated in the following as "match", or "identification".</p>
<p>Point identification is performed in two steps. In the first step only a subset of the points is identified (preliminary match). In the second step the identified points are used to define a first-guess transformation from <em>pattern</em> points to <em>data</em> points, that is applied to identify all the remaining points as well. The second step would be avoided if a <em>use_pattern</em> equal to the number of points in <em>pattern</em> is given, and exactly <em>use_pattern</em> points would be identified already in the first step.</p>
<p>First step:</p>
<p>All possible triangles (sub-patterns) are built using the first <em>use_data</em> points from <em>data</em> and the first <em>use_pattern</em> points from <em>pattern</em>. The values of <em>use_data</em> and <em>use_pattern</em> must always be at least 3 (however, see the note at the end), and should not be greater than the length of the corresponding lists of points. The point-matching algorithm goes as follow:</p>
<div class="fragment"><div class="line">For every triplet of points:</div>
<div class="line"> Select one point as the reference. The triangle coordinates </div>
<div class="line"> are defined by</div>
<div class="line"></div>
<div class="line"> ((Rmin/Rmax)^2, theta_min - theta_max)</div>
<div class="line"></div>
<div class="line"> where Rmin (Rmax) is the shortest (longest) distance from the </div>
<div class="line"> reference point to one of the two other points, and theta_min</div>
<div class="line"> (theta_max) is the view angle in [0; 2pi[ to the nearest </div>
<div class="line"> (farthest) point.</div>
<div class="line"></div>
<div class="line"> Triangles are computed by using each point in the triplet </div>
<div class="line"> as reference, thereby computing 3 times as many triangles </div>
<div class="line"> as needed.</div>
<div class="line"></div>
<div class="line"> The accuracy of triangle patterns is robust against distortions</div>
<div class="line"> (i.e., systematic inaccuracies in the points positions) of the </div>
<div class="line"> second order. This is because, if the points positions had </div>
<div class="line"> constant statistical uncertainty, the relative uncertainty in </div>
<div class="line"> the triangle coordinates would be inversely proportional to </div>
<div class="line"> the triangle size, while if second order distortions are </div>
<div class="line"> present the systematic error on points position would be </div>
<div class="line"> directly proportional to the triangle size.</div>
<div class="line"></div>
<div class="line">For every triangle derived from the @em pattern points:</div>
<div class="line"> Match with nearest triangle derived from @em data points </div>
<div class="line"> if their distance in the parameter space is less than their</div>
<div class="line"> uncertainties (propagated from the points positions uncertainties</div>
<div class="line"> @em err_data and @em err_pattern). For every matched pair of </div>
<div class="line"> triangles, record their scale ratio, and their orientation </div>
<div class="line"> difference. Note that if both @em err_data and @em err_pattern</div>
<div class="line"> are zero, the tolerance in triangle comparison will also be</div>
<div class="line"> zero, and therefore no match will be found.</div>
<div class="line"></div>
<div class="line">Get median scale ratio and median angle of rotation, and reject </div>
<div class="line">matches with a relative variation greater than @em tolerance from </div>
<div class="line">the median of either quantities. The estimator of all the rotation </div>
<div class="line">angles a_i is computed as </div>
<div class="line"></div>
<div class="line"> atan( med sin(a_i) / med cos(a_i) )</div>
</div><!-- fragment --><p>Second step:</p>
<p>From the safely matched triangles, a list of identified points is derived, and the best transformation from <em>pattern</em> points to <em>data</em> points (in terms of best rotation angle, best scaling factor, and best shift) is applied to attempt the identification of all the points that are still without match. This matching is made by selecting for each <em>pattern</em> point the <em>data</em> point which is closest to its transformed position, and at a distance less than <em>radius</em>.</p>
<p>The returned array of integers is as long as the number of points in <em>pattern</em>, and each element reports the position of the matching point in <em>data</em> (counted starting from zero), or is invalid if no match was found for the <em>pattern</em> point. For instance, if element N of the array has value M, it means that the Nth point in <em>pattern</em> matches the Mth point in <em>data</em>. A NULL pointer is returned in case no point was identified.</p>
<p>If <em>mdata</em> and <em>mpattern</em> are both valid pointers, two more matrices will be returned with the coordinates of the identified points. These two matrices will both have the same size: 2 rows, and as many columns as successfully identified points. Matching points will be in the same column of both matrices. Those matrix should in the end be destroyed using <a class="el" href="group__cpl__matrix.html#ga76f34c669aefde2a5ac3fe1e9a96d9a4" title="Delete a matrix. ">cpl_matrix_delete()</a>.</p>
<p>If <em>lin_scale</em> is a valid pointer, it is returned with a good estimate of the scale (distance_in_data = lin_scale * distance_in_pattern). This makes sense only in case the transformation between <em>pattern</em> and <em>data</em> is an affine transformation. In case of failure, <em>lin_scale</em> is set to zero.</p>
<p>If <em>lin_angle</em> is a valid pointer, it is returned with a good estimate of the rotation angle between <em>pattern</em> and <em>data</em> in degrees (counted counterclockwise, from -180 to +180, and with data_orientation = pattern_orientation + lin_angle). This makes sense only in case the transformation between <em>pattern</em> and <em>data</em> is an affine transformation. In case of failure, <em>lin_angle</em> is set to zero.</p>
<p>The returned values for <em>lin_scale</em> and <em>lin_angle</em> have the only purpose of providing a hint on the relation between <em>pattern</em> points and <em>data</em> points. This function doesn't attempt in any way to determine or even suggest a possible transformation between <em>pattern</em> points and <em>data</em> points: this function just matches points, and it is entriely a responsibility of the caller to fit the appropriate transformation between one coordinate system and the other. A polynomial transformation of degree 2 from <em>pattern</em> to <em>data</em> may be fit in the following way (assuming that <em>mpattern</em> and <em>mdata</em> are available):</p>
<div class="fragment"><div class="line"><span class="keywordtype">int</span> degree = 2;</div>
<div class="line"><span class="keywordtype">int</span> npoints = <a class="code" href="group__cpl__matrix.html#ga4bade56f31c3e0f69ca513a557c1d4fd">cpl_matrix_get_ncol</a>(mdata);</div>
<div class="line"><span class="keywordtype">double</span> *dpoints = <a class="code" href="group__cpl__matrix.html#gac3ae0a639b51b6e2a7c85046ad3f4b7f">cpl_matrix_get_data</a>(mdata);</div>
<div class="line">cpl_vector *data_x = <a class="code" href="group__cpl__vector.html#ga1f52028a78be1cab17567cf15c483fcc">cpl_vector_wrap</a>(npoints, dpoints);</div>
<div class="line">cpl_vector *data_y = <a class="code" href="group__cpl__vector.html#ga1f52028a78be1cab17567cf15c483fcc">cpl_vector_wrap</a>(npoints, dpoints + npoints);</div>
<div class="line">cpl_polynomial *x_trans = <a class="code" href="group__cpl__polynomial.html#ga6e95c460a991e29169ff1d079377f334">cpl_polynomial_new</a>(degree);</div>
<div class="line">cpl_polynomial *y_trans = <a class="code" href="group__cpl__polynomial.html#ga6e95c460a991e29169ff1d079377f334">cpl_polynomial_new</a>(degree);</div>
<div class="line"></div>
<div class="line"><a class="code" href="group__cpl__polynomial.html#gaa4cdbbf2a50f568d9768cf793b53b187">cpl_polynomial_fit</a>(x_trans, mpattern, NULL, data_x, NULL, CPL_FALSE,</div>
<div class="line"> NULL, degree);</div>
<div class="line"><a class="code" href="group__cpl__polynomial.html#gaa4cdbbf2a50f568d9768cf793b53b187">cpl_polynomial_fit</a>(y_trans, mpattern, NULL, data_y, NULL, CPL_FALSE,</div>
<div class="line"> NULL, degree);</div>
</div><!-- fragment --><dl class="section note"><dt>Note</dt><dd>The basic requirement for using this function is that the searched point pattern (or at least most of it) is contained in the data. As an indirect consequence of this, it would generally be appropriate to have more points in <em>data</em> than in <em>pattern</em> (and analogously, to have <em>use_data</em> greater than <em>use_pattern</em>), even if this is not strictly necessary.</dd></dl>
<p>Also, <em>pattern</em> and <em>data</em> should not contain too few points (say, less than 5 or 4) or the identification may risk to be incorrect: more points enable the construction of many more triangles, reducing the risk of ambiguity (multiple valid solutions). Special situations, involving regularities in patterns (as, for instance, input <em>data</em> containing just three equidistant points, or the case of a regular grid of points) would certainly provide an answer, and this answer would very likely be wrong (the human brain would fail as well, and for exactly the same reasons).</p>
<p>The reason why a two steps approach is encouraged here is mainly to enable an efficient use of this function: in principle, constructing all possible triangles using <em>all</em> of the available points is never wrong, but it could become very slow: a list of N points implies the evaluation of N*(N-1)*(N-2)/2 triangles, and an even greater number of comparisons between triangles. The possibility of evaluating first a rough transformation based on a limited number of identified points, and then using this transformation for recovering all the remaining points, may significantly speed up the whole identification process. However it should again be ensured that the main requirement (i.e., that the searched point pattern must be contained in the data) would still be valid for the selected subsets of points: a random choice would likely lead to a matching failure (due to too few, or no, common points).</p>
<p>A secondary reason for the two steps approach is to limit the effect of another class of ambiguities, happening when either or both of the input matrices contains a very large number of uniformely distributed points. The likelihood to find several triangles that are similar by chance, and at all scales and orientations, may increase to unacceptable levels.</p>
<p>A real example may clarify a possible way of using this function: let <em>data</em> contain the positions (in pixel) of detected stars on a CCD. Typically hundreds of star positions would be available, but only the brightest ones may be used for preliminary identification. The input <em>data</em> positions will therefore be opportunely ordered from the brightest to the dimmest star positions. In order to identify stars, a star catalogue is needed. From a rough knowledge of the pointing position of the telescope and of the size of the field of view, a subset of stars can be selected from the catalogue: they will be stored in the <em>pattern</em> list, ordered as well by their brightness, and with their RA and Dec coordinates converted into standard coordinates (a gnomonic coordinate system centered on the telescope pointing, i.e., a cartesian coordinate system), no matter in what units of arc, and no matter what orientation of the field. For the first matching step, the 10 brightest catalogue stars may be selected (selecting less stars would perhaps be unsafe, selecting more would likely make the program slower without producing any better result). Therefore <em>use_pattern</em> would be set to 10. From the data side, it would generally be appropriate to select twice as many stars positions, just to ensure that the searched pattern is present. Therefore <em>use_data</em> would be set to 20. A reasonable value for <em>tolerance</em> and for <em>radius</em> would be respectively 0.1 (a 10% variation of scales and angles) and 20 (pixels). </p>
<p>References <a class="el" href="group__cpl__array.html#ga6bffcca34e6751f1e5c2db6497be2074">cpl_array_delete()</a>, <a class="el" href="group__cpl__error.html#gga49a0c316d52d2afbfd9fd94b95344900a0d916ea6a7e198a74863ecd9ea03d733">CPL_ERROR_ACCESS_OUT_OF_RANGE</a>, <a class="el" href="group__cpl__error.html#gga49a0c316d52d2afbfd9fd94b95344900ae6ab32df318c1af9afcddcb8249cad51">CPL_ERROR_ILLEGAL_INPUT</a>, <a class="el" href="group__cpl__error.html#gga49a0c316d52d2afbfd9fd94b95344900a7b054cf7927d1bd0a9b3693a6715be84">CPL_ERROR_NULL_INPUT</a>, <a class="el" href="group__cpl__error.html#gad7cf962bbe59df1b5991b17b1a2361a3">cpl_error_set</a>, <a class="el" href="group__cpl__math.html#ga3f1aef1f3bb06fa03ff7f68cde9ec14b">CPL_MATH_DEG_RAD</a>, <a class="el" href="group__cpl__matrix.html#ga4bade56f31c3e0f69ca513a557c1d4fd">cpl_matrix_get_ncol()</a>, <a class="el" href="group__cpl__msg.html#ga79b9e333679e2b8f2cf8af77b8f58a91">cpl_msg_debug()</a>, <a class="el" href="group__cpl__msg.html#gaf695659392a057a4e3aea9c994ff092e">cpl_msg_indent_less()</a>, <a class="el" href="group__cpl__msg.html#gaa456b25e1c142cba44048007b8a32880">cpl_msg_indent_more()</a>, <a class="el" href="group__cpl__polynomial.html#gaad27580d5c9e514cdbcddbd0d4d038e7">cpl_polynomial_delete()</a>, <a class="el" href="group__cpl__polynomial.html#ga6e95c460a991e29169ff1d079377f334">cpl_polynomial_new()</a>, <a class="el" href="group__cpl__table.html#ga7fa13d6c00a323556c31bd531d6dc00c">cpl_table_delete()</a>, <a class="el" href="group__cpl__table.html#ga1b730484d1f4a4c260e62e042d1b7d9d">cpl_table_fill_column_window_double()</a>, <a class="el" href="group__cpl__table.html#ga7f58ee405b0bcc98d709b3acfbb71ee8">cpl_table_get_column_median()</a>, <a class="el" href="group__cpl__table.html#gabab0fdcc3cd3af2ac66fc56f1e3dda71">cpl_table_get_column_stdev()</a>, <a class="el" href="group__cpl__table.html#ga87ca9a6aca3ddfc830f64906142a21cb">cpl_table_get_data_double()</a>, <a class="el" href="group__cpl__table.html#ga92c0b33a617d6110efea6e3878987d6c">cpl_table_has_valid()</a>, <a class="el" href="group__cpl__table.html#ga1037bec8976297a42ca42da2e26f88b4">cpl_table_new()</a>, <a class="el" href="group__cpl__table.html#ga8bece2b610c28f279984da0b126939a1">cpl_table_new_column()</a>, <a class="el" href="group__cpl__table.html#gab1c5943ee40c3c71fb2e3634124e970b">cpl_table_set_invalid()</a>, and <a class="el" href="group__cpl__type.html#gga3f03371e201544e9115b40065e47f086a4923f03f3a673edd344b0d81835ca69e">CPL_TYPE_DOUBLE</a>.</p>
</div>
</div>
<a class="anchor" id="gab7a7213433ef92ec70318f6bc3a1456f"></a>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">cpl_bivector* cpl_ppm_match_positions </td>
<td>(</td>
<td class="paramtype">const cpl_vector * </td>
<td class="paramname"><em>peaks</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">const cpl_vector * </td>
<td class="paramname"><em>lines</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">double </td>
<td class="paramname"><em>min_disp</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">double </td>
<td class="paramname"><em>max_disp</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">double </td>
<td class="paramname"><em>tolerance</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">cpl_array ** </td>
<td class="paramname"><em>seq_peaks</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">cpl_array ** </td>
<td class="paramname"><em>seq_lines</em> </td>
</tr>
<tr>
<td></td>
<td>)</td>
<td></td><td></td>
</tr>
</table>
</div><div class="memdoc">
<p>Match 1-D patterns. </p>
<dl class="params"><dt>Parameters</dt><dd>
<table class="params">
<tr><td class="paramname">peaks</td><td>List of observed positions (e.g., of emission peaks) </td></tr>
<tr><td class="paramname">lines</td><td>List of positions in searched pattern (e.g., wavelengths) </td></tr>
<tr><td class="paramname">min_disp</td><td>Min expected scale (e.g., spectral dispersion in A/pixel) </td></tr>
<tr><td class="paramname">max_disp</td><td>Max expected scale (e.g., spectral dispersion in A/pixel) </td></tr>
<tr><td class="paramname">tolerance</td><td>Tolerance for interval ratio comparison </td></tr>
<tr><td class="paramname">seq_peaks</td><td>Returned: index of identified peaks in input <em>peaks</em> </td></tr>
<tr><td class="paramname">seq_lines</td><td>Returned: index of identified lines in input <em>lines</em> </td></tr>
</table>
</dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd>List of all matching points positions</dd></dl>
<p>This function attempts to find the reference pattern <em>lines</em> in a list of observed positions <em>peaks</em>. In the following documentation a terminology drawn from the context of arc lamp spectra calibration is used for simplicity: the reference pattern is then a list of wavelengths corresponding to a set of reference arc lamp emission lines - the so-called line catalog; while the observed positions are the positions (in pixel) on the CCD, measured along the dispersion direction, of any significant peak of the signal. To identify the observed peaks means to associate them with the right reference wavelength. This is attempted here with a point-pattern matching technique, where the pattern is contained in the vector <em>lines</em>, and is searched in the vector <em>peak</em>.</p>
<p>In order to work, this method just requires a rough expectation value of the spectral dispersion (in Angstrom/pixel), and a line catalog. The line catalog <em>lines</em> should just include lines that are expected somewhere in the CCD exposure of the calibration lamp (note, however, that a catalog including extra lines at its blue and/or red ends is still allowed).</p>
<p>Typically, the arc lamp lines candidates <em>peak</em> will include light contaminations, hot pixels, and other unwanted signal, but only in extreme cases does this prevent the pattern-recognition algorithm from identifying all the spectral lines. The pattern is detected even in the case <em>peak</em> contained more arc lamp lines than actually listed in the input line catalog.</p>
<p>This method is based on the assumption that the relation between wavelengths and CCD positions is with good approximation <em>locally</em> linear (this is always true, for any modern spectrograph).</p>
<p>The ratio between consecutive intervals pairs in wavelength and in pixel is invariant to linear transformations, and therefore this quantity can be used in the recognition of local portions of the searched pattern. All the examined sub-patterns will overlap, leading to the final identification of the whole pattern, notwithstanding the overall non-linearity of the relation between pixels and wavelengths.</p>
<p>Ambiguous cases, caused by exceptional regularities in the pattern, or by a number of undetected (but expected) peaks that disrupt the pattern on the data, are recovered by linear interpolation and extrapolation of the safely identified peaks.</p>
<p>More details about the applied algorithm can be found in the comments to the function code.</p>
<p>The <em>seq_peaks</em> and <em>seq_lines</em> are array reporting the positions of matching peaks and wavelengths in the input <em>peaks</em> and <em>lines</em> vectors. This functionality is not yet supported: this arguments should always be set to NULL or a CPL_ERROR_UNSUPPORTED_MODE would be set. </p>
<p>References <a class="el" href="group__cpl__bivector.html#ga8ae96fc17c12f7140ac23448874b72ff">cpl_bivector_wrap_vectors()</a>, <a class="el" href="group__cpl__memory.html#gab672473d6f7d0d933e06c2e8c456bd3b">cpl_calloc()</a>, <a class="el" href="group__cpl__error.html#gad7cf962bbe59df1b5991b17b1a2361a3">cpl_error_set</a>, <a class="el" href="group__cpl__error.html#gga49a0c316d52d2afbfd9fd94b95344900a74ef8e37f3412e85cfc22840d13bdd0c">CPL_ERROR_UNSUPPORTED_MODE</a>, <a class="el" href="group__cpl__memory.html#ga9cd2b64cbbe05ec9f34fda048184b4d1">cpl_free()</a>, <a class="el" href="group__cpl__memory.html#gac884edcb0a592489c65239d0e5d08785">cpl_malloc()</a>, <a class="el" href="group__cpl__vector.html#ga991ded30622122c78bb34191f7c7a7c6">cpl_vector_get_data_const()</a>, <a class="el" href="group__cpl__vector.html#gac72d7e38ce2f5ac2e0863e2a11e9af1d">cpl_vector_get_size()</a>, and <a class="el" href="group__cpl__vector.html#ga1f52028a78be1cab17567cf15c483fcc">cpl_vector_wrap()</a>.</p>
</div>
</div>
</div><!-- contents -->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated by  <a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/>
</a> 1.8.6
</small></address>
</body>
</html>
|