use of org.csstudio.javafx.rtplot.data.ValueRange in project org.csstudio.display.builder by kasemir.
the class PlotProcessor method roundValueRange.
/**
* Round value range up/down to add a little room above & below the exact range.
* This results in "locking" to a nice looking range for a while
* until a new sample outside of the rounded range is added.
*
* @param low Low and
* @param high high end of value range
* @return Adjusted range
*/
public ValueRange roundValueRange(final double low, final double high) {
final double size = Math.abs(high - low);
if (size > 0) {
// Add 2 digits to the 'tight' order of magnitude
final double order_of_magnitude = Math.floor(Log10.log10(size)) - 2;
final double round = Math.pow(10, order_of_magnitude);
return new ValueRange(Math.floor(low / round) * round, Math.ceil(high / round) * round);
} else
return new ValueRange(low, high);
}
use of org.csstudio.javafx.rtplot.data.ValueRange in project org.csstudio.display.builder by kasemir.
the class ImageConfigDialog method createContent.
private Node createContent() {
final GridPane layout = new GridPane();
layout.setHgap(5);
layout.setVgap(5);
// Debug layout
// layout.setGridLinesVisible(true);
// Row to use for the next elements
int row = 0;
Label label = new Label("Value Range");
final Font font = label.getFont();
final Font section_font = Font.font(font.getFamily(), FontWeight.BOLD, font.getSize());
label.setFont(section_font);
layout.add(label, 0, ++row);
// Only show the color mapping selector when it's currently a named mapping.
// Suppress when widget has a custom color map.
final ColorMappingFunction selected_mapping = plot.internalGetImagePlot().getColorMapping();
if (selected_mapping instanceof NamedColorMapping) {
label = new Label("Mapping");
layout.add(label, 1, row);
final ComboBox<String> mappings = new ComboBox<>();
mappings.setEditable(false);
mappings.setMaxWidth(Double.MAX_VALUE);
for (NamedColorMapping mapping : NamedColorMappings.getMappings()) mappings.getItems().add(mapping.getName());
mappings.setValue(((NamedColorMapping) selected_mapping).getName());
mappings.setOnAction(event -> {
final NamedColorMapping mapping = NamedColorMappings.getMapping(mappings.getValue());
plot.setColorMapping(mapping);
});
layout.add(mappings, 2, row++);
}
label = new Label("Minimum");
layout.add(label, 1, row);
final TextField min = new TextField(Double.toString(plot.getValueRange().getLow()));
layout.add(min, 2, row);
label = new Label("Maximum");
layout.add(label, 1, ++row);
final TextField max = new TextField(Double.toString(plot.getValueRange().getHigh()));
layout.add(max, 2, row);
final EventHandler<ActionEvent> update_range = event -> {
try {
plot.setValueRange(Double.parseDouble(min.getText().trim()), Double.parseDouble(max.getText().trim()));
plot.internalGetImagePlot().fireChangedValueRange();
} catch (NumberFormatException ex) {
final ValueRange range = plot.getValueRange();
min.setText(Double.toString(range.getLow()));
max.setText(Double.toString(range.getHigh()));
}
};
min.setOnAction(update_range);
max.setOnAction(update_range);
final CheckBox autoscale = new CheckBox("auto-scale");
autoscale.setSelected(plot.isAutoscale());
min.setDisable(autoscale.isSelected());
max.setDisable(autoscale.isSelected());
autoscale.setOnAction(event -> {
plot.setAutoscale(autoscale.isSelected());
min.setDisable(autoscale.isSelected());
max.setDisable(autoscale.isSelected());
plot.internalGetImagePlot().fireChangedAutoScale();
});
layout.add(autoscale, 2, ++row);
final CheckBox show_color_bar = new CheckBox("show color bar");
show_color_bar.setSelected(plot.isShowingColorMap());
show_color_bar.setOnAction(event -> plot.showColorMap(show_color_bar.isSelected()));
layout.add(show_color_bar, 2, ++row);
final CheckBox logscale = new CheckBox("log scale");
logscale.setSelected(plot.isLogscale());
logscale.setOnAction(event -> {
plot.setLogscale(logscale.isSelected());
plot.internalGetImagePlot().fireChangedLogarithmic();
});
layout.add(logscale, 2, ++row);
label = new Label("Horizontal Axis");
label.setFont(section_font);
layout.add(label, 0, ++row);
row = addAxisContent(layout, row, plot.getXAxis());
label = new Label("Vertical Axis");
label.setFont(section_font);
layout.add(label, 0, ++row);
row = addAxisContent(layout, row, plot.getYAxis());
return layout;
}
use of org.csstudio.javafx.rtplot.data.ValueRange in project org.csstudio.display.builder by kasemir.
the class PlotProcessor method stagger.
/**
* Stagger the range of axes
*/
public void stagger() {
thread_pool.execute(() -> {
final double GAP = 0.1;
// Arrange all axes so they don't overlap by assigning 1/Nth of
// the vertical range to each one
// Determine range of each axes' traces in parallel
final List<YAxisImpl<XTYPE>> y_axes = new ArrayList<>();
final List<AxisRange<Double>> original_ranges = new ArrayList<>();
final List<AxisRange<Double>> new_ranges = new ArrayList<>();
final List<Future<ValueRange>> ranges = new ArrayList<Future<ValueRange>>();
for (YAxisImpl<XTYPE> axis : plot.getYAxes()) {
y_axes.add(axis);
// As fallback, assume that new range matches old range
new_ranges.add(axis.getValueRange());
original_ranges.add(axis.getValueRange());
ranges.add(determineValueRange(axis, plot.getXAxis().getValueRange()));
}
final int N = y_axes.size();
for (int i = 0; i < N; ++i) {
final YAxisImpl<XTYPE> axis = y_axes.get(i);
// Does axis handle itself in another way?
if (axis.isAutoscale())
continue;
// Fetch range of values on this axis
final ValueRange axis_range;
try {
axis_range = ranges.get(i).get();
} catch (Exception ex) {
logger.log(Level.WARNING, "Axis stagger error", ex);
continue;
}
// Skip axis which for some reason cannot determine its range
double low = axis_range.getLow();
double high = axis_range.getHigh();
if (low > high)
continue;
if (low == high) {
// Center trace with constant value (empty range)
final double half = Math.abs(low / 2);
low -= half;
high += half;
}
if (axis.isLogarithmic()) {
// Transition into log space
low = Log10.log10(low);
high = Log10.log10(high);
}
double span = high - low;
// Make some extra space
low -= GAP * span;
high += GAP * span;
span = high - low;
// With N axes, assign 1/Nth of the vertical plot space to this axis
// by shifting the span down according to the axis index,
// using a total of N*range.
low -= (N - i - 1) * span;
high += i * span;
final ValueRange rounded = roundValueRange(low, high);
low = rounded.getLow();
high = rounded.getHigh();
if (axis.isLogarithmic()) {
// Revert from log space
low = Log10.pow10(low);
high = Log10.pow10(high);
}
// Sanity check for empty traces
if (low < high && !Double.isInfinite(low) && !Double.isInfinite(high)) {
final AxisRange<Double> orig = original_ranges.get(i);
final boolean normal = orig.getLow() < orig.getHigh();
new_ranges.set(i, normal ? new AxisRange<Double>(low, high) : new AxisRange<Double>(high, low));
}
}
// 'Stagger' tends to be on-demand,
// or executed infrequently as archived data arrives after a zoom operation
// -> Use undo, which also notifies listeners
plot.getUndoableActionManager().execute(new ChangeAxisRanges<>(plot, Messages.Zoom_Stagger, y_axes, original_ranges, new_ranges, null));
});
}
use of org.csstudio.javafx.rtplot.data.ValueRange in project org.csstudio.display.builder by kasemir.
the class PlotProcessor method autoscale.
/**
* Perform autoscale for all axes that are marked as such
*/
public void autoscale() {
// Determine range of each axes' traces in parallel
final List<YAxisImpl<XTYPE>> all_y_axes = plot.getYAxes();
final List<YAxisImpl<XTYPE>> y_axes = new ArrayList<>();
final List<Future<ValueRange>> ranges = new ArrayList<Future<ValueRange>>();
for (YAxisImpl<XTYPE> axis : all_y_axes) if (axis.isAutoscale()) {
y_axes.add(axis);
ranges.add(determineValueRange(axis, plot.getXAxis().getValueRange()));
}
// If X axis is auto-scale, schedule fetching its range
final Future<AxisRange<XTYPE>> pos_range = plot.getXAxis().isAutoscale() ? determinePositionRange(all_y_axes) : null;
final int N = y_axes.size();
for (int i = 0; i < N; ++i) {
final YAxisImpl<XTYPE> axis = y_axes.get(i);
try {
final ValueRange new_range = ranges.get(i).get();
double low = new_range.getLow(), high = new_range.getHigh();
if (low > high)
continue;
if (low == high) {
// Center trace with constant value (empty range)
final double half = Math.abs(low / 2);
low -= half;
high += half;
}
if (axis.isLogarithmic()) {
// But first, refuse to deal with <= 0
if (low <= 0.0)
low = 1;
if (high <= low)
high = 100;
low = Log10.log10(low);
high = Log10.log10(high);
}
final ValueRange rounded = roundValueRange(low, high);
low = rounded.getLow();
high = rounded.getHigh();
if (axis.isLogarithmic()) {
low = Log10.pow10(low);
high = Log10.pow10(high);
} else {
// Stretch range a little bit
// (but not for log scale, where low just above 0
// could be stretched to <= 0)
final double headroom = (high - low) * 0.05;
low -= headroom;
high += headroom;
}
// Do not use undo, but notify listeners.
if (low != high) {
final AxisRange<Double> orig = axis.getValueRange();
final boolean normal = orig.getLow() < orig.getHigh();
final boolean changed = normal ? axis.setValueRange(low, high) : axis.setValueRange(high, low);
if (changed)
plot.fireYAxisChange(axis);
}
} catch (Exception ex) {
logger.log(Level.WARNING, "Axis autorange error for " + axis, ex);
}
}
if (pos_range == null)
return;
try {
final AxisRange<XTYPE> range = pos_range.get();
if (range == null)
return;
plot.getXAxis().setValueRange(range.getLow(), range.getHigh());
plot.fireXAxisChange();
} catch (Exception ex) {
logger.log(Level.WARNING, "Axis autorange error for " + plot.getXAxis(), ex);
}
}
Aggregations