com.actelion.research.orbit.imageAnalysis.components.AnnotationPanel Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of orbit-image-analysis Show documentation
Show all versions of orbit-image-analysis Show documentation
Orbit, a versatile image analysis software for biological image-based quantification
/*
* Orbit, a versatile image analysis software for biological image-based quantification.
* Copyright (C) 2009 - 2018 Idorsia Pharmaceuticals Ltd., Hegenheimermattweg 91, 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.components;
import com.actelion.research.orbit.beans.OrbitUser;
import com.actelion.research.orbit.beans.RawAnnotation;
import com.actelion.research.orbit.imageAnalysis.components.RecognitionFrame.Tools;
import com.actelion.research.orbit.imageAnalysis.dal.DALConfig;
import com.actelion.research.orbit.imageAnalysis.models.*;
import com.actelion.research.orbit.imageAnalysis.tasks.AnnotationClassificationTask;
import com.actelion.research.orbit.imageAnalysis.tasks.AnnotationFeaturesTask;
import com.actelion.research.orbit.imageAnalysis.utils.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.media.jai.PlanarImage;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.*;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
public class AnnotationPanel extends JPanel implements PropertyChangeListener {
private static final long serialVersionUID = 1L;
private static final Logger logger = LoggerFactory.getLogger(AnnotationPanel.class);
private final JButton btnAddAnnotationPoly = new JButton(new ImageIcon(OrbitImageAnalysis.class.getResource(OrbitUtils.DARKUI ? "/resource/annoAddPoly_substance.png" : "/resource/annoAddPoly.png")));
private final JButton btnAddAnnotationMagneticLasso = new JButton(new ImageIcon(OrbitImageAnalysis.class.getResource(OrbitUtils.DARKUI ? "/resource/annoAddMagneticLasso_substance.png" : "/resource/annoAddPoly.png")));
private final JButton btnAddAnnotationRect = new JButton(new ImageIcon(OrbitImageAnalysis.class.getResource(OrbitUtils.DARKUI ? "/resource/annoAddRect_substance.png" : "/resource/annoAddRect.png")));
private final JButton btnEditAnnotation = new JButton(new ImageIcon(OrbitImageAnalysis.class.getResource("/resource/annoEdit.png")));
private final JButton btnRemoveAnnotation = new JButton(new ImageIcon(OrbitImageAnalysis.class.getResource("/resource/annoRemove.png")));
private final JButton btnMoveAnnotation = new JButton(new ImageIcon(OrbitImageAnalysis.class.getResource(OrbitUtils.DARKUI ? "/resource/annoMove_substance.png" : "/resource/annoMove.png")));
private final JButton btnRotateAnnotation = new JButton(new ImageIcon(OrbitImageAnalysis.class.getResource(OrbitUtils.DARKUI ? "/resource/annoRotate_substance.png" : "/resource/annoRotate.png")));
private final JCheckBoxMenuItem cbClosed = new JCheckBoxMenuItem("Close Annotation Polygon", true);
private final JCheckBoxMenuItem cbSave = new JCheckBoxMenuItem("Store Annotations in DB", true);
private final JCheckBoxMenuItem cbFixedRect = new JCheckBoxMenuItem("Draw Fixed Size Rectangle", false);
private ImageAnnotation currentAnnotation = null;
private static final int thumbnailWidth = 70;
private static final int thumbnailHeight = 70;
private final AnnotationListCellRenderer cellRenderer = new AnnotationListCellRenderer();
private List annotationClipboard = null;
private double annotationClipboardScale = 1d; // to store the mm per pixel of the source image (when pasting the scale is normalized to the mm per pixel ratio of source/dest image)
private double fixedRectangleRatio = 1d;
private int activeGroup = 0; // 0 means all groups, >0 means one specific active group
private int defaultGroup = 0; // 0 means all groups, >0 means one specific active group (default group for new annotations)
private final AtomicBoolean annoListAdjusting = new AtomicBoolean(false);
public final ActionListener addPolygonActionListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
OrbitImageAnalysis.getInstance().forceLogin();
if (OrbitImageAnalysis.loginOk) {
prepareNewAnnotationPolygon(false);
}
}
};
public final ActionListener addMagneticLassoActionListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
OrbitImageAnalysis.getInstance().forceLogin();
if (OrbitImageAnalysis.loginOk) {
prepareNewAnnotationPolygon(true);
}
}
};
private final FilteredListModel model = new FilteredListModel() {
@Override
protected boolean accept(ImageAnnotation element) {
if (activeGroup == 0) {
return true;
} else {
return element.getGroup() == activeGroup;
}
}
};
private final JList list = new JList(model);
public AnnotationPanel() {
list.setCellRenderer(cellRenderer);
btnAddAnnotationPoly.setToolTipText("add polygon");
btnAddAnnotationPoly.addActionListener(addPolygonActionListener);
btnAddAnnotationMagneticLasso.setToolTipText("add magnetic lasso polygon
hold left mouse button to draw, right-click to set fixed points, release left-mouse to finish");
btnAddAnnotationMagneticLasso.addActionListener(addMagneticLassoActionListener);
btnAddAnnotationRect.setToolTipText("add rectangle");
btnAddAnnotationRect.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
OrbitImageAnalysis.getInstance().forceLogin();
if (OrbitImageAnalysis.loginOk) {
prepareNewAnnotationRect();
}
}
});
btnEditAnnotation.setToolTipText("edit annotation");
btnEditAnnotation.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
OrbitImageAnalysis.getInstance().forceLogin();
if (OrbitImageAnalysis.loginOk) {
editAnnotation();
}
}
});
btnRemoveAnnotation.setToolTipText("remove annotation");
btnRemoveAnnotation.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
OrbitImageAnalysis.getInstance().forceLogin();
if (OrbitImageAnalysis.loginOk) {
removeAnnotation();
}
}
});
btnMoveAnnotation.setToolTipText("move annotation");
btnMoveAnnotation.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
OrbitImageAnalysis.getInstance().forceLogin();
if (OrbitImageAnalysis.loginOk) {
moveAnnotation();
}
}
});
btnRotateAnnotation.setToolTipText("rotate annotation");
btnRotateAnnotation.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
OrbitImageAnalysis.getInstance().forceLogin();
if (OrbitImageAnalysis.loginOk) {
rotateAnnotation();
}
}
});
list.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
annotationClicked();
}
});
// just additional so that a click on a single annotation works, too
list.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
annotationClicked();
}
});
/*
// sample code for scrolling to the selected annotation (does not work properly...)
Thread thread = new Thread() {
public void run() {
final int ms = 30;
for (int j=0; j 0) {
s = s.replaceAll(",", "\\.");
double d = Double.NaN;
try {
d = Double.parseDouble(s);
} catch (Exception e1) {
JOptionPane.showMessageDialog(AnnotationPanel.this, "Please enter a valid number (e.g. 1.3)", "Could not set rectangle ratio", JOptionPane.ERROR_MESSAGE);
}
if (!Double.isNaN(d)) {
fixedRectangleRatio = d;
JOptionPane.showMessageDialog(AnnotationPanel.this, "Rectangle ratio successfully set to " + fixedRectangleRatio, "Ratio set", JOptionPane.INFORMATION_MESSAGE);
}
}
}
});
menu.add(ratioItem);
JMenuItem rectangleSizeItem = new JMenuItem("Set Fixed Rectangle size");
rectangleSizeItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ImageFrame iFrame = OrbitImageAnalysis.getInstance().getIFrame();
final RecognitionFrame rf = iFrame.getRecognitionFrame();
String s = (String) JOptionPane.showInputDialog(
AnnotationPanel.this,
"Please enter the width of the fixed rectangle:",
"Rectangle Size",
JOptionPane.PLAIN_MESSAGE,
null,
null,
"" + rf.getTargetRadius());
System.out.println("s is: " + s);
if (s != null && s.length() > 0) {
Integer size = 0;
try {
s = s.replaceAll(",", "\\.");
size = (int) Double.parseDouble(s);
} catch (Exception e1) {
JOptionPane.showMessageDialog(AnnotationPanel.this, "Please enter a valid number (e.g. 50)", "Could not set rectangle size", JOptionPane.ERROR_MESSAGE);
}
if (size > 0) {
rf.setTargetRadius(size);
OrbitImageAnalysis.getInstance().getSizeBox().setSelectedItem(new Integer(size));
JOptionPane.showMessageDialog(AnnotationPanel.this, "Rectangle size successfully set to " + size, "Size set", JOptionPane.INFORMATION_MESSAGE);
}
}
}
});
menu.add(rectangleSizeItem);
menu.addSeparator();
menu.add(cbSave);
item = new JMenuItem("Store Annotations manually");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
saveUnsaved();
}
});
menu.add(item);
menuBar.add(menu);
// Classify / Computation
menu = new JMenu("Computation");
item = new JMenuItem("Classification per Annotation");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
annotationClassification();
}
});
menu.add(item);
item = new JMenuItem("Features per Annotation");
item.setToolTipText("Set class features (F3) to retrieve the features of only specific classes.");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
annotationFeatures();
}
});
menu.add(item);
item = new JMenuItem("Compute Annotation Statistics");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
computeStatistics();
}
});
menu.add(item);
menu.addSeparator();
item = new JMenuItem("Set Selected Annotations as ROI");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
setAnnotationsAsROI();
}
});
menu.add(item);
menuBar.add(menu);
// copy&paste
menu = new JMenu("Copy&Paste");
item = new JMenuItem("Copy Annotation");
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, ActionEvent.CTRL_MASK + ActionEvent.SHIFT_MASK));
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
copyAnnotation();
}
});
menu.add(item);
item = new JMenuItem("Paste Annotation");
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, ActionEvent.CTRL_MASK + ActionEvent.SHIFT_MASK));
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
pasteAnnotation();
}
});
menu.add(item);
menuBar.add(menu);
// group
menu = new JMenu("Groups");
JMenu filterMenu = new JMenu("Visible Groups");
final int groupSize = OrbitUtils.ANNOTATION_GROUPS;
final JCheckBoxMenuItem[] subMenuGroup = new JCheckBoxMenuItem[groupSize + 1];
for (int g = 0; g < (groupSize + 1); g++) {
final int group = g;
String lab = "All Groups";
if (group > 0) lab = "Group " + group;
subMenuGroup[group] = new JCheckBoxMenuItem(lab);
subMenuGroup[group].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < (groupSize + 1); i++) {
if (i != group) {
subMenuGroup[i].setSelected(false);
}
if (!subMenuGroup[group].isSelected()) {
subMenuGroup[0].setSelected(true);
}
}
for (int i = 0; i < (groupSize + 1); i++) {
if (subMenuGroup[i].isSelected()) {
setActiveGroup(i);
break;
}
}
}
});
if (group == 0) subMenuGroup[group].setSelected(true);
filterMenu.add(subMenuGroup[group]);
}
menu.add(filterMenu);
JMenu defaultGroupMenu = new JMenu("Default Group (new Annotations)");
final JCheckBoxMenuItem[] subDefaultGroup = new JCheckBoxMenuItem[groupSize];
for (int g = 0; g < groupSize; g++) {
final int group = g + 1;
String lab = "Group " + group;
subDefaultGroup[group - 1] = new JCheckBoxMenuItem(lab);
subDefaultGroup[group - 1].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
for (int i = 1; i < (groupSize + 1); i++) {
if (i != group) {
subDefaultGroup[i - 1].setSelected(false);
}
if (!subDefaultGroup[group - 1].isSelected()) {
subDefaultGroup[group - 1].setSelected(true);
}
}
for (int i = 1; i < (groupSize + 1); i++) {
if (subDefaultGroup[i - 1].isSelected()) {
defaultGroup = i;
setActiveGroup(i);
// adjust subGroup checkBoxMenuItems
for (int j = 0; j < (groupSize + 1); j++) {
if (j != group) {
subMenuGroup[j].setSelected(false);
} else {
subMenuGroup[j].setSelected(true);
}
}
logger.debug("default group: " + defaultGroup + " active group set to: " + activeGroup);
}
}
}
});
defaultGroupMenu.add(subDefaultGroup[group - 1]);
}
subDefaultGroup[0].setSelected(true);
menu.add(defaultGroupMenu);
menuBar.add(menu);
// layout
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new GridBagLayout());
JScrollPane scrollPane = new JScrollPane(list, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
mainPanel.add(scrollPane, new GridBagConstraints(0, 0, GridBagConstraints.REMAINDER, GridBagConstraints.RELATIVE, 1, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(1, 1, 0, 1), 0, 0));
// JPanel btnPanel = new JPanel(new GridBagLayout());
// btnPanel.add(btnAddAnnotationPoly,new GridBagConstraints(0, 0, 1, GridBagConstraints.RELATIVE, 1, 0, GridBagConstraints.SOUTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
// btnPanel.add(btnAddAnnotationRect,new GridBagConstraints(1, 0, 1, GridBagConstraints.RELATIVE, 1, 0, GridBagConstraints.SOUTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
// btnPanel.add(btnEditAnnotation,new GridBagConstraints (2, 0, 1, GridBagConstraints.RELATIVE, 1, 0, GridBagConstraints.SOUTH, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
// btnPanel.add(btnRemoveAnnotation,new GridBagConstraints(3, 0, 1, GridBagConstraints.RELATIVE, 1, 0, GridBagConstraints.SOUTHEAST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
// btnPanel.add(btnMoveAnnotation,new GridBagConstraints(4, 0, 1, GridBagConstraints.RELATIVE, 1, 0, GridBagConstraints.SOUTH, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
JPanel btnPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0));
btnPanel.add(btnAddAnnotationMagneticLasso);
btnPanel.add(btnAddAnnotationPoly);
btnPanel.add(btnAddAnnotationRect);
btnPanel.add(btnMoveAnnotation);
btnPanel.add(btnRotateAnnotation);
btnPanel.add(btnEditAnnotation);
btnPanel.add(btnRemoveAnnotation);
mainPanel.add(btnPanel, new GridBagConstraints(0, 1, 1, GridBagConstraints.RELATIVE, 1, 0, GridBagConstraints.SOUTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
setLayout(new BorderLayout());
add(menuBar, BorderLayout.NORTH);
add(mainPanel, BorderLayout.CENTER);
}
private void setActiveGroup(int i) {
activeGroup = i;
model.filter();
list.repaint();
logger.debug("active group: " + activeGroup);
RecognitionFrame.getActiveAnnotationGroup().set(i);
// repaint active frames
for (ImageFrame iFrame : OrbitImageAnalysis.getInstance().getIFrames()) {
iFrame.repaint();
}
}
protected void annotationClicked() {
// first, set all unselected
for (ImageAnnotation ia : model.getAllElements()) {
ia.setSelected(false);
}
if (annoListAdjusting.get() || list.getValueIsAdjusting())
return; // e.g. list is reloaded, don't jump to selection
final ImageFrame iFrame = OrbitImageAnalysis.getInstance().getIFrame();
if (list.getSelectedValues() != null && iFrame != null) {
Rectangle bbAll = null;
for (Object obj : list.getSelectedValues()) {
if (obj instanceof ImageAnnotation) {
ImageAnnotation ann = (ImageAnnotation) obj;
ann.setSelected(true);
if (ann.getShape().getShapeList().size() > 0) {
IScaleableShape shape = (IScaleableShape) ann.getShape().getShapeList().get(0);
Rectangle bb = shape.getScaledInstance(100, new Point(0, 0)).getBounds();
if (bbAll == null) bbAll = bb;
else bbAll = bbAll.union(bb);
}
}
}
if (bbAll != null) {
double sc = iFrame.recognitionFrame.getScale() / 100d;
final Point targetP = new Point((int) (bbAll.getCenterX() * sc) - iFrame.recognitionFrame.getWidth() / 2, (int) (bbAll.getCenterY() * sc) - iFrame.recognitionFrame.getHeight() / 2);
iFrame.setViewPortPositionAndAdjust(targetP);
}
}
}
;
protected void combineSelectedPolygons() {
// check if all selected annotations are of type PolygonExt (other annotations, e.g. rectangles, cannot be joined)
ImageAnnotation[] annotations = null;
if (list.getSelectedValue() != null && list.getSelectedValues() != null && list.getSelectedValues().length > 0) {
annotations = new ImageAnnotation[list.getSelectedValues().length];
for (int i = 0; i < list.getSelectedValues().length; i++) {
annotations[i] = (ImageAnnotation) list.getSelectedValues()[i];
}
for (ImageAnnotation anno : annotations) {
if (anno.getShape().getShapeList().size() > 0) {
IScaleableShape scaleableShape = (IScaleableShape) anno.getShape().getShapeList().get(0);
if (!(scaleableShape instanceof PolygonExt)) {
JOptionPane.showMessageDialog(AnnotationPanel.this, "Only polygon annotations can be joined.", "Please select only polygon annotations", JOptionPane.ERROR_MESSAGE);
return;
}
}
}
}
// checks ok
ImageFrame iFrame = OrbitImageAnalysis.getInstance().getIFrame();
if (annotations != null && annotations.length > 0) {
Color color = null;
String user = null;
int rawAnnotationId = 0;
int rawDataFileId = 0;
int group = 0;
PolygonExt mergedPoly = null;
for (ImageAnnotation anno : annotations) {
if (anno.getShape().getShapeList().size() > 0) {
if (color == null) color = anno.getShape().getColor();
if (user == null) user = anno.getUserId();
if (rawAnnotationId == 0) rawAnnotationId = anno.getRawAnnotationId();
if (rawDataFileId == 0) rawDataFileId = anno.getRawDataFileId();
if (group == 0) group = anno.getGroup();
IScaleableShape scaleableShape = (IScaleableShape) anno.getShape().getShapeList().get(0);
IScaleableShape pScaled = (IScaleableShape) scaleableShape.getScaledInstance(100d, new Point(0, 0));
PolygonExt poly = (PolygonExt) pScaled;
if (mergedPoly == null) mergedPoly = poly;
else mergedPoly.addPolygon(poly);
}
}
// remove selected polygons and add new combined one
for (ImageAnnotation anno : annotations) {
model.removeElement(anno);
if (iFrame != null) iFrame.recognitionFrame.getAnnotations().remove(anno);
}
// remove old ones from db if same user
String loginUser = OrbitImageAnalysis.getInstance().loginUser;
for (ImageAnnotation annotation : annotations) {
try {
if (annotation.getRawDataFileId() > 0 && annotation.getUserId().equals(loginUser))
DALConfig.getImageProvider().DeleteRawAnnotation(annotation.getRawAnnotationId());
} catch (Exception e) {
logger.error("error: ", e);
}
}
ClassShape cs = new ClassShape("combined", color, ClassShape.SHAPETYPE_POLYGONEXT);
cs.getShapeList().add(mergedPoly);
ImageAnnotation ia = new ImageAnnotation("combined", cs);
ia.setUserId(loginUser);
ia.setRawAnnotationId(rawAnnotationId);
ia.setRawDataFileId(rawDataFileId);
ia.setGroup(group);
model.addElement(ia);
if (iFrame != null) iFrame.recognitionFrame.getAnnotations().add(ia);
// add to db
if (ia.getRawDataFileId() > 0 && loginUser != null) {
try {
int id = DALConfig.getImageProvider().InsertRawAnnotation(ia);
ia.setRawAnnotationId(id);
} catch (Exception e) {
logger.error("error: ", e);
}
}
model.filter();
} else {
JOptionPane.showMessageDialog(AnnotationPanel.this, "Please select polygon annotations first.", "No polygon annotations selected", JOptionPane.ERROR_MESSAGE);
}
}
private void annotationClassification() {
if (list.getSelectedValues() == null || list.getSelectedValues().length < 1) {
JOptionPane.showMessageDialog(this, "Please select one or several annotations first.", "No annotations selected", JOptionPane.ERROR_MESSAGE);
return;
}
ImageFrame iFrame = OrbitImageAnalysis.getInstance().getIFrame();
if (iFrame != null && list.getSelectedValues() != null && list.getSelectedValues().length > 0) {
List annotations = new ArrayList();
for (int i = 0; i < list.getSelectedValues().length; i++) {
Object obj = list.getSelectedValues()[i];
if (obj instanceof ImageAnnotation) {
annotations.add((ImageAnnotation) obj);
}
}
AnnotationClassificationTask task = new AnnotationClassificationTask(iFrame.getRdf(), iFrame.recognitionFrame, OrbitImageAnalysis.getInstance().getModel(), annotations);
OrbitImageAnalysis.getInstance().addAndExecuteTask(new ProgressPanel(iFrame.getTitle(), "Annotation Classification", task));
}
}
private void annotationFeatures() {
if (list.getSelectedValues() == null || list.getSelectedValues().length < 1) {
JOptionPane.showMessageDialog(this, "Please select one or several annotations first.", "No annotations selected", JOptionPane.ERROR_MESSAGE);
return;
}
ImageFrame iFrame = OrbitImageAnalysis.getInstance().getIFrame();
if (iFrame != null && list.getSelectedValues() != null && list.getSelectedValues().length > 0) {
List annotations = new ArrayList();
for (int i = 0; i < list.getSelectedValues().length; i++) {
Object obj = list.getSelectedValues()[i];
if (obj instanceof ImageAnnotation) {
annotations.add((ImageAnnotation) obj);
}
}
AnnotationFeaturesTask task = new AnnotationFeaturesTask(iFrame.getRdf(), iFrame.recognitionFrame, OrbitImageAnalysis.getInstance().getModel(), annotations);
OrbitImageAnalysis.getInstance().addAndExecuteTask(new ProgressPanel(iFrame.getTitle(), "Annotation Features", task));
}
}
/**
* Sets annotations as ROI. Does NOT check for annotations with name "ROI".
*/
private void setAnnotationsAsROI() {
ImageFrame iFrame = OrbitImageAnalysis.getInstance().getIFrame();
if (iFrame == null) {
JOptionPane.showMessageDialog(this, "Please open and select an image first", "No image available", JOptionPane.ERROR_MESSAGE);
return;
}
Object[] selectedAnnotations = list.getSelectedValues();
if (selectedAnnotations == null || selectedAnnotations.length == 0) {
JOptionPane.showMessageDialog(this, "Please select one or several annotations first", "No annotations selected", JOptionPane.ERROR_MESSAGE);
}
List pList = new ArrayList();
for (int i = 0; i < selectedAnnotations.length; i++) {
Object obj = selectedAnnotations[i];
if (obj instanceof ImageAnnotation) {
ImageAnnotation anno = (ImageAnnotation) obj;
if (anno.getShape().getShapeList().size() > 0) {
IScaleableShape scaleableShape = (IScaleableShape) anno.getShape().getShapeList().get(0);
IScaleableShape pScaled = (IScaleableShape) scaleableShape.getScaledInstance(100d, new Point(0, 0));
pList.add(pScaled);
}
}
}
ShapeExtList roi = new ShapeExtList(pList, new Rectangle(Integer.MAX_VALUE, Integer.MAX_VALUE));
iFrame.recognitionFrame.setROI(roi);
JOptionPane.showMessageDialog(this, "Annotation ROI successfully set.\nPlease continue with normal classification or segmentation.", "Annotation ROI set", JOptionPane.INFORMATION_MESSAGE);
}
/**
* if fullPath, the getDistPath function of polygonExt, otherwise the distance between the first and the last point of the polygon is computed
*
* @param fullPath
*/
private String computeStatisticsStr(boolean fullPath, boolean copypaste) {
ImageFrame iFrame = OrbitImageAnalysis.getInstance().getIFrame();
if (iFrame != null && list.getModel().getSize() > 0) {
StringBuilder sb = new StringBuilder(fullPath ? "Length of annotation path:" : "Distance from first to last point of annotation:");
sb.append("\n");
double mm = iFrame.recognitionFrame.getMuMeterPerPixel();
if (mm > 0) {
for (int i = 0; i < list.getModel().getSize(); i++) {
ImageAnnotation anno = (ImageAnnotation) list.getModel().getElementAt(i);
if (anno.getShape().getShapeList().size() > 0) {
PolygonExt poly = (PolygonExt) anno.getShape().getShapeList().get(0);
if (poly.npoints > 1) {
//poly = poly.getScaledInstance(100, new Point(0,0));
double dist;
if (fullPath) dist = (poly.getDistPath() / (poly.getScale() / 100d)) * mm;
else dist = (poly.getDistDirstLast() / (poly.getScale() / 100d)) * mm;
if (!copypaste)
sb.append(anno.getDescription() + ": " + String.format("%1.4f", dist) + " " + (char) 181 + "m\n");
else sb.append(String.format("%1.4f", dist) + "\n");
}
}
}
} // otherwise show message!
return sb.toString();
}
return "";
}
private HashMap> computeStatisticsMap(OrbitUtils.ScaleAndUnit sau) {
HashMap> map = new HashMap>();
ImageFrame iFrame = OrbitImageAnalysis.getInstance().getIFrame();
if (iFrame != null && list.getModel().getSize() > 0) {
double mm = sau.getScale();
if (mm > 0) {
for (int i = 0; i < list.getModel().getSize(); i++) {
ImageAnnotation anno = (ImageAnnotation) list.getModel().getElementAt(i);
if (anno.getShape().getShapeList().size() > 0) {
if (anno.getShape().getShapeList().get(0) instanceof PolygonExt) {
PolygonExt poly = (PolygonExt) anno.getShape().getShapeList().get(0);
PolygonMetrics pm = new PolygonMetrics(poly.getScaledInstance(100, new Point(0, 0)));
if (poly.npoints > 1) {
double fullPath = (poly.getDistPath() / (poly.getScale() / 100d)) * mm;
double dist = (poly.getDistDirstLast() / (poly.getScale() / 100d)) * mm;
//double area = (pm.getArea()/(poly.getScale()/100d))*mm;
double area = pm.getArea() * mm * mm;
HashMap annoMap = new HashMap();
annoMap.put("Pathlength", String.format("%1.4f", fullPath));
annoMap.put("First-Last", String.format("%1.4f", dist));
annoMap.put("Area", String.format("%1.4f", area));
map.put(anno, annoMap);
}
} else if (anno.getShape().getShapeList().get(0) instanceof RectangleExt) {
RectangleExt rectExt = (RectangleExt) anno.getShape().getShapeList().get(0);
rectExt = rectExt.getScaledInstance(100, new Point(0, 0));
double area = rectExt.getWidth() * rectExt.getHeight() * mm * mm;
double w = rectExt.getWidth() * mm;
double h = rectExt.getHeight() * mm;
HashMap annoMap = new HashMap();
annoMap.put("Pathlength", String.format("%1.4f", w));
annoMap.put("First-Last", String.format("%1.4f", h));
annoMap.put("Area", String.format("%1.4f", area));
map.put(anno, annoMap);
} else { // not supported
HashMap annoMap = new HashMap();
annoMap.put("Pathlength", String.format("%1.4f", 0d));
annoMap.put("First-Last", String.format("%1.4f", 0d));
annoMap.put("Area", String.format("%1.4f", 0d));
map.put(anno, annoMap);
}
}
}
} // otherwise show message!
}
return map;
}
private void computeStatistics() {
getRootPane().setCursor(new Cursor(Cursor.WAIT_CURSOR));
try {
ImageFrame iFrame = OrbitImageAnalysis.getInstance().getIFrame();
if (iFrame != null && list.getModel().getSize() > 0) {
OrbitUtils.ScaleAndUnit sau = OrbitUtils.getImageScaleAndUnit(iFrame.getRdf());
HashMap> map = computeStatisticsMap(sau);
StringBuilder sb = new StringBuilder();
sb.append("#" + iFrame.getTitle() + "\n");
// header
sb.append("Annotation\tPathlength(" + sau.getUnit() + ")\tFirst-Last(" + sau.getUnit() + ")\tArea(" + sau.getUnitSquare() + ")\n");
List annotations = new ArrayList();
for (int i = 0; i < list.getModel().getSize(); i++) {
ImageAnnotation anno = (ImageAnnotation) list.getModel().getElementAt(i);
annotations.add(anno); // used later for roi area
sb.append(anno.getDescription().replaceAll("\\n", " ") + "\t");
HashMap annoMap = map.get(anno);
for (String s : new String[]{"Pathlength", "First-Last", "Area"}) {
sb.append(annoMap.get(s) + "\t");
}
sb.deleteCharAt(sb.length() - 1);
sb.append("\n");
}
// combined annotation roi area
IScaleableShape roiCombined = new ShapeAnnotationList(annotations, 0, null);
if (roiCombined != null) {
OrbitTiledImage2 img = iFrame.recognitionFrame.bimg.getImage();
double roiArea = OrbitUtils.getROISize(img.getWidth(), img.getHeight(), roiCombined.getBounds(), roiCombined, null, sau.getScale());
String mmUnit = "mm";
if (sau.getUnit().equalsIgnoreCase("pixel")) mmUnit = "pixel";
else roiArea /= 1000000d;
sb.append("\nCombined ROI area (" + mmUnit + "): " + String.format("%1.4f", roiArea) + "\n");
}
//copy&paste columns
sb.append("\nCopy&Paste Column Pathlength\n");
for (int i = 0; i < list.getModel().getSize(); i++) {
ImageAnnotation anno = (ImageAnnotation) list.getModel().getElementAt(i);
HashMap annoMap = map.get(anno);
System.out.println("annoMAp: " + annoMap);
sb.append(annoMap.get("Pathlength") + "\n");
sb.deleteCharAt(sb.length() - 1);
sb.append("\n");
}
sb.append("\nCopy&Paste Column First-Last\n");
for (int i = 0; i < list.getModel().getSize(); i++) {
ImageAnnotation anno = (ImageAnnotation) list.getModel().getElementAt(i);
HashMap annoMap = map.get(anno);
sb.append(annoMap.get("First-Last") + "\n");
sb.deleteCharAt(sb.length() - 1);
sb.append("\n");
}
sb.append("\nCopy&Paste Column Area\n");
for (int i = 0; i < list.getModel().getSize(); i++) {
ImageAnnotation anno = (ImageAnnotation) list.getModel().getElementAt(i);
HashMap annoMap = map.get(anno);
sb.append(annoMap.get("Area") + "\n");
sb.deleteCharAt(sb.length() - 1);
sb.append("\n");
}
String res = OrbitUtils.text2SmartHtml(sb.toString());
if (sb.length() > 0) {
ResultFrame rf = new ResultFrame(res, "Measurement Results for " + iFrame.getTitle());
OrbitImageAnalysis.getInstance().addInternalFrame(rf);
}
}
} finally {
getRootPane().setCursor(new Cursor((Cursor.DEFAULT_CURSOR)));
}
}
private void computeStatisticsOld() {
ImageFrame iFrame = OrbitImageAnalysis.getInstance().getIFrame();
if (iFrame != null && list.getModel().getSize() > 0) {
if (iFrame.recognitionFrame.getMuMeterPerPixel() == 0) {
JOptionPane.showMessageDialog(this, "No scale available. Measurement cannot be performed.", "No scale available", JOptionPane.ERROR_MESSAGE);
return;
}
StringBuilder sb = new StringBuilder();
sb.append(computeStatisticsStr(false, false));
sb.append("\n\n");
sb.append(computeStatisticsStr(true, false));
sb.append("\n\nCopy&Paste Column:\n");
sb.append(iFrame.getTitle() + "\n");
sb.append(computeStatisticsStr(true, true));
if (sb.length() > 0) {
ResultFrame rf = new ResultFrame(sb.toString(), "Measurement Results for " + iFrame.getTitle());
OrbitImageAnalysis.getInstance().addInternalFrame(rf);
}
}
}
private void moveAnnotation() {
ImageFrame iFrame = OrbitImageAnalysis.getInstance().getIFrame();
if (iFrame != null && list.getSelectedValues() != null) {
iFrame.recognitionFrame.setSelectedTool(Tools.moveAnnotation);
// iFrame.recognitionFrame.getMyListener().setShapeMode(ClassShape.SHAPETYPE_POLYGONEXT);
iFrame.recognitionFrame.getMyListener().setDeleteMode(false);
// jre6 cast. For jre7 use list.getSelectedValueList!
List selectedAnnotationList = new ArrayList(list.getSelectedValues().length);
for (Object obj : list.getSelectedValues()) {
if (obj instanceof ImageAnnotation) {
selectedAnnotationList.add((ImageAnnotation) obj);
}
}
iFrame.recognitionFrame.getMyListener().setCurrentAnnotationList(selectedAnnotationList);
if (!iFrame.recognitionFrame.getMyListener().containsPropertyChangeListener(this)) {
iFrame.recognitionFrame.getMyListener().addPropertyChangeListener(this);
}
iFrame.recognitionFrame.setCursor(new Cursor(Cursor.MOVE_CURSOR));
}
}
private void rotateAnnotation() {
ImageFrame iFrame = OrbitImageAnalysis.getInstance().getIFrame();
if (iFrame != null && list.getSelectedValues() != null) {
iFrame.recognitionFrame.setSelectedTool(Tools.rotateAnnotation);
// iFrame.recognitionFrame.getMyListener().setShapeMode(ClassShape.SHAPETYPE_POLYGONEXT);
iFrame.recognitionFrame.getMyListener().setDeleteMode(false);
// jre6 cast. For jre7 use list.getSelectedValueList!
List selectedAnnotationList = new ArrayList(list.getSelectedValues().length);
for (Object obj : list.getSelectedValues()) {
if (obj instanceof ImageAnnotation) {
selectedAnnotationList.add((ImageAnnotation) obj);
}
}
iFrame.recognitionFrame.getMyListener().setCurrentAnnotationList(selectedAnnotationList);
if (!iFrame.recognitionFrame.getMyListener().containsPropertyChangeListener(this)) {
iFrame.recognitionFrame.getMyListener().addPropertyChangeListener(this);
}
iFrame.recognitionFrame.setCursor(new Cursor(Cursor.HAND_CURSOR));
}
}
private void prepareNewAnnotationPolygon(final boolean magneticLasso) {
ImageFrame iFrame = OrbitImageAnalysis.getInstance().getIFrame();
if (iFrame != null) {
logger.trace("mip layer: " + iFrame.getMipLayer());
if (iFrame.getMipLayer() > 0) {
JOptionPane.showMessageDialog(this, "Annotation can only be created on full-size images, not on special layers.\nPlease create the annotation on the original image.\nThe annotations will then be copied and scaled to the special resolution images.", "Cannot create annotaiton", JOptionPane.ERROR_MESSAGE);
return;
}
currentAnnotation = new ImageAnnotation();
currentAnnotation.setDescription("Annotation");
currentAnnotation.setUserId(OrbitImageAnalysis.loginUser);
currentAnnotation.setGroup(defaultGroup > 0 ? defaultGroup : 1);
iFrame.recognitionFrame.getAnnotations().add(currentAnnotation);
iFrame.recognitionFrame.setSelectedTool(magneticLasso? Tools.magneticLasso : Tools.brush);
iFrame.recognitionFrame.getMyListener().setShapeMode(ClassShape.SHAPETYPE_POLYGONEXT);
iFrame.recognitionFrame.getMyListener().setDeleteMode(false);
iFrame.recognitionFrame.getMyListener().setCloseNextPolygonExt(cbClosed.isSelected());
iFrame.recognitionFrame.getMyListener().setShapeList(currentAnnotation.getShape().getShapeList(), currentAnnotation.getShape().getShapeType(), currentAnnotation.getShape().getName());
if (!iFrame.recognitionFrame.getMyListener().containsPropertyChangeListener(this)) {
iFrame.recognitionFrame.getMyListener().addPropertyChangeListener(this);
}
iFrame.recognitionFrame.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
}
}
private void prepareNewAnnotationRect() {
ImageFrame iFrame = OrbitImageAnalysis.getInstance().getIFrame();
if (iFrame != null) {
logger.trace("mip layer: " + iFrame.getMipLayer());
if (iFrame.getMipLayer() > 0) {
JOptionPane.showMessageDialog(this, "Annotation can only be created on full-size images, not on special layers.\nPlease create the annotation on the original image.\nThe annotations will then be copied and scaled to the special resolution images.", "Cannot create annotaiton", JOptionPane.ERROR_MESSAGE);
return;
}
currentAnnotation = new ImageAnnotation();
currentAnnotation.setDescription("Annotation");
currentAnnotation.setUserId(OrbitImageAnalysis.loginUser);
currentAnnotation.getShape().setShapeType(ClassShape.SHAPETYPE_RECTANGLE);
currentAnnotation.setGroup(defaultGroup > 0 ? defaultGroup : 1);
iFrame.recognitionFrame.getAnnotations().add(currentAnnotation);
iFrame.recognitionFrame.setSelectedTool(Tools.rectangle);
iFrame.recognitionFrame.getMyListener().setShapeMode(ClassShape.SHAPETYPE_RECTANGLE);
iFrame.recognitionFrame.getMyListener().setFixedRectangle(cbFixedRect.isSelected());
iFrame.recognitionFrame.getMyListener().setFixedRectangleRatio(fixedRectangleRatio);
iFrame.recognitionFrame.getMyListener().setDeleteMode(false);
iFrame.recognitionFrame.getMyListener().setShapeList(currentAnnotation.getShape().getShapeList(), currentAnnotation.getShape().getShapeType(), currentAnnotation.getShape().getName());
if (!iFrame.recognitionFrame.getMyListener().containsPropertyChangeListener(this)) {
iFrame.recognitionFrame.getMyListener().addPropertyChangeListener(this);
}
iFrame.recognitionFrame.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
}
}
private void attachAnnotation() {
ImageFrame iFrame = OrbitImageAnalysis.getInstance().getIFrame();
if (iFrame != null) {
// if (currentAnnotation.getShape().getShapeList().size()>0) {
// ((PolygonExt)currentAnnotation.getShape().getShapeList().get(0)).setClosed(false);
// }
currentAnnotation.setDescription(generateDescription(currentAnnotation, model));
if (cbFixedRect.isSelected()) {
//int w = (int)((iFrame.recognitionFrame.getTargetRadius()/2d)*(iFrame.recognitionFrame.getScale()/100d));
int w = (int) ((iFrame.recognitionFrame.getTargetRadius() / 2d));
int h = (int) ((double) w * fixedRectangleRatio);
currentAnnotation.setDescription(currentAnnotation.getDescription() + " [" + w * 2 + "x" + h * 2 + "]");
}
model.addElement(currentAnnotation);
model.filter();
iFrame.recognitionFrame.setSelectedTool(Tools.finger);
iFrame.recognitionFrame.getMyListener().setShapeList(null, null);
iFrame.recognitionFrame.getMyListener().setShapeMode(ClassShape.SHAPETYPE_POLYGONEXT);
iFrame.recognitionFrame.getMyListener().setFixedRectangle(false);
iFrame.recognitionFrame.getMyListener().removePropertyChangeListener(this);
iFrame.recognitionFrame.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
if (cbSave.isSelected()) {
if (iFrame.getRdf() != null) {
try {
//RawAnnotation ra = currentAnnotation.toRawAnnotation(iFrame.getRdf().getRawDataFileId(), OrbitImageAnalysis.loginUser);
currentAnnotation.setRawDataFileId(iFrame.getRdf().getRawDataFileId());
currentAnnotation.setUserId(OrbitImageAnalysis.loginUser);
if (currentAnnotation.getShape().getShapeList().get(0) instanceof PolygonExt) {
((PolygonExt) currentAnnotation.getShape().getShapeList().get(0)).setClosed(cbClosed.isSelected());
}
int newId = DALConfig.getImageProvider().InsertRawAnnotation(currentAnnotation);
currentAnnotation.setRawAnnotationId(newId);
} catch (Exception e) {
logger.error("Annotation cannot be saved.\nProbably you don't have the permission to save annotations for this image.", e);
}
} else {
logger.info("Annotation cannot be persisted because the image is not in Orbit.");
}
} // cbSave
}
/**
* returns a String "Annotation GROUP/NUMBER". NUMBER is the size of the model, but will be increased until the description is unique.
*/
private String generateDescription(ImageAnnotation anno, FilteredListModel model) {
model.filter();
int n = model.getSize() + 1;
boolean found = true;
String d = "";
while (found) {
found = false;
d = "Annotation " + currentAnnotation.getGroup() + "/" + n;
for (int i = 0; i < model.getSize(); i++) {
ImageAnnotation a = (ImageAnnotation) model.getElementAt(i);
if (a.getDescription().equals(d)) {
found = true;
n++;
}
}
}
return d;
}
private void updateAnnotation(List movedAnnotationList) {
ImageFrame iFrame = OrbitImageAnalysis.getInstance().getIFrame();
if (iFrame != null) {
// model.filter();
iFrame.recognitionFrame.setSelectedTool(Tools.finger);
iFrame.recognitionFrame.getMyListener().setShapeMode(ClassShape.SHAPETYPE_POLYGONEXT); // ?
iFrame.recognitionFrame.getMyListener().removePropertyChangeListener(this); // ?
iFrame.recognitionFrame.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
if (cbSave.isSelected()) {
if (iFrame.getRdf() != null) {
try {
for (ImageAnnotation movedAnnotation : movedAnnotationList) {
DALConfig.getImageProvider().UpdateRawAnnotation(movedAnnotation);
}
} catch (Exception e) {
logger.error("error: ", e);
}
} else {
logger.info("Annotation cannot be persisted because the image is not in Orbit.");
}
} // cbSave
list.repaint();
}
private void editAnnotation() {
if (list.getSelectedValues() != null) {
List annotations = new ArrayList();
for (Object obj : list.getSelectedValues()) {
ImageAnnotation annotation = (ImageAnnotation) obj;
// if (!(annotation.getUserId() == null || annotation.getUserId().equals("") || annotation.getUserId().equals(OrbitImageAnalysis.GUEST_USER) || annotation.getUserId().equals(OrbitImageAnalysis.loginUser) || DALConfig.getImageProvider().getAdminUsers().contains(OrbitImageAnalysis.loginUser) || DALConfig.getTemporaryUsers().contains(annotation.getUserId()))) {
// JOptionPane.showMessageDialog(this, "Only the owner of the annotation is able edit this annotation.\nThis annotation is owned by " + annotation.getUserId() + " but login user is " + OrbitImageAnalysis.loginUser + ".", "Cannot edit annotation.", JOptionPane.ERROR_MESSAGE);
// return;
// }
annotations.add(annotation);
}
if (annotations.size() == 0) return;
AnnotationEditor editor = new AnnotationEditor(annotations);
editor.setVisible(true);
list.repaint();
ImageFrame iFrame = OrbitImageAnalysis.getInstance().getIFrame();
if (iFrame != null) {
iFrame.recognitionFrame.repaint();
}
// update in db
if (cbSave.isSelected()) {
for (ImageAnnotation annotation : annotations) {
try {
annotation.setRawDataFileId(iFrame.getRdf().getRawDataFileId());
//annotation.setUserId(OrbitImageAnalysis.loginUser);
DALConfig.getImageProvider().UpdateRawAnnotation(annotation);
} catch (Exception e) {
logger.error("error saving annotation ", e);
}
}
}
model.filter();
}
}
/**
* stores unsaved annotations in the orbit database
*/
private void saveUnsaved() {
OrbitImageAnalysis.getInstance().forceLogin();
if (!OrbitImageAnalysis.loginOk) return;
ImageFrame iFrame = OrbitImageAnalysis.getInstance().getIFrame();
if (iFrame != null) {
if (iFrame.getRdf() != null) {
try {
for (int i = 0; i < list.getModel().getSize(); i++) {
ImageAnnotation anno = (ImageAnnotation) list.getModel().getElementAt(i);
anno.setRawDataFileId(iFrame.getRdf().getRawDataFileId());
anno.setUserId(OrbitImageAnalysis.loginUser);
if (anno.getRawAnnotationId() > 0) { // update existing annotation
DALConfig.getImageProvider().UpdateRawAnnotation(anno);
} else { // insert new annotation
int newId = DALConfig.getImageProvider().InsertRawAnnotation(anno);
anno.setRawAnnotationId(newId);
}
}
JOptionPane.showMessageDialog(this, list.getModel().getSize() + " Annotations successfully saved in database", "Annotations successfully saved", JOptionPane.INFORMATION_MESSAGE);
} catch (Exception e) {
logger.error("error: ", e);
}
} else {
logger.info("Annotation cannot be persisted because the image is not in Orbit.");
}
} // iFrame!=null
}
private void removeAnnotation() {
if (list.getSelectedValue() != null && list.getSelectedValues() != null && list.getSelectedValues().length > 0) {
ImageAnnotation[] annotations = new ImageAnnotation[list.getSelectedValues().length];
StringBuilder sb = new StringBuilder();
for (int i = 0; i < list.getSelectedValues().length; i++) {
annotations[i] = (ImageAnnotation) list.getSelectedValues()[i];
String s = annotations[i].getDescription();
if (s != null && s.length() > 20) s = s.substring(0, 20) + "...";
sb.append(s + ",");
if (i % 4 == 0) sb.append("\n");
}
sb.deleteCharAt(sb.length() - 1);
if (!(JOptionPane.showConfirmDialog(this,
"Do you really want to delete the following annotations: " + sb.toString() + "?",
"Delete Annotations", JOptionPane.YES_NO_OPTION)
== JOptionPane.YES_OPTION)) return;
// check rights
// boolean rightsOk = true;
// String otherOwner = "";
// for (ImageAnnotation annotation : annotations) {
// if (!(annotation.getUserId() == null || annotation.getUserId().equals("") || annotation.getUserId().equals(OrbitImageAnalysis.GUEST_USER) || annotation.getUserId().equals(OrbitImageAnalysis.loginUser) || DALConfig.getImageProvider().getAdminUsers().contains(OrbitImageAnalysis.loginUser) || DALConfig.getTemporaryUsers().contains(annotation.getUserId()))) {
// rightsOk = false;
// otherOwner = annotation.getUserId();
// break;
// }
// }
// if (!rightsOk) {
// JOptionPane.showMessageDialog(this, "Only the owner of the annotation is able remove the annotation(s).\nAt least one annotation is owned by " + otherOwner + ".", "Cannot remove annotation.", JOptionPane.ERROR_MESSAGE);
// return;
// }
// (OrbitAnnotation[])list.getSelectedValues();
// remove in annotation list
for (ImageAnnotation annotation : annotations) {
model.removeElement(annotation);
model.filter();
}
// synch iFrame
ImageFrame iFrame = OrbitImageAnalysis.getInstance().getIFrame();
if (iFrame != null) {
for (ImageAnnotation annotation : annotations) {
iFrame.recognitionFrame.getAnnotations().remove(annotation);
}
iFrame.recognitionFrame.repaint();
}
// remove from database
for (ImageAnnotation annotation : annotations) {
try {
DALConfig.getImageProvider().DeleteRawAnnotation(annotation.getRawAnnotationId());
} catch (Exception e) {
logger.error("error: ", e);
}
}
}
}
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(ShapePainterListener.SHAPE_DRAWN)) {
attachAnnotation();
}
if (evt.getPropertyName().equals(ShapePainterListener.SHAPE_MOVED)) {
updateAnnotation((List) evt.getNewValue());
}
}
public FilteredListModel getModel() {
return model;
}
/**
* clears list model and icon cache
*/
public void clear() {
model.clear();
cellRenderer.clear();
}
// copy&paste
protected void copyAnnotation() {
if (list.getSelectedValue() != null && list.getSelectedValues() != null && list.getSelectedValues().length > 0) {
ImageFrame iFrame = OrbitImageAnalysis.getInstance().getIFrame();
if (iFrame != null) {
double mm = iFrame.recognitionFrame.getMuMeterPerPixel();
annotationClipboardScale = mm > 0 ? mm : 1d;
}
annotationClipboard = new ArrayList(list.getSelectedValues().length);
int cnt = 0;
for (Object obj : list.getSelectedValues()) {
if (obj instanceof ImageAnnotation) {
ImageAnnotation anno = (ImageAnnotation) obj;
anno.setModifyDate(new Date());
anno.setRawAnnotationId(0);
anno.setRawDataFileId(0);
annotationClipboard.add(anno);
cnt++;
}
}
if (cnt > 0) {
logger.info("annotation(s) copied to clipboard");
//JOptionPane.showMessageDialog(this, cnt+" annotation(s) successfully copied to clipboard.", "Copied to clipboard", JOptionPane.INFORMATION_MESSAGE);
}
} else {
JOptionPane.showMessageDialog(this, "Please select first one or several annotations.", "No annotation selected", JOptionPane.ERROR_MESSAGE);
}
}
protected void pasteAnnotation() {
ImageFrame iFrame = OrbitImageAnalysis.getInstance().getIFrame();
if (iFrame == null) {
JOptionPane.showMessageDialog(this, "Please open and select an image (from Orbit) first.", "No image selected", JOptionPane.ERROR_MESSAGE);
return;
}
if (iFrame.getRdf() == null) {
JOptionPane.showMessageDialog(this, "Please open an image from Orbit. Annotations cannot be created for file based images.", "Image is not an Orbit image", JOptionPane.ERROR_MESSAGE);
return;
}
double scaleRatio = 1d;
if (iFrame != null) {
double mm = iFrame.recognitionFrame.getMuMeterPerPixel();
if (annotationClipboardScale > 0 && mm > 0) scaleRatio = annotationClipboardScale / mm;
}
int cnt = 0;
if (annotationClipboard != null && annotationClipboard.size() > 0) {
OrbitImageAnalysis.getInstance().forceLogin();
if (OrbitImageAnalysis.loginOk) {
HashSet annoNames = new HashSet(model.getSize());
for (ImageAnnotation ia : model.getAllElements()) {
annoNames.add(ia.getDescription());
}
for (ImageAnnotation annoOld : annotationClipboard) {
// clone annotation to be pasted in the same image (duplicated)
ImageAnnotation anno = annoOld.clone();
anno.getShape().getShapeList().set(0, ((IScaleableShape) anno.getFirstShape()).getScaledInstance(scaleRatio * 100d, new Point(0, 0))); // normalize scale to mm per pixel ratio of source and dest image
((IScaleableShape) anno.getFirstShape()).setScale(100d);
anno.setSelected(true);
anno.setUserId(OrbitImageAnalysis.loginUser);
if (iFrame.getRdf() != null)
anno.setRawDataFileId(iFrame.getRdf().getRawDataFileId());
anno.setDescription(OrbitUtils.getNewName(anno.getDescription(), annoNames));
model.addElement(anno);
iFrame.recognitionFrame.getAnnotations().add(anno);
cnt++;
// save in DB?
if (cbSave.isSelected() && anno.getRawDataFileId() > 0) {
try {
int id = DALConfig.getImageProvider().InsertRawAnnotation(anno);
anno.setRawAnnotationId(id);
} catch (Exception e) {
logger.error("error: ", e);
}
}
}
}
if (cnt > 0) {
model.filter();
iFrame.repaint();
logger.info(cnt + " annotation(s) pasted");
//JOptionPane.showMessageDialog(this, cnt+" annotation(s) successfully pasted (but not saved in the database).\nIf you want to persist the annotations please click on Options->Save annotations (in DB).", "Annotations pasted", JOptionPane.INFORMATION_MESSAGE);
}
} else {
JOptionPane.showMessageDialog(this, "Please copy first one or several annotations to clipboard.", "No annotation in clipboard", JOptionPane.ERROR_MESSAGE);
}
}
/**
* 0 means all groups, >0 means one specific active group
*
* @return
*/
public int getActiveGroup() {
return activeGroup;
}
/**
* 0 means all groups, >0 means one specific active group (default group for new annotations)
*
* @return
*/
public int getDefaultGroup() {
return defaultGroup;
}
public AtomicBoolean getAnnoListAdjusting() {
return annoListAdjusting;
}
public JList getList() {
return list;
}
private class AnnotationListCellRenderer extends DefaultListCellRenderer {
private static final long serialVersionUID = 1L;
protected long maxHashSize = 500;
//private final HashMap cellHash = new HashMap();
protected Map cellCache = Collections.synchronizedMap(new HashMap());
private ExecutorService executor = Executors.newSingleThreadExecutor();
private ImageIcon dummyThn = null;
public AnnotationListCellRenderer() {
dummyThn = new ImageIcon(new BufferedImage(thumbnailWidth, thumbnailHeight, BufferedImage.TYPE_INT_RGB));
dummyThn.getImage().getGraphics().setColor(Color.white);
dummyThn.getImage().getGraphics().fillRect(0, 0, dummyThn.getIconWidth(), dummyThn.getIconHeight());
}
/**
* clears the cell cache
*/
public void clear() {
cellCache.clear();
}
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
ImageAnnotation annotation = (ImageAnnotation) value;
OrbitUser emp = DALConfig.getImageProvider().getOrbitUser(annotation.getUserId());
String userFullname = annotation.getUserId();
if (emp != null) userFullname = emp.getFirstName() + " " + emp.getLastName();
String s = "" + annotation.getDescription() + "
[" + userFullname + "]
" + annotation.getSubTypeName() + " Group " + annotation.getGroup() + "";
JLabel label = (JLabel) super.getListCellRendererComponent(list, s, index, isSelected, cellHasFocus);
if (annotation.getDescription().length() > 100)
label.setVerticalTextPosition(TOP);
else label.setVerticalTextPosition(CENTER);
// get and set icon
ImageIcon icon = dummyThn;
int shapeHash = 0;
if (annotation.getShape().getShapeList() != null && annotation.getShape().getShapeList().size() > 0)
shapeHash = annotation.getShape().getShapeList().get(0).getBounds().x + annotation.getShape().getShapeList().get(0).getBounds().y + annotation.getShape().getShapeList().get(0).getBounds().width + annotation.getShape().getShapeList().get(0).getBounds().height;
int hash = label.getText().hashCode() + index + shapeHash;
if (cellCache.containsKey(hash)) icon = cellCache.get(hash);
else {
try {
if (cellCache.size() <= maxHashSize)
executor.execute(new ThnRunny(annotation, hash));
} catch (Throwable re) {
// can happen while shutting down the executor, but no problem
}
} // not in hash
label.setIcon(icon);
return label;
//return super.getListCellRendererComponent(list, label, index, isSelected, cellHasFocus);
}
/**
* Helper class for thumbnail creation in separate thread.
*
* @author stritma1
*/
public class ThnRunny implements Runnable {
private ImageAnnotation annotation = null;
private int hash = 0;
public ThnRunny(ImageAnnotation annotation, int hash) {
this.hash = hash;
this.annotation = annotation;
}
public void run() {
try {
ClassShape classShape = annotation.getShape();
if (classShape != null && classShape.getShapeList() != null) {
if (classShape.getShapeList() != null && classShape.getShapeList().size() > 0) {
IScaleableShape p = (IScaleableShape) classShape.getShapeList().get(0); // only the first shape
ImageFrame iFrame = OrbitImageAnalysis.getInstance().getIFrame();
if (iFrame != null) {
final long maxW = 2000;
Rectangle rect = p.getScaledInstance(100d, new Point(0, 0)).getBounds();
PlanarImage img = iFrame.recognitionFrame.bimg.getImage();
if ((long) rect.getWidth() * rect.getHeight() > (maxW * maxW)) {
if (iFrame.recognitionFrame.bimg.getMipMaps() != null && iFrame.recognitionFrame.bimg.getMipMaps().length > 0) {
img = iFrame.recognitionFrame.bimg.getMipMaps()[iFrame.recognitionFrame.bimg.getMipMaps().length - 1].getImage();
double scale = (double) img.getWidth() / (double) iFrame.recognitionFrame.bimg.getImage().getWidth();
rect = p.getScaledInstance(scale * 100d, new Point(0, 0)).getBounds();
}
}
BufferedImage bi = img.getAsBufferedImage(rect, iFrame.recognitionFrame.bimg.getImage().getColorModel());
bi = TiffConverter.makeScaledImage(bi, thumbnailWidth, thumbnailHeight);
ImageIcon icon = new ImageIcon(bi);
if ((cellCache != null) && (icon != null)) {
cellCache.put(hash, icon);
list.revalidate();
list.repaint();
}
}
}
}
} catch (Throwable t) {
// can happen (e.g, outofmemory), but no problem
}
}
} // ThnRunny
}
}