Chemistry-Reaction

 view release on metacpan or  search on metacpan

lib/Chemistry/Reaction.pm  view on Meta::CPAN

            0/3 (creation of a triple bond)

An explicit chemical reaction $react can be forward or reverse applied
once to a molecule $mol at the first subgraph of $mol found which is
isomorphic to the substrate or product of $react:

    my $subst = $react->substrate;
    if ($subst->match($mol)) {
      $react->forward($mol, $subst->atom_map);
    }

Also, an explicit chemical reaction $react can be forward or reverse
applied once to a molecule $mol at each subgraph of $mol which is
isomorphic to the substrate or product of $react:

    my $subst = $react->substrate;
    my @products;
    while ($subst->match($mol)) {
      my $new_mol = $mol->clone; # start from a fresh molecule
      my @map = $subst->atom_map;
      # translate atom map to the clone
      my @m = map { $new_mol->by_id($_->id) } @map;
      $react->forward($new_mol, @m);
      push @products, $new_mol;
    }

Furthermore, an explicit chemical reaction $react can be forward or
reverse applied as long as possible to a molecule $mol at the first
subgraph of $mol found which is isomorphic to the substrate or product
of $react:

    my $subst = $react->substrate;
    while ($subst->match($mol)) {
      $react->forward($mol, $subst->atom_map);
    }

=cut

use 5.006;
use strict;
use warnings;
use base qw(Chemistry::Pattern);

=head1 METHODS

=over 4

=item Chemistry::Reaction->new($subst, $prod, \%map)

Create a new Reaction object that describes the transformation of the
$subst substrate into the $prod product, according to the %map mapping
of substrate atoms to product atoms.

=cut

sub new {
  my ($class, $substrate, $product, $mapping, %args) = @_;

  die sprintf(
    "$class substrate and product must coincide on atoms (%s ne %s)\n", 
        $substrate->formula, $product->formula) 
    if $substrate->formula ne $product->formula;

  my $order1 = 0;
  foreach my $bond ($substrate->bonds) {
    $order1 += $bond->order;
  }
  my $order2 = 0;
  foreach my $bond ($product->bonds) {
    $order2 += $bond->order;
  }
  die "$class substrate and product must coincide on total bond order\n"
    if $order1 != $order2;

  foreach my $atom ($substrate->atoms) {
    die sprintf(
        "$class substrate and product must coincide on atom symbols "
        ."(%s ne %s)\n", $atom->symbol, $mapping->{$atom}->symbol)
      if $atom->symbol ne $mapping->{$atom}->symbol;
  }

  foreach my $atom ($product->atoms) {
    $atom->attr("reaction/mapped", 1);
  }
  foreach my $atom ($substrate->atoms) {
    $mapping->{$atom}->attr("reaction/mapped", 0);
  }
  foreach my $atom ($product->atoms) {
    die "$class atom mapping must be bijective\n"
      if $atom->attr("reaction/mapped");
  }

  # the substrate of the reaction is cloned in order to isolate all
  # changes to bond orders from the given $substrate
  
  my $self = $substrate->clone;
  bless $self, ref $class || $class;

  $self->$_($args{$_}) for (keys %args);
  # the $mapping array gives the product atom which each substrate
  # atom is mapped to, and the %unmapping hash gives back the
  # substrate atom which each product atom is mapped to
  
  my %unmapping;
  foreach my $a1 (keys %$mapping) {
    my $a2 = ${$mapping}{$a1};
    $unmapping{$a2} = $a1;
  }

  # the %bonds hash gives an array of substrate and product bond
  # orders for each pair of atoms which are bonded in substrate or in
  # the product of the reaction

  # first of all, set $bonds{$a1}{$a2} to an array containing only the
  # substrate bond order, for each pair of atoms $a1 and $a2 which are
  # bonded in the substrate

  my %bonds;
  foreach my $bond ($self->bonds) {
    my @atoms = $bond->atoms;
    @atoms[0,1] = @atoms[1,0] unless $atoms[0] lt $atoms[1];
    $bonds{$atoms[0]}{$atoms[1]} = [$bond->order];



( run in 1.528 second using v1.01-cache-2.11-cpan-d7a12ab2c7f )