NetworkX visualization from Torch Geometric, duplicated unconnected nodes - networkx

I have nodes features stored in a dataframe and graphs attributes stored in an object, and I am trying to visualize the Torch Geometric graphs via networkx, but beside the actual nodes it also plots an equal number of unconnected nodes, and I am trying to understand why..
for example for graph 8779, if I construct the networkx graph from my object it looks fine:
G = nx.Graph()
for e in graphs[8779].edges:
G.add_edge(e.source, e.target)
plt.figure(8779)
plt.suptitle(8779)
nx.draw(G)
When I go through Torch Geometric it doesn't:
attr = []
for n in graphs[8779].nodes:
vals = df_features[df_features.event_id == int(n.event_id)].iloc[:,1:].values[0]
attr.append(vals)
attr = torch.FloatTensor(np.array(attr))
rows = [int(e.source) for e in graphs[8779].edges]
cols = [int(e.target) for e in graphs[8779].edges]
edges = torch.tensor([rows, cols])
gr = data.Data(x=attr, edge_index=edges)
vis = to_networkx(gr)
plt.figure(1,figsize=(15,13))
nx.draw(vis, cmap=plt.get_cmap('Set3'),node_size=70,linewidths=6)
plt.show()
I checked the Torch Geometric graph properties and everything looks fine:
('x', tensor([[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
...,
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 1., 0.],
[0., 0., 0., ..., 0., 1., 0.]]))
('edge_index', tensor([[829072, 829072, 829068, 829118, 829132, 829070, 829073, 829066, 829113,
829084, 829075, 829075, 829129, 829090, 829082],
[829073, 829075, 829070, 829129, 829133, 829072, 829075, 829068, 829118,
829132, 829082, 829084, 829132, 829113, 829090]]))
('num_nodes', 14)
what am I doing wrong? :(

Related

How to fit a curve to a set of data for same x values?

I have some curves from the lab tests on material. each set of data has different lenghts. i am willing to fit a curve to these data.
Lets start with data having same lenght: y1 y2 y3 with same x values.
import numpy as np
import matplotlib.pyplot as plt
def my_function(x,y):
curve = np.polyfit(x, y, 4)
poly = np.poly1d(curve)
new_x = np.arange(x[0],x[-1],1)
new_y= poly(new_x)
plt.plot(new_x, new_y)
plt.scatter(x, y)
print(poly)
x = [0, 5.25, 10.5, 21, 31.5, 42, 52.5, 63, 73.5, 84, 94.5, 99.75, 105]
y1=[0.2535,0.3552,0.456,0.489,0.5265,0.58384,1.87616,2.87328,2.55184,2.66992,2.8208,3.09632,3.51616]
y2=[0.116112,0.425088,0.582528,0.70192,1.07584,2.41408,3.75232,4.61824,2.55184,2.66992,2.8208,3.09632,3.51616]
y3=[0.389664,1.166368,1.60392,2.05984,2.788,4.02784,5.0184,5.60224,2.55184,2.66992,2.8208,3.09632,3.51616]
ylist = [ y1, y2, y3]
for y in ylist:
my_function(x,y)
My final goal is to do this for pairs of y and x, which their lenghts are different from other pairs of data.
what im expecting is like this:
enter image description here
I may be misunderstanding your question but nothing in your code presumes that all your y's have to have the same length. This works for me:
import numpy as np
import matplotlib.pyplot as plt
def my_function(x,y):
curve = np.polyfit(x, y, 4)
poly = np.poly1d(curve)
new_x = np.arange(x[0],x[-1],1)
new_y= poly(new_x)
plt.plot(new_x, new_y)
plt.scatter(x, y)
print(poly)
x1 = [0, 5.25, 10.5, 21, 31.5, 42, 52.5, 63, 73.5, 84, 94.5, 99.75, 105]
x2 = [0, 5.25, 10.5, 21, 31.5, 42, 52.5, 63, 73.5, 84, 94.5, 99.75]
x3 = [0, 5.25, 10.5, 21, 31.5, 42, 52.5, 63, 73.5, 84, 94.5]
y1=[0.2535,0.3552,0.456,0.489,0.5265,0.58384,1.87616,2.87328,2.55184,2.66992,2.8208,3.09632,3.51616]
y2=[0.116112,0.425088,0.582528,0.70192,1.07584,2.41408,3.75232,4.61824,2.55184,2.66992,2.8208,3.09632]
y3=[0.389664,1.166368,1.60392,2.05984,2.788,4.02784,5.0184,5.60224,2.55184,2.66992,2.8208]
ylist = [ y1, y2, y3]
xlist = [ x1, x2, x3]
for x, y in zip(xlist, ylist):
my_function(x,y)
Edit: From the clarification in the comment
the goal is to fit one curve for all three y1 y2 y3 with their corresponding x1 x2 x3 curves
So all points in the curves defined by (x1, y1), (x2, y2), (x3, y3), ... should be fit to a single polynomial.
This can be done by simply concatenating the vectors containing the data:
x_tot = np.concatenate((x1, x2, x3))
y_tot = np.concatenate((y1, y2, y3))
my_function(x_tot,y_tot)
Which results in:
Note that the (x, y) arrays don't have to be the same length. In case that y1, y2, ..., share the same x, the concatenation should be x_tot = np.concatenate((x, x, x))

How to plot only a fitting curve in MATLAB?

I want to graph a fitting curve given vectors with X and Y values, but also some example points, as the vectors are really big (10k+ terms).
Here is an equivalent MWE of the problem I'm facing:
xData = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
yData = [1.5, 2.6, 3.7, 4.8, 5.9, 7.0, 8.1, 9.2, 10.3, 11.4];
[pX, pY] = prepareCurveData(xData, yData);
ft = 'linearinterp';
[fitresult, gof] = fit( pX, pY, ft, 'Normalize', 'on' );
gX = xData(1:2:end);
gY = yData(1:2:end);
hold on;
plot(fitresult, pX, pY);
plot(gX, gY, 'k*');
And here is the result of the MWE. As you can see, I can plot the selected points (in black), but the plot(fitresult, pX, pY); command also plots all the points I used to the curve fitting process (the small, blue ones):
I tried with the plot(fitresult); command but with that I lose the fitted curve, although the data points are also not plotted.
So, is there a way to plot a fitted curve without its data points?
I edited the code according to the discussion in the comment:
xData = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
yData = [1.5, 2.6, 3.7, 4.8, 5.9, 7.0, 8.1, 9.2, 10.3, 11.4];
[pX, pY] = prepareCurveData(xData, yData);
ft = 'linearinterp';
[fitresult, gof] = fit( pX, pY, ft, 'Normalize', 'on' );
% set the scale for a new plot
gX = 1:20;
gY = fitresult(gX);
plot(gX, gY, 'r'); axis tight;

How to display two overlapping lines in matlab

I have to plot 5 lines that overlap in some regions, and I need to be able to see all the lines.
I can think of shifting the lines a bit to allow them to be displayed, but this doesn't seem a very elegante solution. Even so, how could I code such a thing?
Is there any other way to plot multiple overlapping lines while being able to distinguish them at every point?
For exemple, here is one exemple with 3 overlapping lines:
Thank you in advance!
Another way is to use transparency.
Unfortunatelly, line objects do not obey
transparency commands :(
A workaround is to:
1. download patchline (<-- link to Matlab Central)
2. use it to plot patchline with transparency
Once you have patchline, you can try something like:
% create some lines:
l1 = [1, 1, 1, 0, 0, 0.25, 1, 1, 0, 0, 0, 0, 1 1];
l2 = [0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1];
l3 = [1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0];
% plot with patchline (notice the use of 'EdgeAlpha'):
figure;
patchline(1:length(l1), l1, [], 'EdgeColor', [0.8, 0.2, 0.35],...
'LineWidth', 5, 'EdgeAlpha', 0.5 );
hold on;
patchline(1:length(l1), l2, 'EdgeColor', [0.2, 0.7, 0.55],...
'LineWidth', 5, 'EdgeAlpha', 0.5 );
patchline(1:length(l1), l3, 'EdgeColor', [0.1, 0.2, 0.95],...
'LineWidth', 5, 'EdgeAlpha', 0.5);
% change y limits to see line overlap clearly
set(gca, 'YLim', [-0.5, 1.5]);
Not an ideal way to do it - the rough 'cracks' will stay this way,
but you can experiment with different line widths or moving the
lines in y axis by a value that would correspond to an image with each
line covering only half of it closest neighbour...
You may play with EraseMode property of the plot line. The following code example shows how to shift the lines and EraseMode effect:
% First we generate some data
NLines = 2;
NPoints = 50;
LineWidth = 3;
ShiftStep = 1.1;
XData = linspace(0,1,NPoints);
YData = rand(NPoints,NLines);
for k=1:NLines
YData(:,k) = YData(:,k) > (k/(NLines+1));
end
% Then we create plot
figure('color','w');
subplot(3,1,1); plot(XData,YData, 'LineWidth',LineWidth);
ylim([-0.1 1.1]);
title('simple')
subplot(3,1,2); plot(XData,YData+repmat((0:NLines-1)*ShiftStep,NPoints,1), 'LineWidth',LineWidth, 'EraseMode','xor');
ylim([-0.1 1.1+ShiftStep*(NLines-1)]);
title('Shifted vertically')
subplot(3,1,3); plot(XData,YData, 'LineWidth',LineWidth, 'EraseMode','xor');
ylim([-0.1 1.1]);
title('EraseMode = xor')
In my opinion if you have more than three lines similar to your plot, shifting is visually more attractive. Also you may create several axes (Like I did) and plot each line in its own axes, so they will have y-labels set accordingly, but their X-labels will be essentially the same.
You can use plot3 and assign different Z values to different overlapping lines. However, it'll look more like you expect (Z being the "up" direction) if you swap the Y and Z axes:
Example:
Y1 = randn(1,100);
Y2 = randn(1,100);
X = 1:100;
Z1 = 1*ones(size(X));
Z2 = 2*ones(size(X));
plot3(X,Z1,Y1);
hold on;
plot3(X,Z2,Y2);

Drawing 3D points in Matlab and connect them in order via line

I have an array that contains 3D float points. Not only I want to depict them in a figure but also I want to connect them with lines.
Example) lets say we have array called X:
X=[0, 0, 0; 0.48, -0.88, 0.09; -1.06, 0.55, 0.9; -0.65, 1.5, -1.44; 1.1, 0.59,
-1.11;0.76, 0.86, -0.52; -1.08, -0.28, 0.55; 1.47, -1.21, 0.14; 1.42, -2.15, 0.71; -0.64,
1.87, 2.4;2.32, -2.44, 2.02; 2.25, -2.56, -3.03; 2.35, 2.65, -1.5; 0.23, -2.25, 2.78; 2.47,
-3.12, -1.91; 2.27, 1.37, -3.05; 2.3, 1.9, -1.29; -1.77, -0.51, 2.33];
X1= [0,0,0]
X2=[0.48, -0.88, 0.09]
X3=[-1.06, 0.55, 0.9] ...
now I want that X1...Xn to be drawn in figure as points then X1 get connected to X2, X2 get connected to X3, X3 get connected to X4, etc
how could I do that?
Here is what I ve done but I get a wrong figure:
figure;hold on;
P=[];
for i=1:size(X,1)
x=X(i,1);
y=X(i,2);
z=X(i,3);
A=[ x,y,z];
P=vertcat(P,A);
plot(P);
end
And Here is the output:
Check out the plot3 documentation.
In particular, plot3(X, Y, Z) will plot the points and join them with a line.
In your case:
plot3(X(:, 1), X(:, 2), X(:, 3))

Converting matlab-style indexing to numpy

I would like to convert (a more complicated form of) the follwing Matlab code
a=zeros(9,9);
a(3+(1:3),6+(1:3))=1;
to Numpy. I tried
from numpy import zeros, r_
a=zeros((9,9))
a[3+r_[0:3],6+r_[0:3]] = 1
But this only puts 3 1's in the matrix. How can I write the matlab code in a similar (short) form in Python?
To be honest, I'd probably just do
>>> a = zeros((9,9))
>>> a[3:6, 6:9] = 1
or the non-hardcoded equivalent. If you want the indexing to look more like Matlab's here, though, then you can use ix_:
>>> a = zeros((9,9))
>>> a[ix_(3+r_[0:3], 6+r_[0:3])] = 1
>>> a
array([[ 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 1., 1., 1.],
[ 0., 0., 0., 0., 0., 0., 1., 1., 1.],
[ 0., 0., 0., 0., 0., 0., 1., 1., 1.],
[ 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0., 0.]])