Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NF,DOC improve docstring for show and make_static #548

Merged
merged 2 commits into from
Jul 19, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
231 changes: 154 additions & 77 deletions cortex/webgl/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,27 @@
colormaps = [(os.path.splitext(os.path.split(cm)[1])[0], serve.make_base64(cm))
for cm in sorted(colormaps)]

def make_static(outpath, data, types=("inflated",), recache=False, cmap="RdBu_r",
template="static.html", layout=None, anonymize=False, overlays_available=None,
html_embed=True, overlays_visible=('rois', 'sulci'), labels_visible=('rois', ),
overlay_file=None, copy_ctmfiles=True, title='Brain', **kwargs):
def make_static(
outpath,
data,
recache=False,
template="static.html",
anonymize=False,
overlays_available=None,
overlays_visible=("rois", "sulci"),
labels_visible=("rois",),
types=("inflated",),
html_embed=True,
copy_ctmfiles=True,
title="Brain",
layout=None,
overlay_file=None,
curvature_brightness=None,
curvature_contrast=None,
curvature_smoothness=None,
surface_specularity=None,
**kwargs,
):
"""
Creates a static webGL MRI viewer in your filesystem so that it can easily
be posted publicly for sharing or just saved for later viewing.
Expand Down Expand Up @@ -77,20 +94,12 @@ def make_static(outpath, data, types=("inflated",), recache=False, cmap="RdBu_r"
Labels for the listed layers will be set visible by default. Labels for
layers not listed here will be hidden by default (but can be enabled in
the viewer GUI). Default ('rois', )
**kwargs
All additional keyword arguments are passed to the template renderer.

Other parameters
----------------
types : tuple, optional
Types of surfaces to include in addition to the original (fiducial, pial,
and white matter) and flat surfaces. Default ('inflated', )
cmap : string, optional
Name of default colormap. Default 'RdBu_r'
TODO: DOES THIS DO ANYTHING ANYMORE?
overlay_file : str, optional
Custom overlays.svg file to use instead of the default one for this
subject (if not None). Default None.
html_embed : bool, optional
Whether to embed the webgl resources in the html output. Default 'True'.
If 'False', the webgl resources must be served by your web server.
Expand All @@ -104,22 +113,35 @@ def make_static(outpath, data, types=("inflated",), recache=False, cmap="RdBu_r"
a browser.
layout : None or list of (int, int)
The layout of the viewer subwindows for showing multiple subjects, passed to
the template generator.
the template generator.
Default to None, corresponding to no subwindows.
overlay_file : str or None, optional
Custom overlays.svg file to use instead of the default one for this
subject (if not None). Default None.
curvature_brightness : float or None, optional
Brightness of curvature overlay. Default None, which uses the value
specified in the config file.
curvature_contrast : float or None, optional
Contrast of curvature overlay. Default None, which uses the value
specified in the config file.
curvature_smoothness : float or None, optional
Smoothness of curvature overlay. Default None, which uses the value
specified in the config file.
surface_specularity : float or None, optional
Specularity of surfaces visualized with the WebGL viewer.
Default None, which uses the value specified in the config file under
`webgl_viewopts.specularity`.
**kwargs
All additional keyword arguments are passed to the template renderer.

Notes
-----
You will need a real web server to view this, since `file://` paths
don't handle xsrf correctly
"""

outpath = os.path.abspath(os.path.expanduser(outpath)) # To handle ~ expansion
if not os.path.exists(outpath):
os.makedirs(outpath)
if not os.path.exists(os.path.join(outpath, 'data')):
# Don't lump together w/ outpath, because of edge cases
# for which outpath exists but not sub-folder `data`
os.makedirs(os.path.join(outpath, "data"))
outpath = os.path.abspath(os.path.expanduser(outpath)) # To handle ~ expansion
os.makedirs(os.path.join(outpath, "data"), exist_ok=True)

