graphviz cluster's label multiple lines - python

I'm using python+graphviz in order to create networking topologies out of the information contained in Racktables. I've succeded pretty well so far but I'm willing now to add multiple lines labels to a cluster (not a node).
For example, I have the following code with python:
for router in routers:
[...]
cluster_name = "cluster"+str(i)
router_label=router_name+"\n"+router_hw
c = gv.Graph(cluster_name)
c.body.append('label='+router_label)
When ever I run that program, I get the following:
ST120_CMS70_SARM
SARM
ST202_P9J70_SARM
SARM
Error: node "SARM" is contained in two non-comparable clusters "cluster1" and "cluster0"
But, if I change this router_label=router_name+"\n"+router_hw to this router_label=router_name+"_"+router_hw, I get no error and the topology gets drawn, but, of course, a one line label.
Any hint on this?
Many thanks!
Lucas

Ok, I've found the solution. The multiline label is achieved using HTML like labels, like the following one...
router_label="<"+router_name+"<BR />"+router_ip+">"
c = gv.Graph(cluster_name)
c.body.append('label='+router_label)
This code provides the following:
Thanks!
Lucas

Related

Plotting OpenStreetMap relations does not generate continous lines

All,
I have been working on an index of all MTB trails worldwide. I'm a Python person so for all steps involved I try to use Python modules.
I was able to grab relations from the OSM overpass API like this:
from OSMPythonTools.overpass import Overpass
overpass = Overpass()
def fetch_relation_coords(relation):
rel = overpass.query('rel(%s); (._;>;); out;' % relation)
return rel
rel = fetch_relation_coords("6750628")
I'm choosing this particular relation (6750628) because it is one of several that is resulting in discontinuous (or otherwise erroneous) plots.
I process the "rel" object to get a pandas.DataFrame like this:
elements = pd.DataFrame(rel.toJSON()['elements'])
"elements" looks like this:
The Elements pandas.DataFrame contains rows of the types "relation" (1 in this case), several of the type "way" and many of the type "node". It was my understanding that I would use the "relation" row, "members" column to extract the order of the ways (which point to the nodes), and use that order to make a list of the latitudes and longitudes of the nodes (for later use in leaflet), in the correct order, that is, the order that leads to continuous path on a map.
However, that is not the case. For this particular relation, I end up with the following plot:
If we compare that with the way the relation is displayed on openstreetmap.org itself, we see that it goes wrong (focus on the middle, eastern part of the trail). I have many examples of this happening, although there are also a lot of relations that do display correctly.
So I was wondering, what am I missing? Are there nodes with tags that need to be ignored? I already tried several things, including leaving out nodes with any tags, this does not help. Somewhere my processing is wrong but I don't understand where.
You need to sort the ways inside the relation yourself. Only a few relation types require sorted members, for example some route relations such as route=bus and route=tram. Others may have sorted members, such as route=hiking, route=bicycle etc., but they don't require them. Various other relations, such as boundary relations (type=boundary), usually don't have sorted members.
I'm pretty sure there are already various tools for sorting relation members, obviously this includes the openstreetmap.org website where this relation is shown correctly. Unfortunately I'm not able to point you to these tools but I guess a little bit research will reveal others.
If I opt to just plot the different way on top of each other, I indeed get a continuous plot (index contains the indexes for all nodes per way):
In the Database I would have preferred to have the nodes sorted anyway because I could use them to make a GPX file on the fly. But I guess I did answer my own question with this approach, thank you #scai for tipping me into this direction.
You could have a look at shapely.ops.linemerge, which seems to be smart enough to chain multiple linestrings even if the directions are inconsistent. For example (adapted from here):
from shapely import geometry, ops
line_a = geometry.LineString([[0,0], [1,1]])
line_b = geometry.LineString([[1,0], [2,5], [1,1]]) # <- switch direction
line_c = geometry.LineString([[1,0], [2,0]])
multi_line = geometry.MultiLineString([line_a, line_b, line_c])
merged_line = ops.linemerge(multi_line)
print(merged_line)
# output:
LINESTRING (0 0, 1 1, 2 5, 1 0, 2 0)
Then you just need to make sure that the endpoints match exactly.

