aysylu / loom

Graph library for Clojure. Mailing list https://groups.google.com/forum/#!forum/loom-clj
http://aysy.lu/loom/
887 stars 108 forks source link

Added ability to choose which attributes get passed to the dot graph node/edge. #42

Closed ducky427 closed 10 years ago

ducky427 commented 10 years ago

I've added the ability to filter out or add additional keys to the attributes of a dot node or a dot edge.

This is useful as some data is not really part of the loom node/edge but it is meta-data like shape, colour etc. This gives the user a way to add that information if needed.

I've also added a way to add some metadata for the global dot nodes and edges.

aysylu commented 10 years ago

Could you please provide some examples? What kind of metadata might one want to add for the global dot nodes and edges?

ducky427 commented 10 years ago

I've needed to add metadata like fontname, fontsize for the edges and nodes. For nodes, I've also had to add shape.

Usage would be something like:

(def g (graph [1 2] [2 3] {3 [4] 5 [6 7]} 7 8 9))

(dot g "graph.dot" {:node {:shape "Mrecord"
                           :fontname "Bitstream Vera Sans"
                           :fontsize "8"}
                    :edge {:fontsize 8
                           :fontname "Bitstream Vera Sans"
                           :arrowhead "vee"}})
ducky427 commented 10 years ago

Another example:

(def g (-> (digraph 0 1)
           (add-attr 0 :name "Alice" :type "Sender")
           (add-attr 1 :name "Bob" :type "Receiver")
           (add-edges [0 1])))

(defn get-node-props
  [x]
  {:label (format "{%s|%s}" (:type x) (:name x))})

(dot g "graph.dot" {:node-attrs get-node-props
                    :node {:shape "Mrecord"
                           :fontname "Bitstream Vera Sans"
                           :fontsize "8"}
                    :edge {:fontsize "8"
                           :fontname "Bitstream Vera Sans"
                           :arrowhead "vee"}})
ducky427 commented 10 years ago

For my last example, I could have easily used the node-label variable as well. But using the node-attrs variable, I have the ability to set other properties of the dot graph node itself like colour, etc. The same thing goes for edge-attrs.

I feel that these 2 are generalizations of node-label and edge-label.

aysylu commented 10 years ago

Thanks for the clarifications! I see your point. You're right that node-attrs and edge-attrs is more general and powerful, but I think we can eliminate the need for both by creating a transform-edge-attrs (similarly, for nodes) that will take all loom attrs and create a new graph with the added dot attrs (see below). What do you think?

(def transform-edge-attrs [g f]
  (reduce
      (fn [g e]
           ; this is an approximation, needs to actually work (see return values of attrs and add-attr)
           (add-attr g e (f (attrs g n1 n2)))
       g
      (edges g))
ducky427 commented 10 years ago

I agree. transform-edge-attrs and transform-node-attrs would be even more general.

I'll work up another pull request with those two functions along with remove-attrs function. This function would work the same as remove-attr except it would take a sequence of keys to remove.

aysylu commented 10 years ago

Sounds good, @ducky427. Let me know when the PR is ready.