| Method from org.jfree.data.time.DynamicTimeSeriesCollection Detail: |
public void addSeries(float[] values,
int seriesNumber,
Comparable seriesKey) {
invalidateRangeInfo();
int i;
if (values == null) {
throw new IllegalArgumentException("TimeSeriesDataset.addSeries(): "
+ "cannot add null array of values.");
}
if (seriesNumber >= this.valueHistory.length) {
throw new IllegalArgumentException("TimeSeriesDataset.addSeries(): "
+ "cannot add more series than specified in c'tor");
}
if (this.valueHistory[seriesNumber] == null) {
this.valueHistory[seriesNumber]
= new ValueSequence(this.historyCount);
this.seriesCount++;
}
// But if that series array already exists, just overwrite its contents
// Avoid IndexOutOfBoundsException:
int srcLength = values.length;
int copyLength = this.historyCount;
boolean fillNeeded = false;
if (srcLength < this.historyCount) {
fillNeeded = true;
copyLength = srcLength;
}
//{
for (i = 0; i < copyLength; i++) { // deep copy from values[], caller
// can safely discard that array
this.valueHistory[seriesNumber].enterData(i, values[i]);
}
if (fillNeeded) {
for (i = copyLength; i < this.historyCount; i++) {
this.valueHistory[seriesNumber].enterData(i, 0.0f);
}
}
//}
if (seriesKey != null) {
this.seriesKeys[seriesNumber] = seriesKey;
}
fireSeriesChanged();
}
Adds a series to the dataset. Only the y-values are supplied, the
x-values are specified elsewhere. |
public void addValue(int seriesNumber,
int index,
float value) {
invalidateRangeInfo();
if (seriesNumber >= this.valueHistory.length) {
throw new IllegalArgumentException(
"TimeSeriesDataset.addValue(): series #"
+ seriesNumber + "unspecified in c'tor"
);
}
if (this.valueHistory[seriesNumber] == null) {
this.valueHistory[seriesNumber]
= new ValueSequence(this.historyCount);
this.seriesCount++;
}
// But if that series array already exists, just overwrite its contents
//synchronized(this)
//{
this.valueHistory[seriesNumber].enterData(index, value);
//}
fireSeriesChanged();
}
Adds a value to a series. |
public synchronized RegularTimePeriod advanceTime() {
RegularTimePeriod nextInstant = this.pointsInTime[this.newestAt].next();
this.newestAt = this.oldestAt; // newestAt takes value previously held
// by oldestAT
/***
* The next 10 lines or so should be expanded if data can be negative
***/
// if the oldest data contained a maximum Y-value, invalidate the stored
// Y-max and Y-range data:
boolean extremaChanged = false;
float oldMax = 0.0f;
if (this.maxValue != null) {
oldMax = this.maxValue.floatValue();
}
for (int s = 0; s < getSeriesCount(); s++) {
if (this.valueHistory[s].getData(this.oldestAt) == oldMax) {
extremaChanged = true;
}
if (extremaChanged) {
break;
}
} /*** If data can be < 0, add code here to check the minimum **/
if (extremaChanged) {
invalidateRangeInfo();
}
// wipe the next (about to be used) set of data slots
float wiper = (float) 0.0;
for (int s = 0; s < getSeriesCount(); s++) {
this.valueHistory[s].enterData(this.newestAt, wiper);
}
// Update the array of TimePeriods:
this.pointsInTime[this.newestAt] = nextInstant;
// Now advance "oldestAt", wrapping at end of the array
this.oldestAt++;
if (this.oldestAt >= this.historyCount) {
this.oldestAt = 0;
}
// Update the domain limits:
long startL = this.domainStart.longValue(); //(time is kept in msec)
this.domainStart = new Long(startL + this.deltaTime);
long endL = this.domainEnd.longValue();
this.domainEnd = new Long(endL + this.deltaTime);
this.domainRange = new Range(startL, endL);
fireSeriesChanged();
return nextInstant;
}
Adjust the array offset as needed when a new time-period is added:
Increments the indices "oldestAt" and "newestAt", mod(array length),
zeroes the series values at newestAt, returns the new TimePeriod. |
public void appendData(float[] newData) {
int nDataPoints = newData.length;
if (nDataPoints > this.valueHistory.length) {
throw new IllegalArgumentException(
"More data than series to put them in"
);
}
int s; // index to select the "series"
for (s = 0; s < nDataPoints; s++) {
// check whether the "valueHistory" array member exists; if not,
// create them:
if (this.valueHistory[s] == null) {
this.valueHistory[s] = new ValueSequence(this.historyCount);
}
this.valueHistory[s].enterData(this.newestAt, newData[s]);
}
fireSeriesChanged();
}
|
public void appendData(float[] newData,
int insertionIndex,
int refresh) {
int nDataPoints = newData.length;
if (nDataPoints > this.valueHistory.length) {
throw new IllegalArgumentException(
"More data than series to put them " + "in"
);
}
for (int s = 0; s < nDataPoints; s++) {
if (this.valueHistory[s] == null) {
this.valueHistory[s] = new ValueSequence(this.historyCount);
}
this.valueHistory[s].enterData(insertionIndex, newData[s]);
}
if (refresh > 0) {
insertionIndex++;
if (insertionIndex % refresh == 0) {
fireSeriesChanged();
}
}
}
Appends data at specified index, for loading up with data from file(s). |
protected void findDomainLimits() {
long startL = getOldestTime().getFirstMillisecond(this.workingCalendar);
long endL;
if (this.domainIsPointsInTime) {
endL = getNewestTime().getFirstMillisecond(this.workingCalendar);
}
else {
endL = getNewestTime().getLastMillisecond(this.workingCalendar);
}
this.domainStart = new Long(startL);
this.domainEnd = new Long(endL);
this.domainRange = new Range(startL, endL);
}
Finds the domain limits. Note: this doesn't need to be synchronized
because it's called from within another method that already is. |
protected double findMaxValue() {
double max = 0.0f;
for (int s = 0; s < getSeriesCount(); s++) {
for (int i = 0; i < this.historyCount; i++) {
double tmp = getYValue(s, i);
if (tmp > max) {
max = tmp;
}
}
}
return max;
}
Returns the maximum value. |
protected void fireSeriesChanged() {
seriesChanged(new SeriesChangeEvent(this));
}
|
public Range getDomainBounds(boolean includeInterval) {
if (this.domainRange == null) {
findDomainLimits();
}
return this.domainRange;
}
Returns the range of the values in this dataset's domain. |
public double getDomainLowerBound(boolean includeInterval) {
return this.domainStart.doubleValue();
// a Long kept updated by advanceTime()
}
Returns the minimum x-value in the dataset. |
public double getDomainUpperBound(boolean includeInterval) {
return this.domainEnd.doubleValue();
// a Long kept updated by advanceTime()
}
Returns the maximum x-value in the dataset. |
public Number getEndX(int series,
int item) {
RegularTimePeriod tp = this.pointsInTime[translateGet(item)];
return new Long(tp.getLastMillisecond(this.workingCalendar));
}
|
public Number getEndY(int series,
int item) {
return getY(series, item);
}
|
public int getItemCount(int series) {
// all arrays equal length,
// so ignore argument:
return this.historyCount;
}
Returns the number of items in a series.
For this implementation, all series have the same number of items. |
public int getNewestIndex() {
return this.newestAt;
}
Returns the index of the newest data item. |
public RegularTimePeriod getNewestTime() {
return this.pointsInTime[this.newestAt];
}
|
public int getOldestIndex() {
return this.oldestAt;
}
Returns the index of the oldest data item. |
public RegularTimePeriod getOldestTime() {
return this.pointsInTime[this.oldestAt];
}
|
public int getPosition() {
return this.position;
}
Returns the x position type (START, MIDDLE or END). |
public Range getRangeBounds(boolean includeInterval) {
if (this.valueRange == null) {
double max = getRangeUpperBound(includeInterval);
this.valueRange = new Range(0.0, max);
}
return this.valueRange;
}
|
public double getRangeLowerBound(boolean includeInterval) {
double result = Double.NaN;
if (this.minValue != null) {
result = this.minValue.doubleValue();
}
return result;
}
Returns the minimum range value. |
public double getRangeUpperBound(boolean includeInterval) {
double result = Double.NaN;
if (this.maxValue != null) {
result = this.maxValue.doubleValue();
}
return result;
}
Returns the maximum range value. |
public int getSeriesCount() {
return this.seriesCount;
}
Returns the number of series in the collection. |
public Comparable getSeriesKey(int series) {
return this.seriesKeys[series];
}
Returns the key for a series. |
public Number getStartX(int series,
int item) {
RegularTimePeriod tp = this.pointsInTime[translateGet(item)];
return new Long(tp.getFirstMillisecond(this.workingCalendar));
}
Returns the start x-value. |
public Number getStartY(int series,
int item) {
return getY(series, item);
}
Returns the start y-value. |
public Number getX(int series,
int item) {
RegularTimePeriod tp = this.pointsInTime[translateGet(item)];
return new Long(getX(tp));
}
|
public Number getY(int series,
int item) {
return new Float(getYValue(series, item));
}
|
public double getYValue(int series,
int item) {
// Don't synchronize this!!
// Instead, synchronize the loop that calls it.
ValueSequence values = this.valueHistory[series];
return values.getData(translateGet(item));
}
|
public void invalidateRangeInfo() {
this.maxValue = null;
this.valueRange = null;
}
Invalidates the range info. |
public int offsetFromNewest(int delta) {
return wrapOffset(this.newestAt + delta);
}
Returns the actual index to a time offset by "delta" from newestAt. |
public int offsetFromOldest(int delta) {
return wrapOffset(this.oldestAt + delta);
}
|
public void setPosition(int position) {
this.position = position;
}
Sets the x position type (START, MIDDLE or END). |
public void setSeriesKey(int seriesNumber,
Comparable key) {
this.seriesKeys[seriesNumber] = key;
}
Sets the name of a series. If planning to add values individually. |
public synchronized long setTimeBase(RegularTimePeriod start) {
if (this.pointsInTime[0] == null) {
this.pointsInTime[0] = start;
for (int i = 1; i < this.historyCount; i++) {
this.pointsInTime[i] = this.pointsInTime[i - 1].next();
}
}
long oldestL = this.pointsInTime[0].getFirstMillisecond(
this.workingCalendar
);
long nextL = this.pointsInTime[1].getFirstMillisecond(
this.workingCalendar
);
this.deltaTime = nextL - oldestL;
this.oldestAt = 0;
this.newestAt = this.historyCount - 1;
findDomainLimits();
return this.deltaTime;
}
Fill the pointsInTime with times using TimePeriod.next():
Will silently return if the time array was already populated.
Also computes the data cached for later use by
methods implementing the DomainInfo interface: |
protected int translateGet(int toFetch) {
if (this.oldestAt == 0) {
return toFetch; // no translation needed
}
// else [implicit here]
int newIndex = toFetch + this.oldestAt;
if (newIndex >= this.historyCount) {
newIndex -= this.historyCount;
}
return newIndex;
}
Re-map an index, for use in retrieving data. |
protected int wrapOffset(int protoIndex) {
int tmp = protoIndex;
if (tmp >= this.historyCount) {
tmp -= this.historyCount;
}
else if (tmp < 0) {
tmp += this.historyCount;
}
return tmp;
}
|