File Coverage

blib/lib/SNA/Network/Filter/Guess.pm
Criterion Covered Total %
statement 71 71 100.0
branch 10 16 62.5
condition 2 4 50.0
subroutine 12 12 100.0
pod 3 3 100.0
total 98 106 92.4


line stmt bran cond sub pod time code
1             package SNA::Network::Filter::Guess;
2              
3 14     14   220 use strict;
  14         21  
  14         453  
4 14     14   53 use warnings;
  14         14  
  14         443  
5              
6             require Exporter;
7 14     14   48 use base qw(Exporter);
  14         15  
  14         1159  
8             our @EXPORT = qw(load_from_gdf new_from_gdf save_to_gdf);
9              
10 14     14   67 use Carp;
  14         14  
  14         735  
11 14     14   82 use English;
  14         13  
  14         55  
12 14     14   12257 use List::MoreUtils qw(pairwise);
  14         12576  
  14         13876  
13              
14              
15             =head1 NAME
16              
17             SNA::Network::Filter::Guess - load and save networks from/to Guess .gdf files
18              
19              
20             =head1 SYNOPSIS
21              
22             use SNA::Network;
23              
24             my $net = SNA::Network->new();
25             $net->load_from_gdf($filename);
26             ...
27             # shortcut
28             my $net = SNA::Network->new_from_gdf($filename);
29             ...
30             $net->save_to_gdf(filename => $filename, edge_fields => ['weight']);
31              
32              
33             =head1 DESCRIPTION
34              
35             This enables import/export to the GUESS data format.
36             See L for details about the format.
37              
38              
39             =head1 METHODS
40              
41             The following methods are added to L.
42              
43             =head2 load_from_gdf
44              
45             load a network from a passed filename.
46             Nodes and edges are created with the fields specified in the file.
47             They are accessible as hash entries of the objects.
48              
49             =cut
50              
51             sub load_from_gdf {
52 3     3 1 11 my ($self, $filename) = @_;
53 3 50       99 open my $GDF_FILE, '<', $filename or croak "cannot open '$filename': $OS_ERROR\n";
54            
55 3         4 my $line;
56            
57             # search start of node definitions
58             START:
59 3         44 while (defined($line = <$GDF_FILE>)) {
60 3 50       18 last START if $line =~ m/^nodedef>/;
61             }
62 3         9 $line =~ m/^nodedef> (.+)$/;
63 3         17 my ($name, $label, @fields) = split /,/, $1;
64 3         7 foreach (@fields) {
65 6         25 s/\s*(\w+).*/$1/
66             }
67            
68             # read nodes and create graph nodes
69             NODES:
70 3         10 while (defined($line = <$GDF_FILE>)) {
71 15 100       33 last NODES if $line =~ m/^edgedef> (.+)$/;
72              
73             #chomp $line;
74 12         25 $line =~ s/\s//g;
75 12         29 my ($node_number, $node_name, @field_values) = split ',', $line;
76            
77             $self->create_node_at_index(
78             index => _extract_index($node_number),
79             name => $node_name,
80 12     24   19 (pairwise { ($a, $b) } @fields, @field_values)
  24         54  
81             );
82             }
83            
84             # read arcs and create graph edges
85 3         7 $line =~ m/^edgedef> (.+)$/;
86 3         4 my ($node1, $node2);
87 3         8 ($node1, $node2, @fields) = split /,/, $1;
88 3         6 foreach (@fields) {
89 6         16 s/\s*(\w+).*/$1/
90             }
91            
92             EDGES:
93 3         8 while (defined($line = <$GDF_FILE>)) {
94 20 100       66 last EDGES unless $line =~ m/\s*\w+,\s*\w+/;
95            
96 18         41 $line =~ s/\s//g;
97 18         43 my ($source, $target, @field_values) = split ',', $line;
98             $self->create_edge(
99             source_index => _extract_index($source),
100             target_index => _extract_index($target),
101 18     36   26 (pairwise { ($a, $b) } @fields, @field_values)
  36         78  
102             );
103             }
104              
105 3 50       32 close $GDF_FILE or croak "cannot close '$filename': $OS_ERROR\n";
106             }
107              
108              
109             =head2 new_from_gdf
110              
111             Returns a newly created network from a passed filename.
112             Nodes and edges are created with the fields specified in the file.
113             They are accessible as hash entries of the objects.
114              
115             =cut
116              
117             sub new_from_gdf {
118 1     1 1 296 my ($package, $filename) = @_;
119 1         3 my $net = $package->new;
120 1         3 $net->load_from_gdf($filename);
121 1         2 return $net;
122             }
123              
124              
125              
126             =head2 save_to_gdf
127              
128             Saves the current network to a GDF file.
129             The named parameters are B,
130             and optionally array references in B and B,
131             that will write the corresponding hash entries of the objects into the file.
132              
133             =cut
134              
135             sub save_to_gdf {
136 1     1 1 284 my ($self, %params) = @_;
137 1 50       4 croak "no filename passed to save_to_gdf!" unless $params{filename};
138 1   50     5 $params{node_fields} ||= [];
139 1   50     3 $params{edge_fields} ||= [];
140              
141 1 50       99 open my $GDF_FILE, '>', $params{filename} or croak "cannot open '$params{filename}': $OS_ERROR\n";
142              
143             # process nodes
144 1         3 printf $GDF_FILE "nodedef> %s\n", join ',', ('name', 'label', @{ $params{node_fields} });
  1         17  
145              
146 1         4 foreach my $node ($self->nodes()) {
147 8         15 printf $GDF_FILE "%s\n", join(',',
148             'n' . ($node->index() + 1),
149             $node->{name},
150 4         12 map { $node->{$_} } @{ $params{node_fields} }
  4         6  
151             );
152             }
153              
154             # process edges
155 1         3 printf $GDF_FILE "edgedef> %s\n", join ',', qw(node1 node2 directed), @{ $params{edge_fields} };
  1         2  
156              
157 1         3 foreach my $edge ($self->edges()) {
158 12         17 printf $GDF_FILE "%s\n", join(',',
159 6         16 ( map { 'n' . ($_->index() + 1) } ($edge->source(), $edge->target()) ),
160             'true',
161 6         10 ( map { $edge->{$_} } @{ $params{edge_fields} } )
  6         7  
162             );
163             }
164            
165 1 50       50 close $GDF_FILE or croak "cannot close '$params{filename}': $OS_ERROR\n";
166             }
167              
168              
169             sub _extract_index {
170 48     48   40 my ($node_name) = @_;
171 48         67 $node_name =~ m/\D+(\d+)/;
172 48         209 return $1 - 1;
173             }
174              
175              
176             =head1 AUTHOR
177              
178             Darko Obradovic, C<< >>
179              
180             =head1 BUGS
181              
182             Please report any bugs or feature requests to C, or through
183             the web interface at L. I will be notified, and then you'll
184             automatically be notified of progress on your bug as I make changes.
185              
186              
187              
188              
189             =head1 SUPPORT
190              
191             You can find documentation for this module with the perldoc command.
192              
193             perldoc SNA::Network
194              
195              
196             You can also look for information at:
197              
198             =over 4
199              
200             =item * RT: CPAN's request tracker
201              
202             L
203              
204             =item * AnnoCPAN: Annotated CPAN documentation
205              
206             L
207              
208             =item * CPAN Ratings
209              
210             L
211              
212             =item * Search CPAN
213              
214             L
215              
216             =back
217              
218              
219             =head1 COPYRIGHT & LICENSE
220              
221             Copyright 2009 Darko Obradovic, all rights reserved.
222              
223             This program is free software; you can redistribute it and/or modify it
224             under the same terms as Perl itself.
225              
226              
227             =cut
228              
229             1; # End of SNA::Network::Filter::Guess
230