示例#1
0
def main():
    # Callback required for FURY
    def keypress_callback(obj, _):
        key = obj.GetKeySym().lower()
        nonlocal clusters_linewidth, background_linewidth
        nonlocal curr_streamlines_actor, concat_streamlines_actor, show_curr_actor
        iterator = len(accepted_streamlines) + len(rejected_streamlines)
        renwin = interactor_style.GetInteractor().GetRenderWindow()
        renderer = interactor_style.GetCurrentRenderer()

        if key == 'c' and iterator < len(sft_accepted_on_size):
            if show_curr_actor:
                renderer.rm(concat_streamlines_actor)
                renwin.Render()
                show_curr_actor = False
                logging.info('Streamlines rendering OFF')
            else:
                renderer.add(concat_streamlines_actor)
                renderer.rm(curr_streamlines_actor)
                renderer.add(curr_streamlines_actor)
                renwin.Render()
                show_curr_actor = True
                logging.info('Streamlines rendering ON')
            return

        if key == 'q':
            show_manager.exit()
            if iterator < len(sft_accepted_on_size):
                logging.warning(
                    'Early exit, everything remaining to be rejected.')
            return

        if key in ['a', 'r'] and iterator < len(sft_accepted_on_size):
            if key == 'a':
                accepted_streamlines.append(iterator)
                choices.append('a')
                logging.info('Accepted file %s',
                             filename_accepted_on_size[iterator])
            elif key == 'r':
                rejected_streamlines.append(iterator)
                choices.append('r')
                logging.info('Rejected file %s',
                             filename_accepted_on_size[iterator])
            iterator += 1

        if key == 'z':
            if iterator > 0:
                last_choice = choices.pop()
                if last_choice == 'r':
                    rejected_streamlines.pop()
                else:
                    accepted_streamlines.pop()
                logging.info('Rewind on step.')

                iterator -= 1
            else:
                logging.warning('Cannot rewind, first element.')

        if key in ['a', 'r', 'z'] and iterator < len(sft_accepted_on_size):
            renderer.rm(curr_streamlines_actor)
            curr_streamlines = sft_accepted_on_size[iterator].streamlines
            curr_streamlines_actor = actor.line(curr_streamlines,
                                                opacity=0.8,
                                                linewidth=clusters_linewidth)
            renderer.add(curr_streamlines_actor)

        if iterator == len(sft_accepted_on_size):
            print('No more cluster, press q to exit')
            renderer.rm(curr_streamlines_actor)

        renwin.Render()

    parser = _build_args_parser()
    args = parser.parse_args()

    assert_inputs_exist(parser, args.in_bundles)
    assert_outputs_exist(parser, args, [args.out_accepted, args.out_rejected])

    if args.out_accepted_dir:
        assert_output_dirs_exist_and_empty(parser,
                                           args,
                                           args.out_accepted_dir,
                                           create_dir=True)
    if args.out_rejected_dir:
        assert_output_dirs_exist_and_empty(parser,
                                           args,
                                           args.out_rejected_dir,
                                           create_dir=True)

    if args.verbose:
        logging.basicConfig(level=logging.INFO)

    if args.min_cluster_size < 1:
        parser.error('Minimum cluster size must be at least 1.')

    clusters_linewidth = args.clusters_linewidth
    background_linewidth = args.background_linewidth

    # To accelerate procedure, clusters can be discarded based on size
    # Concatenation is to give spatial context
    sft_accepted_on_size, filename_accepted_on_size = [], []
    sft_rejected_on_size, filename_rejected_on_size = [], []
    concat_streamlines = []
    for filename in args.in_bundles:
        if not is_header_compatible(args.in_bundles[0], filename):
            return
        basename = os.path.basename(filename)
        sft = load_tractogram_with_reference(parser,
                                             args,
                                             filename,
                                             bbox_check=False)
        if len(sft) >= args.min_cluster_size:
            sft_accepted_on_size.append(sft)
            filename_accepted_on_size.append(basename)
            concat_streamlines.extend(sft.streamlines)
        else:
            logging.info('File %s has %s streamlines, automatically rejected.',
                         filename, len(sft))
            sft_rejected_on_size.append(sft)
            filename_rejected_on_size.append(basename)

    if not filename_accepted_on_size:
        parser.error('No cluster survived the cluster_size threshold.')

    logging.info('%s clusters to be classified.', len(sft_accepted_on_size))
    # The clusters are sorted by size for simplicity/efficiency
    tuple_accepted = zip(
        *sorted(zip(sft_accepted_on_size, filename_accepted_on_size),
                key=lambda x: len(x[0]),
                reverse=True))
    sft_accepted_on_size, filename_accepted_on_size = tuple_accepted

    # Initialize the actors, scene, window, observer
    concat_streamlines_actor = actor.line(concat_streamlines,
                                          colors=(1, 1, 1),
                                          opacity=args.background_opacity,
                                          linewidth=background_linewidth)
    curr_streamlines_actor = actor.line(sft_accepted_on_size[0].streamlines,
                                        opacity=0.8,
                                        linewidth=clusters_linewidth)

    scene = window.Scene()
    interactor_style = interactor.CustomInteractorStyle()
    show_manager = window.ShowManager(scene,
                                      size=(800, 800),
                                      reset_camera=False,
                                      interactor_style=interactor_style)
    scene.add(concat_streamlines_actor)
    scene.add(curr_streamlines_actor)
    interactor_style.AddObserver('KeyPressEvent', keypress_callback)

    # Lauch rendering and selection procedure
    choices, accepted_streamlines, rejected_streamlines = [], [], []
    show_curr_actor = True
    show_manager.start()

    # Early exit means everything else is rejected
    missing = len(args.in_bundles) - len(choices) - len(sft_rejected_on_size)
    len_accepted = len(sft_accepted_on_size)
    rejected_streamlines.extend(range(len_accepted - missing, len_accepted))
    if missing > 0:
        logging.info('%s clusters automatically rejected from early exit',
                     missing)

    # Save accepted clusters (by GUI)
    accepted_streamlines = save_clusters(sft_accepted_on_size,
                                         accepted_streamlines,
                                         args.out_accepted_dir,
                                         filename_accepted_on_size)

    accepted_sft = StatefulTractogram(accepted_streamlines,
                                      sft_accepted_on_size[0], Space.RASMM)
    save_tractogram(accepted_sft, args.out_accepted, bbox_valid_check=False)

    # Save rejected clusters (by GUI)
    rejected_streamlines = save_clusters(sft_accepted_on_size,
                                         rejected_streamlines,
                                         args.out_rejected_dir,
                                         filename_accepted_on_size)

    # Save rejected clusters (by size)
    rejected_streamlines.extend(
        save_clusters(sft_rejected_on_size, range(len(sft_rejected_on_size)),
                      args.out_rejected_dir, filename_rejected_on_size))

    rejected_sft = StatefulTractogram(rejected_streamlines,
                                      sft_accepted_on_size[0], Space.RASMM)
    save_tractogram(rejected_sft, args.out_rejected, bbox_valid_check=False)
