Skip to content

Commit e2089a2

Browse files
rpezzishahor02
authored andcommitted
Refactored MFT track seed covariances matrix for low Pt Tracks
1 parent 4666905 commit e2089a2

2 files changed

Lines changed: 109 additions & 115 deletions

File tree

DataFormats/Reconstruction/src/TrackFwd.cxx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ void TrackParCovFwd::addMCSEffect(double dZ, double x_over_X0)
325325
auto pathLengthOverX0 = x_over_X0 * csclambda; //
326326

327327
// Angular dispersion square of the track (variance) in a plane perpendicular to the trajectory
328-
auto sigmathetasq = 0.0136 * getInverseMomentum() * (1 + 0.038 * TMath::Log(pathLengthOverX0));
328+
auto sigmathetasq = 0.0136 * getInverseMomentum();
329329
sigmathetasq *= sigmathetasq * pathLengthOverX0;
330330

331331
// Get covariance matrix

Detectors/ITSMFT/MFT/tracking/src/TrackFitter.cxx

Lines changed: 108 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -98,127 +98,123 @@ bool TrackFitter::initTrack(TrackLTF& track, bool outward)
9898
auto& mftTrackingParam = MFTTrackingParam::Instance();
9999

100100
// initialize the starting track parameters and cluster
101-
double sigmainvQPtsq;
101+
double sigmainvQPtsq;
102102
double chi2invqptquad;
103-
double invQPtSeed;
103+
auto invQPt0 = invQPtFromFCF(track, mBZField, sigmainvQPtsq);
104104
auto nPoints = track.getNumberOfPoints();
105105
auto k = TMath::Abs(o2::constants::math::B2C * mBZField);
106106
auto Hz = std::copysign(1, mBZField);
107-
invQPtSeed = invQPtFromFCF(track, mBZField, sigmainvQPtsq);
108107

109108
if (mftTrackingParam.verbose) {
110109
std::cout << "\n ***************************** Start Fitting new track ***************************** \n";
111110
std::cout << "N Clusters = " << nPoints << std::endl;
112111
}
113112

114-
track.setInvQPtSeed(invQPtSeed);
113+
track.setInvQPtSeed(invQPt0);
115114
track.setChi2QPtSeed(chi2invqptquad);
116-
track.setInvQPt(invQPtSeed);
115+
track.setInvQPt(invQPt0);
117116

118117
/// Compute the initial track parameters to seed the Kalman filter
119118

120-
int start; // Start fitting by the first or the last cluster
121-
if (outward)
122-
start = 0;
123-
else
124-
start = nPoints - 1;
125-
126-
double x0 = track.getXCoordinates()[start];
127-
double y0 = track.getYCoordinates()[start];
128-
double z0 = track.getZCoordinates()[start];
129-
double deltaX = track.getXCoordinates()[nPoints - 1] - track.getXCoordinates()[0];
130-
double deltaY = track.getYCoordinates()[nPoints - 1] - track.getYCoordinates()[0];
131-
double deltaZ = track.getZCoordinates()[nPoints - 1] - track.getZCoordinates()[0];
132-
double deltaR = TMath::Sqrt(deltaX * deltaX + deltaY * deltaY);
133-
double tanl = 0.5 * TMath::Sqrt(2) * (deltaZ / deltaR) *
134-
TMath::Sqrt(TMath::Sqrt((invQPtSeed * deltaR * k) * (invQPtSeed * deltaR * k) + 1) + 1);
135-
double phi0 = TMath::ATan2(deltaY, deltaX) - 0.5 * Hz * invQPtSeed * deltaZ * k / tanl;
136-
double r0sq = x0 * x0 + y0 * y0;
137-
double r0cu = r0sq * TMath::Sqrt(r0sq);
138-
double invr0sq = 1.0 / r0sq;
139-
double invr0cu = 1.0 / r0cu;
140-
double sigmax0sq = track.getSigmasX2()[start];
141-
double sigmay0sq = track.getSigmasY2()[start];
142-
double sigmaDeltaZsq = 5.0; // Primary vertex distribution: beam interaction diamond
143-
double sigmaboost = mftTrackingParam.sigmaboost; // Boost q/pt seed covariances
144-
double seedH_k = mftTrackingParam.seedH_k; // SeedH constant
119+
int first_cls, last_cls;
120+
if (outward) { // MCH matching
121+
first_cls = 0;
122+
last_cls = nPoints - 1;
123+
} else { // Vertexing
124+
first_cls = nPoints - 1;
125+
last_cls = 0;
126+
}
127+
128+
auto x0 = track.getXCoordinates()[first_cls];
129+
auto y0 = track.getYCoordinates()[first_cls];
130+
auto z0 = track.getZCoordinates()[first_cls];
131+
132+
auto deltaX = track.getXCoordinates()[nPoints - 1] - track.getXCoordinates()[0];
133+
auto deltaY = track.getYCoordinates()[nPoints - 1] - track.getYCoordinates()[0];
134+
auto deltaZ = track.getZCoordinates()[nPoints - 1] - track.getZCoordinates()[0];
135+
auto deltaR = TMath::Sqrt(deltaX * deltaX + deltaY * deltaY);
136+
auto tanl0 = 0.5 * TMath::Sqrt2() * (deltaZ / deltaR) *
137+
TMath::Sqrt(TMath::Sqrt((invQPt0 * deltaR * k) * (invQPt0 * deltaR * k) + 1) + 1);
138+
auto phi0 = TMath::ATan2(deltaY, deltaX) - 0.5 * Hz * invQPt0 * deltaZ * k / tanl0;
139+
auto sigmax0sq = track.getSigmasX2()[first_cls];
140+
auto sigmay0sq = track.getSigmasY2()[first_cls];
141+
auto sigmax1sq = track.getSigmasX2()[last_cls];
142+
auto sigmay1sq = track.getSigmasY2()[last_cls];
143+
auto sigmaDeltaXsq = sigmax0sq + sigmax1sq;
144+
auto sigmaDeltaYsq = sigmay0sq + sigmay1sq;
145145

