package hep.aida.ref.histogram;
import hep.aida.IAnnotation;
import hep.aida.IDataPoint;
import hep.aida.IDataPointSet;
import hep.aida.IMeasurement;
import hep.aida.ref.AidaUtils;
import hep.aida.ref.Annotation;
import hep.aida.ref.ManagedObject;
import hep.aida.ref.event.AIDAListener;
import hep.aida.ref.event.DataPointSetEvent;
import hep.aida.ref.event.IsObservable;
import java.util.ArrayList;
import java.util.EventObject;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* Basic user-level interface class for holding and managing
* a single set of "data points".
*
* @author The AIDA team @ SLAC.
*
*/
public class DataPointSet extends ManagedObject implements IDataPointSet, IsObservable, AIDAListener {
private int defaultSize = 0;
private IAnnotation annotation;
//private String title;
private int dimension;
private List points;
// Constructors
protected DataPointSet() {
super("");
initDataPointSet();
annotation.addItem(Annotation.titleKey,"Title", true);
}
public DataPointSet(String name, String title, int dimOfPoints) {
this(name, title, dimOfPoints, 0);
}
public DataPointSet(String name, String title, int dimOfPoints, int defaultCapacity) {
this(name, title, dimOfPoints, defaultCapacity, null);
}
public DataPointSet(String name, String title, int dimOfPoints, String options) {
this(name, title, dimOfPoints, 0, options);
}
public DataPointSet(String name, String title, int dimOfPoints, int defaultCapacity, String options) {
super(name);
//this.title = title;
defaultSize = defaultCapacity;
dimension = dimOfPoints;
initDataPointSet();
annotation.addItem(Annotation.titleKey,title, true);
setOptions(options);
}
private void initDataPointSet() {
annotation = new Annotation();
clear();
points = new ArrayList(defaultSize);
for ( int i = 0; i < defaultSize; i++ ) {
DataPoint point = new DataPoint(dimension);
points.add( point );
if (point instanceof IsObservable) {
((IsObservable) point).addListener(this);
}
}
}
private void setOptions(String options) {
if (options == null || options.trim().equals("")) return;
String[] arr = AidaUtils.parseString(options);
if (arr == null || arr.length == 0) return;
ArrayList list = new ArrayList();
for (int i=0; i<arr.length; i++) {
String tmp = arr[i];
if (tmp.length() > 11 && tmp.substring(0, 11).equalsIgnoreCase("annotation.")) {
String key = tmp.substring(11);
int index = key.indexOf("=");
if (index > 0) key = key.substring(0, index);
list.add(key);
}
}
Map optionMap = AidaUtils.parseOptions( options );
Iterator it = optionMap.keySet().iterator();
while (it.hasNext()) {
String key = (String) it.next();
for (int i=0; i<list.size(); i++) {
if (key.equals((String) list.get(i))) {
String val = (String) optionMap.get(key);
if (val != null) annotation.addItem(key, val, true);
}
}
}
}
// End of Constructors
protected java.util.EventObject createEvent() {
return new DataPointSetEvent(this);
}
public IAnnotation annotation() { return annotation; }
public void setAnnotation( IAnnotation annotation ) {this.annotation = annotation; }
public String title() {
//return title;
return annotation.value(Annotation.titleKey);
}
public void setTitle(String title) throws IllegalArgumentException {
//this.title = title;
annotation.setValue(Annotation.titleKey,title);
if (isValid) fireStateChanged();
}
public int dimension() { return dimension; }
public void clear() {
//annotation = new Annotation();
if (points != null && points.size() > 0) {
for (int i=0; i<points.size(); i++) {
removePoint(i);
}
}
points = new ArrayList(defaultSize);
}
public int size() { return points.size(); }
public IDataPoint point(int index) { return (IDataPoint) points.get(index); }
/**
* Set the IDataPoint at a give index in the set.
* This method is not in the IDataSet interface and is here for efficiency reasons
* @param index The IDataPoint index.
* @param point The corresponding IDataPoint to be set at the index
* @throws IllegalArgumentException If the index is < 0 or >= size().
*
*/
public void setPoint(int index, IDataPoint point) throws IllegalArgumentException {
if (index >= points.size() || index < 0) throw new IllegalArgumentException("Wrong argument in setPoint(): index="+index+", size="+points.size());
IDataPoint oldPoint = (IDataPoint) points.get(index);
if (oldPoint instanceof IsObservable) {
((IsObservable) oldPoint).removeListener(this);
}
points.set(index, point);
if (point instanceof IsObservable) {
((IsObservable) point).addListener(this);
}
if (isValid) fireStateChanged();
}
public IDataPoint addPoint() throws java.lang.RuntimeException {
IDataPoint point = new DataPoint(dimension);
addPoint( point );
return point;
}
public void addPoint(IDataPoint point) throws IllegalArgumentException {
if (point.dimension() == dimension) points.add(point);
else throw new IllegalArgumentException("Wrong dimension in addPoint(): DataPointSet.dimension()="+dimension+
", DataPoint.dimension()="+point.dimension());
if (point instanceof IsObservable) {
((IsObservable) point).addListener(this);
}
if (isValid) fireStateChanged();
}
public void removePoint(int index) throws IllegalArgumentException {
if (index >= points.size() || index < 0) throw new IllegalArgumentException("Wrong argument in removePoint() index="+index+", size="+points.size());
IDataPoint point = (IDataPoint) points.remove(index);
if (point instanceof IsObservable) ((IsObservable) point).removeListener(this);
if (point instanceof DataPoint) ((DataPoint) point).clear();
if (isValid) fireStateChanged();
}
public double lowerExtent(int coord) throws IllegalArgumentException {
if (coord<0 || coord>=dimension || points.size()==0)
throw new IllegalArgumentException("Can not calculate lowerExtent: coord="+coord+", size="+points.size());
double lowerExtent = Double.NaN;
for (int i=0; i<points.size(); i++) {
double lower = ((DataPoint) points.get(i)).lowerExtent(coord);
if (Double.isNaN(lowerExtent) || lowerExtent > lower) lowerExtent = lower;
}
return lowerExtent;
}
public double upperExtent(int coord) throws IllegalArgumentException {
if (coord<0 || coord>=dimension || points.size()==0)
throw new IllegalArgumentException("Can not calculate upperExtent: coord="+coord+", size="+points.size());
double upperExtent = Double.NaN;
for (int i=0; i<points.size(); i++) {
double upper = ((DataPoint) points.get(i)).upperExtent(coord);
if (Double.isNaN(upperExtent) || upper > upperExtent ) upperExtent = upper;
}
return upperExtent;
}
public void scale(double scaleFactor) throws IllegalArgumentException {
if (scaleFactor<=0)
throw new IllegalArgumentException("Illegal scale factor: scaleFactor="+scaleFactor);
for (int i=0; i<points.size(); i++) {
IDataPoint p = (IDataPoint) points.get(i);
for (int j=0; j<dimension; j++) {
IMeasurement meas = p.coordinate(j);
meas.setValue(meas.value() * scaleFactor);
meas.setErrorMinus(meas.errorMinus() * scaleFactor);
meas.setErrorPlus(meas.errorPlus() * scaleFactor);
}
}
if (isValid) fireStateChanged();
}
public void scaleValues(double scaleFactor) throws IllegalArgumentException {
if (scaleFactor<=0)
throw new IllegalArgumentException("Illegal scale factor: scaleFactor="+scaleFactor);
for (int i=0; i<points.size(); i++) {
IDataPoint p = (IDataPoint) points.get(i);
for (int j=0; j<dimension; j++) {
IMeasurement meas = p.coordinate(j);
meas.setValue(meas.value() * scaleFactor);
}
}
if (isValid) fireStateChanged();
}
public void scaleErrors(double scaleFactor) throws IllegalArgumentException {
if (scaleFactor<=0)
throw new IllegalArgumentException("Illegal scale factor: scaleFactor="+scaleFactor);
for (int i=0; i<points.size(); i++) {
IDataPoint p = (IDataPoint) points.get(i);
for (int j=0; j<dimension; j++) {
IMeasurement meas = p.coordinate(j);
meas.setErrorMinus(meas.errorMinus() * scaleFactor);
meas.setErrorPlus(meas.errorPlus() * scaleFactor);
}
}
if (isValid) fireStateChanged();
}
public void setCoordinate(int coord, double[] values, double[] errors) throws IllegalArgumentException {
setCoordinate(coord, values, errors, errors);
}
public void setCoordinate(int coord, double[] values, double[] errp, double[] errm) throws IllegalArgumentException {
if ( coord < 0 || coord >= dimension() ) throw new IllegalArgumentException("Illegal coordinate "+coord+"!! It has to be 0 <= coord < "+dimension());
int nPoints = values.length;
if ( nPoints != errp.length ) throw new IllegalArgumentException("Incompatible array sizes! Value's size "+nPoints+" while error's size is "+errp.length);
if ( nPoints != errm.length ) throw new IllegalArgumentException("Incompatible array sizes! Value's size "+nPoints+" while error's size is "+errm.length);
if ( size() == 0 )
addNPoints(nPoints);
if ( nPoints != size() ) throw new IllegalArgumentException("Array size "+nPoints+" is incompatible with the number of points "+size());
for ( int i = 0; i < nPoints; i++ ) {
IMeasurement meas = point(i).coordinate(coord);
meas.setValue( values[i] );
meas.setErrorMinus( errm[i] );
meas.setErrorPlus( errp[i] );
}
}
/**
* Non-AIDA methods.
*
*/
protected void setDimension( int dimOfPoints ) {
dimension = dimOfPoints;
}
private void addNPoints( int n ) {
for( int i = 0; i < n; i++ )
addPoint();
}
protected void finalize() throws Throwable {
defaultSize = 0;
clear();
}
// AIDAListener interface
public void stateChanged(EventObject e) {
//System.out.println("DataPointSet.stateChanged isValid="+isValid);
if (isValid) fireStateChanged();
}
} // class or interface