diff --git a/core/src/main/java/tgmm/Ellipsoid.java b/core/src/main/java/tgmm/Ellipsoid.java
new file mode 100644
index 0000000000000000000000000000000000000000..9995887ada5b1a8d6e0b408bcdf37a3b530b5c35
--- /dev/null
+++ b/core/src/main/java/tgmm/Ellipsoid.java
@@ -0,0 +1,59 @@
+package tgmm;
+
+import net.imglib2.RealPoint;
+import net.imglib2.realtransform.AffineTransform3D;
+import net.imglib2.util.LinAlgHelpers;
+import tgmm.TgmmXmlReader.Gaussian;
+import Jama.EigenvalueDecomposition;
+import Jama.Matrix;
+
+public class Ellipsoid extends RealPoint
+{
+	final double[] m;
+
+	final double[][] W;
+
+	final double[][] S;
+
+	final double boundingSphereRadiusSquared;
+
+	public Ellipsoid( final Gaussian gaussian, final AffineTransform3D transform )
+	{
+		super( 3 );
+		m = position;
+
+		final double[] wtmp = new double[9];
+		LinAlgHelpers.scale( gaussian.getW(), gaussian.getNu(), wtmp );
+
+		final Matrix precMat = new Matrix( wtmp, 3 );
+		final Matrix covMat = precMat.inverse();
+		S = covMat.getArray();
+
+		transform.apply( gaussian.getM(), m );
+
+		final double[][] T = new double[3][3];
+		for ( int r = 0; r < 3; ++r )
+			for ( int c = 0; c < 3; ++c )
+				T[r][c] = transform.get( r, c );
+
+		final double[][] TS = new double[3][3];
+		LinAlgHelpers.mult( T, S, TS );
+		LinAlgHelpers.multABT( TS, T, S );
+
+		W = covMat.inverse().getArray();
+
+		final EigenvalueDecomposition eig = covMat.eig();
+		final double[] eigVals = eig.getRealEigenvalues();
+		double max = 0;
+		for ( int k = 0; k < eigVals.length; k++ )
+			max = Math.max( max, eigVals[ k ] );
+		boundingSphereRadiusSquared = max * EllipsoidRealRandomAccessible.nSigmasSquared;
+	}
+
+	public static double squaredMahalanobis( final double[] x, final double[] m, final double[][] W, final double[] tmp1, final double[] tmp2 )
+	{
+		LinAlgHelpers.subtract( x, m, tmp1 );
+		LinAlgHelpers.mult( W, tmp1, tmp2 );
+		return LinAlgHelpers.dot( tmp1, tmp2 );
+	}
+}
\ No newline at end of file
diff --git a/core/src/main/java/tgmm/EllipsoidRealRandomAccessible.java b/core/src/main/java/tgmm/EllipsoidRealRandomAccessible.java
new file mode 100644
index 0000000000000000000000000000000000000000..edafe58cdba34c6ae1734c0872f4b6338d089574
--- /dev/null
+++ b/core/src/main/java/tgmm/EllipsoidRealRandomAccessible.java
@@ -0,0 +1,112 @@
+package tgmm;
+
+import java.util.List;
+
+import net.imglib2.RealInterval;
+import net.imglib2.RealPoint;
+import net.imglib2.RealRandomAccess;
+import net.imglib2.RealRandomAccessible;
+import net.imglib2.collection.KDTree;
+import net.imglib2.neighborsearch.RadiusNeighborSearchOnKDTree;
+import net.imglib2.type.numeric.integer.UnsignedShortType;
+
+public class EllipsoidRealRandomAccessible implements RealRandomAccessible< UnsignedShortType >
+{
+	final static double nSigmas = 2;
+
+	final static double nSigmasSquared = nSigmas * nSigmas;
+
+	final KDTree< Ellipsoid > tree;
+
+	final double maxRadius;
+
+	public EllipsoidRealRandomAccessible( final List< Ellipsoid > ellipsoids )
+	{
+		tree = new KDTree< Ellipsoid >( ellipsoids, ellipsoids );
+		double max = 0;
+		for ( final Ellipsoid e : ellipsoids )
+			max = Math.max( max, e.boundingSphereRadiusSquared );
+		maxRadius = Math.sqrt( max );
+	}
+
+	@Override
+	public int numDimensions()
+	{
+		return 3;
+	}
+
+	@Override
+	public RealRandomAccess< UnsignedShortType > realRandomAccess( final RealInterval interval )
+	{
+		return realRandomAccess();
+	}
+
+	class Access extends RealPoint implements RealRandomAccess< UnsignedShortType >
+	{
+		private final RadiusNeighborSearchOnKDTree< Ellipsoid > search;
+
+		private final UnsignedShortType t = new UnsignedShortType();
+
+		final double[] tmp1 = new double[ 3 ];
+
+		final double[] tmp2 = new double[ 3 ];
+
+		public Access()
+		{
+			super( 3 );
+			search = new RadiusNeighborSearchOnKDTree< Ellipsoid >( tree );
+		}
+
+		private KDTree< Ellipsoid > tree()
+		{
+			return tree;
+		}
+
+		protected Access( final Access a )
+		{
+			super( a );
+			search = new RadiusNeighborSearchOnKDTree< Ellipsoid >( a.tree() );
+		}
+
+		@Override
+		public UnsignedShortType get()
+		{
+//			boolean inBoundingSphere = false;
+			search.search( this, maxRadius, false );
+			final int numNeighbors = search.numNeighbors();
+			for ( int i = 0; i < numNeighbors; ++i )
+			{
+				final Ellipsoid ell = search.getSampler( i ).get();
+				if ( search.getSquareDistance( i ) < ell.boundingSphereRadiusSquared )
+				{
+//					inBoundingSphere = true;
+					if ( Ellipsoid.squaredMahalanobis( this.position, ell.m, ell.W, tmp1, tmp2 ) < nSigmasSquared )
+					{
+						t.set( 1000 );
+						return t;
+					}
+				}
+			}
+			t.set( 0 );
+			return t;
+		}
+
+		@Override
+		public Access copy()
+		{
+			return new Access( this );
+		}
+
+		@Override
+		public Access copyRealRandomAccess()
+		{
+			return copy();
+		}
+	}
+
+	@Override
+	public RealRandomAccess< UnsignedShortType > realRandomAccess()
+	{
+		return new Access();
+	}
+}
diff --git a/core/src/main/java/tgmm/ShowEllipsoids.java b/core/src/main/java/tgmm/ShowEllipsoids.java
new file mode 100644
index 0000000000000000000000000000000000000000..8a2e88a0af651c3c81866504ce96a578edbaedfd
--- /dev/null
+++ b/core/src/main/java/tgmm/ShowEllipsoids.java
@@ -0,0 +1,157 @@
+package tgmm;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import mpicbg.spim.data.SpimDataException;
+import net.imglib2.Interval;
+import net.imglib2.RandomAccessibleInterval;
+import net.imglib2.RealLocalizable;
+import net.imglib2.RealPoint;
+import net.imglib2.RealRandomAccessible;
+import net.imglib2.display.RealARGBColorConverter;
+import net.imglib2.display.RealARGBColorConverter.Imp1;
+import net.imglib2.realtransform.AffineTransform3D;
+import net.imglib2.type.numeric.ARGBType;
+import net.imglib2.type.numeric.integer.UnsignedShortType;
+import net.imglib2.util.Intervals;
+import net.imglib2.view.Views;
+
+import org.jdom2.JDOMException;
+
+import tgmm.TgmmXmlReader.Gaussian;
+import bdv.BigDataViewer;
+import bdv.export.ProgressWriterConsole;
+import bdv.tools.brightness.RealARGBColorConverterSetup;
+import bdv.util.IntervalBoundingBox;
+import bdv.util.ModifiableInterval;
+import bdv.viewer.Interpolation;
+import bdv.viewer.Source;
+import bdv.viewer.SourceAndConverter;
+import bdv.viewer.state.ViewerState;
+
+public class ShowEllipsoids
+{
+	public static class EllipsoidsSource implements Source< UnsignedShortType >
+	{
+		private final ModifiableInterval interval;
+
+		private final HashMap< Integer, EllipsoidRealRandomAccessible > timepointIndexToEllipsoidAccessible;
+
+		private final String name;
+
+		private final UnsignedShortType type;
+
+		protected final AffineTransform3D identity;
+
+		public EllipsoidsSource( final HashMap< Integer, EllipsoidRealRandomAccessible > timepointIndexToEllipsoidAccessible, final String name )
+		{
+			this.timepointIndexToEllipsoidAccessible = timepointIndexToEllipsoidAccessible;
+			this.name = name;
+			this.interval = new ModifiableInterval( Intervals.createMinMax( -100, -100, -100, 100, 100, 100 ) );
+			this.type = new UnsignedShortType();
+			this.identity = new AffineTransform3D();
+		}
+
+		public final ModifiableInterval getInterval( final int t, final int level )
+		{
+			return interval;
+		}
+
+		@Override
+		public boolean isPresent( final int t )
+		{
+			return timepointIndexToEllipsoidAccessible.containsKey( t );
+		}
+
+		@Override
+		public RandomAccessibleInterval< UnsignedShortType > getSource( final int t, final int level )
+		{
+			return Views.interval( Views.raster( timepointIndexToEllipsoidAccessible.get( t ) ), interval );
+		}
+
+		@Override
+		public RealRandomAccessible< UnsignedShortType > getInterpolatedSource( final int t, final int level, final Interpolation method )
+		{
+			return timepointIndexToEllipsoidAccessible.get( t );
+		}
+
+		@Override
+		public AffineTransform3D getSourceTransform( final int t, final int level )
+		{
+			return identity;
+		}
+
+		@Override
+		public UnsignedShortType getType()
+		{
+			return type;
+		}
+
+		@Override
+		public String getName()
+		{
+			return name;
+		}
+
+		@Override
+		public int getNumMipmapLevels()
+		{
+			return 1;
+		}
+	}
+
+	public static void main( final String[] args ) throws IOException, JDOMException, SpimDataException
+	{
+		final int timepointIndex = 245;
+		final String fn = "/Users/pietzsch/desktop/data/BDV130418A325/BDV130418A325_NoTempReg.xml";
+
+		System.setProperty( "apple.laf.useScreenMenuBar", "true" );
+		final BigDataViewer bdv = new BigDataViewer( fn, new File( fn ).getName(), new ProgressWriterConsole() );
+		bdv.getViewer().setTimepoint( timepointIndex );
+
+		final ViewerState viewerState = bdv.getViewer().getState();
+		final int currentSourceId = viewerState.getCurrentSource();
+		final Source< ? > imgSource = viewerState.getSources().get( currentSourceId ).getSpimSource();
+		final Interval imgSourceInterval = imgSource.getSource( timepointIndex, 0 );
+
+		final HashMap< Integer, EllipsoidRealRandomAccessible > timepointIndexToEllipsoidAccessible = new HashMap< Integer, EllipsoidRealRandomAccessible >();
+		for ( int tp = 240; tp < 248; ++tp )
+		{
+			final int timepointId = tp + 1;
+			final String tgmmFilename = "/Users/pietzsch/Desktop/data/Fernando/extract/GMEMfinalResult_frame0" + timepointId + ".xml";
+			System.out.println( tgmmFilename );
+			final ArrayList< Gaussian > gaussians = TgmmXmlReader.read( tgmmFilename );
+			final ArrayList< Ellipsoid > ellipsoids = new ArrayList< Ellipsoid >();
+			final AffineTransform3D imgSourceTransform = imgSource.getSourceTransform( tp, 0 );
+			for ( final Gaussian g : gaussians )
+				ellipsoids.add( new Ellipsoid( g, imgSourceTransform ) );
+			final EllipsoidRealRandomAccessible ellipsoidsAccessible = new EllipsoidRealRandomAccessible( ellipsoids );
+			timepointIndexToEllipsoidAccessible.put( tp, ellipsoidsAccessible );
+		}
+
+		final EllipsoidsSource ellipsoidsSource = new EllipsoidsSource( timepointIndexToEllipsoidAccessible, "ellipsoids" );
+		final Imp1< UnsignedShortType > converter = new RealARGBColorConverter.Imp1< UnsignedShortType >( 0, 3000 );
+		converter.setColor( new ARGBType( ARGBType.rgba( 255, 0, 0, 0 ) ) );
+		final SourceAndConverter< UnsignedShortType > ellipsoidsSourceAndConverter = new SourceAndConverter< UnsignedShortType >( ellipsoidsSource, converter );
+
+		final ArrayList< RealPoint > sourceCorners = new ArrayList< RealPoint >();
+		final AffineTransform3D imgSourceTransform = imgSource.getSourceTransform( timepointIndex, 0 );
+		for ( final RealLocalizable corner : IntervalBoundingBox.getCorners( imgSourceInterval ) )
+		{
+			final RealPoint sourceCorner = new RealPoint( 3 );
+			imgSourceTransform.apply( corner, sourceCorner );
+			sourceCorners.add( sourceCorner );
+		}
+		final Interval bb = Intervals.smallestContainingInterval( IntervalBoundingBox.getBoundingBox( sourceCorners ) );
+		ellipsoidsSource.getInterval( timepointIndex, 0 ).set( bb );
+
+		final int ellipsoidSetupId = 12469; // some non-existing setup id
+		final RealARGBColorConverterSetup cs = new RealARGBColorConverterSetup( ellipsoidSetupId, converter );
+		cs.setViewer( bdv.getViewer() );
+		bdv.getSetupAssignments().addSetup( cs );
+		bdv.getViewer().addSource( ellipsoidsSourceAndConverter );
+	}
+}
diff --git a/core/src/main/java/tgmm/TgmmXmlReader.java b/core/src/main/java/tgmm/TgmmXmlReader.java
new file mode 100644
index 0000000000000000000000000000000000000000..759b0b8df5e94bb5bf0322db2c2f52dd6d46ca4f
--- /dev/null
+++ b/core/src/main/java/tgmm/TgmmXmlReader.java
@@ -0,0 +1,159 @@
+package tgmm;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jdom2.Document;
+import org.jdom2.Element;
+import org.jdom2.JDOMException;
+import org.jdom2.input.SAXBuilder;
+
+public class TgmmXmlReader
+{
+	public static void main( final String[] args )
+	{
+		try
+		{
+			final ArrayList< Gaussian > gaussians = read( "/Users/pietzsch/Desktop/data/Fernando/extract/GMEMfinalResult_frame0249.xml" );
+//			for ( final Gaussian g : gaussians )
+//				System.out.println( g );
+		}
+		catch ( final IOException e )
+		{
+			e.printStackTrace();
+		}
+		catch ( final JDOMException e )
+		{
+			e.printStackTrace();
+		}
+	}
+
+	public static class Gaussian
+	{
+		private final double nu;
+
+		private final double[] m;
+
+		private final double[] W;
+
+		private final int id;
+
+		private final int lineage;
+
+		private final int parent;
+
+		public Gaussian(
+				final double nu,
+				final double[] m,
+				final double[] W,
+				final int id,
+				final int lineage,
+				final int parent )
+		{
+			this.nu = nu;
+			this.m = m;
+			this.W = W;
+			this.id = id;
+			this.lineage = lineage;
+			this.parent = parent;
+		}
+
+		public double getNu()
+		{
+			return nu;
+		}
+
+		public double[] getM()
+		{
+			return m;
+		}
+
+		public double[] getW()
+		{
+			return W;
+		}
+
+		public int getId()
+		{
+			return id;
+		}
+
+		public int getLineage()
+		{
+			return lineage;
+		}
+
+		public int getParent()
+		{
+			return parent;
+		}
+
+		@Override
+		public String toString()
+		{
+			return "Gaussian( " +
+					"nu = " + nu +
+					"m = " + net.imglib2.util.Util.printCoordinates( m ) +
+					"W = " + net.imglib2.util.Util.printCoordinates( W ) +
+					"id = " + id +
+					"lineage = " + lineage +
+					"parent = " + parent +
+					" )";
+		}
+	}
+
+	public static double getDoubleAttribute( final Element parent, final String name )
+	{
+		return Double.parseDouble( parent.getAttributeValue( name ) );
+	}
+
+	public static double[] getDoubleArrayAttribute( final Element parent, final String name )
+	{
+		try
+		{
+			final String text = parent.getAttributeValue( name );
+			final String[] entries = text.split( "\\s+" );
+			final double[] array = new double[ entries.length ];
+			for ( int i = 0; i < entries.length; ++i )
+				array[ i ] = Double.parseDouble( entries[ i ] );
+			return array;
+		}
+		catch ( final Exception e )
+		{
+			final String text = parent.getAttributeValue( name );
+			System.out.println( text );
+			final String[] entries = text.split( "\\s+" );
+			for ( int i = 0; i < entries.length; ++i )
+				System.out.println( entries[ i ] );
+			return null;
+		}
+	}
+
+	public static int getIntAttribute( final Element parent, final String name )
+	{
+		return Integer.parseInt( parent.getAttributeValue( name ) );
+	}
+
+	public static ArrayList< Gaussian > read( final String xmlFilename ) throws IOException, JDOMException
+	{
+		final SAXBuilder sax = new SAXBuilder();
+		final Document doc = sax.build( xmlFilename );
+		final Element root = doc.getRootElement();
+
+		final List< Element > gaussianMixtureModels = root.getChildren( "GaussianMixtureModel" );
+		final ArrayList< Gaussian > gaussians = new ArrayList< Gaussian >();
+		for ( final Element elem : gaussianMixtureModels )
+		{
+			final double nu = getDoubleAttribute( elem, "nu" );
+			final double[] m = getDoubleArrayAttribute( elem, "m" );
+			final double[] W = getDoubleArrayAttribute( elem, "W" );
+			final int id = getIntAttribute( elem, "id" );
+			final int lineage = getIntAttribute( elem, "lineage" );
+			final int parent = getIntAttribute( elem, "parent" );
+
+			gaussians.add( new Gaussian( nu, m, W, id, lineage, parent ) );
+		}
+		return gaussians;
+	}
+}