use of qupath.lib.gui.tma.TMAEntries.TMAEntry in project qupath by qupath.
the class TMASummaryViewer method createScoresMap.
private Map<String, List<TMAEntry>> createScoresMap(final List<TMAEntry> entries, final String colScore, final String colID) {
// Create a map of entries
Map<String, List<TMAEntry>> scoreMap = new HashMap<>();
for (TMAEntry entry : entries) {
Number score = model.getNumericValue(entry, colScore);
String id = entry.getMetadataValue(colID);
if (id == null && entry.getMeasurement(colID) != null)
id = Double.toString(entry.getMeasurement(colID).doubleValue());
if (id != null && score != null && !Double.isNaN(score.doubleValue())) {
List<TMAEntry> list = scoreMap.get(id);
if (list == null) {
list = new ArrayList<>();
scoreMap.put(id, list);
}
list.add(entry);
}
}
return scoreMap;
}
use of qupath.lib.gui.tma.TMAEntries.TMAEntry in project qupath by qupath.
the class TMASummaryViewer method importScores.
private int importScores(final String text) {
Map<String, List<String>> data = TMAScoreImporter.readCSV(text);
List<String> idColumn = data.remove(TMACoreObject.KEY_UNIQUE_ID);
if (idColumn == null) {
Dialogs.showErrorMessage("Import TMA data", "No '" + TMACoreObject.KEY_UNIQUE_ID + "' column found!");
return 0;
}
// Nothing left to import...
if (data.isEmpty())
return 0;
// Get the numeric columns, if possible
Map<String, double[]> dataNumeric = new HashMap<>();
for (String key : data.keySet().toArray(new String[0])) {
double[] vals = TMAScoreImporter.parseNumeric(data.get(key), true);
if (vals != null && GeneralTools.numNaNs(vals) != vals.length) {
dataNumeric.put(key, vals);
data.remove(key);
}
}
// Loop through IDs, adding values where needed
int counter = 0;
for (int i = 0; i < idColumn.size(); i++) {
boolean matched = false;
String id = idColumn.get(i);
if (id == null) {
logger.debug("Skipping missing ID");
continue;
}
for (TMAEntry entry : entriesBase) {
if (id.equals(entry.getMetadataValue(TMACoreObject.KEY_UNIQUE_ID))) {
matched = true;
for (Entry<String, double[]> dataEntry : dataNumeric.entrySet()) {
entry.putMeasurement(dataEntry.getKey(), dataEntry.getValue()[i]);
}
for (Entry<String, List<String>> dataEntry : data.entrySet()) {
entry.putMetadata(dataEntry.getKey(), dataEntry.getValue().get(i));
}
counter++;
}
}
if (!matched)
logger.warn("No match for ID: " + id);
}
Optional<TMAEntry> objectEntry = entriesBase.stream().filter(t -> t instanceof TMAObjectEntry).findAny();
if (objectEntry.isPresent()) {
Dialogs.showInfoNotification("TMA data update", "TMA cores updated!");
}
return counter;
}
use of qupath.lib.gui.tma.TMAEntries.TMAEntry in project qupath by qupath.
the class TMASummaryViewer method setInputFile.
/**
* Set the input file for the summary viewer.
* @param file
*/
public void setInputFile(File file) {
if (file == null)
return;
if (file.getName().toLowerCase().endsWith(PathPrefs.getSerializationExtension())) {
try {
ImageData<BufferedImage> imageData = PathIO.readImageData(file, null, null, BufferedImage.class);
setTMAEntriesFromImageData(imageData);
} catch (IOException e) {
logger.error("Error reading image data", e);
}
return;
}
List<TMAEntry> entriesTemp = new ArrayList<>();
File dir = file.isDirectory() ? file : file.getParentFile();
for (File fileInput : dir.listFiles()) {
if (fileInput.isHidden() || fileInput.isDirectory() || !fileInput.getName().toLowerCase().endsWith(".qptma"))
continue;
parseInputFile(fileInput, entriesTemp);
}
if (entriesTemp.isEmpty()) {
logger.error("No data found for " + file.getAbsolutePath());
return;
}
setTMAEntries(entriesTemp);
stage.setTitle("TMA Results View: " + dir.getName());
}
use of qupath.lib.gui.tma.TMAEntries.TMAEntry in project qupath by qupath.
the class TMASummaryViewer method createSummaryEntries.
// class SummaryTreeItem extends TreeItem<TMAEntry> implements ChangeListener<Predicate<? super TMAEntry>> {
//
// private TMASummaryEntry entry;
//
// SummaryTreeItem(final TMASummaryEntry entry) {
// super(entry);
// this.entry = entry;
// combinedPredicate.addListener(new WeakChangeListener<Predicate<? super TMAEntry>>(this));
// updateChildren();
// }
//
// private void updateChildren() {
// ArrayList<TreeItem<TMAEntry>> children = new ArrayList<>();
// for (TMAEntry subEntry : entry.getEntries())
// children.add(new TreeItem<>(subEntry));
// super.getChildren().setAll(children);
// }
//
// @Override
// public void changed(ObservableValue<? extends Predicate<? super TMAEntry>> observable,
// Predicate<? super TMAEntry> oldValue, Predicate<? super TMAEntry> newValue) {
// updateChildren();
// }
//
// }
/**
* Create summaries entries by grouping according to Unique ID.
*
* @param entries
* @return
*/
private Collection<? extends TMAEntry> createSummaryEntries(final List<? extends TMAEntry> entries) {
Map<String, TMASummaryEntry> summaryEntryMap = new TreeMap<>();
int maxSummaryLength = 0;
for (TMAEntry entry : entries) {
String id = entry.getMetadataValue(TMACoreObject.KEY_UNIQUE_ID);
if (id == null && entry.getMeasurement(TMACoreObject.KEY_UNIQUE_ID) != null)
id = entry.getMeasurement(TMACoreObject.KEY_UNIQUE_ID).toString();
if (id == null || id.trim().length() == 0) {
if (!"True".equals(entry.getMetadataValue(MISSING_COLUMN)))
logger.trace("No ID found for {}", entry);
continue;
}
TMASummaryEntry summary = summaryEntryMap.get(id);
if (summary == null) {
summary = new TMASummaryEntry(selectedMeasurementCombinationProperty, skipMissingCoresProperty, combinedPredicate);
summaryEntryMap.put(id, summary);
}
summary.addEntry(entry);
maxSummaryLength = Math.max(maxSummaryLength, summary.getEntries().size());
}
// If we don't have any summaries, just return the original entries
if (summaryEntryMap.isEmpty() || maxSummaryLength <= 1)
return entries;
return summaryEntryMap.values();
}
use of qupath.lib.gui.tma.TMAEntries.TMAEntry in project qupath by qupath.
the class TMASummaryViewer method createSidePane.
private Pane createSidePane() {
BorderPane pane = new BorderPane();
TabPane tabPane = new TabPane();
kmDisplay = new KaplanMeierDisplay(null, null, null, null);
BorderPane paneKaplanMeier = new BorderPane();
paneKaplanMeier.setCenter(kmDisplay.getView());
paneKaplanMeier.setPadding(new Insets(10, 10, 10, 10));
// comboMainMeasurement.prefWidthProperty().bind(paneKaplanMeier.widthProperty());
comboMainMeasurement.setMaxWidth(Double.MAX_VALUE);
comboMainMeasurement.setTooltip(new Tooltip("Measurement thresholded to create survival curves etc."));
GridPane kmTop = new GridPane();
kmTop.add(new Label("Score"), 0, 0);
kmTop.add(comboMainMeasurement, 1, 0);
kmTop.add(new Label("Survival type"), 0, 1);
kmTop.add(comboSurvival, 1, 1);
comboSurvival.setTooltip(new Tooltip("Specify overall or recurrence-free survival (if applicable)"));
comboSurvival.setMaxWidth(Double.MAX_VALUE);
GridPane.setHgrow(comboMainMeasurement, Priority.ALWAYS);
GridPane.setHgrow(comboSurvival, Priority.ALWAYS);
kmTop.setHgap(5);
paneKaplanMeier.setTop(kmTop);
// kmDisplay.setOrientation(Orientation.VERTICAL);
histogramDisplay = new HistogramDisplay(model, false);
comboMainMeasurement.getSelectionModel().selectedItemProperty().addListener((v, o, n) -> {
histogramDisplay.refreshCombo();
histogramDisplay.showHistogram(n);
updateSurvivalCurves();
});
comboMeasurementMethod.getSelectionModel().selectedItemProperty().addListener((v, o, n) -> {
histogramDisplay.refreshHistogram();
scatterPane.updateChart();
updateSurvivalCurves();
});
comboSurvival.getSelectionModel().selectedItemProperty().addListener((v, o, n) -> {
updateSurvivalCurves();
});
// Create a Tab for showing images
BorderPane paneImages = new BorderPane();
CheckBox cbShowOverlay = new CheckBox("Show overlay");
imageAvailability.addListener((c, v, n) -> {
if (n == ImageAvailability.OVERLAY_ONLY)
cbShowOverlay.setSelected(true);
else if (n == ImageAvailability.IMAGE_ONLY)
cbShowOverlay.setSelected(false);
cbShowOverlay.setDisable(n != ImageAvailability.BOTH);
});
ListView<TMAEntry> listImages = new ListView<>();
listImages.setCellFactory(v -> new ImageListCell(cbShowOverlay.selectedProperty(), imageCache));
listImages.widthProperty().addListener((v, o, n) -> listImages.refresh());
listImages.setStyle("-fx-control-inner-background-alt: -fx-control-inner-background ;");
table.getSelectionModel().getSelectedItems().addListener((Change<? extends TreeItem<TMAEntry>> e) -> {
List<TMAEntry> entries = new ArrayList<>();
for (TreeItem<TMAEntry> item : e.getList()) {
if (item.getChildren().isEmpty()) {
if (item.getValue().hasImage() || item.getValue().hasOverlay())
entries.add(item.getValue());
} else {
for (TreeItem<TMAEntry> item2 : item.getChildren()) {
if (item2.getValue().hasImage() || item2.getValue().hasOverlay())
entries.add(item2.getValue());
}
}
listImages.getItems().setAll(entries);
}
});
cbShowOverlay.setAlignment(Pos.CENTER);
cbShowOverlay.setMaxWidth(Double.MAX_VALUE);
cbShowOverlay.setPadding(new Insets(5, 5, 5, 5));
cbShowOverlay.selectedProperty().addListener((v, o, n) -> listImages.refresh());
paneImages.setCenter(listImages);
paneImages.setTop(cbShowOverlay);
// Determine visibility based upon whether there are any images to show
// Tab tabImages = new Tab("Images", paneImages);
ScrollPane scrollPane = new ScrollPane(paneKaplanMeier);
scrollPane.setFitToWidth(true);
scrollPane.setFitToHeight(true);
scrollPane.setVbarPolicy(ScrollBarPolicy.AS_NEEDED);
scrollPane.setHbarPolicy(ScrollBarPolicy.AS_NEEDED);
Tab tabSurvival = new Tab("Survival", scrollPane);
tabPane.getTabs().addAll(new Tab("Table", getCustomizeTablePane()), // tabImages,
new Tab("Histogram", histogramDisplay.getPane()), new Tab("Scatterplot", scatterPane.getPane()), tabSurvival);
tabPane.setTabClosingPolicy(TabClosingPolicy.UNAVAILABLE);
// if (imageAvailability.get() != ImageAvailability.NONE)
// tabPane.getTabs().add(1, tabImages);
//
// imageAvailability.addListener((c, v, n) -> {
// if (n == ImageAvailability.NONE)
// tabPane.getTabs().remove(tabImages);
// else if (!tabPane.getTabs().contains(tabImages))
// tabPane.getTabs().add(1, tabImages);
// });
// tabSurvival.visibleProperty().bind(
// Bindings.createBooleanBinding(() -> !survivalColumns.isEmpty(), survivalColumns)
// );
pane.setCenter(tabPane);
pane.setMinWidth(350);
return pane;
}
Aggregations