CbmRoot
Loading...
Searching...
No Matches
CaCloneMerger.cxx
Go to the documentation of this file.
1/* Copyright (C) 2010-2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Sergei Zharko, Maksym Zyzak [committer]*/
4
9
10#include "CaCloneMerger.h"
11
12#include "CaFramework.h"
13#include "CaParameters.h"
14#include "CaTrack.h"
15#include "CaVector.h"
16#include "KfTrackKalmanFilter.h"
17
18#include <iostream>
19
20namespace cbm::algo::ca
21{
22 // -------------------------------------------------------------------------------------------------------------------
23 //
24 CloneMerger::CloneMerger(const ca::Parameters<fvec>& pars, const fscal mass) : fParameters(pars), fDefaultMass(mass)
25 {
26 }
27
28 // -------------------------------------------------------------------------------------------------------------------
29 //
31
32 // -------------------------------------------------------------------------------------------------------------------
33 //
34 void CloneMerger::Exec(const ca::InputData& input, WindowData& wData)
35 {
36 Vector<Track>& extTracks = wData.RecoTracks();
37 Vector<ca::HitIndex_t>& extRecoHits = wData.RecoHitIndices();
38
44 Vector<fscal>& trackChi2 = fTrackChi2;
45 Vector<char>& isStored = fTrackIsStored;
46 Vector<char>& isDownstreamNeighbour = fTrackIsDownstreamNeighbour;
47
48 int nTracks = extTracks.size();
49
50 assert(nTracks < std::numeric_limits<unsigned short>::max());
51
52 constexpr unsigned short kNoNeighbour = std::numeric_limits<unsigned short>::max();
53
54 fTracksNew.clear();
55 fTracksNew.reserve(nTracks);
56 fRecoHitsNew.clear();
57 fRecoHitsNew.reserve(extRecoHits.size());
58
59 firstStation.reset(nTracks);
60 lastStation.reset(nTracks);
61 firstHit.reset(nTracks);
62 lastHit.reset(nTracks);
63 isStored.reset(nTracks);
64 trackChi2.reset(nTracks);
65 neighbour.reset(nTracks);
66 isDownstreamNeighbour.reset(nTracks);
67
68 ca::HitIndex_t start_hit = 0;
69
70 for (int iTr = 0; iTr < nTracks; iTr++) {
71 firstHit[iTr] = start_hit;
72 firstStation[iTr] = input.GetHit(extRecoHits[start_hit]).Station();
73 start_hit += extTracks[iTr].fNofHits - 1;
74 lastHit[iTr] = start_hit;
75 lastStation[iTr] = input.GetHit(extRecoHits[start_hit]).Station();
76 start_hit++;
77
78 isStored[iTr] = false;
79 neighbour[iTr] = kNoNeighbour;
80 trackChi2[iTr] = 100000.;
81 isDownstreamNeighbour[iTr] = false;
82 }
83
86 fitB.SetMask(fmask::One());
87 fitB.SetQp0(fvec(0.));
88
91 fitF.SetMask(fmask::One());
92 fitF.SetQp0(fvec(0.));
93
94 TrackParamV& Tb = fitB.Tr();
95 TrackParamV& Tf = fitF.Tr();
98
99 // Max length for merging
100 unsigned char maxLengthForMerge = static_cast<unsigned char>(fParameters.GetNstationsActive() - 3);
101
102 for (int iTr = 0; iTr < nTracks; iTr++) {
103 if (extTracks[iTr].fNofHits > maxLengthForMerge) continue;
104 for (int jTr = 0; jTr < nTracks; jTr++) {
105 if (extTracks[jTr].fNofHits > maxLengthForMerge) continue;
106 if (iTr == jTr) continue;
107 if (firstStation[iTr] <= lastStation[jTr]) continue;
108
109 unsigned short stab = firstStation[iTr];
110
111 Tb.Set(extTracks[iTr].fParFirst);
112
113 fitB.SetQp0(fitB.Tr().GetQp());
114
115 unsigned short staf = lastStation[jTr];
116
117 Tf.Set(extTracks[jTr].fParLast);
118 fitF.SetQp0(fitF.Tr().GetQp());
119
120 if (Tf.NdfTime()[0] >= 0. && Tb.NdfTime()[0] >= 0.) {
121 if (fabs(Tf.GetTime()[0] - Tb.GetTime()[0]) > 3 * sqrt(Tf.C55()[0] + Tb.C55()[0])) continue;
122 }
123
124 unsigned short stam;
125
126 fBf = fParameters.GetStation(staf).fieldSlice.GetFieldValue(Tf.X(), Tf.Y());
127 fBb = fParameters.GetStation(stab).fieldSlice.GetFieldValue(Tb.X(), Tb.Y());
128
129 unsigned short dist = firstStation[iTr] - lastStation[jTr];
130
131 if (dist > 1)
132 stam = staf + 1;
133 else
134 stam = staf - 1;
135
136 fvec zm = fParameters.GetStation(stam).fZ;
137 fvec xm = fvec(0.5) * (Tf.GetX() + Tf.Tx() * (zm - Tf.Z()) + Tb.GetX() + Tb.Tx() * (zm - Tb.Z()));
138 fvec ym = fvec(0.5) * (Tf.Y() + Tf.Ty() * (zm - Tf.Z()) + Tb.Y() + Tb.Ty() * (zm - Tb.Z()));
139 fBm = fParameters.GetStation(stam).fieldSlice.GetFieldValue(xm, ym);
140 fld.Set(fBb, Tb.Z(), fBm, zm, fBf, Tf.Z());
141
142 fvec zMiddle = fvec(0.5) * (Tb.Z() + Tf.Z());
143
144 fitF.Extrapolate(zMiddle, fld);
145 fitB.Extrapolate(zMiddle, fld);
146
147 fvec Chi2Tracks(0.);
148 FilterTracks(&(Tf.X()), &(Tf.C00()), &(Tb.X()), &(Tb.C00()), nullptr, nullptr, &Chi2Tracks);
149 if (Chi2Tracks[0] > 50) continue;
150
151 if (Chi2Tracks[0] < trackChi2[iTr] || Chi2Tracks[0] < trackChi2[jTr]) {
152 if (neighbour[iTr] < kNoNeighbour) {
153 neighbour[neighbour[iTr]] = kNoNeighbour;
154 trackChi2[neighbour[iTr]] = 100000.;
155 isDownstreamNeighbour[neighbour[iTr]] = false;
156 }
157 if (neighbour[jTr] < kNoNeighbour) {
158 neighbour[neighbour[jTr]] = kNoNeighbour;
159 trackChi2[neighbour[jTr]] = 100000.;
160 isDownstreamNeighbour[neighbour[jTr]] = false;
161 }
162 neighbour[iTr] = jTr;
163 neighbour[jTr] = iTr;
164 trackChi2[iTr] = Chi2Tracks[0];
165 trackChi2[jTr] = Chi2Tracks[0];
166 isDownstreamNeighbour[iTr] = true;
167 isDownstreamNeighbour[jTr] = false;
168 }
169 }
170 }
171
172 for (int iTr = 0; iTr < nTracks; iTr++) {
173 if (isStored[iTr]) continue;
174
175 fTracksNew.push_back(extTracks[iTr]);
176 if (!isDownstreamNeighbour[iTr]) {
177 for (ca::HitIndex_t HI = firstHit[iTr]; HI <= lastHit[iTr]; HI++) {
178 fRecoHitsNew.push_back(extRecoHits[HI]);
179 }
180 }
181
182 if (neighbour[iTr] < kNoNeighbour) {
183 isStored[neighbour[iTr]] = true;
184 fTracksNew.back().fNofHits += extTracks[neighbour[iTr]].fNofHits;
185 for (ca::HitIndex_t HI = firstHit[neighbour[iTr]]; HI <= lastHit[neighbour[iTr]]; HI++)
186 fRecoHitsNew.push_back(extRecoHits[HI]);
187 }
188
189 if (isDownstreamNeighbour[iTr]) {
190 for (ca::HitIndex_t HI = firstHit[iTr]; HI <= lastHit[iTr]; HI++) {
191 fRecoHitsNew.push_back(extRecoHits[HI]);
192 }
193 }
194 }
195
196 // Save the merging results into external vectors
197 extTracks = std::move(fTracksNew);
198 extRecoHits = std::move(fRecoHitsNew);
199 }
200
201 // -------------------------------------------------------------------------------------------------------------------
202 //
203 void CloneMerger::FilterTracks(fvec const r[5], fvec const C[15], fvec const m[5], fvec const V[15], fvec R[5],
204 fvec W[15], fvec* chi2)
205 {
206 fvec S[15];
207 for (int i = 0; i < 15; i++) {
208 if (W) W[i] = C[i];
209 S[i] = C[i] + V[i];
210 }
211
213
214 fvec dzeta[5];
215
216 for (int i = 0; i < 5; i++)
217 dzeta[i] = m[i] - r[i];
218
219 if (W && R) {
220 for (int i = 0; i < 5; i++)
221 R[i] = r[i];
222
223 fvec K[5][5];
224 MultiplySS(C, S, K);
225
226 fvec KC[15];
227 MultiplyMS(K, C, KC);
228 for (int i = 0; i < 15; i++)
229 W[i] -= KC[i];
230
231 fvec kd;
232 for (int i = 0; i < 5; i++) {
233 kd = 0.f;
234 for (int j = 0; j < 5; j++)
235 kd += K[i][j] * dzeta[j];
236 R[i] += kd;
237 }
238 }
239 if (chi2) {
240 fvec S_dzeta[5];
241 MultiplySR(S, dzeta, S_dzeta);
242 *chi2 = dzeta[0] * S_dzeta[0] + dzeta[1] * S_dzeta[1] + dzeta[2] * S_dzeta[2] + dzeta[3] * S_dzeta[3]
243 + dzeta[4] * S_dzeta[4];
244 }
245 }
246
247 // -------------------------------------------------------------------------------------------------------------------
248 //
250 {
251 fvec d[5], uud, u[5][5];
252 for (int i = 0; i < 5; i++) {
253 d[i] = 0.f;
254 for (int j = 0; j < 5; j++)
255 u[i][j] = 0.f;
256 }
257
258 for (int i = 0; i < 5; i++) {
259 uud = 0.f;
260 for (int j = 0; j < i; j++)
261 uud += u[j][i] * u[j][i] * d[j];
262 uud = a[i * (i + 3) / 2] - uud;
263
264 fvec smallval(1.e-12);
265 uud = iif(uud >= smallval, uud, smallval);
266
267 d[i] = uud / kf::utils::fabs(uud);
268 u[i][i] = sqrt(kf::utils::fabs(uud));
269
270 for (int j = i + 1; j < 5; j++) {
271 uud = 0.f;
272 for (int k = 0; k < i; k++)
273 uud += u[k][i] * u[k][j] * d[k];
274 uud = a[j * (j + 1) / 2 + i] /*a[i][j]*/ - uud;
275 u[i][j] = d[i] / u[i][i] * uud;
276 }
277 }
278
279 fvec u1[5];
280
281 for (int i = 0; i < 5; i++) {
282 u1[i] = u[i][i];
283 u[i][i] = 1.f / u[i][i];
284 }
285 for (int i = 0; i < 4; i++) {
286 u[i][i + 1] = -u[i][i + 1] * u[i][i] * u[i + 1][i + 1];
287 }
288 for (int i = 0; i < 3; i++) {
289 u[i][i + 2] = u[i][i + 1] * u1[i + 1] * u[i + 1][i + 2] - u[i][i + 2] * u[i][i] * u[i + 2][i + 2];
290 }
291 for (int i = 0; i < 2; i++) {
292 u[i][i + 3] = u[i][i + 2] * u1[i + 2] * u[i + 2][i + 3] - u[i][i + 3] * u[i][i] * u[i + 3][i + 3];
293 u[i][i + 3] -= u[i][i + 1] * u1[i + 1] * (u[i + 1][i + 2] * u1[i + 2] * u[i + 2][i + 3] - u[i + 1][i + 3]);
294 }
295 u[0][4] = u[0][2] * u1[2] * u[2][4] - u[0][4] * u[0][0] * u[4][4];
296 u[0][4] += u[0][1] * u1[1] * (u[1][4] - u[1][3] * u1[3] * u[3][4] - u[1][2] * u1[2] * u[2][4]);
297 u[0][4] += u[3][4] * u1[3] * (u[0][3] - u1[2] * u[2][3] * (u[0][2] - u[0][1] * u1[1] * u[1][2]));
298
299 for (int i = 0; i < 5; i++)
300 a[i + 10] = u[i][4] * d[4] * u[4][4];
301 for (int i = 0; i < 4; i++)
302 a[i + 6] = u[i][3] * u[3][3] * d[3] + u[i][4] * u[3][4] * d[4];
303 for (int i = 0; i < 3; i++)
304 a[i + 3] = u[i][2] * u[2][2] * d[2] + u[i][3] * u[2][3] * d[3] + u[i][4] * u[2][4] * d[4];
305 for (int i = 0; i < 2; i++)
306 a[i + 1] =
307 u[i][1] * u[1][1] * d[1] + u[i][2] * u[1][2] * d[2] + u[i][3] * u[1][3] * d[3] + u[i][4] * u[1][4] * d[4];
308 a[0] = u[0][0] * u[0][0] * d[0] + u[0][1] * u[0][1] * d[1] + u[0][2] * u[0][2] * d[2] + u[0][3] * u[0][3] * d[3]
309 + u[0][4] * u[0][4] * d[4];
310 }
311
312 // -------------------------------------------------------------------------------------------------------------------
313 //
314 void CloneMerger::MultiplyMS(fvec const C[5][5], fvec const V[15], fvec K[15])
315 {
316 K[0] = C[0][0] * V[0] + C[0][1] * V[1] + C[0][2] * V[3] + C[0][3] * V[6] + C[0][4] * V[10];
317
318 K[1] = C[1][0] * V[0] + C[1][1] * V[1] + C[1][2] * V[3] + C[1][3] * V[6] + C[1][4] * V[10];
319 K[2] = C[1][0] * V[1] + C[1][1] * V[2] + C[1][2] * V[4] + C[1][3] * V[7] + C[1][4] * V[11];
320
321 K[3] = C[2][0] * V[0] + C[2][1] * V[1] + C[2][2] * V[3] + C[2][3] * V[6] + C[2][4] * V[10];
322 K[4] = C[2][0] * V[1] + C[2][1] * V[2] + C[2][2] * V[4] + C[2][3] * V[7] + C[2][4] * V[11];
323 K[5] = C[2][0] * V[3] + C[2][1] * V[4] + C[2][2] * V[5] + C[2][3] * V[8] + C[2][4] * V[12];
324
325 K[6] = C[3][0] * V[0] + C[3][1] * V[1] + C[3][2] * V[3] + C[3][3] * V[6] + C[3][4] * V[10];
326 K[7] = C[3][0] * V[1] + C[3][1] * V[2] + C[3][2] * V[4] + C[3][3] * V[7] + C[3][4] * V[11];
327 K[8] = C[3][0] * V[3] + C[3][1] * V[4] + C[3][2] * V[5] + C[3][3] * V[8] + C[3][4] * V[12];
328 K[9] = C[3][0] * V[6] + C[3][1] * V[7] + C[3][2] * V[8] + C[3][3] * V[9] + C[3][4] * V[13];
329
330 K[10] = C[4][0] * V[0] + C[4][1] * V[1] + C[4][2] * V[3] + C[4][3] * V[6] + C[4][4] * V[10];
331 K[11] = C[4][0] * V[1] + C[4][1] * V[2] + C[4][2] * V[4] + C[4][3] * V[7] + C[4][4] * V[11];
332 K[12] = C[4][0] * V[3] + C[4][1] * V[4] + C[4][2] * V[5] + C[4][3] * V[8] + C[4][4] * V[12];
333 K[13] = C[4][0] * V[6] + C[4][1] * V[7] + C[4][2] * V[8] + C[4][3] * V[9] + C[4][4] * V[13];
334 K[14] = C[4][0] * V[10] + C[4][1] * V[11] + C[4][2] * V[12] + C[4][3] * V[13] + C[4][4] * V[14];
335 }
336
337 // -------------------------------------------------------------------------------------------------------------------
338 //
339 void CloneMerger::MultiplySR(fvec const C[15], fvec const r_in[5], fvec r_out[5])
340 {
341 r_out[0] = r_in[0] * C[0] + r_in[1] * C[1] + r_in[2] * C[3] + r_in[3] * C[6] + r_in[4] * C[10];
342 r_out[1] = r_in[0] * C[1] + r_in[1] * C[2] + r_in[2] * C[4] + r_in[3] * C[7] + r_in[4] * C[11];
343 r_out[2] = r_in[0] * C[3] + r_in[1] * C[4] + r_in[2] * C[5] + r_in[3] * C[8] + r_in[4] * C[12];
344 r_out[3] = r_in[0] * C[6] + r_in[1] * C[7] + r_in[2] * C[8] + r_in[3] * C[9] + r_in[4] * C[13];
345 r_out[4] = r_in[0] * C[10] + r_in[1] * C[11] + r_in[2] * C[12] + r_in[3] * C[13] + r_in[4] * C[14];
346 }
347
348 // -------------------------------------------------------------------------------------------------------------------
349 //
350 void CloneMerger::MultiplySS(fvec const C[15], fvec const V[15], fvec K[5][5])
351 {
352 K[0][0] = C[0] * V[0] + C[1] * V[1] + C[3] * V[3] + C[6] * V[6] + C[10] * V[10];
353 K[0][1] = C[0] * V[1] + C[1] * V[2] + C[3] * V[4] + C[6] * V[7] + C[10] * V[11];
354 K[0][2] = C[0] * V[3] + C[1] * V[4] + C[3] * V[5] + C[6] * V[8] + C[10] * V[12];
355 K[0][3] = C[0] * V[6] + C[1] * V[7] + C[3] * V[8] + C[6] * V[9] + C[10] * V[13];
356 K[0][4] = C[0] * V[10] + C[1] * V[11] + C[3] * V[12] + C[6] * V[13] + C[10] * V[14];
357
358 K[1][0] = C[1] * V[0] + C[2] * V[1] + C[4] * V[3] + C[7] * V[6] + C[11] * V[10];
359 K[1][1] = C[1] * V[1] + C[2] * V[2] + C[4] * V[4] + C[7] * V[7] + C[11] * V[11];
360 K[1][2] = C[1] * V[3] + C[2] * V[4] + C[4] * V[5] + C[7] * V[8] + C[11] * V[12];
361 K[1][3] = C[1] * V[6] + C[2] * V[7] + C[4] * V[8] + C[7] * V[9] + C[11] * V[13];
362 K[1][4] = C[1] * V[10] + C[2] * V[11] + C[4] * V[12] + C[7] * V[13] + C[11] * V[14];
363
364 K[2][0] = C[3] * V[0] + C[4] * V[1] + C[5] * V[3] + C[8] * V[6] + C[12] * V[10];
365 K[2][1] = C[3] * V[1] + C[4] * V[2] + C[5] * V[4] + C[8] * V[7] + C[12] * V[11];
366 K[2][2] = C[3] * V[3] + C[4] * V[4] + C[5] * V[5] + C[8] * V[8] + C[12] * V[12];
367 K[2][3] = C[3] * V[6] + C[4] * V[7] + C[5] * V[8] + C[8] * V[9] + C[12] * V[13];
368 K[2][4] = C[3] * V[10] + C[4] * V[11] + C[5] * V[12] + C[8] * V[13] + C[12] * V[14];
369
370 K[3][0] = C[6] * V[0] + C[7] * V[1] + C[8] * V[3] + C[9] * V[6] + C[13] * V[10];
371 K[3][1] = C[6] * V[1] + C[7] * V[2] + C[8] * V[4] + C[9] * V[7] + C[13] * V[11];
372 K[3][2] = C[6] * V[3] + C[7] * V[4] + C[8] * V[5] + C[9] * V[8] + C[13] * V[12];
373 K[3][3] = C[6] * V[6] + C[7] * V[7] + C[8] * V[8] + C[9] * V[9] + C[13] * V[13];
374 K[3][4] = C[6] * V[10] + C[7] * V[11] + C[8] * V[12] + C[9] * V[13] + C[13] * V[14];
375
376 K[4][0] = C[10] * V[0] + C[11] * V[1] + C[12] * V[3] + C[13] * V[6] + C[14] * V[10];
377 K[4][1] = C[10] * V[1] + C[11] * V[2] + C[12] * V[4] + C[13] * V[7] + C[14] * V[11];
378 K[4][2] = C[10] * V[3] + C[11] * V[4] + C[12] * V[5] + C[13] * V[8] + C[14] * V[12];
379 K[4][3] = C[10] * V[6] + C[11] * V[7] + C[12] * V[8] + C[13] * V[9] + C[14] * V[13];
380 K[4][4] = C[10] * V[10] + C[11] * V[11] + C[12] * V[12] + C[13] * V[13] + C[14] * V[14];
381 }
382} // namespace cbm::algo::ca
source file for the ca::Track class
friend fvec sqrt(const fvec &a)
friend fvec iif(fmask a, fvec b, fvec c)
Track fit utilities for the CA tracking based on the Kalman filter.
Vector< unsigned short > fTrackLastStation
Last station of a track.
static void MultiplySS(fvec const C[15], fvec const V[15], fvec K[5][5])
Vector< char > fTrackIsDownstreamNeighbour
Flag: is the track a downstream neighbour of another track.
fscal fDefaultMass
mass of the propagated particle [GeV/c2]
CloneMerger(const ca::Parameters< fvec > &pars, const fscal mass)
Default constructor.
Vector< Track > fTracksNew
vector of tracks after the merge
const Parameters< fvec > & fParameters
Object of Framework parameters class.
Vector< unsigned short > fTrackNeighbour
Index (TODO:??) of a track that can be merge with the given track.
Vector< ca::HitIndex_t > fRecoHitsNew
vector of track hits after the merge
static void MultiplyMS(fvec const C[5][5], fvec const V[15], fvec K[15])
void Exec(const ca::InputData &input, WindowData &wData)
Registers.
static void MultiplySR(fvec const C[15], fvec const r_in[5], fvec r_out[5])
Vector< char > fTrackIsStored
Flag: is the given track already stored to the output.
Vector< unsigned short > fTrackFirstStation
First station of a track.
Vector< fscal > fTrackChi2
Chi2 value of the track merging procedure.
Vector< ca::HitIndex_t > fTrackFirstHit
Index of the first hit of a track.
static void FilterTracks(fvec const r[5], fvec const C[15], fvec const m[5], fvec const V[15], fvec R[5], fvec W[15], fvec *chi2)
Vector< ca::HitIndex_t > fTrackLastHit
Index of the last hit of a track.
static void InvertCholesky(fvec a[15])
int Station() const
Get the station index.
Definition CaHit.h:138
const Hit & GetHit(HitIndex_t index) const
Gets reference to hit by its index.
Definition CaInputData.h:55
A container for all external parameters of the CA tracking algorithm.
void push_back(Tinput value)
Pushes back a value to the vector.
Definition CaVector.h:176
T & back()
Mutable access to the last element of the vector.
Definition CaVector.h:230
void reserve(std::size_t count)
Reserves a new size for the vector.
Definition CaVector.h:162
void reset(std::size_t count, Tinput... value)
Clears vector and resizes it to the selected size with selected values.
Definition CaVector.h:121
Container for internal data, processed on a single time window.
Vector< Track > & RecoTracks()
Accesses reconstructed track container.
Vector< HitIndex_t > & RecoHitIndices()
Accesses indices of hits, used by reconstructed tracks.
Magnetic field region, corresponding to a hit triplet.
Magnetic flux density vector.
void Set(const I &bx, const I &by, const I &bz)
Constructor from components.
void Extrapolate(DataT z, const kf::FieldRegion< DataT > &F)
kf::TrackParam< DataT > & Tr()
void SetParticleMass(DataT mass)
set particle mass for the fit
T C00() const
Individual getters for covariance matrix elements.
T NdfTime() const
Gets NDF of time measurements.
T Tx() const
Gets slope along x-axis.
T GetTime() const
Gets time [ns].
T X() const
Gets x position [cm].
T GetQp() const
Gets charge over momentum [ec/GeV].
T Y() const
Gets y position [cm].
T Z() const
Gets z position [cm].
void Set(const TrackParamBase< T1 > &Tb)
T Ty() const
Gets slope along y-axis.
T GetX() const
Gets x position [cm].
static fmask One()
TODO: SZh 8.11.2022: add selection of parameterisation.
Definition CaBranch.h:14
class cbm::algo::ca::WindowData _fvecalignment
kf::fscal fscal
Definition CaSimd.h:14
unsigned int HitIndex_t
Index of ca::Hit.
Definition CaHit.h:27
kf::fvec fvec
Definition CaSimd.h:13
fvec fabs(const fvec &v)
Definition KfUtils.h:30