"""
python/ui/presentation.py: CCP4MG Molecular Graphics Program
Copyright (C) 2001-2008 University of York, CCLRC
Copyright (C) 2009-2010 University of York
Copyright (C) 2012 STFC
This library is free software: you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License
version 3, modified in accordance with the provisions of the
license to address the requirements of UK law.
You should have received a copy of the modified GNU Lesser General
Public License along with this library. If not, copies may be
downloaded from http://www.ccp4.ac.uk/ccp4license.php
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
"""
import os, sys, utils
from PyQt4 import QtCore
from global_definitions import *
directory_ext = 'ccp4mg_presentation'
SNAPSHOT_SIZE = 200
#----------------------------------------------------------------------
def open_presentation( presentation_dir='', DIR_presentation_dir='',
mode='',**keywords):
#----------------------------------------------------------------------
#print 'open_presentation',presentation_dir
if os.path.splitext(presentation_dir)[1] == '.zip':
presentation_dir = os.path.abspath(utils.get_filename(DIR_presentation_dir,presentation_dir))
rv = utils.unzip(presentation_dir)
if rv[0]:
MGGUI().WarningMessage('Error unpacking presentation '+presentation_dir)
return None
else:
presentation_dir = rv[1]
if presentation_dir:
dir = os.path.abspath(utils.get_filename(DIR_presentation_dir,presentation_dir))
pref_file = os.path.join(dir,'preferences.pkl')
if os.path.exists(dir) and os.path.exists(pref_file):
action = 'open'
else:
# Beware in 'open' mode file browser does not add extension
if os.path.splitext(dir)[1]!= '.'+directory_ext:
dir = dir + '.' + directory_ext
action = 'create'
#print "presentation.insts",presentation.insts,exit
#if sys.platform == 'win32': pref_file = utils.msvcescape(pref_file)
#print "pref_file",pref_file
if presentation.insts:
for obj in presentation.insts:
if obj.master_dir == dir:
return obj
#print 'presentation.open_presentation',action
if action == 'open':
new_presentation = presentation(master_dir= dir)
status = new_presentation.unpickle_movie(file=pref_file)
#print "unpickled movie project_name",new_presentation.project_name
if status:
MGGUI().WarningMessage('Error attempting to open movie '+dir)
new_presentation.delete()
return None
else:
new_presentation.open(mode=mode)
return new_presentation
elif action == 'create':
dir = create_presentation_dir(dir)
if dir:
new_presentation=presentation(master_dir= dir)
new_presentation.pickle_movie(new_presentation.movie_file)
return new_presentation
else:
MGGUI().WarningMessage('Error attempting to create movie directory '+dir)
return None
else:
if sys.platform == 'win32':
import re
pref_file = re.sub(r'/','\\',pref_file)
MGGUI().WarningMessage('Error attempting to open presentation preferences file '+pref_file)
del new_presentation
return None
#----------------------------------------------------------------------
def create_presentation_dir(presentation_dir,mode='movie'):
#----------------------------------------------------------------------
# Create new directory
parent,tail=os.path.split(presentation_dir)
name,ext = os.path.splitext(tail)
if not ext: presentation_dir =presentation_dir + directory_ext
if os.path.exists(presentation_dir):
MGGUI().WarningMessage('Attempting to create a '+mode+' file.\nA directory '+presentation_dir+' already exists.\n Please give an alternative NEW name for a new '+mode)
return ''
if not os.path.exists(parent) or not os.path.isdir(parent):
MGGUI().WarningMessage('Can not create directory '+presentation_dir+
'\nParent directory does not exist')
return ''
try:
os.mkdir(presentation_dir)
except:
MGGUI().WarningMessage('Error attempting to create directory\n'+presentation_dir)
return ''
return presentation_dir
#---------------------------------------------------------------------
#---------------------------------------------------------------------
#---------------------------------------------------------------------
class presentation():
#---------------------------------------------------------------------
#---------------------------------------------------------------------
#---------------------------------------------------------------------
insts = []
saved_program_status = None
default_details = {
'transform' : [ 0.0,0.0,0.0, 0.0,0.0,0.0, 0.0],
'rock_angle': 20,
'rock_axis' : 'y',
'rock_period' : 2.0,
'interpolate_time' : 1,
'interpolate_rock':0,
'interpolate_repeats':1,
'ramp_start':0,
'ramp_end':0,
'time' : 2,
'view' : 'fixed'
}
#'raytrace' : 0,
#'render_quality' : 0}
render_quality_menu = ['0','1']
render_quality_alias = ['fast','good']
directory_ext = 'ccp4mg_presentation'
movie_encoder_menu = ['ffmpeg','ImageMagick convert']
movie_encoder_alias = ['ffmpeg','convert']
movie_ext_menu = ['.gif','.mpg','.mp4','.avi']
movie_encoder_size_multiple = {'ffmpeg':8,'mencoder':8,'convert':1}
movie_encoder_fps = {'ffmpeg':[25,30],'mencoder':[25,30],'convert':[]}
movie_encoder_formats = {'ffmpeg':('.mpg','.mp4','.avi'),'mencoder':('.mpg','.mp4','.avi'),'convert':('.gif','.mpg','.mp4','.avi')}
initialisation = {
'title' : '',
'identifier' : '',
'frame_rate' : 25,
'encoder_quality' : 100,
'frame_size' : [640,480],
'antialias' : 0,
'movie_encoder' : 'ffmpeg',
'movie_ext' : '.mpg',
'save_file_format' : 'status',
'html_template' : ['','',''],
'render_quality' : 0,
'last_scene' : 0,
'last_movie_snapshot_id' : 0,
'snapshot_list' : [],
'snapshot_details' : {},
'recorded_details' : {},
'notes' : {},
'gui_mode' : 'presentation',
'true_transparency' : 0,
'do_render' : 0,
'scale_fonts_and_images' : 0
}
#self.mencoder_command = "-ovc xvid -xvidencopts fixed_quant=1"
#----------------------------------------------------------------------
def __init__(self,master_dir='',params={},**keywords):
#----------------------------------------------------------------------
#print 'presentation.init master_dir',master_dir,params
self.last_frame = 0
self.current_scene = -1
self.make_frame_mode = 'status'
self.animation_on = 0
self.animation_time_delay = 0.5
self.animation_rock = 0
self.master_dir = unicode(master_dir,'utf-8')
self.movie_file = os.path.join(self.master_dir,'preferences.pkl')
self.movie_file_root = utils.fileRoot(self.master_dir)
self.pending_jobs = {}
for key,value in presentation.initialisation.items():
setattr(self,key,value)
if params:
for key,value in params.items(): setattr(self,key,value)
if self.master_dir and not self.identifier:
import string
self.identifier = string.split(os.path.split(master_dir)[1],'.')[0]
if not self.title: self.title = self.identifier
presentation.insts.append(self)
self.last_restored = 0
self.snapshot_changes = {}
self.interruptable = 0
# From v1.1 want ot use png files for snapshots (supported
# by browsers and noe supported by Tk with Img extension
# But stick with ppm for 'old' presentation directory
self.snapshot_ext = '.ppm'
#import glob
#if len(glob.glob(os.path.join(self.master_dir,'snapshot_*.ppm')))>0:
# self.snapshot_ext = '.ppm'
#print "self.snapshot_ext",self.snapshot_ext
def open(self,mode=''):
# The open mode (which depends on how it was opened
# on the GUI) takes precedence over the stored mode which was
# how it was opened last time
if mode: self.gui_mode = mode
#-------------------------------------------------------------------
def apply(self, action='',notes='',
load_file='',select='',gui_mode='',
index='',show_notes='',show_details='',
**keywords):
#-------------------------------------------------------------------
#print 'presentation.apply',action
if gui_mode:
self.gui_mode = gui_mode
if action == 'current_status':
indx,backup = self.add_movie_snapshot()
#print "current_status indx",indx
self.pickle_movie(file = self.movie_file)
return indx
elif action == 'write_html':
if self.html_template[1]:
template_file=utils.get_filename(self.html_template[0],self.html_template[1])
else:
template_file = ''
rv = self.write_html(template_file=template_file)
if rv[0]:
MGGUI().WarningMessage(rv[1])
else:
WEB().launch_browser(rv[1],internal=1)
elif action == 'backup':
if keywords.has_key('identifier'):
self.identifier = keywords['identifier']
compress = int(keywords.get('compress',0))
self.do_backup_data_files(project=self.identifier,compress=compress)
elif action == 'cleanup':
import glob,re
# Remove all files not currently in the snapshot list
filn_list = glob.glob(os.path.join(self.master_dir,'snapshot_*'+self.snapshot_ext))
for filn in filn_list:
indx = filn[-9:-4]
if not self.snapshot_list.count(indx):
utils.remove_file(filn)
filn0 = re.sub('snapshot','status',filn)
if os.path.exists(filn0): utils.remove_file(filn0)
# Remove all the backup status files
for mode in ['status','snapshot']:
filn_list = glob.glob(os.path.join(self.master_dir,mode+'_*.*.pkl'))
for filn in filn_list: utils.remove_file(filn)
elif action == 'delete_movie' or action == 'delete_frame':
import glob,re
for scene_list in self.tmp_delete_range:
for scene in scene_list:
# Remove all files not currently in the snapshot list
filn_list = glob.glob(os.path.join(self.master_dir,'scene_'+scene,action[7:]+'*'))
for filn in filn_list: utils.remove_file(filn)
del self.tmp_delete_range
self.get_movie_files(update_gui=1)
elif action == 'delete_all':
# zap everything - probably only wise to enable for animation
import glob
filn_list = glob.glob(os.path.join(self.master_dir,'scene_*'))
#print "presenrtation.apply clear",filn_list
for filn in filn_list: utils.remove_directory(filn)
self.snapshot_list = []
elif load_file:
if self.snapshot_list.count(load_file):
# This status is already in the movie so copy
indx,backup=self.add_movie_snapshot(index='',create=0)
import shutil
try:
shutil.copy( self.snapshot_file(load_file),
self.snapshot_file(indx) )
shutil.copy( self.snapshot_file(load_file,mode='status'),
self.snapshot_file(indx,mode='status') )
#GUI.GUI.insts.WarningMessage('Snapshot '+load_file+' already in '+ \
# self.movie_file_root+' so copied to '+indx)
except:
MGGUI().WarningMessage('Snapshot '+load_file+' already in '+ \
self.movie_file_root+' so attempting to make copy\n'+ \
'Error attempting to make copies')
else:
indx = load_file
self.add_movie_snapshot(index=indx,create=0)
self.pickle_movie(file = self.movie_file)
self.update_gui_details(indx)
elif action == 'undo_selection':
self.snapshot_select = []
elif select:
self.snapshot_select = select
elif ['restore','restore_view','restore_display'].count(action):
return self.restore_status(action=action,index=index)
elif ['replace'].count(action):
indx,backup = self.add_movie_snapshot(index=index,save_changes='replaced')
#print "replace",indx,backup
if indx>0: self.update_gui_details(indx)
elif ['replace_propagate'].count(action):
targets = self.get_play_list(default_all=0,group_interp_ranges=0)
self.handle_copy_changes(index=index)
elif ['next','previous'].count(action):
if len(self.snapshot_list)>0 and \
hasattr(self,'last_restored') and \
self.snapshot_list.count(self.last_restored):
if action == 'next':
next = self.snapshot_list.index(self.last_restored)+1
if next>=len(self.snapshot_list): next = 0
else:
next = self.snapshot_list.index(self.last_restored)-1
if next<0: next = len(self.snapshot_list)-1
else:
if action == 'next':
next = 0
else:
next = len(self.snapshot_list)-1
#print "next",next,self.snapshot_list
self.last_restored = self.snapshot_list[next]
self.restore_status(action='restore',index=self.snapshot_list[next])
#elif action == 'copy_changes':
# self.handle_copy_changes(copy_changes=1)
elif show_details:
self.handle_movie_details(index=show_details)
elif show_notes:
#self.handle_movie_details(index=show_details)
index=show_notes
if not self.notes.has_key(index):
self.notes[index] = {}
if not self.notes[index].has_key('notes'):
self.notes[index]['notes'] = ' '
notes_text = self.notes[index]['notes']
elif notes:
self.notes[index]['notes']= notes
elif action == 'quit':
self.delete()
elif action == 'preferences':
if self.gui_mode == 'movie':
self.define_movie_params()
else:
self.define_presentation_params()
elif ['preview','run_auto','record'].count(action):
if action == 'run_auto': action = 'preview'
self.make_movie_frames(action)
elif action == 'compile':
self.run_compile()
elif action == 'merge':
self.run_compile(merge=1,compile=0)
elif action == 'make':
rv = self.make_movie_frames('record',compile=1)
elif action == 'run_animation':
if self.snapshot_details[index].has_key('animation'):
ret=self.restore_status(action='restore',index=index)
if ret: return
molobj_list = get_dataobj(name= self.snapshot_details[index]['animation'][0])
if molobj_list and hasattr(molobj_list[0],'animation'):
molobj_list[0].animation.run_animation()
return 0
#----------------------------------------------------------------------
def makeCopy(self,copy_from):
#----------------------------------------------------------------------
if self.snapshot_list.count(copy_from):
# This status is already in the movie so create new snapshot_details
# and copy the status/snapshot file
indx,backup=self.add_movie_snapshot(index='',create=0)
import shutil
try:
shutil.copy( self.snapshot_file(copy_from),
self.snapshot_file(indx) )
shutil.copy( self.snapshot_file(copy_from,mode='status'),
self.snapshot_file(indx,mode='status') )
#GUI.GUI.insts.WarningMessage('Snapshot '+copy_from+' already in '+ \
# self.movie_file_root+' so copied to '+indx)
except:
MGGUI().WarningMessage('Snapshot '+copy_from+' already in '+ \
self.movie_file_root+' so attempting to make copy\n'+ \
'Error attempting to make copies')
return [1,'Error attempting to make copy of '+copy_from]
else:
# Just recreate the snapshot_details for this indx
indx = copy_from
self.add_movie_snapshot(index=indx,create=0)
return [0,indx]
#----------------------------------------------------------------------
def check_status_files(self,snapshot_list=[]):
#----------------------------------------------------------------------
if not snapshot_list: snapshot_list = self.snapshot_list
objList=[]
fileDef= {}
for snapshot in self.snapshot_list:
filn = self.snapshot_file(snapshot,mode='status')
if filn:
rv = HISTORY().get_status_data_files(filn)
if rv[0]<1: return [1,snapshot]
if rv[0]>0:
for item in rv[1]:
if not objList.count(item):
objList.append(item)
fileDef[item] = rv[2][item]
if not objList:
return [0]
else:
return [2,objList,fileDef]
#----------------------------------------------------------------------
def edit_status_data_files(self,objList,fileDefn):
#----------------------------------------------------------------------
failed = []
for snapshot in self.snapshot_list:
filn = self.snapshot_file(snapshot,mode='status')
if filn:
status = HISTORY().edit_status_data_files(filn,1,objList,fileDefn)
rv = HISTORY().write_pickle_file(filn,status)
if rv: failed.append(snapshot)
return failed
#----------------------------------------------------------------------
def restore_status(self,action='restore',id=''):
#----------------------------------------------------------------------
#print "presentation.restore_status id",id,action
if utils.safeInt(id,-1)<0: return [1,'Unrecognised snapshot id'+id]
self.last_restored = id
filn = self.snapshot_file(id,mode=self.save_file_format)
if os.path.exists(filn):
format = self.save_file_format
else:
# try the alternative format
format = ['status','mgpic'][1-['status','mgpic'].index(self.save_file_format)]
filn = self.snapshot_file(index,mode=format)
if not os.path.exists(filn):
return [1,'Snapshot '+filn+' not found ']
if format == 'status':
rv = 0
if ['restore','restore_view'].count(action):
rv = HISTORY().restore_view(filename=filn)
if ['restore','restore_display'].count(action):
rv = HISTORY().get_status_data_files(filename=filn)
if rv[0]<0:
return [1,'Unable to restore status from snapshot '+filn]
return
elif rv[0]:
hints = []
if file:
hints.append(os.path.split(filn)[0])
nLost,objList,fileDef,nFound = HISTORY().get_status_data_files(filn,hints)
if nLost == nFound:
status_new = HISTORY().edit_status_data_files(filn,1,objList,fileDef)
rv = HISTORY().update_data_status(status=status_new,
override_visible=0,exclude_list=['screenshot_preferences'],
delay_delete=1)
else:
rv = HISTORY().update_data_status(filename=filn,
override_visible=0,exclude_list=['screenshot_preferences'],
delay_delete=1)
if rv:
return [1,'Unable to restore status from snapshot '+filn]
else:
restore_list = []
keep_current = 0
if ['restore','restore_display'].count(action):
restore_list.extend(['colours','display','params'])
if ['restore','restore_view'].count(action):
restore_list.append('view')
if ['restore_view'].count(action):keep_current=1
PD().restore_picture_definition(filename=filn,trap_errors=1,test=0,
restore_list=restore_list,keep_current=keep_current,
delay_delete=1)
return [0,'']
#-------------------------------------------------------------------------
def Exit(self):
#-------------------------------------------------------------------------
self.pickle_movie(self.movie_file)
return
#------------------------------------------------------------------------
def animate(self,mode=-1):
#------------------------------------------------------------------------
if mode<0:
mode = 1 - self.animation_on
if not mode:
MAINWINDOW().removeAnimationHandler('Animation')
self.animation_on = 0
else:
play_list = self.get_play_list()
#print "presentation.animate play_list",play_list
self.animate_scene_list = []
for item in play_list:
for scene in item:
status = HISTORY().load_pickle_file(filename=self.snapshot_file(scene,mode='status'))
self.animate_scene_list.append(status)
if len(self.animate_scene_list)<2:
MGGUI().WarningMessage("Need at least two scenes selected for animation")
del self.animate_scene_list
return
# Set the initial status
self.animate_scene_position = -1
self.animate_scene_incr = 1
self.animation_count = 10
self.handle_animate()
MAINWINDOW().addAnimationHandler('Animation',self.handle_animate)
self.animation_on = 1
#------------------------------------------------------------------------
def handle_animate(self):
#------------------------------------------------------------------------
self.animation_count = self.animation_count + 1
# This assumes the animation timer is firing every 0.1s
if self.animation_count < (self.animation_time_delay * 10):
return
self.animation_count = 0
self.animate_scene_position = self.animate_scene_position + self.animate_scene_incr
# Rotate or rock?
if self.animation_rock:
if self.animate_scene_position<0:
self.animate_scene_position=1
self.animate_scene_incr = 1
elif self.animate_scene_position>=len(self.animate_scene_list):
self.animate_scene_incr = -1
self.animate_scene_position = len(self.animate_scene_list)-2
else:
if self.animate_scene_position>=len(self.animate_scene_list):
self.animate_scene_position = 0
#print "presentation.handle_animate animate_scene_position",self.animate_scene_position
status = self.animate_scene_list[self.animate_scene_position]
for data_name in status['Data_list']:
if status.has_key(data_name):
d_obj = get_dataobj(name=data_name)
if d_obj:
rv = d_obj[0].animate(status[data_name])
#print "presentation.handle_animate",d_obj[0].name,d_obj[0].visible
import rebuild
rebuild.UpdateDisplay()
#------------------------------------------------------------------------
def make_movie_frames(self,action='',compile=0):
#------------------------------------------------------------------------
# Sort out a play_list listing the snapshots to be
# processed with those that are part of a glide or interpolate
# grouped into a sublist
play_list = self.get_play_list()
if not play_list: return 1
self.make_frame_mode = action
if self.make_frame_mode == 'record' and not self.do_render:
#print "presentation.make_movie_frames self.frame_size",self.frame_size
MAINWINDOW().setGLSize(width=self.frame_size[0],height=self.frame_size[1],save=1)
MAINWINDOW().hideWindows()
sleep_period = 0
elif self.make_frame_mode == 'internal':
import ffmpeg_wrapper
ffmpeg_wrapper.OpenMovie(self.frame_size[0],self.frame_size[1],'test.mov')
sleep_period = 0
else:
sleep_period = 1.0/self.frame_rate
for snap_list in play_list:
scene = snap_list[0]
# Check for status files
for snap in snap_list:
if not os.path.exists( self.snapshot_file(snap,mode='status')):
MGGUI().WarningMessage('Status file for snapshot '+snap+' not found')
return 0
#cleanup all movie snapshots
if self.make_frame_mode=='record':
import glob
scene_dir = os.path.join(self.master_dir,'scene_'+scene)
if os.path.exists(scene_dir):
for ext in ['png','gif','mpg','mp4','avi']:
for file in glob.glob(os.path.join(scene_dir,'*.'+ext)) :
utils.remove_file(file)
else:
os.mkdir(scene_dir)
interrupt = self.transform(
play_list = play_list,
interrupt_label = 'Movie:'+self.identifier,
update_method=self.make_frame,
finish_method = [self.end_transform,{'compile':compile,'play_list':play_list}],
label=0)
return 0
#--------------------------------------------------------------------
def restore_status_0(self,status):
#--------------------------------------------------------------------
import rebuild
HISTORY().update_data_status(status=initial_status,
exclude_list=['screenshot_preferences'],restore_all_visible=1)
rebuild.UpdateDisplay()
if initial_status.has_key('view'):
initial_status['view'].restore()
elif initial_status.has_key('view2'):
MAINWINDOW().setViewParams(initial_status['view2'])
#--------------------------------------------------------------------
def run_compile(self,scene_list=[],merge=0,compile=1,**keywords):
#--------------------------------------------------------------------
# Need to test if this exists - beware executable may just
# be on the PATH
if not scene_list:
import glob
play_list = self.get_play_list()
scene_list=[]
for snap_list in play_list:
snap = snap_list[0]
scene_dir = os.path.join(self.master_dir,'scene_'+snap)
if os.path.exists(scene_dir) and \
glob.glob(os.path.join(scene_dir,'frame*')):
scene_list.append(snap)
# Run a test compile which will return error code if there
# are obvious problems
if compile:
rv = self.compile(compile=0,scene_list=scene_list)
#print "presentation.run_compile rv",rv
if rv[0]==-3:
import string
utils.remove_file(string.split(rv[1])[-1])
return
elif rv[0]<0:
MGGUI().WarningMessage('Aborting compiling movie..\n'+rv[1])
return
try:
if not self.movie_ext in self.movie_encoder_formats[self.movie_encoder]:
print "RESETTING SUFFIX to", self.movie_encoder_formats[self.movie_encoder][0]
self.movie_ext = self.movie_encoder_formats[self.movie_encoder][0]
if len(self.movie_encoder_fps[self.movie_encoder])>0 and not self.frame_rate in self.movie_encoder_fps[self.movie_encoder]:
print "RESETTING FRAME RATE to", self.movie_encoder_fps[self.movie_encoder][0]
self.frame_rate = self.movie_encoder_fps[self.movie_encoder][0]
except:
print "problem setting suffix"
if merge and not compile:
# test if there are some movies to merge
rv = self.merge_movies(scene_list=scene_list,overwrite=1,ext=self.movie_ext,encoder=self.movie_encoder,test=1)
if rv[0]:
MGGUI().WarningMessage('Aborting merging movie..\n'+rv[1])
# Ensure current status is saved
self.pickle_movie(file = self.movie_file)
args = ['-dir',self.master_dir.encode('utf-8'),'-master',self.movie_file.encode('utf-8'),'-scene']
for scene in scene_list: args.append(scene)
args.extend(['-encoder',self.movie_encoder,'-ext',self.movie_ext])
pm = PM('movie_preferences')
for item in [self.movie_encoder+'_exe']:
args.extend(['-'+item,pm.get(item)])
for item in [self.movie_encoder+'_command']:
cmd_args = pm.get(item)
if self.movie_encoder == "ffmpeg":
cmd_args += ' -r '+str(self.frame_rate)
cmd_args += ' -s '+str(self.frame_size[0])+"x"+str(self.frame_size[1])
args.extend(['-'+item,cmd_args])
for item in [self.movie_encoder+'_merge_command']:
args.extend(['-'+item,pm.get(item)])
#print args
#print self.movie_encoder
#print self.frame_size
if merge : args.append('-merge')
if not compile: args.append('-no_compile')
#print 'run_compile pm args',pm,args
label = 'For movie '+self.identifier[0:25]+'\n'
if compile and merge:
label = label + 'Converting frames to scene movie\nand merging scene movies'
elif compile:
label = label+'Converting frames to scene movies'
elif merge:
label = label+'Merging scene movies'
if merge and len(scene_list)>1:
movie_file = \
os.path.join(self.master_dir,'movie_'+scene_list[0]+'_'+scene_list[-1]+self.movie_ext)
else:
movie_file = \
os.path.join(self.master_dir,'scene_'+scene_list[-1],'movie'+self.movie_ext)
#print os.path.join(os.environ["CCP4MG"],"bin","compile_movie")
#print args
rv = JOBCONTROL().start_process(
name='compile_movie',
command=os.path.join(os.environ["CCP4MG"],"bin","compile_movie"),
args= args,
interpreter = 'python',
handler=[self.review_compiled_scene,{ 'movie':movie_file}],
add_job_id = 1,
progress= { 'TITLE' : 'Compile movie',
'HELP' : 'movies',
'LABEL' : label } )
if rv[0]:
MGGUI().WarningMessage(rv[1])
return
#--------------------------------------------------------------------
def handle_movie_details(self,index='',params={},**keywords):
#--------------------------------------------------------------------
if not index: return
details = self.snapshot_details[index]
params.update(keywords)
# Take snapshot quality from movie default
if not details.has_key('render_quality'): details['render_quality'] = self.render_quality
for key,value in self.default_details.items():
if not details.has_key(key): details[key] = value
if params.has_key('transform'):
details['transform'] = params['transform']
for key in ['raytrace','interpolate_rock','interpolate_repeats','ramp_start','ramp_end','render_quality']:
if params.has_key(key): details[key] = int(params[key])
for key in ['rock_period','rock_angle']:
if params.has_key(key): details[key] = float(params[key])
#print "presentation.handle_movie_details",index,self.snapshot_details[index]
self.pickle_movie(file = self.movie_file)
#-----------------------------------------------------------------------
def review_compiled_scene(self,id='',**kw):
#-----------------------------------------------------------------------
#print "presentation.review_compiled_scene",id,kw
mess = ''
status = JOBCONTROL().read_log_file(id)
#print "review_compiled_scene status",status
if status.has_key('status') and status['status']:
if status['status'] != 'FINISHED':
messs = 'Error compiling movie.'
if not kw.has_key('movie'):
messs = 'Error compiling movie.'
elif not os.path.exists(kw['movie']):
mess = mess + 'Movie file '+kw['movie']+' not found.'
if mess:
mess = mess + ' Look in Tools->Review jobs for further information'
MGGUI().WarningMessage(mess)
else:
self.play_movie(filename=kw['movie'])
#-----------------------------------------------------------------------
def get_last_frame(self,scene_dir='',ext='*'):
#-----------------------------------------------------------------------
'''
Initialise setup at start of recording a movie
'''
# Find the last file number
import glob, string, utils
existing_files = glob.glob(os.path.join(scene_dir,'frame_*.'+ext))
#print "existing_files",existing_files
last = 0
for file in existing_files:
i = utils.safeInt(string.split \
(string.split(os.path.basename(file),'_')[-1],'.')[0],0)
if ( i > last): last = i
return last
#-----------------------------------------------------------------------
def get_movie_files(self,scene='*',update_gui=0):
#-----------------------------------------------------------------------
'''
Get a list of movie files
'''
# Return list of movies
import glob
import string
movie_list = []
if scene != '*':
return glob.glob(os.path.join(self.master_dir,'scene_'+scene,'movie*.*'))
else:
for path in glob.glob(os.path.join(self.master_dir,'movie*.*')):
movie_list.append(os.path.basename(path))
path_list = glob.glob(os.path.join(self.master_dir,'scene_'+scene,'movie*.*'))
for path in path_list:
split1 = os.path.split(path)
split2= os.path.split(split1[0])
movie_list.append(split2[1]+'/'+split1[1])
return movie_list
#-------------------------------------------------------------------------
def pickle_movie(self,file=''):
#--------------------------------------------------------------------------
import pickle
if not file: file = self.movie_file
try:
errcode = 2
f = open(file,'w')
errcode = 3
pars = self.getparams()
#print 'presentation.pickle_movie',pars
#pars['preferences']=PM('movie_preferences').get()
pickle.dump(pars,f)
errcode = 4
f.close()
except:
MGGUI().WarningMessage("Error saving movie control file "+file+"\nError code is "+str(errcode))
return errcode
return 0
#-------------------------------------------------------------------------
def unpickle_movie(self,file=''):
#-------------------------------------------------------------------------
import pickle
pars = {}
if not os.path.exists(file):
MGGUI().WarningMessage("Error presentation preferences file "+file+' not found')
return 1
try:
err=1
f = open(file,'rU')
if f:
err=2
#print "f",f
pars = pickle.load(f)
#print "unpickle_movie pars",file,pars
err=3
f.close()
else:
raise IOError
except:
print sys.exc_info()
MGGUI().WarningMessage("Error reading presentation preferences file "+file+'\nError code='+str(err))
return 1
# Load the parameters from the pickle file
#print 'presentation.unpickle',pars
for key,value in pars.items(): setattr(self,key,value)
if self.master_dir :
import string
if not self.identifier : self.identifier = string.split( \
os.path.split(self.master_dir)[1],'.')[0]
return 0
#----------------------------------------------------------------------
def compile(self,scene_list=[],overwrite=1,compile=1,ext='gif', \
encoder='convert',preferences={}):
#----------------------------------------------------------------------
'''
Compile the image files in one scene directory into a movie gif
'''
try:
if not self.movie_ext in self.movie_encoder_formats[self.movie_encoder]:
print "RESETTING SUFFIX to", self.movie_encoder_formats[self.movie_encoder][0]
self.movie_ext = self.movie_encoder_formats[self.movie_encoder][0]
if len(self.movie_encoder_fps[self.movie_encoder])>0 and not self.frame_rate in self.movie_encoder_fps[self.movie_encoder]:
print "RESETTING FRAME RATE to", self.movie_encoder_fps[self.movie_encoder][0]
self.frame_rate = self.movie_encoder_fps[self.movie_encoder][0]
except:
print "problem setting suffix"
#print "compile ext",ext,self.frame_size,povray
#print "movie.compile scene",compile,scene_list,preferences
import re,sys
log = 0
spawn_mode = os.P_WAIT
if len(scene_list)<1: return [-1,'']
if sys.platform == 'win32':
master = re.sub('/',r'\\',self.master_dir)
else:
master = self.master_dir
# Check into scene directories and frames exist
for scene in scene_list:
err = ''
scene_dir = os.path.join(master,'scene_'+str(scene))
if not os.path.exists(scene_dir) or not os.path.isdir(scene_dir):
return [-2,"Directory does not exist "+scene_dir]
last_frame = self.get_last_frame(scene_dir)
if last_frame<=0: err = err + 'No frames recorded for scene '+scene+'\n'
if self.is_recording_done(scene) > 0:
err = err + 'Recorded frames not up to date for '+scene +'\n'
if err: return [-1,err]
# Create output filename
scene_dir = os.path.join(master,'scene_'+str(scene_list[0]))
filename = os.path.join(scene_dir,'movie'+'.'+ext.lstrip('.'))
# Just return prospective file name
if os.path.exists(filename):
if overwrite:
utils.remove_file(filename)
else:
return [-3,'Output movie file exists: '+filename]
if not compile:
# This is just a test inside ccp4mg - if all OK then the
# compile will be run as a separate process
return [0,filename]
if sys.platform == 'win32': filename = utils.msvcescape(filename)
# Run convert or mencoder to convert pngs to movie
if encoder == 'convert':
encoder_exe = preferences.get('convert_exe','convert')
#encoder_args = preferences.get('convert_command','-quality 100')
encoder_args = '-quality '+str(int(self.encoder_quality))
command = ' -delay '+str(self.frame_rate)+' '+encoder_args+' '
for scene in scene_list:
command = ''
command_list = [encoder_exe]
scene_dir = os.path.join(master,'scene_'+scene)
first_frame = 1
last_frame = self.get_last_frame(scene_dir,ext='png')
for i in range(first_frame,last_frame+1):
ppmfile = os.path.join(scene_dir,'frame_'+('00000'+str(i))[-6:]+ '.png')
command_list.append(ppmfile)
if sys.platform == 'win32': ppmfile = utils.msvcescape(ppmfile)
command = command + ' ' + ppmfile
output = os.path.join(scene_dir,'movie'+ext)
command_list.append(output)
if sys.platform == 'win32': output = utils.msvcescape(output)
command = command + ' ' + output
#print "convert command",command
#os.system(encoder_exe+' '+command)
import subprocess
try:
if sys.platform == 'win32':
subprocess.call(command_list,shell=True)
else:
subprocess.call(command_list)
except:
return [-4,'Failed to run ImageMagick program convert successfully']
elif encoder == 'mencoder':
encoder_exe = preferences.get('mencoder_exe','mencoder')
#encoder_args = preferences.get('mencoder_command','-ovc lavc -lavcopts vcodec=msmpeg4v2:vbitrate=1800')
encoder_args = '-ovc lavc -lavcopts vcodec=msmpeg4v2:vbitrate=1800'
for scene in scene_list:
# This is written to allow possibility of 2 runs of mencoder
for com in [encoder_args]:
if com:
command = ''
scene_dir = os.path.join(master,'scene_'+scene)
command=command+'"mf://'+os.path.join(scene_dir,'*.png')+'" '
# 'fps=' + str(self.frame_rate) +
command = command + \
' -mf type=png ' + com + \
' -o ' + os.path.join(scene_dir,'movie'+self.movie_ext)
#print "mencoder command",command
if sys.platform == 'win32':
# Try to get path from the registry
import _winreg
try:
reg_key = _winreg.OpenKeyEx(_winreg.HKEY_LOCAL_MACHINE,'SOFTWARE\\mencoder\\Current',0,_winreg.KEY_READ)
except:
reg_key = None
if not reg_key: return [-3,'Can not find mencoder program']
binpath = _winreg.QueryValueEx(reg_key,'BinPath')[0]
_winreg.CloseKey(reg_key)
print "Attempting to run mencoder program:",os.path.join(binpath,'mencoder.exe')
try:
os.spawnl(spawn_mode,os.path.join(binpath,'mencoder.exe'),'--',command)
except:
print "ERROR starting mencoder"
return [1,'Can not start mencoder program']
else:
#print "command",command
ret = os.system(encoder_exe+' '+command)
if ret/512:
return [1,'Can not start mencoder program']
elif encoder == 'ffmpeg':
print '--------------------------------------------------'
encoder_exe = preferences.get('ffmpeg_exe','ffmpeg')
#encoder_args = preferences.get('ffmpeg_command','')
encoder_args = '-f mpeg -vcodec mpeg1video -ar 48000 -b '+str(500000*int(self.encoder_quality))+' -ab 192000 -y'
print encoder_args
import glob,sys,shutil
import subprocess
for scene in scene_list:
scene_dir = os.path.join(master,'scene_'+scene)
file_list = glob.glob(os.path.join(scene_dir,'*.png'))
file_list.sort()
clist = [encoder_exe,'-i',os.path.normpath(os.path.join(scene_dir,'frame_%06d.png'))]
clist.extend(encoder_args.strip().split())
clist.append(os.path.join(scene_dir,'movie'+self.movie_ext))
#print "ffmpeg command",clist
try:
if sys.platform == 'win32':
subprocess.call(clist,shell=True)
else:
subprocess.call(clist)
except:
return [-4,'Failed to run ffmpeg successfully']
return [0,filename]
#-----------------------------------------------------------------------
def merge_movies(self,scene_list=[],overwrite=1,ext='gif',encoder='convert',preferences={},test=0):
#-----------------------------------------------------------------------
import os
import subprocess
spawn_mode = os.P_WAIT
if sys.platform == 'win32':
import re
master = re.sub('/',r'\\',self.master_dir)
else:
master = self.master_dir
if len(scene_list) == 1:
return [0,os.path.join(master,'scene_'+scene_list[0],'movie.'+ext)]
elif len(scene_list) == 0:
return [2,'No scenes selected for merging']
#print "merge_movies scene_list",scene_list
merged_file = os.path.normpath(os.path.join(master,'movie_'+scene_list[0]+'_'+scene_list[-1]+ext))
if os.path.exists(merged_file):
if overwrite:
utils.remove_file(merged_file)
else:
return [-3,'Output movie file exists: '+merged_file]
command = ''
nmerge = 0
input_files = []
for scene in scene_list:
if os.path.exists( os.path.join(master,'scene_'+scene ,'movie'+ext)):
nmerge = nmerge+1
file = os.path.join(master,'scene_'+scene ,'movie'+ext)
input_files.append(os.path.normpath(file))
if sys.platform == 'win32': file = utils.msvcescape(file)
command = command + file + ' '
if nmerge==1:
return [2,'Only one movie file in selected scene - can not merge']
elif nmerge == 0:
return [2,'No movie files in selected scenes - can not merge']
if test:
# This is just a test inside ccp4mg - if all OK then the
# compile will be run as a separate process
return [0,merged_file]
if encoder == 'convert':
encoder_exe = preferences.get('convert_exe','convert')
clist = [encoder_exe]
for f in input_files:
clist.append(f)
clist.append(merged_file)
try:
if sys.platform == 'win32':
subprocess.call(clist,shell=True)
else:
subprocess.call(clist)
except:
print 'Can not start ImageMagick program convert'; sys.stdout.flush()
return [1,'Can not start ImageMagick program convert']
elif encoder=='mencoder':
if sys.platform == 'win32': merged_file = utils.msvcescape(merged_file)
encoder_exe = preferences.get('mencoder_exe','mencoder')
#encoder_merge = preferences.get('mencoder_merge_command','-ovc copy')
encoder_merge = '-ovc copy'
command = encoder_merge + ' -o '+merged_file + ' ' + command
#print "merge_movies command",command
if sys.platform == 'win32':
# Try to get path from the registry
import _winreg
try:
reg_key = _winreg.OpenKeyEx(_winreg.HKEY_LOCAL_MACHINE,'SOFTWARE\\mencoder\\Current',0,_winreg.KEY_READ)
except:
reg_key = None
if not reg_key: return [-3,'Can not find mencoder program']
binpath = _winreg.QueryValueEx(reg_key,'BinPath')[0]
_winreg.CloseKey(reg_key)
try:
os.spawnl(spawn_mode,os.path.join(binpath,'mencoder.exe'),'--',command)
except:
print "ERROR starting mencoder"
return [1,'Can not start mencoder program']
else:
ret = os.system(encoder_exe+' '+command)
if ret/512:
return [1,'Can not start mencoder program']
elif encoder == 'ffmpeg':
import tempfile
ftmp = tempfile.NamedTemporaryFile(suffix='.mpg',delete=False)
for f in input_files:
fin = open(f,"rb")
ftmp.write(fin.read())
fin.close()
ftmp.close()
try:
if sys.platform == 'win32':
subprocess.call(['ffmpeg','-i',ftmp.name,'-sameq',merged_file],shell=True)
else:
subprocess.call(['ffmpeg','-i',ftmp.name,'-sameq',merged_file])
except:
return [-4,'Failed to run ffmpeg successfully']
return [0,merged_file]
return [0,merged_file]
def get_movie_params(self):
pars = {}
#---------------------------------------------------------------------------
def set_movie_params(self, params={},**keywords):
#---------------------------------------------------------------------------
params.update(keywords)
#print "set_movie_params",params
for key in ['frame_size','frame_rate','movie_ext','movie_encoder','encoder_quality','render_quality','true_transparency','do_render','scale_fonts_and_images']:
if params.has_key(key):
setattr(self,key,params[key])
# Save the new parameters
self.pickle_movie(file = self.movie_file)
#---------------------------------------------------------------------
def get_snapshot_list(self):
#---------------------------------------------------------------------
snap = []
for item in self.snapshot_list: snap.append(item)
return snap
#---------------------------------------------------------------------
def set_snapshot_list(self,new_list):
#---------------------------------------------------------------------
self.snapshot_list = []
for item in new_list:
self.snapshot_list.append(item)
#---------------------------------------------------------------------
def get_snapshot_details(self,index=''):
#---------------------------------------------------------------------
pars = {}
if index:
index_list = [index]
else:
index_list = self.snapshot_details.keys()
#print 'get_snapshot_details index_list',index_list,
for idx in index_list:
pars[idx] = {}
pars[idx].update(self.snapshot_details[idx])
if not self.snapshot_details[idx].has_key('transform'):
pars[idx].update(presentation.default_details)
return pars
def snapshot_detail(self,index,key):
if self.snapshot_details.has_key(index) and self.snapshot_details[index].has_key(key):
if ['time','interpolate_time'].count(key):
try:
val = float(self.snapshot_details[index][key])
except:
val = presentation.default_details[key]
return val
else:
return self.snapshot_details[index][key]
else:
return presentation.default_details[key]
#---------------------------------------------------------------------
def getparams(self):
#---------------------------------------------------------------------
pars = {}
for item in presentation.initialisation.keys():
if hasattr(self,item): pars[item] = getattr(self,item)
#print "presentation.getparams",pars
return pars
#------------------------------------------------------------------
def setparams(self,params={},**keywords):
#------------------------------------------------------------------
import string,re
params.update(keywords)
#print 'presentation.setparams',params
# update the snapshot list order
if params.has_key('snapshot_list'):
self.snapshot_list = []
for item in params['snapshot_list']:
self.snapshot_list.append(item)
if not self.snapshot_details.has_key(item):
print "WARNING snapshot_list contains item without details",item
#self.snapshot_details[item] = {}
#print "presentation.setparams snapshot_list",self.snapshot_list
# This handles pre-2.0 data grouped by the attribute
# In 2.0+ data is grouped by the snapshot
for key in ['time','to_snapshot','view','display','interpolate_time']:
if params.has_key(key):
nn = -1
for item in self.snapshot_list:
nn = nn + 1
if not self.snapshot_details.has_key(item): self.snapshot_details[item] = {}
self.snapshot_details[item][key] = params[key][nn]
# update the snapshot_details for given snapshot id
for id,value in params.items():
#print "presentation.setparams",id,value
if self.snapshot_details.has_key(id):
self.snapshot_details[id].update(value)
#print "presentation.setparams snapshot_details",self.snapshot_details
self.pickle_movie()
#-------------------------------------------------------------------
def add_movie_snapshot(self,index='',create=1,copy_from=None, \
save_changes=''):
#-------------------------------------------------------------------
import shutil
backup=''
#print "add_movie_snapshot",index
if save_changes and index:
for mode in ['snapshot','status']:
filn0 = self.snapshot_file(index,mode=mode)
if os.path.exists(filn0):
#Backup to filename with extension derived from epoc time
backup = self.snapshot_file(index,mode=mode,version=save_changes)
shutil.copyfile(filn0, backup)
if not index:
self.last_movie_snapshot_id = self.last_movie_snapshot_id + 1
index = str(self.last_movie_snapshot_id)
index = '00000'[0:5-len(index)] + index
animation = ['']
if create:
filn = self.snapshot_file(index)
#print "add_movie_snapshot filn",filn
if os.path.exists(filn): utils.remove_file(filn)
size = SNAPSHOT_SIZE
import screenshot
screenshot.makeScreenshot(filename=filn.encode('utf-8'),size=[size,size],clear_labels=1,render_quality=0)
filn0 = self.snapshot_file(index,mode=self.save_file_format)
if self.save_file_format == 'status':
copy_to_dir = os.path.dirname(filn0)
HISTORY().save_status(filename=filn0, \
overwrite='overwrite',save_list = ['view','data','COLOUR','params','view_options'],copy_to_dir=copy_to_dir)
else:
PD().save_picture_definition(filename=filn0,limited_save=0)
if copy_from:
animation = self.snapshot_details[copy_from]['animation']
else:
#Are there any animations - get the frame range
import global_definitions
for moldata in global_definitions.get_dataobj(object_type='MolData'):
if hasattr(moldata,'animation'):
animation = [moldata.name,moldata.animation.frame_range[0],
moldata.animation.frame_range[1]]
break
#print 'Presentation.add_movie_snapshot animation',animation,index, self.snapshot_details.has_key(index)
if not self.snapshot_details.has_key(index):
self.snapshot_details[index] = {}
self.snapshot_details[index].update(presentation.default_details)
self.snapshot_details[index]['animation'] = animation
self.snapshot_details[index]['to_snapshot'] =index
if animation != ['']:
self.snapshot_details[index]['time']= \
(float(animation[2])-float(animation[1])+1.0)/ \
float(self.frame_rate)
#print 'Presentation.add_movie_snapshot time',self.snapshot_details[index]['time']
else:
# Just make sure the animation status us correct
self.snapshot_details[index]['animation']=animation
if not self.notes.has_key(index):
self.notes[index] = {
'title' : ' ',
'notes' : ' ' }
#print 'presentation.add_snapshot'
self.pickle_movie(self.movie_file)
return index,backup
#-----------------------------------------------------------------------
def snapshot_file(self,index='',mode='snapshot',version=''):
#-----------------------------------------------------------------------
'''
Return path for file containing status or snapshot image for given index
'''
if mode == 'snapshot':
ext = self.snapshot_ext
elif mode == 'mgpic':
ext = '.py'
else:
ext = '.pkl'
filn = os.path.join(self.master_dir,mode+'_'+str(index))
# Add the version number extension
if ['new','replaced','edited'].count(version):
import time,string,re
t0 = string.split(time.ctime(time.time()))
t1 = t0[0]+'_'+t0[2]+'_'+t0[1]+'_'+re.sub(':','_',t0[3])
filn = filn + '.' + t1
if version != 'new': filn = filn + '_' + version
elif version:
filn = filn + '.' + str(version)
#print "snapshot_file",index,'*',mode,'*',version,'*',filn
filn = filn+ext
return filn
#----------------------------------------------------------------------
def get_play_list(self,default_all=1,group_interp_ranges=1):
#----------------------------------------------------------------------
play_list = []
details = self.snapshot_details
if hasattr(self,'snapshot_select') and self.snapshot_select:
if self.snapshot_list.count(self.snapshot_select[0]) and \
self.snapshot_list.count(self.snapshot_select[1]):
isnap = self.snapshot_list.index(self.snapshot_select[0])
last = self.snapshot_list.index(self.snapshot_select[1])+1
else:
return []
elif not default_all:
return []
else:
isnap = 0
last = len(self.snapshot_list)
if not group_interp_ranges:
for ii in range(isnap,last):
play_list.append(self.snapshot_list[ii])
else:
while isnap < last:
snap = self.snapshot_list[isnap]
#if details[snap]['display'] == 'interpolate' or \
# details[snap]['view'] == 'glide':
if details[snap]['to_snapshot'] != snap and \
self.snapshot_list.count( details[snap]['to_snapshot']) and \
self.snapshot_list.index( details[snap]['to_snapshot']) > isnap:
play_list.append(self.snapshot_list[isnap: self.snapshot_list.index( details[snap]['to_snapshot']) +1])
isnap = self.snapshot_list.index( details[snap]['to_snapshot'])
else:
play_list.append([snap])
isnap = isnap + 1
#print "snapshot_select",self.snapshot_select,"play_list",play_list
return play_list
#-----------------------------------------------------------------------
def is_recording_done(self,snap):
#-----------------------------------------------------------------------
import glob
scene_dir = os.path.join(self.master_dir,'scene_'+snap)
if not os.path.exists(scene_dir):
return -1
if not glob.glob(os.path.join(scene_dir,'frame*')):
return -2
if not self.recorded_details.has_key(snap):
return 1
if self.snapshot_details[snap] != self.recorded_details[snap]:
#print 'is_recording_done no',self.snapshot_details[snap], self.recorded_details[snap]
return 1
return 0
#----------------------------------------------------------------------
def make_frame(self,repeat=1,**keywords):
#----------------------------------------------------------------------
'''
Make one frame of a movie
'''
from PyQt4 import QtOpenGL
current_scene = keywords.get('scene')
self.last_frame = self.last_frame+1
#print "make_frame current_scene",current_scene,self.last_frame
if self.make_frame_mode == 'preview':
return 0
elif self.make_frame_mode == 'internal':
import opengl, image_info, ffmpeg_wrapper
yuv = image_info.image_info_yuv_tPtr(opengl.get_yuvdata())
#print yuv.y
#print yuv.u
#print yuv.v
ffmpeg_wrapper.AddYUVMovieFrame(yuv)
if repeat>1:
n = 1
while n < repeat:
n = n + 1
ffmpeg_wrapper.AddMovieFrame(yuv.y,yuv.u,yuv.v)
return 0
else:
#print "snapshot_details", self.snapshot_details[current_scene]
filn = os.path.join(self.master_dir,'scene_'+str(current_scene),
'frame_'+('00000'+str(self.last_frame))[-6:])+'.png'
if self.snapshot_details[current_scene].has_key('render_quality'):
render_quality = self.snapshot_details[current_scene]['render_quality']
else:
render_quality=self.render_quality
# Somehow need to consider scaling text and images.
if not self.do_render: # Simple Screenshot
import tempfile
from PyQt4 import QtGui,QtCore
import screenshot
import MGApplication
havePixiePlugin = True
try:
from PixieDialog import RendererCore
mainwin = MGApplication.GetMainWindow()
if self.scale_fonts_and_images: # Scale text and images using rendererCore methods.
oldDrawImages = mainwin.glWidget.drawImages
oldDrawText = mainwin.glWidget.drawText
oldDrawTextSeparately = mainwin.glWidget.drawTextSeparately
mainwin.glWidget.drawImages = False
mainwin.glWidget.drawText = False
mainwin.glWidget.drawTextSeparately = False
except:
havePixiePlugin = False
# After all PixieDialog is a plugin.
pass
doOffscreen = 1
try:
screenshot_pm = PM('screenshot_preferences')
doOffscreen = screenshot_pm.get('offscreen')
except:
doOffscreen = 0
#if QtOpenGL.QGLPixelBuffer.hasOpenGLPbuffers ():
if doOffscreen:
screenshot.makeScreenshot(filename=filn.encode('utf-8'),clear_labels=1,render_quality=0,hideWindows=0,use_pbuffer=True,size=[self.frame_size[0],self.frame_size[1]])
else:
screenshot.makeScreenshot(filename=filn.encode('utf-8'),clear_labels=1,render_quality=0,hideWindows=0)
if self.scale_fonts_and_images and havePixiePlugin: # Scale text and images using rendererCore methods.
mainwin.glWidget.drawImages = oldDrawImages
mainwin.glWidget.drawText = oldDrawText
mainwin.glWidget.drawTextSeparately = oldDrawTextSeparately
fontScaling = 1.0
if hasattr(mainwin,"savedGLSize"):
fontScaling = float(self.frame_size[1])/mainwin.savedGLSize[1]
renderer = RendererCore()
mainwin = MGApplication.GetMainWindow()
renderer.glScale = mainwin.glWidget.viewsize* mainwin.glWidget.RADIUS *2 / 60.0
labelsAndImages = renderer.renderFile(mainwin.glWidget,"dummy.tiff",filn,getGLScale=False,size=self.frame_size,current_size_in=mainwin.glWidget.size(),transparent=False,raytrace=False,smoothRibbons=False,darkInside=False,createInputFile=False,fontScaling=fontScaling)
renderer.applyTextLabelsFromLabelsAndImages(labelsAndImages,filn,[255,255,255],transparent=False)
else: # render!
import tempfile
from PyQt4 import QtGui,QtCore
import MGApplication
from PixieDialog import RendererCore
renderer = RendererCore()
f = filn
if f.rfind(".")>-1:
frib = f[:f.rfind(".")]+".rib"
else:
frib = f+".rib"
ftiff_ = tempfile.mkstemp(".tiff",prefix="ccp4mg"+str(os.getpid()))
ftiff = ftiff_[1]
os.close(ftiff_[0])
mainwin = MGApplication.GetMainWindow()
renderer.glScale = mainwin.glWidget.viewsize* mainwin.glWidget.RADIUS *2 / 60.0
# Need to sort options
labelsAndImages = renderer.renderFile(mainwin.glWidget,frib,ftiff,getGLScale=False,size=self.frame_size,current_size_in=mainwin.glWidget.size(),transparent=False,raytrace=False,smoothRibbons=False,darkInside=False)
renderer.runPixie(frib,ftiff,labelsAndImages,transparent=False)
renderer.applyTextLabelsFromLabelsAndImages(labelsAndImages,ftiff,[255,255,255],transparent=False)
fin = QtGui.QImage(ftiff)
fin.save(filn)
os.unlink(ftiff)
if repeat>1:
n = 1
while n < repeat:
n = n + 1
self.last_frame = self.last_frame+1
fr = os.path.join(self.master_dir,'scene_'+str(current_scene),
'frame_'+('00000'+str(self.last_frame))[-6:])+'.png'
##NEED TO DO A COPY *************************
return 0
#-----------------------------------------------------------------------
def end_transform(self,compile=0,play_list={},**kw):
#-----------------------------------------------------------------------
#print "presentation.end_transform",compile,play_list,kw
if self.make_frame_mode == 'internal':
ffmpeg_wrapper.CloseMovie()
for scene in play_list:
#print 'end_transform scene',scene
self.recorded_details[scene[0]] = {}
self.recorded_details[scene[0]].update(self.snapshot_details[scene[0]])
#print 'end_transform',self.recorded_details
if not self.do_render:
MAINWINDOW().setGLSize(restore=1)
MAINWINDOW().hideWindows(open=1)
if compile:
self.run_compile(merge=1)
#-----------------------------------------------------------------------
def do_backup_data_files ( self,dir='',project='' ,compress=0):
#-----------------------------------------------------------------------
import shutil,glob,pickle
import dataobj,utils
if not dir:
# Default is to save to the master directory
dir = os.path.join(self.master_dir)
else:
# Cleanout or create any named directory ?????
if os.path.exists(dir): shutil.rmtree(dir)
if not os.path.exists(dir):
try:
os.mkdir(dir)
except:
return (1,'Error creating directory'+dir)
#print 'Presentation.do_backup_data_files',dir
errors = []
for indx in self.snapshot_list:
filn = self.snapshot_file(index=indx,mode='status')
status = HISTORY().load_pickle_file(filename=filn)
if status:
# Copy all data files to this directory
print " Presentation.do_backup_data_files status['Data_list']", status['Data_list']
for objname in status['Data_list']:
if status.has_key(objname) and \
status[objname].dataparams.has_key('filename'):
rv = status[objname].copy_data_files(dir=dir,project=project)
#print "Presentation.do_backup_data_files rv",rv
if rv[0]:
for error in rv[1]:
if not errors.count(error): errors.append(error)
# Save the updated status
f = utils.openFile(filn,'w',overwrite='overwrite')
pickle.dump(status,f)
f.close()
if errors:
text = errors[0]
for item in errors[1:]: text = text +'\n' + item
return [1,text]
if compress:
import utils
rv = utils.ZipAFile(filelist=[self.master_dir],zip_file=self.master_dir+'.zip')
if rv[0]:
return [1,[rv[1]]]
else:
return [0,'Saved presentation to '+self.master_dir+'.zip']
else:
return [0,'All data files copied to '+self.master_dir]
#---------------------------------------------------------------------------
def copy_changes(self,index='',oldfile='',new_index='',new_version='', \
targets=[],recreate_snapshot=1):
#---------------------------------------------------------------------------
# Get the differences between the old and new version of the
# index status files
import shutil,pickle
old_status = HISTORY().load_pickle_file(filename=oldfile)
if not new_index: new_index=index
filename = self.snapshot_file(index,mode='status',version=new_version)
new_status = HISTORY().load_pickle_file(filename=filename)
# Parameters
param_diffs = old_status['params'].difference(new_status['params'].data)
#print "params diffs",param_diffs
#Display data
diffs=HISTORY().status_difference(old_status,new_status)
#print "status_difference diffs",diffs
if not diffs:
MGGUI().WarningMessage('No differences between '+index+ ' version '+str(version)+ '\\n and '+new_index+' version '+new_version+'\\n No changes applied')
#print "targets",targets
# Make sure selection does not include the original changed snapshot
if targets.count(index): targets.remove(index)
for indx in targets:
filename = self.snapshot_file(indx,mode='status')
#print "copy_changes indx",indx
status = HISTORY().load_pickle_file(filename=filename)
HISTORY().status_add(status,diffs[0],diffs[1],diffs[2])
if param_diffs: status['params'].add(param_diffs)
backup = self.snapshot_file(indx,mode='status',version='edited')
try:
shutil.copy( filename,backup )
shutil.copy( os.path.splitext(filename)[0]+self.snapshot_ext, \
os.path.splitext(backup)[0]+self.snapshot_ext )
except:
pass
f = utils.openFile(filename,'w',overwrite=1)
if f:
pickle.dump(status,f)
f.close()
else:
MGGUI().WarningMessage('Error saving updated status to '+filename)
if recreate_snapshot:
self.restore_status(action='restore',index=indx)
# Can not use apply method to restore here as will save
# the status file in add_movie_snapshot
indx0,backup = self.add_movie_snapshot(index=indx)
if indx0>0:
self.update_gui_details(indx)
else:
MGGUI().WarningMessage('Error saving updated snapshot for '+indx)
del status
#-----------------------------------------------------------------------
def write_html(self,file='',template_file=''):
#-----------------------------------------------------------------------
import os,utils,re
#Get name for output html file
backup = 0
if not file: file = os.path.join(self.master_dir,'index.html')
if os.path.exists(file):
root,ext = os.path.splitext(file)
while backup == 0 or os.path.exists(backup_file):
backup = backup + 1
backup_file = root + '_' + str(backup) + '.' + ext
#Read template file
if not template_file:
template_file = os.path.join (os.environ["CCP4MG"],'data','presentation_template.html')
if not os.path.exists(template_file):
return [1,'Template file '+template_file+' does not exist']
f = utils.openFile(template_file,'r')
if f:
template = f.read()
f.close()
else:
return [1,'Error reading template file '+template_file]
#Parse template file
rx = re.search(r'(.*)(.*)(.*)',template,re.DOTALL)
#if rx: print "rx.groups",rx.groups()
if not rx or len(rx.groups())!=3:
return [1,'Error could not find \\n.. in template file \\n'+template_file]
head,loop,tail = rx.groups()
# Create the html file content
content = re.sub('%TITLE%',self.title,head)
for indx in self.snapshot_list:
content = content + re.sub ('%REFERENCE%', self.identifier, re.sub ( '%INDEX%',indx,loop))
content = content + tail
# make backup
if backup>0:
import shutil
shutil.copyfile(file,backup_file)
# Write html file
f = utils.openFile(file,'w',overwrite=1)
if f:
try:
f.write(content)
f.close()
except:
return [1,'Error writing to file '+file]
else:
return [1,'Error opening file '+file]
return [0,file]
def setInterrupt(self):
#print 'presentation.setInterrupt'
self.interruptSet = 1
#------------------------------------------------------------------------
def transform ( self,play_list=[],update_method='',finish_method='',label=0,interrupt_label='',**keywords):
#-----------------------------------------------------------------------
self.do_label=label
self.update_method = update_method
self.finish_method = finish_method
if interrupt_label:
self.interrupt_label = interrupt_label
else:
self.interrupt_label = 'Transform'
self.transform_play_list = play_list
self.transform_scene = 0
self.interruptSet = 0
self.setup_scene_transform()
MAINWINDOW().addAnimationHandler(self.interrupt_label,self.next_transform)
self.interruptable = 1
#-----------------------------------------------------------------------
def setup_scene_transform(self):
#-----------------------------------------------------------------------
#print "setup_scene_transform transform_scene",self.transform_scene
interpolate_status = 1
snap_list = self.transform_play_list[self.transform_scene]
scene = snap_list[0]
#print "setup_scene_transform scene",snap_list,scene,self.snapshot_detail(scene,'view')
# Set information for make_frame method
self.last_frame = 0
# Restore the initial status
initial_status = HISTORY().load_pickle_file(filename=self.snapshot_file(scene,mode='status'))
self.restore_status(id=scene)
import rebuild
rebuild.UpdateDisplay()
# Initialise parameters for Transform
max_repeat=self.snapshot_detail(scene,'interpolate_repeats')
period=self.snapshot_detail(scene,'time')
ramp_start = self.snapshot_detail(scene,'ramp_start')
ramp_end = self.snapshot_detail(scene,'ramp_end')
interpolate_rock=self.snapshot_detail(scene,'interpolate_rock')
transf=[[0.0,0.0,0.0, 0.0,0.0,0.0, 0.0]]
transform_rock = 0
interpolate_view = []
update_objects = []
# Beware snapshot without animation has [scene]['animation']=['']
if self.snapshot_details[scene].has_key('animation') and \
self.snapshot_details[scene]['animation'][0]:
update_objects.extend(get_dataobj(name= self.snapshot_details[scene]['animation'][0]))
ntransparent = HISTORY().get_status_transparency(initial_status)
#print 'setup_scene_transform ntransparent',ntransparent
self.status_list = [[initial_status,0,ntransparent]]
for snap in snap_list[1:]:
stat = HISTORY().load_pickle_file(filename=self.snapshot_file(snap,mode='status'))
frac_time = self.snapshot_detail(snap,'interpolate_time'
)
ntransparent = HISTORY().get_status_transparency(stat)
self.status_list.append([stat,frac_time,ntransparent])
if self.snapshot_detail(scene,'view') == 'rotate':
transf=[[0.0,360.0,0.0, 0.0,0.0,0.0, 0.0]]
elif self.snapshot_detail(scene,'view')== 'rock':
rock_period = self.snapshot_detail(scene,'rock_period')
transform_rock = int((period/float(rock_period))+0.5)
rock_angle = self.snapshot_detail(scene,'rock_angle')
transf = [[ 0.0,rock_angle,0.0, 0.0,0.0,0.0, 0.0, 0.0]]
elif self.snapshot_detail(scene,'view') == 'transform':
transf = [self.snapshot_detail(scene,'transform')]
transform_rock = interpolate_rock
elif self.snapshot_detail(scene,'view') == 'glide':
transf = []
for snap in snap_list:
status,view=self.read_view(filename=self.snapshot_file(snap,mode='status'))
frac_time =self.snapshot_detail(snap,'interpolate_time')
if status:
return 1
else:
interpolate_view.append([view,frac_time])
if interpolate_view:
rock_centre = 0
else:
rock_centre = 1
nsteps = int ( 0.5 + (period * self.frame_rate))
#print "period,frame_rate,nsteps",period,frame_rate,nsteps
if nsteps<=2: nsteps = 3
if transform_rock and rock_centre:
nsteps = 4 * int((nsteps+2)/4)
elif transform_rock:
nsteps = 2 * int((nsteps+1)/1)
if max_repeat<=0:
self.maxframes = 0
else:
self.maxframes = nsteps*max_repeat
self.vpattern = []
self.tpattern = []
self.spattern = []
if len(interpolate_view)>1:
MAINWINDOW().setViewParams(interpolate_view[0][0])
time_frac_total = 0
for iv in interpolate_view[1:]: time_frac_total=time_frac_total + iv[1]
for vw in range(0,len(interpolate_view)-1):
ns = nsteps * (interpolate_view[vw+1][1]/time_frac_total) * \
1.0/float(interpolate_rock+1) # number steps between each view
r_start = 0
r_end = 0
if vw==0: r_start = ramp_start
if vw==len(interpolate_view)-2: r_end = ramp_end
self.vpattern.append([[interpolate_view[vw][0],interpolate_view[vw+1][0]], \
self.get_steps(nsteps=ns,ramp_start=r_start,ramp_end=r_end)])
if interpolate_rock:
# Repeat everything in reverse
for vw in range(len(interpolate_view)-1,0,-1):
ns = nsteps * (interpolate_view[vw][1]/time_frac_total) * \
1.0/float(interpolate_rock+1) # number steps between each view
self.vpattern.append([[interpolate_view[vw][0],interpolate_view[vw-1][0]],\
self.get_steps(nsteps=ns)])
self.vshot = 0
self.vframe = -1
else:
if not transf: transf=[[0.0,0.0,0.0, 0.0,0.0,0.0, 0.0, 0]]
ns = nsteps/len(transf)
for tr in transf:
self.tpattern.append([tr,self.get_steps(nsteps=ns,rock=transform_rock,delta=1,centre_rock=1)])
self.tshot = 0
self.tframe = -1
#if interpolate_status:
update_dataobj_list=[]
#print 'transform len self.status_list',len(self.status_list)
if len(self.status_list)>1:
time_frac_total=0.0
for iv in self.status_list[1:]: time_frac_total=time_frac_total + iv[1]
for st in range(0,len(self.status_list)-1):
#print "nsteps",nsteps,"status_list[st+1][1]",status_list[st+1][1],"time_frac_total",time_frac_total
ns = nsteps * (self.status_list[st+1][1]/time_frac_total) * \
1.0/float(interpolate_rock+1)
# number steps between each view
update_dataobj_list=self.get_changed_objects( \
self.status_list[st][0],self.status_list[st+1][0],
interpolate_status=interpolate_status)
#print "Transform update_dataobj_list",update_dataobj_list
# beware -- we dont have initial and final status for the following objects
for item in update_objects:
if not update_dataobj_list.count(item): update_dataobj_list.append([item,None,None])
if update_dataobj_list:
pattern = self.get_steps(nsteps=ns,rock=0)
#print "spattern",pattern
self.spattern.append([update_dataobj_list,pattern])
if interpolate_rock:
# 'Rock' back by reversing though the different states
for st in range(len(self.status_list)-1,0,-1):
ns = nsteps * (self.status_list[st][1]/time_frac_total) * \
1.0/float(interpolate_rock+1)
# number steps between each view
update_dataobj_list=self.get_changed_objects( \
self.status_list[st][0],self.status_list[st-1][0],
interpolate_status=interpolate_status)
# beware -- we dont have initial and final status for the following objects
for item in update_objects:
if not update_dataobj_list.count(item): update_dataobj_list.append([item,None,None])
if update_dataobj_list:
pattern = self.get_steps(nsteps=ns,rock=0)
self.spattern.append([update_dataobj_list,pattern])
else:
ns=nsteps
for item in update_objects:
update_dataobj_list.append([item,None,None])
if update_dataobj_list:
self.spattern.append([update_dataobj_list,self.get_steps(nsteps=ns,rock=interpolate_rock)])
self.sshot = 0
self.sframe = -1
#print "setup_scene_transform vpattern",len(self.vpattern)
#print "tpattern",len(self.tpattern),self.tpattern
#print "spattern",len(self.spattern)
self.iframe = -1
return 0
#----------------------------------------------------------------------------------------------------
def next_transform(self):
#----------------------------------------------------------------------------------------------------
import time
import rebuild
#print "next_transform", self.vpattern
if self.interruptSet:
MAINWINDOW().removeAnimationHandler(self.interrupt_label)
self.interruptSet = 0
self.interruptable = 0
return
# Set up the grapics thread for transform
glWidget = GLWIDGETS()[0]
ntransparent = 0
self.iframe = self.iframe + 1
#print "next_transform iframe",self.iframe
if self.do_label: self.label(text=str(self.iframe+1))
if self.spattern:
#if interpolate_status:
self.sframe = self.sframe+1
if self.sframe>=len(self.spattern[self.sshot][1]):
self.sframe = 0
self.sshot = self.sshot + 1
if self.sshot>=len(self.spattern):
self.sshot= 0
HISTORY().update_data_status( \
status=self.status_list[0][0],restore_all_visible=1)
frac = self.spattern[self.sshot][1][self.sframe]
#print "sshot frac",self.sshot,frac
#if interpolate_status:
for item in self.spattern[self.sshot][0]:
if item[1]: ntransparent = ntransparent + item[1].nofTransparentObjects()
if item[2]: ntransparent = ntransparent + item[2].nofTransparentObjects()
item[0].movie_interpolation(initial_status=item[1], \
final_status=item[2],fraction=frac,step=self.sframe)
#print 'ntransparent',ntransparent
#if spattern or label:
update_transparency = ( self.true_transparency and ntransparent>0 )
if self.spattern or self.do_label or update_transparency :
if update_transparency:
saved_transparency = glWidget.transparency()
glWidget.setTransparency(1)
rebuild.UpdateDisplay(auto_save=0)
if update_transparency: glWidget.setTransparency(saved_transparency)
if self.vpattern:
import pygl_coord
qPtr = pygl_coord.doublea(4)
start_quat = pygl_coord.Quat()
end_quat = pygl_coord.Quat()
self.vframe = self.vframe+1
if self.vframe>=len(self.vpattern[self.vshot][1]):
self.vframe = 0
self.vshot = self.vshot + 1
if self.vshot>=len(self.vpattern): self.vshot= 0
start = self.vpattern[self.vshot][0][0]
end = self.vpattern[self.vshot][0][1]
frac = self.vpattern[self.vshot][1][self.vframe]
for ii in range(0,4):qPtr[ii]=start['quat'][ii]
start_quat.Setdval(qPtr)
for ii in range(0,4):qPtr[ii]=end['quat'][ii]
end_quat.Setdval(qPtr)
l1,l2= pygl_coord.Quat.Distance(start_quat,end_quat), pygl_coord.Quat.Distance(start_quat,-end_quat)
if abs(l1)<0.01:
quat = None
elif l2>=l1:
quat = pygl_coord.Quat().Slerp(start_quat,end_quat,frac)
else:
quat = pygl_coord.Quat().Slerp(start_quat,-end_quat,frac)
if quat: glWidget.setQuatNoUpdate(quat)
if start.has_key('rpos'):
rpos = []
for j in range(0,3): rpos.append(
((1.0-frac)*start['rpos'][j])+(frac*end['rpos'][j]))
glWidget.setPositionNoUpdate(rpos)
if start.has_key('RADIUS'):
glWidget.setZoomNoUpdate((((1.0-frac)*start['RADIUS'])+(frac*end['RADIUS'])))
if start.has_key('pos'):
pos = []
for j in range(0,3): pos.append(
((1.0-frac)*start['pos'][j])+(frac*end['pos'][j]))
glWidget.setPositionNoUpdate(pos)
if start.has_key('scale'):
glWidget.setZoomNoUpdate((((1.0-frac)*start['scale'])+(frac*end['scale'])))
if start.has_key('fog_near') and start.has_key('fog_far'):
glWidget.setFogNearAndFar((((1.0-frac)*start['fog_near'])+(frac*end['fog_near'])),(((1.0-frac)*start['fog_far'])+(frac*end['fog_far'])))
if start.has_key('slab_width') and start.has_key('slab_offset') and start.has_key('slab_enabled'):
glWidget.setSlab(start['slab_enabled'],(((1.0-frac)*start['slab_width'])+(frac*end['slab_width'])),(((1.0-frac)*start['slab_offset'])+(frac*end['slab_offset'])))
if self.tpattern:
self.tframe = self.tframe+1
if self.tframe>=len(self.tpattern[self.tshot][1]):
self.tframe = 0
self.tshot = self.tshot + 1
if self.tshot>=len(self.tpattern): self.tshot= 0
transf = self.tpattern[self.tshot][0]
frac = self.tpattern[self.tshot][1][self.tframe]
#print "tframe,tshot,frac,transf",tframe,tshot,frac,transf
glWidget.setRotationNoUpdate(transf[0]*frac,transf[1]*frac,transf[2]*frac )
#glWidget.setPosition((transf[3]*frac,transf[4]*frac,transf[5]*frac ))
#glWidget.setZoom( transf[6]*frac )
#glWidget.frame_count = str(self.iframe+1)
glWidget.updateGL()
glWidget.emit(QtCore.SIGNAL("PositionChanged"),(glWidget))
glWidget.emit(QtCore.SIGNAL("QuatChanged"),(glWidget))
glWidget.emit(QtCore.SIGNAL("ZoomChanged"),(glWidget))
#self.update_dependents('transform')
if self.update_method:
rv = self.update_method(scene=self.transform_play_list[self.transform_scene][0])
if self.maxframes and self.iframe>= self.maxframes-1:
if self.do_label: self.label(delete=1)
MAINWINDOW().removeAnimationHandler(self.interrupt_label)
self.interruptable = 0
if self.transform_scene < len(self.transform_play_list)-1:
self.transform_scene = self.transform_scene + 1
self.setup_scene_transform()
MAINWINDOW().addAnimationHandler(self.interrupt_label,self.next_transform)
elif self.finish_method:
DISPLAYTABLE().update()
apply(self.finish_method[0],[],self.finish_method[1])
#--------------------------------------------------------------------
def get_steps(self,nsteps=1,rock=0,centre_rock=0,delta=0,mode='', \
ramp_start=0, ramp_end=0):
#--------------------------------------------------------------------
ramp_start=2*(ramp_start/2)
ramp_end=2*(ramp_end/2)
#print "get_steps",ramp_start,ramp_end,rock
tmp = []
if mode == 'sine':
import math,copy
last_phase = 0.0
if rock:
f = 2.0
else:
f= 1.0
for step in range (1,nsteps+1):
phase = math.sin ( float(step) * math.pi * f / nsteps )
if delta:
tmp.append(phase-last_phase)
else:
tmp.append(phase)
last_phase=copy.deepcopy(phase)
else:
ns = int(nsteps/(rock+1))
#print 'get_steps ns',ns
if rock and centre_rock:
if delta:
frac = 1.0/float(ns)
for i in range(0,ns/2): tmp.append(-frac)
for i in range(0,ns): tmp.append(frac)
for i in range(0,ns/2): tmp.append(-frac)
else:
for i in range(ns/2,-1,-1): tmp.append(float(i)/float(ns))
for i in range(0,ns): tmp.append(float(i)/float(ns))
for i in range(ns,ns/2,-1): tmp.append(float(i)/float(ns))
else:
if ramp_start+ramp_end>0:
inc = 1.0/(float(ns-(ramp_start+ramp_end))+ \
0.5*float(ramp_start+ramp_end))
else:
inc = 1.0/float(ns)
if delta:
for i in range(0,ns): tmp.append(inc)
if rock:
for i in range(0,ns): tmp.append(-inc)
else:
frac = 0.0
if ramp_start:
for i in range(1,ramp_start+1):
tmp.append(frac)
#print "i",i,float(i-1)/float(ramp_start),frac
frac=frac+(inc*float(i)/float(ramp_start))
for i in range(ramp_start+1,ns-ramp_end+1):
frac=frac+inc
#print "i",i,frac
tmp.append(frac)
if ramp_end:
for i in range(ns-ramp_end+1,ns+1):
frac=frac+(inc*float(ns-i)/float(ramp_end))
#print "i",i,float(ns-i)/float(ramp_end),frac
tmp.append(frac)
if rock:
for i in range(ns-1,-1,-1):
tmp.append(tmp[i])
#print 'get_steps',nsteps,tmp
if rock>1:
for nn in range(2,rock+1):
for i in range(0,ns): tmp.append(tmp[i])
#print "tmp",tmp
return tmp
#------------------------------------------------------------------------
def get_changed_objects(self,initial_status,final_status,
interpolate_status=1):
#------------------------------------------------------------------------
changed_list = []
#print "transform.get_changed_objects interpolate_status",interpolate_status,initial_status.keys(),final_status.keys()
if interpolate_status:
# Get list of ShadowDataObj which have changed between the initial and final status
# and convert this to list of names
difobj_list = HISTORY().status_difference(initial_status,final_status)[0]
difobj_name_list = []
for item in difobj_list: difobj_name_list.append(item.name)
#print 'presentation.get_changed_objects',difobj_name_list
# Create list with one item for each currently loaded dataobj
# Each item in list is [dataobj, dataobj_initial_status, dataobj_final_status]
# The dataobj_initial_status and dataobj_final_status are None if there arew no changes
import dataobj
for item in dataobj.get_dataobj():
if difobj_name_list.count(item.name):
changed_list.append([item,initial_status[item.name],final_status[item.name]])
else:
changed_list.append([item,None,None])
#print 'presentation.get_changed_objects changed_list',changed_list
'''
import dataobj
for item in dataobj.get_dataobj():
if initial_status.has_key(item.name) and \
final_status.has_key(item.name):
initial_obj = initial_status[item.name]
final_obj = final_status[item.name]
if initial_obj == final_obj:
#print "transform.get_changed_objects initial and final status identical for",item
changed_list.append( [item,None,None])
else:
changed_list.append([item,initial_obj,final_obj])
'''
if initial_status.has_key('COLOUR') and final_status.has_key('COLOUR'):
diffs = MGCOLOUR().compare_objects( \
initial_status['COLOUR'],final_status['COLOUR'])
#print "COLOUR diffs",diffs
if diffs[0]:
changed_list.append([MGCOLOUR(),diffs[0],diffs[1]])
if initial_status.has_key('params') and final_status.has_key('params'):
import services
for key in initial_status['params'].data.keys():
if final_status['params'].data.has_key(key) and services.PM(key):
diffs=services.PM(key).compare_objects( \
initial_status['params'].data[key], \
final_status['params'].data[key])
#print "diffs",key,diffs
if diffs[0]:
changed_list.append([services.PM(key),diffs[0],diffs[1]])
#print "transform.get_changed_objects changed_list",changed_list
return changed_list
#------------------------------------------------------------------------
def read_view(self,filename=''):
#------------------------------------------------------------------------
'''
Read the view from a status file
'''
import pickle
params={}
if not os.path.exists(filename): return [1,params]
try:
f = open(filename,'r')
except:
return [1,params]
try:
status = pickle.load(f)
except:
return [2,params]
if status.has_key('view'):
for key in ['rpos','RADIUS','NEAR','FAR','quat']:
params[key] = getattr(status['view'],key)
return [0,params]
elif status.has_key('view2'):
#print "transform.read_view",status['view2']
for key in ['pos','scale','quat','fog_far','fog_near','slab_width','slab_offset','slab_enabled']:
params[key] = status['view2'].get(key)
return [0,params]
return [3,params]
#-----------------------------------------------------------------
def label(self,text='transform label',delete=0):
#------------------------------------------------------------------
import build,cprim,pygl_coord,graphicsmodel
#print "transform::label",text
if delete:
#if hasattr(self,'label_graphmod') and self.label_graphmod:
# build.build.insts.deletemod(self.label_graphmod)
# del self.label_graphmod
# del self.label_graphmod_obj
return
else:
if not hasattr(self,'label_graphmod') or not self.label_graphmod:
import build
self.label_graphmod = graphicsmodel.graphicsmodel( )
build.build.insts.append(self.label_graphmod)
if hasattr(self,'label_graphmod_obj') and len(self.label_graphmod_obj)>0:
for obj in self.label_graphmod_obj:
cprim.DeleteTextLabel(self.label_graphmod.obj,obj.GetID())
self.label_graphmod_obj = []
x,y=0.1,0.9
label_ob = cprim.BillBoardText( \
pygl_coord.Cartesian(x,y,0.0), \
text, pygl_coord.Cartesian(x,y,0.0))
label_ob.thisown = 0
self.label_graphmod.obj.add_text_primitive(label_ob)
self.label_graphmod_obj.append(label_ob)
self.label_graphmod.obj.rebuild()
font = DT().viewmenu.default_font
self.label_graphmod.obj.SetTextFont(str(font['family']),str(font['weight']), \
str(font['slant']),'24',font['underline'])
#-------------------------------------------------------------------
def play_movie(self,filename):
#-------------------------------------------------------------------
import os
from PyQt4 import QtGui,QtCore
image_formats_c = QtGui.QMovie.supportedFormats()
image_formats = []
for im in image_formats_c:
if not image_formats.count(str(im).lower()):
image_formats.append(str(im))
if os.path.exists(filename):
name_split = os.path.splitext(filename)
if len(name_split)>1 and '.' in name_split[1] and image_formats.count(name_split[1][1:]):
viewer = FILEVIEWER(self.identifier)
viewer.open(filename,format='movie',title=filename)
else:
if sys.platform == 'linux2':
viewer = FILEVIEWER(self.identifier)
viewer.open(filename,format='movie_phonon',title=filename)
else:
QtGui.QDesktopServices.openUrl(QtCore.QUrl.fromLocalFile(filename))
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
class movie_preferences:
#-------------------------------------------------------------------
#-------------------------------------------------------------------
#-------------------------------------------------------------------
insts = None
#-------------------------------------------------------------------
def __init__(self):
#-------------------------------------------------------------------
movie_preferences.insts = self
self.PM = self.create_movie_preferences()
#-------------------------------------------------------------------
def movie_preferences(self):
#-------------------------------------------------------------------
return self.PM
#-------------------------------------------------------------------------
def create_movie_preferences(self):
#-------------------------------------------------------------------------
import services
return services.ParamsManager (
name='movie_preferences',
help = 'movies#movies',
title='Movie Compile',
gui =['convert_exe','ffmpeg_exe','mencoder_exe','player_exe','show_progress'],
default = {
'convert_command' : '-quality 100',
'ffmpeg_command' : '-f mpeg -vcodec mpeg1video -ar 48000 -b 7000000 -ab 192000 -y',
'mencoder_command' : '-ovc lavc -lavcopts vcodec=msmpeg4v2:vbitrate=1800',
'mencoder_merge_command' : '-ovc copy',
'player_command' : '-loop 0',
'convert_exe' : 'convert',
'ffmpeg_exe' : 'ffmpeg',
'mencoder_exe' : 'mencoder',
'player_exe' : 'mplayer',
'show_progress' : 1 },
definition = { \
'convert_exe' : dict(type=str,label='Convert executable(Imagemagick)'),
'convert_command' : dict(type=str,label='Convert arguments'),
'ffmpeg_exe' : dict(type=str,label='Ffmpeg executable'),
'ffmpeg_command' : dict(type=str,label='Ffmpeg arguments'),
'mencoder_exe' : dict(type=str,label='mencoder executable'),
'mencoder_command': dict(type=str,label='Mencoder arguments'),
'mencoder_merge_command': dict(type=str,label='Mencoder merge arguments'),
'player_exe' : dict(type=str,label='mpeg player executable'),
'player_command' : dict(type=str,label='mpeg player arguments'),
'show_progress' : dict(type='bool',label='Show progress',style='checkbox')
})