All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 472 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:551
int fMaxLines
Max number of lines that can be found.
Definition: HoughBaseAlg.h:536
float fMissedHitsDistance
Distance between hits in a hough line before a hit is considered missed.
Definition: HoughBaseAlg.h:559
int fNumAngleCells
that fall into the &quot;correct&quot; bin will be small and consistent with noise.
Definition: HoughBaseAlg.h:540
int fSaveAccumulator
Save bitmap image of accumulator for debugging?
Definition: HoughBaseAlg.h:539
float fMaxDistance
Max distance that a hit can be from a line to be considered part of that line.
Definition: HoughBaseAlg.h:545
float fMaxSlope
Max slope a line can have.
Definition: HoughBaseAlg.h:546
int fRhoZeroOutRange
Range in rho over which to zero out area around previously found lines in the accumulator.
Definition: HoughBaseAlg.h:548
int fThetaZeroOutRange
Range in theta over which to zero out area around previously found lines in the accumulator.
Definition: HoughBaseAlg.h:550
float fMissedHitsToLineSize
Ratio of missed hits to line size for a line to be considered a fake.
Definition: HoughBaseAlg.h:561
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 =
902  art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(evt, clockData);
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
process_name hit
Definition: cheaterreco.fcl:51
static const SentryArgument_t Sentry
An instance of the sentry object.
Definition: Cluster.h:182
Description of geometry of one entire detector.
float PeakTime() const
Time of the signal peak, in tick units.
Definition: Hit.h:218
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:8
auto const detProp
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)
auto const detProp
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:551
process_name opflash particleana ie x
pdgs p
Definition: selectors.fcl:22
process_name hit
Definition: cheaterreco.fcl:51
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:536
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
float fMissedHitsDistance
Distance between hits in a hough line before a hit is considered missed.
Definition: HoughBaseAlg.h:559
T abs(T value)
int fNumAngleCells
that fall into the &quot;correct&quot; bin will be small and consistent with noise.
Definition: HoughBaseAlg.h:540
int fSaveAccumulator
Save bitmap image of accumulator for debugging?
Definition: HoughBaseAlg.h:539
unsigned int Nplanes(unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wire planes in the specified TPC.
process_name opflash particleana ie ie y
double distance(geo::Point_t const &point, CathodeDesc_t const &cathode)
Returns the distance of a point from the cathode.
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:545
CryostatGeo const & Cryostat(geo::CryostatID const &cryoid) const
Returns the specified cryostat.
float fMaxSlope
Max slope a line can have.
Definition: HoughBaseAlg.h:546
Class providing information about the quality of channels.
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:548
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
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:550
std::size_t count(Cont const &cont)
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
float fMissedHitsToLineSize
Ratio of missed hits to line size for a line to be considered a fake.
Definition: HoughBaseAlg.h:561
auto const detProp
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 *  fileName,
unsigned char *  pix,
int  dx,
int  dy 
)
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 }
std::size_t size(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:561
BEGIN_PROLOG Z planes
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 
)
Todo:
provide comment about where the 0.001 comes from

characteristic hit width of induction and collection plane

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.

Outline of PPHT, J. Matas et. al.

LOOP over hits, picking a random one Enter the point into the accumulator IF it is already in the accumulator or part of a line, skip it Store it in a vector of points that have been chosen

Find max value in accumulator; IF above threshold, create a line Subtract points in line from accumulator

END LOOP over hits, picking a random one

Init specifies the size of the two-dimensional accumulator (based on the arguments, number of wires and number of time samples).

Adds all of the hits to the accumulator

count is how many points are left to randomly insert

The random hit we are examining unsigned int randInd = rand() % hits.size();

If the point isn't in the current fuzzy cluster, skip it

Skip if it's already in a line

If we have already accumulated the point, skip it

zeroes out the neighborhood of all previous lines

end loop over size of listxmax

Find the weightiest cell in the accumulator.

Add the randomly selected point to the accumulator

Find the center of mass of the 3x3 cell system (with maxCell at the center).

fill the list of cells that have already been found

end iterator over hits

Subtract points from the accumulator that have already been used

end if !std::isnan

end loop over hits

Definition at line 280 of file HoughBaseAlg.cxx.

