package pl.edu.fuw.fid.signalanalysis.ica; import java.awt.event.ActionEvent; import java.io.File; import java.io.IOException; import javax.swing.JOptionPane; import javax.swing.WindowConstants; import org.apache.commons.math.linear.RealMatrix; import org.signalml.app.document.DocumentFlowIntegrator; import org.signalml.app.document.signal.SignalDocument; import org.signalml.app.view.signal.SignalView; import org.signalml.domain.montage.Montage; import org.signalml.domain.montage.MontageMismatchException; import org.signalml.domain.montage.SourceMontage; 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.space.ChannelSpaceType; import org.signalml.domain.signal.space.SignalSpace; import org.signalml.domain.signal.space.SignalSpaceConstraints; import org.signalml.plugin.export.NoActiveObjectException; import org.signalml.plugin.export.SignalMLException; import org.signalml.plugin.export.signal.ExportedSignalSelection; import org.signalml.plugin.export.signal.SvarogAccessSignal; import org.signalml.plugin.export.view.AbstractSignalMLAction; import org.signalml.plugin.export.view.SvarogAccessGUI; import org.signalml.plugin.impl.PluginAccessClass; import pl.edu.fuw.fid.signalanalysis.SignalAnalysisTools; /** * Action triggered when user decides to compute ICA * (Independent Component Analysis). * * @author ptr@mimuw.edu.pl */ public class IcaMethodAction extends AbstractSignalMLAction { private static final String TITLE = "Compute ICA"; private final SvarogAccessGUI guiAccess; private final SvarogAccessSignal signalAccess; public IcaMethodAction(SvarogAccessGUI guiAccess, SvarogAccessSignal signalAccess) { super(); this.guiAccess = guiAccess; this.signalAccess = signalAccess; this.setText(TITLE); } @Override public void actionPerformed(ActionEvent e) { try { SignalDocument signalDocument = (SignalDocument) signalAccess.getActiveSignalDocument(); SignalView signalView = (SignalView) signalDocument.getDocumentView(); SignalSpaceConstraints signalSpaceConstraints = signalView.createSignalSpaceConstraints(); ExportedSignalSelection selection = null; try { selection = signalAccess.getActiveSelection(); } catch (NoActiveObjectException ex) { // all right, no problem } SignalSpace signalSpace = new SignalSpace(); IcaDialog dialog = new IcaDialog(guiAccess.getDialogParent(), signalSpaceConstraints, selection); dialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); if (dialog.showDialog(signalSpace)) { int[] outputChannels; if (signalSpace.getChannelSpaceType() == ChannelSpaceType.WHOLE_SIGNAL) { int channelCount = signalSpaceConstraints.getChannels().length; outputChannels = new int[channelCount]; for (int i=0; i<channelCount; ++i) { outputChannels[i] = i; } } else { outputChannels = signalSpace.getChannelSpace().getSelectedChannels(); } SignalProcessingChain signalChain = SignalProcessingChain.createFilteredChain(signalDocument.getSampleSource()); Montage montage = signalDocument.getMontage(); if (montage != null) { signalChain.applyMontageDefinition(montage); } RealMatrix output = SignalAnalysisTools.extractDataFromSignal(signalChain.getOutput(), signalSpace.getSelectionTimeSpace(), outputChannels); IcaMethodComputer computer = new IcaMethodComputer(); // transfer matrix from transformed signal to ICA components RealMatrix icaFromOutput = computer.compute(output); // ICA component data RealMatrix ica = icaFromOutput.multiply(output); // transfer matrix from raw signal to ICA components if (montage == null) { montage = new Montage(new SourceMontage(signalDocument)); } RealMatrix outputFromRaw = SignalAnalysisTools.extractMatrixFromMontage(montage, outputChannels); File newFile = SignalAnalysisTools.createRawTemporaryFileFromData(signalAccess, ica); // open generated data in a new tab RawSignalDescriptor newDescriptor = new RawSignalDescriptor(); newDescriptor.setBlocksPerPage(signalDocument.getBlocksPerPage()); newDescriptor.setByteOrder(RawSignalByteOrder.BIG_ENDIAN); newDescriptor.setChannelLabels(SignalAnalysisTools.generateIcaComponentNames(ica.getRowDimension())); newDescriptor.setChannelCount(ica.getRowDimension()); newDescriptor.setSampleCount(ica.getColumnDimension()); newDescriptor.setSampleType(RawSignalSampleType.DOUBLE); newDescriptor.setSamplingFrequency(signalDocument.getSamplingFrequency()); newDescriptor.setSourceFileName(newFile.getName()); IcaSignalDocument newDocument = new IcaSignalDocument(newDescriptor, icaFromOutput, outputFromRaw, montage); newDocument.setBackingFile(newFile); newDocument.openDocument(); DocumentFlowIntegrator dfi = PluginAccessClass.getManager().getDocumentFlowIntegrator(); dfi.getDocumentManager().addDocument(newDocument); dfi.getActionFocusManager().setActiveDocument(newDocument); } } catch (IcaMethodException ex) { JOptionPane.showMessageDialog(guiAccess.getDialogParent(), "ICA method failed: "+ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); } catch (MontageMismatchException ex) { JOptionPane.showMessageDialog(guiAccess.getDialogParent(), "Montage mismatch.", "Error", JOptionPane.ERROR_MESSAGE); } catch (NoActiveObjectException ex) { JOptionPane.showMessageDialog(guiAccess.getDialogParent(), "Choose an active signal first.", "Error", JOptionPane.WARNING_MESSAGE); } catch (SignalMLException ex) { JOptionPane.showMessageDialog(guiAccess.getDialogParent(), "Error: "+ex, "Error", JOptionPane.ERROR_MESSAGE); } catch (IOException ex) { JOptionPane.showMessageDialog(guiAccess.getDialogParent(), "Error: "+ex, "Error", JOptionPane.ERROR_MESSAGE); } } }