User will overwrite this function. Histogram booking is no longer done in C++. This function is called in execute once the filters are all passed.
69 {
70
71 ATH_MSG_DEBUG(
"Pixel MVAMon: Filling MVA Monitoring Histograms");
72
73 using namespace Monitored;
75 auto lbval = Monitored::Scalar<int>(
"pixmvamontool_lb",
lb );
76
77 const int MAXHASH =
m_pixelid->wafer_hash_max();
78
79
80
81
84 std::vector<float>
status(MAXHASH*2);
85
88 for (; idIt != idItEnd; ++idIt) {
89
90 Identifier waferID = *idIt;
91 IdentifierHash modHash =
m_pixelid->wafer_hash(waferID);
93 if (pixlayer == 99) continue;
94
96 {
97
98
100 for (int iFE=0; iFE<nFE; iFE++) {
101 Identifier pixID =
m_pixelReadout->getPixelIdfromHash(modHash, iFE, 1, 1);
105 modHash, iFE);
106 if (is_active)
107 {
108 if (is_good)
status[modHash+MAXHASH*iFE] = 0;
109 else status[modHash+MAXHASH*iFE] = 1;
110 }
111 else status[modHash+MAXHASH*iFE] = 2;
112 }
113 }
114 }
115 else
116 {
117
118
121 if (is_active)
122 {
123 if (is_good)
status[modHash] = 0;
125 }
127 }
128 }
129
130
131
132
134 if ( !(trackParticles.isValid()) ) {
136 return StatusCode::RECOVERABLE;
137 } else {
138 ATH_MSG_DEBUG(
"Pixel MVAMon: TrackParticle container "<< trackParticles.name() <<
" is found.");
139 }
140
141 bool eventHasPixHits(false);
142 std::vector<std::pair<Identifier, double> > ClusterIDs;
143
144 std::vector<float>
holes(MAXHASH*2);
145 std::vector<float> outliers(MAXHASH*2);
146 std::vector<float> measurements(MAXHASH*2);
147 std::vector<float> trkalpha(MAXHASH*2);
148 std::vector<float> trkchi2byndf(MAXHASH*2);
149 std::vector<float> trknpixdead(MAXHASH*2);
150 std::vector<float> trknblayerhits(MAXHASH*2);
151
153
154 for (auto trackPart: *trackParticles) {
155 const Trk::Track *
track = trackPart->track();
157
158 if (track ==
nullptr ||
track->perigeeParameters() ==
nullptr ||
track->trackSummary() ==
nullptr || numberOfPixelHits == 0) {
159 ATH_MSG_DEBUG(
"Pixel MVAMon: Track either invalid or it does not contain pixel hits, continuing...");
160 continue;
161 }
162
164 bool hasIBLTSOS(false);
165
166 bool passJOTrkCut =
static_cast<bool>(
m_trackSelTool->accept(*track) );
167 if (!passJOTrkCut) continue;
168 float trkfitndf =
track->fitQuality()->numberDoF();
169 float trkfitchi2byndf =
track->fitQuality()->chiSquared();
170 if (trkfitndf != 0) trkfitchi2byndf /= trkfitndf;
171 else continue;
173 float nblayerhits(0);
175 if (expBLhit==1) {
177 }
178
179 const Trk::Track* trackWithHoles( track );
180 std::unique_ptr<const Trk::Track> trackWithHolesUnique = nullptr;
182 if ( nPixHoles > 0 ) {
184 trackWithHoles = trackWithHolesUnique.get();
185 }
186 const Trk::TrackStates *trackStates = trackWithHoles->trackStateOnSurfaces();
187 for (auto trackStateOnSurface: *trackStates) {
188
189 const Trk::MeasurementBase* mesBase = trackStateOnSurface->measurementOnTrack();
190
191
192
193 const Trk::RIO_OnTrack* RIOOnTrack = nullptr;
195 RIOOnTrack = static_cast<const Trk::RIO_OnTrack*>(mesBase);
196 }
197 if (mesBase && !RIOOnTrack) continue;
198
199
200
201 Identifier surfaceID;
205 } else {
206 if (trkParameters) {
208 } else {
209 ATH_MSG_DEBUG(
"Pixel MVAMon: can't obtain track parameters for TSOS.");
210 continue;
211 }
212 }
213
214
215
216 if (!
m_atlasid->is_pixel(surfaceID))
continue;
218 if (pixlayer == 99) continue;
220
221 int indexModule =
static_cast<int>(
m_pixelid->wafer_hash(surfaceID) );
222
223 const InDetDD::SiDetectorElement *sde =
dynamic_cast<const InDetDD::SiDetectorElement *
>(trkParameters->
associatedSurface().associatedDetectorElement());
225 const InDetDD::SiLocalPosition& trkLocalPos = trkParameters->
localPosition();
226 Identifier locPosID;
227 int iFE(0);
228 bool goodPixelMeasurement(false);
229
231 {
233 {
234 const InDet::PixelClusterOnTrack *pixClus = dynamic_cast<const InDet::PixelClusterOnTrack *>(mesBase);
235 if ( mesBase && pixClus) {
238 ATH_MSG_WARNING(
"Pixel MVAMon: got invalid track local position on surface for an outlier.");
239 continue;
240 }
242 outliers[indexModule+MAXHASH*iFE] += 1;
243 }
244 }
245 else
246 {
247 outliers[indexModule] += 1;
248 }
249 }
251 {
253 {
256 ATH_MSG_WARNING(
"Pixel MVAMon: got invalid track local position on surface for a hole.");
257 continue;
258 }
260 holes[indexModule+MAXHASH*iFE] += 1;
261 }
262 else
263 {
264 holes[indexModule] += 1;
265 }
266 }
268 {
269
270
271 if (not mesBase) continue;
272 sde = dynamic_cast<const InDetDD::SiDetectorElement *>(mesBase->associatedSurface().associatedDetectorElement());
273 const InDet::PixelClusterOnTrack *pixClus = dynamic_cast<const InDet::PixelClusterOnTrack *>(mesBase);
274 if (!sde || !pixClus) continue;
275 const InDet::PixelCluster *rawPixClus = pixClus->
prepRawData();
276 if (!rawPixClus) continue;
277
279 goodPixelMeasurement = true;
283 continue;
284 }
286 measurements[indexModule+MAXHASH*iFE] += 1;
287 }
288 else continue;
289
290 if (trackAtPlane) {
293 double trackpnormcomp = trackp.dot(normal);
294 double trackp_mag = trackp.mag();
296 if (trackp_mag != 0)
alpha = std::acos(std::abs(trackpnormcomp / trackp_mag));
297
298 trkalpha[indexModule+MAXHASH*iFE] +=
alpha;
299
300 if (goodPixelMeasurement) ClusterIDs.emplace_back(locPosID, alpha);
301 }
302 trkchi2byndf[indexModule+MAXHASH*iFE] += trkfitchi2byndf;
303 trknpixdead[indexModule+MAXHASH*iFE] += npixdead;
304 trknblayerhits[indexModule+MAXHASH*iFE] += nblayerhits;
305 }
306 eventHasPixHits = eventHasPixHits || (
nPixelHits > 0);
307
309 if (!hasIBLTSOS && expIBLhit==1 && nPixHoles==0 )
310 {
313 transSurf.setIdentity();
314 const Trk::CylinderSurface BiggerThanIBLSurface(transSurf, 40.0, 400.0);
315 std::vector<std::unique_ptr<Trk::TrackParameters> > iblTrkParameters =
317 Identifier sensorPosID, chipPosID;
319 bool foundIBLElem(false);
320
321 for (auto& tp: iblTrkParameters) {
322 const InDetDD::SiDetectorElement *sde =
dynamic_cast<const InDetDD::SiDetectorElement *
>(
tp->associatedSurface().associatedDetectorElement());
323 if (!(sde !=
nullptr && sde->
identify() != 0)) {
324 continue;
325 }
328 ATH_MSG_DEBUG(
"Pixel MVAMon: found non-IBL element: "<< sensorPosID);
329 continue;
330 }
331 const InDetDD::SiLocalPosition& trkLocalPos =
tp->localPosition();
334 foundIBLElem=false;
335 ATH_MSG_DEBUG(
"Pixel MVAMon: got invalid track local position on surface for an expected IBL hit.");
336 continue;
337 } else foundIBLElem=true;
338 double trackpnormcomp =
tp->momentum().dot(
tp->associatedSurface().normal());
339 double trackp_mag =
tp->momentum().mag();
340 if (trackp_mag != 0)
alpha = std::acos(std::abs(trackpnormcomp / trackp_mag));
341 }
342 if (!foundIBLElem) {
343 ATH_MSG_DEBUG(
"Pixel MVAMon: couldn't find IBL pos ID: "<< sensorPosID);
344 continue;
345 }
346 int indexModule =
static_cast<int>(
m_pixelid->wafer_hash(sensorPosID) );
348 holes[indexModule+MAXHASH*iFE] += 1;
349 trkalpha[indexModule+MAXHASH*iFE] +=
alpha;
350 trkchi2byndf[indexModule+MAXHASH*iFE] += trkfitchi2byndf;
351 trknpixdead[indexModule+MAXHASH*iFE] += npixdead;
352 trknblayerhits[indexModule+MAXHASH*iFE] += nblayerhits;
353 }
354 }
355
356 if (!eventHasPixHits) {
357 ATH_MSG_DEBUG(
"Pixel MVAMon: event doesn't contain any pixel hits on tracks, skipping evaluation.");
358 return StatusCode::SUCCESS;
359 }
360
361
362 sort(ClusterIDs.begin(), ClusterIDs.end(), [](
const std::pair<Identifier, double> &left,
const std::pair<Identifier, double> &right) {
363 return left.first < right.first;
364 });
365
366 std::vector<float> misshitsf(MAXHASH*2);
367 float alltrackinfo;
368 for (int ih=0; ih<MAXHASH; ++ih) {
369 alltrackinfo =
holes[ih] + outliers[ih] + measurements[ih];
370 if (alltrackinfo) {
371 misshitsf[ih] = (
holes[ih]+outliers[ih])/alltrackinfo;
372 trkalpha[ih] = trkalpha[ih]/alltrackinfo;
373 trkchi2byndf[ih] = trkchi2byndf[ih]/alltrackinfo;
374 trknpixdead[ih] = trknpixdead[ih]/alltrackinfo;
375 trknblayerhits[ih] = trknblayerhits[ih]/alltrackinfo;
376 }
378 alltrackinfo =
holes[ih+MAXHASH]+outliers[ih+MAXHASH]+measurements[ih+MAXHASH];
379 if (alltrackinfo) {
380 misshitsf[ih+MAXHASH] = (
holes[ih+MAXHASH]+outliers[ih+MAXHASH])/alltrackinfo;
381 trkalpha[ih+MAXHASH] = trkalpha[ih+MAXHASH]/alltrackinfo;
382 trkchi2byndf[ih+MAXHASH] = trkchi2byndf[ih+MAXHASH]/alltrackinfo;
383 trknpixdead[ih+MAXHASH] = trknpixdead[ih+MAXHASH]/alltrackinfo;
384 trknblayerhits[ih+MAXHASH] = trknblayerhits[ih+MAXHASH]/alltrackinfo;
385 }
386 }
387 }
388
389
390
391
392
393 std::vector<float> clsall(MAXHASH*2);
394 std::vector<float> clsontrkf(MAXHASH*2);
395 std::vector<float> clsontrk(MAXHASH*2);
396 std::vector<float> clsofftrk(MAXHASH*2);
397
398
399 std::vector<float> clsontrksize(MAXHASH*2);
400 std::vector<float> clsontrkrowsize(MAXHASH*2);
401 std::vector<float> clsontrkcolsize(MAXHASH*2);
402 std::vector<float> clsofftrksize(MAXHASH*2);
403 std::vector<float> clsofftrkrowsize(MAXHASH*2);
404 std::vector<float> clsofftrkcolsize(MAXHASH*2);
405
406 std::vector<float> clsontrktot(MAXHASH*2);
407 std::vector<float> clsofftrktot(MAXHASH*2);
408
410
411 if ( !(pixel_clcontainer.isValid()) ) {
413 return StatusCode::RECOVERABLE;
414 } else {
415 ATH_MSG_DEBUG(
"Pixel MVAMon: Pixel Cluster container "<< pixel_clcontainer.name() <<
" is found.");
416 }
417
418 Identifier clusID;
419
420 for (auto colNext: *pixel_clcontainer) {
421
423 if (!ClusterCollection) {
424 ATH_MSG_DEBUG(
"Pixel MVAMon: Pixel Cluster container is empty.");
425 continue;
426 }
427
428 IdentifierHash clusIDHash = ClusterCollection->identifyHash();
429 int indexModule = static_cast<int>( clusIDHash );
430
431 for (auto p_clus: *ClusterCollection) {
432
433 clusID = p_clus->identify();
434
436 if (pixlayer == 99) continue;
437
438 int iFE=0;
441 }
442 int idxCluster = indexModule+MAXHASH*iFE;
443
444 clsall[idxCluster] += 1;
445
446 const InDet::PixelCluster& cluster = *p_clus;
449 clsontrk[idxCluster] += 1;
450 clsontrksize[idxCluster] += cluster.
rdoList().size();
451 clsontrkrowsize[idxCluster] += cluster.
width().
colRow().x();
452 clsontrkcolsize[idxCluster] += cluster.
width().
colRow().y();
453 clsontrktot[idxCluster] += cluster.
totalToT();
454 } else {
455 clsofftrk[idxCluster] += 1;
456 clsofftrksize[idxCluster] += cluster.
rdoList().size();
457 clsofftrkrowsize[idxCluster]+= cluster.
width().
colRow().x();
458 clsofftrkcolsize[idxCluster]+= cluster.
width().
colRow().y();
459 clsofftrktot[idxCluster] += cluster.
totalToT();
460 }
461 }
462 }
463
464 ClusterIDs.clear();
465
466
467
468
469 for (int ih=0; ih<MAXHASH; ++ih) {
470 if (clsontrk[ih]) {
471 clsontrksize[ih] /= clsontrk[ih];
472 clsontrkrowsize[ih]/= clsontrk[ih];
473 clsontrkcolsize[ih]/= clsontrk[ih];
474 clsontrktot[ih] /= clsontrk[ih];
475 }
476 if (clsofftrk[ih]) {
477 clsofftrksize[ih] /= clsofftrk[ih];
478 clsofftrkrowsize[ih]/= clsofftrk[ih];
479 clsofftrkcolsize[ih]/= clsofftrk[ih];
480 clsofftrktot[ih] /= clsofftrk[ih];
481 }
482 if (clsall[ih]) {
483 clsontrkf[ih] = clsontrk[ih]/clsall[ih];
484 }
485
487 if (clsontrk[ih+MAXHASH]) {
488 clsontrksize[ih+MAXHASH] /= clsontrk[ih+MAXHASH];
489 clsontrkrowsize[ih+MAXHASH]/= clsontrk[ih+MAXHASH];
490 clsontrkcolsize[ih+MAXHASH]/= clsontrk[ih+MAXHASH];
491 clsontrktot[ih+MAXHASH] /= clsontrk[ih+MAXHASH];
492 }
493 if (clsofftrk[ih+MAXHASH]) {
494 clsofftrksize[ih+MAXHASH] /= clsofftrk[ih+MAXHASH];
495 clsofftrkrowsize[ih+MAXHASH]/= clsofftrk[ih+MAXHASH];
496 clsofftrkcolsize[ih+MAXHASH]/= clsofftrk[ih+MAXHASH];
497 clsofftrktot[ih+MAXHASH] /= clsofftrk[ih+MAXHASH];
498 }
499 if (clsall[ih+MAXHASH]) {
500 clsontrkf[ih+MAXHASH] = clsontrk[ih+MAXHASH]/clsall[ih+MAXHASH];
501 }
502 }
503 }
504
505
506
507
508 std::vector<float> bdtweights(MAXHASH*2);
509 VecAccumulator2DMap BDT_Weights(*this, "BDTWeights");
510
511 for (int ih=12; ih<MAXHASH-12; ++ih)
512 {
513 int nFE(1);
515 float mod_eta(0);
517
518 if ( ih>=156 && ih<=435 )
519 {
520 module = (ih-156) % 20;
521 nFE = 2;
522 if (module<4 || module>15) continue;
523 else mod_eta = module-9.5;
524 }
525 else if (ih>=436 && ih<=721 )
526 {
527 module = (ih-436) % 13;
528 el_eta = std::abs(module-6);
529 }
530 else if (ih>=722 && ih<=1215)
531 {
532 module = (ih-722) % 13;
533 el_eta = std::abs(module-6);
534 }
535 else if (ih>=1216 && ih<=1891)
536 {
537 module = (ih-1216) % 13;
538 el_eta = std::abs(module-6);
539 }
540 else if ( (ih>=12 && ih<=155) || (ih>=1892 && ih<=2035) )
541 {
542
543
545 }
546 else continue;
547
548 Identifier waferID =
m_pixelid->wafer_id(ih);
550 if (pixlayer == 99) continue;
551 std::string partitionLabel("Disks");
553
554 for (int iFE=0; iFE<nFE; iFE++) {
555 Identifier pixID = waferID;
560 continue;
561 }
563 if (mod_eta > 0)
el_eta-=1.0;
564 el_eta = std::abs(el_eta);
565 }
566
567 int idx = ih+MAXHASH*iFE;
568 if ( status[idx]==2 ) BDT_Weights.add(pixlayer, pixID, 0);
569 if ( status[idx]!=0 || (measurements[idx]+holes[idx]+outliers[idx]==0) ) continue;
570
571 std::vector<float> bdtVars;
573 bdtVars = {
el_eta, misshitsf[
idx], clsontrkf[
idx], clsontrkrowsize[
idx],
574 clsontrkcolsize[
idx], clsofftrkrowsize[
idx], clsofftrkcolsize[
idx],
575 clsontrktot[
idx], clsofftrktot[
idx], trkalpha[
idx],
576 trkchi2byndf[
idx], trknpixdead[
idx], trknblayerhits[
idx] };
577 } else {
578 bdtVars = {
el_eta, misshitsf[
idx], clsontrkf[
idx], clsontrkrowsize[
idx],
579 clsontrkcolsize[
idx], clsofftrkrowsize[
idx], clsofftrkcolsize[
idx],
580 clsontrktot[
idx], clsofftrktot[
idx], trkalpha[
idx],
581 trkchi2byndf[
idx], trknpixdead[
idx] };
582 }
583 bdtweights[
idx] =
m_classBDT.at(partitionLabel)->GetClassification(bdtVars);
584 BDT_Weights.add(pixlayer, pixID, bdtweights[idx]);
585 }
586 }
589
596
601
608
615
617
618 fill( mvaGroup, lbval, mon_status_vec, mon_h_vec, mon_o_vec, mon_m_vec,
619 mon_clsontrkf_vec, mon_clsontrk_vec, mon_clsofftrk_vec, mon_clsall_vec,
620 mon_clsontrksize_vec, mon_clsontrkrowsize_vec, mon_clsontrkcolsize_vec,
621 mon_clsofftrksize_vec, mon_clsofftrkrowsize_vec, mon_clsofftrkcolsize_vec,
622 mon_clsontrktot_vec, mon_clsofftrktot_vec, mon_trkalpha_vec, mon_trkchi2byndf_vec,
623 mon_trknpixdead_vec, mon_trknblayerhits_vec, mon_mva_vec );
624 }
625
626 return StatusCode::SUCCESS;
627}
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
const ToolHandle< GenericMonitoringTool > & getGroup(const std::string &name) const
Get a specific monitoring tool from the tool handle array.
SG::ReadHandle< xAOD::EventInfo > GetEventInfo(const EventContext &) const
Return a ReadHandle for an EventInfo object (get run/event numbers, etc.)
bool is_valid() const
Check if id is in a valid state.
virtual const Amg::Vector3D & normal() const override final
Get reconstruction local normal axes in global frame.
virtual Identifier identify() const override final
identifier of this detector element (inline)
Identifier identifierOfPosition(const Amg::Vector2D &localPos) const
Full identifier of the cell for a given position: assumes a raw local position (no Lorentz shift)
virtual const PixelCluster * prepRawData() const override final
returns the PrepRawData - is a SiCluster in this scope
const InDet::SiWidth & width() const
return width class reference
const Amg::Vector2D & colRow() const
Trk::PrepRawDataCollection< PixelCluster > PixelClusterCollection
std::map< std::string, std::unique_ptr< MVAUtils::BDT > > m_classBDT
SG::ReadHandleKey< xAOD::TrackParticleContainer > m_trackParticlesKey
SG::ReadHandleKey< InDet::PixelClusterContainer > m_clustersKey
void fill2DProfLayerAccum(const VecAccumulator2DMap &accumulator) const
take VecAccumulator2DMap and fill the corresponding group
SG::ReadHandleKey< InDet::SiDetectorElementStatus > m_pixelDetElStatusActiveOnly
Optional read handle to get status data to test whether a pixel detector element is active.
int getNumberOfFEs(int pixlayer, int etaMod) const
helper function to get number of FEs per module
bool isClusterOnTrack(Identifier id, std::vector< std::pair< Identifier, double > > const &ClusterIDs) const
checks if cluster is on track
void fill1DModProfAccum(const VecAccumulator2DMap &accumulator, int lumiblock) const
take VecAccumulator2DMap and fill 3D arrays [layer, pm, em] with its values and lumiblock
ServiceHandle< InDetDD::IPixelReadoutManager > m_pixelReadout
bool isGood(const InDet::SiDetectorElementStatus *element_status, const IdentifierHash &module_hash) const
int getPixLayersID(int ec, int ld) const
helper function to get layers ID
bool isIBL2D(int hashID) const
helper function to check if module is IBL planar based on pixel hash ID
std::tuple< bool, bool > isChipGood(const IdentifierHash &module_hash, unsigned int chip_i) const
SG::ReadHandleKey< InDet::SiDetectorElementStatus > m_pixelDetElStatus
Optional read handle to get status data to test whether a pixel detector element is good.
bool isActive(const InDet::SiDetectorElementStatus *element_status, const IdentifierHash &module_hash) const
SG::ReadHandle< InDet::SiDetectorElementStatus > getPixelDetElStatus(const SG::ReadHandleKey< InDet::SiDetectorElementStatus > &key, const EventContext &ctx) const
const PixelID * m_pixelid
std::vector< Identifier >::const_iterator const_id_iterator
const_pointer_type cptr()
Dereference the pointer.
virtual const Surface & associatedSurface() const =0
Interface method to get the associated Surface.
virtual bool type(MeasurementBaseType::Type type) const =0
Interface method checking the type.
const Amg::Vector3D & momentum() const
Access method for the momentum.
virtual const Surface & associatedSurface() const override=0
Access to the Surface associated to the Parameters.
Amg::Vector2D localPosition() const
Access method for the local coordinates, local parameter definitions differ for each surface type.
const std::vector< Identifier > & rdoList() const
return the List of rdo identifiers (pointers)
Identifier identify() const
return the identifier -extends MeasurementBase
const TrkDetElementBase * associatedDetectorElement() const
return associated Detector Element
Identifier associatedDetectorElementIdentifier() const
return Identifier of the associated Detector Element
@ Measurement
This is a measurement, and will at least contain a Trk::MeasurementBase.
@ Outlier
This TSoS contains an outlier, that is, it contains a MeasurementBase/RIO_OnTrack which was not used ...
@ Hole
A hole on the track - this is defined in the following way.
virtual Identifier identify() const =0
Identifier.
void fill(const ToolHandle< GenericMonitoringTool > &groupHandle, std::vector< std::reference_wrapper< Monitored::IMonitoredVariable > > &&variables) const
Fills a vector of variables to a group by reference.
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
float nPixelHits(const U &p)
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
DataVector< const Trk::TrackStateOnSurface > TrackStates
ParametersT< TrackParametersDim, Charged, PerigeeSurface > Perigee
ParametersBase< TrackParametersDim, Charged > TrackParameters
ParametersT< TrackParametersDim, Charged, PlaneSurface > AtaPlane
@ expectInnermostPixelLayerHit
Do we expect a 0th-layer barrel hit for this track?
@ numberOfPixelHoles
number of pixel layers on track with absence of hits [unit8_t].
@ numberOfNextToInnermostPixelLayerHits
these are the hits in the 1st pixel barrel layer
@ expectNextToInnermostPixelLayerHit
Do we expect a 1st-layer barrel hit for this track?
@ numberOfPixelHits
these are the pixel hits, including the b-layer [unit8_t].
@ numberOfPixelDeadSensors
number of dead pixel sensors crossed [unit8_t].