diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..3d47f986c41db29ec6dc0d5036bf760b3a1cf366 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.idea/ +target/ +.settings/ +*.iml +.project +.classpath \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..16a016f9f0d85b7cdd630cf55040481644cbfbfd --- /dev/null +++ b/pom.xml @@ -0,0 +1,104 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <!-- Inherited Icy Parent POM --> + <parent> + <groupId>org.bioimageanalysis.icy</groupId> + <artifactId>parent-pom-plugin</artifactId> + <version>1.0.3</version> + </parent> + + <!-- Project Information --> + <artifactId>distance-profiler</artifactId> + <version>1.0.0</version> + + <packaging>jar</packaging> + + <name>Distance Profiler</name> + <description> + rack Processor plugin that computes the relative distance between detections and their evolution over time, with possibility to + export to Excel for further analysis + </description> + <url>http://icy.bioimageanalysis.org/plugin/distance-profiler-track-processor/</url> + <inceptionYear>2020</inceptionYear> + + <organization> + <name>Institut Pasteur</name> + <url>https://pasteur.fr</url> + </organization> + + <licenses> + <license> + <name>GNU GPLv3</name> + <url>https://www.gnu.org/licenses/gpl-3.0.en.html</url> + <distribution>repo</distribution> + </license> + </licenses> + + <developers> + <developer> + <id>sdallongeville</id> + <name>Stéphane Dallongeville</name> + <url>https://research.pasteur.fr/fr/member/stephane-dallongeville/</url> + <roles> + <role>founder</role> + <role>lead</role> + <role>architect</role> + <role>developer</role> + <role>debugger</role> + <role>tester</role> + <role>maintainer</role> + <role>support</role> + </roles> + </developer> + </developers> + + <!-- Project properties --> + <properties> + + </properties> + + <!-- Project build configuration --> + <build> + + </build> + + <!-- List of project's dependencies --> + <dependencies> + <!-- The core of Icy --> + <dependency> + <groupId>org.bioimageanalysis.icy</groupId> + <artifactId>icy-kernel</artifactId> + </dependency> + + <!-- The EzPlug library, simplifies writing UI for Icy plugins. --> + <dependency> + <groupId>org.bioimageanalysis.icy</groupId> + <artifactId>ezplug</artifactId> + </dependency> + + <dependency> + <groupId>org.bioimageanalysis.icy</groupId> + <artifactId>track-manager</artifactId> + <version>1.4.6</version> + </dependency> + + <dependency> + <groupId>org.bioimageanalysis.icy</groupId> + <artifactId>workbooks</artifactId> + <version>3.4.10</version> + </dependency> + </dependencies> + + <!-- Icy Maven repository (to find parent POM) --> + <repositories> + <repository> + <id>icy</id> + <name>Icy's Nexus</name> + <url>https://icy-nexus.pasteur.fr/repository/Icy/</url> + </repository> + </repositories> +</project> \ No newline at end of file diff --git a/src/main/java/plugins/adufour/trackprocessors/DistanceProfiler.java b/src/main/java/plugins/adufour/trackprocessors/DistanceProfiler.java new file mode 100644 index 0000000000000000000000000000000000000000..ef189ea0c6a92e670617f8bd220baa52cac67c57 --- /dev/null +++ b/src/main/java/plugins/adufour/trackprocessors/DistanceProfiler.java @@ -0,0 +1,157 @@ +package plugins.adufour.trackprocessors; + +import java.awt.BorderLayout; +import java.awt.FlowLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.io.FileOutputStream; +import java.util.ArrayList; + +import javax.swing.JButton; +import javax.swing.JFileChooser; +import javax.swing.JPanel; +import javax.vecmath.Point3d; + +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; + +import icy.gui.dialog.ConfirmDialog; +import plugins.adufour.vars.gui.swing.SwingVarEditor; +import plugins.adufour.vars.lang.VarWorkbook; +import plugins.fab.trackmanager.PluginTrackManagerProcessor; +import plugins.fab.trackmanager.TrackGroup; +import plugins.fab.trackmanager.TrackSegment; +import plugins.nchenouard.spot.Detection; + +public class DistanceProfiler extends PluginTrackManagerProcessor +{ + public DistanceProfiler() + { + setName("Relative distance between detections"); + } + + @Override + public void Close() + { + + } + + @Override + public void Compute() + { + panel.setVisible(false); + panel.removeAll(); + panel.setLayout(new BorderLayout()); + + final VarWorkbook wb = new VarWorkbook("Distance profile", "Distance profile"); + SwingVarEditor<Workbook> viewer = (SwingVarEditor<Workbook>) wb.createVarViewer(); + panel.add(viewer.getEditorComponent(), BorderLayout.CENTER); + + Sheet sheet = wb.getValue().getSheetAt(0); + int rowIndex = 0; + + Row headerRow = sheet.createRow(rowIndex++); + headerRow.createCell(0).setCellValue("Group (A)"); + headerRow.createCell(1).setCellValue("Track (A)"); + headerRow.createCell(2).setCellValue("Group (B)"); + headerRow.createCell(3).setCellValue("Track (B)"); + headerRow.createCell(4).setCellValue("Frame"); + headerRow.createCell(5).setCellValue("Distance (pixels)"); + + // System.out.println("Track Group (A)\tTrack ID (A)\tTrack Group (B)\tTrack ID (B)\tFrame\tDistance (pixels)"); + + ArrayList<TrackGroup> trackGroups = trackPool.getTrackGroupList(); + + for (int trackGroupIndexA = 0; trackGroupIndexA < trackGroups.size(); trackGroupIndexA++) + { + TrackGroup tgA = trackGroups.get(trackGroupIndexA); + ArrayList<TrackSegment> trackSegmentsA = tgA.getTrackSegmentList(); + + for (int trackGroupIndexB = trackGroupIndexA; trackGroupIndexB < trackGroups.size(); trackGroupIndexB++) + { + TrackGroup tgB = trackGroups.get(trackGroupIndexB); + ArrayList<TrackSegment> trackSegmentsB = tgB.getTrackSegmentList(); + + for (int trackSegmentIndexA = 0; trackSegmentIndexA < trackSegmentsA.size(); trackSegmentIndexA++) + { + TrackSegment tsA = trackSegmentsA.get(trackSegmentIndexA); + int trackIDA = tgA.getTrackSegmentList().indexOf(tsA); + + for (int trackSegmentIndexB = trackSegmentIndexA; trackSegmentIndexB < trackSegmentsB.size(); trackSegmentIndexB++) + { + TrackSegment tsB = trackSegmentsB.get(trackSegmentIndexB); + + if (tsA == tsB) continue; + + int trackIDB = tgB.getTrackSegmentList().indexOf(tsB); + + // measure the distance between each detection set + for (Detection dA : tsA.getDetectionList()) + { + Point3d pA = new Point3d(dA.getX(), dA.getY(), dA.getZ()); + + for (Detection dB : tsB.getDetectionList()) + { + if (dA.getT() != dB.getT()) continue; + + Point3d pB = new Point3d(dB.getX(), dB.getY(), dB.getZ()); + + Row row = sheet.createRow(rowIndex++); + row.createCell(0).setCellValue(tgA.getDescription()); + row.createCell(1).setCellValue("" + trackIDA); + row.createCell(2).setCellValue(tgB.getDescription()); + row.createCell(3).setCellValue("" + trackIDB); + row.createCell(4).setCellValue("" + dA.getT()); + row.createCell(5).setCellValue(pA.distance(pB)); + // System.out.println(tgA.getDescription() + "\t" + trackIDA + "\t" + // + tgB.getDescription() + "\t" + trackIDB + "\t" + dA.getT() + + // "\t" + pA.distance(pB)); + } + } + } + } + } + } + // notify the viewer that the value has changed + viewer.valueChanged(wb, null, wb.getValue()); + + JPanel options = new JPanel(new FlowLayout(FlowLayout.CENTER)); + JButton bExport = new JButton("Export to Excel"); + bExport.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + JFileChooser f = new JFileChooser(); + if (f.showOpenDialog(getPanel().getParent()) != JFileChooser.APPROVE_OPTION) return; + + File file = f.getSelectedFile(); + if (!file.getPath().endsWith(".xls") && !file.getPath().endsWith(".xlsx")) file = new File(file.getPath() + ".xls"); + + if (!file.exists() || ConfirmDialog.confirm("Overwrite " + file.getPath() + "?")) + { + try + { + wb.getValue().write(new FileOutputStream(file, false)); + } + catch (Exception e1) + { + throw new RuntimeException(e1); + } + } + } + }); + options.add(bExport); + + panel.add(options, BorderLayout.NORTH); + + panel.setVisible(true); + } + + @Override + public void displaySequenceChanged() + { + } +}