from numpy import *
import vtk
from struct import calcsize, unpack
from dv3dNiftiReader import *
from dv3dObjectsToRender import *
from dv3dPropertyFrames import *


def Load_Dipole_4DNI(frame_parent, dipole_file, dipole_transform):

    DipoleJointActor, dipole_rows, dipole_mat, ar, line, Sphere = Create_Dipole_4DNI(frame_parent, dipole_file,
                                                                       dipole_transform)
    
    AddVTKObjectWithAttributes(DipoleJointActor,\
                        frame_parent,\
                        '4DNI_Dipole',\
                        'MEG Dipole',\
                        None,\
                        None,\
                        0,\
                        1,\
                        1,\
                        'functional',\
                        None,\
                        dipole_file,\
                        1,\
                        '4DNI_Dipole',\
                        None)
    
    #beacause we are using an actor collection set the pointer to the first
    #  object in the list NB we must reset this after!
    frame_parent.ren.AddActor(frame_parent.ListOfObjects[-1].InitTraversal())
    
    #now get the objects in turn
    for i in range(2):
        frame_parent.ren.AddActor(frame_parent.ListOfObjects[-1].GetNextActor())
    
    #and reset the pointer once we have finished
    frame_parent.ren.AddActor(frame_parent.ListOfObjects[-1].InitTraversal())
    
    #tag the time_series data to the new actor collection
    frame_parent.ListOfObjects[-1].dipole_rows = dipole_rows
    frame_parent.ListOfObjects[-1].dipole_mat = dipole_mat
    frame_parent.ListOfObjects[-1].ar = ar
    frame_parent.ListOfObjects[-1].line = line
    frame_parent.ListOfObjects[-1].Sphere = Sphere
    
    #apply the new table for later referecnce - tag it to the volume
    new_surface = frame_parent.tree.AppendItem(frame_parent.tree_structural, frame_parent.ListOfObjects[-1].my_label)
    #add the newly created treeitem as an atribute of the plane_group
    frame_parent.ListOfObjects[-1].my_treeitem = new_surface
    
    frame_parent.tree.Refresh()

    # .. create a properties window for the plane set ...
    # we pass the parent frame and the newly created object as args
    frame = MyPropertyFrame(frame_parent, frame_parent.ListOfObjects[-1], 0)
    frame.Show(True)

    # ... and apply it to the relevant list object
    frame_parent.ListOfObjects[-1].my_property_frame_instance = frame



def Create_Dipole_4DNI(frame_parent, dipole_file, dipole_transform):

    p = open(dipole_file)       
    d = p.readlines()
    p.close()
    rows = []
    data1 = []
    for c in d:
        f = c.split()
        rows.append(f)
    dipole_file_loaded = 1

    #establish where the dipole values start i.e. how long the header of the output file is (it varies!)

    for i in range(len(rows)):
        if len(rows[i]) < 1:
            pass
        else:
            if rows[i][0] == 'EPOCH':
                header_length = i



    rows = rows[header_length+1:] # first x lines are header
    dipole_rows = array(rows).astype(float)
    dipole_min_time = int(ceil(dipole_rows[0][0]))
    first_dipole_point = dipole_min_time
    dipole_max_time = int(floor(dipole_rows[len(rows)-1][0]))
    dipole_data = dipole_rows[dipole_rows[:,0] >= float(first_dipole_point), :][0]
    t = open(dipole_transform,'rb')
    y = t.readlines()
    for i in range(4):
        y[i]=y[i].strip()
    for i in range(4):
        y[i]=y[i].split(' ')
    p = array(y)
    e = empty((4,4),float)
    for i in range(4):
        for j in range(4):
            e[i][j] = float(p[i][j])
            
    t.close()
    
    base_filename = frame_parent.ListOfObjects[0].my_data_path
    ar = nifti_reader(base_filename)

    coord1 = array([dipole_data[1]/100, dipole_data[2]/100, dipole_data[3]/100,1]).reshape(4,1)
    coord2 = array([dipole_data[4]/100, dipole_data[5]/100, dipole_data[6]/100,1]).reshape(4,1)         
    trans_coord1 = dot(e, coord1).reshape(1,4)
    trans_coord2 = dot(e, coord2).reshape(1,4)
    #  ADD Sphere  #
    Sphere = vtk.vtkSphereSource()
    Sphere.SetCenter( -trans_coord1[0][0]+ar.fov[0]*ar.pixdim[0], trans_coord1[0][1], trans_coord1[0][2])
    Sphere.SetRadius( dipole_data[7]/2 )
    SphereMapper = vtk.vtkPolyDataMapper()
    SphereMapper.SetInput(Sphere.GetOutput())
    dipoleSphereActor = vtk.vtkActor()
    dipoleSphereActor.SetMapper(SphereMapper)
    dipoleSphereActor.GetProperty().SetColor(1,0,0) 
    point1 = [-trans_coord1[0][0]+ar.fov[0]*ar.pixdim[0], trans_coord1[0][1], trans_coord1[0][2]]
    point2 = [-trans_coord2[0][0]-trans_coord1[0][0]+ar.fov[0]*ar.pixdim[0], trans_coord2[0][1]+trans_coord1[0][1], trans_coord2[0][2]+trans_coord1[0][2]]
    point2_rescale = add((subtract(point2,point1))/10,point1)            
    #  ADD Line  #
    line = vtk.vtkLineSource()
    line.SetPoint1(point1)
    line.SetPoint2(point2_rescale)            
    lineMapper = vtk.vtkPolyDataMapper()
    lineMapper.SetInput(line.GetOutput())
    dipoleLineActor = vtk.vtkActor()
    dipoleLineActor.SetMapper(lineMapper)
    dipoleLineActor.GetProperty().SetColor(1,0,0)
    dipoleLineActor.GetProperty().SetLineWidth(2)
    
    #frame_parent.ren.AddActor(dipoleLineActor)
    #frame_parent.ren.AddActor(dipoleSphereActor)
    #frame_parent.widget.Render()
    
    DipoleJointActor = vtk.vtkActorCollection()
    DipoleJointActor.AddItem(dipoleLineActor)
    DipoleJointActor.AddItem(dipoleSphereActor)
    DipoleJointActor.dipole_min_time = dipole_min_time
    DipoleJointActor.dipole_max_time = dipole_max_time
    DipoleJointActor.curr_pos = first_dipole_point
    
    dipole_mat = e
    
    return DipoleJointActor, dipole_rows, dipole_mat, ar, line, Sphere
