44 mMaxBunchesFull =
TIME_ORBIT / config.bunchSpacing;
45 mMaxBunches = (
TIME_ORBIT - config.abortGapTime) / config.bunchSpacing;
47 if (config.overlayRaw &&
chain->GetTPCTransformHelper() ==
nullptr) {
48 GPUInfo(
"Overlay Raw Events requires TPC Fast Transform");
49 throw std::exception();
51 if (config.bunchSim) {
52 if (config.bunchCount * config.bunchTrainCount > mMaxBunches) {
53 GPUInfo(
"Invalid timeframe settings: too many colliding bunches requested!");
54 throw std::exception();
56 mTrainDist = mMaxBunches / config.bunchTrainCount;
57 mCollisionProbability = (float)config.interactionRate * (
float)(mMaxBunchesFull * config.bunchSpacing / 1e9f) / (
float)(config.bunchCount * config.bunchTrainCount);
58 GPUInfo(
"Timeframe settings: %d trains of %d bunches, bunch spacing: %d, train spacing: %dx%d, filled bunches %d / %d (%d), collision probability %f, mixing %d events", config.bunchTrainCount, config.bunchCount, config.bunchSpacing, mTrainDist, config.bunchSpacing,
59 config.bunchCount * config.bunchTrainCount, mMaxBunches, mMaxBunchesFull, mCollisionProbability, mNEventsInDirectory);
64 mEventUsed.resize(mNEventsInDirectory);
65 if (config.noEventRepeat == 2) {
66 memset(mEventUsed.data(), 0, mNEventsInDirectory *
sizeof(mEventUsed[0]));
73 if (config.overlayRaw) {
75 for (uint32_t iSector = 0; iSector < NSECTORS; iSector++) {
78 tmp.fTime += shiftTTotal;
83 for (uint32_t iSector = 0; iSector < NSECTORS; iSector++) {
86 tmp.z += iSector < NSECTORS / 2 ? shiftZ : -shiftZ;
91 tmp.z +=
i < NSECTORS / 2 ? shiftZ : -shiftZ;
99 uint32_t currentClusterTotal = 0;
100 for (uint32_t iSector = 0; iSector < NSECTORS; iSector++) {
101 uint32_t currentClusterSector = 0;
104 float sign = iSector < NSECTORS / 2 ? 1 : -1;
106 if (currentClusterSector !=
i) {
116 currentClusterSector++;
122 currentClusterTotal++;
133 for (uint32_t
i = 0;
i < NSECTORS;
i++) {
141 GPUInfo(
"\tRemoved %u / %u clusters", removed,
nClusters + removed);
152 for (uint32_t
i = 0;
i < mShiftedEvents.size();
i++) {
153 auto&
ptr = std::get<0>(mShiftedEvents[
i]);
154 for (uint32_t
j = 0;
j < NSECTORS;
j++) {
156 if (config.overlayRaw) {
163 SetDisplayInformation(
i);
165 uint32_t nClustersTotal = 0;
166 uint32_t nClustersTotalRaw = 0;
167 uint32_t nClustersSectorOffset[NSECTORS] = {0};
168 for (uint32_t
i = 0;
i < NSECTORS;
i++) {
169 nClustersSectorOffset[
i] = nClustersTotal;
173 if (nClustersTotalRaw && nClustersTotalRaw != nClustersTotal) {
174 GPUError(
"Inconsitency between raw clusters and cluster data");
175 throw std::exception();
178 GPUError(
"Inconsitency between TPC clusters and MC labels");
179 throw std::exception();
184 uint32_t nTrackOffset = 0;
185 uint32_t nColOffset = 0;
186 uint32_t nClustersEventOffset[NSECTORS] = {0};
187 for (uint32_t
i = 0;
i < mShiftedEvents.size();
i++) {
188 auto&
ptr = std::get<0>(mShiftedEvents[
i]);
189 uint32_t inEventOffset = 0;
190 for (uint32_t
j = 0;
j < NSECTORS;
j++) {
191 memcpy((
void*)&mChain->
mIOMem.
clusterData[
j][nClustersEventOffset[
j]], (
void*)
ptr.clusterData[
j],
ptr.nClusterData[
j] *
sizeof(
ptr.clusterData[
j][0]));
192 if (nClustersTotalRaw) {
193 memcpy((
void*)&mChain->
mIOMem.
rawClusters[
j][nClustersEventOffset[
j]], (
void*)
ptr.rawClusters[
j],
ptr.nRawClusters[
j] *
sizeof(
ptr.rawClusters[
j][0]));
196 memcpy((
void*)&mChain->
mIOMem.
mcLabelsTPC[nClustersSectorOffset[
j] + nClustersEventOffset[
j]], (
void*)&
ptr.mcLabelsTPC[inEventOffset],
ptr.nClusterData[
j] *
sizeof(
ptr.mcLabelsTPC[0]));
198 for (uint32_t k = 0; k <
ptr.nClusterData[
j]; k++) {
199 mChain->
mIOMem.
clusterData[
j][nClustersEventOffset[
j] + k].id = nClustersSectorOffset[
j] + nClustersEventOffset[
j] + k;
201 for (int32_t l = 0; l < 3; l++) {
203 if (
label.fMCID >= 0) {
204 label.fMCID += nTrackOffset;
210 nClustersEventOffset[
j] +=
ptr.nClusterData[
j];
211 inEventOffset +=
ptr.nClusterData[
j];
214 memcpy((
void*)&mChain->
mIOMem.
mcInfosTPC[nTrackOffset], (
void*)
ptr.mcInfosTPC,
ptr.nMCInfosTPC *
sizeof(
ptr.mcInfosTPC[0]));
215 for (uint32_t
j = 0;
j <
ptr.nMCInfosTPCCol;
j++) {
219 nTrackOffset +=
ptr.nMCInfosTPC;
220 nColOffset +=
ptr.nMCInfosTPCCol;
223 GPUInfo(
"Merged %d events, %u clusters total", (int32_t)mShiftedEvents.size(), nClustersTotal);
225 mShiftedEvents.clear();
230 if (config.nTotalEventsInTF && mNTotalCollisions >= config.nTotalEventsInTF) {
234 int64_t nBunch = -
DRIFT_TIME / config.bunchSpacing;
235 int64_t lastBunch = config.timeFrameLen / config.bunchSpacing;
236 int64_t lastTFBunch = lastBunch -
DRIFT_TIME / config.bunchSpacing;
237 int32_t nCollisions = 0, nBorderCollisions = 0, nTrainCollissions = 0, nMultipleCollisions = 0, nTrainMultipleCollisions = 0;
239 int32_t mcMin = -1, mcMax = -1;
240 uint32_t nTotalClusters = 0;
241 while (nBunch < lastBunch) {
242 for (int32_t iTrain = 0; iTrain < config.bunchTrainCount && nBunch < lastBunch; iTrain++) {
243 int32_t nCollisionsInTrain = 0;
244 for (int32_t iBunch = 0; iBunch < config.bunchCount && nBunch < lastBunch; iBunch++) {
245 const bool inTF = nBunch >= 0 && nBunch < lastTFBunch && (config.nTotalEventsInTF == 0 || nCollisions < mNTotalCollisions + config.nTotalEventsInTF);
246 if (mcMin == -1 && inTF) {
249 if (mcMax == -1 && nBunch >= 0 && !inTF) {
252 int32_t nInBunchPileUp = 0;
253 double randVal = mDisUniReal(inTF ? mRndGen2 : mRndGen1);
254 double p =
exp(-mCollisionProbability);
256 while (randVal > p) {
257 if (config.noBorder && (nBunch < 0 || nBunch >= lastTFBunch)) {
260 if (nCollisionsInTrain >= mNEventsInDirectory) {
261 GPUError(
"Error: insuffient events for mixing!");
264 if (nCollisionsInTrain == 0 && config.noEventRepeat == 0) {
265 memset(mEventUsed.data(), 0, mNEventsInDirectory *
sizeof(mEventUsed[0]));
273 if (config.noEventRepeat == 1) {
274 useEvent = mSimBunchNoRepeatEvent;
276 while (mEventUsed[useEvent = (inTF && config.eventStride ? (mEventStride += config.eventStride) : mDisUniInt(inTF ? mRndGen2 : mRndGen1)) % mNEventsInDirectory]) {
280 if (config.noEventRepeat) {
281 mSimBunchNoRepeatEvent++;
283 mEventUsed[useEvent] = 1;
284 double shift = (double)nBunch * (
double)config.bunchSpacing * (double)
TPCZ / (
double)
DRIFT_TIME;
287 GPUError(
"Unexpected error");
291 printf(
"Placing event %4d+%d (ID %4d) at z %7.3f (time %'dns) %s(collisions %4d, bunch %6ld, train %3d) (%'10d clusters, %'10d MC labels, %'10d track MC info)\n", nCollisions, nBorderCollisions, useEvent, shift, (int32_t)(nBunch * config.bunchSpacing), inTF ?
" inside" :
"outside",
294 nCollisionsInTrain++;
295 p2 *= mCollisionProbability / nInBunchPileUp;
297 if (config.noEventRepeat && mSimBunchNoRepeatEvent >= mNEventsInDirectory) {
301 if (nInBunchPileUp > 1) {
302 nMultipleCollisions++;
306 nBunch += mTrainDist - config.bunchCount;
307 if (nCollisionsInTrain) {
310 if (nCollisionsInTrain > 1) {
311 nTrainMultipleCollisions++;
315 nBunch += mMaxBunchesFull - mTrainDist * config.bunchTrainCount;
317 mNTotalCollisions += nCollisions;
318 GPUInfo(
"Timeframe statistics: collisions: %d+%d in %d trains (inside / outside), average rate %f (pile up: in bunch %d, in train %d)", nCollisions, nBorderCollisions, nTrainCollissions, (
float)nCollisions / (
float)(config.timeFrameLen -
DRIFT_TIME) * 1e9, nMultipleCollisions,
319 nTrainMultipleCollisions);
323 if (!config.noBorder && mChain->
GetQA()) {
331 for (int32_t iEventInTimeframe = 0; iEventInTimeframe < config.nMerge; iEventInTimeframe++) {
333 if (config.shiftFirstEvent || iEventInTimeframe) {
334 if (config.randomizeDistance) {
335 shift = mDisUniReal(mRndGen2);
336 if (config.shiftFirstEvent) {
337 shift = (iEventInTimeframe + shift) * config.averageDistance;
339 if (iEventInTimeframe == 0) {
342 shift = (iEventInTimeframe - 0.5f + shift) * config.averageDistance;
346 if (config.shiftFirstEvent) {
347 shift = config.averageDistance * (iEventInTimeframe + 0.5f);
349 shift = config.averageDistance * (iEventInTimeframe);
356 if (
ReadEventShifted(iEvent * config.nMerge + iEventInTimeframe, shift) < 0) {