def write_connected_lobe(mylock):  # neural network inference needs GPU which can not be computed by multi threads, so the
        # consumer is just the upsampling only.
        while True:
            with mylock:
                ct_fpath = None
                if len(scan_files):  # if scan_files are empty, then threads should not wait any more
                    print(threading.current_thread().name + " gets the lock, thread id: " + str(
                        threading.get_ident()) + " prepare to compute largest 5 lobes , waiting for the data from queue")
                    ct_fpath = scan_files.pop()  # wait up to 1 minutes
                    print(threading.current_thread().name + " gets the data, thread id: " + str(
                        threading.get_ident()) + " prepare to release the lock.")

            if ct_fpath is not None:
                t1 = time.time()
                print(threading.current_thread().name + "is computing ...")
                pred, pred_origin, pred_spacing = cu.load_itk(ct_fpath)
                pred = largest_connected_parts(pred, nb_need_saved=5)
                suffex_len = len(os.path.basename(ct_fpath).split(".")[-1])
                if target_dir:
                    new_dir = target_dir
                else:
                    new_dir = os.path.dirname(ct_fpath) + "/biggest_5_lobe"
                if not os.path.exists(new_dir):
                    os.makedirs(new_dir)
                    print('successfully create directory:', new_dir)
                write_fpath = new_dir + "/" + os.path.basename(ct_fpath)[:-suffex_len - 1] + '.mhd'
                cu.save_itk(write_fpath, pred, pred_origin, pred_spacing)
                t3 = time.time()
                print("successfully save largest 5 lobes at " + write_fpath)
                print("it costs tis seconds to compute the largest 5 lobes of the data " + str(t3 - t1))
            else:
                print(threading.current_thread().name + "scan_files are empty, finish the thread")
                return None
Ejemplo n.º 2
0
 def load_scan(self, file_name):
     """Load mhd or nrrd 3d scan thread safelly. Output is scan and spacing with shape (z,y,x)"""
     with self.lock:
         print(threading.current_thread().name + " get the lock, thread id: " + str(threading.get_ident()) +
               " prepare to load data")
         scan, origin, spacing = cu.load_itk(file_name)  # all the output shape are (z, y, z)
         print(threading.current_thread().name + " load data successfully, release the lock")
     return np.expand_dims(scan, axis=-1), spacing  # size=(z,x,y,1)
def main():
    task = 'vessel'
    model = '1591438344_307_lr0.0001ld0m6l0m7l0pm0.5no_label_dirSScao0ds0dr1bn1fn16trszNonetrzszNonetrspNonetrzspNoneptch_per_scan500tr_nb18ptsz144ptzsz96'
    for file_name in ['52', '53']:
        pred_file_name = '/data/jjia/new/results/vessel/valid/pred/SSc/' + model + '/SSc_patient_' + file_name + '.mhd'
        gdth_file_name = '/data/jjia/mt/data/vessel/valid/gdth_ct/SSc/SSc_patient_' + file_name + '.mhd'
        gdth, gdth_origin, gdth_spacing = cu.load_itk(gdth_file_name)
        pred, pred_origin, pred_spacing = cu.load_itk(pred_file_name)

        # pred, pred_origin, pred_spacing = futil.load_itk('/data/jjia/new/results/SSc_51_lobe_segmentation/loberecon/SSc_patient_51.mhd')

        # connedted_pred = largest_connected_parts(pred, nb_parts_saved=5)
        # pred[connedted_pred == 0] = 0
        # futil.save_itk(
        #     'results/SSc_51_lobe_segmentation/SSc_patient_51_connected.nrrd',
        #     pred, pred_origin, pred_spacing)

        #
        # pred, pred_origin, pred_spacing = futil.load_itk(pred_file_name)
        #
        # connedted_pred = largest_connected_parts(pred, nb_parts_saved=5)
        # pred[connedted_pred==0] = 0
        # futil.save_itk('/data/jjia/new/results/lobe/valid/pred/GLUCOLD/' + model + '/GLUCOLD_patients_' + file_name + '_connected.nrrd', pred, pred_origin, pred_spacing)

        if task == 'vessel':
            labels = [1]
        elif task == 'lobe':
            labels = [4, 5, 6, 7, 8]
        gdth = one_hot_encode_3D(gdth, labels=labels)
        pred = one_hot_encode_3D(pred, labels=labels)

        metrics_dict_all_labels = metrics_dict_all_labels(
            labels, gdth, pred, spacing=gdth_spacing[::-1])
        metrics_dict_all_labels[
            'filename'] = pred_file_name  # add a new key to the metrics
        data_frame = pd.DataFrame(metrics_dict_all_labels)
        data_frame.to_csv('/data/jjia/new/results/vessel/valid/pred/SSc/' +
                          model + '/SSc_patient_' + file_name +
                          'connected.csv',
                          index=False)
