In [51]:
prod = ['eggs','milk']
act = ['Producer','Consumer']
loc = [
        'Portugal',
        'Spain',
        'France',
        'Italy',
        'Germany',
        'Montenegro',
        'others'
        ]
     
myNW = go.createGraph(
        listOfActors=act,
        listOfLocations=loc,
        listOfProducts=prod)
    
#---------------------------
myData = {
    loc[0]: [1, 625, 1737, 2509, 2781, 3351,4000],
    loc[1]: [625, 1, 1277, 1965, 2320, 2804,4000],
    loc[2]: [1737, 1277, 1, 1420, 1054, 2038,4000],
    loc[3]: [2509, 1965, 1420, 1, 1505, 740,4000],
    loc[4]: [2781, 2320, 1054, 1505, 1, 1636,4000],
    loc[5]: [3351, 2804, 2038, 740, 1636, 1,4000],
    loc[6]: [4000,4000,4000,4000,4000,4000,1]
}
    
myDF = pd.DataFrame(myData,index=loc)
    

# supply and demand   
sendingProd = [[12588339,44688368,48464470,33153139,24304433,2300,9204611],#eggs
                   [75752927,121886945,490834291,3933048,497278336,138,0]]#milk
   
receivingProd = [[19101284,91333314,48818138,957046,12195878,0,0],#eggs
                 [70146856,121623784,95268102,761020054,104160029,14602,37452258]]#milk


myTDs = []    
allFlows = np.ndarray((7,7,2,5))
    
# creating list of node IDs of participants
for run,p in enumerate(prod):
    senderIDs = go.getListOfNodeIDs(
    myNW,
    actors=['Producer'],
    products=[p]
    )
    receiverIDs = go.getListOfNodeIDs(
        myNW,
        actors=['Consumer'],
        products=[p]
    )
    
    # creating edgeIDs for adding 'distance' to graph
    allcombIDs1, allcombIDs2 = go.getAllCombinations(
        senderIDs,
        receiverIDs,
        order='1st'
    )

    myEdges4Graph = go.getEdgeID(myNW, allcombIDs1, allcombIDs2)
        
    didItWork3 = go.addAttr2Edges(
        myNW,
        myEdges4Graph,
        myDF.values.flatten(),
        attr='distance'
    )
    
    go.addAttr2ExistingNodes(myNW,senderIDs,'output',sendingProd[run])
    go.addAttr2ExistingNodes(myNW,receiverIDs,'input',receivingProd[run])
    
    # get the transport distances
    myTDs.append(
        go.calcPotTransportDistances(
            myNW,
            listOfSenderIDs=senderIDs,
            listOfReceiverIDs=receiverIDs
        )
    )
    
    # Run the gravity model with given transport distance and return the
    # flow each myTDs[run] is a list of 5 transport distances
    # allFlows is input for the calibration algorithm
    for it, td in enumerate(myTDs[run]):
        allFlows[
            0:len(senderIDs),
            0:len(receiverIDs),
            run,
            it
            ] = go.hymanModel(
                myNW,
                listOfSenderIDs=senderIDs,
                listOfReceiverIDs=receiverIDs,
                transportDistance=td,
                tolerance=0.01
            )
    
#creating calibration measure that halfway might make sense
allFoodTransported = sum(sum(sendingProd,[]))
dummy = np.random.rand(48)*allFoodTransported/80+allFoodTransported/(len(sum(sendingProd,[]))+1)
myCalMat = np.append(
        dummy,
        allFoodTransported-np.sum(dummy)).reshape((len(senderIDs),
        len(receiverIDs))
)
    
print(go.calibration(allFlows,myCalMat))
#--------------------------

myDF1 = pd.DataFrame(myCalMat, index=loc)
    
# entering distance information to the right nodes on the graph
senderIDs = go.getListOfNodeIDs(
    SCGraph=myNW,
    actors=['Producer'],
    products=['milk'])
receiverIDs = go.getListOfNodeIDs(
    myNW,
    actors=['Consumer'],
    products=['milk'])

