def execute_extraction(extractor, scan_path, msk_path, day_name, voxelbased, verbose): if verbose: rad.setVerbosity(20) print('Extracting features...') t0 = time.time() if voxelbased: results = extractor.execute(scan_path, msk_path, voxelBased=True) else: results = extractor.execute(scan_path, msk_path) features_list = get_features_list(results, extractor) data = {'Day':day_name} for feat in features_list: data[feat] = results[feat] tf = time.time() print('Feature extraction completed') if (tf-t0) > 3600: print('\tElapsed Time: %f hours'%((tf-t0)/3600)) elif (tf-t0) > 60: print('\tElapsed Time: %f min'%((tf-t0)/60)) else: print('\tElapsed Time: %f sec'%(tf-t0)) return data
def extract_features_from_image(imagePath, maskPath, paramsPath): """ ACTION: Extract radiomic features from one image, given mask and parameters, and return a dictionary with the feature values INPUT: imagePath: path to image nrrd-file (without extension) maskPath: path to mask nrrd-file (without extension) paramsPath: path to file with radiomic feature extraction settings OUTPUT: dictionary with all extracted features """ img = imagePath + ".nrrd" mask = maskPath + ".nrrd" if not os.path.isfile(img): raise IOError('File does not exist: %s' % img) elif not os.path.isfile(mask): raise IOError('File does not exist: %s' % mask) elif not os.path.isfile(paramsPath): raise IOError('File does not exist: %s' % paramsPath) extractor = featureextractor.RadiomicsFeatureExtractor(paramsPath) setVerbosity( 40 ) # Set level of verbosity, 40=Errors, 30=Warnings, 20=Info, 10=Debug results = extractor.execute(img, mask) return results
def _configureLogging(args): global scriptlogger, logging_config # Initialize Logging logLevel = getattr(logging, args.logging_level) rLogger = radiomics.logger logging_config['logLevel'] = logLevel fmt = logging.Formatter( "[%(asctime)-.19s] %(levelname)-.1s: %(name)s: %(message)s") rLogger.handlers[0].setFormatter(fmt) # Set up optional logging to file if args.log_file is not None: logging_config['logFile'] = args.log_file logHandler = logging.FileHandler(filename=args.log_file, mode='a') logHandler.setFormatter(fmt) logHandler.setLevel(logLevel) rLogger.addHandler(logHandler) if rLogger.level > logHandler.level: rLogger.level = logHandler.level # Set verbosity of output (stderr) verboseLevel = (6 - args.verbosity) * 10 # convert to python logging level radiomics.setVerbosity(verboseLevel) logging_config['verbosity'] = verboseLevel scriptlogger.debug('Logging initialized')
def main(): args = parser.parse_args() # Initialize Logging logLevel = getattr(logging, args.logging_level) rLogger = radiomics.logger # Set up optional logging to file if args.log_file is not None: rLogger.setLevel(logLevel) handler = logging.StreamHandler(args.log_file) handler.setFormatter( logging.Formatter("%(levelname)s:%(name)s: %(message)s")) rLogger.addHandler(handler) # Set verbosity of output (stderr) verboseLevel = (6 - args.verbosity) * 10 # convert to python logging level radiomics.setVerbosity(verboseLevel) # Initialize logging for script log messages logger = rLogger.getChild('script') # Initialize extractor try: if args.param is not None: extractor = featureextractor.RadiomicsFeaturesExtractor( args.param[0]) else: extractor = featureextractor.RadiomicsFeaturesExtractor() logger.info( 'Extracting features with kwarg settings: %s\n\tImage: %s\n\tMask: %s', str(extractor.kwargs), os.path.abspath(args.image), os.path.abspath(args.mask)) featureVector = collections.OrderedDict() featureVector['image'] = os.path.basename(args.image) featureVector['mask'] = os.path.basename(args.mask) featureVector.update( extractor.execute(args.image, args.mask, args.label)) if args.format == 'csv': writer = csv.writer(args.out, lineterminator='\n') writer.writerow(list(featureVector.keys())) writer.writerow(list(featureVector.values())) elif args.format == 'json': json.dump(featureVector, args.out) args.out.write('\n') else: for k, v in six.iteritems(featureVector): args.out.write('%s: %s\n' % (k, v)) except Exception: logger.error('FEATURE EXTRACTION FAILED:\n%s', traceback.format_exc()) args.out.close() if args.log_file is not None: args.log_file.close()
def _configurParallelExtraction(parallel_config): """ Initialize logging for parallel extraction. This needs to be done here, as it needs to be done for each thread that is created. """ # Configure logging ################### rLogger = logging.getLogger('radiomics') # Add logging to file is specified logFile = parallel_config.get('logFile', None) if logFile is not None: logHandler = logging.FileHandler(filename=logFile, mode='a') logHandler.setLevel(parallel_config.get('logLevel', logging.INFO)) rLogger.addHandler(logHandler) # Include thread name in Log-message output for all handlers. parallelFormatter = logging.Formatter( '[%(asctime)-.19s] %(levelname)-.1s: (%(threadName)s) %(name)s: %(message)s' ) for h in rLogger.handlers: h.setFormatter(parallelFormatter) if parallel_config.get('addFilter', True): # Define filter that allows messages from specified filter and level INFO and up, and level WARNING and up from # other loggers. class info_filter(logging.Filter): def __init__(self, name): super(info_filter, self).__init__(name) self.level = logging.WARNING def filter(self, record): if record.levelno >= self.level: return True if record.name == self.name and record.levelno >= logging.INFO: return True return False # Adding the filter to the first handler of the radiomics logger limits the info messages on the output to just # those from radiomics.script, but warnings and errors from the entire library are also printed to the output. # This does not affect the amount of logging stored in the log file. outputhandler = rLogger.handlers[0] # Handler printing to the output outputhandler.addFilter(info_filter('radiomics.script')) # Ensures that log messages are being passed to the filter with the specified level setVerbosity(parallel_config.get('verbosity', logging.INFO)) # Ensure the entire extraction for each cases is handled on 1 thread #################################################################### sitk.ProcessObject_SetGlobalDefaultNumberOfThreads(1)
def tqdmProgressbar(): """ This function will setup the progress bar exposed by the 'tqdm' package. Progress reporting is only used in PyRadiomics for the calculation of GLCM and GLSZM in full python mode, therefore enable GLCM and full-python mode to show the progress bar functionality N.B. This function will only work if the 'click' package is installed (not included in the PyRadiomics requirements) """ global extractor radiomics.setVerbosity(logging.INFO) # Verbosity must be at least INFO to enable progress bar import tqdm radiomics.progressReporter = tqdm.tqdm
def onApplyButton(self): if self.debuggingCheckBox.checked: # Setup debug logging for the pyradiomics toolbox # PyRadiomics logs to stderr by default, which is picked up by slicer and added to the slicer log. radiomics.setVerbosity(logging.DEBUG) else: radiomics.setVerbosity(logging.WARNING) if not self.outputTableSelector.currentNode(): tableNode = slicer.vtkMRMLTableNode() slicer.mrmlScene.AddNode(tableNode) self.outputTableSelector.setCurrentNode(tableNode) logic = SlicerRadiomicsLogic() featureClasses = self.getCheckedFeatureClasses() # Lock GUI self.applyButton.text = 'Working...' self.applyButton.setEnabled(False) slicer.app.processEvents() # Compute features kwargs = {} kwargs['binWidth'] = int(self.binWidthSliderWidget.value) kwargs['symmetricalGLCM'] = self.symmetricalGLCMCheckBox.checked # kwargs['label'] = int(self.labelSliderWidget.value) imageNode = self.inputVolumeSelector.currentNode() labelNode = self.inputMaskSelector.currentNode() segmentationNode = self.inputSegmentationSelector.currentNode() try: featuresDict = logic.run(imageNode, labelNode, segmentationNode, featureClasses, **kwargs) logic.exportToTable(featuresDict, self.outputTableSelector.currentNode()) except: self.logger.error("Feature calculation failed.") # Unlock GUI self.applyButton.setEnabled(True) self.applyButton.text = 'Apply' # Show results logic.showTable(self.outputTableSelector.currentNode())
def run_main(subject_dirs, aseg_file, labels, results_csv): LUT = lut_parse() print(results_csv) with open(results_csv, 'w') as out_file: writer = csv.writer(out_file, delimiter=',') header = None for subjects_dir in subject_dirs: for subject_name in sorted(os.listdir(subjects_dir)): fname = '{}/{}/{}'.format(subjects_dir, subject_name, aseg_file) if not os.path.exists(fname): print('{}: {} not found. Skipping'.format( subject_name, aseg_file)) continue print(subject_name) fields = list() values = list() img = sitk.ReadImage(fname) for label in labels: if ':' in label: label, label_id = label.split(':') else: label_id = LUT[label] radiomics.setVerbosity(50) shape_features = radiomics.shape.RadiomicsShape( img, img, **{'label': int(label_id)}) shape_features.enableAllFeatures() results = shape_features.execute() for key in results.keys(): fields.append('{}.{}'.format(label, key)) values.append( float(results[key] ) if results['VoxelVolume'] > 0 else 'nan') if header is None: header = fields writer.writerow(['Subject'] + header) else: assert header == fields writer.writerow([subject_name] + values)
def clickProgressbar(): """ This function will setup the progress bar exposed by the 'click' package. Progress reporting is only used in PyRadiomics for the calculation of GLCM and GLSZM in full python mode, therefore enable GLCM and full-python mode to show the progress bar functionality. Because the signature used to instantiate a click progress bar is different from what PyRadiomics expects, we need to write a simple wrapper class to enable use of a click progress bar. In this case we only need to change the 'desc' keyword argument to a 'label' keyword argument. N.B. This function will only work if the 'click' package is installed (not included in the PyRadiomics requirements) """ global extractor extractor.kwargs['enableCExtensions'] = False # Enable the GLCM class to show the progress bar extractor.enableFeatureClassByName('glcm') radiomics.setVerbosity( logging.INFO) # Verbosity must be at least INFO to enable progress bar import click class progressWrapper(): def __init__(self, iterable, desc=''): # For a click progressbar, the description must be provided in the 'label' keyword argument. self.bar = click.progressbar(iterable, label=desc) def __iter__(self): return self.bar.__iter__( ) # Redirect to the __iter__ function of the click progressbar def __enter__(self): return self.bar.__enter__( ) # Redirect to the __enter__ function of the click progressbar def __exit__(self, exc_type, exc_value, tb): return self.bar.__exit__( exc_type, exc_value, tb ) # Redirect to the __exit__ function of the click progressbar radiomics.progressReporter = progressWrapper
def main(): args = parser.parse_args() # Initialize Logging logLevel = getattr(logging, args.logging_level) rLogger = radiomics.logger # Set up optional logging to file if args.log_file is not None: rLogger.setLevel(logLevel) handler = logging.StreamHandler(args.log_file) handler.setFormatter( logging.Formatter("%(levelname)s:%(name)s: %(message)s")) rLogger.addHandler(handler) # Set verbosity of output (stderr) verboseLevel = (6 - args.verbosity) * 10 # convert to python logging level radiomics.setVerbosity(verboseLevel) # Initialize logging for script log messages logger = rLogger.getChild('batch') # Load patient list flists = [] try: cr = csv.reader(args.inFile, lineterminator='\n') flists = [row for row in cr] args.inFile.close() except Exception: logging.error('CSV READ FAILED:\n%s', traceback.format_exc()) args.inFile.close() args.outFile.close() if args.log_file is not None: args.log_file.close() exit(-1) # Initialize extractor try: logger.debug("Initializing extractor") if args.param is not None: extractor = featureextractor.RadiomicsFeaturesExtractor( args.param[0]) else: extractor = featureextractor.RadiomicsFeaturesExtractor() except Exception: logger.error('EXTRACTOR INITIALIZATION FAILED:\n%s', traceback.format_exc()) args.outFile.close() args.log_file.close() exit(-1) # Extract features logger.info('Extracting features with kwarg settings: %s', str(extractor.kwargs)) headers = None for idx, entry in enumerate(flists, start=1): logger.info("(%d/%d) Processing Patient: %s, Study: %s, Reader: %s", idx, len(flists), entry[0], entry[1], entry[2]) imageFilepath = entry[3] maskFilepath = entry[4] if (imageFilepath is not None) and (maskFilepath is not None): featureVector = collections.OrderedDict() featureVector['PatientID'] = entry[0] featureVector['Study'] = entry[1] featureVector['Reader'] = entry[2] featureVector['image'] = os.path.basename(imageFilepath) featureVector['mask'] = os.path.basename(maskFilepath) try: featureVector.update( extractor.execute(imageFilepath, maskFilepath, args.label)) if args.format == 'csv': writer = csv.writer(args.outFile, lineterminator='\n') if headers is None: headers = list(featureVector.keys()) writer.writerow(headers) row = [] for h in headers: row.append(featureVector.get(h, "N/A")) writer.writerow(row) elif args.format == 'json': json.dump(featureVector, args.out) args.out.write('\n') except Exception: logger.error('FEATURE EXTRACTION FAILED:\n%s', traceback.format_exc()) args.outFile.close() if args.log_file is not None: args.log_file.close()
CASES = six.moves.range(1, 6) TYPES = ['', '_Combined'] IBSI_BINNING = False IBSI_RESAMPLING = False GRAY_VALUE_ROUNDING = True #""" rLogger = radiomics.logger logHandler = logging.FileHandler(filename='results/IBSIlog.log', mode='w') logHandler.setLevel(logging.DEBUG) logHandler.setFormatter(logging.Formatter('%(levelname)-.1s: %(name)s: %(message)s')) rLogger.setLevel(logging.DEBUG) rLogger.addHandler(logHandler) setVerbosity(logging.INFO) # """ ibsiLogger = logging.getLogger('radiomics.ibsi') def run_phantom(): global TYPES ibsiLogger.info('################################### Extracting Phantom #############################') extractor = featureextractor.RadiomicsFeaturesExtractor() image = sitk.ReadImage(os.path.join('data', 'digital_phantom', 'Phantom.nrrd')) mask = sitk.ReadImage(os.path.join('data', 'digital_phantom', 'Phantom-label.nrrd')) result_series = pd.Series() extraction_mode = ('2D', '3D')
def main(): ###给出基本路径 params_path = r'E:\Radiomics\huaxi_jiang_yinjie\feature' base_outpath = r'E:\Radiomics\huaxi_jiang_yinjie\feature' base_dicom_nii_path = r'G:\West China Hospotal-Gastric Cancer SRCC\NRRD' series = 'pre' ##给定序列号 AP pre PVP outPath = os.path.join(base_outpath, series) dicom_nii_path = os.path.join(base_dicom_nii_path, series)###原始图片转换成nrrd文件 ###给出输入输出文件路径 inputCSV = os.path.join(outPath, 'presample_nii_path.csv')###文件中是分割文件的路径 'AP PVP pre' outputFilepath = os.path.join(outPath, 'radiomics_SRCC_pre_Primary.csv') ###记得更改不同的特征名称 'AP PVP pre' progress_filename = os.path.join(outPath, 'pyrad_log.txt') # params = os.path.join(outPath, 'exampleSettings', 'Params.yaml') params = os.path.join(params_path, 'exampleCT.yaml') # Configure logging rLogger = logging.getLogger('radiomics') # Set logging level # rLogger.setLevel(logging.INFO) # Not needed, default log level of logger is INFO # Create handler for writing to log file handler = logging.FileHandler(filename=progress_filename, mode='w') handler.setFormatter(logging.Formatter('%(levelname)s:%(name)s: %(message)s')) rLogger.addHandler(handler) # Initialize logging for batch log messages logger = rLogger.getChild('batch') # Set verbosity level for output to stderr (default level = WARNING) radiomics.setVerbosity(logging.INFO) logger.info('pyradiomics version: %s', radiomics.__version__) logger.info('Loading CSV') flists = [] try: with open(inputCSV, 'r') as inFile: cr = csv.DictReader(inFile, lineterminator='\n') flists = [row for row in cr] except Exception: logger.error('CSV READ FAILED', exc_info=True) logger.info('Loading Done') logger.info('Patients: %d', len(flists)) if os.path.isfile(params): extractor = featureextractor.RadiomicsFeatureExtractor(params) else: # Parameter file not found, use hardcoded settings instead settings = {} settings['binWidth'] = 25 settings['resampledPixelSpacing'] = None # [3,3,3] settings['interpolator'] = sitk.sitkBSpline settings['enableCExtensions'] = True extractor = featureextractor.RadiomicsFeatureExtractor(**settings) # extractor.enableInputImages(wavelet= {'level': 2}) logger.info('Enabled input images types: %s', extractor.enabledImagetypes) logger.info('Enabled features: %s', extractor.enabledFeatures) logger.info('Current settings: %s', extractor.settings) headers = None for idx, entry in enumerate(flists, start=1): newname = entry['name'] + '.nrrd'#####改名字 # logger.info("(%d/%d) Processing Patient (Image: %s, Mask: %s)", idx, len(flists), entry['Image'], entry['Mask']) logger.info("(%d/%d) Processing Patient (Image: %s, Mask: %s)", idx, len(flists), os.path.join(dicom_nii_path, newname), entry['path'])###更改mask_path和primary名称 # imageFilepath = entry['Image'] # maskFilepath = entry['Mask'] imageFilepath = os.path.join(dicom_nii_path, newname) # maskFilepath = entry['primary']###更改原发灶和淋巴结 maskFilepath = entry['path'] ###更改原发灶和淋巴结 label = entry.get('Label', None) if str(label).isdigit(): label = int(label) else: label = None if (imageFilepath is not None) and (maskFilepath is not None): featureVector = collections.OrderedDict(entry) featureVector['Image'] = os.path.basename(imageFilepath) featureVector['Mask'] = os.path.basename(maskFilepath) try: featureVector.update(extractor.execute(imageFilepath, maskFilepath, label)) with open(outputFilepath, 'a') as outputFile: writer = csv.writer(outputFile, lineterminator='\n') if headers is None: headers = list(featureVector.keys()) writer.writerow(headers) row = [] for h in headers: row.append(featureVector.get(h, "N/A")) writer.writerow(row) except Exception: logger.error('FEATURE EXTRACTION FAILED', exc_info=True)
def main(): outPath = r'E:\Git-Repos\PyRadiomicsNKI\pyradiomics-API' inputCSV = outPath + os.path.sep + "TestCases.csv" outputFilepath = outPath + os.path.sep + "radiomics_features.csv" progress_filename = outPath + os.path.sep + "pyrad_log.txt" # Configure logging rLogger = logging.getLogger('radiomics') # Set logging level # rLogger.setLevel(logging.INFO) # Not needed, default log level of logger is INFO # Create handler for writing to log file handler = logging.FileHandler(filename=progress_filename, mode='w') handler.setFormatter( logging.Formatter("%(levelname)s:%(name)s: %(message)s")) rLogger.addHandler(handler) # Initialize logging for batch log messages logger = rLogger.getChild('batch') # Set verbosity level for output to stderr (default level = WARNING) radiomics.setVerbosity(logging.INFO) logger.info('Loading CSV') flists = [] try: with open(inputCSV, 'r') as inFile: cr = csv.DictReader(inFile, lineterminator='\n') flists = [row for row in cr] except Exception: logging.error('CSV READ FAILED', exc_info=True) logger.info('Loading Done') logger.info('Patients: %d', len(flists)) kwargs = {} kwargs['binWidth'] = 25 kwargs['resampledPixelSpacing'] = None # [3,3,3] kwargs['interpolator'] = sitk.sitkBSpline kwargs['enableCExtensions'] = False logger.info('pyradiomics version: %s', radiomics.__version__) logger.info('Extracting features with kwarg settings: %s', str(kwargs)) extractor = featureextractor.RadiomicsFeaturesExtractor(**kwargs) extractor.enableInputImages(Original={}) # extractor.enableInputImages(wavelet= {'level': 2}) headers = None for idx, entry in enumerate(flists, start=1): logger.info("(%d/%d) Processing Patient (Image: %s, Mask: %s)", idx, len(flists), entry['Image'], entry['Mask']) imageFilepath = entry['Image'] maskFilepath = entry['Mask'] if (imageFilepath is not None) and (maskFilepath is not None): featureVector = collections.OrderedDict(entry) featureVector['Image'] = os.path.basename(imageFilepath) featureVector['Mask'] = os.path.basename(maskFilepath) try: featureVector.update( extractor.execute(imageFilepath, maskFilepath)) with open(outputFilepath, 'a') as outputFile: writer = csv.writer(outputFile, lineterminator='\n') if headers is None: headers = list(featureVector.keys()) writer.writerow(headers) row = [] for h in headers: row.append(featureVector.get(h, "N/A")) writer.writerow(row) except Exception: logger.error('FEATURE EXTRACTION FAILED', exc_info=True)
def execute_extraction_pipeline(patient_name, day_name, organ, voxelbased=False, verbose=False): if verbose: rad.setVerbosity(50)
def main(): outPath = r'' inputCSV = os.path.join(outPath, 'testCases.csv') outputFilepath = os.path.join(outPath, 'radiomics_features.csv') progress_filename = os.path.join(outPath, 'pyrad_log.txt') params = os.path.join(outPath, 'exampleSettings', 'Params.yaml') # Configure logging rLogger = logging.getLogger('radiomics') # Set logging level # rLogger.setLevel(logging.INFO) # Not needed, default log level of logger is INFO # Create handler for writing to log file handler = logging.FileHandler(filename=progress_filename, mode='w') handler.setFormatter(logging.Formatter('%(levelname)s:%(name)s: %(message)s')) rLogger.addHandler(handler) # Initialize logging for batch log messages logger = rLogger.getChild('batch') # Set verbosity level for output to stderr (default level = WARNING) radiomics.setVerbosity(logging.INFO) logger.info('pyradiomics version: %s', radiomics.__version__) logger.info('Loading CSV') # ####### Up to this point, this script is equal to the 'regular' batchprocessing script ######## try: # Use pandas to read and transpose ('.T') the input data # The transposition is needed so that each column represents one test case. This is easier for iteration over # the input cases flists = pandas.read_csv(inputCSV).T except Exception: logger.error('CSV READ FAILED', exc_info=True) exit(-1) logger.info('Loading Done') logger.info('Patients: %d', len(flists.columns)) if os.path.isfile(params): extractor = featureextractor.RadiomicsFeatureExtractor(params) else: # Parameter file not found, use hardcoded settings instead settings = {} settings['binWidth'] = 25 settings['resampledPixelSpacing'] = None # [3,3,3] settings['interpolator'] = sitk.sitkBSpline settings['enableCExtensions'] = True extractor = featureextractor.RadiomicsFeatureExtractor(**settings) # extractor.enableInputImages(wavelet= {'level': 2}) logger.info('Enabled input images types: %s', extractor.enabledImagetypes) logger.info('Enabled features: %s', extractor.enabledFeatures) logger.info('Current settings: %s', extractor.settings) # Instantiate a pandas data frame to hold the results of all patients results = pandas.DataFrame() for entry in flists: # Loop over all columns (i.e. the test cases) logger.info("(%d/%d) Processing Patient (Image: %s, Mask: %s)", entry + 1, len(flists), flists[entry]['Image'], flists[entry]['Mask']) imageFilepath = flists[entry]['Image'] maskFilepath = flists[entry]['Mask'] label = flists[entry].get('Label', None) if str(label).isdigit(): label = int(label) else: label = None if (imageFilepath is not None) and (maskFilepath is not None): featureVector = flists[entry] # This is a pandas Series featureVector['Image'] = os.path.basename(imageFilepath) featureVector['Mask'] = os.path.basename(maskFilepath) try: # PyRadiomics returns the result as an ordered dictionary, which can be easily converted to a pandas Series # The keys in the dictionary will be used as the index (labels for the rows), with the values of the features # as the values in the rows. result = pandas.Series(extractor.execute(imageFilepath, maskFilepath, label)) featureVector = featureVector.append(result) except Exception: logger.error('FEATURE EXTRACTION FAILED:', exc_info=True) # To add the calculated features for this case to our data frame, the series must have a name (which will be the # name of the column. featureVector.name = entry # By specifying an 'outer' join, all calculated features are added to the data frame, including those not # calculated for previous cases. This also ensures we don't end up with an empty frame, as for the first patient # it is 'joined' with the empty data frame. results = results.join(featureVector, how='outer') # If feature extraction failed, results will be all NaN logger.info('Extraction complete, writing CSV') # .T transposes the data frame, so that each line will represent one patient, with the extracted features as columns results.T.to_csv(outputFilepath, index=False, na_rep='NaN') logger.info('CSV writing complete')
features = {} for key, value in result.items(): features[key] = value df = pd.DataFrame(result.items()) df.to_csv(Output_path) if __name__ == "__main__": descr = 'Extraction features from image with a given mask. Image path, mask path and output path must be in a list with 3 columns' parser = argparse.ArgumentParser(description=descr) parser.add_argument('path_list_path', type=str, help='the path of list of path') parser.add_argument( 'bin_count', type=int, help='number if the bin of the istogram. Must be between 30 and 130') parser.add_argument('-v', '--verbosity', type=int, choices=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], default=0, help='increase verbosity of the output') args = parser.parse_args() radiomics.setVerbosity(args.verbosity) EstrattoreFeaturesADC(args.path_list_path, args.bin_count)
def main(): args = parser.parse_args() # Initialize Logging logLevel = getattr(logging, args.logging_level) rLogger = radiomics.logger # Set up optional logging to file if args.log_file is not None: rLogger.setLevel(logLevel) handler = logging.StreamHandler(args.log_file) handler.setFormatter( logging.Formatter("%(levelname)s:%(name)s: %(message)s")) rLogger.addHandler(handler) # Set verbosity of output (stderr) verboseLevel = (6 - args.verbosity) * 10 # convert to python logging level radiomics.setVerbosity(verboseLevel) # Initialize logging for script log messages logger = rLogger.getChild('batch') logger.warning( "This entry point is deprecated. It's enhanced functionality for batch extraction is now available " 'in the "pyradiomics" entry point. See "http://pyradiomics.readthedocs.io/en/latest/usage.html" ' 'for more details.') # Load patient list flists = [] try: cr = csv.DictReader(args.inFile, lineterminator='\n') flists = [row for row in cr] args.inFile.close() # Check if required Image and Mask columns are present if 'Image' not in cr.fieldnames: logger.error( 'Required column "Image" not present in input, unable to extract features...' ) exit(-1) if 'Mask' not in cr.fieldnames: logger.error( 'Required column "Mask" not present in input, unable to extract features...' ) exit(-1) except Exception: logging.error('CSV READ FAILED', exc_info=True) exit(-1) # Initialize extractor try: logger.debug("Initializing extractor") if args.param is not None: extractor = featureextractor.RadiomicsFeaturesExtractor(args.param) else: extractor = featureextractor.RadiomicsFeaturesExtractor() except Exception: logger.error('EXTRACTOR INITIALIZATION FAILED', exc_info=True) exit(-1) # Extract features logger.info('Extracting features with kwarg settings: %s', str(extractor.settings)) headers = None for idx, entry in enumerate(flists, start=1): # Check if the required columns have a value, if not, skip them. if entry['Image'] == '': logger.error( 'Missing value in column "Image", cannot process. Skipping patient (%d/%d)', idx, len(flists)) continue if entry['Mask'] == '': logger.error( 'Missing value in column "Mask", cannot process. Skipping patient (%d/%d)', idx, len(flists)) continue logger.info("(%d/%d) Processing Patient (Image: %s, Mask: %s)", idx, len(flists), entry['Image'], entry['Mask']) imageFilepath = entry['Image'] maskFilepath = entry['Mask'] if (imageFilepath is not None) and (maskFilepath is not None): if not os.path.isabs(imageFilepath): imageFilepath = os.path.abspath( os.path.join(os.path.dirname(args.inFile.name), imageFilepath)) logger.debug( 'Updated relative image filepath to be relative to input CSV: %s', imageFilepath) if not os.path.isabs(maskFilepath): maskFilepath = os.path.abspath( os.path.join(os.path.dirname(args.inFile.name), maskFilepath)) logger.debug( 'Updated relative mask filepath to be relative to input CSV: %s', maskFilepath) featureVector = collections.OrderedDict(entry) if args.shorten: featureVector['Image'] = os.path.basename(imageFilepath) featureVector['Mask'] = os.path.basename(maskFilepath) try: entryLabel = entry.get('Label', None) if str(entryLabel).isdigit(): label = int(entryLabel) else: label = args.label featureVector.update( extractor.execute(imageFilepath, maskFilepath, label)) # if specified, skip NaN values if args.skip_nans: for key in list(featureVector.keys()): if isinstance(featureVector[key], float) and numpy.isnan( featureVector[key]): logger.debug( 'Feature %s computed NaN, removing from results', key) del featureVector[key] if args.format == 'csv': writer = csv.writer(args.outFile, lineterminator='\n') if headers is None: headers = list(featureVector.keys()) writer.writerow(headers) row = [] for h in headers: row.append(featureVector.get(h, "")) writer.writerow(row) elif args.format == 'json': json.dump(featureVector, args.out) args.out.write('\n') except Exception: logger.error('FEATURE EXTRACTION FAILED', exc_info=True) args.outFile.close() if args.log_file is not None: args.log_file.close()
import numpy as np import pickle import nrrd import radiomics import pandas as pd import matplotlib.pyplot as plt import seaborn as sns from radiomics import featureextractor from .globals import (SVM_MODEL_FILES, XGB_MODEL_FILES, IMPORTANT_FEATURES, X_FEATURES, DISEASES) radiomics.setVerbosity(40) dataset = './data/datasets/radiomics_features.csv' def load_models(model='svm'): models_arr = [] model_files = None if model == 'svm': model_files = SVM_MODEL_FILES else: model_files = XGB_MODEL_FILES for i in range(len(model_files)): models_arr.append(pickle.load(open(model_files[i], 'rb'))) return models_arr
def main(argv=None): logger = logging.getLogger('radiomics.addTest') logger.setLevel(logging.INFO) radiomics.setVerbosity(logging.INFO) handler = logging.FileHandler(filename='testLog.txt', mode='w') formatter = logging.Formatter("%(levelname)s:%(name)s: %(message)s") handler.setFormatter(formatter) radiomics.logger.addHandler(handler) parser = argparse.ArgumentParser() parser.add_argument( 'TestName', type=str, help= 'Name for the new test, must not be already present in the baseline') parser.add_argument('TestCase', type=str, choices=list(radiomics.testCases), help='Test image and segmentation to ' 'use in the new test') parser.add_argument( 'Configuration', metavar='FILE', default=None, help='Parameter file containing the settings to be used in extraction') parser.add_argument('--force', '-f', action='store_true', help='When the test is already known for the class, ' 'overwrite it in stead of just skipping that class') args = parser.parse_args(argv) logger.info('Input accepted, starting addTest...') try: testutils = RadiomicsTestUtils() try: assert args.TestCase in radiomics.testCases except AssertionError: logger.error('Input not valid, cancelling addTest!') exit(1) logger.debug('Initializing extractor') extractor = featureextractor.RadiomicsFeaturesExtractor( args.Configuration) logger.debug('Starting extraction') featurevector = extractor.execute( *radiomics.getTestCase(args.TestCase)) configuration = {} baselines = {} for k, v in six.iteritems(featurevector): if 'diagnostics' in k: configuration[k] = v else: image_filter, feature_class, feature_name = k.split('_') if feature_class not in baselines: baselines[feature_class] = {} baselines[feature_class][k] = v configuration['diagnostics_Configuration_TestCase'] = args.TestCase testutils.addTest(args.TestName, configuration, baselines) logger.info('addTest Done') except Exception: logger.error('Error running addTest!', exc_info=True)
def main(): args = parser.parse_args() # Initialize Logging logLevel = getattr(logging, args.logging_level) rLogger = radiomics.logger # Set up optional logging to file if args.log_file is not None: rLogger.setLevel(logLevel) handler = logging.StreamHandler(args.log_file) handler.setFormatter( logging.Formatter("%(levelname)s:%(name)s: %(message)s")) rLogger.addHandler(handler) # Set verbosity of output (stderr) verboseLevel = (6 - args.verbosity) * 10 # convert to python logging level radiomics.setVerbosity(verboseLevel) # Initialize logging for script log messages logger = rLogger.getChild('script') # Initialize extractor try: if args.param is not None: extractor = featureextractor.RadiomicsFeaturesExtractor(args.param) else: extractor = featureextractor.RadiomicsFeaturesExtractor() logger.info( 'Extracting features with kwarg settings: %s\n\tImage: %s\n\tMask: %s', str(extractor.settings), os.path.abspath(args.image), os.path.abspath(args.mask)) featureVector = collections.OrderedDict() if args.shorten: featureVector['Image'] = os.path.basename(args.image) featureVector['Mask'] = os.path.basename(args.mask) featureVector.update( extractor.execute(args.image, args.mask, args.label)) # if specified, skip NaN values if args.skip_nans: for key in list(featureVector.keys()): if isinstance(featureVector[key], float) and numpy.isnan( featureVector[key]): logger.debug( 'Feature %s computed NaN, removing from results', key) del featureVector[key] if args.format == 'csv': writer = csv.writer(args.out, lineterminator='\n') writer.writerow(list(featureVector.keys())) writer.writerow(list(featureVector.values())) elif args.format == 'json': json.dump(featureVector, args.out) args.out.write('\n') else: for k, v in six.iteritems(featureVector): args.out.write('%s: %s\n' % (k, v)) except Exception: logger.error('FEATURE EXTRACTION FAILED', exc_info=True) args.out.close() if args.log_file is not None: args.log_file.close()
def main(outPath=r'', patch=None, patchsize=30, allfilters=False): ''' Func that runs PyRadiomics analysis. Creates a csv file with results. Accepts an input CSV (pyradExcel) which indicates image and mask. By default runs features on whole segmentation file (mhd in our case). If want to run PyRadiomics in patches (grid-mode): (1.pt) call patch='2D' or '3D', depending on the dimensions of your Region of Interest. (2) in input CSV, under Slices column, indicate first and last slice in this format - X, Y (otherwise leave empty) ''' inputCSV = os.path.join(outPath, 'pyradExcel.csv') outputFilepath = os.path.join(outPath, 'radiomics_features.csv') progress_filename = os.path.join(outPath, 'pyrad_log.txt') # params = os.path.join(outPath, 'exampleSettings', 'Params.yaml') # default fr PyR. skipped later if not found # Configure logging rLogger = logging.getLogger('radiomics') # Set logging level rLogger.setLevel(logging.INFO) # default log level of logger is INFO # Create handler for writing to log file handler = logging.FileHandler(filename=progress_filename, mode='w') handler.setFormatter( logging.Formatter('%(levelname)s:%(name)s: %(message)s')) rLogger.addHandler(handler) # Initialize logging for batch log messages logger = rLogger.getChild('batch') # Set verbosity level for output to stderr (default level = WARNING) (amount of messages displayed) radiomics.setVerbosity(logging.INFO) logger.info('pyradiomics version: %s', radiomics.__version__) logger.info('Loading CSV') try: with open(inputCSV, 'r') as inFile: reader = csv.DictReader(inFile, lineterminator='\n') index = [row for row in reader] except Exception: logger.error('CSV READ FAILED', exc_info=True) logger.info('Loading Done') logger.info('Patients: %d', len(index)) # Set custom geometryTolerance. This is the only setting that will overun default settings. # There can be a tiny delta between image and mask space direction values (ElementSpacing/Size field in mhd/mha). # From primary tests they should be equal upto at least 4 decimal places, so I set to 10**-4. settings = {} settings['geometryTolerance'] = 10**-4 count = 0 for idx, entry in enumerate(index, start=1): logger.info("(%d/%d) Processing Patient (Image: %s, Mask: %s)", idx, len(index), entry['Image'], entry['Mask']) imageFilepath = entry['Image'] maskFilepath = entry['Mask'] slices = entry['Slices'].split(', ') if (imageFilepath is not None) and (maskFilepath is not None): # Extract label from mask. # PyRadiomics calls on label 1.pt by default, but mhd has default 255 and Philips TISSUE mask file -1.pt. # From my understanding, in TISSUE mask file generated by Philips Portal there is only one label per mask sitkMask = sitk.ReadImage(maskFilepath) sitkarray = sitk.GetArrayFromImage(sitkMask) labels = numpy.unique(sitkarray) if 255 in labels: totalLabel = int(labels[1]) elif -1 in labels: totalLabel = int(labels[0]) # By default, only Original input image is enabled (No filter applied). extractor = featureextractor.RadiomicsFeatureExtractor(**settings) if allfilters: extractor.enableAllImageTypes() logger.info('Enabled input images types: %s', extractor.enabledImagetypes) logger.info('Enabled features: %s', extractor.enabledFeatures) logger.info('Current settings: %s', extractor.settings) # Checks if want to run in patch mode or whole mask if patch is None: # If mask is 3D, get full mask for later feature extraction. If 2D, leave sitkMask unchanged if slices != ['']: sitkMask = getFullMask(imageFilepath, maskFilepath, slices) featureVector = collections.OrderedDict(entry) featureVector['Image'] = os.path.basename(imageFilepath) featureVector['Mask'] = os.path.basename(maskFilepath) try: featureVector.update( extractor.execute(imageFilepath, sitkMask, totalLabel)) writeResults(featureVector, outputFilepath, count) count += 1 except Exception: logger.error('FEATURE EXTRACTION FAILED', exc_info=True) writeResults(featureVector, outputFilepath, count) elif patch == '3D' and slices != ['']: sitkMask = getFullMask(imageFilepath, maskFilepath, slices) sitkarray = sitk.GetArrayFromImage(sitkMask) patchedMask, dctLabel, dctABC = patch3Dmask( sitkarray, totalLabel, patchsize=patchsize) newMask = sitk.GetImageFromArray(patchedMask) newMask.CopyInformation(sitkMask) for label in dctLabel: featureVector = collections.OrderedDict(entry) featureVector['Image'] = os.path.basename(imageFilepath) featureVector['Mask'] = os.path.basename(maskFilepath) featureVector['PatchNumber'] = label featureVector['PatchName'] = dctABC[label] featureVector['FractionLabelInPatch'] = dctLabel[label] try: featureVector.update( extractor.execute(imageFilepath, newMask, label)) writeResults(featureVector, outputFilepath, count) count += 1 except Exception: logger.error('FEATURE EXTRACTION FAILED', exc_info=True) writeResults(featureVector, outputFilepath, count) elif patch == '2D': patchedMask, dctLabel = patchMask(sitkarray, totalLabel, patchsize=patchsize) newMask = sitk.GetImageFromArray(patchedMask) newMask.CopyInformation(sitkMask) for label in dctLabel: featureVector = collections.OrderedDict(entry) featureVector['Image'] = os.path.basename(imageFilepath) featureVector['Mask'] = os.path.basename( maskFilepath) + '_' + str(label) featureVector['PatchNumber'] = label # featureVector['PatchName'] = label # sort out alphabetical name for 2D patching as well featureVector['FractionLabelInPatch'] = dctLabel[label] try: featureVector.update( extractor.execute(imageFilepath, newMask, label)) writeResults(featureVector, outputFilepath, count) count += 1 except Exception: logger.error('FEATURE EXTRACTION FAILED', exc_info=True) writeResults(featureVector, outputFilepath, count)
import six import matplotlib.pyplot as plt from radiomics import featureextractor, setVerbosity, getTestCase resultPath = '/home/zzr/git/pyradiomics1111/result' dataDir = '/home/zzr/git/pyradiomics1111' imageName, maskName = getTestCase('brain1', dataDir) # imageName = os.path.join('/media/zzr/My Passport/430/MRI/Preprocess_MRI/03534455_WANG YONG SHENG_MR', 'T2_img.nii.gz') # maskName = os.path.join('/media/zzr/My Passport/430/MRI/Preprocess_MRI/03534455_WANG YONG SHENG_MR', 'T2_label.nii.gz') params = os.path.join(dataDir, 'examples', 'exampleSettings', 'mine.yaml') extractor = featureextractor.RadiomicsFeaturesExtractor(params) extractor.addProvenance(provenance_on=False) extractor.enableAllFeatures() # extractor.enableFeatureClassByName('shape', False) extractor.enableAllImageTypes() setVerbosity(60) # image, mask = extractor.loadImage(imageName, maskName) # waveletImage = list(imageoperations.getWaveletImage(image, mask)) # print(len(waveletImage)) # img = sitk.GetArrayFromImage(waveletImage(0)) # for i in xrange(img.shape[0]): # plt.imshow(img[i, ...], cmap=plt.cm.gray) # plt.show() # print(waveletImage) # for x in waveletImage: # img = sitk.GetArrayFromImage(x[0]) # print(img.shape) # for i in xrange(img.shape[0]): # plt.imshow(img[i, ...], cmap=plt.cm.gray) # plt.show() # break
# Configure logging rLogger = logging.getLogger('radiomics') # Set logging level # rLogger.setLevel(logging.INFO) # Not needed, default log level of logger is INFO # Create handler for writing to log file handler = logging.FileHandler(filename=progress_filename, mode='w') handler.setFormatter(logging.Formatter('%(levelname)s:%(name)s: %(message)s')) rLogger.addHandler(handler) # Initialize logging for batch log messages logger = rLogger.getChild('batch') # Set verbosity level for output to stderr (default level = WARNING) radiomics.setVerbosity(logging.INFO) logger.info('pyradiomics version: %s', radiomics.__version__) logger.info('Loading CSV') flists = [] try: with open(inputCSV, 'r') as inFile: cr = csv.DictReader(inFile, lineterminator='\n') flists = [row for row in cr] except Exception: logger.error('CSV READ FAILED', exc_info=True) logger.info('Loading Done') logger.info('Patients: %d', len(flists))
import os import multiprocessing import threading import queue from pathlib import Path import numpy as np import pandas as pd import cv2 import radiomics radiomics.setVerbosity(60) #Quiet import SimpleITK as sitk from scipy.spatial import distance from scipy.signal import resample augm_patLvDiv_train = Path('data/augm_patLvDiv_train/') augm_patLvDiv_valid = Path('data/augm_patLvDiv_valid') patLvDiv_test = Path('data/patLvDiv_test') def readImage(path, color): if color == 'rgb': return cv2.cvtColor(cv2.imread(str(path)), cv2.COLOR_BGR2RGB) elif color == 'gray': return cv2.cvtColor(cv2.imread(str(path)), cv2.COLOR_BGR2GRAY) elif color == 'hsv': return cv2.cvtColor(cv2.imread(str(path)), cv2.COLOR_BGR2HSV) return None def getPyRadImageAndMask(grayScaleImage, jointSeries=False): _, pyRadMask = cv2.threshold(grayScaleImage, 1, 1, cv2.THRESH_BINARY)
def onApplyButton(self): if self.verboseCheckBox.checked: # Setup debug logging for the pyradiomics toolbox # PyRadiomics logs to stderr by default, which is picked up by slicer and added to the slicer log. setVerbosity(logging.DEBUG) else: setVerbosity(logging.WARNING) if not self.outputTableSelector.currentNode(): tableNode = slicer.vtkMRMLTableNode() slicer.mrmlScene.AddNode(tableNode) self.outputTableSelector.setCurrentNode(tableNode) logic = SlicerRadiomicsLogic() # Lock GUI self.applyButton.text = 'Working...' self.applyButton.setEnabled(False) slicer.app.processEvents() imageNode = self.inputVolumeSelector.currentNode() labelNode = self.inputMaskSelector.currentNode() segmentationNode = self.inputSegmentationSelector.currentNode() if self.manualCustomizationRadioButton.checked: # Set up customization featureClasses = self.getCheckedFeatureClasses() settings = {} settings['binWidth'] = self.binWidthSliderWidget.value settings['symmetricalGLCM'] = self.symmetricalGLCMCheckBox.checked enabledImageTypes = {'Original': {}} logKernelSizesValue = self.logKernelSizes.text if logKernelSizesValue: try: enabledImageTypes['LoG'] = { 'sigma': [float(i) for i in logKernelSizesValue.split(',')] } except: self.logger.error( 'Failed to parse LoG sigma value from string \"' + logKernelSizesValue + '\"') traceback.print_exc() return resampledVoxelSizeValue = self.resampledVoxelSize.text if resampledVoxelSizeValue: try: settings['resampledPixelSpacing'] = [ float(i) for i in resampledVoxelSizeValue.split(',') ] except: self.logger.error( 'Failed to parse resampled voxel spacing from string \"' + resampledVoxelSizeValue + '\"') settings['resampledPixelSpacing'] = None traceback.print_exc() return if self.waveletCheckBox.checked: enabledImageTypes['Wavelet'] = {} # Compute features try: featuresDict = logic.run(imageNode, labelNode, segmentationNode, featureClasses, settings, enabledImageTypes) logic.exportToTable(featuresDict, self.outputTableSelector.currentNode()) except: self.logger.error("Feature calculation failed.") traceback.print_exc() else: # Compute Features try: parameterFile = self.parameterFilePathLineEdit.currentPath featuresDict = logic.runWithParameterFile( imageNode, labelNode, segmentationNode, parameterFile) logic.exportToTable(featuresDict, self.outputTableSelector.currentNode()) except: self.logger.error("Feature calculation failed.") traceback.print_exc() # Unlock GUI self.applyButton.setEnabled(True) self.applyButton.text = 'Apply' # Show results logic.showTable(self.outputTableSelector.currentNode())
#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Created on Wed Jun 5 17:07:02 2019 @author: leonardo """ import radiomics import SimpleITK as sitk import os radiomics.setVerbosity(10) dataDir = '/home/leonardo/pyradiomics/data' Image_path = '/home/leonardo/Scrivania/paziente_prova/CSI+Boost/RTDOSE_2011-09-29_075800_TomoTherapy.Patient.Disease_TomoTherapy.Planned.Dose_n1__00000/1.2.826.0.1.3680043.2.200.426397767.89.47755.958.dcm' Mask_path = '/home/leonardo/Scrivania/paziente_prova/RTst_nii' #PER USARE PYRADIOMICS SERVONO IMMAGINI IN FORMATO COMPATIBILE CON SIMPLEITK. USARE sitk.ReadImage. IL PROBLEMA È CHE L'IMMAGINE CT È SPACCHETTATA IN TANTE IMMAGINI SI SINGOLE SLICE. #CI SONO DELLE FUNZIONI DI SITK PER APRIRE I DICOM #Carico immagine Mask Maskstk = sitk.ReadImage(Mask_path + '/mask_Body.nii') #Carico immagine DOSE #Imagestk=sitk.ImageSeriesReader.GetGDCMSeriesFileNames(Image_path) Imagestk = sitk.ReadImage(Image_path)
def main(): outPath = r'' inputCSV = os.path.join(outPath, 'testCases.csv') outputFilepath = os.path.join(outPath, 'radiomics_features.csv') progress_filename = os.path.join(outPath, 'pyrad_log.txt') params = os.path.join(outPath, 'exampleSettings', 'Params.yaml') # Configure logging rLogger = logging.getLogger('radiomics') # Set logging level # rLogger.setLevel(logging.INFO) # Not needed, default log level of logger is INFO # Create handler for writing to log file handler = logging.FileHandler(filename=progress_filename, mode='w') handler.setFormatter(logging.Formatter('%(levelname)s:%(name)s: %(message)s')) rLogger.addHandler(handler) # Initialize logging for batch log messages logger = rLogger.getChild('batch') # Set verbosity level for output to stderr (default level = WARNING) radiomics.setVerbosity(logging.INFO) logger.info('pyradiomics version: %s', radiomics.__version__) logger.info('Loading CSV') flists = [] try: with open(inputCSV, 'r') as inFile: cr = csv.DictReader(inFile, lineterminator='\n') flists = [row for row in cr] except Exception: logger.error('CSV READ FAILED', exc_info=True) logger.info('Loading Done') logger.info('Patients: %d', len(flists)) if os.path.isfile(params): extractor = featureextractor.RadiomicsFeatureExtractor(params) else: # Parameter file not found, use hardcoded settings instead settings = {} settings['binWidth'] = 25 settings['resampledPixelSpacing'] = None # [3,3,3] settings['interpolator'] = sitk.sitkBSpline settings['enableCExtensions'] = True extractor = featureextractor.RadiomicsFeatureExtractor(**settings) # extractor.enableInputImages(wavelet= {'level': 2}) logger.info('Enabled input images types: %s', extractor.enabledImagetypes) logger.info('Enabled features: %s', extractor.enabledFeatures) logger.info('Current settings: %s', extractor.settings) headers = None for idx, entry in enumerate(flists, start=1): logger.info("(%d/%d) Processing Patient (Image: %s, Mask: %s)", idx, len(flists), entry['Image'], entry['Mask']) imageFilepath = entry['Image'] maskFilepath = entry['Mask'] label = entry.get('Label', None) if str(label).isdigit(): label = int(label) else: label = None if (imageFilepath is not None) and (maskFilepath is not None): featureVector = collections.OrderedDict(entry) featureVector['Image'] = os.path.basename(imageFilepath) featureVector['Mask'] = os.path.basename(maskFilepath) try: featureVector.update(extractor.execute(imageFilepath, maskFilepath, label)) with open(outputFilepath, 'a') as outputFile: writer = csv.writer(outputFile, lineterminator='\n') if headers is None: headers = list(featureVector.keys()) writer.writerow(headers) row = [] for h in headers: row.append(featureVector.get(h, "N/A")) writer.writerow(row) except Exception: logger.error('FEATURE EXTRACTION FAILED', exc_info=True)
def pyradiomics_batch(input_file_name, output_file_name): ''' Extract features from a batch of images using radiomics. :param str input_file_name: Name of the excel-document that contains patient ID, path the image and path to the mask of the image :param str output_file_name: Name of the excel-document that is going to containing the extracted features ''' #Finding the directory and setting up a logging file outPath = os.getcwd() inputXLSX = os.path.join(outPath, input_file_name) outputFilepath = os.path.join(outPath, output_file_name) progress_filename = os.path.join(outPath, 'pyrad_log.txt') rLogger = logging.getLogger('radiomics') handler = logging.FileHandler(filename=progress_filename, mode='w') handler.setFormatter( logging.Formatter('%(levelname)s:%(name)s: %(message)s')) rLogger.addHandler(handler) logger = rLogger.getChild('batch') radiomics.setVerbosity(logging.INFO) try: # Use pandas to read and transpose ('.T') the input data # The transposition is needed so that each column represents one test case. This is easier for iteration over the input cases flists = pandas.read_excel(inputXLSX).T except Exception: logger.error('Excel READ FAILED', exc_info=True) exit(-1) logger.info('Loading Done') logger.info('Patients: %d', len(flists.columns)) #Change the settings settings = {} settings['binWidth'] = 2 #To get the right amount of bins settings['sigma'] = [1] extractor = featureextractor.RadiomicsFeaturesExtractor(**settings) extractor.enableAllImageTypes() logger.info('Enabled input images types: %s', extractor._enabledImagetypes) logger.info('Enabled features: %s', extractor._enabledFeatures) logger.info('Current settings: %s', extractor.settings) results = pandas.DataFrame() for entry in flists: # Loop over all columns (i.e. the test cases) logger.info("(%d/%d) Processing Patient: %s", entry + 1, len(flists.columns), flists[entry]['pasientID']) imageFilepath = flists[entry]['Image'] maskFilepath = flists[entry]['Mask'] label = flists[entry].get('Label', None) if str(label).isdigit(): label = int(label) else: label = None if (imageFilepath is not None) and (maskFilepath is not None): featureVector = flists[entry] # This is a pandas Series featureVector['Image'] = os.path.basename(imageFilepath) featureVector['Mask'] = os.path.basename(maskFilepath) try: # PyRadiomics returns the result as an ordered dictionary, which can be easily converted to a pandas Series # The keys in the dictionary will be used as the index (labels for the rows), with the values of the features # as the values in the rows. result = pandas.Series( extractor.execute(imageFilepath, maskFilepath, label)) featureVector = featureVector.append(result) except Exception: logger.error('FEATURE EXTRACTION FAILED:', exc_info=True) featureVector.name = entry # By specifying an 'outer' join, all calculated features are added to the data frame, including those not # calculated for previous cases. This also ensures we don't end up with an empty frame, as for the first patient # it is 'joined' with the empty data frame. results = results.join(featureVector, how='outer') logger.info('Extraction complete, writing Excel') # .T transposes the data frame, so that each line will represent one patient, with the extracted features as columns results.T.to_excel(outputFilepath, index=False, na_rep='NaN') logger.info('Excel writing complete')
#FINALLY: give the value of the calculated h_final to the parameter file _createParameterFile(h_final) #Perform pyRadiomics feature extraction with such parameter for (i, j) in zip(list_images, list_masks): case = i[0:4] imagePath = os.path.join(src, i) labelPath = os.path.join(src, j) image = sitk.ReadImage(imagePath) label = sitk.ReadImage(labelPath) #print(len(out_bin)) #number of bins radiomics.setVerbosity(level=10) extractor = radiomics.featureextractor.RadiomicsFeatureExtractor(paramPath) print("Enabled filters:\n\t", extractor.enabledImagetypes, "") print("Extraction parameters:\n\t", extractor.settings) print("Enabled features:\n\t", extractor.enabledFeatures) # Extract features print("Calculating features") featureVector = extractor.execute(image, label) d1 = featureVector d1.update({'Case': case}) d1.move_to_end('Case', last=False)