Ejemplo n.º 4
0
def write_preds_to_disk(segment,
                        data_dir,
                        preds_dir,
                        number=None,
                        stride=0.25,
                        workers=1,
                        qsize=1,
                        pad=0):
    """
    write predes to disk. Divided into 2 parts: predict (require segmentor.py, using GPU, can not use multi threads),
    and upsampling (require upsample_crop_save_ct, using cpu, multi threads).
    :param segment: an object or an instance
    :param data_dir: directory where ct data is
    :param preds_dir: directory where prediction result will be saved
    :param number: number of predicted ct
    :param stride: stride or overlap ratio during patching
    :return: None
    """
    scan_files = get_all_ct_names(data_dir, number=number)
    print("files are: ", scan_files)
    pad_nb = pad
    q = queue.Queue(qsize)
    cooking_flag = False

    def consumer(
        mylock
    ):  # neural network inference needs GPU which can not be computed by multi threads, so the
        # consumer is just the upsampling only.
        while True:
            if len(scan_files) or cooking_flag or not q.empty(
            ):  # if scan_files and q are empty, then threads should not wait any more
                with mylock:
                    print(
                        threading.current_thread().name +
                        " gets the lock, thread id: " +
                        str(threading.get_ident()) +
                        " prepare to upsample data, waiting for the data from queue"
                    )
                    try:
                        out_mask = q.get(timeout=60)  # wait up to 1 minutes
                        t2 = time.time()
                        print(threading.current_thread().name +
                              " gets the data before upsample at time " +
                              str(t2) + ", the thread releases the lock")
                    except:
                        out_mask = None
                        print(
                            threading.current_thread().name +
                            " does not get the data in 60s, check again if " +
                            "the scan_files are still not empty, the thread releases the lock"
                        )
                if out_mask is not None:
                    t1 = time.time()
                    out_mask.upsample_crop_save_ct()
                    t3 = time.time()
                    print("it costs tis secons to upsample the data " +
                          str(t3 - t1))
            else:
                print(
                    threading.current_thread().name +
                    "files: empty, cooking flag: False, q:empty, finish the thread"
                )
                return None

    thd_list = []
    mylock = threading.Lock()
    for i in range(workers):
        thd = threading.Thread(target=consumer, args=(mylock, ))
        thd.start()
        thd_list.append(thd)

    # for scan_file in scan_files:
    for i in range(len(scan_files)):
        print('start iterate')
        scan_file = scan_files.pop()
        cooking_flag = True

        # ct_scan.shape: (717,, 512, 512), spacing: 0.5, 0.741, 0.741
        ct_scan, origin, spacing = futil.load_itk(filename=scan_file)
        ct_scan = np.pad(ct_scan, ((pad_nb, pad_nb), (pad_nb, pad_nb),
                                   (pad_nb, pad_nb)),
                         mode='constant',
                         constant_values=-3000)
        print('Spacing: ', spacing, 'size', ct_scan.shape)

        # NORMALIZATION
        ct_scan = futil.normalize(ct_scan)

        mask, trgt_space_list, original_shape, labels, trgt_sz_list, io, task = segment.predict(
            ct_scan[..., np.newaxis], ori_space_list=spacing,
            stride=stride)  # shape: (717, 512, 512,1)
        mask = Mask(mask, scan_file, pad_nb, preds_dir, origin, spacing,
                    trgt_space_list, original_shape, labels, trgt_sz_list, io,
                    task)
        q.put(mask, timeout=6000)
        cooking_flag = False

    for thd in thd_list:
        thd.join()
