File Coverage

blib/lib/HackaMol/Angle.pm
Criterion Covered Total %
statement 48 48 100.0
branch 4 4 100.0
condition 6 6 100.0
subroutine 13 13 100.0
pod 5 5 100.0
total 76 76 100.0


line stmt bran cond sub pod time code
1             $HackaMol::Angle::VERSION = '0.053';
2             #ABSTRACT: Angle class for HackaMol
3             use 5.008;
4 12     12   863 use Moose;
  12         43  
5 12     12   59 use namespace::autoclean;
  12         29  
  12         95  
6 12     12   68945 use Carp;
  12         27  
  12         124  
7 12     12   1036 use Math::Vector::Real;
  12         29  
  12         778  
8 12     12   68 use MooseX::StrictConstructor;
  12         21  
  12         627  
9 12     12   75  
  12         22  
  12         94  
10             #use MooseX::Storage;
11             #with Storage( 'io' => 'StorableFile' ),
12             with 'HackaMol::Roles::NameRole', 'HackaMol::Roles::AtomGroupRole';
13              
14             has $_ => (
15             is => 'rw',
16             isa => 'Num',
17             default => 0,
18             lazy => 1,
19             clearer => "clear_$_",
20             predicate => "has_$_",
21             ) foreach qw(ang_fc ang_eq);
22              
23             my $self = shift;
24             my @atoms = $self->all_atoms;
25 34     34 1 4083 my $ang = $self->ang_deg;
26 34         1146 return V( 0, 0, 0 ) if ( $ang == 0 or $ang == 180 );
27 34         86 my $vec1 = $atoms[1]->inter_dcoords( $atoms[0] );
28 34 100 100     448 my $vec2 = $atoms[1]->inter_dcoords( $atoms[2] );
29 14         43 my $v1xv2 = $vec1 x $vec2;
30 14         32 return ( $v1xv2->versor );
31 14         43 }
32 14         97  
33              
34             # vector that bisects the angle between two vectors of the angle
35             my $self = shift;
36             my @atoms = $self->all_atoms;
37             my $ang = $self->ang_deg;
38 5     5 1 14 return V( 0, 0, 0 ) if ( $ang == 0 or $ang == 180 );
39 5         152 my $vec1 = $atoms[1]->inter_dcoords( $atoms[0] );
40 5         12 my $vec2 = $atoms[1]->inter_dcoords( $atoms[2] );
41 5 100 100     71 my $bvec = ( $vec1->versor + $vec2->versor )->versor;
42 2         6 return $bvec;
43 2         6 }
44 2         11  
45 2         33 my $self = shift;
46             my @atoms = $self->all_atoms;
47             return ( $atoms[1]->angle_deg( $atoms[0], $atoms[2] ) );
48             }
49 199     199 1 6072  
50 199         5234 my $self = shift;
51 199         456 my @atoms = $self->all_atoms;
52             return ( $atoms[1]->angle_rad( $atoms[0], $atoms[2] ) );
53             }
54              
55 10     10 1 4511 has 'angle_efunc' => (
56 10         349 is => 'rw',
57 10         38 isa => 'CodeRef',
58             builder => "_build_angle_efunc",
59             lazy => 1,
60             );
61              
62              
63             #my $self = shift; #self is passed by moose, but we don't use it here
64             my $subref = sub {
65             my $angle = shift;
66             my $val = ( $angle->ang_deg - $angle->ang_eq )**2;
67             return ( $angle->ang_fc * $val );
68             };
69             return ($subref);
70             }
71 2     2   3  
72 2         5 my $self = shift;
73 2         42 my $energy = &{ $self->angle_efunc }( $self, @_ );
74 1     1   6 return ($energy);
75 1         22 }
76              
77             __PACKAGE__->meta->make_immutable;
78              
79 3     3 1 7 1;
80 3         6  
  3         84  
