def load_manual_gmseg(list_slices_target,
                      list_fname_manual_gmseg,
                      tmp_dir,
                      im_sc_seg_rpi,
                      new_res,
                      square_size_size_mm,
                      for_model=False,
                      fname_mask=None):
    if isinstance(list_fname_manual_gmseg, str):
        # consider fname_manual_gmseg as a list of file names to allow multiple manual GM segmentation
        list_fname_manual_gmseg = [list_fname_manual_gmseg]

    curdir = os.getcwd()

    for fname_manual_gmseg in list_fname_manual_gmseg:
        copy(fname_manual_gmseg, tmp_dir)
        # change fname level to only file name (path = tmp dir now)
        path_gm, file_gm, ext_gm = extract_fname(fname_manual_gmseg)
        fname_manual_gmseg = file_gm + ext_gm
        os.chdir(tmp_dir)

        im_manual_gmseg = Image(fname_manual_gmseg).change_orientation("RPI")

        if fname_mask is not None:
            cropper = ImageCropper(im_manual_gmseg)
            cropper.get_bbox_from_mask(fname_mask)
            im_manual_gmseg_crop = cropper.crop()
            im_manual_gmseg = im_manual_gmseg_crop

        # assert gmseg has the right number of slices
        assert im_manual_gmseg.data.shape[2] == len(
            list_slices_target
        ), 'ERROR: the manual GM segmentation has not the same number of slices than the image.'

        # interpolate gm to reference image
        nz_gmseg, nx_gmseg, ny_gmseg, nt_gmseg, pz_gmseg, px_gmseg, py_gmseg, pt_gmseg = im_manual_gmseg.dim

        list_im_gm = interpolate_im_to_ref(im_manual_gmseg,
                                           im_sc_seg_rpi,
                                           new_res=new_res,
                                           sq_size_size_mm=square_size_size_mm,
                                           interpolation_mode=0)

        # load gm seg in list of slices
        n_poped = 0
        for im_gm, slice_im in zip(list_im_gm, list_slices_target):
            if im_gm.data.max() == 0 and for_model:
                list_slices_target.pop(slice_im.id - n_poped)
                n_poped += 1
            else:
                slice_im.gm_seg.append(im_gm.data)
                wm_slice = (slice_im.im > 0) - im_gm.data
                slice_im.wm_seg.append(wm_slice)

        os.chdir(curdir)

    return list_slices_target
def main(argv=None):
    """
    Main function
    :param argv:
    :return:
    """
    parser = get_parser()
    arguments = parser.parse_args(argv if argv else ['--help'])
    verbose = arguments.v
    set_global_loglevel(verbose=verbose)

    # initialize ImageCropper
    cropper = ImageCropper(Image(arguments.i))
    cropper.verbose = verbose

    # Switch across cropping methods
    if arguments.g:
        cropper.get_bbox_from_gui()
    elif arguments.m:
        cropper.get_bbox_from_mask(Image(arguments.m))
    elif arguments.ref:
        cropper.get_bbox_from_ref(Image(arguments.ref))
    else:
        cropper.get_bbox_from_minmax(
            BoundingBox(arguments.xmin, arguments.xmax,
                        arguments.ymin, arguments.ymax,
                        arguments.zmin, arguments.zmax)
        )

    # Crop image
    img_crop = cropper.crop(background=arguments.b)

    # Write cropped image to file
    if arguments.o is None:
        fname_out = add_suffix(arguments.i, '_crop')
    else:
        fname_out = arguments.o
    img_crop.save(fname_out)

    display_viewer_syntax([arguments.i, fname_out])
def main(args=None):
    """
    Main function
    :param args:
    :return:
    """
    # get parser args
    if args is None:
        args = None if sys.argv[1:] else ['--help']
    parser = get_parser()
    arguments = parser.parse_args(args=args)

    # initialize ImageCropper
    cropper = ImageCropper(Image(arguments.i))
    cropper.verbose = arguments.v
    init_sct(log_level=cropper.verbose, update=True)  # Update log level

    # Switch across cropping methods
    if arguments.g:
        cropper.get_bbox_from_gui()
    elif arguments.m:
        cropper.get_bbox_from_mask(Image(arguments.m))
    elif arguments.ref:
        cropper.get_bbox_from_ref(Image(arguments.ref))
    else:
        cropper.get_bbox_from_minmax(
            BoundingBox(arguments.xmin, arguments.xmax, arguments.ymin,
                        arguments.ymax, arguments.zmin, arguments.zmax))

    # Crop image
    img_crop = cropper.crop(background=arguments.b)

    # Write cropped image to file
    if arguments.o is None:
        fname_out = sct.add_suffix(arguments.i, '_crop')
    else:
        fname_out = arguments.o
    img_crop.save(fname_out)

    sct.display_viewer_syntax([arguments.i, fname_out])