Ejemplo n.º 5
0
def writeFissure(ctFpath, fissureFpath, radiusValue=3, Absdir=None):
    scan, origin, spacing = cu.load_itk(ctFpath)
    fissure = get_fissure(scan, radiusValue=radiusValue)
    cu.save_itk(fissureFpath, fissure, origin, spacing)
    print('save ct mask at', fissureFpath)
Ejemplo n.º 6
0
def write_dices_to_csv(step_nb,
                       labels,
                       gdth_path,
                       pred_path,
                       csv_file,
                       gdth_extension='.nrrd',
                       pred_extension='.nrrd'):
    '''
    this function is to calculate dice between the files in gdth_path and pred_mask_path. all the files must be
    '.nrrd' or '.mhd'. All the files dimensions should be 4, shape is like: (512, 512, 400, 1) or (400, 512, 512, 1)
    the default extension of masks are '.nrrd'

    '''
    print('start calculate dice and write dices to csv')
    gdth_names, pred_names = cu.get_gdth_pred_names(gdth_path, pred_path)

    total_dices_names = ['step_nb']  # dices_names corresponding to total_dices
    total_dices = [step_nb]
    dices_values_matrix = []  # for average computation
    for gdth_name, pred_name in zip(gdth_names, pred_names):
        gdth_name = gdth_name
        pred_name = pred_name
        gdth_file, _, _ = cu.load_itk(gdth_name)
        pred_file, _, _ = cu.load_itk(pred_name)
        dices_values = calculate_dices(
            labels, gdth_file,
            pred_file)  # calculated dices exclude background
        dices_values_matrix.append(dices_values)

        dices_names = [gdth_name]
        for l in labels:  # calculated dices exclude background
            dices_names.append(
                'dice_' + str(l)
            )  # dice_names is a list corresponding to the specific dices_values
        total_dices_names.extend(
            dices_names)  # extend a list by another small list

        total_dices.append(True)  # place a fixed number under the file name
        total_dices.extend(dices_values)
        print('dice_value')
        print(dices_values)

    dices_values_matrix = np.array(dices_values_matrix)

    # average dice of each class and their names
    ave_dice_of_class = np.average(dices_values_matrix, axis=0)
    total_dices.extend(ave_dice_of_class)

    names_ave_of_dice = ['ave_dice_class_' + str(l) for l in labels
                         ]  # calculated ave dices exclude background
    total_dices_names.extend(names_ave_of_dice)

    # average dice of each image and their names
    ave_dice_of_imgs = np.average(dices_values_matrix, axis=1)
    total_dices.extend(ave_dice_of_imgs)

    names_ave_of_imgs = [
        'ave_dice_img_' + str(i) for i in range(len(pred_names))
    ]
    total_dices_names.extend(names_ave_of_imgs)

    # average dices of total class and images
    ave_dice_total = np.average(dices_values_matrix)
    total_dices.append(ave_dice_total)

    name_ave_total = 'ave_total'
    total_dices_names.append(name_ave_total)

    if not os.path.exists(csv_file):
        with open(csv_file, 'a+', newline='') as f:
            writer = csv.writer(f)
            writer.writerow(total_dices_names)

    with open(csv_file, 'a+', newline='') as f:
        writer = csv.writer(f)
        writer.writerow(total_dices)
    print('finish writing dices to csv file at ' + csv_file)
    return None
Ejemplo n.º 7
0
# -*- coding: utf-8 -*-
# @Time    : 11/12/20 3:17 PM
# @Author  : Jingnan
# @Email   : [email protected]

import matplotlib.pyplot as plt
import numpy as np
import random
from jjnutils.util import load_itk

img, _, _ = load_itk(
    "/data/jjia/mt/data/lesion/valid/ori_ct/Covid_lesion/volume-covid19-A-0698.nii.gz"
)
img = img[20, :, :, ...]
noise = np.random.normal(0, 0.05, img.shape)

img_addnnoise = img + noise

plt.figure()
plt.subplot(3, 3, 1)
plt.imshow(noise)
plt.subplot(3, 3, 2)
plt.imshow(img)
plt.subplot(3, 3, 3)
plt.imshow(img_addnnoise)

