#!/usr/bin/python

#-------~----------------------------------------------------------------------
# Copyright 2006-2011, Andre Gouws
#
# Version:        0.550 Beta
# Name :          ynicDV3D - ynic Data Viewer 3D
# Description :   multi-modal imaging visualisation toolkit
# Author :        Andre Gouws
# Created :       2006-October-06
# Last Update:    2011-Jan
# Notes :
#
#
# History:        windows/linux alpha 0.1 (Oct 2008)
# Dependencies:   Python 2.4.1 or later, VTK 5.0 or later (CVS 5.3+ on PPC Mac),  wxPython 2.6 or later!
# 
#
# Major Changes:  uses a main wx app unlike OS X version (pipes between processes)
#
# TODO :
#      translate major load routines from OS X version
#            - functional data
#            - surfaces
#            - MEG
#            - other (?)
#      Safe exit routine
#      mouse-tracking for mm update on planewidgets
#      TEST transform code for reference comparison (MNI/TAL)
#      treectrl resize errors- sizers?
#-----------------------------------------------------------------------------





# import usual libraries
import sys, os
import vtk
import wx
import math
import time
import random
from scipy import *
from vtk.util.colors import *
import threading
import time


# import custom modules
from dv3dImginfo import *
from dv3dNiftiReader import *
from dv3dSceneExportImport import *
from dv3dAviExporter import *
#from dv3dRenderWindowInteractor import wxVTKRenderWindowInteractor
from vtk.wx.wxVTKRenderWindowInteractor import wxVTKRenderWindowInteractor
from dv3dNifti2VtkImageData import nifti2vtkImageData
from dv3dPlanesTextPos import *
from dv3dTrackMouse import *
from dv3dKeyCapture import ProcessKey
from dv3dCoordLookups import *
from dv3dPlaneWidgets import *
from dv3dDataVolumes import *
from dv3dTreeCtrl import *
from dv3dObjectsToRender import *
from dv3dSetupNewPlanes import *
from dv3dOrthoViews_single import OrthoViews
from dv3dSurfaceFunctions import *
from dv3dDialogs import *
from dv3dExportRTImageStream import *
from dv3dLoadVTKPolyData import CreateVTKPolyDataSurface
from dv3dAddLight import *
from dv3dLoadPreviousSession import LoadPreviousSession
from dv3dGenerateRadiusMarker import GenerateRadiusMarker
from dv3dGeneratePositionMarker import GeneratePositionMarker
from dv3dExportPolyDataToDotVTKFile import dv3dExportPolyDataToDotVTKFile
from dv3dVolumeRender import *
from dv3dOrientationAxes import *
from dv3dLoadMarkerList import *
import dv3dReloader
import dv3dAnimate
import dv3dCustomROIExporter
from dv3dSTCprocessing import loadSTC

from readMRM4 import *

#utilities / modules for button panels
from utils import *
import globalvar as globalvar
from buttonPanel_planes import *
from buttonPanel_volumes import *
from buttonPanel_refvol import *
from buttonPanel_functional import *
from buttonPanel_surfaces import *
from buttonPanel_markers import *
from buttonPanel_DTIFibers import *
from buttonPanel_colours import *
from buttonPanel_export import *
from buttonPanel_MEG import *
from buttonPanel_Misc import *
from buttonPanel_Threads import *
from buttonPanel_Views import *

from common_functions import *

########
from dv3dTestCode import do_stuff
########

t = vtk.vtkVersion()
print t.GetVTKVersion()

class ProcessKeyRoutine(ProcessKey):
    def __init__(self, parent, frame_parent):
        ProcessKey.__init__(self, parent, frame_parent)

class PlanesPage(PlanesTab):
    def __init__(self, parent, frame_parent):
        PlanesTab.__init__(self, parent, frame_parent)

class VolumesPage(VolumesTab):
    def __init__(self, parent, frame_parent):
        VolumesTab.__init__(self, parent, frame_parent)

class FunctionalPage(FunctionalTab):
    def __init__(self, parent, frame_parent):
        FunctionalTab.__init__(self, parent, frame_parent)

class SurfacesPage(SurfacesTab):
    def __init__(self, parent, frame_parent):
        SurfacesTab.__init__(self, parent, frame_parent)

class MarkersPage(MarkersTab):
    def __init__(self, parent, frame_parent):
        MarkersTab.__init__(self, parent, frame_parent)

class ColoursPage(ColoursTab):
    def __init__(self, parent, frame_parent):
        ColoursTab.__init__(self, parent, frame_parent)

class ExportPage(ExportTab):
    def __init__(self, parent, frame_parent):
        ExportTab.__init__(self, parent, frame_parent)

class MEGPage(MEGTab):
    def __init__(self, parent, frame_parent):
        MEGTab.__init__(self, parent, frame_parent)

class DTIFiber_page(DTIFiberTab):
    def __init__(self, parent, frame_parent):
        DTIFiberTab.__init__(self, parent, frame_parent)
        
class Threads_page(ThreadsTab):
    def __init__(self, parent, frame_parent):
        ThreadsTab.__init__(self, parent, frame_parent)

class REFVolPage(RefTab):
    def __init__(self, parent, frame_parent):
        RefTab.__init__(self, parent, frame_parent)

class MiscPage(MiscTab):
    def __init__(self, parent, frame_parent):
        MiscTab.__init__(self, parent, frame_parent)

class ViewsPage(ViewsTab):
    def __init__(self, parent, frame_parent):
        ViewsTab.__init__(self, parent, frame_parent)


class DataObjectTree(CreateObjectTree):
    def __init__(self, parent, frame_parent):
        CreateObjectTree.__init__(self, parent, frame_parent)



#preference loading

if os.path.isfile('.dv3d_config.txt'):
    pass




#path to the talairach volume
tal_file_to_load = './DV3D_essentials/talairach.nii.gz'
tal_lookup_list = './DV3D_essentials/talairach_labels.txt'


# global lists / variables required to hold data away from vtk routines for threading purposes
thread_input_data = []
thread_output_data = []
parent_frame = ''

###################################################################################


# example test code do demonstrate the power of threading
class StartupThread ( threading.Thread ):
    def run(self):
        my_file = thread_input_data[0]
        #parent_frame.SetStatusText('Processing a thread in the background ...')
        Load_OFF_File(parent_frame, parent_frame, my_file)
        #parent_frame.SetStatusText('Last thread successfully completed.')
        