data = dataset.normalize(data)
if not isinstance(data, dataset.Dataset):
Expand All @@ -130,10 +152,14 @@ def make_static(outpath, data, types=("inflated",), recache=False, cmap="RdBu_r"
package = Package(data)
subjects = list(package.subjects)

ctmargs = dict(method='mg2', level=9, recache=recache, external_svg=overlay_file,
overlays_available=overlays_available)
ctms = dict((subj, utils.get_ctmpack(subj, types, **ctmargs))
for subj in subjects)
ctmargs = dict(
method="mg2",
level=9,
recache=recache,
external_svg=overlay_file,
overlays_available=overlays_available,
)
ctms = dict((subj, utils.get_ctmpack(subj, types, **ctmargs)) for subj in subjects)
package.reorder(ctms)

db.auxfile = None
Expand All @@ -144,15 +170,15 @@ def make_static(outpath, data, types=("inflated",), recache=False, cmap="RdBu_r"
oldpath, fname = os.path.split(ctmfile)
fname, ext = os.path.splitext(fname)
if anonymize:
newfname = "S%d"%i
newfname = "S%d" % i
submap[subj] = newfname
else:
newfname = fname
ctms[subj] = newfname+".json"
ctms[subj] = newfname + ".json"

for ext in ['json', 'ctm', 'svg']:
srcfile = os.path.join(oldpath, "%s.%s"%(fname, ext))
newfile = os.path.join(outpath, "%s.%s"%(newfname, ext))
for ext in ["json", "ctm", "svg"]:
srcfile = os.path.join(oldpath, "%s.%s" % (fname, ext))
newfile = os.path.join(outpath, "%s.%s" % (newfname, ext))
if os.path.exists(newfile):
os.unlink(newfile)

Expand All @@ -170,30 +196,31 @@ def make_static(outpath, data, types=("inflated",), recache=False, cmap="RdBu_r"
ofh.close()
if anonymize:
old_subjects = sorted(list(ctms.keys()))
ctms = dict(('S%d'%i, ctms[k]) for i, k in enumerate(old_subjects))
ctms = dict(("S%d" % i, ctms[k]) for i, k in enumerate(old_subjects))
if len(submap) == 0:
submap = None

#Process the data
# Process the data
metadata = package.metadata(fmt="data/{name}_{frame}.png", submap=submap)
images = package.images
#Write out the PNGs
# Write out the PNGs
for name, imgs in images.items():
impath = os.path.join(outpath, "data", "{name}_{frame}.png")
for i, img in enumerate(imgs):
with open(impath.format(name=name, frame=i), "wb") as binfile:
binfile.write(img)

#Copy any stimulus files
# Copy any stimulus files
stimpath = os.path.join(outpath, "stim")
for name, view in data:
if 'stim' in view.attrs and os.path.exists(view.attrs['stim']):
if "stim" in view.attrs and os.path.exists(view.attrs["stim"]):
if not os.path.exists(stimpath):
os.makedirs(stimpath)
shutil.copy2(view.attrs['stim'], stimpath)
shutil.copy2(view.attrs["stim"], stimpath)

#Parse the html file and paste all the js and css files directly into the html
# Parse the html file and paste all the js and css files directly into the html
from . import htmlembed

if os.path.exists(template):
## Load locally
templatedir, templatefile = os.path.split(os.path.abspath(template))
Expand All @@ -206,27 +233,46 @@ def make_static(outpath, data, types=("inflated",), recache=False, cmap="RdBu_r"
tpl = loader.load(templatefile)

# Put together all view options
my_viewopts = dict(options.config.items('webgl_viewopts'))
my_viewopts['overlays_visible'] = overlays_visible
my_viewopts['labels_visible'] = labels_visible
my_viewopts['brightness'] = options.config.get('curvature', 'brightness')
my_viewopts['smoothness'] = options.config.get('curvature', 'webgl_smooth')
my_viewopts['contrast'] = options.config.get('curvature', 'contrast')
my_viewopts = dict(options.config.items("webgl_viewopts"))
my_viewopts["overlays_visible"] = overlays_visible
my_viewopts["labels_visible"] = labels_visible
my_viewopts["brightness"] = (
options.config.get("curvature", "brightness")
if curvature_brightness is None
else curvature_brightness
)
my_viewopts["contrast"] = (
options.config.get("curvature", "contrast")
if curvature_contrast is None
else curvature_contrast
)
my_viewopts["smoothness"] = (
options.config.get("curvature", "webgl_smooth")
if curvature_smoothness is None
else curvature_smoothness
)
my_viewopts["specularity"] = (
options.config.get("webgl_viewopts", "specularity")
if surface_specularity is None
else surface_specularity
)

for sec in options.config.sections():
if 'paths' in sec or 'labels' in sec:
if "paths" in sec or "labels" in sec:
my_viewopts[sec] = dict(options.config.items(sec))

html = tpl.generate(data=json.dumps(metadata),
colormaps=colormaps,
default_cmap=cmap,
python_interface=False,
leapmotion=True,
layout=layout,
subjects=json.dumps(ctms),
viewopts=json.dumps(my_viewopts),
title=title,
**kwargs)
html = tpl.generate(
data=json.dumps(metadata),
colormaps=colormaps,
default_cmap="RdBu_r",
python_interface=False,
leapmotion=True,
layout=layout,
subjects=json.dumps(ctms),
viewopts=json.dumps(my_viewopts),
title=title,
**kwargs,
)
desthtml = os.path.join(outpath, "index.html")
if html_embed:
htmlembed.embed(html, desthtml, rootdirs)
Expand All @@ -235,15 +281,27 @@ def make_static(outpath, data, types=("inflated",), recache=False, cmap="RdBu_r"
htmlfile.write(html)


def show(data, types=("inflated", ), recache=False, cmap='RdBu_r', layout=None,
autoclose=None, open_browser=None, port=None, pickerfun=None,
template="mixer.html", overlays_available=None,
overlays_visible=('rois', 'sulci'), labels_visible=('rois', ),
overlay_file=None,
curvature_brightness=None,
curvature_smoothness=None,
curvature_contrast=None,
title='Brain', **kwargs):
def show(
data,
autoclose=None,
open_browser=None,
port=None,
pickerfun=None,
recache=False,
template="mixer.html",
overlays_available=None,
overlays_visible=("rois", "sulci"),
labels_visible=("rois",),
types=("inflated",),
overlay_file=None,
curvature_brightness=None,
curvature_contrast=None,
curvature_smoothness=None,
surface_specularity=None,
title="Brain",
layout=None,
**kwargs,
):
"""
Creates a webGL MRI viewer that is dynamically served by a tornado server
running inside the current python process.
Expand Down Expand Up @@ -273,6 +331,10 @@ def show(data, types=("inflated", ), recache=False, cmap='RdBu_r', layout=None,
Force recreation of CTM and SVG files for surfaces. Default False
template : string, optional
Name of template HTML file. Default 'mixer.html'
overlays_available : tuple, optional
Overlays available in the viewer. If None, then all overlay layers of the
svg file will be potentially available in the viewer (whether initially
visible or not).
overlays_visible : tuple, optional
The listed overlay layers will be set visible by default. Layers not listed
here will be hidden by default (but can be enabled in the viewer GUI).
Expand All @@ -281,36 +343,37 @@ def show(data, types=("inflated", ), recache=False, cmap='RdBu_r', layout=None,
Labels for the listed layers will be set visible by default. Labels for
layers not listed here will be hidden by default (but can be enabled in
the viewer GUI). Default ('rois', )
**kwargs
All additional keyword arguments are passed to the template renderer.

Other parameters
----------------
types : tuple, optional
Types of surfaces to include in addition to the original (fiducial, pial,
and white matter) and flat surfaces. Default ('inflated', )
cmap : string, optional
Name of default colormap. Default 'RdBu_r'
TODO: DOES THIS DO ANYTHING ANYMORE?
overlay_file : str or None, optional
Custom overlays.svg file to use instead of the default one for this
subject (if not None). Default None.
curvature_brightness : float or None, optional
Brightness of curvature overlay. Default None, which uses the value
specified in the config file.
curvature_smoothness : float or None, optional
Smoothness of curvature overlay. Default None, which uses the value
specified in the config file.
curvature_contrast : float or None, optional
Contrast of curvature overlay. Default None, which uses the value
specified in the config file.
curvature_smoothness : float or None, optional
Smoothness of curvature overlay. Default None, which uses the value
specified in the config file.
surface_specularity : float or None, optional
Specularity of surfaces visualized with the WebGL viewer.
Default None, which uses the value specified in the config file under
`webgl_viewopts.specularity`.
title : str, optional
The title that is displayed on the viewer website when it is loaded in
a browser.
layout : None or list of (int, int), optional
The layout of the viewer subwindows for showing multiple subjects, passed to
the template generator.
Default None, corresponding to no subwindows.
**kwargs
All additional keyword arguments are passed to the template renderer.
"""

# populate default webshow args
Expand Down Expand Up @@ -361,12 +424,26 @@ def show(data, types=("inflated", ), recache=False, cmap='RdBu_r', layout=None,
my_viewopts = dict(options.config.items('webgl_viewopts'))
my_viewopts['overlays_visible'] = overlays_visible
my_viewopts['labels_visible'] = labels_visible
my_viewopts['brightness'] = options.config.get('curvature', 'brightness') \
if curvature_brightness is None else curvature_brightness
my_viewopts['smoothness'] = options.config.get('curvature', 'webgl_smooth') \
if curvature_smoothness is None else curvature_smoothness
my_viewopts['contrast'] = options.config.get('curvature', 'contrast') \
if curvature_contrast is None else curvature_contrast
my_viewopts["brightness"] = (
options.config.get("curvature", "brightness")
if curvature_brightness is None
else curvature_brightness
)
my_viewopts["contrast"] = (
options.config.get("curvature", "contrast")
if curvature_contrast is None
else curvature_contrast
)
my_viewopts["smoothness"] = (
options.config.get("curvature", "webgl_smooth")
if curvature_smoothness is None
else curvature_smoothness
)
my_viewopts["specularity"] = (
options.config.get("webgl_viewopts", "specularity")
if surface_specularity is None
else surface_specularity
)

for sec in options.config.sections():
if 'paths' in sec or 'labels' in sec:
Expand Down Expand Up @@ -441,7 +518,7 @@ def get(self):
self.set_header("Content-Type", "text/html")
generated = html.generate(data=metadata,
colormaps=colormaps,
default_cmap=cmap,
default_cmap="RdBu_r",
python_interface=True,
leapmotion=True,
layout=layout,
Expand Down