1 package com.github.celldynamics.quimp.plugin.binaryseg;
2
3 import java.awt.event.ActionEvent;
4 import java.awt.event.ActionListener;
5 import java.awt.event.ItemEvent;
6 import java.awt.event.ItemListener;
7 import java.io.FileNotFoundException;
8 import java.nio.file.Path;
9 import java.nio.file.Paths;
10 import java.util.ArrayList;
11 import java.util.List;
12
13 import org.slf4j.Logger;
14 import org.slf4j.LoggerFactory;
15
16 import com.github.celldynamics.quimp.BOAState;
17 import com.github.celldynamics.quimp.BOA_;
18 import com.github.celldynamics.quimp.CellStatsEval;
19 import com.github.celldynamics.quimp.Constrictor;
20 import com.github.celldynamics.quimp.Nest;
21 import com.github.celldynamics.quimp.QuimP;
22 import com.github.celldynamics.quimp.QuimpException;
23 import com.github.celldynamics.quimp.QuimpException.MessageSinkTypes;
24 import com.github.celldynamics.quimp.Serializer;
25 import com.github.celldynamics.quimp.SnakeHandler;
26 import com.github.celldynamics.quimp.ViewUpdater;
27 import com.github.celldynamics.quimp.filesystem.DataContainer;
28 import com.github.celldynamics.quimp.filesystem.FileExtensions;
29 import com.github.celldynamics.quimp.filesystem.StatsCollection;
30 import com.github.celldynamics.quimp.geom.SegmentedShapeRoi;
31 import com.github.celldynamics.quimp.plugin.AbstractOptionsParser;
32 import com.github.celldynamics.quimp.plugin.AbstractPluginOptions;
33 import com.github.celldynamics.quimp.plugin.AbstractPluginTemplate;
34 import com.github.celldynamics.quimp.plugin.IQuimpPluginAttachImagePlus;
35 import com.github.celldynamics.quimp.plugin.IQuimpPluginAttachNest;
36 import com.github.celldynamics.quimp.plugin.IQuimpPluginExchangeData;
37 import com.github.celldynamics.quimp.plugin.IQuimpPluginSynchro;
38 import com.github.celldynamics.quimp.plugin.ParamList;
39 import com.github.celldynamics.quimp.plugin.QuimpPluginException;
40 import com.github.celldynamics.quimp.utils.QuimpToolsCollection;
41
42 import ij.IJ;
43 import ij.ImagePlus;
44 import ij.WindowManager;
45 import ij.io.FileInfo;
46 import ij.io.OpenDialog;
47 import ij.io.SaveDialog;
48 import ij.process.ImageProcessor;
49
50
51
52
53
54
55
56
57
58
59
60
61
62 public class BinarySegmentation_ extends AbstractPluginTemplate implements IQuimpPluginSynchro,
63 IQuimpPluginAttachNest, IQuimpPluginExchangeData, IQuimpPluginAttachImagePlus {
64
65
66
67
68 static final Logger LOGGER = LoggerFactory.getLogger(BinarySegmentation_.class.getName());
69
70 private static String thisPluginName = "Generate Qconf";
71
72 private Nest nest = null;
73 private ViewUpdater vu = null;
74 private BinarySegmentationViewn/binaryseg/BinarySegmentationView.html#BinarySegmentationView">BinarySegmentationView bsp = new BinarySegmentationView();
75 private boolean wasNest = false;
76
77 private ImagePlus ip = null;
78
79
80
81
82 public BinarySegmentation_() {
83 super(new BinarySegmentationOptions(), thisPluginName);
84 BinarySegmentationOptions/com/github/celldynamics/quimp/plugin/binaryseg/BinarySegmentationOptions.html#BinarySegmentationOptions">BinarySegmentationOptions opts = (BinarySegmentationOptions) options;
85 bsp.addApplyListener(new ActionListener() {
86
87
88
89
90
91
92
93
94 @Override
95 public void actionPerformed(ActionEvent e) {
96 BinarySegmentationOptions/com/github/celldynamics/quimp/plugin/binaryseg/BinarySegmentationOptions.html#BinarySegmentationOptions">BinarySegmentationOptions opts = (BinarySegmentationOptions) options;
97
98 opts.options = bsp.getValues();
99 try {
100 runPlugin();
101 publishMacroString(thisPluginName);
102 } catch (QuimpException qe) {
103 qe.setMessageSinkType(errorSink);
104 qe.handleException(IJ.getInstance(), BinarySegmentation_.class.getSimpleName());
105 } catch (Exception ee) {
106 logger.debug(ee.getMessage(), ee);
107 logger.error("Problem with running plugin: " + ee.getMessage());
108 }
109 }
110 });
111
112 bsp.addLoadMaskListener(new ActionListener() {
113
114
115
116
117
118
119
120
121 @Override
122 public void actionPerformed(ActionEvent e) {
123 opts.paramFile = "";
124 OpenDialog od = new OpenDialog("Load mask file", "");
125 if (od.getPath() != null) {
126 opts.maskFileName = od.getPath();
127 }
128 }
129 });
130
131 bsp.addSelectImageListener(new ItemListener() {
132
133 @Override
134 public void itemStateChanged(ItemEvent e) {
135 if (e.getStateChange() == ItemEvent.ITEM_STATE_CHANGED) {
136 opts.paramFile = "";
137 }
138 }
139 });
140
141 opts.options = bsp.getValues();
142 }
143
144
145
146
147
148
149
150
151
152 public BinarySegmentation_(AbstractPluginOptions options) {
153 super(options, thisPluginName);
154 apiCall = true;
155 errorSink = MessageSinkTypes.CONSOLE;
156 }
157
158
159
160
161
162
163 @Override
164 protected void runPlugin() throws QuimpPluginException {
165 bsp.setValues(((BinarySegmentationOptions) options).options);
166 DataContainer dt = null;
167 BinarySegmentationOptions/com/github/celldynamics/quimp/plugin/binaryseg/BinarySegmentationOptions.html#BinarySegmentationOptions">BinarySegmentationOptions opts = (BinarySegmentationOptions) options;
168 LOGGER.debug(opts.toString());
169
170 String selectedImage = opts.options.get(BinarySegmentationView.SELECT_MASK);
171 String selectedOriginalImage = opts.options.get(BinarySegmentationView.SELECT_ORIGINAL_IMAGE);
172
173 ImagePlus maskFile = null;
174 ImagePlus orgFile = null;
175 Path orgFilePath = null;
176 if (selectedImage != null && !selectedImage.equals(BOA_.NONE)) {
177 maskFile = WindowManager.getImage(selectedImage);
178 } else {
179 if (opts.maskFileName != null && !opts.maskFileName.isEmpty()) {
180 maskFile = IJ.openImage(opts.maskFileName);
181 }
182 }
183 if (selectedOriginalImage != null && !selectedOriginalImage.equals(BOA_.NONE)) {
184 orgFile = WindowManager.getImage(selectedOriginalImage);
185 if (orgFile != null) {
186 FileInfo orgfileinfo = orgFile.getFileInfo();
187 orgFilePath = Paths.get(orgfileinfo.directory, orgFile.getTitle());
188 } else {
189 orgFile = IJ.openImage(selectedOriginalImage);
190 orgFilePath = Paths.get(selectedOriginalImage);
191 }
192 } else {
193 orgFilePath = Paths.get("");
194 }
195 if (maskFile == null) {
196 throw new QuimpPluginException("Mask can not be loaded or found.");
197 }
198
199 FileInfo maskfileinfo = maskFile.getFileInfo();
200
201
202 if (wasNest == false) {
203 nest = new Nest();
204
205
206 BOA_.qState = new BOAState(maskFile);
207 dt = new DataContainer();
208 dt.BOAState = BOA_.qState;
209 dt.BOAState.nest = nest;
210 dt.BOAState.binarySegmentationPlugin = this;
211 dt.Stats = new StatsCollection();
212
213
214 if (orgFile == null) {
215 throw new QuimpPluginException(
216 "Original image " + orgFilePath.toString() + " can not be opened");
217 }
218 dt.BOAState.boap.setOrgFile(orgFilePath.toFile());
219 dt.BOAState.boap.setOutputFileCore(opts.paramFile);
220
221 }
222 LOGGER.debug("Segmentation: " + (maskFile != null ? maskFile.toString() : "null") + "params: "
223 + opts.toString());
224 BinarySegmentationlugin/binaryseg/BinarySegmentation.html#BinarySegmentation">BinarySegmentation obj = new BinarySegmentation(maskFile);
225 obj.trackObjects();
226 ArrayList<ArrayList<SegmentedShapeRoi>> ret = obj.getChains();
227
228
229 boolean smoothing = opts.options.getBooleanValue(BinarySegmentationView.SMOOTHING2);
230 int step = opts.options.getIntValue(BinarySegmentationView.STEP2);
231 LOGGER.debug("step: " + step + " smooth: " + smoothing);
232 for (ArrayList<SegmentedShapeRoi> asS : ret) {
233 for (SegmentedShapeRoi ss : asS) {
234 ss.setInterpolationParameters(step, smoothing);
235 }
236 }
237 if (opts.options.getBooleanValue(BinarySegmentationView.CLEAR_NEST)) {
238 nest.cleanNest();
239 }
240 nest.addHandlers(ret);
241
242
243 if (ip == null) {
244 ip = maskFile;
245 }
246 if (opts.options.getBooleanValue(BinarySegmentationView.RESTORE_SNAKE)) {
247 Constrictornstrictor.html#Constrictor">Constrictor constrictor = new Constrictor();
248 for (SnakeHandler sh : nest.getHandlers()) {
249 for (int f = sh.getStartFrame(); f <= sh.getEndFrame(); f++) {
250 sh.getBackupSnake(f).calcCentroid();
251 sh.getBackupSnake(f).setPositions();
252 sh.getBackupSnake(f).updateNormals(true);
253 sh.getBackupSnake(f).getBounds();
254
255 sh.getStoredSnake(f).calcCentroid();
256 sh.getStoredSnake(f).setPositions();
257 sh.getStoredSnake(f).updateNormals(true);
258 sh.getStoredSnake(f).getBounds();
259
260 constrictor.constrict(sh.getStoredSnake(f), ip.getStack().getProcessor(f));
261 constrictor.constrict(sh.getBackupSnake(f), ip.getStack().getProcessor(f));
262 }
263 sh.getLiveSnake().calcCentroid();
264 sh.getLiveSnake().setPositions();
265 sh.getLiveSnake().updateNormals(true);
266 sh.getLiveSnake().getBounds();
267 constrictor.constrict(sh.getLiveSnake(), ip.getStack().getProcessor(sh.getStartFrame()));
268 }
269 }
270 if (vu != null) {
271 vu.updateView();
272 }
273
274 Serializer<DataContainer> n = new Serializer<>(dt, QuimP.TOOL_VERSION);
275 n.setPretty();
276 if (wasNest == false && vu == null) {
277
278 List<CellStatsEval> retstat = nest.analyse(orgFile, true);
279 dt.Stats.copyFromCellStat(retstat);
280
281 if (opts.paramFile == null || opts.paramFile.isEmpty()) {
282 String folder = maskfileinfo.directory;
283 if (folder == null || folder.isEmpty()) {
284 folder = IJ.getDirectory("current");
285 }
286 String name = QuimpToolsCollection.removeExtension(maskFile.getTitle());
287 SaveDialog sd = new SaveDialog("Save QCONF", folder, name, FileExtensions.newConfigFileExt);
288 String selPath = sd.getDirectory();
289 String selName = sd.getFileName();
290 if (selPath != null && selName != null && !selPath.isEmpty() && !selName.isEmpty()) {
291 opts.paramFile = Paths.get(selPath, selName).toString();
292 dt.BOAState.boap.setOutputFileCore(opts.paramFile);
293 }
294 }
295
296 try {
297 n.save(opts.paramFile);
298 } catch (FileNotFoundException e) {
299 throw new QuimpPluginException(e);
300 }
301
302 }
303 }
304
305
306
307
308
309
310 public boolean isWindowVisible() {
311 return bsp.isWindowVisible();
312 }
313
314
315
316
317
318
319
320
321 @Override
322 public void attachNest(Nest data) {
323 this.nest = data;
324 wasNest = true;
325 }
326
327
328
329
330
331
332
333
334 @Override
335 public void attachContext(ViewUpdater b) {
336 vu = b;
337 }
338
339
340
341
342
343
344 @Override
345 public void showUi(boolean val) {
346 bsp.setValues(((BinarySegmentationOptions) options).options);
347 bsp.showWindow(val);
348
349 }
350
351
352
353
354
355
356 @Override
357 public ParamList getPluginConfig() {
358 BinarySegmentationOptions/com/github/celldynamics/quimp/plugin/binaryseg/BinarySegmentationOptions.html#BinarySegmentationOptions">BinarySegmentationOptions opts = (BinarySegmentationOptions) options;
359 ParamList tmp = bsp.getValues();
360 if (opts.maskFileName != null) {
361 tmp.put(BinarySegmentationView.LOADED_FILE, opts.maskFileName);
362 }
363 return tmp;
364 }
365
366
367
368
369
370
371 @Override
372 public void setPluginConfig(ParamList par) throws QuimpPluginException {
373 bsp.setValues(par);
374 }
375
376
377
378
379
380
381
382 @Override
383 public void attachImage(ImageProcessor img) {
384 ip = new ImagePlus("", img);
385
386 }
387
388
389
390
391
392
393
394 @Override
395 public void attachImagePlus(ImagePlus img) {
396 ip = img;
397 }
398
399
400
401
402
403
404 @Override
405 public String about() {
406 return "Binary segmentation.\n" + "Author: Piotr Baniukiewicz\n"
407 + "mail: p.baniukiewicz@warwick.ac.uk";
408 }
409 }