technical_graph 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/DOCUMENTATION.md +6 -3
- data/DOCUMENTATION.textile +411 -16
- data/Gemfile +6 -1
- data/Gemfile.lock +13 -11
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/lib/technical_graph/data_layer.rb +1 -1
- data/lib/technical_graph/data_layer_processor_noise_removal.rb +46 -10
- data/lib/technical_graph/graph_axis.rb +33 -0
- data/lib/technical_graph/graph_color_library.rb +5 -0
- data/lib/technical_graph/graph_data_processor.rb +1 -1
- data/lib/technical_graph/graph_image_drawer.rb +41 -9
- data/lib/technical_graph/graph_image_drawer_rasem.rb +18 -9
- data/lib/technical_graph/graph_image_drawer_rmagick.rb +4 -1
- data/lib/technical_graph.rb +3 -2
- data/test/test_technical_graph_axis.rb +3 -1
- data/test/test_technical_readme.rb +305 -8
- metadata +7 -7
data/DOCUMENTATION.md
CHANGED
@@ -36,6 +36,10 @@ Axis labels:
|
|
36
36
|
options[:x_axis_label] = 'x'
|
37
37
|
options[:y_axis_label] = 'y'
|
38
38
|
|
39
|
+
Adjust axis to be on 'zero':
|
40
|
+
|
41
|
+
options[:adjust_axis_to_zero] = true
|
42
|
+
|
39
43
|
Labels has truncate string to define precision. Default it is "%.2f".
|
40
44
|
|
41
45
|
options[:truncate_string] = "%.2f"
|
@@ -57,19 +61,18 @@ Colors:
|
|
57
61
|
Possible #RRGGBB or color names (ex. 'white').
|
58
62
|
|
59
63
|
options[:background_color] - background color of image
|
60
|
-
options[:background_hatch_color] - background hatch color
|
64
|
+
options[:background_hatch_color] - background hatch color, used only in rmagick renderer
|
61
65
|
options[:axis_color] - color of axis, default #000000
|
62
66
|
|
63
67
|
Anti-aliasing:
|
64
68
|
|
65
69
|
options[:antialias] - draw axis using antialias
|
66
|
-
# options[:layers_antialias] - use anti-aliasing for data layers, default false, can be override using layer option
|
67
|
-
# options[:font_antialias] - use anti-aliasing for all fonts, default false
|
68
70
|
|
69
71
|
Font size:
|
70
72
|
|
71
73
|
options[:layers_font_size] - size of font used for values in graph
|
72
74
|
options[:axis_font_size] - size of font used in axis
|
75
|
+
options[:legend_font_size] - size of font used in legend
|
73
76
|
options[:axis_label_font_size] - size of font used in options[:x_axis_label] and options[:y_axis_label]
|
74
77
|
|
75
78
|
Sometime because of axis options and large amount of data, axis can be put densely on graph. Turning this option graph size will be enlarged to maintain set distanced between axis.
|
data/DOCUMENTATION.textile
CHANGED
@@ -396,7 +396,21 @@ file_name = 'samples/readme/09_image_size.png'
|
|
396
396
|
|
397
397
|
h2. Colours
|
398
398
|
|
399
|
-
p. If you think you have better artistic taste feel free to change colours used in graph :)
|
399
|
+
p. If you think you have better artistic taste feel free to change colours used in graph :) Keep in mind that hatch
|
400
|
+
color is not available in rasem renderer which is default now.
|
401
|
+
|
402
|
+
There are 3 color options per graph:
|
403
|
+
|
404
|
+
# options[:background_color] - background color of image
|
405
|
+
|
406
|
+
# options[:background_hatch_color] - background hatch color, used only in RMagick renderer
|
407
|
+
|
408
|
+
# options[:axis_color] - color of axis, default #000000
|
409
|
+
|
410
|
+
Ane 1 layer options
|
411
|
+
|
412
|
+
# layer_options[:color] - it is color of layer
|
413
|
+
|
400
414
|
|
401
415
|
<pre>
|
402
416
|
<code>
|
@@ -411,31 +425,412 @@ p. If you think you have better artistic taste feel free to change colours used
|
|
411
425
|
|
412
426
|
@tg = TechnicalGraph.new(
|
413
427
|
{
|
414
|
-
:
|
415
|
-
:
|
428
|
+
:background_color => '#000000',
|
429
|
+
:background_hatch_color => '#222222',
|
430
|
+
:axis_color => '#FFFFFF'
|
416
431
|
})
|
417
|
-
@tg.add_layer(@simple_data_array,
|
432
|
+
@tg.add_layer(@simple_data_array, {:color => '#0000FF'})
|
418
433
|
@tg.render
|
419
|
-
file_name = 'samples/readme/
|
434
|
+
file_name = 'samples/readme/10_colors.png'
|
420
435
|
@tg.image_drawer.save_to_file(file_name)
|
421
436
|
</code>
|
422
437
|
</pre>
|
423
438
|
|
424
|
-
!https://github.com/akwiatkowski/technical_graph/raw/master/samples/readme/
|
439
|
+
!https://github.com/akwiatkowski/technical_graph/raw/master/samples/readme/10_colors.png((10) colors)!
|
440
|
+
|
441
|
+
|
442
|
+
h2. Image render
|
443
|
+
|
444
|
+
p. From version 0.4.0 there are two render classes: Rasem and RMagick. Rasem is better for fast SVG rendering, but
|
445
|
+
RMagick is better for bitmaps like PNG. Svg can be converted to bitmap using 'convert' command (ImageMagick). It is
|
446
|
+
intended that Rasem will be default renderer, and RMagick renderer will be supported as long as possible.
|
447
|
+
|
448
|
+
You can override default setting which is Rasem using:
|
449
|
+
|
450
|
+
<pre>
|
451
|
+
<code>
|
452
|
+
options[:drawer_class] = :rasem
|
453
|
+
options[:drawer_class] = :rmagick
|
454
|
+
</code>
|
455
|
+
</pre>
|
456
|
+
|
457
|
+
There is fallback - if you don't have install rmagick gem even if you set RMagick, technical_graph will use Rasem.
|
458
|
+
|
459
|
+
<pre>
|
460
|
+
<code>
|
461
|
+
@simple_data_array = [
|
462
|
+
{ :x => 0, :y => 0 },
|
463
|
+
{ :x => 1, :y => 1 },
|
464
|
+
{ :x => 2, :y => 2 },
|
465
|
+
{ :x => 3, :y => 2 },
|
466
|
+
{ :x => 4, :y => 1 },
|
467
|
+
{ :x => 5, :y => 0 },
|
468
|
+
]
|
469
|
+
|
470
|
+
@tg = TechnicalGraph.new(
|
471
|
+
{
|
472
|
+
:drawer_class => :rmagick
|
473
|
+
})
|
474
|
+
@tg.add_layer(@simple_data_array)
|
475
|
+
@tg.render
|
476
|
+
file_name = 'samples/readme/11_renderer_rmagick.png'
|
477
|
+
@tg.image_drawer.save_to_file(file_name)
|
478
|
+
|
479
|
+
@tg = TechnicalGraph.new(
|
480
|
+
{
|
481
|
+
:drawer_class => :rasem
|
482
|
+
})
|
483
|
+
@tg.add_layer(@simple_data_array)
|
484
|
+
@tg.render
|
485
|
+
file_name = 'samples/readme/11_renderer_rasem.png'
|
486
|
+
@tg.image_drawer.save_to_file(file_name)
|
487
|
+
</code>
|
488
|
+
</pre>
|
489
|
+
|
490
|
+
!https://github.com/akwiatkowski/technical_graph/raw/master/samples/readme/11_renderer_rmagick.png((11) RMagick)!
|
491
|
+
!https://github.com/akwiatkowski/technical_graph/raw/master/samples/readme/11_renderer_rasem.png((11) Rasem)!
|
425
492
|
|
426
493
|
|
494
|
+
h2. Anti-aliasing
|
495
|
+
|
496
|
+
p. Anti-aliasing is only available using RMagick renderer. On default it is disabled.
|
497
|
+
|
498
|
+
<pre>
|
499
|
+
<code>
|
500
|
+
options[:antialias] = true
|
501
|
+
</code>
|
502
|
+
</pre>
|
503
|
+
|
504
|
+
Sample graph without anti-aliasing has 11kB, with 69kB. Does size matter to you?
|
505
|
+
|
506
|
+
<pre>
|
507
|
+
<code>
|
508
|
+
@simple_data_array = [
|
509
|
+
{ :x => 0, :y => 0 },
|
510
|
+
{ :x => 1, :y => 1 },
|
511
|
+
{ :x => 2, :y => 2 },
|
512
|
+
{ :x => 3, :y => 2 },
|
513
|
+
{ :x => 4, :y => 1 },
|
514
|
+
{ :x => 5, :y => 0 },
|
515
|
+
]
|
516
|
+
|
517
|
+
@tg = TechnicalGraph.new(
|
518
|
+
{
|
519
|
+
:antialias => true,
|
520
|
+
:drawer_class => :rmagick
|
521
|
+
})
|
522
|
+
@tg.add_layer(@simple_data_array)
|
523
|
+
@tg.render
|
524
|
+
file_name = 'samples/readme/12_aa_true.png'
|
525
|
+
@tg.image_drawer.save_to_file(file_name)
|
526
|
+
|
527
|
+
# only for size comparison
|
528
|
+
@tg = TechnicalGraph.new(
|
529
|
+
{
|
530
|
+
:antialias => false,
|
531
|
+
:drawer_class => :rmagick
|
532
|
+
})
|
533
|
+
@tg.add_layer(@simple_data_array)
|
534
|
+
@tg.render
|
535
|
+
file_name = 'samples/readme/12_aa_false.png'
|
536
|
+
@tg.image_drawer.save_to_file(file_name)
|
537
|
+
</code>
|
538
|
+
</pre>
|
539
|
+
|
540
|
+
!https://github.com/akwiatkowski/technical_graph/raw/master/samples/readme/12_aa_true.png((12) Anti-aliasing enabled)!
|
541
|
+
!https://github.com/akwiatkowski/technical_graph/raw/master/samples/readme/12_aa_false.png((12) Anti-aliasing disabled)!
|
542
|
+
|
543
|
+
|
544
|
+
|
545
|
+
h2. Font size
|
546
|
+
|
547
|
+
p. You can set various font sizes.
|
548
|
+
|
549
|
+
# options[:layers_font_size] - size of font used for values in graph, keep in mind that layer_options[:value_labels]
|
550
|
+
must be enabled to see any result
|
551
|
+
|
552
|
+
# options[:axis_font_size] - size of font used in axis
|
553
|
+
|
554
|
+
# options[:axis_label_font_size] - size of font used in options[:x_axis_label] and options[:y_axis_label], to see
|
555
|
+
any result at least one of them must be set
|
556
|
+
|
557
|
+
|
558
|
+
<pre>
|
559
|
+
<code>
|
560
|
+
@simple_data_array = [
|
561
|
+
{ :x => 0, :y => 0 },
|
562
|
+
{ :x => 1, :y => 1 },
|
563
|
+
{ :x => 2, :y => 2 },
|
564
|
+
{ :x => 3, :y => 2 },
|
565
|
+
{ :x => 4, :y => 1 },
|
566
|
+
{ :x => 5, :y => 0 },
|
567
|
+
]
|
568
|
+
|
569
|
+
@tg = TechnicalGraph.new(
|
570
|
+
{
|
571
|
+
:x_axis_label => 'parameter',
|
572
|
+
:y_axis_label => 'value',
|
573
|
+
:layers_font_size => 14,
|
574
|
+
:axis_font_size => 18,
|
575
|
+
:axis_label_font_size => 48
|
576
|
+
})
|
577
|
+
@tg.add_layer(@simple_data_array, {:value_labels => true})
|
578
|
+
@tg.render
|
579
|
+
file_name = 'samples/readme/13_font_sizes.png'
|
580
|
+
@tg.image_drawer.save_to_file(file_name)
|
581
|
+
</code>
|
582
|
+
</pre>
|
583
|
+
|
584
|
+
!https://github.com/akwiatkowski/technical_graph/raw/master/samples/readme/13_font_sizes.png((13) Font size)!
|
585
|
+
|
586
|
+
|
587
|
+
|
588
|
+
h2. Legend
|
589
|
+
|
590
|
+
p. If you want to use legend you only have to set labels for layers and turn legend enabled by using:
|
591
|
+
|
592
|
+
# options[:legend] - turn on legend, on default auto position mode is enabled
|
593
|
+
|
594
|
+
# layer_options[:label] - label used for legend
|
595
|
+
|
596
|
+
Position of legend is calculated automatic - 8 corner places are checked for distance to all graph points. Point
|
597
|
+
which has longest distance is used for legend position.
|
598
|
+
|
599
|
+
Every layer has own color which can be set by user using code below. If you don't set there is bank of some fixed colors
|
600
|
+
and random color generator.
|
601
|
+
|
602
|
+
<pre>
|
603
|
+
<code>
|
604
|
+
layer_options[:color] = '#FF0000' # color in format #RRGGBB
|
605
|
+
</code>
|
606
|
+
</pre>
|
607
|
+
|
608
|
+
Graph sample code:
|
609
|
+
|
610
|
+
<pre>
|
611
|
+
<code>
|
612
|
+
@simple_data_array = [
|
613
|
+
{ :x => 0, :y => 0 },
|
614
|
+
{ :x => 1, :y => 1 },
|
615
|
+
{ :x => 2, :y => 2 },
|
616
|
+
{ :x => 3, :y => 2 },
|
617
|
+
{ :x => 4, :y => 1 },
|
618
|
+
{ :x => 5, :y => 0 },
|
619
|
+
]
|
620
|
+
|
621
|
+
@simple_data_array_second = @simple_data_array.collect{|a| {:x => a[:x] + 0.31, :y => a[:y] + 0.21 }}
|
622
|
+
@simple_data_array_third = @simple_data_array.collect{|a| {:x => a[:x] * 0.99 + 0.23, :y => a[:y] * 1.2 - 0.12 }}
|
623
|
+
|
624
|
+
@tg = TechnicalGraph.new(
|
625
|
+
{
|
626
|
+
:legend => true
|
627
|
+
})
|
628
|
+
@tg.add_layer(@simple_data_array, {:label => 'simple', :color => '#FFFF00'})
|
629
|
+
@tg.add_layer(@simple_data_array_second, {:label => 'offset', :color => '#00FFFF'})
|
630
|
+
@tg.add_layer(@simple_data_array_third, {:label => 'scaled', :color => '#FF00FF'})
|
631
|
+
@tg.render
|
632
|
+
file_name = 'samples/readme/14_simple_legend.png'
|
633
|
+
@tg.image_drawer.save_to_file(file_name)
|
634
|
+
</code>
|
635
|
+
</pre>
|
636
|
+
|
637
|
+
!https://github.com/akwiatkowski/technical_graph/raw/master/samples/readme/14_simple_legend.png((14) Legend)!
|
638
|
+
|
639
|
+
You can turn off auto position if you like:
|
640
|
+
|
641
|
+
<pre>
|
642
|
+
<code>
|
643
|
+
options[:legend_auto] = false
|
644
|
+
options[:legend_x] = 100
|
645
|
+
options[:legend_y] = 100
|
646
|
+
</code>
|
647
|
+
</pre>
|
648
|
+
|
649
|
+
There are also other useful parameters
|
650
|
+
|
651
|
+
# options[:legend_width] - width of longest label in pixels used for setting proper distance while drawing on right border
|
652
|
+
default 100 and is enlarged auto. using font size
|
653
|
+
|
654
|
+
# options[:legend_margin] - graph margin used not to draw legend on border, default 50
|
655
|
+
|
656
|
+
|
657
|
+
|
658
|
+
h2. Smoothing
|
659
|
+
|
660
|
+
p. Useful when origin of data is a bit noisy. For best results you can add two layers: one raw, and second with smoothing.
|
661
|
+
|
662
|
+
<pre>
|
663
|
+
<code>
|
664
|
+
@tg = TechnicalGraph.new(
|
665
|
+
{
|
666
|
+
:width => 2000,
|
667
|
+
:height => 1500,
|
668
|
+
:legend => true,
|
669
|
+
:x_axis_label => "Parameter",
|
670
|
+
:y_axis_label => "Value"
|
671
|
+
}
|
672
|
+
)
|
673
|
+
max = 250 #2000
|
674
|
+
|
675
|
+
@layer_data = Array.new
|
676
|
+
(0..max).each do |i|
|
677
|
+
x = -10.0 + (20.0 * i.to_f / max.to_f)
|
678
|
+
y = 10.0 * Math.cos(i.to_f * (2.0 * 3.14 / max.to_f))
|
679
|
+
|
680
|
+
y += rand * 2.0
|
681
|
+
|
682
|
+
@layer_data << { :x => x, :y => y }
|
683
|
+
end
|
684
|
+
|
685
|
+
# adding simple layer
|
686
|
+
@layer_params = {
|
687
|
+
:label => 'raw',
|
688
|
+
:value_labels => false,
|
689
|
+
:simple_smoother => false,
|
690
|
+
:simple_smoother_level => 1,
|
691
|
+
:simple_smoother_strategy => :gauss,
|
692
|
+
:simple_smoother_x => false,
|
693
|
+
}
|
694
|
+
@layer_params_b = @layer_params.clone.merge(
|
695
|
+
{
|
696
|
+
:label => 'smoothed - level 3',
|
697
|
+
:simple_smoother_level => 3,
|
698
|
+
:simple_smoother => true
|
699
|
+
})
|
700
|
+
@layer_params_e = @layer_params.clone.merge(
|
701
|
+
{
|
702
|
+
:label => 'smoothed - level 50',
|
703
|
+
:simple_smoother_level => 50,
|
704
|
+
:simple_smoother => true
|
705
|
+
})
|
706
|
+
|
707
|
+
@tg.add_layer(@layer_data.clone, @layer_params)
|
708
|
+
@tg.add_layer(@layer_data.clone, @layer_params_b)
|
709
|
+
@tg.add_layer(@layer_data.clone, @layer_params_e)
|
710
|
+
|
711
|
+
@tg.render
|
712
|
+
file_name = 'samples/readme/15_smoothing.png'
|
713
|
+
@tg.image_drawer.save_to_file(file_name)
|
714
|
+
</code>
|
715
|
+
</pre>
|
716
|
+
|
717
|
+
!https://github.com/akwiatkowski/technical_graph/raw/master/samples/readme/15_smoothing.png((15) Smoothing)!
|
718
|
+
|
719
|
+
|
720
|
+
|
721
|
+
h2. Noise removal
|
722
|
+
|
723
|
+
p. Useful when origin of data is a bit noisy. For best results you can add two layers: one raw, and second with noise removal.
|
724
|
+
Can be used with smoothing.
|
725
|
+
|
726
|
+
<pre>
|
727
|
+
<code>
|
728
|
+
@tg = TechnicalGraph.new(
|
729
|
+
{
|
730
|
+
:legend => true
|
731
|
+
}
|
732
|
+
)
|
733
|
+
max = 250
|
734
|
+
|
735
|
+
@layer_data = Array.new
|
736
|
+
(0..max).each do |i|
|
737
|
+
x = -10.0 + (20.0 * i.to_f / max.to_f)
|
738
|
+
y = -10.0 + (20.0 * i.to_f / max.to_f)
|
739
|
+
@layer_data << { :x => x, :y => y }
|
740
|
+
end
|
741
|
+
|
742
|
+
# custom spikes
|
743
|
+
[3, 36, 99, 187, 204].each do |i|
|
744
|
+
offset = 5.0
|
745
|
+
offset *= -1.0 if rand(100) % 2 == 1
|
746
|
+
@layer_data[i][:y] += offset
|
747
|
+
end
|
748
|
+
|
749
|
+
# some random spikes
|
750
|
+
150.times do
|
751
|
+
i = rand(@layer_data.size)
|
752
|
+
offset = rand(80).to_f / 10.0
|
753
|
+
offset *= -1.0 if rand(100) % 2 == 1
|
754
|
+
|
755
|
+
@layer_data[i][:y] += offset
|
756
|
+
end
|
757
|
+
|
758
|
+
# adding simple layer
|
759
|
+
@layer_params = {
|
760
|
+
:label => 'raw',
|
761
|
+
:value_labels => false,
|
762
|
+
}
|
763
|
+
@layer_params_b = @layer_params.clone.merge(
|
764
|
+
{
|
765
|
+
:label => 'n.r. level 3, window 10',
|
766
|
+
:noise_removal_window_size => 10,
|
767
|
+
:noise_removal_level => 3,
|
768
|
+
:noise_removal => true
|
769
|
+
})
|
770
|
+
@layer_params_e = @layer_params.clone.merge(
|
771
|
+
{
|
772
|
+
:label => 'n.r level 10, window 30',
|
773
|
+
:noise_removal_window_size => 10,
|
774
|
+
:noise_removal_level => 30,
|
775
|
+
:noise_removal => true
|
776
|
+
})
|
777
|
+
|
778
|
+
@tg.add_layer(@layer_data.clone, @layer_params)
|
779
|
+
@tg.add_layer(@layer_data.clone, @layer_params_b)
|
780
|
+
@tg.add_layer(@layer_data.clone, @layer_params_e)
|
781
|
+
|
782
|
+
@tg.render
|
783
|
+
file_name = 'samples/readme/16_noise_removal.png'
|
784
|
+
@tg.image_drawer.save_to_file(file_name)
|
785
|
+
</code>
|
786
|
+
</pre>
|
787
|
+
|
788
|
+
!https://github.com/akwiatkowski/technical_graph/raw/master/samples/readme/16_noise_removal.png((16) Noise removal)!
|
789
|
+
|
790
|
+
|
791
|
+
|
792
|
+
|
793
|
+
|
794
|
+
h2. Axis interval enlargement
|
795
|
+
|
796
|
+
p. In case of large amount of data axis can be squeezed and graph is unreadable. You can set axis enlargement to kick in
|
797
|
+
in these situations. When distance between axis is lower than set in options[:x_axis_min_distance] or
|
798
|
+
options[:y_axis_min_distance] image dimensions are enlarged to maintain proper axis distances.
|
799
|
+
|
800
|
+
<pre>
|
801
|
+
<code>
|
802
|
+
@tg = TechnicalGraph.new(
|
803
|
+
{
|
804
|
+
:axis_density_enlarge_image => true,
|
805
|
+
:x_axis_min_distance => 500,
|
806
|
+
:x_axis_interval => 1.0,
|
807
|
+
:x_axis_fixed_interval => true,
|
808
|
+
:width => 400
|
809
|
+
}
|
810
|
+
)
|
811
|
+
max = 250
|
812
|
+
|
813
|
+
@layer_data = Array.new
|
814
|
+
(0..max).each do |i|
|
815
|
+
x = -10.0 + (20.0 * i.to_f / max.to_f)
|
816
|
+
y = -10.0 + rand(2000).to_f / 100.0
|
817
|
+
@layer_data << { :x => x, :y => y }
|
818
|
+
end
|
819
|
+
|
820
|
+
@tg.add_layer(@layer_data)
|
821
|
+
|
822
|
+
@tg.render
|
823
|
+
file_name = 'samples/readme/17_axis_enlargement.png'
|
824
|
+
@tg.image_drawer.save_to_file(file_name)
|
825
|
+
</code>
|
826
|
+
</pre>
|
427
827
|
|
828
|
+
!https://github.com/akwiatkowski/technical_graph/raw/master/samples/readme/17_axis_enlargement.png((17) Axis enlargement)!
|
428
829
|
|
429
830
|
|
430
831
|
h2. TODO
|
431
832
|
|
432
|
-
#
|
433
|
-
#
|
434
|
-
#
|
435
|
-
#
|
436
|
-
# Layer labels: used in legend
|
437
|
-
# Layer colors, random colors
|
438
|
-
# Legend with set position
|
439
|
-
# Legend with auto position
|
440
|
-
# Smoother:
|
441
|
-
# Noise removal
|
833
|
+
# Axis density checking algorithm - more info
|
834
|
+
# Smoother - parameters
|
835
|
+
# Noise removal - para
|
836
|
+
# Adjusting axis to zero
|