#MAIN APPLICATION CLASS
class Layout(wx.Frame):
    def __init__(self, parent, id, title):
    
        global parent_frame
        
        file_to_load = ''
        self.base_loaded = 0
        
        #let's deal with command line arguments first
        num_args = len(sys.argv)
        
        preload_array = []
        
        for i in range(1,len(sys.argv)):
            preload_array.append(sys.argv[i])
        
        if len(preload_array) >= 2:
            if preload_array[0] == '-base':
                file_to_load = preload_array[1]
                source_dir = os.path.dirname(file_to_load)
                self.base_loaded = 1
            
        
        ###################
        # track all processing events
        #  allows us to write out a workspace file later
        #  this array will hold the following fields:
        # 1 - internal or external data
        # 2 - path / reference to data
        # 3 - manipulation applied
        # 4 - set of values passed (comma separated string)
        self.Completed_processes = [['','','','']]

        ###################
        
        self.x = StartupThread()
        
        #self.Timer = wx.Timer()
        #self.Timer.Start(0)
        
        
        #create a list to hold buffered images for output to stream
        self.stream_image_list = []
        
        ##dialog to load our base file
        if file_to_load == '':
            dlg = wx.FileDialog(parent, "You can choose an MRI volume file or a previous session file:", "", "", "NIFTI files (*.nii.gz)|*.nii.gz|ANALYZE header (*.hdr)|*.hdr|ANALYZE image (*.img)|*.img|DICOM volume (select 1st file in folder)|*|DV3D session file|*.sess|All files|*", wx.OPEN)
            
            if dlg.ShowModal() == wx.ID_OK:
                file_to_load = dlg.GetPath()
                
                if file_to_load[-5:] == '.sess':
                    file_to_load, source_dir = LoadPreviousSession(self, file_to_load)
                
                else:
                    source_dir = dlg.GetDirectory()
            
                    self.base_loaded = 1
            else:
                file_to_load = './DV3D_essentials/MNI_structural.nii.gz'
                source_dir = './DV3D_essentials/'
                self.base_loaded = 0
        else:
            pass
            
            
        #?#we need to set the planewidgets as global to initialise them outside the
        #?# main loop ... a quirk of using the vtkRenderwindowinteractor with wx
        # global planeWidgetX, planeWidgetY, planeWidgetz
        
        #empty lists to hold all objects we create
        self.ListOfObjects = []
        self.st_act_list  = []
        self.st_act_vis_count = 0
        
        #empty list of viewpoints saved by the user
        self.CapturedViewPointList = []
        
        self.tmp_selected_lookup_table = 1
                
        self.my_loaded_volumes = [[0],[0],[0]] #LVD   # LoadedVolumeData - a list of vtkImageData objects returned from Nifti2VtkImageData
                                    # 1st (0) is always the base structural volume
                                    # 2nd is always the talairach volume
                                    # 3rd is always a place-holder in case a ref volume is loaded
                                    # 4.... are the overlay volumes
                                        
        #a few variables we will reference throughout the program
        self.first_load = 0 # is this load the first or 'base' image
        self.base_data_min, self.base_data_max = 0, 0
        self.ref_loaded = 0 # when we try to load a reference image .. check if we already have one
        self.ShowRefTransform = 0
        self.ShowTalTransform = 0
        self.overlay_count = 0 #allows us to track and reference extra volumes loaded later
        self.tmp_data_max = 0
        self.SYNC_ortho = 1 #allows the user to disable automatic rendering of ortho windows to improve speed
        #the following are used to output an image stream capturing real-time interaction
        self.write_imagestream_on = 0
        self.write_imagestream_count = 0
        self.write_imagestream_directory = '/tmp/'
        self.exportable_surface_count = 0 #used to generate a list for surface exports
        self.AutoLoadFileNow = '' #TODO explain - circular import hack
        self.temp_LUT = 0 #place holder for a temporary lookup table
        
        self.applyVTKxfm = 1 #for freesurfer


        #the input or 'base' data set
        if self.first_load == 0:
            base_vol = create_new_volume(file_to_load,'base data', source_dir)
            self.base_vol_source = file_to_load
            self.first_load =1
            self.my_loaded_volumes[0] = [base_vol]
            self.base_data_min, self.base_data_max = self.my_loaded_volumes[0][0].data_min, self.my_loaded_volumes[0][0].data_max
            #method to load the Talairach reference list automaticall on startup

            f = open(tal_lookup_list, 'rb')
            self.tal_ref_list = f.readlines()
            f.close()
            
            #load the talairach data into and array
            talairach_vol = create_new_volume(tal_file_to_load,'talairach data')
            self.first_load =1
            self.my_loaded_volumes[1] = [talairach_vol]
        else:
            vol, ign1, ign2, ign3, ign4, ign5, ign6,ign7, ign8, ign9, ign10  = nifti2vtkImageData(file_to_load)



        #------------- WX WINDOW ------------------------------------

        # -- Set up the main window with its sub-regions --
        # initialise a wx frame to act as the main app window
        wx.Frame.__init__(self, parent, id, title, size=(800,600))
        
        def test1():
            print 'ok'
        
        self.StatusBar = self.CreateStatusBar()
        self.status_message = ('ynicDV3D')
        self.SetStatusText(self.status_message)
        self.StatusBar.Bind(wx.EVT_TIMER, test1())
        
        
