1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
|
#!/usr/bin/perl
use strict;
use warnings;
use Chemistry::OpenSMILES;
use Chemistry::OpenSMILES::Parser;
use Chemistry::OpenSMILES::Stereo qw(
chirality_to_pseudograph
cis_trans_to_pseudoedges
);
use Chemistry::OpenSMILES::Writer qw( write_SMILES );
use File::Basename qw( basename );
use Getopt::Long::Descriptive;
use Graph::Nauty qw( orbits );
use List::Util qw( any );
$Graph::Nauty::worksize = 25600;
my $basename = basename $0;
my( $opt, $usage ) = describe_options( <<"END" . 'OPTIONS',
USAGE
$basename [<args>] [<files>]
DESCRIPTION
$basename reads in files with SMILES descriptors and warns about
unusual features in it, for example, both superfluous and unmarked
chiral centers, strange representations of cis/trans settings etc.
END
[ 'help', 'print usage message and exit', { shortcircuit => 1 } ],
);
if( $opt->help ) {
print $usage->text;
exit;
}
my $errors = 0;
while (<>) {
chomp;
my $additional_position = '';
if( s/\t([^\t]*)$// ) {
$additional_position = ' ' . $1;
}
local $SIG{__WARN__} = sub {
print STDERR "$basename: $ARGV($.)$additional_position: $_[0]";
};
my $parser = Chemistry::OpenSMILES::Parser->new;
my @moieties;
eval {
@moieties = $parser->parse( $_ );
};
if( $@ ) {
$@ =~ s/^[^:]+:\s*// if !index( $@, $0 );
print STDERR "$basename: $ARGV($.)$additional_position: $@";
$errors++;
}
my @smiles_parts;
for my $moiety (@moieties) {
# copy() makes a shallow copy without edge attributes, thus they
# have to be added later:
my $copy = $moiety->copy;
for my $bond ($moiety->edges) {
next unless $moiety->has_edge_attribute( @$bond, 'bond' );
$copy->set_edge_attribute( @$bond,
'bond',
$moiety->get_edge_attribute( @$bond, 'bond' ) );
}
cis_trans_to_pseudoedges( $copy );
chirality_to_pseudograph( $copy );
my @orbits = orbits( $copy,
sub { ref $_[0] && exists $_[0]->{symbol} ? &represent_vertex : '' } );
my $color_sub = sub {
for my $i (0..$#orbits) {
return $i if any { $_ == $_[0] } @{$orbits[$i]};
}
};
Chemistry::OpenSMILES::_validate( $moiety, $color_sub );
}
}
exit( $errors > 0 );
sub represent_vertex
{
my( $vertex ) = @_;
return '' unless %$vertex;
my %atom = %$vertex;
delete $atom{chirality};
return write_SMILES( \%atom );
}
|