Summary and Final Submission

After an amazing summer, GSOC has finally come to an end. My project with DIPY under the umbrella of Python Software Foundation was one of the most interesting and challenging projects I have ever worked on.

All my merged pull requests are listed here and the pending ones are available here

The Project

dipy.viz provides many visualization capabilities. The goal of my project was to improve DIPY’s current User Interface widgets and create new ones so as to have a complete library from which users can build interactive applications.

Overview of the work done

Before my project, the library already had working implementations of button, rectangle, disk, sliders, panel, text-box and file menu.

VTK is a great framework as its provides a high level abstraction over the complicated code for graphics rendering. However, there isn’t much documentation and working examples available on the internet to refer to. Therefore, whenever I experimented with new stuff like 3D widgets, animations and filters, progress was slow. But the weekly meetings with my mentors and the targets given kept me going on and I was able to create a lot of new elements.

Since we were building a highly customizable UI, we kept a lot of parameters as arguments so that users can create elements according to their needs. Most of the parameters were also given default values to allow users to simply instantiate an element and see how it works.

Here is an overview of the various widgets that will soon be provided by the library:

ImageContainer2D

PR: https://github.com/nipy/dipy/pull/1522

My first widget was a simple image element which takes the image path and the required size as inputs. I started off with this because the code for this was pretty simple and most of it was already written in other classes.

Option, Checkbox and RadioButton

PR:  https://github.com/nipy/dipy/pull/1559

The Option class, which is a set of a `Button2D` and a TextBlock2D, acts as a single option for check-boxes and radio buttons. It keeps a checked attribute to facilitate checking and unchecking in `Checkbox` and RadioButton classes. The toggle logic is used to change its state.

The Checkbox class implements check-boxes, which is a set of Option objects, where multiple options can be checked at once.

The RadioButton class, which inherits from Checkbox implements radio buttons, which is a set of Option objects, where only one option can be checked at a time.

LineDoubleSlider2D and RangeSlider

PR:  https://github.com/nipy/dipy/pull/1557 

The LineDoubleSlider2D allows the user to have two handles on the same slider. These handles can slide on the track, while not crossing each other at any point. This element is useful for setting a range for a parameter.

This element uses a LineDoubleSlider2D to select a range which restricts a LineSlider2D to move within that range. This is done by updating the min_value or max_value of the LineSlider2D according to the positions of the handles of LineDoubleSlider2D.

Scroll Bar

PR:  https://github.com/nipy/dipy/pull/1564

The scroll bar is an addition to the ListBox2D element which used up and down arrow keys for navigation earlier.

FileMenu

PR:  https://github.com/nipy/dipy/pull/1592

This element allows the user to browse their file system and look at files and folders. They can navigate into and out of directories by clicking on them in the menu.

Orbital Menu

Code:  https://github.com/karandeepSJ/dipy/commit/6a7aed9d9ecc1c94664317601b63581ea037ede7

This is a disk menu around the menu objects which always faces the camera. This is my first try at 3D elements. I haven’t made a PR for this because it requires a major change is the entire library since all the current elements only work in a 2D setting. This has been put on hold and will be continued later. Meanwhile, I assembled a working sample of how it would look like by manually making some changes to the other elements.

Preloader

PR:  https://github.com/nipy/dipy/pull/1611

A Preloader is a visual indication of the process of ‘loading’, displayed to tell the user that the program is running in the background and has not stopped. These include those rotating circles and moving bars we all hate to see on our screens.

Color Picker

PR:  https://github.com/nipy/dipy/pull/1615

The Color Picker I made follows the HSV color model and converts the selected color to RGB. It consists of a vertical bar that selects the hue and a square that selects the saturation and value for the selected hue. There is a small ring inside the square to track the colors selected. The colors in the square get updated whenever the hue is changed.

Future Work

