/* EegSignalTypeConfigurer.java created 2007-11-22
*
*/
package org.signalml.domain.montage;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Polygon;
import java.awt.RenderingHints;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import org.signalml.app.document.signal.SignalDocument;
import org.signalml.domain.montage.system.IChannelFunction;
import org.signalml.domain.montage.generators.RawMontageGenerator;
import org.signalml.domain.montage.system.ChannelFunction;
/**
* This class represents the {@link SignalTypeConfigurer configurer} for
* an EEG signal.
* It configures (or creates) a {@link Montage montage} to be an EEG montage.
* Contains generators for different EEG montages
* (left and right ear, linked ears, longitudinal, transverse).
* Returns the backdrop for the signal of that type.
*
* @author Michal Dobaczewski © 2007-2008 CC Otwarte Systemy Komputerowe Sp. z o.o.
*/
public class SignalConfigurer {
/**
* The 'length' of an ear or nose (the triangle) on the backdrop image.
* (How much an ear 'protrudes').
*/
public static final int EAR_OR_NOSE_LENGTH = 30;
/**
* The 'width' of an ear or nose (marked as a triangle) on the backdrop
* image.
*/
public static final int EAR_OR_NOSE_WIDTH = 34;
/**
* the predefined raw MontageGenerator
*/
private static final RawMontageGenerator rawMontageGenerator = new RawMontageGenerator();
/**
* the cached backdrop
*/
private Image cachedBackdrop = null;
/**
* the width (pixels) of the cached backdrop
*/
private int cachedBackdropWidth;
/**
* the height (pixels) of the cached backdrop
*/
private int cachedBackdropHeight;
/**
* Creates the {@link Montage montage} with channelCount channels for
* a EEG signal
* @param channelCount the desired number of channels for the montage
* @return the created montage
*/
public static Montage createMontage(int channelCount) {
Montage montage = new Montage(new SourceMontage(channelCount));
rawMontageGenerator.createMontage(montage);
return montage;
}
/**
* Creates the {@link Montage montage} based on the
* {@link SignalDocument document} with a signal
* @return the created montage
*/
public static Montage createMontage(SignalDocument signalDocument) {
Montage montage = new Montage(new SourceMontage(signalDocument));
rawMontageGenerator.createMontage(montage);
return montage;
}
/**
* Returns an {@link EegChannel eegChannel} of type 'UNKNOWN'
* @return EegChannel.UNKNOWN
*/
public static IChannelFunction genericChannel() {
return ChannelFunction.UNKNOWN;
}
/**
* Creates the backdrop for electrodes positions matrix.
* If backdrop parameters haven't changed and cachedBackdrop exists,
* it is used.
* @param width the width of the backdrop
* @param height the height of the backdrop
* @return an Image with backdrop for electrodes positions matrix
*/
public Image getMatrixBackdrop(int width, int height) {
if (width < 60 || height < 60) {
return null;
}
if (cachedBackdrop == null || cachedBackdropWidth != width || cachedBackdropHeight != height) {
cachedBackdrop = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = (Graphics2D) cachedBackdrop.getGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, width, height);
g.setColor(Color.BLACK);
g.setStroke(new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.CAP_ROUND));
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Area head = new Area(new Ellipse2D.Float(20, 20, width-41, height-41));
int noseX = ((width-40)/2) + 20;
int earY = (height-20)/2 + 20;
Area nose = new Area(new Polygon(new int[] { noseX, noseX-EAR_OR_NOSE_WIDTH/2, noseX+EAR_OR_NOSE_WIDTH/2}, new int[] { 0, EAR_OR_NOSE_LENGTH, EAR_OR_NOSE_LENGTH }, 3));
Area lEar = new Area(new Polygon(new int[] { 0, EAR_OR_NOSE_LENGTH, EAR_OR_NOSE_LENGTH}, new int [] { earY, earY-EAR_OR_NOSE_WIDTH/2, earY+EAR_OR_NOSE_WIDTH/2 }, 3));
Area rEar = new Area(new Polygon(new int[] { width-1, width-31, width-31 }, new int [] { earY, earY-EAR_OR_NOSE_WIDTH/2, earY+EAR_OR_NOSE_WIDTH/2 }, 3));
head.add(nose);
head.add(lEar);
head.add(rEar);
g.setColor(Color.DARK_GRAY);
g.draw(head);
cachedBackdropWidth = width;
cachedBackdropHeight = height;
}
return cachedBackdrop;
}
}