This file is indexed.

/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
   &#160;<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&#160;Page</span></a></li>
      <li><a href="pages.html"><span>Related&#160;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 *&#160;</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">&#160;</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">&#160;</td></tr>
<tr class="memitem:gab7a7213433ef92ec70318f6bc3a1456f"><td class="memItemLeft" align="right" valign="top">cpl_bivector *&#160;</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">&#160;</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">&#160;</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 &quot;cpl_ppm.h&quot;</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 *&#160;</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>&#160;</td>
          <td class="paramname"><em>use_data</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">double&#160;</td>
          <td class="paramname"><em>err_data</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">const cpl_matrix *&#160;</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>&#160;</td>
          <td class="paramname"><em>use_pattern</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">double&#160;</td>
          <td class="paramname"><em>err_pattern</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">double&#160;</td>
          <td class="paramname"><em>tolerance</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">double&#160;</td>
          <td class="paramname"><em>radius</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">cpl_matrix **&#160;</td>
          <td class="paramname"><em>mdata</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">cpl_matrix **&#160;</td>
          <td class="paramname"><em>mpattern</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">double *&#160;</td>
          <td class="paramname"><em>lin_scale</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">double *&#160;</td>
          <td class="paramname"><em>lin_angle</em>&#160;</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 *&#160;</td>
          <td class="paramname"><em>peaks</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">const cpl_vector *&#160;</td>
          <td class="paramname"><em>lines</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">double&#160;</td>
          <td class="paramname"><em>min_disp</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">double&#160;</td>
          <td class="paramname"><em>max_disp</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">double&#160;</td>
          <td class="paramname"><em>tolerance</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">cpl_array **&#160;</td>
          <td class="paramname"><em>seq_peaks</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">cpl_array **&#160;</td>
          <td class="paramname"><em>seq_lines</em>&#160;</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 &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/>
</a> 1.8.6
</small></address>
</body>
</html>