net.imglib2.histogram.DiscreteFrequencyDistribution Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of imglib2 Show documentation
Show all versions of imglib2 Show documentation
A multidimensional, type-agnostic image processing library.
/*
* #%L
* ImgLib2: a general-purpose, multidimensional image processing library.
* %%
* Copyright (C) 2009 - 2018 Tobias Pietzsch, Stephan Preibisch, Stephan Saalfeld,
* John Bogovic, Albert Cardona, Barry DeZonia, Christian Dietz, Jan Funke,
* Aivar Grislis, Jonathan Hale, Grant Harris, Stefan Helfrich, Mark Hiner,
* Martin Horn, Steffen Jaensch, Lee Kamentsky, Larry Lindsey, Melissa Linkert,
* Mark Longair, Brian Northan, Nick Perry, Curtis Rueden, Johannes Schindelin,
* Jean-Yves Tinevez and Michael Zinsmaier.
* %%
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* #L%
*/
package net.imglib2.histogram;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import net.imglib2.Cursor;
import net.imglib2.Interval;
import net.imglib2.Positionable;
import net.imglib2.RandomAccess;
import net.imglib2.RealPositionable;
import net.imglib2.img.Img;
import net.imglib2.img.ImgFactory;
import net.imglib2.img.array.ArrayImgFactory;
import net.imglib2.type.numeric.integer.LongType;
/**
* This class represents an n-dimensional set of counters. Histogram
* implementations use these for tracking value counts.
*
* @author Barry DeZonia
*/
public class DiscreteFrequencyDistribution implements Img< LongType >
{
// -- instance variables --
private final Img< LongType > counts;
private final RandomAccess< LongType > accessor;
private long totalValues;
// -- public api --
/**
* Construct an n-dimensional counter with the given number of bins
*/
public DiscreteFrequencyDistribution( final long[] binCounts )
{
// check inputs for issues
for ( int i = 0; i < binCounts.length; i++ )
{
if ( binCounts[ i ] <= 0 ) { throw new IllegalArgumentException( "invalid bin count (<= 0)" ); }
}
// then build object
counts = new ArrayImgFactory<>( new LongType() ).create( binCounts );
accessor = counts.randomAccess();
totalValues = 0;
}
/**
* Construct an n-dimensional counter using a provided {@code Img} to
* store counts.
*/
public DiscreteFrequencyDistribution( final Img< LongType > img )
{
counts = img;
accessor = counts.randomAccess();
resetCounters();
}
/**
* Resets all frequency counts to zero.
*/
public void resetCounters()
{
final Cursor< LongType > cursor = counts.cursor();
while ( cursor.hasNext() )
{
cursor.next().setZero();
}
totalValues = 0;
}
/**
* Returns the frequency count associated with a given bin.
*/
public long frequency( final long[] binPos )
{
for ( int i = 0; i < accessor.numDimensions(); i++ )
{
if ( binPos[ i ] < 0 || binPos[ i ] >= dimension( i ) )
return 0;
}
accessor.setPosition( binPos );
return accessor.get().get();
}
/**
* Sets the frequency count associated with a given bin.
*/
public void setFrequency( final long[] binPos, final long value )
{
if ( value < 0 ) { throw new IllegalArgumentException( "frequency count must be >= 0" ); }
accessor.setPosition( binPos );
final long currentValue = accessor.get().get();
totalValues += ( value - currentValue );
accessor.get().set( value );
}
/**
* Returns the relative frequency {@code (0 <= f <= 1)} associated with a given bin.
*/
public double relativeFrequency( final long[] binPos )
{
if ( totalValues == 0 )
return 0;
return 1.0 * frequency( binPos ) / totalValues;
}
/**
* Increments the frequency count of a specified bin.
*/
public void increment( final long[] binPos )
{
accessor.setPosition( binPos );
accessor.get().inc();
totalValues++;
}
/**
* Decrements the frequency count of a specified bin.
*/
public void decrement( final long[] binPos )
{
accessor.setPosition( binPos );
accessor.get().dec();
totalValues--;
}
/**
* Returns the total number of values counted by this distribution.
*/
public long totalValues()
{
return totalValues;
}
/**
* Returns the highest frequency count found within the bins.
*/
public long modeCount()
{
final List< long[] > modes = modePositions();
return frequency( modes.get( 0 ) );
}
/**
* Returns a list of bin positions of the highest frequency bins.
*/
public List< long[] > modePositions()
{
long commonValue = 0;
final List< long[] > modePositions = new ArrayList< long[] >();
final Cursor< LongType > cursor = localizingCursor();
while ( cursor.hasNext() )
{
final long val = cursor.next().get();
if ( val > commonValue )
{
commonValue = val;
modePositions.clear();
final long[] pos = new long[ numDimensions() ];
cursor.localize( pos );
modePositions.add( pos );
}
else if ( val == commonValue )
{
final long[] pos = new long[ numDimensions() ];
cursor.localize( pos );
modePositions.add( pos );
}
}
return modePositions;
}
// -- Img methods --
@Override
public RandomAccess< LongType > randomAccess()
{
return counts.randomAccess();
}
@Override
public RandomAccess< LongType > randomAccess( final Interval interval )
{
return counts.randomAccess( interval );
}
@Override
public int numDimensions()
{
return counts.numDimensions();
}
@Override
public long min( final int d )
{
return counts.min( d );
}
@Override
public void min( final long[] min )
{
counts.min( min );
}
@Override
public void min( final Positionable min )
{
counts.min( min );
}
@Override
public long max( final int d )
{
return counts.max( d );
}
@Override
public void max( final long[] max )
{
counts.max( max );
}
@Override
public void max( final Positionable max )
{
counts.max( max );
}
@Override
public double realMin( final int d )
{
return counts.realMin( d );
}
@Override
public void realMin( final double[] min )
{
counts.realMin( min );
}
@Override
public void realMin( final RealPositionable min )
{
counts.realMin( min );
}
@Override
public double realMax( final int d )
{
return counts.realMax( d );
}
@Override
public void realMax( final double[] max )
{
counts.realMax( max );
}
@Override
public void realMax( final RealPositionable max )
{
counts.realMax( max );
}
@Override
public void dimensions( final long[] dimensions )
{
counts.dimensions( dimensions );
}
@Override
public long dimension( final int d )
{
return counts.dimension( d );
}
@Override
public Cursor< LongType > cursor()
{
return counts.cursor();
}
@Override
public Cursor< LongType > localizingCursor()
{
return counts.localizingCursor();
}
@Override
public long size()
{
return counts.size();
}
@Override
public LongType firstElement()
{
return counts.firstElement();
}
@Override
public Object iterationOrder()
{
return counts.iterationOrder();
}
@Override
public Iterator< LongType > iterator()
{
return counts.iterator();
}
@Override
public ImgFactory< LongType > factory()
{
return counts.factory();
}
@Override
public DiscreteFrequencyDistribution copy()
{
return new DiscreteFrequencyDistribution( counts.copy() );
}
}