Overview
The following document describes a general architecture for Cytoscape that uses OSGi. Subsequent sections describe the primary interfaces of the new Cytoscape API, the primary services made available by Cytoscape, and the interfaces to services that Cytoscape will expect plugins to implement. We then describe the overall organization of the bundles that will comprise the application. The primary "action" in cytoscape will be an Algorithm, which we describe in some detail. In addition we describe how the user interface might interact with these Algorithms in a manner that separates the action from the user interface implementation. Finally, we list current actions and categorize them based on relationship to the user interface.
Sample Code
We've built a sample version of Cytoscape that consists of OSGi compatible bundles and runs on OSGi. The source code is available here:
We've also built a sample plugin that is an OSGi bundle that uses OSGi's service registry to make itself available to Cytoscape. This code provides the ability to read SBML files.
Cytoscape PUBLIC API
The core network and network view interfaces. We should consider rolling groups into network/view.
org.cytoscape.network.CyNetwork
org.cytoscape.network.CyNode
org.cytoscape.network.CyEdge
org.cytoscape.network.CyNetworkView
org.cytoscape.network.CyNodeView
org.cytoscape.network.CyEdgeView
org.cytoscape.network.CyGroup
org.cytoscape.network.CyGroupView
The core attribute interface.
org.cytoscape.attributes.CyAttributes
Interfaces for writing various types to data. Session writing will not be provided as a service since on the internal core will ever write a session.
org.cytoscape.io.export.CyNetworkWriter
org.cytoscape.io.export.CyAttributesWriter
org.cytoscape.io.export.GraphicsWriter
Interfaces for reading various types of data along with file filters that can be used to define how files get read.
org.cytoscape.io.import.CyNetworkFileFilter
org.cytoscape.io.import.CyNetworkReader
org.cytoscape.io.import.CyAttributesReader
org.cytoscape.io.import.CyAttributesFileFilter
The interfaces used for defining general actions in Cytoscape. Algorithms are strictly separated from any sort of UI. The interfaces defining the user interface. Tunable objects are the primary mechanism for communicating data between Algorithms and the UI. If an Algorithm wants to be present in the UI, then it must provide its own SwingFactory. Eventually we'll have interfaces for things like CommandLineFactory (we could perhaps infer this automatically) or AJAXFactory.
- org.cytoscape.algorithm.ui.UI
- org.cytoscape.algorithm.ui.SwingUI
- org.cytoscape.algorithm.ui.UIFactory
- org.cytoscape.algorithm.control.Tunable
org.cytoscape.algorithm.control.TunableType
org.cytoscape.algorithm.control.InteractionController
- org.cytoscape.algorithm.control.Constraint
org.cytoscape.algorithm.AlgorithmStatus
- org.cytoscape.algorithm.Algorithm
org.cytoscape.algorithm.AlgorithmFactory
org.cytoscape.algorithm.InteractiveAlgorithm
The interface for defining a web service client.
org.cytoscape.webservice.WebServiceClient
The (substantially simplified) interfaces for defining visual styles.
org.cytoscape.vizmap.VisualStyle
- org.cytoscape.vizmap.Calculator
- org.cytoscape.vizmap.Mapping
org.cytoscape.vizmap.VisualPropertyType
The service interfaces for Cytoscape. These interfaces represent much of the functionality that is currently included in Cytoscape.java as static methods. These services will be implemented by cytoscape.
org.cytoscape.service.network.CyNetworkViewManager
org.cytoscape.service.network.CyNetworkManager
org.cytoscape.service.attributes.CyAttributesManager
org.cytoscape.service.session.SessionManager
org.cytoscape.service.ontology.OntologyManager
org.cytoscape.service.bookmark.BookmarkManager
org.cytoscape.service.proxy.ProxyManager
Plugin Implemented Services
The general mechanism for plugins to provide services to the rest of Cytoscape is to implement a public Cytoscape interface and register that object as a service with OSGi's service registry. The primary example of this is the Algorithm/AlgorithmFactory interface. Another example is the CyNetworkFileFilter.
Here is some example plugin code that would provide an SBML reader:
package sbmlreader; import org.cytoscape.io.import.CyNetworkFileFilter; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleActivator; import org.osgi.framework.ServiceReference; import org.osgi.framework.ServiceRegistration; import java.util.Hashtable; public class SBMLReaderPlugin implements BundleActivator { private ServiceRegistration filterReg; public void start(BundleContext bc) { // defin the service metadata Hashtable metadata = new Hashtable(); metadata.put("file.extensions",".sbml,.xml"); metadata.put("description","SBML files"); metadata.put("service.pid",SBMLFilter.class.getName()); // just an interface, implementation of interface, metadata filterReg = bc.registerService(CyNetworkFileFilter.class.getName(), new SBMLFilter(), metadata); } public void stop(BundleContext bc) { filterReg.unregister(); } }
Here is code that would exist in the Cytoscape core, consume services that have been registered as implementing CyNetworkFileFilter. Since SBMLReaderPlugin has done this, it will be found and used within the core normally.
package cytoscape; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; import org.cytoscape.io.import.CyNetworkFileFilter; public class ServiceHandler { private BundleContext bc; // perhaps called at startup or some other time public ServiceHandler(BundleContext bc) { this.bc = bc; registerCyFileFilters(); } public void registerCyFileFilters() { try { ServiceReference[] sr = bc.getServiceReferences(CyNetworkFileFilter.class.getName(), null); for (ServiceReference r : sr ) { CyNetworkFileFilter filter = (CyNetworkFileFilter)bc.getService(r)); // do something with filter } } catch (Exception e) { e.printStackTrace(); } }
CORE Bundle Organization
- Each service described above will consist of a small number of interfaces. All service interfaces will be part of a single framework bundle.
- Each service implementation will (probably) have a separate bundle. This isn't necessary, but some organization is a good idea.
- There will be an initialization bundle that will handle starting and stopping all of the core services defined in the framework.
- The GUI will consist of separate bundles.
- Each service will (for the most part) have an associated GUI bundle.
Plugin Bundle Organization
- Most plugins will provide a single bundle that includes an Algorithm (model) component and a GUI (view) component.
- For large/complicated plugins, it is recommend that these be in separate bundles.
- Multiple algorithms can be included in the same bundle.
- Plugins can provide libraries as separate bundles.
- We will need to have bundles of bundles (i.e. themes in cytoscape or features in Eclipse) to that users can request a single feature and not be concerned with loading all necessary bundles.
Consider using OSGi Bundle Repository (OBR) to create feature bundles. This also allows for federated bundle repositories.
Algorithms
Algorithms can implement additional interfaces, e.g. ProgressTrackable, which would mean a progress monitor could be added.
CIShell does all of this now.
Workflow
JMenu Context
Menu is created with menu items that are connected to GUI services. The GUI services are associated with Algorithms via thier metadata (i.e. the algorithm.service.pid).
The menu item does not actually load the GUI service, it merely keeps a reference to it. The GUI service is only actually retrieved when the menu item is clicked.
- Click Top-level menu
- Check algorithm meta data to see if menu item should be enabled. For example, if a "requiresNetwork=true" attribute is found, then the menu item should only be enabled if a network has actually been loaded into cytoscape.
- Click menu item.
- Menu item creates a GUIController object that connects the Algorithm and the GUI.
- The GUI queries the GUIController to get the Algorithm Tunables.
- The GUI returns a JPanel that is inserted (by Cytoscape) into a Tab or Dialog depending on the GUI metadata.
- User does stuff to the GUI setting the various Tunables.
- Some user interaction (i.e. click OK) indicates that the algorithm should be run.
The GUI service calls GUIController.trigger(List<Tunables>) where the list of tunables are those needed to run the algorithm.
GUIController, at its leisure, calls AlgorithmFactory.createAlgorithm(List<Tunable>) which instantiates an Algorithm with the proper parameters.
- The algorithm is executed via the execute() method.
- GUI Service calls GUIController.close() when it is finished.
WARNING This scheme currently does not support the case where the Algorithm interacts with the GUI, i.e. returns a result to the GUI.
Scripting
This Algorithm model is separated from the GUI so that it can be easily used in a scripting context (i.e headless mode).
Event Handling
OSGi provides a basic event handling service. We could consider using this service.
Visual Styles Refactoring
A VisualStyle consists of a NodeAppearanceCalculator, EdgeAppearanceCalculator, and GlobalAppearanceCalculator.
NodeAppearanceCalculators and EdgeAppearanceCalculators consist of lists of Calculator objects. Each calculator has a specific VisualPropertyType. Only one Calculator of a given VisualPropertyType is allowed in either NodeAppearanceCalculators or EdgeAppearanceCalculators.
Possible Improvements for VisualStyles
Get rid of the NodeAppearance and EdgeAppearance objects. Instead, operate directly on CyNodeView and CyEdgeView.
Get rid of NodeAppearanceCalculator and EdgeAppearanceCalculator and just let VisualStyle keep a list of the individual Calculators.
Make GlobalAppearanceCalculator based on VisualPropertyType. Perhaps with dummy calculators?
Re-enable applyVisualStyle to CyNetworkView instead of applying the visual style in the VisualMappingManager. This would have the advantage of allowing different implementations of views to handle different visual properties as they deem appropriate.
The Calculator objects must to be reworked to fetch attributes from CyAttributes rather than operating on their own attribute bundle model. The attribute in question should be an argument to the Calculator.
Consider getting rid of CalculatorCatalog. Calculators are small objects and there won't be that many of them any way.
- Perhaps consolidate Mapping and Calculator since Calculator really just passes a mapping value through to an Appearance.
UI Services
The Cytoscape GUI will look for GUI services. Each GUI service will have (among other things) two key pieces of information in its metadata. The first will be a location where the GUI Services JPanel can be placed. Some possible locations are:
- Control Tab
- Results Tab
- Data Tab
- Dialog
The second piece of metadata will be an action style which indicates whether the GUI Service will be instantiated from a menu item or a toolbar button. Some possible action styles are:
- menu item
- toolbar button
The GUI service should also be able to use the Algorithm metadata to further define its functionality.
Possible GUI Service MetaData
- preferred.menu
- preferred.location
- preferred.action.style
- label
- description
- service.pid
- hot.keys
- preferred.icon
Possible Algorithm MetaData
- requires.network
- requires.network.view
- requires.selected.nodes
- requires.selected.edges
Current Cytoscape Actions
SHOULD be gui independent
ExportAction.java
- ExportAsGMLAction.java
- ExportAsXGMMLAction.java
ExportVizmapAction.java
ExitAction.java
CloneGraphInNewWindowAction.java // misnamed
DeselectAllAction.java
DestroyNetworkAction.java
NewWindowSelectedNodesEdgesAction.java // new NETWORK from selected
NewWindowSelectedNodesOnlyAction.java // new NETWORK from selected
ImportVizmapAction.java
NewSessionAction.java
OpenSessionAction.java
ProxyServerAction.java
SaveSessionAction.java
SaveSessionAsAction.java
pops up dialog
MapOntologyAction.java
PluginManagerAction.java
PluginUpdateAction.java
PreferenceAction.java
PrintAction.java
HelpAboutAction.java
HelpContentsAction.java
BookmarkAction.java
gui specific view manipulation
FitContentAction.java
HideSelectedAction.java
AlignVerticalAction.java
SelectAllAction.java
SelectAllEdgesAction.java
SelectAllNodesAction.java
ShowAllAction.java
UnHideSelectedAction.java
ZoomAction.java
ZoomSelectedAction.java
gui specific state
SelectionModeAction.java
CytoPanelAction.java // pops up a cytopanel and takes a cyto panel type as arg
BirdsEyeViewAction.java