All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.actelion.research.orbit.imageAnalysis.modules.ExclusionModule Maven / Gradle / Ivy

Go to download

Orbit, a versatile image analysis software for biological image-based quantification

There is a newer version: 3.15
Show newest version
/*
 *     Orbit, a versatile image analysis software for biological image-based quantification.
 *     Copyright (C) 2009 - 2017 Actelion Pharmaceuticals Ltd., Gewerbestrasse 16, CH-4123 Allschwil, Switzerland.
 *
 *     This program is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU General Public License
 *     along with this program.  If not, see .
 *
 */

package com.actelion.research.orbit.imageAnalysis.modules;

import com.actelion.research.orbit.imageAnalysis.components.*;
import com.actelion.research.orbit.imageAnalysis.models.ClassShape;
import com.actelion.research.orbit.imageAnalysis.models.OrbitModel;
import com.actelion.research.orbit.imageAnalysis.tasks.ExclusionMapGen;
import com.actelion.research.orbit.imageAnalysis.tasks.OrbitWorker;
import com.actelion.research.orbit.imageAnalysis.tasks.TrainWorker;
import com.actelion.research.orbit.imageAnalysis.utils.ClassListCellRenderer;
import com.actelion.research.orbit.imageAnalysis.utils.OrbitUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.prefs.Preferences;

import static com.actelion.research.orbit.imageAnalysis.components.OrbitImageAnalysis.loginOk;

public class ExclusionModule extends AbstractOrbitModule {

    private static final long serialVersionUID = 1L;
    private final static Logger logger = LoggerFactory.getLogger(ExclusionModule.class);
    private final JButton btnSetupClasses = new JButton("Setup Classes");
    private final JButton btnConfigureClasses = new JButton("Configure Classes");
    private final JButton btnTrain = new JButton("Train, Set and Classify");
    private final JButton btnLoad = new JButton(btnLoadTextLocal);
    private final JButton btnLoadServer = new JButton(btnLoadTextServer);
    private final JButton btnClassify = new JButton("Classify Trained Exclusion Model");
    private final JButton btnReset = new JButton("Reset Exclusion Model");
    private final JButton btnHelp = new JButton("Help");
    protected final Preferences prefs = Preferences.userNodeForPackage(this.getClass());

    public static final String btnLoadTextLocal = "Load and Set (local)";
    public static final String btnLoadTextServer = "Load and Set (server)";


