Skip to content
Merged
43 changes: 43 additions & 0 deletions lib/public/domain/enums/DetectorOrders.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* @license
* Copyright CERN and copyright holders of ALICE O2. This software is
* distributed under the terms of the GNU General Public License v3 (GPL
* Version 3), copied verbatim in the file "COPYING".
*
* See http://alice-o2.web.cern.ch/license for full licensing information.
*
* In applying this license CERN does not waive the privileges and immunities
* granted to it by virtue of its status as an Intergovernmental Organization
* or submit itself to any jurisdiction.
*/

import { DetectorType } from './DetectorTypes.js';

/**
* Defines priority mappings for detector types.
* Each key is a mapping between {@link DetectorType} values and their numeric priority
* (larger values will appear first - see detectorsProvider LN88).
*
* - **DEFAULT**: Standard ordering used across most views.
* - **RCT**: Ordering used in the Run Condition Table, which prioritizes PHYSICAL detectors.
*/
export const DetectorOrders = Object.freeze({
DEFAULT: {
[DetectorType.OTHER]: 0,
[DetectorType.VIRTUAL]: 1,
[DetectorType.PHYSICAL]: 2,
[DetectorType.AOT_GLO]: 3,
[DetectorType.AOT_EVENT]: 4,
[DetectorType.MUON_GLO]: 5,
[DetectorType.QC_ONLY]: 6,
},
RCT: {
[DetectorType.OTHER]: 0,
[DetectorType.AOT_GLO]: 1,
[DetectorType.AOT_EVENT]: 2,
[DetectorType.MUON_GLO]: 3,
[DetectorType.VIRTUAL]: 4,
[DetectorType.PHYSICAL]: 5,
[DetectorType.QC_ONLY]: 6,
},
});
18 changes: 8 additions & 10 deletions lib/public/services/detectors/detectorsProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { switchCase } from '/js/src/index.js';
import { getRemoteData } from '../../utilities/fetch/getRemoteData.js';
import { ObservableData } from '../../utilities/ObservableData.js';
import { DetectorType, DATA_TAKING_DETECTOR_TYPES, QC_DETECTORS } from '../../domain/enums/DetectorTypes.js';
import { DetectorOrders } from '../../domain/enums/DetectorOrders.js';

import { NonPhysicalDetector } from '../../domain/enums/detectorsNames.mjs';

