-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdisplay_mask_3D.m
1655 lines (1456 loc) · 62.8 KB
/
display_mask_3D.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
function display_mask_3D(data, varargin)
%DISPLAY_MASK Overlays mask and displays it
%
% Inputs
% data: structure containing image and mask
% varargin: structure containing points and hull information
%
% Outputs
% None, will open a GUI to display images with overlayed masks.
%
% Overview
% Takes a data structure and opens a GUI for displaying images and
% creating overlays of the mask on the image, defined by field. The
% function can display an overlay for each entry in the structure.
% Set defaults
[i, channels, colors, ch, color, c, z, t, T, B, n, em_vis,...
im_vis, im_field, mask_field, im_type, im_ind, hull_vis,...
pts_vis] = set_defaults(data);
% Save image and mask
[im, mask] = set_image_and_mask(data, im_field, mask_field, i, n);
% Create a uifigure
fig_pos = [0, 0, 1200, 750];
f = uifigure('Name', 'Mask Viewer', 'NumberTitle', 'off',...
'Position', fig_pos, 'Visible', 'off');
set(f, 'doublebuffer', 'off');
movegui(f, 'center');
set(f, 'Visible', 'on');
% Create a grid layout with 5 rows and 6 columns. The first 4 rows
% should be the same size, and the last row should be big enough to fit
% the sliders
g1 = uigridlayout(f,[5, 6]);
g1.RowHeight = {'1x', '1x', '1x', '1x', 'fit'};
g1.ColumnWidth = {'2.25x', '1x', '1x', '1x', '1x', '2x'};
% Create a uiaxes to load the images into the uifigure
uiax = uiaxes(g1, 'XLim', [0 size(im, 2)], 'YLim', [0 size(im, 1)],...
'XTick', [], 'YTick', [],...
'XTickLabel', [], 'YTickLabel', []);
% Hide the axes so its an image display
uiax.XAxis.Visible = false;
uiax.YAxis.Visible = false;
% Set the axis so its in row 1 through 4 and column 2 through 5 of the
% grid layout
uiax.Layout.Row = [1, 4];
uiax.Layout.Column = [2, 5];
% Create a nested gridlayout with 11 rows and 4 columns for the buttons
g2 = uigridlayout(g1, [11, 4], 'Scrollable','on');
% Set the new gidlayout in the second and fourth row and first column
g2.Layout.Row = [2, 4];
g2.Layout.Column = 1;
% Set the first and last row, and first and last column to 1x so that
% the buttons are centered. Set the rest of the rows to fit so the
% label is readable. Set the width of the second column to a fixed 100
% so that it doesn't change.
g2.RowHeight = {'1x', 'fit', 'fit', 'fit', 'fit', 'fit', 'fit',...
'fit', 'fit', 'fit', '1x'};
g2.ColumnWidth = {'1x', 125, 100, '1x'};
% Create a nested gridlayout with 3 rows and 5 columns for the sliders
g3 = uigridlayout(g1,[3, 5]);
% Set the new gidlayout in the fifth row and first through sixth column
g3.Layout.Row = 5;
g3.Layout.Column = [1 6];
% Set all the row heights to fit so that the sliders fit, and set the
% width of the label column as well as the width of the <> buttons
% column, but allow the slider column to fill remaining column width
g3.RowHeight = {'fit', 'fit', 'fit'};
g3.ColumnWidth = {75, '1x', 40, 40, 40};
% Initialize the figure with the first image
[em_h, im_h, hull_h, p_h] = display_image(uiax, z, t, im, mask, ch,...
c, B, T, data, i, em_vis, im_vis, n, color, hull_vis, pts_vis,...
varargin{:});
% If image is a z-stack
if size(im,3) > 1
% Create a text label for the z slider
uilabel(g3, 'Text', 'z slice', 'HorizontalAlignment', 'right');
% Create a slider for controlling which z plane to display, also
% set the limits and tick marks
sld_z = uislider(g3,...
'Limits', [1, size(im,3)],...
'MajorTicks', 1:size(im,3),...
'MinorTicks', [],...
'ValueChangingFcn',...
@(sld,event) update_z(sld, event),...
'ValueChangedFcn',...
@(sld,event) update_z_pos(sld, event));
% Create a push button for decreasing z
minus_z = uibutton(g3,'push',...
'Text', '<',...
'HorizontalAlignment', 'center',...
'VerticalAlignment', 'center',...
'FontSize', 20,...
'Enable', false,...
'ButtonPushedFcn',...
@(btn, events) minusZButtonPushed(btn, events));
% Create a push button for increasing z
plus_z = uibutton(g3,'push',...
'Text', '>',...
'HorizontalAlignment', 'center',...
'VerticalAlignment', 'center',...
'FontSize', 20,...
'ButtonPushedFcn',...
@(btn, events) plusZButtonPushed(btn, events));
% Create a field for entering which z plane to display
edt_z = uieditfield(g3, 'numeric',...
'HorizontalAlignment', 'center',...
'FontSize', 14,...
'Limits', [1, size(im,3)+0.5],...
'LowerLimitInclusive','on',...
'UpperLimitInclusive','on',...
'Value', 1,...
'ValueChangedFcn',...
@(txt,event) edit_z_update(txt,event));
end
% If image is a time series
if size(im,4) > 1
tMinTick = ceil(size(im,4)/350) * 5;
tMajTick = tMinTick * 5;
% Create a text label for the time slider
uilabel(g3, 'Text', 'time', 'HorizontalAlignment', 'right');
% Create a slider for controlling which time point to display, also
% set the limits and tick marks
sld_t = uislider(g3,...
'Limits', [1, size(im,4)],...
'MajorTicks', [1, tMajTick:tMajTick:size(im,4)],...
'MinorTicks', [1, tMinTick:tMinTick:size(im,4)],...
'ValueChangingFcn',...
@(sld,event) update_t(sld, event),...
'ValueChangedFcn',...
@(sld,event) update_t_pos(sld, event));
% Create a push button for decreasing time
minus_t = uibutton(g3,'push',...
'Text', '<',...
'HorizontalAlignment', 'center',...
'VerticalAlignment', 'center',...
'FontSize', 20,...
'Enable', false,...
'ButtonPushedFcn',...
@(btn, events) minustButtonPushed(btn, events));
% Create a push button for increasing time
plus_t = uibutton(g3,'push',...
'Text', '>',...
'HorizontalAlignment', 'center',...
'VerticalAlignment', 'center',...
'FontSize', 20,...
'ButtonPushedFcn',...
@(btn, events) plustButtonPushed(btn, events));
% Create a field for entering which time to display
edt_t = uieditfield(g3, 'numeric',...
'HorizontalAlignment', 'center',...
'FontSize', 14,...
'Limits', [1 size(im,4)],...
'LowerLimitInclusive','on',...
'UpperLimitInclusive','on',...
'Value', 1,...
'ValueChangedFcn',...
@(txt,event) edit_t_update(txt,event));
end
% If there is a threshold field and more than one threshold
if isfield(data, 'threshold') && size(data(i).threshold,2) > 1
% Create a text label for the threshold slider
uilabel(g3, 'Text', 'Threshold', 'HorizontalAlignment', 'right');
% Create a slider for controlling the displayed data for the
% specified threshold and set the limits and tick marks
sld_T = uislider(g3,...
'Limits', [1, size(data(i).threshold,2)],...
'MajorTicks', 1:size(mask,5),...
'MinorTicks', [],...
'ValueChangingFcn',...
@(sld,event) update_T(sld, event),...
'ValueChangedFcn',...
@(sld,event) update_T_pos(sld, event));
% Create a push button for decreasing threshold
minus_T = uibutton(g3,'push',...
'Text', '<',...
'HorizontalAlignment', 'center',...
'VerticalAlignment', 'center',...
'FontSize', 20,...
'Enable', false,...
'ButtonPushedFcn',...
@(btn, events) minusTButtonPushed(btn, events));
% Create a push button for increasing threshold
plus_T = uibutton(g3,'push',...
'Text', '>',...
'HorizontalAlignment', 'center',...
'VerticalAlignment', 'center',...
'FontSize', 20,...
'ButtonPushedFcn',...
@(btn, events) plusTButtonPushed(btn, events));
% Create a entry field for specifying the threshold for the
% displayed data
edt_T = uieditfield(g3, 'numeric',...
'HorizontalAlignment', 'center',...
'FontSize', 14,...
'Limits', [1, size(data(i).threshold,2)],...
'LowerLimitInclusive', 'on',...
'UpperLimitInclusive', 'on',...
'Value', 1,...
'ValueChangedFcn',...
@(txt,event) edit_T_update(txt,event));
end
% Create a text label for the brightness slider
uilabel(g3, 'Text', 'Brightness', 'HorizontalAlignment', 'right');
% Create a slider for controlling the brightness
uislider(g3,...
'Value', 100,...
'Limits', [0, 100],...
'MajorTicks', 0:5:100,...
'ValueChangingFcn', @(sld,event) update_B(sld, event));
% Label for the image selecting dropdown menu
lbl_exp = uilabel(g2, 'Text', 'Select image',...
'HorizontalAlignment', 'left',...
'WordWrap', 'on');
lbl_exp.Layout.Row = 2;
lbl_exp.Layout.Column = 2;
% Create a dropdown menu for changing which movie/image to display
exp = uidropdown(g2, 'Items', {data.name},...
'Value', data(1).name,...
'ValueChangedFcn',...
@(dd,event) exp_selection(dd,event));
exp.Layout.Row = 2;
exp.Layout.Column = 3;
% Label for the mask overlaying button
lbl_mask_btn = uilabel(g2, 'Text', 'Toggle on/off overlay of mask',...
'HorizontalAlignment', 'left',...
'WordWrap', 'on');
lbl_mask_btn.Layout.Row = 3;
lbl_mask_btn.Layout.Column = 2;
% Create a push button for overlaying the mask on the image
mask_btn = uibutton(g2,'state',...
'Text', 'Display Mask',...
'valueChangedFcn',...
@(mask_btn, events) maskButtonPushed(...
mask_btn, events));
mask_btn.Layout.Row = 3;
mask_btn.Layout.Column = 3;
% Label for the circling detected spots button
lbl_circle_btn = uilabel(g2, 'Text', 'Toggle on/off spots',...
'HorizontalAlignment', 'left',...
'WordWrap', 'on');
lbl_circle_btn.Layout.Row = 4;
lbl_circle_btn.Layout.Column = 2;
% Create a push button for circling the detected spots on the image
circle_btn = uibutton(g2,'state',...
'Text', 'Circle Spots',...
'valueChangedFcn',...
@(circle_btn, events) circleButtonPushed(...
circle_btn, events));
circle_btn.Layout.Row = 4;
circle_btn.Layout.Column = 3;
% Label for the plotting convex hull button
lbl_hull_btn = uilabel(g2, 'Text', 'Toggle on/off convex hull',...
'HorizontalAlignment', 'left',...
'WordWrap', 'on');
lbl_hull_btn.Layout.Row = 5;
lbl_hull_btn.Layout.Column = 2;
% Create a push button for plotting the convex hull on the image
hull_btn = uibutton(g2,'state',...
'Text', 'Display Convex Hull',...
'valueChangedFcn',...
@(hull_btn, events) hullButtonPushed(...
hull_btn, events));
hull_btn.Layout.Row = 5;
hull_btn.Layout.Column = 3;
% Label for the dropdown menu for selecting which color channel to
% display
lbl_dd1 = uilabel(g2, 'Text', 'Choose image channel',...
'HorizontalAlignment', 'left',...
'WordWrap', 'on');
lbl_dd1.Layout.Row = 6;
lbl_dd1.Layout.Column = 2;
% Create a dropdown menu for selecting which color channel to display
dd1 = uidropdown(g2,...
'Items', channels,...
'Value', 'Channel 1',...
'ValueChangedFcn', @(dd,event) channel_select(dd,event));
dd1.Layout.Row = 6;
dd1.Layout.Column = 3;
% Label for the dropdown menu to choose which color to display the mask
% in
lbl_dd2 = uilabel(g2, 'Text', 'Choose color of mask',...
'HorizontalAlignment', 'left',...
'WordWrap', 'on');
lbl_dd2.Layout.Row = 7;
lbl_dd2.Layout.Column = 2;
% Create a dropdown menu to choose which color to display the mask in
dd2 = uidropdown(g2,...
'Items', colors,...
'Value', 'Red',...
'ValueChangedFcn', @(dd,event) color_select(dd,event));
dd2.Layout.Row = 7;
dd2.Layout.Column = 3;
% Label for the dropdown menu for selecting which mask to display
lbl_dd3 = uilabel(g2, 'Text', 'Choose mask type',...
'HorizontalAlignment', 'left',...
'WordWrap', 'on');
lbl_dd3.Layout.Row = 8;
lbl_dd3.Layout.Column = 2;
% Create a dropdown menu for selecting which mask to display
dd3 = uidropdown(g2,...
'ValueChangedFcn', @(dd,event) mask_select(dd,event));
dd3.Layout.Row = 8;
dd3.Layout.Column = 3;
% The following if statement determines if the data is from
% quantify_ms2.m or from quantify_in_situ.m
% If max_projections is a field
if isfield(data, 'avg_projection')
% If size of field is 2
if size(im_field, 1) == 2
% Set the choices for the mask dropdown menu to differentiate
% between a max, sum, and avg projection for both signal and
% background
dd3.Items = {'Avg Signal'; 'Avg Background';...
'Max Signal'; 'Max Background'};
dd3.Value = 'Avg Signal';
n = [2,3,1];
% Save image and mask
[im, mask] = set_image_and_mask(data, im_field, mask_field, i, n);
else
dd3.Items = {'Signal'; 'Background'};
dd3.Value = 'Signal';
n = [1,1,1];
end
% Create a text label for the data set/image slider
lbl_i = uilabel(g3, 'Text', 'Image',...
'HorizontalAlignment', 'right');
lbl_i.Layout.Row = 2;
lbl_i.Layout.Column = 1;
% Create a slider for changing the data set/image
sld_i = uislider(g3,...
'Limits', [1, size(data,2)],...
'MajorTicks', 1:ceil(size(data,2)/20):size(data,2),...
'MinorTicks', 1:size(data,2),...
'ValueChangingFcn',...
@(sld,event) update_i(sld, event),...
'ValueChangedFcn',...
@(sld,event) update_i_pos(sld, event));
% Create a push button for decreasing the data set/image
minus_i = uibutton(g3,'push',...
'Text', '<',...
'Enable', false,...
'ButtonPushedFcn',...
@(btn, events) minusiButtonPushed(btn, events));
% Create a push button for increasing the data set/image
plus_i = uibutton(g3,'push',...
'Text', '>',...
'ButtonPushedFcn',...
@(btn, events) plusiButtonPushed(btn, events));
% Label for the button for displaying embryo ellipse
lbl_b1 = uilabel(g2, 'Text',...
'Toggle on/off ellipse fit to embryo',...
'HorizontalAlignment', 'left',...
'WordWrap', 'on');
lbl_b1.Layout.Row = 9;
lbl_b1.Layout.Column = 2;
% Create a push button for displaying a plot of an ellipse that is
% calculated from the segmented embryo
b1 = uibutton(g2,'state',...
'Text', 'Embryo Ellipse',...
'Position', [183, 70, 150, 22],...
'valueChangedFcn',...
@(btn, events) plotEmButtonPushed(btn, events));
b1.Layout.Row = 9;
b1.Layout.Column = 3;
% Label for the button for displaying signal ellipse
lbl_b2 = uilabel(g2, 'Text',...
'Toggle on/off ellipse fit to signal',...
'HorizontalAlignment', 'left',...
'WordWrap', 'on');
lbl_b2.Layout.Row = 10;
lbl_b2.Layout.Column = 2;
% Create a push button for displaing a plot of an ellipse that is
% calculated from the segmented signal
b2 = uibutton(g2,'state',...
'Text', 'Signal Ellipse',...
'Position', [367, 70, 150, 22],...
'valueChangedFcn',...
@(btn, events) plotImButtonPushed(btn, events));
b2.Layout.Row = 10;
b2.Layout.Column = 3;
else
% If size of field.mask is equal to 2
if size(mask_field, 1) == 2
% Set mask dropdown menu choices to different MS2 or nuclear
dd3.Items = {'Nuclear', 'MS21', 'MS22'};
dd3.Value = 'Nuclear';
% Elseif the size is only 1, set the choice to MS2
elseif size(mask_field, 1) == 1
dd3.Items = {'MS2'};
dd3.Value = 'MS2';
elseif size(mask_field, 1) == 4
dd3.Items = {'ROI','Quant','Nuclei','Single'};
dd3.Value = 'ROI';
end
end
% Change the z slice value when the slider is moved
function update_z(~, event)
z = update_slider(event, size(im,3), false, plus_z, minus_z,...
sld_z, edt_z);
% Make the mask overlay and update the image
[em_h, im_h, hull_h, p_h] = display_image(uiax, z, t, im, mask,...
ch, c, B, T, data, i, em_vis, im_vis, n, color,...
hull_vis, pts_vis, varargin{:});
end
% Change the z slice slider value so it is discrete
function update_z_pos(sld, event)
update_slider_pos(sld, event, false, size(im,3));
end
% Callback when a z is entered to change the z slice
function edit_z_update(~,event)
z = edit_x_update(event, size(im,3), false, plus_z, minus_z,...
sld_z, edt_z);
% Make the mask overlay and update the image
[em_h, im_h, hull_h, p_h] = display_image(uiax, z, t, im, mask,...
ch, c, B, T, data, i, em_vis, im_vis, n, color,...
hull_vis, pts_vis, varargin{:});
end
% Create the function for the callback for when the minus z button is
% pushed
function minusZButtonPushed(~, ~)
z = plusminusXButtonPushed(z, size(im,3), plus_z, minus_z,...
sld_z, edt_z, 'minus');
% Make the mask overlay and update the image
[em_h, im_h, hull_h, p_h] = display_image(uiax, z, t, im, mask,...
ch, c, B, T, data, i, em_vis, im_vis, n, color,...
hull_vis, pts_vis, varargin{:});
end
% Create the function for the callback to the plus z button
function plusZButtonPushed(~, ~)
z = plusminusXButtonPushed(z, size(im,3), plus_z, minus_z,...
sld_z, edt_z, 'plus');
% Make the mask overlay and update the image
[em_h, im_h, hull_h, p_h] = display_image(uiax, z, t, im, mask,...
ch, c, B, T, data, i, em_vis, im_vis, n, color,...
hull_vis, pts_vis, varargin{:});
end
% Change the time value when the slider is moved
function update_t(~, event)
t = update_slider(event, size(im,4), true, plus_t, minus_t,...
sld_t, edt_t);
% Make the mask overlay and update the image
[em_h, im_h, hull_h, p_h] = display_image(uiax, z, t, im, mask,...
ch, c, B, T, data, i, em_vis, im_vis, n, color,...
hull_vis, pts_vis, varargin{:});
end
% Change the time slider value so it is discrete
function update_t_pos(sld, event)
update_slider_pos(sld, event, true, size(im,4));
end
% Callback when a t is entered to change the time
function edit_t_update(~,event)
t = edit_x_update(event, size(im,4), true, plus_t, minus_t,...
sld_t, edt_t);
% Make the mask overlay and update the image
[em_h, im_h, hull_h, p_h] = display_image(uiax, z, t, im, mask,...
ch, c, B, T, data, i, em_vis, im_vis, n, color,...
hull_vis, pts_vis, varargin{:});
end
% Create the function for the callback to the minus button for time
% index
function minustButtonPushed(~, ~)
t = plusminusXButtonPushed(t, size(im,4), plus_t, minus_t,...
sld_t, edt_t, 'minus');
% Make the mask overlay and update the image
[em_h, im_h, hull_h, p_h] = display_image(uiax, z, t, im, mask,...
ch, c, B, T, data, i, em_vis, im_vis, n, color,...
hull_vis, pts_vis, varargin{:});
end
% Create the function for the callback to the plus button for time
% index
function plustButtonPushed(~, ~)
t = plusminusXButtonPushed(t, size(im,4), plus_t, minus_t,...
sld_t, edt_t, 'plus');
% Make the mask overlay and update the image
[em_h, im_h, hull_h, p_h] = display_image(uiax, z, t, im, mask,...
ch, c, B, T, data, i, em_vis, im_vis, n, color,...
hull_vis, pts_vis, varargin{:});
end
% Change the threshold value when the slider is moved
function update_T(~, event)
T = update_slider(event, size(data(i).threshold,2), false,...
plus_T, minus_T, sld_T, edt_T);
% Make the mask overlay and update the image
[em_h, im_h, hull_h, p_h] = display_image(uiax, z, t, im, mask,...
ch, c, B, T, data, i, em_vis, im_vis, n, color,...
hull_vis, pts_vis, varargin{:});
end
% Change the threshold slider value so it is discrete
function update_T_pos(sld, event)
update_slider_pos(sld, event, false, size(data(i).threshold,2));
end
% Callback when a number is entered to change the threshold
function edit_T_update(~,event)
T = edit_x_update(event, size(data(i).threshold,2), false,...
plus_T, minus_T, sld_T, edt_T);
% Make the mask overlay and update the image
[em_h, im_h, hull_h, p_h] = display_image(uiax, z, t, im, mask,...
ch, c, B, T, data, i, em_vis, im_vis, n, color,...
hull_vis, pts_vis, varargin{:});
end
% Create the function for the callback to the minus button for
% threshold
function minusTButtonPushed(~, ~)
T = plusminusXButtonPushed(T, size(data(i).threshold,2), plus_T,...
minus_T, sld_T, edt_T, 'minus');
% Make the mask overlay and update the image
[em_h, im_h, hull_h, p_h] = display_image(uiax, z, t, im, mask,...
ch, c, B, T, data, i, em_vis, im_vis, n, color,...
hull_vis, pts_vis, varargin{:});
end
% Create the function for the callback to the plus button for threshold
function plusTButtonPushed(~, ~)
T = plusminusXButtonPushed(T, size(data(i).threshold,2), plus_T,...
minus_T, sld_T, edt_T, 'plus');
% Make the mask overlay and update the image
[em_h, im_h, hull_h, p_h] = display_image(uiax, z, t, im, mask,...
ch, c, B, T, data, i, em_vis, im_vis, n, color,...
hull_vis, pts_vis, varargin{:});
end
% Function to update value of brightness for image
function update_B(~, event)
% Get new value for brightness factor from current position of
% slider
B = event.Value;
% To prevent an error where max and min values are equal, add a
% small number to brightness factor to make it nonzero if zero
if B == 0
B = B + 0.000000001;
end
% Make the mask overlay and update the image
[em_h, im_h, hull_h, p_h] = display_image(uiax, z, t, im, mask,...
ch, c, B, T, data, i, em_vis, im_vis, n, color,...
hull_vis, pts_vis, varargin{:});
end
% Create callback for the dropdown menu to select the experiment
function exp_selection(dd,~)
% Find the index of the experiment with experiment name that
% matches the value selected in the dropdown menu
i = find(strcmp({data.name}, dd.Value));
% If plus_i and minus_i exist, meaning that data is from
% quantify_in_situ_.m
if exist('plus_i', 'var') && exist('minus_i', 'var')
% Check limits to determine if plus or minus button is active
check_limits(i, size(data,2), plus_i, minus_i)
end
% Set the slider for the experiment slider to the new experiment
% index
sld_i.Value = i;
% Set the image and mask to those determined by the new experiment
% index
[im, mask] = set_image_and_mask(data, im_field, mask_field, i, n);
% If slide for time exists
if exist('sld_t', 'var')
% Change t back to 1 and reset slider
t = change_exp(sld_t, size(im,4), plus_t, minus_t, edt_t,...
true);
end
% If slide for z exists
if exist('sld_z', 'var')
% Change z back to 1 and reset slider
z = change_exp(sld_z, size(im,3), plus_z, minus_z, edt_z,...
false);
end
% If slide for threshold exists
if exist('sld_T', 'var')
% Change T back to 1 and reset slider
T = change_exp(sld_T, size(data(i).threshold,2), plus_T,...
minus_T, edt_T, false);
end
% Make the mask overlay and update the image
[em_h, im_h, hull_h, p_h] = display_image(uiax, z, t, im, mask,...
ch, c, B, T, data, i, em_vis, im_vis, n, color,...
hull_vis, pts_vis, varargin{:});
end
% Create the function for the callback when the display mask button is
% pushed
function maskButtonPushed(mask_btn,~)
% If the button is not clicked
if mask_btn.Value == false
% Set the color to 0,0,0 so the mask is not seen
c = [0, 0, 0];
% Elseif the button is clicked
elseif mask_btn.Value == true
% Set the color to the color from the dropdown menu
c = pick_color(color);
end
% Make the mask overlay and update the image
[em_h, im_h, hull_h, p_h] = display_image(uiax, z, t, im, mask,...
ch, c, B, T, data, i, em_vis, im_vis, n, color,...
hull_vis, pts_vis, varargin{:});
end
% Create the function for the callback when the circle spots button is
% pushed
function circleButtonPushed(circle_btn,~)
% If the button is not clicked
if circle_btn.Value == false
% Set the points visibility flag to false
pts_vis = false;
% Elseif the button is clicked
elseif circle_btn.Value == true
% Set the points visibility flag to true
pts_vis = true;
end
% Set visibility handle to show or hide convex hull based on if the
% button is pressed
if ~isempty(pts_vis)
set(p_h, 'Visible', pts_vis);
end
end
% Create the function for the callback when the convex hull button is
% pushed
function hullButtonPushed(hull_btn,~)
% If the plot convex hull function is not pressed
if hull_btn.Value == false
% Set the hull visibility flag to false
hull_vis = false;
% Elseif the plot convex function is pressed
elseif hull_btn.Value == true
% Set the hull visibility flag to true
hull_vis = true;
end
% Set visibility handle to show or hide convex hull based on if the
% button is pressed
if ~isempty(hull_vis)
set(hull_h, 'Visible', hull_vis);
end
end
% Create callback when the channel is changed from the dropdown menu
function channel_select(dd,~)
% Save the channel number based on which channel is picked
switch dd.Value
case 'Channel 1'
ch = 1;
case 'Channel 2'
ch = 2;
case 'Channel 3'
ch = 3;
case 'Channel 4'
ch = 4;
end
% Make the mask overlay and update the image
[em_h, im_h, hull_h, p_h] = display_image(uiax, z, t, im, mask,...
ch, c, B, T, data, i, em_vis, im_vis, n, color,...
hull_vis, pts_vis, varargin{:});
end
% Create callback for when the color is channged from the dropdown menu
function color_select(dd,~)
% Set color to the selected value
color = dd.Value;
% If the display mask button is currently pressed
if mask_btn.Value == true
% Change the color of the mask to the new color picked from the
% dropdown menu
c = pick_color(color);
end
% Make the mask overlay and update the image
[em_h, im_h, hull_h, p_h] = display_image(uiax, z, t, im, mask,...
ch, c, B, T, data, i, em_vis, im_vis, n, color,...
hull_vis, pts_vis, varargin{:});
end
% Create callback for dropdown menu that picks the mask type
function mask_select(dd,~)
% Save values n, index into image and mask fields
im_i = strcmp(im_type, dd.Value);
n = im_ind(im_i, :);
% Set the image and mask to those determined by the selection
[im, mask] = set_image_and_mask(data, im_field, mask_field, i, n);
% Set the thresholds slider to the new thresholds and initialize it
% to the first threshold
if exist('sld_T', 'var')
T = change_exp(sld_T, size(data(i).threshold,2), plus_T,...
minus_T, edt_T, false);
end
% Make the mask overlay and update the image
[em_h, im_h, hull_h, p_h] = display_image(uiax, z, t, im, mask,...
ch, c, B, T, data, i, em_vis, im_vis, n, color,...
hull_vis, pts_vis, varargin{:});
end
% Change the experiment/image number value when the slider is moved
function update_i(~, event)
i = update_slider(event, size(data,2), false, plus_i, minus_i,...
sld_i, []);
% Set the dropdown menu to the experiment that is currently
% selected
exp.Value = data(i).name;
% Set the image and mask for the new experiment selected
[im, mask] = set_image_and_mask(data, im_field, mask_field, i, n);
% Make the mask overlay and update the image
[em_h, im_h, hull_h, p_h] = display_image(uiax, z, t, im, mask,...
ch, c, B, T, data, i, em_vis, im_vis, n, color,...
hull_vis, pts_vis, varargin{:});
end
% Change the experiment/image slider value so it is discrete
function update_i_pos(sld, event)
update_slider_pos(sld, event, false, size(data,2));
end
% Create the function for the callback to the minus button for
% experiment/image number
function minusiButtonPushed(~, ~)
i = plusminusXButtonPushed(i, size(data,2), plus_i, minus_i,...
sld_i, [], 'minus');
% Set the dropdown menu to the experiment that is currently
% selected
exp.Value = data(i).name;
% Set the image and mask to those determined by the new experiment
% index
[im, mask] = set_image_and_mask(data, im_field, mask_field, i, n);
% Make the mask overlay and update the image
[em_h, im_h, hull_h, p_h] = display_image(uiax, z, t, im, mask,...
ch, c, B, T, data, i, em_vis, im_vis, n, color,...
hull_vis, pts_vis, varargin{:});
end
% Create the function for the callback to the plus button for
% experiment/image number
function plusiButtonPushed(~, ~)
i = plusminusXButtonPushed(i, size(data,2), plus_i, minus_i,...
sld_i, [], 'plus');
% Set the dropdown menu for choosing the experiment to the new
% experiment
exp.Value = data(i).name;
% Set the image and mask to those determined by the new experiment
% index
[im, mask] = set_image_and_mask(data, im_field, mask_field, i, n);
% Make the mask overlay and update the image
[em_h, im_h, hull_h, p_h] = display_image(uiax, z, t, im, mask,...
ch, c, B, T, data, i, em_vis, im_vis, n, color,...
hull_vis, pts_vis, varargin{:});
end
% Create the function for the callback to the plot embryo ellipse
% function
function plotEmButtonPushed(btn,~)
% If the plot embryo ellipse function is not pressed
if btn.Value == false
% Set the ellipse visibility flag to false
em_vis = false;
% Elseif the plot embryo ellipse function is pressed
elseif btn.Value == true
% Set the ellipse visibility flag to true
em_vis = true;
end
% Set visibility handle to show or hide ellipse based on if button
% is pressed
if ~isempty(em_h)
set(em_h, 'Visible', em_vis);
end
end
% Create the function for the callback to the plot image ellipse
% function
function plotImButtonPushed(btn,~)
% If the plot embryo ellipse function is not pressed
if btn.Value == false
% Set the ellipse visibility flag to false
im_vis = false;
% Elseif the plot embryo ellipse function is pressed
elseif btn.Value == true
% Set the ellipse visibility flag to true
im_vis = true;
end
% Set visibility handle to show or hide ellipse based on if button
% is pressed
if ~isempty(im_h)
set(im_h, 'Visible', im_vis);
end
end
end
function [em_h, im_h, hull_h, p_h] = display_image(uiax, z, t, im, mask,...
ch, c, B, T, data, i, em_vis, im_vis, n, color,...
hull_vis, pts_vis, varargin)
%DISPLAY_IMAGE Overlays mask or plots points and convex hull and displays
%
% Inputs
% uiax: axis handle to axis in the uifigure
% z: z slice index
% t: time index
% im: image data
% mask: mask data
% ch: channel index
% c: color array for overlaying mask
% B: brightness factor
% T: threshold index
% data: data structure
% i: experiment/image index
% em_vis: true or false to determine if ellipse for the background/
% embryo should be displayed
% im_vis:true or false to determine if ellipse for the signal/
% image should be displayed
% n: the index to the image field, mask field, and mask dimension
% color: the current color for the points
% hull_vis: true or false to determine if convex hull is visible
% pts_vis: true or false to determine if points are visible
% varargin: structure containing points and hull information
%
% Outputs
% em_h: handle to the background/embryo ellipse plot
% im_h: handle to the signal/image ellipse plot
% hull_h: handle to the convex hull plot
% p_h: handle to the points plot
%
% Overview
% The image is brightend using the set brightness. If a mask is
% specified, it is overlaid on the image specified by the inputs. The
% grayscale image is converted to RGB, and then the color is
% determined by decreasing the appropriate channels to zero where the
% mask is. Also plots the centroids and convex hull if the
% corresponding buttons were pressed.
% Clear the axes
cla(uiax);
% Set limits to size of image, so only image is displayed
uiax.XLim = [0 size(im, 2)];
uiax.YLim = [0 size(im, 1)];
% Set the image based on the brightness factor B
brighter = imadjust(im(:,:,z,t,ch), [0, B ./ 100]);
% If the mask variable is not empty
if ~isempty(mask)
% If the image is 8 bit
if isa(im, 'uint8')
% Make a RGB image where the original image is grayscale
mask_im = cat(3, uint8(~mask(:,:,z,t,T)).^c(1) .* brighter,...
uint8(~mask(:,:,z,t,T)).^c(2) .* brighter,...
uint8(~mask(:,:,z,t,T)).^c(3) .* brighter);
% Elseif the image is 16 bit
elseif isa(im, 'uint16')
% Make a RGB image where the original image is grayscale
mask_im = cat(3, uint16(~mask(:,:,z,t,T)).^c(1) .* brighter,...
uint16(~mask(:,:,z,t,T)).^c(2) .* brighter,...
uint16(~mask(:,:,z,t,T)).^c(3) .* brighter);
else
im = im(:,:,z,t,ch);
% Normalize image by maximum so that it displays. The 0.5
% factor is to approximate the brightness of original images
im = im./max(im(:));
brighter = imadjust(im, [0, B ./ 100]);
mask_im = cat(3, double(~mask(:,:,z,t,T)).^c(1) .* brighter,...
double(~mask(:,:,z,t,T)).^c(2) .* brighter,...
double(~mask(:,:,z,t,T)).^c(3) .* brighter);
end
% If the data includes the field angle_em_max, which means the data
% is from quanitfy_in_situ.m and can plot an ellipse
if isfield(data, 'angle_em_max')
% Call plot_ellipse for the updated data
[em_h, im_h] = plot_ellipse(uiax, data(i), em_vis, im_vis, n);
else
em_h = [];
im_h = [];
end
% If postion data is provided, determined by an extra input
% argument and varargin is not empty
if nargin >= 18 && ~isempty(varargin{1})
% If rm_pts is a field and is not empty
if isfield(varargin{1}, 'rm_pts')...
&& ~isempty(varargin{1}(i).rm_pts)...
&& ~isempty(varargin{1}(i).rm_pts{t,1})
hold(uiax,'on');
% Plot points from rm_pts which is the list of points with
% outliers removed
p_h = plot(uiax, varargin{1}(i).rm_pts{t,1}(:,1),...
varargin{1}(i).rm_pts{t,1}(:,2), 'o',...
'MarkerSize', 12,...
'MarkerEdgeColor', color,...
'Linewidth', 1,...
'Visible', pts_vis);
hold(uiax,'off');
elseif isfield(varargin{1}, 'new_center')...
&& ~isempty(varargin{1}(i).new_center)
hold(uiax,'on');
% Plot points from centers which is the list of points
% without outliers removed
p_h = plot(uiax, varargin{1}(i).new_center{t,1}(:,1),...