Beispiel #1
0
def main():

    #logger = logging.getLogger(__name__)
    logger = logging.getLogger()

    logger.setLevel(logging.WARNING)
    ch = logging.StreamHandler()
    logger.addHandler(ch)

    #logger.debug('input params')

    print 'version: ', qmisc.getVersionString()
###
# Configuration is has three sources:
#  * Default function values
#  * Config file 'organ_segmentation.config' in directory with application
#  * Config file 'organ_segmentation.config' in output data directory
#
# It is read in this order so the last one has highest priority

###
## read confguraton from file, use default values from OrganSegmentation
    cfgplus = {
        'datapath': None,
        'viewermax': 300,
        'viewermin': -100,
        'output_datapath': os.path.expanduser("~/lisa_data"),
        'lisa_operator_identifier': "",
        'experiment_caption': ''
    }

    cfg = config.get_default_function_config(OrganSegmentation.__init__)
    cfg.update(cfgplus)
    # now is in cfg default values

    cfg = config.get_config("organ_segmentation.config", cfg)
# read user defined config in user data
    cfg = config.get_config(
        os.path.join(cfg['output_datapath'], "organ_segmentation.config"),
        cfg
    )

    # input parser
    parser = argparse.ArgumentParser(
        description='Segment vessels from liver \n\
                \npython organ_segmentation.py\n\
                \npython organ_segmentation.py -mroi -vs 0.6')
    parser.add_argument('-dd', '--datapath',
                        default=cfg["datapath"],
                        help='path to data dir')
    parser.add_argument('-d', '--debug', action='store_true',
                        help='run in debug mode')
    parser.add_argument(
        '-vs', '--working_voxelsize_mm',
        default=cfg["working_voxelsize_mm"],
        type=eval,  # type=str,
        help='Insert working voxelsize. It can be number or \
        array of three numbers. It is possible use original \n \
        resolution or half of original resolution. \n \
        -vs 3 \n \
        -vs [3,3,5] \n \
        -vs orig \n \
        -vs orig*2 \n \
        -vs orig*4 \n \
        '
    )
    parser.add_argument('-mroi', '--manualroi', action='store_true',
                        help='manual crop before data processing',
                        default=cfg["manualroi"])

    parser.add_argument('-op', '--output_datapath',
                        default=cfg["output_datapath"],
                        help='path for output data')

    parser.add_argument('-ol', '--output_label', default=1,
                        help='label for segmented data')
    parser.add_argument(
        '--slab',
        default=cfg["slab"],
        type=eval,
        help='labels for segmentation,\
            example -slab "{\'liver\':1, \'lesions\':6}"')
    parser.add_argument(
        '-acr', '--autocrop',
        help='automatic crop after data processing',
        default=cfg["autocrop"])
    parser.add_argument(
        '-iparams', '--iparams',
        default=None,
        help='filename of ipars file with stored interactivity')
    parser.add_argument(
        '-sp', '--segparams', type=eval,
        default=cfg["segparams"],
        help='params for segmentation,\
            example -sp "{\'pairwise_alpha_per_mm2\':90}"')
    parser.add_argument(
        '-tx', '--texture_analysis', action='store_true',
        help='run with texture analysis')
    parser.add_argument('-exd', '--exampledata', action='store_true',
                        help='run unittest')
    parser.add_argument('-ed', '--edit_data', action='store_true',
                        help='Run data editor')
    parser.add_argument(
        '-vmax', '--viewermax', type=eval,  # type=int,
        help='Maximum of viewer window, set None for automatic maximum.',
        default=cfg["viewermax"])
    parser.add_argument(
        '-vmin', '--viewermin', type=eval,  # type=int,
        help='Minimum of viewer window, set None for automatic minimum.',
        default=cfg["viewermin"])
    parser.add_argument(
        '-so', '--show_output', action='store_true',
        help='Show output data in viewer')
    parser.add_argument('-a', '--arg', nargs='+', type=float)
    parser.add_argument(
        '-ec', '--experiment_caption', type=str,  # type=int,
        help='Short caption of experiment. No special characters.',
        default=cfg["experiment_caption"])
    parser.add_argument(
        '-oi', '--lisa_operator_identifier', type=str,  # type=int,
        help='Identifier of Lisa operator.',
        default=cfg["experiment_caption"])
    parser.add_argument(
        '-ss',
        '--segmentation_smoothing',
        action='store_true',
        help='Smoothing of output segmentation',
        default=cfg["segmentation_smoothing"]
    )
    args_obj = parser.parse_args()
    args = vars(args_obj)
    #print args["arg"]
    oseg_argspec_keys = config.get_function_keys(OrganSegmentation.__init__)

    # voxelsize_mm can be number or array
    #if args.voxelsize_mm != 'orig':