Expand Down Expand Up @@ -44,9 +45,12 @@ const getQcDetectorsFromAllDetectors = (allDetectors) => allDetectors
export class DetectorsProvider extends RemoteDataProvider {
/**
* Constructor
*
* @param {DetectorOrders} detectorOrder the order to base sorting on, default is DetectorOrders.DEFAULT
*/
constructor() {
constructor(detectorOrder = DetectorOrders.DEFAULT) {
super();
this._detectorOrder = detectorOrder;
this._physical$ = ObservableData.builder()
.source(this._items$)
.apply((remoteDetectors) => remoteDetectors.apply({
Expand Down Expand Up @@ -74,21 +78,14 @@ export class DetectorsProvider extends RemoteDataProvider {
*/
async getRemoteData() {
const { data: detectors } = await getRemoteData('/api/detectors');
const typeToOrderingKey = (type) => switchCase(type, {
[DetectorType.OTHER]: 0,
[DetectorType.VIRTUAL]: 1,
[DetectorType.PHYSICAL]: 2,
[DetectorType.AOT_GLO]: 3,
[DetectorType.AOT_EVENT]: 4,
[DetectorType.MUON_GLO]: 5,
[DetectorType.QC_ONLY]: 6,
});
const typeToOrderingKey = (type) => switchCase(type, this._detectorOrder);

const orderingKey = (detector1, detector2) => {
const specialPair = ['ZDC', 'TST'];
if (specialPair.includes(detector1.name) && specialPair.includes(detector2.name)) {
return detector1.name === 'ZDC' ? 1 : -1;
}
// Note the negative sign to have larger priority types appear first
return -(typeToOrderingKey(detector1.type) - typeToOrderingKey(detector2.type)) * 10 + detector1.name.localeCompare(detector2.name);
};

Expand Down Expand Up @@ -161,3 +158,4 @@ export class DetectorsProvider extends RemoteDataProvider {
}

export const detectorsProvider = new DetectorsProvider();
export const rctDetectorsProvider = new DetectorsProvider(DetectorOrders.RCT);
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { buildUrl, RemoteData } from '/js/src/index.js';
import { ObservableData } from '../../../utilities/ObservableData.js';
import { getRemoteDataSlice } from '../../../utilities/fetch/getRemoteDataSlice.js';
import { getRemoteData } from '../../../utilities/fetch/getRemoteData.js';
import { detectorsProvider } from '../../../services/detectors/detectorsProvider.js';
import { rctDetectorsProvider } from '../../../services/detectors/detectorsProvider.js';
import { FixedPdpBeamTypeRunsOverviewModel } from '../Overview/FixedPdpBeamTypeRunsOverviewModel.js';
import { jsonPatch } from '../../../utilities/fetch/jsonPatch.js';
import { jsonPut } from '../../../utilities/fetch/jsonPut.js';
Expand Down Expand Up @@ -43,7 +43,7 @@ export class RunsPerDataPassOverviewModel extends FixedPdpBeamTypeRunsOverviewMo

this._detectors$ = ObservableData
.builder()
.sources([detectorsProvider.qc$, this._dataPass$])
.sources([rctDetectorsProvider.qc$, this._dataPass$])
.apply((remoteDataList) => mergeRemoteData(remoteDataList)
.apply({ Success: ([detectors, dataPass]) => ALL_CPASS_PRODUCTIONS_REGEX.test(dataPass.name)
? detectors.filter(({ name, type }) => type !== DetectorType.AOT_GLO || DETECTOR_NAMES_NOT_IN_CPASSES.includes(name))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
*/
import { buildUrl, RemoteData } from '/js/src/index.js';
import { TabbedPanelModel } from '../../../components/TabbedPanel/TabbedPanelModel.js';
import { detectorsProvider } from '../../../services/detectors/detectorsProvider.js';
import { rctDetectorsProvider } from '../../../services/detectors/detectorsProvider.js';
import { jsonFetch } from '../../../utilities/fetch/jsonFetch.js';
import { DetectorType } from '../../../domain/enums/DetectorTypes.js';
import { ObservableData } from '../../../utilities/ObservableData.js';
Expand All @@ -38,11 +38,11 @@ export class RunsPerLhcPeriodOverviewModel extends FixedPdpBeamTypeRunsOverviewM
this._lhcPeriodId = null;
this._lhcPeriodStatistics$ = new ObservableData(RemoteData.notAsked());

this._onlineDetectors$ = detectorsProvider.physical$;
this._onlineDetectors$ = rctDetectorsProvider.physical$;

this._syncDetectors$ = ObservableData
.builder()
.source(detectorsProvider.qc$)
.source(rctDetectorsProvider.qc$)
.apply((remoteDetectors) =>
remoteDetectors.apply({
Success: (detectors) => detectors.filter(({ type }) => [DetectorType.PHYSICAL, DetectorType.MUON_GLO].includes(type)),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import { buildUrl, RemoteData } from '/js/src/index.js';
import { ObservableData } from '../../../utilities/ObservableData.js';
import { getRemoteData } from '../../../utilities/fetch/getRemoteData.js';
import { detectorsProvider } from '../../../services/detectors/detectorsProvider.js';
import { rctDetectorsProvider } from '../../../services/detectors/detectorsProvider.js';
import { FixedPdpBeamTypeRunsOverviewModel } from '../Overview/FixedPdpBeamTypeRunsOverviewModel.js';

/**
Expand All @@ -29,7 +29,7 @@ export class RunsPerSimulationPassOverviewModel extends FixedPdpBeamTypeRunsOver

this._simulationPass$ = new ObservableData(RemoteData.notAsked());

this._detectors$ = detectorsProvider.qc$;
this._detectors$ = rctDetectorsProvider.qc$;

this.registerObervablesQcSummaryDependesOn([this._detectors$]);
this.registerDetectorsNotBadFractionFilterModels(this._detectors$);
Expand Down
17 changes: 14 additions & 3 deletions test/public/runs/runsPerDataPass.overview.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,17 @@ module.exports = () => {
.to.be.equal('Missing 3 verifications');
});

it('should display detector columns in RCT order (AOT/MUON after physical)', async () => {
const headers = await page.$$eval(
'table thead th',
(ths) => ths.map((th) => th.id).filter(Boolean),
);

// See DetectorOrders.RCT in detectorOrders.js
expect(headers.indexOf('VTX')).to.be.greaterThan(headers.indexOf('ZDC'));
expect(headers.indexOf('MUD')).to.be.greaterThan(headers.indexOf('ZDC'));
});

it('should ignore QC flags created by services in QC summaries of AOT and MUON ', async () => {
await navigateToRunsPerDataPass(page, 2, 1, 3); // apass
await expectInnerText(page, '#row106-VTX-text', '100');
Expand Down Expand Up @@ -394,10 +405,10 @@ module.exports = () => {
const exportContent = fs.readFileSync(path.resolve(downloadPath, targetFileName)).toString();

expect(exportContent.trim()).to.be.eql([
'runNumber;VTX;CPV',
'runNumber;CPV;VTX',
'108;"";""',
'107;"";"Good (from: 1565290800000 to: 1565359260000) | Limited Acceptance MC Reproducible (from: 1565269140000 to: 1565290800000)"',
'106;"Good (from: 1565269200000 to: 1565304200000) | Good (from: 1565324200000 to: 1565359200000)";"Limited Acceptance MC Reproducible (from: 1565304200000 to: 1565324200000) | Limited acceptance (from: 1565329200000 to: 1565334200000) | Bad (from: 1565339200000 to: 1565344200000)"',
'107;"Good (from: 1565290800000 to: 1565359260000) | Limited Acceptance MC Reproducible (from: 1565269140000 to: 1565290800000)";""',
'106;"Limited Acceptance MC Reproducible (from: 1565304200000 to: 1565324200000) | Limited acceptance (from: 1565329200000 to: 1565334200000) | Bad (from: 1565339200000 to: 1565344200000)";"Good (from: 1565269200000 to: 1565304200000) | Good (from: 1565324200000 to: 1565359200000)"',
].join('\r\n'));
fs.unlinkSync(path.resolve(downloadPath, targetFileName));
});
Expand Down
11 changes: 11 additions & 0 deletions test/public/runs/runsPerLhcPeriod.overview.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,17 @@ module.exports = () => {
await expectInnerText(page, '#row56-FT0', '83');
});

it('should display detector columns in RCT order (AOT/MUON after physical) for synchronous flags', async () => {
// Note test starts already on synchronous flags tab
const headers = await page.$$eval(
'table thead th',
(ths) => ths.map((th) => th.id).filter(Boolean),
);

// See DetectorOrders.RCT in detectorOrders.js
expect(headers.indexOf('MUD')).to.be.greaterThan(headers.indexOf('ZDC'));
});

it('should successfully sort by runNumber in ascending and descending manners', async () => {
await testTableSortingByColumn(page, 'runNumber');
});
Expand Down
11 changes: 11 additions & 0 deletions test/public/runs/runsPerSimulationPass.overview.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,17 @@ module.exports = () => {
await qcFlagService.delete(tmpQcFlag.id);
});

it('should display detector columns in RCT order (AOT/MUON after physical)', async () => {
const headers = await page.$$eval(
'table thead th',
(ths) => ths.map((th) => th.id).filter(Boolean),
);

// See DetectorOrders.RCT in detectorOrders.js
expect(headers.indexOf('VTX')).to.be.greaterThan(headers.indexOf('ZDC'));
expect(headers.indexOf('MUD')).to.be.greaterThan(headers.indexOf('ZDC'));
});

it('should successfully sort by runNumber in ascending and descending manners', async () => {
await testTableSortingByColumn(page, 'runNumber');
});
Expand Down
Loading