Search in sources :

Example 11 with TMACoreObject

use of qupath.lib.objects.TMACoreObject in project qupath by qupath.

the class TMADataIO method importDearrayedTMAData.

/**
 * Import a TMA grid from an exported TMA analysis file, i.e. with extension ".qptma"
 *
 * @param file
 * @return
 */
public static TMAGrid importDearrayedTMAData(final File file) {
    try (Scanner scanner = new Scanner(file)) {
        int gridWidth = -1;
        int gridHeight = -1;
        String line = null;
        while (scanner.hasNextLine()) {
            line = scanner.nextLine();
            if (line.startsWith("TMA grid width:"))
                gridWidth = Integer.parseInt(line.replace("TMA grid width:", "").trim());
            else if (line.startsWith("TMA grid height:"))
                gridHeight = Integer.parseInt(line.replace("TMA grid height:", "").trim());
            if (gridWidth >= 0 && gridHeight >= 0)
                break;
        }
        if (gridWidth <= 0 || gridHeight <= 0) {
            logger.error("No grid dimensions available!");
            return null;
        }
        Map<String, List<String>> csvData = TMAScoreImporter.readCSV(scanner);
        List<String> colNames = csvData.get("Core name");
        List<String> colX = csvData.get("X");
        List<String> colY = csvData.get("Y");
        List<String> colWidth = csvData.get("Width");
        List<String> colHeight = csvData.get("Height");
        List<String> colPresent = csvData.get("Present");
        List<String> colID = csvData.get(TMACoreObject.KEY_UNIQUE_ID);
        if (colX == null || colY == null || colWidth == null || colHeight == null) {
            logger.error("No core locations available!");
            return null;
        }
        // int count = 0;
        List<TMACoreObject> cores = new ArrayList<>();
        for (int i = 0; i < colX.size(); i++) {
            double x = Double.parseDouble(colX.get(i));
            double y = Double.parseDouble(colY.get(i));
            double w = Double.parseDouble(colWidth.get(i));
            double h = Double.parseDouble(colHeight.get(i));
            boolean present = colPresent == null ? true : Boolean.parseBoolean(colPresent.get(i));
            String name = colNames == null ? null : colNames.get(i);
            String id = colID == null ? null : colID.get(i);
            TMACoreObject core = PathObjects.createTMACoreObject(x, y, w, h, !present);
            if (name != null)
                core.setName(name);
            if (id != null && !id.isEmpty())
                core.setUniqueID(id);
            cores.add(core);
        }
        return DefaultTMAGrid.create(cores, gridWidth);
    } catch (FileNotFoundException e) {
        logger.error("Cannot find file: {}", file);
        return null;
    }
}
Also used : Scanner(java.util.Scanner) TMACoreObject(qupath.lib.objects.TMACoreObject) ArrayList(java.util.ArrayList) FileNotFoundException(java.io.FileNotFoundException) ArrayList(java.util.ArrayList) List(java.util.List)

Example 12 with TMACoreObject

use of qupath.lib.objects.TMACoreObject in project qupath by qupath.

the class TMASummaryViewer method getEntriesForTMAData.

private static List<TMAEntry> getEntriesForTMAData(final ImageData<BufferedImage> imageData) {
    List<TMAEntry> entriesNew = new ArrayList<>();
    if (imageData.getHierarchy().getTMAGrid() == null)
        return entriesNew;
    ObservableMeasurementTableData data = new ObservableMeasurementTableData();
    data.setImageData(imageData, imageData.getHierarchy().getTMAGrid().getTMACoreList());
    for (TMACoreObject core : imageData.getHierarchy().getTMAGrid().getTMACoreList()) {
        entriesNew.add(TMAEntries.createTMAObjectEntry(imageData, data, core));
    }
    return entriesNew;
}
Also used : ObservableMeasurementTableData(qupath.lib.gui.measure.ObservableMeasurementTableData) TMACoreObject(qupath.lib.objects.TMACoreObject) TMAEntry(qupath.lib.gui.tma.TMAEntries.TMAEntry) ArrayList(java.util.ArrayList)

