Algorithm-RandomPointGenerator
view release on metacpan or search on metacpan
lib/Algorithm/RandomPointGenerator.pm view on Meta::CPAN
}
# Plotting a 3D surface with Gnuplot requires that the input data be provided as a
# sequence of triples in a text file, with each triple in a separate line, and with
# each triple consisting of the x coordinate, followed by the y coordinate, which is
# then following by the height of the surface at that point. Additionally, and very
# importantly, this file must be separated into blocks, with the blocks separated by
# empty lines. Each block is for a single x coordinate and all the lines in a single
# block must be sorted with respected to the y coordinated. The blocks must be
# sorted with respect to the x coordinate.
sub plot_histogram_3d_surface {
my $self = shift;
die "\nyou must call make_output_histogram_for_generated_points() before you can call\n" .
"plot_histogram_3d_surface()$!\n" unless $self->{_output_histogram};
my $pause_time = shift;
my $hist = $self->{_output_histogram};
my @plot_points = ();
foreach my $y (0..@$hist-1) {
foreach my $x (0..@{$hist->[0]}-1) {
push @plot_points, [$x, $y, $hist->[$y][$x]];
push @plot_points, [$x+1, $y, $hist->[$y][$x]];
push @plot_points, [$x, $y+1, $hist->[$y][$x]];
push @plot_points, [$x+1, $y+1, $hist->[$y][$x]];
}
}
@plot_points = sort {$a->[0] <=> $b->[0]} @plot_points;
@plot_points = sort {$a->[1] <=> $b->[1] if $a->[0] == $b->[0]} @plot_points;
my $master_file_basename = basename($self->{_hist_file}, ('.csv', '.dat', '.txt'));
my $temp_file = "__temp_$master_file_basename.dat";
open(OUTFILE , ">$temp_file") or die "Cannot open temporary file: $!";
my ($first, $oldfirst);
$oldfirst = $plot_points[0]->[0];
foreach my $sample (@plot_points) {
$first = $sample->[0];
if ($first == $oldfirst) {
my @out_sample;
$out_sample[0] = $self->{_bounding_box}->[0][0] + $sample->[0] *
$self->{_bin_width_for_output_hist};
$out_sample[1] = $self->{_bounding_box}->[1][0] + $sample->[1] *
$self->{_bin_height_for_output_hist};
$out_sample[2] = $sample->[2];
print OUTFILE "@out_sample\n";
} else {
print OUTFILE "\n";
}
$oldfirst = $first;
}
print OUTFILE "\n";
close OUTFILE;
my $x_left = $self->{_bounding_box}->[0][0];
my $x_right = $self->{_bounding_box}->[0][1];
my $y_lower = $self->{_bounding_box}->[1][0];
my $y_upper = $self->{_bounding_box}->[1][1];
my $argstring = <<"END";
set xrange [$x_left:$x_right]
set yrange [$y_lower:$y_upper]
set pm3d
splot "$temp_file" with pm3d
END
unless (defined $pause_time) {
my $hardcopy_name = "output_histogram_for_$master_file_basename.png";
my $plot1 = Graphics::GnuplotIF->new();
$plot1->gnuplot_cmd( 'set terminal png', "set output \"$hardcopy_name\"");
$plot1->gnuplot_cmd( $argstring );
my $plot2 = Graphics::GnuplotIF->new(persist => 1);
$plot2->gnuplot_cmd( $argstring );
} else {
my $plot = Graphics::GnuplotIF->new();
$plot->gnuplot_cmd( $argstring );
$plot->gnuplot_pause( $pause_time );
}
}
sub plot_histogram_lineplot {
my $self = shift;
my $pause_time = shift;
die "\nyou must call make_output_histogram_for_generated_points() before you can call\n" .
"plot_histogram_lineplot()$!\n" unless $self->{_output_histogram};
my $hist = $self->{_output_histogram};
my @plot_points = ();
foreach my $y (0..@$hist-1) {
foreach my $x (0..@{$hist->[0]}-1) {
push @plot_points, [$x, $y, $hist->[$y][$x]];
push @plot_points, [$x+1, $y, $hist->[$y][$x]];
push @plot_points, [$x, $y+1, $hist->[$y][$x]];
push @plot_points, [$x+1, $y+1, $hist->[$y][$x]];
}
}
@plot_points = sort {$a->[0] <=> $b->[0]} @plot_points;
@plot_points = sort {$a->[1] <=> $b->[1] if $a->[0] == $b->[0]} @plot_points;
my $master_file_basename = basename($self->{_hist_file}, ('.csv', '.dat', '.txt'));
my $temp_file = "__temp_$master_file_basename.dat";
open(OUTFILE , ">$temp_file") or die "Cannot open temporary file: $!";
my ($first, $oldfirst);
$oldfirst = $plot_points[0]->[0];
foreach my $sample (@plot_points) {
$first = $sample->[0];
if ($first == $oldfirst) {
my @out_sample;
$out_sample[0] = $self->{_bounding_box}->[0][0] + $sample->[0] *
$self->{_bin_width_for_output_hist};
$out_sample[1] = $self->{_bounding_box}->[1][0] + $sample->[1] *
$self->{_bin_height_for_output_hist};
$out_sample[2] = $sample->[2];
print OUTFILE "@out_sample\n";
} else {
print OUTFILE "\n";
}
$oldfirst = $first;
}
print OUTFILE "\n";
close OUTFILE;
my $argstring = <<"END";
set hidden3d
splot "$temp_file" with lines
END
my $plot;
if (!defined $pause_time) {
$plot = Graphics::GnuplotIF->new( persist => 1 );
} else {
$plot = Graphics::GnuplotIF->new();
}
# my $plot = Graphics::GnuplotIF->new(persist => 1);
lib/Algorithm/RandomPointGenerator.pm view on Meta::CPAN
Graphics::GnuplotIF, for creating a 3D surface plot of the histogram of the random
points generated by the module.
=item B<plot_histogram_lineplot():>
$generator->plot_histogram_lineplot();
This creates a 3D line plot display of the histogram of the generated random points.
=item B<display_output_histogram_in_terminal_window():>
$generator->display_output_histogram_in_terminal_window();
Useful for debugging purposes, it displays in the terminal window a two dimensional
array of numbers that is the histogram of the random points generated by the module.
=back
=head1 THE C<examples> DIRECTORY
Probably the most useful item in the C<examples> directory is the command-line script
C<genRand2D> that can be called simply with two arguments for generating a set of
random points. A call to this script looks like
genRand2D --histfile your_histogram_file.csv --bbfile your_bounding_box_file.csv
where the C<--histfile> option supplies the name of the file that contains a 2D input
histogram and the C<--bbfile> option the name of the file that defines the bounding
box in the XY-plane. You can also execute the command line
genRand2D --help
for displaying information as to what is required by the two options for the
C<genRand2D> command. The command-line invocation of C<genRand2D> gives you 2000
random points that are deposited in a file whose name is printed out in the terminal
window in which you execute the command.
To become more familiar with all of the different options you can use with this
module, you should experiment with the script:
generate_random_points.pl
You can feed it different 2D histograms --- even made-up 2D histograms --- and look
at the histogram of the generated random points to see how well the module is
working. Keep in mind, though, if your made-up input histogram has disconnected
blobs in it, the random-points that are generated may correspond to just one of the
blobs. Since the process of random-point generation involves a random walk, the
algorithm may not be able to hop from one blob to another in the input histogram if
they are too far apart. As to what exactly you'll get by way of the output histogram
would depend on your choice of the width of the proposal density.
The C<examples> directory contains the following histogram and bounding-box files
for you to get started:
hist1.csv bb1.csv
hist2.csv bb2.csv
If you run the C<generate_random_points.pl> script with the C<hist1.csv> and
C<bb1.csv> files, the histogram you get for the 2000 random points generated by the
module will look like what you see in the file C<output_histogram_for_hist1.png>. On
a Linux machine, you can see this histogram with the usual C<display> command from
the ImageMagick library. And if you run C<generate_random_points.pl> script with the
C<hist2.csv> and C<bb2.csv> files, you'll see an output histogram that should look
like what you see in C<output_histogram_for_hist2.png>.
You should also try invoking the command-line calls:
genRand2D --histfile hist1.csv --bbfile bb1.csv
genRand2D --histfile hist2.csv --bbfile bb2.csv
=head1 REQUIRED
This module requires the following three modules:
List::Util
Graphics::GnuplotIF
Math::Big
Math::Random
=head1 EXPORT
None by design.
=head1 BUGS
Please notify the author if you encounter any bugs. When sending email, please place
the string 'RandomPointGenerator' in the subject line.
=head1 INSTALLATION
Download the archive from CPAN in any directory of your choice. Unpack the archive
with a command that on a Linux machine would look like:
tar zxvf Algorithm-RandomPointGenerator-1.01.tar.gz
This will create an installation directory for you whose name will be
C<Algorithm-RandomPointGenerator-1.01>. Enter this directory and execute the
following commands for a standard install of the module if you have root privileges:
perl Makefile.PL
make
make test
sudo make install
if you do not have root privileges, you can carry out a non-standard install the
module in any directory of your choice by:
perl Makefile.PL prefix=/some/other/directory/
make
make test
make install
With a non-standard install, you may also have to set your PERL5LIB environment
variable so that this module can find the required other modules. How you do that
would depend on what platform you are working on. In order to install this module in
a Linux machine on which I use tcsh for the shell, I set the PERL5LIB environment
variable by
setenv PERL5LIB /some/other/directory/lib64/perl5/:/some/other/directory/share/perl5/
If I used bash, I'd need to declare:
( run in 2.073 seconds using v1.01-cache-2.11-cpan-df04353d9ac )