Skip to content

Commit 2636bf3

Browse files
author
NarrowsProjects
committed
feat: create summary views for runs
1 parent 29a73eb commit 2636bf3

7 files changed

Lines changed: 266 additions & 100 deletions

File tree

lib/database/adapters/EorReasonAdapter.js

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class EorReasonAdapter {
2525
this.reasonTypeAdapter = null;
2626

2727
this.toEntity = this.toEntity.bind(this);
28+
this.toSummary = this.toSummary.bind(this);
2829
this.toDatabase = this.toDatabase.bind(this);
2930
}
3031

@@ -34,21 +35,31 @@ class EorReasonAdapter {
3435
* @returns {EorReason} Converted entity object.
3536
*/
3637
toEntity({ id, description, runId, reasonTypeId, reasonType, lastEditedName, createdAt, updatedAt }) {
37-
const entityObject = {
38+
return {
39+
...this.toSummary({ description, reasonType }),
3840
id,
39-
description,
40-
lastEditedName,
41-
reasonTypeId,
4241
runId,
42+
reasonTypeId,
43+
lastEditedName,
4344
createdAt: new Date(createdAt).getTime(),
4445
updatedAt: new Date(updatedAt).getTime(),
4546
};
47+
}
48+
49+
/**
50+
* Converts the given end of run reason database object to an summary reason object.
51+
* @param {SequelizeEorReason} databaseObject Object to convert.
52+
* @returns {EorReason} Converted summary object.
53+
*/
54+
toSummary({ description, reasonType }) {
55+
const entityObject = { description };
4656

4757
if (reasonType) {
4858
const reasonTypeEntity = this.reasonTypeAdapter.toEntity(reasonType);
4959
entityObject.category = reasonTypeEntity.category;
5060
entityObject.title = reasonTypeEntity.title;
5161
}
62+
5263
return entityObject;
5364
}
5465

lib/database/adapters/QcFlagAdapter.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,31 @@ class QcFlagAdapter {
2020
*/
2121
constructor() {
2222
this.toEntity = this.toEntity.bind(this);
23+
this.toSummary = this.toSummary.bind(this);
2324

2425
this.qcFlagTypeAdapter = null;
2526
this.qcFlagVerificationAdapter = null;
2627
this.qcFlagEffectivePeriodAdapter = null;
2728
this.userAdapter = null;
2829
}
2930

31+
/**
32+
* Converts the given database object to an summary object.
33+
*
34+
* @param {SequelizeQcFlag} databaseObject Object to convert.
35+
* @returns {QcFlag} Converted summary object.
36+
*/
37+
toSummary(databaseObject) {
38+
const { effectivePeriods = [], detectorId, flagType, id } = databaseObject;
39+
40+
return {
41+
id,
42+
dplDetectorId: detectorId,
43+
flagType: flagType ? { name: flagType.name } : null,
44+
effectivePeriods: effectivePeriods.map(this.qcFlagEffectivePeriodAdapter.toEntity),
45+
};
46+
}
47+
3048
/**
3149
* Converts the given database object to an entity object.
3250
*

lib/database/adapters/RunAdapter.js

Lines changed: 106 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ class RunAdapter {
8787
this.qcFlagAdapter = null;
8888

8989
this.toEntity = this.toEntity.bind(this);
90+
this.toSummary = this.toSummary.bind(this);
9091
this.toLhcFillSummary = this.toLhcFillSummary.bind(this);
9192
this.toDatabase = this.toDatabase.bind(this);
9293
this.toMinifiedEntity = this.toMinifiedEntity.bind(this);
@@ -119,6 +120,26 @@ class RunAdapter {
119120
}
120121
}
121122

123+
/**
124+
* Adds detectors along with their qualities to an entity
125+
*
126+
* @param {Detector[]} detectors the list of detector models
127+
* @param {object} entityObject the entity object that is to be modified
128+
* @param {boolean} [addDetectorQuality = true] if detectorQuality should be included
129+
* @returns {void}
130+
*/
131+
_computeQcFlags(qcFlags = [], entityObject, isSummary = false) {
132+
const adaptedQcFlags = isSummary
133+
? qcFlags.map(this.qcFlagAdapter.toSummary)
134+
: qcFlags.map(this.qcFlagAdapter.toEntity);
135+
136+
entityObject.qcFlags = adaptedQcFlags.reduce((acc, qcFlag) => {
137+
acc[qcFlag.dplDetectorId] = acc[qcFlag.dplDetectorId] ?? [];
138+
acc[qcFlag.dplDetectorId].push(qcFlag);
139+
return acc;
140+
}, {});
141+
}
142+
122143
/**
123144
* Converts the given database object to an entity object.
124145
*
@@ -311,12 +332,91 @@ class RunAdapter {
311332
? lhcFill.collidingBunchesCount ?? extractNumberOfCollidingLhcBunchCrossings(lhcFill.fillingSchemeName)
312333
: null;
313334

314-
const adaptedQcFlags = qcFlags ? qcFlags.map(this.qcFlagAdapter.toEntity) : [];
315-
entityObject.qcFlags = adaptedQcFlags.reduce((acc, qcFlag) => {
316-
acc[qcFlag.dplDetectorId] = acc[qcFlag.dplDetectorId] ?? [];
317-
acc[qcFlag.dplDetectorId].push(qcFlag);
318-
return acc;
319-
}, {});
335+
this._computeQcFlags(qcFlags, entityObject);
336+
337+
return entityObject;
338+
}
339+
340+
/**
341+
* Converts the given database object to an summary object.
342+
*
343+
* @param {SequelizeRun} databaseObject Object to convert.
344+
* @returns {Run} Converted summary object.
345+
*/
346+
toSummary(databaseObject) {
347+
const {
348+
detectors,
349+
eorReasons,
350+
runNumber,
351+
timeO2Start,
352+
timeO2End,
353+
timeTrgStart,
354+
timeTrgEnd,
355+
firstTfTimestamp,
356+
lastTfTimestamp,
357+
qcTimeStart,
358+
qcTimeEnd,
359+
inelasticInteractionRateAvg,
360+
inelasticInteractionRateAtStart,
361+
inelasticInteractionRateAtMid,
362+
inelasticInteractionRateAtEnd,
363+
aliceL3Polarity,
364+
aliceL3Current,
365+
aliceDipolePolarity,
366+
aliceDipoleCurrent,
367+
qcFlags = [],
368+
} = databaseObject;
369+
370+
/**
371+
* @type {Run}
372+
*/
373+
const entityObject = {
374+
runNumber,
375+
timeO2Start: timeO2Start ? new Date(timeO2Start).getTime() : timeO2Start,
376+
timeO2End: timeO2End ? new Date(timeO2End).getTime() : timeO2End,
377+
timeTrgStart: timeTrgStart ? new Date(timeTrgStart).getTime() : timeTrgStart,
378+
timeTrgEnd: timeTrgEnd ? new Date(timeTrgEnd).getTime() : timeTrgEnd,
379+
firstTfTimestamp: firstTfTimestamp ? new Date(firstTfTimestamp).getTime() : firstTfTimestamp,
380+
lastTfTimestamp: lastTfTimestamp ? new Date(lastTfTimestamp).getTime() : lastTfTimestamp,
381+
qcTimeStart: qcTimeStart ? new Date(qcTimeStart).getTime() : qcTimeStart,
382+
qcTimeEnd: qcTimeEnd ? new Date(qcTimeEnd).getTime() : qcTimeEnd,
383+
id: databaseObject.id,
384+
runDuration: databaseObject.runDuration,
385+
environmentId: databaseObject.environmentId,
386+
runType: databaseObject.runType,
387+
definition: databaseObject.definition,
388+
calibrationStatus: databaseObject.calibrationStatus,
389+
runQuality: databaseObject.runQuality,
390+
nDetectors: databaseObject.nDetectors,
391+
nFlps: databaseObject.nFlps,
392+
nEpns: databaseObject.nEpns,
393+
dd_flp: databaseObject.dd_flp,
394+
dcs: databaseObject.dcs,
395+
epn: databaseObject.epn,
396+
epnTopology: databaseObject.epnTopology,
397+
nSubtimeframes: databaseObject.nSubtimeframes,
398+
bytesReadOut: databaseObject.bytesReadOut,
399+
fillNumber: databaseObject.fillNumber,
400+
lhcBeamMode: databaseObject.lhcBeamMode,
401+
odcTopologyFullName: databaseObject.odcTopologyFullName,
402+
triggerValue: databaseObject.triggerValue,
403+
tags: databaseObject.tags,
404+
pdpBeamType: databaseObject.pdpBeamType,
405+
lhcPeriod: databaseObject.lhcPeriod,
406+
aliceL3Polarity,
407+
aliceL3Current,
408+
aliceDipolePolarity,
409+
aliceDipoleCurrent,
410+
};
411+
412+
entityObject.eorReasons = eorReasons ? eorReasons.map(this.eorReasonAdapter.toSummary) : [];
413+
entityObject.inelasticInteractionRateAvg = inelasticInteractionRateAvg;
414+
entityObject.inelasticInteractionRateAtStart = inelasticInteractionRateAtStart;
415+
entityObject.inelasticInteractionRateAtMid = inelasticInteractionRateAtMid;
416+
entityObject.inelasticInteractionRateAtEnd = inelasticInteractionRateAtEnd;
417+
418+
this._addDetectorsToObject(detectors, entityObject);
419+
this._computeQcFlags(qcFlags, entityObject, true);
320420

321421
return entityObject;
322422
}

lib/server/views/runs/summary.js

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/**
2+
* @license
3+
* Copyright CERN and copyright holders of ALICE O2. This software is
4+
* distributed under the terms of the GNU General Public License v3 (GPL
5+
* Version 3), copied verbatim in the file "COPYING".
6+
*
7+
* See http://alice-o2.web.cern.ch/license for full licensing information.
8+
*
9+
* In applying this license CERN does not waive the privileges and immunities
10+
* granted to it by virtue of its status as an Intergovernmental Organization
11+
* or submit itself to any jurisdiction.
12+
*/
13+
14+
export const runSummary = {
15+
attributes: [
16+
'id',
17+
'runNumber',
18+
'nDetectors',
19+
'lhcBeamMode',
20+
'timeO2Start',
21+
'timeTrgEnd',
22+
'timeTrgStart',
23+
'timeO2End',
24+
'firstTfTimestamp',
25+
'lastTfTimestamp',
26+
'triggerValue',
27+
'runDuration',
28+
'definition',
29+
'calibrationStatus',
30+
'environmentId',
31+
'runQuality',
32+
'nEpns',
33+
'pdpBeamType',
34+
'nFlps',
35+
'nSubtimeframes',
36+
'bytesReadOut',
37+
'dd_flp',
38+
'dcs',
39+
'epn',
40+
'qcTimeStart',
41+
'qcTimeEnd',
42+
'epnTopology',
43+
'odcTopologyFullName',
44+
'inelasticInteractionRateAvg',
45+
'inelasticInteractionRateAtStart',
46+
'inelasticInteractionRateAtMid',
47+
'inelasticInteractionRateAtEnd',
48+
'aliceDipolePolarity',
49+
'aliceDipoleCurrent',
50+
'aliceL3Polarity',
51+
'aliceL3Current',
52+
'fillNumber',
53+
],
54+
include: [
55+
{ association: 'runType', attributes: ['name'] },
56+
{ association: 'tags', attributes: ['text', 'id'] },
57+
{
58+
association: 'detectors',
59+
attributes: ['name'],
60+
through: {
61+
attributes: ['quality'],
62+
},
63+
},
64+
{
65+
association: 'eorReasons',
66+
attributes: ['description'],
67+
include: {
68+
association: 'reasonType',
69+
},
70+
},
71+
{ association: 'lhcPeriod', attributes: ['name'] },
72+
],
73+
};

lib/usecases/run/GetAllRunsUseCase.js

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ const { DetectorType } = require('../../domain/enums/DetectorTypes.js');
2626
const { unpackNumberRange } = require('../../utilities/rangeUtils.js');
2727
const { splitStringToStringsTrimmed } = require('../../utilities/stringUtils.js');
2828
const { setTimeRangeQuery } = require('../../utilities/setTimeRangeQuery.js');
29+
const { runSummary } = require('../../server/views/runs/summary.js');
2930

3031
/**
3132
* GetAllRunsUseCase
@@ -491,18 +492,9 @@ class GetAllRunsUseCase {
491492
const { count, rows } = await RunRepository.findAndCountAll(filteringQueryBuilder);
492493

493494
const fetchQueryBuilder = new QueryBuilder();
494-
fetchQueryBuilder.include({ association: 'runType' });
495-
fetchQueryBuilder.include({ association: 'lhcFill' });
496-
fetchQueryBuilder.include({ association: 'tags' });
497-
fetchQueryBuilder.include({ association: 'detectors' });
498-
fetchQueryBuilder.include({
499-
association: 'eorReasons',
500-
include: {
501-
association: 'reasonType',
502-
attributes: ['category', 'title'],
503-
},
504-
});
505-
fetchQueryBuilder.include({ association: 'lhcPeriod' });
495+
fetchQueryBuilder.selectAttributes([...runSummary.attributes]);
496+
fetchQueryBuilder.includeAll([...runSummary.include]);
497+
506498
fetchQueryBuilder.where('id').oneOf(...rows.map(({ id }) => id));
507499
for (const property in sort) {
508500
fetchQueryBuilder.orderBy(property, sort[property]);
@@ -524,6 +516,7 @@ class GetAllRunsUseCase {
524516

525517
const qcFlagsAssociationDef = {
526518
association: 'qcFlags',
519+
attributes: ['id', 'detectorId'],
527520
required: false,
528521
separate: true,
529522
order: [['from', 'ASC']],
@@ -535,10 +528,10 @@ class GetAllRunsUseCase {
535528
)`),
536529
] },
537530
include: [
538-
{ association: 'effectivePeriods', required: true, separate: true },
539-
{ association: 'flagType' },
540-
{ association: 'detector', required: true },
541-
{ association: 'createdBy' },
531+
{ association: 'effectivePeriods', required: true, separate: true, attributes: ['from', 'to'] },
532+
{ association: 'flagType', attributes: ['name'] },
533+
{ association: 'detector', attributes: ['name'], required: true },
534+
{ association: 'createdBy', attributes: [], required: true },
542535
],
543536
};
544537

@@ -557,9 +550,9 @@ class GetAllRunsUseCase {
557550
}
558551
}
559552

560-
const runs = (await RunRepository.findAll(fetchQueryBuilder)).map(runAdapter.toEntity);
553+
const runs = await RunRepository.findAll(fetchQueryBuilder);
561554

562-
return { count, runs };
555+
return { count, runs: runs.map(runAdapter.toSummary) };
563556
}
564557
}
565558

0 commit comments

Comments
 (0)