Example 13 with TMACoreObject

use of qupath.lib.objects.TMACoreObject in project qupath by qupath.

the class TMAScoreImporter method importFromCSV.

private static int importFromCSV(final Map<String, List<String>> map, final PathObjectHierarchy hierarchy) {
    TMAGrid tmaGrid = hierarchy.getTMAGrid();
    if (tmaGrid == null || tmaGrid.nCores() == 0) {
        logger.error("No TMA grid found!");
        return 0;
    }
    // Try to get a 'core' column
    String coreKey = null;
    for (String key : map.keySet()) {
        if (key.trim().toLowerCase().equals("core")) {
            coreKey = key;
            break;
        }
    }
    List<String> coreNames = coreKey == null ? null : map.remove(coreKey);
    // Try to get a unique ID column
    List<String> coreIDs = map.remove(TMACoreObject.KEY_UNIQUE_ID);
    // If we don't have a core column OR a unique ID column, we can't do anything
    if (coreNames == null && coreIDs == null) {
        logger.error("No column with header 'core' or '" + TMACoreObject.KEY_UNIQUE_ID + "' found");
        return 0;
    }
    // int n = coreNames == null ? coreIDs.size() : coreNames.size();
    // Get a list of cores ordered by whatever info we have
    Map<Integer, List<TMACoreObject>> cores = new HashMap<>();
    boolean coresFound = false;
    // If we have any unique IDs, use these and change names accordingly - if possible, and necessary
    if (coreIDs != null) {
        int i = 0;
        for (String id : coreIDs) {
            List<TMACoreObject> coresByID = new ArrayList<>();
            for (TMACoreObject coreTemp : tmaGrid.getTMACoreList()) if (id != null && id.equals(coreTemp.getUniqueID()))
                coresByID.add(coreTemp);
            if (!coresByID.isEmpty()) {
                cores.put(i, coresByID);
                coresFound = true;
                if (coreNames != null && coresByID.size() == 1) {
                    String currentName = coresByID.get(0).getName();
                    String newName = coreNames.get(i);
                    if (!newName.equals(currentName)) {
                        coresByID.get(0).setName(newName);
                        if (currentName != null)
                            logger.warn("Core name changed from {} to {}", currentName, newName);
                    }
                }
            }
            i++;
        }
    }
    // If we didn't have any unique IDs, we need to work with core names instead
    if (!coresFound && coreNames != null) {
        int i = 0;
        for (String name : coreNames) {
            TMACoreObject core = tmaGrid.getTMACore(name);
            if (core != null) {
                cores.put(i, Collections.singletonList(core));
                coresFound = true;
                if (coreIDs != null) {
                    String currentID = core.getUniqueID();
                    String newID = coreIDs.get(i);
                    if (newID != null && !newID.equals(currentID)) {
                        core.setUniqueID(newID);
                        // It shouldn't occur that an existing ID is changed... although it's possible if there are duplicates
                        if (currentID != null)
                            logger.warn("Core unique ID changed from {} to {}", currentID, newID);
                    }
                }
            }
            i++;
        }
    }
    // Add extra columns from the map, either as metadata or measurements
    for (Entry<String, List<String>> entry : map.entrySet()) {
        // Skip columns without headers
        if (entry.getKey() == null || entry.getKey().trim().length() == 0)
            continue;
        // If we have survival data, or else can't parse numeric values, add as metadata
        boolean isOverallSurvival = entry.getKey().equalsIgnoreCase(TMACoreObject.KEY_OVERALL_SURVIVAL);
        boolean isRecurrenceFreeSurvival = entry.getKey().equalsIgnoreCase(TMACoreObject.KEY_RECURRENCE_FREE_SURVIVAL);
        boolean isOSCensored = entry.getKey().equalsIgnoreCase(TMACoreObject.KEY_OS_CENSORED);
        boolean isRFSCensored = entry.getKey().equalsIgnoreCase(TMACoreObject.KEY_RFS_CENSORED);
        // Try to parse numeric data, if we can
        boolean isSurvivalRelated = isOverallSurvival || isRecurrenceFreeSurvival || isOSCensored || isRFSCensored;
        double[] vals = parseNumeric(entry.getValue(), !isSurvivalRelated);
        if (isSurvivalRelated || vals == null || vals.length == GeneralTools.numNaNs(vals)) {
            for (int i : cores.keySet()) {
                for (TMACoreObject core : cores.get(i)) {
                    if (core == null)
                        continue;
                    if (isOverallSurvival)
                        core.getMeasurementList().putMeasurement(TMACoreObject.KEY_OVERALL_SURVIVAL, vals[i]);
                    else if (isRecurrenceFreeSurvival)
                        core.getMeasurementList().putMeasurement(TMACoreObject.KEY_RECURRENCE_FREE_SURVIVAL, vals[i]);
                    else if (isOSCensored)
                        core.getMeasurementList().putMeasurement(TMACoreObject.KEY_OS_CENSORED, vals[i] > 0 ? 1 : 0);
                    else if (isRFSCensored)
                        core.getMeasurementList().putMeasurement(TMACoreObject.KEY_RFS_CENSORED, vals[i] > 0 ? 1 : 0);
                    else
                        core.putMetadataValue(entry.getKey(), entry.getValue().get(i));
                }
            }
        } else {
            // If we have a numeric column, add to measurement list
            for (int i : cores.keySet()) {
                for (TMACoreObject core : cores.get(i)) {
                    core.getMeasurementList().addMeasurement(entry.getKey(), vals[i]);
                }
            }
        }
    }
    // Loop through and close any measurement lists, recording anywhere changes were made
    Set<PathObject> changed = new HashSet<>();
    for (List<TMACoreObject> coreList : cores.values()) {
        for (TMACoreObject core : coreList) {
            if (core == null)
                continue;
            core.getMeasurementList().close();
            changed.add(core);
        }
    }
    hierarchy.fireObjectsChangedEvent(null, changed);
    return changed.size();
}
Also used : HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) TMACoreObject(qupath.lib.objects.TMACoreObject) TMAGrid(qupath.lib.objects.hierarchy.TMAGrid) ArrayList(java.util.ArrayList) PathObject(qupath.lib.objects.PathObject) ArrayList(java.util.ArrayList) List(java.util.List) HashSet(java.util.HashSet)

Example 14 with TMACoreObject

use of qupath.lib.objects.TMACoreObject in project qupath by qupath.

the class GuiTools method promptToClearAllSelectedObjects.

/**
 * Prompt user to select all currently-selected objects (except TMA core objects).
 *
 * @param imageData
 * @return
 */
public static boolean promptToClearAllSelectedObjects(final ImageData<?> imageData) {
    // Get all non-TMA core objects
    PathObjectHierarchy hierarchy = imageData.getHierarchy();
    Collection<PathObject> selectedRaw = hierarchy.getSelectionModel().getSelectedObjects();
    List<PathObject> selected = selectedRaw.stream().filter(p -> !(p instanceof TMACoreObject)).collect(Collectors.toList());
    if (selected.isEmpty()) {
        if (selectedRaw.size() > selected.size())
            Dialogs.showErrorMessage("Delete selected objects", "No valid objects selected! \n\nNote: Individual TMA cores cannot be deleted with this method.");
        else
            Dialogs.showErrorMessage("Delete selected objects", "No objects selected!");
        return false;
    }
    int n = selected.size();
    String message;
    if (n == 1)
        message = "Delete selected object?";
    else
        message = "Delete " + n + " selected objects?";
    if (Dialogs.showYesNoDialog("Delete objects", message)) {
        // Check for descendants
        List<PathObject> children = new ArrayList<>();
        for (PathObject temp : selected) {
            children.addAll(temp.getChildObjects());
        }
        children.removeAll(selected);
        boolean keepChildren = true;
        if (!children.isEmpty()) {
            Dialogs.DialogButton response = Dialogs.showYesNoCancelDialog("Delete objects", "Keep descendant objects?");
            if (response == Dialogs.DialogButton.CANCEL)
                return false;
            keepChildren = response == Dialogs.DialogButton.YES;
        }
        hierarchy.removeObjects(selected, keepChildren);
        hierarchy.getSelectionModel().clearSelection();
        imageData.getHistoryWorkflow().addStep(new DefaultScriptableWorkflowStep("Delete selected objects", "clearSelectedObjects(" + keepChildren + ");"));
        if (keepChildren)
            logger.info(selected.size() + " object(s) deleted");
        else
            logger.info(selected.size() + " object(s) deleted with descendants");
        imageData.getHistoryWorkflow().addStep(new DefaultScriptableWorkflowStep("Delete selected objects", "clearSelectedObjects();"));
        logger.info(selected.size() + " object(s) deleted");
        return true;
    } else
        return false;
}
Also used : CheckComboBox(org.controlsfx.control.CheckComboBox) UnaryOperator(java.util.function.UnaryOperator) TextFormatter(javafx.scene.control.TextFormatter) PathRootObject(qupath.lib.objects.PathRootObject) ParameterList(qupath.lib.plugins.parameters.ParameterList) PointsROI(qupath.lib.roi.PointsROI) Matcher(java.util.regex.Matcher) Action(java.awt.Desktop.Action) ColorTools(qupath.lib.common.ColorTools) GraphicsContext(javafx.scene.canvas.GraphicsContext) Canvas(javafx.scene.canvas.Canvas) Screen(javafx.stage.Screen) PathAnnotationObject(qupath.lib.objects.PathAnnotationObject) Platform(javafx.application.Platform) CountDownLatch(java.util.concurrent.CountDownLatch) Transparency(java.awt.Transparency) Clipboard(javafx.scene.input.Clipboard) SimpleDoubleProperty(javafx.beans.property.SimpleDoubleProperty) StringProperty(javafx.beans.property.StringProperty) Callable(java.util.concurrent.Callable) PathObjectHierarchy(qupath.lib.objects.hierarchy.PathObjectHierarchy) DefaultColorDeconvolutionStains(qupath.lib.color.ColorDeconvolutionStains.DefaultColorDeconvolutionStains) Bindings(javafx.beans.binding.Bindings) NumberFormat(java.text.NumberFormat) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) Slider(javafx.scene.control.Slider) SplitAnnotationsPlugin(qupath.lib.plugins.objects.SplitAnnotationsPlugin) GridPane(javafx.scene.layout.GridPane) Color(javafx.scene.paint.Color) GeneralTools(qupath.lib.common.GeneralTools) Commands(qupath.lib.gui.commands.Commands) Node(javafx.scene.Node) CheckBox(javafx.scene.control.CheckBox) IOException(java.io.IOException) File(java.io.File) PathObjectTools(qupath.lib.objects.PathObjectTools) Menu(javafx.scene.control.Menu) ROI(qupath.lib.roi.interfaces.ROI) SimpleObjectProperty(javafx.beans.property.SimpleObjectProperty) ObservableValue(javafx.beans.value.ObservableValue) Image(javafx.scene.image.Image) Button(javafx.scene.control.Button) ImageServer(qupath.lib.images.servers.ImageServer) CombineOp(qupath.lib.roi.RoiTools.CombineOp) DoubleBinding(javafx.beans.binding.DoubleBinding) ListCell(javafx.scene.control.ListCell) CheckMenuItem(javafx.scene.control.CheckMenuItem) LoggerFactory(org.slf4j.LoggerFactory) RenderingHints(java.awt.RenderingHints) Side(javafx.geometry.Side) ContextMenu(javafx.scene.control.ContextMenu) URI(java.net.URI) QuPathGUI(qupath.lib.gui.QuPathGUI) TextField(javafx.scene.control.TextField) MenuItem(javafx.scene.control.MenuItem) BufferedImage(java.awt.image.BufferedImage) Collection(java.util.Collection) Spinner(javafx.scene.control.Spinner) Collectors(java.util.stream.Collectors) StainVector(qupath.lib.color.StainVector) PathObject(qupath.lib.objects.PathObject) SeparatorMenuItem(javafx.scene.control.SeparatorMenuItem) QuPathViewer(qupath.lib.gui.viewer.QuPathViewer) List(java.util.List) Robot(javafx.scene.robot.Robot) DefaultScriptableWorkflowStep(qupath.lib.plugins.workflow.DefaultScriptableWorkflowStep) Pattern(java.util.regex.Pattern) ClipboardContent(javafx.scene.input.ClipboardContent) Scene(javafx.scene.Scene) ListView(javafx.scene.control.ListView) TextArea(javafx.scene.control.TextArea) ParsePosition(java.text.ParsePosition) DoubleProperty(javafx.beans.property.DoubleProperty) ColorDeconvolutionHelper(qupath.lib.color.ColorDeconvolutionHelper) Function(java.util.function.Function) Dialogs(qupath.lib.gui.dialogs.Dialogs) ColorDeconvolutionStains(qupath.lib.color.ColorDeconvolutionStains) SwingUtilities(javax.swing.SwingUtilities) Graphics2D(java.awt.Graphics2D) ActionTools(qupath.lib.gui.ActionTools) Tooltip(javafx.scene.control.Tooltip) ColorPicker(javafx.scene.control.ColorPicker) ImageData(qupath.lib.images.ImageData) Desktop(java.awt.Desktop) ObjectProperty(javafx.beans.property.ObjectProperty) Logger(org.slf4j.Logger) Label(javafx.scene.control.Label) WritableImage(javafx.scene.image.WritableImage) TMACoreObject(qupath.lib.objects.TMACoreObject) DoubleSpinnerValueFactory(javafx.scene.control.SpinnerValueFactory.DoubleSpinnerValueFactory) SimpleBooleanProperty(javafx.beans.property.SimpleBooleanProperty) Stage(javafx.stage.Stage) SpinnerValueFactory(javafx.scene.control.SpinnerValueFactory) SwingFXUtils(javafx.embed.swing.SwingFXUtils) Window(javafx.stage.Window) Collections(java.util.Collections) PathObjectHierarchy(qupath.lib.objects.hierarchy.PathObjectHierarchy) TMACoreObject(qupath.lib.objects.TMACoreObject) ArrayList(java.util.ArrayList) DefaultScriptableWorkflowStep(qupath.lib.plugins.workflow.DefaultScriptableWorkflowStep) PathObject(qupath.lib.objects.PathObject) Dialogs(qupath.lib.gui.dialogs.Dialogs)

