def test_slope_corrector_slice_wise_slope_5d_fail(): in_data = np.random.normal(5, 10, [2, 3, 4, 5, 6]) sl = np.random.normal(5, 10, 7) with assert_raises(IOError): data_corrector(in_data, sl, kind='slope')
def test_slope_corrector_slice_wise_slope_3d_fail(): in_data = np.random.normal(5, 10, [4, 5, 3]) sl = np.random.normal(5, 10, 5) with assert_raises(IOError): data_corrector(in_data, sl)
def test_slope_corrector_int_float_slope(): in_data = np.random.normal(5, 10, [3, 4, 5]) sl1 = 5 sl2 = 5.3 out_data1 = data_corrector(in_data, sl1, kind='slope', dtype=np.float64) out_data2 = data_corrector(in_data, sl2, kind='slope', dtype=np.float64) assert_equal(out_data1.dtype, np.float64) assert_equal(out_data2.dtype, np.float64) assert_array_equal(out_data1, sl1 * in_data) assert_array_equal(out_data2, sl2 * in_data)
def test_slope_corrector_slice_wise_slope_5d(): in_data = np.random.normal(5, 10, [2, 3, 4, 5, 6]) sl = np.random.normal(5, 10, 5) out_data = data_corrector(in_data, sl, kind='slope', dtype=np.float64) for t in range(6): for k in range(5): assert_array_equal(out_data[..., k, t], in_data[..., k, t] * sl[k])
def test_slope_corrector_slice_wise_slope_3d(): in_data = np.random.normal(5, 10, [4, 5, 3]) sl = np.random.normal(5, 10, 3) out_data = data_corrector(in_data, sl, kind='slope', dtype=np.float64) for k in range(3): assert_array_equal(out_data[..., k], in_data[..., k] * sl[k])
def slope_corrector_path(slopes_array, path_im_input, path_im_output, eliminate_consec_duplicates=False): """ Correct for the slope from the path of the elements :param slopes_array: :param path_im_input: :param path_im_output: :param eliminate_consec_duplicates: :return: """ im_input = nib.load(path_im_input) # slopes = np.loadtxt(slopes_txt_path) if eliminate_consec_duplicates: slopes_array = np.array( eliminates_consecutive_duplicates(list(slopes_array))) data_output = data_corrector(im_input.get_data(), slopes_array, kind='slope') im_output = set_new_data(im_input, data_output) nib.save(im_output, path_im_output) msg = 'Scaled image saved in ' + path_im_output print(msg)
def nifti_getter(img_data_vol, visu_pars, correct_slope, correct_offset, sample_upside_down, nifti_version, qform_code, sform_code, frame_body_as_frame_head=False, keep_same_det=True, consider_subject_position=False): """ Passage method to get a nifti image from the volume and the element contained into visu_pars. :param img_data_vol: volume of the image. :param visu_pars: corresponding dictionary to the 'visu_pars' data file. :param correct_slope: [True/False] if you want to correct the slope. :param correct_offset: [True/False] if you want to correct the offset. :param sample_upside_down: [True/False] if you want to have the sample rotated 180 around the Ant-Post axis. :param nifti_version: [1/2] according to the required nifti output :param qform_code: required nifti ouptut qform code. :param sform_code: required nifti ouput sform code :param frame_body_as_frame_head: [True/False] if the frame is the same for head and body [monkey] or not [mouse]. :param keep_same_det: flag to constrain the determinant to be as the one provided into the orientation parameter. :param consider_subject_position: [False] if taking into account the 'Head_prone' 'Head_supine' input. :return: """ # Check units of measurements: if not [ 'mm', ] * len(visu_pars['VisuCoreSize']) == visu_pars['VisuCoreUnits']: # if the UoM is not mm, change here. Add other measurements and refer to xyzt_units from nibabel convention. print( 'Warning, measurement not in mm. This version of the converter deals with data in mm only.' ) # get pre-shape and re-shape volume: (pre-shape is the shape compatible with the slope). vol_pre_shape = [int(i) for i in visu_pars['VisuCoreSize']] if int(visu_pars['VisuCoreFrameCount']) > 1: vol_pre_shape += [int(visu_pars['VisuCoreFrameCount'])] if np.prod(vol_pre_shape) == img_data_vol.shape[0]: vol_data = img_data_vol.reshape(vol_pre_shape, order='F') else: echo = img_data_vol.shape[0] / np.prod(vol_pre_shape) vol_pre_shape += [echo] vol_pre_shape = [int(k) for k in vol_pre_shape] vol_data = img_data_vol.reshape(vol_pre_shape, order='F') # correct slope if required if correct_slope: vol_data = data_corrector(vol_data, visu_pars['VisuCoreDataSlope'], kind='slope') # correct offset (AFTER slope) if required if correct_offset: vol_data = data_corrector(vol_data, visu_pars['VisuCoreDataOffs'], kind='offset') # get number sub-volumes num_sub_volumes = len( eliminate_consecutive_duplicates(list( visu_pars['VisuCoreOrientation']))) if num_sub_volumes > 1: output_nifti = [] assert vol_pre_shape[2] % num_sub_volumes == 0 vol_shape = vol_pre_shape[0], vol_pre_shape[1], int(vol_pre_shape[2] / num_sub_volumes) # get resolution - same for all sub-volumes. resolution = compute_resolution_from_visu_pars( visu_pars['VisuCoreExtent'], visu_pars['VisuCoreSize'], visu_pars['VisuCoreFrameThickness']) for id_sub_vol in range(num_sub_volumes): # compute affine affine_transf = compute_affine_from_visu_pars( list(visu_pars['VisuCoreOrientation'])[id_sub_vol * vol_shape[2]], list(visu_pars['VisuCorePosition'])[id_sub_vol * vol_shape[2]], visu_pars['VisuSubjectPosition'], resolution, frame_body_as_frame_head=frame_body_as_frame_head, keep_same_det=keep_same_det, consider_subject_position=consider_subject_position) if sample_upside_down: affine_transf = affine_transf.dot(np.diag([-1, 1, -1, 1])) # get sub volume in the correct shape img_data_sub_vol = vol_data[..., id_sub_vol * vol_shape[2]:(id_sub_vol + 1) * vol_shape[2]] if nifti_version == 1: nib_im_sub_vol = nib.Nifti1Image(img_data_sub_vol, affine=affine_transf) elif nifti_version == 2: nib_im_sub_vol = nib.Nifti2Image(img_data_sub_vol, affine=affine_transf) else: raise IOError('Nifti versions allowed are 1 or 2.') hdr_sub_vol = nib_im_sub_vol.header hdr_sub_vol.set_qform(affine_transf, code=qform_code) hdr_sub_vol.set_sform(affine_transf, code=sform_code) hdr_sub_vol['xyzt_units'] = 10 # default mm, seconds nib_im_sub_vol.update_header() output_nifti.append(nib_im_sub_vol) else: # get shape sh = vol_pre_shape # check for frame groups: -- Very convoluted scaffolding. Waiting to have more infos to refactor this part. # ideally an external function read VisuFGOrderDesc should provide the sh and the choice between # A and # B # while testing for exception. if 'VisuFGOrderDescDim' in visu_pars.keys(): # see manuals D-2-73 if visu_pars['VisuFGOrderDescDim'] > 0: if isinstance(visu_pars['VisuFGOrderDesc'], list): if len(visu_pars['VisuFGOrderDesc']) > 1: descr = visu_pars['VisuFGOrderDesc'][:] # sort descr so that FG_SLICE is the first one, all the others came as they are after swapping. fg_slice_pos = -1 fg_echo = -1 fg_movie = -1 for d in range(len(descr)): if '<FG_SLICE>' in descr[d]: fg_slice_pos = d if '<FG_ECHO>' in descr[d]: fg_echo = d if '<FG_MOVIE>' in descr[d]: fg_movie = d if fg_slice_pos == -1: raise IOError( 'FG_SLICE not found in the order descriptor, can not tell the ordering.' ) descr[fg_slice_pos], descr[0] = descr[0], descr[ fg_slice_pos] dims = [] for dd in descr: dims.append( int( dd.replace('(', '').replace(')', '').split(',')[0])) if np.prod(dims) == sh[-1]: sh = vol_pre_shape[:-1] + dims # A if fg_echo > -1: # MSME stack_data = np.zeros(sh, dtype=vol_data.dtype) for t in range(sh[3]): for z in range(sh[2]): stack_data[:, :, z, t] = vol_data[:, :, z * sh[3] + t] vol_data = np.copy(stack_data) # B elif fg_movie > -1: # DTI vol_data = vol_data.reshape(sh, order='F') else: # Else ? vol_data = vol_data.reshape(sh, order='F') # get resolution resolution = compute_resolution_from_visu_pars( visu_pars['VisuCoreExtent'], visu_pars['VisuCoreSize'], visu_pars['VisuCoreFrameThickness']) # compute affine affine_transf = compute_affine_from_visu_pars( list(visu_pars['VisuCoreOrientation'])[0], list(visu_pars['VisuCorePosition'])[0], visu_pars['VisuSubjectPosition'], resolution, frame_body_as_frame_head=frame_body_as_frame_head, keep_same_det=keep_same_det, consider_subject_position=consider_subject_position) if sample_upside_down: affine_transf = affine_transf.dot(np.diag([-1, 1, -1, 1])) if nifti_version == 1: output_nifti = nib.Nifti1Image(vol_data, affine=affine_transf) elif nifti_version == 2: output_nifti = nib.Nifti2Image(vol_data, affine=affine_transf) else: raise IOError('Nifti versions allowed are 1 or 2.') hdr_sub_vol = output_nifti.header hdr_sub_vol.set_qform(affine_transf, code=qform_code) hdr_sub_vol.set_sform(affine_transf, code=sform_code) hdr_sub_vol['xyzt_units'] = 10 output_nifti.update_header() return output_nifti