How to use distancematrix function from Biopython?

I would like to calculate the distance matrix (using genetic distance function) on a data set using http://biopython.org/DIST/docs/api/Bio.Cluster.Record-class.html#distancematrix, but I seem to keep getting errors, typically telling me the rank is not of 2. I'm not actually sure what it wants as an input since the documentation never says and there are no examples online.
Say I read in some aligned gene sequences:
SingleLetterAlphabet() alignment with 7 rows and 52 columns
AEPNAATNYATEAMDSLKTQAIDLISQTWPVVTTVVVAGLVIRL...SKA COATB_BPIKE/30-81
AEPNAATNYATEAMDSLKTQAIDLISQTWPVVTTVVVAGLVIKL...SRA Q9T0Q8_BPIKE/1-52
DGTSTATSYATEAMNSLKTQATDLIDQTWPVVTSVAVAGLAIRL...SKA COATB_BPI22/32-83
AEGDDP---AKAAFNSLQASATEYIGYAWAMVVVIVGATIGIKL...SKA COATB_BPM13/24-72
AEGDDP---AKAAFDSLQASATEYIGYAWAMVVVIVGATIGIKL...SKA COATB_BPZJ2/1-49
AEGDDP---AKAAFDSLQASATEYIGYAWAMVVVIVGATIGIKL...SKA Q9T0Q9_BPFD/1-49
FAADDATSQAKAAFDSLTAQATEMSGYAWALVVLVVGATVGIKL...SRA COATB_BPIF1/22-73
which would be done by
data = Align.read("dataset.fasta","fasta")
But the distance matrix in Cluster.Record class does not accept this. How can I get it to work! ie
dist_mtx = distancematrix(data)
The short answer: You don't.
From the documentation:
A Record stores the gene expression data and related information
The Cluster object is used for gene expression data and not for MSA.
I would recommend using an external tool like MSARC which runs in Python as well.

(graph-tool) how to get the value from property map as an array

First, I'm newbie on python.
This is my code to get centrality betweenness using graph-tool module on python3
vertex_betweenness = betweenness(g)
then after I got a property map which contains the value I want.
I have tried this
for v in g.vertices():
print(vertex_betweenness[v])
I have tried to output it in some ways, print to the screen or create csv file but I cannot do it. I think I don't know about how to iterate through that property map.
I already googled for a few days but no pages can help me solve this question.
The function betweenness() returns two property maps, for both vertex and edge property maps (see the documentation at https://graph-tool.skewed.de/static/doc/centrality.html#graph_tool.centrality.betweenness). Your snipped will work if you modify it to
vertex_betweenness, edge_betweenness = betweenness(g)
In the docs, you can get the scalar values from a property map using the .get_array() method or .a. Seems to be the easiest way for me!

Print a line/multiline in a new layer over a map using Folium

I have tried Python folium library with impressive results, but there is one feature I am missing, or in any case I can't find: I want to print a multiline in a new layer over the map.
If I check de documentation, I can only find how to add markers and poligon markers. But about printing in a new layer, I can only find examples like this one.
I need something much simplier than that. I guess I could insert a GeoJSON with the multiline info in a similar way, but I haven't been able to even find which format should that GeoJSON have.
Any idea for getting my multiline?
PD: If you don't know how to achieve this using Python/Folium, I will be happy to hear what should I add to the Javascript output to get the multiline using Leaflet (that's what Folium library is using).
Some of the functions in the earlier example are now deprecated; apparently, the preferred method is now something like:
import folium
# Coordinates are 10 points on the great circle from Boston to
# San Francisco.
# Reference: http://williams.best.vwh.net/avform.htm#Intermediate
coordinates = [
[42.3581, -71.0636],
[42.82995815, -74.78991444],
[43.17929819, -78.56603306],
[43.40320216, -82.37774519],
[43.49975489, -86.20965845],
[41.4338549, -108.74485069],
[40.67471747, -112.29609954],
[39.8093434, -115.76190821],
[38.84352776, -119.13665678],
[37.7833, -122.4167]]
# Create the map and add the line
m = folium.Map(location=[41.9, -97.3], zoom_start=4)
my_PolyLine=folium.PolyLine(locations=coordinates,weight=5)
m.add_child(my_PolyLine)
# m.save('line_example_newer.html')
I finally found a way implemented in Folium in January 2014 and not documented. Its the line method.
Here appears an example provided by the author of this addon.
Neither of the above worked for me for adding lines as a new layer to a folium.Map object (using folium 0.11). What works for me is using folium.FeatureGroup:
coords = [[[42.3554025, -71.0728116], [42.3554142, -71.0728438]],
[[42.3554142, -71.0728438], [42.3554296, -71.0728738]]]
test_map = folium.Map([42.3554025, -71.0728116], tiles='Cartodb Positron', zoom_start=15)
fg = folium.FeatureGroup("Lines")
folium.PolyLine(coords).add_to(fg)
f.add_to(test_map)
folium.LayerControl(position='bottomright').add_to(test_map)
test_map
This prints a map that has a "Lines" layer which, when toggled, will show the lines plotted at the coordinates above.

