Skip to content

Commit 21e8517

Browse files
committed
Support for setting threshold when comparing array/table elements
1 parent 9a8d40c commit 21e8517

File tree

6 files changed

+99
-13
lines changed

6 files changed

+99
-13
lines changed

app/save-and-restore/app/src/main/java/org/phoebus/applications/saveandrestore/ui/snapshot/VDeltaCellEditor.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,10 @@ public void updateItem(T item, boolean empty) {
7878
setStyle(TableCellColors.DISCONNECTED_STYLE);
7979
} else if (pair.value == VNoData.INSTANCE) {
8080
setText(pair.value.toString());
81-
} else {
81+
} else if(pair.base == VNoData.INSTANCE){
82+
setText(VNoData.INSTANCE.toString());
83+
}
84+
else {
8285
Utilities.VTypeComparison vtc = Utilities.deltaValueToString(pair.value, pair.base, pair.threshold);
8386
if (vtc.getValuesEqual() != 0 &&
8487
(pair.base instanceof VNumberArray ||

app/save-and-restore/app/src/main/java/org/phoebus/applications/saveandrestore/ui/snapshot/compare/ColumnEntry.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@
66

77
import javafx.beans.property.ObjectProperty;
88
import javafx.beans.property.SimpleObjectProperty;
9+
import org.epics.vtype.VNumber;
910
import org.epics.vtype.VType;
11+
import org.phoebus.applications.saveandrestore.SafeMultiply;
1012
import org.phoebus.applications.saveandrestore.ui.VTypePair;
1113
import org.phoebus.saveandrestore.util.Threshold;
14+
import org.phoebus.saveandrestore.util.Utilities;
1215
import org.phoebus.saveandrestore.util.VNoData;
1316

1417
import java.util.Optional;
@@ -31,7 +34,7 @@ public class ColumnEntry {
3134
*/
3235
private final ObjectProperty<VType> liveValue = new SimpleObjectProperty<>(this, "liveValue", VNoData.INSTANCE);
3336

34-
private final Optional<Threshold<?>> threshold = Optional.empty();
37+
private Optional<Threshold<?>> threshold = Optional.empty();
3538

3639
public ColumnEntry(VType storedValue) {
3740
this.storedValue.set(storedValue);
@@ -54,4 +57,19 @@ public ObjectProperty<VType> liveValueProperty() {
5457
public ObjectProperty<VTypePair> getDelta() {
5558
return delta;
5659
}
60+
61+
/**
62+
* Set the threshold value for this entry. All value comparisons related to this entry are calculated using the
63+
* threshold (if it exists).
64+
*
65+
* @param ratio the threshold
66+
*/
67+
public void setThreshold(double ratio) {
68+
if (storedValue.get() instanceof VNumber) {
69+
VNumber vNumber = SafeMultiply.multiply((VNumber) storedValue.get(), ratio);
70+
boolean isNegative = vNumber.getValue().doubleValue() < 0;
71+
Threshold t = new Threshold<>(isNegative ? SafeMultiply.multiply(vNumber.getValue(), -1.0) : vNumber.getValue());
72+
this.delta.set(new VTypePair(liveValue.get(), storedValue.get(), Optional.of(t)));
73+
}
74+
}
5775
}

app/save-and-restore/app/src/main/java/org/phoebus/applications/saveandrestore/ui/snapshot/compare/ComparisonData.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,13 @@
66

77
import javafx.beans.property.IntegerProperty;
88
import javafx.beans.property.SimpleIntegerProperty;
9+
import org.epics.vtype.VType;
10+
import org.phoebus.applications.saveandrestore.ui.VTypePair;
11+
import org.phoebus.saveandrestore.util.Threshold;
12+
import org.phoebus.saveandrestore.util.Utilities;
913

1014
import java.util.List;
15+
import java.util.Optional;
1116

1217
/**
1318
* Data class for the {@link javafx.scene.control.TableView} of the comparison dialog.
@@ -37,4 +42,14 @@ public IntegerProperty indexProperty() {
3742
public List<ColumnEntry> getColumnEntries() {
3843
return columnEntries;
3944
}
45+
46+
/**
47+
* Set the threshold value for this entry. All value comparisons related to this entry are calculated using the
48+
* threshold (if it exists).
49+
*
50+
* @param ratio the threshold
51+
*/
52+
public void setThreshold(double ratio) {
53+
columnEntries.forEach(columnEntry -> columnEntry.setThreshold(ratio));
54+
}
4055
}

app/save-and-restore/app/src/main/java/org/phoebus/applications/saveandrestore/ui/snapshot/compare/TableComparisonViewController.java

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,14 @@
88
import javafx.beans.property.SimpleStringProperty;
99
import javafx.beans.property.StringProperty;
1010
import javafx.fxml.FXML;
11+
import javafx.geometry.Pos;
1112
import javafx.scene.control.Label;
13+
import javafx.scene.control.Spinner;
14+
import javafx.scene.control.SpinnerValueFactory;
1215
import javafx.scene.control.TableColumn;
1316
import javafx.scene.control.TableView;
17+
import javafx.scene.control.Tooltip;
18+
import javafx.util.converter.DoubleStringConverter;
1419
import org.epics.util.array.ListBoolean;
1520
import org.epics.vtype.VBoolean;
1621
import org.epics.vtype.VBooleanArray;
@@ -31,6 +36,7 @@
3136
import org.epics.vtype.VString;
3237
import org.epics.vtype.VStringArray;
3338
import org.epics.vtype.VType;
39+
import org.phoebus.applications.saveandrestore.Messages;
3440
import org.phoebus.applications.saveandrestore.ui.VTypePair;
3541
import org.phoebus.applications.saveandrestore.ui.snapshot.VDeltaCellEditor;
3642
import org.phoebus.applications.saveandrestore.ui.snapshot.VTypeCellEditor;
@@ -68,11 +74,14 @@ public class TableComparisonViewController {
6874
@FXML
6975
private TableColumn<ComparisonData, VType> liveValueColumn;
7076

71-
7277
@SuppressWarnings("unused")
7378
@FXML
7479
private TableColumn<ComparisonData, VTypePair> deltaColumn;
7580

81+
@SuppressWarnings("unused")
82+
@FXML
83+
private Spinner<Double> thresholdSpinner;
84+
7685
@SuppressWarnings("unused")
7786
@FXML
7887
private Label pvName;
@@ -99,11 +108,18 @@ public void initialize() {
99108
deltaColumn.setComparator(Comparator.comparingDouble(VTypePair::getAbsoluteDelta));
100109

101110
deltaColumn.setCellFactory(e -> new VDeltaCellEditor<>());
111+
112+
SpinnerValueFactory<Double> thresholdSpinnerValueFactory = new SpinnerValueFactory.DoubleSpinnerValueFactory(0.0, 999.0, 0.0, 0.01);
113+
thresholdSpinnerValueFactory.setConverter(new DoubleStringConverter());
114+
thresholdSpinner.setValueFactory(thresholdSpinnerValueFactory);
115+
thresholdSpinner.getEditor().setAlignment(Pos.CENTER_RIGHT);
116+
thresholdSpinner.getEditor().textProperty().addListener((a, o, n) -> parseAndUpdateThreshold(n));
102117
}
103118

104119
/**
105120
* Loads snapshot data and then connects to the corresponding PV.
106-
* @param data Data as stored in a {@link org.phoebus.applications.saveandrestore.model.Snapshot}
121+
*
122+
* @param data Data as stored in a {@link org.phoebus.applications.saveandrestore.model.Snapshot}
107123
* @param pvName The name of the PV.
108124
*/
109125
public void loadDataAndConnect(VType data, String pvName) {
@@ -188,6 +204,7 @@ private void connect() {
188204
/**
189205
* Updates the {@link TableView} from the live data acquired through a PV monitor event.
190206
* Differences in data sizes between stored and live data is considered.
207+
*
191208
* @param liveData EPICS data from the connected PV, or {@link VDisconnectedData#INSTANCE}.
192209
*/
193210
private void updateTable(VType liveData) {
@@ -310,4 +327,31 @@ private void updateTable(VType liveData) {
310327
}
311328
}
312329
}
330+
331+
private void parseAndUpdateThreshold(String value) {
332+
thresholdSpinner.getEditor().getStyleClass().remove("input-error");
333+
thresholdSpinner.setTooltip(null);
334+
335+
double parsedNumber;
336+
try {
337+
parsedNumber = Double.parseDouble(value.trim());
338+
updateThreshold(parsedNumber);
339+
} catch (Exception e) {
340+
thresholdSpinner.getEditor().getStyleClass().add("input-error");
341+
thresholdSpinner.setTooltip(new Tooltip(Messages.toolTipMultiplierSpinner));
342+
}
343+
}
344+
345+
/**
346+
* Computes thresholds on scalar data types. The threshold is used to indicate that a delta value within threshold
347+
* should not decorate the delta column, i.e. consider saved and live values equal.
348+
*
349+
* @param threshold Threshold in percent
350+
*/
351+
private void updateThreshold(double threshold) {
352+
double ratio = threshold / 100;
353+
comparisonTable.getItems().forEach(comparisonData -> {
354+
comparisonData.setThreshold(ratio);
355+
});
356+
}
313357
}

app/save-and-restore/app/src/main/resources/org/phoebus/applications/saveandrestore/ui/snapshot/compare/TableComparisonView.fxml

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,19 @@
55
<?import javafx.scene.control.cell.*?>
66
<?import javafx.scene.layout.*?>
77

8+
89
<BorderPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/17.0.12" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.phoebus.applications.saveandrestore.ui.snapshot.compare.TableComparisonViewController">
10+
<top>
11+
<ToolBar>
12+
<Label fx:id="pvName" style="-fx-font-size: 18;" text="Label" maxWidth="1.7976931348623157E308" minWidth="-Infinity" prefHeight="26.0" HBox.hgrow="ALWAYS">
13+
<BorderPane.margin>
14+
<Insets bottom="10.0" right="5.0" top="5.0" />
15+
</BorderPane.margin>
16+
</Label>
17+
<Label text="%labelThreshold" />
18+
<Spinner fx:id="thresholdSpinner" editable="true" maxWidth="80.0" minWidth="80.0" prefWidth="80.0" />
19+
</ToolBar>
20+
</top>
921
<center>
1022
<TableView fx:id="comparisonTable" prefHeight="600.0" prefWidth="400.0" BorderPane.alignment="CENTER">
1123
<columns>
@@ -24,11 +36,5 @@
2436
</columns>
2537
</TableView>
2638
</center>
27-
<top>
28-
<Label fx:id="pvName" style="-fx-font-size: 18;" text="Label" BorderPane.alignment="CENTER_LEFT">
29-
<BorderPane.margin>
30-
<Insets bottom="10.0" right="5.0" top="5.0" />
31-
</BorderPane.margin>
32-
</Label>
33-
</top>
39+
3440
</BorderPane>

app/save-and-restore/app/src/test/java/org/phoebus/applications/saveandrestore/ui/snapshot/compare/ComparisonDialogDemo.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@ public static void main(String[] args) {
2626
public void start(Stage primaryStage) {
2727

2828
VDoubleArray vDoubleArray =
29-
VDoubleArray.of(ArrayDouble.of(1, 2, 3, 4, 5),
29+
VDoubleArray.of(ArrayDouble.of(1, 2, 3),
3030
Alarm.none(),
3131
Time.now(), Display.none());
3232
ComparisonDialog comparisonDialog =
33-
new ComparisonDialog(vDoubleArray, "loc://x(1, 8, 7, 0)");
33+
new ComparisonDialog(vDoubleArray, "loc://x(1, 1.9, 4, 8)");
3434
comparisonDialog.show();
3535
}
3636
}

0 commit comments

Comments
 (0)