Skip to content

Commit 88ada15

Browse files
author
Matthieu Totet
committed
Layout class that aim to ease layout usage
1 parent 0668d07 commit 88ada15

File tree

1 file changed

+85
-2
lines changed

1 file changed

+85
-2
lines changed

gephipy/gephipy.py

Lines changed: 85 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,14 @@
22
import jpype.imports
33
import networkx as nx
44

5+
import inspect
6+
from tqdm import tqdm
7+
from functools import lru_cache
58
# Starting the JVM
69
from gephipy import jvm
7-
jvm.start()
10+
11+
if not jpype.isJVMStarted():
12+
jvm.start()
813

914
# Java import
1015
from java.io import File
@@ -14,6 +19,8 @@
1419
from org.gephi.io.processor.plugin import DefaultProcessor
1520
from org.gephi.io.exporter.api import ExportController
1621
from org.gephi.io.importer.api import ImportController, EdgeDirectionDefault
22+
from org.gephi.layout.spi import LayoutBuilder
23+
from typing import Union
1724

1825
#
1926
# Create a new Gephi workspace
@@ -122,4 +129,80 @@ def export_png(workspace, file_path="./graph.png"):
122129
export = Lookup.getDefault().lookup(ExportController)
123130
png = export.getExporter("png")
124131
png.setWorkspace(workspace)
125-
export.exportFile(File(file_path), png)
132+
export.exportFile(File(file_path), png)
133+
134+
@lru_cache(1)
135+
def get_available_layouts():
136+
"""
137+
Dictonary of available Layout
138+
"""
139+
return {str(layout.getName()):layout for layout in Lookup.getDefault().lookupAll(LayoutBuilder)}
140+
141+
# Context Class to ease Layout usage
142+
class Layout:
143+
class _LayoutInstance():
144+
"""
145+
Internal Layout Class that offers run() or pass the method call to the underlying
146+
class instance
147+
"""
148+
def __init__(self,instance,log_progress:bool):
149+
self.instance = instance
150+
self.log_progress = log_progress
151+
152+
153+
@lru_cache(1)
154+
def _inspect(self):
155+
"""
156+
Inspect utils tool to fetch existing method for the class
157+
"""
158+
return dict(inspect.getmembers(self.instance))
159+
160+
def run(self, step=1):
161+
"""
162+
Perform a run of the layout within given steps.
163+
It's a pure wrapper function to ease usage of Layout.
164+
"""
165+
166+
loop = range(step)
167+
168+
if self.log_progress: # Could be useful, especially for jupyter folks to keep track of the algo status
169+
loop = tqdm(loop,desc=f"Running {self.instance}")
170+
for _ in loop:
171+
if self.instance.canAlgo():
172+
self.instance.goAlgo()
173+
else:
174+
break
175+
176+
def __getattr__(self, name: str):
177+
"""
178+
If other attributes or method are call, passing the invokation to underlying instance
179+
"""
180+
return self._inspect()[name]
181+
182+
def __init__(self,layout:Union[jpype.JClass, str], graphModel, log_progress=False):
183+
"""
184+
When creating the object
185+
"""
186+
if isinstance(layout,str):
187+
available_layouts = get_available_layouts()
188+
_layout = available_layouts.get(layout)
189+
if _layout is None:
190+
raise Exception(f"Invalid Layout name {layout}, available layout are : {', '.join(available_layouts.keys())} ")
191+
else:
192+
_layout = layout
193+
self.layout_instance = Layout._LayoutInstance(_layout.buildLayout(), log_progress)
194+
self.layout_instance.setGraphModel(graphModel)
195+
196+
def __enter__(self):
197+
"""
198+
Entering the context (with ... as ...)
199+
"""
200+
self.layout_instance.resetPropertiesValues()
201+
self.layout_instance.initAlgo()
202+
return self.layout_instance
203+
204+
def __exit__(self,tp,e,traceback):
205+
"""
206+
Exiting context
207+
"""
208+
self.layout_instance.endAlgo()

0 commit comments

Comments
 (0)