1 package com.github.celldynamics.quimp;
2
3 import java.io.FileWriter;
4 import java.io.PrintWriter;
5
6 import com.github.celldynamics.quimp.geom.ExtendedVector2d;
7
8 import ij.process.ImageProcessor;
9
10
11
12
13
14
15
16
17 public class Constrictor {
18
19
20
21
22 public Constrictor() {
23 }
24
25
26
27
28
29
30
31
32
33
34
35
36 public boolean constrict(final Snake snake, final ImageProcessor ip) {
37
38 ExtendedVector2d tempF;
39 ExtendedVector2dtendedVector2d.html#ExtendedVector2d">ExtendedVector2d tempV = new ExtendedVector2d();
40
41 Node n = snake.getHead();
42 do {
43
44 if (!n.isFrozen()) {
45
46
47 tempV.setX(n.getNormal().getX() * BOA_.qState.segParam.f_central);
48 tempV.setY(n.getNormal().getY() * BOA_.qState.segParam.f_central);
49 n.setF_total(tempV);
50
51
52 tempF = contractionForce(n);
53 tempV.setX(tempF.getX() * BOA_.qState.segParam.f_contract);
54 tempV.setY(tempF.getY() * BOA_.qState.segParam.f_contract);
55 n.addF_total(tempV);
56
57
58 tempF = imageForce(n, ip);
59 tempV.setX(tempF.getX() * BOA_.qState.segParam.f_image);
60
61 tempV.setY(tempF.getY() * BOA_.qState.segParam.f_image);
62
63 n.addF_total(tempV);
64
65
66 tempV.setX(BOA_.qState.boap.delta_t * n.getF_total().getX());
67 tempV.setY(BOA_.qState.boap.delta_t * n.getF_total().getY());
68 n.addVel(tempV);
69
70
71 tempV.setX(BOA_.qState.boap.delta_t * n.getVel().getX());
72 tempV.setY(BOA_.qState.boap.delta_t * n.getVel().getY());
73 n.setPrelim(tempV);
74
75
76
77
78
79
80
81
82
83
84
85 n.getVel().multiply(BOA_.qState.boap.f_friction);
86
87
88 if (n.getVel().length() < BOA_.qState.segParam.vel_crit) {
89 snake.freezeNode(n);
90 }
91 }
92 n = n.getNext();
93 } while (!n.isHead());
94
95
96 n = snake.getHead();
97 do {
98 n.update();
99 n = n.getNext();
100 } while (!n.isHead());
101
102 snake.updateNormals(BOA_.qState.segParam.expandSnake);
103
104 return snake.isFrozen();
105 }
106
107
108
109
110
111
112
113
114
115 public boolean constrictWrite(final Snake snake, final ImageProcessor ip) {
116
117 try {
118 PrintWriter pw = new PrintWriter(
119 new FileWriter("/Users/rtyson/Documents/phd/tmp/test/forcesWrite/forces.txt"), true);
120 ExtendedVector2d tempF;
121 ExtendedVector2dtendedVector2d.html#ExtendedVector2d">ExtendedVector2d tempV = new ExtendedVector2d();
122
123 Node n = snake.getHead();
124 do {
125
126
127
128
129 tempV.setX(n.getNormal().getX() * BOA_.qState.segParam.f_central);
130 tempV.setY(n.getNormal().getY() * BOA_.qState.segParam.f_central);
131 pw.print("\n" + n.getTrackNum() + "," + tempV.length() + ",");
132 n.setF_total(tempV);
133
134
135 tempF = contractionForce(n);
136 if (n.getCurvatureLocal() > 0) {
137 pw.print(tempF.length() + ",");
138 } else {
139 pw.print((tempF.length() * -1) + ",");
140 }
141 tempV.setX(tempF.getX() * BOA_.qState.segParam.f_contract);
142 tempV.setY(tempF.getY() * BOA_.qState.segParam.f_contract);
143 n.addF_total(tempV);
144
145
146 tempF = imageForce(n, ip);
147 pw.print((tempF.length() * -1) + ",");
148 tempV.setX(tempF.getX() * BOA_.qState.segParam.f_image);
149
150 tempV.setY(tempF.getY() * BOA_.qState.segParam.f_image);
151
152 n.addF_total(tempV);
153 pw.print(n.getF_total().length() + "");
154
155
156 tempV.setX(BOA_.qState.boap.delta_t * n.getF_total().getX());
157 tempV.setY(BOA_.qState.boap.delta_t * n.getF_total().getY());
158 n.addVel(tempV);
159
160
161 n.getVel().multiply(BOA_.qState.boap.f_friction);
162
163
164 tempV.setX(BOA_.qState.boap.delta_t * n.getVel().getX());
165 tempV.setY(BOA_.qState.boap.delta_t * n.getVel().getY());
166 n.setPrelim(tempV);
167
168
169 if (n.getVel().length() < BOA_.qState.segParam.vel_crit) {
170 snake.freezeNode(n);
171 }
172
173 n = n.getNext();
174 } while (!n.isHead());
175
176
177 n = snake.getHead();
178 do {
179 n.update();
180 n = n.getNext();
181 } while (!n.isHead());
182
183 snake.updateNormals(BOA_.qState.segParam.expandSnake);
184
185 pw.close();
186 return snake.isFrozen();
187 } catch (Exception e) {
188 return false;
189 }
190 }
191
192
193
194
195
196
197
198 ExtendedVector2d contractionForce(final Node n) {
199
200 ExtendedVector2d resultR;
201 ExtendedVector2d resultL;
202 ExtendedVector2dtendedVector2d.html#ExtendedVector2d">ExtendedVector2d force = new ExtendedVector2d();
203
204
205 resultL = ExtendedVector2d.unitVector(n.getPoint(), n.getPrev().getPoint());
206
207
208 resultR = ExtendedVector2d.unitVector(n.getPoint(), n.getNext().getPoint());
209
210 force.setX((resultR.getX() + resultL.getX()) * 0.5);
211 force.setY((resultR.getY() + resultL.getY()) * 0.5);
212
213 return (force);
214 }
215
216
217
218
219
220
221
222
223 ExtendedVector2d imageForce(final Node n, final ImageProcessor ip) {
224 ExtendedVector2dendedVector2d.html#ExtendedVector2d">ExtendedVector2d result = new ExtendedVector2d();
225 ExtendedVector2d tan = n.getTangent();
226 int i;
227 int j;
228
229 double a = 0.75;
230 double deltaI;
231 double x;
232 double y;
233 double xt;
234 double yt;
235 int insideI = 0;
236 int outsideI = 0;
237 int inI = 0;
238 int outI = 0;
239
240
241
242 for (i = 0; i <= 1. / a * BOA_.qState.segParam.sample_tan; i++) {
243
244 xt = n.getPoint().getX() + (a * i - BOA_.qState.segParam.sample_tan / 2) * tan.getX();
245 yt = n.getPoint().getY() + (a * i - BOA_.qState.segParam.sample_tan / 2) * tan.getY();
246
247 for (j = 0; j <= 1. / a * BOA_.qState.segParam.sample_norm / 2; ++j) {
248 x = xt + a * j * n.getNormal().getX();
249 y = yt + a * j * n.getNormal().getY();
250
251 insideI += ip.getPixel((int) x, (int) y);
252 inI++;
253
254 x = xt - a * j * n.getNormal().getX();
255 y = yt - a * j * n.getNormal().getY();
256
257 outsideI += ip.getPixel((int) x, (int) y);
258 outI++;
259 }
260 }
261
262 deltaI = ((double) insideI / inI - (double) outsideI / outI) / 255.;
263 if (deltaI > 0.) {
264 result.setX(-Math.sqrt(deltaI) * n.getNormal().getX());
265 result.setY(-Math.sqrt(deltaI) * n.getNormal().getY());
266 }
267
268 return (result);
269 }
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289 public void loosen(final Nest nest, int frame) throws BoaException {
290 int nestSize = nest.size();
291 Snake snakeA;
292 Snake snakeB;
293
294 double[][] prox = computeProxMatrix(nest);
295
296 double stepSize = 0.1 * Math.signum(BOA_.qState.segParam.blowup);
297 double steps = (double) BOA_.qState.segParam.blowup / stepSize;
298
299 for (int i = 0; i < steps; i++) {
300
301
302 for (int si = 0; si < nestSize; si++) {
303
304
305
306 snakeA = nest.getHandler(si).getLiveSnake();
307 if (!snakeA.alive || frame < nest.getHandler(si).getStartFrame()) {
308 continue;
309 }
310 for (int sj = si + 1; sj < nestSize; sj++) {
311 snakeB = nest.getHandler(sj).getLiveSnake();
312 if (!snakeB.alive || frame < nest.getHandler(si).getStartFrame()) {
313 continue;
314 }
315
316
317 if (prox[si][sj] > BOA_.qState.boap.proximity) {
318 continue;
319 }
320 freezeProx(snakeA, snakeB);
321 }
322
323 }
324
325
326
327 for (int s = 0; s < nestSize; s++) {
328
329
330
331 snakeA = nest.getHandler(s).getLiveSnake();
332 if (snakeA.alive && frame > nest.getHandler(s).getStartFrame()) {
333 snakeA.scaleSnake(stepSize, Math.abs(stepSize), true);
334 }
335 }
336
337 }
338 }
339
340
341
342
343
344
345
346
347 public void freezeProxSnakes(final Nest nest, int frame) throws BoaException {
348 int nestSize = nest.size();
349 Snake snakeA;
350 Snake snakeB;
351
352 double[][] prox = computeProxMatrix(nest);
353
354
355
356 for (int si = 0; si < nestSize; si++) {
357 snakeA = nest.getHandler(si).getLiveSnake();
358 if (!snakeA.alive || frame < nest.getHandler(si).getStartFrame()) {
359 continue;
360 }
361 for (int sj = si + 1; sj < nestSize; sj++) {
362 snakeB = nest.getHandler(sj).getLiveSnake();
363 if (!snakeB.alive || frame < nest.getHandler(si).getStartFrame()) {
364 continue;
365 }
366
367
368 if (prox[si][sj] > BOA_.qState.boap.proximity) {
369 continue;
370 }
371 freezeProx(snakeA, snakeB);
372 }
373
374 }
375 }
376
377
378
379
380
381
382
383 private double[][] computeProxMatrix(final Nest nest) {
384 int nestSize = nest.size();
385 Snake snakeA;
386 Snake snakeB;
387
388 double[][] prox = new double[nestSize][nestSize];
389 for (int si = 0; si < nestSize; si++) {
390 snakeA = nest.getHandler(si).getLiveSnake();
391 snakeA.calcCentroid();
392 for (int sj = si + 1; sj < nestSize; sj++) {
393 snakeB = nest.getHandler(sj).getLiveSnake();
394 snakeB.calcCentroid();
395 prox[si][sj] = ExtendedVector2d.lengthP2P(snakeA.getCentroid(), snakeB.getCentroid());
396 }
397 }
398 return prox;
399 }
400
401
402
403
404
405
406
407
408
409
410
411 private void freezeProx(final Snake/quimp/Snake.html#Snake">Snake a, final Snake b) {
412
413 Node bn;
414 Node an = a.getHead();
415 double prox;
416
417 do {
418 bn = b.getHead();
419 do {
420 if (an.isFrozen() && bn.isFrozen()) {
421
422 bn = bn.getNext();
423 continue;
424 }
425
426 prox = ExtendedVector2d.distPointToSegment(an.getPoint(), bn.getPoint(),
427 bn.getNext().getPoint());
428 if (prox < BOA_.qState.boap.proxFreeze) {
429 a.freezeNode(an);
430 b.freezeNode(bn);
431 b.freezeNode(bn.getNext());
432
433
434
435
436 break;
437 }
438 bn = bn.getNext();
439 } while (!bn.isHead());
440
441 an = an.getNext();
442 } while (!an.isHead());
443
444 }
445
446
447
448
449
450
451
452
453
454 public void implode(final Nest nest, int f) throws BoaException {
455
456 SnakeHandler snakeH;
457 Snake snake;
458 for (int s = 0; s < nest.size(); s++) {
459 snakeH = nest.getHandler(s);
460 if (nest.getHandler(s).isSnakeHandlerFrozen()) {
461 continue;
462 }
463 snake = snakeH.getLiveSnake();
464 if (snake.alive && f > snakeH.getStartFrame()) {
465 snake.implode();
466 }
467 }
468 }
469 }