def update(ev):
     global y, p, tx, ty, tz, q1, q2, signx, signy, signz
     q1 = Quaternion.create_from_axis_angle(y, 0, 0, 1, degrees=True)
     q2 = Quaternion.create_from_axis_angle(p, 0, 1, 0, degrees=True)
     q = q1 * q2
     mp.transformCube((tx, ty, tz), (q.w, q.x, q.y, q.z))
     mp.update()
     y += 1
     p += 3
     tx += signx * 0.08
     ty += signy * 0.05
     tz += signy * 0.02
     if abs(tx) > 3:
         signx *= -1
     if abs(ty) > 3:
         signy *= -1
     if abs(tz) > 3:
         signz *= -1
Exemple #2
0
    def handle_mouse(self, last_pos, cur_pos):
        va = _get_arcball_vector(*cur_pos, *self.size)
        vb = _get_arcball_vector(*last_pos, *self.size)
        angle = min(np.arccos(min(1.0, np.dot(va, vb))) * self.rotate_speed,
                    self.max_speed)
        axis_in_camera_coord = np.cross(va, vb)

        cam_to_world = self.view_mat()[:3, :3].T
        axis_in_world_coord = cam_to_world.dot(axis_in_camera_coord)

        rotation_quat = Quaternion.create_from_axis_angle(angle,
                                                          *axis_in_world_coord)
        self.position = rotation_quat.rotate_point(self.position)
Exemple #3
0
    def handle_mouse(self, last_pos, cur_pos):
        va = _get_arcball_vector(*cur_pos, *self.size)
        vb = _get_arcball_vector(*last_pos, *self.size)
        angle = min(np.arccos(min(1.0, np.dot(va, vb))) * self.rotate_speed,
                    self.max_speed)
        axis_in_camera_coord = np.cross(va, vb)

        cam_to_world = self.view_mat()[:3, :3].T
        axis_in_world_coord = cam_to_world.dot(axis_in_camera_coord)

        rotation_quat = Quaternion.create_from_axis_angle(angle,
                                                          *axis_in_world_coord)
        self.position = rotation_quat.rotate_point(self.position)
