File Coverage

blib/lib/Tk/ForDummies/Graph/Boxplots.pm
Criterion Covered Total %
statement 15 15 100.0
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 20 20 100.0


line stmt bran cond sub pod time code
1             package Tk::ForDummies::Graph::Boxplots;
2            
3 1     1   11321 use warnings;
  1         2  
  1         45  
4 1     1   8 use strict;
  1         3  
  1         36  
5 1     1   7 use Carp;
  1         2  
  1         106  
6            
7             #==================================================================
8             # Author : Djibril Ousmanou
9             # Copyright : 2010
10             # Update : 19/06/2010 22:47:22
11             # AIM : Create bars graph
12             #==================================================================
13            
14 1     1   6 use vars qw($VERSION);
  1         2  
  1         76  
15             $VERSION = '1.06';
16            
17 1     1   7 use base qw/Tk::Derived Tk::Canvas::GradientColor/;
  1         2  
  1         782  
18             use Tk::Balloon;
19            
20             use Tk::ForDummies::Graph::Utils qw (:DUMMIES);
21             use Tk::ForDummies::Graph qw (:DUMMIES);
22            
23             Construct Tk::Widget 'Boxplots';
24            
25             sub Populate {
26            
27             my ( $CompositeWidget, $RefParameters ) = @_;
28            
29             # Get initial parameters
30             $CompositeWidget->{RefInfoDummies} = _InitConfig();
31            
32             $CompositeWidget->SUPER::Populate($RefParameters);
33            
34             $CompositeWidget->Advertise( 'GradientColor' => $CompositeWidget );
35             $CompositeWidget->Advertise( 'canvas' => $CompositeWidget->SUPER::Canvas );
36             $CompositeWidget->Advertise( 'Canvas' => $CompositeWidget->SUPER::Canvas );
37            
38             # remove highlightthickness if necessary
39             unless ( exists $RefParameters->{-highlightthickness} ) {
40             $CompositeWidget->configure( -highlightthickness => 0 );
41             }
42            
43             $CompositeWidget->ConfigSpecs(
44             -title => [ 'PASSIVE', 'Title', 'Title', undef ],
45             -titlecolor => [ 'PASSIVE', 'Titlecolor', 'TitleColor', 'black' ],
46             -titlefont =>
47             [ 'PASSIVE', 'Titlefont', 'TitleFont', $CompositeWidget->{RefInfoDummies}->{Font}{DefaultTitle} ],
48             -titleposition => [ 'PASSIVE', 'Titleposition', 'TitlePosition', 'center' ],
49             -titleheight =>
50             [ 'PASSIVE', 'Titleheight', 'TitleHeight', $CompositeWidget->{RefInfoDummies}->{Title}{Height} ],
51            
52             -xlabel => [ 'PASSIVE', 'Xlabel', 'XLabel', undef ],
53             -xlabelcolor => [ 'PASSIVE', 'Xlabelcolor', 'XLabelColor', 'black' ],
54             -xlabelfont =>
55             [ 'PASSIVE', 'Xlabelfont', 'XLabelFont', $CompositeWidget->{RefInfoDummies}->{Font}{DefaultLabel} ],
56             -xlabelposition => [ 'PASSIVE', 'Xlabelposition', 'XLabelPosition', 'center' ],
57             -xlabelheight => [
58             'PASSIVE', 'Xlabelheight',
59             'XLabelHeight', $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{xlabelHeight}
60             ],
61             -xlabelskip => [ 'PASSIVE', 'Xlabelskip', 'XLabelSkip', 0 ],
62            
63             -xvaluecolor => [ 'PASSIVE', 'Xvaluecolor', 'XValueColor', 'black' ],
64             -xvaluevertical => [ 'PASSIVE', 'Xvaluevertical', 'XValueVertical', 0 ],
65             -xvaluespace => [
66             'PASSIVE', 'Xvaluespace',
67             'XValueSpace', $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{ScaleValuesHeight}
68             ],
69             -xvalueview => [ 'PASSIVE', 'Xvalueview', 'XValueView', 1 ],
70             -yvalueview => [ 'PASSIVE', 'Yvalueview', 'YValueView', 1 ],
71             -xvaluesregex => [ 'PASSIVE', 'Xvaluesregex', 'XValuesRegex', qr/.+/ ],
72            
73             -ylabel => [ 'PASSIVE', 'Ylabel', 'YLabel', undef ],
74             -ylabelcolor => [ 'PASSIVE', 'Ylabelcolor', 'YLabelColor', 'black' ],
75             -ylabelfont =>
76             [ 'PASSIVE', 'Ylabelfont', 'YLabelFont', $CompositeWidget->{RefInfoDummies}->{Font}{DefaultLabel} ],
77             -ylabelposition => [ 'PASSIVE', 'Ylabelposition', 'YLabelPosition', 'center' ],
78             -ylabelwidth => [
79             'PASSIVE', 'Ylabelwidth',
80             'YLabelWidth', $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{ylabelWidth}
81             ],
82            
83             -yvaluecolor => [ 'PASSIVE', 'Yvaluecolor', 'YValueColor', 'black' ],
84            
85             -labelscolor => [ 'PASSIVE', 'Labelscolor', 'LabelsColor', undef ],
86             -valuescolor => [ 'PASSIVE', 'Valuescolor', 'ValuesColor', undef ],
87             -textcolor => [ 'PASSIVE', 'Textcolor', 'TextColor', undef ],
88             -textfont => [ 'PASSIVE', 'Textfont', 'TextFont', undef ],
89            
90             -boxaxis => [ 'PASSIVE', 'Boxaxis', 'BoxAxis', 0 ],
91             -noaxis => [ 'PASSIVE', 'Noaxis', 'NoAxis', 0 ],
92             -zeroaxisonly => [ 'PASSIVE', 'Zeroaxisonly', 'ZeroAxisOnly', 0 ],
93             -zeroaxis => [ 'PASSIVE', 'Zeroaxis', 'ZeroAxis', 0 ],
94             -longticks => [ 'PASSIVE', 'Longticks', 'LongTicks', 0 ],
95            
96             -xtickheight => [
97             'PASSIVE', 'Xtickheight',
98             'XTickHeight', $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{TickHeight}
99             ],
100             -xtickview => [ 'PASSIVE', 'Xtickview', 'XTickView', 1 ],
101            
102             -yticknumber => [
103             'PASSIVE', 'Yticknumber',
104             'YTickNumber', $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{TickNumber}
105             ],
106             -ytickwidth =>
107             [ 'PASSIVE', 'Ytickwidth', 'YtickWidth', $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{TickWidth} ],
108             -ytickview => [ 'PASSIVE', 'Ytickview', 'YTickView', 1 ],
109            
110             -alltickview => [ 'PASSIVE', 'Alltickview', 'AllTickView', 1 ],
111            
112             -width => [ 'SELF', 'width', 'Width', $CompositeWidget->{RefInfoDummies}->{Canvas}{Width} ],
113             -height => [ 'SELF', 'height', 'Height', $CompositeWidget->{RefInfoDummies}->{Canvas}{Height} ],
114            
115             -linewidth => [ 'PASSIVE', 'Linewidth', 'LineWidth', 1 ],
116             -colordata =>
117             [ 'PASSIVE', 'Colordata', 'ColorData', $CompositeWidget->{RefInfoDummies}->{Legend}{Colors} ],
118             -spacingbar => [ 'PASSIVE', 'Spacingbar', 'SpacingBar', 1 ],
119             );
120            
121             $CompositeWidget->Delegates( DEFAULT => $CompositeWidget, );
122            
123             # recreate graph after widget resize
124             $CompositeWidget->enabled_automatic_redraw();
125             $CompositeWidget->disabled_gradientcolor();
126             }
127            
128             sub _Balloon {
129             my ($CompositeWidget) = @_;
130            
131             # balloon defined and user want to stop it
132             if ( defined $CompositeWidget->{RefInfoDummies}->{Balloon}{Obj}
133             and $CompositeWidget->{RefInfoDummies}->{Balloon}{State} == 0 )
134             {
135             $CompositeWidget->_DestroyBalloonAndBind();
136             return;
137             }
138            
139             # balloon not defined and user want to stop it
140             elsif ( $CompositeWidget->{RefInfoDummies}->{Balloon}{State} == 0 ) {
141             return;
142             }
143            
144             # balloon defined and user want to start it again (may be new option)
145             elsif ( defined $CompositeWidget->{RefInfoDummies}->{Balloon}{Obj}
146             and $CompositeWidget->{RefInfoDummies}->{Balloon}{State} == 1 )
147             {
148            
149             # destroy the balloon, it will be re create above
150             $CompositeWidget->_DestroyBalloonAndBind();
151             }
152            
153             # Balloon creation
154             $CompositeWidget->{RefInfoDummies}->{Balloon}{Obj} = $CompositeWidget->Balloon(
155             -statusbar => $CompositeWidget,
156             -background => $CompositeWidget->{RefInfoDummies}->{Balloon}{Background},
157             );
158             $CompositeWidget->{RefInfoDummies}->{Balloon}{Obj}->attach(
159             $CompositeWidget,
160             -balloonposition => 'mouse',
161             -msg => $CompositeWidget->{RefInfoDummies}->{Legend}{MsgBalloon},
162             );
163            
164             # no legend, no bind
165             unless ( my $LegendTextNumber = $CompositeWidget->{RefInfoDummies}->{Legend}{LegendTextNumber} ) {
166             return;
167             }
168            
169             # bind legend and bars
170             for my $IndexLegend ( 1 .. $CompositeWidget->{RefInfoDummies}->{Legend}{LegendTextNumber} ) {
171            
172             my $LegendTag = $IndexLegend . $CompositeWidget->{RefInfoDummies}->{TAGS}{Legend};
173             my $BoxplotTag = $IndexLegend . $CompositeWidget->{RefInfoDummies}->{TAGS}{Boxplot};
174            
175             $CompositeWidget->bind(
176             $LegendTag,
177             '',
178             sub {
179             my $OtherColor = $CompositeWidget->{RefInfoDummies}->{Balloon}{ColorData}->[0];
180            
181             # Change color if bar have the same color
182             if ( $OtherColor eq $CompositeWidget->{RefInfoDummies}{Boxplot}{$BoxplotTag}{color} ) {
183             $OtherColor = $CompositeWidget->{RefInfoDummies}->{Balloon}{ColorData}->[1];
184             }
185             $CompositeWidget->itemconfigure(
186             $BoxplotTag,
187             -fill => $OtherColor,
188             -width => $CompositeWidget->cget( -linewidth )
189             + $CompositeWidget->{RefInfoDummies}->{Balloon}{MorePixelSelected},
190             );
191             }
192             );
193            
194             $CompositeWidget->bind(
195             $LegendTag,
196             '',
197             sub {
198             $CompositeWidget->itemconfigure(
199             $BoxplotTag,
200             -fill => $CompositeWidget->{RefInfoDummies}{Boxplot}{$BoxplotTag}{color},
201             -width => $CompositeWidget->cget( -linewidth ),
202             );
203            
204             # Allow value bar to display
205             $CompositeWidget->itemconfigure( $CompositeWidget->{RefInfoDummies}->{TAGS}{BarValues},
206             -fill => 'black', );
207             }
208             );
209             }
210            
211             return;
212             }
213            
214             sub boxplot_information {
215             my ($CompositeWidget) = @_;
216            
217             # Test if plot defined
218             unless ( defined $CompositeWidget->{RefInfoDummies}->{Data}{PlotDefined} ) {
219             $CompositeWidget->_error( 'You have to plot before get boxplots informations', 1 );
220             }
221            
222             my @boxplot_information;
223             my @AllData = @{ $CompositeWidget->{RefInfoDummies}->{Data}{RefAllData} };
224             my $NbrData = scalar @AllData;
225             my ( $dim1, $dim2 ) = ( 0, 0 );
226            
227             # Read data and store information in A dimension table and hash.
228             foreach my $SampleNumber ( 1 .. $NbrData - 1 ) {
229            
230             # Fisrt dimension
231             $dim1 = $SampleNumber - 1;
232             $dim2 = 0;
233            
234             # Get information foreach sample
235             foreach my $RefData ( @{ $AllData[$SampleNumber] } ) {
236             my ( $Q1, $Q2, $Q3 ) = ( _Quantile( $RefData, 1 ), _Quantile( $RefData, 2 ), _Quantile( $RefData, 3 ) );
237             my ( $SnonOutlier, $LnonOutlier ) = _NonOutlier( $RefData, $Q1, $Q3 );
238             $boxplot_information[$dim1][$dim2] = {
239             mean => _moy($RefData),
240             median => $Q2,
241             Q1 => $Q1,
242             Q3 => $Q3,
243             largest_non_outlier => $LnonOutlier,
244             smallest_non_outlier => $SnonOutlier,
245             outliers => [],
246             };
247            
248             foreach my $value ( @{$RefData} ) {
249             if ( $value < $SnonOutlier or $value > $LnonOutlier ) {
250             push( @{ $boxplot_information[$dim1][$dim2]->{outliers} }, $value );
251             }
252             }
253             $dim2++;
254             }
255             }
256            
257             return \@boxplot_information;
258             }
259            
260             sub set_legend {
261             my ( $CompositeWidget, %InfoLegend ) = @_;
262             my $RefLegend = $InfoLegend{-data};
263             unless ( defined $RefLegend ) {
264             $CompositeWidget->_error(
265             "Can't set -data in set_legend method. "
266             . "May be you forgot to set the value\n"
267             . "Eg : set_legend( -data => ['legend1', 'legend2', ...] );",
268             1
269             );
270             }
271            
272             unless ( defined $RefLegend and ref($RefLegend) eq 'ARRAY' ) {
273             $CompositeWidget->_error(
274             "Can't set -data in set_legend method. Bad data\n"
275             . "Eg : set_legend( -data => ['legend1', 'legend2', ...] );",
276             1
277             );
278             }
279            
280             my @LegendOption = qw / -box -legendmarkerheight -legendmarkerwidth -heighttitle /;
281            
282             foreach my $OptionName (@LegendOption) {
283             if ( defined $InfoLegend{$OptionName}
284             and $InfoLegend{$OptionName} !~ m{^\d+$} )
285             {
286             $CompositeWidget->_error(
287             "'Can't set $OptionName to " . "'$InfoLegend{$OptionName}', $InfoLegend{$OptionName}' isn't numeric",
288             1
289             );
290             }
291             }
292            
293             # Check legend and data size
294             if ( my $RefData = $CompositeWidget->{RefInfoDummies}->{Data}{RefAllData} ) {
295             unless ( $CompositeWidget->_CheckSizeLengendAndData( $RefData, $RefLegend ) ) {
296             undef $CompositeWidget->{RefInfoDummies}->{Legend}{DataLegend};
297             return;
298             }
299             }
300            
301             # Get Legend options
302             # Title
303             if ( defined $InfoLegend{-title} ) {
304             $CompositeWidget->{RefInfoDummies}->{Legend}{title} = $InfoLegend{-title};
305             }
306             else {
307             undef $CompositeWidget->{RefInfoDummies}->{Legend}{title};
308             $CompositeWidget->{RefInfoDummies}->{Legend}{HeightTitle} = 0;
309             }
310            
311             # Title and legend font
312             if ( defined $InfoLegend{-titlefont} ) {
313             $CompositeWidget->{RefInfoDummies}->{Legend}{titlefont} = $InfoLegend{-titlefont};
314             }
315             if ( defined $InfoLegend{-legendfont} ) {
316             $CompositeWidget->{RefInfoDummies}->{Legend}{legendfont} = $InfoLegend{-legendfont};
317             }
318            
319             # box legend
320             if ( defined $InfoLegend{-box} ) {
321             $CompositeWidget->{RefInfoDummies}->{Legend}{box} = $InfoLegend{-box};
322             }
323            
324             # title color
325             if ( defined $InfoLegend{-titlecolors} ) {
326             $CompositeWidget->{RefInfoDummies}->{Legend}{titlecolors} = $InfoLegend{-titlecolors};
327             }
328            
329             # legendmarkerheight
330             if ( defined $InfoLegend{-legendmarkerheight} ) {
331             $CompositeWidget->{RefInfoDummies}->{Legend}{HCube} = $InfoLegend{-legendmarkerheight};
332             }
333            
334             # legendmarkerwidth
335             if ( defined $InfoLegend{-legendmarkerwidth} ) {
336             $CompositeWidget->{RefInfoDummies}->{Legend}{WCube} = $InfoLegend{-legendmarkerwidth};
337             }
338            
339             # heighttitle
340             if ( defined $InfoLegend{-heighttitle} ) {
341             $CompositeWidget->{RefInfoDummies}->{Legend}{HeightTitle} = $InfoLegend{-heighttitle};
342             }
343            
344             # Get the biggest length of legend text
345             my @LengthLegend = map { length; } @{$RefLegend};
346             my $BiggestLegend = _MaxArray( \@LengthLegend );
347            
348             # 100 pixel => 13 characters, 1 pixel => 0.13 pixels then 1 character = 7.69 pixels
349             $CompositeWidget->{RefInfoDummies}->{Legend}{WidthOneCaracter} = 7.69;
350            
351             # Max pixel width for a legend text for us
352             $CompositeWidget->{RefInfoDummies}->{Legend}{LengthTextMax}
353             = int( $CompositeWidget->{RefInfoDummies}->{Legend}{WidthText}
354             / $CompositeWidget->{RefInfoDummies}->{Legend}{WidthOneCaracter} );
355            
356             # We have free space
357             my $Diff = $CompositeWidget->{RefInfoDummies}->{Legend}{LengthTextMax} - $BiggestLegend;
358            
359             # Get new size width for a legend text with one pixel security
360             $CompositeWidget->{RefInfoDummies}->{Legend}{WidthText}
361             -= ( $Diff - 1 ) * $CompositeWidget->{RefInfoDummies}->{Legend}{WidthOneCaracter};
362            
363             # Store Reference data
364             $CompositeWidget->{RefInfoDummies}->{Legend}{DataLegend} = $RefLegend;
365             $CompositeWidget->{RefInfoDummies}->{Legend}{NbrLegend} = scalar @{$RefLegend};
366            
367             return 1;
368             }
369            
370             sub _Legend {
371             my ( $CompositeWidget, $RefLegend ) = @_;
372            
373             # One legend width
374             $CompositeWidget->{RefInfoDummies}->{Legend}{LengthOneLegend}
375             = +$CompositeWidget->{RefInfoDummies}->{Legend}{SpaceBeforeCube} # space between each legend
376             + $CompositeWidget->{RefInfoDummies}->{Legend}{WCube} # width legend marker
377             + $CompositeWidget->{RefInfoDummies}->{Legend}{SpaceAfterCube} # space after marker
378             + $CompositeWidget->{RefInfoDummies}->{Legend}{WidthText} # legend text width allowed
379             ;
380            
381             # Number of legends per line
382             $CompositeWidget->{RefInfoDummies}->{Legend}{NbrPerLine}
383             = int( $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{Width}
384             / $CompositeWidget->{RefInfoDummies}->{Legend}{LengthOneLegend} );
385             $CompositeWidget->{RefInfoDummies}->{Legend}{NbrPerLine} = 1
386             if ( $CompositeWidget->{RefInfoDummies}->{Legend}{NbrPerLine} == 0 );
387            
388             # How many legend we will have
389             $CompositeWidget->{RefInfoDummies}->{Legend}{LegendTextNumber}
390             = scalar @{ $CompositeWidget->{RefInfoDummies}->{Data}{RefAllData} } - 1;
391            
392             =for NumberLines:
393             We calculate the number of lines set for the legend graph.
394             If wa can set 11 legends per line, then for 3 legend, we will need one line
395             and for 12 legends, we will need 2 lines
396             If NbrLeg / NbrPerLine = integer => get number of lines
397             If NbrLeg / NbrPerLine = float => int(float) + 1 = get number of lines
398            
399             =cut
400            
401             $CompositeWidget->{RefInfoDummies}->{Legend}{NbrLine}
402             = $CompositeWidget->{RefInfoDummies}->{Legend}{LegendTextNumber}
403             / $CompositeWidget->{RefInfoDummies}->{Legend}{NbrPerLine};
404             unless (
405             int( $CompositeWidget->{RefInfoDummies}->{Legend}{NbrLine} )
406             == $CompositeWidget->{RefInfoDummies}->{Legend}{NbrLine} )
407             {
408             $CompositeWidget->{RefInfoDummies}->{Legend}{NbrLine}
409             = int( $CompositeWidget->{RefInfoDummies}->{Legend}{NbrLine} ) + 1;
410             }
411            
412             # Total Height of Legend
413             $CompositeWidget->{RefInfoDummies}->{Legend}{Height}
414             = $CompositeWidget->{RefInfoDummies}->{Legend}{HeightTitle} # Hauteur Titre légende
415             + $CompositeWidget->{RefInfoDummies}->{Legend}{NbrLine}
416             * $CompositeWidget->{RefInfoDummies}->{Legend}{HLine};
417            
418             # Get number legend text max per line to reajust our graph
419             if ( $CompositeWidget->{RefInfoDummies}->{Legend}{LegendTextNumber}
420             < $CompositeWidget->{RefInfoDummies}->{Legend}{NbrPerLine} )
421             {
422             $CompositeWidget->{RefInfoDummies}->{Legend}{NbrPerLine}
423             = $CompositeWidget->{RefInfoDummies}->{Legend}{LegendTextNumber};
424             }
425            
426             return;
427             }
428            
429             sub _ViewLegend {
430             my ($CompositeWidget) = @_;
431            
432             # legend option
433             my $LegendTitle = $CompositeWidget->{RefInfoDummies}->{Legend}{title};
434             my $legendmarkercolors = $CompositeWidget->cget( -colordata );
435             my $legendfont = $CompositeWidget->{RefInfoDummies}->{Legend}{legendfont};
436             my $titlecolor = $CompositeWidget->{RefInfoDummies}->{Legend}{titlecolors};
437             my $titlefont = $CompositeWidget->{RefInfoDummies}->{Legend}{titlefont};
438            
439             # display legend title
440             if ( defined $LegendTitle ) {
441             my $xLegendTitle = $CompositeWidget->{RefInfoDummies}->{Axis}{CxMin}
442             + $CompositeWidget->{RefInfoDummies}->{Legend}{SpaceBeforeCube};
443             my $yLegendTitle
444             = $CompositeWidget->{RefInfoDummies}->{Axis}{CyMin}
445             + $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{TickHeight}
446             + $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{ScaleValuesHeight}
447             + $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{xlabelHeight};
448            
449             $CompositeWidget->createText(
450             $xLegendTitle,
451             $yLegendTitle,
452             -text => $LegendTitle,
453             -anchor => 'nw',
454             -font => $titlefont,
455             -fill => $titlecolor,
456             -width => $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{Width},
457             -tags => [
458             $CompositeWidget->{RefInfoDummies}->{TAGS}{TitleLegend},
459             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTagsDummiesGraph},
460             ],
461             );
462             }
463            
464             # Display legend
465             my $IndexColor = 0;
466             my $IndexLegend = 0;
467            
468             for my $NumberLine ( 0 .. $CompositeWidget->{RefInfoDummies}->{Legend}{NbrLine} - 1 ) {
469             my $x1Cube = $CompositeWidget->{RefInfoDummies}->{Axis}{CxMin}
470             + $CompositeWidget->{RefInfoDummies}->{Legend}{SpaceBeforeCube};
471             my $y1Cube
472             = ( $CompositeWidget->{RefInfoDummies}->{Axis}{CyMin}
473             + $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{TickHeight}
474             + $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{ScaleValuesHeight}
475             + $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{xlabelHeight}
476             + $CompositeWidget->{RefInfoDummies}->{Legend}{HeightTitle}
477             + $CompositeWidget->{RefInfoDummies}->{Legend}{HLine} / 2 )
478             + $NumberLine * $CompositeWidget->{RefInfoDummies}->{Legend}{HLine};
479            
480             my $x2Cube = $x1Cube + $CompositeWidget->{RefInfoDummies}->{Legend}{WCube};
481             my $y2Cube = $y1Cube - $CompositeWidget->{RefInfoDummies}->{Legend}{HCube};
482             my $xText = $x2Cube + $CompositeWidget->{RefInfoDummies}->{Legend}{SpaceAfterCube};
483             my $yText = $y2Cube;
484             my $MaxLength = $CompositeWidget->{RefInfoDummies}->{Legend}{LengthTextMax};
485            
486             LEGEND:
487             for my $NumberLegInLine ( 0 .. $CompositeWidget->{RefInfoDummies}->{Legend}{NbrPerLine} - 1 ) {
488            
489             my $LineColor = $legendmarkercolors->[$IndexColor];
490             unless ( defined $LineColor ) {
491             $IndexColor = 0;
492             $LineColor = $legendmarkercolors->[$IndexColor];
493             }
494            
495             # Cut legend text if too long
496             my $Legende = $CompositeWidget->{RefInfoDummies}->{Legend}{DataLegend}->[$IndexLegend];
497             next unless ( defined $Legende );
498             my $NewLegend = $Legende;
499            
500             if ( length $NewLegend > $MaxLength ) {
501             $MaxLength -= 3;
502             $NewLegend =~ s/^(.{$MaxLength}).*/$1/;
503             $NewLegend .= '...';
504             }
505            
506             my $Tag = ( $IndexLegend + 1 ) . $CompositeWidget->{RefInfoDummies}->{TAGS}{Legend};
507             $CompositeWidget->createRectangle(
508             $x1Cube, $y1Cube, $x2Cube, $y2Cube,
509             -fill => $LineColor,
510             -outline => $LineColor,
511             -tags => [ $Tag, $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTagsDummiesGraph}, ],
512             );
513            
514             my $Id = $CompositeWidget->createText(
515             $xText, $yText,
516             -text => $NewLegend,
517             -anchor => 'nw',
518             -tags => [ $Tag, $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTagsDummiesGraph}, ],
519             );
520             if ($legendfont) {
521             $CompositeWidget->itemconfigure( $Id, -font => $legendfont, );
522             }
523            
524             $IndexColor++;
525             $IndexLegend++;
526            
527             # cube
528             $x1Cube += $CompositeWidget->{RefInfoDummies}->{Legend}{LengthOneLegend};
529             $x2Cube += $CompositeWidget->{RefInfoDummies}->{Legend}{LengthOneLegend};
530            
531             # Text
532             $xText += $CompositeWidget->{RefInfoDummies}->{Legend}{LengthOneLegend};
533             my $BoxplotTag = $IndexLegend . $CompositeWidget->{RefInfoDummies}->{TAGS}{Boxplot};
534            
535             # balloon on legend
536             $CompositeWidget->{RefInfoDummies}->{Legend}{MsgBalloon}->{$Tag} = $Legende;
537            
538             last LEGEND
539             if ( $IndexLegend == $CompositeWidget->{RefInfoDummies}->{Legend}{LegendTextNumber} );
540             }
541             }
542            
543             # box legend
544             my $x1Box = $CompositeWidget->{RefInfoDummies}->{Axis}{CxMin};
545             my $y1Box
546             = $CompositeWidget->{RefInfoDummies}->{Axis}{CyMin}
547             + $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{TickHeight}
548             + $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{ScaleValuesHeight}
549             + $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{xlabelHeight};
550             my $x2Box
551             = $x1Box
552             + ( $CompositeWidget->{RefInfoDummies}->{Legend}{NbrPerLine}
553             * $CompositeWidget->{RefInfoDummies}->{Legend}{LengthOneLegend} );
554            
555             # Reajuste box if width box < legend title text
556             my @InfoLegendTitle = $CompositeWidget->bbox( $CompositeWidget->{RefInfoDummies}->{TAGS}{TitleLegend} );
557             if ( $InfoLegendTitle[2] and $x2Box <= $InfoLegendTitle[2] ) {
558             $x2Box = $InfoLegendTitle[2] + 2;
559             }
560             my $y2Box = $y1Box + $CompositeWidget->{RefInfoDummies}->{Legend}{Height};
561             $CompositeWidget->createRectangle(
562             $x1Box, $y1Box, $x2Box, $y2Box,
563             -tags => [
564             $CompositeWidget->{RefInfoDummies}->{TAGS}{BoxLegend},
565             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTagsDummiesGraph},
566             ],
567             );
568            
569             return;
570             }
571            
572             sub _axis {
573             my ($CompositeWidget) = @_;
574            
575             # x axis width
576             $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{Width}
577             = $CompositeWidget->{RefInfoDummies}->{Canvas}{Width}
578             - ( 2 * $CompositeWidget->{RefInfoDummies}->{Canvas}{WidthEmptySpace}
579             + $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{ylabelWidth}
580             + $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{ScaleValuesWidth}
581             + $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{TickWidth} );
582            
583             # get Height legend
584             if ( $CompositeWidget->{RefInfoDummies}->{Legend}{NbrLegend} > 0 ) {
585             $CompositeWidget->_Legend( $CompositeWidget->{RefInfoDummies}->{Legend}{DataLegend} );
586             }
587            
588             # Height y axis
589             $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{Height}
590             = $CompositeWidget->{RefInfoDummies}->{Canvas}{Height} # Largeur canvas
591             - (
592             2 * $CompositeWidget->{RefInfoDummies}->{Canvas}{HeightEmptySpace} # 2 fois les espace vides
593             + $CompositeWidget->{RefInfoDummies}->{Title}{Height} # Hauteur du titre
594             + $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{TickHeight} # Hauteur tick (axe x)
595             + $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{ScaleValuesHeight} # Hauteur valeurs axe
596             + $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{xlabelHeight} # Hauteur x label
597             + $CompositeWidget->{RefInfoDummies}->{Legend}{Height} # Hauteur légende
598             );
599            
600             #===========================
601             # Y axis
602             # Set 2 points (CxMin, CyMin) et (CxMin, CyMax)
603             $CompositeWidget->{RefInfoDummies}->{Axis}{CxMin} # Coordonnées CxMin
604             = $CompositeWidget->{RefInfoDummies}->{Canvas}{WidthEmptySpace} # Largeur vide
605             + $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{ylabelWidth} # Largeur label y
606             + $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{ScaleValuesWidth} # Largeur valeur axe y
607             + $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{TickWidth}; # Largeur tick axe y
608            
609             $CompositeWidget->{RefInfoDummies}->{Axis}{CyMax} # Coordonnées CyMax
610             = $CompositeWidget->{RefInfoDummies}->{Canvas}{HeightEmptySpace} # Hauteur vide
611             + $CompositeWidget->{RefInfoDummies}->{Title}{Height} # Hauteur titre
612             ;
613            
614             $CompositeWidget->{RefInfoDummies}->{Axis}{CyMin} # Coordonnées CyMin
615             = $CompositeWidget->{RefInfoDummies}->{Axis}{CyMax} # Coordonnées CyMax (haut)
616             + $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{Height} # Hauteur axe Y
617             ;
618            
619             # display Y axis
620             $CompositeWidget->createLine(
621             $CompositeWidget->{RefInfoDummies}->{Axis}{CxMin},
622             $CompositeWidget->{RefInfoDummies}->{Axis}{CyMin},
623             $CompositeWidget->{RefInfoDummies}->{Axis}{CxMin},
624             $CompositeWidget->{RefInfoDummies}->{Axis}{CyMax},
625             -tags => [
626             $CompositeWidget->{RefInfoDummies}->{TAGS}{yAxis},
627             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllAXIS},
628             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTagsDummiesGraph},
629             ],
630             );
631            
632             #===========================
633             # X axis
634             # Set 2 points (CxMin,CyMin) et (CxMax,CyMin)
635             # ou (Cx0,Cy0) et (CxMax,Cy0)
636             $CompositeWidget->{RefInfoDummies}->{Axis}{CxMax} = $CompositeWidget->{RefInfoDummies}->{Axis}{CxMin}
637             + $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{Width};
638            
639             # Bottom x axis
640             $CompositeWidget->createLine(
641             $CompositeWidget->{RefInfoDummies}->{Axis}{CxMin},
642             $CompositeWidget->{RefInfoDummies}->{Axis}{CyMin},
643             $CompositeWidget->{RefInfoDummies}->{Axis}{CxMax},
644             $CompositeWidget->{RefInfoDummies}->{Axis}{CyMin},
645             -tags => [
646             $CompositeWidget->{RefInfoDummies}->{TAGS}{xAxis},
647             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllAXIS},
648             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTagsDummiesGraph},
649             ],
650             );
651            
652             # POINT (0,0)
653             # min positive value >= 0
654             if ( $CompositeWidget->{RefInfoDummies}->{Data}{MinYValue} >= 0 ) {
655             $CompositeWidget->{RefInfoDummies}->{Axis}{Cx0} = $CompositeWidget->{RefInfoDummies}->{Axis}{CxMin};
656             $CompositeWidget->{RefInfoDummies}->{Axis}{Cy0} = $CompositeWidget->{RefInfoDummies}->{Axis}{CyMin};
657            
658             $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{HeightUnit} # Height unit for value = 1
659             = $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{Height}
660             / ( $CompositeWidget->{RefInfoDummies}->{Data}{MaxYValue} - 0 );
661             }
662            
663             # min positive value < 0
664             else {
665            
666             $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{HeightUnit} # Height unit for value = 1
667             = $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{Height}
668             / ( $CompositeWidget->{RefInfoDummies}->{Data}{MaxYValue}
669             - $CompositeWidget->{RefInfoDummies}->{Data}{MinYValue} );
670             $CompositeWidget->{RefInfoDummies}->{Axis}{Cx0} = $CompositeWidget->{RefInfoDummies}->{Axis}{CxMin};
671             $CompositeWidget->{RefInfoDummies}->{Axis}{Cy0}
672             = $CompositeWidget->{RefInfoDummies}->{Axis}{CyMin}
673             + ( $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{HeightUnit}
674             * $CompositeWidget->{RefInfoDummies}->{Data}{MinYValue} );
675            
676             # X Axis (0,0)
677             $CompositeWidget->createLine(
678             $CompositeWidget->{RefInfoDummies}->{Axis}{Cx0},
679             $CompositeWidget->{RefInfoDummies}->{Axis}{Cy0},
680             $CompositeWidget->{RefInfoDummies}->{Axis}{CxMax},
681             $CompositeWidget->{RefInfoDummies}->{Axis}{Cy0},
682             -tags => [
683             $CompositeWidget->{RefInfoDummies}->{TAGS}{xAxis0},
684             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllAXIS},
685             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTagsDummiesGraph},
686             ],
687             );
688             }
689            
690             return;
691             }
692            
693             sub _xtick {
694             my ($CompositeWidget) = @_;
695            
696             my $xvaluecolor = $CompositeWidget->cget( -xvaluecolor );
697             my $longticks = $CompositeWidget->cget( -longticks );
698            
699             # x coordinates y ticks on bottom x axis
700             my $Xtickx1 = $CompositeWidget->{RefInfoDummies}->{Axis}{CxMin};
701             my $Xticky1 = $CompositeWidget->{RefInfoDummies}->{Axis}{CyMin};
702            
703             # x coordinates y ticks on 0,0 x axis if the graph have only y value < 0
704             if ( $CompositeWidget->cget( -zeroaxisonly ) == 1
705             and $CompositeWidget->{RefInfoDummies}->{Data}{MaxYValue} > 0 )
706             {
707             $Xticky1 = $CompositeWidget->{RefInfoDummies}->{Axis}{Cy0};
708             }
709            
710             my $Xtickx2 = $Xtickx1;
711             my $Xticky2 = $Xticky1 + $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{TickHeight};
712            
713             # Coordinates of x values (first value)
714             my $XtickxValue = $CompositeWidget->{RefInfoDummies}->{Axis}{CxMin}
715             + ( $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{SpaceBetweenTick} / 2 );
716             my $XtickyValue = $Xticky2 + ( $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{ScaleValuesHeight} / 2 );
717             my $NbrLeg = scalar( @{ $CompositeWidget->{RefInfoDummies}->{Data}{RefXLegend} } );
718            
719             my $xlabelskip = $CompositeWidget->cget( -xlabelskip );
720            
721             # index of tick and vlaues that will be skip
722             my %IndiceToSkip;
723             if ( defined $xlabelskip ) {
724             for ( my $i = 1; $i <= $NbrLeg; $i++ ) {
725             $IndiceToSkip{$i} = 1;
726             $i += $xlabelskip;
727             }
728             }
729            
730             for ( my $Indice = 1; $Indice <= $NbrLeg; $Indice++ ) {
731             my $data = $CompositeWidget->{RefInfoDummies}->{Data}{RefXLegend}->[ $Indice - 1 ];
732            
733             # tick
734             $Xtickx1 += $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{SpaceBetweenTick};
735             $Xtickx2 = $Xtickx1;
736            
737             # tick legend
738             my $RegexXtickselect = $CompositeWidget->cget( -xvaluesregex );
739            
740             if ( $data =~ m{$RegexXtickselect} ) {
741             next unless ( defined $IndiceToSkip{$Indice} );
742            
743             # Long tick
744             if ( defined $longticks and $longticks == 1 ) {
745             $Xticky1 = $CompositeWidget->{RefInfoDummies}->{Axis}{CyMax};
746             $Xticky2 = $CompositeWidget->{RefInfoDummies}->{Axis}{CyMin};
747             }
748            
749             $CompositeWidget->createLine(
750             $Xtickx1, $Xticky1, $Xtickx2, $Xticky2,
751             -tags => [
752             $CompositeWidget->{RefInfoDummies}->{TAGS}{xTick},
753             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTick},
754             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTagsDummiesGraph},
755             ],
756             );
757             if ( defined $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{SpaceBetweenTick}
758             and defined $CompositeWidget->{RefInfoDummies}->{Legend}{WidthOneCaracter} )
759             {
760             my $MaxLength = $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{SpaceBetweenTick};
761             my $WidthData = $CompositeWidget->{RefInfoDummies}->{Legend}{WidthOneCaracter} * length $data;
762             my $NbrCharacter = int( $MaxLength / $CompositeWidget->{RefInfoDummies}->{Legend}{WidthOneCaracter} );
763             if ( defined $MaxLength and $WidthData > $MaxLength ) {
764             $data =~ s/^(.{$NbrCharacter}).*/$1/;
765             $data .= '...';
766             }
767             }
768            
769             $CompositeWidget->createText(
770             $XtickxValue,
771             $XtickyValue,
772             -text => $data,
773             -fill => $xvaluecolor,
774             -tags => [
775             $CompositeWidget->{RefInfoDummies}->{TAGS}{xValues},
776             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllValues},
777             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTagsDummiesGraph},
778             ],
779            
780             # %option,
781             );
782            
783             }
784             $XtickxValue += $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{SpaceBetweenTick};
785             }
786            
787             return;
788             }
789            
790             sub _ViewData {
791             my ($CompositeWidget) = @_;
792            
793             my $legendmarkercolors = $CompositeWidget->cget( -colordata );
794             my $spacingbar = $CompositeWidget->cget( -spacingbar );
795             my $showvalues = $CompositeWidget->cget( -showvalues );
796            
797             # number of value for x axis
798             $CompositeWidget->{RefInfoDummies}->{Data}{xtickNumber}
799             = $CompositeWidget->{RefInfoDummies}->{Data}{NumberXValues};
800            
801             # Space between x ticks
802             $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{SpaceBetweenTick}
803             = $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{Width}
804             / ( $CompositeWidget->{RefInfoDummies}->{Data}{xtickNumber} + 1 );
805            
806             my $IdData = 0;
807             my $IndexColor = 0;
808             my $WidthBar = $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{SpaceBetweenTick}
809             / $CompositeWidget->{RefInfoDummies}->{Data}{NumberRealData};
810            
811             # Spacing if necessary
812             my $SpacingPixel = 0;
813             if ( $spacingbar == 1 ) {
814             $SpacingPixel = $WidthBar / 4;
815             }
816            
817             my $YMin0 = $CompositeWidget->{RefInfoDummies}->{Axis}{Cy0};
818             my $XMin0 = $CompositeWidget->{RefInfoDummies}->{Axis}{Cx0};
819             my $YaxisHeightUnit = $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{HeightUnit};
820             foreach my $RefArrayData ( @{ $CompositeWidget->{RefInfoDummies}->{Data}{RefAllData} } ) {
821             if ( $IdData == 0 ) {
822             $IdData++;
823             next;
824             }
825             my $NumberData = 1; # Number of data
826             # each boxplot
827             foreach my $Refdata ( @{$RefArrayData} ) {
828             unless ( defined $Refdata and scalar @{$Refdata} > 3 ) {
829             $NumberData++;
830             next;
831             }
832            
833             # statistic calcul
834             my $Quantile1 = _Quantile( $Refdata, 1 );
835             my $Quantile2 = _Quantile( $Refdata, 2 );
836             my $Quantile3 = _Quantile( $Refdata, 3 );
837             my ( $SnonOutlier, $LnonOutlier ) = _NonOutlier( $Refdata, $Quantile1, $Quantile3 );
838             my $moy = _moy($Refdata);
839            
840             # Boxplot graph coord
841             my $x
842             = $XMin0
843             + $NumberData * $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{SpaceBetweenTick}
844             - ( ( $CompositeWidget->{RefInfoDummies}->{Data}{NumberRealData} - $IdData ) * $WidthBar );
845             my $x0 = $x - $WidthBar + $SpacingPixel;
846             my $xc = ( $x + $x0 ) / 2;
847            
848             # y Boxplot
849             my $yQuantile1 = $YMin0 - ( $Quantile1 * $YaxisHeightUnit );
850             my $yQuantile3 = $YMin0 - ( $Quantile3 * $YaxisHeightUnit );
851             my $yQuantile2 = $YMin0 - ( $Quantile2 * $YaxisHeightUnit );
852             my $ySnonOutlier = $YMin0 - ( $SnonOutlier * $YaxisHeightUnit );
853             my $yLnonOutlier = $YMin0 - ( $LnonOutlier * $YaxisHeightUnit );
854             my $ymoy = $YMin0 - ( $moy * $YaxisHeightUnit );
855             $moy = sprintf( "%.2f", $moy );
856            
857             # color
858             my $LineColor = $legendmarkercolors->[$IndexColor];
859             unless ( defined $LineColor ) {
860             $IndexColor = 0;
861             $LineColor = $legendmarkercolors->[$IndexColor];
862             }
863            
864             # tag
865             my $tag = $IdData . '_' . $NumberData . $CompositeWidget->{RefInfoDummies}->{TAGS}{Boxplot};
866             my $tag2 = $IdData . $CompositeWidget->{RefInfoDummies}->{TAGS}{Boxplot};
867             $CompositeWidget->{RefInfoDummies}{Boxplot}{$tag2}{color} = $LineColor;
868             my $Message;
869             if ( $Message = $CompositeWidget->{RefInfoDummies}->{Legend}{DataLegend}->[ $IdData - 1 ] ) {
870             $Message .= " : \n";
871             }
872             $Message .= <<"MESSAGE";
873             Sample : $CompositeWidget->{RefInfoDummies}->{Data}{RefAllData}->[0]->[$NumberData-1]
874             Largest non-outlier : $LnonOutlier
875             75th percentile : $Quantile3
876             Median : $Quantile2
877             Mean : $moy
878             25th percentile : $Quantile1
879             Smallest non-outlier : $SnonOutlier
880             MESSAGE
881             $CompositeWidget->{RefInfoDummies}->{Legend}{MsgBalloon}->{$tag} = $Message;
882            
883             # D9
884             $CompositeWidget->createLine(
885             $x0,
886             $yLnonOutlier,
887             $x,
888             $yLnonOutlier,
889             -tags => [
890             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllData},
891             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTagsDummiesGraph},
892             ],
893             -width => $CompositeWidget->cget( -linewidth ),
894             );
895             $CompositeWidget->createLine(
896             $xc,
897             $yLnonOutlier,
898             $xc,
899             $yQuantile3,
900             -tags => [
901             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllData},
902             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTagsDummiesGraph},
903             ],
904             -width => $CompositeWidget->cget( -linewidth ),
905             );
906            
907             # D1
908             $CompositeWidget->createLine(
909             $x0,
910             $ySnonOutlier,
911             $x,
912             $ySnonOutlier,
913             -tags => [
914             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllData},
915             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTagsDummiesGraph},
916             ],
917             -width => $CompositeWidget->cget( -linewidth ),
918             );
919             $CompositeWidget->createLine(
920             $xc,
921             $ySnonOutlier,
922             $xc,
923             $yQuantile1,
924             -tags => [
925             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllData},
926             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTagsDummiesGraph},
927             ],
928             -width => $CompositeWidget->cget( -linewidth ),
929             );
930            
931             # box : median
932             $CompositeWidget->createRectangle(
933             $x0,
934             $yQuantile1,
935             $x,
936             $yQuantile3,
937             -tags => [
938             $tag2, $tag,
939             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllData},
940             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTagsDummiesGraph},
941             ],
942             -width => $CompositeWidget->cget( -linewidth ),
943             -fill => $LineColor,
944             );
945            
946             # Q2 : median
947             $CompositeWidget->createLine(
948             $x0,
949             $yQuantile2,
950             $x,
951             $yQuantile2,
952             -tags => [
953             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllData},
954             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTagsDummiesGraph},
955             ],
956             -width => $CompositeWidget->cget( -linewidth ),
957             );
958            
959             # Moy
960             $CompositeWidget->_CreateType(
961             x => $xc,
962             y => $ymoy,
963             pixel => 6,
964             type => 'horizontal cross',
965             option => {
966             -tags => [
967             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllData},
968             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTagsDummiesGraph},
969             ],
970             -width => $CompositeWidget->cget( -linewidth ),
971             },
972             );
973            
974             # outlier
975             foreach my $value ( @{$Refdata} ) {
976             if ( $value < $SnonOutlier or $value > $LnonOutlier ) {
977             my $OutlierTag = $IdData . '_' . $NumberData . "_$value" . 'Outlier';
978             $CompositeWidget->{RefInfoDummies}->{Legend}{MsgBalloon}->{$OutlierTag} = "outlier : $value";
979            
980             my $yOutlier = $YMin0 - ( $value * $YaxisHeightUnit );
981             $CompositeWidget->_CreateType(
982             x => $xc,
983             y => $yOutlier,
984             pixel => 6,
985             type => 'diagonal cross',
986             option => {
987             -tags => [
988             $OutlierTag,
989             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllData},
990             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTagsDummiesGraph},
991             ],
992             -width => $CompositeWidget->cget( -linewidth ),
993             },
994             );
995             $CompositeWidget->_CreateType(
996             x => $xc,
997             y => $yOutlier,
998             pixel => 6,
999             type => 'horizontal cross',
1000             option => {
1001             -tags => [
1002             $OutlierTag,
1003             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllData},
1004             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTagsDummiesGraph},
1005             ],
1006             -width => $CompositeWidget->cget( -linewidth ),
1007             },
1008             );
1009             }
1010             }
1011            
1012             $NumberData++;
1013            
1014             }
1015            
1016             $IdData++;
1017             $IndexColor++;
1018             }
1019            
1020             return 1;
1021             }
1022            
1023             sub plot {
1024             my ( $CompositeWidget, $RefData, %option ) = @_;
1025            
1026             my $yticknumber = $CompositeWidget->cget( -yticknumber );
1027            
1028             if ( defined $option{-substitutionvalue}
1029             and _isANumber( $option{-substitutionvalue} ) )
1030             {
1031             $CompositeWidget->{RefInfoDummies}->{Data}{SubstitutionValue} = $option{-substitutionvalue};
1032             }
1033            
1034             $CompositeWidget->{RefInfoDummies}->{Data}{NumberRealData} = scalar( @{$RefData} ) - 1;
1035            
1036             unless ( defined $RefData ) {
1037             $CompositeWidget->_error('data not defined');
1038             return;
1039             }
1040            
1041             unless ( scalar @{$RefData} > 1 ) {
1042             $CompositeWidget->_error('You must have at least 2 arrays');
1043             return;
1044             }
1045            
1046             # Check legend and data size
1047             if ( $CompositeWidget->{RefInfoDummies}->{Legend}{NbrLegend} > 0 ) {
1048             my $RefLegend = $CompositeWidget->{RefInfoDummies}->{Legend}{DataLegend};
1049             unless ( $CompositeWidget->_CheckSizeLengendAndData( $RefData, $RefLegend ) ) {
1050             undef $CompositeWidget->{RefInfoDummies}->{Legend}{DataLegend};
1051             }
1052             }
1053            
1054             # Check array size
1055             $CompositeWidget->{RefInfoDummies}->{Data}{NumberXValues} = scalar @{ $RefData->[0] };
1056             my $i = 0;
1057             my @arrayTemp = (0) x scalar @{ $RefData->[0] };
1058             foreach my $RefArray ( @{$RefData} ) {
1059             unless ( scalar @{$RefArray} == $CompositeWidget->{RefInfoDummies}->{Data}{NumberXValues} ) {
1060             $CompositeWidget->_error( 'Make sure that every array has the ' . 'same size in plot data method', 1 );
1061             return;
1062             }
1063            
1064             # Get min and max size
1065             if ( $i != 0 ) {
1066            
1067             # substitute none real value
1068             foreach my $RefArray2 ( @{$RefArray} ) {
1069            
1070             # First data must be an array ref
1071             unless ( ref $RefArray2 eq 'ARRAY' ) {
1072             $CompositeWidget->_error( 'Each boxplot data must be in an array reference', 1 );
1073             }
1074             foreach my $data ( @{$RefArray2} ) {
1075             if ( defined $data and !_isANumber($data) ) {
1076             $data = $CompositeWidget->{RefInfoDummies}->{Data}{SubstitutionValue};
1077             }
1078             }
1079             }
1080            
1081             # max, min
1082             foreach my $RefArray2 ( @{$RefArray} ) {
1083             $CompositeWidget->{RefInfoDummies}->{Data}{MaxYValue}
1084             = _MaxArray( [ $CompositeWidget->{RefInfoDummies}->{Data}{MaxYValue}, _MaxArray($RefArray2) ] );
1085             $CompositeWidget->{RefInfoDummies}->{Data}{MinYValue}
1086             = _MinArray( [ $CompositeWidget->{RefInfoDummies}->{Data}{MinYValue}, _MinArray($RefArray2) ] );
1087            
1088             # Size each data points
1089             if ( scalar @{$RefArray2} < 4 and scalar @{$RefArray2} > 0 ) {
1090             my $data = join( ',', @{$RefArray2} );
1091             $data = "[$data]";
1092             $CompositeWidget->_error(
1093             "Data set $data does not contain the minimum of 4 data points.\n" . "It has been skipped." );
1094             }
1095             }
1096            
1097             }
1098             $i++;
1099             }
1100            
1101             $CompositeWidget->{RefInfoDummies}->{Data}{RefXLegend} = $RefData->[0];
1102             $CompositeWidget->{RefInfoDummies}->{Data}{RefAllData} = $RefData;
1103             $CompositeWidget->{RefInfoDummies}->{Data}{PlotDefined} = 1;
1104            
1105             if ( $CompositeWidget->{RefInfoDummies}->{Data}{MinYValue} > 0 ) {
1106             $CompositeWidget->{RefInfoDummies}->{Data}{MinYValue} = 0;
1107             }
1108             while ( ( $CompositeWidget->{RefInfoDummies}->{Data}{MaxYValue} / $yticknumber ) % 5 != 0 ) {
1109             $CompositeWidget->{RefInfoDummies}->{Data}{MaxYValue}
1110             = int( $CompositeWidget->{RefInfoDummies}->{Data}{MaxYValue} + 1 );
1111             }
1112            
1113             $CompositeWidget->_GraphForDummiesConstruction;
1114            
1115             return 1;
1116             }
1117            
1118             1;
1119             __END__