/** * */ package org.signalml.plugin.impl; import static org.signalml.app.util.i18n.SvarogI18n._; import java.awt.Window; import java.io.File; import java.io.IOException; import java.io.InvalidClassException; import java.nio.ByteOrder; import java.security.InvalidParameterException; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Set; import java.util.TreeSet; import java.util.concurrent.ExecutionException; import org.apache.log4j.Logger; import org.signalml.app.action.selector.ActionFocusManager; import org.signalml.app.document.DocumentFlowIntegrator; import org.signalml.app.document.DocumentManager; import org.signalml.app.document.ManagedDocumentType; import org.signalml.app.document.TagDocument; import org.signalml.app.document.signal.SignalDocument; import org.signalml.app.model.document.OpenDocumentDescriptor; import org.signalml.app.model.document.opensignal.SignalMLDescriptor; import org.signalml.app.model.document.opensignal.elements.SignalParameters; import org.signalml.app.model.signal.SignalExportDescriptor; import org.signalml.app.view.common.dialogs.OptionPane; import org.signalml.app.view.common.dialogs.PleaseWaitDialog; import org.signalml.app.view.common.dialogs.errors.Dialogs; import org.signalml.app.view.signal.PositionedTag; import org.signalml.app.view.signal.SampleSourceUtils; import org.signalml.app.view.signal.SignalPlot; import org.signalml.app.view.signal.SignalScanResult; import org.signalml.app.view.signal.SignalView; import org.signalml.app.view.workspace.ViewerElementManager; import org.signalml.app.worker.document.ExportSignalWorker; import org.signalml.app.worker.signal.ScanSignalWorker; import org.signalml.codec.SignalMLCodec; import org.signalml.codec.SignalMLCodecManager; import org.signalml.codec.XMLSignalMLCodec; import org.signalml.codec.generator.xml.XMLCodecException; import org.signalml.domain.signal.SignalProcessingChain; import org.signalml.domain.signal.raw.RawSignalByteOrder; import org.signalml.domain.signal.raw.RawSignalDescriptor; import org.signalml.domain.signal.raw.RawSignalSampleType; import org.signalml.domain.signal.samplesource.MultichannelSampleSource; import org.signalml.domain.signal.samplesource.OriginalMultichannelSampleSource; import org.signalml.domain.signal.space.ChannelSpace; import org.signalml.domain.signal.space.ChannelSpaceType; import org.signalml.domain.signal.space.SegmentedSampleSourceFactory; import org.signalml.domain.signal.space.SignalSourceLevel; import org.signalml.domain.signal.space.SignalSpace; import org.signalml.domain.signal.space.TimeSpaceType; import org.signalml.domain.tag.LegacyTagImporter; import org.signalml.domain.tag.StyledTagSet; import org.signalml.plugin.export.NoActiveObjectException; import org.signalml.plugin.export.SignalMLException; import org.signalml.plugin.export.signal.Document; import org.signalml.plugin.export.signal.ExportedRawSignalSampleType; import org.signalml.plugin.export.signal.ExportedSignalDocument; import org.signalml.plugin.export.signal.ExportedSignalSelection; import org.signalml.plugin.export.signal.ExportedSignalSelectionType; import org.signalml.plugin.export.signal.ExportedTag; import org.signalml.plugin.export.signal.ExportedTagDocument; import org.signalml.plugin.export.signal.SignalSamples; import org.signalml.plugin.export.signal.SignalSelection; import org.signalml.plugin.export.signal.SignalSelectionType; import org.signalml.plugin.export.signal.SvarogAccessSignal; import org.signalml.plugin.export.signal.Tag; import org.signalml.plugin.export.signal.TagStyle; import org.signalml.plugin.export.signal.TemporaryFile; import org.signalml.plugin.export.view.DocumentView; import org.signalml.plugin.export.view.ExportedSignalPlot; /** * Implementation of {@link SvarogAccessSignal} interface. * Contains only two fields: * <ul> * <li>the {@link ViewerElementManager element manager} - allows to access * elements of Svarog. It is used to open documents, * {@link #addCodec(File, String) add codecs} and return * {@link #getProfileDirectory() profile directory}.</li> * <li>the {@link ActionFocusManager focus manager} - allows to get active * {@link SignalDocument signal} and {@link TagDocument documents}, used in * every function where active element is needed.</li> * </ul> * @author Marcin Szumski */ public class SignalsAccessImpl extends AbstractAccess implements SvarogAccessSignal { protected static final Logger logger = Logger.getLogger(SignalsAccessImpl.class); /** * informs which objects are focused */ private ActionFocusManager focusManager; private SignalsAccessImpl() { } private static final SignalsAccessImpl _instance = new SignalsAccessImpl(); protected static SignalsAccessImpl getInstance() { return _instance; } /** * Returns the output of signal samples. * @return the output of signal samples * @throws NoActiveObjectException if there is no active signal plot */ private MultichannelSampleSource getOutput() throws NoActiveObjectException { SignalPlot plot = getFocusManager().getActiveSignalPlot(); if (plot == null) throw new NoActiveObjectException("no active signal plot"); MultichannelSampleSource output = plot.getSignalOutput(); if (output == null) throw new RuntimeException("output of signal samples is null"); return output; } /** * Returns samples for the given source of samples and the given channel. * @param source the source of samples * @param channel the number of the channel (from 0 to {@code source.getChannelCount()-1}) * @return samples for the given source of samples and the given channel * @throws IndexOutOfBoundsException if the index of a channel is out of range */ private ChannelSamplesImpl getSamplesFromSource(MultichannelSampleSource source, int channel) throws IndexOutOfBoundsException { indexInBounds(source, channel); int sz = source.getSampleCount(channel); double[] samples = new double[sz]; source.getSamples(channel, samples, 0, sz, 0); ChannelSamplesImpl channelSamples = new ChannelSamplesImpl(samples, channel, source.getSamplingFrequency(), source.getLabel(channel)); return channelSamples; } /** * Returns samples for the given source of samples and the given channel. * @param source the source of samples * @param channel the number of the channel (from 0 to {@code source.getChannelCount()-1}) * @param signalOffset the position (in time) in the signal starting * from which samples will be returned * @param count the number of samples to be returned * @return samples for the given source of samples and the given channel * @throws IndexOutOfBoundsException if the index of a channel is out of range */ private ChannelSamplesImpl getSamplesFromSource(MultichannelSampleSource source, int channel, int signalOffset, int count) throws IndexOutOfBoundsException { indexInBounds(source, channel); double[] samples = new double[count]; source.getSamples(channel, samples, signalOffset, count, 0); return new ChannelSamplesImpl(samples, channel, source.getSamplingFrequency(), source.getLabel(channel)); } /** * Checks if the index of the channel is in range from 0 to * {@code source.getChannelCount()-1}. Throws exception if not. * @param source the source of samples * @param channel the index of the channel * @throws IndexOutOfBoundsException if the index of a channel is out of range */ private void indexInBounds(MultichannelSampleSource source, int channel) throws IndexOutOfBoundsException { if ((channel < 0) || (channel >= source.getChannelCount())) throw new IndexOutOfBoundsException("index "+ channel + "is out of range ["+ "0, " + (source.getChannelCount()-1) + "]"); } /* (non-Javadoc) * @see org.signalml.plugin.export.PluginAccessSignal#getActiveProcessedSignalSamples(int) */ @Override public ChannelSamplesImpl getActiveProcessedSignalSamples(int channel) throws NoActiveObjectException, IndexOutOfBoundsException { MultichannelSampleSource output = getOutput(); ChannelSamplesImpl channelSamples = getSamplesFromSource(output, channel); return channelSamples; } /* (non-Javadoc) * @see org.signalml.plugin.export.PluginAccessSignal#getActiveProcessedSignalSamples() */ @Override public SignalSamples getActiveProcessedSignalSamples() throws NoActiveObjectException { MultichannelSampleSource output = getOutput(); int numberOfChannels = output.getChannelCount(); SignalSamplesImpl signalSamples = new SignalSamplesImpl(); for (int i = 0; i < numberOfChannels; ++i) { ChannelSamplesImpl channelSamples = getActiveProcessedSignalSamples(i); if (channelSamples == null) throw new RuntimeException(); signalSamples.addChannelSamples(channelSamples); } return signalSamples; } /** * * @return the list of documents in the signal. may be empty */ private ArrayList<SignalDocument> getSignalDocuments() { DocumentManager documentManager = getViewerElementManager().getDocumentManager(); int numberOfDocuments = documentManager.getDocumentCount(); ArrayList<SignalDocument> documents = new ArrayList<SignalDocument>(); for (int i = 0; i < numberOfDocuments; ++i) { Document documentTmp = documentManager.getDocumentAt(i); if (documentTmp instanceof SignalDocument) { documents.add((SignalDocument) documentTmp); } } return documents; } /* (non-Javadoc) * @see org.signalml.plugin.export.PluginAccessSignal#getProcessedSignalSamplesForAllSignals() */ @Override public SignalSamples[] getProcessedSignalSamplesForAllSignals() { ArrayList<SignalDocument> documents = getSignalDocuments(); ArrayList<SignalSamplesImpl> signalsSamples = new ArrayList<SignalSamplesImpl>(); for (SignalDocument signalDocument : documents) { SignalSamplesImpl samplesTmp; try { samplesTmp = getProcessedSignalSamplesFromDocument(signalDocument); signalsSamples.add(samplesTmp); } catch (InvalidClassException e) { //never happens } } return signalsSamples.toArray(new SignalSamplesImpl[signalsSamples.size()]); } /** * Returns the source of unprocessed signal samples for the active signal. * @return the source of unprocessed signal samples for the active signal * @throws NoActiveObjectException if there is no active signal */ private OriginalMultichannelSampleSource getOriginalSource() throws NoActiveObjectException { SignalPlot plot = getFocusManager().getActiveSignalPlot(); if (plot == null) throw new NoActiveObjectException("no active signal plot"); OriginalMultichannelSampleSource originalSource = plot.getSignalSource(); if (originalSource == null) throw new RuntimeException("original source of samples is null"); return originalSource; } /* (non-Javadoc) * @see org.signalml.plugin.export.PluginAccessSignal#getActiveRawSignalSamples(int) */ @Override public ChannelSamplesImpl getActiveRawSignalSamples(int channel) throws NoActiveObjectException, IndexOutOfBoundsException { MultichannelSampleSource source = getOriginalSource(); ChannelSamplesImpl channelSamples = getSamplesFromSource(source, channel); return channelSamples; } /* (non-Javadoc) * @see org.signalml.plugin.export.PluginAccessSignal#getActiveRawSignalSamples(int) */ @Override public ChannelSamplesImpl getActiveRawSignalSamples(int channel, int signalOffset, int count) throws NoActiveObjectException, IndexOutOfBoundsException { MultichannelSampleSource source = getOriginalSource(); ChannelSamplesImpl channelSamples = getSamplesFromSource(source, channel, signalOffset, count); return channelSamples; } @Override public ChannelSamplesImpl getActiveProcessedSignalSamples(int channel, int signalOffset, int count) throws NoActiveObjectException, IndexOutOfBoundsException { MultichannelSampleSource source = getOutput(); ChannelSamplesImpl channelSamples = getSamplesFromSource(source, channel, signalOffset, count); return channelSamples; } @Override public ChannelSamplesImpl getRawSignalSamplesFromDocument(ExportedSignalDocument document, int channel, int signalOffset, int count) throws InvalidClassException, IndexOutOfBoundsException { MultichannelSampleSource source = getOriginalSourceFromDocument(document); ChannelSamplesImpl channelSamples = getSamplesFromSource(source, channel, signalOffset, count); return channelSamples; } @Override public ChannelSamplesImpl getProcessedSignalSamplesFromDocument(ExportedSignalDocument document, int channel, int signalOffset, int count) throws InvalidClassException, IndexOutOfBoundsException { MultichannelSampleSource source = getOutputFromDocument(document); ChannelSamplesImpl channelSamples = getSamplesFromSource(source, channel, signalOffset, count); return channelSamples; } /** * Returns samples for the given source of samples, the given channel and * the specified period of time. * @param source the source of samples * @param channel the number of the channel (from 0 to {@code * source.getChannelCount()-1}) * @param signalOffsetTime the position (in time in seconds) in the signal * starting from which samples will be returned * @param length the length of the part of the signal which should be returned * @return samples for the given source of samples and the given channel * @throws IndexOutOfBoundsException if the index of a channel is out of range */ private ChannelSamplesImpl getSamplesFromSource(MultichannelSampleSource source, int channel, float signalOffsetTime, float length) throws IndexOutOfBoundsException { ChannelSamplesImpl channelSamples = getSamplesFromSource(source, channel, (int)(signalOffsetTime*source.getSamplingFrequency()), (int)(length*source.getSamplingFrequency())); return channelSamples; } @Override public ChannelSamplesImpl getActiveProcessedSignalSamples(int channel, float signalOffsetTime, float length) throws NoActiveObjectException, IndexOutOfBoundsException { MultichannelSampleSource source = getOutput(); ChannelSamplesImpl channelSamples = getSamplesFromSource(source, channel, signalOffsetTime, length); return channelSamples; } @Override public ChannelSamplesImpl getActiveRawSignalSamples(int channel, float signalOffsetTime, float length) throws NoActiveObjectException, IndexOutOfBoundsException { MultichannelSampleSource source = getOriginalSource(); ChannelSamplesImpl channelSamples = getSamplesFromSource(source, channel, signalOffsetTime, length); return channelSamples; } @Override public ChannelSamplesImpl getRawSignalSamplesFromDocument(ExportedSignalDocument document, int channel, float signalOffsetTime, float length) throws InvalidClassException, IndexOutOfBoundsException { MultichannelSampleSource source = getOriginalSourceFromDocument(document); ChannelSamplesImpl channelSamples = getSamplesFromSource(source, channel, signalOffsetTime, length); return channelSamples; } @Override public ChannelSamplesImpl getProcessedSignalSamplesFromDocument(ExportedSignalDocument document, int channel, float signalOffsetTime, float length) throws InvalidClassException, IndexOutOfBoundsException { MultichannelSampleSource source = getOutputFromDocument(document); ChannelSamplesImpl channelSamples = getSamplesFromSource(source, channel, signalOffsetTime, length); return channelSamples; } /* (non-Javadoc) * @see org.signalml.plugin.export.PluginAccessSignal#getActiveRawSignalSamples() */ @Override public SignalSamples getActiveRawSignalSamples() throws NoActiveObjectException { MultichannelSampleSource source = getOutput(); int numberOfChannels = source.getChannelCount(); SignalSamplesImpl signalSamples = new SignalSamplesImpl(); for (int i = 0; i < numberOfChannels; ++i) { ChannelSamplesImpl channelSamples = getActiveRawSignalSamples(i); if (channelSamples == null) throw new RuntimeException("Channel samples are null"); signalSamples.addChannelSamples(channelSamples); } return signalSamples; } /* (non-Javadoc) * @see org.signalml.plugin.export.PluginAccessSignal#getActiveSignalSamplesForAllSignals() */ @Override public SignalSamples[] getRawSignalSamplesForAllSignals() { ArrayList<SignalDocument> documents = getSignalDocuments(); if (documents == null) return null; ArrayList<SignalSamplesImpl> signalsSamples = new ArrayList<SignalSamplesImpl>(); for (SignalDocument signalDocument : documents) { SignalSamplesImpl samplesTmp; try { samplesTmp = getRawSignalSamplesFromDocument(signalDocument); signalsSamples.add(samplesTmp); } catch (InvalidClassException e) { //never happens } } return signalsSamples.toArray(new SignalSamplesImpl[signalsSamples.size()]); } /** * Returns the {@link OriginalMultichannelSampleSource original source} * of samples (source of raw samples) for a given * {@link ExportedSignalDocument signal document}. * @param document the signal document * @return the original source of samples * @throws InvalidClassException if document is not of type {@link SignalDocument} */ private MultichannelSampleSource getOriginalSourceFromDocument(ExportedSignalDocument document) throws InvalidClassException { SignalPlot signalPlot = getSignalPlotFromDocument(document); if (signalPlot == null) throw new RuntimeException("signal plot is null"); MultichannelSampleSource source = signalPlot.getSignalSource(); if (source == null) throw new RuntimeException("source of samples is null"); return source; } /* (non-Javadoc) * @see org.signalml.plugin.export.PluginAccessSignal#getRawSignalSamplesFromDocument(org.signalml.plugin.export.ExportedSignalDocument, int) */ @Override public ChannelSamplesImpl getRawSignalSamplesFromDocument(ExportedSignalDocument document, int channel) throws InvalidClassException, IndexOutOfBoundsException { MultichannelSampleSource source = getOriginalSourceFromDocument(document); ChannelSamplesImpl channelSamples = getSamplesFromSource(source, channel); return channelSamples; } /* (non-Javadoc) * @see org.signalml.plugin.export.PluginAccessSignal#getRawSignalSamplesFromDocument(org.signalml.plugin.export.ExportedSignalDocument) */ @Override public SignalSamplesImpl getRawSignalSamplesFromDocument(ExportedSignalDocument document) throws InvalidClassException { MultichannelSampleSource source = getOriginalSourceFromDocument(document); int numberOfChannels = source.getChannelCount(); SignalSamplesImpl signalSamples = new SignalSamplesImpl(); for (int i = 0; i < numberOfChannels; ++i) { try { signalSamples.addChannelSamples(getRawSignalSamplesFromDocument(document, i)); } catch (IndexOutOfBoundsException e) { throw new RuntimeException("incorrect index of a channel passed"); } } return signalSamples; } /* (non-Javadoc) * @see org.signalml.plugin.export.PluginAccessSignal#getTagsFromActiveDocument() */ @Override public Set<ExportedTag> getTagsFromActiveDocument() throws NoActiveObjectException { TagDocument tagDocument = getFocusManager().getActiveTagDocument(); if (tagDocument == null) throw new NoActiveObjectException("no active tag document"); return new TreeSet<ExportedTag>(tagDocument.getSetOfTags()); } /* (non-Javadoc) * @see org.signalml.plugin.export.PluginAccessSignal#getTagsFromAllDocumentsAssociatedWithAcitiveSignal() */ @Override public List<ExportedTag> getTagsFromAllDocumentsAssociatedWithAcitiveSignal() throws NoActiveObjectException { SignalDocument signalDocument = getFocusManager().getActiveSignalDocument(); if (signalDocument == null) throw new NoActiveObjectException("no active signal document"); try { return getTagsFromSignalDocument(signalDocument); } catch (InvalidClassException e) { throw new RuntimeException("getActiveSignalDocument() didn't return an object of class SignalDocument"); } } /* (non-Javadoc) * @see org.signalml.plugin.export.PluginAccessSignal#getTagsFromAllDocuments() */ @Override public List<ExportedTag> getTagsFromAllDocuments() { ArrayList<SignalDocument> signalDocuments = getSignalDocuments(); List<ExportedTag> tags = new ArrayList<ExportedTag>(); for (SignalDocument signalDocument : signalDocuments) { try { List<ExportedTag> tagsTmp = getTagsFromSignalDocument(signalDocument); tags.addAll(tagsTmp); } catch (InvalidClassException e) { //never occurs } } return tags; } /* (non-Javadoc) * @see org.signalml.plugin.export.PluginAccessSignal#getActiveTag() */ @Override public ExportedTag getActiveTag() throws NoActiveObjectException { SignalDocument signalDocument = getFocusManager().getActiveSignalDocument(); if (signalDocument == null) throw new NoActiveObjectException("no active singal document"); DocumentView documentView = signalDocument.getDocumentView(); if (!(documentView instanceof SignalView)) throw new RuntimeException("signal documetn didn't return a valid SignalView"); SignalView signalView = (SignalView) documentView; PositionedTag positionedTag = signalView.getActiveTag(); if (positionedTag == null) throw new NoActiveObjectException("no active tag"); return positionedTag.getTag(); } /* (non-Javadoc) * @see org.signalml.plugin.export.PluginAccessSignal#getTagsFromSignalDocument(org.signalml.plugin.export.ExportedSignalDocument) */ @Override public List<ExportedTag> getTagsFromSignalDocument(ExportedSignalDocument document) throws InvalidClassException { if (!(document instanceof SignalDocument)) throw new InvalidClassException("document is not of type SignalDocument = was not returned from Svarog"); SignalDocument signalDocument = (SignalDocument) document; List<TagDocument> tagDocuments = signalDocument.getTagDocuments(); List<ExportedTag> tags = new ArrayList<ExportedTag>(); for (TagDocument tagDocument : tagDocuments) { tags.addAll(tagDocument.getSetOfTags()); } return tags; } /* (non-Javadoc) * @see org.signalml.plugin.export.PluginAccessSignal#getActiveSelection() */ @Override public ExportedSignalSelection getActiveSelection() throws NoActiveObjectException { SignalPlot signalPlot = getFocusManager().getActiveSignalPlot(); if (signalPlot == null) throw new NoActiveObjectException("no active signal plot"); SignalView signalView = signalPlot.getView(); ExportedSignalSelection selection = signalView.getSignalSelection(); if (selection == null) throw new NoActiveObjectException("no active signal selection"); return selection; } /* (non-Javadoc) * @see org.signalml.plugin.export.PluginAccessSignal#addTagToActiveTagDocument(org.signalml.plugin.export.Tag) */ @Override public void addTagToActiveTagDocument(ExportedTag tag) throws NoActiveObjectException, IllegalArgumentException { TagDocument tagDocument = getFocusManager().getActiveTagDocument(); try { addTagToDocument(tagDocument, tag); } catch (InvalidClassException e) { throw new RuntimeException("FocusManager.getActiveTagDocument() didn't return a valid TagDocument object"); } } /** * In the given document finds the {@link TagStyle style} that is equal to * the style of the provided {@link ExportedTag tag}. * @param tagDocument the document in which we are looking for a style * @param tag the tag for which the actual style is to be found * @return the style that is equal to the style of the provided tag * @throws IllegalArgumentException if there is no such tag style in * the document */ private TagStyle findStyle(TagDocument tagDocument, ExportedTag tag) throws IllegalArgumentException { StyledTagSet tagSet = tagDocument.getTagSet(); Collection<TagStyle> styles = tagSet.getListOfStyles(); TagStyle style = null; for (TagStyle styleTmp : styles) { if (styleTmp.equals(tag.getStyle())) { style = styleTmp; break; } } if (style == null) throw new IllegalArgumentException("tag style is not in the document"); return style; } /** * From the given {@link ExportedTag exported tag} creates a collection of * {@link Tag tags} by splitting it to separate blocks/pages (only if * exported tag has a {@link ExportedSignalSelectionType type} * {@code BLOCK} or {@code PAGE}). * If the exported tag has a type {@code CHANNEL} the collection contains * only one tag created from it * @param tag the tag to be converted * @param tagDocument the document to which the tag will be added; * used to get styles and lengths of blocks/pages. * @return the collection of tags */ private Collection<Tag> splitTag(ExportedTag tag, TagDocument tagDocument) { float blockOrPageLength = 0; Collection<Tag> tags = new ArrayList<Tag>(); TagStyle style = findStyle(tagDocument, tag); if (tag.getType().getName().equals(ExportedSignalSelectionType.BLOCK)) { blockOrPageLength = tagDocument.getBlockSize(); } else if (tag.getType().getName().equals(ExportedSignalSelectionType.PAGE)) { blockOrPageLength = tagDocument.getPageSize(); } else { Tag trueTag = new Tag(style, tag.getPosition(), tag.getLength(), tag.getChannel(), tag.getAnnotation()); tags.add(trueTag); return tags; } int startBlockOrPage = tag.getStartSegment(blockOrPageLength); int endBlockOrPage = tag.getEndSegment(blockOrPageLength); for (int i=startBlockOrPage; i<endBlockOrPage; i++) { Tag trueTag = new Tag(style, i*blockOrPageLength, blockOrPageLength, SignalSelection.CHANNEL_NULL, tag.getAnnotation()); tags.add(trueTag); } return tags; } /* (non-Javadoc) * @see org.signalml.plugin.export.PluginAccessSignal#addTagToDocument(org.signalml.plugin.export.ExportedTagDocument, org.signalml.plugin.export.Tag) */ @Override public void addTagToDocument(ExportedTagDocument document, ExportedTag tag) throws InvalidClassException, IllegalArgumentException { if (!(document instanceof TagDocument)) throw new InvalidClassException("document is not of type TagDocument => was not returned from Svarog"); TagDocument tagDocument = (TagDocument) document; StyledTagSet tagSet = tagDocument.getTagSet(); TagStyle style = findStyle(tagDocument, tag); ExportedSignalSelectionType type = tag.getType(); if (!(style.getType().getName().equals(type.getName()))) throw new IllegalArgumentException("tag style is not in the document"); Collection<Tag> tags = splitTag(tag, tagDocument); for (Tag trueTag : tags) tagSet.replaceSameTypeTags(trueTag); tagDocument.setSaved(false); } /* (non-Javadoc) * @see org.signalml.plugin.export.PluginAccessSignal#getTagDocumentsFromActiveSignal() */ @Override public ExportedTagDocument[] getTagDocumentsFromActiveSignal() throws NoActiveObjectException { SignalDocument signalDocument = getFocusManager().getActiveSignalDocument(); if (signalDocument == null) throw new NoActiveObjectException("no active signal document"); List<TagDocument> tagDocuments = signalDocument.getTagDocuments(); return tagDocuments.toArray(new TagDocument[tagDocuments.size()]); } /* (non-Javadoc) * @see org.signalml.plugin.export.PluginAccessSignal#getActiveTagDocument() */ @Override public ExportedTagDocument getActiveTagDocument() throws NoActiveObjectException { ExportedTagDocument exportedTagDocument = getFocusManager().getActiveTagDocument(); if (exportedTagDocument == null) throw new NoActiveObjectException("no active tag document"); return exportedTagDocument; } /* (non-Javadoc) * @see org.signalml.plugin.export.PluginAccessSignal#getActiveDocument() */ @Override public Document getActiveDocument() throws NoActiveObjectException { Document document = getFocusManager().getActiveDocument(); if (document == null) throw new NoActiveObjectException("no active document"); return document; } /* (non-Javadoc) * @see org.signalml.plugin.export.PluginAccessSignal#openSignal(java.lang.String) */ @Override public void openRawSignal(File file, float samplingFrequency, int channelCount, ExportedRawSignalSampleType sampleType, ByteOrder byteOrder, float calibration, float pageSize, int blocksPerPage) throws SignalMLException, IOException { OpenDocumentDescriptor ofd = new OpenDocumentDescriptor(); ofd.setMakeActive(true); if (file == null) throw new NullPointerException("file can not be null"); if (!file.exists()) throw new IOException("file doesn't exist"); if (!file.canRead()) throw new IOException("can not access file"); ofd.setFile(file); ofd.setType(ManagedDocumentType.SIGNAL); RawSignalDescriptor descriptor = new RawSignalDescriptor(); descriptor.setSamplingFrequency(samplingFrequency); descriptor.setChannelCount(channelCount); descriptor.setSampleType(getSampleType(sampleType)); descriptor.setByteOrder(getByteOrder(byteOrder)); descriptor.setCalibrationGain(calibration); descriptor.setPageSize(pageSize); descriptor.setBlocksPerPage(blocksPerPage); ofd.setOpenSignalDescriptor(descriptor); DocumentFlowIntegrator documentFlowIntegrator = getViewerElementManager().getDocumentFlowIntegrator(); if (documentFlowIntegrator.maybeOpenDocument(ofd) == null) throw new SignalMLException("failed to open document"); } /* (non-Javadoc) * @see org.signalml.plugin.export.PluginAccessSignal#openTagDocument(java.lang.String, org.signalml.plugin.export.ExportedSignalDocument, boolean) */ @Override public void openTagDocument(File file, ExportedSignalDocument document, boolean activeFlag) throws SignalMLException, IOException { if (file == null) throw new NullPointerException("file can not be null"); if (!(document instanceof SignalDocument)) throw new InvalidClassException("document is not of type SignalDocument = was not returned from Svarog"); SignalDocument signalDocument = (SignalDocument) document; if (!file.exists()) throw new IOException("file doesn't exist"); if (!file.canRead()) throw new IOException("can not access file"); OpenDocumentDescriptor ofd = new OpenDocumentDescriptor(); ofd.setType(ManagedDocumentType.TAG); ofd.setMakeActive(activeFlag); boolean legTag = true; LegacyTagImporter importer = new LegacyTagImporter(); StyledTagSet tagSet = null; try { tagSet = importer.importLegacyTags(file, signalDocument.getSamplingFrequency()); } catch (SignalMLException ex) { legTag = false; } TagDocument tagDocument = null; try { tagDocument = new TagDocument(tagSet); } catch (SignalMLException ex) { legTag = false; } if (legTag) { ofd.getTagOptions().setExistingDocument(tagDocument); } else { ofd.setFile(file); } ofd.getTagOptions().setParent(signalDocument); DocumentFlowIntegrator documentFlowIntegrator = getViewerElementManager().getDocumentFlowIntegrator(); //if (documentFlowIntegrator == null) return false; if (documentFlowIntegrator.maybeOpenDocument(ofd) == null) throw new SignalMLException("failed to open document"); } /** * Returns a {@link SignalPlot signal plot} for a {@link SignalView view} * associated with a given document. * @param document the document with the signal. Must be of type SignalDocument * @return a plot for a view associated with a given document * @throws InvalidClassException if document is not of type SignalDocument */ private SignalPlot getSignalPlotFromDocument(ExportedSignalDocument document) throws InvalidClassException { if (!(document instanceof SignalDocument)) throw new InvalidClassException("document is not of type SignalDocument => was not returned from Svarog"); SignalDocument signalDocument = (SignalDocument) document; DocumentView documentView = signalDocument.getDocumentView(); if (!(documentView instanceof SignalView)) throw new RuntimeException("view is not of type SignalView"); SignalView signalView = (SignalView) documentView; SignalPlot signalPlot = signalView.getMasterPlot(); if (signalPlot == null) throw new RuntimeException("no master plot for signal view"); return signalPlot; } /** * Returns the output of signal samples associated with a given document. * @param document the document with the signal. Must be of type SignalDocument * @return the output of signal samples associated with a given document * @throws InvalidClassException if document is not of type SignalDocument */ private MultichannelSampleSource getOutputFromDocument(ExportedSignalDocument document) throws InvalidClassException { SignalPlot signalPlot = getSignalPlotFromDocument(document); MultichannelSampleSource output = signalPlot.getSignalOutput(); if (output == null) throw new RuntimeException("no output of signal samples for a signal plot"); return output; } /* (non-Javadoc) * @see org.signalml.plugin.export.PluginAccessSignal#getProcessedSignalSamplesFromDocument(org.signalml.plugin.export.ExportedSignalDocument, int) */ @Override public ChannelSamplesImpl getProcessedSignalSamplesFromDocument(ExportedSignalDocument document, int channel) throws InvalidClassException, IndexOutOfBoundsException { MultichannelSampleSource output = getOutputFromDocument(document); ChannelSamplesImpl channelSamples = getSamplesFromSource(output, channel); return channelSamples; } /* (non-Javadoc) * @see org.signalml.plugin.export.PluginAccessSignal#getProcessedSignalSamplesFromDocument(org.signalml.plugin.export.ExportedSignalDocument) */ @Override public SignalSamplesImpl getProcessedSignalSamplesFromDocument(ExportedSignalDocument document) throws InvalidClassException { MultichannelSampleSource output = getOutputFromDocument(document); int numberOfChannels = output.getChannelCount(); SignalSamplesImpl signalSamples = new SignalSamplesImpl(); for (int i = 0; i < numberOfChannels; ++i) { signalSamples.addChannelSamples(getProcessedSignalSamplesFromDocument(document, i)); } return signalSamples; } /* (non-Javadoc) * @see org.signalml.plugin.export.signal.PluginAccessSignal#openSignalWithCodec(java.io.File, java.lang.String) */ @Override public void openSignalWithCodec(File file, String codecFormatName, float pageSize, int blocksPerPage) throws IOException, IllegalArgumentException, SignalMLException { OpenDocumentDescriptor ofd = new OpenDocumentDescriptor(); ofd.setMakeActive(true); ofd.setFile(file); ofd.setType(ManagedDocumentType.SIGNAL); SignalMLDescriptor signalMLDescriptor = (SignalMLDescriptor) ofd.getOpenSignalDescriptor(); SignalParameters spd = signalMLDescriptor.getSignalParameters(); SignalMLCodecManager codecManager = getViewerElementManager().getCodecManager(); if (file == null) throw new NullPointerException("file can not be null"); if (!file.exists()) throw new IOException("file doesn't exist"); if (!file.canRead()) throw new IOException("can not access file"); SignalMLCodec codec = codecManager.getCodecForFormat(codecFormatName); if (codec == null) throw new IllegalArgumentException("codec of this name doesn't exist"); signalMLDescriptor.setCodec(codec); if (spd.isBlocksPerPageEditable()) { spd.setBlocksPerPage(blocksPerPage); } if (spd.isPageSizeEditable()) { spd.setPageSize(pageSize); } DocumentFlowIntegrator documentFlowIntegrator = getViewerElementManager().getDocumentFlowIntegrator(); if (documentFlowIntegrator.maybeOpenDocument(ofd) == null) throw new SignalMLException("failed to open document"); } /* (non-Javadoc) * @see org.signalml.plugin.export.signal.PluginAccessSignal#addCodec(java.io.File, java.lang.String) */ @Override public void addCodec(File codecFile, String codecFormatName) throws IOException { SignalMLCodecManager codecManager = getViewerElementManager().getCodecManager(); if (codecFile == null) throw new NullPointerException("file can not be null"); if (!codecFile.exists()) throw new IOException("file doesn't exist"); if (!codecFile.canRead()) throw new IOException("can not access file"); SignalMLCodec codec; try { codec = new XMLSignalMLCodec(codecFile, ConfigAccessImpl.getInstance().getProfileDirectory()); } catch (XMLCodecException e) { throw new IOException("failed to read codec"); } codec.setFormatName(codecFormatName); codecManager.registerSignalMLCodec(codec); } /* (non-Javadoc) * @see org.signalml.plugin.export.signal.PluginAccessSignal#openBook(java.io.File) */ @Override public void openBook(File file) throws IOException, SignalMLException { OpenDocumentDescriptor ofd = new OpenDocumentDescriptor(); if (file == null) throw new NullPointerException("file can not be null"); if (!file.exists()) throw new IOException("file doesn't exist"); if (!file.canRead()) throw new IOException("can not access file"); ofd.setMakeActive(true); ofd.setFile(file); ofd.setType(ManagedDocumentType.BOOK); DocumentFlowIntegrator documentFlowIntegrator = getViewerElementManager().getDocumentFlowIntegrator(); if (documentFlowIntegrator.maybeOpenDocument(ofd) == null) throw new SignalMLException("failed to open book document"); } /** * @return the focusManager */ private ActionFocusManager getFocusManager() { if (focusManager == null) focusManager = getViewerElementManager().getActionFocusManager(); return focusManager; } /* (non-Javadoc) * @see org.signalml.plugin.export.signal.SvarogAccessSignal#getActiveSignalDocument() */ @Override public ExportedSignalDocument getActiveSignalDocument() throws NoActiveObjectException { Document document = getActiveDocument(); if (!(document instanceof ExportedSignalDocument)) throw new NoActiveObjectException("no active signal document"); return (ExportedSignalDocument) document; } /** * Obtains {@link RawSignalByteOrder} for a given {@link ByteOrder} * @param order the ByteOrder * @return the RawSignalByteOrder * @throws InvalidClassException if there is no such RawSignalByteOrder */ private RawSignalByteOrder getByteOrder(ByteOrder order) throws InvalidClassException { RawSignalByteOrder[] rawByteOrders = RawSignalByteOrder.values(); for (RawSignalByteOrder rawByteOrder : rawByteOrders) { if (rawByteOrder.getByteOrder().equals(order)) return rawByteOrder; } throw new InvalidClassException("No such byte order"); } /** * Obtains {@link RawSignalSampleType} for a given * {@link ExportedRawSignalSampleType}. * @param sampleType the {@link ExportedRawSignalSampleType} * @return the RawSignalSampleType * @throws InvalidParameterException if there is no type */ private RawSignalSampleType getSampleType(ExportedRawSignalSampleType sampleType) { switch (sampleType) { case DOUBLE: return RawSignalSampleType.DOUBLE; case FLOAT: return RawSignalSampleType.FLOAT; case INT: return RawSignalSampleType.INT; case SHORT: return RawSignalSampleType.SHORT; default: throw new InvalidParameterException("such type doesn't exist"); } } @Override public void exportSignal(float position, float length, int[] channels, SignalSourceLevel level, ExportedRawSignalSampleType sampleType, ByteOrder byteOrder, ExportedSignalPlot plot, File file) throws InvalidClassException, SignalMLException { if (!(plot instanceof SignalPlot)) throw new InvalidClassException("document is not of type SignalPlot => was not returned from Svarog"); SignalPlot masterPlot = (SignalPlot) plot; RawSignalByteOrder rawByteOrder = getByteOrder(byteOrder); SignalExportDescriptor descriptor = new SignalExportDescriptor(); SignalSpace signalSpace = new SignalSpace(); descriptor.setSignalSpace(signalSpace); ChannelSpace channelSpace = new ChannelSpace(channels); signalSpace.setChannelSpace(channelSpace); SignalSelection selection = new SignalSelection(SignalSelectionType.CHANNEL, position, length); signalSpace.setSelectionTimeSpace(selection); signalSpace.setChannelSpaceType(ChannelSpaceType.SELECTED); signalSpace.setSignalSourceLevel(level); signalSpace.setTimeSpaceType(TimeSpaceType.SELECTION_BASED); descriptor.setByteOrder(rawByteOrder); descriptor.setBlockSize(masterPlot.getBlockSize()); descriptor.setPageSize(masterPlot.getPageSize()); RawSignalSampleType rawSignalSampleType = getSampleType(sampleType); descriptor.setSampleType(rawSignalSampleType); descriptor.setNormalize(false); SignalProcessingChain signalChain; try { signalChain = masterPlot.getSignalChain().createLevelCopyChain(signalSpace.getSignalSourceLevel()); } catch (SignalMLException ex) { logger.error("Failed to create subchain", ex); Dialogs.showExceptionDialog((Window) null, ex); return; } SegmentedSampleSourceFactory factory = SegmentedSampleSourceFactory.getSharedInstance(); MultichannelSampleSource sampleSource = factory.getContinuousOrSegmentedSampleSource(signalChain, signalSpace, descriptor.getTagSet(), descriptor.getPageSize(), descriptor.getBlockSize()); PleaseWaitDialog pleaseWaitDialog = new PleaseWaitDialog(getViewerElementManager().getDialogParent()); pleaseWaitDialog.initializeNow(); if (rawSignalSampleType == RawSignalSampleType.INT || rawSignalSampleType == RawSignalSampleType.SHORT) { // normalization - check signal half-amplitude maximum ScanSignalWorker scanWorker = new ScanSignalWorker(sampleSource, pleaseWaitDialog); scanWorker.execute(); pleaseWaitDialog.setActivity(_("scanning signal")); pleaseWaitDialog.configureForDeterminate(0, SampleSourceUtils.getMaxSampleCount(sampleSource), 0); pleaseWaitDialog.waitAndShowDialogIn(getViewerElementManager().getDialogParent(), 500, scanWorker); SignalScanResult signalScanResult = null; try { signalScanResult = scanWorker.get(); } catch (InterruptedException ex) { // ignore } catch (ExecutionException ex) { logger.error("Worker failed to save", ex.getCause()); Dialogs.showExceptionDialog((Window) null, ex.getCause()); return; } double maxSignalAbsValue = Math.max(Math.abs(signalScanResult.getMaxSignalValue()), Math.abs(signalScanResult.getMinSignalValue())); double maxTypeAbsValue = 0; if (rawSignalSampleType == RawSignalSampleType.INT) { maxTypeAbsValue = Math.min((Integer.MAX_VALUE-1), -(Integer.MIN_VALUE+1)); } else { maxTypeAbsValue = Math.min((Short.MAX_VALUE-1), -(Short.MIN_VALUE+1)); } boolean normalize = descriptor.isNormalize(); if (!normalize) { // check if normalization needs to be forced if (maxTypeAbsValue < Math.ceil(maxSignalAbsValue)) { int ans = OptionPane.showNormalizationUnavoidable(getViewerElementManager().getOptionPaneParent()); if (ans != OptionPane.OK_OPTION) { return; } normalize = true; descriptor.setNormalize(normalize); } } if (normalize) { descriptor.setNormalizationFactor(maxTypeAbsValue / maxSignalAbsValue); } } int minSampleCount = SampleSourceUtils.getMinSampleCount(sampleSource); ExportSignalWorker worker = new ExportSignalWorker(sampleSource, file, descriptor, pleaseWaitDialog); worker.execute(); pleaseWaitDialog.setActivity(_("exporting signal")); pleaseWaitDialog.configureForDeterminate(0, minSampleCount, 0); pleaseWaitDialog.waitAndShowDialogIn(getViewerElementManager().getOptionPaneParent(), 500, worker); try { worker.get(); } catch (InterruptedException ex) { // ignore } catch (ExecutionException ex) { logger.error("Worker failed to save", ex.getCause()); throw new SignalMLException("failed to export signal", ex); } } @Override public File getTemporaryFile(String extension) throws IOException { File profileDirectory = getViewerElementManager().getProfileDir().getAbsoluteFile(); File tempDirectory = new File(profileDirectory, "temp"); if (tempDirectory.exists() && !tempDirectory.isDirectory()) throw new IOException("can not create the directory for temporary files"); if (!tempDirectory.exists()) tempDirectory.mkdir(); File tempFile = File.createTempFile("temp", extension, tempDirectory); TemporaryFile temporaryFile = new TemporaryFile(tempFile.getAbsolutePath()); temporaryFile.deleteOnExit(); return temporaryFile; } }