Classes | Public Member Functions | Private Member Functions | Private Attributes | Friends | List of all members
cluster::HoughBaseAlg Class Reference

#include <HoughBaseAlg.h>

Classes

struct  ChargeInfo_t
 Data structure collecting charge information to be filled in cluster. More...
 

Public Member Functions

 HoughBaseAlg (fhicl::ParameterSet const &pset)
 
virtual ~HoughBaseAlg ()=default
 
size_t FastTransform (const std::vector< art::Ptr< recob::Cluster >> &clusIn, std::vector< recob::Cluster > &ccol, std::vector< art::PtrVector< recob::Hit >> &clusHitsOut, CLHEP::HepRandomEngine &engine, art::Event const &evt, std::string const &label)
 
size_t Transform (const detinfo::DetectorClocksData &clockData, detinfo::DetectorPropertiesData const &detProp, std::vector< art::Ptr< recob::Hit >> const &hits, CLHEP::HepRandomEngine &engine, std::vector< unsigned int > *fpointId_to_clusterId, unsigned int clusterId, unsigned int *nClusters, std::vector< protoTrack > *protoTracks)
 
size_t FastTransform (detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, std::vector< art::Ptr< recob::Hit >> const &clusIn, std::vector< art::PtrVector< recob::Hit >> &clusHitsOut, CLHEP::HepRandomEngine &engine)
 
size_t FastTransform (detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, std::vector< art::Ptr< recob::Hit >> const &clusIn, std::vector< art::PtrVector< recob::Hit >> &clusHitsOut, CLHEP::HepRandomEngine &engine, std::vector< double > &slope, std::vector< ChargeInfo_t > &totalQ)
 
size_t Transform (std::vector< art::Ptr< recob::Hit >> const &hits)
 
size_t Transform (detinfo::DetectorPropertiesData const &detProp, std::vector< art::Ptr< recob::Hit >> const &hits, double &slope, double &intercept)
 

Private Member Functions

void HLSSaveBMPFile (char const *, unsigned char *, int, int)
 

Private Attributes

int fMaxLines
 Max number of lines that can be found. More...
 
int fMinHits
 
int fSaveAccumulator
 Save bitmap image of accumulator for debugging? More...
 
int fNumAngleCells
 that fall into the "correct" bin will be small and consistent with noise. More...
 
float fMaxDistance
 Max distance that a hit can be from a line to be considered part of that line. More...
 
float fMaxSlope
 Max slope a line can have. More...
 
int fRhoZeroOutRange
 Range in rho over which to zero out area around previously found lines in the accumulator. More...
 
int fThetaZeroOutRange
 Range in theta over which to zero out area around previously found lines in the accumulator. More...
 
float fRhoResolutionFactor
 Factor determining the resolution in rho. More...
 
int fPerCluster
 
int fMissedHits
 
float fMissedHitsDistance
 Distance between hits in a hough line before a hit is considered missed. More...
 
float fMissedHitsToLineSize
 Ratio of missed hits to line size for a line to be considered a fake. More...
 

Friends

class HoughTransformClus
 

Detailed Description

Definition at line 468 of file HoughBaseAlg.h.

Constructor & Destructor Documentation

cluster::HoughBaseAlg::HoughBaseAlg ( fhicl::ParameterSet const &  pset)
explicit

Definition at line 261 of file HoughBaseAlg.cxx.

262 {
263  fMaxLines = pset.get<int>("MaxLines");
264  fMinHits = pset.get<int>("MinHits");
265  fSaveAccumulator = pset.get<int>("SaveAccumulator");
266  fNumAngleCells = pset.get<int>("NumAngleCells");
267  fMaxDistance = pset.get<float>("MaxDistance");
268  fMaxSlope = pset.get<float>("MaxSlope");
269  fRhoZeroOutRange = pset.get<int>("RhoZeroOutRange");
270  fThetaZeroOutRange = pset.get<int>("ThetaZeroOutRange");
271  fRhoResolutionFactor = pset.get<float>("RhoResolutionFactor");
272  fPerCluster = pset.get<int>("HitsPerCluster");
273  fMissedHits = pset.get<int>("MissedHits");
274  fMissedHitsDistance = pset.get<float>("MissedHitsDistance");
275  fMissedHitsToLineSize = pset.get<float>("MissedHitsToLineSize");
276 }
float fRhoResolutionFactor
Factor determining the resolution in rho.
Definition: HoughBaseAlg.h:545
int fMaxLines
Max number of lines that can be found.
Definition: HoughBaseAlg.h:530
float fMissedHitsDistance
Distance between hits in a hough line before a hit is considered missed.
Definition: HoughBaseAlg.h:553
int fNumAngleCells
that fall into the "correct" bin will be small and consistent with noise.
Definition: HoughBaseAlg.h:534
int fSaveAccumulator
Save bitmap image of accumulator for debugging?
Definition: HoughBaseAlg.h:533
float fMaxDistance
Max distance that a hit can be from a line to be considered part of that line.
Definition: HoughBaseAlg.h:539
float fMaxSlope
Max slope a line can have.
Definition: HoughBaseAlg.h:540
int fRhoZeroOutRange
Range in rho over which to zero out area around previously found lines in the accumulator.
Definition: HoughBaseAlg.h:542
int fThetaZeroOutRange
Range in theta over which to zero out area around previously found lines in the accumulator.
Definition: HoughBaseAlg.h:544
float fMissedHitsToLineSize
Ratio of missed hits to line size for a line to be considered a fake.
Definition: HoughBaseAlg.h:555
virtual cluster::HoughBaseAlg::~HoughBaseAlg ( )
virtualdefault

Member Function Documentation

size_t cluster::HoughBaseAlg::FastTransform ( const std::vector< art::Ptr< recob::Cluster >> &  clusIn,
std::vector< recob::Cluster > &  ccol,
std::vector< art::PtrVector< recob::Hit >> &  clusHitsOut,
CLHEP::HepRandomEngine &  engine,
art::Event const &  evt,
std::string const &  label 
)

Definition at line 886 of file HoughBaseAlg.cxx.

892 {
893  std::vector<int> skip;
894 
895  art::FindManyP<recob::Hit> fmh(clusIn, evt, label);
896 
897  geo::GeometryCore const* geom = lar::providerFrom<geo::Geometry>();
898  HoughTransform c;
899 
900  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(evt);
901  auto const detProp =
903  util::GeometryUtilities const gser{*geom, clockData, detProp};
904 
905  // prepare the algorithm to compute the cluster characteristics;
906  // we use the "standard" one here; configuration would happen here,
907  // but we are using the default configuration for that algorithm
908  ClusterParamsImportWrapper<StandardClusterParamsAlg> ClusterParamAlgo;
909 
910  std::vector<art::Ptr<recob::Hit>> hit;
911 
912  for (auto view : geom->Views()) {
913 
914  MF_LOG_DEBUG("HoughBaseAlg") << "Analyzing view " << view;
915 
916  art::PtrVector<recob::Cluster>::const_iterator clusterIter = clusIn.begin();
917  int clusterID = 0; //the unique ID of the cluster
918 
919  size_t cinctr = 0;
920  while (clusterIter != clusIn.end()) {
921 
922  MF_LOG_DEBUG("HoughBaseAlg")
923  << "Analyzing cinctr=" << cinctr << " which is in view " << (*clusterIter)->View();
924 
925  hit.clear();
926  if (fPerCluster) {
927  if ((*clusterIter)->View() == view) hit = fmh.at(cinctr);
928  }
929  else {
930  while (clusterIter != clusIn.end()) {
931  if ((*clusterIter)->View() == view) {
932 
933  hit = fmh.at(cinctr);
934  } // end if cluster is in correct view
935  clusterIter++;
936  ++cinctr;
937  } //end loop over clusters
938  } //end if not fPerCluster
939  if (hit.size() == 0) {
940  if (fPerCluster) {
941  clusterIter++;
942  ++cinctr;
943  }
944  continue;
945  }
946 
947  MF_LOG_DEBUG("HoughBaseAlg") << "We have all the hits..." << hit.size();
948 
949  std::vector<double> slopevec;
950  std::vector<ChargeInfo_t> totalQvec;
951  std::vector<art::PtrVector<recob::Hit>> planeClusHitsOut;
952  this->FastTransform(clockData, detProp, hit, planeClusHitsOut, engine, slopevec, totalQvec);
953 
954  MF_LOG_DEBUG("HoughBaseAlg") << "Made it through FastTransform" << planeClusHitsOut.size();
955 
956  for (size_t xx = 0; xx < planeClusHitsOut.size(); ++xx) {
957  auto const& hits = planeClusHitsOut.at(xx);
958  recob::Hit const& FirstHit = *hits.front();
959  recob::Hit const& LastHit = *hits.back();
960  const unsigned int sw = FirstHit.WireID().Wire;
961  const unsigned int ew = LastHit.WireID().Wire;
962 
963  // feed the algorithm with all the cluster hits
964  ClusterParamAlgo.ImportHits(gser, hits);
965 
966  // create the recob::Cluster directly in the vector;
967  // NOTE usually we would use cluster::ClusterCreator to save some typing
968  // and some mistakes. In this case, we don't want to pull in the
969  // dependency on ClusterFinder, where ClusterCreator currently lives
970  ccol.emplace_back(float(sw), // start_wire
971  0., // sigma_start_wire
972  FirstHit.PeakTime(), // start_tick
973  FirstHit.SigmaPeakTime(), // sigma_start_tick
974  ClusterParamAlgo.StartCharge(gser).value(),
975  ClusterParamAlgo.StartAngle().value(),
976  ClusterParamAlgo.StartOpeningAngle().value(),
977  float(ew), // end_wire
978  0., // sigma_end_wire,
979  LastHit.PeakTime(), // end_tick
980  LastHit.SigmaPeakTime(), // sigma_end_tick
981  ClusterParamAlgo.EndCharge(gser).value(),
982  ClusterParamAlgo.EndAngle().value(),
983  ClusterParamAlgo.EndOpeningAngle().value(),
984  ClusterParamAlgo.Integral().value(),
985  ClusterParamAlgo.IntegralStdDev().value(),
986  ClusterParamAlgo.SummedADC().value(),
987  ClusterParamAlgo.SummedADCStdDev().value(),
988  ClusterParamAlgo.NHits(),
989  ClusterParamAlgo.MultipleHitDensity(),
990  ClusterParamAlgo.Width(gser),
991  clusterID,
992  FirstHit.View(),
993  FirstHit.WireID().planeID(),
995 
996  ++clusterID;
997  clusHitsOut.push_back(planeClusHitsOut.at(xx));
998  }
999 
1000  hit.clear();
1001  if (clusterIter != clusIn.end()) {
1002  clusterIter++;
1003  ++cinctr;
1004  }
1005  // listofxmax.clear();
1006  // listofymax.clear();
1007  } // end loop over clusters
1008 
1009  } // end loop over views
1010 
1011  return ccol.size();
1012 }
geo::WireID WireID() const
Definition: Hit.h:233
std::set< geo::View_t > const & Views() const
Returns a list of possible views in the detector.
size_t FastTransform(const std::vector< art::Ptr< recob::Cluster >> &clusIn, std::vector< recob::Cluster > &ccol, std::vector< art::PtrVector< recob::Hit >> &clusHitsOut, CLHEP::HepRandomEngine &engine, art::Event const &evt, std::string const &label)
geo::View_t View() const
View for the plane of the hit.
Definition: Hit.h:232
WireID_t Wire
Index of the wire within its plane.
Definition: geo_types.h:580
static const SentryArgument_t Sentry
An instance of the sentry object.
Definition: Cluster.h:182
typename data_t::const_iterator const_iterator
Definition: PtrVector.h:55
Description of geometry of one entire detector.
float PeakTime() const
Time of the signal peak, in tick units.
Definition: Hit.h:218
#define MF_LOG_DEBUG(id)
float SigmaPeakTime() const
Uncertainty for the signal peak, in tick units.
Definition: Hit.h:219
2D representation of charge deposited in the TDC/wire plane
Definition: Hit.h:48
constexpr PlaneID const & planeID() const
Definition: geo_types.h:638
TCEvent evt
Definition: DataStructs.cxx:7
size_t cluster::HoughBaseAlg::FastTransform ( detinfo::DetectorClocksData const &  clockData,
detinfo::DetectorPropertiesData const &  detProp,
std::vector< art::Ptr< recob::Hit >> const &  clusIn,
std::vector< art::PtrVector< recob::Hit >> &  clusHitsOut,
CLHEP::HepRandomEngine &  engine 
)

Definition at line 1016 of file HoughBaseAlg.cxx.

1021 {
1022  std::vector<double> slopevec;
1023  std::vector<ChargeInfo_t> totalQvec;
1024  return FastTransform(clockData, detProp, clusIn, clusHitsOut, engine, slopevec, totalQvec);
1025 }
size_t FastTransform(const std::vector< art::Ptr< recob::Cluster >> &clusIn, std::vector< recob::Cluster > &ccol, std::vector< art::PtrVector< recob::Hit >> &clusHitsOut, CLHEP::HepRandomEngine &engine, art::Event const &evt, std::string const &label)
size_t cluster::HoughBaseAlg::FastTransform ( detinfo::DetectorClocksData const &  clockData,
detinfo::DetectorPropertiesData const &  detProp,
std::vector< art::Ptr< recob::Hit >> const &  clusIn,
std::vector< art::PtrVector< recob::Hit >> &  clusHitsOut,
CLHEP::HepRandomEngine &  engine,
std::vector< double > &  slope,
std::vector< ChargeInfo_t > &  totalQ 
)
Todo:
explain where the 0.001 comes from
Todo:
: the collection plane's characteristic hit width's are,
Todo:
: on average, about 5 time samples wider than the induction plane's.
Todo:
: this is hard-coded for now.
Todo:
should it really be wire_pitch[0] in the if statements below, or the pitch for the plane of the hit?

Definition at line 1029 of file HoughBaseAlg.cxx.

1036 {
1037  std::vector<int> skip;
1038 
1039  geo::GeometryCore const* geom = lar::providerFrom<geo::Geometry>();
1040  lariov::ChannelStatusProvider const* channelStatus =
1041  lar::providerFrom<lariov::ChannelStatusService>();
1042 
1043  CLHEP::RandFlat flat(engine);
1044 
1045  std::vector<art::Ptr<recob::Hit>> hit;
1046 
1047  size_t cinctr = 0;
1048  hit.clear();
1049  for (std::vector<art::Ptr<recob::Hit>>::const_iterator ii = clusIn.begin(); ii != clusIn.end();
1050  ii++)
1051  hit.push_back((*ii)); // this is new
1052 
1053  if (hit.size() == 0) {
1054  if (fPerCluster) { ++cinctr; }
1055  return -1;
1056  }
1057 
1058  unsigned int cs = hit.at(0)->WireID().Cryostat;
1059  unsigned int t = hit.at(0)->WireID().TPC;
1060  unsigned int p = hit.at(0)->WireID().Plane;
1061  geo::WireID const& wireid = hit.at(0)->WireID();
1062 
1063  geo::SigType_t sigt = geom->SignalType(wireid);
1064 
1065  if (hit.size() == 0) {
1066  if (fPerCluster) { ++cinctr; }
1067  return -1; // continue;
1068  }
1069 
1070  std::vector<double> wire_pitch(geom->Nplanes(t, cs), 0.);
1071  for (size_t p = 0; p < wire_pitch.size(); ++p) {
1072  wire_pitch[p] = geom->WirePitch(p);
1073  }
1074 
1075  //factor to make x and y scale the same units
1076  std::vector<double> xyScale(geom->Nplanes(t, cs), 0.);
1077 
1078  /// \todo explain where the 0.001 comes from
1079  double driftVelFactor = 0.001 * detProp.DriftVelocity(detProp.Efield(), detProp.Temperature());
1080 
1081  for (size_t p = 0; p < xyScale.size(); ++p)
1082  xyScale[p] = driftVelFactor * sampling_rate(clockData) / wire_pitch[p];
1083 
1084  int x = 0, y = 0;
1085  int dx = geom->Cryostat(cs).TPC(t).Plane(p).Nwires(); // number of wires
1086  const int dy = detProp.ReadOutWindowSize(); // number of time samples.
1087  skip.clear();
1088  skip.resize(hit.size());
1089  std::vector<int> listofxmax;
1090  std::vector<int> listofymax;
1091  std::vector<int> hitTemp; //indecies ofcandidate hits
1092  std::vector<int> sequenceHolder; //channels of hits in list
1093  std::vector<int> currentHits; //working vector of hits
1094  std::vector<int> lastHits; //best list of hits
1095  art::PtrVector<recob::Hit> clusterHits;
1096  float indcolscaling = 0.; //a parameter to account for the different
1097  //characteristic hit width of induction and collection plane
1098  float centerofmassx = 0;
1099  float centerofmassy = 0;
1100  float denom = 0;
1101  float intercept = 0.;
1102  float slope = 0.;
1103  //this array keeps track of the hits that have already been associated with a line.
1104  int xMax = 0;
1105  int yMax = 0;
1106  float rho;
1107  float theta;
1108  int accDx(0), accDy(0);
1109 
1110  HoughTransform c;
1111  //Init specifies the size of the two-dimensional accumulator
1112  //(based on the arguments, number of wires and number of time samples).
1113  //adds all of the hits (that have not yet been associated with a line) to the accumulator
1114  c.Init(dx, dy, fRhoResolutionFactor, fNumAngleCells);
1115 
1116  // count is how many points are left to randomly insert
1117  unsigned int count = hit.size();
1118  std::vector<unsigned int> accumPoints;
1119  accumPoints.resize(hit.size());
1120  int nAccum = 0;
1121  unsigned int nLinesFound = 0;
1122 
1123  for (; count > 0; count--) {
1124 
1125  // The random hit we are examining
1126  unsigned int randInd = (unsigned int)(flat.fire() * hit.size());
1127 
1128  MF_LOG_DEBUG("HoughBaseAlg") << "randInd=" << randInd << " and size is " << hit.size();
1129 
1130  // Skip if it's already in a line
1131  if (skip.at(randInd) == 1) continue;
1132 
1133  // If we have already accumulated the point, skip it
1134  if (accumPoints.at(randInd)) continue;
1135  accumPoints.at(randInd) = 1;
1136 
1137  // zeroes out the neighborhood of all previous lines
1138  for (unsigned int i = 0; i < listofxmax.size(); ++i) {
1139  int yClearStart = listofymax.at(i) - fRhoZeroOutRange;
1140  if (yClearStart < 0) yClearStart = 0;
1141 
1142  int yClearEnd = listofymax.at(i) + fRhoZeroOutRange;
1143  if (yClearEnd >= accDy) yClearEnd = accDy - 1;
1144 
1145  int xClearStart = listofxmax.at(i) - fThetaZeroOutRange;
1146  if (xClearStart < 0) xClearStart = 0;
1147 
1148  int xClearEnd = listofxmax.at(i) + fThetaZeroOutRange;
1149  if (xClearEnd >= accDx) xClearEnd = accDx - 1;
1150 
1151  for (y = yClearStart; y <= yClearEnd; ++y) {
1152  for (x = xClearStart; x <= xClearEnd; ++x) {
1153  c.SetCell(y, x, 0);
1154  }
1155  }
1156  } // end loop over size of listxmax
1157 
1158  //find the weightiest cell in the accumulator.
1159  int maxCell = 0;
1160  unsigned int wireMax = hit.at(randInd)->WireID().Wire;
1161 
1162  // Add the randomly selected point to the accumulator
1163  std::array<int, 3> max = c.AddPointReturnMax(wireMax, (int)(hit.at(randInd)->PeakTime()));
1164  maxCell = max.at(0);
1165  xMax = max.at(1);
1166  yMax = max.at(2);
1167  nAccum++;
1168 
1169  // Continue if the biggest maximum for the randomly selected point is smaller than fMinHits
1170  if (maxCell < fMinHits) continue;
1171 
1172  // Find the center of mass of the 3x3 cell system (with maxCell at the center).
1173  denom = centerofmassx = centerofmassy = 0;
1174 
1175  if (xMax > 0 && yMax > 0 && xMax + 1 < accDx && yMax + 1 < accDy) {
1176  for (int i = -1; i < 2; ++i) {
1177  for (int j = -1; j < 2; ++j) {
1178  int cell = c.GetCell(yMax + i, xMax + j);
1179  denom += cell;
1180  centerofmassx += j * cell;
1181  centerofmassy += i * cell;
1182  }
1183  }
1184  centerofmassx /= denom;
1185  centerofmassy /= denom;
1186  }
1187  else
1188  centerofmassx = centerofmassy = 0;
1189 
1190  //fill the list of cells that have already been found
1191  listofxmax.push_back(xMax);
1192  listofymax.push_back(yMax);
1193 
1194  // Find the lines equation
1195  c.GetEquation(yMax + centerofmassy, xMax + centerofmassx, rho, theta);
1196  MF_LOG_DEBUG("HoughBaseAlg") << "Transform(I) found maximum at (d=" << rho << " a=" << theta
1197  << ")"
1198  " from absolute maximum "
1199  << c.GetCell(yMax, xMax) << " at (d=" << yMax << ", a=" << xMax
1200  << ")";
1201  slope = -1. / tan(theta);
1202  intercept = (rho / sin(theta));
1203  double distance;
1204  /// \todo: the collection plane's characteristic hit width's are,
1205  /// \todo: on average, about 5 time samples wider than the induction
1206  /// plane's. \todo: this is hard-coded for now.
1207  if (sigt == geo::kInduction)
1208  indcolscaling = 5.;
1209  else
1210  indcolscaling = 0.;
1211 
1212  // note this doesn't work for wrapped wire planes!
1213  if (!std::isinf(slope) && !std::isnan(slope)) {
1214  sequenceHolder.clear();
1215  hitTemp.clear();
1216  for (size_t i = 0; i < hit.size(); ++i) {
1217  distance = (TMath::Abs(hit.at(i)->PeakTime() - slope * (double)(hit.at(i)->WireID().Wire) -
1218  intercept) /
1219  (std::sqrt(pow(xyScale[hit.at(i)->WireID().Plane] * slope, 2) + 1)));
1220 
1221  if (distance < fMaxDistance + hit.at(i)->RMS() + indcolscaling && skip.at(i) != 1) {
1222  hitTemp.push_back(i);
1223  sequenceHolder.push_back(hit.at(i)->Channel());
1224  }
1225 
1226  } // end loop over hits
1227 
1228  if (hitTemp.size() < 2) continue;
1229  currentHits.clear();
1230  lastHits.clear();
1231  int j;
1232  currentHits.push_back(0);
1233  for (size_t i = 0; i + 1 < sequenceHolder.size(); ++i) {
1234  j = 1;
1235  while ((channelStatus->IsBad(sequenceHolder.at(i) + j)) == true)
1236  j++;
1237  if (sequenceHolder.at(i + 1) - sequenceHolder.at(i) <= j + fMissedHits)
1238  currentHits.push_back(i + 1);
1239  else if (currentHits.size() > lastHits.size()) {
1240  lastHits = currentHits;
1241  currentHits.clear();
1242  }
1243  else
1244  currentHits.clear();
1245  }
1246 
1247  if (currentHits.size() > lastHits.size()) lastHits = currentHits;
1248 
1249  // Check if lastHits has hits with big gaps in it
1250  // lastHits[i] is ordered in increasing channel and then increasing peak time,
1251  // as a consequence, if the line has a negative slope and there are multiple hits in the line for a channel,
1252  // we have to go back to the first hit (in terms of lastHits[i]) of that channel to find the distance
1253  // between hits
1254  //std::cout << "New line" << std::endl;
1255  double tickToDist = detProp.DriftVelocity(detProp.Efield(), detProp.Temperature());
1256  tickToDist *= 1.e-3 * sampling_rate(clockData); // 1e-3 is conversion of 1/us to 1/ns
1257  int missedHits = 0;
1258  int lastHitsChannel = 0; //lastHits.at(0);
1259  int nHitsPerChannel = 1;
1260 
1261  MF_LOG_DEBUG("HoughBaseAlg") << "filling the pCorner arrays around here..."
1262  << "\n but first, lastHits size is " << lastHits.size()
1263  << " and lastHitsChannel=" << lastHitsChannel;
1264 
1265  double pCorner0[2];
1266  double pCorner1[2];
1267  unsigned int lastChannel = hit.at(hitTemp.at(lastHits.at(0)))->Channel();
1268 
1269  for (size_t i = 0; i < lastHits.size() - 1; ++i) {
1270  bool newChannel = false;
1271  if (slope < 0) {
1272  if (hit.at(hitTemp.at(lastHits.at(i + 1)))->Channel() != lastChannel) {
1273  newChannel = true;
1274  }
1275  if (hit.at(hitTemp.at(lastHits.at(i + 1)))->Channel() == lastChannel) nHitsPerChannel++;
1276  }
1277 
1278  /// \todo should it really be wire_pitch[0] in the if statements below,
1279  /// or the pitch for the plane of the hit?
1280 
1281  if (slope > 0 || (!newChannel && nHitsPerChannel <= 1)) {
1282 
1283  pCorner0[0] = (hit.at(hitTemp.at(lastHits.at(i)))->Channel()) * wire_pitch[0];
1284  pCorner0[1] = hit.at(hitTemp.at(lastHits.at(i)))->PeakTime() * tickToDist;
1285  pCorner1[0] = (hit.at(hitTemp.at(lastHits.at(i + 1)))->Channel()) * wire_pitch[0];
1286  pCorner1[1] = hit.at(hitTemp.at(lastHits.at(i + 1)))->PeakTime() * tickToDist;
1287  if (std::sqrt(pow(pCorner0[0] - pCorner1[0], 2) + pow(pCorner0[1] - pCorner1[1], 2)) >
1289  missedHits++;
1290  }
1291 
1292  else if (slope < 0 && newChannel && nHitsPerChannel > 1) {
1293 
1294  pCorner0[0] =
1295  (hit.at(hitTemp.at(lastHits.at(lastHitsChannel)))->Channel()) * wire_pitch[0];
1296  pCorner0[1] = hit.at(hitTemp.at(lastHits.at(lastHitsChannel)))->PeakTime() * tickToDist;
1297  pCorner1[0] = (hit.at(hitTemp.at(lastHits.at(i + 1)))->Channel()) * wire_pitch[0];
1298  pCorner1[1] = hit.at(hitTemp.at(lastHits.at(i + 1)))->PeakTime() * tickToDist;
1299  if (std::sqrt(pow(pCorner0[0] - pCorner1[0], 2) + pow(pCorner0[1] - pCorner1[1], 2)) >
1301  missedHits++;
1302  lastChannel = hit.at(hitTemp.at(lastHits.at(i)))->Channel();
1303  lastHitsChannel = i + 1;
1304  nHitsPerChannel = 0;
1305  }
1306  }
1307 
1308  if ((double)missedHits / ((double)lastHits.size() - 1) > fMissedHitsToLineSize) continue;
1309 
1310  clusterHits.clear();
1311  if (lastHits.size() < 5) continue;
1312 
1313  // reduce rounding errors by using double (RMS is very sensitive to them)
1314  lar::util::StatCollector<double> integralQ, summedQ;
1315 
1316  for (size_t i = 0; i < lastHits.size(); ++i) {
1317  clusterHits.push_back(hit.at(hitTemp.at(lastHits.at(i))));
1318  integralQ.add(clusterHits.back()->Integral());
1319  summedQ.add(clusterHits.back()->SummedADC());
1320  skip.at(hitTemp.at(lastHits.at(i))) = 1;
1321  }
1322  //protection against very steep uncorrelated hits
1323  if (std::abs(slope) > fMaxSlope) continue;
1324 
1325  clusHitsOut.push_back(clusterHits);
1326  slopevec.push_back(slope);
1327  totalQvec.emplace_back(integralQ.Sum(),
1328  integralQ.RMS(), // TODO biased value; should unbias?
1329  summedQ.Sum(),
1330  summedQ.RMS() // TODO biased value; should unbias?
1331  );
1332 
1333  } // end if !std::isnan
1334 
1335  nLinesFound++;
1336 
1337  if (nLinesFound > (unsigned int)fMaxLines) break;
1338 
1339  } // end loop over hits
1340 
1341  // saves a bitmap image of the accumulator (useful for debugging),
1342  // with scaling based on the maximum cell value
1343  if (fSaveAccumulator) {
1344  //finds the maximum cell in the accumulator for image scaling
1345  int cell, pix = 0, maxCell = 0;
1346  for (y = 0; y < accDy; ++y) {
1347  for (x = 0; x < accDx; ++x) {
1348  cell = c.GetCell(y, x);
1349  if (cell > maxCell) maxCell = cell;
1350  }
1351  }
1352 
1353  std::unique_ptr<unsigned char[]> outPix(new unsigned char[accDx * accDy]);
1354  unsigned int PicIndex = 0;
1355  for (y = 0; y < accDy; ++y) {
1356  for (x = 0; x < accDx; ++x) {
1357  //scales the pixel weights based on the maximum cell value
1358  if (maxCell > 0) pix = (int)((1500 * c.GetCell(y, x)) / maxCell);
1359  outPix[PicIndex++] = pix;
1360  }
1361  }
1362 
1363  HLSSaveBMPFile("houghaccum.bmp", outPix.get(), accDx, accDy);
1364  } // end if saving accumulator
1365 
1366  hit.clear();
1367  lastHits.clear();
1368  listofxmax.clear();
1369  listofymax.clear();
1370  return clusHitsOut.size();
1371 }
float fRhoResolutionFactor
Factor determining the resolution in rho.
Definition: HoughBaseAlg.h:545
constexpr T pow(T x)
Definition: pow.h:72
struct vector vector
SigType_t SignalType(geo::PlaneID const &pid) const
Returns the type of signal on the channels of specified TPC plane.
geo::Length_t WirePitch(geo::PlaneID const &planeid) const
Returns the distance between two consecutive wires.
Weight_t RMS() const
Returns the root mean square.
int fMaxLines
Max number of lines that can be found.
Definition: HoughBaseAlg.h:530
float fMissedHitsDistance
Distance between hits in a hough line before a hit is considered missed.
Definition: HoughBaseAlg.h:553
T abs(T value)
reference back()
Definition: PtrVector.h:387
int fNumAngleCells
that fall into the "correct" bin will be small and consistent with noise.
Definition: HoughBaseAlg.h:534
int fSaveAccumulator
Save bitmap image of accumulator for debugging?
Definition: HoughBaseAlg.h:533
unsigned int Nplanes(unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wire planes in the specified TPC.
void push_back(Ptr< U > const &p)
Definition: PtrVector.h:435
Signal from induction planes.
Definition: geo_types.h:145
Weight_t Sum() const
Returns the weighted sum of the values.
enum geo::_plane_sigtype SigType_t
float fMaxDistance
Max distance that a hit can be from a line to be considered part of that line.
Definition: HoughBaseAlg.h:539
p
Definition: test.py:223
CryostatGeo const & Cryostat(geo::CryostatID const &cryoid) const
Returns the specified cryostat.
float fMaxSlope
Max slope a line can have.
Definition: HoughBaseAlg.h:540
double distance(double x1, double y1, double z1, double x2, double y2, double z2)
Class providing information about the quality of channels.
static int max(int a, int b)
Description of geometry of one entire detector.
int fRhoZeroOutRange
Range in rho over which to zero out area around previously found lines in the accumulator.
Definition: HoughBaseAlg.h:542
const TPCGeo & TPC(unsigned int itpc) const
Return the itpc&#39;th TPC in the cryostat.
Definition: CryostatGeo.cxx:93
unsigned int Nwires() const
Number of wires in this plane.
Definition: PlaneGeo.h:269
#define MF_LOG_DEBUG(id)
list x
Definition: train.py:276
PlaneGeo const & Plane(geo::View_t view) const
Return the plane in the tpc with View_t view.
Definition: TPCGeo.cxx:263
int fThetaZeroOutRange
Range in theta over which to zero out area around previously found lines in the accumulator.
Definition: HoughBaseAlg.h:544
const char * cs
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
void clear()
Definition: PtrVector.h:533
Collects statistics on a single quantity (weighted)
float fMissedHitsToLineSize
Ratio of missed hits to line size for a line to be considered a fake.
Definition: HoughBaseAlg.h:555
void add(Data_t value, Weight_t weight=Weight_t(1.0))
Adds one entry with specified value and weight.
void HLSSaveBMPFile(char const *, unsigned char *, int, int)
void cluster::HoughBaseAlg::HLSSaveBMPFile ( char const *  ,
unsigned char *  ,
int  ,
int   
)
private

Definition at line 851 of file HoughBaseAlg.cxx.

852 {
853  std::ofstream bmpFile(fileName, std::ios::binary);
854  bmpFile.write("B", 1);
855  bmpFile.write("M", 1);
856  int bitsOffset = 54 + 256 * 4;
857  int size = bitsOffset + dx * dy; //header plus 256 entry LUT plus pixels
858  bmpFile.write((const char*)&size, 4);
859  int reserved = 0;
860  bmpFile.write((const char*)&reserved, 4);
861  bmpFile.write((const char*)&bitsOffset, 4);
862  int bmiSize = 40;
863  bmpFile.write((const char*)&bmiSize, 4);
864  bmpFile.write((const char*)&dx, 4);
865  bmpFile.write((const char*)&dy, 4);
866  short planes = 1;
867  bmpFile.write((const char*)&planes, 2);
868  short bitCount = 8;
869  bmpFile.write((const char*)&bitCount, 2);
870  int i, temp = 0;
871  for (i = 0; i < 6; i++)
872  bmpFile.write((const char*)&temp, 4); // zero out optional color info
873  // write a linear LUT
874  char lutEntry[4]; // blue,green,red
875  lutEntry[3] = 0; // reserved part
876  for (i = 0; i < 256; i++) {
877  lutEntry[0] = lutEntry[1] = lutEntry[2] = i;
878  bmpFile.write(lutEntry, sizeof lutEntry);
879  }
880  // write the actual pixels
881  bmpFile.write((const char*)pix, dx * dy);
882 }
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
fileName
Definition: dumpTree.py:9
size_t cluster::HoughBaseAlg::Transform ( const detinfo::DetectorClocksData clockData,
detinfo::DetectorPropertiesData const &  detProp,
std::vector< art::Ptr< recob::Hit >> const &  hits,
CLHEP::HepRandomEngine &  engine,
std::vector< unsigned int > *  fpointId_to_clusterId,
unsigned int  clusterId,
unsigned int *  nClusters,
std::vector< protoTrack > *  protoTracks 
)
size_t cluster::HoughBaseAlg::Transform ( std::vector< art::Ptr< recob::Hit >> const &  hits)
size_t cluster::HoughBaseAlg::Transform ( detinfo::DetectorPropertiesData const &  detProp,
std::vector< art::Ptr< recob::Hit >> const &  hits,
double &  slope,
double &  intercept 
)
Todo:
could eventually refine this method to throw out hits that are
Todo:
far from the hough line and refine the fit

Definition at line 1375 of file HoughBaseAlg.cxx.

1379 {
1380  HoughTransform c;
1381 
1383 
1384  int dx = geom->Nwires(0); // number of wires
1385  const int dy = detProp.ReadOutWindowSize(); // number of time samples.
1386 
1387  c.Init(dx, dy, fRhoResolutionFactor, fNumAngleCells);
1388 
1389  for (unsigned int i = 0; i < hits.size(); ++i) {
1390  c.AddPointReturnMax(hits[i]->WireID().Wire, (int)(hits[i]->PeakTime()));
1391  } // end loop over hits
1392 
1393  //gets the actual two-dimensional size of the accumulator
1394  int accDx = 0;
1395  int accDy = 0;
1396  c.GetAccumSize(accDy, accDx);
1397 
1398  //find the weightiest cell in the accumulator.
1399  int xMax = 0;
1400  int yMax = 0;
1401  c.GetMax(yMax, xMax);
1402 
1403  //find the center of mass of the 3x3 cell system (with maxCell at the center).
1404  float centerofmassx = 0.;
1405  float centerofmassy = 0.;
1406  float denom = 0.;
1407 
1408  if (xMax > 0 && yMax > 0 && xMax + 1 < accDx && yMax + 1 < accDy) {
1409  for (int i = -1; i < 2; ++i) {
1410  for (int j = -1; j < 2; ++j) {
1411  denom += c.GetCell(yMax + i, xMax + j);
1412  centerofmassx += j * c.GetCell(yMax + i, xMax + j);
1413  centerofmassy += i * c.GetCell(yMax + i, xMax + j);
1414  }
1415  }
1416  centerofmassx /= denom;
1417  centerofmassy /= denom;
1418  }
1419  else
1420  centerofmassx = centerofmassy = 0;
1421 
1422  float rho = 0.;
1423  float theta = 0.;
1424  c.GetEquation(yMax + centerofmassy, xMax + centerofmassx, rho, theta);
1425  MF_LOG_DEBUG("HoughBaseAlg") << "Transform(III) found maximum at (d=" << rho << " a=" << theta
1426  << ")"
1427  " from absolute maximum "
1428  << c.GetCell(yMax, xMax) << " at (d=" << yMax << ", a=" << xMax
1429  << ")";
1430  slope = -1. / tan(theta);
1431  intercept = rho / sin(theta);
1432 
1433  ///\todo could eventually refine this method to throw out hits that are
1434  ///\todo far from the hough line and refine the fit
1435 
1436  return hits.size();
1437 }
float fRhoResolutionFactor
Factor determining the resolution in rho.
Definition: HoughBaseAlg.h:545
unsigned int Nwires(unsigned int p, unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wires in the specified plane.
int fNumAngleCells
that fall into the "correct" bin will be small and consistent with noise.
Definition: HoughBaseAlg.h:534
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
#define MF_LOG_DEBUG(id)

Friends And Related Function Documentation

friend class HoughTransformClus
friend

Definition at line 525 of file HoughBaseAlg.h.

Member Data Documentation

float cluster::HoughBaseAlg::fMaxDistance
private

Max distance that a hit can be from a line to be considered part of that line.

Definition at line 539 of file HoughBaseAlg.h.

int cluster::HoughBaseAlg::fMaxLines
private

Max number of lines that can be found.

Definition at line 530 of file HoughBaseAlg.h.

float cluster::HoughBaseAlg::fMaxSlope
private

Max slope a line can have.

Definition at line 540 of file HoughBaseAlg.h.

int cluster::HoughBaseAlg::fMinHits
private

Min number of hits in the accumulator to consider (number of hits required to be considered a line).

Definition at line 531 of file HoughBaseAlg.h.

int cluster::HoughBaseAlg::fMissedHits
private

Number of wires that are allowed to be missed before a line is broken up into segments

Definition at line 550 of file HoughBaseAlg.h.

float cluster::HoughBaseAlg::fMissedHitsDistance
private

Distance between hits in a hough line before a hit is considered missed.

Definition at line 553 of file HoughBaseAlg.h.

float cluster::HoughBaseAlg::fMissedHitsToLineSize
private

Ratio of missed hits to line size for a line to be considered a fake.

Definition at line 555 of file HoughBaseAlg.h.

int cluster::HoughBaseAlg::fNumAngleCells
private

that fall into the "correct" bin will be small and consistent with noise.

Number of angle cells in the accumulator (a measure of the angular resolution of the line finder). If this number is too large than the number of votes

Definition at line 534 of file HoughBaseAlg.h.

int cluster::HoughBaseAlg::fPerCluster
private

Tells the original Hough algorithm to look at clusters individually, or all hits at once

Definition at line 547 of file HoughBaseAlg.h.

float cluster::HoughBaseAlg::fRhoResolutionFactor
private

Factor determining the resolution in rho.

Definition at line 545 of file HoughBaseAlg.h.

int cluster::HoughBaseAlg::fRhoZeroOutRange
private

Range in rho over which to zero out area around previously found lines in the accumulator.

Definition at line 542 of file HoughBaseAlg.h.

int cluster::HoughBaseAlg::fSaveAccumulator
private

Save bitmap image of accumulator for debugging?

Definition at line 533 of file HoughBaseAlg.h.

int cluster::HoughBaseAlg::fThetaZeroOutRange
private

Range in theta over which to zero out area around previously found lines in the accumulator.

Definition at line 544 of file HoughBaseAlg.h.


The documentation for this class was generated from the following files: