Skip to content
Merged
29 changes: 29 additions & 0 deletions lib/public/utilities/filterOutLegacyDetectorsForNewerPeriods.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* @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.
*/

const LEGACY_DETECTOR_NAMES_FOR_AFTER_25 = ['CPV', 'PHS'];

/**
* Remove legacy detectors for newer LHC periods/passes (after LHC25) from the list of detectors.
*
* @param {Detector[]} detectors detectors to filter
* @param {string} [label=''] name of the period or data pass
* @return {Detector[]} filtered detectors
*/
const filterOutLegacyDetectorsForNewerPeriods = (detectors = [], label = '') => {
const shouldFilterOutLegacyDetectors = /LHC(2[5-9]|[3-9]\d)/.test(label ?? '');

return detectors.filter(({ name }) => !shouldFilterOutLegacyDetectors || !LEGACY_DETECTOR_NAMES_FOR_AFTER_25.includes(name));
};

export { filterOutLegacyDetectorsForNewerPeriods };
52 changes: 50 additions & 2 deletions lib/public/views/Runs/Overview/RunsWithQcModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import { DetectorType } from '../../../domain/enums/DetectorTypes.js';
import { mergeRemoteData } from '../../../utilities/mergeRemoteData.js';
import { ToggleFilterModel } from '../../../components/Filters/common/filters/ToggleFilterModel.js';
import { MultiCompositionFilterModel } from '../../../components/Filters/RunsFilter/MultiCompositionFilterModel.js';
import { rctDetectorsProvider } from '../../../services/detectors/detectorsProvider.js';

/**
* Merge QC summaries
Expand Down Expand Up @@ -133,6 +134,48 @@ export class RunsWithQcModel extends RunsOverviewModel {
super.load();
}

/**
* Build and register a detectors observable with optional filtering logic.
*
* @param {ObservableData|ObservableData[]} [sourceOrSources=rctDetectorsProvider.qc$] detector source(s)
* @param {function} [filterDetectors=(detectors) => detectors] callback used to filter detectors on success
* @return {ObservableData<RemoteData<Detector[]>>} detector observable
*/
_setDetectorsObservable(sourceOrSources = rctDetectorsProvider.qc$, filterDetectors = (detectors) => detectors) {
this._detectors$ = this._buildDetectorsObservable(sourceOrSources, filterDetectors);
this._detectors$.bubbleTo(this);
return this._detectors$;
}

/**
* Create a detectors observable from one or multiple sources.
*
* @param {ObservableData|ObservableData[]} sourceOrSources detector source(s)
* @param {function} filterDetectors callback used to filter detectors on success
* @return {ObservableData<RemoteData<Detector[]>>} detector observable
*/
_buildDetectorsObservable(sourceOrSources, filterDetectors) {
const builder = ObservableData.builder();

if (Array.isArray(sourceOrSources)) {
builder.sources(sourceOrSources);
} else {
builder.source(sourceOrSources);
}

return builder
.apply((remoteDataList) => {
const mergedRemoteData = Array.isArray(remoteDataList)
? mergeRemoteData(remoteDataList)
: remoteDataList;

return mergedRemoteData.apply({
Success: (payload) => filterDetectors(payload),
});
})
.build();
}

/**
* Register not-bad fraction detectors filtering model and update it when detectors are loaded
* Also, trigger an immediate update if detectors are already loaded at the moment of registration
Expand Down Expand Up @@ -216,12 +259,17 @@ export class RunsWithQcModel extends RunsOverviewModel {
}

/**
* Return detectors which a model uses
* Return detectors which a model uses.
*
* @returns {RemoteData<Detector[]>} remote data list of detectors
*/
get detectors() {
throw Error('Method not implemented');
if (!this._detectors$) {
this._detectors$ = new ObservableData(RemoteData.notAsked());
this._detectors$.bubbleTo(this);
}

return this._detectors$.getCurrent();
}
Comment thread
graduta marked this conversation as resolved.

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ import { jsonPatch } from '../../../utilities/fetch/jsonPatch.js';
import { jsonPut } from '../../../utilities/fetch/jsonPut.js';
import { SkimmingStage } from '../../../domain/enums/SkimmingStage.js';
import { jsonFetch } from '../../../utilities/fetch/jsonFetch.js';
import { mergeRemoteData } from '../../../utilities/mergeRemoteData.js';
import { RemoteDataSource } from '../../../utilities/fetch/RemoteDataSource.js';
import { DetectorType } from '../../../domain/enums/DetectorTypes.js';
import { GaqFilterModel } from '../../../components/Filters/RunsFilter/GaqFilterModel.js';
import { filterOutLegacyDetectorsForNewerPeriods } from '../../../utilities/filterOutLegacyDetectorsForNewerPeriods.js';

