File Coverage

blib/lib/HackaMol/Roles/ReadZmatRole.pm
Criterion Covered Total %
statement 18 93 19.3
branch 0 8 0.0
condition n/a
subroutine 6 8 75.0
pod 1 1 100.0
total 25 110 22.7


line stmt bran cond sub pod time code
1             package HackaMol::Roles::ReadZmatRole;
2             $HackaMol::Roles::ReadZmatRole::VERSION = '0.051';
3             # ABSTRACT: Read files with molecular information
4 11     11   6039 use Moose::Role;
  11         38  
  11         77  
5 11     11   57602 use HackaMol::PeriodicTable qw(%KNOWN_NAMES _trim);
  11         29  
  11         1315  
6 11     11   93 use Math::Vector::Real;
  11         30  
  11         537  
7 11     11   99 use Carp;
  11         27  
  11         721  
8 11     11   84 use List::MoreUtils qw(singleton);
  11         45  
  11         92  
9              
10             with qw(
11             HackaMol::Roles::NERFRole
12             );
13              
14             sub read_zmat_atoms {
15              
16             #xyz file and generate list of Atom object
17 0     0 1   my $self = shift;
18 0           my $fh = shift;
19             # my $file = shift;
20             # my $fh = FileHandle->new("<$file") or croak "unable to open $file";
21              
22 0           my @atoms;
23 0           my ( $n, $t ) = ( 0, 0 );
24            
25 0           my @zmat = <$fh>;
26 0           @zmat = _substitute_variables(@zmat);
27              
28             # we have 5 types of extensions
29             # A. SYM 0 x y z
30             # B. SYM
31             # C. SYM i R
32             # D. SYM i R j Ang
33             # E. SYM i R j Ang k Tors
34             # we need to filter the indices (can't lose the location)
35              
36             #type A
37 0           my @iA = grep { $zmat[$_] =~ m/^\s*\w+\s+0(\s+-*\d*\.*\d*){3}/ } 0 .. $#zmat;
  0            
38 0           my @inA = singleton( 0 .. $#zmat, @iA );
39              
40             #type B
41 0           my @iB = grep { $zmat[$_] =~ m/^\s*\w+\s*$/ } @inA;
  0            
42              
43             #type C
44 0           my @iC = grep { $zmat[$_] =~ m/^\s*\w+(\s+\d+\s+\d*\.*\d*)\s*$/ } @inA;
  0            
45              
46             #type D
47 0           my @iD = grep { $zmat[$_] =~ m/^\s*\w+(\s+\d+\s+\d*\.*\d*){2}\s*$/ } @inA;
  0            
48              
49             #type E
50             my @iE = grep {
51 0           $zmat[$_] =~ m/^\s*\w+(\s+\d+\s+\d*\.*\d*){2}\s+\d+\s+-*\d*\.*\d*\s*$/
  0            
52             } @inA;
53              
54 0           my $diff = @zmat - (@iA+@iB+@iC+@iD+@iE); #scalar context
55            
56 0 0         if ($diff){
57 0           print "Lines in Z-matrix: ", scalar (@zmat), " Number of lines to be processed: ", scalar (@zmat) - $diff, "\n";
58 0           print "Lines missed: ", $diff, "\n";
59 0           print "\n\nHere is your Z-matrix:\n";
60 0           print $_ foreach @zmat;
61 0           print "Indices of lines to be processed: ", join("\n", @iA, @iB, @iC, @iD, @iE);
62 0           croak "\nThere is something funky with your zmatrix";
63             }
64              
65 0           foreach my $ia (@iA) {
66 0           my ( $sym, $iat1, @xyz ) = split( ' ', $zmat[$ia] );
67 0           $atoms[$ia] = HackaMol::Atom->new(
68             name => $sym.$ia,
69             symbol => $sym,
70             coords => [ V(@xyz) ]
71             );
72             }
73            
74 0           foreach my $ib (@iB) {
75 0           my $sym = $zmat[$ib];
76 0           my $a = $self->init;
77 0           $sym =~ s/^\s+|\s+$//;
78 0           $atoms[$ib] = HackaMol::Atom->new(
79             name => $sym.$ib,
80             symbol => $sym,
81             coords => [$a]
82             );
83             }
84              
85             # print Dump 'B', \@atoms;
86              
87 0           foreach my $ic (@iC) {
88 0           my ( $sym, $iat1, $R ) = split( ' ', $zmat[$ic] );
89 0           my $a = $atoms[ $iat1 - 1 ]->xyz;
90 0           my $b = $self->extend_a( $a, $R );
91 0           $atoms[$ic] = HackaMol::Atom->new(
92             name => $sym.$ic,
93             symbol => $sym,
94             coords => [$b]
95             );
96             }
97              
98             # print Dump 'C', \@atoms;
99              
100 0           foreach my $id (@iD) {
101 0           my ( $sym, $iat1, $R, $iat2, $ang ) = split( ' ', $zmat[$id] );
102 0           my $a = $atoms[ $iat1 - 1 ]->xyz;
103 0           my $b = $atoms[ $iat2 - 1 ]->xyz;
104 0           my $c = $self->extend_ab( $b, $a, $R, $ang );
105 0           $atoms[$id] = HackaMol::Atom->new(
106             name => $sym.$id,
107             symbol => _trim($sym),
108             coords => [$c]
109             );
110             }
111              
112             # print Dump 'D', \@atoms;
113              
114 0           foreach my $ie (@iE) {
115 0           my ( $sym, $iat1, $R, $iat2, $ang, $iat3, $tor ) =
116             split( ' ', $zmat[$ie] );
117 0           my $a = $atoms[ $iat1 - 1 ]->xyz;
118 0           my $b = $atoms[ $iat2 - 1 ]->xyz;
119 0           my $c = $atoms[ $iat3 - 1 ]->xyz;
120 0           my $d = $self->extend_abc( $c, $b, $a, $R, $ang, $tor );
121 0           $atoms[$ie] = HackaMol::Atom->new(
122             name => $sym.$ie,
123             symbol => _trim($sym),
124             coords => [$d]
125             );
126             }
127 0           $atoms[$_]->iatom($_) foreach ( 0 .. $#atoms );
128 0           return (\@atoms);
129              
130             }
131              
132             sub _substitute_variables{
133 0     0     my @Zmat = @_;
134              
135 0           chomp @Zmat;
136              
137 0           my %bin;
138             my %var = map {
139 0           my ($key,$val) = map{ s/^\s+|\s+$//; $_ } split(/\s*=\s*/,$_);
  0            
  0            
140 0           $bin{$key}++;
141 0           $key => $val,
142 0           } grep {/=/} @Zmat;
  0            
143              
144             # check for double entry of variables
145 0           my @too_many = grep {$bin{$_}>1} keys(%bin);
  0            
146 0 0         if (@too_many) {
147 0           carp "ReadZMatRole> you have more than one entry for these variables: ". join("\n", @too_many);
148             }
149              
150 0           @Zmat = grep {!/(^\#)|=|(^\s*$)/} @Zmat;
  0            
151              
152 0           foreach my $line (@Zmat){
153 0           my @vals = split (/ /, $line);
154 0 0         next unless @vals > 2;
155 0 0         $line = join(' ', $vals[0], map{ exists($var{$_}) ? $var{$_} : $_ } @vals[1 .. $#vals] );
  0            
156             }
157 0           return (@Zmat);
158             }
159              
160 11     11   22810 no Moose::Role;
  11         53  
  11         61  
161              
162             1;
163              
164             __END__
165              
166             =pod
167              
168             =head1 NAME
169              
170             HackaMol::Roles::ReadZmatRole - Read files with molecular information
171              
172             =head1 VERSION
173              
174             version 0.051
175              
176             =head1 SYNOPSIS
177              
178             my @atoms = HackaMol->new
179             ->read_zmat_atoms("some.zmat");
180              
181             =head1 DESCRIPTION
182              
183             The HackaMol::Roles::ReadZmatRole provides read_zmat_atoms for the flexible reading of Z-matrix files.
184             It supports inline cartesian coordinates and variables as in the following example:
185              
186             N 0 -12.781 3.620 15.274
187              
188             C 0 -11.976 4.652 15.944
189              
190             C 0 -12.722 6.019 15.985
191              
192             O 0 -13.133 6.378 14.897
193              
194             C 2 CBCA 3 CBCAC 4 CBCACO
195              
196             C 5 CBCA 2 CBCAC 3 CG1CBCAC
197              
198             C 5 CBCA 2 CBCAC 3 CG2CBCAC
199              
200             CBCA = 1.54
201              
202             CBCAC = 113.4
203              
204             CBCACO = 71.85
205              
206             CG1CBCAC = 54.
207              
208             CG2CBCAC = 180.
209              
210             =head1 METHODS
211              
212             =head2 read_zmat_atoms
213              
214             One argument: the filename
215             Returns a list of HackaMol::Atom objects.
216              
217             =head1 SEE ALSO
218              
219             =over 4
220              
221             =item *
222              
223             L<HackaMol>
224              
225             =item *
226              
227             L<HackaMol::Atom>
228              
229             =item *
230              
231             L<HackaMol::Roles::MolReadRole>
232              
233             =item *
234              
235             L<Protein Data Bank|http://pdb.org>
236              
237             =back
238              
239             =head1 CONSUMES
240              
241             =over 4
242              
243             =item * L<HackaMol::Roles::NERFRole>
244              
245             =back
246              
247             =head1 AUTHOR
248              
249             Demian Riccardi <demianriccardi@gmail.com>
250              
251             =head1 COPYRIGHT AND LICENSE
252              
253             This software is copyright (c) 2017 by Demian Riccardi.
254              
255             This is free software; you can redistribute it and/or modify it under
256             the same terms as the Perl 5 programming language system itself.
257              
258             =cut