# supply and demand for milk and enrich the graph with this data
sendingProd1 = [75752927,121886945,490834291,3933048,497278336,138,0]#milk
receivingProd1 = [70146856,121623784,95268102,761020054,104160029,14602,37452258]#milk


myInt = 1000000
sendingProd1 = [x / myInt for x in sendingProd1]
receivingProd1 = [x / myInt for x in receivingProd1]

#sendingProd = [1, 4, 9, 15, 2]
#receivingProd = [36, 47, 68, 79, 100]
go.addAttr2ExistingNodes(
    SCGraph=myNW,
    listOfNodeIDs=senderIDs,
    nameOfAttr='output',
    listOfAttr=sendingProd1)
go.addAttr2ExistingNodes(
    SCGraph=myNW,
    listOfNodeIDs=receiverIDs,
    nameOfAttr='input',
    listOfAttr=receivingProd1)


# get edge IDs for enriching graph with distance matrix
allcombIDs1, allcombIDs2 = go.getAllCombinations(
    senderIDs,
    receiverIDs,
    order='1st')
myEdges4Graph = go.getEdgeID(
    SCGraph=myNW,
    outgoingNodes=allcombIDs1,
    incomingNodes=allcombIDs2)

# actual adding edges to graph
go.addAttr2Edges(
    SCGraph=myNW,
    listOfEdgeIDs=myEdges4Graph,
    listOfContent=myDF1.values.flatten(),
    attr='weight')
/home/NeubertK/anaconda3/envs/p39/lib/python3.9/site-packages/ipfn/ipfn.py:146: RuntimeWarning: invalid value encountered in double_scalars
  if abs(m_ijk / ori_ijk - 1) > max_conv:
/home/NeubertK/anaconda3/envs/p39/lib/python3.9/site-packages/supplychainmodelhelper/graphoperations.py:1628: RuntimeWarning: invalid value encountered in double_scalars
  WeightDist = np.sum(flow * dist) / (np.sum(flow))