##########################

        #frame header information
        self.SetTitle("ynicDV3D v0.542 Beta")
        
        #do the core wx application window layout
        
        #the main background is a splitter window - splits into top half and bottom half of screen
        self.splitwindow_bg_horz = wx.SplitterWindow(self, -1, style=wx.SP_3DSASH)

        #sizers - place one in each of the compartments
        sizer_bg_all = wx.BoxSizer(wx.VERTICAL)
        sizer_bg_bottomhalf = wx.BoxSizer(wx.HORIZONTAL)
        sizer_bottomleft = wx.BoxSizer(wx.HORIZONTAL)
        sizer_bottomright = wx.BoxSizer(wx.HORIZONTAL)
        sizer_bg_tophalf = wx.BoxSizer(wx.HORIZONTAL)
        sizer_topright = wx.BoxSizer(wx.HORIZONTAL)
        sizer_topleft = wx.BoxSizer(wx.HORIZONTAL)

        self.SetSizer(sizer_bg_all)
        
        #place a panel on the top and one on the bottom half
        self.panel_bg_bottomhalf = wx.Panel(self.splitwindow_bg_horz, -1)
        self.panel_bg_tophalf = wx.Panel(self.splitwindow_bg_horz, -1)
        self.splitwindow_bg_horz.SplitHorizontally(self.panel_bg_tophalf, self.panel_bg_bottomhalf)
        sizer_bg_all.Add(self.splitwindow_bg_horz, 1, wx.EXPAND, 0)

 
        #split the top panel vertically and place a panel on the left and right
        self.splitwindow_upper_all = wx.SplitterWindow(self.panel_bg_tophalf, -1, style=wx.SP_3DSASH)
        sizer_bg_tophalf.Add(self.splitwindow_upper_all, 1, wx.EXPAND, 0)
        self.panel_topright = wx.Panel(self.splitwindow_upper_all, -1)
        self.panel_topleft = wx.Panel(self.splitwindow_upper_all, -1)
        self.splitwindow_upper_all.SplitVertically(self.panel_topleft, self.panel_topright)
        self.panel_bg_tophalf.SetSizer(sizer_bg_tophalf)
        
        #split the bottom panel vertically and place a panel on the left and right
        self.splitwindow_lower_all = wx.SplitterWindow(self.panel_bg_bottomhalf, -1, style=wx.SP_3D|wx.SP_BORDER)
        sizer_bg_bottomhalf.Add(self.splitwindow_lower_all, 1, wx.EXPAND, 0)
        self.panel_bottomleft = wx.Panel(self.splitwindow_lower_all, -1)
        self.panel_bottomright = wx.Panel(self.splitwindow_lower_all, -1)
        self.splitwindow_lower_all.SplitVertically(self.panel_bottomleft, self.panel_bottomright)
        self.panel_bg_bottomhalf.SetSizer(sizer_bg_bottomhalf)


        #place a text ctrl in the top left to display messages/information
        self.panel_topleft.SetSizer(sizer_topleft)
        self.textCtrl1 = wx.TextCtrl(self.panel_topleft, -1, "", style=wx.TE_MULTILINE)
        sizer_topleft.Add(self.textCtrl1, 1, wx.EXPAND, 0)

        #place a notebook in the top left to hold our button panels
        self.panel_topright.SetSizer(sizer_topright)
        self.notebook_1 = wx.Notebook(self.panel_topright, -1, style=0)
        sizer_topright.Add(self.notebook_1, 1, wx.EXPAND, 0)
        #TODO .. set up the notebook
        
        # the notebook object

        #1.) manipulating the main image planes
        self.planes_page = PlanesPage(self.notebook_1, self)
        self.notebook_1.AddPage(self.planes_page, "Planes")

        #1a.) volume rendering
        self.volumes_page = VolumesPage(self.notebook_1, self)
        self.notebook_1.AddPage(self.volumes_page, "Volumes")

        #8.) YNiC MEG
        self.MEG_page = MEGPage(self.notebook_1, self)
        self.notebook_1.AddPage(self.MEG_page, "MEG")

        #2.) load a volume to reference against int real time
        self.ref_page = REFVolPage(self.notebook_1, self)
        self.notebook_1.AddPage(self.ref_page, "Reference")

        #3.) loading functional data
        self.functional_page = FunctionalPage(self.notebook_1, self)
        self.notebook_1.AddPage(self.functional_page, "Overlay")

        #4.) loading surface files
        self.surfaces_page = SurfacesPage(self.notebook_1, self)
        self.notebook_1.AddPage(self.surfaces_page, "Surfaces")

        #5.) placing markers
        self.markers_page = MarkersPage(self.notebook_1, self)
        self.notebook_1.AddPage(self.markers_page, "Markers")

        #9.) DTI-Fiber data
        self.DTIFiber_page = DTIFiber_page(self.notebook_1, self)
        self.notebook_1.AddPage(self.DTIFiber_page, "Example: DTI Fibers")

        #10.) Threads_example
        self.Threads_page = Threads_page(self.notebook_1, self)
        self.notebook_1.AddPage(self.Threads_page, "Example: Threading")

        #
        ##6.) manipulating colours
        #self.colours_page = ColoursPage(self.notebook_1, self)
        #self.notebook_1.AddPage(self.colours_page, "Colours")

        #7.) export routines
        self.export_page = ExportPage(self.notebook_1, self)
        self.notebook_1.AddPage(self.export_page, "Export")

        ##9.) Views
        self.Views_page = ViewsPage(self.notebook_1, self)
        self.notebook_1.AddPage(self.Views_page, "Views")

        ##10.) Misc items
        self.misc_page = MiscPage(self.notebook_1, self)
        self.notebook_1.AddPage(self.misc_page, "Misc")

        
        ###place a TREE CTRL in the BOTTOM left to hold A LIST OF OUR OBJECTS
        ##self.panel_bottomleft.SetSizer(sizer_bottomleft)
        ##self.tree_ctrl_1 = wx.TreeCtrl(self.panel_bottomleft, -1, style=wx.TR_HAS_BUTTONS|wx.TR_DEFAULT_STYLE|wx.SUNKEN_BORDER)
        ##sizer_bottomleft.Add(self.tree_ctrl_1, 1, wx.EXPAND, 0)
        
        #PREPARE TO PLACE THE VTK WINDOW IN THE BOTTOM RIGHT
        self.panel_bottomright.SetSizer(sizer_bottomright)
        
        ##lay out the main app window
        #sizer_bg_all.Fit(self)
        #self.Layout()