288 {
289  int nClustersTemp = *nClusters;
290 
291  geo::GeometryCore const* geom = lar::providerFrom<geo::Geometry>();
292  lariov::ChannelStatusProvider const* channelStatus =
293  lar::providerFrom<lariov::ChannelStatusService>();
294 
295  unsigned int wire = 0;
296  unsigned int wireMax = 0;
297  unsigned int cs = hits[0]->WireID().Cryostat;
298  unsigned int t = hits[0]->WireID().TPC;
299  geo::WireID const& wireid = hits[0]->WireID();
300 
301  geo::SigType_t sigt = geom->SignalType(wireid);
302  std::vector<int> skip;
303 
304  std::vector<double> wire_pitch(geom->Nplanes(t, cs), 0.);
305  for (size_t p = 0; p < wire_pitch.size(); ++p) {
306  wire_pitch[p] = geom->WirePitch(p);
307  }
308 
309  //factor to make x and y scale the same units
310  std::vector<double> xyScale(geom->Nplanes(t, cs), 0.);
311 
312  /// \todo provide comment about where the 0.001 comes from
313  double driftVelFactor = 0.001 * detProp.DriftVelocity(detProp.Efield(), detProp.Temperature());
314 
315  for (size_t p = 0; p < xyScale.size(); ++p)
316  xyScale[p] = driftVelFactor * sampling_rate(clockData) / wire_pitch[p];
317 
318  float tickToDist = driftVelFactor * sampling_rate(clockData);
319 
320  int x, y;
321  // there must be a better way to find which plane a cluster comes from
322  const int dx = geom->Cryostat(hits[0]->WireID().Cryostat)
323  .TPC(hits[0]->WireID().TPC)
324  .Plane(hits[0]->WireID().Plane)
325  .Nwires(); // number of wires
326  const int dy = detProp.NumberTimeSamples(); // number of time samples.
327  skip.clear();
328  skip.resize(hits.size());
329  std::vector<int> listofxmax;
330  std::vector<int> listofymax;
331  std::vector<int> hitsTemp; //indecies ofcandidate hits
332  std::vector<int> sequenceHolder; //wire numbers of hits in list
333  std::vector<int> channelHolder; //channels of hits in list
334  std::vector<int> currentHits; //working vector of hits
335  std::vector<int> lastHits; //best list of hits
336  std::vector<art::Ptr<recob::Hit>> clusterHits;
337  float indcolscaling = 0.; //a parameter to account for the different
338  ////characteristic hit width of induction and collection plane
339  /// \todo: the collection plane's characteristic hit width's are,
340  /// \todo: on average, about 5 time samples wider than the induction plane's.
341  /// \todo: this is hard-coded for now.
342  if (sigt == geo::kInduction)
343  indcolscaling = 0.;
344  else
345  indcolscaling = 1.;
346  float centerofmassx = 0;
347  float centerofmassy = 0;
348  float denom = 0;
349  float intercept = 0.;
350  float slope = 0.;
351  //this array keeps track of the hits that have already been associated with a line.
352  int xMax = 0;
353  int yMax = 0;
354  int yClearStart;
355  int yClearEnd;
356  int xClearStart;
357  int xClearEnd;
358  int maxCell = 0;
359  float rho;
360  float theta;
361  int accDx(0), accDy(0);
362  float pCornerMin[2];
363  float pCornerMax[2];
364 
365  unsigned int fMaxWire = 0;
366  int iMaxWire = 0;
367  unsigned int fMinWire = 99999999;
368  int iMinWire = -1;
369 
370  /// Outline of PPHT, J. Matas et. al.
371  /// ---------------------------------------
372  ///
373  ///LOOP over hits, picking a random one
374  /// Enter the point into the accumulator
375  /// IF it is already in the accumulator or part of a line, skip it
376  /// Store it in a vector of points that have been chosen
377  ///
378  /// Find max value in accumulator; IF above threshold, create a line
379  /// Subtract points in line from accumulator
380  ///
381  ///
382  ///END LOOP over hits, picking a random one
383  ///
384 
385  mf::LogInfo("HoughBaseAlg") << "dealing with " << hits.size() << " hits";
386 
387  HoughTransform c;
388 
389  ///Init specifies the size of the two-dimensional accumulator
390  ///(based on the arguments, number of wires and number of time samples).
391  c.Init(dx, dy, fRhoResolutionFactor, fNumAngleCells);
392  /// Adds all of the hits to the accumulator
393 
394  c.GetAccumSize(accDy, accDx);
395 
396  // Define the prototrack object
397  protoTrack protoTrackToLoad;
398 
399  // The number of lines we've found
400  unsigned int nLinesFound = 0;
401  std::vector<unsigned int> accumPoints(hits.size(), 0);
402  int nAccum = 0;
403 
404  /// count is how many points are left to randomly insert
405  int count = 0;
406  for (auto fpointId_to_clusterIdItr = fpointId_to_clusterId->begin();
407  fpointId_to_clusterIdItr != fpointId_to_clusterId->end();
408  fpointId_to_clusterIdItr++)
409  if (*fpointId_to_clusterIdItr == clusterId) count++;
410 
411  unsigned int randInd;
412 
413  CLHEP::RandFlat flat(engine);
414  TStopwatch w;
415 
416  for (; count > 0;) {
417 
418  /// The random hit we are examining
419  ///unsigned int randInd = rand() % hits.size();
420  randInd = (unsigned int)(flat.fire() * hits.size());
421 
422  /// If the point isn't in the current fuzzy cluster, skip it
423  if (fpointId_to_clusterId->at(randInd) != clusterId) continue;
424 
425  --count;
426 
427  /// Skip if it's already in a line
428  if (skip[randInd] == 1) { continue; }
429 
430  /// If we have already accumulated the point, skip it
431  if (accumPoints[randInd]) continue;
432  accumPoints[randInd] = 1;
433 
434  /// zeroes out the neighborhood of all previous lines
435  for (auto listofxmaxItr = listofxmax.begin(); listofxmaxItr != listofxmax.end();
436  ++listofxmaxItr) {
437  yClearStart = listofymax[listofxmaxItr - listofxmax.begin()] - fRhoZeroOutRange;
438  if (yClearStart < 0) yClearStart = 0;
439 
440  yClearEnd = listofymax[listofxmaxItr - listofxmax.begin()] + fRhoZeroOutRange;
441  if (yClearEnd >= accDy) yClearEnd = accDy - 1;
442 
443  xClearStart = *listofxmaxItr - fThetaZeroOutRange;
444  if (xClearStart < 0) xClearStart = 0;
445 
446  xClearEnd = *listofxmaxItr + fThetaZeroOutRange;
447  if (xClearEnd >= accDx) xClearEnd = accDx - 1;
448 
449  for (y = yClearStart; y <= yClearEnd; ++y) {
450  for (x = xClearStart; x <= xClearEnd; ++x) {
451  c.SetCell(y, x, 0);
452  }
453  }
454  } /// end loop over size of listxmax
455 
456  /// Find the weightiest cell in the accumulator.
457  uint32_t channel = hits[randInd]->Channel();
458  wireMax = hits[randInd]->WireID().Wire;
459 
460  /// Add the randomly selected point to the accumulator
461  std::array<int, 3> max = c.AddPointReturnMax(wireMax, (int)(hits[randInd]->PeakTime()));
462  maxCell = max[0];
463  xMax = max[1];
464  yMax = max[2];
465  ++nAccum;
466 
467  // The threshold calculation using a Binomial distribution
468  double binomProbSum = TMath::BinomialI(1 / (double)accDx, nAccum, maxCell);
469  if (binomProbSum > 1e-21) continue;
470 
471  /// Find the center of mass of the 3x3 cell system (with maxCell at the
472  /// center).
473  denom = centerofmassx = centerofmassy = 0;
474 
475  if (xMax > 0 && yMax > 0 && xMax + 1 < accDx && yMax + 1 < accDy) {
476  for (int i = -1; i < 2; ++i) {
477  for (int j = -1; j < 2; ++j) {
478  denom += c.GetCell(yMax + i, xMax + j);
479  centerofmassx += j * c.GetCell(yMax + i, xMax + j);
480  centerofmassy += i * c.GetCell(yMax + i, xMax + j);
481  }
482  }
483  centerofmassx /= denom;
484  centerofmassy /= denom;
485  }
486  else
487  centerofmassx = centerofmassy = 0;
488 
489  ///fill the list of cells that have already been found
490  listofxmax.push_back(xMax);
491  listofymax.push_back(yMax);
492 
493  // Find the lines equation
494  c.GetEquation(yMax + centerofmassy, xMax + centerofmassx, rho, theta);
495  MF_LOG_DEBUG("HoughBaseAlg") << "Transform(II) found maximum at (d=" << rho << " a=" << theta
496  << ")"
497  " from absolute maximum "
498  << c.GetCell(yMax, xMax) << " at (d=" << yMax << ", a=" << xMax
499  << ")";
500  slope = -1. / tan(theta);
501  intercept = (rho / sin(theta));
502  float distance;
503 
504  if (!std::isinf(slope) && !std::isnan(slope)) {
505  channelHolder.clear();
506  sequenceHolder.clear();
507  fMaxWire = 0;
508  iMaxWire = 0;
509  fMinWire = 99999999;
510  iMinWire = -1;
511  hitsTemp.clear();
512  for (auto hitsItr = hits.cbegin(); hitsItr != hits.cend(); ++hitsItr) {
513  wire = (*hitsItr)->WireID().Wire;
514  if (fpointId_to_clusterId->at(hitsItr - hits.begin()) != clusterId) continue;
515  channel = (*hitsItr)->Channel();
516  distance = (std::abs((*hitsItr)->PeakTime() - slope * (float)((*hitsItr)->WireID().Wire) -
517  intercept) /
518  (std::sqrt(sqr(xyScale[(*hitsItr)->WireID().Plane] * slope) + 1.)));
519  if (distance < fMaxDistance + (*hitsItr)->RMS() + indcolscaling &&
520  skip[hitsItr - hits.begin()] != 1) {
521  hitsTemp.push_back(hitsItr - hits.begin());
522  sequenceHolder.push_back(wire);
523  channelHolder.push_back(channel);
524  }
525  } /// end iterator over hits
526 
527  if (hitsTemp.size() < 5) continue;
528  currentHits.clear();
529  lastHits.clear();
530  int j;
531  currentHits.push_back(0);
532  for (auto sequenceHolderItr = sequenceHolder.begin();
533  sequenceHolderItr + 1 != sequenceHolder.end();
534  ++sequenceHolderItr) {
535  j = 1;
536  while (channelStatus->IsBad(sequenceHolderItr - sequenceHolder.begin() + j))
537  j++;
538  if (sequenceHolder[sequenceHolderItr - sequenceHolder.begin() + 1] -
539  sequenceHolder[sequenceHolderItr - sequenceHolder.begin()] <=
540  j + fMissedHits)
541  currentHits.push_back(sequenceHolderItr - sequenceHolder.begin() + 1);
542  else if (currentHits.size() > lastHits.size()) {
543  lastHits = currentHits;
544  currentHits.clear();
545  }
546  else
547  currentHits.clear();
548  }
549  if (currentHits.size() > lastHits.size()) lastHits = currentHits;
550 
551  clusterHits.clear();
552 
553  if (lastHits.size() < (unsigned int)fMinHits) continue;
554 
555  if (std::abs(slope) > fMaxSlope) { continue; }
556 
557  // Add new line to list of lines
558  float totalQ = 0;
559  std::vector<art::Ptr<recob::Hit>> lineHits;
560  nClustersTemp++;
561  for (auto lastHitsItr = lastHits.begin(); lastHitsItr != lastHits.end(); ++lastHitsItr) {
562  fpointId_to_clusterId->at(hitsTemp[(*lastHitsItr)]) = nClustersTemp - 1;
563  totalQ += hits[hitsTemp[(*lastHitsItr)]]->Integral();
564  wire = hits[hitsTemp[(*lastHitsItr)]]->WireID().Wire;
565 
566  if (!accumPoints[hitsTemp[(*lastHitsItr)]]) count--;
567 
568  skip[hitsTemp[(*lastHitsItr)]] = 1;
569 
570  lineHits.push_back(hits[hitsTemp[(*lastHitsItr)]]);
571 
572  /// Subtract points from the accumulator that have already been used
573  if (accumPoints[hitsTemp[(*lastHitsItr)]])
574  c.SubtractPoint(wire, (int)(hits[hitsTemp[(*lastHitsItr)]]->PeakTime()));
575 
576  if (wire < fMinWire) {
577  fMinWire = wire;
578  iMinWire = hitsTemp[(*lastHitsItr)];
579  }
580  if (wire > fMaxWire) {
581  fMaxWire = wire;
582  iMaxWire = hitsTemp[(*lastHitsItr)];
583  }
584  }
585  int pnum = hits[iMinWire]->WireID().Plane;
586  pCornerMin[0] = (hits[iMinWire]->WireID().Wire) * wire_pitch[pnum];
587  pCornerMin[1] = hits[iMinWire]->PeakTime() * tickToDist;
588  pCornerMax[0] = (hits[iMaxWire]->WireID().Wire) * wire_pitch[pnum];
589  pCornerMax[1] = hits[iMaxWire]->PeakTime() * tickToDist;
590 
591  protoTrackToLoad.Init(nClustersTemp - 1,
592  pnum,
593  slope,
594  intercept,
595  totalQ,
596  pCornerMin[0],
597  pCornerMin[1],
598  pCornerMax[0],
599  pCornerMax[1],
600  iMinWire,
601  iMaxWire,
602  fMinWire,
603  fMaxWire,
604  lineHits);
605  linesFound->push_back(protoTrackToLoad);
606 
607  } /// end if !std::isnan
608 
609  nLinesFound++;
610 
611  if (nLinesFound > (unsigned int)fMaxLines) break;
612 
613  } /// end loop over hits
614 
615  lastHits.clear();
616 
617  listofxmax.clear();
618  listofymax.clear();
619 
620  // saves a bitmap image of the accumulator (useful for debugging),
621  // with scaling based on the maximum cell value
622  if (fSaveAccumulator) {
623  unsigned char* outPix = new unsigned char[accDx * accDy];
624  //finds the maximum cell in the accumulator for image scaling
625  int cell, pix = 0, maxCell = 0;
626  for (int y = 0; y < accDy; ++y) {
627  for (int x = 0; x < accDx; ++x) {
628  cell = c.GetCell(y, x);
629  if (cell > maxCell) maxCell = cell;
630  }
631  }
632  for (int y = 0; y < accDy; ++y) {
633  for (int x = 0; x < accDx; ++x) {
634  //scales the pixel weights based on the maximum cell value
635  if (maxCell > 0) pix = (int)((1500 * c.GetCell(y, x)) / maxCell);
636  outPix[y * accDx + x] = pix;
637  }
638  }
639 
640  HLSSaveBMPFile("houghaccum.bmp", outPix, accDx, accDy);
641  delete[] outPix;
642  } // end if saving accumulator
643 
644  *nClusters = nClustersTemp;
645 
646  return 1;
647 }
float fRhoResolutionFactor
Factor determining the resolution in rho.
Definition: HoughBaseAlg.h:551
BEGIN_PROLOG true icarus_rawdigitfilter FilterTools FilterPlane1 Plane
process_name opflash particleana ie x
pdgs p
Definition: selectors.fcl:22
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.
BEGIN_PROLOG TPC
int fMaxLines
Max number of lines that can be found.
Definition: HoughBaseAlg.h:536
T abs(T value)
int fNumAngleCells
that fall into the &quot;correct&quot; bin will be small and consistent with noise.
Definition: HoughBaseAlg.h:540
int fSaveAccumulator
Save bitmap image of accumulator for debugging?
Definition: HoughBaseAlg.h:539
unsigned int Nplanes(unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wire planes in the specified TPC.
process_name opflash particleana ie ie y
double distance(geo::Point_t const &point, CathodeDesc_t const &cathode)
Returns the distance of a point from the cathode.
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
Signal from induction planes.
Definition: geo_types.h:145
enum geo::_plane_sigtype SigType_t
constexpr T sqr(T v)
float fMaxDistance
Max distance that a hit can be from a line to be considered part of that line.
Definition: HoughBaseAlg.h:545
CryostatGeo const & Cryostat(geo::CryostatID const &cryoid) const
Returns the specified cryostat.
float fMaxSlope
Max slope a line can have.
Definition: HoughBaseAlg.h:546
Class providing information about the quality of channels.
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:548
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
do i e
void Init(unsigned int num=999999, unsigned int pnum=999999, float slope=999999, float intercept=999999, float totalQTemp=-999999, float Min0=999999, float Min1=999999, float Max0=-999999, float Max1=-999999, int iMinWireTemp=999999, int iMaxWireTemp=-999999, int minWireTemp=999999, int maxWireTemp=-999999, std::vector< art::Ptr< recob::Hit >> hitsTemp=std::vector< art::Ptr< recob::Hit >>())
Definition: HoughBaseAlg.h:226
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:550
std::size_t count(Cont const &cont)
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
auto const detProp
void HLSSaveBMPFile(char const *, unsigned char *, int, int)
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 
1382  art::ServiceHandle<geo::Geometry const> geom;
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:551
int fNumAngleCells
that fall into the &quot;correct&quot; bin will be small and consistent with noise.
Definition: HoughBaseAlg.h:540
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
auto const detProp

Friends And Related Function Documentation

friend class HoughTransformClus
friend

Definition at line 531 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 545 of file HoughBaseAlg.h.

int cluster::HoughBaseAlg::fMaxLines
private

Max number of lines that can be found.

Definition at line 536 of file HoughBaseAlg.h.

float cluster::HoughBaseAlg::fMaxSlope
private

Max slope a line can have.

Definition at line 546 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 537 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 556 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 559 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 561 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 540 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 553 of file HoughBaseAlg.h.

float cluster::HoughBaseAlg::fRhoResolutionFactor
private

Factor determining the resolution in rho.

Definition at line 551 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 548 of file HoughBaseAlg.h.

int cluster::HoughBaseAlg::fSaveAccumulator
private

Save bitmap image of accumulator for debugging?

Definition at line 539 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 550 of file HoughBaseAlg.h.


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