All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.WeronikaJargielo.protein_interaction_finder.HydrogenBondFinder Maven / Gradle / Ivy

The newest version!
package io.github.WeronikaJargielo.protein_interaction_finder;

import com.google.common.collect.Lists;
import org.biojava.nbio.structure.Atom;
import org.biojava.nbio.structure.Calc;

import java.util.*;
import java.util.function.Function;

final class HydrogenBondFinder {

    // Inner class representing donors and acceptors which create hydrogen bond.
    final private class BondParticipant {
        public final String[] atoms;
        public final AminoAcidAbbreviations aminoAcid;
        public final Function> bondParticipantFilter;
        public final  Boolean specialTreatment;

        public BondParticipant(String[] atoms, AminoAcidAbbreviations aminoAcid) {
            this.atoms = atoms;
            this.aminoAcid = aminoAcid;
            this.bondParticipantFilter = null;
            this.specialTreatment = false;
        }

        public BondParticipant(String[] atoms, AminoAcidAbbreviations aminoAcid, Function> bondParticipantFilter) {
            this.atoms = atoms;
            this.aminoAcid = aminoAcid;
            this.bondParticipantFilter = bondParticipantFilter;
            this.specialTreatment = true;
        }

    }

    private final int bondParticipantSize = 2;
    private PdbStructureParser pdbStructureParser;

    public HydrogenBondFinder(PdbStructureParser pdbStructureParser) {
        this.pdbStructureParser = pdbStructureParser;
    }

//  Filter is essential due to the fact that the histidine is particularly difficult to examine. There are two scenarios:
//  1. On uncharged HIS the H atom may be located on either HIS ND1 or HIS NE2, so in this situation one nitrogen may only donate a proton,
//     in a hydrogen bond while the other nitrogen can only accept one.
//  2. Additionally, HIS could be charged with a hydrogen on each nitrogen, allowing both only to donate.
//  The important message here is that a single histidine side-chain nitrogen cannot simultaneously accept and donate a hydrogen bond.
    private final Function> acceptorHistidineFilter = (bondParticipant -> {
        List histidineAcceptorsAtoms = new ArrayList<>();
        final String[] desiredAtomsPdbNames = bondParticipant.atoms;
        final List desiredAbbreviations = Arrays.asList(bondParticipant.aminoAcid);

        final List foundAtoms = pdbStructureParser.getAtoms(desiredAtomsPdbNames, desiredAbbreviations);
        if (foundAtoms.isEmpty()) { return histidineAcceptorsAtoms; }

        final List> dublets = Lists.partition(foundAtoms, desiredAtomsPdbNames.length);

        final int indN = (foundAtoms.get(0).getName().charAt(0) == ('N')) ? 0 : 1;
        String HPdbName = desiredAtomsPdbNames[indN];
        HPdbName.replace("N", "H");

        final List foundHs = pdbStructureParser.getAtoms(new String[] {HPdbName}, desiredAbbreviations);

        dublets.forEach(dublet -> {
            final Integer dubletSeqNum = dublet.get(indN).getGroup().getResidueNumber().getSeqNum();
            final String dubletChain = dublet.get(indN).getGroup().getChain().getName();

            final Optional matchingH = foundHs.stream()
                                                    .filter(H -> dubletSeqNum.equals(H.getGroup().getResidueNumber().getSeqNum())
                                                                 && dubletChain.equals(H.getGroup().getChain().getName()))
                                                    .findAny();

            if (matchingH.isEmpty()) {
                histidineAcceptorsAtoms.addAll(foundAtoms);
            }
        });

        return histidineAcceptorsAtoms;
    });


    final private List donorsDesiredAtomsMainChain = Arrays.asList(  new BondParticipant(new String[]{"N", "H"}, null),
//                                                                                    For amino acids at the N-terminus of protein's chain.
                                                                                      new BondParticipant(new String[]{"N", "H1"}, null),
                                                                                      new BondParticipant(new String[]{"N", "H2"}, null),
                                                                                      new BondParticipant(new String[]{"N", "H3"}, null));

