From 042dbb13b4b1fc39dbfe8c7b541badd71be295bc Mon Sep 17 00:00:00 2001 From: Alireza Date: Fri, 16 Jul 2021 13:32:51 -0400 Subject: [PATCH 1/2] Fix: Google cloud config and tooltips (#2471) * fix: google cloud config and tooltips * fix: version number * fix: cine player commandOptions --- .../default/src/DicomWebDataSource/index.js | 4 + modes/longitudinal/src/toolbarButtons.js | 107 +++++++++++++----- package.json | 1 + .../ThumbnailTracked/ThumbnailTracked.jsx | 9 +- platform/viewer/package.json | 1 + platform/viewer/public/config/google.js | 55 +++++++-- 6 files changed, 135 insertions(+), 42 deletions(-) diff --git a/extensions/default/src/DicomWebDataSource/index.js b/extensions/default/src/DicomWebDataSource/index.js index 214f56a11..30b0a59e0 100644 --- a/extensions/default/src/DicomWebDataSource/index.js +++ b/extensions/default/src/DicomWebDataSource/index.js @@ -266,6 +266,10 @@ function createDicomWebApi(dicomWebConfig, UserAuthenticationService) { study.isLoaded = true; } + // Google Cloud Healthcare doesn't return StudyInstanceUID, so we need to add + // it manually here + seriesSummaryMetadata.forEach(aSeries => { aSeries.StudyInstanceUID = StudyInstanceUID }) + DicomMetadataStore.addSeriesMetadata(seriesSummaryMetadata, madeInClient); const numberOfSeries = seriesPromises.length; diff --git a/modes/longitudinal/src/toolbarButtons.js b/modes/longitudinal/src/toolbarButtons.js index 673235c3f..87d148707 100644 --- a/modes/longitudinal/src/toolbarButtons.js +++ b/modes/longitudinal/src/toolbarButtons.js @@ -15,14 +15,15 @@ const { windowLevelPresets } = defaults; * @param {*} icon * @param {*} label */ -function _createButton(type, id, icon, label, commandName, commandOptions) { +function _createButton(type, id, icon, label, commandName, commandOptions, tooltip) { return { id, icon, label, type, commandName, - commandOptions + commandOptions, + tooltip, }; } @@ -56,9 +57,14 @@ export default [ groupId: 'MeasurementTools', isRadio: true, // ? // Switch? - primary: _createToolButton('Length', 'tool-length', 'Length', undefined, { - toolName: 'Length', - }), + primary: _createToolButton( + 'Length', + 'tool-length', + 'Length', + undefined, + { toolName: 'Length' }, + 'Length' + ), secondary: { icon: 'chevron-down', label: '', @@ -66,22 +72,29 @@ export default [ tooltip: 'More Measure Tools', }, items: [ - _createToolButton('Length', 'tool-length', 'Length', undefined, { - toolName: 'Length', - }), + _createToolButton( + 'Length', + 'tool-length', + 'Length', + undefined, + { toolName: 'Length' }, + 'Length Tool' + ), _createToolButton( 'Bidirectional', 'tool-bidirectional', 'Bidirectional', undefined, - { toolName: 'Bidirectional' } + { toolName: 'Bidirectional' }, + 'Bidirectional Tool' ), _createToolButton( 'ArrowAnnotate', 'tool-annotate', 'Annotation', undefined, - { toolName: 'ArrowAnnotate' } + { toolName: 'ArrowAnnotate' }, + 'Arrow Annotate' ), _createToolButton( 'EllipticalRoi', @@ -90,7 +103,8 @@ export default [ undefined, { toolName: 'EllipticalRoi', - } + }, + 'Ellipse Tool' ), ], }, @@ -117,7 +131,8 @@ export default [ 'tool-window-level', 'Window Level', undefined, - { toolName: 'Wwwc' } + { toolName: 'Wwwc' }, + 'Window Level' ), secondary: { icon: 'chevron-down', @@ -172,7 +187,9 @@ export default [ 'Reset', 'tool-reset', 'Reset View', - 'resetViewport' + 'resetViewport', + undefined, + 'Reset' ), secondary: { icon: 'chevron-down', @@ -185,49 +202,81 @@ export default [ 'Reset', 'tool-reset', 'Reset View', - 'resetViewport' + 'resetViewport', + undefined, + 'Reset' ), _createActionButton( 'rotate-right', 'tool-rotate-right', 'Rotate Right', - 'rotateViewportCW' + 'rotateViewportCW', + undefined, + 'Rotate +90' ), _createActionButton( 'flip-horizontal', 'tool-flip-horizontal', 'Flip Horizontally', - 'flipViewportHorizontal' + 'flipViewportHorizontal', + undefined, + 'Flip Horizontal' ), _createToolButton( 'StackScroll', 'tool-stack-scroll', 'Stack Scroll', undefined, - { toolName: 'StackScroll' } + { toolName: 'StackScroll' }, + 'Stack Scroll' + ), + _createToolButton( + 'Magnify', + 'tool-magnify', + 'Magnify', + undefined, + { toolName: 'Magnify' }, + 'Magnify' ), - _createToolButton('Magnify', 'tool-magnify', 'Magnify', undefined, { - toolName: 'Magnify', - }), _createActionButton( 'invert', 'tool-invert', 'Invert', - 'invertViewport' + 'invertViewport', + undefined, + 'Invert Colors' + ), + _createToggleButton( + 'cine', + 'tool-cine', + 'Cine', + 'toggleCine', + undefined, + 'Cine' + ), + _createToolButton( + 'Angle', + 'tool-angle', + 'Angle', + undefined, + { toolName: 'Angle' }, + 'Angle' + ), + _createToolButton( + 'DragProbe', + 'tool-probe', + 'Probe', + undefined, + { toolName: 'DragProbe' }, + 'Probe' ), - _createToggleButton('cine', 'tool-cine', 'Cine', 'toggleCine'), - _createToolButton('Angle', 'tool-angle', 'Angle', undefined, { - toolName: 'Angle', - }), - _createToolButton('DragProbe', 'tool-probe', 'Probe', undefined, { - toolName: 'DragProbe', - }), _createToolButton( 'Rectangle', 'tool-rectangle', 'Rectangle', undefined, - { toolName: 'RectangleRoi' } + { toolName: 'RectangleRoi' }, + 'Rectangle' ), ], }, diff --git a/package.json b/package.json index 90b8c93fc..eb8e4fb57 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "cm": "npx git-cz", "build": "lerna run build:viewer --stream", "build:ci": "lerna run build:viewer:ci --stream", + "build:qa": "lerna run build:viewer:qa --stream", "build:ui:deploy-preview": "lerna run build:ui:deploy-preview --stream", "build:demo": "lerna run build:viewer:demo --stream", "dev": "lerna run dev:viewer --stream", diff --git a/platform/ui/src/components/ThumbnailTracked/ThumbnailTracked.jsx b/platform/ui/src/components/ThumbnailTracked/ThumbnailTracked.jsx index 8fbb8105d..9a056c3e2 100644 --- a/platform/ui/src/components/ThumbnailTracked/ThumbnailTracked.jsx +++ b/platform/ui/src/components/ThumbnailTracked/ThumbnailTracked.jsx @@ -70,7 +70,10 @@ const ThumbnailTracked = ({ position="right" content={
-
+
+ +
+
Series is @@ -86,9 +89,7 @@ const ThumbnailTracked = ({ )}
-
- -
+
} > diff --git a/platform/viewer/package.json b/platform/viewer/package.json index 46664fc1e..70a4ca45c 100644 --- a/platform/viewer/package.json +++ b/platform/viewer/package.json @@ -18,6 +18,7 @@ "proxy": "http://localhost:8042", "scripts": { "build:viewer": "cross-env NODE_ENV=production node --max_old_space_size=4096 ./../../node_modules/webpack/bin/webpack.js --config .webpack/webpack.pwa.js --progress", + "build:viewer:qa": "cross-env NODE_ENV=production APP_CONFIG=config/google.js node --max_old_space_size=4096 ./../../node_modules/webpack/bin/webpack.js --config .webpack/webpack.pwa.js --progress", "build:viewer:ci": "cross-env NODE_ENV=production PUBLIC_URL=/pwa/ APP_CONFIG=config/netlify.js QUICK_BUILD=true node --max_old_space_size=4096 ./../../node_modules/webpack/bin/webpack.js --config .webpack/webpack.pwa.js", "build:viewer:demo": "cross-env NODE_ENV=production APP_CONFIG=config/demo.js HTML_TEMPLATE=rollbar.html QUICK_BUILD=true node --max_old_space_size=4096 ./../../node_modules/webpack/bin/webpack.js --progress --config .webpack/webpack.pwa.js", "dev": "cross-env NODE_ENV=development webpack-dev-server --config .webpack/webpack.pwa.js --watch", diff --git a/platform/viewer/public/config/google.js b/platform/viewer/public/config/google.js index 7a4eb9d83..6de99fe2b 100644 --- a/platform/viewer/public/config/google.js +++ b/platform/viewer/public/config/google.js @@ -1,19 +1,15 @@ window.config = { routerBasename: '/', - enableGoogleCloudAdapter: true, - healthcareApiEndpoint: 'https://healthcare.googleapis.com/v1beta1', - servers: { - // This is an array, but we'll only use the first entry for now - dicomWeb: [], - }, + enableGoogleCloudAdapter: false, // This is an array, but we'll only use the first entry for now oidc: [ { // ~ REQUIRED // Authorization Server URL authority: 'https://accounts.google.com', - client_id: 'YOURCLIENTID.apps.googleusercontent.com', - redirect_uri: '/callback', // `OHIFStandaloneViewer.js` + client_id: + '723928408739-k9k9r3i44j32rhu69vlnibipmmk9i57p.apps.googleusercontent.com', + redirect_uri: '/callback', response_type: 'id_token token', scope: 'email profile openid https://www.googleapis.com/auth/cloudplatformprojects.readonly https://www.googleapis.com/auth/cloud-healthcare', // email profile openid @@ -24,5 +20,46 @@ window.config = { revokeAccessTokenOnSignout: true, }, ], - studyListFunctionsEnabled: true, + // whiteLabelling: {}, + extensions: [], + modes: [], + showStudyList: true, + // filterQueryParam: false, + dataSources: [ + { + friendlyName: 'dcmjs DICOMWeb Server', + namespace: 'org.ohif.default.dataSourcesModule.dicomweb', + sourceName: 'dicomweb', + configuration: { + name: 'GCP', + wadoUriRoot: + 'https://healthcare.googleapis.com/v1/projects/ohif-cloud-healthcare/locations/us-east4/datasets/ohif-qa-dataset/dicomStores/ohif-qa-2/dicomWeb', + qidoRoot: + 'https://healthcare.googleapis.com/v1/projects/ohif-cloud-healthcare/locations/us-east4/datasets/ohif-qa-dataset/dicomStores/ohif-qa-2/dicomWeb', + wadoRoot: + 'https://healthcare.googleapis.com/v1/projects/ohif-cloud-healthcare/locations/us-east4/datasets/ohif-qa-dataset/dicomStores/ohif-qa-2/dicomWeb', + qidoSupportsIncludeField: true, + imageRendering: 'wadors', + thumbnailRendering: 'wadors', + enableStudyLazyLoad: true, + supportsFuzzyMatching: true, + supportsWildcard: false, + }, + }, + { + friendlyName: 'dicom json', + namespace: 'org.ohif.default.dataSourcesModule.dicomjson', + sourceName: 'dicomjson', + configuration: { + name: 'json', + }, + }, + { + friendlyName: 'dicom local', + namespace: 'org.ohif.default.dataSourcesModule.dicomlocal', + sourceName: 'dicomlocal', + configuration: {}, + }, + ], + defaultDataSourceName: 'dicomweb', }; From 3dec7cfcda45271f7a2fc10a57dc575b2636137a Mon Sep 17 00:00:00 2001 From: Alireza Date: Mon, 19 Jul 2021 08:31:40 -0400 Subject: [PATCH 2/2] fix: Address various layout and prompt bugs (#2472) * fix: layout should not reset when opening a new study in studyBrowser * fix: added state to handle ignored SR series for hydration --- .../default/src/Panels/PanelStudyBrowser.jsx | 3 ++- .../Panels/requestDisplaySetCreationForStudy.js | 5 +++-- .../src/viewports/OHIFCornerstoneSRViewport.js | 2 +- .../TrackedMeasurementsContext.jsx | 1 + .../measurementTrackingMachine.js | 17 ++++++++++++++++- .../promptHydrateStructuredReport.js | 4 +++- .../PanelStudyBrowserTracking.jsx | 3 ++- .../requestDisplaySetCreationForStudy.js | 5 +++-- .../HangingProtocolService.js | 2 +- platform/ui/src/assets/svgs/logo-ohif.svg | 4 ++-- platform/viewer/src/routes/Mode/Mode.jsx | 6 ++++-- 11 files changed, 38 insertions(+), 14 deletions(-) diff --git a/extensions/default/src/Panels/PanelStudyBrowser.jsx b/extensions/default/src/Panels/PanelStudyBrowser.jsx index c5576458f..e1adb583d 100644 --- a/extensions/default/src/Panels/PanelStudyBrowser.jsx +++ b/extensions/default/src/Panels/PanelStudyBrowser.jsx @@ -175,7 +175,8 @@ function PanelStudyBrowser({ setExpandedStudyInstanceUIDs(updatedExpandedStudyInstanceUIDs); if (!shouldCollapseStudy) { - requestDisplaySetCreationForStudy(DisplaySetService, StudyInstanceUID); + const madeInClient = true + requestDisplaySetCreationForStudy(DisplaySetService, StudyInstanceUID, madeInClient); } } diff --git a/extensions/default/src/Panels/requestDisplaySetCreationForStudy.js b/extensions/default/src/Panels/requestDisplaySetCreationForStudy.js index a87184a8e..8c463c1f9 100644 --- a/extensions/default/src/Panels/requestDisplaySetCreationForStudy.js +++ b/extensions/default/src/Panels/requestDisplaySetCreationForStudy.js @@ -1,7 +1,8 @@ function requestDisplaySetCreationForStudy( dataSource, DisplaySetService, - StudyInstanceUID + StudyInstanceUID, + madeInClient, ) { // TODO: is this already short-circuited by the map of Retrieve promises? if ( @@ -12,7 +13,7 @@ function requestDisplaySetCreationForStudy( return; } - dataSource.retrieveSeriesMetadata({ StudyInstanceUID }); + dataSource.retrieveSeriesMetadata({ StudyInstanceUID, madeInClient }); } export default requestDisplaySetCreationForStudy; diff --git a/extensions/dicom-sr/src/viewports/OHIFCornerstoneSRViewport.js b/extensions/dicom-sr/src/viewports/OHIFCornerstoneSRViewport.js index 9d8d4e74d..de7c82785 100644 --- a/extensions/dicom-sr/src/viewports/OHIFCornerstoneSRViewport.js +++ b/extensions/dicom-sr/src/viewports/OHIFCornerstoneSRViewport.js @@ -377,7 +377,7 @@ function OHIFCornerstoneSRViewport({ evt.preventDefault(); }} onPillClick={() => { - sendTrackedMeasurementsEvent('PROMPT_HYDRATE_SR', { + sendTrackedMeasurementsEvent('RESTORE_PROMPT_HYDRATE_SR', { displaySetInstanceUID: displaySet.displaySetInstanceUID, viewportIndex, }); diff --git a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/TrackedMeasurementsContext.jsx b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/TrackedMeasurementsContext.jsx index 1cce041e0..b9edb4279 100644 --- a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/TrackedMeasurementsContext.jsx +++ b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/TrackedMeasurementsContext.jsx @@ -164,6 +164,7 @@ function TrackedMeasurementsContextProvider( console.log('sending event...', trackedMeasurements); sendTrackedMeasurementsEvent('PROMPT_HYDRATE_SR', { displaySetInstanceUID: displaySet.displaySetInstanceUID, + SeriesInstanceUID: displaySet.SeriesInstanceUID, viewportIndex: activeViewportIndex, }); } diff --git a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/measurementTrackingMachine.js b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/measurementTrackingMachine.js index 4c2d96776..45382e8a1 100644 --- a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/measurementTrackingMachine.js +++ b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/measurementTrackingMachine.js @@ -22,6 +22,7 @@ const machineConfiguration = { prevTrackedSeries: [], prevIgnoredSeries: [], // + ignoredSRSeriesForHydration: [], isDirty: false, }, states: { @@ -39,7 +40,11 @@ const machineConfiguration = { actions: ['setTrackedStudyAndMultipleSeries', 'setIsDirtyToClean'], }, ], - PROMPT_HYDRATE_SR: 'promptHydrateStructuredReport', + PROMPT_HYDRATE_SR: { + target: 'promptHydrateStructuredReport', + cond: 'hasNotIgnoredSRSeriesForHydration', + }, + RESTORE_PROMPT_HYDRATE_SR: 'promptHydrateStructuredReport' }, }, promptBeginTracking: { @@ -218,6 +223,8 @@ const machineConfiguration = { }, { target: 'idle', + actions: ['ignoreHydrationForSRSeries'], + cond: 'shouldIgnoreHydrationForSR' }, ], onError: { @@ -300,6 +307,9 @@ const defaultOptions = { prevIgnoredSeries: [...ctx.ignoredSeries], ignoredSeries: [...ctx.ignoredSeries, evt.data.SeriesInstanceUID], })), + ignoreHydrationForSRSeries: assign((ctx, evt) => ({ + ignoredSRSeriesForHydration: [...ctx.ignoredSRSeriesForHydration, evt.data.srSeriesInstanceUID], + })), addTrackedSeries: assign((ctx, evt) => ({ prevTrackedSeries: [...ctx.trackedSeries], trackedSeries: [...ctx.trackedSeries, evt.data.SeriesInstanceUID], @@ -348,6 +358,8 @@ const defaultOptions = { evt.data && evt.data.userResponse === RESPONSE.NO_NOT_FOR_SERIES, shouldPromptSaveReport: (ctx, evt) => evt.data && evt.data.userResponse === RESPONSE.CREATE_REPORT, + shouldIgnoreHydrationForSR: (ctx, evt) => + evt.data && evt.data.userResponse === RESPONSE.CANCEL, shouldSaveAndContinueWithSameReport: (ctx, evt) => evt.data && evt.data.userResponse === RESPONSE.CREATE_REPORT && @@ -363,6 +375,9 @@ const defaultOptions = { hasRemainingTrackedSeries: (ctx, evt) => ctx.trackedSeries.length > 1 || !ctx.trackedSeries.includes(evt.SeriesInstanceUID), + hasNotIgnoredSRSeriesForHydration: (ctx, evt) => { + return !ctx.ignoredSRSeriesForHydration.includes(evt.SeriesInstanceUID) + }, isNewStudy: (ctx, evt) => !ctx.ignoredSeries.includes(evt.SeriesInstanceUID) && ctx.trackedStudy !== evt.StudyInstanceUID, diff --git a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptHydrateStructuredReport.js b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptHydrateStructuredReport.js index 4d017cf10..f377b3752 100644 --- a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptHydrateStructuredReport.js +++ b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptHydrateStructuredReport.js @@ -11,8 +11,9 @@ const RESPONSE = { }; function promptUser({ servicesManager, extensionManager }, ctx, evt) { - const { UIViewportDialogService } = servicesManager.services; + const { UIViewportDialogService, DisplaySetService } = servicesManager.services; const { viewportIndex, displaySetInstanceUID } = evt; + const srDisplaySet = DisplaySetService.getDisplaySetByUID(displaySetInstanceUID) return new Promise(async function(resolve, reject) { const promptResult = await _askTrackMeasurements( @@ -37,6 +38,7 @@ function promptUser({ servicesManager, extensionManager }, ctx, evt) { resolve({ userResponse: promptResult, displaySetInstanceUID: evt.displaySetInstanceUID, + srSeriesInstanceUID: srDisplaySet.SeriesInstanceUID, viewportIndex, StudyInstanceUID, SeriesInstanceUIDs, diff --git a/extensions/measurement-tracking/src/panels/PanelStudyBrowserTracking/PanelStudyBrowserTracking.jsx b/extensions/measurement-tracking/src/panels/PanelStudyBrowserTracking/PanelStudyBrowserTracking.jsx index 8b064d303..03f3e84e0 100644 --- a/extensions/measurement-tracking/src/panels/PanelStudyBrowserTracking/PanelStudyBrowserTracking.jsx +++ b/extensions/measurement-tracking/src/panels/PanelStudyBrowserTracking/PanelStudyBrowserTracking.jsx @@ -260,7 +260,8 @@ function PanelStudyBrowserTracking({ setExpandedStudyInstanceUIDs(updatedExpandedStudyInstanceUIDs); if (!shouldCollapseStudy) { - requestDisplaySetCreationForStudy(DisplaySetService, StudyInstanceUID); + const madeInClient = true + requestDisplaySetCreationForStudy(DisplaySetService, StudyInstanceUID, madeInClient); } } diff --git a/extensions/measurement-tracking/src/panels/PanelStudyBrowserTracking/requestDisplaySetCreationForStudy.js b/extensions/measurement-tracking/src/panels/PanelStudyBrowserTracking/requestDisplaySetCreationForStudy.js index 86e63213d..f6ff12b45 100644 --- a/extensions/measurement-tracking/src/panels/PanelStudyBrowserTracking/requestDisplaySetCreationForStudy.js +++ b/extensions/measurement-tracking/src/panels/PanelStudyBrowserTracking/requestDisplaySetCreationForStudy.js @@ -1,7 +1,8 @@ function requestDisplaySetCreationForStudy( dataSource, DisplaySetService, - StudyInstanceUID + StudyInstanceUID, + madeInClient, ) { if ( DisplaySetService.activeDisplaySets.some( @@ -11,7 +12,7 @@ function requestDisplaySetCreationForStudy( return; } - dataSource.retrieveSeriesMetadata({ StudyInstanceUID }); + dataSource.retrieveSeriesMetadata({ StudyInstanceUID, madeInClient }); } export default requestDisplaySetCreationForStudy; diff --git a/platform/core/src/services/HangingProtocolService/HangingProtocolService.js b/platform/core/src/services/HangingProtocolService/HangingProtocolService.js index fd976698b..d00dcb15e 100644 --- a/platform/core/src/services/HangingProtocolService/HangingProtocolService.js +++ b/platform/core/src/services/HangingProtocolService/HangingProtocolService.js @@ -71,7 +71,7 @@ class HangingProtocolService { this.customAttributeRetrievalCallbacks ); - // if there is no pre-defiend protocol + // if there is no pre-defined protocol if (!protocol || protocol.id === undefined) { const matchedProtocol = this.ProtocolEngine.run(metaData); this._setProtocol(matchedProtocol); diff --git a/platform/ui/src/assets/svgs/logo-ohif.svg b/platform/ui/src/assets/svgs/logo-ohif.svg index 2a83a2ada..e828d9b97 100644 --- a/platform/ui/src/assets/svgs/logo-ohif.svg +++ b/platform/ui/src/assets/svgs/logo-ohif.svg @@ -1,7 +1,7 @@ - Artboard - + Open Health Imaging Foundation + diff --git a/platform/viewer/src/routes/Mode/Mode.jsx b/platform/viewer/src/routes/Mode/Mode.jsx index 2dc4ff9b3..939650b90 100644 --- a/platform/viewer/src/routes/Mode/Mode.jsx +++ b/platform/viewer/src/routes/Mode/Mode.jsx @@ -39,9 +39,11 @@ async function defaultRouteInit({ const { unsubscribe: seriesAddedUnsubscribe } = DicomMetadataStore.subscribe( DicomMetadataStore.EVENTS.SERIES_ADDED, - ({ StudyInstanceUID }) => { + ({ StudyInstanceUID, madeInClient }) => { const studyMetadata = DicomMetadataStore.getStudy(StudyInstanceUID); - HangingProtocolService.run(studyMetadata); + if (!madeInClient) { + HangingProtocolService.run(studyMetadata); + } } ); unsubscriptions.push(seriesAddedUnsubscribe);