001/*
002 *                    BioJava development code
003 *
004 * This code may be freely distributed and modified under the
005 * terms of the GNU Lesser General Public Licence.  This should
006 * be distributed with the code.  If you do not have a copy,
007 * see:
008 *
009 *      http://www.gnu.org/copyleft/lesser.html
010 *
011 * Copyright for this code is held jointly by the individual
012 * authors.  These should be listed in @author doc comments.
013 *
014 * For more information on the BioJava project and its aims,
015 * or to join the biojava-l mailing list, visit the home page
016 * at:
017 *
018 *      http://www.biojava.org/
019 *
020 */
021package org.biojava.nbio.structure.align.multiple.util;
022
023import org.biojava.nbio.structure.*;
024import org.biojava.nbio.structure.align.multiple.MultipleAlignment;
025import org.slf4j.Logger;
026import org.slf4j.LoggerFactory;
027
028import javax.vecmath.Matrix4d;
029
030import java.util.ArrayList;
031import java.util.Arrays;
032import java.util.List;
033
034/**
035 * Utility functions to generalize the visualization of MultipleAlignments in
036 * molecular viewers. The methods return different types of selectors for the
037 * aligned residues in the alignment.
038 *
039 * @author Andreas Prlic
040 * @author Aleix Lafita
041 * @author Spencer Bliven
042 * @since 4.2.0
043 *
044 */
045public class MultipleAlignmentDisplay {
046
047        private static final Logger logger = LoggerFactory
048                        .getLogger(MultipleAlignmentDisplay.class);
049
050        /**
051         * New structures are downloaded if they were not cached in the alignment
052         * and they are entirely transformed here with the superposition information
053         * in the Multiple Alignment.
054         *
055         * @param multAln
056         * @return list of transformed AtomArrays
057         * @throws StructureException
058         */
059        public static List<Atom[]> getRotatedAtoms(MultipleAlignment multAln)
060                        throws StructureException {
061
062                int size = multAln.size();
063
064                List<Atom[]> atomArrays = multAln.getAtomArrays();
065                for (int i = 0; i < size; i++) {
066                        if (atomArrays.get(i).length < 1)
067                                throw new StructureException(
068                                                "Length of atoms arrays is too short! Size: "
069                                                                + atomArrays.get(i).length);
070                }
071
072                List<Atom[]> rotatedAtoms = new ArrayList<Atom[]>();
073
074                // TODO implement independent BlockSet superposition of the structure
075                List<Matrix4d> transf = multAln.getBlockSet(0).getTransformations();
076
077                if (transf == null) {
078
079                        logger.error("Alignment Transformations are not calculated. "
080                                        + "Superimposing to first structure as reference.");
081
082                        multAln = multAln.clone();
083                        MultipleSuperimposer imposer = new ReferenceSuperimposer();
084                        imposer.superimpose(multAln);
085                        transf = multAln.getBlockSet(0).getTransformations();
086                        assert (transf != null);
087                }
088
089                // Rotate the atom coordinates of all the structures
090                for (int i = 0; i < size; i++) {
091                        // TODO handle BlockSet-level transformations
092                        // make sure this method has the same behavior as the other display.
093                        // -SB 2015-06
094
095                        // Assume all atoms are from the same structure
096                        Structure displayS = atomArrays.get(i)[0].getGroup().getChain()
097                                        .getStructure().clone();
098
099                        // Get all the atoms and include ligands and hetatoms
100                        Atom[] rotCA = StructureTools.getRepresentativeAtomArray(displayS);
101                        List<Group> hetatms = StructureTools.getUnalignedGroups(rotCA);
102                        int index = rotCA.length;
103                        rotCA = Arrays.copyOf(rotCA, rotCA.length + hetatms.size());
104                        for (Group g : hetatms) {
105                                rotCA[index] = g.getAtom(0);
106                                index++;
107                        }
108
109                        // Transform the structure to ensure a full rotation in the display
110                        Calc.transform(displayS, transf.get(i));
111                        rotatedAtoms.add(rotCA);
112                }
113
114                return rotatedAtoms;
115        }
116}