def pre_processing(fname_target,
                   fname_sc_seg,
                   fname_level=None,
                   fname_manual_gmseg=None,
                   new_res=0.3,
                   square_size_size_mm=22.5,
                   denoising=True,
                   verbose=1,
                   rm_tmp=True,
                   for_model=False):
    printv('\nPre-process data...', verbose, 'normal')

    tmp_dir = tmp_create()

    copy(fname_target, tmp_dir)
    fname_target = ''.join(extract_fname(fname_target)[1:])
    copy(fname_sc_seg, tmp_dir)
    fname_sc_seg = ''.join(extract_fname(fname_sc_seg)[1:])

    curdir = os.getcwd()
    os.chdir(tmp_dir)

    original_info = {
        'orientation': None,
        'im_sc_seg_rpi': None,
        'interpolated_images': []
    }

    im_target = Image(fname_target).copy()
    im_sc_seg = Image(fname_sc_seg).copy()

    # get original orientation
    printv('  Reorient...', verbose, 'normal')
    original_info['orientation'] = im_target.orientation

    # assert images are in the same orientation
    assert im_target.orientation == im_sc_seg.orientation, "ERROR: the image to segment and it's SC segmentation are not in the same orientation"

    im_target_rpi = im_target.copy().change_orientation(
        'RPI', generate_path=True).save()
    im_sc_seg_rpi = im_sc_seg.copy().change_orientation(
        'RPI', generate_path=True).save()
    original_info['im_sc_seg_rpi'] = im_sc_seg_rpi.copy(
    )  # target image in RPI will be used to post-process segmentations

    # denoise using P. Coupe non local means algorithm (see [Manjon et al. JMRI 2010]) implemented in dipy
    if denoising:
        printv('  Denoise...', verbose, 'normal')
        # crop image before denoising to fasten denoising
        nx, ny, nz, nt, px, py, pz, pt = im_target_rpi.dim
        size_x, size_y = (square_size_size_mm + 1) / px, (square_size_size_mm +
                                                          1) / py
        size = int(np.ceil(max(size_x, size_y)))
        # create mask
        fname_mask = 'mask_pre_crop.nii.gz'
        sct_create_mask.main([
            '-i', im_target_rpi.absolutepath, '-p',
            'centerline,' + im_sc_seg_rpi.absolutepath, '-f', 'box', '-size',
            str(size), '-o', fname_mask
        ])
        # crop image
        cropper = ImageCropper(im_target_rpi)
        cropper.get_bbox_from_mask(Image(fname_mask))
        im_target_rpi_crop = cropper.crop()
        # crop segmentation
        cropper = ImageCropper(im_sc_seg_rpi)
        cropper.get_bbox_from_mask(Image(fname_mask))
        im_sc_seg_rpi_crop = cropper.crop()
        # denoising
        from spinalcordtoolbox.math import denoise_nlmeans
        block_radius = 3
        block_radius = int(
            im_target_rpi_crop.data.shape[2] /
            2) if im_target_rpi_crop.data.shape[2] < (block_radius *
                                                      2) else block_radius
        patch_radius = block_radius - 1
        data_denoised = denoise_nlmeans(im_target_rpi_crop.data,
                                        block_radius=block_radius,
                                        patch_radius=patch_radius)
        im_target_rpi_crop.data = data_denoised

        im_target_rpi = im_target_rpi_crop
        im_sc_seg_rpi = im_sc_seg_rpi_crop
    else:
        fname_mask = None

    # interpolate image to reference square image (resample and square crop centered on SC)
    printv('  Interpolate data to the model space...', verbose, 'normal')
    list_im_slices = interpolate_im_to_ref(im_target_rpi,
                                           im_sc_seg_rpi,
                                           new_res=new_res,
                                           sq_size_size_mm=square_size_size_mm)
    original_info[
        'interpolated_images'] = list_im_slices  # list of images (not Slice() objects)

    printv('  Mask data using the spinal cord segmentation...', verbose,
           'normal')
    list_sc_seg_slices = interpolate_im_to_ref(
        im_sc_seg_rpi,
        im_sc_seg_rpi,
        new_res=new_res,
        sq_size_size_mm=square_size_size_mm,
        interpolation_mode=1)
    for i in range(len(list_im_slices)):
        # list_im_slices[i].data[list_sc_seg_slices[i].data == 0] = 0
        list_sc_seg_slices[i] = binarize(list_sc_seg_slices[i],
                                         thr_min=0.5,
                                         thr_max=1)
        list_im_slices[
            i].data = list_im_slices[i].data * list_sc_seg_slices[i].data

    printv('  Split along rostro-caudal direction...', verbose, 'normal')
    list_slices_target = [
        Slice(slice_id=i, im=im_slice.data, gm_seg=[], wm_seg=[])
        for i, im_slice in enumerate(list_im_slices)
    ]

    # load vertebral levels
    if fname_level is not None:
        printv('  Load vertebral levels...', verbose, 'normal')
        # copy level file to tmp dir
        os.chdir(curdir)
        copy(fname_level, tmp_dir)
        os.chdir(tmp_dir)
        # change fname level to only file name (path = tmp dir now)
        fname_level = ''.join(extract_fname(fname_level)[1:])
        # load levels
        list_slices_target = load_level(list_slices_target, fname_level)

    os.chdir(curdir)

    # load manual gmseg if there is one (model data)
    if fname_manual_gmseg is not None:
        printv('\n\tLoad manual GM segmentation(s) ...', verbose, 'normal')
        list_slices_target = load_manual_gmseg(list_slices_target,
                                               fname_manual_gmseg,
                                               tmp_dir,
                                               im_sc_seg_rpi,
                                               new_res,
                                               square_size_size_mm,
                                               for_model=for_model,
                                               fname_mask=fname_mask)

    if rm_tmp:
        # remove tmp folder
        rmtree(tmp_dir)
    return list_slices_target, original_info