146146
track.setX(x0);
147147
track.setY(y0);
148148
track.setZ(z0);
149149
track.setPhi(phi0);
150-
track.setTanl(tanl);
151-
152-
// Configure the track seed
153-
switch (mftTrackingParam.seed) {
154-
case AB:
155-
if (mftTrackingParam.verbose)
156-
std::cout << " Init track with Seed A / B; sigmaboost = " << sigmaboost << (track.isCA() ? " CA Track " : " LTF Track") << std::endl;
157-
track.setInvQPt(1.0 / TMath::Sqrt(x0 * x0 + y0 * y0)); // Seeds A & B
158-
break;
159-
case DH:
160-
if (mftTrackingParam.verbose)
161-
std::cout << " Init track with Seed H; (k = " << seedH_k << "); sigmaboost = " << sigmaboost << (track.isCA() ? " CA Track " : " LTF Track") << std::endl;
162-
track.setInvQPt(track.getInvQPt() / seedH_k); // SeedH
163-
break;
164-
default:
165-
LOG(ERROR) << "Invalid MFT tracking seed";
166-
return false;
167-
break;
168-
}
150+
track.setTanl(tanl0);
151+
169152
if (mftTrackingParam.verbose) {
153+
std::cout << " Init " << (track.isCA() ? "CA Track " : "LTF Track") << std::endl;
170154
auto model = (mftTrackingParam.trackmodel == Helix) ? "Helix" : (mftTrackingParam.trackmodel == Quadratic) ? "Quadratic" : "Linear";
171155
std::cout << "Track Model: " << model << std::endl;
172-
std::cout << " initTrack: X = " << x0 << " Y = " << y0 << " Z = " << z0 << " Tgl = " << track.getTanl() << " Phi = " << track.getPhi() << " pz = " << track.getPz() << " qpt = " << 1.0 / track.getInvQPt() << std::endl;
173-
std::cout << " Variances: sigma_x0 = " << TMath::Sqrt(sigmax0sq) << " sigma_y0 = " << TMath::Sqrt(sigmay0sq) << " sigma_q/pt = " << TMath::Sqrt(sigmainvQPtsq) << std::endl;
156+
std::cout << " initTrack: X = " << x0 << " Y = " << y0 << " Z = " << z0 << " Tgl = " << tanl0 << " Phi = " << phi0 << " pz = " << track.getPz() << " qpt = " << 1.0 / track.getInvQPt() << std::endl;
157+
std::cout << " Variances: sigma2_x0 = " << TMath::Sqrt(sigmax0sq) << " sigma2_y0 = " << TMath::Sqrt(sigmay0sq) << " sigma2_q/pt = " << TMath::Sqrt(sigmainvQPtsq) << std::endl;
174158
}
175159