const ALL_CPASS_PRODUCTIONS_REGEX = /cpass\d+/;
const DETECTOR_NAMES_NOT_IN_CPASSES = ['EVS'];
Expand All @@ -42,19 +42,18 @@ export class RunsPerDataPassOverviewModel extends FixedPdpBeamTypeRunsOverviewMo
this._dataPass$ = new ObservableData(RemoteData.notAsked());
this._dataPass$.bubbleTo(this);

this._detectors$ = ObservableData
.builder()
.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))
: detectors,
}))
.build();

this._filteringModel.put('gaq', new GaqFilterModel(this._mcReproducibleAsNotBad));

this._detectors$.bubbleTo(this);
this._setDetectorsObservable(
[rctDetectorsProvider.qc$, this._dataPass$],
([detectors, dataPass]) => {
const filteredDetectors = filterOutLegacyDetectorsForNewerPeriods(detectors, dataPass.name);

return ALL_CPASS_PRODUCTIONS_REGEX.test(dataPass.name)
? filteredDetectors.filter(({ name, type }) => type !== DetectorType.AOT_GLO || DETECTOR_NAMES_NOT_IN_CPASSES.includes(name))
: filteredDetectors;
},
);

this._markAsSkimmableRequestResult$ = new ObservableData(RemoteData.notAsked());
this._markAsSkimmableRequestResult$.bubbleTo(this);
Expand Down Expand Up @@ -285,14 +284,6 @@ export class RunsPerDataPassOverviewModel extends FixedPdpBeamTypeRunsOverviewMo
return this._dataPass$.getCurrent();
}

/**
* Get all detectors
* @return {RemoteData<DplDetector[]>} detectors
*/
get detectors() {
return this._detectors$.getCurrent();
}