    public ExclusionModule() {

        btnSetupClasses.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                setupClasses();
            }
        });

        btnConfigureClasses.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                configureClasses();
            }
        });

        btnTrain.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                trainSetAndClassifyExcl();
            }
        });

        btnClassify.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                classifyExcl();
            }
        });

        btnReset.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                resetModel();
            }
        });

        btnLoad.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                loadModel();
            }
        });

        btnLoadServer.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                loadModelServer();
            }
        });

        btnHelp.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                showHelp();
            }
        });

        setLayout(new GridLayout(7, 1));
        add(btnSetupClasses);
        add(btnConfigureClasses);
        add(btnTrain);
        add(btnLoad);
        add(btnClassify);
        add(btnReset);
        add(btnHelp);
    }


    protected void setupClasses() {
        final OrbitImageAnalysis OIA = OrbitImageAnalysis.getInstance();
        if (JOptionPane.showConfirmDialog(OIA,
                "This will reset all current training shapes.\nDo you want to continue?",
                "Reset current training data?", JOptionPane.YES_NO_OPTION)
                == JOptionPane.YES_OPTION) {
            List classShapes = new ArrayList(4);    // define some default classes
            classShapes.add(new ClassShape("Exclusion 1", Color.yellow, ClassShape.SHAPETYPE_POLYGONEXT, ClassShape.EXCLUSION));
            classShapes.add(new ClassShape("Exclusion 2", Color.red, ClassShape.SHAPETYPE_POLYGONEXT, ClassShape.EXCLUSION));
            classShapes.add(new ClassShape("Inclusion 1", Color.green, ClassShape.SHAPETYPE_POLYGONEXT, ClassShape.INCLUSION));
            classShapes.add(new ClassShape("Inclusion 2", Color.blue, ClassShape.SHAPETYPE_POLYGONEXT, ClassShape.INCLUSION));
            for (ImageFrame iFrame : OIA.getIFrames()) {
                iFrame.recognitionFrame.setClassShapes(OrbitUtils.cloneClassShapes(classShapes));
                iFrame.recognitionFrame.setWindowSize(OIA.getModel().getFeatureDescription().getWindowSize());
                iFrame.recognitionFrame.setBoundaryClass(OIA.getModel().getBoundaryClass());
            }
            OIA.getModel().setClassShapes(classShapes);
            OIA.makeClassCombobox();
        }
    }

    private void configureClasses() {
        final OrbitImageAnalysis OIA = OrbitImageAnalysis.getInstance();
        OrbitModel exclModel = OIA.getModel().getExclusionModel();
        if (exclModel == null) {
            JOptionPane.showMessageDialog(ExclusionModule.this, "Exclusion model not available.\nPlease train an exclusion model first.", "Exclusion model not available.", JOptionPane.ERROR_MESSAGE);
            return;
        }
        ClassAdminFrame configFrame = new ClassAdminFrame(exclModel.getClassShapes(), new ClassListCellRenderer(), -1, false);
        configFrame.setAlwaysOnTop(true);
        configFrame.setVisible(true);
    }


    private void trainSetAndClassifyExcl() {
        final OrbitImageAnalysis OIA = OrbitImageAnalysis.getInstance();
        List lowFrames = new ArrayList();
        for (ImageFrame iFrame : OIA.getIFrames()) {
            RecognitionFrame lowResFrame = ExclusionMapGen.getExclusionMapFrame(iFrame.getRdf(), iFrame.recognitionFrame, OIA.getModel());
            double scaleFactor = lowResFrame.bimg.getWidth() / (double) iFrame.recognitionFrame.bimg.getWidth();
            logger.trace("exclusion frame / normal frame scalefactor: " + scaleFactor);
            List classShapes = ClassShape.scaleShapes(iFrame.recognitionFrame.getClassShapes(), scaleFactor);
            lowResFrame.setClassShapes(classShapes);
            ImageFrame lowResIFrame = new ImageFrame(lowResFrame);
            lowFrames.add(lowResIFrame);
        }

        TrainWorker trainWorker = new TrainWorker(lowFrames, true, false, OIA.getModel());
        trainWorker.run();

        OIA.setModelAsExclusionModel(OIA.getModel(), false);
        OIA.setModifiedClassShapes(false);

        classifyExcl();
    }

    private void classifyExcl() {
        final OrbitImageAnalysis OIA = OrbitImageAnalysis.getInstance();
        final ImageFrame iFrame = OIA.getIFrame();
        if (iFrame.getRdf() != null)
            iFrame.recognitionFrame.loadAnnotationROI(iFrame.getRdf().getRawDataFileId(), OIA.getModel().getAnnotationGroup());
        final ExclusionMapGen exMapGen = ExclusionMapGen.constructExclusionMap(iFrame.getRdf(), iFrame.recognitionFrame, OIA.getModel());
        OrbitWorker worker = new OrbitWorker() {
            @Override
            protected void doWork() throws Exception {
                try {
                    logger.trace("start classifying exclusion map");
                    exMapGen.generateMap();
                    iFrame.recognitionFrame.setExMapGen(exMapGen);
                    if (exMapGen.getClassificationImage() != null)
                        iFrame.recognitionFrame.setClassImage(exMapGen.getClassificationImage());
                    iFrame.recognitionFrame.setClassImageScale((float) (1d / exMapGen.getScaleFactor()));
                    iFrame.getOpacitySlider().setEnabled(true);
                    iFrame.repaint();
                    logger.trace("end classifying exclusion map");
                } catch (Exception e1) {
                    e1.printStackTrace();
                    logger.error("error creating the exclusion map (maybe the exclusion model is not set?): " + e1.getMessage());
                }
            }
        };
        ProgressPanel progressPanel = new ProgressPanel(OIA.getCurrentPicName(), "Excl Map Classification", worker);
        OIA.addAndExecuteTask(progressPanel);
    }


    private void resetModel() {
        final OrbitImageAnalysis OIA = OrbitImageAnalysis.getInstance();
        OIA.getModel().setExclusionModel(null);
        OIA.updateStatusBar();
    }

    private void loadModel() {
        final OrbitImageAnalysis OIA = OrbitImageAnalysis.getInstance();
        JFileChooser fileChooser = new JFileChooser();
        FileNameExtensionFilter filter = new FileNameExtensionFilter(
                "OrbitImageAnalysis Models (*.omo)", "omo");
        fileChooser.setFileFilter(filter);
        String dir = prefs.get("OrbitImageAnalysis.OpenExclusionModelCurrentDir", null);
        if (dir != null) {
            File cd = new File(dir);
            fileChooser.setCurrentDirectory(cd);
        }
        int returnVal = fileChooser.showOpenDialog(null);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            prefs.put("OrbitImageAnalysis.OpenExclusionModelCurrentDir", fileChooser.getCurrentDirectory().getAbsolutePath());
            File file = fileChooser.getSelectedFile();
            OrbitModel exclModel = OrbitModel.LoadFromFile(file.getAbsolutePath());
            OIA.getModel().setExclusionModel(exclModel);
            logger.info("exclusion model loaded and set");
            OIA.updateStatusBar();
            JOptionPane.showMessageDialog(null, "Exclusion model loaded and set.", "Success", JOptionPane.INFORMATION_MESSAGE);
        } else {
            logger.trace("load model canceled.");
        }
    }

    private void loadModelServer() {
        final OrbitImageAnalysis OIA = OrbitImageAnalysis.getInstance();
        OrbitModel exclModel = null;
        ModelBrowser modelBrowser = new ModelBrowser();
        try {
            OIA.forceLogin();
            if (loginOk) {
                modelBrowser.showModelBrowser(OIA, OIA.loginUser,false);  // modal
                exclModel = modelBrowser.getSelectedModel();
            }
        } catch (Exception e1) {
            e1.printStackTrace();
        }

        if (exclModel!=null) {
            OIA.getModel().setExclusionModel(exclModel);
            logger.info("exclusion model loaded and set");
            OIA.updateStatusBar();
            JOptionPane.showMessageDialog(null, "Exclusion model loaded and set.", "Success", JOptionPane.INFORMATION_MESSAGE);
        } else {
            logger.trace("load model canceled.");
        }
    }


    @Override
    public String getName() {
        return "Exclusion Model";
    }

    @Override
    public void init() {
    }

    @Override
    public void reset() {
    }

    private void showHelp() {
        final OrbitImageAnalysis oia = OrbitImageAnalysis.getInstance();
        String color = OrbitUtils.DARKUI ? " color=white" : "";
        String h = "" +
                "

Exclusion Model Module

" + "

Description

" + "An exclusion model defines exclusion and inclusion classes and can be seen as a trainable region of interest (ROI) definition. The model is used to exclude some regions from classification or segmentation. This is typically used to exclude background or artefacts like dirt or folds." + "
Internally the model is applied to a low level resolution image to classify larger regions of a high resolution (e.g. slide) image.
" + "

How to build and use an exclusion model

" + "
    " + "
  1. Setup inclusion and exclusion classes. You might click on 'Setup classes' in this module to use a predefined class setup. You can rename the classes or select different colors if you want.
  2. " + "
  3. Configure model parameters (F3), set structure size and median filter values. For exclusion models for whole slide images a structure size between 4 and 15 is recommended.
  4. " + "
  5. Mark regions for exclusion and inclusion classes using the standard class marking tools from the main toolbar. You might skip the some exclusion or inclusion class. Hint: Set the zoom to a low level so that you have an overview of your whole image.
  6. " + "
  7. Click on 'Train, Set and Classify' and drag the classification transparency slider of your image to check the model. This step sets the exclusion model of your main (loaded or trained) model. If you save your model, the embedded exclusion model will be saved, too.
  8. " + "
  9. Mark further class regions or remove class regions using the rubber tool and repeat the last setp until you're fine with the model.
  10. " + "
  11. To apply this exclusion model to further images, use the 'classify trained exclusion model' button.
  12. " + "
  13. You can add manual exclusion or inclusion annotations with the annotation tab on the right side, which will overrule the regions defined by the exclusion model.
  14. " + "
  15. If you're fine with your exclusion model save it to disk or in Orbit if you want (optional) and continue with a normal classification model (either 'Model->Reset Training Data' to reset the class regions or clasification->setup classes which does that automatically) to define an e.g. active/non-active model.
  16. " + "
  17. Continue with a normal classification or segmentation.
  18. " + "
  19. To remove the exclusion model from the main model, click on 'Reset Exclusion Model'.
  20. " + "
  21. Hint: Often it is easier to 1) define an exclusion model, save it. 2) Creating a complete new classification or segmentation model. Finally 3) Embed the exclusion model via model->load existing exclusion model.
  22. " + "
" + ""; oia.addInternalFrame(new ResultFrame(h, "Exclusion Model Help")); } public JButton getBtnClassify() { return btnClassify; } public JButton getBtnConfigureClasses() { return btnConfigureClasses; } public JButton getBtnHelp() { return btnHelp; } public JButton getBtnLoad() { return btnLoad; } public JButton getBtnLoadServer() { return btnLoadServer; } public JButton getBtnReset() { return btnReset; } public JButton getBtnSetupClasses() { return btnSetupClasses; } public JButton getBtnTrain() { return btnTrain; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy