use of org.csstudio.archive.vtype.ArchiveVStatistics in project org.csstudio.display.builder by kasemir.
the class CSVSampleImporter method importValues.
/**
* {@inheritDoc}
*/
@Override
public List<VType> importValues(final InputStream input) throws Exception {
// To be reentrant, need per-call parsers
final DateFormat date_parser = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
final Pattern pattern = Pattern.compile(// YYYY/MM/DD HH:MM:SS.SSSSSSSSS value ignore
"\\s*([0-9][0-9][0-9][0-9][-/][0-9][0-9][-/][0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]\\.[0-9]*)[ \\t,]+([-+0-9.,eE]+)\\s*.*");
final Pattern statisticsPattern = Pattern.compile(// YYYY/MM/DD HH:MM:SS.SSSSSSSSS value negativeError positiveError ignore
"\\s*([0-9][0-9][0-9][0-9][-/][0-9][0-9][-/][0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]\\.[0-9]*)[ \\t,]+([-+0-9.,eE]+)[ \\t,]+([-+0-9.,eE]+)[ \\t,]+([-+0-9.,eE]+)\\s*.*");
final List<VType> values = new ArrayList<VType>();
final BufferedReader reader = new BufferedReader(new InputStreamReader(input));
String line;
char groupingSeparator = DecimalFormatSymbols.getInstance().getGroupingSeparator();
char decimalSeparator = DecimalFormatSymbols.getInstance().getDecimalSeparator();
boolean statistics = true;
while ((line = reader.readLine()) != null) {
line = line.trim();
// Skip empty lines, comments
if (line.length() <= 0 || line.startsWith("#"))
continue;
statistics = true;
// Locate time and value
// Is statistical data?
Matcher matcher = statisticsPattern.matcher(line);
if (!matcher.matches()) {
// Not statistical data, try normal
matcher = pattern.matcher(line);
if (!matcher.matches()) {
logger.log(Level.INFO, "Ignored input: {0}", line);
continue;
}
statistics = false;
}
// Parse
// Date may use '-' or '/' as separator. Force '-'
String date_text = matcher.group(1).replace('/', '-');
// Can only parse up to millisecs, so limit length
if (date_text.length() > 23)
date_text = date_text.substring(0, 23);
final Date date = date_parser.parse(date_text);
// Double.parseDouble only parses numbers in format #.#... or #.#...#E0, meaning
// that you cannot have any grouping separators, and the decimal separator must be '.'
// First remove all grouping separators, then replace the decimal separator with a '.'
final double number = Double.parseDouble(remove(matcher.group(2), groupingSeparator).replace(decimalSeparator, '.'));
final Instant time = TimestampHelper.fromMillisecs(date.getTime());
if (statistics) {
final double min = Double.parseDouble(remove(matcher.group(3), groupingSeparator).replace(decimalSeparator, '.'));
final double max = Double.parseDouble(remove(matcher.group(4), groupingSeparator).replace(decimalSeparator, '.'));
values.add(new ArchiveVStatistics(time, AlarmSeverity.NONE, "", meta_data, number, number - min, number + max, 0, 1));
} else {
values.add(new ArchiveVNumber(time, AlarmSeverity.NONE, "", meta_data, number));
}
}
reader.close();
return values;
}
use of org.csstudio.archive.vtype.ArchiveVStatistics in project org.csstudio.display.builder by kasemir.
the class FormulaItem method compute.
/**
* Evaluate formula for each input sample
* <p>
* Iterates over the input samples in a manner of spreadsheet or
* staircase-interpolation: An input with a time stamp is valid
* until there's a sample with a greater time stamp.
*/
private void compute() {
final List<PlotSample> result = new ArrayList<PlotSample>();
final Display display = ValueFactory.displayNone();
try {
// Prevent changes to formula & inputs
synchronized (this) {
// 'Current' value for each input or null when no more
// In computation loop, values is actually moved to the _next_
// value
final VType[] values = new VType[inputs.length];
// 'Current' numeric min/val/max of values
final double[] min = new double[inputs.length];
final double[] val = new double[inputs.length];
final double[] max = new double[inputs.length];
// Determine first sample for each input
boolean more_input = false;
for (int i = 0; i < values.length; i++) {
// Initially, none have any data
min[i] = val[i] = max[i] = Double.NaN;
// Is there an initial value for any input?
values[i] = inputs[i].first();
if (values[i] != null)
more_input = true;
}
// Compute result for each 'line in the spreadsheet'
Instant time;
while (more_input) {
// Find oldest time stamp of all the inputs
time = null;
for (int i = 0; i < values.length; i++) {
if (values[i] == null)
continue;
final Instant sample_time = VTypeHelper.getTimestamp(values[i]);
if (time == null || sample_time.compareTo(time) < 0)
time = sample_time;
}
if (time == null) {
// No input left with any data
more_input = false;
break;
}
// 'time' now defines the current spreadsheet line.
// Set min/max/val to sample from each input for that time.
// This might move values[i] resp. the inputs' iterators
// to the 'next' sample
boolean have_min_max = true;
for (int i = 0; i < values.length; i++) {
if (// No more data
values[i] == null) {
min[i] = val[i] = max[i] = Double.NaN;
have_min_max = false;
} else if (VTypeHelper.getTimestamp(values[i]).compareTo(time) <= 0) {
// Input is valid before-and-up-to 'time'
if (values[i] instanceof VStatistics) {
final VStatistics mmv = (VStatistics) values[i];
min[i] = mmv.getMin();
val[i] = mmv.getAverage();
max[i] = mmv.getMax();
} else {
min[i] = max[i] = Double.NaN;
val[i] = VTypeHelper.toDouble(values[i]);
// Use NaN for any non-number
if (Double.isInfinite(val[i]))
val[i] = Double.NaN;
have_min_max = false;
}
// Move to next input sample
values[i] = inputs[i].next();
} else {
// Just update the have_min_max flag
if (Double.isNaN(min[i]) || Double.isNaN(max[i]))
have_min_max = false;
}
}
// Set variables[] from val to get res_val
for (int i = 0; i < values.length; i++) variables[i].setValue(val[i]);
// Evaluate formula for these inputs
final double res_val = formula.eval();
final VType value;
if (have_min_max) {
// Set variables[] from min
for (int i = 0; i < values.length; i++) variables[i].setValue(min[i]);
final double res_min = formula.eval();
// Set variables[] from max
for (int i = 0; i < values.length; i++) variables[i].setValue(max[i]);
final double res_max = formula.eval();
value = new ArchiveVStatistics(time, AlarmSeverity.NONE, Messages.Formula, display, res_val, res_min, res_max, 0.0, 1);
} else {
// No min/max.
if (Double.isNaN(res_val))
value = new ArchiveVNumber(time, AlarmSeverity.INVALID, Messages.Formula, display, res_val);
else
value = new ArchiveVNumber(time, AlarmSeverity.NONE, ArchiveVType.STATUS_OK, display, res_val);
}
result.add(new PlotSample(Messages.Formula, value));
}
}
} catch (Exception ex) {
logger.log(Level.WARNING, "Error computing " + this, ex);
}
// Update PlotSamples
samples.set(result);
}
Aggregations