def test(path_data='', parameters=''): # initializations output = '' file_init_label_vertebrae = 'init_label_vertebrae.txt' rmse = float('NaN') max_dist = float('NaN') diff_manual_result = float('NaN') if not parameters: parameters = '-i t2/t2.nii.gz -s t2/t2_seg.nii.gz -c t2 -initfile t2/init_label_vertebrae.txt' # retrieve flags try: parser = sct_label_vertebrae.get_parser() dict_param = parser.parse(parameters.split(), check_file_exist=False) dict_param_with_path = parser.add_path_to_file(deepcopy(dict_param), path_data, input_file=True) # update template path because the previous command wrongly adds path to testing data dict_param_with_path['-t'] = dict_param['-t'] param_with_path = parser.dictionary_to_string(dict_param_with_path) # in case not all mandatory flags are filled except SyntaxError as err: print err status = 1 output = err return status, output, DataFrame(data={'status': int(status), 'output': output}, index=[path_data]) # create output folder to deal with multithreading (i.e., we don't want to have outputs from several subjects in the current directory) import time, random subject_folder = path_data.split('/') if subject_folder[-1] == '' and len(subject_folder) > 1: subject_folder = subject_folder[-2] else: subject_folder = subject_folder[-1] path_output = sct.slash_at_the_end('sct_label_vertebrae_' + subject_folder + '_' + time.strftime("%y%m%d%H%M%S") + '_'+str(random.randint(1, 1000000)), slash=1) os.mkdir(path_output) param_with_path += ' -ofolder ' + path_output # log file fname_log = path_output + 'output.log' # Extract contrast contrast = '' if dict_param['-i'][0] == '/': dict_param['-i'] = dict_param['-i'][1:] input_split = dict_param['-i'].split('/') if len(input_split) == 2: contrast = input_split[0] if not contrast: # if no contrast folder, send error. status = 1 output += '\nERROR: when extracting the contrast folder from input file in command line: ' + dict_param['-i'] + ' for ' + path_data write_to_log_file(fname_log, output, 'w') return status, output, DataFrame(data={'status': status, 'output': output, 'dice_segmentation': float('nan')}, index=[path_data]) # Check if input files exist if not (os.path.isfile(dict_param_with_path['-i']) and os.path.isfile(dict_param_with_path['-s'])): status = 200 output += '\nERROR: the file(s) provided to test function do not exist in folder: ' + path_data write_to_log_file(fname_log, output, 'w') return status, output, DataFrame(data={'status': int(status), 'output': output}, index=[path_data]) # open ground truth fname_labels_manual = path_data + contrast + '/' + contrast + '_labeled_center_manual.nii.gz' try: label_manual = ProcessLabels(fname_labels_manual) list_label_manual = label_manual.image_input.getNonZeroCoordinates(sorting='value') except: status = 201 output += '\nERROR: cannot file: ' + fname_labels_manual write_to_log_file(fname_log, output, 'w') return status, output, DataFrame(data={'status': int(status), 'output': output}, index=[path_data]) cmd = 'sct_label_vertebrae ' + param_with_path output = '\n====================================================================================================\n'+cmd+'\n====================================================================================================\n\n' # copy command time_start = time.time() try: status, o = sct.run(cmd, 0) except: status, o = 1, '\nERROR: Function crashed!' output += o duration = time.time() - time_start # initialization of results: must be NaN if test fails result_mse = float('nan'), float('nan') if status == 0: # copy input data (for easier debugging) sct.run('cp '+dict_param_with_path['-i']+' '+path_output, verbose=0) # extract center of vertebral labels path_seg, file_seg, ext_seg = sct.extract_fname(dict_param['-s']) try: sct.run('sct_label_utils -i '+path_output+file_seg+'_labeled.nii.gz -vert-body 0 -o '+path_output+contrast+'_seg_labeled_center.nii.gz', verbose=0) label_results = ProcessLabels(path_output + contrast + '_seg_labeled_center.nii.gz') list_label_results = label_results.image_input.getNonZeroCoordinates(sorting='value') # get dimension # from msct_image import Image # img = Image(path_output+contrast+'_seg_labeled.nii.gz') nx, ny, nz, nt, px, py, pz, pt = label_results.image_input.dim except: status = 1 output += '\nERROR: cannot open file: ' + path_output + contrast + '_seg_labeled.nii.gz' write_to_log_file(fname_log, output, 'w') return status, output, DataFrame(data={'status': int(status), 'output': output}, index=[path_data]) mse = 0.0 max_dist = 0.0 for coord_manual in list_label_manual: for coord in list_label_results: if round(coord.value) == round(coord_manual.value): # Calculate MSE mse += (((coord_manual.x - coord.x)*px) ** 2 + ((coord_manual.y - coord.y)*py) ** 2 + ((coord_manual.z - coord.z)*pz) ** 2) / float(3) # Calculate distance (Frobenius norm) dist = linalg.norm([(coord_manual.x - coord.x)*px, (coord_manual.y - coord.y)*py, (coord_manual.z - coord.z)*pz]) if dist > max_dist: max_dist = dist break rmse = sqrt(mse / len(list_label_manual)) # calculate number of label mismatch diff_manual_result = len(list_label_manual) - len(list_label_results) # check if MSE is superior to threshold th_rmse = 2 if rmse > th_rmse: status = 99 output += '\nWARNING: RMSE = '+str(rmse)+' > '+str(th_rmse) th_max_dist = 4 if max_dist > th_max_dist: status = 99 output += '\nWARNING: Max distance = '+str(max_dist)+' > '+str(th_max_dist) th_diff_manual_result = 3 if abs(diff_manual_result) > th_diff_manual_result: status = 99 output += '\nWARNING: Diff manual-result = '+str(diff_manual_result)+' > '+str(th_diff_manual_result) # transform results into Pandas structure results = DataFrame(data={'status': int(status), 'output': output, 'rmse': rmse, 'max_dist': max_dist, 'diff_man': diff_manual_result, 'duration [s]': duration}, index=[path_data]) # write log file write_to_log_file(fname_log, output, 'w') return status, output, results
def test(path_data='', parameters=''): file_init_label_vertebrae = 'init_label_vertebrae.txt' if not parameters: parameters = '-i t2/t2.nii.gz -s t2/t2_seg.nii.gz -o t2_seg_labeled.nii.gz' parser = sct_label_vertebrae.get_parser() dict_param = parser.parse(parameters.split(), check_file_exist=False) dict_param_with_path = parser.add_path_to_file(dict_param, path_data, input_file=True) param_with_path = parser.dictionary_to_string(dict_param_with_path) # Check if input files exist if not (os.path.isfile(dict_param_with_path['-i']) and os.path.isfile(dict_param_with_path['-s'])): status = 200 output = 'ERROR: the file(s) provided to test function do not exist in folder: ' + path_data return status, output, DataFrame(data={'status': status, 'output': output, 'mse': float('nan')}, index=[path_data]) # add initialization parameter contained in file: init_label_vertebrae.txt if not os.path.isfile(path_data+'t2/'+file_init_label_vertebrae): status = 200 output = 'ERROR: the file init_label_vertebrae.txt does not exist in folder: ' + path_data return status, output, DataFrame(data={'status': status, 'output': output, 'mse': float('nan')}, index=[path_data]) else: file = open(path_data+'t2/'+file_init_label_vertebrae, 'r') param_with_path += ' '+file.read().replace('\n', '') cmd = 'sct_label_vertebrae ' + param_with_path output = '\n====================================================================================================\n'+cmd+'\n====================================================================================================\n\n' # copy command time_start = time.time() status, o = sct.run(cmd, 0) output += o duration = time.time() - time_start # initialization of results: must be NaN if test fails result_mse = float('nan'), float('nan') if status == 0: # extract center of vertebral labels sct.run('sct_label_utils -i t2_seg_labeled.nii.gz -p label-vertebrae -o t2_seg_labeled_center.nii.gz', verbose=0) # open labels from sct_label_utils import ProcessLabels from numpy import linalg from math import sqrt label_results = ProcessLabels('t2_seg_labeled_center.nii.gz') list_label_results = label_results.image_input.getNonZeroCoordinates(sorting='value') label_manual = ProcessLabels(path_data+'t2/t2_labeled_center_manual.nii.gz') list_label_manual = label_manual.image_input.getNonZeroCoordinates(sorting='value') mse = 0.0 max_dist = 0.0 for coord_manual in list_label_manual: for coord in list_label_results: if round(coord.value) == round(coord_manual.value): # Calculate MSE mse += ((coord_manual.x - coord.x) ** 2 + (coord_manual.y - coord.y) ** 2 + (coord_manual.z - coord.z) ** 2) / float(3) # Calculate distance (Frobenius norm) dist = linalg.norm([(coord_manual.x - coord.x), (coord_manual.y - coord.y), (coord_manual.z - coord.z)]) if dist > max_dist: max_dist = dist break rmse = sqrt(mse / len(list_label_manual)) # calculate number of label mismatch diff_manual_result = len(list_label_manual) - len(list_label_results) # # display results # sct.printv('RMSE = ' + str(rmse) + ' mm') # sct.printv('Max distance = ' + str(max_dist) + ' mm') # sct.printv('Diff manual-test = ' + str(diff_manual_result)) # check if MSE is superior to threshold th_rmse = 2 if rmse > th_rmse: status = 99 output += '\nWARNING: RMSE = '+str(rmse)+' > '+str(th_rmse) th_max_dist = 3.2 if max_dist > th_max_dist: status = 99 output += '\nWARNING: Max distance = '+str(max_dist)+' > '+str(th_max_dist) th_diff_manual_result = 3 if abs(diff_manual_result) > 3: status = 99 output += '\nWARNING: Diff manual-result = '+str(diff_manual_result)+' > '+str(th_diff_manual_result) # transform results into Pandas structure results = DataFrame(data={'status': status, 'output': output, 'rmse': rmse, 'max_dist': max_dist, 'diff_man': diff_manual_result, 'duration [s]': duration}, index=[path_data]) return status, output, results
def test(path_data='', parameters=''): # initializations output = '' file_init_label_vertebrae = 'init_label_vertebrae.txt' rmse = float('NaN') max_dist = float('NaN') diff_manual_result = float('NaN') if not parameters: parameters = '-i t2/t2.nii.gz -s t2/t2_seg.nii.gz -c t2 -initfile t2/init_label_vertebrae.txt' # retrieve flags try: parser = sct_label_vertebrae.get_parser() dict_param = parser.parse(parameters.split(), check_file_exist=False) dict_param_with_path = parser.add_path_to_file(deepcopy(dict_param), path_data, input_file=True) # update template path because the previous command wrongly adds path to testing data dict_param_with_path['-t'] = dict_param['-t'] param_with_path = parser.dictionary_to_string(dict_param_with_path) # in case not all mandatory flags are filled except SyntaxError as err: print err status = 1 output = err return status, output, DataFrame(data={ 'status': int(status), 'output': output }, index=[path_data]) # create output folder to deal with multithreading (i.e., we don't want to have outputs from several subjects in the current directory) import time, random subject_folder = path_data.split('/') if subject_folder[-1] == '' and len(subject_folder) > 1: subject_folder = subject_folder[-2] else: subject_folder = subject_folder[-1] path_output = sct.slash_at_the_end( 'sct_label_vertebrae_' + subject_folder + '_' + time.strftime("%y%m%d%H%M%S") + '_' + str(random.randint(1, 1000000)), slash=1) os.mkdir(path_output) param_with_path += ' -ofolder ' + path_output # log file fname_log = path_output + 'output.log' # Extract contrast contrast = '' if dict_param['-i'][0] == '/': dict_param['-i'] = dict_param['-i'][1:] input_split = dict_param['-i'].split('/') if len(input_split) == 2: contrast = input_split[0] if not contrast: # if no contrast folder, send error. status = 1 output += '\nERROR: when extracting the contrast folder from input file in command line: ' + dict_param[ '-i'] + ' for ' + path_data write_to_log_file(fname_log, output, 'w') return status, output, DataFrame(data={ 'status': status, 'output': output, 'dice_segmentation': float('nan') }, index=[path_data]) # Check if input files exist if not os.path.isfile(dict_param_with_path['-i']): status = 200 output += '\nERROR: This file does not exist: ' + dict_param_with_path[ '-i'] write_to_log_file(fname_log, output, 'w') return status, output, DataFrame(data={ 'status': int(status), 'output': output }, index=[path_data]) if not os.path.isfile(dict_param_with_path['-s']): status = 200 output += '\nERROR: This file does not exist: ' + dict_param_with_path[ '-s'] write_to_log_file(fname_log, output, 'w') return status, output, DataFrame(data={ 'status': int(status), 'output': output }, index=[path_data]) # open ground truth fname_labels_manual = path_data + contrast + '/' + contrast + '_labeled_center_manual.nii.gz' try: label_manual = ProcessLabels(fname_labels_manual) list_label_manual = label_manual.image_input.getNonZeroCoordinates( sorting='value') except: status = 201 output += '\nERROR: cannot file: ' + fname_labels_manual write_to_log_file(fname_log, output, 'w') return status, output, DataFrame(data={ 'status': int(status), 'output': output }, index=[path_data]) cmd = 'sct_label_vertebrae ' + param_with_path output = '\n====================================================================================================\n' + cmd + '\n====================================================================================================\n\n' # copy command time_start = time.time() try: status, o = sct.run(cmd, 0) except: status, o = 1, '\nERROR: Function crashed!' output += o duration = time.time() - time_start # initialization of results: must be NaN if test fails result_mse = float('nan'), float('nan') if status == 0: # copy input data (for easier debugging) sct.run('cp ' + dict_param_with_path['-i'] + ' ' + path_output, verbose=0) # extract center of vertebral labels path_seg, file_seg, ext_seg = sct.extract_fname(dict_param['-s']) try: sct.run('sct_label_utils -i ' + path_output + file_seg + '_labeled.nii.gz -vert-body 0 -o ' + path_output + contrast + '_seg_labeled_center.nii.gz', verbose=0) label_results = ProcessLabels(path_output + contrast + '_seg_labeled_center.nii.gz') list_label_results = label_results.image_input.getNonZeroCoordinates( sorting='value') # get dimension # from msct_image import Image # img = Image(path_output+contrast+'_seg_labeled.nii.gz') nx, ny, nz, nt, px, py, pz, pt = label_results.image_input.dim except: status = 1 output += '\nERROR: cannot open file: ' + path_output + contrast + '_seg_labeled.nii.gz' write_to_log_file(fname_log, output, 'w') return status, output, DataFrame(data={ 'status': int(status), 'output': output }, index=[path_data]) mse = 0.0 max_dist = 0.0 for coord_manual in list_label_manual: for coord in list_label_results: if round(coord.value) == round(coord_manual.value): # Calculate MSE mse += (((coord_manual.x - coord.x) * px)**2 + ((coord_manual.y - coord.y) * py)**2 + ((coord_manual.z - coord.z) * pz)**2) / float(3) # Calculate distance (Frobenius norm) dist = linalg.norm([(coord_manual.x - coord.x) * px, (coord_manual.y - coord.y) * py, (coord_manual.z - coord.z) * pz]) if dist > max_dist: max_dist = dist break rmse = sqrt(mse / len(list_label_manual)) # calculate number of label mismatch diff_manual_result = len(list_label_manual) - len(list_label_results) # check if MSE is superior to threshold th_rmse = 2 if rmse > th_rmse: status = 99 output += '\nWARNING: RMSE = ' + str(rmse) + ' > ' + str(th_rmse) th_max_dist = 4 if max_dist > th_max_dist: status = 99 output += '\nWARNING: Max distance = ' + str( max_dist) + ' > ' + str(th_max_dist) th_diff_manual_result = 3 if abs(diff_manual_result) > th_diff_manual_result: status = 99 output += '\nWARNING: Diff manual-result = ' + str( diff_manual_result) + ' > ' + str(th_diff_manual_result) # transform results into Pandas structure results = DataFrame(data={ 'status': int(status), 'output': output, 'rmse': rmse, 'max_dist': max_dist, 'diff_man': diff_manual_result, 'duration [s]': duration }, index=[path_data]) # write log file write_to_log_file(fname_log, output, 'w') return status, output, results