/******************************************************************************* * Copyright (c) 2016 Weasis Team and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Nicolas Roduit - initial API and implementation *******************************************************************************/ package org.weasis.dicom.explorer; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; import org.dcm4che3.data.Attributes; import org.dcm4che3.data.Tag; import org.slf4j.LoggerFactory; import org.weasis.core.api.explorer.ObservableEvent; import org.weasis.core.api.explorer.model.DataExplorerModel; import org.weasis.core.api.gui.util.GuiExecutor; import org.weasis.core.api.media.data.MediaElement; import org.weasis.core.api.media.data.MediaSeries; import org.weasis.core.api.media.data.MediaSeriesGroup; import org.weasis.core.api.media.data.MediaSeriesGroupNode; import org.weasis.core.api.media.data.Series; import org.weasis.core.api.media.data.SeriesThumbnail; import org.weasis.core.api.media.data.TagW; import org.weasis.core.api.media.data.Thumbnail; import org.weasis.core.ui.docking.UIManager; import org.weasis.core.ui.editor.SeriesViewerFactory; import org.weasis.core.ui.editor.ViewerPluginBuilder; import org.weasis.dicom.codec.DicomMediaIO; import org.weasis.dicom.codec.DicomSpecialElement; import org.weasis.dicom.codec.TagD; import org.weasis.dicom.codec.TagD.Level; /** * @note This class is a pure copy of LoadLocalDicom taking care only of the DicomObject and not the file * * @version $Rev$ $Date$ */ public class LoadDicomObjects extends ExplorerTask<Boolean, String> { private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(LoadDicomObjects.class); private final Attributes[] dicomObjectsToLoad; private final DicomModel dicomModel; private boolean openPlugin = true; public LoadDicomObjects(DataExplorerModel explorerModel, Attributes... dcmObjects) { super(Messages.getString("DicomExplorer.loading"), false); //$NON-NLS-1$ if (dcmObjects == null || dcmObjects.length < 1 || !(explorerModel instanceof DicomModel)) { throw new IllegalArgumentException("invalid parameters"); //$NON-NLS-1$ } this.dicomModel = (DicomModel) explorerModel; this.dicomObjectsToLoad = dcmObjects; } @Override protected Boolean doInBackground() throws Exception { dicomModel .firePropertyChange(new ObservableEvent(ObservableEvent.BasicAction.LOADING_START, dicomModel, null, this)); addSelectionAndnotify(); return true; } @Override protected void done() { dicomModel .firePropertyChange(new ObservableEvent(ObservableEvent.BasicAction.LOADING_STOP, dicomModel, null, this)); LOGGER.info("End of loading DICOM locally"); //$NON-NLS-1$ } public void addSelectionAndnotify() { openPlugin = true; final ArrayList<SeriesThumbnail> thumbs = new ArrayList<>(dicomObjectsToLoad.length); for (Attributes dicom : dicomObjectsToLoad) { if (isCancelled()) { return; } try { DicomMediaIO loader = new DicomMediaIO(dicom); if (loader.isReadableDicom()) { // Issue: must handle adding image to viewer and building thumbnail (middle image) SeriesThumbnail t = buildDicomStructure(loader); if (t != null) { thumbs.add(t); } } } catch (URISyntaxException e) { LOGGER.debug("", e); //$NON-NLS-1$ } } for (final SeriesThumbnail t : thumbs) { MediaSeries<MediaElement> series = t.getSeries(); // Avoid to rebuild most of CR series thumbnail if (series != null && series.size(null) > 2) { GuiExecutor.instance().execute(t::reBuildThumbnail); } } } private SeriesThumbnail buildDicomStructure(DicomMediaIO dicomReader) { SeriesThumbnail thumb = null; String patientPseudoUID = (String) dicomReader.getTagValue(TagD.getUID(Level.PATIENT)); MediaSeriesGroup patient = dicomModel.getHierarchyNode(MediaSeriesGroupNode.rootNode, patientPseudoUID); if (patient == null) { patient = new MediaSeriesGroupNode(TagW.PatientPseudoUID, patientPseudoUID, DicomModel.patient.getTagView()); dicomReader.writeMetaData(patient); dicomModel.addHierarchyNode(MediaSeriesGroupNode.rootNode, patient); LOGGER.info("Adding patient: {}", patient); //$NON-NLS-1$ } String studyUID = (String) dicomReader.getTagValue(TagD.getUID(Level.STUDY)); MediaSeriesGroup study = dicomModel.getHierarchyNode(patient, studyUID); if (study == null) { study = new MediaSeriesGroupNode(TagD.getUID(Level.STUDY), studyUID, DicomModel.study.getTagView()); dicomReader.writeMetaData(study); dicomModel.addHierarchyNode(patient, study); } String seriesUID = (String) dicomReader.getTagValue(TagD.get(Tag.SeriesInstanceUID)); Series<?> dicomSeries = (Series<?>) dicomModel.getHierarchyNode(study, seriesUID); try { if (dicomSeries == null) { dicomSeries = dicomReader.buildSeries(seriesUID); dicomSeries.setTag(TagW.ExplorerModel, dicomModel); dicomSeries.setTag(TagW.ObjectToSave, Boolean.TRUE); dicomReader.writeMetaData(dicomSeries); dicomModel.addHierarchyNode(study, dicomSeries); MediaElement[] medias = dicomReader.getMediaElement(); if (medias != null) { for (MediaElement media : medias) { dicomModel.applySplittingRules(dicomSeries, media); media.setTag(TagW.ObjectToSave, Boolean.TRUE); } if (medias.length > 0) { dicomSeries.setFileSize(dicomSeries.getFileSize() + medias[0].getLength()); } } // Load image and create thumbnail in this Thread SeriesThumbnail t = (SeriesThumbnail) dicomSeries.getTagValue(TagW.Thumbnail); if (t == null) { t = DicomExplorer.createThumbnail(dicomSeries, dicomModel, Thumbnail.DEFAULT_SIZE); dicomSeries.setTag(TagW.Thumbnail, t); t.repaint(); } if (DicomModel.isSpecialModality(dicomSeries)) { dicomModel.addSpecialModality(dicomSeries); Arrays.stream(medias).filter(DicomSpecialElement.class::isInstance) .map(DicomSpecialElement.class::cast).findFirst().ifPresent(d -> dicomModel.firePropertyChange( new ObservableEvent(ObservableEvent.BasicAction.UPDATE, dicomModel, null, d))); } else { dicomModel.firePropertyChange( new ObservableEvent(ObservableEvent.BasicAction.ADD, dicomModel, null, dicomSeries)); } // After the thumbnail is sent to interface, it will be return to be rebuilt later thumb = t; Integer splitNb = (Integer) dicomSeries.getTagValue(TagW.SplitSeriesNumber); if (splitNb != null) { dicomModel.firePropertyChange( new ObservableEvent(ObservableEvent.BasicAction.UPDATE, dicomModel, null, dicomSeries)); } if (openPlugin) { SeriesViewerFactory plugin = UIManager.getViewerFactory(dicomSeries.getMimeType()); if (plugin != null && !(plugin instanceof MimeSystemAppFactory)) { openPlugin = false; ViewerPluginBuilder.openSequenceInPlugin(plugin, dicomSeries, dicomModel, true, true); } } } else { // Test if SOPInstanceUID already exists if (isSOPInstanceUIDExist(study, dicomSeries, seriesUID, TagD.getTagValue(dicomReader, Tag.SOPInstanceUID, String.class))) { return null; } MediaElement[] medias = dicomReader.getMediaElement(); if (medias != null) { for (MediaElement media : medias) { dicomModel.applySplittingRules(dicomSeries, media); media.setTag(TagW.ObjectToSave, Boolean.TRUE); } if (medias.length > 0) { dicomSeries.setFileSize(dicomSeries.getFileSize() + medias[0].getLength()); // Refresh the number of images on the thumbnail Thumbnail t = (Thumbnail) dicomSeries.getTagValue(TagW.Thumbnail); if (t != null) { t.repaint(); } } if (DicomModel.isSpecialModality(dicomSeries)) { dicomModel.addSpecialModality(dicomSeries); Arrays.stream(medias).filter(DicomSpecialElement.class::isInstance) .map(DicomSpecialElement.class::cast).findFirst().ifPresent(d -> dicomModel.firePropertyChange( new ObservableEvent(ObservableEvent.BasicAction.UPDATE, dicomModel, null, d))); } // If Split series or special DICOM element update the explorer view and View2DContainer Integer splitNb = (Integer) dicomSeries.getTagValue(TagW.SplitSeriesNumber); if (splitNb != null) { dicomModel.firePropertyChange( new ObservableEvent(ObservableEvent.BasicAction.UPDATE, dicomModel, null, dicomSeries)); } } } } catch (Exception e) { e.printStackTrace(); } finally { // dicomReader.reset(); } return thumb; } private boolean isSOPInstanceUIDExist(MediaSeriesGroup study, Series dicomSeries, String seriesUID, Object sopUID) { TagW sopTag = TagD.getUID(Level.INSTANCE); if (dicomSeries.hasMediaContains(sopTag, sopUID)) { return true; } Object splitNb = dicomSeries.getTagValue(TagW.SplitSeriesNumber); if (splitNb != null && study != null) { String uid = TagD.getTagValue(dicomSeries, Tag.SeriesInstanceUID, String.class); if (uid != null) { for (MediaSeriesGroup group : dicomModel.getChildren(study)) { if (dicomSeries != group && group instanceof Series) { Series s = (Series) group; if (uid.equals(TagD.getTagValue(group, Tag.SeriesInstanceUID))) { if (s.hasMediaContains(sopTag, sopUID)) { return true; } } } } } } return false; } }