1 // ******************************************************************************
2 //
3 // Title: Force Field X.
4 // Description: Force Field X - Software for Molecular Biophysics.
5 // Copyright: Copyright (c) Michael J. Schnieders 2001-2025.
6 //
7 // This file is part of Force Field X.
8 //
9 // Force Field X is free software; you can redistribute it and/or modify it
10 // under the terms of the GNU General Public License version 3 as published by
11 // the Free Software Foundation.
12 //
13 // Force Field X is distributed in the hope that it will be useful, but WITHOUT
14 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16 // details.
17 //
18 // You should have received a copy of the GNU General Public License along with
19 // Force Field X; if not, write to the Free Software Foundation, Inc., 59 Temple
20 // Place, Suite 330, Boston, MA 02111-1307 USA
21 //
22 // Linking this library statically or dynamically with other modules is making a
23 // combined work based on this library. Thus, the terms and conditions of the
24 // GNU General Public License cover the whole combination.
25 //
26 // As a special exception, the copyright holders of this library give you
27 // permission to link this library with independent modules to produce an
28 // executable, regardless of the license terms of these independent modules, and
29 // to copy and distribute the resulting executable under terms of your choice,
30 // provided that you also meet, for each linked independent module, the terms
31 // and conditions of the license of that module. An independent module is a
32 // module which is not derived from or based on this library. If you modify this
33 // library, you may extend this exception to your version of the library, but
34 // you are not obligated to do so. If you do not wish to do so, delete this
35 // exception statement from your version.
36 //
37 // ******************************************************************************
38 package ffx.potential;
39
40 import ffx.potential.bonded.Atom;
41 import ffx.potential.bonded.MSNode;
42 import ffx.potential.bonded.MultiResidue;
43 import ffx.potential.bonded.Residue;
44 import ffx.potential.bonded.ResidueState;
45
46 import java.util.ArrayList;
47 import java.util.List;
48
49 /**
50 * The AssemblyState class stores the chemical and coordinate state of a Molecular Assembly. Not
51 * robust to any chemical perturbation except for mutation of MultiResidues.
52 *
53 * @author Michael J. Schnieders
54 * @author Jacob M. Litman
55 * @since 1.0
56 */
57 public class AssemblyState {
58 private final MolecularAssembly mola;
59 private final Residue[] residues;
60 private final ResidueState[] resStates;
61 private final Atom[] otherAtoms;
62 private final double[][] otherCoords;
63
64 /**
65 * Construct a snapshot of a MolecularAssembly. Currently accounts for the coordinates of all
66 * entities, and the chemical state of MultiResidues. Does not include velocities, etc.
67 *
68 * @param assembly To store state of.
69 */
70 public AssemblyState(MolecularAssembly assembly) {
71 mola = assembly;
72
73 List<Residue> residueList = mola.getResidueList();
74 List<Residue> copyResList = new ArrayList<>(residueList);
75 // Remove all Residue nodes, including subnodes of a MultiResidue, from otherNodeList.
76 List<MSNode> otherNodeList = mola.getNodeList();
77 otherNodeList.removeAll(residueList);
78
79 // Remove any Residue nodes which are beneath a MultiResidue.
80 for (Residue res : copyResList) {
81 if (res instanceof MultiResidue) {
82 List<Residue> subResidues = ((MultiResidue) res).getConsideredResidues();
83 residueList.removeAll(subResidues);
84 }
85 }
86
87 residues = residueList.toArray(new Residue[0]);
88 resStates = ResidueState.storeAllCoordinates(residues);
89
90 List<Atom> otherAtomList = new ArrayList<>();
91 for (MSNode node : otherNodeList) {
92 otherAtomList.addAll(node.getAtomList());
93 }
94 int nOtherAtoms = otherAtomList.size();
95 otherAtoms = new Atom[nOtherAtoms];
96 otherAtomList.toArray(otherAtoms);
97 otherCoords = ResidueState.storeAtomicCoordinates(otherAtoms);
98 }
99
100 /**
101 * Copies an AssemblyState. Note: side effects possible if they occur between applying the state
102 * to be copied and reverting to the pre-method-call state.
103 *
104 * @param state AssemblyState to copy.
105 * @return A copied AssemblyState.
106 */
107 public static AssemblyState copyState(AssemblyState state) {
108 MolecularAssembly assembly = state.getMolecularAssembly();
109 AssemblyState orig = new AssemblyState(assembly);
110 state.revertState();
111 AssemblyState copiedState = new AssemblyState(assembly);
112 orig.revertState();
113 return copiedState;
114 }
115
116 /**
117 * Returns the MolecularAssembly associated with this AssemblyState.
118 *
119 * @return The associated MolecularAssembly.
120 */
121 public MolecularAssembly getMolecularAssembly() {
122 return mola;
123 }
124
125 /**
126 * Revert the state of the associated MolecularAssembly, assuming no chemical changes were made
127 * except to MultiResidues.
128 */
129 public void revertState() {
130 int nResidues = residues.length;
131 for (int i = 0; i < nResidues; i++) {
132 residues[i].revertState(resStates[i]);
133 }
134
135 int nOthers = otherAtoms.length;
136 for (int i = 0; i < nOthers; i++) {
137 otherAtoms[i].setXYZ(otherCoords[i]);
138 }
139 }
140 }