Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

wxPerl Integration with GD::Graph Example

by jmlynesjr (Friar)
on Jun 29, 2013 at 19:43 UTC ( #1041508=CUFP: print w/ replies, xml ) Need Help??

For your graphing enjoyment...an L or C Impedance Graph with selectable frequency sweep and scaling.

Original version used the Gnome viewer to display the graph. This "final" version uses a PaintDC and is thus platform independant. Many thanks to Mark Dootson for the PaintDC code.

#! /home/pete/CitrusPerl/perl/bin/perl # ImpedanceGraph2.pl # Impedance calculator for Ls & Cs with graphic display # # Example of using GD::Graph with wxPerl to draw a simple line graph. # # Calculates and graphs the L or C impedance for a range of frequencie +s. # Graph and save_chart borrowed from GD::Graph sample51.pl # # Notes: Original version used the Linux Gnome File Viewer - eog - to +display the graph file. # # This version uses a Display Dialog and Display Panel to display +the # png graph image using a PaintDC. This version is platform Indepe +ndant. # # James M. Lynes, Jr. # Last Modified: June 29, 2013 # # DisplayDialog and DisplayPanel code provided by Mark Dootson, integr +ated June 29, 2013. # package main; use strict; use warnings; my $app = App->new(); $app->MainLoop; package App; use strict; use warnings; use base 'Wx::App'; sub OnInit { Wx::InitAllImageHandlers(); my $frame = Frame->new(); $frame->Show(1); } package DisplayPanel; use strict; use warnings; use Wx qw(:everything); use base qw(Wx::Panel); use Wx::Event qw( EVT_PAINT ); sub new { my ($class, $parent, $bitmap) = @_; my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, [ $bitmap->GetWidth, $bitmap->GetHeight +], wxBORDER_NONE); $self->{bitmap} = $bitmap; EVT_PAINT($self, \&OnEvtPaint); return $self; } sub OnEvtPaint { my ($self, $event) = @_; my $dc = Wx::PaintDC->new($self); $dc->DrawBitmap($self->{bitmap}, 0,0,0); } package DisplayDialog; use strict; use warnings; use Wx qw(:everything); use base qw(Wx::Dialog); sub new { my($class, $parent, $image) = @_; my $self = $class->SUPER::new($parent, -1, 'Impedance vs. Frequenc +y Graph'); my $bitmap = Wx::Bitmap->new($image); my $canvas = DisplayPanel->new($self, $bitmap); my $sizer = Wx::BoxSizer->new(wxVERTICAL); $sizer->Add($canvas,1,wxEXPAND|wxALL,0); $self->SetSizerAndFit($sizer); return $self; } package Frame; use strict; use warnings; use Wx qw(:everything); use base qw(Wx::Frame); use Wx::Event qw(EVT_BUTTON EVT_CHOICE); use GD::Graph::lines; use Data::Dumper; sub new { my($self) = @_; $self = $self->SUPER::new(undef, -1, "L or C Impedance Graph", wxDefaultPosition, [375, 550]); my @Inductors = ("nH", "uH", "mH"); my @Capacitors = ("pF", "nF", "uF"); my @Frequency = ("Hz", "KHz", "MHz"); $self->{lmultiplyer} = 1E-09; # nH Default Scale Factors $self->{cmultiplyer} = 1E-12; # pF $self->{flmultiplyer} = 1E06; # MHz $self->{fhmultiplyer} = 1E06; # MHz $self->{swmultiplyer} = 1E06; # Mhz $self->{xamultiplyer} = 1E06; # Mhz $self->{st1} = Wx::StaticText->new($self, -1, "Inductor Value", Wx +::Point->new(25,50), wxDefaultSize, wxALIGN_LEFT); $self->{st2} = Wx::StaticText->new($self, -1, "Capacitor Value", W +x::Point->new(25,100), wxDefaultSize, wxALIGN_LEFT); $self->{st3} = Wx::StaticText->new($self, -1, "Sweep Start", Wx::P +oint->new(25,150), wxDefaultSize, wxALIGN_LEFT); $self->{st4} = Wx::StaticText->new($self, -1, "Sweep End", Wx::Poi +nt->new(25,200), wxDefaultSize, wxALIGN_LEFT); $self->{st5} = Wx::StaticText->new($self, -1, "Sweep Step", Wx::Po +int->new(25,250), wxDefaultSize, wxALIGN_LEFT); $self->{st6} = Wx::StaticText->new($self, -1, "Enter an L or C and + a Sweep Range to be Graphed", Wx::Point->new(25,15), wxDefaul +tSize, wxALIGN_LEFT); $self->{st7} = Wx::StaticText->new($self, -1, "Y-Axis Max", Wx::Po +int->new(25,450), wxDefaultSize, wxALIGN_LEFT); $self->{st8} = Wx::StaticText->new($self, -1, "Y-Axis Ticks", Wx:: +Point->new(25,475), wxDefaultSize, wxALIGN_LEFT); $self->{st8} = Wx::StaticText->new($self, -1, "X-Axis Scale", Wx:: +Point->new(25,500), wxDefaultSize, wxALIGN_LEFT); $self->{tc1} = Wx::TextCtrl->new($self, -1, "", Wx::Point->new(150 +,50), Wx::Size->new(100,20)); $self->{tc2} = Wx::TextCtrl->new($self, -1, "", Wx::Point->new(150 +,100), Wx::Size->new(100,20)); $self->{tc3} = Wx::TextCtrl->new($self, -1, "", Wx::Point->new(150 +,150), Wx::Size->new(100,20)); $self->{tc4} = Wx::TextCtrl->new($self, -1, "", Wx::Point->new(150 +,200), Wx::Size->new(100,20)); $self->{tc5} = Wx::TextCtrl->new($self, -1, "", Wx::Point->new(150 +,250), Wx::Size->new(100,20)); $self->{tc6} = Wx::TextCtrl->new($self, -1, "", Wx::Point->new(150 +,450), Wx::Size->new(100,20)); $self->{tc7} = Wx::TextCtrl->new($self, -1, "", Wx::Point->new(150 +,475), Wx::Size->new(100,20)); $self->{tc1}->SetValue(0); # L = 0 Default Data Values $self->{tc2}->SetValue(0); # C = 0 $self->{tc3}->SetValue(1); # 1 MHz $self->{tc4}->SetValue(30); # 30 MHz $self->{tc5}->SetValue(1); # 1 MHz $self->{tc6}->SetValue(10000); # 10K ohms $self->{tc7}->SetValue(20); # 20 ticks $self->{lc} = Wx::Choice->new($self, 1, Wx::Point->new(250, 50), w +xDefaultSize, \@Inductors); $self->{cc} = Wx::Choice->new($self, 2, Wx::Point->new(250, 100), +wxDefaultSize, \@Capacitors); $self->{flc} = Wx::Choice->new($self, 3, Wx::Point->new(250, 150), + wxDefaultSize, \@Frequency); $self->{fhc} = Wx::Choice->new($self, 4, Wx::Point->new(250, 200), + wxDefaultSize, \@Frequency); $self->{swc} = Wx::Choice->new($self, 5, Wx::Point->new(250, 250), + wxDefaultSize, \@Frequency); $self->{xscale} = Wx::Choice->new($self, 6, Wx::Point->new(150, 50 +0), wxDefaultSize, \@Frequency); $self->{flc}->SetSelection(2); # MHz Defaut Choices $self->{fhc}->SetSelection(2); # MHz $self->{swc}->SetSelection(2); # MHz $self->{xscale}->SetSelection(2); # MHz $self->{bt1} = Wx::Button->new($self, 4, "Graph Cs", Wx::Point->ne +w(25,350), wxDefaultSize); $self->{bt1} = Wx::Button->new($self, 5, "Graph Ls", Wx::Point->ne +w(150,350), wxDefaultSize); $self->{bt1} = Wx::Button->new($self, 6, "Clear C and L", Wx::Poin +t->new(25,300), wxDefaultSize); $self->{bt2} = Wx::Button->new($self, wxID_CLOSE, "Exit", Wx::Poin +t->new(25,400), wxDefaultSize); EVT_BUTTON($self, 4, \&CalcC); EVT_BUTTON($self, 5, \&CalcL); EVT_BUTTON($self, 6, \&ClearAll); EVT_BUTTON($self, wxID_CLOSE, \&Close); EVT_CHOICE($self, 1, \&ChoiceL); EVT_CHOICE($self, 2, \&ChoiceC); EVT_CHOICE($self, 3, \&ChoiceFL); EVT_CHOICE($self, 4, \&ChoiceFH); EVT_CHOICE($self, 5, \&ChoiceSW); EVT_CHOICE($self, 6, \&ChoiceXA); return $self; } sub CalcC { my($self, $event) = @_; my @xvalues; my @yvalues; my $C = $self->{tc2}->GetValue * $self->{cmultiplyer}; if($C == 0) {return}; my $fl = $self->{tc3}->GetValue * $self->{flmultiplyer}; my $fh = $self->{tc4}->GetValue * $self->{fhmultiplyer}; my $sw = $self->{tc5}->GetValue * $self->{swmultiplyer}; for(my $F = $fl; $F <= $fh; $F += $sw) { my $I = 1/(6.28 * $C * $F); push(@xvalues, $F/$self->{xamultiplyer}); push(@yvalues, $I); } Graph($self, \@xvalues, \@yvalues); } sub CalcL { my($self, $event) = @_; my @xvalues; my @yvalues; my $L = $self->{tc1}->GetValue * $self->{lmultiplyer}; if($L == 0) {return}; my $fl = $self->{tc3}->GetValue * $self->{flmultiplyer}; my $fh = $self->{tc4}->GetValue * $self->{fhmultiplyer}; my $sw = $self->{tc5}->GetValue * $self->{swmultiplyer}; for(my $F = $fl; $F <= $fh; $F += $sw) { my $I = 6.28 * $L * $F; push(@xvalues, $F/$self->{xamultiplyer}); push(@yvalues, $I); } Graph($self, \@xvalues, \@yvalues); } sub ChoiceL { my($self, $event) = @_; if($self->{lc}->GetSelection == 0) {$self->{lmultiplyer} = 1E-09}; + # nH if($self->{lc}->GetSelection == 1) {$self->{lmultiplyer} = 1E-06}; + # uH if($self->{lc}->GetSelection == 2) {$self->{lmultiplyer} = 1E-03}; + # mH } sub ChoiceC { my($self, $event) = @_; if($self->{cc}->GetSelection == 0) {$self->{cmultiplyer} = 1E-12}; + # pF if($self->{cc}->GetSelection == 1) {$self->{cmultiplyer} = 1E-09}; + # nF if($self->{cc}->GetSelection == 2) {$self->{cmultiplyer} = 1E-06}; + # uF } sub ChoiceFL { my($self, $event) = @_; if($self->{flc}->GetSelection == 0) {$self->{flmultiplyer} = 1}; + # Hz if($self->{flc}->GetSelection == 1) {$self->{flmultiplyer} = 1E03} +; # KHz if($self->{flc}->GetSelection == 2) {$self->{flmultiplyer} = 1E06} +; # MHz } sub ChoiceFH { my($self, $event) = @_; if($self->{fhc}->GetSelection == 0) {$self->{fhmultiplyer} = 1}; + # Hz if($self->{fhc}->GetSelection == 1) {$self->{fhmultiplyer} = 1E03} +; # KHz if($self->{fhc}->GetSelection == 2) {$self->{fhmultiplyer} = 1E06} +; # MHz } sub ChoiceSW { my($self, $event) = @_; if($self->{swc}->GetSelection == 0) {$self->{swmultiplyer} = 1}; + # Hz if($self->{swc}->GetSelection == 1) {$self->{swmultiplyer} = 1E03} +; # KHz if($self->{swc}->GetSelection == 2) {$self->{swmultiplyer} = 1E06} +; # MHz } sub ChoiceXA { my($self, $event) = @_; if($self->{xscale}->GetSelection == 0) {$self->{xamultiplyer} = 1} +; # Hz if($self->{xscale}->GetSelection == 1) {$self->{xamultiplyer} = 1E +03}; # KHz if($self->{xscale}->GetSelection == 2) {$self->{xamultiplyer} = 1E +06}; # MHz } sub ClearAll { my($self, $event) = @_; $self->{tc1}->SetValue(0); # L = 0 $self->{tc2}->SetValue(0); # C = 0 } sub Close { my($self, $event) = @_; $self->Destroy; } sub Graph { # GD::Graph::lines Line Graph Module my($self, $xvalues, $yvalues) = @_; # From GDGraph-1.45.tar +.gz sample51.pl my @data = ( # Other graph formats are supported. +See the pod. [(@{$xvalues}) ], [(@{$yvalues})], ); my $xlskip = (int(@{$xvalues}) / 30) + 1; # Only about 30 label +s will fit on the x axis. Gotta skip some. # Labels still overwrite on occasions. Play wi +th the scaling. my $my_graph = new GD::Graph::lines(600,400); my $xscale = $self->{xscale}->GetStringSelection; # Hz, KHz, MH +z $my_graph->set( x_label => "Frequency($xscale)", y_label => 'Impedance(Ohms)', title => 'Impedance vs. Frequency', y_max_value => $self->{tc6}->GetValue, y_min_value => 0, y_tick_number => $self->{tc7}->GetValue, y_label_skip => 2, box_axis => 0, line_width => 3, transparent => 0, x_label_position => 1/2, x_label_skip => $xlskip, ); my $gd = $my_graph->plot(\@data); #save_chart($my_graph, 'impedance'); # From sample51.pl not + used in this configuration #system('eog /home/pete/Projects/perlprojects/RFdesign/impedance.g +if'); # Get the raw PNG data my $png = $gd->png; # Get a file handle and load it as a wxImage open my $fh, '<', \$png; my $img = Wx::Image->new($fh, &Wx::wxBITMAP_TYPE_PNG); close $fh; my $dialog = DisplayDialog->new($self, $img); $dialog->Centre; $dialog->ShowModal(); $dialog->Destroy; } sub save_chart # Separate sub because the sampl +e51.pl was setup this way. { # Not used in this configuration my $chart = shift or die "Need a chart!"; my $name = shift or die "Need a name!"; local(*OUT); my $ext = $chart->export_format; open(OUT, ">$name.$ext") or die "Cannot open $name.$ext for write: $!"; binmode OUT; print OUT $chart->gd->$ext(); close OUT; } 1;

Cross-Posted to wxperl-users.org

James

There's never enough time to do it right, but always enough time to do it over...

Comment on wxPerl Integration with GD::Graph Example
Download Code

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: CUFP [id://1041508]
Approved by kcott
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chanting in the Monastery: (10)
As of 2015-07-29 12:11 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (263 votes), past polls