Skip to content

Commit

Permalink
ENH: Add option for UNIX path sep for voxel-based output
Browse files Browse the repository at this point in the history
This allows the user to force the path separators in the output to be "/", even when running on Windows-based systems.
  • Loading branch information
JoostJM committed May 17, 2019
1 parent fab347b commit 3c0708a
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 8 deletions.
15 changes: 13 additions & 2 deletions radiomics/scripts/__init__.py
Expand Up @@ -97,6 +97,9 @@ def getParser(cls):
'"absolute" (Default): Absolute file paths.\n'
'"relative": File paths relative to current working directory.\n'
'"basename": Only stores filename.')
outputGroup.add_argument('--unix-path', '-up', action='store_true',
help='If specified, ensures that all paths in the output\n'
'use unix-style path separators ("/").')

loggingGroup = parser.add_argument_group(title='Logging',
description='Controls the (amount of) logging output to the '
Expand Down Expand Up @@ -241,7 +244,8 @@ def _processCases(self, case_generator):
task = pool.map_async(partial(self.parallel_func,
extractor=extractor,
out_dir=self.args.out_dir,
logging_config=self.logging_config),
logging_config=self.logging_config,
unix_path=self.args.unix_path),
case_generator,
chunksize=min(10, self.case_count))
# Wait for the results to be done. task.get() without timeout performs a blocking call, which prevents
Expand All @@ -260,7 +264,10 @@ def _processCases(self, case_generator):
self.case_count)
results = []
for case in case_generator:
results.append(self.serial_func(*case, extractor=extractor, out_dir=self.args.out_dir))
results.append(self.serial_func(*case,
extractor=extractor,
out_dir=self.args.out_dir,
unix_path=self.args.unix_path))
else:
# No cases defined in the batch
self.logger.error('No cases to process...')
Expand Down Expand Up @@ -305,6 +312,10 @@ def _processOutput(self, results):
case['Image'] = pathFormatter(case['Image'])
case['Mask'] = pathFormatter(case['Mask'])

if self.args.unix_path and os.path.sep != '/':
case['Image'] = case['Image'].replace(os.path.sep, '/')
case['Mask'] = case['Mask'].replace(os.path.sep, '/')

# Write out results per case if format is 'csv' or 'txt', handle 'json' outside of this loop (issue #483)
if self.args.format == 'csv':
writer = csv.DictWriter(self.args.out, headers, lineterminator='\n', extrasaction='ignore')
Expand Down
8 changes: 5 additions & 3 deletions radiomics/scripts/segment.py
Expand Up @@ -14,9 +14,11 @@
_parallel_extraction_configured = False


def extractSegment(case_idx, case, extractor, out_dir):
def extractSegment(case_idx, case, extractor, **kwargs):
global caseLogger

out_dir = kwargs.get('out_dir', None)

if out_dir is None:
return _extractFeatures(case_idx, case, extractor)

Expand Down Expand Up @@ -82,15 +84,15 @@ def _extractFeatures(case_idx, case, extractor):
return feature_vector


def extractSegment_parallel(args, extractor, out_dir=None, logging_config=None):
def extractSegment_parallel(args, logging_config=None, **kwargs):
try:
# set thread name to patient name
threading.current_thread().name = 'case %s' % args[0] # args[0] = case_idx

if logging_config is not None:
_configureParallelExtraction(logging_config)

return extractSegment(*args, extractor=extractor, out_dir=out_dir)
return extractSegment(*args, **kwargs)
except (KeyboardInterrupt, SystemExit):
# Catch the error here, as this represents the interrupt of the child process.
# The main process is also interrupted, and cancellation is further handled there
Expand Down
11 changes: 8 additions & 3 deletions radiomics/scripts/voxel.py
Expand Up @@ -13,9 +13,12 @@
_parallel_extraction_configured = False


def extractVoxel(case_idx, case, extractor, out_dir):
def extractVoxel(case_idx, case, extractor, **kwargs):
global caseLogger

out_dir = kwargs.get('out_dir', None)
unix_path = kwargs.get('unix_path', False)

# Instantiate the output
feature_vector = OrderedDict(case)

Expand Down Expand Up @@ -45,6 +48,8 @@ def extractVoxel(case_idx, case, extractor, out_dir):
if isinstance(result[k], sitk.Image):
target = os.path.join(out_dir, 'Case-%i_%s.nrrd' % (case_idx, k))
sitk.WriteImage(result[k], target, True)
if unix_path and os.path.sep != '/':
target = target.replace(os.path.sep, '/')
feature_vector[k] = target
else:
feature_vector[k] = result[k]
Expand All @@ -64,15 +69,15 @@ def extractVoxel(case_idx, case, extractor, out_dir):
return feature_vector


def extractVoxel_parallel(args, extractor, out_dir=None, logging_config=None):
def extractVoxel_parallel(args, logging_config=None, **kwargs):
try:
# set thread name to patient name
threading.current_thread().name = 'case %s' % args[0] # args[0] = case_idx

if logging_config is not None:
_configureParallelExtraction(logging_config)

return extractVoxel(*args, extractor=extractor, out_dir=out_dir)
return extractVoxel(*args, **kwargs)
except (KeyboardInterrupt, SystemExit):
# Catch the error here, as this represents the interrupt of the child process.
# The main process is also interrupted, and cancellation is further handled there
Expand Down

0 comments on commit 3c0708a

Please sign in to comment.