##########################
        
        
        ####the main window has a bakground panel and a sizer
        ###sizer = wx.BoxSizer(wx.HORIZONTAL)
        ###panel = wx.Panel(self,-1)
        ####split the main window into two side by side boxes
        ###splitter = wx.SplitterWindow(panel)
        ###
        ####LEFT
        ####add a sizer for the left side, a panel for its background
        ###sizer_left = wx.BoxSizer(wx.VERTICAL)
        ###panel_left = wx.Panel(splitter,-1)
        ###
        ####split it vertically and add panels for the top and bottom
        ###splitter_left = wx.SplitterWindow(panel_left, style=1)
        ###
        ###self.panel_left_upper = wx.Panel(splitter_left,style= wx.NO_BORDER)
        ###self.panel_left_upper.SetBackgroundColour("WHITE")
        ###
        ###self.panel_left_lower = wx.Panel(splitter_left,style= wx.NO_BORDER)
        ###splitter_left.SplitHorizontally(self.panel_left_upper,self.panel_left_lower)
        ###sizer_left.Add(splitter_left,1,wx.EXPAND)
        ###
        ####RIGHT
        ####add a sizer for the rigth side, a panel for its background
        ###sizer_right = wx.BoxSizer(wx.VERTICAL)
        ###panel_right = wx.Panel(splitter,-1)
        ###
        ####split it vertically and add panels for the top and bottom
        ###splitter_right =wx.SplitterWindow(panel_right)
        ###panel_right_upper = wx.Panel(splitter_right,style= wx.NO_BORDER)
        ###
        ###
        #### -------- Set up the objects with populate each of the sub-regions --
        #### Top left has logo(?)
        #### Top right has the main button panel - a notebook with multiple tabs
        #### Bottom Left has a Tree ctrl which holds all loaded objects
        #### Bottom Right hold the VTK window
        ###
        ###
        #### a text box to display messages and coords in
        ###self.textCtrl1 = wx.TextCtrl(id=-1, name='msgBox1',
        ###       parent=self.panel_left_upper, pos=wx.Point(0, 0),
        ###       style=wx.TE_MULTILINE, value='')
        ###self.textCtrl1.SetHelpText('')
        ###self.textCtrl1.SetFont(wx.Font(7, wx.SWISS, wx.NORMAL, wx.NORMAL, False,
        ###      'Arial'))
        ###
        ###
        #### -------- Main Button Panel - Top right --------
        #### the notebook object
        ###self.MainButtonNotebook = wx.Notebook(id=-1, name='self.MainButtonNotebook',
        ###      parent=panel_right_upper, pos=wx.Point(0, 0), style=0)
        ###
        ####1.) manipulating the main image planes
        ###self.planes_page = PlanesPage(self.MainButtonNotebook, self)
        ###self.MainButtonNotebook.AddPage(self.planes_page, "Planes")
        ###
        ####1a.) volume rendering
        ###self.volumes_page = VolumesPage(self.MainButtonNotebook, self)
        ###self.MainButtonNotebook.AddPage(self.volumes_page, "Volumes")
        ###
        ####2.) load a volume to reference against int real time
        ###self.ref_page = REFVolPage(self.MainButtonNotebook, self)
        ###self.MainButtonNotebook.AddPage(self.ref_page, "Reference")
        ###
        ####3.) loading functional data
        ###self.functional_page = FunctionalPage(self.MainButtonNotebook, self)
        ###self.MainButtonNotebook.AddPage(self.functional_page, "Overlay")
        ###
        ####4.) loading surface files
        ###self.surfaces_page = SurfacesPage(self.MainButtonNotebook, self)
        ###self.MainButtonNotebook.AddPage(self.surfaces_page, "Surfaces")
        ###
        ####9.) DTI-Fiber data
        ###self.DTIFiber_page = DTIFiber_page(self.MainButtonNotebook, self)
        ###self.MainButtonNotebook.AddPage(self.DTIFiber_page, "Example: DTI Fibers")
        ###
        ####10.) Threads_example
        ###self.Threads_page = Threads_page(self.MainButtonNotebook, self)
        ###self.MainButtonNotebook.AddPage(self.Threads_page, "Example: Threading")
        ###
        ###
        #####5.) placing markers
        ####self.markers_page = MarkersPage(self.MainButtonNotebook, self)
        ####self.MainButtonNotebook.AddPage(self.markers_page, "Markers")
        ####
        #####6.) manipulating colours
        ####self.colours_page = ColoursPage(self.MainButtonNotebook, self)
        ####self.MainButtonNotebook.AddPage(self.colours_page, "Colours")
        ###
        ####7.) export routines
        ###self.export_page = ExportPage(self.MainButtonNotebook, self)
        ###self.MainButtonNotebook.AddPage(self.export_page, "Export")
        ###
        ####8.) YNiC MEG
        ###self.MEG_page = MEGPage(self.MainButtonNotebook, self)
        ###self.MainButtonNotebook.AddPage(self.MEG_page, "MEG")
        ###
        #####9.) Misc items
        ###self.misc_page = MiscPage(self.MainButtonNotebook, self)
        ###self.MainButtonNotebook.AddPage(self.misc_page, "Misc")
        ###
        #### Set the sizer for the main button panel and give it a background
        ###sizer_panel_ru = wx.GridSizer(rows = 1, cols = 1)
        ###sizer_panel_ru.Add(self.MainButtonNotebook, 0, wx.EXPAND)
        ###panel_right_upper.SetSizer(sizer_panel_ru)
        ###
        ###
        #### END Main Button Panel --------
        ###
        ###
        ###panel_right_lower = wx.Panel(splitter_right,style= wx.BORDER_SUNKEN)
        ####panel_right_lower.SetBackgroundColour("RED")
        ###splitter_right.SplitHorizontally(panel_right_upper,panel_right_lower)
        ###sizer_right.Add(splitter_right,1,wx.EXPAND)
        ###
        ###sizer_panel_rl = wx.GridSizer(rows = 1, cols = 1)
        ###panel_right_lower.SetSizer(sizer_panel_rl)        
        ###
        ###panel_right_upper.SetSizer(sizer_panel_ru)        
        ###splitter.SplitVertically(panel_left,panel_right)
        ###sizer.Add(splitter,1,wx.EXPAND)
        ###panel.SetSizer(sizer)
        ###panel_left.SetSizer(sizer_left)
        ###panel_right.SetSizer(sizer_right)
        ###
        self.splitter = self.splitwindow_bg_horz        
        self.splitter_left = self.splitwindow_lower_all
        self.splitter_right = self.splitwindow_upper_all
        self.splitter.SetMinimumPaneSize(150)
        self.splitter_left.SetMinimumPaneSize(135)
        self.splitter_right.SetMinimumPaneSize(135)

        self.splitter_left.SetSashPosition(135)
        self.splitter_right.SetSashPosition(135)
        self.splitter.SetSashPosition(150)
        #### END OF WX STUFF
        ###
        ###
        ###
        #------------- VTK WINDOW ------------------------------------
        #the interactor
        self.widget = wxVTKRenderWindowInteractor(self.panel_bottomright ,-1)

        #self.boxWidget1 = vtk.vtkBoxWidget()
        #self.boxWidget1.SetPriority(1.0)
        #self.boxWidget1.SetInteractor(self.widget)
        #self.boxWidget1.SetKeyPressActivationValue('V')
        #self.boxWidget1.SetPlaceFactor(1.25)

        self.interactor_style = vtk.vtkInteractorStyleTrackballCamera()
        self.widget.SetInteractorStyle(self.interactor_style)

        
        
        
        #allow key bindings to be sent to the interactor
        wx.EVT_CHAR(self.widget, self.myKeyEvents)
        #self.widget.AddObserver("KeyPressEvent", self.myKeyEvents)
        self.widget.AddObserver("MouseMoveEvent", self.myTimerEvents)

        for i in range(200):
            self.widget.UnregisterHotKey(i)

        # The shared picker enables us to use 3 planes at one time
        # and gets the picking order right
        self.picker = vtk.vtkCellPicker()
        self.picker.SetTolerance(0.005)
    
        #add a safe exit routine
        self.widget.AddObserver("ExitEvent", lambda o,e,f=Layout: sys.exit())

        #define the vtk renderer to do the drawing
        self.ren = vtk.vtkRenderer()
		
        self.ren.SetAutomaticLightCreation(0)
        self.ren.RemoveAllLights()
        ##self.ren.GetActiveCamera().ParallelProjectionOn()
        #self.ren.SetBackground(self.bg_cols[self.bg_col_index])

        #add the renderwindowinteractor to the wx application
        sizer_bottomright.Add(self.widget, 1, wx.EXPAND)

        #tell the renderer to draw the widget's output
        self.widget.GetRenderWindow().AddRenderer(self.ren)

        #now enable and initialise the vtk components
        self.widget.Enable(1)
        
        #the base image planes x, y and z
        base_vol = self.my_loaded_volumes[0][0].volume_data.GetOutput()

        #prepare the initial planes - TODO- see 2x comments below
        planes_setup(self, file_to_load, 'base')

        # we may want to reference this later to reset
        self.original_LU_table = self.ListOfObjects[0].GetLookupTable()
        
        self.ListOfObjects[0].SetLookupTable(self.original_LU_table)
        self.ListOfObjects[1].SetLookupTable(self.original_LU_table)
        self.ListOfObjects[2].SetLookupTable(self.original_LU_table)

        self.ListOfObjects[0].SetSliceIndex(self.my_loaded_volumes[0][0].x_slice_pos,)
        self.ListOfObjects[1].SetSliceIndex(self.my_loaded_volumes[0][0].y_slice_pos,)
        self.ListOfObjects[2].SetSliceIndex(self.my_loaded_volumes[0][0].z_slice_pos,)        

        #Add a Tree Control object to hold all the loaded data objects for later
        # interaction
        self.panel_bottomleft.SetSizer(sizer_bottomleft)
        DataObjectTree(self.panel_bottomleft, self)
        sizer_bottomleft.Add(self.tree, 1, wx.EXPAND, 0)
        
        
        #lay out the main app window
        sizer_bg_all.Fit(self)
        self.Layout()
                    
        #clean up any children if the app closes
        self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)

        #create 3 plane widgets for the ortho planes
        
        self.slice_pos = self.my_loaded_volumes[0][0].x_slice_pos, \
            self.my_loaded_volumes[0][0].y_slice_pos, \
            self.my_loaded_volumes[0][0].z_slice_pos
        
        
        #routine for preparing a window with automatic orthogonal views of  the main 3d-window
        self.ortho_planes = []
        self.ortho_windowX = OrthoViews(self, 0)#, plane1, plane2, plane3)
        self.ortho_windowX.Show()
        self.ortho_windowY = OrthoViews(self, 1)#, plane1, plane2, plane3)
        self.ortho_windowY.Show()
        self.ortho_windowZ = OrthoViews(self, 2)#, plane1, plane2, plane3)
        self.ortho_windowZ.Show()
        
        parent_frame = self
        parent_frame.Update()

        if self.base_loaded == 0:
            self.ListOfObjects[0].Off()
            self.ListOfObjects[1].Off()
            self.ListOfObjects[2].Off()
            self.ortho_windowX.plane1.Off()
            self.ortho_windowY.plane1.Off()
            self.ortho_windowZ.plane1.Off()
            self.ortho_windowX.widget1.Render()
            self.ortho_windowY.widget1.Render()
            self.ortho_windowZ.widget1.Render()

        #align_all_planes(self)
        
        #code to initialise real-time image streaming
        self.w2i = vtk.vtkWindowToImageFilter()
        self.w2i.SetInput(self.ren.GetRenderWindow())
        self.writer = vtk.vtkJPEGWriter()
        self.writer.SetInput(self.w2i.GetOutput())
        
        #add some lights to the scene - improves transparency rendering
        # on 3d objects
        AddMainLights(self)

        #for structural only .. ignore values below 0 ?? will this need changing?
        lut_min =  0
        lut_max =  self.original_LU_table.GetTableRange()[1]
        try:
            self.original_LU_table.SetTableValue(0,(0.0,0.0,0.0,1.0))
            self.original_LU_table.SetTableRange(lut_min, lut_max)
            self.original_LU_table.Build()
            
        except:
            pass #todo fix
        
        #Add a PointPicker
        
        self.point_picker = vtk.vtkPointPicker()
        self.widget.SetPicker(self.point_picker)
        
        def annotatePick(object, event):
			try:
				self.selPt = self.point_picker.GetSelectionPoint()
				self.pickPos = self.point_picker.GetPickPosition()
				self.pickPointID = self.point_picker.GetPointId()
				print 'index of point picked: '+ str(self.pickPointID)
				print 'position of point picked: '+str(self.pickPos)
				scalar_at_selected_point = self.point_picker.GetActor().GetMapper().GetInput().GetPointData().GetScalars().GetTuple1(self.pickPointID)
				print 'scalar value at selected point (may be proportion of max): '+str(scalar_at_selected_point)
				print '\n\n'
			except:
				print '\npick failed\n'
				pass
             
        # Now at the end of the pick event call the above function.
        self.point_picker.AddObserver("EndPickEvent", annotatePick)
        

        self.selPt = []
        self.pickPos = []
        self.pickPoint = []
        
	AddOrientationsAxes(self)
        
        #cur_cam = self.frame_parent.ren.GetActiveCamera()
        self.ren.ResetCamera()
        # ? redundant ? 
        ## a quick auto-resize to size all the subwindows
        #self.leftChange('evt')
        #self.midChange('evt')
        #self.rightChange('evt')
      
        
        
        ###########
        ###TEST CODE ONLY
        #self.ren.SetBackground(1.0,1.0,1.0)        
        #write actions so far to processing array
        # 1 - internal or external data
        # 2 - path / reference to data
        # 3 - manipulation applied
        # 4 - set of values passed (comma separated string)
        self.Completed_processes[0] = ['ext',file_to_load,'base volume',str(self.base_loaded)]
        
        #command line pre-load tests
        if len(preload_array) >= 4:
            try:
                if preload_array[2] == '-overlay':
                    self.immediate_overlay1 = preload_array[3]
                    self.overlay_files_to_load = []
                    self.overlay_files_to_load.append(self.immediate_overlay1)
                    
                    planes_setup(self, self.immediate_overlay1, 'stat', os.path.dirname(self.immediate_overlay1))
                    self.ListOfObjects[-5].myScalarBar.On()
            except:
                pass
                
	# Set up the image tracer widget
	#
	###########
    
    
    #------------
    #Functions for interaction in the main window
    
    def OnCloseWindow(self, event):
        sys.exit()
        #todo - more elegant exit routine
    
    
    def ChooseFile(self, my_filetypes):
        dlg = wx.FileDialog(self, "Choose file:", './DV3D_examples', "", my_filetypes, wx.OPEN)
        if dlg.ShowModal() == wx.ID_OK:
            path = dlg.GetPath()
            return path


    def myTimerEvents(self,  *args, **kwargs):
        self.SetStatusText(self.status_message)
        
	#test depth sorting
	#self.depthSort.Update()
	#self.ren.SetActiveCamera(self.depthSort.GetCamera())
        #try:
        #    f = open('/tmp/dv3d_rdy.tmp')
        #    print 'yup'
        #except:
        #    print 'nope'
        
        #additional routine to avoid data being shared between surfaces
        if self.AutoLoadFileNow != '':
            LoadVTKPolyDataFile(self, self)
            self.ListOfObjects[-1].GetMapper().SetScalarRange(self.temp_LUT.GetTableRange())
            self.ListOfObjects[-1].GetMapper().SetLookupTable(self.temp_LUT)
            self.ListOfObjects[-1].GetMapper().SetColorModeToMapScalars()
            self.ListOfObjects[-1].GetMapper().ScalarVisibilityOn()
            
            #clear the place holder
            self.AutoLoadFileNow = ''
        
                    
    
    def myKeyEvents(self,  event):

        # disable some of the native behaviours of key-bindins in vtk
        keycode = (event.GetKeyCode())
        self.key = chr(keycode)

        if self.key == 'l':
            #AddLightToActor(self, self.ListOfObjects[-1])
            # The box widget observes the events invoked by the render window
            # interactor.  These events come from user interaction in the render
            # window.
            boxWidget = vtk.vtkBoxWidget()
            boxWidget.SetInteractor(self.widget)
            boxWidget.SetPlaceFactor(1.25)
            
            # As the box widget is interacted with, it produces a transformation
            # matrix that is set on the actor.
            self.t = vtk.vtkTransform()
            def TransformActor(obj, event):
                #global t, maceActor
                obj.GetTransform(self.t)
                self.maceActor.SetUserTransform(self.t)
            
            self.maceActor = self.ListOfObjects[-1]
            
            boxWidget.SetProp3D(self.maceActor)
            boxWidget.PlaceWidget()
            boxWidget.SetKeyPressActivationValue('ggg')
            
            boxWidget.AddObserver("InteractionEvent", TransformActor)
            
            self.boxWidget = boxWidget
            
            
        if self.key == 'gggg':
            print self.ListOfObjects[-1].GetProperty().GetColor()
            self.ListOfObjects[-1].GetProperty().SetColor((1.0,0.0,0.0))
            
            self.ListOfObjects[-1].Modified()
            self.widget.Render()
            print self.ListOfObjects[-1].GetProperty().GetColor()
            
            
            print self.ListOfObjects[-1].GetMapper().GetLookupTable().GetNumberOfColors()
            #self.boxWidget.On()
            #self.man_x_offset = 0
        
        if self.key == 'h':
	    loadSTC(self)
	    
	    #depth sort testing
	    #try:
	        #self.sphere_count += 1
	    #except:
		#self.sphere_count = 1
	
	    #self.curr_pos = 20 * self.sphere_count
	    #self.size = 10.0 * self.sphere_count
	    
	    #t = vtk.vtkSphereSource()
	    #t.SetCenter((self.curr_pos,self.curr_pos,self.curr_pos))
	    #t.SetRadius(self.size)
	    
	    ##tt = vtk.vtkPolyDataMapper()
	    ##tt.SetInput(t.GetOutput())
	    
	    ##ttt = vtk.vtkActor()
	    ##ttt.SetMapper(tt)
	    ##ttt.GetProperty().SetOpacity(0.5)
	    ##ttt.GetProperty().SetColor((self.size/100.0, 0.5, 0.5 ))
	    
	    ##self.ren.AddActor(ttt)


	    #self.appendData = vtk.vtkAppendPolyData()
	    #self.appendData.AddInput(t.GetOutput())

	    #self.depthSort = vtk.vtkDepthSortPolyData()
	    #self.depthSort.SetInput(self.appendData.GetOutput())
	    #self.depthSort.SetCamera(self.ren.GetActiveCamera())
	    #self.depthSort.SetDirectionToBackToFront()
	    #self.depthSort.SetDepthSortModeToBoundsCenter()
	    ##self.depthSort.SetVector(1,1,1)
	    #self.depthSort.SetCamera(self.ren.GetActiveCamera())
	    ##self.depthSort.SortScalarsOn()
	    #self.depthSort.Update()

	    #tt = vtk.vtkPolyDataMapper()
	    #tt.SetInput(self.depthSort.GetOutput())
	    
	    #ttt = vtk.vtkActor()
	    #ttt.SetMapper(tt)
	    #ttt.GetProperty().SetOpacity(0.5)
	    #ttt.GetProperty().SetColor((self.size/100.0, 0.5, 0.5 ))
	    
	    #self.ren.AddActor(ttt)





	    ##self.man_x_offset += 10.0
            ##t = vtk.vtkTransform()
            ##t.Translate(self.man_x_offset,0.0,0.0)
            ##self.maceActor.SetUserTransform(t)
            ##self.boxWidget.SetTransform(t)
            
        if self.key == 'j':
            #do_stuff(self)
            dv3dExportPolyDataToDotVTKFile('/home/andre/out.vtk', self.ListOfObjects[-1])
            #self.inion_widget.On()
	    dv3dReloader.dv3dReload()
        
	if self.key == 'Y':
	    dv3dReloader.dv3dReload()
	    dv3dCustomROIExporter.importROI(self)

	if self.key == 'A':
		dv3dReloader.dv3dReload()
		dv3dAnimate.animate(self)
            #self.ren.AddActor(self.st_act_list[-1])
	    #self.st_act_list[-1].VisibilityOff()
            #try:
	    #	self.st_act_list[-2].VisibilityOn()
            #except:
	    #	pass
	    #self.widget.Render()
	    #dv3dCustomROIExporter.exportROI(self)
        
        
        if self.key == 'J':
            #do_stuff(self)
            #dv3dExportPolyDataToDotVTKFile('/home/andre/out.vtk', self.ListOfObjects[-1])
            #self.inion_widget.Off()
            #self.will_test()
            #LoadMrMFile(self)
	    LoadMarkerList(self)
	    

        if self.key == 'L':
            dv3dVolumeRender(self, self.base_vol_source)
            self.Boxwidget.On()

        if self.key == 'K':
            a = self.Boxwidget.GetProp3D()
            if a.GetProperty().GetShade() == 0:
                a.GetProperty().ShadeOn()
            else:
                a.GetProperty().ShadeOff()
            

        if self.key == 'M':
            GenerateRadiusMarker(self)            

            
            
        if self.key == 'm':
            GeneratePositionMarker(self)
            
            
        if self.key == '+':
                print self.st_act_vis_count
                self.st_act_vis_count+=1
                try:
                    self.st_act_list[self.st_act_vis_count].VisibilityOn()
                except:
                    pass
                try:
                    self.st_act_list[self.st_act_vis_count-1].VisibilityOff()
                except:
                    pass
                try:
                    self.st_act_list[self.st_act_vis_count+1].VisibilityOff()
                except:
                    pass

                self.widget.Render()
            ##oldscale = self.ListOfObjects[-1].GetScale()
            ##newscale = (oldscale[0]*1.1, oldscale[0]*1.1, oldscale[0]*1.1)
            ##self.ListOfObjects[-1].SetScale(newscale)
            #xfm = vtk.vtkTransform()
            #xfm.Scale(2.1,2.1,2.1)
            #self.ListOfObjects[-1].SetUserTransform(xfm)
            #self.ListOfObjects[-1].SetCenter(self.ListOfObjects[-1].GetOrigin())
            #self.widget.Render()
            #print self.ListOfObjects[-1].GetOrigin(), self.ListOfObjects[-1].GetCenter()
            
            
        
        if self.key == '-':
                print self.st_act_vis_count
                self.st_act_vis_count-=1
                try:
                    self.st_act_list[self.st_act_vis_count].VisibilityOn()
                except:
                    pass
                try:
                    self.st_act_list[self.st_act_vis_count-1].VisibilityOff()
                except:
                    pass
                try:
                    self.st_act_list[self.st_act_vis_count+1].VisibilityOff()
                except:
                    pass
                self.widget.Render()
            ##oldscale = self.ListOfObjects[-1].GetScale()
            ##newscale = (oldscale[0]*0.9, oldscale[0]*0.9, oldscale[0]*0.9)
            ##self.ListOfObjects[-1].SetScale(newscale)
            #xfm = vtk.vtkTransform()
            #xfm.Scale(0.9,0.9,0.9)
            #self.ListOfObjects[-1].SetUserTransform(xfm)
            #self.widget.Render()
            #print self.ListOfObjects[-1].GetOrigin(), self.ListOfObjects[-1].GetCenter()
                
        if self.key == 'P':
            my_file = ChooseFile(self, '*.off')
            thread_input_data.append(my_file)
            self.x.start()
            self.status_message = 'Thread running in the background ...'

        if self.key == 'kkkkkk':
            #######
            s1 = vtk.vtkSphereSource()
            s1.SetCenter(100,100,100)
            s1.SetRadius(5)
            
            s2 = vtk.vtkSphereSource()
            s2.SetCenter(50,50,50)
            s2.SetRadius(5)
            
            l1 = vtk.vtkLineSource()
            l1.SetPoint1(100,100,100)
            l1.SetPoint2(50,50,50)
             
            
            my_inion_marker = vtk.vtkAppendPolyData()
            my_inion_marker.AddInput(s1.GetOutput())
            my_inion_marker.AddInput(s2.GetOutput())
            my_inion_marker.AddInput(l1.GetOutput())
            
            
            s1_map = vtk.vtkPolyDataMapper()
            s1_map.SetInput(my_inion_marker.GetOutput()) 
            
            s1_actor = vtk.vtkActor()
            s1_actor.SetMapper(s1_map)
            
            #add a boxwidget so we can manipulate the position of the tms coil
            TMS_Widget = vtk.vtkBoxWidget()
            
            TMS_Widget.SetInteractor(self.widget)
            TMS_Widget.SetPlaceFactor(0.5)
            tms_transform = vtk.vtkTransform()
            def TransformActor(obj, event):
                obj.GetTransform(tms_transform)
                s1_actor.SetUserTransform(tms_transform)
                        
            TMS_Widget.SetProp3D(s1_actor)
            TMS_Widget.PlaceWidget()
            TMS_Widget.SetKeyPressActivationValue('g')
                
            TMS_Widget.AddObserver("InteractionEvent", TransformActor)
            
            self.ren.AddActor(s1_actor)
            
            self.inion_widget = TMS_Widget
            
            #######
          


        #V2 TEST CODE - import and export an entire scene 
        #if self.key == 'x':
        #    exportScene(self)
        #    self.widget.Render()
        #    
        #if self.key == 'o':
        #    importScene(self)
        #    self.widget.Render()
        if self.key == 'x':

            # Create transfer mapping scalar value to opacity
            opacityTransferFunction = vtk.vtkPiecewiseFunction()
            opacityTransferFunction.AddPoint(20, 0.0)
            opacityTransferFunction.AddPoint(255, 0.2)
            
            # Create transfer mapping scalar value to color
            colorTransferFunction = vtk.vtkColorTransferFunction()
            colorTransferFunction.AddRGBPoint(0.0, 0.0, 0.0, 0.0)
            colorTransferFunction.AddRGBPoint(64.0, 1.0, 0.0, 0.0)
            colorTransferFunction.AddRGBPoint(128.0, 0.0, 0.0, 1.0)
            colorTransferFunction.AddRGBPoint(192.0, 0.0, 1.0, 0.0)
            colorTransferFunction.AddRGBPoint(255.0, 0.0, 0.2, 0.0)
            
            # The property describes how the data will look
            volumeProperty = vtk.vtkVolumeProperty()
            volumeProperty.SetColor(colorTransferFunction)
            volumeProperty.SetScalarOpacity(opacityTransferFunction)
            volumeProperty.ShadeOn()
            volumeProperty.SetInterpolationTypeToLinear()
            
            # The mapper / ray cast function know how to render the data
            compositeFunction = vtk.vtkVolumeRayCastCompositeFunction()
            volumeMapper = vtk.vtkVolumeRayCastMapper()
            volumeMapper.SetVolumeRayCastFunction(compositeFunction)
            t = vtk.vtkImageData()
            t.DeepCopy(self.my_loaded_volumes[0][0])
            t.Update()
            volumeMapper.SetInput(t)
            
            # The volume holds the mapper and the property and
            # can be used to position/orient the volume
            volume = vtk.vtkVolume()
            volume.SetMapper(volumeMapper)
            volume.SetProperty(volumeProperty)
    

 #print self.my_loaded_volumes[0][0]
            self.ren.AddVolume(volume)
            self.widget.Render()
            

        modifiers = event.HasModifiers()
        if keycode < 256:
            key = chr(keycode)
            #save only the native behaviours of these:            
            if key in ['V','3', 'r', 's', 'w', 't', 'j', 'p', 'i']:
                event.Skip()
                return

        #? redundant now?
        #self.key=self.widget.GetKeyCode()
        #ProcessKeyRoutine(self.MainButtonNotebook, self)
        
            
    # track the mouse interaction with gthe planes and ouput the slice number, mm and ref details if loaded
    def MouseTracker(self, *args, **kwargs):
        
        # first use a routine to update the ortho-windows to the current view
        align_all_planes(self)
        
        #scan the list and find groups of planes
        
        if  self.ListOfObjects[0].GetCursorDataStatus() == 1:
            self.cursor_curr_slice_num =  self.ListOfObjects[0].GetCurrentCursorPosition()
            try:
		display_coords(self, self)
            except:
                print 'cannot display these coordinates'

        elif  self.ListOfObjects[1].GetCursorDataStatus() == 1:
            self.cursor_curr_slice_num =  self.ListOfObjects[1].GetCurrentCursorPosition()
            try:
		display_coords(self, self)
            except:
                print 'cannot display these coordinates'
                
        elif  self.ListOfObjects[2].GetCursorDataStatus() == 1:
            self.cursor_curr_slice_num =  self.ListOfObjects[2].GetCurrentCursorPosition()
            try:
		display_coords(self, self)
            except:
                print 'cannot display these coordinates'
        
        else:
            return
    
    #control routines for the sub-window sizers - these make sure
    # that if we resize the left the right resizes to the same
    ## weird? - have to loop twice and tell each object to load
    ## it own parameters otherwise panels dont size properly(?)
    def leftChange(self, event):
        self.textCtrl1.SetSize(self.treepanel.GetSize())
        self.textCtrl1.Refresh()
        for i in range(2):
            pos = self.splitter_left.GetSashPosition()
            self.splitter_right.SetSashPosition(pos)
            pos = self.splitter_right.GetSashPosition()
            self.splitter_left.SetSashPosition(pos)
            try:
                self.tree.SetSize(self.treepanel.GetSize())
                self.treepanel.Refresh()
            except:
                pass #TODO fix

    def midChange(self, event):
        self.textCtrl1.SetSize(self.treepanel.GetSize())
        self.textCtrl1.Refresh()
        for i in range(2):
            pos = self.splitter.GetSashPosition()
            self.splitter.SetSashPosition(pos)
            pos = self.splitter_left.GetSashPosition()
            self.splitter_right.SetSashPosition(pos)
            pos = self.splitter_right.GetSashPosition()
            self.splitter_left.SetSashPosition(pos)
            try:
                self.tree.SetSize(self.treepanel.GetSize())
                self.treepanel.Refresh()
            except:
                 pass #TODO fix

    def rightChange(self, event):
        self.textCtrl1.SetSize(self.treepanel.GetSize())
        self.textCtrl1.Refresh()
        for i in range(2):
            pos = self.splitter_right.GetSashPosition()
            self.splitter_left.SetSashPosition(pos)
            pos = self.splitter_left.GetSashPosition()
            self.splitter_right.SetSashPosition(pos)
            try:
                self.tree.SetSize(self.treepanel.GetSize())
                self.treepanel.Refresh()
            except:
                 pass #TODO fix



    def will_test(self):
    
        pdr = vtk.vtkPolyDataReader()
        pdr.SetFileName('/home/andre/retinotopic_3d/MNI_surf.vtk')
        polyData = pdr.GetOutput()
    
    
        t = vtk.vtkSmoothPolyDataFilter()
        #t = vtk.vtkWindowedSincPolyDataFilter()
        t.SetNumberOfIterations(10)
        t.SetInput(polyData)
        #t.SetInput(d.GetOutput())
        t.Update()
    
    
        # Create a mapper and actor for the surface
        mapMesh = vtk.vtkPolyDataMapper()
        mapMesh.SetInput(t.GetOutput())
        mapMesh.ScalarVisibilityOff()
        mapMesh.SetColorModeToDefault()
        
        mapMesh.ImmediateModeRenderingOn()
        mapMesh.Update()
        meshActor = vtk.vtkLODActor()
        meshActor.SetMapper(mapMesh)
    
        meshActor.GetProperty().SetRepresentationToWireframe()
        meshActor.GetProperty().SetOpacity(0.1)
        meshActor.GetProperty().SetColor(1.0,1.0,1.0)
    
        prop = vtk.vtkProperty()
        prop.SetDiffuseColor(1.0,0.5,0.2)
        #prop.SetOpacity(0.1)
        meshActor.SetBackfaceProperty(prop)
        mapMesh.Update()
        
        #self.ren.AddActor(meshActor)

        f = meshActor.GetMapper().GetInput()
        
        output = f
        output.Update()

        planes1 = vtk.vtkPlanes()
        clipper1 = vtk.vtkClipPolyData()
        clipper1.SetInput(output)
        clipper1.SetClipFunction(planes1)
        clipper1.InsideOutOn()
        selectMapper1 = vtk.vtkPolyDataMapper()
        selectMapper1.SetInput(clipper1.GetOutput())
        #TODO fix
        try:
            if PolyDataObject.vertex_file[-5:-4] != 's':
                selectMapper1.SetColorModeToDefault()
                selectMapper1.ScalarVisibilityOff()
        except:
            pass
        selectActor1 = vtk.vtkLODActor()
        selectActor1.SetMapper(selectMapper1)
        #inherit the colors and transparency assigned to the original actor
        selectActor1.GetProperty().SetColor(meshActor.GetProperty().GetColor())
        selectActor1.GetProperty().SetOpacity(meshActor.GetProperty().GetOpacity())
        
        
        #set some properties for the inner face
        #property1 = vtk.vtkProperty()
        #property1.SetColor((0.6, 0.6, 0.6))
    
        #selectActor1.SetBackfaceProperty(property1)
        #selectActor1.SetScale(1.01, 1.01, 1.01)
        
        #frame_parent.ren.AddActor(selectActor1)
        
        # This callback funciton does the actual work: updates the vtkPlanes
        # implicit function.  This in turn causes the pipeline to update.
        def SelectPolygons1(object, event):
            # object will be the boxWidget
            object.GetPlanes(planes1)
            selectActor1.VisibilityOn()
            
        def RefreshMe(object, event):
            object.GetPlanes(planes1)
            selectActor1.VisibilityOn()
            selectActor1.my_ClipperBoxWidget.Modified()
            self.widget.Render()
            
        
        meshActor.my_ClipperBoxWidget = vtk.vtkBoxWidget()
        boxWidget = vtk.vtkBoxWidget()
        boxWidget.SetPriority(1.0)
        boxWidget.SetInteractor(self.widget)
        #boxWidget.SetKeyPressActivationValue('V')
        boxWidget.KeyPressActivationOff()
        boxWidget.SetPlaceFactor(1.25)
        
        selectActor1.my_Clipper = clipper1
        
        selectActor1.my_ClipperBoxWidget = boxWidget
        selectActor1.my_ClipperBoxWidget.SetInput(output)
                
        selectActor1.my_ClipperBoxWidget.PlaceWidget()
        selectActor1.my_ClipperBoxWidget.AddObserver("StartInteractionEvent", SelectPolygons1)
        selectActor1.my_ClipperBoxWidget.AddObserver("EndInteractionEvent", RefreshMe)
        selectActor1.my_ClipperBoxWidget.AddObserver("WidgetModifiedEvent", RefreshMe)
        
        property2 = vtk.vtkProperty()
        property2.SetDiffuseColor(1.0, 0.5, 0.4)
        #property2.SetDiffuse(0.7)
        #property2.SetSpecular(0.4)
        #property2.SetSpecularPower(20)
        
        
            
        #my_mnorm_brain.GetProperty().SetColor(1.0,0.0,0.0)
        selectActor1.SetBackfaceProperty(property2)
        
        selectActor1.VisibilityOn()
        
        self.ren.AddActor(selectActor1)




#The main application loop
app = wx.App(0)
k = Layout(None, -1, 'DV3D 0.541 Beta (c) YNiC 2009 - Main application window')
k.Show(True)
k.SetSize((800,600)) #HACK for OSX: have to resize the window on startup to make the vtk window visible
app.MainLoop()
