File Coverage

/.cpan/build/Simulation-Automate-1.0.1-vTiPpZ/blib/lib/Simulation/Automate/Analysis.pm
Criterion Covered Total %
statement 15 223 6.7
branch 0 72 0.0
condition 0 21 0.0
subroutine 5 13 38.4
pod 0 8 0.0
total 20 337 5.9


line stmt bran cond sub pod time code
1             package Simulation::Automate::Analysis;
2              
3 2     2   8 use vars qw( $VERSION );
  2         4  
  2         107  
4             $VERSION = "1.0.1";
5              
6             #################################################################################
7             # #
8             # Copyright (C) 2000,2002 Wim Vanderbauwhede. All rights reserved. #
9             # This program is free software; you can redistribute it and/or modify it #
10             # under the same terms as Perl itself. #
11             # #
12             #################################################################################
13              
14             #=headers
15              
16             #Package for statistical analysis of SynSim results.
17             #Based on create_histograms.pl
18             #This is not finished by far, but already useful.
19             #This module is used by SynSim.pm and PostProcessors.pm
20              
21             #$Id$
22              
23             #=cut
24              
25 2     2   9 use strict;
  2         3  
  2         52  
26 2     2   8 use Carp;
  2         4  
  2         117  
27 2     2   1494 use FileHandle;
  2         23506  
  2         12  
28 2     2   830 use Exporter;
  2         5  
  2         4775  
