Mercurial > repos > perssond > basic_illumination
comparison imagej_basic_ashlar.py @ 0:fd8dfd64f25e draft
"planemo upload for repository https://github.com/ohsu-comp-bio/basic-illumination commit a8d2367c8c66eecfc2586a593acc8547a7f8611c-dirty"
author | perssond |
---|---|
date | Fri, 12 Mar 2021 00:13:46 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:fd8dfd64f25e |
---|---|
1 # @File(label="Select a slide to process") filename | |
2 # @File(label="Select the output location", style="directory") output_dir | |
3 # @String(label="Experiment name (base name for output files)") experiment_name | |
4 # @Float(label="Flat field smoothing parameter (0 for automatic)", value=0.1) lambda_flat | |
5 # @Float(label="Dark field smoothing parameter (0 for automatic)", value=0.01) lambda_dark | |
6 | |
7 # Takes a slide (or other multi-series BioFormats-compatible file set) and | |
8 # generates flat- and dark-field correction profile images with BaSiC. The | |
9 # output format is two multi-series TIFF files (one for flat and one for dark) | |
10 # which is the input format used by Ashlar. | |
11 | |
12 # Invocation for running from the commandline: | |
13 # | |
14 # ImageJ --ij2 --headless --run imagej_basic_ashlar.py "filename='input.ext',output_dir='output',experiment_name='my_experiment'" | |
15 | |
16 import sys | |
17 from ij import IJ, WindowManager, Prefs | |
18 from ij.macro import Interpreter | |
19 from loci.plugins import BF | |
20 from loci.plugins.in import ImporterOptions | |
21 from loci.formats import ImageReader | |
22 from loci.formats.in import DynamicMetadataOptions | |
23 import BaSiC_ as Basic | |
24 | |
25 import pdb | |
26 | |
27 | |
28 def main(): | |
29 | |
30 Interpreter.batchMode = True | |
31 | |
32 if (lambda_flat == 0) ^ (lambda_dark == 0): | |
33 print ("ERROR: Both of lambda_flat and lambda_dark must be zero," | |
34 " or both non-zero.") | |
35 return | |
36 lambda_estimate = "Automatic" if lambda_flat == 0 else "Manual" | |
37 | |
38 print "Loading images..." | |
39 | |
40 # For multi-scene .CZI files, we need raw tiles instead of the | |
41 # auto-stitched mosaic and we don't want labels or overview images. This | |
42 # only affects BF.openImagePlus, not direct use of the BioFormats reader | |
43 # classes which we also do (see below) | |
44 Prefs.set("bioformats.zeissczi.allow.autostitch", "false") | |
45 Prefs.set("bioformats.zeissczi.include.attachments", "false") | |
46 | |
47 # Use BioFormats reader directly to determine dataset dimensions without | |
48 # reading every single image. The series count (num_images) is the one value | |
49 # we can't easily get any other way, but we might as well grab the others | |
50 # while we have the reader available. | |
51 dyn_options = DynamicMetadataOptions() | |
52 # Directly calling a BioFormats reader will not use the IJ Prefs settings | |
53 # so we need to pass these options explicitly. | |
54 dyn_options.setBoolean("zeissczi.autostitch", False) | |
55 dyn_options.setBoolean("zeissczi.attachments", False) | |
56 bfreader = ImageReader() | |
57 bfreader.setMetadataOptions(dyn_options) | |
58 bfreader.id = str(filename) | |
59 num_images = bfreader.seriesCount | |
60 num_channels = bfreader.sizeC | |
61 width = bfreader.sizeX | |
62 height = bfreader.sizeY | |
63 bfreader.close() | |
64 | |
65 # The internal initialization of the BaSiC code fails when we invoke it via | |
66 # scripting, unless we explicitly set a the private 'noOfSlices' field. | |
67 # Since it's private, we need to use Java reflection to access it. | |
68 Basic_noOfSlices = Basic.getDeclaredField('noOfSlices') | |
69 Basic_noOfSlices.setAccessible(True) | |
70 basic = Basic() | |
71 Basic_noOfSlices.setInt(basic, num_images) | |
72 | |
73 # Pre-allocate the output profile images, since we have all the dimensions. | |
74 ff_image = IJ.createImage("Flat-field", width, height, num_channels, 32); | |
75 df_image = IJ.createImage("Dark-field", width, height, num_channels, 32); | |
76 | |
77 print("\n\n") | |
78 | |
79 # BaSiC works on one channel at a time, so we only read the images from one | |
80 # channel at a time to limit memory usage. | |
81 for channel in range(num_channels): | |
82 print "Processing channel %d/%d..." % (channel + 1, num_channels) | |
83 print "===========================" | |
84 | |
85 options = ImporterOptions() | |
86 options.id = str(filename) | |
87 options.setOpenAllSeries(True) | |
88 # concatenate=True gives us a single stack rather than a list of | |
89 # separate images. | |
90 options.setConcatenate(True) | |
91 # Limit the reader to the channel we're currently working on. This loop | |
92 # is mainly why we need to know num_images before opening anything. | |
93 for i in range(num_images): | |
94 options.setCBegin(i, channel) | |
95 options.setCEnd(i, channel) | |
96 # openImagePlus returns a list of images, but we expect just one (a | |
97 # stack). | |
98 input_image = BF.openImagePlus(options)[0] | |
99 | |
100 # BaSiC seems to require the input image is actually the ImageJ | |
101 # "current" image, otherwise it prints an error and aborts. | |
102 WindowManager.setTempCurrentImage(input_image) | |
103 basic.exec( | |
104 input_image, None, None, | |
105 "Estimate shading profiles", "Estimate both flat-field and dark-field", | |
106 lambda_estimate, lambda_flat, lambda_dark, | |
107 "Ignore", "Compute shading only" | |
108 ) | |
109 input_image.close() | |
110 | |
111 # Copy the pixels from the BaSiC-generated profile images to the | |
112 # corresponding channel of our output images. | |
113 ff_channel = WindowManager.getImage("Flat-field:%s" % input_image.title) | |
114 ff_image.slice = channel + 1 | |
115 ff_image.getProcessor().insert(ff_channel.getProcessor(), 0, 0) | |
116 ff_channel.close() | |
117 df_channel = WindowManager.getImage("Dark-field:%s" % input_image.title) | |
118 df_image.slice = channel + 1 | |
119 df_image.getProcessor().insert(df_channel.getProcessor(), 0, 0) | |
120 df_channel.close() | |
121 | |
122 print("\n\n") | |
123 | |
124 template = '%s/%s-%%s.tif' % (output_dir, experiment_name) | |
125 ff_filename = template % 'ffp' | |
126 IJ.saveAsTiff(ff_image, ff_filename) | |
127 ff_image.close() | |
128 df_filename = template % 'dfp' | |
129 IJ.saveAsTiff(df_image, df_filename) | |
130 df_image.close() | |
131 | |
132 print "Done!" | |
133 | |
134 | |
135 main() |