Here’s a list of what we want to do in the future:

  • Generalize the entire viz module, so that all elements work in both 2D and 3D settings. 2D elements should not transform when the camera is moved in a 3D environment.
  • Change the way callbacks are bound to elements. Currently, there are multiple ways this can be done. We want to make a single function to bind callbacks to actors before the next release this year.
  • Style the elements to give a futuristic/ sci-fi appearance.

Acknowledgements

I would like to thank my mentors, Eleftherios Garyfallidis , David Reagan and Ranveer Aggarwal for helping me throughout the summer and holding regular meetings to discuss the project. They, along with other contributors like Marc-Alexandre Côté and Serge Koudoro regularly provided feedback and suggestions to improve my code.

Apart from improving my coding style, this project has helped me to overcome my fear of starting working on large projects.

Thank You !!

 

The Final Weeks

These final weeks were mostly filled with bug fixes and improvements in my previous PRs.

Color Picker

I completed the Color Picker I talked about in the previous post. It is a rectangular color picker based on the HSV model.

It consists of a vertical bar that selects the hue and a square that selects the saturation and value for the selected hue. The horizontal direction of the square corresponds to saturation and the vertical axis to value.
There is a small ring inside the square to track the colors selected. The colors in the square get updated whenever the hue is changed.

The code for this can be found at https://github.com/nipy/dipy/pull/1615.

The Final Challenge

