gephi / gephi-plugins

Repository for Gephi Plugins maintained by the team. Each plugin has it's branch.
270 stars 623 forks source link

Filter API #108

Closed jbliesener closed 2 years ago

jbliesener commented 8 years ago

OK, risking to be named the troll of the day for submitting the third issue today.

Now, this is really special. I was working with a self-developed filter-plugin in Gephi 0.8.2 that, in order to perform the desired operation had to "clone" edges and change their attributes. So, the filtered graph contained some edges that were different from the original graph.

For example, my graph model had two columns that could act as a weight and I had a filter that copied the values from one of these columns into the weight column of the filtered graph. So, I "cloned" the edge with some code like:

    public Edge cloneEdge(GraphFactory fact, Graph graph, Edge e) {
        Edge newEdge = fact.newEdge(e.getEdgeData().getId(), e.getSource(), e.getTarget(), 1, false);
        AttributeRow newAt = (AttributeRow) newEdge.getAttributes();
        AttributeRow a = (AttributeRow) e.getAttributes();
        AttributeValue[] oldValues = ((AttributeRow) a).getValues();
        for (AttributeValue av : oldValues) {
            newAt.setValue(av);
        } 
        return newEdge;
    }

...

    @Override
    public Graph filter(Graph graph) {

        GraphFactory fact = graph.getGraphModel().factory();
        for (Edge e : graph.getEdges().toArray()) {

            Attributes a = e.getAttributes();
            Float weight1 = (Float) a.getValue(EDGE_ATTR_WEIGHT1);
            Float weight2 = (Float) a.getValue(EDGE_ATTR_WEIGHT2);

            graph.removeEdge(e);
            Edge newEdge = cloneEdge(fact, graph, e);

            if (weight2 != null) {
                newEdge.setWeight(weight2);
            } else {
                newEdge.setWeight(weight1);
            }

            graph.addEdge(newEdge);
        }
        return graph;
    }

That approach doesn't work anymore with the new Graphstore, which requires me to put every edge into the original graph and allows only real filtering (eliminating nodes and edges).

While I completely understand the issue and reasons (at last, it's called FILTERING, so it should FILTER instead of MANIPULATE), the rich user interface that allows nested filters, filter parameters (even ranges), and interactive changes on these parameters is not available in any other Gephi module.

So, I'm looking for a way to implement that feature (yes, I admit it was a hack, but it worked flawlessly) in Gephi 0.9.

It already would help if, apart from the "filter" function on ComplexFilters I also had an "unfilter" function that would be called on undoing (clearing) the filter. That would allow me to undo the changes applied by my "manipulating" filter.

Or is there any other way that allows me to use the filter UI to create a subgraph that has some attributes and properties that are DIFFERENT from the original graph?

I don't want to finish this issue without my highest appreciations for what you guys have developed. Gephi really makes a difference in my work and I won't stop recommending it. Great work!

mbastian commented 2 years ago

Hi @jbliesener, and sorry for taking so long. I'm finally up to the task to cleanup all the issues over here on gephi-plugins...

First, the Filters API is quite old and not to our current standards. It probably would need a cleanup at some point so even though we might not have a good solution now it's always good to hear new use-cases for future API improvements. Just wanted to share this context for you, who take time to report issues and suggestions (I appreciate it).

Now to your problem :) GraphStore has a handy GraphBridge utility class that can essentially clone your graph in one command. It's what we use under the hood when nodes are copied from one workspace to the other. With this, you could maybe create that subgraph and manipulate it within your filter, and destroy it at the end.