10#include <ecl/dataobjects/ECLElementNumbers.h>
11#include <ecl/geometry/ECLNeighbours.h>
12#include <ecl/geometry/ECLGeometryPar.h>
15#include <framework/gearbox/Unit.h>
16#include <framework/logging/Logger.h>
19#include <Math/Vector3D.h>
20#include <Math/VectorUtil.h>
30 std::vector<short int> fakeneighbours;
31 fakeneighbours.push_back(0);
34 int parToInt = int(par);
37 if (neighbourDef ==
"N") {
38 B2DEBUG(150,
"ECLNeighbours::ECLNeighbours: initialize " << neighbourDef <<
", n x n: " << parToInt * 2 + 1 <<
" x " << parToInt * 2
40 if ((parToInt >= 0) and (parToInt < 11))
initializeN(parToInt, sorted);
41 else B2FATAL(
"ECLNeighbours::ECLNeighbours: " <<
LogVar(
"parameter", parToInt) <<
"Invalid parameter (must be between 0 and 10)!");
42 }
else if (neighbourDef ==
"NC") {
43 B2DEBUG(150,
"ECLNeighbours::ECLNeighbours: initialize " << neighbourDef <<
", n x n (minus corners): " << parToInt * 2 + 1 <<
" x "
46 if ((parToInt >= 0) and (parToInt < 11))
initializeNC(parToInt);
47 else B2FATAL(
"ECLNeighbours::ECLNeighbours: " <<
LogVar(
"parameter", parToInt) <<
"Invalid parameter (must be between 0 and 10)!");
48 }
else if (neighbourDef ==
"NLegacy") {
49 B2DEBUG(150,
"ECLNeighbours::ECLNeighbours: initialize " << neighbourDef <<
", n x n: " << parToInt * 2 + 1 <<
" x " << parToInt * 2
52 else B2FATAL(
"ECLNeighbours::ECLNeighbours: " <<
LogVar(
"parameter", parToInt) <<
"Invalid parameter (must be between 0 and 10)!");
53 }
else if (neighbourDef ==
"NCLegacy") {
54 B2DEBUG(150,
"ECLNeighbours::ECLNeighbours: initialize " << neighbourDef <<
", n x n (minus corners): " << parToInt * 2 + 1 <<
" x "
58 else B2FATAL(
"ECLNeighbours::ECLNeighbours: " <<
LogVar(
"parameter", parToInt) <<
"Invalid parameter (must be between 0 and 10)!");
61 else if (neighbourDef ==
"R") {
62 B2DEBUG(150,
"ECLNeighbours::ECLNeighbours: initialize " << neighbourDef <<
", radius: " << par <<
" cm");
64 else B2FATAL(
"ECLNeighbours::ECLNeighbours: " << par <<
" is an invalid parameter (must be between 0 cm and 30 cm)!");
67 else if (neighbourDef ==
"F") {
68 double parChecked = par;
69 if (parChecked > 1.0) parChecked = 1.0;
70 else if (parChecked < 0.1) parChecked = 0.1;
71 B2DEBUG(150,
"ECLNeighbours::ECLNeighbours: initialize " << neighbourDef <<
", fraction: " << parChecked);
76 B2FATAL(
"ECLNeighbours::ECLNeighbours (constructor via std::string): Invalid option: " << neighbourDef <<
77 " (valid: N(n), NC(n), NLegacy(n), NCLegacy(n), R ( with R<30 cm), F (with 0.1<f<1)");
90 std::vector<short int> fakeneighbours;
91 fakeneighbours.push_back(0);
102 ROOT::Math::XYZVector direction = geom->GetCrystalVec(i);
103 ROOT::Math::XYZVector position = geom->GetCrystalPos(i);
107 std::vector<short int> neighboursTemp;
110 for (
auto const&
id : neighbours) {
111 const ROOT::Math::XYZVector& directionNeighbour = geom->GetCrystalVec(
id - 1);
112 const double alpha = ROOT::Math::VectorUtil::Angle(
113 direction, directionNeighbour);
114 const double R = position.R();
117 if (distance <= radius) neighboursTemp.push_back(
id);
135 std::vector<short int> neighbours;
139 const short tid = geom->GetThetaID();
140 const short pid = geom->GetPhiID();
145 neighbours.push_back(geom->GetCellID(tid, pid) + 1);
146 neighbours.push_back(geom->GetCellID(tid, phiInc) + 1);
147 neighbours.push_back(geom->GetCellID(tid, phiDec) + 1);
152 short int tidinner = tid - 1;
163 const double dist = fabs(fracPos - f);
168 n1 = geom->GetCellID(tidinner, inner);
170 }
else if (dist < dist2) {
172 n2 = geom->GetCellID(tidinner, inner);
182 neighbours.push_back(n1 + 1);
183 if (cov < frac - 1e-4) neighbours.push_back(n2 + 1);
187 short int tidouter = tid + 1;
188 if (tidouter <= 68) {
190 double disto1 = 999.;
191 short int pido1 = -1;
193 double disto2 = 999.;
197 const double dist = fabs(fracPos - f);
202 no1 = geom->GetCellID(tidouter, outer);
204 }
else if (dist < disto2) {
206 no2 = geom->GetCellID(tidouter, outer);
215 neighbours.push_back(no1 + 1);
216 if (cov < frac - 1e-4) {
217 neighbours.push_back(no2 + 1);
233 std::vector<short int> neighbours;
234 neighbours.push_back(i + 1);
236 std::vector<short int> neighbours_temp;
239 for (
int idx = 0; idx < n; idx++) {
241 for (
const auto& nbr : neighbours) {
243 for (std::vector<EclNbr::Identifier>::const_iterator newnbr = aNbr.
nearBegin(); newnbr != aNbr.
nearEnd(); ++newnbr) {
244 neighbours_temp.push_back(((
short) *newnbr) + 1);
249 sort(neighbours_temp.begin(), neighbours_temp.end());
250 neighbours_temp.erase(unique(neighbours_temp.begin(), neighbours_temp.end()), neighbours_temp.end());
251 neighbours.insert(neighbours.end(), neighbours_temp.begin(), neighbours_temp.end());
255 sort(neighbours.begin(), neighbours.end());
256 neighbours.erase(unique(neighbours.begin(), neighbours.end()), neighbours.end());
259 if (sorted ==
true) {
273 std::vector<crystal> crystals;
274 for (
const auto& nbr : neighbours) {
275 geom->Mapping(nbr - 1);
276 crystals.push_back({nbr, geom->GetPhiID(), geom->GetThetaID(), n});
280 std::sort(crystals.begin(), crystals.end(), [](
const auto & left,
const auto & right) {
282 if (left.thetaid < right.thetaid) return true;
283 if (left.thetaid > right.thetaid) return false;
290 if (fabs(left.phiid - right.phiid) > (2 * left.neighbourn + 1)) {
291 return right.phiid > left.phiid;
293 return left.phiid > right.phiid;
301 for (
int nbidx = 0; nbidx < int(neighbours.size()); nbidx++) {
302 neighbours[nbidx] = crystals[nbidx].cellid;
321 std::vector<short int> neighbours_temp;
324 const int centerthetaid = geom->GetThetaID();
326 for (
const auto& nbr : neighbours) {
327 geom->Mapping(nbr - 1);
328 const int thetaid = geom->GetThetaID();
330 if (abs(thetaid - centerthetaid) == n) {
331 const short int phiInc =
increasePhiId(geom->GetPhiID(), geom->GetThetaID(), 1);
332 const short int phiDec =
decreasePhiId(geom->GetPhiID(), geom->GetThetaID(), 1);
333 const int cid1 = geom->GetCellID(thetaid, phiInc) + 1;
334 const int cid2 = geom->GetCellID(thetaid, phiDec) + 1;
337 if (!((std::find(neighbours.begin(), neighbours.end(), cid1) != neighbours.end()) and
338 (std::find(neighbours.begin(), neighbours.end(), cid2) != neighbours.end()))) {
342 neighbours_temp.push_back(nbr);
362 std::vector<short int> neighbours;
366 const short tid = geom->GetThetaID();
367 const short pid = geom->GetPhiID();
372 const double fractionalPhiInc =
static_cast < double >(phiInc) /
m_crystalsPerRing [ tid ];
373 const double fractionalPhiDec =
static_cast < double >(phiDec) /
m_crystalsPerRing [ tid ];
376 for (
int theta = tid - n; theta <= tid + n; theta++) {
377 if ((theta > 68) || (theta < 0))
continue;
379 short int thisPhiInc = std::lround(fractionalPhiInc *
m_crystalsPerRing [ theta ]);
381 short int thisPhiDec = std::lround(fractionalPhiDec *
m_crystalsPerRing [ theta ]);
384 const std::vector<short int> phiList =
getPhiIdsInBetween(thisPhiInc, thisPhiDec, theta);
386 for (
unsigned int k = 0; k < phiList.size(); ++k) {
387 neighbours.push_back(geom->GetCellID(theta, phiList.at(k)) + 1);
408 std::vector<short int> neighbours;
412 const short tid = geom->GetThetaID();
413 const short pid = geom->GetPhiID();
418 const double fractionalPhiInc =
static_cast < double >(phiInc) /
m_crystalsPerRing [ tid ];
419 const double fractionalPhiDec =
static_cast < double >(phiDec) /
m_crystalsPerRing [ tid ];
422 for (
int theta = tid - n; theta <= tid + n; theta++) {
423 if ((theta > 68) || (theta < 0))
continue;
425 short int thisPhiInc = std::lround(fractionalPhiInc *
m_crystalsPerRing [ theta ]);
427 short int thisPhiDec = std::lround(fractionalPhiDec *
m_crystalsPerRing [ theta ]);
430 std::vector<short int> phiList;
431 if ((theta == tid - n) or (theta == tid + n)) phiList =
getPhiIdsInBetweenC(thisPhiInc, thisPhiDec, theta, corners);
432 else if (corners == 2 and ((theta == tid - n + 1)
433 or (theta == tid + n - 1))) phiList =
getPhiIdsInBetweenC(thisPhiInc, thisPhiDec, theta, 1);
436 for (
unsigned int k = 0; k < phiList.size(); ++k) {
437 neighbours.push_back(geom->GetCellID(theta, phiList.at(k)) + 1);
455 short int previousPhiId = ((phiid - n < 0) ?
m_crystalsPerRing[thetaid] + phiid - n : phiid - n);
456 return previousPhiId;
469 std::vector<short int> phiList;
470 short int loop = phi0;
473 phiList.push_back(loop);
474 if (loop == phi1)
break;
484 std::vector<short int> phiList;
485 if (phi0 == phi1)
return phiList;
488 if (loop == phi1)
return phiList;
493 phiList.push_back(loop);
494 if (loop == stop)
break;
503 return 2.0 *
R * TMath::Sin(alpha / 2.0);
The Class for ECL Geometry Parameters.
static ECLGeometryPar * Instance()
Static method to get a reference to the ECLGeometryPar instance.
std::vector< short int > getPhiIdsInBetweenC(const short int phiInc, const short int phiDec, const short int theta, const int corners)
return a list of phi ids between two phi ids minus edges
ECLNeighbours(const std::string &neighbourDef, const double par, const bool sorted=false)
Constructor: Fix number of neighbours ("N") in the seed theta ring, fraction cross ("F"),...
const std::vector< short int > & getNeighbours(short int cid) const
Return the neighbours for a given cell ID.
const short m_crystalsPerRing[69]
Number of crystals in each theta ring.
void initializeNCLegacy(const int nneighbours, const int corners)
initialize the mask neighbour list, remove corners, legacy code.
void initializeF(const double fraction)
initialize the fractional cross neighbour list.
void initializeR(const double radius)
initialize the radius neighbour list.
std::vector< std::vector< short int > > m_neighbourMapTemp
temporary list of list of neighbour cids.
short int increasePhiId(const short int phiid, const short int thetaid, const short int n)
return the next phi id.
std::vector< std::vector< short int > > m_neighbourMap
list of list of neighbour cids.
std::vector< short int > getPhiIdsInBetween(const short int phiInc, const short int phiDec, const short int theta)
return a list of phi ids between two phi ids
void initializeNC(const int nneighbours)
initialize the mask neighbour list, remove corners.
~ECLNeighbours()
Destructor.
void initializeN(const int nneighbours, const bool sorted=false)
initialize the mask neighbour list.
void initializeNLegacy(const int nneighbours)
initialize the mask neighbour list, legacy code.
double getDistance(const double alpha, const double R)
return the chord length between cells
short int decreasePhiId(const short int phiid, const short int thetaid, const short int n)
return the previous phi id.
EclNbr getNbr(const Identifier aCellId)
get crystals nbr
const std::vector< Identifier >::const_iterator nearEnd() const
get crystals nearEnd
const std::vector< Identifier >::const_iterator nearBegin() const
get crystals nearBegin
static const double cm
Standard units with the value = 1.
Class to store variables with their name which were sent to the logging service.
const int c_NCrystals
Number of crystals.
Abstract base class for different kinds of events.