error with gdalbuildvrt, in Python

I am new to python/GDAL and am running into perhaps a trivial issue. This may stem from the fact that I don't really understand how to use GDAL properly in python, or something careless, but even though I think I am following the help doc, I keep getting a syntax error when trying to use "gdalbuildvrt".
What I want to do is take several (amount varies for each set, call it N) geotagged 1-band binary rasters [all values are either 0 or 1] of different sizes (each raster in the set overlaps for the most part though), and "stack" them on top of each other so that they are aligned properly according to their coordinate information. I want this "stack" simply so I can sum the values and produce a 'total' tiff that has an extent to match the exclusive extent (meaning not just the overlap region) of all the original rasters. The resulting tiff would have values ranging from 0 to N, to represent the total number of "hits" the pixel in that location received over the course of the N rasters.
I was led to gdalbuildvrt [http://www.gdal.org/gdalbuildvrt.html] and after reading about it, it seemed that by using the keyword -separate, I would be able to achieve what I need. However, each time I try to run my program, I get a syntax error. The following shows two of the several different ways I tried calling gdalbuildvrt:
gdalbuildvrt -separate -input_file_list stack.vrt inputlist.txt
gdalbuildvrt -separate stack.vrt inclassfiles
Where inputlist.txt is a text file with a path to the tif on every line, just like the help doc specifies. And inclassfiles is a python list of the pathnames. Every single time, no matter which way I call it, I get a syntax error on the first word after the keywords (i.e. 'inputlist' in inputlist.txt, or 'stack' in stack.vrt).
Could someone please shed some light on what I might be doing wrong? Alternatively, does anyone know how else I could use python to get what I need?
Thanks so much.
gdalbuildvrt is a GDAL command line utility. From your example its a bit unclear how you actually run it, but when running from within Python you should execute it as a subprocess.
And in your first line you have the .vrt and the .txt in the wrong order. The textfile containing the files should follow directly after the -input_file_list.
From within Python you can call gdalbuildvrt like:
import os
os.system('gdalbuildvrt -separate -input_file_list inputlist.txt stack.vrt')
Note that the command is provided as a string. Using a Python list with the files can be done with something like:
os.system('gdalbuildvrt -separate stack.vrt %s') % ' '.join(data)
The ' '.join(data) part converts the list to a string with a space between the items.
Depending on how your GDAL is build, its sometimes possible to use wildcards as well:
os.system('gdalbuildvrt -separate stack.vrt *.tif')

Categories

Resources