#TODO easy way to set half of resolution
#    if isinstance(args["working_voxelsize_mm"], numbers.Number)
#        if args["working_voxelsize_mm"] == -1:
#            args["working_voxelsize_mm"] = 'orig'
## todo and so on
#    if not args["working_voxelsize_mm"].startswith('orig'):
#        #import pdb; pdb.set_trace()
#        args["working_voxelsize_mm"] = eval(args["working_voxelsize_mm"])

    #
    #args["segparams"] = eval(args["segparams"])
    #args["slab"] = eval(args["slab"])

    #args["viewermin"] = eval(args["viewermin"])
    #args["viewermax"] = eval(args["viewermax"])

    if args["debug"]:
        logger.setLevel(logging.DEBUG)

    if args["exampledata"]:

        args["datapath"] = '../sample_data/\
                matlab/examples/sample_data/DICOM/digest_article/'

    if args["iparams"] is not None:
        iparams = misc.obj_from_file(args["iparams"], filetype='pickle')
        oseg = OrganSegmentation(**iparams)

    else:
    #else:
    #dcm_read_from_dir('/home/mjirik/data/medical/data_orig/46328096/')
        #data3d, metadata = dcmreaddata.dcm_read_from_dir()
        data3d, metadata, qt_app = readData3d(args["datapath"])
        args['datapath'] = metadata['datadir']

        oseg_params = config.subdict(args, oseg_argspec_keys)
        oseg_params["data3d"] = data3d
        oseg_params["metadata"] = metadata
        oseg_params['qt_app'] = qt_app
        oseg = OrganSegmentation(**oseg_params)

    oseg.interactivity(args["viewermin"], args["viewermax"])

    #igc = pycut.ImageGraphCut(data3d, zoom = 0.5)
    #igc.interactivity()

    #igc.make_gc()
    #igc.show_segmentation()
    # volume
    #volume_mm3 = np.sum(oseg.segmentation > 0) * np.prod(oseg.voxelsize_mm)

    audiosupport.beep()
    print(
        "Volume " +
        str(oseg.get_segmented_volume_size_mm3() / 1000000.0) + ' [l]')
    #pyed = py3DSeedEditor.py3DSeedEditor(oseg.data3d, contour =
    # oseg.segmentation)
    #pyed.show()
    print("Total time: " + str(oseg.processing_time))

    if args["show_output"]:
        oseg.show_output()

    #print savestring
    save_outputs(args, oseg, qt_app)
#    import pdb; pdb.set_trace()
    return
Beispiel #2
0
def save_outputs(args, oseg, qt_app):
    from PyQt4.QtGui import QInputDialog
    savestring_qt, ok = QInputDialog.getText(
        None,
        "Save",
        'Save output data? Yes/No/All+Dicom with input data (y/n/a/ad):',
        text="a"
    )
    savestring = str(savestring_qt)
    #import pdb; pdb.set_trace()
    #savestring = raw_input(
    #    'Save output data? Yes/No/All with input data (y/n/a): '
    #)
    if savestring in ['Y', 'y', 'a', 'A', 'ad']:
        if not os.path.exists(args["output_datapath"]):
            os.makedirs(args['output_datapath'])

        op = args['output_datapath']
