diff --git a/examples/webgl/animation.py b/examples/webgl/animation.py new file mode 100644 index 000000000..d7c5d9ccd --- /dev/null +++ b/examples/webgl/animation.py @@ -0,0 +1,43 @@ +""" +============== +make animation +============== +The dynamic viewer generated by cortex can be used to make an animation +such as a transition between inflated and flattened brain or a rotating +brain, of a cortical surface. We show here an example. + +""" + +import cortex + +# gather data Volume +volume = cortex.Volume.random(subject='S1', xfmname='fullhead') + +# select path for the animated movie on disk +animation_path = '/path/to/save/animation' + +# create viewer (additional viewer parameters can be specified here, +# such as omitting ROI labels for example) +handle = cortex.webgl.show(data=volume) + +# Called after a call of the form: js_handle = cortex.webgl.show(DataViewObject) +# Start with left hemisphere view +start_view = dict(azimuth=90, altitude=90.5) + +# utility functions to set the different views +prefix = dict(altitude='camera.', azimuth='camera.', + pivot='surface.{subject}.', radius='camera.', + unfold='surface.{subject}.') +_tolists = lambda p: {prefix[k]+k:[v] for k,v in p.items()} + +handle._set_view(**_tolists(start_view)) + +# Initialize list +animation = [] +# Append 5 key frames for a simple rotation +for az, idx in zip([90, 180, 270, 360, 450], [0, .5, 1.0, 1.5, 2.0]): + animation.append({'state':'camera.azimuth', 'idx':idx, 'value':[az]}) +# Animate! (use default settings) +handle.makeMovie(animation, filename=os.path.join(movie_path,'brainmovie%07d.png')) + +# the 'movie_path' directory will now have all the frames of the animation \ No newline at end of file diff --git a/examples/webgl/save_3d_views.py b/examples/webgl/save_3d_views.py new file mode 100644 index 000000000..a29325584 --- /dev/null +++ b/examples/webgl/save_3d_views.py @@ -0,0 +1,85 @@ +""" +============= +Save 3D views +============= +The dynamic viewer generated by cortex can be used to produce images +of brains in 3D. This examples show how different views can be +captured into '.png' images after a dynamic viewer is instantiated. + +""" + +import os +import time +import cortex + +# gather data Volume +volume = cortex.Volume.random(subject='S1', xfmname='fullhead') + +# select path for the generated images on disk +image_path = '/path/to/save/images' + +# pattern of the saved images names +file_pattern = '{base}_{view}_{surface}.png' +# in this case, let's use 'test' as a base name: +base_str = 'test' + +# create viewer (additional viewer parameters can be specified here, +# such as omitting ROI labels for example) +handle = cortex.webgl.show(data=volume) + +# wait to make sure the viewer was instantiated: +time.sleep(5.0) + +# Set up params + +# projection parameters +basic = dict(radius=400) # projection=['orthographic'], + +# different views available, more views can be added and the +# existing list can be removed +views = dict(lateral=dict(altitude=90.5, azimuth=181, pivot=180), + medial=dict(altitude=90.5, azimuth=0, pivot=180), + front=dict(altitude=90.5, azimuth=0, pivot=0), + back=dict(altitude=90.5, azimuth=181, pivot=0), + top=dict(altitude=0, azimuth=180, pivot=0), + bottom=dict(altitude=180, azimuth=0, pivot=0) + ) + +# different surfaces options can be used +surfaces = dict(inflated=dict(unfold=0.5), + fiducial=dict(unfold=0.0)) + + +# utility functions to set the different views +prefix = dict(altitude='camera.', azimuth='camera.', + pivot='surface.{subject}.', radius='camera.', + unfold='surface.{subject}.') +_tolists = lambda p: {prefix[k]+k:[v] for k,v in p.items()} +_combine = lambda a,b: ( lambda c: [c, c.update(b)][0] )(dict(a)) + + +# Save images by iterating over the different views and surfaces +for view,vparams in views.items(): + for surf,sparams in surfaces.items(): + # Combine basic, view, and surface parameters + params = _combine(_combine(basic, vparams), sparams) + # Set the view + handle._set_view(**_tolists(params)) + # Save image + filename = file_pattern.format(base=base_str, view=view, surface=surf) + output_path = os.path.join(image_path, filename) + handle.getImage(output_path, size =(1920, 1080)) + + # the block below trims the edges of the image: + # wait for image to be written + while not os.path.exists(output_path): + pass + time.sleep(0.5) + try: + import subprocess + subprocess.call(['convert', '-trim', output_path, output_path]) + except: + pass + +# Close the window! +handle.close() \ No newline at end of file