    final private List acceptorsDesiredAtomsMainChain = Arrays.asList(new BondParticipant(new String[]{"C", "O"}, null),
//                                                                                     For amino acids at the C-terminus of protein's chain.
                                                                                       new BondParticipant(new String[]{"C", "OXT"}, null));


//                                                                                  new BondParticipant(new String[]{donor, hydrogen}, abbreviation of amino acid)
    final private List donorsDesiredAtomsSideChain = Arrays.asList(new BondParticipant(new String[]{"NE", "HE"}, AminoAcidAbbreviations.ARG),
                                                                                    new BondParticipant(new String[]{"NH1", "HH11"}, AminoAcidAbbreviations.ARG),
                                                                                    new BondParticipant(new String[]{"NH1", "HH12"}, AminoAcidAbbreviations.ARG),
                                                                                    new BondParticipant(new String[]{"NH2", "HH21"}, AminoAcidAbbreviations.ARG),
                                                                                    new BondParticipant(new String[]{"NH2", "HH22"}, AminoAcidAbbreviations.ARG),

                                                                                    new BondParticipant(new String[]{"ND2", "HD21"}, AminoAcidAbbreviations.ASN),
                                                                                    new BondParticipant(new String[]{"ND2", "HD22"}, AminoAcidAbbreviations.ASN),

                                                                                    new BondParticipant(new String[]{"SG", "HG"}, AminoAcidAbbreviations.CYS),

                                                                                    new BondParticipant(new String[]{"NE2", "HE21"}, AminoAcidAbbreviations.GLN),
                                                                                    new BondParticipant(new String[]{"NE2", "HE22"}, AminoAcidAbbreviations.GLN),

                                                                                    new BondParticipant(new String[]{"NE2", "HE2"}, AminoAcidAbbreviations.HIS),
                                                                                    new BondParticipant(new String[]{"ND1", "HD1"}, AminoAcidAbbreviations.HIS),

                                                                                    new BondParticipant(new String[]{"NZ", "HZ1"}, AminoAcidAbbreviations.LYS),
                                                                                    new BondParticipant(new String[]{"NZ", "HZ2"}, AminoAcidAbbreviations.LYS),
                                                                                    new BondParticipant(new String[]{"NZ", "HZ3"}, AminoAcidAbbreviations.LYS),

                                                                                    new BondParticipant(new String[]{"OG", "HG"}, AminoAcidAbbreviations.SER),

                                                                                    new BondParticipant(new String[]{"OG1", "HG1"}, AminoAcidAbbreviations.THR),

                                                                                    new BondParticipant(new String[]{"NE1", "HE1"}, AminoAcidAbbreviations.TRP),

                                                                                    new BondParticipant(new String[]{"OH", "HH"}, AminoAcidAbbreviations.TYR));



//                                                                                     new BondParticipant(new String[]{acceptor, acceptor antecedent}, abbreviation of amino acid)
    final private List acceptorsDesiredAtomsSideChain = Arrays.asList(new BondParticipant(new String[]{"OD1", "CG"}, AminoAcidAbbreviations.ASN),

                                                                                       new BondParticipant(new String[]{"OD1", "CG"}, AminoAcidAbbreviations.ASP),
                                                                                       new BondParticipant(new String[]{"OD2", "CG"}, AminoAcidAbbreviations.ASP),

                                                                                       new BondParticipant(new String[]{"SG", "CB"}, AminoAcidAbbreviations.CYS),

                                                                                       new BondParticipant(new String[]{"OE1", "CD"}, AminoAcidAbbreviations.GLN),

                                                                                       new BondParticipant(new String[]{"OE1", "CD"}, AminoAcidAbbreviations.GLU),
                                                                                       new BondParticipant(new String[]{"OE2", "CD"}, AminoAcidAbbreviations.GLU),

                                                                                       new BondParticipant(new String[]{"ND1", "CG"}, AminoAcidAbbreviations.HIS, acceptorHistidineFilter),
                                                                                       new BondParticipant(new String[]{"NE2", "CD2"}, AminoAcidAbbreviations.HIS, acceptorHistidineFilter),

                                                                                       new BondParticipant(new String[]{"SD", "CG"}, AminoAcidAbbreviations.MET),

                                                                                       new BondParticipant(new String[]{"OG", "CB"}, AminoAcidAbbreviations.SER),

                                                                                       new BondParticipant(new String[]{"OG1", "CB"}, AminoAcidAbbreviations.THR),

                                                                                       new BondParticipant(new String[]{"OH", "CZ"}, AminoAcidAbbreviations.TYR));



    public List findMainMainHydrogenBonds(HydrogenBondCriteria criteria) {
        final List> donors = this.getDonorsMainChain();
        final List> acceptors = this.getAcceptorsMainChain();

        return this.findHydrogenBonds(donors, acceptors, criteria);
    }

    public List findMainSideHydrogenBonds(HydrogenBondCriteria criteria) {
        final List> donorsMainChain = this.getDonorsMainChain();
        final List> donorsSideChain = this.getDonorsSideChain();

        final List> acceptorsMainChain = this.getAcceptorsMainChain();
        final List> acceptorsSideChain = this.getAcceptorsSideChain();

        List foundMainSideHydrogenBonds = this.findHydrogenBonds(donorsMainChain, acceptorsSideChain, criteria);
        foundMainSideHydrogenBonds.addAll(this.findHydrogenBonds(donorsSideChain, acceptorsMainChain, criteria));

        return foundMainSideHydrogenBonds;
    }

    public List findSideSideHydrogenBonds(HydrogenBondCriteria criteria) {
        final List> donors = this.getDonorsSideChain();
        final List> acceptors = this.getAcceptorsSideChain();

        return this.findHydrogenBonds(donors, acceptors, criteria);
    }

