Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling

Creating Pie chart based graph network

by KuntalBhusan (Acolyte)
on Sep 25, 2013 at 12:33 UTC ( #1055675=perlquestion: print w/replies, xml ) Need Help??
KuntalBhusan has asked for the wisdom of the Perl Monks concerning the following question:

Dear monks, Can you please guide me to create a graph network in perl Tk canvas where the nodes will be pie charts. There are modules like Tk::Graphitems and Tk::Chart but cannot be cross linked to create what I want. Looking forward for your help. Thanks, Kuntal

Replies are listed 'Best First'.
Re: Creating Pie chart based graph network
by choroba (Chancellor) on Sep 25, 2013 at 12:39 UTC
    What have you tried? Please, provide a sample code that shows how far you have got. Also, try to be more cooperative by providing links to the libraries: [mod://Tk::GraphItems]Tk::GraphItems, [mod://Tk::Chart]Tk::Chart; and by providing more information on what you need: What do you mean by crosslinking? Tk::Canvas is very powerful...
    لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

      I have a file consisting of some nodes (and edges) with the coordinates of the nodes. I also need to map some data specific to the nodes that are in form of pie charts.Here is a cropped snipped of the code.

      my $index = 0; if(open(FH, 'layout_coords')) { while($line = <FH>) { chomp($line); @arr = (); @arr = split('\t', $line ); my $label = $node_labels[$index]; my $x = $arr[0]; my $y = $arr[1]; my $x1 = $x + 20; my $y1 = $y + 20; $canvas->createOval($x,$y, $x1, $y1,-fill => 'green'); ## I need this +oval as a pie (I have the data for each node in form of a fixed array + like (2,3,1,3), etc.) $canvas->createText($x,$y, -text => $label); $index++; } } else { die "can't open file layout_coords: $!"; } close FH;
Re: Creating Pie chart based graph network
by kcott (Chancellor) on Sep 25, 2013 at 13:52 UTC

    G'day KuntalBhusan,

    For creating pie charts in a Tk::Canvas, you'll probably want to use $canvas->createArc(...) with various options, including -style => 'pieslice'. See Tk::Canvas: ARC ITEMS.

    I'm not really sure what you have in mind with respect to a "graph network". Tk::Canvas: LINE ITEMS seems like the obvious choice; however, you're also talking about cross-linking, so perhaps that's not what you want. You'll need to clarify what you mean in this regard.

    -- Ken

      Dear Ken,

      To put it in a more simpler way I need to get the output of the code below in form of a pie. Probably this will be a subroutine with the shown inputs that will be taken dynamically.can you help me in getting the values for $x1, $x2, $y1, $y2 in the code dynamically.

      use strict; use Tk; my $mw = new MainWindow(-title => 'Test'); my $canvas = $mw->Canvas(-width => 512, -height => 512)->pack; ## input ######################### my $start_x = 0; my $stary_y = 0; my $radius = 10; my @data = (4,5,2,6,8); ######################### my $slices = $data; my $slice_angle = 360/$slices; foreach my $this_value (@data) { my $x1 = ?; ## need to get dynamically my $y1 = ?; ## need to get dynamically my $x2 = ?; ## need to get dynamically my $y2 = ?; ## need to get dynamically $canvas->createArc( $x1, $y2, $x2, $y2, -start => 0, -extent => $slice +_angle, -style => 'pieslice', ); } MainLoop;

        Here's a working script that produces pie charts. See the notes at the end (which will probably make more sense after you've read the code and run the script).

        #!/usr/bin/env perl use strict; use warnings; use Tk; use List::Util 'sum'; my $pie_slice_colours = [ map { '#' . $_ } qw{ff0000 ffff00 00ff00 00ffff 0000ff ff00ff} + ]; my @pie_data = ( { centre_x => 50, centre_y => 150, radius => 40, values => [ 1, 2, 5, 3 ], fills => $pie_slice_colours, }, { centre_x => 220, centre_y => 105, radius => 100, values => [ 1, 8, 16, 4, 2 ], fills => $pie_slice_colours, }, { centre_x => 420, centre_y => 75, radius => 75, values => [ 1, 1, 2, 3, 5, 8 ], fills => $pie_slice_colours, }, { centre_x => 60, centre_y => 40, radius => 50, values => [ 32, 16, 8, 4, 2, 1 ], fills => $pie_slice_colours, }, ); my $mw = MainWindow->new; my $ctrl_F = $mw->Frame->pack(-side => 'bottom'); $ctrl_F->Button(-text => 'Quit', -command => sub { exit })->pack; my $canv_F = $mw->Frame->pack(-side => 'top', -fill => 'both', -expand + => 1); my $sc = $canv_F->Scrolled(Canvas => -scrollbars => 'osoe', -bg => '#ffffff', -width => 500, -height => 220, -scrollregion => [0, 0, 500, 220], ); $sc->pack(-fill => 'both', -expand => 1); my $canvas = $sc->Subwidget('canvas'); draw_pie(\$canvas, $_) for @pie_data; MainLoop; sub draw_pie { my ($c_ref, $data) = @_; my @coords = @{_get_pie_coords($c_ref, $data)}; $$c_ref->createArc(@coords, %$_) for @{_get_pie_slices($data)}; return; } sub _get_pie_coords { my ($c_ref, $data) = @_; my ($x, $y, $r) = @$data{qw{centre_x centre_y radius}}; my $h = $$c_ref->cget('-height'); return [$x - $r, $h - $y + $r, $x + $r, $h - $y - $r]; } sub _get_pie_slices { my $data = shift; my @values = @{$data->{values}}; my @fills = @{$data->{fills}}; my $total_values = sum @values; my $start = 90; return [ map { my $extent = 360 * $values[$_] / $total_values; $start -= $extent; +{ -extent => $extent, -start => $start, -fill => $fills[$ +_] } } 0 .. $#values ]; }


        • The Tk::Canvas coordinate system is an upside-down version of Cartesian coordinates. I personally don't like this: mainly because I find it counter-intuitive (x increases along the x-axis but y decreases along the y-axis). _get_pie_coords() takes (x,y) Cartesian coordinates for the centre of the pie chart, as well as the radius for the pie chart, and returns the coordinates required by createArc(). Feel free to revert to the Tk::Canvas coordinate system; however, you'll still need a function like this unless you're happy to specify (x1, y1, x2, y2) for every pie chart (and note those coordinates are outside the pie chart).
        • The placement of the pie slices is also somewhat counter-intuitive (at least, in my opinion). If you take the defaults, -start is called 0 (but, on a compass, it would be east, i.e. 90); and -extent (whose default value is 90) increases in an anticlockwise direction such that adding 90 to east results in north (on a compass, that would be south). Anyway, _get_pie_slices() works all that out for you: the first slice starts at 0 (north) and extends proportionally in a clockwise fashion; subsequent slices continue to be added in the same manner.
        • Unless you have a particular reason not to, you probably want (at least optional) scrollbars. Note that Scrolled(Canvas => ...) is actually a composite widget and the Tk::Canvas widget is a component of this accessed with Subwidget('canvas').
        • I've added six colours ($pie_slice_colours) and reused them for each pie chart. You may need more colours. You may not want the same colours for every chart: set the value of the fills key how you want it.
        • Everything else should either be fairly straightforward Perl or documented via links already supplied.

        -- Ken

Re: Creating Pie chart based graph network
by SuicideJunkie (Vicar) on Sep 25, 2013 at 14:54 UTC

    Drawing a simple example manually would probably help a lot.

    My impression is you want something that looks like:

    ClientA _____Master ___Link /\________/ | \ / | \ __Archive \/ |___| |_______| | |_______/ \ | \ | \_|_/ \__/ /\____\/ __ __/ / \/ \__/Client B

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1055675]
Approved by kcott
Front-paged by sparkyichi
[Corion]: (maybe I should write this up as a SoPW) - currently, the "most efficient" data structure I come up with is a single array which I scan for the first fitting one-shot. Not efficient but I don't expect more than five outstanding one-shots anyway
[choroba]: can't you create a meta-key corresponding to the disjunction of the events?
[robby_dobby]: Corion: Heh. This whole thing smells of Strategy Pattern or MVC pattern.
[Corion]: And performance linear to the number of registered one-shots doesn't feel that bad. Maybe I should collect statistics on how many callbacks are outstanding ;)
[Corion]: choroba: Yes, but the longer I thought about efficient hashes mapping the event type back to their callbacks, and how to keep them in sync, the more I thought that all that optimization might just not be worth it, even if it's horribly inelegant
[Lady_Aleena]: My biggest problem with hashes at the moment is one with 2,501 keys.
[choroba]: how many event types are there?
[Corion]: Also I found that I can't conveniently weaken an array slot, which also is inconvenient, as I want my one-shots to disappear if the caller discards them
[Corion]: choroba: Currently two or three that my program handles (WWW::Mechanize:: Chrome), but there might be more that become interesting
[Corion]: But I don't expect more than 100 to be active at the same time, so I'm not really sure if there is a not-too-fancy data structure that is maintained with few lines of code where the performance is better than the linear scan ;)

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (7)
As of 2017-05-29 07:56 GMT
Find Nodes?
    Voting Booth?