Skip to content

Commit 4a48f80

Browse files
authored
Bugfix and GUI refactoring
2 parents 1f992b2 + b614574 commit 4a48f80

42 files changed

Lines changed: 820 additions & 1220 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/main/java/fr/igred/nucleus/autocrop/AutoCrop.java

Lines changed: 2 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
import java.util.TreeMap;
6060
import java.util.concurrent.ExecutionException;
6161

62+
import static fr.igred.nucleus.utils.Thresholding.binarize;
6263
import static fr.igred.nucleus.utils.Thresholding.contrastAnd8bits;
6364

6465

@@ -270,7 +271,7 @@ public void thresholdKernels(String typeThresholding) {
270271
}
271272
}
272273
this.otsuThreshold = thresh;
273-
this.imageSeg = generateSegmentedImage(imageSeg, thresh);
274+
binarize(imageSeg, thresh);
274275
}
275276

276277

@@ -566,34 +567,6 @@ public List<String> getFileCoordinates() {
566567
}
567568

568569

569-
/**
570-
* Create binary image with the threshold value gave in input
571-
*
572-
* @param imagePlusInput ImagePlus raw image to binarize
573-
* @param threshold integer threshold value
574-
*
575-
* @return The segmented binary image.
576-
*/
577-
private static ImagePlus generateSegmentedImage(ImagePlus imagePlusInput, int threshold) {
578-
ImageStack imageStackInput = imagePlusInput.getStack();
579-
ImagePlus imagePlusSegmented = imagePlusInput.duplicate();
580-
ImageStack imageStackSegmented = imagePlusSegmented.getStack();
581-
for (int k = 0; k < imagePlusInput.getStackSize(); ++k) {
582-
for (int i = 0; i < imagePlusInput.getWidth(); ++i) {
583-
for (int j = 0; j < imagePlusInput.getHeight(); ++j) {
584-
double voxelValue = imageStackInput.getVoxel(i, j, k);
585-
if (voxelValue >= threshold) {
586-
imageStackSegmented.setVoxel(i, j, k, 255);
587-
} else {
588-
imageStackSegmented.setVoxel(i, j, k, 0);
589-
}
590-
}
591-
}
592-
}
593-
return imagePlusSegmented;
594-
}
595-
596-
597570
/**
598571
* Crop of the bounding box on 3D image. The coordinates are inputs of this methods
599572
*

src/main/java/fr/igred/nucleus/autocrop/Box.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,7 @@ public class Box {
4949
* @param zMin: coordinate z min of the Box
5050
* @param zMax: coordinate z max of the Box
5151
*/
52-
public Box(short xMin, short xMax, short yMin, short yMax, short zMin,
53-
short zMax) {
52+
public Box(short xMin, short xMax, short yMin, short yMax, short zMin, short zMax) {
5453
this.xMin = xMin;
5554
this.xMax = xMax;
5655
this.yMin = yMin;

src/main/java/fr/igred/nucleus/autocrop/RectangleIntersection.java

Lines changed: 25 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public class RectangleIntersection {
7070
* Constructor getting list of boxes computed in autocrop class. Initialisation of a list of 2D rectangles and a
7171
* list of Z stack associated (zMin-zMax).
7272
*
73-
* @param boxes List of boxes
73+
* @param boxes List of boxes
7474
* @param params Autocrop parameters
7575
*/
7676
public RectangleIntersection(Map<Double, Box> boxes, AutocropParameters params) {
@@ -114,12 +114,13 @@ public static double percentOf2Rectangles(Rectangle2D r1, Rectangle2D r2) {
114114
*/
115115
public void runRectangleRecompilation() {
116116
this.newBoxesAdded = true;
117-
int tours = 0;
117+
int i = 0;
118118
while (newBoxesAdded) {
119-
tours++;
120119
computeIntersection();
121120
rectangleRegroup();
122121
recompileRectangle();
122+
i++;
123+
LOGGER.trace("Iteration {}: {} boxes detected", i, listRectangle.size());
123124
}
124125
}
125126

@@ -133,9 +134,7 @@ public void computeIntersection() {
133134
if (i != y &&
134135
!rectangleIntersect.contains(i + "-" + y) &&
135136
!rectangleIntersect.contains(y + "-" + i)) {
136-
137137
if (listRectangle.get(i).intersects(listRectangle.get(y))) {
138-
139138
if (percentOf2Rectangles(listRectangle.get(i), listRectangle.get(y)) >
140139
autocropParameters.getBoxesSurfacePercent() ||
141140
percentOf2Rectangles(listRectangle.get(y), listRectangle.get(i)) >
@@ -211,28 +210,28 @@ public void recompileRectangle() {
211210
List<Rectangle> rectanglesToRemove = new ArrayList<>();
212211
for (String value : finalListRectangle) {
213212
String[] splitList2 = value.split("-");
214-
double xMixNewRectangle = 0;
215-
double yMinNewRectangle = 0;
216-
double maxWidth = 0;
217-
double maxHeight = 0;
213+
int xMixNewRectangle = 0;
214+
int yMinNewRectangle = 0;
215+
int maxWidth = 0;
216+
int maxHeight = 0;
218217
int minZSlice = 0;
219218
int maxZSlice = 0;
220219
if (splitList2.length > 1) {
221220
for (String s : splitList2) {
222221
int tmp = Integer.parseInt(s);
223222
if (listRectangle.get(tmp).getX() < xMixNewRectangle || xMixNewRectangle == 0) {
224-
xMixNewRectangle = listRectangle.get(tmp).getX();
223+
xMixNewRectangle = listRectangle.get(tmp).x;
225224
}
226225
if (listRectangle.get(tmp).getY() < yMinNewRectangle || yMinNewRectangle == 0) {
227-
yMinNewRectangle = listRectangle.get(tmp).getY();
226+
yMinNewRectangle = listRectangle.get(tmp).y;
228227
}
229228
if (listRectangle.get(tmp).getX() + listRectangle.get(tmp).getWidth() > maxWidth ||
230229
maxWidth == 0) {
231-
maxWidth = listRectangle.get(tmp).getX() + listRectangle.get(tmp).getWidth();
230+
maxWidth = listRectangle.get(tmp).x + listRectangle.get(tmp).width;
232231
}
233232
if (listRectangle.get(tmp).getY() + listRectangle.get(tmp).getHeight() > maxHeight ||
234233
maxHeight == 0) {
235-
maxHeight = listRectangle.get(tmp).getY() + listRectangle.get(tmp).getHeight();
234+
maxHeight = listRectangle.get(tmp).y + listRectangle.get(tmp).height;
236235
}
237236

238237
String[] zSliceTMP = zSlices.get(tmp).split("-");
@@ -242,20 +241,14 @@ public void recompileRectangle() {
242241
if (Integer.parseInt(zSliceTMP[0] + Integer.valueOf(zSliceTMP[1])) > maxZSlice || maxZSlice == 0) {
243242
maxZSlice = Integer.parseInt(zSliceTMP[0]) + Integer.parseInt(zSliceTMP[1]);
244243
}
245-
rectanglesToRemove.add(new Rectangle((int) listRectangle.get(tmp).getX(),
246-
(int) listRectangle.get(tmp).getY(),
247-
(int) listRectangle.get(tmp).getWidth(),
248-
(int) listRectangle.get(tmp).getHeight()));
244+
rectanglesToRemove.add(new Rectangle(listRectangle.get(tmp)));
249245
}
250246

251247
maxZSlice -= minZSlice;
252248
rectangleZSliceToAdd.add(minZSlice + "-" + maxZSlice);
253-
maxWidth = (int) maxWidth - (int) xMixNewRectangle;
254-
maxHeight = (int) maxHeight - (int) yMinNewRectangle;
255-
rectanglesToAdd.add(new Rectangle((int) xMixNewRectangle,
256-
(int) yMinNewRectangle,
257-
(int) maxWidth,
258-
(int) maxHeight));
249+
maxWidth -= xMixNewRectangle;
250+
maxHeight -= yMinNewRectangle;
251+
rectanglesToAdd.add(new Rectangle(xMixNewRectangle, yMinNewRectangle, maxWidth, maxHeight));
259252
}
260253
}
261254
LOGGER.debug("{} boxes will be merged in {} new boxes",
@@ -287,18 +280,16 @@ public Map<Double, Box> getNewBoxes() {
287280

288281
for (int i = 0; i < listRectangle.size(); i++) {
289282
String[] zSliceTMP = zSlices.get(i).split("-");
290-
short tmpXMax = (short) (listRectangle.get(i).getX() + listRectangle.get(i).getWidth());
291-
short tmpYMax = (short) (listRectangle.get(i).getY() + listRectangle.get(i).getHeight());
292-
short tmpZMax = (short) (Short.parseShort(zSliceTMP[0]) + Short.parseShort(zSliceTMP[1]));
293-
if (tmpZMax == 0) {
294-
tmpZMax = 1;
283+
short xMin = (short) listRectangle.get(i).x;
284+
short yMin = (short) listRectangle.get(i).y;
285+
short zMin = Short.parseShort(zSliceTMP[0]);
286+
short xMax = (short) (xMin + listRectangle.get(i).width);
287+
short yMax = (short) (yMin + listRectangle.get(i).height);
288+
short zMax = (short) (zMin + Short.parseShort(zSliceTMP[1]));
289+
if (zMax == 0) {
290+
zMax = 1;
295291
}
296-
Box box = new Box((short) listRectangle.get(i).getX(),
297-
tmpXMax,
298-
(short) listRectangle.get(i).getY(),
299-
tmpYMax,
300-
Short.parseShort(zSliceTMP[0]),
301-
tmpZMax);
292+
Box box = new Box(xMin, xMax, yMin, yMax, zMin, zMax);
302293
boxes.put((double) i, box);
303294
}
304295
return boxes;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,20 @@
1+
/*
2+
* NucleusJ
3+
* Copyright (C) 2025 iGReD
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
119
/** This package contains classes and interfaces for the AutoCrop feature in the Nucleus plugin. */
220
package fr.igred.nucleus.autocrop;

src/main/java/fr/igred/nucleus/cli/CLIRunAction.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ private void runSegCC() {
127127
params.getInputFolder(),
128128
params.getSegmentedInputFolder(),
129129
params.getOutputFolder());
130-
ccCalling.runSeveralImages2();
130+
ccCalling.runSeveralImages();
131131
} catch (IOException | FormatException e) {
132132
LOGGER.error("An error occurred during chromocenter segmentation.", e);
133133
}

src/main/java/fr/igred/nucleus/cli/package-info.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
/*
2+
* NucleusJ
3+
* Copyright (C) 2025 iGReD
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
119
/**
220
* Package containing classes for command line interface (CLI) actions and options for NucleusJ. This package provides
321
* functionality to run various actions such as autocrop, segmentation, and compute parameters through command line
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,20 @@
1+
/*
2+
* NucleusJ
3+
* Copyright (C) 2025 iGReD
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
119
/** This package contains classes for analyses. */
220
package fr.igred.nucleus.core;

src/main/java/fr/igred/nucleus/dialogs/AutocropConfigDialog.java

Lines changed: 17 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -31,30 +31,28 @@
3131
import java.awt.GridBagConstraints;
3232
import java.awt.GridBagLayout;
3333
import java.awt.Insets;
34-
import java.awt.event.ActionEvent;
35-
import java.awt.event.ActionListener;
3634
import java.awt.event.ItemEvent;
3735
import java.awt.event.ItemListener;
3836

3937

4038
public class AutocropConfigDialog extends JFrame implements ItemListener {
41-
private final JTextField xCropBoxSize = new JTextField();
42-
private final JTextField yCropBoxSize = new JTextField();
43-
private final JTextField zCropBoxSize = new JTextField();
44-
private final JTextField boxNumberFontSize = new JTextField();
45-
private final JTextField xCalibration = new JTextField();
46-
private final JTextField yCalibration = new JTextField();
47-
private final JTextField zCalibration = new JTextField();
48-
private final JTextField minVolume = new JTextField();
49-
private final JTextField maxVolume = new JTextField();
50-
private final JTextField thresholdOTSUComputing = new JTextField();
51-
private final JTextField channelToComputeThreshold = new JTextField();
52-
private final JTextField slicesOTSUComputing = new JTextField();
53-
private final JTextField boxesSurfacePercent = new JTextField();
54-
private final JCheckBox regroupBoxes = new JCheckBox();
55-
private final JCheckBox addCalibrationBox = new JCheckBox();
39+
private final JTextField xCropBoxSize = new JTextField();
40+
private final JTextField yCropBoxSize = new JTextField();
41+
private final JTextField zCropBoxSize = new JTextField();
42+
private final JTextField boxNumberFontSize = new JTextField();
43+
private final JTextField xCalibration = new JTextField();
44+
private final JTextField yCalibration = new JTextField();
45+
private final JTextField zCalibration = new JTextField();
46+
private final JTextField minVolume = new JTextField();
47+
private final JTextField maxVolume = new JTextField();
48+
private final JTextField thresholdOTSUComputing = new JTextField();
49+
private final JTextField channelToComputeThreshold = new JTextField();
50+
private final JTextField slicesOTSUComputing = new JTextField();
51+
private final JTextField boxesSurfacePercent = new JTextField();
52+
private final JCheckBox regroupBoxes = new JCheckBox();
53+
private final JCheckBox addCalibrationBox = new JCheckBox();
5654
private final JPanel cropBoxPane;
57-
private Boolean isRegroupBoxesSelected = true;
55+
private Boolean isRegroupBoxesSelected = true;
5856
private JPanel xCalibrationPanel;
5957
private JPanel yCalibrationPanel;
6058
private JPanel zCalibrationPanel;
@@ -266,8 +264,7 @@ public AutocropConfigDialog() {
266264

267265
super.setVisible(false);
268266

269-
ActionListener startListener = new StartListener(this);
270-
buttonOK.addActionListener(startListener);
267+
buttonOK.addActionListener(e -> setVisible(false));
271268
}
272269

273270

@@ -399,21 +396,4 @@ public void itemStateChanged(ItemEvent e) {
399396
repaint();
400397
}
401398

402-
403-
private static class StartListener implements ActionListener {
404-
AutocropConfigDialog autocropDialog;
405-
406-
407-
/** @param autocropDialog */
408-
StartListener(AutocropConfigDialog autocropDialog) {
409-
this.autocropDialog = autocropDialog;
410-
}
411-
412-
413-
public void actionPerformed(ActionEvent actionEvent) {
414-
autocropDialog.setVisible(false);
415-
}
416-
417-
}
418-
419399
}

0 commit comments

Comments
 (0)