176-
auto model = (mftTrackingParam.trackmodel == Helix) ? "Helix" : (mftTrackingParam.trackmodel == Quadratic) ? "Quadratic" : "Linear";
177-
178-
179-
double C1 = track.getInvQPt() * k * deltaR;
180-
double D1 = TMath::Sqrt(C1 * C1 + 1);
181-
double invD1 = 1. / D1;
182-
double D2 = 1. / TMath::Sqrt(D1 + 1);
183-
double E1 = deltaR * D2 * D2 * invD1;
184-
double F1 = Hz * k * D2;
185-
double G1 = deltaZ * k * D2 / D1;
186-
double invDr2 = 1. / (deltaR * deltaR);
187-
double J1 = G1 * invDr2 / (k*deltaR);
188-
double L1 = C1 * C1 - 2 * D1 * (D1 + 1);
189-
double inv2rt2 = 0.25 * TMath::Sqrt(2);
190-
double Mx = invDr2 * (inv2rt2 * track.getInvQPt() * E1 * F1 * L1 * deltaX - deltaY);
191-
double My = invDr2 * (inv2rt2 * track.getInvQPt() * E1 * F1 * L1 * deltaY + deltaX);
192-
193-
double sigmax1sq = track.getSigmasX2()[0];
194-
double sigmay1sq = track.getSigmasY2()[0];
195-
double sigmaDeltaX = sigmax0sq + sigmax1sq;
196-
double sigmaDeltaY = sigmay0sq + sigmay1sq;
197-
198-
// compute the track parameter covariances at the last cluster (as if the other clusters did not exist)
199-
SMatrix55 lastParamCov;
200-
lastParamCov(0, 0) = sigmax0sq; // <X,X>
201-
lastParamCov(0, 1) = 0; // <Y,X>
202-
lastParamCov(0, 2) = sigmax0sq * Mx; // <PHI,X>
203-
lastParamCov(0, 3) = sigmax0sq * inv2rt2 * J1 * L1 * deltaX; // <TANL,X>
204-
lastParamCov(0, 4) = 0; // <INVQPT,X>
205-
206-
lastParamCov(1, 1) = sigmay0sq; // <Y,Y>
207-
lastParamCov(1, 2) = sigmay0sq * My; // <PHI,Y>
208-
lastParamCov(1, 3) = sigmay0sq * inv2rt2 * J1 * L1 * deltaY; // <TANL,Y>
209-
lastParamCov(1, 4) = 0; // <INVQPT,Y>
160+
auto deltaR2 = deltaR * deltaR;
161+
auto deltaR3 = deltaR2 * deltaR;
162+
auto deltaR4 = deltaR2 * deltaR2;
163+
auto k2 = k * k;
164+
auto A = TMath::Sqrt(track.getInvQPt() * track.getInvQPt() * deltaR2 * k2 + 1);
165+
auto A2 = A * A;
166+
auto B = A + 1.0;
167+
auto B2 = B * B;
168+
auto B3 = B * B * B;
169+
auto B12 = TMath::Sqrt(B);
170+
auto B32 = B * B12;
171+
auto B52 = B * B32;
172+
auto C = invQPt0 * k;
173+
auto C2 = C * C;
174+
auto C3 = C * C2;
175+
auto D = 1.0 / (A2 * B2 * B2 * deltaR4);
176+
auto E = D * deltaZ / (B * deltaR);
177+
auto F = deltaR * deltaX * C3 * Hz / (A * B32);
178+
auto G = 0.5 * TMath::Sqrt2() * A * B32 * C * Hz * deltaR;
179+
auto Gx = G * deltaX;
180+
auto Gy = G * deltaY;
181+
auto H = -0.25 * TMath::Sqrt2() * B12 * C3 * Hz * deltaR3;
182+
auto Hx = H * deltaX;
183+
auto Hy = H * deltaY;
184+
auto I = A * B2;
185+
auto Ix = I * deltaX;
186+
auto Iy = I * deltaY;
187+
auto J = 2 * B * deltaR3 * deltaR3 * k2;
188+
auto K = 0.5 * A * B - 0.25 * C2 * deltaR2;
189+
auto L0 = Gx + Hx + Iy;
190+
auto M0 = -Gy - Hy + Ix;
191+
auto N = -0.5 * B3 * C * Hz * deltaR3 * deltaR4 * k2;
192+
auto O = 0.125 * C2 * deltaR4 * deltaR4 * k2;
193+
auto P = -K * k * Hz * deltaR / A;
194+
auto Q = deltaZ * deltaZ / (A2 * B * deltaR3 * deltaR3);
195+
auto R = 0.25 * C * deltaZ * TMath::Sqrt2() * deltaR * k / (A * B12);
210196

