view release on metacpan or search on metacpan
0.07 2022-07-26 12:50:22-04:00 America/New_York
[BUG FIX]
* make tests work with Type::Tiny v1.016 (ANDK++)
0.06 2021-10-18 22:06:31-04:00 America/New_York
[BUG FIX]
* CXC::Number::Grid::overlay_n compared range extrema as strings instead
of numbers. Ooops.
[ENHANCEMENT]
* The edges argument to CXC::Number::Grid->new can take a CXC::Number::Sequence object
0.05 2021-05-03 10:13:09-04:00 America/New_York
[BUILD FIXES]
* Requires at least Hash::Wrap 0.11 (RT#136409 ++srezic)
t/00-compile.t
t/00-report-prereqs.dd
t/00-report-prereqs.t
t/Grid/Tree/basic.t
t/Grid/Tree/snap.t
t/Grid/combine_bins.t
t/Grid/edges.t
t/Grid/interface.t
t/Grid/join.t
t/Grid/ops.t
t/Grid/overlay.t
t/Grid/regressions.t
t/Grid/select.t
t/Grid/split.t
t/Sequence/Fixed/sequence.t
t/Sequence/Linear/interface.t
t/Sequence/Linear/sequence.t
t/Sequence/Ratio/interface.t
t/Sequence/Ratio/sequence.t
t/Sequence/Types.t
t/Sequence/interface.t
CXC::Number
The following are known:
CXC::Number::Grid
A representation of a grid of numbers, with the ability to join and
overlay grids. Useful for binning data.
CXC::Number::Sequence
A namespace and module for dealing with sequences of numbers, often
constructed so that they are useful for binning data.
INSTALLATION
This is a Perl module distribution. It should be installed with whichever
tool you use to manage your installation of Perl, e.g. any of
lib/CXC/Number.pm view on Meta::CPAN
=head1 DESCRIPTION
The following are known:
=over
=item L<CXC::Number::Grid>
A representation of a grid of numbers, with the ability to join and
overlay grids. Useful for binning data.
=item L<CXC::Number::Sequence>
A namespace and module for dealing with sequences of numbers, often
constructed so that they are useful for binning data.
=back
=head1 INTERNALS
lib/CXC/Number/Grid.pm view on Meta::CPAN
use Moo;
our $VERSION = '0.13';
use constant GridObject => InstanceOf [ ( __PACKAGE__ ) ];
use constant IncludeArray => ArrayRef [ Enum [ 0, 1 ] ];
use experimental 'signatures';
use Exporter::Shiny qw( join_n overlay_n );
use namespace::clean;
use MooX::StrictConstructor;
use overload
'!' => \&_overload_not,
'|' => \&_overload_or,
'&' => \&_overload_and,
fallback => 1,
lib/CXC/Number/Grid.pm view on Meta::CPAN
sub overlay ( $self, @args ) {
return overlay_n( $self, @args );
}
lib/CXC/Number/Grid.pm view on Meta::CPAN
sub overlay_n {
state $signature = signature(
positional => [
ArrayRef [GridObject],
Optional [
Dict [
snap_dist => Optional [BigPositiveOrZeroNum],
snap_to => Optional [ Enum [ 'underlay', 'overlay' ] ],
],
],
],
);
my @dict = ( @_ && is_plain_hashref( $_[-1] ) ? pop @_ : () );
my ( $grids, $opt ) = $signature->( \@_, @dict, );
$opt->{snap_to} //= 'underlay';
lib/CXC/Number/Grid.pm view on Meta::CPAN
$gridj = $grid1->join( $grid2 );
=head1 DESCRIPTION
C<CXC::Number::Grid> provides an abstraction of a one dimensional
grid. A grid is composed of contiguous bins, each of which has a flag
indicating whether or not it should be included in a process (where
I<process> is defined by the user of the grid).
This class provides facilities to I<join> grids (e.g. butt them
together) and I<overlay> grids, with a number of approaches to
handle the consequences of inevitable numeric imprecision.
Underneath the grid is stored as L<Math::BigFloat> objects.
=head1 OBJECT ATTRIBUTES
=head2 oob
A boolean, which, if true, indicates that extra bins are added to
either end of the grid which catch values outside of the range of the
lib/CXC/Number/Grid.pm view on Meta::CPAN
=head2 join
$grid = $grid1->join( $grid2, $grid3, ..., ?\%options );
Join two grids together. This is akin to a I<butt> joint, with control
over how to handle any gap between the grids.
See C<< L</join_n> >> for a description of the options.
=head2 overlay
$grid = $grid1->overlay( $grid2, ..., $gridn, ?\%options );
Overlay one or more grids on top of C<$grid1> and return a new grid.
See C<< L</overlay_n> >> for a description of the options.
=head2 not
$flipped = $grid->not;
return a copy of C<$grid> with a Boolean not of its include values.
=head2 or
$ABC = $A->or( $B, $C, ..., ?\%options );
lib/CXC/Number/Grid.pm view on Meta::CPAN
$AB = $A | $B
The logical AND C<&> operator is overloaded via
$AB = $A->and($B);
see L</or> for details.
=head1 SUBROUTINES
=head2 overlay_n
$grid = CXC::Number::Grid::overlay_n( $grid1, $grid2, ... $gridN, ?\%options );
Overlay each successive grid on the overlay of the previous sequence of grids.
The process essentially excises the range in the underlying grid covered by the
overlying grid and inserts the overlying grid in that place. For example, if
$overlay = overlay_n( $grid1, $grid2 );
with
$grid1:
: +-------------------------------------------------+
: | | | | | | | | | | |
: +-------------------------------------------------+
$grid2:
: +--------------------------------+
: | | | |
: +--------------------------------+
$overlay:
: +-------------------------------------------------+
: | | | | | | | |
: +-------------------------------------------------+
The C<%options> hash is optional; the following options are available:
=over
=item C<snap_dist> => I<float>
If the minimum or maximum edge of an overlying grid is closer than
this number to the nearest unobscured edge in the underlying grid,
snap the grid edges according to the value of L<snap_to>.
The default value is C<0>, which turns off snapping.
=item C<snap_to> => C<underlay> | C<overlay>
This indicates how to treat bin edges when C<< L</snap_dist> >> is not zero.
From the above example of the overlay of two grids:
0 1 2 3 4 5 6 7
+-------------------------------------------------+
| | | | | | | |
+-------------------------------------------------+
1 1 2 2 2 2 1 1
The upper numbers are the edge indices and the lower indicate the grid
the edge came from.
lib/CXC/Number/Grid.pm view on Meta::CPAN
Setting C<snap_to> to C<underlay> will adjust edge I<2> (which
originates from C<$grid2>, the overlying grid) so that it is equal to
edge I<1> (from C<$grid1>, the underlying grid).
0 1 2 3 4 5 6
+-------------------------------------------------+
| | | | | | |
+-------------------------------------------------+
1 1 2 2 2 1 1
Conversely, setting C<snap_to> to C<overlay> will adjust edge I<1>
(originating from C<$grid1>, the underlying grid) so that it is equal
to edge I<2> (from C<$grid2> the overlying grid).
0 1 2 3 4 5 6
+-------------------------------------------------+
| | | | | | |
+-------------------------------------------------+
1 2 2 2 2 1 1
=back
lib/CXC/Number/Grid/Tree.pm view on Meta::CPAN
lb => $r[1],
ub => $r[2],
} )
: undef;
}
my $current = next_range();
my $next;
my %SnapTo = (
overlay => {
right => sub {
# would prefer
# $self->range_set( $prev->lb, $current->ub, $current->value );
# but there's no way to get $prev from Tree::Range.
#
# This code depends upon Tree::Range storing [ $lb, $value ]
# in each node, so deleting a node extends the previous
# range.
$self->delete( $current->lb );
$iter = iter( $current->lb );
lib/CXC/Number/Grid/Tree.pm view on Meta::CPAN
Snap overlaid bins' edges.
B<Works in place!!>
This assumes that the Tree has been
=over
=item 1
loaded with ranges from two grids, one of which overlays the other; and
=item 2
that the range values are arrayrefs with the first value being the
layer id (larger number indicates the top grid); and
=item 3
that the top grid is contiguous (e.g. no holes through which the
lower grid is visible)
lib/CXC/Number/Grid/Tree.pm view on Meta::CPAN
=over
=item *
move the outer edge of the top grid to coincide with the remaining edge of the intersected lower bin
(C<$snap_to = 'underlay'>)
=item *
move the remaining edge of the intersected lower bin to coincide with the edge of the top grid.
(C<$snap_to = 'overlay'>)
=back
=head2 clone
$clone = $tree->clone;
Clone a tree, performing a shallow copy of the values associated with each bin in the tree.
=head1 INTERNALS
t/Grid/Tree/snap.t view on Meta::CPAN
array {
item [ 0, 1, [ 1, 0 ] ];
item [ 1, 2, [ 1, 0 ] ];
item [ 2, 3, [ 1, 0 ] ];
end;
},
'layer 1, as array',
);
# unlink in overlay.t, use 0.2 & 1.2 instead of 0.1 & 1.1.
# we're not using BigFloat here, and 0.1 & 1.1 cause the tests to fail,
# as using standard doubles, abs(1.1-1) != 0.1
# second layer
$tree->range_set( 1.2, 2.2, [ 2, 1 ] );
is(
$tree->to_array,
array {
item [ 0, 1, [ 1, 0 ] ];
t/Grid/Tree/snap.t view on Meta::CPAN
is(
$tree->to_grid,
object {
call edges => [ 0, 1, 1.2, 2.2, 3 ];
call include => [ 0, 0, 1, 0 ];
},
'layer 2, as grid',
);
$tree->snap_overlaid( 2, 'overlay', 0.25 );
is(
$tree->to_array,
array {
item [ 0, 1.2, [ 1, 0 ] ];
item [ 1.2, 2.2, [ 2, 1 ] ];
item [ 2.2, 3, [ 1, 0 ] ];
end;
},
'1+2 snapped, as array',
) or note $tree->to_string;
$tree->range_set( 2.4, 3.4, [ 3, 0 ] );
$tree->snap_overlaid( 3, 'overlay', 0.25 );
is(
$tree->to_array,
array {
item [ 0, 1.2, [ 1, 0 ] ];
item [ 1.2, 2.4, [ 2, 1 ] ];
item [ 2.4, 3.4, [ 3, 0 ] ];
end;
},
'2+3 snapped, as array',
t/Grid/overlay.t view on Meta::CPAN
#! perl
use Test2::V0;
use CXC::Number::Grid qw( overlay_n );
use constant Grid => 'CXC::Number::Grid';
sub Failure { join( '::', 'CXC::Number::Grid::Failure', @_ ) }
subtest 'overlap' => sub {
subtest 'as is' => sub {
#<<< no tidy
my $grid1 = Grid->new( edges => [ 0, 1, 3, 5 ],
include => [ 0, 0, 0 ] );
my $grid2 = Grid->new( edges => [ 2, 4 ],
include => [ 1 ] );
#>>> ydit on
my $gridN = overlay_n( $grid1, $grid2 );
is(
$gridN,
object {
call bin_edges => array { item number $_ for 0, 1, 2, 4, 5 };
call include => array { item number $_ for 0, 0, 1, 0 };
},
);
};
subtest 'snap to overlay' => sub {
my $grid1
= Grid->new( edges => [ 0, 1, 2, 3 ], include => [ 0, 0, 0 ] );
my $grid2 = Grid->new( edges => [ 1.1, 2.2 ], include => [1] );
my $grid3 = Grid->new( edges => [ 2.3, 3.4 ], include => [0] );
my $gridN = overlay_n( $grid1, $grid2, $grid3, { snap_dist => 0.1, snap_to => 'overlay' } );
# grid1 < grid 2
# before snap
# edges : [ 0, 1, 1.1, 2.2, 3 ]
# layers: [ 1, 1, 2, 1 ]
# include: [ 0, 0, 1, 0 ]
# after snap
# edges : [ 0, 1.1, 2.2, 3 ]
# layers: [ 1, 2, 1 ]
# include: [ 0, 1, 0 ]
t/Grid/overlay.t view on Meta::CPAN
);
};
subtest 'snap to underlay' => sub {
my $grid1
= Grid->new( edges => [ 0, 1, 2, 3 ], include => [ 0, 0, 0 ] );
my $grid2 = Grid->new( edges => [ 1.1, 1.9 ], include => [1] );
my $gridN = overlay_n( $grid1, $grid2, { snap_dist => 0.1, snap_to => 'underlay' } );
# grid1 < grid 2
# before snap
# edges : [ 0, 1, 1.1, 1.9, 2, 3 ]
# layers: [ 1, 1, 2, 1, 1 ]
# include: [ 0, 0, 1, 0, 0 ]
# after snap (1)
# edges : [ 0, 1, 1.9, 2, 3 ]
# layers: [ 1, 2, 1, 1 ]
# include: [ 0, 1, 0, 0 ]
t/Grid/overlay.t view on Meta::CPAN
};
};
subtest 'isolated' => sub {
my $grid1 = Grid->new( edges => [ 0, 1, 2, 3 ], include => [ 1, 1, 1 ] );
my $grid2 = Grid->new( edges => [ 4, 5 ], include => [1] );
my $gridN = overlay_n( $grid1, $grid2 );
is(
$gridN,
object {
call bin_edges => array { item number $_ for 0, 1, 2, 3, 4, 5 };
call include => array { item number $_ for 1, 1, 1, 0, 1 };
},
);
};
t/Grid/regressions.t view on Meta::CPAN
#! perl
use Test2::V0;
use CXC::Number::Grid qw( overlay_n );
use constant Grid => 'CXC::Number::Grid';
sub Failure { join( '::', 'CXC::Number::Grid::Failure', @_ ) }
subtest 'overlap' => sub {
subtest 'use numerical comparison' => sub {
# this will blow up if Tree::Range isn't set up for numerical comparisons
my $gti = Grid->new( {
edges => [ -1, 2, 4, 5 ],
include => [ 1, 0, 1 ],
} );
my $bins
= Grid->new( { edges => [ map { -1.5 + $_ * 0.5 } 0 .. 10 ] } );
ok( lives { $gti->overlay( $bins ) } )
or note $@;
};
};
done_testing;
xt/author/no-tabs.t view on Meta::CPAN
't/00-compile.t',
't/00-report-prereqs.dd',
't/00-report-prereqs.t',
't/Grid/Tree/basic.t',
't/Grid/Tree/snap.t',
't/Grid/combine_bins.t',
't/Grid/edges.t',
't/Grid/interface.t',
't/Grid/join.t',
't/Grid/ops.t',
't/Grid/overlay.t',
't/Grid/regressions.t',
't/Grid/select.t',
't/Grid/split.t',
't/Sequence/Fixed/sequence.t',
't/Sequence/Linear/interface.t',
't/Sequence/Linear/sequence.t',
't/Sequence/Ratio/interface.t',
't/Sequence/Ratio/sequence.t',
't/Sequence/Types.t',
't/Sequence/interface.t',