diff --git a/.classpath b/.classpath
index f7ad53eba4..725899b55b 100644
--- a/.classpath
+++ b/.classpath
@@ -1,367 +1,372 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.gitignore b/.gitignore
index 21ed2319f0..8ed7b69bbe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,8 @@
/bin/
/export/
/null/
-classes
\ No newline at end of file
+classes
+*.csv
+*.pdf
+*.png
+/output/
diff --git a/src/gov/nih/mipav/view/renderer/WildMagic/VOI/VOILatticeManagerInterface.java b/src/gov/nih/mipav/view/renderer/WildMagic/VOI/VOILatticeManagerInterface.java
index bcca3ceb42..c082dfe85a 100644
--- a/src/gov/nih/mipav/view/renderer/WildMagic/VOI/VOILatticeManagerInterface.java
+++ b/src/gov/nih/mipav/view/renderer/WildMagic/VOI/VOILatticeManagerInterface.java
@@ -23,6 +23,8 @@
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Vector;
import javax.swing.ButtonGroup;
@@ -33,6 +35,8 @@
import javax.swing.JPanel;
import javax.swing.JTextField;
+import org.janelia.mipav.plugins.worm.untwisting.AccurateModeListener;
+
import WildMagic.LibFoundation.Distance.DistanceVector3Segment3;
import WildMagic.LibFoundation.Mathematics.Segment3f;
import WildMagic.LibFoundation.Mathematics.Vector3f;
@@ -1092,39 +1096,78 @@ private void setVoxelSize()
defaultVoxelSize = new JTextField( "" + VoxelSize );
defaultVoxelSize.addActionListener(this);
JPanel panel = new JPanel( new GridLayout(1, 3) );
- panel.add( new JLabel( "Current Voxel Size" ) );
- panel.add( defaultVoxelSize );
- panel.add( new JLabel("um") );
+ panel.add(new JLabel("Current Voxel Size"));
+ panel.add(defaultVoxelSize);
+ panel.add(new JLabel("um"));
updateVoxelSize = new JDialog();
updateVoxelSize.getContentPane().setLayout(new BorderLayout());
- updateVoxelSize.setModalityType( JDialog.ModalityType.APPLICATION_MODAL);
- updateVoxelSize.getContentPane().add( panel, BorderLayout.NORTH );
- updateVoxelSize.getContentPane().add( OK, BorderLayout.SOUTH );
+ updateVoxelSize.setModalityType(JDialog.ModalityType.APPLICATION_MODAL);
+ updateVoxelSize.getContentPane().add(panel, BorderLayout.NORTH);
+ updateVoxelSize.getContentPane().add(OK, BorderLayout.SOUTH);
updateVoxelSize.pack();
updateVoxelSize.setResizable(false);
MipavUtil.centerOnScreen(updateVoxelSize);
updateVoxelSize.setVisible(true);
}
-
- public void mouseReleased(MouseEvent e) {
+
+ // Handle event when mouse button is released
+ public void mouseReleased(MouseEvent e) {
movingPickedPoint = false;
- if(editingCrossSections) {
+ if (editingCrossSections) {
latticeModel.showLattice(true);
}
- }
+ }
+ // Handle key press events if the key is pressed
public void keyPressed(KeyEvent e) {
isShiftSelected = e.isShiftDown();
}
-
+
+ // Maintains state for accurate mode and listeners for its changes
+ private boolean accurateMode = true;
+ // List of listeners that will be notified when accurate mode changes
+ // TODO: might want to change the array into set
+ private List listeners = new ArrayList<>();
+
+ // Check if the accurate mode is currently enabled
+ public boolean isAccurateMode() {
+ return accurateMode;
+ }
+
+ // Toggle the accurate mode state and notify all listeners
+ public void toggleAccurateMode() {
+ accurateMode = !accurateMode;
+ setAccurateMode(accurateMode);
+ }
+
+ // Set the accurate mode and notify listeners about the mode change
+ public void setAccurateMode(boolean accurateMode) {
+ this.accurateMode = accurateMode;
+ for (AccurateModeListener listener : listeners) {
+ listener.accurateModeChanged(accurateMode);
+ }
+ }
+
+ // Add a new listener to be notified about accurate mode changes
+ public void addAccurateModeListener(AccurateModeListener listener) {
+ listeners.add(listener);
+ }
+
+ // Handle key release events and perform actions based on the key released
public void keyReleased(KeyEvent e) {
isShiftSelected = e.isShiftDown();
movingPickedPoint = false;
- if(editingCrossSections) {
- switch(e.getKeyChar()) {
+
+ // Specific actions based on key codes, e.g., toggle accurate mode on 'M' key
+ if (e.getKeyCode() == KeyEvent.VK_M) {
+ toggleAccurateMode();
+ }
+
+ if (editingCrossSections) {
+ switch (e.getKeyChar()) {
case '+':
latticeModel.decreaseCrossSectionSamples();
break;
@@ -1155,7 +1198,7 @@ public void keyReleased(KeyEvent e) {
case 'R':
latticeModel.showLattice(false);
latticeModel.resetCrossSections();
- if(editingCrossSections) {
+ if (editingCrossSections) {
latticeModel.showLattice(true);
}
break;
@@ -1168,46 +1211,40 @@ public void keyReleased(KeyEvent e) {
}
}
}
-
- public static VOIBase findNearestAnnotation( final VOI annotations, final Vector3f startPt, final Vector3f endPt, final Vector3f pt ) {
+ public static VOIBase findNearestAnnotation(final VOI annotations, final Vector3f startPt, final Vector3f endPt,
+ final Vector3f pt) {
int pickedAnnotation = -1;
float minDist = Float.MAX_VALUE;
- for ( int i = 0; i < annotations.getCurves().size(); i++ )
- {
+ for (int i = 0; i < annotations.getCurves().size(); i++) {
final Vector3f annotationPt = annotations.getCurves().elementAt(i).elementAt(0);
final float distance = pt.distance(annotationPt);
- if ( distance < minDist )
- {
+ if (distance < minDist) {
minDist = distance;
- if ( minDist <= 12 )
- {
+ if (minDist <= 12) {
pickedAnnotation = i;
}
}
}
// System.err.println("findNearestAnnotation " + minDist + " " + pickedAnnotation );
- if ( (pickedAnnotation == -1) && (startPt != null) && (endPt != null) )
- {
+ if ((pickedAnnotation == -1) && (startPt != null) && (endPt != null)) {
minDist = Float.MAX_VALUE;
// look at the vector under the mouse and see which lattice point is closest...
final Segment3f mouseVector = new Segment3f(startPt, endPt);
- for ( int i = 0; i < annotations.getCurves().size(); i++ )
- {
- DistanceVector3Segment3 dist = new DistanceVector3Segment3(annotations.getCurves().elementAt(i).elementAt(0), mouseVector);
+ for (int i = 0; i < annotations.getCurves().size(); i++) {
+ DistanceVector3Segment3 dist = new DistanceVector3Segment3(
+ annotations.getCurves().elementAt(i).elementAt(0), mouseVector);
float distance = dist.Get();
- // System.err.println( i + " " + distance );
- if ( distance < minDist )
- {
+ // System.err.println( i + " " + distance );
+ if (distance < minDist) {
minDist = distance;
- if ( minDist <= 12 )
- {
+ if (minDist <= 12) {
pickedAnnotation = i;
}
}
}
}
- if ( pickedAnnotation != -1 ) {
+ if (pickedAnnotation != -1) {
return annotations.getCurves().elementAt(pickedAnnotation);
}
return null;
diff --git a/src/gov/nih/mipav/view/renderer/WildMagic/VolumeTriPlanarRender.java b/src/gov/nih/mipav/view/renderer/WildMagic/VolumeTriPlanarRender.java
index d5da71688a..bc3ce1cbf9 100644
--- a/src/gov/nih/mipav/view/renderer/WildMagic/VolumeTriPlanarRender.java
+++ b/src/gov/nih/mipav/view/renderer/WildMagic/VolumeTriPlanarRender.java
@@ -53,7 +53,11 @@
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
import java.util.Vector;
import com.jogamp.opengl.GLAutoDrawable;
@@ -61,6 +65,10 @@
import com.jogamp.opengl.awt.GLCanvas;
import javax.swing.KeyStroke;
+import org.janelia.mipav.plugins.worm.untwisting.AccurateModeListener;
+import org.janelia.mipav.plugins.worm.untwisting.PlotDataUpdateListener;
+import org.janelia.mipav.plugins.worm.untwisting.PlugInDialogVolumeRenderDualJanelia;
+
import WildMagic.LibFoundation.Mathematics.ColorRGBA;
import WildMagic.LibFoundation.Mathematics.Mathf;
import WildMagic.LibFoundation.Mathematics.Matrix3f;
@@ -844,8 +852,15 @@ else if ( m_bErase )
m_bMouseDrag = false;
}
- private void PickVolume3D(Vector3f kPos, Vector3f kDir, Vector3f maxPt)
+
+
+ private void PickVolume3D(Vector3f kPos, Vector3f kDir, Vector3f maxPtAccurate)
{
+ // Lists to store values and points for plot updates or further processing
+ List plotAccurateValues = new ArrayList<>();
+ List plotValues = new ArrayList<>();
+ List points = new ArrayList<>();
+
m_kPicker.Execute(m_kVolumeRayCast.GetScene(),kPos,kDir,0.0f,
Float.MAX_VALUE);
@@ -857,6 +872,8 @@ private void PickVolume3D(Vector3f kPos, Vector3f kDir, Vector3f maxPt)
Vector3f pickedPoints[] = new Vector3f[m_kPicker.Records.size()];
float distances[] = new float[m_kPicker.Records.size()];
+ long time = System.currentTimeMillis();
+
for ( int i = 0; i < m_kPicker.Records.size(); i++ )
{
PickRecord kPickPoint = m_kPicker.Records.elementAt(i);
@@ -879,7 +896,9 @@ private void PickVolume3D(Vector3f kPos, Vector3f kDir, Vector3f maxPt)
firstIntersectionPoint.copy(pickedPoints[0]);
secondIntersectionPoint.copy(pickedPoints[1]);
+ float maxValueAccurate = -Float.MAX_VALUE;
float maxValue = -Float.MAX_VALUE;
+ Vector3f maxPt = new Vector3f();
Vector3f p0 = new Vector3f(firstIntersectionPoint);
Vector3f p1 = new Vector3f(secondIntersectionPoint);
@@ -931,62 +950,88 @@ private void PickVolume3D(Vector3f kPos, Vector3f kDir, Vector3f maxPt)
continue;
}
}
- float value = 0;
- int sampleX = Math.round(p0.X);
- int sampleY = Math.round(p0.Y);
- int sampleZ = Math.round(p0.Z);
- // loop over imageA, imageB, hyperstack, get value, apply color & opacity for 'value'
- // take the maximum value:
- if ( hyperstack != null ) {
- for ( int h = 0; h < hyperstack.length; h++ ) {
- if ( (hyperstack[h] != null) && (hyperstack[h].GetImage() != null) )
- {
- if ( m_kVolumeRayCast.getImageOn(h) )
- {
- value = Math.max(value, hyperstack[h].GetTransferedValue(sampleX, sampleY, sampleZ));
+
+
+ // Two modes can be switched from the accurate mode to the 3-color mode(not working currently) by press key "M" or "m"
+ if (m_kVOIInterface.isAccurateMode()) {
+ // Old Mipav but more accurate click
+ float valueAccurate = 0;
+ valueAccurate = m_kVolumeImageA.GetImage().getFloatTriLinearBounds(p0.X, p0.Y, p0.Z);
+ if ((m_kVolumeImageB != null) && (m_kVolumeImageB.GetImage() != null)) {
+ float valueB = m_kVolumeImageB.GetImage().getFloatTriLinearBounds(p0.X, p0.Y, p0.Z);
+ float blend = getABBlend();
+ valueAccurate = (blend * valueAccurate + (1 - blend) * valueB);
+ }
+
+ if (valueAccurate > maxValueAccurate) {
+ maxValueAccurate = valueAccurate;
+ maxPtAccurate.copy(p0);
+ }
+ plotAccurateValues.add(valueAccurate);// add value to the list for plotting
+
+ } else {
+ //this is not working, made for more than 3 colors. -Diyi Chen May 1, 2024
+ float value = 0;
+ int sampleX = Math.round(p0.X);
+ int sampleY = Math.round(p0.Y);
+ int sampleZ = Math.round(p0.Z);
+ // loop over imageA, imageB, hyperstack, get value, apply color & opacity for
+ // 'value'
+ // take the maximum value:
+ if (hyperstack != null) {
+ for (int h = 0; h < hyperstack.length; h++) {
+ if ((hyperstack[h] != null) && (hyperstack[h].GetImage() != null)) {
+ if (m_kVolumeRayCast.getImageOn(h)) {
+ value = Math.max(value,
+ hyperstack[h].GetTransferedValue(sampleX, sampleY, sampleZ));
+ }
}
}
+ } else if ((m_kVolumeImageB != null) && (m_kVolumeImageB.GetImage() != null)) {
+ float valueA = m_kVolumeImageA.GetTransferedValue(sampleX, sampleY, sampleZ);
+ float valueB = m_kVolumeImageB.GetTransferedValue(sampleX, sampleY, sampleZ);
+ float blend = getABBlend();
+ value = (blend * valueA + (1 - blend) * valueB);
+ } else {
+ // Only one imageA:
+ value = m_kVolumeImageA.GetTransferedValue(sampleX, sampleY, sampleZ);
}
+ if (value > maxValue) {
+ maxValue = value;
+ maxPt.copy(p0);
+ }
+ plotValues.add(value);// add value to the list for plotting
}
- else if ( (m_kVolumeImageB != null) && (m_kVolumeImageB.GetImage() != null)) {
- float valueA = m_kVolumeImageA.GetTransferedValue(sampleX, sampleY, sampleZ);
- float valueB = m_kVolumeImageB.GetTransferedValue(sampleX, sampleY, sampleZ);
- float blend = getABBlend();
- value = (blend * valueA + (1 - blend) * valueB);
- }
- else
- {
- // Only one imageA:
- value = m_kVolumeImageA.GetTransferedValue(sampleX, sampleY, sampleZ);
- }
- if ( value > maxValue )
- {
- maxValue = value;
- maxPt.copy(p0);
- }
+ Vector3f p2 = new Vector3f();
+ p2.copy(p0);
+ points.add(p2);
}
- if ( maxValue != -Float.MAX_VALUE )
- {
+ if (!m_kVOIInterface.isAccurateMode()) {
+ maxValueAccurate = maxValue;
+ maxPtAccurate.copy(maxPt);
+ }
+
+ if (maxValueAccurate != -Float.MAX_VALUE) {
boolean picked = false;
// System.err.println( "mouse drag? " + m_bMouseDrag );
- if ( !m_bMouseDrag ) {
+ if (!m_bMouseDrag) {
// select or create a new marker:
- picked = select3DMarker( firstIntersectionPoint, secondIntersectionPoint, maxPt, rightMousePressed, altPressed );
- }
- else if ( m_bMouseDrag ) {
+ picked = select3DMarker(firstIntersectionPoint, secondIntersectionPoint, maxPtAccurate,
+ rightMousePressed, altPressed);
+ } else if (m_bMouseDrag) {
// modify currently selected, if exists
- picked = modify3DMarker( firstIntersectionPoint, secondIntersectionPoint, maxPt );
+ picked = modify3DMarker(firstIntersectionPoint, secondIntersectionPoint, maxPtAccurate);
}
- if ( !picked )
+ if (!picked)
{
// add a new picked point:
short id = (short) m_kVolumeImageA.GetImage().getVOIs().getUniqueID();
int colorID = 0;
VOI newTextVOI = new VOI((short) colorID, "annotation3d_" + id, VOI.ANNOTATION, -1.0f);
VOIText textVOI = new VOIText( );
- textVOI.add( maxPt );
- textVOI.add( maxPt );
+ textVOI.add( maxPtAccurate );
+ textVOI.add( maxPtAccurate );
// Transformation world = m_kVolumeRayCast.getMesh().World;
// Vector3f dir = world.InvertVector(m_spkCamera.GetRVector());
// dir.scale(5);
@@ -1017,16 +1062,38 @@ else if ( !doAutomaticLabels() )
m_kVOIInterface.updateDisplay();
}
}
- }
+ }
+ if (m_kVOIInterface.isAccurateMode()) {
+ notifyPlotListeners(points, plotAccurateValues, "Selection Chart");
+ } else {
+ notifyPlotListeners(points, plotValues, "3-Color Chart");
+ }
+ }
+
+ // Create a Set to hold PlotListener instances
+ private Set listeners = new HashSet<>();
+
+ // update all listeners with new plot values and title.
+ public void notifyPlotListeners(List points, List values, String title) {
+ for (PlotDataUpdateListener listener : listeners) {
+ listener.updatePlotPanel(points, values, title);
+ }
+ }
+
+ // add a new PlotListener
+ public void addPlotListener(PlotDataUpdateListener listener) {
+ listeners.add(listener);
}
- private boolean PickSlice3D(Vector3f kPos, Vector3f kDir, Vector3f maxPt)
- {
+ // remove an existing PlotListener
+ public void removePlotListener(PlotDataUpdateListener listener) {
+ listeners.remove(listener);
+ }
+
+ private boolean PickSlice3D(Vector3f kPos, Vector3f kDir, Vector3f maxPt) {
// pick on the slices
- m_kPicker.Execute(m_kSlices.GetScene(),kPos,kDir,0.0f,
- Float.MAX_VALUE);
- if (m_kPicker.Records.size() > 0)
- {
+ m_kPicker.Execute(m_kSlices.GetScene(), kPos, kDir, 0.0f, Float.MAX_VALUE);
+ if (m_kPicker.Records.size() > 0) {
PickRecord kPickPoint = m_kPicker.GetClosestNonnegative();
TriMesh kMesh = (TriMesh)kPickPoint.Intersected;
int iPlane = m_kSlices.whichPlane(kMesh);
diff --git a/src/gov/nih/mipav/view/renderer/WildMagic/WormUntwisting/LatticeModel.java b/src/gov/nih/mipav/view/renderer/WildMagic/WormUntwisting/LatticeModel.java
index 0076dc92d0..930f70d45d 100644
--- a/src/gov/nih/mipav/view/renderer/WildMagic/WormUntwisting/LatticeModel.java
+++ b/src/gov/nih/mipav/view/renderer/WildMagic/WormUntwisting/LatticeModel.java
@@ -82,7 +82,7 @@ public static void checkParentDir( String parentDir )
} else if (parentFileDir.exists() && !parentFileDir.isDirectory()) { // do nothing
} else { // voiFileDir does not exist
// System.err.println( "LatticeModel:checkParentDir" + parentDir);
- parentFileDir.mkdir();
+ parentFileDir.mkdirs();
}
}
@@ -374,7 +374,7 @@ public static void saveAllVOIsTo(final String voiDir, final ModelImage image) {
voiFileDir.delete();
} else { // voiFileDir does not exist
// System.err.println( "saveAllVOIsTo " + voiDir);
- voiFileDir.mkdir();
+ voiFileDir.mkdirs();
}
final int nVOI = VOIs.size();
@@ -445,10 +445,8 @@ public static void saveAnnotationsAsCSV(final String dir, final String fileName,
// check files, create new directories and delete any existing files:
final File fileDir = new File(dir);
- if (fileDir.exists() && fileDir.isDirectory()) {}
- else if (fileDir.exists() && !fileDir.isDirectory()) { // voiFileDir.delete();
- } else { // voiFileDir does not exist
- fileDir.mkdir();
+ if (!fileDir.exists() && !fileDir.mkdirs()) { // voiFileDir does not exist
+ System.err.println("Failed to create directory in svaeAnnotationAsCSV: " + fileDir);
}
File file = new File(fileDir + File.separator + fileName);
@@ -2815,8 +2813,8 @@ private void saveMeshContoursCSV() {
String dir = sharedOutputDir + File.separator + "model_contours" + File.separator;
File fileDir = new File(dir);
- if ( !fileDir.exists() ) { // voiFileDir does not exist
- fileDir.mkdir();
+ if (!fileDir.exists() && !fileDir.mkdirs()) { // voiFileDir does not exist
+ System.err.println("Failed to create directory in saveMeshContourCSV: " + fileDir);
}
File file = new File(dir + File.separator + "wormContours.csv");
@@ -3075,10 +3073,8 @@ public ModelImage segmentLattice(final ModelImage image, boolean saveContourImag
final File lrFile = new File(voiDir + list[i]);
lrFile.delete();
}
- } else if (voiFileDir.exists() && !voiFileDir.isDirectory()) { // voiFileDir.delete();
- } else { // voiFileDir does not exist
- // System.err.println( "segmentLattice" + voiDir);
- voiFileDir.mkdir();
+ } else if (!voiFileDir.exists() && !voiFileDir.mkdirs()) { // voiFileDir does not exist
+ System.err.println("Failed to create directory in segmentLattice: " + voiFileDir);
}
System.err.println( "Segment Lattice " + paddingFactor );
@@ -3734,17 +3730,17 @@ public void setImage(ModelImage image)
outputDirectory = new String(imageA.getImageDirectory() + JDialogBase.makeImageName(imageA.getImageFileName(), "") + File.separator);
boolean isStraight = image.getImageFileName().contains("_straight");
File file = new File(outputDirectory);
- if ( !file.exists() && !isStraight ) file.mkdir();
+ if ( !file.exists() && !isStraight ) file.mkdirs();
outputDirectory += JDialogBase.makeImageName(imageA.getImageFileName(), "_results") + File.separator;
file = new File(outputDirectory);
- if ( !file.exists() && !isStraight ) file.mkdir();
+ if ( !file.exists() && !isStraight ) file.mkdirs();
}
}
public void setSharedDirectory( String dir ) {
sharedOutputDir = new String(dir);
File file = new File(sharedOutputDir + File.separator + "output_images" + File.separator);
- if ( !file.exists() ) file.mkdir();
+ if ( !file.exists() ) file.mkdirs();
}
@@ -5341,14 +5337,14 @@ protected VOI saveAnnotationStatistics(final String imageDir, final ModelImage m
if (voiFileDir.exists() && voiFileDir.isDirectory()) { // do nothing
} else if (voiFileDir.exists() && !voiFileDir.isDirectory()) { // voiFileDir.delete();
} else { // voiFileDir does not exist
- voiFileDir.mkdir();
+ voiFileDir.mkdirs();
}
voiDir = imageDir + "statistics" + File.separator;
voiFileDir = new File(voiDir);
if (voiFileDir.exists() && voiFileDir.isDirectory()) {} else if (voiFileDir.exists() && !voiFileDir.isDirectory()) {} else { // voiFileDir
- voiFileDir.mkdir();
+ voiFileDir.mkdirs();
}
File file = new File(voiDir + "AnnotationInfo" + postFix + ".csv");
@@ -5404,7 +5400,7 @@ protected void saveDiameters( Vector diameters, String imageDir ) {
} else if (voiFileDir.exists() && !voiFileDir.isDirectory()) { // voiFileDir.delete();
} else { // voiFileDir does not exist
// System.err.println( "saveDiameters " + voiDir);
- voiFileDir.mkdir();
+ voiFileDir.mkdirs();
}
voiDir = imageDir + "statistics" + File.separator;
@@ -5412,7 +5408,7 @@ protected void saveDiameters( Vector diameters, String imageDir ) {
if (voiFileDir.exists() && voiFileDir.isDirectory()) {
} else if (voiFileDir.exists() && !voiFileDir.isDirectory()) {} else { // voiFileDir does not exist
// System.err.println( "saveDiameters " + voiDir);
- voiFileDir.mkdir();
+ voiFileDir.mkdirs();
}
File file = new File(voiDir + "Diameters.csv");
@@ -5460,14 +5456,14 @@ protected void saveLatticeStatistics( String imageDir, final float length, final
if (voiFileDir.exists() && voiFileDir.isDirectory()) { // do nothing
} else if (voiFileDir.exists() && !voiFileDir.isDirectory()) { // voiFileDir.delete();
} else { // voiFileDir does not exist
- voiFileDir.mkdir();
+ voiFileDir.mkdirs();
}
voiDir = imageDir + "statistics" + File.separator;
voiFileDir = new File(voiDir);
if (voiFileDir.exists() && voiFileDir.isDirectory()) {
} else if (voiFileDir.exists() && !voiFileDir.isDirectory()) {} else { // voiFileDir does not exist
- voiFileDir.mkdir();
+ voiFileDir.mkdirs();
}
File file = new File(voiDir + "LatticeInfo" + postFix + ".csv");
@@ -5508,7 +5504,7 @@ protected void savePositions( VOIContour contour, String imageDir, String name )
} else if (voiFileDir.exists() && !voiFileDir.isDirectory()) { // voiFileDir.delete();
} else { // voiFileDir does not exist
// System.err.println( "savePositions " + voiDir);
- voiFileDir.mkdir();
+ voiFileDir.mkdirs();
}
voiDir = imageDir + "statistics" + File.separator;
@@ -5516,7 +5512,7 @@ protected void savePositions( VOIContour contour, String imageDir, String name )
if (voiFileDir.exists() && voiFileDir.isDirectory()) {
} else if (voiFileDir.exists() && !voiFileDir.isDirectory()) {} else { // voiFileDir does not exist
// System.err.println( "savePositions " + voiDir);
- voiFileDir.mkdir();
+ voiFileDir.mkdirs();
}
File file = new File(voiDir + name + "Positions.csv");
@@ -5558,7 +5554,7 @@ protected void saveSamplePlanes( VOI planes, String imageDir ) {
} else if (voiFileDir.exists() && !voiFileDir.isDirectory()) { // voiFileDir.delete();
} else { // voiFileDir does not exist
// System.err.println( "saveSamplePlanes " + voiDir);
- voiFileDir.mkdir();
+ voiFileDir.mkdirs();
}
voiDir = imageDir + "statistics" + File.separator;
@@ -5566,7 +5562,7 @@ protected void saveSamplePlanes( VOI planes, String imageDir ) {
if (voiFileDir.exists() && voiFileDir.isDirectory()) {
} else if (voiFileDir.exists() && !voiFileDir.isDirectory()) {} else { // voiFileDir does not exist
// System.err.println( "saveSamplePlanes " + voiDir);
- voiFileDir.mkdir();
+ voiFileDir.mkdirs();
}
File file = new File(voiDir + "SamplePlanes.csv");
@@ -6654,13 +6650,13 @@ private void saveImage(final String imageName, final ModelImage image, final boo
} else if (voiFileDir.exists() && !voiFileDir.isDirectory()) { // voiFileDir.delete();
} else { // voiFileDir does not exist
// System.err.println( "saveImage " + voiDir);
- voiFileDir.mkdir();
+ voiFileDir.mkdirs();
}
voiDir = outputDirectory + File.separator + "output_images" + File.separator;
voiFileDir = new File(voiDir);
if (voiFileDir.exists() && voiFileDir.isDirectory()) {} else if (voiFileDir.exists() && !voiFileDir.isDirectory()) {} else { // voiFileDir
- voiFileDir.mkdir();
+ voiFileDir.mkdirs();
}
final File file = new File(voiDir + imageName);
@@ -6688,7 +6684,7 @@ public static void saveImage(final ModelImage originalImage, final ModelImage im
} else if (voiFileDir.exists() && !voiFileDir.isDirectory()) { // voiFileDir.delete();
} else { // voiFileDir does not exist
// System.err.println( "saveImage " + voiDir);
- voiFileDir.mkdir();
+ voiFileDir.mkdirs();
}
voiDir = outputDirectory + File.separator + subDir + File.separator;
@@ -6729,7 +6725,7 @@ public static void saveImage(final ModelImage originalImage, final ModelImage im
// } else if (voiFileDir.exists() && !voiFileDir.isDirectory()) { // voiFileDir.delete();
// } else { // voiFileDir does not exist
// // System.err.println( "saveImage " + voiDir);
-// voiFileDir.mkdir();
+// voiFileDir.mkdirs();
// }
//
// maxVal++;
@@ -6785,7 +6781,7 @@ public static void saveContourAsCSV( ModelImage image, String subDir, String pos
} else if (voiFileDir.exists() && !voiFileDir.isDirectory()) { // voiFileDir.delete();
} else { // voiFileDir does not exist
// System.err.println( "saveImage " + voiDir);
- voiFileDir.mkdir();
+ voiFileDir.mkdirs();
}
voiDir = outputDirectory + File.separator + subDir + File.separator;
@@ -6805,7 +6801,7 @@ public static void saveContourAsCSV( final String voiDir, final String fileName,
if (fileDir.exists() && fileDir.isDirectory()) {}
else if (fileDir.exists() && !fileDir.isDirectory()) { // voiFileDir.delete();
} else { // voiFileDir does not exist
- fileDir.mkdir();
+ fileDir.mkdirs();
}
File file = new File(fileDir + File.separator + fileName);
if (file.exists()) {
@@ -6901,7 +6897,7 @@ public static void saveBasisVectorsAsCSV( ModelImage image, String subDir, Strin
} else if (voiFileDir.exists() && !voiFileDir.isDirectory()) { // voiFileDir.delete();
} else { // voiFileDir does not exist
// System.err.println( "saveImage " + voiDir);
- voiFileDir.mkdir();
+ voiFileDir.mkdirs();
}
voiDir = outputDirectory + File.separator + subDir + File.separator;
@@ -6914,7 +6910,7 @@ public static void saveBasisVectorsAsCSV( ModelImage image, String subDir, Strin
if (fileDir.exists() && fileDir.isDirectory()) {}
else if (fileDir.exists() && !fileDir.isDirectory()) { // voiFileDir.delete();
} else { // voiFileDir does not exist
- fileDir.mkdir();
+ fileDir.mkdirs();
}
File file = new File(fileDir + File.separator + imageName);
if (file.exists()) {
@@ -6956,7 +6952,7 @@ private void saveContours( ModelImage image, Box3f[] contours ) {
if (voiFileDir.exists() && voiFileDir.isDirectory()) { // do nothing
} else if (voiFileDir.exists() && !voiFileDir.isDirectory()) { // voiFileDir.delete();
} else { // voiFileDir does not exist
- voiFileDir.mkdir();
+ voiFileDir.mkdirs();
}
String imageName = JDialogBase.makeImageName(image.getImageFileName(), "");
imageName = imageName + "_contours";
@@ -7080,7 +7076,7 @@ public static void saveTriMesh( ModelImage image, String outputDirectory, String
} else if (voiFileDir.exists() && !voiFileDir.isDirectory()) { // voiFileDir.delete();
} else { // voiFileDir does not exist
// System.err.println( "saveImage " + voiDir);
- voiFileDir.mkdir();
+ voiFileDir.mkdirs();
}
voiDir = outputDirectory + File.separator + subDir + File.separator;
voiFileDir = new File(voiDir);
@@ -7088,7 +7084,7 @@ public static void saveTriMesh( ModelImage image, String outputDirectory, String
} else if (voiFileDir.exists() && !voiFileDir.isDirectory()) { // voiFileDir.delete();
} else { // voiFileDir does not exist
// System.err.println( "saveImage " + voiDir);
- voiFileDir.mkdir();
+ voiFileDir.mkdirs();
}
String imageName = JDialogBase.makeImageName(image.getImageFileName(), "");
@@ -7130,7 +7126,7 @@ private void saveSpline(String outputDirectory, VOI data, Vector3f transformedOr
} else if (voiFileDir.exists() && !voiFileDir.isDirectory()) { // voiFileDir.delete();
} else { // voiFileDir does not exist
// System.err.println( "saveSpline " + voiDir);
- voiFileDir.mkdir();
+ voiFileDir.mkdirs();
}
voiDir = outputDirectory + File.separator + "statistics" + File.separator;
voiFileDir = new File(voiDir);
@@ -7139,7 +7135,7 @@ private void saveSpline(String outputDirectory, VOI data, Vector3f transformedOr
// not
// exist
// System.err.println( "saveSpline " + voiDir);
- voiFileDir.mkdir();
+ voiFileDir.mkdirs();
}
File file = new File(voiDir + data.getName() + postFix + ".csv");
@@ -7312,7 +7308,7 @@ private void untwistLattice(final ModelImage image, final int[] resultExtents)
if (voiFileDir.exists() && voiFileDir.isDirectory()) {
} else if (voiFileDir.exists() && !voiFileDir.isDirectory()) {} else { // voiFileDir does not exist
// System.err.println( "untwistLattice" + voiDir);
- voiFileDir.mkdir();
+ voiFileDir.mkdirs();
}
File file = new File(voiDir + imageName + "_Frame_Straight.csv");
@@ -8427,6 +8423,9 @@ private void updateLattice(final boolean rebuild) {
}
if (right.getCurves().size() == 0) {
updateLatticeListeners();
+ // added updateSelected() to fix the movable of first 3D marker to reflects the
+ // mourseDrag of the marker in the plot
+ updateSelected();
return;
}
diff --git a/src/gov/nih/mipav/view/renderer/WildMagic/WormUntwisting/WormData.java b/src/gov/nih/mipav/view/renderer/WildMagic/WormUntwisting/WormData.java
index 7e730d6315..85dc3f9919 100644
--- a/src/gov/nih/mipav/view/renderer/WildMagic/WormUntwisting/WormData.java
+++ b/src/gov/nih/mipav/view/renderer/WildMagic/WormUntwisting/WormData.java
@@ -87,17 +87,15 @@ public WormData( ModelImage image )
checkParentDir(parentDir);
}
File dir = new File(outputDirectory);
- if ( !dir.exists() )
- {
- // System.err.println( "WormData " + outputDirectory);
- dir.mkdir();
- }
+
+ if (!dir.exists() && !dir.mkdirs()) { // dir does not exist
+ System.err.println("Failed to create directory in WormData: " + dir);
+ }
+
if ( outputImagesDirectory != null ) {
dir = new File(outputImagesDirectory);
- if ( !dir.exists() )
- {
- // System.err.println( "WormData " + outputImagesDirectory);
- dir.mkdir();
+ if ( !dir.exists() && !dir.mkdirs()){
+ System.err.println("Failed to create directory in WormData: " + dir);
}
}
}
diff --git a/src/lib/jfreechart-1.5.4.jar b/src/lib/jfreechart-1.5.4.jar
new file mode 100644
index 0000000000..ddd7c23d17
Binary files /dev/null and b/src/lib/jfreechart-1.5.4.jar differ
diff --git a/src/org/janelia/mipav/BatchProcessLogFrame.java b/src/org/janelia/mipav/BatchProcessLogFrame.java
index 5f6ac23e0c..c19b28abda 100644
--- a/src/org/janelia/mipav/BatchProcessLogFrame.java
+++ b/src/org/janelia/mipav/BatchProcessLogFrame.java
@@ -1,77 +1,53 @@
package org.janelia.mipav;
-import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
-import java.awt.LayoutManager;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.Dialog.ModalityType;
-import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
+import java.io.FileNotFoundException;
import java.io.FileWriter;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
-import javax.swing.JTextField;
public class BatchProcessLogFrame implements ActionListener {
- // add variables here
+ // variables
JFrame frame;
JButton buttonOk, buttonCopyAll, buttonBrowse;
- JPanel panelButton, checkPanel, radioPanel;
- JOptionPane panelButtonDialog, panelNoDupAnnDialog;
- JDialog dialogAfterButton, noDupAnnDialog;
- LayoutManager layout;
- StringBuffer choices;
- JRadioButton radioButtonA, radioButtonB;
- String newline = "\n";
- JTextField textField;
+ JDialog noDupAnnDialog;
JTextArea textArea;
JFileChooser fileChooser;
File file, directory;
+ // Constructor
public BatchProcessLogFrame() {
- // write code here
this.frame = new JFrame("Batch Process Log");
- this.layout = new FlowLayout();
createGUI();
}
private void createGUI() {
+ JOptionPane panelNoDupAnnDialog;
+
frame.setLayout(new GridBagLayout());
- // create buttonOK
- buttonOk = new JButton("Ok to Close");
- // add button to actionListener
+ // create buttons and add top actionListener
+ buttonOk = new JButton("Ok");
buttonOk.addActionListener(this);
- // add buttonCopyAll
- buttonCopyAll = new JButton("Copy All");
- //buttonCopyAll.setBounds(70, 270, 150, 50);
- //buttonCopyAll.setPreferredSize(new Dimension(200,500));
+ buttonCopyAll = new JButton("Copy");
buttonCopyAll.addActionListener(this);
- // add buttonBrowse
- buttonBrowse = new JButton("Browse to save");
- //buttonBrowse.setBounds(70, 270, 150, 50);
- //buttonBrowse.setPreferredSize(new Dimension(200,500));
+ buttonBrowse = new JButton("Save");
buttonBrowse.addActionListener(this);
- // create JPanel for the button
- panelButton = new JPanel();
- panelButton.add(buttonOk); // Add button to JPanel
- panelButton.add(buttonCopyAll);
- panelButton.add(buttonBrowse);
-
// a dialog pop out when there is no content in the textArea
panelNoDupAnnDialog = new JOptionPane("No duplicated annotations are found!");
noDupAnnDialog = panelNoDupAnnDialog.createDialog("Dialog");
@@ -99,29 +75,29 @@ private void createGUI() {
c.gridy = 1;
c.gridheight = 1;
c.gridwidth = 1;
- c.weightx = 1; // distribute space
+ c.weightx = 1;
c.weighty = 0;
- frame.add(buttonCopyAll, c); // add buttonCopyAll to the frame
+ frame.add(buttonCopyAll, c);
// Anchor the buttonBrowse to the right (EAST) of the frame
c.anchor = GridBagConstraints.EAST;
c.fill = GridBagConstraints.NONE;
c.gridx = 2;
c.gridy = 1;
- c.gridheight = 1; // see the height of the button the same as the height of checkbox1 + checkbox2
+ c.gridheight = 1;
c.weightx = 1;
- frame.add(buttonBrowse, c); // add button to the frame
+ frame.add(buttonBrowse, c);
// Anchor the "OK" button to the CENTER of the frame
c.anchor = GridBagConstraints.CENTER;
c.fill = GridBagConstraints.NONE;
c.gridx = 1;
c.gridy = 2;
- c.gridheight = 2; // see the height of the button the same as the height of checkbox1 + checkbox2
+ c.gridheight = 2;
c.weightx = 1;
- frame.add(buttonOk, c); // add button to the frame
+ frame.add(buttonOk, c);
- // Display the window.
+ // Display the frame.
frame.setBounds(80, 80, 80, 80);
frame.pack();
frame.setVisible(true);
@@ -131,7 +107,7 @@ private void createGUI() {
@Override
public void actionPerformed(ActionEvent e) {
- frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ String newline = "\n";
String data = textArea.getText().trim(); // read contents of text area into 'data'
if (!data.equals("")) {
@@ -144,9 +120,6 @@ public void actionPerformed(ActionEvent e) {
clpbrd.setContents(stringSelection, null);
JOptionPane.showMessageDialog(null, "Texts are copied to clipboard!");
} else if (e.getSource() == buttonBrowse) {
- // fileChooser = new JFileChooser("C:\\Users\\chend\\Desktop");
- // fileChooser = new JFileChooser(latticeStraighten.outputDirectory);
-
fileChooser.setSelectedFile(new File("Duplicated_Annotations.txt"));
int returnVal = fileChooser.showSaveDialog(frame);
@@ -155,12 +128,17 @@ public void actionPerformed(ActionEvent e) {
// save to file
try (FileWriter fw = new FileWriter(fileChooser.getSelectedFile())) {
fw.write(textArea.getText());
+ textArea.append("\n\n <<" + file.getName() + ">> is saved to: "
+ + fileChooser.getSelectedFile().getAbsolutePath() + newline);
+ } catch (FileNotFoundException ex) {
+ JOptionPane panelSaveFailedDialog = new JOptionPane("File save failed! " + "\n" + ex);
+ JDialog saveFailedDialog = panelSaveFailedDialog.createDialog("Dialog");
+ saveFailedDialog.setModalityType(ModalityType.APPLICATION_MODAL);
+ saveFailedDialog.setVisible(true);
+
} catch (Exception ex) {
ex.printStackTrace();
}
-
- textArea.append("\n\n <<" + file.getName() + ">> is saved to: "
- + fileChooser.getSelectedFile().getAbsolutePath() + newline);
}
}
} else {
diff --git a/src/org/janelia/mipav/plugins/worm/untwisting/AccurateModeListener.java b/src/org/janelia/mipav/plugins/worm/untwisting/AccurateModeListener.java
new file mode 100644
index 0000000000..61dba10b75
--- /dev/null
+++ b/src/org/janelia/mipav/plugins/worm/untwisting/AccurateModeListener.java
@@ -0,0 +1,20 @@
+package org.janelia.mipav.plugins.worm.untwisting;
+
+/**
+ * The listener interface for receiving changes to accurateMode.
+ * The class that is interested in processing an action event
+ * implements this interface, and the object created with that
+ * class is registered with a component, using the component's
+ * {@code addAccurateModeListener} method. When the action event
+ * occurs, that object's {@code accurateModeChanged} method is
+ * invoked.
+ *
+ * @author diyi chen
+ */
+public interface AccurateModeListener {
+ /**
+ * Add this method for responding to the accurateModeListener
+ * @param isAccurateMode true if the state of the mode is accurate
+ */
+ void accurateModeChanged(boolean isAccurateMode);
+}
\ No newline at end of file
diff --git a/src/org/janelia/mipav/plugins/worm/untwisting/PlotDataUpdateListener.java b/src/org/janelia/mipav/plugins/worm/untwisting/PlotDataUpdateListener.java
new file mode 100644
index 0000000000..30e7ae3475
--- /dev/null
+++ b/src/org/janelia/mipav/plugins/worm/untwisting/PlotDataUpdateListener.java
@@ -0,0 +1,30 @@
+package org.janelia.mipav.plugins.worm.untwisting;
+
+import java.util.List;
+
+import WildMagic.LibFoundation.Mathematics.Vector3f;
+
+/**
+ * Interface for handling updates to a plot panel. Classes that need to respond
+ * to plot data changes should implement this interface. An instance of a class
+ * implementing this interface can be registered with components that generate
+ * plot data updates. When plot data changes occur, the {@code updatePlotPanel}
+ * method of each registered listener is called, allowing the implementing class
+ * to update the plot display accordingly.
+ *
+ * @author diyi chen
+ */
+public interface PlotDataUpdateListener {
+
+ /**
+ * Invoked to update the plot panel with new data.
+ * @param points
+ *
+ * @param values The list of data values to plot. Each value represents a data
+ * point on the plot.
+ * @param title The title of the plot, describing the data or context of what
+ * is being displayed
+ */
+ void updatePlotPanel(List points, List values, String title);
+
+}
diff --git a/src/org/janelia/mipav/plugins/worm/untwisting/PlugInAlgorithmWormUntwistingJanelia.java b/src/org/janelia/mipav/plugins/worm/untwisting/PlugInAlgorithmWormUntwistingJanelia.java
index 3e41fe34f0..eb2f05eb54 100644
--- a/src/org/janelia/mipav/plugins/worm/untwisting/PlugInAlgorithmWormUntwistingJanelia.java
+++ b/src/org/janelia/mipav/plugins/worm/untwisting/PlugInAlgorithmWormUntwistingJanelia.java
@@ -494,17 +494,20 @@ public static void batchFlipLattices( JProgressBar batchProgress, final Vector includeRange,
final String[] baseFileDir, final String baseFileName, final String outputDir, final int paddingFactor, final boolean segmentLattice)
{
diff --git a/src/org/janelia/mipav/plugins/worm/untwisting/PlugInDialogVolumeRenderDualJanelia.java b/src/org/janelia/mipav/plugins/worm/untwisting/PlugInDialogVolumeRenderDualJanelia.java
index c7e96f2ad1..b2d5185864 100644
--- a/src/org/janelia/mipav/plugins/worm/untwisting/PlugInDialogVolumeRenderDualJanelia.java
+++ b/src/org/janelia/mipav/plugins/worm/untwisting/PlugInDialogVolumeRenderDualJanelia.java
@@ -1,6 +1,5 @@
package org.janelia.mipav.plugins.worm.untwisting;
-
//MIPAV is freely available from http://mipav.cit.nih.gov
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
@@ -68,20 +67,29 @@
import static org.jocl.CL.CL_DEVICE_TYPE_GPU;
+import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
+import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
+import java.awt.Point;
+import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseMotionAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.BufferedReader;
@@ -92,6 +100,8 @@
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
import java.util.List;
import java.util.Vector;
import java.util.stream.Collectors;
@@ -111,8 +121,12 @@
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
+import javax.swing.JToggleButton;
+import javax.swing.SwingUtilities;
+import javax.swing.border.TitledBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
+import javax.swing.ImageIcon;
import org.jocl.Sizeof;
@@ -128,14 +142,15 @@
import WildMagic.LibGraphics.SceneGraph.TriMesh;
/**
-* Implements the user-interface for the semi-automatic straightening of the
-* worm. Provides batch-process algorithms for segmenting the seam cells and
-* building lattices. Provides the framework for enabling the user to step
-* through the selected image volumes and view/edit results from the automatic
-* processes. Provides framework for animating the annotations after untwisting.
-*/
-public class PlugInDialogVolumeRenderDualJanelia extends JFrame implements ActionListener, RendererListener,
- PropertyChangeListener, ViewImageUpdateInterface, WindowListener, ChangeListener {
+ * Implements the user-interface for the semi-automatic straightening of the
+ * worm. Provides batch-process algorithms for segmenting the seam cells and
+ * building lattices. Provides the framework for enabling the user to step
+ * through the selected image volumes and view/edit results from the automatic
+ * processes. Provides framework for animating the annotations after untwisting.
+ */
+public class PlugInDialogVolumeRenderDualJanelia extends JFrame
+ implements ActionListener, RendererListener, PropertyChangeListener, ViewImageUpdateInterface, WindowListener,
+ ChangeListener, AccurateModeListener, PlotDataUpdateListener {
private static final long serialVersionUID = -9056581285643263551L;
@@ -215,6 +230,9 @@ public class PlugInDialogVolumeRenderDualJanelia extends JFrame implements Actio
private JPanel opacityPanel;
private JTabbedPane opacityTab;
private JPanel clipPanel;
+ private JPanel accuratePanel;
+ private JToggleButton accurateModeButton;
+ private JButton nextPeakButton;
private PlugInDialogVolumeRenderDualJanelia parent;
private JTextField rangeFusionText;
@@ -251,6 +269,9 @@ public class PlugInDialogVolumeRenderDualJanelia extends JFrame implements Actio
private Vector annotationNames;
private JSplitPane latticePanel = null;
private JPanel latticePanelSingle = null;
+
+ private SelectionChartPanel chartPanel;
+
private class IntegratedWormData {
private VOIVector annotations;
@@ -307,15 +328,15 @@ public PlugInDialogVolumeRenderDualJanelia() {
public void actionPerformed(ActionEvent event) {
String command = event.getActionCommand();
Object source = event.getSource();
-
- if ( command.equals("BrowseConclude") ) {
+
+ if (command.equals("BrowseConclude")) {
UntwistDialog inputs = new UntwistDialog(baseFileLocText.getText());
- if ( inputs.latticeOutputDir != null ) {
+ if (inputs.latticeOutputDir != null) {
latticeFileDir = new String(inputs.latticeOutputDir.getText());
setDefaultInputList(latticeFileDir);
}
}
-
+
if (currentSize == null) {
currentSize = new Dimension(getSize());
System.err.println(currentSize);
@@ -330,8 +351,7 @@ public void actionPerformed(ActionEvent event) {
this.setVisible(false);
annotationAnimationFromSpreadSheet();
return;
- }
- else {
+ } else {
// this.setVisible(false);
// testForceGraph();
MipavUtil.displayError("Please specify a range of images.");
@@ -342,8 +362,8 @@ public void actionPerformed(ActionEvent event) {
if (batchFlipLattice.isSelected()) {
try {
// Batch Automatic Lattice-Building
- PlugInAlgorithmWormUntwistingJanelia.batchFlipLattices(batchProgress, includeRange, latticeFileDir,
- baseFileNameText.getText());
+ PlugInAlgorithmWormUntwistingJanelia.batchFlipLattices(batchProgress, includeRange,
+ latticeFileDir, baseFileNameText.getText());
} catch (java.lang.OutOfMemoryError e) {
MipavUtil
.displayError("Error: Not enough memory. Unable to finish automatic lattice-building.");
@@ -378,8 +398,7 @@ public void actionPerformed(ActionEvent event) {
try {
if (resliceImageCheck.isSelected()) {
PlugInAlgorithmWormUntwistingJanelia.reslice(batchProgress, includeRange, baseFileDir,
- baseFileNameText.getText(), resliceXValue, resliceYValue,
- resliceZValue);
+ baseFileNameText.getText(), resliceXValue, resliceYValue, resliceZValue);
}
} catch (java.lang.OutOfMemoryError e) {
MipavUtil.displayError("Error: Not enough memory. Unable to finish reslice calculation.");
@@ -408,7 +427,8 @@ public void actionPerformed(ActionEvent event) {
validate();
leftRenderer.setVisible(true);
- if ( rightRenderer != null ) rightRenderer.setVisible(true);
+ if (rightRenderer != null)
+ rightRenderer.setVisible(true);
} else {
editMode = EditNONE;
startButton.setEnabled(true);
@@ -422,12 +442,13 @@ public void actionPerformed(ActionEvent event) {
editCrossSections.setVisible(true);
predict.setVisible(true);
previewUntwisting.setVisible(true);
- displayControls.setVisible(false);
+ displayControls.setVisible(false);
imageChannels.setVisible(true);
validate();
leftRenderer.setVisible(true);
- if ( rightRenderer != null ) rightRenderer.setVisible(true);
+ if (rightRenderer != null)
+ rightRenderer.setVisible(true);
} else {
editMode = EditNONE;
startButton.setEnabled(true);
@@ -445,7 +466,8 @@ public void actionPerformed(ActionEvent event) {
validate();
leftRenderer.setVisible(true);
- if ( rightRenderer != null ) rightRenderer.setVisible(true);
+ if (rightRenderer != null)
+ rightRenderer.setVisible(true);
} else {
editMode = EditNONE;
startButton.setEnabled(true);
@@ -548,12 +570,12 @@ public void actionPerformed(ActionEvent event) {
// Closes the editing:
else if (command.equals("done")) {
if (!displayControls.isVisible()) {
- displayControls.setVisible(true);
+ displayControls.setVisible(true);
imageChannels.setVisible(false);
validate();
}
- //mkitti 2023_03_01: this is where we save when "done"
+ // mkitti 2023_03_01: this is where we save when "done"
saveAll();
if (parent != null) {
parent.enableNext(editMode);
@@ -562,10 +584,9 @@ else if (command.equals("done")) {
} else {
enableNext(editMode);
}
- }
- else if (command.equals("demo")) {
+ } else if (command.equals("demo")) {
updateSurfacePanels();
- activeRenderer.addAnimationLattice( activeImage.voiManager.getLattice() );
+ activeRenderer.addAnimationLattice(activeImage.voiManager.getLattice());
}
// Enables user to generate a new lattice (when none of the automatic ones match
// well)
@@ -641,16 +662,15 @@ else if (command.equals("newLattice")) {
// activeImage.opacity[i] = activeImage.volOpacityPanel[i].getCompA().getOpacityTransferFunction();
//// activeImage.hyperstack[i].UpdateImages(activeImage.opacity[i], 0, null);
// }
-
+
if (previewUntwisting.getText().equals("preview")) {
previewUntwisting.setText("return");
-
+
previewCount++;
-
+
// save relative contours here upon returning from preview
activeImage.voiManager.saveCrossSections();
-
// save image orientation:
activeImage.volumeMatrix = new Matrix3f(activeRenderer.GetSceneRotation());
@@ -661,28 +681,25 @@ else if (command.equals("newLattice")) {
activeImage.annotationsTwisted = null;
}
activeImage.latticeTwisted = new VOIVector(activeImage.voiManager.getLattice());
-
-
if (activeImage.previewHS != null) {
- for ( int i = 0; i < activeImage.previewHS.length; i++ ) {
+ for (int i = 0; i < activeImage.previewHS.length; i++) {
activeImage.previewHS[i].GetImage().disposeLocal(false);
}
}
activeImage.previewHS = untwistingTest();
- for ( int i = 0; i < activeImage.previewHS.length; i++ ) {
- activeImage.previewHS[i].UpdateImages( activeImage.hyperstack[i].GetLUT());
+ for (int i = 0; i < activeImage.previewHS.length; i++) {
+ activeImage.previewHS[i].UpdateImages(activeImage.hyperstack[i].GetLUT());
}
activeImage.voiManager.removeListeners();
activeImage.voiManager.setImage(activeImage.previewHS[0].GetImage(), null);
activeImage.volumeImage = activeImage.previewHS[0];
activeRenderer.setHyperStack(activeImage.previewHS, activeImage.colormap);
- }
- else {
+ } else {
// "return"
previewCount--;
previewUntwisting.setText("preview");
-
+
// save relative contours here upon returning from preview
activeImage.voiManager.saveCrossSections();
@@ -690,8 +707,6 @@ else if (command.equals("newLattice")) {
activeImage.voiManager.setImage(activeImage.hyperstack[0].GetImage(), null);
activeImage.volumeImage = activeImage.hyperstack[0];
-
-
// restore twisted annotations and lattice:
activeImage.wormImage.unregisterAllVOIs();
VOIVector newLatticeTwisted = activeImage.voiManager.retwistLattice(activeImage.latticeTwisted);
@@ -741,18 +756,15 @@ else if (command.equals("newLattice")) {
}
}
}
-
-
-
+
if (activeImage.previewHS != null) {
- for ( int i = 0; i < activeImage.previewHS.length; i++ ) {
+ for (int i = 0; i < activeImage.previewHS.length; i++) {
activeImage.previewHS[i].GetImage().disposeLocal(false);
}
activeImage.previewHS = null;
}
activeRenderer.setHyperStack(activeImage.hyperstack, activeImage.colormap);
-
-
+
// activeImage.voiManager.setImage(activeImage.wormImage, null);
// activeImage.volumeImage.UpdateData(activeImage.wormImage, activeImage.volumeImage.GetLUT(), true);
// activeRenderer.resetAxis();
@@ -819,44 +831,44 @@ else if (command.equals("newLattice")) {
if (activeImage.voiManager != null) {
activeImage.voiManager.setPaddingFactor(paddingFactor);
}
- }
-
- if ( source instanceof JCheckBox ) {
- boolean selected = ((JCheckBox)source).isSelected();
- int which = imageChannel(command);
+ }
+
+ if (source instanceof JCheckBox) {
+ boolean selected = ((JCheckBox) source).isSelected();
+ int which = imageChannel(command);
// System.err.println(which + " " + selected );
- if ( which != -1 ) {
- activeRenderer.setImageOn(which, selected);
+ if (which != -1) {
+ activeRenderer.setImageOn(which, selected);
}
- if(opacityTab != null && opacityTab.getTabCount() > 0) {
+ if (opacityTab != null && opacityTab.getTabCount() > 0) {
which = opacityTab.getSelectedIndex();
- for(int i = 0; i < opacityTab.getTabCount(); ++i) {
- if( opacityTab.getTitleAt(i).startsWith(command) ) {
+ for (int i = 0; i < opacityTab.getTabCount(); ++i) {
+ if (opacityTab.getTitleAt(i).startsWith(command)) {
opacityTab.setEnabledAt(i, selected);
- if( !selected && i == which) {
+ if (!selected && i == which) {
opacityTab.setSelectedIndex((which + 1) % opacityTab.getTabCount());
}
- if( selected ) {
+ if (selected) {
opacityTab.setSelectedIndex(i);
}
}
}
}
- if(lutTab != null && lutTab.getTabCount() > 0) {
+ if (lutTab != null && lutTab.getTabCount() > 0) {
which = lutTab.getSelectedIndex();
- for(int i = 0; i < lutTab.getTabCount(); ++i) {
- if( lutTab.getTitleAt(i).startsWith(command) ) {
+ for (int i = 0; i < lutTab.getTabCount(); ++i) {
+ if (lutTab.getTitleAt(i).startsWith(command)) {
lutTab.setEnabledAt(i, selected);
- if( !selected && i == which) {
+ if (!selected && i == which) {
lutTab.setSelectedIndex((which + 1) % lutTab.getTabCount());
}
- if ( selected ) {
+ if (selected) {
lutTab.setSelectedIndex(i);
}
}
}
}
-
+
}
}
@@ -878,7 +890,6 @@ private void checkAnnotations() {
}
}
-
private String resultsDir(String sharedDir, ModelImage image) {
String imageName = image.getImageFileName();
if (imageName.contains("_clone")) {
@@ -887,13 +898,13 @@ private String resultsDir(String sharedDir, ModelImage image) {
if (imageName.contains("_straight")) {
imageName = imageName.replaceAll("_straight", "");
}
- String outputDir = sharedDir + File.separator + JDialogBase.makeImageName(imageName, "") +
- File.separator + JDialogBase.makeImageName(imageName, "_results") + File.separator;
+ String outputDir = sharedDir + File.separator + JDialogBase.makeImageName(imageName, "") + File.separator
+ + JDialogBase.makeImageName(imageName, "_results") + File.separator;
return outputDir;
}
-
+
public void rendererConfigured(VolumeTriPlanarRenderBase renderer) {
-
+
if ((annotationList != null) && (annotationNames != null) && (triVolume != null)) {
triVolume.addVOIS(annotationList, annotationNames);
triVolume.displayAnnotationSpheres();
@@ -914,6 +925,7 @@ public void rendererConfigured(VolumeTriPlanarRenderBase renderer) {
leftDisplayPanel.setBorder(JDialogBase.buildTitledBorder(leftImage.wormImage.getImageName()));
rightDisplayPanel.setBorder(JDialogBase.buildTitledBorder(rightImage.wormImage.getImageName(), Color.red));
}
+ activeRenderer.addPlotListener(this);
if (activeImage.voiManager == null) {
activeImage.voiManager = new VOILatticeManagerInterface(null, activeRenderer.getVolumeImage().GetImage(),
@@ -921,29 +933,26 @@ public void rendererConfigured(VolumeTriPlanarRenderBase renderer) {
}
activeRenderer.setVOILatticeManager(activeImage.voiManager);
- if ( activeImage.previewHS != null ) {
+ if (activeImage.previewHS != null) {
activeImage.voiManager.setPreviewMode(true, activeImage.voiManager.getLatticeStraight(),
activeImage.voiManager.getAnnotationsStraight());
activeRenderer.resetAxisXInv();
- }
- else if ( activeImage.latticeTwisted != null ) {
- activeImage.voiManager.setPreviewMode(false, activeImage.latticeTwisted,
- activeImage.annotationsTwisted);
+ } else if (activeImage.latticeTwisted != null) {
+ activeImage.voiManager.setPreviewMode(false, activeImage.latticeTwisted, activeImage.annotationsTwisted);
activeRenderer.SetSceneRotation(activeImage.volumeMatrix);
- }
- else {
- if (editMode == ReviewResults) {
- activeImage.voiManager.setLattice(WormData.readStraightLattice( resultsDir(latticeFileDir, activeImage.wormImage)));
- }
- else {
+ } else {
+ if (editMode == ReviewResults) {
+ activeImage.voiManager
+ .setLattice(WormData.readStraightLattice(resultsDir(latticeFileDir, activeImage.wormImage)));
+ } else {
if (loadLegacyLatticeCheck.isSelected()) {
activeImage.wormImage.setResolutions(originalResolutions);
}
final String dir = resultsDir(latticeFileDir, activeImage.wormImage);
- activeImage.voiManager
- .setLattice(WormData.readFinalLattice(dir,
- loadLegacyLatticeCheck.isSelected(), activeImage.wormImage), dir);
+ activeImage.voiManager.setLattice(
+ WormData.readFinalLattice(dir, loadLegacyLatticeCheck.isSelected(), activeImage.wormImage),
+ dir);
if (loadLegacyLatticeCheck.isSelected()) {
activeImage.wormImage.setResolutions(new float[] { 1f, 1f, 1 });
@@ -957,17 +966,19 @@ else if ( activeImage.latticeTwisted != null ) {
activeImage.annotations = null;
}
VOI annotations = activeImage.voiManager.getAnnotations();
- // System.err.println( activeImage.wormImage.getImageName() + " " + annotations);
+ // System.err.println( activeImage.wormImage.getImageName() + " " +
+ // annotations);
if (annotations != null) {
for (int i = 0; i < annotations.getCurves().size(); i++) {
final VOIText text = (VOIText) annotations.getCurves().elementAt(i);
- // System.err.println( " " + i + " " + text.getText() + " " + text.elementAt(0));
+ // System.err.println( " " + i + " " + text.getText() + " " +
+ // text.elementAt(0));
text.createVolumeVOI(activeImage.volumeImage, activeRenderer.getTranslate());
}
}
}
-
+
activeRenderer.displayVOIs(true);
activeImage.voiManager.editAnnotations(editMode == EditSeamCells);
activeImage.voiManager.colorAnnotations(editMode == EditSeamCells);
@@ -979,7 +990,7 @@ else if ( activeImage.latticeTwisted != null ) {
activeImage.annotationPanelUI.setPreviewMode(activeImage.previewHS != null);
activeImage.latticeTable.setPreviewMode(activeImage.previewHS != null);
-
+
activeImage.voiManager.editAnnotations(false);
// initDisplaySeamPanel();
} else if (editMode == EditLattice) {
@@ -998,16 +1009,16 @@ else if ( activeImage.latticeTwisted != null ) {
renderer.resetAxisXInv();
}
-
initImageChannels(activeImage);
updateHistoLUTPanels(activeImage);
updateClipPanel(activeImage, activeRenderer, true);
updateSurfacePanels();
+ updateSelectionPanel();
if (activeImage.currentTab != -1) {
tabbedPane.setSelectedIndex(activeImage.currentTab);
}
-
+
int nextStep = dualGPU == null ? 1 : 2;
imageIndex = Math.min(includeRange.size() - 1, imageIndex);
imageIndex = Math.max(0, imageIndex);
@@ -1021,7 +1032,6 @@ else if ( activeImage.latticeTwisted != null ) {
backButton.setEnabled(false);
nextButton.setEnabled(false);
}
-
setExtendedState(JFrame.MAXIMIZED_BOTH);
if (dualGPU != null) {
@@ -1042,7 +1052,7 @@ else if ( activeImage.latticeTwisted != null ) {
public void setActiveRenderer(VolumeTriPlanarRenderBase renderer) {
// System.err.println("setActiveRenderer");
- VolumeTriPlanarRenderBase previousActive = activeRenderer;
+ VolumeTriPlanarRender previousActive = activeRenderer;
if (leftRenderer == renderer) {
activeRenderer = leftRenderer;
leftDisplayPanel.setBorder(JDialogBase.buildTitledBorder(leftImage.wormImage.getImageName(), Color.red));
@@ -1056,7 +1066,8 @@ public void setActiveRenderer(VolumeTriPlanarRenderBase renderer) {
activeImage = rightImage;
}
-
+ activeRenderer.addPlotListener(this);
+
if (previousActive != activeRenderer) {
if (activeImage.voiManager.isPreview()) {
@@ -1070,6 +1081,7 @@ public void setActiveRenderer(VolumeTriPlanarRenderBase renderer) {
updateSurfacePanels();
updateClipPanel(activeImage, activeRenderer, true);
updateHistoLUTPanels(activeImage);
+ updateSelectionPanel();
if (editMode == EditLattice) {
leftImage.voiManager.editLattice();
@@ -1079,6 +1091,8 @@ public void setActiveRenderer(VolumeTriPlanarRenderBase renderer) {
tabbedPane.setSelectedIndex(activeImage.currentTab);
stateChanged(null);
}
+ previousActive.removePlotListener(this);
+
}
int nextStep = dualGPU == null ? 1 : 2;
if (includeRange != null) {
@@ -1107,7 +1121,7 @@ public void dispose() {
* lattice, or annotations. The next step in the straightening process is
* automatically enabled and selected.
*
- * @param mode
+ * @param mode TODO
*/
public void enableNext(int mode) {
closeAll();
@@ -1132,9 +1146,11 @@ public void enableNext(int mode) {
lutPanel.removeAll();
opacityPanel.removeAll();
clipPanel.removeAll();
+ accuratePanel.removeAll();
tabbedPane.addTab("LUT", null, lutPanel);
tabbedPane.addTab("Opacity", null, opacityPanel);
tabbedPane.addTab("Clip", null, clipPanel);
+ tabbedPane.addTab("AccurateMode", null, accuratePanel);
tabbedPane.addChangeListener(this);
startButton.setEnabled(true);
@@ -1195,11 +1211,11 @@ private void closeAll() {
if (imageStack[i].voiManager != null) {
imageStack[i].voiManager = null;
}
- if ( imageStack[i].hyperstack != null ) {
- for ( int j = 0; j < imageStack[i].hyperstack.length; j++ ) {
- if ( imageStack[i].hyperstack[j] != null ) {
+ if (imageStack[i].hyperstack != null) {
+ for (int j = 0; j < imageStack[i].hyperstack.length; j++) {
+ if (imageStack[i].hyperstack[j] != null) {
imageStack[i].hyperstack[j].dispose();
- imageStack[i].hyperstack[j] = null;
+ imageStack[i].hyperstack[j] = null;
}
}
}
@@ -1228,8 +1244,9 @@ public void propertyChange(PropertyChangeEvent event) {
if (propertyName.equals("Opacity")) {
int which = opacityTab.getSelectedIndex();
// System.err.println("propertyChange " + which);
- if ( which != -1 ) {
- final TransferFunction kTransfer = activeImage.volOpacityPanel[which].getCompA().getOpacityTransferFunction();
+ if (which != -1) {
+ final TransferFunction kTransfer = activeImage.volOpacityPanel[which].getCompA()
+ .getOpacityTransferFunction();
updateImages(activeImage.colormap, activeImage.hyperstack[which].GetImage(), kTransfer, which);
activeImage.hyperstack[which].UpdateImages(kTransfer, 0, null);
//
@@ -1258,8 +1275,8 @@ public boolean updateImages() {
// System.err.println("updateImages" );
if (activeImage.hyperstack != null && lutTab != null) {
int which = lutTab.getSelectedIndex();
- if ( which != -1 ) {
- updateImages(activeImage.colormap, activeImage.hyperstack[which].GetLUT(), which );
+ if (which != -1) {
+ updateImages(activeImage.colormap, activeImage.hyperstack[which].GetLUT(), which);
// System.err.println("updateImages " + which);
activeImage.hyperstack[which].UpdateImages(activeImage.hyperstack[which].getLUT());
// if ( activeImage.previewHS != null ) {
@@ -1272,14 +1289,14 @@ public boolean updateImages() {
}
return false;
}
-
- private void updateImages(Texture texture, ModelLUT lut, int index ) {
+
+ private void updateImages(Texture texture, ModelLUT lut, int index) {
byte[] data = texture.GetImage().GetData();
ModelLUT.exportIndexedLUTMin(lut, data, index);
texture.Reload(true);
}
- private void updateImages(Texture texture, ModelImage image, TransferFunction tf, int index ) {
+ private void updateImages(Texture texture, ModelImage image, TransferFunction tf, int index) {
final int lutHeight = texture.GetImage().GetBound(0);
final byte[] data = texture.GetImage().GetData();
int offset = index * lutHeight * 4;
@@ -1295,6 +1312,7 @@ private void updateImages(Texture texture, ModelImage image, TransferFunction tf
}
texture.Reload(true);
}
+
/*
* (non-Javadoc)
*
@@ -1319,6 +1337,21 @@ public boolean updateImages(ModelLUT LUTa, ModelLUT LUTb, boolean flag, int inte
return false;
}
+ /**
+ * Responds to changes in accurate mode by updating the button's appearance and
+ * text to reflect the current mode state. This method is typically called by a
+ * listener that is notified when accurate mode settings are toggled elsewhere
+ * in the application.
+ *
+ * @param isAccurateMode A boolean indicating whether accurate mode is enabled
+ * (true) or disabled (false).
+ */
+ @Override
+ public void accurateModeChanged(boolean isAccurateMode) {
+ accurateModeButton.setSelected(isAccurateMode);
+ accurateModeButton.setText(isAccurateMode ? "Accurate Mode is now On" : "Accurate Mode is now Off");
+ }
+
@Override
public void windowActivated(WindowEvent e) {
}
@@ -1419,7 +1452,7 @@ public boolean trackMIPAV_Python() throws Exception {
// rightImage.wormData.getAnnotationsPath() );
ProcessBuilder processBuilder = new ProcessBuilder("python", baseFileDir + File.separator + "track_MIPAV.py",
- WormData.getStraightAnnotationsPath(resultsDir(latticeFileDir, leftImage.wormImage)),
+ WormData.getStraightAnnotationsPath(resultsDir(latticeFileDir, leftImage.wormImage)),
WormData.getStraightAnnotationsPath(resultsDir(latticeFileDir, rightImage.wormImage)),
WormData.getIntegratedMarkerAnnotationsPath(resultsDir(latticeFileDir, leftImage.wormImage)),
WormData.getIntegratedMarkerAnnotationsPath(resultsDir(latticeFileDir, rightImage.wormImage)));
@@ -1447,10 +1480,10 @@ public boolean restraightenMIPAV_Python(IntegratedWormData data) throws Exceptio
// leftImage.wormData.getAnnotationsPath() + " " +
// rightImage.wormData.getAnnotationsPath() );
- String predictedTwisted = resultsDir(latticeFileDir, data.wormImage) + File.separator + "prediction" + File.separator
- + "predicted_annotations.csv";
- String predictedStraight = resultsDir(latticeFileDir, data.wormImage) + File.separator + "prediction" + File.separator
- + "predicted_straightened_annotations.csv";
+ String predictedTwisted = resultsDir(latticeFileDir, data.wormImage) + File.separator + "prediction"
+ + File.separator + "predicted_annotations.csv";
+ String predictedStraight = resultsDir(latticeFileDir, data.wormImage) + File.separator + "prediction"
+ + File.separator + "predicted_straightened_annotations.csv";
File file = new File(predictedTwisted);
if (!file.exists())
@@ -1461,7 +1494,7 @@ public boolean restraightenMIPAV_Python(IntegratedWormData data) throws Exceptio
ProcessBuilder processBuilder = new ProcessBuilder("python",
baseFileDir[0] + File.separator + "restraighten_MIPAV.py", predictedStraight, predictedTwisted,
- WormData.getIntegratedMarkerAnnotationsPath( resultsDir(latticeFileDir, rightImage.wormImage)));
+ WormData.getIntegratedMarkerAnnotationsPath(resultsDir(latticeFileDir, rightImage.wormImage)));
processBuilder.redirectErrorStream(true);
Process process = processBuilder.start();
@@ -1479,8 +1512,8 @@ public boolean restraightenMIPAV_Python(IntegratedWormData data) throws Exceptio
private void runPython() {
// delete the predicted files for the right image:
- String fileName = resultsDir(latticeFileDir, rightImage.wormImage) + File.separator + "prediction" + File.separator
- + "predicted_straightened_annotations.csv";
+ String fileName = resultsDir(latticeFileDir, rightImage.wormImage) + File.separator + "prediction"
+ + File.separator + "predicted_straightened_annotations.csv";
File straightFile = new File(fileName);
if (straightFile.exists()) {
straightFile.delete();
@@ -1495,7 +1528,8 @@ private void runPython() {
// when user presses 'predict'
// prototype:
// 1. straighten the right image - left annotations remain fixed:
- ModelImage contourImage = rightImage.voiManager.untwistAnnotations(resultsDir(latticeFileDir, rightImage.wormImage), rightImage.contourImage);
+ ModelImage contourImage = rightImage.voiManager
+ .untwistAnnotations(resultsDir(latticeFileDir, rightImage.wormImage), rightImage.contourImage);
if (rightImage.contourImage != null && rightImage.contourImage != contourImage) {
rightImage.contourImage.disposeLocal(false);
rightImage.contourImage = null;
@@ -1547,7 +1581,7 @@ private VolumeImage[] untwistingTest() {
activeImage.voiManager.setPaddingFactor(paddingFactor);
ModelImage[] images = activeImage.voiManager.untwistTest(activeImage.hyperstack);
VolumeImage[] hyperstack = new VolumeImage[images.length];
- for ( int i = 0; i < images.length; i++ ) {
+ for (int i = 0; i < images.length; i++) {
images[i].unregisterAllVOIs();
hyperstack[i] = new VolumeImage(false, images[i], "" + i, null, 0, false);
}
@@ -1566,19 +1600,19 @@ private boolean checkGPUMemory(ModelImage[] images) {
OpenCLInfo.getMaxMemSize(CL_DEVICE_TYPE_GPU, maxMemSizeArray);
long maxAllocSize = maxMemSizeArray[0];
long totalMemSize = maxMemSizeArray[1];
-
+
long memoryUsed = 0;
- for ( int i = 0; i < images.length; i++ ) {
- if ( images[i] != null ) {
+ for (int i = 0; i < images.length; i++) {
+ if (images[i] != null) {
int dataSize = images[i].getDataSize();
- if ( dataSize > (maxAllocSize / (Sizeof.cl_float)) ) {
+ if (dataSize > (maxAllocSize / (Sizeof.cl_float))) {
return false;
}
memoryUsed += dataSize;
}
}
- if ( memoryUsed >= (totalMemSize / Sizeof.cl_float) ) {
+ if (memoryUsed >= (totalMemSize / Sizeof.cl_float)) {
return false;
}
return true;
@@ -1627,12 +1661,12 @@ private boolean openHyperStack() {
long memoryInUse = MipavUtil.getUsedHeapMemory();
for (int i = 0; i < includeRange.size(); i++) {
-
+
ModelImage[] images = new ModelImage[baseFileDir.length];
String fileName = baseFileName + "_" + includeRange.elementAt(i) + ".tif";
File[] imageFiles = new File[baseFileDir.length];
- for ( int j = 0; j < baseFileDir.length; j++ ) {
+ for (int j = 0; j < baseFileDir.length; j++) {
if (editMode == ReviewResults) {
fileName = baseFileName + "_" + includeRange.elementAt(i) + "_straight.tif";
String subDirName = baseFileName + "_" + includeRange.elementAt(i) + File.separator;
@@ -1640,16 +1674,15 @@ private boolean openHyperStack() {
+ File.separator;
imageFiles[j] = new File(baseFileDir[j] + File.separator + subDirName + subDirNameResults
+ PlugInAlgorithmWormUntwistingJanelia.outputImages + File.separator + fileName);
- }
- else {
+ } else {
imageFiles[j] = new File(baseFileDir[j] + File.separator + fileName);
}
if (imageFiles[j].exists()) {
images[j] = openImage(imageFiles[j], fileName);
- System.err.println("Opening... " + fileName + " " + images[j].isColorImage() );
+ System.err.println("Opening... " + fileName + " " + images[j].isColorImage());
images[j].calcMinMax();
- if ( images[j].isColorImage() ) {
+ if (images[j].isColorImage()) {
images[j] = convertToGray(images[j]);
}
}
@@ -1657,12 +1690,12 @@ private boolean openHyperStack() {
// Add memory check here:
if (i == 0) {
- if ( !checkGPUMemory(images) ) {
+ if (!checkGPUMemory(images)) {
MipavUtil.displayError("Image size too big to load on GPU.");
progressBar.setVisible(false);
progressBar.dispose();
progressBar = null;
- for ( int j = 0; j < images.length; j++ ) {
+ for (int j = 0; j < images.length; j++) {
if (images[j] != null) {
images[j].disposeLocal();
images[j] = null;
@@ -1683,7 +1716,7 @@ private boolean openHyperStack() {
progressBar.setVisible(false);
progressBar.dispose();
progressBar = null;
- for ( int j = 0; j < images.length; j++ ) {
+ for (int j = 0; j < images.length; j++) {
if (images[j] != null) {
images[j].disposeLocal();
images[j] = null;
@@ -1697,7 +1730,7 @@ private boolean openHyperStack() {
thresholdImage(images);
leftImage.wormImage = images[0];
-
+
imageStack[i] = leftImage;
System.err.println("... adding " + i + " " + leftImage.wormImage.getImageName());
@@ -1708,15 +1741,18 @@ private boolean openHyperStack() {
leftImage.annotations = null;
}
leftImage.hyperstack = new VolumeImage[images.length];
- for ( int j = 0; j < images.length; j++ ) {
+ for (int j = 0; j < images.length; j++) {
leftImage.hyperstack[j] = new VolumeImage(false, images[j], "" + j, null, 0, false);
}
- leftImage.volumeImage = leftImage.hyperstack[0]; //new VolumeImage(false, leftImage.wormImage, "A", null, 0, false);
+ leftImage.volumeImage = leftImage.hyperstack[0]; // new VolumeImage(false, leftImage.wormImage, "A",
+ // null, 0, false);
leftImage.voiManager = new VOILatticeManagerInterface(null, leftImage.volumeImage.GetImage(), null,
0, true, null);
-
+ leftImage.voiManager.addAccurateModeListener(this);
+
byte[] aucData = new byte[256 * 4 * images.length];
- GraphicsImage cmImage = new GraphicsImage(GraphicsImage.FormatMode.IT_RGBA8888, 256, images.length, aucData, new String("colormap" + leftImage.volumeImage.GetImage().getImageFileName()));
+ GraphicsImage cmImage = new GraphicsImage(GraphicsImage.FormatMode.IT_RGBA8888, 256, images.length,
+ aucData, new String("colormap" + leftImage.volumeImage.GetImage().getImageFileName()));
leftImage.colormap = new Texture();
leftImage.colormap.SetImage(cmImage);
@@ -1736,7 +1772,7 @@ private boolean openHyperStack() {
return false;
success = true;
- leftRenderer = new VolumeTriPlanarRender( leftImage.hyperstack, leftImage.colormap );
+ leftRenderer = new VolumeTriPlanarRender(leftImage.hyperstack, leftImage.colormap);
leftRenderer.setVisible(false);
leftRenderer.addConfiguredListener(this);
@@ -1836,10 +1872,10 @@ private boolean openHyperStack() {
return success;
}
- private void thresholdImage(ModelImage[] images ) {
+ private void thresholdImage(ModelImage[] images) {
if (thresholdImageCheck.isSelected()) {
- for ( int i = 0; i < images.length; i++ ) {
- if ( images[i] != null ) {
+ for (int i = 0; i < images.length; i++) {
+ if (images[i] != null) {
for (int j = 0; j < images[i].getDataSize(); j++) {
if (images[i].getFloat(j) > threshold) {
@@ -1852,40 +1888,45 @@ private void thresholdImage(ModelImage[] images ) {
}
}
- private ModelImage convertToGray(ModelImage image ) {
+ private ModelImage convertToGray(ModelImage image) {
ModelImage result = new ModelImage(ModelStorageBase.FLOAT, image.getExtents(),
JDialogBase.makeImageName(image.getImageFileName(), ""));
- final int dimX = image.getExtents().length > 0 ? image.getExtents()[0] : 1;
+ final int dimX = image.getExtents().length > 0 ? image.getExtents()[0] : 1;
final int dimY = image.getExtents().length > 1 ? image.getExtents()[1] : 1;
- final int dimZ = image.getExtents().length > 2 ? image.getExtents()[2] : 1;
-
+ final int dimZ = image.getExtents().length > 2 ? image.getExtents()[2] : 1;
+
float max = 0;
float maxSum = 0;
- for ( int z = 0; z < dimZ; z++ ) {
- for ( int y = 0; y < dimY; y++ ) {
- for ( int x = 0; x < dimX; x++ ) {
+ for (int z = 0; z < dimZ; z++) {
+ for (int y = 0; y < dimY; y++) {
+ for (int x = 0; x < dimX; x++) {
float r = image.getFloatC(x, y, z, 1);
float g = image.getFloatC(x, y, z, 2);
float b = image.getFloatC(x, y, z, 3);
- if ( r > max ) max = r;
- if ( g > max ) max = g;
- if ( b > max ) max = b;
+ if (r > max)
+ max = r;
+ if (g > max)
+ max = g;
+ if (b > max)
+ max = b;
float sum = r + b + g;
- if ( sum > maxSum ) maxSum = sum;
+ if (sum > maxSum)
+ maxSum = sum;
result.set(x, y, z, sum);
}
}
}
- if ( maxSum > max ) {
+ if (maxSum > max) {
float scale = maxSum / max;
- for ( int i = 0; i < result.getDataSize(); i++ ) {
- result.set(i, result.getFloat(i) / scale);;
+ for (int i = 0; i < result.getDataSize(); i++) {
+ result.set(i, result.getFloat(i) / scale);
+ ;
}
}
result.calcMinMax();
return result;
}
-
+
private ModelImage combineImages(ModelImage imageA, ModelImage imageB, ModelImage imageC) {
// imageA is never null and is always written into the 'green' channel...
@@ -1895,7 +1936,7 @@ private ModelImage combineImages(ModelImage imageA, ModelImage imageB, ModelImag
// Make algorithm
ModelImage blank = null;
- if ( imageB == null && imageC != null ) {
+ if (imageB == null && imageC != null) {
blank = new ModelImage(ModelImage.SHORT, imageA.getExtents(),
JDialogBase.makeImageName(imageA.getImageName(), ""));
@@ -1903,8 +1944,7 @@ private ModelImage combineImages(ModelImage imageA, ModelImage imageB, ModelImag
true, true);
mathAlgo.run();
blank.disposeLocal(false);
- }
- else if ( imageB != null && imageC == null ) {
+ } else if (imageB != null && imageC == null) {
blank = new ModelImage(ModelImage.SHORT, imageA.getExtents(),
JDialogBase.makeImageName(imageA.getImageName(), ""));
@@ -1912,8 +1952,7 @@ else if ( imageB != null && imageC == null ) {
true, true);
mathAlgo.run();
blank.disposeLocal(false);
- }
- else {
+ } else {
AlgorithmRGBConcat mathAlgo = new AlgorithmRGBConcat(imageB, imageA, imageC, displayImage, true, false, 255,
true, true);
mathAlgo.run();
@@ -1949,7 +1988,7 @@ private void annotationAnimationFromSpreadSheet() {
MipavUtil.centerOnScreen(progress);
String inputDirName = baseFileDir[0] + File.separator;
- System.err.println( inputDirName );
+ System.err.println(inputDirName);
final File inputFileDir = new File(inputDirName);
Vector3f min = new Vector3f(Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE);
@@ -2163,7 +2202,34 @@ private void annotationAnimationFromSpreadSheet() {
progress.dispose();
progress = null;
}
-
+
+ /**
+ * Updates the plot panel by invoking the chart creation and updating the
+ * display.
+ *
+ * @param points List of 3D points for the plot.
+ * @param values List of values corresponding to each 3D point.
+ * @param title Title for the updated plot.
+ */
+ public void updatePlotPanel(List points, List values, String title) {
+ SwingUtilities.invokeLater(() -> {
+ chartPanel.updateChart(values, title);
+ chartPanel.setChart3DPoints(points);
+
+ chartPanel.revalidate();
+ chartPanel.repaint();
+ });
+ }
+
+ /**
+ * Updates the 3D model visualization based on a new 3D point.
+ *
+ * @param point The 3D point that the model needs to reflect.
+ */
+ public void update3DModel(Vector3f point) {
+ activeImage.voiManager.modify3DMarker(point, point, point);
+ }
+
/**
* User-interface initialization. If the UI is integrated all panels are
* displayed in one window. Otherwise the UI is divided into volume display and
@@ -2255,20 +2321,70 @@ private void init() {
dialogGUI.getContentPane().add(panel1, BorderLayout.NORTH);
dialogGUI.getContentPane().add(panel2, BorderLayout.SOUTH);
- lutPanel = new JPanel(new GridLayout(2,1));
+ lutPanel = new JPanel(new GridLayout(2, 1));
lutTab = new JTabbedPane();
lutTab.addChangeListener(this);
lutPanel.add(lutTab, BorderLayout.CENTER);
- opacityPanel = new JPanel( new BorderLayout() );
+ opacityPanel = new JPanel(new BorderLayout());
opacityTab = new JTabbedPane();
opacityTab.addChangeListener(this);
opacityPanel.add(opacityTab, BorderLayout.CENTER);
+ clipPanel = new JPanel(new BorderLayout());
+
+ // Create a panel for toggling between accurate and 3-color modes(not working
+ // currently)
+ accuratePanel = new JPanel(new BorderLayout());
+ // Panel get larger horizontally if remove the two lines below
+ accuratePanel.setPreferredSize(new Dimension(400, 400));
+ accuratePanel.setMaximumSize(new Dimension(400, 400));
+ JPanel buttonPanel = new JPanel();
+
+ // Initialize a toggle button for switching modes
+ accurateModeButton = new JToggleButton("Accurate Mode");
+ accurateModeChanged(true);
+ accurateModeButton.setPreferredSize(new Dimension(200, 50));
+ accurateModeButton.setToolTipText("Press 'M' to toggle Accurate Mode");
+
+ // Add an action response to the button
+ accurateModeButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ JToggleButton toggleButton = (JToggleButton) e.getSource();
+ boolean isSelected = toggleButton.isSelected();
+ activeImage.voiManager.toggleAccurateMode();
+ }
+ });
+
+ // Add the toggle button to the button panel and then add the panel to the
+ // accurate mode panel
+ buttonPanel.add(accurateModeButton);
+ accuratePanel.add(buttonPanel, BorderLayout.NORTH);
+
+ chartPanel = new SelectionChartPanel(Arrays.asList(0.0f, 0.0f, 0.0f), "Selection Chart", this);
- clipPanel = new JPanel( new BorderLayout() );
+ // Created a fakePanel to split the panel
+ JPanel fakePanel = new JPanel();
+ fakePanel.setPreferredSize(new Dimension(100,500)); // plot gets larger vertically if remove this line
+ JSplitPane chartFakeSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT, chartPanel, fakePanel);
+ chartFakeSplit.setOneTouchExpandable(true);
+ chartFakeSplit.setContinuousLayout(true);
+ chartFakeSplit.setResizeWeight(0.7);
+ chartFakeSplit.setDividerLocation(0.5);
+
+ nextPeakButton = new JButton("Next Peak");
+ nextPeakButton.setPreferredSize(new Dimension(200, 50));
+ nextPeakButton.setToolTipText("Press 'N' move to Next Peak");
+ nextPeakButton.addActionListener(chartPanel);
+
+ fakePanel.add(nextPeakButton);
+
+ accuratePanel.add(chartFakeSplit, BorderLayout.CENTER);
+
tabbedPane = new JTabbedPane();
tabbedPane.addTab("LUT", null, lutPanel);
tabbedPane.addTab("Opacity", null, opacityPanel);
tabbedPane.addTab("Clip", null, clipPanel);
+ tabbedPane.addTab("Selection", null, accuratePanel);
tabbedPane.setVisible(false);
tabbedPane.addChangeListener(this);
@@ -2276,9 +2392,10 @@ private void init() {
displayControls.add(dialogGUI.getContentPane(), BorderLayout.NORTH);
JPanel leftPanel = new JPanel(new BorderLayout());
leftPanel.add(displayControls, BorderLayout.NORTH);
-
+
imageChannels = new JPanel();
- imageChannels.add(new JLabel("Select image channel:") );
+ imageChannels.add(new JLabel("Select image channel:"));
+ imageChannels.add(new JLabel("Select Mode:"));
imageChannels.setVisible(false);
leftPanel.add(imageChannels, BorderLayout.CENTER);
leftPanel.add(tabbedPane, BorderLayout.SOUTH);
@@ -2307,6 +2424,8 @@ private void init() {
segmentSeamCells.setSelected(true);
}
+
+
/**
* Sets up the GPU volume display panel, with the 'back' and 'next' buttons for
@@ -2343,7 +2462,7 @@ private Container initGPUPanel(int editMode) {
doneButton.setVisible(true);
doneButton.setEnabled(true);
backNextPanel.add(doneButton);
-
+
JButton demo = gui.buildButton("demo");
demo.addActionListener(this);
demo.setActionCommand("demo");
@@ -2352,7 +2471,7 @@ private Container initGPUPanel(int editMode) {
// backNextPanel.add(demo);
latticeSelectionPanel = new JPanel();
-
+
newLatticeButton = gui.buildButton("new lattice");
newLatticeButton.addActionListener(this);
newLatticeButton.setActionCommand("newLattice");
@@ -2373,13 +2492,13 @@ private Container initGPUPanel(int editMode) {
displayModel.setVisible(false);
displayModel.setEnabled(true);
latticeSelectionPanel.add(displayModel);
-
+
displaySurface = gui.buildCheckBox("Show Surface", false);
displaySurface.addActionListener(this);
displaySurface.setActionCommand("displaySurface");
displaySurface.setVisible(false);
displaySurface.setEnabled(true);
-
+
editCrossSections = gui.buildCheckBox("Edit Sections", false);
editCrossSections.addActionListener(this);
editCrossSections.setActionCommand("editCrossSections");
@@ -2849,10 +2968,11 @@ private void openNeuriteCurves(IntegratedWormData data) {
private void loadPredicted(IntegratedWormData data) {
// load and save the straightened predicted values:
- VOI markerAnnotations = LatticeModel.readAnnotationsCSV(resultsDir(latticeFileDir, data.wormImage) + File.separator
- + "prediction" + File.separator + "predicted_straightened_annotations.csv");
+ VOI markerAnnotations = LatticeModel.readAnnotationsCSV(resultsDir(latticeFileDir, data.wormImage)
+ + File.separator + "prediction" + File.separator + "predicted_straightened_annotations.csv");
if (markerAnnotations != null) {
- LatticeModel.saveAnnotationsAsCSV( resultsDir(latticeFileDir, data.wormImage) + File.separator + "straightened_annotations",
+ LatticeModel.saveAnnotationsAsCSV(
+ resultsDir(latticeFileDir, data.wormImage) + File.separator + "straightened_annotations",
"straightened_annotations.csv", markerAnnotations);
}
// load, save and display the predicted annotations:
@@ -2868,7 +2988,8 @@ private void loadPredicted(IntegratedWormData data) {
System.err.println(markerAnnotations + " " + markerAnnotations.getCurves().size());
data.annotations.add(markerAnnotations);
data.voiManager.addAnnotations(data.annotations);
- WormData.saveIntegratedMarkerAnnotations(resultsDir(latticeFileDir, data.wormImage), data.voiManager.getAnnotations());
+ WormData.saveIntegratedMarkerAnnotations(resultsDir(latticeFileDir, data.wormImage),
+ data.voiManager.getAnnotations());
data.annotations = null;
VOI annotations = data.voiManager.getAnnotations();
@@ -2896,8 +3017,7 @@ private void openAnnotations(IntegratedWormData data) {
if (markers != null) {
data.annotations.add(markers);
}
- }
- else {
+ } else {
// if (loadLegacyAnnotationsCheck.isSelected()) {
// data.wormImage.setResolutions(originalResolutions);
// }
@@ -2925,7 +3045,7 @@ private void openAnnotations(IntegratedWormData data) {
System.err.println("openAnnotations " + data.wormImage.getImageName() + " "
+ data.annotations.elementAt(0).getCurves().size());
}
-
+
/**
* Saves the seam cells to the default edited file for the current image.
*/
@@ -2936,8 +3056,9 @@ private void saveSeamCells() {
if (imageIndex >= includeRange.size()) {
return;
}
- WormData.saveSeamAnnotations(resultsDir(latticeFileDir, activeImage.wormImage), activeImage.voiManager.getAnnotations(),
- (editMode != CheckSeam) && (editMode != IntegratedEditing), true);
+ WormData.saveSeamAnnotations(resultsDir(latticeFileDir, activeImage.wormImage),
+ activeImage.voiManager.getAnnotations(), (editMode != CheckSeam) && (editMode != IntegratedEditing),
+ true);
}
/**
@@ -2986,7 +3107,7 @@ private boolean setVariables() {
}
baseFileName = baseFileNameText.getText();
-
+
includeRange = new Vector();
String rangeFusion = rangeFusionText.getText();
if (rangeFusion != null) {
@@ -3032,36 +3153,38 @@ private boolean setVariables() {
}
private boolean imageChannelsInit = false;
+
private void initImageChannels(IntegratedWormData integratedData) {
- if ( imageChannelsInit ) return;
+ if (imageChannelsInit)
+ return;
imageChannelsInit = true;
int numImages = integratedData.hyperstack.length;
String[] subDir = new String[numImages];
- for ( int i = 0; i < numImages; i++ ) {
+ for (int i = 0; i < numImages; i++) {
int index = baseFileDir[i].lastIndexOf(File.separator) + 1;
int len = baseFileDir[i].length();
- subDir[i] = baseFileDir[i].substring(index,len);
+ subDir[i] = baseFileDir[i].substring(index, len);
JCheckBox box = new JCheckBox(subDir[i], true);
box.setActionCommand(subDir[i]);
box.addActionListener(this);
- imageChannels.add( box );
+ imageChannels.add(box);
}
}
-
+
private int imageChannel(String cmd) {
int numImages = activeImage.hyperstack.length;
- for ( int i = 0; i < numImages; i++ ) {
+ for (int i = 0; i < numImages; i++) {
int index = baseFileDir[i].lastIndexOf(File.separator) + 1;
int len = baseFileDir[i].length();
- String subDir = baseFileDir[i].substring(index,len);
- if ( subDir.equals(cmd) ) {
+ String subDir = baseFileDir[i].substring(index, len);
+ if (subDir.equals(cmd)) {
return i;
}
}
return -1;
}
-
+
/**
* Creates or updates the histogram / LUT panel and opacity panels when a new
* image is loaded.
@@ -3122,9 +3245,9 @@ private void initHistoLUTPanel(IntegratedWormData integratedData) {
int numImages = integratedData.hyperstack.length;
integratedData.volOpacityPanel = new JPanelVolumeOpacity[numImages];
- for ( int i = 0; i < numImages; i++ ) {
- integratedData.volOpacityPanel[i] = new JPanelVolumeOpacity(integratedData.hyperstack[i].GetImage(),
- null, null, null, true);
+ for (int i = 0; i < numImages; i++) {
+ integratedData.volOpacityPanel[i] = new JPanelVolumeOpacity(integratedData.hyperstack[i].GetImage(), null,
+ null, null, true);
integratedData.volOpacityPanel[i].addPropertyChangeListener(this);
TransferFunction kTransfer = integratedData.volOpacityPanel[i].getCompA().getOpacityTransferFunction();
@@ -3134,18 +3257,17 @@ private void initHistoLUTPanel(IntegratedWormData integratedData) {
// System.err.println( "initHistoLUTPanel " +
// integratedData.volumeImage.getLUT() );
integratedData.lutHistogramPanel = new JFrameHistogram[numImages];
- for ( int i = 0; i < numImages; i++ ) {
+ for (int i = 0; i < numImages; i++) {
- integratedData.lutHistogramPanel[i] = new JFrameHistogram(this, integratedData.hyperstack[i].GetImage(), null,
- integratedData.hyperstack[i].getLUT(), null);
- integratedData.lutHistogramPanel[i].histogramLUT(true, false, false);//!integratedData.volumeImage.GetImage().isColorImage());
+ integratedData.lutHistogramPanel[i] = new JFrameHistogram(this, integratedData.hyperstack[i].GetImage(),
+ null, integratedData.hyperstack[i].getLUT(), null);
+ integratedData.lutHistogramPanel[i].histogramLUT(true, false, false);// !integratedData.volumeImage.GetImage().isColorImage());
}
-
// if (integratedData.volumeImage.GetImage().isColorImage()) {
// integratedData.displayBothChannels.setSelected(true);
// }
- for ( int i = 0; i < numImages; i++ ) {
+ for (int i = 0; i < numImages; i++) {
integratedData.hyperstack[i].GetImage().addImageDisplayListener(this);
}
}
@@ -3156,13 +3278,13 @@ private void updateHistoLUTPanels(IntegratedWormData integratedData) {
// integratedData.lutHistogramPanel.getContainingPanel() );
int numImages = integratedData.hyperstack.length;
String[] subDir = new String[numImages];
- if ( !integratedData.colorMapInit ) {
+ if (!integratedData.colorMapInit) {
integratedData.colorMapInit = true;
- for ( int i = 0; i < numImages; i++ ) {
+ for (int i = 0; i < numImages; i++) {
int index = baseFileDir[i].lastIndexOf(File.separator) + 1;
int len = baseFileDir[i].length();
- subDir[i] = baseFileDir[i].substring(index,len);
- if ( subDir[i].equals("405") ) {
+ subDir[i] = baseFileDir[i].substring(index, len);
+ if (subDir[i].equals("405")) {
// set transfer function:
ModelLUT lut = integratedData.hyperstack[i].GetLUT();
lut.makeBlueTransferFunctions();
@@ -3171,7 +3293,7 @@ private void updateHistoLUTPanels(IntegratedWormData integratedData) {
tf.replacePoint(64, 0, 2);
lut.makeLUT(256);
}
- if ( subDir[i].equals("488") ) {
+ if (subDir[i].equals("488")) {
// set transfer function:
ModelLUT lut = integratedData.hyperstack[i].GetLUT();
lut.makeGreenTransferFunctions();
@@ -3180,7 +3302,7 @@ private void updateHistoLUTPanels(IntegratedWormData integratedData) {
tf.replacePoint(64, 0, 2);
lut.makeLUT(256);
}
- if ( subDir[i].equals("561") ) {
+ if (subDir[i].equals("561")) {
// set transfer function:
ModelLUT lut = integratedData.hyperstack[i].GetLUT();
lut.makeRedTransferFunctions();
@@ -3189,7 +3311,7 @@ private void updateHistoLUTPanels(IntegratedWormData integratedData) {
tf.replacePoint(64, 0, 2);
lut.makeLUT(256);
}
- if ( subDir[i].equals("637") ) {
+ if (subDir[i].equals("637")) {
// set transfer function:
ModelLUT lut = integratedData.hyperstack[i].GetLUT();
TransferFunction tf = lut.getTransferFunction();
@@ -3199,7 +3321,7 @@ private void updateHistoLUTPanels(IntegratedWormData integratedData) {
}
}
}
-
+
// re-add lutTab to lutPanel due to removal in enableNext
if (lutPanel.getComponentCount() == 0) {
lutPanel.add(lutTab, BorderLayout.CENTER);
@@ -3209,52 +3331,52 @@ private void updateHistoLUTPanels(IntegratedWormData integratedData) {
opacityPanel.add(opacityTab, BorderLayout.CENTER);
}
- opacityTab.removeAll();
- for ( int i = 0; i < numImages; i++ ) {
+ opacityTab.removeAll();
+ for (int i = 0; i < numImages; i++) {
int index = baseFileDir[i].lastIndexOf(File.separator) + 1;
int len = baseFileDir[i].length();
- subDir[i] = baseFileDir[i].substring(index,len);
-
- opacityTab.addTab( subDir[i] + File.separator + integratedData.hyperstack[i].GetImage().getImageName(),
- null, integratedData.volOpacityPanel[i].getMainPanel() );
+ subDir[i] = baseFileDir[i].substring(index, len);
-
- final TransferFunction kTransfer = integratedData.volOpacityPanel[i].getCompA().getOpacityTransferFunction();
+ opacityTab.addTab(subDir[i] + File.separator + integratedData.hyperstack[i].GetImage().getImageName(), null,
+ integratedData.volOpacityPanel[i].getMainPanel());
+
+ final TransferFunction kTransfer = integratedData.volOpacityPanel[i].getCompA()
+ .getOpacityTransferFunction();
updateImages(integratedData.colormap, integratedData.hyperstack[i].GetImage(), kTransfer, i);
integratedData.volOpacityPanel[i].getCompA().showHistogram();
integratedData.hyperstack[i].UpdateImages(kTransfer, 0, null);
- if ( integratedData.previewHS != null ) {
+ if (integratedData.previewHS != null) {
integratedData.previewHS[i].UpdateImages(kTransfer, 0, null);
}
}
if (tabbedPane.getSelectedComponent() == opacityPanel) {
int which = opacityTab.getSelectedIndex();
- if ( which != -1 ) {
+ if (which != -1) {
integratedData.volOpacityPanel[which].getCompA().showHistogram();
}
}
lutTab.removeAll();
- for ( int i = 0; i < numImages; i++ ) {
- lutTab.addTab( subDir[i] + File.separator + integratedData.hyperstack[i].GetImage().getImageName(),
- null, integratedData.lutHistogramPanel[i].getContainingPanel());
- updateImages(integratedData.colormap, integratedData.hyperstack[i].GetLUT(), i );
-
+ for (int i = 0; i < numImages; i++) {
+ lutTab.addTab(subDir[i] + File.separator + integratedData.hyperstack[i].GetImage().getImageName(), null,
+ integratedData.lutHistogramPanel[i].getContainingPanel());
+ updateImages(integratedData.colormap, integratedData.hyperstack[i].GetLUT(), i);
+
integratedData.hyperstack[i].UpdateImages(integratedData.hyperstack[i].getLUT());
- if ( integratedData.previewHS != null ) {
+ if (integratedData.previewHS != null) {
integratedData.previewHS[i].UpdateImages(integratedData.hyperstack[i].getLUT());
}
integratedData.lutHistogramPanel[i].redrawFrames();
}
if (tabbedPane.getSelectedComponent() == lutPanel) {
- int which = lutTab.getSelectedIndex();
- if ( which != -1 ) {
+ int which = lutTab.getSelectedIndex();
+ if (which != -1) {
integratedData.lutHistogramPanel[which].redrawFrames();
}
}
-
+
lutPanel.revalidate();
}
@@ -3292,6 +3414,15 @@ private void updateSurfacePanels() {
// }
}
+ /**
+ * Updates the selection panel method ensures that the user interface components
+ * related to VOI management reflect the current operational mode.
+ */
+ private void updateSelectionPanel() {
+ VOILatticeManagerInterface voiManager = activeImage.voiManager;
+ voiManager.setAccurateMode(voiManager.isAccurateMode());
+ }
+
/*
* private VOIVector autoLattice() { VOIVector latticeContainer = new
* VOIVector(); short id = (short) wormImage.getVOIs().getUniqueID(); VOI
@@ -3337,7 +3468,7 @@ public void stateChanged(ChangeEvent arg0) {
}
private void saveIntegrated() {
- activeImage.voiManager.setSharedDirectory( resultsDir(latticeFileDir, activeImage.wormImage));
+ activeImage.voiManager.setSharedDirectory(resultsDir(latticeFileDir, activeImage.wormImage));
if (editMode == EditSeamCells || editMode == CheckSeam) {
saveSeamCells();
@@ -3353,76 +3484,78 @@ private void saveIntegrated() {
// separately so not untwisted twice:
saveSplineCurves();
- if ( activeImage.voiManager != null ) {
+ if (activeImage.voiManager != null) {
// save annotations not in splines:
- WormData.saveIntegratedMarkerAnnotations(resultsDir(latticeFileDir, activeImage.wormImage), activeImage.voiManager.getAnnotations());
+ WormData.saveIntegratedMarkerAnnotations(resultsDir(latticeFileDir, activeImage.wormImage),
+ activeImage.voiManager.getAnnotations());
}
}
-
+
private void setDefaultInputList(String dir) {
File file = new File(dir);
- if ( file.exists() && file.isDirectory() ) {
+ if (file.exists() && file.isDirectory()) {
final String[] list = file.list();
String imageList = "";
for (int i = 0; i < list.length; i++) {
- if ( list[i].endsWith(".tif") ) {
- String temp = list[i].substring(list[i].lastIndexOf("_") + 1, list[i].indexOf(".tif") );
+ if (list[i].endsWith(".tif")) {
+ String temp = list[i].substring(list[i].lastIndexOf("_") + 1, list[i].indexOf(".tif"));
System.err.println(list[i] + " " + temp);
- if ( imageList != "" ) imageList += ",";
+ if (imageList != "")
+ imageList += ",";
imageList += temp;
}
}
- if ( imageList != "" ) {
+ if (imageList != "") {
rangeFusionText.setText(imageList);
}
}
}
-
+
private class UntwistDialog extends JDialogBase implements ActionListener {
private JCheckBox[] volumeChecks;
private String[] volumeDirs;
private JTextField latticeOutputDir;
- public UntwistDialog( String baseDir ) {
+
+ public UntwistDialog(String baseDir) {
File file = new File(baseDir);
- if ( file.exists() && file.isDirectory() ) {
+ if (file.exists() && file.isDirectory()) {
final String[] list = file.list();
Vector tempList = new Vector();
for (int i = 0; i < list.length; i++) {
File subDir = new File(file.getAbsolutePath() + File.separator + list[i]);
- if ( subDir.exists() && subDir.isDirectory() )
- {
+ if (subDir.exists() && subDir.isDirectory()) {
System.err.println(file.getAbsolutePath() + File.separator + list[i]);
tempList.add(list[i]);
}
}
- if ( tempList.size() > 0 ) {
+ if (tempList.size() > 0) {
init(baseDir, tempList);
setVisible(true);
}
}
- }
-
- // Diyi: Created a simpler version of actionPerformed to replace the previous one
+ }
+
+ // Diyi: Created a simpler version of actionPerformed to replace the previous
+ // one
public void actionPerformed(ActionEvent event) {
String command = event.getActionCommand();
Object source = event.getSource();
System.err.println("UntwistDialog " + command);
- if ( command.equals("Cancel") ) {
+ if (command.equals("Cancel")) {
baseFileLocText.setText("");
latticeOutputDir = null;
setVisible(false);
- }
- else if ( command.equals("OK") ) {
-
+ } else if (command.equals("OK")) {
+
ArrayList list = new ArrayList<>(volumeChecks.length);
-
- for (int i = 0; i < volumeChecks.length; i++){
+
+ for (int i = 0; i < volumeChecks.length; i++) {
if (volumeChecks[i].isSelected()) {
- list.add(volumeDirs[i]);
+ list.add(volumeDirs[i]);
}
- baseFileDir = new String [list.size()];
+ baseFileDir = new String[list.size()];
list.toArray(baseFileDir);
}
if (list.size() == 0)
@@ -3430,9 +3563,8 @@ else if ( command.equals("OK") ) {
setVisible(false);
}
}
-
-
- private void init( String baseDir, Vector tempList ) {
+
+ private void init(String baseDir, Vector tempList) {
setForeground(Color.black);
setTitle("Untwisting C.elegans - lattice - 2.0");
@@ -3441,57 +3573,58 @@ private void init( String baseDir, Vector tempList ) {
} catch (FileNotFoundException e) {
Preferences.debug("Failed to load default icon", Preferences.DEBUG_MINOR);
}
- JPanel input = new JPanel( new GridLayout(tempList.size() + 1, 1));
+ JPanel input = new JPanel(new GridLayout(tempList.size() + 1, 1));
GuiBuilder gui = new GuiBuilder(this);
volumeChecks = new JCheckBox[tempList.size()];
volumeDirs = new String[tempList.size()];
String latticeDir = null;
- for ( int i = 0; i < tempList.size(); i++ ) {
+ for (int i = 0; i < tempList.size(); i++) {
volumeChecks[i] = gui.buildCheckBox(tempList.elementAt(i), true);
volumeChecks[i].addActionListener(this);
input.add(volumeChecks[i].getParent());
volumeDirs[i] = new String(baseDir + File.separator + tempList.elementAt(i));
final File subDir = new File(volumeDirs[i]);
- if ( latticeDir == null ) {
- latticeDir = new String(baseDir + File.separator + tempList.elementAt(i));
+ if (latticeDir == null) {
+ latticeDir = new String(baseDir + File.separator + tempList.elementAt(i));
+ }
+ if (containsLattice(subDir)) {
+ latticeDir = new String(baseDir + File.separator + tempList.elementAt(i));
}
- if ( containsLattice(subDir) ) {
- latticeDir = new String(baseDir + File.separator + tempList.elementAt(i));
- }
-
+
}
-
- latticeOutputDir = gui.buildFileField("Lattice Directory:", latticeDir, false, JFileChooser.DIRECTORIES_ONLY,
- this);
+
+ latticeOutputDir = gui.buildFileField("Lattice Directory:", latticeDir, false,
+ JFileChooser.DIRECTORIES_ONLY, this);
input.add(latticeOutputDir.getParent());
-
+
System.err.println(latticeDir);
getContentPane().add(input, BorderLayout.CENTER);
-
+
JPanel buttonPanel = new JPanel();
- buttonPanel.add(JDialogBase.buildOKButton( "OK", this ));
- buttonPanel.add(JDialogBase.buildCancelButton( "Cancel", this ));
+ buttonPanel.add(JDialogBase.buildOKButton("OK", this));
+ buttonPanel.add(JDialogBase.buildCancelButton("Cancel", this));
getContentPane().add(buttonPanel, BorderLayout.SOUTH);
setModal(true);
- if ( bar != null ) bar.setVisible(false);
+ if (bar != null)
+ bar.setVisible(false);
pack();
}
-
- private boolean containsLattice(File dir ) {
- if ( dir.exists() && dir.isDirectory() ) {
+ private boolean containsLattice(File dir) {
+
+ if (dir.exists() && dir.isDirectory()) {
final String[] list = dir.list();
- for ( int i = 0; i < list.length; i++ ) {
- if ( list[i].equals("lattice_final") ) {
+ for (int i = 0; i < list.length; i++) {
+ if (list[i].equals("lattice_final")) {
return true;
- }
- else {
- File file = new File(dir.getAbsolutePath() + File.separator + list[i] );
- if ( file.exists() && file.isDirectory() ) {
- if ( containsLattice(file) ) return true;
+ } else {
+ File file = new File(dir.getAbsolutePath() + File.separator + list[i]);
+ if (file.exists() && file.isDirectory()) {
+ if (containsLattice(file))
+ return true;
}
}
}
@@ -3499,76 +3632,79 @@ private boolean containsLattice(File dir ) {
return false;
}
}
-
+
public void setDemoValues() {
- //baseFileLocText.setText("\\\\nearline4.hhmi.org\\shroff\\shrofflab\\efn-1\\Tracking\\Pos0\\For_Tracking");
+ // baseFileLocText.setText("\\\\nearline4.hhmi.org\\shroff\\shrofflab\\efn-1\\Tracking\\Pos0\\For_Tracking");
// X:\shrofflab\RW10752_NU\Untwisting\031219_RW10752_NU\RW10752_NU\RW10752_NU\Pos2\Decon_registered
-
- //diyi local test path: E:\Diyi\Pos2\Decon_registered
- //String access_path = "E:\\Diyi\\Pos2\\Decon_registered";
-
- //from diyi error mimic path: X:\shrofflab\Vab-1\Tracking\Pos0\SPIMB\Reg_Sample\For_Tracking\RegB
- //from jhonny:Z:\shrofflab\Vab-1\Tracking\Pos0\SPIMB\Reg_Sample\For_Tracking\RegB\Decon_reg_14\Decon_reg_14_results
- //copied to diyi from jhonny: E:\Diyi\SPIMB\Reg_Sample\For_Tracking\RegB\Decon_reg_14\Decon_reg_14_results
-
- //from online:\\\\nearline4.hhmi.org\\shroff\\shrofflab\\efn-1\\Tracking\\Pos0\\For_Tracking
- //String access_path = "\\\\nearline4.hhmi.org\\shroff\\shrofflab\\efn-1\\Tracking\\Pos0\\For_Tracking";
-
- //from online jhonny: X:\shrofflab\Vab-1\Tracking\Pos0\SPIMB\Reg_Sample\For_Tracking\RegB\Decon_reg_14\Decon_reg_14_results
- //String access_path = "X:\\shrofflab\\Vab-1\\Tracking\\Pos0\\SPIMB\\Reg_Sample\\For_Tracking";
-
- //String access_path = "E:\\Diyi\\SPIMB\\Reg_Sample\\For_Tracking";
+
+ // diyi local test path: E:\Diyi\Pos2\Decon_registered
+ // String access_path = "E:\\Diyi\\Pos2\\Decon_registered";
+
+ // from diyi error mimic path:
+ // X:\shrofflab\Vab-1\Tracking\Pos0\SPIMB\Reg_Sample\For_Tracking\RegB
+ // from
+ // jhonny:Z:\shrofflab\Vab-1\Tracking\Pos0\SPIMB\Reg_Sample\For_Tracking\RegB\Decon_reg_14\Decon_reg_14_results
+ // copied to diyi from jhonny:
+ // E:\Diyi\SPIMB\Reg_Sample\For_Tracking\RegB\Decon_reg_14\Decon_reg_14_results
+
+ // from
+ // online:\\\\nearline4.hhmi.org\\shroff\\shrofflab\\efn-1\\Tracking\\Pos0\\For_Tracking
+ // String access_path =
+ // "\\\\nearline4.hhmi.org\\shroff\\shrofflab\\efn-1\\Tracking\\Pos0\\For_Tracking";
+
+ // from online jhonny:
+ // X:\shrofflab\Vab-1\Tracking\Pos0\SPIMB\Reg_Sample\For_Tracking\RegB\Decon_reg_14\Decon_reg_14_results
+ // String access_path =
+ // "X:\\shrofflab\\Vab-1\\Tracking\\Pos0\\SPIMB\\Reg_Sample\\For_Tracking";
+
+ // String access_path = "E:\\Diyi\\SPIMB\\Reg_Sample\\For_Tracking";
String access_path = "D:\\shroff\\For_Tracking";
baseFileLocText.setText(access_path);
editLattice.setSelected(true);
- //actionPerformed(new ActionEvent(this, 0, "BrowseConclude"));
-
+ // actionPerformed(new ActionEvent(this, 0, "BrowseConclude"));
+
String[] volumeDirs;
-
+
String baseDir = baseFileLocText.getText();
File file = new File(baseDir);
-
+
final String[] list = file.list();
Vector tempList = new Vector();
for (int i = 0; i < list.length; i++) {
File subDir = new File(file.getAbsolutePath() + File.separator + list[i]);
- if ( subDir.exists() && subDir.isDirectory() )
- {
+ if (subDir.exists() && subDir.isDirectory()) {
System.err.println(file.getAbsolutePath() + File.separator + list[i]);
- if (list[i].equals("RegA") || list[i].equals("RegB"))
- {
+ if (list[i].equals("RegA") || list[i].equals("RegB")) {
tempList.add(list[i]);
}
}
}
-
+
volumeDirs = new String[tempList.size()];
-
+
int count = 0;
- for ( int i = 0; i < volumeDirs.length; i++ ) {
- count++;
+ for (int i = 0; i < volumeDirs.length; i++) {
+ count++;
volumeDirs[i] = new String(baseDir + File.separator + tempList.elementAt(i));
}
- if ( count == 0 ) {
+ if (count == 0) {
baseFileLocText.setText("");
- //latticeOutputDir = null;
- }
- else {
+ // latticeOutputDir = null;
+ } else {
baseFileDir = new String[count];
count = 0;
- for ( int i = 0; i < volumeDirs.length; i++ ) {
+ for (int i = 0; i < volumeDirs.length; i++) {
baseFileDir[count++] = volumeDirs[i];
}
}
- //baseFileLocText.setText("\\\\nearline4.hhmi.org\\shroff\\shrofflab\\efn-1\\Tracking\\Pos0\\For_Tracking\\RegB");
+ // baseFileLocText.setText("\\\\nearline4.hhmi.org\\shroff\\shrofflab\\efn-1\\Tracking\\Pos0\\For_Tracking\\RegB");
latticeFileDir = new String(access_path + "\\RegB");
setDefaultInputList(latticeFileDir);
rangeFusionText.setText("60-61");
-
+
actionPerformed(new ActionEvent(this, 0, "start"));
}
}
-
diff --git a/src/org/janelia/mipav/plugins/worm/untwisting/SelectionChartPanel.java b/src/org/janelia/mipav/plugins/worm/untwisting/SelectionChartPanel.java
new file mode 100644
index 0000000000..bece67fd75
--- /dev/null
+++ b/src/org/janelia/mipav/plugins/worm/untwisting/SelectionChartPanel.java
@@ -0,0 +1,371 @@
+package org.janelia.mipav.plugins.worm.untwisting;
+
+import org.jfree.chart.*;
+import org.jfree.chart.axis.ValueAxis;
+import org.jfree.chart.event.MarkerChangeEvent;
+import org.jfree.chart.event.MarkerChangeListener;
+import org.jfree.chart.plot.PlotOrientation;
+import org.jfree.chart.plot.ValueMarker;
+import org.jfree.chart.plot.XYPlot;
+import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
+import org.jfree.chart.ui.RectangleAnchor;
+import org.jfree.chart.ui.TextAnchor;
+import org.jfree.chart.ui.Layer;
+import org.jfree.data.xy.XYSeries;
+import org.jfree.data.xy.XYSeriesCollection;
+
+import WildMagic.LibFoundation.Mathematics.Vector3f;
+
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.geom.Rectangle2D;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class SelectionChartPanel extends ChartPanel implements MarkerChangeListener {
+
+
+/**
+ * CustomChartPanel is a custom extension of the ChartPanel class from JFreeChart
+ * used to display and interact with a dynamic XY line chart. It includes custom
+ * behaviors for handling marker changes and mouse drag events.
+ */
+ private static final long serialVersionUID = 1L;
+ private JFreeChart selectionChart;
+ private List chart3DPoints;
+ private PlugInDialogVolumeRenderDualJanelia parent;
+
+ public SelectionChartPanel(List values, String title, PlugInDialogVolumeRenderDualJanelia parent) {
+ super(null);
+ this.selectionChart = createChart(values, title, this);
+ this.parent = parent;
+ this.setChart(selectionChart);
+ setPreferredSize(new Dimension(100,100));// plot gets larger vertically and horizontally if remove this line
+ initialize();
+
+ }
+
+ private void initialize() {
+ setMouseWheelEnabled(false);
+ setDomainZoomable(false);
+ setRangeZoomable(false);
+ setMouseZoomable(false, false);
+ setFillZoomRectangle(false);
+ setZoomAroundAnchor(false);
+
+
+ // Add a mouse motion listener to handle dragging movements over the chart
+ addMouseMotionListener(new MouseAdapter() {
+ @Override
+ public void mouseDragged(MouseEvent e) {
+ // Get the plot area for accurate coordinate calculation
+ Rectangle2D plotArea = getScreenDataArea();
+ XYPlot plot = selectionChart.getXYPlot();
+ ValueAxis xAxis = plot.getDomainAxis();
+ double x = xAxis.java2DToValue(e.getX(), plotArea, plot.getDomainAxisEdge());
+ ValueAxis yAxis = plot.getRangeAxis();
+ double yClick = yAxis.java2DToValue(e.getY(), plotArea, plot.getRangeAxisEdge());
+
+ // Determine the corresponding Y-value by finding the nearest index
+ XYSeriesCollection dataset = (XYSeriesCollection) plot.getDataset();
+ XYSeries series = dataset.getSeries(0);
+ XYSeries slopeSeries = dataset.getSeries(1);
+
+ int index = findNearestXIndex(series, x);
+ double y = series.getY(index).doubleValue();
+ double slope = slopeSeries.getY(index).doubleValue(); // slope is derivative at x
+
+ // Update the marker's value and label on the chart
+ ValueMarker marker = (ValueMarker) plot.getDomainMarkers(Layer.FOREGROUND).iterator().next();
+ marker.setValue(x);
+ marker.setLabel(String.format("Value: %.2f, Derivative: %.2f", y, slope));
+ marker.setLabelFont(new Font("Serif", Font.BOLD, 14));
+ marker.setStroke(new BasicStroke(2.0f));
+
+ // Update the thresholdMarker's value and label on the chart
+ ValueMarker thresholdMarker = (ValueMarker) plot.getRangeMarkers(Layer.FOREGROUND).iterator().next();
+ thresholdMarker.setValue(yClick);
+ thresholdMarker.setLabel(String.format("Threshold Value: %.2f", yClick));
+ thresholdMarker.setLabelFont(new Font("Serif", Font.BOLD, 14));
+ thresholdMarker.setStroke(new BasicStroke(2.0f));
+
+
+ // Redraw the chart to reflect changes
+ repaint();
+ e.consume();
+ }
+ });
+ }
+
+ public void setChart(JFreeChart chart) {
+ super.setChart(chart);
+ setMouseWheelEnabled(false);
+ setDomainZoomable(false);
+ setRangeZoomable(false);
+ setMouseZoomable(false, false);
+ setFillZoomRectangle(false);
+ setZoomAroundAnchor(false);
+ }
+
+ /**
+ * Finds the index of the closest X value to the given target x.
+ *
+ * @param series The series of data points.
+ * @param x The target x value to match.
+ * @return The index of the closest x value.
+ */
+ private int findNearestXIndex(XYSeries series, double x) {
+ double minDistance = Double.MAX_VALUE;
+ int nearestIndex = -1;
+
+ for (int i = 0; i < series.getItemCount(); i++) {
+ double distance = Math.abs(series.getX(i).doubleValue() - x);
+ if (distance < minDistance) {
+ minDistance = distance;
+ nearestIndex = i;
+ }
+ }
+ return nearestIndex;
+ }
+
+ public void updateChart(List values, String title) {
+ this.selectionChart = createChart(values, title, this);
+ setChart(this.selectionChart);
+ revalidate();
+ repaint();
+ }
+
+ // Set up a marker change listener to handle marker position changes
+ @Override
+ public void markerChanged(MarkerChangeEvent event) {
+ ValueMarker marker = (ValueMarker) event.getMarker();
+ float tq = (float) marker.getValue();
+ // Calculate the indices for interpolation
+ int t0 = (int) Math.floor(tq);
+ int t1 = (int) Math.ceil(tq);
+
+ if (t0 >= 0 && t1 < chart3DPoints.size() && t0 != t1) {
+ Vector3f interpolatedPoint = interpolate(t0, t1, tq);
+ parent.update3DModel(interpolatedPoint);
+ } else if (t0 == t1 && t0 < chart3DPoints.size()) {
+ Vector3f exactPoint = chart3DPoints.get(t0);
+ parent.update3DModel(exactPoint);
+ }
+ }
+
+ /**
+ * Interpolates between two 3D points based on a given interpolation parameter.
+ *
+ * @param t0 Index of the first point.
+ * @param t1 Index of the second point.
+ * @param tq The interpolation parameter, typically derived from the marker's
+ * position.
+ * @return The interpolated 3D point.
+ */
+ private Vector3f interpolate(int t0, int t1, float tq) {
+ Vector3f pt0 = chart3DPoints.get(t0);
+ Vector3f pt1 = chart3DPoints.get(t1);
+
+ float m0 = (t1 - tq) / (t1 - t0);
+ float m1 = (tq - t0) / (t1 - t0);
+
+ float x = (float) (m0 * pt0.X + m1 * pt1.X);
+ float y = (float) (m0 * pt0.Y + m1 * pt1.Y);
+ float z = (float) (m0 * pt0.Z + m1 * pt1.Z);
+
+ return new Vector3f(x, y, z);
+ }
+
+ /**
+ * Creates a chart using a list of values and assigns it a title. Each value in
+ * the list is plotted against its index.
+ *
+ * @param values List of floating-point values for the Y-axis.
+ * @param title Title of the chart.
+ * @return A JFreeChart object fully initialized.
+ */
+ private static JFreeChart createChart(List values, String title, MarkerChangeListener markerListener) {
+ XYSeries series = new XYSeries("Data");
+ float maxValue = -Float.MAX_VALUE;
+ int maxIndex = -1;
+
+ // Populate the series with values and track the maximum value and its index
+ for (int i = 0; i < values.size(); i++) {
+ float value = values.get(i);
+ series.add(i, value);
+ if (value > maxValue) {
+ maxValue = value;
+ maxIndex = i;
+ }
+ }
+
+ XYSeriesCollection dataset = new XYSeriesCollection();
+ dataset.addSeries(series);
+
+ // Calculate slopes and add to the series
+ List slopes = calculateSecantSlopes(values);
+
+ XYSeries slopeSeries = new XYSeries("Slopes");
+ for (int i = 2; i < values.size(); i++) {
+ // double slopeIndex = i - 0.5; // offset half an interval, 0.5, from the original values along the x-axis.
+ double slopeIndex = i -1;
+ slopeSeries.add(slopeIndex, slopes.get(i-2));
+ }
+ dataset.addSeries(slopeSeries);
+
+ // Create the chart
+ JFreeChart chart = ChartFactory.createXYLineChart(title, "Index", "Value", dataset, PlotOrientation.VERTICAL,
+ true, true, false);
+
+ XYPlot plot = chart.getXYPlot();
+ plot.setBackgroundPaint(Color.GRAY);
+ plot.setDomainGridlinePaint(Color.DARK_GRAY);
+ plot.setRangeGridlinePaint(Color.DARK_GRAY);
+
+ XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer();
+ renderer.setSeriesPaint(0, Color.YELLOW);
+ renderer.setSeriesStroke(0, new BasicStroke(2.0f));
+ plot.setRenderer(renderer);
+
+ // Added vertical domianMarker
+ ValueMarker marker = new ValueMarker(maxIndex);
+ marker.setPaint(Color.CYAN);
+ marker.setLabel("Max Value: " + maxValue);
+ marker.setLabelFont(new Font("Serif", Font.BOLD, 14));
+ marker.setLabelPaint(Color.WHITE);
+ marker.setLabelAnchor(RectangleAnchor.CENTER);
+ marker.setLabelTextAnchor(TextAnchor.CENTER_LEFT);
+ marker.setStroke(new BasicStroke(2.0f));
+ plot.addDomainMarker(marker);
+
+ // Added horizontal theesholdMarker
+ float thresholdValue = maxValue / 2;
+ ValueMarker thresholdMarker = new ValueMarker(thresholdValue);
+ thresholdMarker.setPaint(Color.CYAN);
+ thresholdMarker.setLabel("Threshold Value: " + thresholdValue);
+ thresholdMarker.setLabelFont(new Font("Serif", Font.BOLD, 14));
+ thresholdMarker.setLabelPaint(Color.WHITE);
+ thresholdMarker.setLabelAnchor(RectangleAnchor.CENTER);
+ thresholdMarker.setLabelTextAnchor(TextAnchor.CENTER_LEFT);
+ thresholdMarker.setStroke(new BasicStroke(2.0f));
+ plot.addRangeMarker(thresholdMarker);
+
+ marker.addChangeListener(markerListener);
+
+ return chart;
+ }
+
+ /**
+ * Calculates the slopes between points in the list
+ *
+ * @param values List of values for which slopes are to be calculated.
+ * @return List of calculated slopes.
+ */
+ private static List calculateAdjacentSlopes(List values) {
+ List slopes = new ArrayList<>();
+ for (int i = 1; i < values.size(); i++) {
+ float slope = (values.get(i) - values.get(i - 1)) / 1.0f;
+ slopes.add(slope);
+ }
+ return slopes;
+ }
+
+ private static List calculateSecantSlopes(List values) {
+ List slopes = new ArrayList<>();
+ for (int i = 2; i < values.size(); i++) {
+ float slope = (values.get(i) - values.get(i - 2)) / 1.0f;
+ slopes.add(slope);
+ }
+ return slopes;
+ }
+
+
+ /**
+ * Sets the 3D points corresponding to the data points in the plot.
+ *
+ * @param points List of 3D points to be used in corresponding 3D model updates.
+ */
+ public void setChart3DPoints(List points) {
+ this.chart3DPoints = points;
+ }
+
+ /**
+ * Method to find the next peak. It cycles through values starting from a given
+ * index to identify a peak where the slope changes sign.
+ *
+ * @param index Starting index for the search, ensuring it doesn't start
+ * before the beginning of the list.
+ * @param values List of Y-values from the dataset.
+ * @param threshold Minimum Y-value to consider for a peak.
+ * @return The index of the next peak if found; otherwise, returns -1.
+ */
+ public float nextPeak(int index, List values, double threshold) {
+ // Calculate slopes between each pair of points using a secant method.
+ List slopes = calculateSecantSlopes(values);
+ // Ensure the starting index is not less than zero
+ index = Math.max(index, 0);
+
+ // Loop through slopes to find where the sign changes.
+ for (int j = 0; j < slopes.size() - 1; j++) {
+ int i = (j + index) % (slopes.size() - 1);
+ float currentSlope = slopes.get(i);
+ float nextSlope = slopes.get(i + 1);
+ float y = values.get(i + 1);
+
+ // Check if current point is a peak by comparing it against the threshold and
+ // slope changes.
+ if (y > threshold && currentSlope > 0 && nextSlope < 0) {
+ // Calculate interpolated index where the slope would cross zero.
+ float indexX = ((-currentSlope) / (nextSlope - currentSlope)) + i;
+ System.out.println("here is the indexX:" + indexX);
+ System.out.println("this is i:" + i);
+ return indexX + 1;
+
+ }
+ }
+ System.out.println("No peak found.");
+ return -1;
+ }
+
+ /***
+ * Handles action events, specifically looking to handle "Next Peak" actions.
+ *
+ * @param e The ActionEvent object containing details about the event.
+ */
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (e.getActionCommand() == "Next Peak") {
+ XYPlot plot = selectionChart.getXYPlot();
+ // Retrieve data and convert it into a List for processing
+ XYSeriesCollection dataset = (XYSeriesCollection) plot.getDataset();
+ XYSeries series = dataset.getSeries(0);
+ double[][] data = series.toArray();
+ List values = Arrays.stream(data[1]).mapToObj(d -> Float.valueOf((float) d))
+ .collect(Collectors.toList());
+
+ // Access current marker position and determine the next index to check for a
+ // peak
+ ValueMarker marker = (ValueMarker) plot.getDomainMarkers(Layer.FOREGROUND).iterator().next();
+ int index = (int) Math.ceil(marker.getValue()) + 1;
+
+ // Retrieve threshold value from the threshold marker
+ ValueMarker thresholdMarker = (ValueMarker) plot.getRangeMarkers(Layer.FOREGROUND).iterator().next();
+ double threshold = thresholdMarker.getValue();
+
+ // Call the nextPeak method to find the next peak and update the chart
+ float peakIndex = nextPeak(index, values, threshold);
+ if (peakIndex != -1) {
+ System.out.println("Next peak is at index: " + peakIndex);
+ marker.setValue(peakIndex);
+ float y = values.get(Math.round(peakIndex));
+ marker.setLabel(String.format("Value: %.2f, Derivative: %.2f", y, 0.0f));
+ }
+ } else {
+ super.actionPerformed(e);
+ }
+ }
+}