Example 15 with TMACoreObject

use of qupath.lib.objects.TMACoreObject in project qupath by qupath.

the class QuPathViewer method getImageLocationString.

/**
 * Get a string representing the image coordinates for a particular x &amp; y location.
 * @param xx x-coordinate in the image space (not the component/viewer space)
 * @param yy y-coordinate in the image space (not the component/viewer space)
 * @param useCalibratedUnits
 * @return
 */
private String getImageLocationString(double xx, double yy, boolean useCalibratedUnits) {
    ImageServer<BufferedImage> server = getServer();
    if (server == null)
        return "";
    String units;
    if (xx < 0 || yy < 0 || xx > server.getWidth() - 1 || yy > server.getHeight() - 1)
        return "";
    double xDisplay = xx;
    double yDisplay = yy;
    PixelCalibration cal = server.getPixelCalibration();
    if (useCalibratedUnits && cal.hasPixelSizeMicrons()) {
        units = GeneralTools.micrometerSymbol();
        xDisplay *= cal.getPixelWidthMicrons();
        yDisplay *= cal.getPixelHeightMicrons();
    } else {
        units = "px";
    }
    // See if we're on top of a TMA core
    String prefix = "";
    TMAGrid tmaGrid = getHierarchy().getTMAGrid();
    if (tmaGrid != null) {
        TMACoreObject core = PathObjectTools.getTMACoreForPixel(tmaGrid, xx, yy);
        if (core != null && core.getName() != null)
            prefix = "Core: " + core.getName() + "\n";
    }
    String s = null;
    RegionRequest request = ImageRegionStoreHelpers.getTileRequest(server, xx, yy, downsampleFactor.get(), getZPosition(), getTPosition());
    if (request != null) {
        BufferedImage img = regionStore.getCachedTile(server, request);
        int xi = 0, yi = 0;
        if (img == null) {
            // Try getting a value from the thumbnail for the whole image
            BufferedImage imgThumbnail = regionStore.getCachedThumbnail(server, getZPosition(), getTPosition());
            if (imgThumbnail != null) {
                img = imgThumbnail;
                double downsample = (double) server.getWidth() / imgThumbnail.getWidth();
                xi = (int) (xx / downsample + .5);
                yi = (int) (yy / downsample + .5);
            }
        } else {
            xi = (int) ((xx - request.getX()) / request.getDownsample());
            yi = (int) ((yy - request.getY()) / request.getDownsample());
        }
        if (img != null) {
            // Make sure we are within range
            xi = Math.min(xi, img.getWidth() - 1);
            yi = Math.min(yi, img.getHeight() - 1);
            // Get the value, having applied any required color transforms
            if (imageDisplay != null)
                s = imageDisplay.getTransformedValueAsString(img, xi, yi);
        }
    }
    // Append z, t position if required
    String zString = null;
    if (server.nZSlices() > 1) {
        double zSpacing = server.getPixelCalibration().getZSpacingMicrons();
        if (!useCalibratedUnits || Double.isNaN(zSpacing))
            zString = "z = " + getZPosition();
        else
            zString = String.format("z = %.2f %s", getZPosition() * zSpacing, GeneralTools.micrometerSymbol());
    }
    String tString = null;
    if (server.nTimepoints() > 1) {
        // TODO: Consider use of TimeUnit
        // TimeUnit timeUnit = server.getTimeUnit();
        // if (!useMicrons || timeUnit == null)
        tString = "t = " + getTPosition();
    // else
    // tString = String.format("z = %.2f %s", getTPosition(), timeUnit.toString());
    }
    String dimensionString;
    if (tString == null && zString == null)
        dimensionString = "";
    else {
        dimensionString = "\n";
        if (zString != null) {
            dimensionString += zString;
            if (tString != null)
                dimensionString += ", " + tString;
        } else
            dimensionString += tString;
    }
    if (s != null)
        return String.format("%s%.2f, %.2f %s\n%s%s", prefix, xDisplay, yDisplay, units, s, dimensionString);
    else
        return String.format("%s%.2f, %.2f %s%s", prefix, xDisplay, yDisplay, units, dimensionString);
// if (s != null)
// return String.format("<html><center>%.2f, %.2f %s<br>%s", xDisplay, yDisplay, units, s);
// else
// return String.format("<html><center>%.2f, %.2f %s", xDisplay, yDisplay, units);
}
Also used : TMACoreObject(qupath.lib.objects.TMACoreObject) TMAGrid(qupath.lib.objects.hierarchy.TMAGrid) PixelCalibration(qupath.lib.images.servers.PixelCalibration) RegionRequest(qupath.lib.regions.RegionRequest) BufferedImage(java.awt.image.BufferedImage)

Aggregations

TMACoreObject (qupath.lib.objects.TMACoreObject)35 PathObject (qupath.lib.objects.PathObject)20 ArrayList (java.util.ArrayList)17 PathObjectHierarchy (qupath.lib.objects.hierarchy.PathObjectHierarchy)15 TMAGrid (qupath.lib.objects.hierarchy.TMAGrid)13 BufferedImage (java.awt.image.BufferedImage)12 PathAnnotationObject (qupath.lib.objects.PathAnnotationObject)12 ROI (qupath.lib.roi.interfaces.ROI)12 IOException (java.io.IOException)9 List (java.util.List)9 RegionRequest (qupath.lib.regions.RegionRequest)9 File (java.io.File)6 ImageServer (qupath.lib.images.servers.ImageServer)6 PathDetectionObject (qupath.lib.objects.PathDetectionObject)6 Collection (java.util.Collection)5 LinkedHashMap (java.util.LinkedHashMap)5 Collectors (java.util.stream.Collectors)5 HashSet (java.util.HashSet)4 Insets (javafx.geometry.Insets)4 Scene (javafx.scene.Scene)4