# rename

        data = oseg.export()
        data['version'] = qmisc.getVersionString()
        data['experiment_caption'] = args['experiment_caption']
        data['lisa_operator_identifier'] = args['lisa_operator_identifier']
        #data['organ_segmentation_time'] = t1
        iparams = oseg.get_iparams()
        #import pdb; pdb.set_trace()
        pth, filename = os.path.split(os.path.normpath(args['datapath']))
        filename += "-" + args['experiment_caption']
        if savestring in ['a', 'A', 'ad']:
# save renamed file too
            filepath = 'ob-' + filename + '.pklz'
            filepath = os.path.join(op, filepath)
            filepath = misc.suggest_filename(filepath)
            misc.obj_to_file(data, filepath, filetype='pklz')

        filepath = 'organ.pklz'
        filepath = os.path.join(op, filepath)
        #filepath = misc.suggest_filename(filepath)
        misc.obj_to_file(data, filepath, filetype='pklz')

        filepath = 'organ_iparams.pklz'
        filepath = os.path.join(op, filepath)
        misc.obj_to_file(iparams, filepath, filetype='pklz')

        data['data3d'] = None
        filepath = 'organ_small-' + filename + '.pklz'
        filepath = os.path.join(op, filepath)
        filepath = misc.suggest_filename(filepath)
        misc.obj_to_file(data, filepath, filetype='pklz')
    #output = segmentation.vesselSegmentation(oseg.data3d,
    # oseg.orig_segmentation)
#    print "uf"

        if savestring in ['ad']:
            # save to DICOM
            filepath = 'dicom-' + filename
            filepath = os.path.join(op, filepath)
            filepath = misc.suggest_filename(filepath)
            output_dicom_dir = filepath
            #import ipdb; ipdb.set_trace()  # BREAKPOINT
            overlays = {
                3:
                (data['segmentation'] == args['output_label']).astype(np.int8)
            }
            saveOverlayToDicomCopy(oseg.metadata['dcmfilelist'],
                                   output_dicom_dir, overlays,
                                   data['crinfo'], data['orig_shape'])
Beispiel #3
0
    def __init__(
        self,
        datapath=None,
        working_voxelsize_mm=3,
        viewermax=None,
        viewermin=None,
        series_number=None,
        autocrop=True,
        autocrop_margin_mm=[10, 10, 10],
        manualroi=False,
        texture_analysis=None,
        segmentation_smoothing=False,
        smoothing_mm=4,
        volume_blowup=1.00,
        data3d=None,
        metadata=None,
        seeds=None,
        edit_data=False,
        segparams={},
        segmodelparams=default_segmodelparams,
        roi=None,
        output_label=1,
        slab={},
        output_datapath=None,
        input_datapath_start='',
        experiment_caption='',
        lisa_operator_identifier='',
        volume_unit='ml',
        save_filetype='pklz',

        #           iparams=None,
    ):
        """ Segmentation of objects from CT data.

        datapath: path to directory with dicom files
        manualroi: manual set of ROI before data processing, there is a
             problem with correct coordinates
        data3d, metadata: it can be used for data loading not from directory.
            If both are setted, datapath is ignored
        output_label: label for output segmented volume
        slab: aditional label system for description segmented data
        {'none':0, 'liver':1, 'lesions':6}
        roi: region of interest. [[startx, stopx], [sty, spy], [stz, spz]]
        seeds: ndimage array with size same as data3d
        experiment_caption = this caption is used for naming of outputs
        lisa_operator_identifier: used for logging
        input_datapath_start: Path where user directory selection dialog
            starts.
        volume_blowup: Blow up volume is computed in smoothing so it is working
            only if smoothing is turned on.

        """

        self.iparams = {}
        self.datapath = datapath
        self.output_datapath = output_datapath
        self.input_datapath_start = input_datapath_start
        self.crinfo = [[0, -1], [0, -1], [0, -1]]
        self.slab = slab
        self.output_label = output_label
        self.working_voxelsize_mm = None
        self.input_wvx_size = working_voxelsize_mm

        # print segparams