示例#2
0
def test_custom_interactor_style_events(recording=False):
    print("Using VTK {}".format(vtk.vtkVersion.GetVTKVersion()))
    filename = "test_custom_interactor_style_events.log.gz"
    recording_filename = pjoin(DATA_DIR, filename)
    scene = window.Scene()

    # the show manager allows to break the rendering process
    # in steps so that the widgets can be added properly
    interactor_style = interactor.CustomInteractorStyle()
    show_manager = window.ShowManager(scene,
                                      size=(800, 800),
                                      reset_camera=False,
                                      interactor_style=interactor_style)

    # Create a cursor, a circle that will follow the mouse.
    polygon_source = vtk.vtkRegularPolygonSource()
    polygon_source.GeneratePolygonOff()  # Only the outline of the circle.
    polygon_source.SetNumberOfSides(50)
    polygon_source.SetRadius(10)
    # polygon_source.SetRadius
    polygon_source.SetCenter(0, 0, 0)

    mapper = vtk.vtkPolyDataMapper2D()
    vtk_utils.set_input(mapper, polygon_source.GetOutputPort())

    cursor = vtk.vtkActor2D()
    cursor.SetMapper(mapper)
    cursor.GetProperty().SetColor(1, 0.5, 0)
    scene.add(cursor)

    def follow_mouse(iren, obj):
        obj.SetPosition(*iren.event.position)
        iren.force_render()

    interactor_style.add_active_prop(cursor)
    interactor_style.add_callback(cursor, "MouseMoveEvent", follow_mouse)

    # create some minimalistic streamlines
    lines = [
        np.array([[-1, 0, 0.], [1, 0, 0.]]),
        np.array([[-1, 1, 0.], [1, 1, 0.]])
    ]
    colors = np.array([[1., 0., 0.], [0.3, 0.7, 0.]])
    tube1 = actor.streamtube([lines[0]], colors[0])
    tube2 = actor.streamtube([lines[1]], colors[1])
    scene.add(tube1)
    scene.add(tube2)

    # Define some counter callback.
    states = defaultdict(lambda: 0)

    def counter(iren, _obj):
        states[iren.event.name] += 1

    # Assign the counter callback to every possible event.
    for event in [
            "CharEvent", "MouseMoveEvent", "KeyPressEvent", "KeyReleaseEvent",
            "LeftButtonPressEvent", "LeftButtonReleaseEvent",
            "RightButtonPressEvent", "RightButtonReleaseEvent",
            "MiddleButtonPressEvent", "MiddleButtonReleaseEvent"
    ]:
        interactor_style.add_callback(tube1, event, counter)

    # Add callback to scale up/down tube1.
    def scale_up_obj(iren, obj):
        counter(iren, obj)
        scale = np.asarray(obj.GetScale()) + 0.1
        obj.SetScale(*scale)
        iren.force_render()
        iren.event.abort()  # Stop propagating the event.

    def scale_down_obj(iren, obj):
        counter(iren, obj)
        scale = np.array(obj.GetScale()) - 0.1
        obj.SetScale(*scale)
        iren.force_render()
        iren.event.abort()  # Stop propagating the event.

    interactor_style.add_callback(tube2, "MouseWheelForwardEvent",
                                  scale_up_obj)
    interactor_style.add_callback(tube2, "MouseWheelBackwardEvent",
                                  scale_down_obj)

    # Add callback to hide/show tube1.
    def toggle_visibility(iren, obj):
        key = iren.event.key
        if key.lower() == "v":
            obj.SetVisibility(not obj.GetVisibility())
            iren.force_render()

    interactor_style.add_active_prop(tube1)
    interactor_style.add_active_prop(tube2)
    interactor_style.remove_active_prop(tube2)
    interactor_style.add_callback(tube1, "CharEvent", toggle_visibility)

    if recording:
        show_manager.record_events_to_file(recording_filename)
        print(list(states.items()))
    else:
        show_manager.play_events_from_file(recording_filename)
        msg = ("Wrong count for '{}'.")
        expected = [('CharEvent', 6), ('KeyPressEvent', 6),
                    ('KeyReleaseEvent', 6), ('MouseMoveEvent', 1652),
                    ('LeftButtonPressEvent', 1), ('RightButtonPressEvent', 1),
                    ('MiddleButtonPressEvent', 2),
                    ('LeftButtonReleaseEvent', 1),
                    ('MouseWheelForwardEvent', 3),
                    ('MouseWheelBackwardEvent', 1),
                    ('MiddleButtonReleaseEvent', 2),
                    ('RightButtonReleaseEvent', 1)]

        # Useful loop for debugging.
        for event, count in expected:
            if states[event] != count:
                print("{}: {} vs. {} (expected)".format(
                    event, states[event], count))

        for event, count in expected:
            npt.assert_equal(states[event], count, err_msg=msg.format(event))
示例#3
0
import vtk
from fury import utils as vtk_utils
from fury import actor, window, interactor
scene = window.Scene()

# the show manager allows to break the rendering process
# in steps so that the widgets can be added properly
interactor_style = interactor.CustomInteractorStyle()
show_manager = window.ShowManager(scene,
                                  size=(800, 800),
                                  reset_camera=False,
                                  interactor_style=interactor_style)

# Create a cursor, a circle that will follow the mouse.
polygon_source = vtk.vtkRegularPolygonSource()
polygon_source.GeneratePolygonOff()  # Only the outline of the circle.
polygon_source.SetNumberOfSides(50)
polygon_source.SetRadius(10)
# polygon_source.SetRadius
polygon_source.SetCenter(0, 0, 0)

mapper = vtk.vtkPolyDataMapper2D()
vtk_utils.set_input(mapper, polygon_source.GetOutputPort())

cursor = vtk.vtkActor2D()
cursor.SetMapper(mapper)
cursor.GetProperty().SetColor(1, 0.5, 0)
scene.add(cursor)


def follow_mouse(iren, obj):