Commit 0f7d671a authored by lambdamusic's avatar lambdamusic

activated 'alpha' dataviz

parent c266a086
...@@ -2,6 +2,11 @@ ...@@ -2,6 +2,11 @@
Summary of changes. Summary of changes.
## December, 2018: v1.9.8
- small bug fixes
- refactor action visualize / activated 'alpha' dataviz
## December, 2018: v1.9.7 ## December, 2018: v1.9.7
- removed support for Python 2 - removed support for Python 2
......
...@@ -97,6 +97,127 @@ Ontospy is a command line inspector for RDF/OWL models. Use the --help option wi ...@@ -97,6 +97,127 @@ Ontospy is a command line inspector for RDF/OWL models. Use the --help option wi
# click.echo('I am about to invoke %s' % ctx.invoked_subcommand) # click.echo('I am about to invoke %s' % ctx.invoked_subcommand)
##
## GENDOCS COMMAND (wrapper around ontodocs)
##
@main_cli.command()
@click.argument('source', nargs=-1)
@click.option(
'--outputpath',
'-o',
help=
'OUTPUT-PATH: where to save the visualization files (default: home folder).'
)
@click.option(
'--type',
help=
'VIZ-TYPE: specify which viz type to use as an integer (eg 1=single-page html, 2=multi-page etc..).'
)
@click.option(
'--title',
help='TITLE: custom title for the visualization (default=graph uri).')
@click.option(
'--theme',
help=
'THEME: bootstrap css style for the html-multi-page visualization (random=use a random theme).'
)
@click.option(
'--lib',
is_flag=True,
help='LIBRARY: choose an ontology from the local library.')
@click.option(
'--showtypes',
is_flag=True,
help='SHOW-TYPES: show the available visualization types.')
@click.option(
'--showthemes',
is_flag=True,
help='SHOW-THEMES: show the available css theme choices.')
@click.pass_context
def gendocs(ctx,
source=None,
outputpath="",
lib=False,
type="",
title="",
theme="",
showthemes=False,
showtypes=False):
"""Generate documentation for an ontology in html or markdown format
"""
verbose = ctx.obj['VERBOSE']
sTime = ctx.obj['STIME']
print_opts = {
'labels': verbose,
}
from .ontodocs.builder import show_themes, random_theme, show_types
try:
# check that we have the required dependencies
import django
except:
click.secho(
"WARNING: this functionality requires the Django package and other extra dependecies.",
fg="red")
click.secho("Install with `pip install ontospy[HTML] -U`")
sys.exit(0)
if not source and not showthemes and not showtypes and not lib:
click.echo(ctx.get_help())
return
if showthemes:
show_themes()
sys.exit(0)
if showtypes:
show_types()
sys.exit(0)
if theme and theme == "random":
theme = random_theme()
if outputpath:
if not (os.path.exists(outputpath)) or not (os.path.isdir(outputpath)):
click.secho(
"WARNING: the -o option must include a valid directory path.",
fg="red")
sys.exit(0)
if source and len(source) > 1:
click.secho(
'Note: currently only one argument can be passed', fg='red')
if lib:
click.secho("Local library => '%s'" % get_home_location(), fg='white')
ontouri = action_listlocal(all_details=False)
if ontouri:
source = [os.path.join(get_home_location(), ontouri)]
else:
raise SystemExit(1)
# note: the local ontospy library gets displayed via this method too
url = action_visualize(
source,
fromshell=False,
path=outputpath,
title=title,
viztype=type,
theme=theme,
verbose=verbose)
if url: # open browser
import webbrowser
webbrowser.open(url)
eTime = time.time()
tTime = eTime - sTime
printDebug("\n-----------\n" + "Time: %0.2fs" % tTime, "comment")
## ##
## LIBRARY COMMAND ## LIBRARY COMMAND
## ##
...@@ -382,90 +503,6 @@ if __name__ == '__main__': ...@@ -382,90 +503,6 @@ if __name__ == '__main__':
except KeyboardInterrupt as e: # Ctrl-C except KeyboardInterrupt as e: # Ctrl-C
raise e raise e
##
## GENDOCS COMMAND (wrapper around ontodocs)
##
@main_cli.command()
@click.argument('source', nargs=-1)
@click.option('--outputpath', '-o', help='Output path (default: home folder).')
@click.option(
'--title', '-t', help='Title for the visualization (default=graph uri).')
@click.option(
'--theme',
help=
'CSS Theme for the html-complex visualization (random=use a random theme).'
)
@click.option(
'--showthemes', is_flag=True, help='Show the available CSS theme choices.')
@click.pass_context
def gendocs(ctx,
source=None,
outputpath="",
title="",
theme="",
showthemes=False):
"""Generate documentation for an ontology in html or markdown format
"""
verbose = ctx.obj['VERBOSE']
sTime = ctx.obj['STIME']
print_opts = {
'labels': verbose,
}
from .ontodocs.builder import action_visualize, show_themes, random_theme
try:
# check that we have the required dependencies
import django
except:
click.secho(
"WARNING: this functionality requires the Django package and other extra dependecies.",
fg="red")
click.secho("Install with `pip install ontospy[HTML] -U`")
sys.exit(0)
if not source and not showthemes:
click.echo(ctx.get_help())
return
if showthemes:
show_themes()
sys.exit(0)
if theme and theme == "random":
theme = ontodocs.random_theme()
if outputpath:
if not (os.path.exists(outputpath)) or not (os.path.isdir(outputpath)):
click.secho(
"WARNING: the -o option must include a valid directory path.",
fg="red")
sys.exit(0)
if source and len(source) > 1:
click.secho(
'Note: currently only one argument can be passed', fg='red')
# note: the local ontospy library gets displayed via this method too
url = action_visualize(
source,
fromshell=False,
path=outputpath,
title=title,
theme=theme,
verbose=verbose)
if url: # open browser
import webbrowser
webbrowser.open(url)
eTime = time.time()
tTime = eTime - sTime
printDebug("\n-----------\n" + "Time: %0.2fs" % tTime, "comment")
if __name__ == '__main__': if __name__ == '__main__':
import sys import sys
try: try:
......
...@@ -599,3 +599,55 @@ def action_erase(): ...@@ -599,3 +599,55 @@ def action_erase():
""" """
get_or_create_home_repo(reset=True) get_or_create_home_repo(reset=True)
return True return True
def action_visualize(args,
fromshell=False,
path=None,
title="",
viztype="",
theme="",
verbose=False):
"""
export model into another format eg html, d3 etc...
<fromshell> : the local name is being passed from ontospy shell
"""
from ..ontodocs.builder import ask_visualization, select_visualization, VISUALIZATIONS_LIST, build_visualization
if fromshell:
ontouri = args
islocal = True
else:
ontouri = args[0]
islocal = False
# select a visualization
if viztype:
viztype = select_visualization(viztype)
else:
viztype = ask_visualization()
if viztype == "":
return None
# raise SystemExit, 1
# 2017-01-23: bypass pickled stuff as it has wrong counts etc..
# get ontospy graph
printDebug("Loading graph...", dim=True)
g = Ontospy(ontouri, verbose=verbose)
# put in home folder by default: <ontouri>/<viztype>/files..
if not path:
from os.path import expanduser
home = expanduser("~")
onto_path = slugify(unicode(ontouri))
viz_path = slugify(unicode(VISUALIZATIONS_LIST[viztype]['Title']))
path = os.path.join(home, "ontospy-viz/" + onto_path + "/" + viz_path)
if not os.path.exists(path):
os.makedirs(path)
# url = build_viz(ontouri, g, viztype, path)
printDebug("Building visualization...", dim=True)
url = build_visualization(ontouri, g, viztype, path, title, theme)
return url
...@@ -2,29 +2,62 @@ ...@@ -2,29 +2,62 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
VISUALIZATIONS_LIST = { VISUALIZATIONS_LIST = {
"Visualizations": "Visualizations": [{
[{
"ID": "html-simple", "ID": "html-simple",
"Title": "Html: single-page", "Title": "Html: single page",
"Description": "@todo", "Description": "@todo",
} , { },
"ID": "html-complex", {
"Title": "Html: multi-page", "ID": "html-complex",
"Description": "@todo", "Title": "Html: multi page",
} , { "Description": "@todo",
"ID": "markdown", },
"Title": "Markdown: multi-page", {
"Description": "@todo", "ID": "markdown",
} , { "Title": "Markdown: multi page",
"ID": "d3-tree", "Description": "@todo",
"Title": "D3 Dendogram", },
"Description": "@todo", {
} "ID": "d3-tree",
] "Title": "D3 Dendogram",
"Description": "@todo",
},
{
"ID": "d3-bubble-chart",
"Title": "D3 Bubble chart [alpha]",
"Description": "@todo",
},
{
"ID": "d3-pack-hierarchy",
"Title": "D3 Pack hierarchy [alpha]",
"Description": "@todo",
},
{
"ID": "d3-bar-hierarchy",
"Title": "D3 Bar hierarchy [alpha]",
"Description": "@todo",
},
{
"ID": "d3-partition-table",
"Title": "D3 Partition table [alpha]",
"Description": "@todo",
},
{
"ID": "d3-rotating-cluster",
"Title": "D3 Rotating cluster [alpha]",
"Description": "@todo",
},
{
"ID": "sigma-force-directed",
"Title": "Sigma.js Force directed graph [alpha]",
"Description": "@todo",
}]
} }
BOOTSWATCH_THEMES = [
BOOTSWATCH_THEMES = ['cerulean' , 'flatly' , 'lumen' , 'sandstone' , 'spacelab' , 'yeti' , 'cosmo' , 'darkly' , 'paper' , 'simplex' , 'superhero' , 'readable' , 'slate' , 'united'] 'cerulean', 'flatly', 'lumen', 'sandstone', 'spacelab', 'yeti', 'cosmo',
'darkly', 'paper', 'simplex', 'superhero', 'readable', 'slate', 'united'
]
BOOTSWATCH_THEME_DEFAULT = "simplex" BOOTSWATCH_THEME_DEFAULT = "simplex"
# 'cyborg' , 'journal' # 'cyborg' , 'journal'
...@@ -81,6 +81,13 @@ except: # Mother of all exceptions ...@@ -81,6 +81,13 @@ except: # Mother of all exceptions
raise raise
def show_types():
for n, t in enumerate(VISUALIZATIONS_LIST):
printDebug("%d. %s" % (n + 1, t['Title']), "green")
printDebug("Note: select a viz type by using its numerical index.",
"comment")
def show_themes(): def show_themes():
for t in BOOTSWATCH_THEMES: for t in BOOTSWATCH_THEMES:
printDebug(t, "green") printDebug(t, "green")
...@@ -127,71 +134,18 @@ def ask_visualization(): ...@@ -127,71 +134,18 @@ def ask_visualization():
continue continue
# MAIN METHOD def select_visualization(n):
def action_visualize(args,
fromshell=False,
path=None,
title="",
theme="",
verbose=False):
""" """
export model into another format eg html, d3 etc... get viz choice based on numerical index
<fromshell> : the local name is being passed from ontospy shell
""" """
try:
# get argument n = int(n) - 1
if not (args): test = VISUALIZATIONS_LIST[n] # throw exception if number wrong
ontouri = ontospy_actions.action_listlocal(all_details=False) return n
if ontouri: except:
islocal = True printDebug("Invalid viz-type option. Valid options are:", "red")
else: show_types()
raise SystemExit(1) raise SystemExit(1)
elif fromshell:
ontouri = args
islocal = True
else:
ontouri = args[0]
islocal = False
# select a visualization
viztype = ask_visualization()
if viztype == "":
return None
# raise SystemExit, 1
# 2017-01-23: bypass pickled stuff as it has wrong counts etc..
USE_CACHE = False
# get ontospy graph
if islocal and USE_CACHE:
g = get_pickled_ontology(ontouri)
if not g:
g = do_pickle_ontology(ontouri)
else:
printDebug("Loading graph...", dim=True)
if islocal:
g = Ontospy(
os.path.join(ontospy_manager.get_home_location(), ontouri),
verbose=verbose)
else:
g = Ontospy(ontouri, verbose=verbose)
# put in home folder by default: <ontouri>/<viztype>/files..
if not path:
from os.path import expanduser
home = expanduser("~")
onto_path = slugify(unicode(ontouri))
viz_path = slugify(unicode(VISUALIZATIONS_LIST[viztype]['Title']))
path = os.path.join(home, "ontospy-viz/" + onto_path + "/" + viz_path)
if not os.path.exists(path):
os.makedirs(path)
# url = build_viz(ontouri, g, viztype, path)
printDebug("Building visualization...", dim=True)
url = build_visualization(ontouri, g, viztype, path, title, theme)
return url
# =========== # ===========
...@@ -224,8 +178,32 @@ def build_visualization(ontouri, g, viz_index, path=None, title="", theme=""): ...@@ -224,8 +178,32 @@ def build_visualization(ontouri, g, viz_index, path=None, title="", theme=""):
v = MarkdownViz(g, title) v = MarkdownViz(g, title)
elif this_viz['ID'] == "d3-tree": elif this_viz['ID'] == "d3-tree":
from .viz.viz_d3tree import D3TreeViz from .viz.viz_d3tree import Dataviz
v = D3TreeViz(g, title) v = Dataviz(g, title)
elif this_viz['ID'] == "d3-bubble-chart":
from .viz.viz_d3bubbleChart import Dataviz
v = Dataviz(g, title)
elif this_viz['ID'] == "d3-pack-hierarchy":
from .viz.viz_d3packHierarchy import Dataviz
v = Dataviz(g, title)
elif this_viz['ID'] == "d3-bar-hierarchy":
from .viz.viz_d3barHierarchy import Dataviz
v = Dataviz(g, title)
elif this_viz['ID'] == "d3-partition-table":
from .viz.viz_d3partitionTable import Dataviz
v = Dataviz(g, title)
elif this_viz['ID'] == "d3-rotating-cluster":
from .viz.viz_d3rotatingCluster import Dataviz
v = Dataviz(g, title)
elif this_viz['ID'] == "sigma-force-directed":
from .viz.viz_sigmajs import Dataviz
v = Dataviz(g, title)
else: else:
return False return False
...@@ -257,7 +235,7 @@ def saveVizGithub(contents, ontouri): ...@@ -257,7 +235,7 @@ def saveVizGithub(contents, ontouri):
'content': 'content':
"""The MIT License (MIT) """The MIT License (MIT)
Copyright (c) 2016 OntoSpy project [http://ontospy.readthedocs.org/] Copyright (c) 2016 OntoSpy project [http://lambdamusic.github.io/Ontospy//]
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
......
...@@ -67,7 +67,7 @@ ...@@ -67,7 +67,7 @@
<h1 class="title">Ontology:&nbsp;<a href="javascript:showpanel('ontoinfo');">{{main_uri}}</a></h1> <h1 class="title">Ontology:&nbsp;<a href="javascript:showpanel('ontoinfo');">{{main_uri}}</a></h1>
<h3>{{ontology.bestDescription}}</h3> <h3>{{ontology.bestDescription}}</h3>
<p><small>Ontology documentation automatically generated by <a class="greylink" href="http://ontospy.readthedocs.org/">OntoSpy</a> on {% now "jS F Y H:i" %}</small></p> <p><small>Ontology documentation automatically generated by <a class="greylink" href="http://lambdamusic.github.io/Ontospy//">OntoSpy</a> on {% now "jS F Y H:i" %}</small></p>
<hr> <hr>
......
...@@ -72,7 +72,7 @@ circle.child:hover { ...@@ -72,7 +72,7 @@ circle.child:hover {
<h1 class="title">Ontology:&nbsp;<a href="javascript:showpanel('ontoinfo');">{{main_uri}}</a></h1> <h1 class="title">Ontology:&nbsp;<a href="javascript:showpanel('ontoinfo');">{{main_uri}}</a></h1>
<h3>{{ontology.bestDescription}}</h3> <h3>{{ontology.bestDescription}}</h3>
<p><small>Ontology documentation automatically generated by <a class="greylink" href="http://ontospy.readthedocs.org/">OntoSpy</a> on {% now "jS F Y H:i" %}</small></p> <p><small>Ontology documentation automatically generated by <a class="greylink" href="http://lambdamusic.github.io/Ontospy//">OntoSpy</a> on {% now "jS F Y H:i" %}</small></p>
<hr> <hr>
......
...@@ -162,7 +162,7 @@ circle.child:hover { ...@@ -162,7 +162,7 @@ circle.child:hover {
<h1 class="title">Ontology:&nbsp;<a href="javascript:showpanel('ontoinfo');">{{main_uri}}</a></h1> <h1 class="title">Ontology:&nbsp;<a href="javascript:showpanel('ontoinfo');">{{main_uri}}</a></h1>
<h3>{{ontology.bestDescription}}</h3> <h3>{{ontology.bestDescription}}</h3>
<p><small>Ontology documentation automatically generated by <a class="greylink" href="http://ontospy.readthedocs.org/">OntoSpy</a> on {% now "jS F Y H:i" %}</small></p> <p><small>Ontology documentation automatically generated by <a class="greylink" href="http://lambdamusic.github.io/Ontospy//">OntoSpy</a> on {% now "jS F Y H:i" %}</small></p>
<hr> <hr>
......
...@@ -140,7 +140,7 @@ text { ...@@ -140,7 +140,7 @@ text {
<h1 class="title">Ontology:&nbsp;<a href="javascript:showpanel('ontoinfo');">{{main_uri}}</a></h1> <h1 class="title">Ontology:&nbsp;<a href="javascript:showpanel('ontoinfo');">{{main_uri}}</a></h1>
<h3>{{ontology.bestDescription}}</h3> <h3>{{ontology.bestDescription}}</h3>
<p><small>Ontology documentation automatically generated by <a class="greylink" href="http://ontospy.readthedocs.org/">OntoSpy</a> on {% now "jS F Y H:i" %}</small></p> <p><small>Ontology documentation automatically generated by <a class="greylink" href="http://lambdamusic.github.io/Ontospy//">OntoSpy</a> on {% now "jS F Y H:i" %}</small></p>
<hr> <hr>
......
...@@ -91,7 +91,7 @@ circle.child:hover { ...@@ -91,7 +91,7 @@ circle.child:hover {
<h1 class="title">Ontology:&nbsp;<a href="javascript:showpanel('ontoinfo');">{{main_uri}}</a></h1> <h1 class="title">Ontology:&nbsp;<a href="javascript:showpanel('ontoinfo');">{{main_uri}}</a></h1>
<h3>{{ontology.bestDescription}}</h3> <h3>{{ontology.bestDescription}}</h3>
<p><small>Ontology documentation automatically generated by <a class="greylink" href="http://ontospy.readthedocs.org/">OntoSpy</a> on {% now "jS F Y H:i" %}</small></p> <p><small>Ontology documentation automatically generated by <a class="greylink" href="http://lambdamusic.github.io/Ontospy//">OntoSpy</a> on {% now "jS F Y H:i" %}</small></p>
<hr> <hr>
......
...@@ -56,7 +56,7 @@ ...@@ -56,7 +56,7 @@
<h1 class="title">Ontology:&nbsp;<a href="javascript:showpanel('ontoinfo');">{{main_uri}}</a></h1> <h1 class="title">Ontology:&nbsp;<a href="javascript:showpanel('ontoinfo');">{{main_uri}}</a></h1>
<h3>{{ontology.bestDescription}}</h3> <h3>{{ontology.bestDescription}}</h3>
<p><small>Ontology documentation automatically generated by <a class="greylink" href="http://ontospy.readthedocs.org/">OntoSpy</a> on {% now "jS F Y H:i" %}</small></p> <p><small>Ontology documentation automatically generated by <a class="greylink" href="http://lambdamusic.github.io/Ontospy//">OntoSpy</a> on {% now "jS F Y H:i" %}</small></p>
<hr> <hr>
......
...@@ -58,7 +58,7 @@ ...@@ -58,7 +58,7 @@
<h1 class="title">Ontology:&nbsp;<a href="javascript:showpanel('ontoinfo');">{{main_uri}}</a></h1> <h1 class="title">Ontology:&nbsp;<a href="javascript:showpanel('ontoinfo');">{{main_uri}}</a></h1>
<h3>{{ontology.bestDescription}}</h3> <h3>{{ontology.bestDescription}}</h3>
<p><small class="credits">Ontology documentation automatically generated with <a class="greylink" href="http://ontospy.readthedocs.org/" target="_blank">OntoSpy</a> on {% now "jS F Y H:i" %}</small></p> <p><small class="credits">Ontology documentation automatically generated with <a class="greylink" href="http://lambdamusic.github.io/Ontospy//" target="_blank">OntoSpy</a> on {% now "jS F Y H:i" %}</small></p>
......
### How To add a new viz ### How To add a new viz
- add .py file named as 'viz_%s' - add .py file named as 'viz\_%s'
- add .html templates (if in new folder, updated also settings.TEMPLATES in builder.py) - add .html templates (if in new folder, updated also settings.TEMPLATES in builder.py)
- update catalogue in `CONFIG.py` - update catalogue in `CONFIG.py`
### Testing locally
### Testing locally - `python -m ontospy.ontodocs.viz.viz_d3barHierarchy` picks a random ontology and runs the script
- ```python -m ontodocs.viz.viz_d3barHierarchy``` picks a random ontology and runs the script
\ No newline at end of file
...@@ -13,7 +13,7 @@ from ..viz_factory import VizFactory ...@@ -13,7 +13,7 @@ from ..viz_factory import VizFactory
# =========== # ===========
class D3BarHierarchyViz(VizFactory): class Dataviz(VizFactory):
""" """
D3 Bar HierarchyViz D3 Bar HierarchyViz
...@@ -23,7 +23,7 @@ class D3BarHierarchyViz(VizFactory): ...@@ -23,7 +23,7 @@ class D3BarHierarchyViz(VizFactory):
""" """
Init Init
""" """
super(D3BarHierarchyViz, self).__init__(ontospy_graph, title) super(Dataviz, self).__init__(ontospy_graph, title)
self.static_files = ["libs/d3-v3", "libs/jquery"] self.static_files = ["libs/d3-v3", "libs/jquery"]
def _buildTemplates(self): def _buildTemplates(self):
...@@ -64,7 +64,7 @@ if __name__ == '__main__': ...@@ -64,7 +64,7 @@ if __name__ == '__main__':
g = get_onto_for_testing(TEST_ONLINE) g = get_onto_for_testing(TEST_ONLINE)
v = D3BarHierarchyViz(g, title="") v = Dataviz(g, title="")
v.build() v.build()
v.preview() v.preview()
......
...@@ -13,7 +13,7 @@ from ..viz_factory import VizFactory ...@@ -13,7 +13,7 @@ from ..viz_factory import VizFactory
# =========== # ===========
class D3BubbleChartViz(VizFactory): class Dataviz(VizFactory):
""" """
D3 Bubbles D3 Bubbles
...@@ -23,7 +23,7 @@ class D3BubbleChartViz(VizFactory): ...@@ -23,7 +23,7 @@ class D3BubbleChartViz(VizFactory):
""" """
Init Init
""" """
super(D3BubbleChartViz, self).__init__(ontospy_graph, title) super(Dataviz, self).__init__(ontospy_graph, title)
self.static_files = ["libs/d3-v3", "libs/jquery"] self.static_files = ["libs/d3-v3", "libs/jquery"]
def _buildTemplates(self): def _buildTemplates(self):
...@@ -64,7 +64,7 @@ if __name__ == '__main__': ...@@ -64,7 +64,7 @@ if __name__ == '__main__':
g = get_onto_for_testing(TEST_ONLINE) g = get_onto_for_testing(TEST_ONLINE)
v = D3BubbleChartViz(g, title="")