Upside down labels

Hi,

I'm suffering from the same issue mentioned in this post:
https://git.skewed.de/count0/graph-tool/issues/174

Namely, I'm trying to draw a graph that includes a lot of self-looping
edges, and my labels are being printed upside down. If I remove the
self-loops the labels are shown the right way up.

Is there a fix for it?

Thanks,

Charlie

No, the bug is still open. It is probably a simple issue with the
fit_view code. It would help if you could provide a small self-contained
example which shows the problem.

Best,
Tiago

I am just now starting with graph_tool and having this issue as well. Has anyone yet resolved it?

This code shows the problem under Ubuntu 20.04 running under WSL2.

-caleb

###################################################3
import time
import threading
import queue
import numpy as np
import graph_tool as gt
import graph_tool.draw as gtd
from numpy.random import *
from numpy.linalg import norm
import sys, os, os.path
from gi.repository import Gtk, Gdk, GdkPixbuf, GObject, GLib

class Producer (threading.Thread):
    def __init__(self, threadID, name, q, priority=None):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.q = q
        self.priority = priority

    def run(self):
        print("Producer " + self.name + " has started")
        while True:
            time.sleep(.25)
            edge = (np.random.randint(0, 100), np.random.randint(0, 10))
            if edge[0] != edge[1]:
                self.q.put(edge)
                print(f'Producer {self.name} has added {edge} to the queue')

# This function will be called repeatedly by the GTK+ main loop, and we use it
# to update the vertex layout and perform the rewiring.
def update_state():
    print(f'update_state():')

    # Perform one iteration of the layout step, starting from the previous positions
    print(f' update_state(): iterate force-directed graph')
    gt.draw.sfdp_layout(graph, pos=pos, K=rest_length, init_step=step, max_iter=1)

    for i in range(100):
        if not node_queue.empty():
            edge = node_queue.get()
            print(f' update_state() has consumed {edge}. Adding to the graph')
            v0_idx = edge[0]
            v1_idx = edge[1]
            v0_name = f'v_{v0_idx}'
            v1_name = f'v_{v1_idx}'
            vertex_names = list(graph.vp['name'])
            if vertex_names[0] == '__TEMP_VERT__':
                graph.remove_vertex(graph.vertex(0))
                graph.remove_vertex(graph.vertex(0))
                graph.remove_vertex(graph.vertex(0))

            if v0_name in vertex_names:
                print(f' update_state() has found {v0_name} in the graph')
                v0_idx = list(vertex_names).index(v0_name)
            else:
                print(f' update_state() has not found {v0_name} in the graph')
                v0_idx = graph.add_vertex()
                graph.vertex_properties['name'][v0_idx] = v0_name
                graph.vertex_properties['size'][v0_idx] = 10.0 # np.random.randint(10,10)

            if v1_name in vertex_names:
                print(f' update_state() has found {v1_name} in the graph')
                v1_idx = list(vertex_names).index(v1_name)
            else:
                print(f' update_state() has not found {v1_name} in the graph')
                v1_idx = graph.add_vertex()
                graph.vertex_properties['name'][v1_idx] = v1_name
                graph.vertex_properties['size'][v1_idx] = 10.0 # np.random.randint(10,10)

            edge = graph.add_edge(v0_idx, v1_idx)
            print(f' update_state() has added ({v0_idx}: {v0_name}, {v1_idx}: {v1_name}) to the graph')

            gt.draw.sfdp_layout(graph, pos=pos, K=rest_length, init_step=step, max_iter=1)

            win.graph.fit_to_window(ink=True)

    # The following will force the re-drawing of the graph, and issue a
    # re-drawing of the GTK window.
    print(f' update_state(): rebuild / redraw)')
    win.graph.regenerate_surface()
    win.graph.queue_draw()

    # We need to return True so that the main loop will call this function more
    # than once.
    print(f'update_state() ends: {time.time()}')
    return True

if __name__ == "__main__":
    # Set up queue to pass edges to display (main) thread
    node_queue = queue.Queue()

    # Set up a worker thread to put edges in the queue
    threads = []
    producer = Producer(1, "prod1", node_queue, 6.) # create producer object with priority 6
    producer.start()
    threads.append(producer)

    # Set up some functional parameters
    seed(42)
    gt.seed_rng(42)

    # Create a graph to initialize the window width.
    # TODO: Is there a way to initialize an empty graph?
    # Initializing the GraphWindow without ay least
    # vertices and some edges seems to cause the
    # vertices and edges to be drawn with unpredictable
    # radii and thicknesses
    graph = gt.Graph(directed=True)
    v0, v1, v2 = graph.add_vertex(3)
    graph.add_edge(0, 1)
    graph.add_edge(0, 2)
    graph.add_edge(1, 2)
    graph.set_directed(True)

    prop_node_name = graph.new_vertex_property("string")
    graph.vertex_properties['name'] = prop_node_name
    prop_node_name[v0] = '__TEMP_VERT__'
    prop_node_name[v1] = '__TEMP_VERT__'
    prop_node_name[v2] = '__TEMP_VERT__'

    prop_node_size = graph.new_vertex_property("float")
    graph.vertex_properties['size'] = prop_node_size
    prop_node_size[v0] = 100
    prop_node_size[v1] = 100
    prop_node_size[v2] = 100

    # Parameters for the layout update
    step = 0.2 # move step
    rest_length = 15 # preferred edge length

    pos = gtd.sfdp_layout(graph, K=rest_length) # initial layout positions
    win = gtd.GraphWindow(
            graph,
            pos,
            geometry = (1600, 900),
            vertex_size = graph.vertex_properties['size'],
            vertex_text = graph.vertex_properties['name'],
            vertex_font_size = 30,
            vertex_rotation = 3.14159266368979323846,
            edge_text = 'relationship',
            edge_font_size = 30,
            edge_pen_width = 5,
            edge_text_parallel = True,
        )

    # Bind the function above as an 'idle' callback.
    cid = GLib.idle_add(update_state)

    # We will give the user the ability to stop the program by closing the window.
    win.connect("delete_event", Gtk.main_quit)

    # Actually show the window, and start the main loop.
    win.show_all()
    Gtk.main()