# @TODO each axis independent alpha
        self.segparams = default_segparams
        self.segparams.update(segparams)
        self.segmodelparams = default_segmodelparams
        self.segmodelparams.update(segmodelparams)
        self.series_number = series_number

        self.autocrop = autocrop
        self.autocrop_margin_mm = np.array(autocrop_margin_mm)
        self.texture_analysis = texture_analysis
        self.segmentation_smoothing = segmentation_smoothing
        self.smoothing_mm = smoothing_mm
        self.volume_blowup = volume_blowup
        self.edit_data = edit_data
        self.roi = roi
        self.data3d = data3d
        self.seeds = seeds
        self.segmentation = None
        self.processing_time = None
        self.experiment_caption = experiment_caption
        self.lisa_operator_identifier = lisa_operator_identifier
        self.version = qmisc.getVersionString()
        self.viewermax = viewermax
        self.viewermin = viewermin
        self.volume_unit = volume_unit
        self.organ_interactivity_counter = 0
        self.dcmfilelist = None
        self.save_filetype = save_filetype

#
        oseg_input_params = locals()
        oseg_input_params = self.__clean_oseg_input_params(oseg_input_params)

        logger.debug("oseg_input_params")
        logger.debug(str(oseg_input_params))
        self.oseg_input_params = oseg_input_params

        if data3d is None or metadata is None:
            # if 'datapath' in self.iparams:
            #     datapath = self.iparams['datapath']

            if datapath is not None:
                reader = datareader.DataReader()
                datap = reader.Get3DData(datapath, dataplus_format=True)
                # self.iparams['series_number'] = metadata['series_number']
                # self.iparams['datapath'] = datapath
                self.import_dataplus(datap)
            else:
                # data will be selected from gui
                pass
                # logger.error('No input path or 3d data')

        else:
            # self.data3d = data3d
            # default values are updated in next line
            mindatap = {'series_number': -1,
                        'voxelsize_mm': 1,
                        'datapath': None,
                        'data3d': data3d
                        }

            mindatap.update(metadata)
            self.import_dataplus(mindatap)
Beispiel #4
0
    def __init__(
        self,
        datapath=None,
        working_voxelsize_mm=3,
        viewermax=None,
        viewermin=None,
        series_number=None,
        autocrop=True,
        autocrop_margin_mm=[10, 10, 10],
        manualroi=False,
        texture_analysis=None,
        segmentation_smoothing=False,
        smoothing_mm=4,
        volume_blowup=1.00,
        data3d=None,
        metadata=None,
        seeds=None,
        edit_data=False,
        segparams={},
        segmodelparams=default_segmodelparams,
        roi=None,
        output_label=1,
        slab={},
        output_datapath=None,
        input_datapath_start='',
        experiment_caption='',
        lisa_operator_identifier='',
        volume_unit='ml',
        save_filetype='pklz',
        debug_mode=False,
        seg_postproc_pars={},
        cache_filename='cache.yml',
        seg_preproc_pars={},


        #           iparams=None,
    ):
        """ Segmentation of objects from CT data.

        :param datapath: path to directory with dicom files
        :param manualroi: manual set of ROI before data processing, there is a
             problem with correct coordinates
        :param data3d, metadata: it can be used for data loading not from
        directory. If both are setted, datapath is ignored
        :param output_label: label for output segmented volume
        :param slab: aditional label system for description segmented data
        {'none':0, 'liver':1, 'lesions':6}
        :param roi: region of interest.
        [[startx, stopx], [sty, spy], [stz, spz]]
        :param seeds: ndimage array with size same as data3d
        :param experiment_caption = this caption is used for naming of outputs
        :param lisa_operator_identifier: used for logging
        :param input_datapath_start: Path where user directory selection dialog
            starts.
        :param volume_blowup: Blow up volume is computed in smoothing so it is
        working only if smoothing is turned on.
        :param seg_postproc_pars: Can be used for setting postprocessing
        parameters. For example
        """

        self.iparams = {}
        self.datapath = datapath
        self.output_datapath = output_datapath
        self.input_datapath_start = input_datapath_start
        self.crinfo = [[0, None], [0, None], [0, None]]
        self.slab = data_plus.default_slab()
        self.slab.update(slab)
        self.output_label = output_label
        self.working_voxelsize_mm = None
        self.input_wvx_size = working_voxelsize_mm

        # print segparams