211-
lastParamCov(2, 2) = sigmainvQPtsq * 0.125 * E1 * E1 * F1 * F1 * L1 * L1 + sigmaDeltaX * Mx * Mx + sigmaDeltaY * My * My; // <PHI,PHI>
212-
213-
lastParamCov(2, 3) = sigmainvQPtsq * 0.125 * C1 * E1 * F1 * G1 * L1 + inv2rt2 * J1 * L1 * (sigmaDeltaX * Mx + sigmaDeltaY * My); // <TANL,PHI>
197+
SMatrix55 lastParamCov;
198+
lastParamCov(0, 0) = sigmax0sq; // <X,X>
199+
lastParamCov(0, 1) = 0; // <Y,X>
200+
lastParamCov(0, 2) = 0; // <PHI,X>
201+
lastParamCov(0, 3) = 0; // <TANL,X>
202+
lastParamCov(0, 4) = 0; // <INVQPT,X>
214203

215-
lastParamCov(2, 4) = sigmainvQPtsq * inv2rt2 * E1 * F1 * L1; // <INVQPT,PHI>
204+
lastParamCov(1, 1) = sigmay0sq; // <Y,Y>
205+
lastParamCov(1, 2) = 0; // <PHI,Y>
206+
lastParamCov(1, 3) = 0; // <TANL,Y>
207+
lastParamCov(1, 4) = 0; // <INVQPT,Y>
216208

217-
lastParamCov(3, 3) = sigmainvQPtsq * 0.125 * C1 * C1 * G1 * G1 + 0.125 * J1 * J1 * L1 * L1 * (sigmaDeltaX * deltaX * deltaX + sigmaDeltaY * deltaY * deltaY); // <TANL,TANL>
209+
lastParamCov(2, 2) = D * (J * K * K * sigmainvQPtsq + L0 * L0 * sigmaDeltaXsq + M0 * M0 * sigmaDeltaYsq); // <PHI,PHI>
210+
lastParamCov(2, 3) = E * K * (TMath::Sqrt2() * B52 * (L0 * deltaX * sigmaDeltaXsq - deltaY * sigmaDeltaYsq * M0) + N * sigmainvQPtsq); // <TANL,PHI>
211+
lastParamCov(2, 4) = P * sigmainvQPtsq * TMath::Sqrt2() / B32; // <INVQPT,PHI>
218212

219-
lastParamCov(3, 4) = sigmainvQPtsq * inv2rt2 * C1 * G1; // <INVQPT,TANL>
213+
lastParamCov(3, 3) = Q * (2 * K * K * (deltaX * deltaX * sigmaDeltaXsq + deltaY * deltaY * sigmaDeltaYsq) + O * sigmainvQPtsq); // <TANL,TANL>
214+
lastParamCov(3, 4) = R * sigmainvQPtsq; // <INVQPT,TANL>
220215

221216
lastParamCov(4, 4) = sigmainvQPtsq; // <INVQPT,INVQPT>
217+
222218
track.setCovariances(lastParamCov);
223219
track.setTrackChi2(0.);
224220

@@ -252,7 +248,7 @@ bool TrackFitter::computeCluster(TrackLTF& track, int cluster)
252248
using o2::mft::constants::LayerZPosition;
253249
int startingLayerID, newLayerID;
254250