/**
* GAQ summary getter
* @return {RemoteData<GaqSummary>} GAQ summary
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { jsonFetch } from '../../../utilities/fetch/jsonFetch.js';
import { DetectorType } from '../../../domain/enums/DetectorTypes.js';
import { ObservableData } from '../../../utilities/ObservableData.js';
import { FixedPdpBeamTypeRunsOverviewModel } from '../Overview/FixedPdpBeamTypeRunsOverviewModel.js';
import { filterOutLegacyDetectorsForNewerPeriods } from '../../../utilities/filterOutLegacyDetectorsForNewerPeriods.js';

/**
* Runs Per LHC Period overview model
Expand All @@ -33,16 +34,15 @@ export class RunsPerLhcPeriodOverviewModel extends FixedPdpBeamTypeRunsOverviewM
this._lhcPeriodId = null;
this._lhcPeriodStatistics$ = new ObservableData(RemoteData.notAsked());

this._syncDetectors$ = ObservableData
.builder()
.source(rctDetectorsProvider.qc$)
.apply((remoteDetectors) =>
remoteDetectors.apply({
Success: (detectors) => detectors.filter(({ type }) => [DetectorType.PHYSICAL, DetectorType.MUON_GLO].includes(type)),
}))
.build();
this._syncDetectors$ = this._setDetectorsObservable(
[rctDetectorsProvider.qc$, this._lhcPeriodStatistics$],
([detectors, lhcPeriodStatistics]) => {
const filteredDetectors = filterOutLegacyDetectorsForNewerPeriods(detectors, lhcPeriodStatistics.lhcPeriod.name);

this._syncDetectors$.bubbleTo(this);
return filteredDetectors.filter(({ type }) => [DetectorType.PHYSICAL, DetectorType.MUON_GLO].includes(type));
},
);
this._detectors$ = this._syncDetectors$;
this._lhcPeriodStatistics$.bubbleTo(this);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@
import { buildUrl, RemoteData } from '/js/src/index.js';
import { ObservableData } from '../../../utilities/ObservableData.js';
import { getRemoteData } from '../../../utilities/fetch/getRemoteData.js';
import { rctDetectorsProvider } from '../../../services/detectors/detectorsProvider.js';
import { FixedPdpBeamTypeRunsOverviewModel } from '../Overview/FixedPdpBeamTypeRunsOverviewModel.js';
import { rctDetectorsProvider } from '../../../services/detectors/detectorsProvider.js';
import { filterOutLegacyDetectorsForNewerPeriods } from '../../../utilities/filterOutLegacyDetectorsForNewerPeriods.js';

/**
* Runs Per Simulation Pass overview model
Expand All @@ -30,10 +31,11 @@ export class RunsPerSimulationPassOverviewModel extends FixedPdpBeamTypeRunsOver

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

this._detectors$ = rctDetectorsProvider.qc$;

this._detectors$.bubbleTo(this);
this._simulationPass$.bubbleTo(this);
this._detectors$ = this._setDetectorsObservable(
[rctDetectorsProvider.qc$, this._simulationPass$],
([detectors, simulationPass]) => filterOutLegacyDetectorsForNewerPeriods(detectors, simulationPass.name),
);
}

/**
Expand Down Expand Up @@ -106,14 +108,6 @@ export class RunsPerSimulationPassOverviewModel extends FixedPdpBeamTypeRunsOver
return this._simulationPass$.getCurrent();
}

/**
* Get all detectors
* @return {RemoteData<DplDetector[]>} detectors
*/
get detectors() {
return this._detectors$.getCurrent();
}

/**
* @inheritdoc
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* @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.
*/

const { expect } = require('chai');

module.exports = () => {
it('should filter legacy detectors for newer periods', async () => {
const { filterOutLegacyDetectorsForNewerPeriods } = await import('../../../../lib/public/utilities/filterOutLegacyDetectorsForNewerPeriods.js');
const detectors = [{ name: 'CPV' }, { name: 'PHS' }, { name: 'ITS' }];

expect(filterOutLegacyDetectorsForNewerPeriods(detectors, 'LHC25ab')).to.deep.equal([{ name: 'ITS' }]);
expect(filterOutLegacyDetectorsForNewerPeriods(detectors, 'LHC26ad_cpass1_residuals')).to.deep.equal([{ name: 'ITS' }]);
expect(filterOutLegacyDetectorsForNewerPeriods(detectors, 'LHC24')).to.deep.equal(detectors);
expect(filterOutLegacyDetectorsForNewerPeriods(detectors, '')).to.deep.equal(detectors);
});
};
2 changes: 2 additions & 0 deletions test/lib/public/utilities/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
*/

const FormattingSuite = require('./formatting/index.js');
const FilterOutLegacyDetectorsForNewerPeriodsSuite = require('./filterOutLegacyDetectorsForNewerPeriods.test.js');