Exemple #4
0
class Script:
    
    def __init__(self, path_to_script = None):

        """Standard __init__ method.
        
        Parameters
        ----------
        path_to_script : str
            path to script
        
        
        Attributes
        ----------
        command_series : list
            list of script commands
        end: int
            max frame
        command_list: list
            list of dictionaries with each element reprenting one operation. Keys are:
            'start': int
                start from of operation
            'end':  int
                start from of operation
            'operation': str
                type of operation, e.g. 'zoom', 'rotate'
            'params': list
                list of parameters needed for operation e.g [2] for 'zoom'
        states_dict : list
            list of dictionaries defining napari viewer states for each frame. Dictionaries have keys:
                'frame': int, frame
                'rotate': vispy quaternion, camera rotation
                'translate': tuple, camera center
                'zoom': float, camera zooming factor
                'vis': list of booleans, visibility of layers
                'time': int, time-point
        key_frames: list
            same as states_dict but only elements containing a change are conserved
            
        """        
        
        if path_to_script is None:
            raise TypeError('You need to pass a string with a path to a script')
        else:
            self.path_to_script = path_to_script
            
        #instantiate Quaternion object
        self.q = Quaternion()

        
        
        
    def read_script(self):
        """Read the script and create a list with groups of 
        commands belonging to a given unit"""
        
        #read all lines
        commands = []
        with open(self.path_to_script) as f:
            commands = f.readlines()

        #group commands belonging together e.g. those belonging to 
        #and From frame ... statement
        command_series = []
        line = 0
        while line<len(commands):
            main_line = commands[line]
            line+=1
            if main_line[0]=='#':
                continue
            if len(re.findall('.*to frame \d+(\n)', main_line))==1:
                temp_lines = []
                while (commands[line][0]=='-'):
                    temp_lines.append(commands[line])
                    line+=1
                    if line == len(commands):
                        break
                command_series.append([main_line,temp_lines])
            else:
                command_series.append([main_line,[main_line]])

        end = [re.findall('(At frame |to frame )(\d+).*',x) for x in commands]
        end = np.max([int(x[0][1]) for x in end if x])
        
        self.command_series = command_series
        self.end = end
        
        
    def create_commandlist(self):    
        """create a dictionary list of each operation. Each operation becomes
        one dictionary. Operations belonging to groups have same start/end frames"""
        
        #go through all commands and parse the information
        command_list = []
        for c in self.command_series:
            
            #get start and end frames. For "At frame..." statements end == start
            if c[0].split()[0] == 'From':
                start = int(re.findall('From frame (\d+) to*', c[0])[0])
                end = int(re.findall('to frame (\d+) *', c[0])[0])
            else:
                start = int(re.findall('At frame (\d+).*', c[0])[0])
                end = int(re.findall('At frame (\d+).*', c[0])[0])
            
            #For each group of statements parse the commands
            for c2 in c[1]:
                parsed = self.parse_command(c2)
                #if parsing returns a list, it means that the operation has been split into parts
                #mainly to handle large rotations
                if type(parsed) is list:
                    interm_steps = np.linspace(start,end,len(parsed)+1).astype(int)
                    for i in range(len(interm_steps)-1):
                        command_list.append([interm_steps[i], interm_steps[i+1], parsed[i]])
                else:
                    command_list.append([start, end, parsed])                        
        
        #sort commands by time
        command_list = np.array(command_list)
        command_list = command_list[np.argsort(command_list[:,0]),:]
        
        #create list of dictionaries
        command_list = [{'start': x[0], 'end': x[1], 'operation': x[2][0], 'params': x[2][1:]} for x in command_list]
        self.command_list = command_list
        
    def parse_command(self, command):
        """given a command line, parse the content
        
        Returns
        -------
        result : tuple
            tuple with the type of operation and the corresponding parameters
            e.g. ('zoom', 2)
        """
        
        #chcek operation type
        mod_type = re.findall('.*(rotate|translate|zoom|make|time).*',command)[0]
        
        #for each operation type recover necessary parameters
        if mod_type == 'rotate':
            angle = int(re.findall('.*rotate by (\d+).*', command)[0])
            axis = list(map(int,re.findall('.*around \((\d+)\,(\d+)\,(\d+).*', command)[0]))

            #if the rotation angle is large split it into 3 to ensure the rotation is accomplished fully
            if angle >= 180:
                new_q = self.q.create_from_axis_angle(angle/3*2*np.pi/360, axis[0], axis[1], axis[2], degrees=False)
                result = [(mod_type, new_q),(mod_type, new_q),(mod_type, new_q)]
            else:
                new_q = self.q.create_from_axis_angle(angle*2*np.pi/360, axis[0], axis[1], axis[2], degrees=False)
                result = (mod_type, new_q)

        elif mod_type == 'zoom':
            factor = float(re.findall('.*factor of (\d*\.*\d+).*', command)[0])
            result = (mod_type, factor)

        elif mod_type == 'translate':
            translate = np.array(list(map(int,re.findall('.*by \((\-*\d+)\,(\-*\d+)\,(\-*\d+).*', command)[0])))
            result = (mod_type, translate)

        elif mod_type == 'make':
            layer = int(re.findall('.*make layer (\d+).*', command)[0])
            vis_status = command.split()[-1]
            if vis_status == 'invisible':
                result = ('vis', layer, False)
            else:
                result = ('vis', layer, True)
                
        elif mod_type == 'time':
            time_shift = int(re.findall('.*by (\-*\d+).*', command)[0])
            result = (mod_type, time_shift)
        return result
    
    def create_frame_commandlist(self, movie):
        """Go through the list of operations and create for each frame a dictionary
        with modifications to be operated. Only frames with an operation are filled,
        the others are interpolated later"""
        
        states_dict = [dict(zip(('frame','rotate','translate','zoom', 'vis','time'), (a, [],[],[],[],[]))) for a in np.arange(self.end+1)]

        #initialize state with current view. This first point can be adjusted by using 
        #a series of "At frame 0... " commands
        current_state = copy.deepcopy(movie.myviewer.window.qt_viewer.view.camera.get_state())
        states_dict[0]['rotate'] = current_state['_quaternion']
        states_dict[0]['zoom'] = current_state['scale_factor']
        states_dict[0]['translate'] = current_state['center']
        states_dict[0]['vis'] = [x.visible for x in movie.myviewer.layers]
        if len(movie.myviewer.dims.point)==4:
            states_dict[0]['time'] = movie.myviewer.dims.point[0]

            
        #fille the states_dict at the start/end positions by compounding operations over frame containing changes
        old_state = copy.deepcopy(states_dict[0])
        for c in self.command_list:

            if c['operation'] == 'rotate':
                states_dict[c['start']]['rotate'] = copy.deepcopy(old_state['rotate'])
                states_dict[c['end']]['rotate'] = copy.deepcopy(old_state['rotate']*c['params'][0])
                old_state['rotate'] = copy.deepcopy(states_dict[c['end']]['rotate'])

            elif c['operation'] == 'translate':
                states_dict[c['start']]['translate'] = copy.deepcopy(old_state['translate'])
                states_dict[c['end']]['translate'] = copy.deepcopy(tuple(np.array(old_state['translate']) + c['params'][0]))
                old_state['translate'] = copy.deepcopy(states_dict[c['end']]['translate'])

            elif c['operation'] == 'zoom':
                states_dict[c['start']]['zoom'] = copy.deepcopy(old_state['zoom'])
                states_dict[c['end']]['zoom'] = copy.deepcopy(old_state['zoom'] * c['params'][0])
                old_state['zoom'] = copy.deepcopy(states_dict[c['end']]['zoom'])

            elif c['operation'] == 'vis':
                states_dict[c['start']]['vis'] = copy.deepcopy(old_state['vis'])
                states_dict[c['end']]['vis'] = copy.deepcopy(old_state['vis'])
                states_dict[c['end']]['vis'][c['params'][0]] = c['params'][1]
                old_state['vis'] = copy.deepcopy(states_dict[c['end']]['vis'])
                
            elif c['operation'] == 'time':
                states_dict[c['start']]['time'] = copy.deepcopy(old_state['time'])
                states_dict[c['end']]['time'] = copy.deepcopy(old_state['time'] + c['params'][0])
                old_state['time'] = copy.deepcopy(states_dict[c['end']]['time'])

        old_state['frame'] = states_dict[-1]['frame']
        states_dict[-1] = copy.deepcopy(old_state)
        
        self.states_dict = states_dict
        
        
    def make_keyframes(self):
        """In the states_dict list of dictionaries, conserve only elements 
        where change is happening
        """

        props = ['rotate', 'translate','zoom','vis','time']
        states_copy = copy.deepcopy(self.states_dict)
        key_frames = [y for y in states_copy if np.any([y[x] for x in props])]
        
        self.key_frames = key_frames