ipfn converged: convergence_rate not updating or below rate_tolerance
ipfn converged: convergence_rate not updating or below rate_tolerance
ipfn converged: convergence_rate not updating or below rate_tolerance
On the  1. iteration: tolerance is down to 284.5620
On the  2. iteration: tolerance is down to 228.5627
ipfn converged: convergence_rate not updating or below rate_tolerance
On the  3. iteration: tolerance is down to 161.4165
On the  4. iteration: tolerance is down to 224.1155
ipfn converged: convergence_rate not updating or below rate_tolerance
On the  5. iteration: tolerance is down to 161.4165
On the  6. iteration: tolerance is down to 224.1075
ipfn converged: convergence_rate not updating or below rate_tolerance
On the  7. iteration: tolerance is down to 161.4165
On the  8. iteration: tolerance is down to 224.1063
ipfn converged: convergence_rate not updating or below rate_tolerance
On the  9. iteration: tolerance is down to 161.4165
ipfn converged: convergence_rate not updating or below rate_tolerance
On the 10. iteration: tolerance is down to 161.4165
ipfn converged: convergence_rate not updating or below rate_tolerance
ipfn converged: convergence_rate not updating or below rate_tolerance
On the last iteration (10.): tolerance is down to 161.4165
On the  1. iteration: tolerance is down to 187.1614
On the  2. iteration: tolerance is down to 109.8858
On the  3. iteration: tolerance is down to 76.9338
On the  4. iteration: tolerance is down to 63.9681
ipfn converged: convergence_rate not updating or below rate_tolerance
On the  5. iteration: tolerance is down to 322.4165
On the  6. iteration: tolerance is down to 63.1864
On the  7. iteration: tolerance is down to 63.1196
ipfn converged: convergence_rate not updating or below rate_tolerance
On the  8. iteration: tolerance is down to 678.0000
ipfn converged: convergence_rate not updating or below rate_tolerance
On the  9. iteration: tolerance is down to 677.9997
ipfn converged: convergence_rate not updating or below rate_tolerance
ipfn converged: convergence_rate not updating or below rate_tolerance
On the last iteration ( 7.): tolerance is down to 63.1196
On the  1. iteration: tolerance is down to 96.7715
On the  2. iteration: tolerance is down to 30.3042
On the  3. iteration: tolerance is down to 10.2949
On the  4. iteration: tolerance is down to 1.6670
On the  5. iteration: tolerance is down to 0.1098
On the  6. iteration: tolerance is down to 0.0013
On the last iteration ( 6.): tolerance is down to 0.0013
On the  1. iteration: tolerance is down to 4.2387
On the  2. iteration: tolerance is down to 0.0496
On the  3. iteration: tolerance is down to 0.0005
On the last iteration ( 3.): tolerance is down to 0.0005
On the  1. iteration: tolerance is down to 98.9327
On the  2. iteration: tolerance is down to 17.7928
On the  3. iteration: tolerance is down to 1.5979
On the  4. iteration: tolerance is down to 0.0178
On the  5. iteration: tolerance is down to 0.0000
On the last iteration ( 5.): tolerance is down to 0.0000
ipfn converged: convergence_rate not updating or below rate_tolerance
ipfn converged: convergence_rate not updating or below rate_tolerance
ipfn converged: convergence_rate not updating or below rate_tolerance
On the  1. iteration: tolerance is down to 695.7447
ipfn converged: convergence_rate not updating or below rate_tolerance
On the  2. iteration: tolerance is down to 235.1083
ipfn converged: convergence_rate not updating or below rate_tolerance
On the  3. iteration: tolerance is down to 235.1083
ipfn converged: convergence_rate not updating or below rate_tolerance
ipfn converged: convergence_rate not updating or below rate_tolerance
On the last iteration ( 2.): tolerance is down to 235.1083
On the  1. iteration: tolerance is down to 492.5820
/home/NeubertK/anaconda3/envs/p39/lib/python3.9/site-packages/supplychainmodelhelper/graphoperations.py:1920: RuntimeWarning: divide by zero encountered in double_scalars
  (
Maximum iterations reached
On the  2. iteration: tolerance is down to 459.8334
ipfn converged: convergence_rate not updating or below rate_tolerance
On the  3. iteration: tolerance is down to 470.1083
ipfn converged: convergence_rate not updating or below rate_tolerance
On the  4. iteration: tolerance is down to 470.1083
ipfn converged: convergence_rate not updating or below rate_tolerance
ipfn converged: convergence_rate not updating or below rate_tolerance
On the last iteration ( 2.): tolerance is down to 459.8334
On the  1. iteration: tolerance is down to 348.0484
On the  2. iteration: tolerance is down to 239.6603
On the  3. iteration: tolerance is down to 225.1587
ipfn converged: convergence_rate not updating or below rate_tolerance
On the  4. iteration: tolerance is down to 705.1083
Maximum iterations reached
On the  5. iteration: tolerance is down to 223.9220
ipfn converged: convergence_rate not updating or below rate_tolerance
On the  6. iteration: tolerance is down to 705.1083
ipfn converged: convergence_rate not updating or below rate_tolerance
On the  7. iteration: tolerance is down to 223.8713
ipfn converged: convergence_rate not updating or below rate_tolerance
On the  8. iteration: tolerance is down to 223.8443
ipfn converged: convergence_rate not updating or below rate_tolerance
On the  9. iteration: tolerance is down to 831.0000
ipfn converged: convergence_rate not updating or below rate_tolerance
On the 10. iteration: tolerance is down to 831.0000
ipfn converged: convergence_rate not updating or below rate_tolerance
ipfn converged: convergence_rate not updating or below rate_tolerance
On the last iteration ( 8.): tolerance is down to 223.8443
On the  1. iteration: tolerance is down to 209.4188
On the  2. iteration: tolerance is down to 77.1483
On the  3. iteration: tolerance is down to 40.6498
On the  4. iteration: tolerance is down to 17.8773
On the  5. iteration: tolerance is down to 7.5900
On the  6. iteration: tolerance is down to 2.6236
On the  7. iteration: tolerance is down to 0.6371
On the  8. iteration: tolerance is down to 0.0760
On the  9. iteration: tolerance is down to 0.0026
On the last iteration ( 9.): tolerance is down to 0.0026
On the  1. iteration: tolerance is down to 47.6112
On the  2. iteration: tolerance is down to 2.6602
On the  3. iteration: tolerance is down to 0.1584
On the  4. iteration: tolerance is down to 0.0006
On the last iteration ( 4.): tolerance is down to 0.0006
exiting with relative difference to calibration matrix: 6.009593217314959
[4, 4]
Out[51]:
True

Visualisation

In [52]:
didItWork4 = go.addAttr2Edges(
    myNW,
    myEdges4Graph,
    myDF.values.flatten(),
    attr='weight'
)
d = Drawer(myNW)
d.draw_it(product=['milk'], actor_type_names=['Producer', 'Consumer'])
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
File ~/anaconda3/envs/p39/lib/python3.9/site-packages/networkx/drawing/nx_pylab.py:456, in draw_networkx_nodes(G, pos, nodelist, node_size, node_color, node_shape, alpha, cmap, vmin, vmax, ax, linewidths, edgecolors, label, margins)
    455 try:
--> 456     xy = np.asarray([pos[v] for v in nodelist])
    457 except KeyError as err:

File ~/anaconda3/envs/p39/lib/python3.9/site-packages/networkx/drawing/nx_pylab.py:456, in <listcomp>(.0)
    455 try:
--> 456     xy = np.asarray([pos[v] for v in nodelist])
    457 except KeyError as err:

KeyError: 0

The above exception was the direct cause of the following exception:

NetworkXError                             Traceback (most recent call last)
Input In [52], in <cell line: 8>()
      1 didItWork4 = go.addAttr2Edges(
      2     myNW,
      3     myEdges4Graph,
      4     myDF.values.flatten(),
      5     attr='weight'
      6 )
      7 d = Drawer(myNW)
----> 8 d.draw_it(product=['milk'], actor_type_names=['Producer', 'Consumer'])

File ~/anaconda3/envs/p39/lib/python3.9/site-packages/supplychainmodelhelper/drawer.py:136, in Drawer.draw_it(self, product, actor_type_names)
    134 import math
    135 fig, ax = plt.subplots()
--> 136 nx.draw(self.SCGraph,
    137         node_positions,
    138         nodelist=node_list,
    139         node_color='grey',
    140         node_size=node_size_avg,
    141         **edge_options,
    142         ax=ax
    143         )
    145 # foreground nodes drawing with edges
    146 nx.draw_networkx_nodes(self.SCGraph,
    147                        node_positions,
    148                        node_color='k',
    149                        nodelist=node_list,
    150                        node_size=node_size
    151                        )

File ~/anaconda3/envs/p39/lib/python3.9/site-packages/networkx/drawing/nx_pylab.py:120, in draw(G, pos, ax, **kwds)
    117 if "with_labels" not in kwds:
    118     kwds["with_labels"] = "labels" in kwds
--> 120 draw_networkx(G, pos=pos, ax=ax, **kwds)
    121 ax.set_axis_off()
    122 plt.draw_if_interactive()

File ~/anaconda3/envs/p39/lib/python3.9/site-packages/networkx/drawing/nx_pylab.py:335, in draw_networkx(G, pos, arrows, with_labels, **kwds)
    332 if pos is None:
    333     pos = nx.drawing.spring_layout(G)  # default to spring layout
--> 335 draw_networkx_nodes(G, pos, **node_kwds)
    336 draw_networkx_edges(G, pos, arrows=arrows, **edge_kwds)
    337 if with_labels:

File ~/anaconda3/envs/p39/lib/python3.9/site-packages/networkx/drawing/nx_pylab.py:458, in draw_networkx_nodes(G, pos, nodelist, node_size, node_color, node_shape, alpha, cmap, vmin, vmax, ax, linewidths, edgecolors, label, margins)
    456     xy = np.asarray([pos[v] for v in nodelist])
    457 except KeyError as err:
--> 458     raise nx.NetworkXError(f"Node {err} has no position.") from err
    460 if isinstance(alpha, Iterable):
    461     node_color = apply_alpha(node_color, alpha, nodelist, cmap, vmin, vmax)

NetworkXError: Node 0 has no position.
In [53]:
d.draw_it(product=['eggs'], actor_type_names=['Producer', 'Consumer'])
#help(Drawer.draw_it)
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
File ~/anaconda3/envs/p39/lib/python3.9/site-packages/networkx/drawing/nx_pylab.py:456, in draw_networkx_nodes(G, pos, nodelist, node_size, node_color, node_shape, alpha, cmap, vmin, vmax, ax, linewidths, edgecolors, label, margins)
    455 try:
--> 456     xy = np.asarray([pos[v] for v in nodelist])
    457 except KeyError as err:

File ~/anaconda3/envs/p39/lib/python3.9/site-packages/networkx/drawing/nx_pylab.py:456, in <listcomp>(.0)
    455 try:
--> 456     xy = np.asarray([pos[v] for v in nodelist])
    457 except KeyError as err:

KeyError: 7

The above exception was the direct cause of the following exception:

NetworkXError                             Traceback (most recent call last)
Input In [53], in <cell line: 1>()
----> 1 d.draw_it(product=['eggs'], actor_type_names=['Producer', 'Consumer'])

File ~/anaconda3/envs/p39/lib/python3.9/site-packages/supplychainmodelhelper/drawer.py:136, in Drawer.draw_it(self, product, actor_type_names)
    134 import math
    135 fig, ax = plt.subplots()
--> 136 nx.draw(self.SCGraph,
    137         node_positions,
    138         nodelist=node_list,
    139         node_color='grey',
    140         node_size=node_size_avg,
    141         **edge_options,
    142         ax=ax
    143         )
    145 # foreground nodes drawing with edges
    146 nx.draw_networkx_nodes(self.SCGraph,
    147                        node_positions,
    148                        node_color='k',
    149                        nodelist=node_list,
    150                        node_size=node_size
    151                        )

File ~/anaconda3/envs/p39/lib/python3.9/site-packages/networkx/drawing/nx_pylab.py:120, in draw(G, pos, ax, **kwds)
    117 if "with_labels" not in kwds:
    118     kwds["with_labels"] = "labels" in kwds
--> 120 draw_networkx(G, pos=pos, ax=ax, **kwds)
    121 ax.set_axis_off()
    122 plt.draw_if_interactive()

File ~/anaconda3/envs/p39/lib/python3.9/site-packages/networkx/drawing/nx_pylab.py:335, in draw_networkx(G, pos, arrows, with_labels, **kwds)
    332 if pos is None:
    333     pos = nx.drawing.spring_layout(G)  # default to spring layout
--> 335 draw_networkx_nodes(G, pos, **node_kwds)
    336 draw_networkx_edges(G, pos, arrows=arrows, **edge_kwds)
    337 if with_labels:

File ~/anaconda3/envs/p39/lib/python3.9/site-packages/networkx/drawing/nx_pylab.py:458, in draw_networkx_nodes(G, pos, nodelist, node_size, node_color, node_shape, alpha, cmap, vmin, vmax, ax, linewidths, edgecolors, label, margins)
    456     xy = np.asarray([pos[v] for v in nodelist])
    457 except KeyError as err:
--> 458     raise nx.NetworkXError(f"Node {err} has no position.") from err
    460 if isinstance(alpha, Iterable):
    461     node_color = apply_alpha(node_color, alpha, nodelist, cmap, vmin, vmax)

NetworkXError: Node 7 has no position.
In [54]:
help(Drawer.draw_it)
Help on function draw_it in module supplychainmodelhelper.drawer:

draw_it(self, product, actor_type_names=None)
    purpose: execute drawing of sc graph
    :param product: choose the name of the product to be shown.
    :param actor_type_names: (optional) list of actor types as defined in
    given graph. Expected to be found in node_attribute "actor".
    choose names of actor types (minimum 2).
    
    :return: image of graph
    
    TODO potential parameters:
        product -> multiple products if no product is chosen???
        node bg color = treshold color, size
        node fg color
        treshold value
        other heatmaps for edges
        labeling nodes with locations
        no stages

Is there any Example for usage of the Drawer?

In [ ]: