0

-------- companytrades.csv --------

date,Company1,Company2
1/2/2017,1001,1111
1/3/2017,1001,1100
1/4/2017,1111,1001
1/5/2017,1100,1001
1/6/2017,1011,1001
1/7/2017,1001,1111
1/8/2017,1111,1100
1/9/2017,1100,1011

I found this great example of a set of classes implementing a networkx into a graphicsscene GraphNetworkX.py

Node.py

Edge.py

I am using the following code to implement these three modules

--------- netxgui.py --------

import pandas as pd
from numpy import *
import sys
from math import *
from PyQt4 import QtCore,QtGui
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import networkx as nx
import GraphNetworkX
from x import *

pf = pd.read_csv('/desktop/companytrades.csv',header=0,index_col=['date'])

#setup the needed variables
if __names__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    app.setStyle("Plastique")

class netx(QtGui.QDialog):
    def __init__(self):
        super(netx,self).__init__()
        self.uiNX = Ui_Form() 
        self.uiNX.setupUi(self)
        G = nx.from_pandas_dataframe(pf,'Company1','Company2',create_using=nx.DiGraph())
Pos = nx.spring_layout(g,scale=300)
scene = GraphNetworkx.GraphGraphicsScene(G=g,pos=Pos)
self.uiNX.neworkx_graphicsView.setScene(scene)

NX = netx()
NX.show()
sys.exit(exit(app.exec_())
app.deleteLater()

------- x.py -------

from PyQt4 import QtCore,QtGui
try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.unicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName(_fromUtf8("Form"))
        Form.resize(1492,1029)
        self.networkx_graphicsView = QtGui.QGraphicsView(Form)
        self.networkx_graphicsView.setGeometry(QtCore.QRect(240,70,971,911))
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(5)
        sizePolicy.setHeightForWidth(self.networkx_graphicsView.sizePolicy().hasHeightForWidth())
        self.networkx_graphicsView.setSizePolicy(sizePolicy)
        self.networkx_graphicsView.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        self.networkx_graphicsView.setObjectName(_fromUtf8("networkx_graphicsView"))
        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)
    def retranslateUi(self,Form):
        Form.setWindowTitle(_translate("Form","Form",None))

I am having issues implementing this. The issue I'm having is in GraphNetworkX under the drawGraph function. It seems the print function is working correctly with n but I really don't understand the reasoning for replacing it with i.

    i = 0
    for n in G.nodes():
        #print str(pos[n][0]) + " " + str(pos[n][1])+ " "+str(n)
        self.addNode(pos[i][0], pos[i][1], n)
        i += 1

I did an experiment replacing i with n and adding the nodes seemed to work but then I have issues with adding the edges.

    for e in G.edges():
        node1 = self.nodes[e[0]]
        node2 = self.nodes[e[1]]
        self.addEdge(node1, node2)

It keeps saying that e[0] is out of range..considering the Nodes.py function is to turn self.nodes into a list of Nodes.nodes objects, I thought maybe that is a placeholder inside each of the objects but I'm not quite sure. I then tried making this change:

node1 = e[0]
node2 = e[1] 

but then I get the error in Edge.py stating that

 x1 = node1.centerX() 

an integer does not have the function centerX()

I'm a bit at a loss. Could someone help me understand this and help me get this to work?

Daniel
  • 77
  • 3
  • 20

1 Answers1

1

A more minimal question might help with obtaining an answer. (for instance, nothing from your x.py seems relevant to the problem at the end)

To get you started, you are likely suffering from some namespace overloading (renaming the same objects). In netxgui.py you have import networkx as nx but then a few lines later you declare a class nx(QtGui.QDialog). After this you try to call nx.spring_layout() which you presumably wanted to be from networkx rather than your custom nx class. It is possible that the structures you are trying to access exist in networkx Graph instances but don't in QDialog instances?

In general, avoiding the use of from examplemodule import * will make your life easier when trying to trace errors or just when developing your code.

--- EDIT ---

I looked closer and the problem is because of the differing representations used in networkx.Graph / .DiGraph etc and in the GraphGraphicsScene. Networkx uses dictionaries underneath, for storing the nodes (and also the edges). GraphGraphicsScene uses a list of nodes.

Quick and dirty solution: these happen to be compatible IF your nodes are labelled starting at 0, and have a contiguous sequence.

Slightly more robust would be to generate your own graphs like this, which could be achieved as follows:

def re_index_digraph(G_orig):
    remap = {i: n for (i,n) in enumerate(G_orig.nodes())}
    inv_remap = {v:k for k,v in remap.items()}
    G = nx.DiGraph()
    G.add_nodes_from(remap)
    remap_edges = [(inv_remap[src], inv_remap[sink]) for (src, sink) in G_orig.edges()]
    G.add_edges_from(remap_edges)
    return G

G_orig = nx.from_pandas_dataframe(pf,'Company1','Company2',create_using=nx.DiGraph())
G = re_index_digraph(G_orig)

and then carry on with G as you had before. (if there are properties other than simply node name and edges, you'd need to extend the remap function accordingly).

Other than this, you may need to invest significant effort in developing the GraphGraphicsScene implementation.

Bonlenfum
  • 19,101
  • 2
  • 53
  • 56
  • Thanks for the advice. I will do the corrections and get back with the results..I doubt tho this will fully solve the issue. I added the x.py because I'm dealing with PyQt4 and I know from experience that dealing with a GUI the environment and the behavior of the components change. – Daniel Feb 21 '17 at 13:29
  • what doesn't work? I suppose that you aren't using the exact code from above (netxgui.py), since it doesn't run as-is. But if you are, at the very minimum you will need to do some indenting of the class definition – Bonlenfum Feb 27 '17 at 18:35
  • I didnt see the editing prior to putting that comment. I implemented what you suggested and the graph showed up. Thank you! – Daniel Feb 28 '17 at 14:26
  • ok great! I didn't know exactly what you were expecting (e.g. node or edge labels, scrolling/zooming -- all stuff that comes "for free" when rendering with matplotlib) but glad to hear that this has got you on the way! – Bonlenfum Mar 02 '17 at 19:15
  • Well I've been working on two different methods getting networkx into pyqt. I'm having the issue with getting the weight of edges being displayed. – Daniel Mar 02 '17 at 19:51
  • could you check this question out? [here](http://stackoverflow.com/questions/42517679/getting-networkx-edge-weight-to-show-in-qgraphicsscene) It's a different angle but I think you are the best source to maybe answer this one. – Daniel Mar 06 '17 at 11:10