Skip to content

Commit db15ca7

Browse files
committed
Add EM tissues segmentation script
1 parent 446e631 commit db15ca7

File tree

1 file changed

+174
-0
lines changed

1 file changed

+174
-0
lines changed
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
#!/usr/bin/python3
2+
# Warning: works only on unix-like systems, not windows where "python3 animaAtlasEMTissuesSegmentation.py ..." has to be run
3+
4+
import sys
5+
import argparse
6+
7+
if sys.version_info[0] > 2:
8+
import configparser as ConfParser
9+
else:
10+
import ConfigParser as ConfParser
11+
12+
import glob
13+
import os
14+
from shutil import copyfile, rmtree
15+
from subprocess import call, check_output
16+
import uuid
17+
18+
configFilePath = os.path.join(os.path.expanduser("~"), ".anima", "config.txt")
19+
if not os.path.exists(configFilePath):
20+
print('Please create a configuration file for Anima python scripts. Refer to the README')
21+
quit()
22+
23+
configParser = ConfParser.RawConfigParser()
24+
configParser.read(configFilePath)
25+
26+
animaDir = configParser.get("anima-scripts", 'anima')
27+
animaExtraDataDir = configParser.get("anima-scripts", 'extra-data-root')
28+
animaPyramidalBMRegistration = os.path.join(animaDir, "animaPyramidalBMRegistration")
29+
animaDenseSVFBMRegistration = os.path.join(animaDir, "animaDenseSVFBMRegistration")
30+
animaTransformSerieXmlGenerator = os.path.join(animaDir, "animaTransformSerieXmlGenerator")
31+
animaApplyTransformSerie = os.path.join(animaDir, "animaApplyTransformSerie")
32+
animaTissuesEMClassification = os.path.join(animaDir, "animaTissuesEMClassification")
33+
animaConvertImage = os.path.join(animaDir, "animaConvertImage")
34+
animaMaskImage = os.path.join(animaDir, "animaMaskImage")
35+
animaThrImage = os.path.join(animaDir, "animaThrImage")
36+
animaN4BiasCorrection = os.path.join(animaDir, "animaN4BiasCorrection")
37+
animaMorphologicalOperations = os.path.join(animaDir, "animaMorphologicalOperations")
38+
39+
# Argument parsing
40+
parser = argparse.ArgumentParser(
41+
description="Computes tissue segmentation from a prior atlas, multiple modalities inputs, and "
42+
"EM tissue classification")
43+
44+
parser.add_argument('-i', '--input', type=str, required=True, action='append',
45+
help='Image input: can give multiple modalities')
46+
parser.add_argument('-a', '--atlas', type=str, help='Atlas folder (default: use the one in anima scripts data '
47+
'- em_prior_atlas folder)')
48+
parser.add_argument('-m', '--mask', type=str, required=True, help='Brain mask of the first input')
49+
50+
parser.add_argument('-o', '--output', type=str, help='Output path of the tissues segmentation '
51+
'(default is inputName_classification.nrrd)')
52+
parser.add_argument('-O', '--classes-output', type=str, help='Output path of the tissues probabilities')
53+
parser.add_argument('-z', '--zsc', type=str, help='Output path of the zscores of classification')
54+
parser.add_argument('-K', '--keep-intermediate-folder', action='store_true',
55+
help='Keep intermediate folder after script end')
56+
parser.add_argument('-P', '--prune-outliers', action='store_true',
57+
help='Remove outliers from the segmentation (according to z-score)')
58+
parser.add_argument('-Z', '--zsc-thr', type=int, default=4,
59+
help='Outliers threshold if -P is activated (default: 4)')
60+
61+
args = parser.parse_args()
62+
63+
numImages = len(sys.argv) - 1
64+
65+
atlasDir = os.path.join(animaExtraDataDir,"em_prior_atlas")
66+
if args.atlas:
67+
atlasDir = args.atlas
68+
69+
atlasImage = os.path.join(atlasDir,"T1.nrrd")
70+
tissuesImage = os.path.join(atlasDir,"Tissue_Probabilities.nrrd")
71+
72+
brainImages = args.input
73+
74+
# Get floating image prefix
75+
brainImagePrefix = os.path.splitext(brainImages[0])[0]
76+
if os.path.splitext(brainImages[0])[1] == '.gz':
77+
brainImagePrefix = os.path.splitext(brainImagePrefix)[0]
78+
79+
tissuesOutputName = args.output if args.output else brainImagePrefix + "_classification.nrrd"
80+
intermediateFolder = os.path.join(os.path.dirname(brainImages[0]), 'em_tissues_' + str(uuid.uuid1()))
81+
82+
if not os.path.isdir(intermediateFolder):
83+
os.mkdir(intermediateFolder)
84+
85+
brainImagePrefix = os.path.join(intermediateFolder, os.path.basename(brainImagePrefix))
86+
87+
# Decide on whether to use large image setting or small image setting
88+
command = [animaConvertImage, "-i", brainImages[0], "-I"]
89+
convert_output = check_output(command, universal_newlines=True)
90+
size_info = convert_output.split('\n')[1].split('[')[1].split(']')[0]
91+
large_image = False
92+
for i in range(0, 3):
93+
size_tmp = int(size_info.split(', ')[i])
94+
if size_tmp >= 350:
95+
large_image = True
96+
break
97+
98+
pyramidOptions = ["-p", "4", "-l", "1"]
99+
if large_image:
100+
pyramidOptions = ["-p", "5", "-l", "2"]
101+
102+
# First preprocess input images
103+
myfileImages = open(os.path.join(intermediateFolder,"listData.txt"),"w")
104+
for i in range(0,len(brainImages)):
105+
currentData = brainImages[i]
106+
if i > 0:
107+
command = [animaPyramidalBMRegistration, "-m", currentData,
108+
"-r", brainImages[0],
109+
"-o", brainImagePrefix + "_rig_onRef_" + str(i) + ".nrrd", "--sp", "3"] + pyramidOptions
110+
call(command)
111+
112+
currentData = brainImagePrefix + '_rig_onRef_' + str(i) + '.nrrd'
113+
114+
command = [animaMaskImage, "-i", currentData, "-m", args.mask,
115+
"-o", brainImagePrefix + '_masked_' + str(i) + '.nrrd']
116+
call(command)
117+
118+
command = [animaN4BiasCorrection, "-i", brainImagePrefix + '_masked_' + str(i) + '.nrrd',
119+
"-o", brainImagePrefix + '_biasCorrected_' + str(i) + '.nrrd']
120+
call(command)
121+
122+
myfileImages.write(brainImagePrefix + '_biasCorrected_' + str(i) + '.nrrd\n')
123+
124+
myfileImages.close()
125+
126+
# Now register prior atlas onto first reference image
127+
command = [animaPyramidalBMRegistration, "-m", atlasImage, "-r", brainImages[0], "-o", brainImagePrefix + "_rig.nrrd",
128+
"-O", brainImagePrefix + "_rig_tr.txt", "--sp", "3"] + pyramidOptions
129+
call(command)
130+
131+
command = [animaPyramidalBMRegistration, "-m", atlasImage, "-r", brainImages[0], "-o", brainImagePrefix + "_aff.nrrd",
132+
"-O", brainImagePrefix + "_aff_tr.txt", "-i", brainImagePrefix + "_rig_tr.txt", "--sp", "3", "--ot",
133+
"2"] + pyramidOptions
134+
call(command)
135+
136+
command = [animaDenseSVFBMRegistration, "-r", brainImages[0], "-m", brainImagePrefix + "_aff.nrrd",
137+
"-o", brainImagePrefix + "_nl.nrrd", "-O", brainImagePrefix + "_nl_tr.nrrd", "--tub", "2"] + pyramidOptions
138+
call(command)
139+
140+
command = [animaTransformSerieXmlGenerator, "-i", brainImagePrefix + "_aff_tr.txt", "-i",
141+
brainImagePrefix + "_nl_tr.nrrd", "-o", brainImagePrefix + "_nl_tr.xml"]
142+
call(command)
143+
144+
command = [animaApplyTransformSerie, "-i", tissuesImage, "-t", brainImagePrefix + "_nl_tr.xml", "-g", brainImages[0],
145+
"-o", brainImagePrefix + "_PriorTissues.nrrd"]
146+
call(command)
147+
148+
# Finally, run classification step
149+
command = [animaTissuesEMClassification, "-i", os.path.join(intermediateFolder,"listData.txt"),
150+
"-m", args.mask, "-t", brainImagePrefix + "_PriorTissues.nrrd", "-o", tissuesOutputName]
151+
152+
if args.classes_output:
153+
command = command + ["-O", args.classes_output]
154+
155+
zscOut = args.zsc
156+
157+
if not args.zsc and args.prune_outliers is True:
158+
zscOut = brainImagePrefix + "_zsc.nrrd"
159+
160+
if zscOut:
161+
command = command + ["-z", zscOut]
162+
163+
call(command)
164+
165+
if args.prune_outliers is True:
166+
command = [animaThrImage, "-i", zscOut, "-t", str(args.zsc_thr), "-o", brainImagePrefix + "_WrongMask.nrrd", "-I"]
167+
call(command)
168+
169+
command = [animaMaskImage, "-i", tissuesOutputName, "-m", brainImagePrefix + "_WrongMask.nrrd",
170+
"-o", tissuesOutputName]
171+
call(command)
172+
173+
if not args.keep_intermediate_folder:
174+
rmtree(intermediateFolder)

0 commit comments

Comments
 (0)