81 3         21  
82             =pod
83              
84             =head1 NAME
85              
86             HackaMol::Angle - Angle class for HackaMol
87              
88             =head1 VERSION
89              
90             version 0.053
91              
92             =head1 SYNOPSIS
93              
94             use HackaMol::Atom;
95             use HackaMol::Angle;
96              
97             my $atom1 = HackaMol::Atom->new(
98             name => 'O1',
99             coords => [ V( 2.05274, 0.01959, -0.07701 ) ],
100             Z => 8,
101             );
102              
103             my $atom2 = HackaMol::Atom->new(
104             name => 'H1',
105             coords => [ V( 1.08388, 0.02164, -0.12303 ) ],
106             Z => 1,
107             );
108            
109             my $atom3 = HackaMol::Atom->new(
110             name => 'H2',
111             coords => [ V( 2.33092, 0.06098, -1.00332 ) ],
112             Z => 1,
113             );
114            
115             my $angle1 = HackaMol::Angle->new(name=>'OH2', atoms=>[$atom1,$atom2,$atom3]);
116             my $angle2 = HackaMol::Angle->new(name=>'OH2', atoms=>[$atom2,$atom1,$atom3]);
117            
118             foreach my $angle ($angle1, $angle2){
119             my $pangle = sprintf(
120             "Angle: %s, angle: %.2f, vector normal to angle plane: %.5 %.5 %.5 \n",
121             $angle->name,
122             $angle->ang,
123             @{$angle->ang_normvec},
124             );
125             print $pangle;
126             }
127            
128             my @COM_ats = map {HackaMol::Atom->new(
129             name => "X".$_->name."X",
130             coords => [ $_->COM ],
131             Z => 1)
132             }($angle1, $angle2);
133            
134             my @ang_w_HH = grep { $_->get_atoms(0)->Z == 1 and
135             $_->get_atoms(1)->Z == 1} ($angle1, $angle2);
136              
137             =head1 DESCRIPTION
138              
139             The HackaMol Angle class provides a set of methods and attributes for working
140             with two connections between three atoms. Like the Bond, the Angle class
141             consumes the AtomGroupRole providing methods to determine the center of mass,
142             total charge, etc (see L<HackaMol::AtomGroupRole>). An Angle containing
143             (atom1,atom2,atom3) produce angles between the atom21 atom23 interatomic vectors.
144              
145             The Angle class also provides attributes and methods to set force_constants and
146             measure energy. The angle_energy method calls on a CodeRef attribute that the
147             user may define. See descriptions below.
148              
149             =head1 METHODS
150              
151             =head2 ang_normvec
152              
153             no arguments. returns Math::Vector::Real (MVR) object from the normalized cross
154             product of the atom21 and atom23 interatomic vectors.
155              
156             =head2 bisector
157              
158             no arguments. returns vector (MVR) that bisects the angle between the two
159             vectors of the angle.
160              
161             =head2 ang_deg
162              
163             no arguments. returns the angle (degrees) between the atom21 and atom23 vectors.
164              
165             =head2 ang_rad
166              
167             no arguments. returns the angle (radians) between the atom21 and atom23 vectors.
168              
169             =head2 angle_energy
170              
171             arguments, as many as you want. Calculates energy using the angle_efunc
172             described below, if the attribute, angle_fc > 0. The angle_energy method calls
173             the angle_efunc as follows:
174              
175             my $energy = &{$self->angle_efunc}($self,@_);
176              
177             which will pass $self and that in @_ array to angle_efunc, which, similar
178             to the Bond class, can be redefined.
179              
180             =head1 ATTRIBUTES
181              
182             =head2 name
183              
184             isa Str that is lazy and rw. useful for labeling, bookkeeping...
185              
186             =head2 angle_fc
187              
188             isa Num that is lazy and rw. default = 0. force constant for harmonic potentials.
189              
190             =head2 ang_eq
191              
192             isa Num that is lazy and rw. default = 0. Equilibrium angle. The ang method
193             returns angle in degrees.
194              
195             =head2 angle_efunc
196              
197             isa CodeRef that is lazy and rw. default uses builder to generate harmonic
198             potential from the angle_fc, ang_eq, and ang. See the _build_angle_efunc,
199             if interested in changing the function form.
200              
201             =head1 SEE ALSO
202              
203             =over 4
204              
205             =item *
206              
207             L<HackaMol::AtomGroupRole>
208              
209             =item *
210              
211             L<HackaMol::Bond>
212              
213             =item *
214              
215             L<HackaMol::Dihedral>
216              
217             =back
218              
219             =head1 EXTENDS
220              
221             =over 4
222              
223             =item * L<Moose::Object>
224              
225             =back
226              
227             =head1 CONSUMES
228              
229             =over 4
230              
231             =item * L<HackaMol::Roles::AtomGroupRole>
232              
233             =item * L<HackaMol::Roles::NameRole>
234              
235             =item * L<HackaMol::Roles::NameRole|HackaMol::Roles::AtomGroupRole>
236              
237             =back
238              
239             =head1 AUTHOR
240              
241             Demian Riccardi <demianriccardi@gmail.com>
242              
243             =head1 COPYRIGHT AND LICENSE
244              
245             This software is copyright (c) 2017 by Demian Riccardi.
246              
247             This is free software; you can redistribute it and/or modify it under
248             the same terms as the Perl 5 programming language system itself.
249              
250             =cut