    private List> getDonorsMainChain() {
        List donorsMainChain = new ArrayList<>();
        donorsDesiredAtomsMainChain.forEach(bondParticipant -> donorsMainChain.addAll(pdbStructureParser.getAtoms(bondParticipant.atoms)));

        return Lists.partition(donorsMainChain, bondParticipantSize);
    }

    private List> getAcceptorsMainChain() {
        List acceptorsMainChain = new ArrayList<>();
        acceptorsDesiredAtomsMainChain.forEach(bondParticipant -> acceptorsMainChain.addAll(pdbStructureParser.getAtoms(bondParticipant.atoms)));

        return Lists.partition(acceptorsMainChain, bondParticipantSize);
    }

    private List> getDonorsSideChain() {
        List donorsSideChain = new ArrayList<>();
        donorsDesiredAtomsSideChain.forEach(bondParticipant -> donorsSideChain.addAll(pdbStructureParser.getAtoms(bondParticipant.atoms, Arrays.asList(bondParticipant.aminoAcid))));

        return Lists.partition(donorsSideChain, bondParticipantSize);
    }

    private List> getAcceptorsSideChain() {
        List acceptorsSideChain = new ArrayList<>();
        acceptorsDesiredAtomsSideChain.forEach(bondParticipant -> {
            if (bondParticipant.specialTreatment) {
                acceptorsSideChain.addAll(bondParticipant.bondParticipantFilter.apply(bondParticipant));
            } else {
                acceptorsSideChain.addAll(pdbStructureParser.getAtoms(bondParticipant.atoms, Arrays.asList(bondParticipant.aminoAcid)));
            }
        });

        return Lists.partition(acceptorsSideChain, bondParticipantSize);
    }

    private HydrogenBond obtainHydrogenBond(List donor, List acceptor, HydrogenBondCriteria criteria) {
        final int indD = (donor.get(0).getName().charAt(0) == ('H')) ? 1 : 0;
        final int indH = (donor.get(0).getName().charAt(0) == ('H')) ? 0 : 1;

        final int indA = (acceptor.get(0).getName().charAt(0) == ('C')) ? 1 : 0;
        final int indAa = (acceptor.get(0).getName().charAt(0) == ('C')) ? 0 : 1;

//      Checking if donor atom is not equal to acceptor atom, to eliminate cases when one atom can be donor and acceptor at the same time.
        if ( (donor.get(indD).getPDBserial() == acceptor.get(indA).getPDBserial())
              && (donor.get(indD).getGroup().equals(acceptor.get(indA).getGroup())) ) {
            return null;
        }

        final double distanceDA = Calc.getDistance(donor.get(indD), acceptor.get(indA));
        if ( ! (distanceDA > criteria.getMinDistanceDA() && distanceDA < criteria.getMaxDistanceDA())) {
            return null;
        }

        final double distanceHA = Calc.getDistance(donor.get(indH), acceptor.get(indA));
        if ( ! (distanceHA > criteria.getMinDistanceHA() && distanceHA < criteria.getMaxDistanceHA()) ) {
            return null;
        }

        final double angleDHA = MathHelper.angle(donor.get(indD), donor.get(indH), acceptor.get(indA));
        if ( ! (angleDHA > criteria.getMinAngleDHA() && angleDHA < criteria.getMaxAngleDHA()) ) {
            return null;
        }

        final double angleHAAa = MathHelper.angle(donor.get(indH), acceptor.get(indA), acceptor.get(indAa));
        if ( ! (angleHAAa > criteria.getMinAngleHAAa() && angleHAAa < criteria.getMaxAngleHAAa()) ) {
            return null;
        }

        final double angleDAAa = MathHelper.angle(donor.get(indD), acceptor.get(indA), acceptor.get(indAa));
        if ( ! (angleDAAa > criteria.getMinAngleDAAa() && angleDAAa < criteria.getMaxAngleDAAa()) ) {
            return null;
        }

        return new HydrogenBond(new AminoAcid(donor.get(indD).getGroup()), new AminoAcid(acceptor.get(indA).getGroup()),
                                donor.get(indD), donor.get(indH), acceptor.get(indA), acceptor.get(indAa),
                                distanceHA, distanceDA, angleDHA, angleHAAa, angleDAAa);
    }

    private List findHydrogenBonds(List> donors, List> acceptors, HydrogenBondCriteria criteria) {
        List foundHydrogenBonds = new ArrayList<>();

        donors.forEach(donor -> {
            acceptors.forEach(acceptor -> {
                final HydrogenBond hydrogenBond = this.obtainHydrogenBond(donor, acceptor, criteria);

                if (hydrogenBond != null) {
                    foundHydrogenBonds.add(hydrogenBond);
                }
            });
        });
        return foundHydrogenBonds;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy