How to get on ggraph the same plot as with RCy3 (Cytoscape) - layout

I can get thanks to the function RCy3::getNodePosition() x and y coordinates from a graph plot drawn with RCy3 on Cytoscape. Then, I can use ggraph with layout based on the dataframe prepared from coordinates. I have got a graph but with a deeply different structure from the previous one. What could explain this difference?
Consider the following example coming from:
http://cytoscape.org/RCy3/articles/Network-functions-and-visualization.html
'''
library(RCy3)
library(ggraph)
'''
'''
lesmis <- system.file("extdata","lesmis.txt", package="RCy3")
dataSet <- read.table(lesmis, header = FALSE, sep = "\t")
'''
Create a graph. Use simplify to ensure that there are no duplicated edges or self loops
'''
gD <- igraph::simplify(igraph::graph.data.frame(dataSet, directed=FALSE))
'''
Verify the number of nodes (77) and edges (254):
'''
igraph::vcount(gD)
igraph::ecount(gD)
'''
create the graph gD on Cytoscape
'''
createNetworkFromIgraph(gD,new.title='Les Miserables')
'''
create a graph using ggraph
'''
ggraph(gD, layout = 'kk') +
geom_edge_link(color = "orange", width=0.7) +
geom_node_point(size=5, color="gray50")+
geom_node_text(aes(label = vlabels_1), size=2, color="gray50", repel=T) +
theme_void()
'''
It is qualitatively the same graph obtained by ggraph as on Cytoscape by using RCy3::createNetworkFromIgraph()
Then, we can get coordinates from graph on Cytoscape as following:
'''
mygraph_Miserables <- createIgraphFromNetwork()
mylayout_Miserables <- getNodePosition()
mylayout_Miserables$x_location <- as.numeric(as.character(mylayout_Miserables$x_location))
mylayout_Miserables$y_location <- as.numeric(as.character(mylayout_Miserables$y_location))
colnames(mylayout_Miserables) <- c('x','y')
vlabels_1 <- get.vertex.attribute(gD, "name")
color_labels_1 <- getNodeColor(vlabels_1)
ggraph(mygraph_Miserables, layout = mylayout_Miserables) +
geom_edge_link(color = "orange", width=0.7) +
geom_node_point(size=5, color="gray50") +
geom_node_text(aes(label = vlabels_1), size=2, color="gray50", repel=T) +
theme_void()
'''
This new graph obtained by ggraph using layout = mylayout_Miserables doesn't provide the same structure of the graph provide directly by ggraph or by RCy3.
How can we explain that?
Alain Paris

Related

Bokeh Widget distorts plot with tile provider

When changing the color through the given widget first, the plot distorts. When first moving the map with the cursor and then changing the color, the plot does not distort. This only happens when a tile background is added. Thus the problem might lay in a difference in the underlaying projection / CRS of the plot and the tile that somehow gets changed in the background (?).
If you are able to find the problem, it would be great if you could also link to resources how you did that so I learn how to debug more in depth.
My browser: Brave (Chromium based)
Simple working example:
props to bigreddot as this working example is mostly based on his answer.
from bokeh.layouts import grid
from bokeh.models.widgets.inputs import ColorPicker
from bokeh.sampledata import us_states
from bokeh.plotting import *
from bokeh.tile_providers import get_provider, CARTODBPOSITRON
us_states = us_states.data.copy()
del us_states["HI"]
del us_states["AK"]
# separate latitude and longitude points for the borders
# of the states.
state_xs = [us_states[code]["lons"] for code in us_states]
state_ys = [us_states[code]["lats"] for code in us_states]
# init figure
p = figure(title="Plotting Points Example: The 5 Largest Cities in Texas",
toolbar_location="left", plot_width=1100, plot_height=700)
p.xgrid.grid_line_color = None
p.ygrid.grid_line_color = None
# Draw state lines
p.patches(state_xs, state_ys, fill_alpha=0.0,
line_color="#884444", line_width=1.5)
# Latitude and Longitude of 5 Cities
# ------------------------------------
# Austin, TX -------30.26° N, 97.74° W
# Dallas, TX -------32.77° N, 96.79° W
# Fort Worth, TX ---32.75° N, 97.33° W
# Houston, TX ------29.76° N, 95.36° W
# San Antonio, TX --29.42° N, 98.49° W
# Now group these values together into a lists of x (longitude) and y (latitude)
x = [-97.7431, -96.79, -97.33, -95.36, -98.49]
y = [30.26, 32.77, 32.75, 29.76, 29.42]
# add basemap and labels
tile_provider = get_provider(CARTODBPOSITRON)
p.add_tile(tile_provider)
points = p.circle(x, y, size=8, color='navy', alpha=1)
picker = ColorPicker(title=f"Point Color", color="navy")
picker.js_link("color", points.glyph, "fill_color")
# output to static HTML file
output_file("texas.html")
l = grid([p, picker], ncols=2, sizing_mode="fixed")
# show results
show(l)
The display via the grid is not the problem - it also occurs if you display the plot via:
show(column([p, picker]))
As indicated here one need to add
p.match_aspect = True
to the above code before the output. This resolves the issue of randomly changing ratios.

Split images losing color when saving RasterBrick array as *jpg

#Packages
library(raster)
library(rgeos)
library(rgdal)
library(jpeg)
I have a RGB color *jpg image:
## Open my RGB image
path<-"https://raw.githubusercontent.com/Leprechault/trash/main/IMG_191022_134242_0000_RGB.JPG" # Image path
download.file(path, "IMG_191022_134242_0000_RGB.JPG", mode = "wb")
rc<-stack(raster("IMG_191022_134242_0000_RGB.JPG")) #Open as a raster and stack
plot(rc)
When I try to split in 16 images of equal size:
# This function spatially aggregates the original raster
# it turns each aggregated cell into a polygon
# then the extent of each polygon is used to crop
# the original raster.
# The function returns a list with all the pieces
# it saves and plots each piece
# The arguments are:
# raster = raster to be chopped (raster object)
# ppside = pieces per side (integer)
# save = write raster (TRUE or FALSE)
# plot = do you want to plot the output? (TRUE or FALSE)
SplitRas <- function(raster,ppside,save,plot){
h <- ceiling(ncol(raster)/ppside)
v <- ceiling(nrow(raster)/ppside)
agg <- aggregate(raster,fact=c(h,v))
agg[] <- 1:ncell(agg)
agg_poly <- rasterToPolygons(agg)
names(agg_poly) <- "polis"
r_list <- list()
for(i in 1:ncell(agg)){
e1 <- extent(agg_poly[agg_poly$polis==i,])
r_list[[i]] <- crop(raster,e1)
}
if(save==T){
for(i in 1:length(r_list)){
options(max.print=999999)
#EBImage::writeImage(as.array(r_list[[i]]/255), paste0("sample_",i,".jpg",sep=""),quality = 100)
writeJPEG(as.array(r_list[[i]]/255), target = paste0("sample_",i,".jpg",sep=""),quality = 1,color.space="RGBA")
}
}
return(r_list)
}
#Slip RGB raster in 16 subimages
splitRBG<-SplitRas(raster=rc,ppside=4,save=TRUE)
#
The results are greyscaled images, eg. 1 (sample_1.jpg) of the 16 images:
I try to make a lot of changes in writeJPEG() function (something is wrong in the as.array(r_list[[i]]/255)code or in the color.space) without success, please any ideas?
Solution: split each RGB channel in a individual raster layer (rst.blue,rst.green nad rst.red) and stack before the crop operation with SplitRas custom function and works!!
#Packages
library(raster)
library(rgeos)
library(rgdal)
library(jpeg)
## download RGB image
path<-"https://raw.githubusercontent.com/Leprechault/trash/main/IMG_191022_134242_0000_RGB.JPG" # Image path
download.file(path, "IMG_191022_134242_0000_RGB.JPG", mode = "wb")
# Open jpeg file
jpg<-readJPEG("IMG_191022_134242_0000_RGB.JPG")
# Convert imagedata to raster
rst.blue <- raster(jpg[,,1])
rst.green <- raster(jpg[,,2])
rst.red <- raster(jpg[,,3])
rc<-stack(rst.blue, rst.green, rst.red)
# This function spatially aggregates the original raster
# it turns each aggregated cell into a polygon
# then the extent of each polygon is used to crop
# the original raster.
# The function returns a list with all the pieces
# it saves and plots each piece
# The arguments are:
# raster = raster to be chopped (raster object)
# ppside = pieces per side (integer)
# save = write raster (TRUE or FALSE)
# plot = do you want to plot the output? (TRUE or FALSE)
SplitRas <- function(raster,ppside,save,plot){
h <- ceiling(ncol(raster)/ppside)
v <- ceiling(nrow(raster)/ppside)
agg <- aggregate(raster,fact=c(h,v))
agg[] <- 1:ncell(agg)
agg_poly <- rasterToPolygons(agg)
names(agg_poly) <- "polis"
r_list <- list()
for(i in 1:ncell(agg)){
e1 <- extent(agg_poly[agg_poly$polis==i,])
r_list[[i]] <- crop(raster,e1)
}
if(save==T){
for(i in 1:length(r_list)){
writeJPEG(as.array(r_list[[i]]), target = paste0("sample_",i,".jpg",sep=""),quality = 1)
}
}
return(r_list)
}
#Slip RGB raster in 4 equal parts
splitRBG<-SplitRas(raster=rc,ppside=4,save=TRUE)
#