module.exports = () => {
describe('FormattingSuite', FormattingSuite);
describe('FilterOutLegacyDetectorsForNewerPeriods', FilterOutLegacyDetectorsForNewerPeriodsSuite);
};
1 change: 1 addition & 0 deletions test/lib/utilities/stringUtils.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,5 @@ module.exports = () => {
expect(snakeToPascal('_THIS_IS_SNAKE_CASE_')).to.equal('ThisIsSnakeCase');
expect(snakeToPascal('SNAKE')).to.equal('Snake');
});

};
20 changes: 8 additions & 12 deletions test/public/runs/overview.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,7 @@ module.exports = () => {
// Override the amount of runs visible per page manually
await navigateToRunsOverview(page);
await page.evaluate(() => {
// eslint-disable-next-line no-undef
model.runs.overviewModel.pagination.itemsPerPage = 1;
window.model.runs.overviewModel.pagination.itemsPerPage = 1;
});
await waitForTableLength(page, 1);

Expand All @@ -237,8 +236,9 @@ module.exports = () => {

it('notifies if table loading returned an error', async () => {
await navigateToRunsOverview(page);
// eslint-disable-next-line no-return-assign, no-undef
await page.evaluate(() => model.runs.overviewModel.pagination.itemsPerPage = 200);
await page.waitForFunction(() => window.model?.runs?.overviewModel?.pagination);
// eslint-disable-next-line no-return-assign
await page.evaluate(() => window.model.runs.overviewModel.pagination.itemsPerPage = 200);
await page.waitForSelector('.alert-danger');

// We expect there to be a fitting error message
Expand All @@ -247,8 +247,7 @@ module.exports = () => {

// Revert changes for next test
await page.evaluate(() => {
// eslint-disable-next-line no-undef
model.runs.overviewModel.pagination.itemsPerPage = 10;
window.model.runs.overviewModel.pagination.itemsPerPage = 10;
});
await waitForTableLength(page, 10);
});
Expand Down Expand Up @@ -436,8 +435,7 @@ module.exports = () => {
};

await page.evaluate(() => {
// eslint-disable-next-line no-undef
model.runs.overviewModel.pagination.itemsPerPage = 20;
window.model.runs.overviewModel.pagination.itemsPerPage = 20;
});

await pressElement(page, physicsFilterSelector, true);
Expand Down Expand Up @@ -473,8 +471,7 @@ module.exports = () => {
await pressElement(page, cosmicsFilterSelector, true);

await page.evaluate(() => {
// eslint-disable-next-line no-undef
model.runs.overviewModel.pagination.itemsPerPage = 20;
window.model.runs.overviewModel.pagination.itemsPerPage = 20;
});

await checkTableSizeAndDefinition(
Expand Down Expand Up @@ -597,8 +594,7 @@ module.exports = () => {
const ltuFilterSelector = `${filterInputSelectorPrefix}LTU`;

await page.evaluate(() => {
// eslint-disable-next-line no-undef
model.runs.overviewModel.pagination.itemsPerPage = 10;
window.model.runs.overviewModel.pagination.itemsPerPage = 10;
});
await waitForTableLength(page, 10);

Expand Down
17 changes: 7 additions & 10 deletions test/public/runs/runsPerDataPass.overview.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -306,17 +306,16 @@ module.exports = () => {
});
await page.waitForSelector(`${amountSelectorId} input:invalid`);
await page.evaluate(() => {
// eslint-disable-next-line no-return-assign, no-undef
model.runs.perDataPassOverviewModel.pagination.reset();
// eslint-disable-next-line no-return-assign, no-undef
model.runs.perDataPassOverviewModel.notify();
window.model.runs.perDataPassOverviewModel.pagination.reset();
window.model.runs.perDataPassOverviewModel.notify();
});
});

it('notifies if table loading returned an error', async () => {
await navigateToRunsPerDataPass(page, 1, 3, 4);
// eslint-disable-next-line no-return-assign, no-undef
await page.evaluate(() => model.runs.perDataPassOverviewModel.pagination.itemsPerPage = 200);
await page.waitForFunction(() => window.model?.runs?.perDataPassOverviewModel?.pagination);
// eslint-disable-next-line no-return-assign
await page.evaluate(() => window.model.runs.perDataPassOverviewModel.pagination.itemsPerPage = 200);
await page.waitForSelector('.alert-danger');

// We expect there to be a fitting error message
Expand All @@ -325,10 +324,8 @@ module.exports = () => {

// Revert changes for next test
await page.evaluate(() => {
// eslint-disable-next-line no-undef
model.runs.perDataPassOverviewModel.pagination.reset();
// eslint-disable-next-line no-undef
model.runs.perDataPassOverviewModel.notify();
window.model.runs.perDataPassOverviewModel.pagination.reset();
window.model.runs.perDataPassOverviewModel.notify();
});
await waitForTableLength(page, 4);
});
Expand Down
Loading