51 #include <Minuit2/FCNBase.h>
52 #include <Minuit2/MnPrint.h>
53 #include <Math/Functor.h>
54 #include <Fit/Fitter.h>
55 #if ROOT_VERSION_CODE < ROOT_VERSION(5,90,0)
56 #include <TFitterMinuit.h>
62 : fMaxRoad(0.0),fMaxXRoad(0.0)
91 double track_position,
95 double position, distance, best_position,best_distance;
99 distance = fabs ( track_position - position );
101 best_position = position;
102 best_distance = distance;
106 distance = fabs ( track_position - position );
108 if ( distance < best_distance )
109 best_position = position;
141 double track_position = *xresult;
143 double minimum = resolution;
144 double wirespacing = hitlist->begin()->GetDetectorInfo()->GetElementSpacing();
147 QwHitContainer::iterator end=hitlist->end();
148 for ( QwHitContainer::iterator hit = hitlist->begin();
151 if(hit->GetHitNumber()!=0 || hit->GetDriftDistance()<0)
continue;
153 for (
int j = 0; j < 2; ++j )
155 double hit_position =
156 j ? ( hit->GetElement()-0.5) * wirespacing +
157 hit->GetDriftDistance() + Dx
158 : (hit->GetElement()-0.5)* wirespacing-hit->GetDriftDistance()+Dx;
159 double signed_distance = track_position - hit_position;
160 double distance = fabs ( signed_distance );
164 if ( distance < resolution )
171 ha[ngood] =
new QwHit;
177 if ( distance < minimum )
191 for (
int i = 0; i < ngood; ++i )
196 if ( distance < odist )
236 for (
int j = 0; j < l; j++ )
243 for (
int j = 0; j < l; j++ )
285 double A[n][2],
G[n][n], AtGA[2][2];
286 double AtGy[2], y[n], x[2];
288 for (
int i = 0; i < n; ++i )
292 for (
int i = 0; i < n; ++i )
297 G[i][i] = 1.0 / ( resolution * resolution );
301 for (
int k = 0; k < 2; ++k )
304 for (
int i = 0; i < n; i++ )
305 sum += ( A[i][k] ) * G[i][i] * y[i];
310 for (
int j = 0; j < 2; ++j )
312 for (
int k = 0; k < 2; ++k )
315 for (
int i = 0; i < n; ++i )
316 sum += ( A[i][j] ) * G[i][i] * A[i][k];
322 double det = ( AtGA[0][0] * AtGA[1][1] - AtGA[1][0] * AtGA[0][1] );
323 double tmp = AtGA[0][0];
324 AtGA[0][0] = AtGA[1][1] / det;
325 AtGA[1][1] = tmp / det;
330 for (
int k = 0; k < 2; ++k )
331 x[k] = AtGA[k][0] * AtGy[0] + AtGA[k][1] * AtGy[1];
341 double firstpass=0.0;
342 for (
int i = 0; i < n; ++i )
348 firstpass+=fabs(residual);
349 sum += G[i][i] * residual * residual;
353 chi = sqrt ( sum / (n-2) );
363 if(n==5 && firstpass>bad_){
366 for(
int drop=0;drop<4;++drop){
367 for (
int k = 0; k < 2; ++k )
370 for (
int i = 0; i < n; ++i ){
372 sum += ( A[i][k] ) * G[i][i] * y[i];
378 for (
int j = 0; j < 2; ++j )
380 for (
int k = 0; k < 2; ++k )
383 for (
int i = 0; i < n; i++ ){
385 sum += ( A[i][j] ) * G[i][i] * A[i][k];
392 double det = ( AtGA[0][0] * AtGA[1][1] - AtGA[1][0] * AtGA[0][1] );
393 double tmp = AtGA[0][0];
394 AtGA[0][0] = AtGA[1][1] / det;
395 AtGA[1][1] = tmp / det;
400 for (
int k = 0; k < 2; ++k )
401 x[k] = AtGA[k][0] * AtGy[0] + AtGA[k][1] * AtGy[1];
412 for (
int i = 0; i < n; ++i )
418 sum += G[i][i] * residual * residual;
422 double chi_second=sqrt(sum/(n-3));
423 if(sqrt(chi_second<chi/10)){
459 const std::vector<QwHit*> hits,
464 if (hits.size() == 0)
return;
467 size_t n = hits.size();
470 double A[n][2],
G[n][n], AtGA[2][2];
471 double AtGy[2], y[n], x[2];
474 for (
size_t i = 0; i < n; i++)
480 for (
size_t i = 0; i < n; i++)
482 if ( wire_offset == -1 )
484 A[i][1] = -hits[i]->GetWirePosition();
485 y[i] = -hits[i]->GetDriftPosition();
490 A[i][1] = -hits[i]->GetElement();
491 y[i] = -hits[i]->GetDriftPosition();
493 double resolution = hits[i]->GetDetectorInfo()->GetSpatialResolution();
494 G[i][i] = 1.0 / ( resolution * resolution );
498 for (
size_t k = 0; k < 2; k++)
501 for (
size_t i = 0; i < n; i++)
502 sum += A[i][k] * G[i][i] * y[i];
506 for (
size_t j = 0; j < 2; j++)
508 for (
size_t k = 0; k < 2; k++)
511 for (
size_t i = 0; i < n; i++)
512 sum += A[i][j] * G[i][i] * A[i][k];
518 double det = (AtGA[0][0] * AtGA[1][1] - AtGA[1][0] * AtGA[0][1]);
519 double tmp = AtGA[0][0];
520 AtGA[0][0] = AtGA[1][1] / det;
521 AtGA[1][1] = tmp / det;
526 for (
size_t k = 0; k < 2; k++)
527 x[k] = AtGA[k][0] * AtGy[0] + AtGA[k][1] * AtGy[1];
537 if ( wire_offset == -1 )
539 for (
size_t i = 0; i < n; i++)
541 hits[i]->SetTreeLinePosition ( slope * ( hits[i]->GetWirePosition() - z1 ) + offset );
542 hits[i]->CalculateTreeLineResidual();
543 double residual = hits[i]->GetTreeLineResidual();
544 sum += G[i][i] * residual * residual;
549 for (
size_t i = 0; i < n; i++)
553 hits[i]->SetWirePosition (hits[i]->GetElement());
554 hits[i]->SetTreeLinePosition ( slope * hits[i]->GetElement() + offset );
555 hits[i]->CalculateTreeLineResidual();
557 double residual = hits[i]->GetTreeLineResidual();
558 sum += G[i][i] * residual * residual;
562 chi = sqrt ( sum / ( n-2 ) );
571 cerr <<
"[QwTrackingTreeCombine::contains] Warning: double == double is unsafe." << endl;
572 for (
int i = 0; i < len ; i++ )
574 if ( var == arr[i]->GetDriftPosition() )
605 double minimum = resolution;
610 QwHit* h = *hitarray;
620 if ( !
contains ( position, ha, good ) )
622 double distance = x - position;
624 if ( fabs ( distance ) < minimum )
627 minimum = fabs ( distance );
653 double cx,
double mx,
654 double cy,
double my )
674 for (
size_t i = 0; i < vdc.size(); i++) {
677 double x = cx + (z - z1) * mx;
678 double y = cy + (z - z1) * my;
725 double x1,
double x2,
726 double dx1,
double dx2,
743 std::vector<int> patterns_copy;
745 if (
DLAYERS < 4 ) cerr <<
"Error: DLAYERS must be >= 4 for region 2!" << endl;
757 for (
int i = 0; i <
DLAYERS; ++i )
770 double orig_slope = (x2 - x1) / Dz;
771 double orig_dmx = (dx2 - dx1) / Dz;
785 double resolution = width / ( 1 << ( levels - 1 ) );
794 int nPlanesWithHits = 0;
797 int nPermutations = 1;
805 for (
size_t plane = 0; plane < planes.size(); ++plane) {
811 double thisZ = planes.at(plane)->GetZPosition();
812 double thisX = orig_slope * (thisZ - z1) + x1;
816 front_plane = planes.at(plane);
823 if (planes.at(plane)->IsInactive()) {
829 if (hitsInPlane->size() == 0) {
837 double resnow = orig_dmx * (thisZ - z1) + dx1;
842 && plane+1 == planes.size()
844 resnow -= resolution * (
fMaxRoad - 1.0);
853 DX_pass = plane<2 ? 0.0:Dx;
855 nHitsInPlane[nPlanesWithHits] =
860 nHitsInPlane[nPlanesWithHits] =
861 selectx(&thisX, resnow, treeline->
fHits, goodHits[nPlanesWithHits]);
867 if ( nHitsInPlane[nPlanesWithHits] ) {
868 nPermutations *= nHitsInPlane[nPlanesWithHits];
881 for (
int planeWithHits = 0; planeWithHits < nPlanesWithHits; ++planeWithHits )
883 for (
int hitInPlane = 0; hitInPlane < nHitsInPlane[planeWithHits]; ++hitInPlane )
885 *hitarray = goodHits[planeWithHits][hitInPlane];
911 int best_permutation = -1;
912 double best_slope = 0.0, best_offset = 0.0, best_chi = 1e10;
913 double best_cov[3] = {0.0, 0.0, 0.0};
914 double best_trackpos[4]={0.0};
915 for (
int permutation = 0; permutation < nPermutations; ++permutation )
922 double slope, offset;
924 double cov[3] = {0.0, 0.0, 0.0};
926 r2_TreelineFit ( slope, offset, cov, chi, usedHits, nPlanesWithHits );
931 double stay_chi = 0.0;
935 ( x1 + orig_slope * ( startZ - z1 ) ) );
938 ( x1 + orig_slope * ( endZ - z1 ) ) );
955 if ( chi < best_chi )
957 for(
int plane=0;plane<nPlanesWithHits;++plane)
958 best_trackpos[plane]=0.0;
961 best_offset = offset;
962 best_permutation = permutation;
963 for(
int plane=0;plane<nPlanesWithHits;++plane){
964 if(!usedHits[plane]->IsUsed())
965 best_trackpos[plane]=usedHits[plane]->GetTreeLinePosition();
968 memcpy ( best_cov, cov,
sizeof cov );
973 for(
int plane=0;plane<nPlanesWithHits;++plane)
974 if(usedHits[plane]->IsUsed())
975 usedHits[plane]->
SetUsed(
false);
980 treeline->
fOffset = best_offset;
981 treeline->
fSlope = best_slope;
982 treeline->
fChi = best_chi;
983 treeline->
fNumHits = nPlanesWithHits;
984 treeline->
SetCov ( best_cov );
988 if ( best_permutation != -1 )
991 nPlanesWithHits, nHitsInPlane, goodHits, usedHits );
993 for(
int plane=0;plane<nPlanesWithHits;++plane){
1003 for (
int plane = 0; plane < nPlanesWithHits; ++plane )
1005 if(best_trackpos[plane]!=0.0){
1006 treeline->
AddHit(usedHits[plane]);
1007 if ( usedHits[plane] )
1008 usedHits[plane]->
SetUsed (
true );
1013 for (
int plane = 0; plane < nPlanesWithHits; ++plane )
1015 if ( usedHits[plane] ) treeline->
AddHit ( usedHits[plane] );
1020 if (treeline->
fHits[0])
1024 if ( best_permutation == -1 )
1036 treeline->
fNumMiss = dlayer - nPlanesWithHits;
1091 double dx = x2 - x1;
1092 double dz = z2 - z1;
1093 double track_slope = dx / dz;
1095 double intercept = x1 - track_slope * z1;
1107 std::vector<size_t> crosstalk_hits;
1109 for (QwHitContainer::iterator hit = hitlist->begin();
1110 hit != hitlist->end() && nHits < tlayers; hit++ )
1115 int wire = hit->GetElement();
1117 if (wire < tl_first || wire > tl_last) {
1121 if (hit->IsUsed() ==
false)
1139 double thisZ = ( double ) hit->GetElement();
1141 double thisX = track_slope * thisZ + intercept;
1151 treeline->
AddHit(goodhit);
1162 QwVerbose <<
"Potential crosstalk: wire " << wire <<
" with " << wire2
1163 <<
" in det " << hit->GetDetectorInfo()->GetDetectorName() <<
QwLog::endl;
1180 double slope = 0.0, offset = 0.0;
1181 double cov[3] = {0.0, 0.0, 0.0};
1201 if (crosstalk_hits.size() > 0) {
1204 std::vector<size_t> delete_hits;
1207 for (
size_t i1 = 0; i1 < crosstalk_hits.size(); i1++) {
1208 const QwHit* hit1 = treeline->
GetHit(crosstalk_hits.at(i1));
1214 for (
size_t i2 = i1+1; i2 < crosstalk_hits.size(); i2++) {
1215 const QwHit* hit2 = treeline->
GetHit(crosstalk_hits.at(i2));
1221 if (wire1 == wire2_crosstalk && wire2 == wire1_crosstalk) {
1227 <<
"wire1 " << wire1 <<
" res1 = " << res1 <<
" cm, "
1228 <<
"wire2 " << wire2 <<
" res2 = " << res2 <<
" cm"
1233 QwVerbose <<
"Will delete hit " << crosstalk_hits.at(i1)
1235 << treeline->
GetHit(crosstalk_hits.at(i1))->GetElement()
1237 delete_hits.push_back(crosstalk_hits.at(i1));
1239 i2 = crosstalk_hits.size();
1241 QwVerbose <<
"Will delete hit " << crosstalk_hits.at(i2)
1243 << treeline->
GetHit(crosstalk_hits.at(i2))->GetElement()
1245 delete_hits.push_back(crosstalk_hits.at(i2));
1259 std::sort(delete_hits.begin(), delete_hits.end());
1260 std::vector<size_t>::iterator uniques_end =
1261 std::unique(delete_hits.begin(), delete_hits.end());
1262 delete_hits.resize(std::distance(delete_hits.begin(),uniques_end));
1263 for (
int i = delete_hits.size() - 1; i >= 0; i--) {
1264 QwVerbose <<
"Deleting hit " << delete_hits.at(i)
1266 << treeline->
GetHit(delete_hits.at(i))->GetElement()
1268 << treeline->
GetHit(delete_hits.at(i))->GetTreeLineResidual()
1300 treeline->
fNumMiss = nWires - nHits;
1305 QwDebug <<
"...well, actually this hasn't been implemented properly yet." <<
QwLog::endl;
1307 treeline->
fNumMiss = nWires - nHits;
1344 treeline && treeline->
IsValid();
1345 treeline = treeline->
next )
1352 double d1 = 0, d2 = 0;
1354 for (QwHitContainer::iterator hit = hitlist->begin(); hit != hitlist->end(); hit++) {
1355 int wire = hit->GetElement();
1357 if(oct==0 && hit->GetDetectorInfo()->GetPackage() == package){
1358 oct=hit->GetDetectorInfo()->GetOctant();
1360 if (row < 0 || row > 7)
continue;
1361 double distance = hit->GetDriftDistance();
1362 double track_resolution=hit->GetDetectorInfo()->GetTrackResolution();
1363 std::pair<double,double> range = treeline->
CalculateDistance(row,width,bins,track_resolution);
1364 if (distance >= range.first && distance <= range.second) {
1367 if (wire == z1 && hit->IsUsed())
1369 else if (wire == z2 && hit->IsUsed())
1405 assert(front->GetOctant()==back->
GetOctant());
1409 double Dz = (z2 - z1);
1418 dx /= ( double ) bins;
1427 treeline; treeline = treeline->
next )
1429 if ( treeline->
IsVoid() )
1436 treeline->
SetOctant(front->GetOctant());
1451 QwDebug <<
"(x1,x2,z1,z2) = (" << x1 <<
", " << x2 <<
", " << z1 <<
", " << z2 <<
"); " <<
QwLog::endl;
1456 x1, x2, dx1, dx2, Dx, z1, Dz,
1458 tlayer, tlayer, 0, 0, width );
1473 for (
QwTreeLine *treeline = treelinelist; treeline;
1474 treeline = treeline->
next) {
1482 for (
QwTreeLine *treeline1 = treelinelist; treeline1;
1483 treeline1 = treeline1->
next) {
1484 if (treeline1->IsValid()) {
1486 treeline2 = treeline2->
next) {
1487 if (treeline2->IsValid()
1488 && treeline1->fOffset == treeline2->fOffset
1489 && treeline1->fSlope == treeline2->fSlope) {
1490 QwDebug << *treeline2 <<
"... ";
1492 treeline2->SetVoid();
1499 cout <<
"List of treelines:" << endl;
1500 if (treelinelist) treelinelist->
Print();
1517 class MyFCN :
public ROOT::Minuit2::FCNBase {
1521 MyFCN(std::vector<QwHit*> fhits) : hits(fhits) {}
1523 double operator() (
const double* array)
const {
1524 const std::vector<double> fit(array, array + 4);
1525 return operator()(fit);
1528 double operator() (
const std::vector<double> & fit)
const {
1531 double resolution = hits[0]->GetDetectorInfo()->GetSpatialResolution();
1532 double normalization = 1/(resolution*resolution);
1536 double dx_[12] = { 0.0 };
1537 double l[3] = { 0.0 };
1538 double h[3] = { 0.0 };
1539 for (
size_t i = 0; i < hits.size(); ++i)
1540 dx_[hits[i]->GetPlane() - 1] = hits[i]->GetDetectorInfo()->GetPlaneOffset();
1542 for (
size_t i = 0; i < 3; ++i)
1544 h[i] = dx_[6 + i] == 0 ? dx_[9 + i] : dx_[6 + i];
1545 l[i] = dx_[i] == 0 ? dx_[3 + i] : dx_[i];
1546 dx_[i] = dx_[3 + i] = 0;
1547 dx_[6 + i] = dx_[9 + i] = h[i] - l[i];
1550 for (
size_t i=0; i<hits.size();i++)
1553 double cosx = hits[i]->GetDetectorInfo()->GetDetectorRollCos();
1554 double sinx = hits[i]->GetDetectorInfo()->GetDetectorRollSin();
1555 double cosy = hits[i]->GetDetectorInfo()->GetDetectorPitchCos();
1556 double siny = hits[i]->GetDetectorInfo()->GetDetectorPitchSin();
1557 double rcos = hits[i]->GetDetectorInfo()->GetElementAngleCos();
1558 double rsin = hits[i]->GetDetectorInfo()->GetElementAngleSin();
1560 double dx = dx_[hits[i]->GetPlane() - 1];
1562 double wire_off = -0.5 * hits[i]->GetDetectorInfo()->GetElementSpacing()
1563 + hits[i]->GetDetectorInfo()->GetElementOffset();
1564 double hit_pos = hits[i]->GetDriftPosition() + wire_off - dx;
1567 double x0 = hit_pos/rsin;
1568 double y0 = hit_pos/rcos;
1571 if(hits[i]->GetPackage()==1) zRot = -315.9965;
1572 if(hits[i]->GetPackage()==2) zRot = -315.33;
1574 double z0 = hits[i]->GetDetectorInfo()->GetZPosition();
1575 double zD = z0 - zRot;
1584 xR_1 = cosy*x0 +zD*cosx*siny;
1586 zR_1 = zD*cosx*cosy + zRot - siny*x0;
1588 xR_2 = zD*cosx*siny - siny*sinx*y0;
1589 yR_2 = cosx*y0 + zD*sinx;
1590 zR_2 = zD*cosx*cosy + zRot - sinx*cosy*y0;
1592 double xc = hits[i]->GetDetectorInfo()->GetXPosition();
1593 double yc = hits[i]->GetDetectorInfo()->GetYPosition();
1595 double z = (-(fit[1]-xc-zD*cosx*siny)*cosx*siny -
1596 (fit[3]-yc-zD*sinx)*sinx*(cosy*cosy-siny*siny) +
1597 (zRot + zD*cosx*cosy)*cosy*cosx) /
1598 (fit[0]*cosx*siny + fit[2]*sinx*(cosy*cosy-siny*siny) + cosy*cosx);
1600 double x = fit[1] + fit[0] * z;
1601 double y = fit[3] + fit[2] * z;
1607 double diffx = xR_2 - xR_1;
1608 double diffy = yR_2 - yR_1;
1609 double diffz = zR_2 - zR_1;
1611 double numx = -y*diffz + z*diffy + yR_1*zR_2 - yR_2*zR_1;
1612 double numy = x*diffz - z*diffx - xR_1*zR_2 + xR_2*zR_1;
1613 double numz = -x*diffy + y*diffx + xR_1*yR_2 - xR_2*yR_1;
1615 double num = sqrt(numx*numx + numy*numy + numz*numz);
1617 double demx = xR_2 - xR_1;
1618 double demy = yR_2 - yR_1;
1619 double demz = zR_2 - zR_1;
1620 double dem = sqrt(demx*demx + demy*demy + demz*demz);
1622 double residual = num / dem;
1624 chi2 += normalization * residual * residual;
1626 chi2 /= (hits.size() - 4);
1633 double Up()
const {
return 1.; }
1674 double* signedresidual,
1675 bool drop_worst_hit)
1683 double *Ap = &A[0][0];
1685 for (
int i = 0; i < 4; ++i)
1688 for (
int j = 0; j < 4; ++j)
1694 for (hitx = 0; hitx < num_hits; ++hitx)
1695 if (hits[hitx]->GetDetectorInfo()->GetElementDirection() ==
kDirectionX)
1699 for (hitu = 0; hitu < num_hits; ++hitu)
1700 if (hits[hitu]->GetDetectorInfo()->GetElementDirection() ==
kDirectionU)
1704 for (hitv = 0; hitv < num_hits; ++hitv)
1705 if (hits[hitv]->GetDetectorInfo()->GetElementDirection() ==
kDirectionV)
1709 if (hitx == num_hits || hitu == num_hits || hitv == num_hits) {
1715 double dx_[12] = { 0.0 };
1716 double l[3] = { 0.0 };
1717 double h[3] = { 0.0 };
1718 for (
int i = 0; i < num_hits; ++i)
1722 for (
int i = 0; i < 3; ++i)
1724 h[i] = dx_[6 + i] == 0 ? dx_[9 + i] : dx_[6 + i];
1725 l[i] = dx_[i] == 0 ? dx_[3 + i] : dx_[i];
1726 dx_[i] = dx_[3 + i] = 0;
1727 dx_[6 + i] = dx_[9 + i] = h[i] - l[i];
1730 for (
int i = 0; i < num_hits; ++i)
1734 double normalization = 1.0 / (resolution * resolution);
1743 double center_offset = rcos * center_y + rsin * center_x;
1746 double dx = dx_[hits[i]->
GetPlane() - 1];
1748 double wire_off = -0.5 * hits[i]->GetDetectorInfo()->GetElementSpacing()
1749 + hits[i]->GetDetectorInfo()->GetElementOffset();
1750 double hit_pos = hits[i]->GetDriftPosition() + wire_off - dx;
1754 r[1] = rsin * (hits[i]->GetDetectorInfo()->GetZPosition());
1756 r[3] = rcos * (hits[i]->GetDetectorInfo()->GetZPosition());
1757 for (
int k = 0; k < 4; ++k)
1759 B[k] += normalization * r[k] * (hit_pos + center_offset);
1760 for (
int j = 0; j < 4; ++j)
1761 A[k][j] += normalization * r[k] * r[j];
1780 std::pair<int, double> worst_case(0, -0.01);
1783 std::vector<QwHit*> test;
1784 for (
int i = 0; i < num_hits; ++i)
1785 test.push_back(hits[i]);
1789 #if ROOT_VERSION_CODE < ROOT_VERSION(5,90,0)
1792 TFitterMinuit minuit;
1793 minuit.SetPrintLevel(
fDebug-1);
1794 minuit.SetMinuitFCN(fcn);
1795 minuit.SetParameter(0,
"M", fit[1],1,0,0);
1796 minuit.SetParameter(1,
"XOff",fit[0],100,0,0);
1797 minuit.SetParameter(2,
"N", fit[3],1,0,0);
1798 minuit.SetParameter(3,
"YOff",fit[2],100,0,0);
1799 minuit.CreateMinimizer();
1800 int iret = minuit.Minimize();
1803 std::vector<double> oldpars;
1804 oldpars.push_back(minuit.GetParameter(0));
1805 oldpars.push_back(minuit.GetParameter(1));
1806 oldpars.push_back(minuit.GetParameter(2));
1807 oldpars.push_back(minuit.GetParameter(3));
1810 oldfit[0] = minuit.GetParameter(1);
1811 oldfit[1] = minuit.GetParameter(0);
1812 oldfit[2] = minuit.GetParameter(3);
1813 oldfit[3] = minuit.GetParameter(2);
1818 ROOT::Math::MinimizerOptions::SetDefaultMinimizer(
"Minuit2",
"Migrad");
1819 ROOT::Math::MinimizerOptions::SetDefaultPrintLevel(-1);
1821 ROOT::Fit::Fitter fitter;
1822 ROOT::Math::Functor functor(*fcn,4);
1823 double values[4] = {fit[1], fit[0], fit[3], fit[2]};
1824 fitter.SetFCN(functor,values);
1826 ROOT::Fit::FitConfig& config = fitter.Config();
1827 config.ParSettings(0).Set(
"M", fit[1], 1.0);
1828 config.ParSettings(1).Set(
"XOff", fit[0], 100.0);
1829 config.ParSettings(2).Set(
"N", fit[3], 1.0);
1830 config.ParSettings(3).Set(
"YOff", fit[2], 100.0);
1832 int prevLevel = gErrorIgnoreLevel;
1834 gErrorIgnoreLevel = 1001;
1836 bool ok = fitter.FitFCN();
1838 gErrorIgnoreLevel = prevLevel;
1842 const ROOT::Fit::FitResult& result = fitter.Result();
1844 std::vector<double> newpars;
1845 newpars.push_back(result.Parameter(0));
1846 newpars.push_back(result.Parameter(1));
1847 newpars.push_back(result.Parameter(2));
1848 newpars.push_back(result.Parameter(3));
1850 double newfit[4];
double newerr[4];
1851 fit[0] = newfit[0] = result.Parameter(1); newerr[0] = result.ParError(1);
1852 fit[1] = newfit[1] = result.Parameter(0); newerr[1] = result.ParError(0);
1853 fit[2] = newfit[2] = result.Parameter(3); newerr[2] = result.ParError(3);
1854 fit[3] = newfit[3] = result.Parameter(2); newerr[3] = result.ParError(2);
1856 #if ROOT_VERSION_CODE < ROOT_VERSION(5,90,0)
1858 if ((oldfit[0]-newfit[0])*(oldfit[0]-newfit[0])/newerr[0]/newerr[0]
1859 +(oldfit[1]-newfit[1])*(oldfit[1]-newfit[1])/newerr[1]/newerr[1]
1860 +(oldfit[2]-newfit[2])*(oldfit[2]-newfit[2])/newerr[2]/newerr[2]
1861 +(oldfit[3]-newfit[3])*(oldfit[3]-newfit[3])/newerr[3]/newerr[3]>0.01) {
1862 QwVerbose <<
"Old fit results: " << oldfit[0] <<
"," << oldfit[1] <<
"," << oldfit[2] <<
"," << oldfit[3] <<
" (" << fcn->operator()(oldpars) <<
")" << QwLog::endl;
1863 QwVerbose <<
"New fit results: " << newfit[0] <<
"," << newfit[1] <<
"," << newfit[2] <<
"," << newfit[3] <<
" (" << fcn->operator()(newpars) <<
")" << QwLog::endl;
1864 QwVerbose <<
"New fit errors: " << newerr[0] <<
"," << newerr[1] <<
"," << newerr[2] <<
"," << newerr[3] <<
QwLog::endl;
1868 for (
int i = 0; i < num_hits; ++i)
1872 double normalization = 1.0 / (resolution * resolution);
1886 double dx = dx_[hits[i]->
GetPlane() - 1];
1888 double wire_off = -0.5 * hits[i]->GetDetectorInfo()->GetElementSpacing()
1889 + hits[i]->GetDetectorInfo()->GetElementOffset();
1890 double hit_pos = hits[i]->GetDriftPosition() + wire_off - dx;
1891 double residual = y * rcos + x * rsin - hit_pos;
1894 hits[i]->SetPartialTrackPosition(dx - wire_off + y * rcos + x * rsin);
1895 hits[i]->CalculatePartialTrackResidual();
1898 signedresidual[hits[i]->GetPlane() - 1] = residual;
1899 residual = fabs(residual);
1900 if (residual > worst_case.second)
1902 worst_case.first = i;
1903 worst_case.second = residual;
1906 chi2 += normalization * residual * residual;
1913 chi2 = fcn->operator()(newpars);
1916 if (drop_worst_hit ==
false) {
1922 double best_chi2 = chi2;
1928 double temp_residual[12];
1930 for (
int i = 1; i < 12; ++i)
1931 temp_residual[i] = -10;
1935 int drop = worst_case.first;
1936 double fit_drop[4] = { 0.0 };
1939 for (
int i = 0; i < 4; ++i)
1942 for (
int j = 0; j < 4; ++j)
1947 for (
int i = 0; i < num_hits; ++i)
1950 if (i == drop)
continue;
1954 double normalization = 1.0 / (resolution * resolution);
1963 double center_offset = rcos * center_y + rsin * center_x;
1966 double dx = dx_[hits[i]->
GetPlane() - 1];
1968 double wire_off = -0.5 * hits[i]->GetDetectorInfo()->GetElementSpacing()
1969 + hits[i]->GetDetectorInfo()->GetElementOffset();
1970 double hit_pos = hits[i]->GetDriftPosition() + wire_off - dx;
1974 r[1] = rsin * (hits[i]->GetDetectorInfo()->GetZPosition());
1976 r[3] = rcos * (hits[i]->GetDetectorInfo()->GetZPosition());
1977 for (
int k = 0; k < 4; k++)
1979 B[k] += normalization * r[k] * (hit_pos + center_offset);
1980 for (
int j = 0; j < 4; j++)
1981 A[k][j] += normalization * r[k] * r[j];
1990 cerr <<
"Inversion failed" << endl;
1998 double chi2_test = 0.0;
1999 for (
int i = 0; i < num_hits; i++)
2002 if (i == drop)
continue;
2007 double normalization = 1.0 / (resolution * resolution);
2021 double dx = dx_[hits[i]->
GetPlane() - 1];
2023 double wire_off = -0.5 * hits[i]->GetDetectorInfo()->GetElementSpacing()
2024 + hits[i]->GetDetectorInfo()->GetElementOffset();
2025 double hit_pos = hits[i]->GetDriftPosition() + wire_off - dx;
2026 double residual = y * rcos + x * rsin - hit_pos;
2029 hits[i]->SetPartialTrackPosition(dx - wire_off + y * rcos + x * rsin);
2030 hits[i]->CalculatePartialTrackResidual();
2033 temp_residual[hits[i]->GetPlane() - 1] = residual;
2034 chi2_test += normalization * residual * residual;
2039 chi2_test /= (num_hits - 5);
2043 if (chi2_test < 0.8 * best_chi2)
2045 best_chi2 = chi2_test;
2046 for (
int k = 0; k < 4; ++k)
2047 fit[k] = fit_drop[k];
2048 for (
int k = 0; k < 12; ++k)
2049 signedresidual[k] = temp_residual[k];
2067 for (
size_t i = 0; i < 4; i++) {
2069 for (
size_t j = 0; j < 4; j++)
2088 double uvshift = 2.54;
2096 double uback = ufront + perp / wu->
fSlope;
2099 double vback = vfront + perp / wv->
fSlope;
2101 double Pufront[3],Puback[3],Pvfront[3],Pvback[3];
2103 double uplane[4],vplane[4];
2109 Puback[2] = perp+Pufront[2];
2112 uplane[3] = -(Pufront[1]+uplane[0]*Pufront[0]);
2113 uplane[2] = -(uplane[0]*Puback[0]+uplane[1]*Puback[1]+uplane[3])/Puback[2];
2117 Pvfront[2] = -uvshift;
2120 Pvback[2] = perp+Pvfront[2];
2123 vplane[2] = (-(vplane[0]*Pvfront[0]+vplane[1]*Pvfront[1])+(vplane[0]*Pvback[0]+vplane[1]*Pvback[1]))/(Pvfront[2]-Pvback[2]);
2124 vplane[3] = -(vplane[0]*Pvfront[0]+vplane[1]*Pvfront[1])-vplane[2]*Pvfront[2];
2128 double P[3],P_dir[3];
2130 P_dir[0]=uplane[1]*vplane[2]-uplane[2]*vplane[1];
2131 P_dir[1]=uplane[2]*vplane[0]-uplane[0]*vplane[2];
2132 P_dir[2]=uplane[0]*vplane[1]-uplane[1]*vplane[0];
2135 P[0]=-(uplane[3]-vplane[3])/(uplane[0]-vplane[0]);
2136 P[1]=-(uplane[0]*P[0]+uplane[3]);
2141 fit[1]=P_dir[0]/P_dir[2];
2143 fit[3]=P_dir[1]/P_dir[2];
2146 double P1[3],P2[3],Pp1[3],Pp2[3];
2147 double ztrans,ytrans,xtrans,costheta,sintheta,cosphi,sinphi;
2195 P1[0] = fit[1] * P1[2] + fit[0];
2196 P1[1] = fit[3] * P1[2] + fit[2];
2197 P2[2] = 92.33705405;
2198 P2[0] = fit[1] * P2[2] + fit[0];
2199 P2[1] = fit[3] * P2[2] + fit[2];
2204 Pp1[0] = (ytrans + P1[0] * costheta + P1[2] * sintheta) * cosphi + (xtrans + P1[1]) * sinphi;
2205 Pp1[1] = -1*(ytrans + P1[0] * costheta + P1[2] * sintheta) * sinphi + (xtrans + P1[1]) * cosphi;
2206 Pp1[2] = ztrans - P1[0] * sintheta + P1[2] * costheta;
2208 Pp2[0] = (ytrans + P2[0] * costheta + P2[2] * sintheta) * cosphi + (xtrans + P2[1]) * sinphi;
2209 Pp2[1] = -1*(ytrans + P2[0] * costheta + P2[2] * sintheta) * sinphi + (xtrans + P2[1]) * cosphi;
2210 Pp2[2] = ztrans - P2[0] * sintheta + P2[2] * costheta;
2213 fit[1] = ( Pp2[0] - Pp1[0] ) / ( Pp2[2] - Pp1[2] );
2214 fit[3] = ( Pp2[1] - Pp1[1] ) / ( Pp2[2] - Pp1[2] );
2215 fit[0] = Pp2[0] - fit[1] * Pp2[2];
2216 fit[2] = Pp2[1] - fit[3] * Pp2[2];
2245 for (
int i = 0; i < 4; i++)
2246 for (
int j = 0; j < 4; j++)
2247 pt->
fCov[i][j] = cov[i][j];
2283 bool drop_worst_hit)
2286 for (
int i = 0; i < 3 *
DLAYERS; i++)
2289 QwHit **hitarray = 0;
2295 double *covp = &cov[0][0];
2296 for (
int i = 0; i < 4; ++i)
2299 for (
int j = 0; j < 4; ++j)
2304 double residual[12];
2305 for (
int i = 0; i < 12; ++i)
2316 hitarray = wu->
fHits;
2319 hitarray = wv->
fHits;
2322 hitarray = wx->
fHits;
2331 for (
int num =
MAXHITPERLINE * DLAYERS; num-- && *hitarray; ++hitarray)
2334 if (h->
IsUsed() != 0 && hitc < DLAYERS * 3)
2363 pt->
fChi = sqrt(chi);
2369 for (
int i = 0; i < 4; i++)
2370 for (
int j = 0; j < 4; j++)
2371 pt->
fCov[i][j] = cov[i][j];
2374 for (
int i = 0; i < 12; ++i)
2412 const std::vector<QwTreeLine*>& treelines_x,
2413 const std::vector<QwTreeLine*>& treelines_u,
2414 const std::vector<QwTreeLine*>& treelines_v,
2423 std::vector<QwPartialTrack*> parttracklist;
2428 int nPartialTracks = 0;
2430 const int MAXIMUM_PARTIAL_TRACKS = 50;
2452 for (
size_t u = 0; u < treelines_u.size(); u++) {
2467 if (wu->
IsVoid())
continue;
2474 for (
size_t v = 0; v < treelines_v.size(); v++) {
2489 if (wv->
IsVoid())
continue;
2494 if (count < 2) nump0 = 1;
2498 for (
size_t u = 0; u < treelines_u.size(); u++) {
2506 if (wu->
IsVoid())
continue;
2509 for (
size_t v = 0; v < treelines_v.size(); v++) {
2517 if (wv->
IsVoid())
continue;
2536 parttracklist.push_back(pt);
2556 double best_chi = 10000;
2563 for (
size_t u = 0; u < treelines_u.size(); u++) {
2575 if (wu->
IsVoid())
continue;
2578 for (
size_t v = 0; v < treelines_v.size(); v++) {
2590 if (wv->
IsVoid())
continue;
2593 for (
size_t x = 0; x < treelines_x.size(); x++) {
2605 if (wx->
IsVoid())
continue;
2613 if (pt->
fChi < best_chi) {
2621 best_chi = best_pt->
fChi;
2654 parttracklist.push_back(best_pt);
2658 if (nPartialTracks >= MAXIMUM_PARTIAL_TRACKS)
2671 QwError <<
"[QwTrackingTreeCombine::TlTreeCombine] Error: "
2672 <<
"Region " << region <<
" not supported!" <<
QwLog::endl;
2680 for (
size_t pt = 0; pt < parttracklist.size(); pt++) {
2687 return parttracklist;
double fChi
chi squared(?)
static const double pi
Angles: base unit is radian.
#define QwOut
Predefined log drain for explicit output.
void CalculateTreeLineResidual()
double GetDetectorPitchSin() const
int fMaxMissedWires
Maximum number of missed wires in region 3.
bool TlCheckForX(double x1, double x2, double dx1, double dx2, double Dx, double z1, double dz, QwTreeLine *treefill, QwHitContainer *hitlist, int dlayer, int tlayer, int iteration, int stay_tuned, double width)
double fOffset
track offset
int TlMatchHits(double x1, double x2, double z1, double z2, QwTreeLine *treeline, QwHitContainer *hitlist, int tlayers)
const std::vector< QwHit * > & GetListOfHits() const
Get the list of hits.
Double_t fOffsetX
x coordinate (at MAGNET_CENTER)
double * M_Invert(double *Ap, double *Bp, const int n)
Matrix inversion of Ap will be stored in Bp.
const QwGeometry in(const EQwRegionID &r) const
Get detectors in given region.
double GetSpatialResolution() const
int fR3Offset
offset of demultiplexed group of 8
int GetElement() const
Get the element number.
EQwDetectorPackage GetPackage() const
Int_t GetNumberOfHits() const
Get the number of hits.
QwPartialTrack * r3_PartialTrackFit(const QwTreeLine *wu, const QwTreeLine *wv)
const Bool_t & IsUsed() const
void SetRegion(EQwRegionID region)
Set the region.
double GetResolutionLast(const double binwidth)
Returns resolution at the last detector plane.
virtual ~QwTrackingTreeCombine()
void SetTreeLinePosition(const Double_t position)
double GetAverageResidual() const
Get the average residuals.
int GetOctant() const
Get the octant number.
#define QwVerbose
Predefined log drain for verbose messages.
void SetSlope(const double slope)
Set the slope.
EQwDirectionID GetDirection() const
Double_t fChi
combined chi square
void SetPackage(EQwDetectorPackage package)
Set the package.
void SetUsed(const Bool_t isused=true)
double GetPositionLast(const double binwidth)
Returns position at the last detector plane.
bool InAcceptance(EQwDetectorPackage package, EQwRegionID region, double cx, double mx, double cy, double my)
void SetVoid(const bool isvoid=true)
void TlTreeLineSort(QwTreeLine *tl, QwHitContainer *hl, EQwDetectorPackage package, EQwRegionID region, EQwDirectionID dir, unsigned long bins, int tlayer, int dlayer, double width)
Definition of the partial track class.
int fR3LastWire
first and last wire in group of 8
int fMaxMissedPlanes
Maximum number of missed planes in region 2.
double GetDetectorPitchCos() const
void AddTreeLine(const QwTreeLine *treeline)
Add an existing tree line as a copy.
Definition of the track class.
EQwRegionID GetRegion() const
Get the region.
std::vector< QwPartialTrack * > TlTreeCombine(const std::vector< QwTreeLine * > &treelines_x, const std::vector< QwTreeLine * > &treelines_u, const std::vector< QwTreeLine * > &treelines_v, EQwDetectorPackage package, EQwRegionID region, int tlayer, int dlayer)
Double_t fDriftPosition
Position of the decoded hit in the drift cell.
void SetChi(const double chi)
Set the chi^2.
T GetValue(const std::string &key)
Get a templated value.
double GetPlaneOffset() const
int GetPlane() const
Get the plane number.
int r2_PartialTrackFit(const int num_hits, QwHit **hits, double *fit, double *cov, double &chi2, double *signedresidual, bool drop_worst_hit)
#define QwDebug
Predefined log drain for debugging output.
void SetValid(const bool isvoid=false)
QwHit * GetHit(int i=0)
Get a specific hit.
bool fDropWorstHit
Drop the hit with largest residual and attempt partial track fit again in region 2.
void RotateCoordinates()
Rotate coordinates to right octant.
A logfile class, based on an identical class in the Hermes analyzer.
const Double_t & GetTreeLineResidual() const
void Print(const Option_t *options=0) const
void SetOctant(int octant)
Set the octant number.
std::vector< QwHit * > hits
const Double_t & GetDriftDistance() const
double GetPositionFirst(const double binwidth)
Returns position at the first detector plane.
double CalculateAverageResidual()
void SetAlone(const int alone)
int SelectLeftRightHit(double *xresult, double dist_cut, QwHitContainer *hitlist, QwHit **ha, double Dx=0)
Select the left or right hit assignment for HDC hits.
bool InAcceptance(const double x, const double y) const
Double_t fCov[4][4]
covariance matrix
int fNumHits
number of hits on this treeline
void SetOffset(const double offset)
Set the offset.
const Double_t & GetDriftPosition() const
void SetAverageResidual(const double residual)
double * M_A_times_b(double *y, const double *A, const int n, const int m, const double *b)
Calculates y[n] = A[n,m] * b[m], with dimensions indicated.
A helper object for transformation between [u,v] and [x,y] frames.
Definition of the one-dimensional track stubs.
Bool_t fIsVoid
marked as being void
Converts between (u,v) and (x,y) coordinates.
void SetDetectorInfo(const QwDetectorInfo *detectorinfo)
Set the detector info pointer.
Double_t TResidual[kNumDirections]
double GetDetectorRollCos() const
bool IsVoid() const
Is this tree line void?
std::vector< int > fMatchingPattern
double GetResolutionFirst(const double binwidth)
Returns resolution at the first detector plane.
double GetYPosition() const
int GetCrosstalkElement(int element) const
One-dimensional (u, v, or x) track stubs and associated hits.
double GetElementAngleSin() const
int fNumMiss
number of planes without hits
std::pair< double, double > CalculateDistance(int row, double width, unsigned int bins, double error)
calculate the upper and lower bound of the drift distance give the row number
static std::ostream & endl(std::ostream &)
End of the line.
void SetCov(const double *cov)
Set the covariance.
void DeleteHit(const size_t i)
Delete a single hit.
void r2_TreelineFit(double &slope, double &offset, double cov[3], double &chi, QwHit **hits, int n)
const QwDetectorInfo * GetDetectorInfo() const
Get the detector info pointer.
void RotateRotator(const QwDetectorInfo *geometry)
Collection of QwDetectorInfo pointers that specifies an experimental geometry.
void SelectPermutationOfHits(int i, int mul, int l, int *r, QwHit *hx[DLAYERS][MAXHITPERLINE], QwHit **ha)
void AddHit(const QwHit *hit)
Add a single hit.
An options class which parses command line, config file and environment.
int selectx(double *xresult, double dist_cut, QwHit **hitarray, QwHit **ha)
Definition of the track search tree.
double GetElementAngleCos() const
bool IsValid() const
Is this tree line valid?
Double_t fOffsetY
y coordinate (at MAGNET_CENTER)
void r3_TreelineFit(double &slope, double &offset, double cov[3], double &chi, const std::vector< QwHit * > hits, double z1, int wire_offset)
Double_t fSignedResidual[12]
double GetDetectorRollSin() const
QwHit * fHits[2 *MAX_LAYERS]
Hit structure uniquely defining each hit.
void SetUsed(const bool isused=true)
double GetZPosition() const
double GetElementAngle() const
#define QwWarning
Predefined log drain for warnings.
int contains(double var, QwHit **arr, int len)
double GetXPosition() const
void GetSubList_Plane(EQwRegionID region, EQwDetectorPackage package, Int_t plane, std::vector< QwHit > &sublist)
Int_t fNumMiss
missing hits
double fXY[2][2]
which satisifies
Contains the straight part of a track in one region only.
QwPartialTrack * TcTreeLineCombine(QwTreeLine *wu, QwTreeLine *wv, QwTreeLine *wx, int tlayer, bool drop_worst_hit)
The.
EQwDirectionID GetDirection() const
Get the direction.
double CalculateAverageResidual()
Calculate the average residuals.
MyFCN(std::vector< QwHit * > fhits)
#define QwError
Predefined log drain for errors.