39 void energyRegressionAndID(
const std::vector<reco::CaloCluster> &
layerClusters,
40 const tensorflow::Session *,
41 std::vector<Trackster> &
result)
const;
42 void printTrackstersDebug(
const std::vector<Trackster> &,
const char *
label)
const;
43 void assignTimeToCandidates(std::vector<TICLCandidate> &resultCandidates)
const;
44 void dumpTrackster(
const Trackster &)
const;
86 static constexpr
int eidNFeatures_ = 3;
100 tfDnnLabel_(ps.getParameter<
std::
string>(
"tfDnnLabel")),
103 optimiseAcrossTracksters_(ps.getParameter<
bool>(
"optimiseAcrossTracksters")),
104 eta_bin_window_(ps.getParameter<
int>(
"eta_bin_window")),
105 phi_bin_window_(ps.getParameter<
int>(
"phi_bin_window")),
106 pt_sigma_high_(ps.getParameter<double>(
"pt_sigma_high")),
107 pt_sigma_low_(ps.getParameter<double>(
"pt_sigma_low")),
108 halo_max_distance2_(ps.getParameter<double>(
"halo_max_distance2")),
109 track_min_pt_(ps.getParameter<double>(
"track_min_pt")),
110 track_min_eta_(ps.getParameter<double>(
"track_min_eta")),
111 track_max_eta_(ps.getParameter<double>(
"track_max_eta")),
112 track_max_missing_outerhits_(ps.getParameter<
int>(
"track_max_missing_outerhits")),
113 cosangle_align_(ps.getParameter<double>(
"cosangle_align")),
114 e_over_h_threshold_(ps.getParameter<double>(
"e_over_h_threshold")),
115 pt_neutral_threshold_(ps.getParameter<double>(
"pt_neutral_threshold")),
116 resol_calo_offset_had_(ps.getParameter<double>(
"resol_calo_offset_had")),
117 resol_calo_scale_had_(ps.getParameter<double>(
"resol_calo_scale_had")),
118 resol_calo_offset_em_(ps.getParameter<double>(
"resol_calo_offset_em")),
119 resol_calo_scale_em_(ps.getParameter<double>(
"resol_calo_scale_em")),
120 eidInputName_(ps.getParameter<
std::
string>(
"eid_input_name")),
121 eidOutputNameEnergy_(ps.getParameter<
std::
string>(
"eid_output_name_energy")),
122 eidOutputNameId_(ps.getParameter<
std::
string>(
"eid_output_name_id")),
123 eidMinClusterEnergy_(ps.getParameter<double>(
"eid_min_cluster_energy")),
124 eidNLayers_(ps.getParameter<
int>(
"eid_n_layers")),
125 eidNClusters_(ps.getParameter<
int>(
"eid_n_clusters")),
126 eidSession_(nullptr) {
127 produces<std::vector<Trackster>>();
128 produces<std::vector<TICLCandidate>>();
132 const std::vector<Trackster> &tracksters,
135 for (
auto const &
t : tracksters) {
136 tracksterTile.
fill(tracksterIteration,
t.barycenter().eta(),
t.barycenter().phi(), tracksterId);
137 LogDebug(
"TrackstersMergeProducerV3") <<
"Adding tracksterId: " << tracksterId <<
" into bin [eta,phi]: [ " 138 << tracksterTile[tracksterIteration].etaBin(
t.barycenter().eta()) <<
", " 139 << tracksterTile[tracksterIteration].
phiBin(
t.barycenter().phi())
140 <<
"] for iteration: " << tracksterIteration << std::endl;
147 auto e_over_h = (
t.raw_em_pt() / ((
t.raw_pt() -
t.raw_em_pt()) != 0. ? (
t.raw_pt() -
t.raw_em_pt()) : 1.));
148 LogDebug(
"TrackstersMergeProducerV3")
149 <<
"\nTrackster raw_pt: " <<
t.raw_pt() <<
" raw_em_pt: " <<
t.raw_em_pt() <<
" eoh: " << e_over_h
150 <<
" barycenter: " <<
t.barycenter() <<
" eta,phi (baricenter): " <<
t.barycenter().eta() <<
", " 151 <<
t.barycenter().phi() <<
" eta,phi (eigen): " <<
t.eigenvectors(0).eta() <<
", " <<
t.eigenvectors(0).phi()
152 <<
" pt(eigen): " <<
std::sqrt(
t.eigenvectors(0).Unit().perp2()) *
t.raw_energy() <<
" seedID: " <<
t.seedID()
153 <<
" seedIndex: " <<
t.seedIndex() <<
" size: " <<
t.vertices().size() <<
" average usage: " 154 << (std::accumulate(std::begin(
t.vertex_multiplicity()), std::end(
t.vertex_multiplicity()), 0.) /
155 (
float)
t.vertex_multiplicity().size())
156 <<
" raw_energy: " <<
t.raw_energy() <<
" regressed energy: " <<
t.regressed_energy()
157 <<
" probs(ga/e/mu/np/cp/nh/am/unk): ";
158 for (
auto const &
p :
t.id_probabilities()) {
161 LogDebug(
"TrackstersMergeProducerV3") <<
" sigmas: ";
162 for (
auto const &
s :
t.sigmas()) {
163 LogDebug(
"TrackstersMergeProducerV3") <<
s <<
" ";
165 LogDebug(
"TrackstersMergeProducerV3") << std::endl;
171 auto resultTrackstersMerged = std::make_unique<std::vector<Trackster>>();
172 auto resultCandidates = std::make_unique<std::vector<TICLCandidate>>();
177 std::vector<bool> usedTrackstersMerged;
178 std::vector<int> indexInMergedCollTRKEM;
179 std::vector<int> indexInMergedCollEM;
180 std::vector<int> indexInMergedCollTRK;
181 std::vector<int> indexInMergedCollHAD;
182 std::vector<bool> usedSeeds;
185 std::map<int, std::vector<std::pair<int, TracksterIterIndex>>> seedToTracksterAssociator;
189 const auto &
tracks = *track_h;
199 usedSeeds.resize(
tracks.size(),
false);
201 fillTile(tracksterTile, trackstersTRKEM, TracksterIterIndex::TRKEM);
202 fillTile(tracksterTile, trackstersEM, TracksterIterIndex::EM);
203 fillTile(tracksterTile, trackstersTRK, TracksterIterIndex::TRKHAD);
204 fillTile(tracksterTile, trackstersHAD, TracksterIterIndex::HAD);
206 auto totalNumberOfTracksters =
207 trackstersTRKEM.size() + trackstersTRK.size() + trackstersEM.size() + trackstersHAD.size();
208 resultTrackstersMerged->reserve(totalNumberOfTracksters);
209 usedTrackstersMerged.resize(totalNumberOfTracksters,
false);
210 indexInMergedCollTRKEM.reserve(trackstersTRKEM.size());
211 indexInMergedCollEM.reserve(trackstersEM.size());
212 indexInMergedCollTRK.reserve(trackstersTRK.size());
213 indexInMergedCollHAD.reserve(trackstersHAD.size());
220 for (
auto const &
t : trackstersTRKEM) {
221 indexInMergedCollTRKEM.push_back(resultTrackstersMerged->size());
222 seedToTracksterAssociator[
t.seedIndex()].emplace_back(resultTrackstersMerged->size(), TracksterIterIndex::TRKEM);
223 resultTrackstersMerged->push_back(
t);
226 for (
auto const &
t : trackstersEM) {
227 indexInMergedCollEM.push_back(resultTrackstersMerged->size());
228 resultTrackstersMerged->push_back(
t);
231 for (
auto const &
t : trackstersTRK) {
232 indexInMergedCollTRK.push_back(resultTrackstersMerged->size());
233 seedToTracksterAssociator[
t.seedIndex()].emplace_back(resultTrackstersMerged->size(), TracksterIterIndex::TRKHAD);
234 resultTrackstersMerged->push_back(
t);
237 for (
auto const &
t : trackstersHAD) {
238 indexInMergedCollHAD.push_back(resultTrackstersMerged->size());
239 resultTrackstersMerged->push_back(
t);
250 auto trackstersMergedHandle = evt.
put(
std::move(resultTrackstersMerged));
256 for (
unsigned i = 0;
i < trackstersEM.size(); ++
i) {
257 auto mergedIdx = indexInMergedCollEM[
i];
258 usedTrackstersMerged[mergedIdx] =
true;
259 const auto &
t = trackstersEM[
i];
266 t.raw_energy() *
t.barycenter().unit().y(),
267 t.raw_energy() *
t.barycenter().unit().z(),
269 tmpCandidate.
setP4(p4);
270 resultCandidates->push_back(tmpCandidate);
274 constexpr
double mpion = 0.13957;
276 for (
unsigned i = 0;
i < trackstersHAD.size(); ++
i) {
277 auto mergedIdx = indexInMergedCollHAD[
i];
278 usedTrackstersMerged[mergedIdx] =
true;
279 const auto &
t = trackstersHAD[
i];
287 momentum *
t.barycenter().unit().y(),
288 momentum *
t.barycenter().unit().z(),
290 tmpCandidate.
setP4(p4);
291 resultCandidates->push_back(tmpCandidate);
295 for (
unsigned i = 0;
i < trackstersTRKEM.size(); ++
i) {
296 auto mergedIdx = indexInMergedCollTRKEM[
i];
297 if (!usedTrackstersMerged[mergedIdx]) {
298 const auto &
t = trackstersTRKEM[
i];
299 auto trackIdx =
t.seedIndex();
301 if (!usedSeeds[trackIdx] and
t.raw_energy() > 0) {
302 usedSeeds[trackIdx] =
true;
303 usedTrackstersMerged[mergedIdx] =
true;
305 std::vector<int> trackstersTRKwithSameSeed;
306 std::vector<int> trackstersTRKEMwithSameSeed;
308 for (
const auto &tracksterIterationPair : seedToTracksterAssociator[trackIdx]) {
309 if (tracksterIterationPair.first != mergedIdx and !usedTrackstersMerged[tracksterIterationPair.first] and
310 trackstersMergedHandle->at(tracksterIterationPair.first).raw_energy() > 0.) {
311 if (tracksterIterationPair.second == TracksterIterIndex::TRKEM) {
312 trackstersTRKEMwithSameSeed.push_back(tracksterIterationPair.first);
313 }
else if (tracksterIterationPair.second == TracksterIterIndex::TRKHAD) {
314 trackstersTRKwithSameSeed.push_back(tracksterIterationPair.first);
319 float tracksterTotalRawPt =
t.raw_pt();
320 std::vector<int> haloTrackstersTRKIdx;
321 bool foundCompatibleTRK =
false;
323 for (
auto otherTracksterIdx : trackstersTRKwithSameSeed) {
324 usedTrackstersMerged[otherTracksterIdx] =
true;
325 tracksterTotalRawPt += trackstersMergedHandle->at(otherTracksterIdx).raw_pt();
328 if ((
t.barycenter() - trackstersMergedHandle->at(otherTracksterIdx).barycenter()).
mag2() <
330 haloTrackstersTRKIdx.push_back(otherTracksterIdx);
333 foundCompatibleTRK =
true;
338 if (trackstersTRKEMwithSameSeed.empty()) {
339 if (foundCompatibleTRK) {
342 double raw_energy =
t.raw_energy();
347 for (
auto otherTracksterIdx : trackstersTRKwithSameSeed) {
349 raw_energy += trackstersMergedHandle->at(otherTracksterIdx).raw_energy();
353 raw_energy *
track.momentum().unit().y(),
354 raw_energy *
track.momentum().unit().z(),
356 tmpCandidate.
setP4(p4);
357 resultCandidates->push_back(tmpCandidate);
362 double raw_energy =
t.raw_energy();
365 for (
auto otherTracksterIdx : trackstersTRKwithSameSeed) {
367 raw_energy += trackstersMergedHandle->at(otherTracksterIdx).raw_energy();
373 raw_energy *
track.momentum().unit().y(),
374 raw_energy *
track.momentum().unit().z(),
376 tmpCandidate.
setP4(p4);
377 resultCandidates->push_back(tmpCandidate);
382 int closestTrackster = mergedIdx;
384 for (
auto otherTracksterIdx : trackstersTRKEMwithSameSeed) {
385 auto thisPt = tracksterTotalRawPt + trackstersMergedHandle->at(otherTracksterIdx).raw_pt() -
t.raw_pt();
386 closestTrackster =
std::abs(thisPt -
track.pt()) < minPtDiff ? otherTracksterIdx : closestTrackster;
388 usedTrackstersMerged[closestTrackster] =
true;
390 if (foundCompatibleTRK) {
393 double raw_energy = trackstersMergedHandle->at(closestTrackster).raw_energy();
398 for (
auto otherTracksterIdx : trackstersTRKwithSameSeed) {
400 raw_energy += trackstersMergedHandle->at(otherTracksterIdx).raw_energy();
405 momentum *
track.momentum().unit().y(),
406 momentum *
track.momentum().unit().z(),
408 tmpCandidate.
setP4(p4);
409 resultCandidates->push_back(tmpCandidate);
414 double raw_energy = trackstersMergedHandle->at(closestTrackster).raw_energy();
418 for (
auto otherTracksterIdx : trackstersTRKwithSameSeed) {
420 raw_energy += trackstersMergedHandle->at(otherTracksterIdx).raw_energy();
425 raw_energy *
track.momentum().unit().y(),
426 raw_energy *
track.momentum().unit().z(),
428 tmpCandidate.
setP4(p4);
429 resultCandidates->push_back(tmpCandidate);
432 for (
auto otherTracksterIdx : trackstersTRKEMwithSameSeed) {
433 auto tmpIndex = (otherTracksterIdx != closestTrackster) ? otherTracksterIdx : mergedIdx;
435 const auto &otherTrackster = trackstersMergedHandle->at(tmpIndex);
436 auto gammaEnergy = otherTrackster.raw_energy();
441 gammaEnergy * otherTrackster.barycenter().unit().y(),
442 gammaEnergy * otherTrackster.barycenter().unit().z(),
444 photonCandidate.
setP4(gammaP4);
446 resultCandidates->push_back(photonCandidate);
453 for (
unsigned i = 0;
i < trackstersTRK.size(); ++
i) {
454 auto mergedIdx = indexInMergedCollTRK[
i];
455 const auto &
t = trackstersTRK[
i];
457 if (!usedTrackstersMerged[mergedIdx] and
t.raw_energy() > 0) {
458 auto trackIdx =
t.seedIndex();
460 if (!usedSeeds[trackIdx]) {
461 usedSeeds[trackIdx] =
true;
462 usedTrackstersMerged[mergedIdx] =
true;
471 momentum *
track.momentum().unit().y(),
472 momentum *
track.momentum().unit().z(),
474 tmpCandidate.
setP4(p4);
475 resultCandidates->push_back(tmpCandidate);
481 if (usedSeeds[
s.index] ==
false) {
491 tmpCandidate.
setP4(p4Polar);
492 resultCandidates->push_back(tmpCandidate);
493 usedSeeds[
s.index] =
true;
498 for (
unsigned i = 0;
i <
tracks.size(); ++
i) {
511 tmpCandidate.
setP4(p4Polar);
512 resultCandidates->push_back(tmpCandidate);
524 const tensorflow::Session *eidSession,
525 std::vector<Trackster> &tracksters)
const {
549 std::vector<int> tracksterIndices;
550 for (
int i = 0;
i < (
int)tracksters.size();
i++) {
555 float sumClusterEnergy = 0.;
561 tracksters[
i].setRegressedEnergy(0.
f);
562 tracksters[
i].zeroProbabilities();
563 tracksterIndices.push_back(
i);
570 int batchSize = (
int)tracksterIndices.size();
571 if (batchSize == 0) {
577 tensorflow::Tensor
input(tensorflow::DT_FLOAT, shape);
579 static constexpr
int inputDimension = 4;
581 std::vector<tensorflow::Tensor>
outputs;
591 for (
int i = 0;
i < batchSize;
i++) {
592 const Trackster &trackster = tracksters[tracksterIndices[
i]];
598 std::vector<int> clusterIndices(trackster.
vertices().size());
600 clusterIndices[
k] =
k;
602 sort(clusterIndices.begin(), clusterIndices.end(), [&
layerClusters, &trackster](
const int &
a,
const int &
b) {
610 for (
const int &
k : clusterIndices) {
647 for (
const int &
i : tracksterIndices) {
648 tracksters[
i].setRegressedEnergy(*(
energy++));
656 float *probs =
outputs[probsIdx].flat<
float>().
data();
658 for (
const int &
i : tracksterIndices) {
659 tracksters[
i].setProbabilities(probs);
660 probs += tracksters[
i].id_probabilities().size();
666 for (
auto &
cand : resultCandidates) {
667 if (
cand.tracksters().size() > 1) {
670 for (
const auto &tr :
cand.tracksters()) {
671 if (tr->timeError() > 0) {
672 auto invTimeESq =
pow(tr->timeError(), -2);
673 time += tr->time() * invTimeESq;
674 timeErr += invTimeESq;
678 timeErr = 1. / timeErr;
688 const char *
label)
const {
691 for (
auto const &
t : tracksters) {
692 LogDebug(
"TrackstersMergeProducerV3")
693 <<
counter++ <<
" TrackstersMergeProducerV3 (" <<
label <<
") obj barycenter: " <<
t.barycenter()
694 <<
" eta,phi (baricenter): " <<
t.barycenter().eta() <<
", " <<
t.barycenter().phi()
695 <<
" eta,phi (eigen): " <<
t.eigenvectors(0).eta() <<
", " <<
t.eigenvectors(0).phi()
696 <<
" pt(eigen): " <<
std::sqrt(
t.eigenvectors(0).Unit().perp2()) *
t.raw_energy() <<
" seedID: " <<
t.seedID()
697 <<
" seedIndex: " <<
t.seedIndex() <<
" size: " <<
t.vertices().size() <<
" average usage: " 698 << (std::accumulate(std::begin(
t.vertex_multiplicity()), std::end(
t.vertex_multiplicity()), 0.) /
699 (
float)
t.vertex_multiplicity().size())
700 <<
" raw_energy: " <<
t.raw_energy() <<
" regressed energy: " <<
t.regressed_energy()
701 <<
" probs(ga/e/mu/np/cp/nh/am/unk): ";
702 for (
auto const &
p :
t.id_probabilities()) {
705 LogDebug(
"TrackstersMergeProducerV3") <<
" sigmas: ";
706 for (
auto const &
s :
t.sigmas()) {
707 LogDebug(
"TrackstersMergeProducerV3") <<
s <<
" ";
709 LogDebug(
"TrackstersMergeProducerV3") << std::endl;
724 desc.add<
bool>(
"optimiseAcrossTracksters",
true);
725 desc.add<
int>(
"eta_bin_window", 1);
726 desc.add<
int>(
"phi_bin_window", 1);
727 desc.add<
double>(
"pt_sigma_high", 2.);
728 desc.add<
double>(
"pt_sigma_low", 2.);
729 desc.add<
double>(
"halo_max_distance2", 4.);
730 desc.add<
double>(
"track_min_pt", 1.);
731 desc.add<
double>(
"track_min_eta", 1.48);
732 desc.add<
double>(
"track_max_eta", 3.);
733 desc.add<
int>(
"track_max_missing_outerhits", 5);
734 desc.add<
double>(
"cosangle_align", 0.9945);
735 desc.add<
double>(
"e_over_h_threshold", 1.);
736 desc.add<
double>(
"pt_neutral_threshold", 2.);
737 desc.add<
double>(
"resol_calo_offset_had", 1.5);
738 desc.add<
double>(
"resol_calo_scale_had", 0.15);
739 desc.add<
double>(
"resol_calo_offset_em", 1.5);
740 desc.add<
double>(
"resol_calo_scale_em", 0.15);
743 desc.add<
std::string>(
"eid_output_name_energy",
"output/regressed_energy");
744 desc.add<
std::string>(
"eid_output_name_id",
"output/id_probabilities");
745 desc.add<
double>(
"eid_min_cluster_energy", 1.);
746 desc.add<
int>(
"eid_n_layers", 50);
747 desc.add<
int>(
"eid_n_clusters", 10);
748 descriptions.
add(
"trackstersMergeProducerV3",
desc);
const double resol_calo_offset_em_
const double pt_sigma_low_
const double resol_calo_offset_had_
const double cosangle_align_
const edm::EDGetTokenT< edm::ValueMap< std::pair< float, float > > > clustersTime_token_
std::vector< NamedTensor > NamedTensorList
void printTrackstersDebug(const std::vector< Trackster > &, const char *label) const
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
const std::vector< std::pair< DetId, float > > & hitsAndFractions() const
const std::string tfDnnLabel_
T const & getData(const ESGetToken< T, R > &iToken) const noexcept(false)
void dumpTrackster(const Trackster &) const
bool get(ProductID const &oid, Handle< PROD > &result) const
const double pt_sigma_high_
const edm::ESGetToken< CaloGeometry, CaloGeometryRecord > geometry_token_
const edm::EDGetTokenT< std::vector< Trackster > > trackstershad_token_
const double halo_max_distance2_
bool getByToken(EDGetToken token, Handle< PROD > &result) const
const int track_max_missing_outerhits_
const float eidMinClusterEnergy_
const double e_over_h_threshold_
double phi() const
azimuthal angle of cluster centroid
tensorflow::Session * eidSession_
static std::string const input
static constexpr int eidNFeatures_
PtEtaPhiMLorentzVectorD PtEtaPhiMLorentzVector
Lorentz vector with cartesian internal representation.
void assignPCAtoTracksters(std::vector< Trackster > &, const std::vector< reco::CaloCluster > &, const edm::ValueMap< std::pair< float, float >> &, double, bool energyWeight=true)
void setCharge(Charge q) final
set electric charge
XYZTLorentzVectorD XYZTLorentzVector
Lorentz vector with cylindrical internal representation using pseudorapidity.
const edm::EDGetTokenT< std::vector< Trackster > > trackstersem_token_
const double resol_calo_scale_em_
const double pt_neutral_threshold_
const edm::EDGetTokenT< std::vector< TICLSeedingRegion > > seedingTrk_token_
void setRawEnergy(float rawEnergy)
const int eta_bin_window_
ticl::Trackster::IterationIndex TracksterIterIndex
const edm::EDGetTokenT< std::vector< reco::Track > > tracks_token_
std::vector< float > features(const reco::PreId &ecal, const reco::PreId &hcal, double rho, const reco::BeamSpot &spot, noZS::EcalClusterLazyTools &ecalTools)
~TrackstersMergeProducerV3() override
TrackstersMergeProducerV3(const edm::ParameterSet &ps)
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
void run(Session *session, const NamedTensorList &inputs, const std::vector< std::string > &outputNames, std::vector< Tensor > *outputs, const thread::ThreadPoolOptions &threadPoolOptions)
const tensorflow::Session * tfSession_
Abs< T >::type abs(const T &t)
#define DEFINE_FWK_MODULE(type)
ESHandle< T > getHandle(const ESGetToken< T, R > &iToken) const
hgcal::RecHitTools rhtools_
const std::string eidOutputNameId_
const std::string eidOutputNameEnergy_
const edm::EDGetTokenT< std::vector< Trackster > > tracksterstrkem_token_
const double track_max_eta_
double energy() const
cluster energy
std::vector< unsigned int > & vertices()
const bool optimiseAcrossTracksters_
void assignTimeToCandidates(std::vector< TICLCandidate > &resultCandidates) const
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
void energyRegressionAndID(const std::vector< reco::CaloCluster > &layerClusters, const tensorflow::Session *, std::vector< Trackster > &result) const
const edm::ESGetToken< TfGraphDefWrapper, TfGraphRecord > tfDnnToken_
const edm::EDGetTokenT< std::vector< Trackster > > tracksterstrk_token_
const int phi_bin_window_
T mag2() const
The vector magnitude squared. Equivalent to vec.dot(vec)
std::vector< float > & vertex_multiplicity()
const double track_min_eta_
void add(std::string const &label, ParameterSetDescription const &psetDescription)
char data[epos_bytes_allocation]
void addTrackster(const edm::Ptr< ticl::Trackster > &trackster)
const edm::EDGetTokenT< std::vector< reco::CaloCluster > > clusters_token_
void fill(int index, double eta, double phi, unsigned int objectId)
double eta() const
pseudorapidity of cluster centroid
const std::string eidInputName_
const double track_min_pt_
void setPdgId(int pdgId) final
const double resol_calo_scale_had_
void setTrackPtr(const edm::Ptr< reco::Track > &trackPtr)
void produce(edm::Event &, const edm::EventSetup &) override
void setP4(const LorentzVector &p4) final
set 4-momentum
Power< A, B >::type pow(const A &a, const B &b)
void fillTile(TICLTracksterTiles &, const std::vector< Trackster > &, TracksterIterIndex)