I was given a final task by my mentors which directly deals with brain images. For the tractogram images being generated by DIPY, I was asked to make an ROI (Region of Interest), that could filter the streamlines in the tractogram to show only those that pass through the ROI (something similar to https://vimeo.com/17680190). Tractograms can be generated using the code provided at https://github.com/nipy/dipy/blob/master/doc/examples/viz_advanced.py.

This task involves two features:

  • Filtering the streamlines to show only those that pass through the ROI.
  • Allowing the user to move and distort the ROI in real time.

For filtering polydata, vtk provides a number of filters. I looked at two of them.

  1.  vtkIntersectionPolyDataFilter: This filter takes two vtkPolyData objects and produces the intersection of the polydatas.
  2. vtkSelectEnclosedPoints: This filter takes an array of points and the polydata of a surface, and evaluates all the input points to determine whether they are enclosed by the surface. The filter produces a (0,1) mask that indicates whether points are outside (mask value=0) or inside (mask value=1) the provided surface.

This is a work in progress and there seems to be some issues in these filters. I plan to continue working on this and many other things after the GSOC period ends.

Colors and Animations

These last two weeks have been really uneventful. I have mainly been focusing on fixing bugs in my existing elements. I did however, start work on 2 new elements: Preloader and Color Picker.

Preloader

A Preloader is a visual indication of the process of ‘loading’, used to display to tell the user that the program is running in the background and has not stopped. These include those rotating circles and moving bars we all hate to see on our screens.

These are some examples:

This was a challenging element for me since it was the first time I was playing with animations and timers in VTK. I referred to the example code here to get started and slowly worked my way towards creating a class in the viz module.

This is what I created:

You can find the code for this at https://github.com/karandeepSJ/dipy/commit/0240ba3e301fa6a3407d5e434ac4141efc0c311c

To run it, use this script:

import dipy.viz.ui as ui
import dipy.viz.window as window
loader=ui.Preloader(100)
sm=window.ShowManager(size=(600,600))
sm.initialize()
sm.iren.CreateRepeatingTimer(10)
loader.add_callback(sm.iren, 'TimerEvent', loader.rotate)
sm.ren.add(loader)
sm.start()

 

Color Picker

HSL and HSV Color Models

HSL (hue, saturation, lightness) and HSV (hue, saturation, value) are two alternative representations of the RGB color model, designed to more closely align with the way human vision perceives color-making attributes.

HSL and HSV are both cylindrical geometries, with hue, their angular dimension, starting at the red primary at 0°, passing through the green primary at 120° and the blue primary at 240°, and then wrapping back to red at 360°. In each geometry, the central vertical axis comprises the neutral, achromatic, or gray colors, ranging from black at lightness 0 or value 0, the bottom, to white at lightness 1 or value 1, the top.

The HSV representation models the way paints of different colors mix together, with the saturation dimension resembling various shades of brightly colored paint, and the value dimension resembling the mixture of those paints with varying amounts of black or white paint.

The HSL model places fully saturated colors around a circle at a lightness value of 1/2, where a lightness value of 0 or 1 is fully black or white, respectively.

Common Color Pickers

All color pickers seen in end-user softwares use the HSL and HSV color models. Most show a two-dimensional slice through the model, along with a slider controlling which particular slice is shown, i.e., the third dimension. These exhibit a great variety, because of the various geometric representations of the models – cylinders, hexagonal prisms and cones/bicones. Some common examples are shown below:

All these color pickers use the mouse click coordinates to determine the HSL/HSV values, which are then converted to RGB using simple formulae you can find here.

Currently, I plan on implementing the following two color pickers:

Square Color Picker

 

This color picker has two components, the vertical Hue Bar and the square next to it. The vertical bar allows the user to select the Hue of the color they want, and the square allows to select the Saturation and Value(or Lightness) for that corresponding hue.

This is a good choice since a common human, when choosing a color, first decides upon a ‘pure color’ or hue, and then chooses the shade for that hue, or the saturation and value.

The vtkScalarBarActor  makes it extremely easy for users to add the hue bar. The example code here illustrates how it can be used. The selected hue value can be measured by the distance from the ‘red’ or bottom of the bar. Once a hue is selected, the square next to it can be colored by assigning corresponding colors to the four vertices. All points inside the square will then be interpolated accordingly. When a point is clicked, the corresponding saturation and value can be determined using the horizontal and vertical distance from the lower-left corner, which corresponds to 0 saturation and 0 value.

Circular Color Picker

This color picker combines hue and saturation inside a circle. The distance from center indicates saturation and the radial distance from red indicates the hue. After a H and S are selected, a Line Slider is used to get the Value dimension.

Implementation-wise, this one is really difficult since I could not find any way to create a multicolored circle.

Refactoring and Menus

Generalizing all 2D elements

Currently, all the elements implemented in dipy.viz.ui only work in a 2D setting, since they use vtkActor2D instead of vtkActor. This poses the problem of not being able to set the depth of these elements in a 3D setting. Also, the AddPart function of Assemblies(discussed in the previous post) only accepts vtkActors.

One possible solution to this is changing all vtkActor2D to vtkActor. But this has two problems:

  • The user will have to unnecessarily provide a third argument while positioning the elements in 2D settings. This can be solved by making a wrapper on the _set_position function.
  • Another problem is that in a 3D setting, the user can move the camera  around with left mouse button. With this, the 2D elements ‘rotate’ as the camera moves, which should not be the case, as is shown below.
import dipy.viz.ui as ui
import dipy.viz.window as window

renderer = window.ren()
current_size = [600, 600]
showm = window.ShowManager(renderer, size=current_size, title="Sci-Fi UI")
cube=ui.Cuboid(size=(10,10,10))
rect=ui.Rectangle2D(size=(7,7),color=(1,0,0),position=(10,10))
showm.ren.add(cube)
showm.ren.add(rect)
showm.start()

This cannot be solved using vtkFollower because that only follows the panning of the camera, not zooming.

The only solution that my mentors and I could come up with is to modify all the existing elements by writing two wrapper classes over the UI element class – 2D and 3D and the user decides whether they wish to render an element as 2D or 3D.

Orbital Menu

I successfully ported the old orbital menu for the current UI class.

import dipy.viz.ui as ui
import dipy.viz.window as window

cube=ui.Cuboid(size=(10,10,10))
rect1=ui.Rectangle2D(size=(2,2),color=(1,0,0))
rect2=ui.Rectangle2D(size=(2,2),color=(0,1,0))
rect3=ui.Rectangle2D(size=(2,2),color=(0,0,1))

def toggle(i_ren, obj, follower):
    menu.set_visibility(not menu.visibility)
    menu.visibility = not menu.visibility
    i_ren.force_render()
cube.add_callback(cube.actor, "RightButtonPressEvent", toggle)

renderer = window.ren()
current_size = [600, 600]
showm = window.ShowManager(renderer, size=current_size, title="Sci-Fi UI")
menu=ui.FollowerMenu((0,0,0),5*1.741,renderer.GetActiveCamera(),[rect1,rect2,rect3])

showm.ren.add(cube)
showm.ren.add(menu)
showm.start()

Radial Text

One thing my mentors wanted me to try was create a disk around which some amount of text can be position that can be aligned radially.

The text element for this purpose uses vtkVectorText instead of vtkTextActor to avoid pixelation on zooming.

class TextFollower(UI):
    """ 3D text that follows the camera.
    """

    def __init__(self, text, color, scale, position=(0,0,0)):
        """

        Parameters
        ----------
        text: string
        color: (float, float, float)
        """
        self.text = text
        super(TextFollower, self).__init__(position)
        self.actor.SetScale(scale)
        self.actor.GetProperty().SetColor(color)

    def _get_actors(self):
        return [self.actor]

    def _setup(self):
        """

        Parameters
        ----------
        text: string
        color: (float, float, float)
        """
        actor_text = vtk.vtkVectorText()
        actor_text.SetText(self.text)

        mapper = vtk.vtkPolyDataMapper()
        mapper.SetInputConnection(actor_text.GetOutputPort())
        self.actor = vtk.vtkActor()
        self.actor.SetMapper(mapper)

    def _add_to_renderer(self):
        ren.add(self.actor)

    def _set_position(self,position):
        position = (position[0],position[1],0)
        self.actor.SetPosition(position)

    def _get_size(self):
        size = 2*(self.actor.GetCenter()-self.position)
        return size

The positioning of various elements uniformly around the menu disk is achieved by the add_components method of the FollowerMenu class.

def add_components(self, components):
    """ Adds parts to the orbit.

    Parameters
    ----------
    components: list(UI)
    """
    num_components = len(components)
    angular_difference = 360/num_components
    self.components = []
    for i in range(num_components):
        self.components.append(components[i])
        theta = math.radians(angular_difference*(i+1))
        x = self.position[0] + ((self.radius+0.5) * math.cos(theta))
        y = self.position[1] + ((self.radius+0.5) * math.sin(theta))
        components[i].center = (x,y,0)

        if isinstance(components[i],TextFollower):
            x = x + 0.5 * math.cos(theta)
            y = y + 0.5 * math.sin(theta)
            text_rotation = angular_difference*(i+1)
            components[i].position = (x,y,0)
            components[i].actor.RotateZ(text_rotation)

        for actor in components[i].actors:
            self.actor.AddPart(actor)

The ouput obtained for the radial text is quite appealing.

Moving on to 3D elements

After the first evaluations, my mentors and I have decided to put a hold on the 2D elements and move to creating 3D UIs and widgets.

FileMenu

Apart from continuously fixing bugs in my previous contributions, I have created a new element, which is a file select menu that allows the user to browse their file system and look at files and folders. They can navigate into and out of directories by clicking on them in the menu.

This element uses the ListBox2D I talked about in my previous post. Files are shown with Blue color and directories with Green.

The PR for this can be found here.

Orbital Menu

The first 3D element that I am creating is an orbital menu. A basic version of this was designed by my mentor 2 years ago.

The main challenge here is to ensure that the menu(disk here) around the object(cubes here) follows the camera always so that they can always be visible. For this, the vtkFollower class is used.

My task here is to first adapt the old version of the code to work with the current codebase. Then, I have to discuss various ideas to make this menu user-friendly and sci-fi and implement them.

Experimenting with Assemblies

Assemblies are a very important part of 3D graphics as they allow us to create a hierarchical model of the elements in a scene. Imagine a 3D model of a human arm. There is a three-level hierarchy – the arm, then the hand and finally the fingers. Any transformation on a parent element in the hierarchy must be applied to the children, while allowing the children to have their own independent motion about their parent.

Thus, if a hand moves, the same motion applies to the fingers. Additionally, the fingers have their local transformations with respect to the knuckles. Assemblies help us in achieving this hierarchy.

in vtk, the vtkAssemblyclass create hierarchies of elements. Parts can be added using the AddPart member function.

I have been experimenting with this a lot to fully understand how assemblies work and wrote a small code to create a 3-level hierarchy of 3 cubes.

import dipy.viz.ui as ui
import dipy.viz.window as window

"""
Cube actor
==========
"""

def cube_maker(color=None, size=(0.2, 0.2, 0.2), center=None):
     cube = window.vtk.vtkCubeSource()
     cube.SetXLength(size[0])
     cube.SetYLength(size[1])
     cube.SetZLength(size[2])
     if center is not None:
         cube.SetCenter(*center)
     cube_mapper = window.vtk.vtkPolyDataMapper()
     cube_mapper.SetInputConnection(cube.GetOutputPort())
     cube_actor = window.vtk.vtkActor()
     cube_actor.SetMapper(cube_mapper)
     if color is not None:
         cube_actor.GetProperty().SetColor(color)
     return cube_actor

cube_actor_1 = cube_maker((1, 0, 0), (25, 25, 25), center=(0, 0, 0))
cube_actor_2 = cube_maker((0, 1, 0), (10, 10, 10), center=(50, 0, 0))
cube_actor_3 = cube_maker((0, 0, 1), (5, 5, 5), center=(100, 0, 0))
cube_actor_3.SetOrigin(cube_actor_3.GetCenter())

"""
Creating assembly
=================
"""

assembly1 = window.vtk.vtkAssembly()
assembly2 = window.vtk.vtkAssembly()

assembly2.AddPart(cube_actor_2)
assembly2.AddPart(cube_actor_3)
assembly2.SetOrigin(cube_actor_2.GetCenter())

assembly1.AddPart(cube_actor_1)
assembly1.AddPart(assembly2)


"""
Adding sliders to transform the cubes
=====================================
"""

def translate_blue_cube(slider):
     value = slider.value
     cube_actor_3.SetPosition(value, 0, 0)

def translate_green_cube(slider):
     value = slider.value
     assembly2.SetPosition(value, 0, 0)

def translate_red_cube(slider):
     value = slider.value
     assembly1.SetPosition(value, 0, 0)

def rotate_blue_cube(slider):
     angle = slider.value
     previous_angle = slider.previous_value
     rotation_angle = angle - previous_angle
     cube_actor_3.RotateY(rotation_angle)

def rotate_green_cube(slider):
     angle = slider.value
     previous_angle = slider.previous_value
     rotation_angle = angle - previous_angle
     assembly2.RotateY(rotation_angle)

def rotate_red_cube(slider):
     angle = slider.value
     previous_angle = slider.previous_value
     rotation_angle = angle - previous_angle
     assembly1.RotateY(rotation_angle)

ring_slider1 = ui.RingSlider2D(text_template="{angle:5.1f}°", center = (100, 500))
ring_slider1.on_change = rotate_red_cube

ring_slider2 = ui.RingSlider2D(text_template="{angle:5.1f}°", center = (300, 500))
ring_slider2.on_change = rotate_green_cube

ring_slider3 = ui.RingSlider2D(text_template="{angle:5.1f}°", center = (500, 500))
ring_slider3.on_change = rotate_blue_cube

line_slider1 = ui.LineSlider2D(center=(100, 100), initial_value=0, min_value=-10, max_value=10, length=150)
line_slider1.on_change = translate_red_cube

line_slider2 = ui.LineSlider2D(center=(300, 100), initial_value=0, min_value=-10, max_value=10, length=150)
line_slider2.on_change = translate_green_cube

line_slider3 = ui.LineSlider2D(center=(500, 100), initial_value=0, min_value=-10, max_value=10, length=150)
line_slider3.on_change = translate_blue_cube

"""
Adding Elements to the ShowManager
==================================

Once all elements have been initialised, they have
to be added to the show manager in the following manner.
"""

current_size = (600, 600)
show_manager = window.ShowManager(size=current_size)
show_manager.ren.add(assembly1)
show_manager.ren.add(ring_slider1)
show_manager.ren.add(ring_slider2)
show_manager.ren.add(ring_slider3)
show_manager.ren.add(line_slider1)
show_manager.ren.add(line_slider2)
show_manager.ren.add(line_slider3)
show_manager.start()

I use the “Peek” screen recorder on Ubuntu to record these demos.

Refactoring and New Elements

Apart from continuously improving previous UI elements, I have worked on three major ones in the past two weeks.

Refactoring

A huge portion of the module I am working on was refactored by another contributor to the library. After this was merged, I had to read through all the changes and modify all my code according to them. It took some time to get used to the changes but now coding new elements is a lot easier than before.

The base class for all the elements was refactored to implement some functions that were common to all or most elements, such as retrieving attributes like position, center and size of the elements.

Checkbox and RadioButtons

These elements have undergone major changes since the previous blog post.  The code for the same is available at https://github.com/nipy/dipy/pull/1559.

Option

The Option class, which is a set of a Button2D and a TextBlock2D, acts as a single option for check-boxes and radio buttons. It keeps a checked attribute to facilitate checking and unchecking in Checkbox and RadioButton classes.

Checkbox

The Checkbox class implements check-boxes, which is a set of Option objects, where multiple options can be checked at once. The toggle_check callback to the on_left_mouse_button_pressed event of the buttons handles the checking and unchecking of options.

def toggle_check(self, i_ren, obj, button):
    """ Toggles the checked status of an option.

    Parameters
    ----------
    i_ren : :class:`CustomInteractorStyle`
    obj : :class:`vtkActor`
    The picked actor
    button : :class:`Button2D`
    """
    event = []
    button.next_icon()
    for option in self.options:
        if option.button == button:
            option.checked = not option.checked
        if option.checked is True:
            event.append(option.label)
    i_ren.force_render()
    print(event)

RadioButton

The RadioButton class implements radio buttons, which is a set of Option objects, where only one option can be checked at once. It inherits from Checkbox class, with a different toggle_check function to uncheck all other options when one is clicked.


Range Slider

This is an addition to the already present LineSlider2D element, which is a line on which a handle slides. Each position of the handle represents some value.

I  have added two new classes as additions to this element.

The code for this is available at https://github.com/nipy/dipy/pull/1557

LineDoubleSlider2D

This element allows the user to have two handles on the same slider. These handles can slide on the track, while not crossing each other at any point.

This element is useful for setting a range for a parameter.  For example, in CT images, this can be used to select a mapping for some window of pixel values to values between 0-255 (Windowing).

RangeSlider

This element uses a LineDoubleSlider2D to select a range which restricts a LineSlider2D to move within that range.

This is done by updating the min_value or max_value of the LineSlider2D according to the positions of the handles of LineDoubleSlider2D.

def range_slider_handle_move_callback(self, i_ren, obj, slider):
    """ Actual movement of range_slider's handles.

   Parameters
    ----------
    i_ren : :class:`CustomInteractorStyle`
    obj : :class:`vtkActor`
        The picked actor
    slider : :class:`RangeSlider`
    """
    position = i_ren.event.position
    if obj == self.range_slider.handles[0].actors[0]:
        self.range_slider.set_position(position, 0)
        self.value_slider.min_value = self.range_slider.left_disk_value
        self.value_slider.update()
    elif obj == self.range_slider.handles[1].actors[0]:
        self.range_slider.set_position(position, 1)
        self.value_slider.max_value = self.range_slider.right_disk_value
        self.value_slider.update()
    i_ren.force_render()
    i_ren.event.abort() # Stop propagating the event.

This can be useful when a user wants to fine tune the value of a parameter by narrowing the permissible range for that parameter.


Scroll Bar

There is a pending PR by another user here that implements a ListBox, which shows a list of items that can be selected using mouse clicks. I was asked to add a scroll bar to it to extend the current existing scrolling capability through mouse wheel and buttons.

The most challenging part of this was finding a formula for the height of the bar and the amount of movement of the bar(in pixels) that should correspond to a unit scroll.

The code for this is available at https://github.com/karandeepSJ/dipy/commit/5c7295da5f20fd966a9f1995184d17f8d180473d

The next goal is to implement a FileSelectMenu that uses this ListBox to make a file dialog to browse the file structure and select a file.

Starting Off With Some Basic Widgets

After I thoroughly went through the code of the library I am working on during the Community Bonding period, I focused my attention to some basic widget implementations to get comfortable with writing code in VTK. After a video chat with my mentors during the first week, we came up with a list of tasks for me to complete to get my hands dirty.

Image Widget

My first widget was a simple image element which takes the image path and the required size as inputs. I started off with this because the code for this was pretty simple and most of it was already written in other classes.

Possible improvements to this include:

  1. Resizing the image with mouse.
  2. Changing the image by browsing the file system during display.

The code for this is available here : https://github.com/nipy/dipy/pull/1522

Checkboxes

I then moved on to implement a checkbox element. This was implemented as a composition of the Button2D and TextBox2D class objects. This was where I really started getting experience with VTK since I faced a lot of problems during implementation which made me go through a lot of documentation of the toolkit. It helped me find a few bugs in the classes that I used. This is what I finally made:

One issue I faced while implementing this was that the set of icons used in the Button2D class was a dictionary. This was a problem because we need a particular order for the icons in the buttons (Block followed by a Tick if checked) but dictionaries in python are randomly ordered, thus sometimes the buttons were initially ticks. After discussing with my mentors, we decided to change the dictionary to a list of tuples. The code for the same can be found here:  https://github.com/nipy/dipy/pull/1534

My mentors and I focused our attention to reviewing a pending PR in the repository. It is an important PR which refactors a huge portion of the code. I have decided to make a PR for checkbox after this PR and the one mentioned above are merged.

Plans for the Project

In a video call meeting, my mentors discussed what outcomes they expect from this project. They want me to move to 3D UI components ASAP, so I decided to complete the 2D portions in the next 2-3 weeks. One of the most important of the 2D widgets is a file select menu, which is not only an important component in itself, but can also enhance the functioning of other elements by allowing the user to control what is displayed.

Introduction

My name is Karandeep Singh Juneja and I am really excited to be working for DIPY this summer as a part of Google Summer of Code. I am a Computer Science undergraduate at IIIT Hyderabad.

About DIPY

DIPY is a free and open source software library for computational neuroanatomy and medical data science. It contains algorithms for diffusion magnetic resonance imaging (dMRI) analysis and tractography but also contains implementations of other computational imaging methods such as denoising and registration that are applicable to the greater medical imaging and image processing communities.

Project Information

dipy.viz provides many visualization capabilities. The goal of my project is to improve DIPY’s current User Interface widgets and create new futuristic ones so as to have a complete library from which users can build interactive applications.

Current Status of the library

Currently, dipy.viz implements some basic functionalities using VTK (Visualization Toolkit) in Python. The interactive tools already present are buttons, sliders, panels, text boxes, and file-select menus, all two dimensional.

My Project

I have planned to divide the project into two main parts:

  1. Improving and implementing 2D widgets: These new 2D widgets will include basic objects like checkboxes, radio buttons, progress bars, color picker, images, divider and combo boxes. There will also be containers like Adaptive Rectangles and stack panels for these widgets. The users would be allowed to change the basic styling like color, size, position, orientation and margins of these widgets at runtime. If time permits, I might experiment with adding some animations to them.
  2. Implementation of 3D widgets: One 3D widget already in progress is an orbital menu.