45 mMaxBunchesFull =
TIME_ORBIT / config.bunchSpacing;
46 mMaxBunches = (
TIME_ORBIT - config.abortGapTime) / config.bunchSpacing;
48 if (config.overlayRaw &&
chain->GetTPCTransformHelper() ==
nullptr) {
49 GPUInfo(
"Overlay Raw Events requires TPC Fast Transform");
50 throw std::exception();
52 if (config.bunchSim) {
53 if (config.bunchCount * config.bunchTrainCount > mMaxBunches) {
54 GPUInfo(
"Invalid timeframe settings: too many colliding bunches requested!");
55 throw std::exception();
57 mTrainDist = mMaxBunches / config.bunchTrainCount;
58 mCollisionProbability = (float)config.interactionRate * (
float)(mMaxBunchesFull * config.bunchSpacing / 1e9f) / (
float)(config.bunchCount * config.bunchTrainCount);
59 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,
60 config.bunchCount * config.bunchTrainCount, mMaxBunches, mMaxBunchesFull, mCollisionProbability, mNEventsInDirectory);
65 mEventUsed.resize(mNEventsInDirectory);
66 if (config.noEventRepeat == 2) {
67 memset(mEventUsed.data(), 0, mNEventsInDirectory *
sizeof(mEventUsed[0]));
74 if (config.overlayRaw) {
76 for (uint32_t iSector = 0; iSector < NSECTORS; iSector++) {
79 tmp.fTime += shiftTTotal;
84 for (uint32_t iSector = 0; iSector < NSECTORS; iSector++) {
87 tmp.z += iSector < NSECTORS / 2 ? shiftZ : -shiftZ;
92 tmp.z +=
i < NSECTORS / 2 ? shiftZ : -shiftZ;
100 uint32_t currentClusterTotal = 0;
101 for (uint32_t iSector = 0; iSector < NSECTORS; iSector++) {
102 uint32_t currentClusterSector = 0;
105 float sign = iSector < NSECTORS / 2 ? 1 : -1;
107 if (currentClusterSector !=
i) {
117 currentClusterSector++;
123 currentClusterTotal++;
134 for (uint32_t
i = 0;
i < NSECTORS;
i++) {
142 GPUInfo(
"\tRemoved %u / %u clusters", removed,
nClusters + removed);
153 for (uint32_t
i = 0;
i < mShiftedEvents.size();
i++) {
154 auto&
ptr = std::get<0>(mShiftedEvents[
i]);
155 for (uint32_t
j = 0;
j < NSECTORS;
j++) {
157 if (config.overlayRaw) {
164 SetDisplayInformation(
i);
166 uint32_t nClustersTotal = 0;
167 uint32_t nClustersTotalRaw = 0;
168 uint32_t nClustersSectorOffset[NSECTORS] = {0};
169 for (uint32_t
i = 0;
i < NSECTORS;
i++) {
170 nClustersSectorOffset[
i] = nClustersTotal;
174 if (nClustersTotalRaw && nClustersTotalRaw != nClustersTotal) {
175 GPUError(
"Inconsitency between raw clusters and cluster data");
176 throw std::exception();
179 GPUError(
"Inconsitency between TPC clusters and MC labels");
180 throw std::exception();
185 uint32_t nTrackOffset = 0;
186 uint32_t nColOffset = 0;
187 uint32_t nClustersEventOffset[NSECTORS] = {0};
188 for (uint32_t
i = 0;
i < mShiftedEvents.size();
i++) {
189 auto&
ptr = std::get<0>(mShiftedEvents[
i]);
190 uint32_t inEventOffset = 0;
191 for (uint32_t
j = 0;
j < NSECTORS;
j++) {
192 memcpy((
void*)&mChain->
mIOMem.
clusterData[
j][nClustersEventOffset[
j]], (
void*)
ptr.clusterData[
j],
ptr.nClusterData[
j] *
sizeof(
ptr.clusterData[
j][0]));
193 if (nClustersTotalRaw) {
194 memcpy((
void*)&mChain->
mIOMem.
rawClusters[
j][nClustersEventOffset[
j]], (
void*)
ptr.rawClusters[
j],
ptr.nRawClusters[
j] *
sizeof(
ptr.rawClusters[
j][0]));
197 memcpy((
void*)&mChain->
mIOMem.
mcLabelsTPC[nClustersSectorOffset[
j] + nClustersEventOffset[
j]], (
void*)&
ptr.mcLabelsTPC[inEventOffset],
ptr.nClusterData[
j] *
sizeof(
ptr.mcLabelsTPC[0]));
199 for (uint32_t k = 0; k <
ptr.nClusterData[
j]; k++) {
200 mChain->
mIOMem.
clusterData[
j][nClustersEventOffset[
j] + k].id = nClustersSectorOffset[
j] + nClustersEventOffset[
j] + k;
202 for (int32_t l = 0; l < 3; l++) {
204 if (
label.fMCID >= 0) {
205 label.fMCID += nTrackOffset;
211 nClustersEventOffset[
j] +=
ptr.nClusterData[
j];
212 inEventOffset +=
ptr.nClusterData[
j];
215 memcpy((
void*)&mChain->
mIOMem.
mcInfosTPC[nTrackOffset], (
void*)
ptr.mcInfosTPC,
ptr.nMCInfosTPC *
sizeof(
ptr.mcInfosTPC[0]));
216 for (uint32_t
j = 0;
j <
ptr.nMCInfosTPCCol;
j++) {
220 nTrackOffset +=
ptr.nMCInfosTPC;
221 nColOffset +=
ptr.nMCInfosTPCCol;
224 GPUInfo(
"Merged %d events, %u clusters total", (int32_t)mShiftedEvents.size(), nClustersTotal);
226 mShiftedEvents.clear();
231 if (config.nTotalEventsInTF && mNTotalCollisions >= config.nTotalEventsInTF) {
235 int64_t nBunch = -
DRIFT_TIME / config.bunchSpacing;
236 int64_t lastBunch = config.timeFrameLen / config.bunchSpacing;
237 int64_t lastTFBunch = lastBunch -
DRIFT_TIME / config.bunchSpacing;
238 int32_t nCollisions = 0, nBorderCollisions = 0, nTrainCollissions = 0, nMultipleCollisions = 0, nTrainMultipleCollisions = 0;
240 int32_t mcMin = -1, mcMax = -1;
241 uint32_t nTotalClusters = 0;
242 while (nBunch < lastBunch) {
243 for (int32_t iTrain = 0; iTrain < config.bunchTrainCount && nBunch < lastBunch; iTrain++) {
244 int32_t nCollisionsInTrain = 0;
245 for (int32_t iBunch = 0; iBunch < config.bunchCount && nBunch < lastBunch; iBunch++) {
246 const bool inTF = nBunch >= 0 && nBunch < lastTFBunch && (config.nTotalEventsInTF == 0 || nCollisions < mNTotalCollisions + config.nTotalEventsInTF);
247 if (mcMin == -1 && inTF) {
250 if (mcMax == -1 && nBunch >= 0 && !inTF) {
253 int32_t nInBunchPileUp = 0;
254 double randVal = mDisUniReal(inTF ? mRndGen2 : mRndGen1);
255 double p =
exp(-mCollisionProbability);
257 while (randVal > p) {
258 if (config.noBorder && (nBunch < 0 || nBunch >= lastTFBunch)) {
261 if (nCollisionsInTrain >= mNEventsInDirectory) {
262 GPUError(
"Error: insuffient events for mixing!");
265 if (nCollisionsInTrain == 0 && config.noEventRepeat == 0) {
266 memset(mEventUsed.data(), 0, mNEventsInDirectory *
sizeof(mEventUsed[0]));
274 if (config.noEventRepeat == 1) {
275 useEvent = mSimBunchNoRepeatEvent;
277 while (mEventUsed[useEvent = (inTF && config.eventStride ? (mEventStride += config.eventStride) : mDisUniInt(inTF ? mRndGen2 : mRndGen1)) % mNEventsInDirectory]) {
281 if (config.noEventRepeat) {
282 mSimBunchNoRepeatEvent++;
284 mEventUsed[useEvent] = 1;
285 double shift = (double)nBunch * (
double)config.bunchSpacing * (double)
TPCZ / (
double)
DRIFT_TIME;
288 GPUError(
"Unexpected error");
292 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",
295 nCollisionsInTrain++;
296 p2 *= mCollisionProbability / nInBunchPileUp;
298 if (config.noEventRepeat && mSimBunchNoRepeatEvent >= mNEventsInDirectory) {
302 if (nInBunchPileUp > 1) {
303 nMultipleCollisions++;
307 nBunch += mTrainDist - config.bunchCount;
308 if (nCollisionsInTrain) {
311 if (nCollisionsInTrain > 1) {
312 nTrainMultipleCollisions++;
316 nBunch += mMaxBunchesFull - mTrainDist * config.bunchTrainCount;
318 mNTotalCollisions += nCollisions;
319 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,
320 nTrainMultipleCollisions);
324 if (!config.noBorder && mChain->
GetQA()) {
332 for (int32_t iEventInTimeframe = 0; iEventInTimeframe < config.nMerge; iEventInTimeframe++) {
334 if (config.shiftFirstEvent || iEventInTimeframe) {
335 if (config.randomizeDistance) {
336 shift = mDisUniReal(mRndGen2);
337 if (config.shiftFirstEvent) {
338 shift = (iEventInTimeframe + shift) * config.averageDistance;
340 if (iEventInTimeframe == 0) {
343 shift = (iEventInTimeframe - 0.5f + shift) * config.averageDistance;
347 if (config.shiftFirstEvent) {
348 shift = config.averageDistance * (iEventInTimeframe + 0.5f);
350 shift = config.averageDistance * (iEventInTimeframe);
357 if (
ReadEventShifted(iEvent * config.nMerge + iEventInTimeframe, shift) < 0) {