Recover elements from each cluster generated by scipy dendrogram

I'm building a dendrogram and truncating it to show only the largest 6 clusters. Also, the labeling is done via a simple leaf label function:
def llf(id):
return str(id)
tree = sch.dendrogram(Z, truncate_mode='lastp',
leaf_label_func=llf, p=6, show_contracted=False,
show_leaf_counts=False, leaf_rotation=90,
no_labels = False, orientation='right')
My output looks like this:
My goal is to replace the non descriptive labels for the leaves with the minimum value of the members from within that cluster. For example, if the top leaf is the cluster that contains the range from 10 to 1000, then I would like to replace '2468' with 10. The actual logic to replace the ticks in the plot is easy to implement:
fig, ax = plt.subplots()
mislabels = ["foo" for i in range(7)]
ax.set_xticklabels(mislabels, fontsize=10, rotation=45)
Any ideas regarding how to extract the values from within the leaders?
So far I'm able to map each singleton leaf to its cluster using fcluster. However, that only maps my initial 1230 points to a cluster. I need to map the point labeled as '2468' to its cluster and I'm not sure how to do that.
Thanks!
I found the way to do it
fig, ax = plt.subplots(2,2,figsize=(10,5))
ax = ax.ravel()
# [idx_plot[k]:, idx_plot[k]:]
for k, val in enumerate(linkages['ward']):
cluster_local = cluster_labels[val]['ward'][6]
leaders = sch.leaders(linkages['ward'][val], cluster_local)
dates_labels = dict()
for v, i in enumerate(leaders[1]):
date_idx = np.where(cluster_local == i)
dates_labels[leaders[0][v]] = (fechas[val][idx_plot[val]:][date_idx[0][0]].strftime('%y/%m'), fechas[val][idx_plot[val]:][date_idx[0][-1]].strftime('%y/%m'))
mislabels = [dates_labels[leaders[0][i]][0] + ', ' + dates_labels[leaders[0][i]][1] for i in range(6)]
yuca = sch.dendrogram(linkages['ward'][val], truncate_mode='lastp', ax=ax[k], leaf_label_func=llf, p=6, show_contracted=False, show_leaf_counts=False,
leaf_rotation=0, no_labels=False, orientation = 'right' )
# ax[k].set_xticklabels(mislabels, fontsize=10, rotation=90)
ax[k].set_yticklabels(mislabels, fontsize=10, rotation=0)
ax[k].set_title(val)
plt.tight_layout()
plt.show()

matplotlib set stacked bar chart labels

I am trying to create a stacked bar chart that groups data by operating system. I'm having trouble creating an individual label for each component in each bar.
What I'm trying to do is different from the example in the docs because in my data each category appears in only one bar, whereas in the example each bar contains one member of each category.
Currently I have this code
plt.cla()
plt.clf()
plt.close()
def get_cmap(n, name='hsv'):
'''Returns a function that maps each index in 0, 1, ..., n-1 to a distinct
RGB color; the keyword argument name must be a standard mpl colormap name.'''
return plt.cm.get_cmap(name, n)
fig = plt.figure(figsize=(18, 10), dpi=80)
# group by the prefixes for now
prefixes = []
indices = []
bars = []
legend = {}
cmap = get_cmap(len(os_counts.index) + 1)
k = 0
for i, prefix in enumerate(d):
indices.append(i)
if len(d[prefix]["names"]) == 1:
prefixes.append(d[prefix]["names"][0])
else:
prefixes.append(prefix)
#colors = [next(cycol) for j in range(len(d[prefix]["names"]))]
colors = [cmap(k + j) for j in range(len(d[prefix]["names"]))]
k += len(colors)
bar = plt.bar([i] * len(d[prefix]["names"]), d[prefix]["values"], color=colors, label=d[prefix]["names"])
bars.append(bar)
plt.xticks(rotation=90)
plt.ylabel("Frequency")
plt.xlabel("Operating System")
plt.xticks(indices, prefixes)
plt.legend()
plt.show()
Which produces this result. As you can see, the legend is created for the first colour within the bar and shows an array.
I think that each call to plt.bar gets one label. So, you are giving it a list as a label for each plt.bar call. If you want a label for every color, representing every operating system then I think the solution is to call plt.bar once for each color or os.

Create VTKpolydata using x,y,z coordinates

I am beginner in VTK. I have a dataset as x,y,z points and the value of each point. I want to create a vtkpolydata set using the points and create a contour using values of each point.
Please tell me how to create a vtkPolyData set using a given set of points in c++.
Thanks.
This example shows how to do both parts of your question:
http://www.vtk.org/Wiki/VTK/Examples/Cxx/GeometricObjects/PolyLine
Here is a script adapted from this blog to plot 3D xyz data:
'''
Modified Python 3 VTK script to Display 3D xyz data
Credits to : https://sukhbinder.wordpress.com/2013/09/17/python-vtk-script-to-display-3d-xyz-data/
Script name: xyzviewer.py
'''
import vtk
from numpy import random,genfromtxt,size
class VtkPointCloud:
def __init__(self, zMin=-10.0, zMax=10.0, maxNumPoints=1e6):
self.maxNumPoints = maxNumPoints
self.vtkPolyData = vtk.vtkPolyData()
self.clearPoints()
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputData(self.vtkPolyData)
mapper.SetColorModeToDefault()
mapper.SetScalarRange(zMin, zMax)
mapper.SetScalarVisibility(1)
self.vtkActor = vtk.vtkActor()
self.vtkActor.SetMapper(mapper)
def addPoint(self, point):
if (self.vtkPoints.GetNumberOfPoints() < self.maxNumPoints):
pointId = self.vtkPoints.InsertNextPoint(point[:])
self.vtkDepth.InsertNextValue(point[2])
self.vtkCells.InsertNextCell(1)
self.vtkCells.InsertCellPoint(pointId)
else:
r = random.randint(0, self.maxNumPoints)
self.vtkPoints.SetPoint(r, point[:])
self.vtkCells.Modified()
self.vtkPoints.Modified()
self.vtkDepth.Modified()
def clearPoints(self):
self.vtkPoints = vtk.vtkPoints()
self.vtkCells = vtk.vtkCellArray()
self.vtkDepth = vtk.vtkDoubleArray()
self.vtkDepth.SetName('DepthArray')
self.vtkPolyData.SetPoints(self.vtkPoints)
self.vtkPolyData.SetVerts(self.vtkCells)
self.vtkPolyData.GetPointData().SetScalars(self.vtkDepth)
self.vtkPolyData.GetPointData().SetActiveScalars('DepthArray')
def load_data(filename,pointCloud):
data = genfromtxt(filename,dtype=float,usecols=[0,1,2])
for k in range(size(data,0)):
point = data[k] #20*(random.rand(3)-0.5)
pointCloud.addPoint(point)
return pointCloud
if __name__ == '__main__':
import sys
if (len(sys.argv) < 2):
print ('Usage: xyzviewer.py itemfile')
sys.exit()
pointCloud = VtkPointCloud()
pointCloud=load_data(sys.argv[1],pointCloud)
# Renderer
renderer = vtk.vtkRenderer()
renderer.AddActor(pointCloud.vtkActor)
#renderer.SetBackground(.2, .3, .4)
renderer.SetBackground(0.0, 0.0, 0.0)
renderer.ResetCamera()
# Render Window
renderWindow = vtk.vtkRenderWindow()
renderWindow.AddRenderer(renderer)
# Interactor
renderWindowInteractor = vtk.vtkRenderWindowInteractor()
renderWindowInteractor.SetRenderWindow(renderWindow)
# Begin Interaction
renderWindow.Render()
renderWindow.SetWindowName("XYZ Data Viewer"+sys.argv[1])
renderWindowInteractor.Start()
You could run it as follows:
python xyzviewer.py filename
filename is the file that contains the xyz data.

Resources