diff --git a/manifest.mf b/manifest.mf index bd68f3e..b714736 100644 --- a/manifest.mf +++ b/manifest.mf @@ -2,5 +2,5 @@ Manifest-Version: 1.0 OpenIDE-Module: cz.cvut.fit.gephi.multimode OpenIDE-Module-Localizing-Bundle: cz/cvut/fit/gephi/multimode/Bundle.properties OpenIDE-Module-Requires: org.openide.windows.WindowManager -OpenIDE-Module-Specification-Version: 0.1.2 +OpenIDE-Module-Specification-Version: 0.1.3 diff --git a/src/cz/cvut/fit/gephi/multimode/Bundle.properties b/src/cz/cvut/fit/gephi/multimode/Bundle.properties index 6c5fd16..e02981b 100644 --- a/src/cz/cvut/fit/gephi/multimode/Bundle.properties +++ b/src/cz/cvut/fit/gephi/multimode/Bundle.properties @@ -3,7 +3,8 @@ OpenIDE-Module-Long-Description=\ This plugin allows multimode networks projection. \ You can project your bipartite (2-mode) graph to monopartite (one-mode) graph. \ The projection/transformation is based on the matrix multiplication approach and allows different types of transformations. \ - The limitation is matrix multiplication - large matrix multiplication takes time and memory. + The limitation is matrix multiplication - large matrix multiplication takes time and memory.\n\ + Threshold to limit the number of generated edges and option to convert directed graphs to undirected has been added\nThe weights are taken into account OpenIDE-Module-Name=MultimodeNetworksTransformationPlugin OpenIDE-Module-Short-Description=Multimode Networks Transformations MultiModeWindowTopComponent.attributes.toolTipText=Attribute column which represents node type. @@ -20,3 +21,6 @@ MultiModeWindowTopComponent.removeNodes.toolTipText=Remove affected Nodes MultiModeWindowTopComponent.load.text=Load attributes MultiModeWindowTopComponent.graphColoring.text=Graph Coloring MultiModeWindowTopComponent.bipartiteLabel.text=Bipartite: ? +MultiModeWindowTopComponent.jLabel1.text=Threshold +MultiModeWindowTopComponent.threshold.text=0.0 +MultiModeWindowTopComponent.directed.text=directed diff --git a/src/cz/cvut/fit/gephi/multimode/LongTaskTransformation.java b/src/cz/cvut/fit/gephi/multimode/LongTaskTransformation.java index 5e4013f..89ebb40 100644 --- a/src/cz/cvut/fit/gephi/multimode/LongTaskTransformation.java +++ b/src/cz/cvut/fit/gephi/multimode/LongTaskTransformation.java @@ -25,14 +25,19 @@ public class LongTaskTransformation implements LongTask, Runnable { private String outDimension; private boolean removeEdges = true; private boolean removeNodes = true; + private boolean directed=false; + private boolean considerDirected=false; + private double threshold=0.0; - public LongTaskTransformation(AttributeColumn attributeColumn, String inDimension, String commonDimension, String outDimension, boolean removeEdges, boolean removeNodes) { + public LongTaskTransformation(AttributeColumn attributeColumn, String inDimension, String commonDimension, String outDimension,double threshold, boolean removeEdges, boolean removeNodes, boolean considerDirected) { this.attributeColumn = attributeColumn; this.inDimension = inDimension; this.commonDimension = commonDimension; this.outDimension = outDimension; this.removeEdges = removeEdges; this.removeNodes = removeNodes; + this.considerDirected=considerDirected; + this.threshold=threshold; } @Override @@ -43,8 +48,14 @@ public void run() { // graph GraphController graphController = Lookup.getDefault().lookup(GraphController.class); GraphModel graphModel = graphController.getModel(); - Graph graph = graphModel.getGraphVisible(); - //Graph graph = graphModel.getUndirectedGraphVisible(); + Graph graph; + if (considerDirected){ + graph = graphModel.getGraphVisible(); + directed=graphModel.isDirected(); + } else { + graph = graphModel.getUndirectedGraphVisible(); + directed=false; + } Node[] nodes = graph.getNodes().toArray(); // matrix axis @@ -72,11 +83,12 @@ public void run() { secondHorizontal.add(n); } } - + Progress.start(progressTicket, firstVertical.size()+5); + if (cancelled) { return; } - Progress.progress(progressTicket); + Progress.progress(progressTicket,1); // first matrix Matrix firstMatrix = new Matrix(firstVertical.size(), firstHorizontal.size()); @@ -86,9 +98,15 @@ public void run() { try { intersection.retainAll(firstHorizontal); for (Node neighbour : intersection) { - firstMatrix.set(i, firstHorizontal.indexOf(neighbour), 1); + int j=firstHorizontal.indexOf(neighbour); + if (j > -1){ + Edge edge = graph.getEdge(firstVertical.get(i), firstHorizontal.get(j)); + if (edge!= null) { + float w=edge.getWeight(); + firstMatrix.set(i, j, w); + } } - } catch (UnsupportedOperationException ex) { + }} catch (UnsupportedOperationException ex) { System.out.println("exception"); // TODO - exception handler } @@ -102,9 +120,16 @@ public void run() { if (intersection != null && intersection.size() > 0) { try { intersection.retainAll(secondHorizontal); - for (Node neighbour : intersection) { - secondMatrix.set(i, secondHorizontal.indexOf(neighbour), 1); - } + for (Node neighbour : intersection) { + int j=secondHorizontal.indexOf(neighbour); + if (j>-1){ + Edge edge =graph.getEdge(secondVertical.get(i), secondHorizontal.get(j)); + if (edge!= null) { + float w=edge.getWeight(); + secondMatrix.set(i, j, w); + } + } + } } catch (UnsupportedOperationException ex) { System.out.println("exception"); // TODO - exception handler @@ -114,13 +139,13 @@ public void run() { if (cancelled) { return; } - Progress.progress(progressTicket, "Multiplication"); + Progress.progress(progressTicket, "Multiplication",2); Matrix result = firstMatrix.timesParallelIndexed(secondMatrix); if (cancelled) { return; } - Progress.progress(progressTicket, "Removing nodes/edges"); + Progress.progress(progressTicket, "Removing nodes/edges",3); if (removeNodes) { @@ -150,7 +175,7 @@ public void run() { if (cancelled) { return; } - Progress.progress(progressTicket, "Creating new edges"); + Progress.progress(progressTicket, "Creating new edges",4); AttributeController ac = Lookup.getDefault().lookup(AttributeController.class); AttributeModel model = ac.getModel(); AttributeColumn edgeTypeCol = model.getEdgeTable().getColumn("MMNT-EdgeType"); @@ -162,8 +187,8 @@ public void run() { Edge ee = null; for (int i = 0; i < result.getM(); i++) { for (int j = 0; j < result.getN(); j++) { - if (graph.contains(firstVertical.get(i)) && graph.contains(secondHorizontal.get(j)) && graph.getEdge(firstVertical.get(i), secondHorizontal.get(j)) == null && result.get(i, j) > 0) { - ee = graphModel.factory().newEdge(firstVertical.get(i), secondHorizontal.get(j), (float) result.get(i, j), graphModel.isDirected()); + if (graph.contains(firstVertical.get(i)) && graph.contains(secondHorizontal.get(j)) && graph.getEdge(firstVertical.get(i), secondHorizontal.get(j)) == null && result.get(i, j) > threshold) { + ee = graphModel.factory().newEdge(firstVertical.get(i), secondHorizontal.get(j), (float) result.get(i, j),this.directed ); if (!ee.isSelfLoop()) { ee.getEdgeData().getAttributes().setValue(edgeTypeCol.getIndex(), inDimension + "<--->" + outDimension); //ee.getEdgeData().setLabel(inDimension + "-" + outDimension); @@ -171,6 +196,10 @@ public void run() { } } } + if (cancelled) { + return; + } + Progress.progress (progressTicket,i+5); } Progress.finish(progressTicket); } diff --git a/src/cz/cvut/fit/gephi/multimode/MultiModeWindowTopComponent.form b/src/cz/cvut/fit/gephi/multimode/MultiModeWindowTopComponent.form index 6399ee9..06c13d4 100644 --- a/src/cz/cvut/fit/gephi/multimode/MultiModeWindowTopComponent.form +++ b/src/cz/cvut/fit/gephi/multimode/MultiModeWindowTopComponent.form @@ -19,37 +19,45 @@ - + - - + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - + + - - + + - - + + @@ -86,9 +94,20 @@ - - - + + + + + + + + + + + + + + @@ -98,7 +117,7 @@ - + @@ -215,5 +234,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/cz/cvut/fit/gephi/multimode/MultiModeWindowTopComponent.java b/src/cz/cvut/fit/gephi/multimode/MultiModeWindowTopComponent.java index e8d67e2..3b30383 100644 --- a/src/cz/cvut/fit/gephi/multimode/MultiModeWindowTopComponent.java +++ b/src/cz/cvut/fit/gephi/multimode/MultiModeWindowTopComponent.java @@ -1,8 +1,10 @@ package cz.cvut.fit.gephi.multimode; +import java.text.ParseException; import java.util.HashSet; import java.util.Set; import javax.swing.JOptionPane; +import javax.swing.text.MaskFormatter; import org.gephi.data.attributes.api.AttributeColumn; import org.gephi.data.attributes.api.AttributeController; import org.gephi.data.attributes.api.AttributeModel; @@ -13,6 +15,7 @@ import org.netbeans.api.settings.ConvertAsProperties; import org.openide.awt.ActionID; import org.openide.awt.ActionReference; +import org.openide.util.Exceptions; import org.openide.util.Lookup; import org.openide.util.NbBundle.Messages; import org.openide.windows.TopComponent; @@ -70,6 +73,9 @@ private void initComponents() { jSeparator1 = new javax.swing.JSeparator(); graphColoring = new javax.swing.JButton(); bipartiteLabel = new javax.swing.JLabel(); + directed = new javax.swing.JCheckBox(); + jLabel1 = new javax.swing.JLabel(); + threshold = new javax.swing.JTextField(); attributes.setToolTipText(org.openide.util.NbBundle.getMessage(MultiModeWindowTopComponent.class, "MultiModeWindowTopComponent.attributes.toolTipText")); // NOI18N attributes.setEnabled(false); @@ -126,6 +132,22 @@ public void actionPerformed(java.awt.event.ActionEvent evt) { org.openide.awt.Mnemonics.setLocalizedText(bipartiteLabel, org.openide.util.NbBundle.getMessage(MultiModeWindowTopComponent.class, "MultiModeWindowTopComponent.bipartiteLabel.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(directed, org.openide.util.NbBundle.getMessage(MultiModeWindowTopComponent.class, "MultiModeWindowTopComponent.directed.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(MultiModeWindowTopComponent.class, "MultiModeWindowTopComponent.jLabel1.text")); // NOI18N + + threshold.setText(org.openide.util.NbBundle.getMessage(MultiModeWindowTopComponent.class, "MultiModeWindowTopComponent.threshold.text")); // NOI18N + threshold.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + thresholdActionPerformed(evt); + } + }); + threshold.addFocusListener(new java.awt.event.FocusAdapter() { + public void focusLost(java.awt.event.FocusEvent evt) { + thresholdFocusLost(evt); + } + }); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( @@ -133,28 +155,35 @@ public void actionPerformed(java.awt.event.ActionEvent evt) { .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(removeNodes) - .addComponent(removeEdges)) - .addGap(0, 0, Short.MAX_VALUE)) + .addComponent(attributeLabel) + .addComponent(leftlabel) + .addComponent(rightLabel)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(secondMatrix, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(firstMatrix, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(attributes, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) + .addComponent(jSeparator1, javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(layout.createSequentialGroup() + .addGap(0, 0, Short.MAX_VALUE) + .addComponent(start) + .addGap(172, 172, 172)) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(removeEdges) + .addComponent(removeNodes)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 66, Short.MAX_VALUE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(attributeLabel) - .addComponent(leftlabel) - .addComponent(rightLabel)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(secondMatrix, 0, 191, Short.MAX_VALUE) - .addComponent(firstMatrix, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(attributes, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) + .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 83, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(1, 1, 1)) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addGap(0, 0, Short.MAX_VALUE) - .addComponent(start)) - .addComponent(jSeparator1, javax.swing.GroupLayout.Alignment.TRAILING)) - .addContainerGap()))) + .addComponent(directed) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED))) + .addComponent(threshold, javax.swing.GroupLayout.PREFERRED_SIZE, 71, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addContainerGap()) .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(load) @@ -183,9 +212,16 @@ public void actionPerformed(java.awt.event.ActionEvent evt) { .addComponent(secondMatrix, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(rightLabel)) .addGap(18, 18, 18) - .addComponent(removeEdges) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(removeNodes) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(removeEdges) + .addComponent(directed)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(removeNodes) + .addComponent(jLabel1))) + .addComponent(threshold, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(start) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) @@ -194,7 +230,7 @@ public void actionPerformed(java.awt.event.ActionEvent evt) { .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(graphColoring) .addComponent(bipartiteLabel)) - .addContainerGap(60, Short.MAX_VALUE)) + .addContainerGap(87, Short.MAX_VALUE)) ); }// //GEN-END:initComponents @@ -270,7 +306,13 @@ private void firstMatrixActionPerformed(java.awt.event.ActionEvent evt) {//GEN-F private void startActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_startActionPerformed LongTaskExecutor executor = new LongTaskExecutor(true); - LongTaskTransformation longTask = new LongTaskTransformation((AttributeColumn) attributes.getSelectedItem(), ((ValueCombination) firstMatrix.getSelectedItem()).getFirst(), ((ValueCombination) firstMatrix.getSelectedItem()).getSecond(), ((ValueCombination) secondMatrix.getSelectedItem()).getSecond(), removeEdges.isSelected(), removeNodes.isSelected()); + LongTaskTransformation longTask = new LongTaskTransformation( + (AttributeColumn) attributes.getSelectedItem(), + ((ValueCombination) firstMatrix.getSelectedItem()).getFirst(), + ((ValueCombination) firstMatrix.getSelectedItem()).getSecond(), + ((ValueCombination) secondMatrix.getSelectedItem()).getSecond(), + Float.parseFloat(threshold.getText()), + removeEdges.isSelected(), removeNodes.isSelected(),directed.isSelected()); executor.execute(longTask, longTask, "Transformation...", null); if (attributes.getItemCount() > 0 && (removeEdges.isSelected() || removeNodes.isSelected())) { @@ -300,12 +342,29 @@ private void graphColoringActionPerformed(java.awt.event.ActionEvent evt) {//GEN boolean bipartite = gc.bipartite(); bipartiteLabel.setText("Bipartite: " + bipartite); }//GEN-LAST:event_graphColoringActionPerformed + + private void thresholdActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_thresholdActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_thresholdActionPerformed + + private void thresholdFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_thresholdFocusLost + float f; + try { + f=Float.parseFloat(threshold.getText()); + } + catch (Exception e){ + threshold.setText("0.0"); + } + }//GEN-LAST:event_thresholdFocusLost + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JLabel attributeLabel; private javax.swing.JComboBox attributes; private javax.swing.JLabel bipartiteLabel; + private javax.swing.JCheckBox directed; private javax.swing.JComboBox firstMatrix; private javax.swing.JButton graphColoring; + private javax.swing.JLabel jLabel1; private javax.swing.JSeparator jSeparator1; private javax.swing.JLabel leftlabel; private javax.swing.JButton load; @@ -314,6 +373,7 @@ private void graphColoringActionPerformed(java.awt.event.ActionEvent evt) {//GEN private javax.swing.JLabel rightLabel; private javax.swing.JComboBox secondMatrix; private javax.swing.JButton start; + private javax.swing.JTextField threshold; // End of variables declaration//GEN-END:variables @Override