29              
30             @Simulation::Automate::Analysis::ISA = qw(Exporter);
31             @Simulation::Automate::Analysis::EXPORT = qw(
32             &calc_statistics
33             &build_histograms
34             );
35              
36             my $v=0;
37             my %bins=();
38             my %spec=();
39             my %trend=();
40             my @parnames;
41             my @parunits;
42             my $info;
43             my @info;
44             my $nlots=0;
45             my @pars=();
46             my $ncols;
47             my $data=0;
48             my $l=0;
49             my $nsites=0;
50              
51             my $binfile;
52             my $title;
53             my $nbins;
54             my $min;
55             my $max;
56             my $uctitle;
57             my $lctitle;
58             my $log='';
59              
60              
61             ################################################################################
62             ##
63             ## PROCESS THE DATAFILE
64             ##
65             sub process_datafile {
66 0     0 0   my $binfile=shift;
67 0           my %trend=();
68 0           push @{$trend{DIFF}},0;
  0            
69              
70 0 0         open(IN,"<$binfile")||carp "Can't open $binfile: $!\n";
71 0           my $j=0;
72 0           $nlots++;
73 0           my $in_table=0;
74 0           $info=0;
75 0           @info=();
76              
77             #if just 1 column:
78 0           my $par=$pars[0];
79 0 0         if($par =~/dif/i){$par='DIFF'};
  0            
80             #else{$par='PAR'}
81              
82 0           my $datacol=$pars[1];
83              
84 0           while() {
85 0 0         /^\s+$/ && next;
86 0 0         /^\s*\#/ && next;
87 0           chomp;
88 0           s/\s+$//;
89 0           s/^\s+//;
90 0           my @row=split(/[\s\t]+/,$_);
91 0           my $ri=0;
92              
93             #foreach my $par (@pars) {
94             #push @{$trend{$par}},$row[$ri];
95             #$ri++
96             #}
97              
98             #if just 1 column:
99             #print "$row[$datacol-1]\n";
100 0           push @{$trend{$par}},$row[$datacol-1];
  0            
101             #print STDERR "$par ($datacol) : ",$row[$datacol-1],"\n";
102 0           $nsites++;
103              
104             }#while
105              
106 0 0         if($v){print "# Done parsing $binfile: $nsites sites\n";}
  0            
107 0           close IN;
108              
109              
110 0 0         if (exists $trend{DIFF}) {
111 0           foreach my $i (0..@{$trend{DIFF}}-2) {
  0            
112 0           ${$trend{DIFF}}[$i]=${$trend{DIFF}}[$i+1]-${$trend{DIFF}}[$i];
  0            
  0            
  0            
113             }
114 0           pop @{$trend{DIFF}};
  0            
115             }
116              
117 0 0         if($log=~/log/i) {
118 0           foreach my $logkey (sort keys %trend) {
119 0 0         ($logkey !~/log/i) && next;
120 0           foreach my $i (0..@{$trend{$logkey}}-1) {
  0            
121             #carp "$i:${$trend{$logkey}}[$i]\n";
122 0 0         if(${$trend{$logkey}}[$i]>0){
  0            
123 0           ${$trend{$logkey}}[$i]=log(${$trend{$logkey}}[$i])/log(10);
  0            
  0            
124             } else {
125 0           ${$trend{$logkey}}[$i]='';
  0            
126             }
127             } # each $i
128             } # each $logkey
129             } # if LOG
130 0           return(\%trend);
131             } # END of process_datafile
132              
133              
134             ##############################################################################################
135              
136             sub calc_average {
137 0     0 0   my $value_array_ref=shift;
138              
139 0           my $avg=0;
140 0           my $stdev=0;
141 0   0       my $pct_bad=shift||0; # means we throw 50% of the devices away as outliers to calculate the rough mean
142 0   0       my $delta=shift||2e10; # means we take all devices within 20% deviation from actual mean
143              
144 0           my @tmp_values=sort numerical @{$value_array_ref};
  0            
145              
146 0           my $min=$tmp_values[0];
147 0           my $max=$tmp_values[@tmp_values-1];
148             #print "#all values:".scalar(@tmp_values)."\n";
149 0           my $n_samp=scalar @tmp_values;
150 0           my $n_iter=int($n_samp*0.5*$pct_bad);
151              
152             #1. allow $pct_bad bad devices
153 0 0         if($n_iter>0){
154              
155 0           foreach my $iter (1..$n_iter) {
156 0           pop @tmp_values;
157 0           shift @tmp_values;
158             }
159             }
160             #2. calc approx average of these
161 0           my $tmpav=0;
162 0           foreach my $tmp_val (@tmp_values) {
163             #print "$tmp_val\n";
164 0           $tmpav+=$tmp_val;
165             }
166             #print "tmpav*ngood:$tmpav\n";
167 0           $tmpav/=@tmp_values;
168             #print "tmpav:$tmpav\n";
169             #3. reject based on $tmpav and $delta; calc actual average
170 0           my $n_good=0;
171 0           my $sumx=0;
172 0           my $sumxsq=0;
173 0           foreach my $tmp_val (@$value_array_ref) {
174             #print "$tmp_val ";
175 0 0 0       if ($tmpav==0||abs(($tmp_val-$tmpav)/$tmpav)<=$delta) {
176 0           $sumx+=$tmp_val;
177 0           $sumxsq+=$tmp_val*$tmp_val;
178 0           $n_good++;
179             #print " :pass\n";
180             } #else {print " :fail\n";}
181             }
182 0 0         if ($n_good>1) {
183 0           $avg=$sumx/$n_good;
184             # calc stdev: stdev^2=(n*sum(xi^2)-sum(xi)^2)/n/(n-1)
185 0           $stdev=sqrt($sumxsq/($n_good-1)-$sumx*$sumx/($n_good*($n_good-1)));
186             } else {
187 0           $avg='';
188 0           $stdev='';}
189 0 0         if($v){print "# samples:$n_good\n";}
  0            
190 0 0         if($v){print "# AVG:$avg\tSTDEV:$stdev\n";}
  0            
191 0           return [$avg,$stdev,$min,$max];
192             }
193              
194             ##############################################################################################
195              
196 0     0 0   sub numerical { $a<=>$b }
197              
198             ##############################################################################################
199              
200             sub min {
201 0     0 0   my $a=shift;
202 0           my $b=shift;
203 0           my $min=abs(($a+$b)-abs($a-$b))/2;
204 0           return $min;
205             }
206              
207              
208             ################################################################################
209             # Build Histogram
210              
211             sub build_histogram {
212             # reference to array with values
213 0     0 0   my $value_array_ref=shift;
214              
215             # number of bins, number of sigmas for with ofinterval
216 0           my $nbins=shift;
217 0           my $nsigma=shift;
218 0   0       my $min=shift||'CALC';
219 0   0       my $max=shift||'CALC';
220              
221             # calculate mean & sigma and min/max/binwidth
222 0           my ($avg,$stdev)=@{&calc_average($value_array_ref)};
  0            
223 0 0         if(not $nsigma){$nsigma=6}
  0            
224             #if((not $min) && ($min!=0)){
225 0 0         if($min=~/C/) {
226 0           $min=$avg-$nsigma*$stdev;
227 0 0         if($stdev>$avg) {
228             # in this case take min and max value of set
229 0           $min=${$value_array_ref}[0];
  0            
230 0           foreach my $val (@{$value_array_ref}) {
  0            
231 0 0         if($val<$min){$min=$val}
  0            
232             }
233             }
234             }
235 0 0         if($v){print "# MIN:$min\n";}
  0            
236 0 0         if( $max=~/C/) {
237 0           $max=$avg+$nsigma*$stdev;
238              
239 0           if(1||$stdev>$avg) {
240             # in this case take min and max value of set
241 0           $max=${$value_array_ref}[0];
  0            
242 0           foreach my $val (@{$value_array_ref}) {
  0            
243 0 0         if($val>$max){$max=$val}
  0            
244             }
245             }
246             }
247 0 0         if($v){print "# MAX:$max\n";}
  0            
248              
249             #For traffic studies, all values are always positive.
250 0 0         if($min<0){$min=0;}
  0            
251 0           my $binwidth=($max-$min)/$nbins;
252              
253             ## first sort
254              
255 0           my @tmp_values=sort numerical @$value_array_ref;
256 0           my $i=0;
257              
258 0           my $n_samp=scalar @tmp_values;
259 0           my @counts;
260 0           for my $i (0..$nbins+1) {
261 0           $counts[$i]=0;
262             }
263 0           my $bin=1;
264 0           my $binh;
265             my $binl;
266              
267 0           foreach my $val (@tmp_values) {
268              
269 0           $binh=$bin*$binwidth+$min;
270 0           $binl=($bin-1)*$binwidth+$min;
271              
272 0 0 0       if($val>=$binl&&$val<$binh) { # if inside bin
    0          
    0          
273 0           $counts[$bin]++;
274              
275             }
276             elsif($val<$min) { # if lower than min
277             #print "lower:$counts[0]\n";
278 0           $counts[0]++;
279             }
280 0           elsif($val>=$binh) { # if higher than bin, next bin
281 0   0       while($val >=$binh && $bin<$nbins) {
282             #print STDERR "$bin\n";
283 0 0         if($bin<$nbins) {
  0            
284 0           $bin++; #max. 25
285 0           $counts[$bin]=0;
286             }else{$bin=$nbins}
287             #so $bin <=25
288 0           $binl=($bin-1)*$binwidth+$min; #WV15072002
289 0           $binh=$bin*$binwidth+$min;
290             }
291              
292 0 0         if($val<$binh){$counts[$bin]++} # if lower than bin+1
  0 0          
    0          
293 0           elsif($val>=$max) {
294             #print "higher:$counts[$nbins]\n";
295 0           $counts[$nbins+1]++
296             } elsif(not defined $counts[$bin] ) {$counts[$bin]=0}
297             } else {print STDERR "#$binl#$val#$binh#\n";}
298             }
299              
300 0           return [\@counts,$min,$binwidth,$avg,$stdev];
301             }
302              
303             #------------------------------------------------------------------------------
304             sub get_common_args {
305 0 0   0 0   if(not @_){die 'arguments: $datafilename,\@parameters,$title,$log'."\n"}
  0            
306              
307 0           $binfile=shift;
308 0           @pars= @{shift(@_)}; # deref an array ref
  0            
309 0   0       $title=shift||'';
310 0   0       $log=shift||'';
311             #carp "LOG:$log\n";
312 0           $uctitle=uc($title);
313 0           $lctitle=lc($title);
314 0           $lctitle=~s/\s+/_/g;
315 0 0         if($v){print "# $uctitle DATA ANALYSIS\n\n";}
  0            
316 0           return [@_];
317             }
318             #------------------------------------------------------------------------------
319             sub calc_statistics {
320 0     0 0   my @specific=@{&get_common_args(@_)};
  0            
321 0           my $reject=shift @specific;
322 0           my $delta=shift @specific;
323 0           my %trend=%{&process_datafile($binfile)};
  0            
324 0           my %stats=();
325              
326             #foreach my $par (@pars) {
327             #just 1 par
328 0           my $par=$pars[0];
329             #($par=~/none/i) && next;
330 0 0         if($v){print "# Processing $par\n";}
  0            
331 0           ($stats{$par}{AVG},$stats{$par}{STDEV},$stats{$par}{MIN},$stats{$par}{MAX})=@{&calc_average(\@{$trend{$par}})};
  0            
  0            
332             #} # foreach par
333              
334 0           return( \%stats );
335              
336             } # END of calc_statistics
337              
338             #------------------------------------------------------------------------------
339             sub build_histograms {
340              
341 0     0 0   my @specific=@{&get_common_args(@_)};
  0            
342 0           $nbins=shift @specific;
343 0           $min =shift @specific;
344 0           $max =shift @specific;
345              
346 0           my %trend=%{&process_datafile($binfile)};
  0            
347              
348 0           my %hists=();
349              
350              
351 0           my $par=$pars[0];
352              
353 0 0         print "# Processing $par\n" if $v;
354              
355 0           my @tmpa=@{&build_histogram(\@{$trend{$par}},$nbins,3,$min,$max)};
  0            
  0            
356 0           my $tmp=$tmpa[0];
357 0           my $minbin=$tmpa[1];
358 0           my $binwidth=$tmpa[2];
359 0           my $avg=$tmpa[@tmpa-2];
360 0           my $stdev=$tmpa[@tmpa-1];
361 0           my $bi=0;
362              
363 0           foreach my $bin (@{$tmp}) {
  0            
364 0 0         if($bi>0){
365 0 0         if($v){print $minbin+($bi-1)*$binwidth,"\t$bin\n";}
  0            
366 0           push @{$hists{$par}},{BIN=>$minbin+($bi-1)*$binwidth,COUNT=>$bin};
  0            
367             }
368 0           $bi++;
369             }
370              
371              
372              
373 0           return( \%hists );
374              
375             } # END of build_histograms
376             #------------------------------------------------------------------------------
377             1;