normized_img = (img - np.mean(img)) / np.std(img)
normized_img_addnoise = normized_img + noise
plt.subplot(3, 3, 4)
plt.imshow(noise)
plt.subplot(3, 3, 5)
def write_all_metrics_for_one_ct(mylock, labels, gdth_name, pred_name,
                                 csv_file, lung, fissure):
    gdth, gdth_origin, gdth_spacing = cu.load_itk(gdth_name)
    pred, pred_origin, pred_spacing = cu.load_itk(pred_name)

    if lung:  # gdth is lung, so pred need to convert to lung from lobes, labels need to be [1],
        # size need to be the same the the gdth size (LOLA11 mask resolutin is 1 mm, 1mm, 1mm)
        pred = get_lung_from_lobe(pred)
        labels = [1]
        if not gdth.shape == pred.shape:  # sometimes the gdth size is different with preds.
            pred = cu.downsample(
                pred,
                ori_sz=pred.shape,
                trgt_sz=gdth.shape,
                order=1,
                labels=labels,
                train=False
            )  # use shape to upsampling because the space is errors sometimes in LOLA11
        suffex_len = len(os.path.basename(pred_name).split(".")[-1])
        lung_file_dir = os.path.dirname(pred_name) + "/lung"
        lung_file_fpath = lung_file_dir + "/" + os.path.basename(
            pred_name)[:-suffex_len - 1] + '.mhd'
        if not os.path.exists(lung_file_dir):
            os.makedirs(lung_file_dir)

        cu.save_itk(lung_file_fpath, pred, pred_origin, pred_spacing)

    elif fissure and ('LOLA11' in gdth_name or "lola11"
                      in gdth_name):  # only have slices annotations
        pred_cp = copy.deepcopy(pred)
        slic_nb = 0
        for i in range(gdth.shape[1]):  # gdth.shape=(600, 512, 512)
            gdth_slice = gdth[:, i, :]
            if not gdth_slice.any():  # the slice is all black
                pred_cp[:, i, :] = 0
            else:
                slic_nb += 1
                # print("gdth slice sum"+str(np.sum(gdth_slice)))
                for j in range(
                        gdth.shape[2]
                ):  # some times only one lobe is annotated in the same slice.
                    gdth_line = gdth_slice[:, j]
                    if not gdth_line.any():
                        pred_cp[:, i, j] = 0
        if slic_nb > 30:
            print('slice number of valuable lobe is greater than 30: ' +
                  str(slic_nb) + ", change to another axis")
            pred_cp = copy.deepcopy(pred)
            slic_nb = 0
            for i in range(gdth.shape[2]):  # gdth.shape=(600, 512, 512)
                gdth_slice = gdth[:, :, i]
                if not gdth_slice.any():  # the slice is all black
                    pred_cp[:, :, i] = 0
                else:
                    slic_nb += 1
                    # print("gdth slice sum" + str(np.sum(gdth_slice)))
                    for j in range(
                            gdth.shape[1]
                    ):  # some times only one lobe is annotated in the same slice.
                        gdth_line = gdth_slice[:, j]
                        if not gdth_line.any():
                            pred_cp[:, j, i] = 0
        if slic_nb > 30:
            raise Exception("cannot get fissure points")
        pred = pred_cp
        cu.save_itk(
            pred_name.split(".mh")[0] + "_points.mha", pred, pred_origin,
            pred_spacing)
        print('slice number of valuable lobe: ', slic_nb)

    gdth = one_hot_encode_3D(gdth, labels=labels)
    pred = one_hot_encode_3D(pred, labels=labels)
    print('start calculate all metrics for image: ', pred_name)
    metrics_dict_all_labels = get_metrics_dict_all_labels(
        labels, gdth, pred, spacing=pred_spacing[::-1])
    metrics_dict_all_labels[
        'filename'] = pred_name  # add a new key to the metrics
    data_frame = pd.DataFrame(metrics_dict_all_labels)
    with mylock:
        data_frame.to_csv(csv_file,
                          mode='a',
                          header=not os.path.exists(csv_file),
                          index=False)
        print(threading.current_thread().name +
              "successfully write metrics to csv " + csv_file)