22import jpype .imports
33import networkx as nx
44
5+ import inspect
6+ from tqdm import tqdm
7+ from functools import lru_cache
58# Starting the JVM
69from gephipy import jvm
7- jvm .start ()
10+
11+ if not jpype .isJVMStarted ():
12+ jvm .start ()
813
914# Java import
1015from java .io import File
1419from org .gephi .io .processor .plugin import DefaultProcessor
1520from org .gephi .io .exporter .api import ExportController
1621from 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