/*
This file is part of Cyclos (www.cyclos.org).
A project of the Social Trade Organisation (www.socialtrade.org).
Cyclos is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Cyclos is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Cyclos; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package nl.strohalm.cyclos.utils.jfreeAsymmetric;
import java.util.List;
import org.jfree.data.KeyedObjects2D;
import org.jfree.data.Range;
import org.jfree.data.RangeInfo;
import org.jfree.data.general.AbstractDataset;
import org.jfree.data.statistics.MeanAndStandardDeviation;
import org.jfree.data.statistics.StatisticalCategoryDataset;
/**
* This class is a replacement of the JFreeChart DefaultStatisticalCategoryDataset as such, that it can handle asymmetrical error bars around numbers.
* It is not a subClass, but it subclasses the parent of DefaultStatisticalCategoryDataset, and copies the code which does not need change.
*
* @author Rinke
*
*/
public class AsymmetricStatisticalCategoryDataset extends AbstractDataset implements StatisticalCategoryDataset, RangeInfo {
private static final long serialVersionUID = -2787641442478041088L;
// ******************** CHANGED OR NEW CODE (COMPARED TO DefaultStatisticalCategoryDataset)************
// ****************************************************************************************************
// ********************* UNCHANGED CODE (copied from DefaultStatisticalCategoryDataset) **************
// **************************************************************************************************
/** Storage for the data. */
private final KeyedObjects2D data;
/** The minimum range value. */
private double minimumRangeValue;
/** The minimum range value including the standard deviation. */
private double minimumRangeValueIncStdDev;
/** The maximum range value. */
private double maximumRangeValue;
/** The maximum range value including the standard deviation. */
private double maximumRangeValueIncStdDev;
/**
* Creates a new dataset.
*/
public AsymmetricStatisticalCategoryDataset() {
data = new KeyedObjects2D();
minimumRangeValue = Double.NaN;
maximumRangeValue = Double.NaN;
minimumRangeValueIncStdDev = Double.NaN;
maximumRangeValueIncStdDev = Double.NaN;
}
/**
* Adds a mean with an asymmetrical error bar around it to the table.
*
* @param mean the mean.
* @param lower the lower limit of the confidence or error bar
* @param upper the upper limit of the confidence or error bar
* @param rowKey the row key.
* @param columnKey the column key.
*/
@SuppressWarnings("rawtypes")
public void add(final double mean, final double lower, final double upper, final Comparable rowKey, final Comparable columnKey) {
add(new Double(mean), new Double(lower), new Double(upper), rowKey, columnKey);
}
/**
* Adds a mean with an asymmetrical error bar around it to the table.
*
* @param mean the mean.
* @param lower the lower limit of the confidence or error bar
* @param upper the upper limit of the confidence or error bar
* @param rowKey the row key.
* @param columnKey the column key.
*/
@SuppressWarnings("rawtypes")
public void add(final Number mean, final Number lower, final Number upper, final Comparable rowKey, final Comparable columnKey) {
final MeanWithAsymmetricErrorBar item = new MeanWithAsymmetricErrorBar(mean, lower, upper);
data.addObject(item, rowKey, columnKey);
double m = 0.0;
double l = 0.0;
double u = 0.0;
if (mean != null) {
m = mean.doubleValue();
}
if (lower != null) {
l = lower.doubleValue();
}
if (upper != null) {
u = upper.doubleValue();
}
if (!Double.isNaN(m)) {
if (Double.isNaN(maximumRangeValue) || m > maximumRangeValue) {
maximumRangeValue = m;
}
}
if (!Double.isNaN(u)) {
if (Double.isNaN(maximumRangeValueIncStdDev) || u > maximumRangeValueIncStdDev) {
maximumRangeValueIncStdDev = u;
}
}
if (!Double.isNaN(m)) {
if (Double.isNaN(minimumRangeValue) || m < minimumRangeValue) {
minimumRangeValue = m;
}
}
if (!Double.isNaN(l)) {
if (Double.isNaN(minimumRangeValueIncStdDev) || l < minimumRangeValueIncStdDev) {
minimumRangeValueIncStdDev = l;
}
}
fireDatasetChanged();
}
/**
* Tests this instance for equality with an arbitrary object.
*
* @param obj the object (<code>null</code> permitted).
*
* @return A boolean.
*/
@Override
public boolean equals(final Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof AsymmetricStatisticalCategoryDataset)) {
return false;
}
final AsymmetricStatisticalCategoryDataset that = (AsymmetricStatisticalCategoryDataset) obj;
if (!data.equals(that.data)) {
return false;
}
return true;
}
/**
* Returns the number of columns in the table.
*
* @return The column count.
*/
@Override
public int getColumnCount() {
return data.getColumnCount();
}
/**
* Returns the column index for a given key.
*
* @param key the column key.
*
* @return The column index.
*/
@Override
@SuppressWarnings("rawtypes")
public int getColumnIndex(final Comparable key) {
return data.getColumnIndex(key);
}
/**
* Returns a column key.
*
* @param column the column index (zero-based).
*
* @return The column key.
*/
@Override
@SuppressWarnings("rawtypes")
public Comparable getColumnKey(final int column) {
return data.getColumnKey(column);
}
/**
* Returns the column keys.
*
* @return The keys.
*/
@Override
@SuppressWarnings("rawtypes")
public List getColumnKeys() {
return data.getColumnKeys();
}
/**
* returns the lower bound of the error bar
*
* @param row
* @param column
* @return the lower value of the error bar
*/
public Number getLowerValue(final int row, final int column) {
Number result = null;
final MeanWithAsymmetricErrorBar mwaeb = (MeanWithAsymmetricErrorBar) data.getObject(row, column);
if (mwaeb != null) {
result = mwaeb.getLower();
}
return result;
}
/**
* Returns the mean value for an item.
*
* @param rowKey the row key.
* @param columnKey the columnKey.
*
* @return The mean value.
*/
@Override
@SuppressWarnings("rawtypes")
public Number getMeanValue(final Comparable rowKey, final Comparable columnKey) {
Number result = null;
final MeanAndStandardDeviation masd = (MeanAndStandardDeviation) data.getObject(rowKey, columnKey);
if (masd != null) {
result = masd.getMean();
}
return result;
}
/**
* Returns the mean value for an item.
*
* @param row the row index (zero-based).
* @param column the column index (zero-based).
*
* @return The mean value.
*/
@Override
public Number getMeanValue(final int row, final int column) {
Number result = null;
final MeanAndStandardDeviation masd = (MeanAndStandardDeviation) data.getObject(row, column);
if (masd != null) {
result = masd.getMean();
}
return result;
}
/**
* Returns the range of the values in this dataset's range.
*
* @param includeInterval a flag that determines whether or not the y-interval is taken into account.
*
* @return The range.
*/
@Override
public Range getRangeBounds(final boolean includeInterval) {
Range result = null;
if (includeInterval) {
if (!Double.isNaN(minimumRangeValueIncStdDev) && !Double.isNaN(maximumRangeValueIncStdDev)) {
result = new Range(minimumRangeValueIncStdDev, maximumRangeValueIncStdDev);
}
} else {
if (!Double.isNaN(minimumRangeValue) && !Double.isNaN(maximumRangeValue)) {
result = new Range(minimumRangeValue, maximumRangeValue);
}
}
return result;
}
/**
* Returns the minimum y-value in the dataset.
*
* @param includeInterval a flag that determines whether or not the y-interval is taken into account (ignored for this dataset).
*
* @return The minimum value.
*/
@Override
public double getRangeLowerBound(final boolean includeInterval) {
return minimumRangeValue;
}
/**
* Returns the maximum y-value in the dataset.
*
* @param includeInterval a flag that determines whether or not the y-interval is taken into account (ignored for this dataset).
*
* @return The maximum value.
*/
@Override
public double getRangeUpperBound(final boolean includeInterval) {
return maximumRangeValue;
}
/**
* Returns the number of rows in the table.
*
* @return The row count.
*/
@Override
public int getRowCount() {
return data.getRowCount();
}
/**
* Returns the row index for a given key.
*
* @param key the row key.
*
* @return The row index.
*/
@Override
@SuppressWarnings("rawtypes")
public int getRowIndex(final Comparable key) {
return data.getRowIndex(key);
}
/**
* Returns a row key.
*
* @param row the row index (zero-based).
*
* @return The row key.
*/
@Override
@SuppressWarnings("rawtypes")
public Comparable getRowKey(final int row) {
return data.getRowKey(row);
}
/**
* Returns the row keys.
*
* @return The keys.
*/
@Override
@SuppressWarnings("rawtypes")
public List getRowKeys() {
return data.getRowKeys();
}
@Override
@SuppressWarnings("rawtypes")
public Number getStdDevValue(final Comparable rowKey, final Comparable columnKey) {
throw new UnsupportedOperationException("getStdDevValue method is not supported. " + "Use the getUpper and getLower methods in stead.");
}
@Override
public Number getStdDevValue(final int row, final int column) {
throw new UnsupportedOperationException("getStdDevValue method is not supported. " + "Use the getUpper and getLower methods in stead.");
}
/**
* returns the upper bound of the error bar
*
* @param row
* @param column
* @return the upper value of the error bar
*/
public Number getUpperValue(final int row, final int column) {
Number result = null;
final MeanWithAsymmetricErrorBar mwaeb = (MeanWithAsymmetricErrorBar) data.getObject(row, column);
if (mwaeb != null) {
result = mwaeb.getUpper();
}
return result;
}
// **************** Not copied from DefaultStatisticalCategoryDataset ******************
/**
* Returns the value for an item (for this dataset, the mean value is returned).
*
* @param rowKey the row key.
* @param columnKey the columnKey.
*
* @return The value.
*/
@SuppressWarnings("rawtypes")
@Override
public Number getValue(final Comparable rowKey, final Comparable columnKey) {
return getMeanValue(rowKey, columnKey);
}
/**
* Returns the value for an item (for this dataset, the mean value is returned).
*
* @param row the row index.
* @param column the column index.
*
* @return The value.
*/
@Override
public Number getValue(final int row, final int column) {
return getMeanValue(row, column);
}
}