255-
double dZ = clz - track.getZ();
251+
auto dZ = clz - track.getZ();
256252
//LayerID of each cluster from ZPosition // TODO: Use ChipMapping
257253
for (auto layer = 10; layer--;)
258254
if (track.getZ() < LayerZPosition[layer] + .3 & track.getZ() > LayerZPosition[layer] - .3)
@@ -267,7 +263,7 @@ bool TrackFitter::computeCluster(TrackLTF& track, int cluster)
267263
else
268264
NDisksMS = (startingLayerID % 2 == 0) ? (newLayerID - startingLayerID + 1) / 2 : (newLayerID - startingLayerID) / 2;
269265

270-
double MFTDiskThicknessInX0 = mftTrackingParam.MFTRadLenghts / 5.0;
266+
auto MFTDiskThicknessInX0 = mftTrackingParam.MFTRadLenghts / 5.0;
271267
if (mftTrackingParam.verbose) {
272268
std::cout << "startingLayerID = " << startingLayerID << " ; "
273269
<< "newLayerID = " << newLayerID << " ; ";
@@ -343,9 +339,9 @@ Double_t invQPtFromFCF(const TrackLTF& track, Double_t bFieldZ, Double_t& sigmai
343339
Double_t* Rn = new Double_t[nPoints - 1];
344340
Double_t* Pn = new Double_t[nPoints - 1];
345341
Double_t A, Aerr, B, Berr, x2, y2, invx2y2, a, b, r, sigmaRsq, u2, sigma;
346-
Double_t F0,F1,F2,F3,F4, SumSRn, SumSPn, SumRn, SumUPn, SumRP;
342+
Double_t F0, F1, F2, F3, F4, SumSRn, SumSPn, SumRn, SumUPn, SumRP;
347343

348-
SumSRn = SumSPn = SumRn = SumUPn = SumRP = 0.0;
344+
SumSRn = SumSPn = SumRn = SumUPn = SumRP = 0.0;
349345
F0 = F1 = F2 = F3 = F4 = 0.0;
350346

351347
for (auto np = 0; np < nPoints; np++) {
@@ -362,54 +358,54 @@ Double_t invQPtFromFCF(const TrackLTF& track, Double_t bFieldZ, Double_t& sigmai
362358
}
363359
zVal[np] = zPositions[np];
364360
}
365-
for (int i = 0; i < (nPoints - 1); i++) {
361+
for (int i = 0; i < (nPoints - 1); i++) {
366362
x2 = xVal[i + 1] * xVal[i + 1];
367363
y2 = yVal[i + 1] * yVal[i + 1];
368364
invx2y2 = 1. / (x2 + y2);
369365
uVal[i] = xVal[i + 1] * invx2y2;
370366
vVal[i] = yVal[i + 1] * invx2y2;
371367
vErr[i] = std::sqrt(8. * xErr[i + 1] * xErr[i + 1] * x2 * y2 + 2. * yErr[i + 1] * yErr[i + 1] * (x2 - y2) * (x2 - y2)) * invx2y2 * invx2y2;
372368
u2 = uVal[i] * uVal[i];
373-
fweight[i] = 1. / vErr[i];
374-
F0 += fweight[i]; // f = fn(Hansroul) que é o peso de cada ponto Vn...inverso da incerteza?
369+
fweight[i] = 1. / vErr[i];
370+
F0 += fweight[i]; // f = fn(Hansroul) que é o peso de cada ponto Vn...inverso da incerteza?
375371
F1 += fweight[i] * uVal[i];
376372
F2 += fweight[i] * u2;
377373
F3 += fweight[i] * uVal[i] * u2;
378374
F4 += fweight[i] * u2 * u2;
379375
}
380376

381-
double Rn_det1 = F2 * F4 - F3 * F3;
377+
double Rn_det1 = F2 * F4 - F3 * F3;
382378
double Rn_det2 = F1 * F4 - F2 * F3;
383379
double Rn_det3 = F1 * F3 - F2 * F2;
384380
double Pn_det1 = Rn_det2;
385381
double Pn_det2 = F0 * F4 - F2 * F2;
386382
double Pn_det3 = F0 * F3 - F1 * F2;
387383

388-
for (int j = 0; j < (nPoints - 1); j++) {
389-
Rn[j] = fweight[j] * (Rn_det1 - uVal[j]*Rn_det2 + uVal[j]*uVal[j]*Rn_det3);
384+
for (int j = 0; j < (nPoints - 1); j++) {
385+
Rn[j] = fweight[j] * (Rn_det1 - uVal[j] * Rn_det2 + uVal[j] * uVal[j] * Rn_det3);
390386
SumSRn += Rn[j] * Rn[j] * vErr[j] * vErr[j];
391387
SumRn += Rn[j];
392388

393-
Pn[j] = fweight[j] * (-Pn_det1 + uVal[j]*Pn_det2 - uVal[j]*uVal[j]*Pn_det3);
389+
Pn[j] = fweight[j] * (-Pn_det1 + uVal[j] * Pn_det2 - uVal[j] * uVal[j] * Pn_det3);
394390
SumSPn += Pn[j] * Pn[j] * vErr[j] * vErr[j];
395391
SumUPn += uVal[j] * Pn[j];
396-
392+
397393
SumRP += Rn[j] * Pn[j] * vErr[j] * vErr[j] * vErr[j];
398394
}
399-
395+
400396
Double_t invqpt_fcf;
401397
Int_t qfcf;
402-
// chi2 = 0.;
398+
// chi2 = 0.;
403399
if (LinearRegression((nPoints - 1), uVal, vVal, vErr, B, Berr, A, Aerr)) {
404400
// v = a * u + b
405401
// circle passing through (0,0):
406402
// (x - rx)^2 + (y - ry)^2 = r^2
407403
// ---> a = - rx / ry;
408404
// ---> b = 1 / (2 * ry)
409-
b = 1. / (2. * A);
405+
b = 1. / (2. * A);
410406
a = -B * b;
411407
r = std::sqrt(a * a + b * b);
412-
double_t invR = 1./r;
408+
double_t invR = 1. / r;
413409

414410
// pt --->
415411
Double_t invpt = 1. / (o2::constants::math::B2C * bFieldZ * r);
@@ -445,15 +441,14 @@ Double_t invQPtFromFCF(const TrackLTF& track, Double_t bFieldZ, Double_t& sigmai
445441
double sigmaBsq = SumSPn / (SumUPn * SumUPn);
446442
double sigmaAB = SumRP / (SumRn * SumUPn);
447443

448-
double sigmaasq_FCF = TMath::Abs (0.25 * invA2 * invA2 * (B * B * sigmaAsq + A * A * sigmaBsq - A * B * sigmaAB));
449-
double sigmabsq_FCF = TMath::Abs (0.25 * invA2 * invA2 * sigmaAsq);
444+
double sigmaasq_FCF = TMath::Abs(0.25 * invA2 * invA2 * (B * B * sigmaAsq + A * A * sigmaBsq - A * B * sigmaAB));
445+
double sigmabsq_FCF = TMath::Abs(0.25 * invA2 * invA2 * sigmaAsq);
450446
double sigma2R = invR * invR * (b * b * sigmaasq_FCF + a * a * sigmabsq_FCF + 2 * a * b * TMath::Sqrt(sigmaasq_FCF) * TMath::Sqrt(sigmabsq_FCF));
451447

452-
sigmainvqptsq = sigma2R * invpt * invpt * invR * invR;
448+
sigmainvqptsq = sigma2R * invpt * invpt * invR * invR;
453449

454-
std::cout << " Sigma^2_A " << sigmaAsq <<" Sigma^2_B " << sigmaBsq <<" Sigma_AB " << sigmaAB << std::endl;
455-
std::cout << " Sigma^2_a " << sigmaasq_FCF <<" Sigma^2_b " << sigmabsq_FCF <<" Sigma^2_R " << sigma2R << std::endl;
456-
450+
std::cout << " Sigma^2_A " << sigmaAsq << " Sigma^2_B " << sigmaBsq << " Sigma_AB " << sigmaAB << std::endl;
451+
std::cout << " Sigma^2_a " << sigmaasq_FCF << " Sigma^2_b " << sigmabsq_FCF << " Sigma^2_R " << sigma2R << std::endl;
457452

458453
} else { // the linear regression failed...
459454
LOG(WARN) << "LinearRegression failed!";
@@ -513,6 +508,5 @@ Bool_t LinearRegression(Int_t nVal, Double_t* xVal, Double_t* yVal, Double_t* yE
513508
return kTRUE;
514509
}
515510

516-
517511
} // namespace mft
518512
} // namespace o2

0 commit comments

Comments
 (0)