# @TODO each axis independent alpha
        self.segparams = default_segparams
        self.segparams.update(segparams)
        self.segmodelparams = default_segmodelparams
        self.segmodelparams.update(segmodelparams)
        self.series_number = series_number

        self.autocrop = autocrop
        self.autocrop_margin_mm = np.array(autocrop_margin_mm)
        self.texture_analysis = texture_analysis
        self.segmentation_smoothing = segmentation_smoothing
        self.smoothing_mm = smoothing_mm
        self.volume_blowup = volume_blowup
        self.edit_data = edit_data
        self.roi = roi
        self.data3d = data3d
        self.seeds = seeds
        self.segmentation = None
        self.processing_time = None
        self.experiment_caption = experiment_caption
        self.lisa_operator_identifier = lisa_operator_identifier
        self.version = qmisc.getVersionString()
        self.viewermax = viewermax
        self.viewermin = viewermin
        self.volume_unit = volume_unit
        self.organ_interactivity_counter = 0
        self.dcmfilelist = None
        self.save_filetype = save_filetype
        self.vessel_tree = {}
        self.debug_mode = debug_mode
        # SegPostprocPars = namedtuple(
        #     'SegPostprocPars', [
        #         'smoothing_mm',
        #         'segmentation_smoothing',
        #         'volume_blowup',
        #         'snakes',
        #         'snakes_method',
        #         'snakes_params']
        # )
        self.cache = cachef.CacheFile(cache_filename)

        self.seg_postproc_pars = {
            'smoothing_mm': smoothing_mm,
            'segmentation_smoothing': segmentation_smoothing,
            'volume_blowup': volume_blowup,
            'snakes': False,
            'snakes_method': 'ACWE',
            'snakes_params': {'smoothing': 1, 'lambda1': 100, 'lambda2': 1},
            'snakes_niter': 20,
        }
        self.seg_postproc_pars.update(seg_postproc_pars)
        self.seg_preproc_pars = {
            'use_automatic_segmentation': True,
        }
        self.seg_preproc_pars.update(seg_preproc_pars)
        # seg_postproc_pars.update(seg_postproc_pars)
        # import ipdb; ipdb.set_trace() #  noqa BREAKPOINT

        # self.seg_postproc_pars = SegPostprocPars(**seg_postproc_pars_default)

#
        oseg_input_params = locals()
        oseg_input_params = self.__clean_oseg_input_params(oseg_input_params)

        logger.debug("oseg_input_params")
        logger.debug(str(oseg_input_params))
        self.oseg_input_params = oseg_input_params

        if data3d is None or metadata is None:
            # if 'datapath' in self.iparams:
            #     datapath = self.iparams['datapath']

            if datapath is not None:
                reader = datareader.DataReader()
                datap = reader.Get3DData(datapath, dataplus_format=True)
                # self.iparams['series_number'] = metadata['series_number']
                # self.iparams['datapath'] = datapath
                self.import_dataplus(datap)

        else:
            # self.data3d = data3d
            # default values are updated in next line
            mindatap = {'series_number': -1,
                        'voxelsize_mm': 1,
                        'datapath': None,
                        'data3d': data3d
                        }

            mindatap.update(metadata)
            self.import_dataplus(mindatap)
Beispiel #5
0
    def test_getVersionString(self):
        """
        """
        verstr = qmisc.getVersionString()

        self.assertTrue(type(verstr) == str)