-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathnumorph_preprocessing.m
More file actions
853 lines (679 loc) · 32.8 KB
/
numorph_preprocessing.m
File metadata and controls
853 lines (679 loc) · 32.8 KB
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
function numorph_preprocessing(varargin)
%call the parser function to parse the input arguments
params = parseInputArgs(varargin{:});
% Get the values of the parameters
input_dir = params.input_dir;
output_dir = params.output_dir;
parameter_file = params.parameter_file;
sample_id = params.sample_name;
stage = params.stage;
% Run the preprocessing pipeline
%addpath(genpath(pwd));
NM_setup % setup numorph
% read in the config file which is a csv file
% convert config file to a structure like in original numorph
home_path = fileparts(which('NM_config'));
% check if not NM_variables exist
if isempty(params.NM_variables)
tmp_folder = fullfile(home_path,'data','tmp', 'NM_variables.mat');
disp("config structure from csv file");
csv_to_mat_file(parameter_file, tmp_folder, input_dir, output_dir, sample_id);
NM_variables = load(tmp_folder);
else
disp("config structure from NM_variables.mat file");
NM_variables = load(params.NM_variables);
tmp_folder = fullfile(home_path,'data','tmp', 'NM_variables.mat');
end
save(tmp_folder, '-struct', 'NM_variables');
switch stage
case 'process'
config = NM_config('process', sample_id);
NM_process(config, "process");
case 'intensity'
config = NM_config('process', sample_id);
NM_process(config, "intensity");
case 'align'
config = NM_config('process', sample_id);
% need this because of nextflows changing work dirs
% need to update it for the subsequent processes (not the first one)
config.output_directory = output_dir;
NM_process(config, "align");
case 'stitch'
config = NM_config('process', sample_id);
config.output_directory = output_dir;
NM_process(config, "stitch");
otherwise
error('Invalid step. Please choose from: process, intensity, align, stitch');
end
varData = load(tmp_folder);
save(fullfile(output_dir, 'NM_variables.mat'), '-struct' ,'varData');
close all;
clear varData;
end
function csv_to_mat_file(csvFilePath, matFilePath, input_dir, output_dir, sample_id)
% Read the CSV file into a table
tbl = readtable(csvFilePath, 'ReadVariableNames', true, 'Delimiter', ',');
% Create a structure to hold the variables
S = struct();
S.img_directory = string(input_dir);
S.output_directory = string(output_dir);
S.sample_id = string(sample_id)
% Iterate over the rows of the table and add to the structure
for i = 1:height(tbl)
parameter = tbl.Parameter{i};
value = tbl.Value{i};
% save vars to structure according to original numorph
% "adjust_intensity": true, update, false; Whether to calculate and apply any of the following intensity adjustments. Intensity adjustment measurements should typically be performed on raw images
if (parameter == "adjust_intensity")
S.adjust_intensity = string(value);
% true, false; Can be 1xn_channels. Normalize tile intensities by position using overlapping regions
elseif (parameter == "adjust_tile_position")
S.adjust_tile_position = string(value);
% basic, manual, false; Can be 1xn_channels. Perform shading correction using BaSIC algorithm or using manual measurements from UMII microscope
elseif (parameter == "adjust_tile_shading")
S.adjust_tile_shading = string(value);
% Option to align only certain channels (set to >1)
elseif (parameter == "align_channels")
if isnan(str2double(value))
S.align_channels = double([]);
else
S.align_channels = str2double(value);
end
% Only for alignment by elastix. Option to align only certain chunks
elseif (parameter == "align_chunks")
value = split(value, ';');
if (strlength(value) == 0)
S.align_chunks = double([]);
else
S.align_chunks = str2double(value);
end
% elastix, translation; Channel alignment by rigid, 2D translation or non-rigid B-splines using elastix
elseif (parameter == "align_method")
S.align_method = string(value);
% Option to align only certain slice ranges. Set as cell array for non-continuous ranges (i.e. {1:100,200:300})
elseif (parameter == "align_slices")
value = split(value, ';');
if (strlength(value) == 0)
S.align_slices = double([]);
else
S.align_slices = cell(value);
end
% interger; Only for alignment by translation. Number of images sampled for determining translations. Images in between are interpolated
elseif (parameter == "align_stepsize")
S.align_stepsize = str2double(value);
% Option to align only certain stacks and not all stacks. Row-major order
elseif (parameter == "align_tiles")
value = split(value, ';');
if (strlength(value) == 0)
S.align_tiles = double([]);
else
S.align_tiles = str2double(value);
end
% sigmoid, linear, max
elseif (parameter == "blending_method")
S.blending_method = string(value);
% integer >= 0; Crops borders during stitching. Increase if images shift significantly between channels to prevent zeros values from entering stitched image
elseif (parameter == "border_pad")
S.border_pad = str2double(value);
% "channel_alignment": true, update, false;
elseif (parameter == "channel_alignment")
S.channel_alignment = string(value);
% Channel id
elseif (parameter == "channel_num")
value = split(value, ';');
if (strlength(value) == 0)
S.channel_num = string([]);
else
S.channel_num = string(value);
end
% integer; Padding around chunks. Should be set to value greater than the maximum expected translation in z
elseif (parameter == "chunk_pad")
S.chunk_pad = str2double(value);
% 1xn_channels; Constant darkfield intensity value (i.e. average intensity of image with nothing present)
elseif (parameter == "darkfield_intensity")
S.darkfield_intensity = str2double(value);
% [0,1]; Factor controlling amount of adjustment to apply. Set to 1 for absolute DoG
elseif (parameter == "DoG_factor")
S.DoG_factor = str2double(value);
% true,false; Apply difference of gaussian enhancement of blobs
elseif (parameter == "DoG_img")
S.DoG_img = string(value);
% 1x2 numeric; Min/max sigma values to take differene from.
elseif (parameter == "DoG_minmax")
value = split(value, ';');
S.DoG_minmax = str2double(value);
% 1xn_channels-1 string; Name of folders containing elastix registration parameters. Place in /supplementary_data/elastix_parameter_files/channel_alignment
elseif (parameter == "elastix_params")
S.elastix_params = string(value);
% "none", "horizontal", "vertical", "both"; Flip image along horizontal or vertical axis
elseif (parameter == "flip_axis")
S.flip_axis = string(value);
% 1xn_channels numeric; Gamma intensity adjustment
elseif (parameter == "Gamma")
S.Gamma = str2double(value);
% Group name/id
elseif (parameter == "group")
value = split(value, ';');
if (strlength(value) == 0)
S.group = string([]);
else
S.group = string(value);
end
% "left","right","both","none"
elseif (parameter == "hemisphere")
S.hemisphere = string(value);
% 1xn_channels-1 interger; Match histogram bins to reference channel? If so, specify number of bins. Otherwise leave empty or set to 0. This can be useful for low contrast images
elseif (parameter == "hist_match")
S.hist_match = str2double(value);
% completely ignore marker from processing steps.
elseif (parameter == "ignore_markers")
S.ignore_markers = string(value);
% Input image directory path
%TODO: check if i need this
%elseif (parameter == "img_directory")
%S.img_directory = string(value);
% [-0.5,0.5]; Displacement of light-sheet along y axis. Value of 0.5 means light-sheet center is positioned at the top of the image
elseif (parameter == "laser_y_displacement")
value = split(value, ';');
S.laser_y_displacement = str2double(value);
% true, false; Apply channel alignment translations during stitching
elseif (parameter == "load_alignment_params")
S.load_alignment_params = string(value);
% 1xn_channels numeric; Lower intensity for rescaling
elseif (parameter == "lowerThresh")
value = split(value, ';');
if (strlength(value) == 0)
S.lowerThresh = double([]);
else
S.lowerThresh = str2double(value);
end
% 1xn_channels interger; Light sheet width setting for UltraMicroscope II as percentage
elseif (parameter == "ls_width")
S.ls_width = str2double(value);
% Name of markers present
elseif (parameter == "markers")
value = split(value, ';');
if (strlength(value) == 0)
S.markers = string([]);
else
S.markers = string(value);
end
% numeric; Mask intensity threshold for choosing signal pixels in elastix channel alignment. Leave empty to calculate automatically
elseif (parameter == "mask_int_threshold")
value = split(value, ';');
if (strlength(value) == 0)
S.mask_int_threshold = double([]);
else
S.mask_int_threshold = str2double(value);
end
% integer; Chunk size for elastix alignment. Decreasing may improve precision but can give spurious results
elseif (parameter == "max_chunk_size")
S.max_chunk_size = str2double(value);
% numeric >= 1; Max radius of cell nuclei along x/y in pixels. Required also for DoG filtering
elseif (parameter == "nuc_radius")
S.nuc_radius = str2double(value);
% true, false; Use only phase correlation for registration. This gives only a quick estimate for channel alignment.
elseif (parameter == "only_pc")
S.only_pc = string(value);
% 1x3 string specifying sample orientation
% Orientation key: anterior(a)/posterior(p), superior(s)/inferior(i), left(l)/right(r)
elseif (parameter == "orientation")
S.orientation = string(value);
% Directory to save results
% TODO: check if i need this
%elseif (parameter == "output_directory")
%S.output_directory = string(value);
% 0:1; overlap between tiles as fraction
elseif (parameter == "overlap")
S.overlap = str2double(value);
% 1x3 string of regular expression specifying image row(y), column(x), slice(z)
elseif (parameter == "position_exp")
value = split(value, ';');
if (strlength(value) == 0)
S.position_exp = string([]);
else
S.position_exp = string(value);
end
% true, false; (Experimental) Option to pre-align using translation method prior to non-linear registration
elseif (parameter == "pre_align")
S.pre_align = string(value);
% 1x3 integer. Amount of downsampling along each axis. Some downsampling, ideally close to isotropic resolution, is recommended
elseif (parameter == "resample_s")
value = split(value, ';');
if (strlength(value) == 0)
S.resample_s = double([]);
else
S.resample_s = str2double(value);
end
% true, false; Rescaling intensities and applying gamma
elseif (parameter == "rescale_intensities")
S.rescale_intensities = string(value);
% Image reolution in um/voxel
elseif (parameter == "resolution")
value = split(value, ';');
if (strlength(value) == 0)
S.resolution = double([]);
else
value = str2double(value);
value = reshape(value,[1,3]);
S.resolution = num2cell(value,2);
end
% 90 or -90; Rotate image
elseif (parameter == "rotate_axis")
S.rotate_axis = str2double(value);
elseif (parameter == "sample")
S.sample = string(value);
%elseif (parameter == "sample_id")
% S.sample_id = string(value);
% [0,1]; Fraction of images to read and sample from. Setting to 1 means use all images
elseif (parameter == "sampling_frequency")
S.sampling_frequency = str2double(value);
elseif (parameter == "save_flag")
S.save_flag = str2double(value);
% true or false; Save images during processing. Otherwise only parameters will be calculated and saved
elseif (parameter == "save_images")
S.save_images = string(value);
% true, false; Save sample results for each major step
elseif (parameter == "save_samples")
S.save_samples = string(value);
% 0:1; Recommended: ~0.05. Steepness of sigmoid-based blending. Larger values give more block-like blending
elseif (parameter == "sd")
S.sd = str2double(value);
% integer vector; Subset tile positions for calculating shading correction (row major order). It's recommended that bright regions are avoid
elseif (parameter == "shading_correction_tiles")
value = split(value, ';');
if (strlength(value) == 0)
S.shading_correction_tiles = double([]);
else
S.shading_correction_tiles = str2double(value);
end
% numeric >= 1; Factor for adjusting the total effect of shading correction. Greater values lead to a smaller overall adjustment
elseif (parameter == "shading_intensity")
S.shading_intensity = str2double(value);
% numeric >= 1; Factor for adjusting smoothness of shading correction. Greater values lead to a smoother flatfield image
elseif (parameter == "shading_smoothness")
S.shading_smoothness = str2double(value);
% true, false; Refine stitching using SIFT algorithm (requires vl_fleat toolbox)
elseif (parameter == "sift_refinement")
S.sift_refinement = string(value);
% 1xn_channels numeric; Rough estimate for minimal intensity for features of interest
elseif (parameter == "signalThresh")
value = split(value, ';');
if (strlength(value) == 0)
S.signalThresh = double([]);
else
S.signalThresh = str2double(value);
end
% true, false; Whether a single sheet was used for acquisition
elseif (parameter == "single_sheet")
S.single_sheet = string(value);
% 1xn_channels, "gaussian", "median", "guided". Apply a smoothing filter
elseif (parameter == "smooth_img")
S.smooth_img = string(value);
% 1xn_channels numeric; Size of smoothing kernel. For median and guided filters, it is the dimension of the kernel size
elseif (parameter == "smooth_sigma")
value = split(value, ';');
if (strlength(value) == 0)
S.smooth_sigma = double([]);
else
S.smooth_sigma = str2double(value);
end
% "stitch_images": true, update, false; 2D iterative stitching
elseif (parameter == "stitch_images")
S.stitch_images = string(value);
% z index; Start stitching from specific position. Otherwise this will be optimized
elseif (parameter == "stitch_start_slice")
value = split(value, ';');
if (strlength(value) == 0)
S.stitch_start_slice = double([]);
else
S.stitch_start_slice = str2double(value);
end
% channel index; If only stitching certain channels
elseif (parameter == "stitch_sub_channel")
value = split(value, ';');
if (strlength(value) == 0)
S.stitch_sub_channel = double([]);
else
S.stitch_sub_channel = str2double(value);
end
% z positions; If only stitching a cetrain z range from all the images
elseif (parameter == "stitch_sub_stack")
value = split(value, ';');
if (strlength(value) == 0)
S.stitch_sub_stack = double([]);
else
S.stitch_sub_stack = str2double(value);
end
% true, false. Subtrat background (similar to Fiji's rolling ball background subtraction)
elseif (parameter == "subtract_background")
S.subtract_background = string(value);
% integers; Update intensity adjustments only to certain channels
elseif (parameter == "update_intensity_channels")
value = split(value, ';');
if (strlength(value) == 0)
S.update_intensity_channels = double([]);
else
S.update_intensity_channels = str2double(value);
end
% true, false; Update z adjusment steps with new parameters. Otherwise pipeline will search for previously calculated parameters
elseif (parameter == "update_z_adjustment")
S.update_z_adjustment = string(value);
% 1xn_channels numeric; Upper intensity for rescaling
elseif (parameter == "upperThresh")
value = split(value, ';');
if (strlength(value) == 0)
S.upperThresh = double([]);
else
S.upperThresh = str2double(value);
end
% "use_processed_images": false or name of sub-directory in output directory (i.e. aligned, stitched...); Load previously processed images in output directory as input images
elseif (parameter == "use_processed_images")
S.use_processed_images = string(value);
% 1xn_channels-1 interger; Predicted initial z displacement between reference channel and secondary channel (i.e.
elseif (parameter == "z_initial")
value = split(value, ';');
S.z_initial = str2double(value);
% integer or numeric; Sampling positions along adjacent image stacks to determine z displacement. If <1, uses fraction of all images. Set to 0 for no adjustment, only if you're confident tiles are aligned along z dimension
elseif (parameter == "z_positions")
S.z_positions = str2double(value);
% integer; Search window for finding corresponding tiles (i.e. +/-n z positions)
elseif (parameter == "z_window")
S.z_window = str2double(value);
% true, update, false; Perform image resampling
elseif (parameter == "resample_images")
S.resample_images = string(value);
% true, update, false; Register image to reference atlas.
elseif (parameter == "register_images")
S.register_images = string(value);
% true, update, false; Count cell nuclei or other blob objects.
elseif (parameter == "count_nuclei")
S.count_nuclei = string(value);
% true, update, false; Classify cell-types for detected nuclei centroids.
elseif (parameter == "classify_cells")
S.classify_cells = string(value);
% Isotropic resample resolution. This is also the resolution at which registration is performed
elseif (parameter == "resample_resolution")
S.resample_resolution = str2double(value);
% Resample specific channels. If empty, only registration channels will be resampled
elseif (parameter == "resample_channels")
value = split(value, ';');
if (strlength(value) == 0)
S.resample_channels = double([]);
else
S.resample_channels = str2double(value);
end
% true, false; Use annotation mask for cell counting
elseif (parameter == "use_annotation_mask")
S.use_annotation_mask = string(value);
% atlas, image; Specify whether annotation file is mapped to the atlas or light-sheet image
elseif (parameter == "annotation_mapping")
S.annotation_mapping = string(value);
% File for storing structure annotation data.
% Specify .mat file in /data/annotation_data if annotation_mapping is to the atlas. To generate a new .mat file with custom annotations, see 'help munge_atlas'
% Specify .nii file if annotation_mapping is to the image. Annotations here are already aligned to the image. Specify the full path for each sample in NM_samples.
elseif (parameter == "annotation_file")
S.annotation_file = string(value);
% Specify csv file in /annotations detailing which structures to analyze
% Alternatively, specify a numeric array structure indexes
elseif (parameter == "use_structures")
S.use_structures = string(value); % nope hier muss ich array oder empty array machen oder file path
% Isotropic resolution of the annotation file. Only needed when mapping is to the image.
elseif (parameter == "annotation_resolution")
S.annotation_resolution = str2double(value);
% atlas_to_image, image_to_atlas; Direction to perform registration
elseif (parameter == "registration_direction")
S.registration_direction = string(value);
% default, points, or name of folder containing elastix registration parameters in /data/elastix_parameter_files/atlas_registration
elseif (parameter == "registration_parameters")
S.registration_parameters = string(value);
% integer; Which light-sheet channels to register. Can select more than 1
elseif (parameter == "registration_channels")
S.registration_channels = str2double(value);
% image. Pre-align multiple light-sheet images by rigid transformation prior to registration
elseif (parameter == "registration_prealignment")
S.registration_prealignment = string(value);
% ara_nissl_25.nii and/or average_template_25.nii and/or a specific atlas .nii file in /data/atlas
elseif (parameter == "atlas_file")
S.atlas_file = string(value);
% Use points during registration
elseif (parameter == "use_points")
S.use_points = string(value);
% Not used
elseif (parameter == "prealign_annotation_index")
value = split(value, ';');
if (strlength(value) == 0)
S.prealign_annotation_index = double([]);
else
S.prealign_annotation_index = str2double(value);
end
% Name of points file to guide registration
elseif (parameter == "points_file")
S.points_file = string(value);
% Whether to save registered images
elseif (parameter == "save_registered_images")
S.save_registered_images = string(value);
% Remove olfactory bulbs and cerebellum from atlas ROI
elseif (parameter == "mask_cerebellum_olfactory")
S.mask_cerebellum_olfactory = string(value);
% 3dunet, hessian.
elseif (parameter == "count_method")
S.count_method = string(value);
% Minimum intensity for cell nuclei
elseif (parameter == "min_intensity")
S.min_intensity = str2double(value);
% Model file name located in /analysis/3dunet/nuclei/models
elseif (parameter == "model_file")
S.model_file = string(value);
% Cuda visible device index.
elseif (parameter == "gpu")
S.gpu = string(value);
% Max chunk size for running hessian
elseif (parameter == "chunk_size")
value = split(value, ';');
if (strlength(value) == 0)
S.chunk_size = double([]);
else
S.chunk_size = str2double(value);
end
% Chunk overlap
elseif (parameter == "chunk_overlap")
value = split(value, ';');
if (strlength(value) == 0)
S.chunk_overlap = double([]);
else
S.chunk_overlap = str2double(value);
end
% Average nucleus diameter in pixels
elseif (parameter == "average_nuc_diameter")
S.average_nuc_diameter = str2double(value);
% threhsold, svm; Cell-type classification method
elseif (parameter == "classify_method")
S.classify_method = string(value);
% which channels to use for classification
elseif (parameter == "classify_channels")
value = split(value, ';');
if (strlength(value) == 0)
S.classify_channels = double([]);
else
S.classify_channels = str2double(value);
end
% "true","false"; If set to "true", treat channel 1 as nuclear label that isn't classified
elseif (parameter == "contains_nuclear_channel")
S.contains_nuclear_channel = string(value);
% true, false; Update channel intensities measurements and save into centroids sheet
elseif (parameter == "remeasure_centroids")
S.remeasure_centroids = string(value);
% Set raw intensity values for thesholding. Leave empty to use expression values
elseif (parameter == "intensity_thresholds")
value = split(value, ';');
if (strlength(value) == 0)
S.intensity_thresholds = double([]);
else
S.intensity_thresholds = str2double(value);
end
% Threshold expression
elseif (parameter == "intensity_expression")
S.intensity_expression = str2double(value);
% Apply z normalization
elseif (parameter == "z_normalization")
S.z_normalization = string(value);
% Load previous centroid patches
elseif (parameter == "load_patches")
S.load_patches = string(value);
% Merge patch annotation from different groups for training
elseif (parameter == "load_groups")
value = split(value, ';');
if (strlength(value) == 0)
S.load_groups = string([]);
else
S.load_groups = string(value);
end
% Which classes to keep after prediction. Other labeled classes will be discarded
elseif (parameter == "keep_classes")
value = split(value, ';');
if (strlength(value) == 0)
S.keep_classes = string([]);
else
S.keep_classes = string(value);
end
% 1x2 integer. [Patch size for viewing, patch size read by classifier]
elseif (parameter == "patch_size")
value = split(value, ';');
if (strlength(value) == 0)
S.patch_size = double([]);
else
S.patch_size = str2double(value);
end
% integer. Number of patches to generate
elseif (parameter == "n_patches")
S.n_patches = str2double(value);
% numeric <1. Remove cells dim in every channel from classifier. (i.e. 0.5 removes cells below 50th percentile for all channels)
else (parameter == "min_class_thresh")
S.min_class_thresh = str2double(value);
end
end
% Save the structure as a .mat file
save(matFilePath, '-struct', 'S');
end
function fileList = getAllMatFiles(startPath)
% Generate a path string that includes all subdirectories
allSubDirs = genpath(startPath);
% Split the path string into individual directory paths
dirList = strsplit(allSubDirs, pathsep);
% Initialize the list of file paths
fileList = {};
% Loop over all directories
for d = 1:length(dirList)
% Skip any empty directory paths (can happen due to the split)
if isempty(dirList{d})
continue;
end
% Get a list of all '.mat' files in the current directory
matFiles = dir(fullfile(dirList{d}, '*.mat'));
% Add their full paths to the list
for k = 1:length(matFiles)
fileList{end+1, 1} = fullfile(matFiles(k).folder, matFiles(k).name);
end
end
end
function [status, outputPath] = convertMatFile(matFile)
status = false;
outputPath = '';
try
% Load the .mat file
loadedData = load(matFilePath);
% Get field names
dataFieldNames = fieldnames(loadedData);
% Process single field
if length(dataFieldNames) == 1
data = loadedData.(dataFieldNames{1});
% Handle table data
if istable(data)
[filePath, fileName, ~] = fileparts(matFilePath);
outputPath = fullfile(filePath, [fileName, '.csv']);
writetable(data, outputPath);
% Handle structure or other data types
else
[filePath, fileName, ~] = fileparts(matFilePath);
outputPath = fullfile(filePath, [fileName, '.json']);
% Convert to JSON
if isstruct(data)
jsonStr = jsonencode(data);
else
jsonStr = jsonencode(data);
end
% Write JSON file
writeJSON(outputPath, jsonStr);
end
% Process multiple fields
elseif length(dataFieldNames) > 1
% Combine all fields into one structure
allData = struct();
for idx = 1:length(dataFieldNames)
fieldName = dataFieldNames{idx};
allData.(fieldName) = loadedData.(fieldName);
end
% Save as JSON
[filePath, fileName, ~] = fileparts(matFilePath);
outputPath = fullfile(filePath, [fileName, '.json']);
writeJSON(outputPath, jsonencode(allData));
else
warning('File contains no variables: %s', matFilePath);
return;
end
% Set success status
status = true;
fprintf('Converted %s to %s\n', matFilePath, outputPath);
catch ME
warning('Failed to convert file %s: %s', matFilePath, ME.message);
return;
end
end
function writeJSON(filepath, jsonStr)
fid = fopen(filepath, 'w');
if fid == -1
error('Cannot create JSON file: %s', filepath);
end
fwrite(fid, jsonStr, 'char');
fclose(fid);
end
% function that parses commanline parameters
function params = parseInputArgs(varargin)
% Create an input parser
p = inputParser;
p.CaseSensitive = false;
p.KeepUnmatched = true;
% Define the required parameters
addParameter(p, 'input_dir', '', @ischar);
addParameter(p, 'output_dir', '', @ischar);
addParameter(p, 'parameter_file', '', @ischar);
addParameter(p, 'sample_name', '', @ischar);
addParameter(p, 'stage', '', @ischar);
addParameter(p, 'NM_variables', '', @ischar);
% Parse the inputs
parse(p, varargin{:});
% Get the values of the parameters
params.input_dir = p.Results.input_dir;
params.output_dir = p.Results.output_dir;
params.parameter_file = p.Results.parameter_file;
params.sample_name = p.Results.sample_name;
params.stage = p.Results.stage;
params.NM_variables = p.Results.NM_variables;
% Check if required arguments exsit
if isempty (params.input_dir)
error('Input directory is required');
end
if isempty (params.output_dir)
error('Output directory is required');
end
if isempty (params.parameter_file)
error('Parameter file is required');
end
if isempty (params.sample_name)
error('Sample name is required');
end
if isempty (params.stage)
error('Stage is required');
end
end