/* SingleChannelReferenceMontageGenerator.java created 2007-11-23 * */ package org.signalml.domain.montage.generators; import org.signalml.app.model.components.validation.ValidationErrors; import org.signalml.domain.montage.system.ChannelType; import org.signalml.domain.montage.Montage; import org.signalml.domain.montage.MontageException; import org.signalml.domain.montage.SourceChannel; import org.signalml.domain.montage.SourceMontage; import org.signalml.domain.montage.system.ChannelFunction; import org.springframework.validation.Errors; /** * This class represents a generator for a single reference montage. * In single reference montage each channel represents the difference between * a certain electrode and a designated reference electrode. * There is no standard position for this reference; it is, however, at a different * position than the "recording" electrodes. Midline positions are often used because * they do not amplify the signal in one hemisphere vs. the other. * Another popular reference is "linked ears," which is a physical or mathematical * average of electrodes attached to both earlobes or mastoids. * (source: {@code http://en.wikipedia.org/wiki/Electroencephalography}) * * This class generates montage of that type from the given "raw" montage and checks if * the given {@link SourceMontage montages} are valid single reference montages. * * @author Michal Dobaczewski © 2007-2008 CC Otwarte Systemy Komputerowe Sp. z o.o. */ public class SingleReferenceMontageGenerator extends AbstractMontageGenerator { private static final long serialVersionUID = 1L; /** * the label of a {@link SourceChannel source channel} * which will be a reference channel */ protected transient String referenceChannelName; /** * Constructor. Creates a new generator based on label * of a reference channel. * @param refChannel label of a {@link SourceChannel source channel} * that will be used as reference channel in a created * {@link Montage montage} */ public SingleReferenceMontageGenerator(String referenceChannelName) { if (referenceChannelName == null) { throw new NullPointerException("Channel cannot be null"); } this.referenceChannelName = referenceChannelName; } /** * Creates a single channel reference montage from a given * {@link Montage montage}. * @param montage a montage to be used * @throws MontageException thrown if there is no channel having the * label equal to the reference channel label */ @Override public void createMontage(Montage montage) throws MontageException { SourceChannel referenceSourceChannel = montage.getSourceChannelByLabel(referenceChannelName); if (referenceSourceChannel == null) { throw new MontageException("Cannot find " + referenceChannelName + " source channel for single reference montage generator "); } boolean oldMajorChange = montage.isMajorChange(); try { montage.setMajorChange(true); montage.reset(); int size = montage.getSourceChannelCount(); int index; for (int i=0; i<size; i++) { index = montage.addMontageChannel(i); SourceChannel sourceChannel = montage.getSourceChannelAt(i); if (sourceChannel.getFunction() == ChannelFunction.EEG && !sourceChannel.isChannelType(ChannelType.REFERENCE)) { montage.setReference(index, referenceSourceChannel.getChannel(), "-1"); } } } finally { montage.setMajorChange(oldMajorChange); } montage.setMontageGenerator(this); montage.setChanged(false); } /** * Checks if {@link Montage montage} is a valid single channel * reference montage. * @param sourceMontage a montage to be checked * @param errors an Errors object used to report errors * @return true if the montage is a valid single channel reference montage, * false otherwise */ @Override public boolean validateSourceMontage(SourceMontage sourceMontage, ValidationErrors errors) { SourceChannel sourceChannel = sourceMontage.getSourceChannelByLabel(referenceChannelName); if (sourceChannel == null) { onNotFound(referenceChannelName, errors); return false; } return true; } }