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
|
|
|
|
|
|
|
|