From 5c24239004b99047fbeafd483407d9c9a60e7a7a Mon Sep 17 00:00:00 2001 From: "Daniel R. Roe" Date: Thu, 12 Mar 2026 08:08:53 -0400 Subject: [PATCH 01/19] Start adding back the old Builder class for modXNA --- src/Structure/OldBuilder.cpp | 109 +++++++++++++++++++++++++++++++++++ src/Structure/OldBuilder.h | 25 ++++++++ 2 files changed, 134 insertions(+) create mode 100644 src/Structure/OldBuilder.cpp create mode 100644 src/Structure/OldBuilder.h diff --git a/src/Structure/OldBuilder.cpp b/src/Structure/OldBuilder.cpp new file mode 100644 index 0000000000..32f1c22412 --- /dev/null +++ b/src/Structure/OldBuilder.cpp @@ -0,0 +1,109 @@ +#include "OldBuilder.h" +#include "BuildAtom.h" +#include "Chirality.h" +#include "Zmatrix.h" +#include "../CpptrajStdio.h" +#include "../Frame.h" +#include "../Topology.h" +#include // std::copy + +using namespace Cpptraj::Structure; + +/** CONSTRUCTOR */ +OldBuilder::OldBuilder() : + debug_(0) +{} + +/** Combine two units. Fragment 1 will be merged into Fragment 0 and bonded. */ +int OldBuilder::Combine(Topology& frag0Top, Frame& frag0frm, + Topology const& frag1Top, Frame const& frag1frm, + int bondAt0, int bondAt1) +{ + int natom0 = frag0Top.Natom(); + int newNatom = natom0 + frag1Top.Natom(); + + // Determine which "direction" we will be combining the fragments. + // Make atA belong to the smaller fragment. atB fragment will be "known". + // Ensure atB index is what it will be after fragments are combined. + Barray posKnown( newNatom, false ); + int atA, atB; + if (frag0Top.HeavyAtomCount() < frag1Top.HeavyAtomCount()) { + // Fragment 1 is larger + atA = bondAt0; + atB = bondAt1 + natom0; + for (int at = frag0Top.Natom(); at != newNatom; at++) + posKnown[at] = true; + } else { + // Fragment 0 is larger or equal + atA = bondAt1 + natom0; + atB = bondAt0; + for (int at = 0; at != natom0; at++) + posKnown[at] = true; + } + + // Combine fragment1 into fragment 0 topology + Topology& combinedTop = frag0Top; + combinedTop.AppendTop( frag1Top ); + // Combined fragment1 into fragment 0 coords. + // Need to save the original coords in frame0 since SetupFrameV does not preserve. + double* tmpcrd0 = new double[natom0*3]; + std::copy( frag0frm.xAddress(), frag0frm.xAddress()+frag0frm.size(), tmpcrd0 ); + frag0frm.SetupFrameV( combinedTop.Atoms(), CoordinateInfo(frag0frm.BoxCrd(), false, false, false)); + std::copy( tmpcrd0, tmpcrd0+natom0*3, frag0frm.xAddress() ); + std::copy( frag1frm.xAddress(), frag1frm.xAddress()+frag1frm.size(), frag0frm.xAddress()+natom0*3 ); + Frame& CombinedFrame = frag0frm; + delete[] tmpcrd0; + + int chiralityDebug; + if (debug_ < 1) + chiralityDebug = 0; + else + chiralityDebug = debug_ - 1; + // Get the chirality around each atom before the bond is added. + BuildAtom AtomA; + if (combinedTop[atA].Nbonds() > 2) + AtomA.SetChirality( DetermineChirality(atA, combinedTop, CombinedFrame, chiralityDebug) ); + if (debug_ > 0) + mprintf("DEBUG:\tAtom %4s chirality %6s\n", combinedTop.AtomMaskName(atA).c_str(), chiralStr(AtomA.Chirality())); + BuildAtom AtomB; + if (combinedTop[atB].Nbonds() > 2) + AtomB.SetChirality( DetermineChirality(atB, combinedTop, CombinedFrame, chiralityDebug) ); + if (debug_ > 0) + mprintf("DEBUG:\tAtom %4s chirality %6s\n", combinedTop.AtomMaskName(atB).c_str(), chiralStr(AtomB.Chirality())); + + // Create the bond + if (debug_ > 0) + mprintf("DEBUG: Bonding atom %s to %s\n", combinedTop.AtomMaskName(atA).c_str(), combinedTop.AtomMaskName(atB).c_str()); + combinedTop.AddBond( atA, atB ); // TODO pseudo-parameter? + // // Regenerate the molecule info FIXME should Topology just do this? + if (combinedTop.DetermineMolecules()) return 1; + + // Determine priorities + if (combinedTop[atA].Nbonds() > 2) { + //AtomA.SetNbonds(combinedTop[atA].Nbonds()); + SetPriority(AtomA.ModifyPriority(), atA, combinedTop, CombinedFrame, chiralityDebug); + } + if (combinedTop[atB].Nbonds() > 2) { + //AtomB.SetNbonds(combinedTop[atB].Nbonds()); + SetPriority(AtomB.ModifyPriority(), atB, combinedTop, CombinedFrame, chiralityDebug); + } + + // Generate Zmatrix only for ICs involving bonded atoms + Zmatrix bondZmatrix; + + bondZmatrix.SetDebug( debug_ ); + if (bondZmatrix.SetupICsAroundBond(atA, atB, CombinedFrame, combinedTop, posKnown, AtomA, AtomB)) { + mprinterr("Error: Zmatrix setup for ICs around %s and %s failed.\n", + combinedTop.AtomMaskName(atA).c_str(), + combinedTop.AtomMaskName(atB).c_str()); + return 1; + } + if (debug_ > 0) + bondZmatrix.print(&combinedTop); + if (bondZmatrix.SetToFrame( CombinedFrame, posKnown )) { + mprinterr("Error: Conversion from bondZmatrix to Cartesian coords failed.\n"); + return 1; + } + + return 0; +} diff --git a/src/Structure/OldBuilder.h b/src/Structure/OldBuilder.h new file mode 100644 index 0000000000..67c588c057 --- /dev/null +++ b/src/Structure/OldBuilder.h @@ -0,0 +1,25 @@ +#ifndef INC_STRUCTURE_OLDBUILDER_H +#define INC_STRUCTURE_OLDBUILDER_H +#include +class Topology; +class Frame; +namespace Cpptraj { +namespace Structure { +/// This is the old ( Barray; + + int debug_; +}; +} +} +#endif From 9f8b37efbab8f75a157d8c6b1aba106fc2d48607 Mon Sep 17 00:00:00 2001 From: "Daniel R. Roe" Date: Thu, 12 Mar 2026 08:12:46 -0400 Subject: [PATCH 02/19] Add OldBuilder to the build and add the old BuildAtom class too --- src/Structure/CMakeLists.txt | 1 + src/Structure/OldBuilder.cpp | 1 - src/Structure/OldBuilder.h | 23 +++++++++++++++++++++++ src/Structure/structuredepend | 1 + src/Structure/structurefiles | 1 + src/cpptrajdepend | 1 + 6 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/Structure/CMakeLists.txt b/src/Structure/CMakeLists.txt index a98547d991..2a30885687 100644 --- a/src/Structure/CMakeLists.txt +++ b/src/Structure/CMakeLists.txt @@ -12,6 +12,7 @@ target_sources(cpptraj_common_obj PRIVATE ${CMAKE_CURRENT_LIST_DIR}/InternalCoords.cpp ${CMAKE_CURRENT_LIST_DIR}/LeastSquaresPlane.cpp ${CMAKE_CURRENT_LIST_DIR}/MetalCenterFinder.cpp + ${CMAKE_CURRENT_LIST_DIR}/OldBuilder.cpp ${CMAKE_CURRENT_LIST_DIR}/PdbCleaner.cpp ${CMAKE_CURRENT_LIST_DIR}/RingFinder.cpp ${CMAKE_CURRENT_LIST_DIR}/Solvate.cpp diff --git a/src/Structure/OldBuilder.cpp b/src/Structure/OldBuilder.cpp index 32f1c22412..d92a8fe5dc 100644 --- a/src/Structure/OldBuilder.cpp +++ b/src/Structure/OldBuilder.cpp @@ -1,5 +1,4 @@ #include "OldBuilder.h" -#include "BuildAtom.h" #include "Chirality.h" #include "Zmatrix.h" #include "../CpptrajStdio.h" diff --git a/src/Structure/OldBuilder.h b/src/Structure/OldBuilder.h index 67c588c057..2bcf49f4d1 100644 --- a/src/Structure/OldBuilder.h +++ b/src/Structure/OldBuilder.h @@ -20,6 +20,29 @@ class OldBuilder { int debug_; }; + +/// Old (& ModifyPriority() { return priority_; } + + /// \return Atom chirality + ChiralType Chirality() const { return ctype_; } + /// \return Priority array + std::vector const& Priority() const { return priority_; } + private: + ChiralType ctype_; ///< Chirality around atom + std::vector priority_; ///< Indices of bonded atoms, sorted by priority +}; + } } #endif diff --git a/src/Structure/structuredepend b/src/Structure/structuredepend index 2bdebfb6b5..48cd6e8840 100644 --- a/src/Structure/structuredepend +++ b/src/Structure/structuredepend @@ -10,6 +10,7 @@ HisProt.o : HisProt.cpp ../ArgList.h ../Atom.h ../AtomMask.h ../Box.h ../Constan InternalCoords.o : InternalCoords.cpp ../Atom.h ../AtomMask.h ../Box.h ../Constants.h ../CoordinateInfo.h ../CpptrajStdio.h ../FileName.h ../Frame.h ../MaskToken.h ../Matrix_3x3.h ../ModXNA_Info.h ../Molecule.h ../NameType.h ../Parallel.h ../ParameterTypes.h ../Range.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../SymbolExporting.h ../Topology.h ../Unit.h ../Vec3.h InternalCoords.h LeastSquaresPlane.o : LeastSquaresPlane.cpp ../Atom.h ../AtomMask.h ../Box.h ../Constants.h ../CoordinateInfo.h ../Frame.h ../MaskToken.h ../Matrix_3x3.h ../Molecule.h ../NameType.h ../Parallel.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../SymbolExporting.h ../Unit.h ../Vec3.h LeastSquaresPlane.h MetalCenterFinder.o : MetalCenterFinder.cpp ../ArgList.h ../Atom.h ../AtomMask.h ../Box.h ../Constants.h ../CoordinateInfo.h ../CpptrajStdio.h ../DistRoutines.h ../FileName.h ../Frame.h ../ImageOption.h ../MaskToken.h ../Matrix_3x3.h ../ModXNA_Info.h ../Molecule.h ../NameType.h ../Parallel.h ../ParameterTypes.h ../Range.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../SymbolExporting.h ../Topology.h ../Unit.h ../Vec3.h MetalCenterFinder.h +OldBuilder.o : OldBuilder.cpp ../Atom.h ../AtomMask.h ../Box.h ../Constants.h ../CoordinateInfo.h ../CpptrajStdio.h ../FileName.h ../Frame.h ../MaskToken.h ../Matrix_3x3.h ../ModXNA_Info.h ../Molecule.h ../NameType.h ../Parallel.h ../ParameterTypes.h ../Range.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../SymbolExporting.h ../Topology.h ../Unit.h ../Vec3.h Chirality.h InternalCoords.h OldBuilder.h StructureEnum.h Zmatrix.h PdbCleaner.o : PdbCleaner.cpp ../ArgList.h ../Atom.h ../AtomMask.h ../Box.h ../Constants.h ../CoordinateInfo.h ../CpptrajStdio.h ../FileName.h ../Frame.h ../MaskToken.h ../Matrix_3x3.h ../ModXNA_Info.h ../Molecule.h ../NameType.h ../Parallel.h ../ParameterTypes.h ../Range.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../SymbolExporting.h ../Topology.h ../Unit.h ../Vec3.h PdbCleaner.h RingFinder.o : RingFinder.cpp ../Atom.h ../AtomMask.h ../Box.h ../CharMask.h ../Constants.h ../CoordinateInfo.h ../CpptrajStdio.h ../FileName.h ../Frame.h ../MaskToken.h ../Matrix_3x3.h ../ModXNA_Info.h ../Molecule.h ../NameType.h ../Parallel.h ../ParameterTypes.h ../Range.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../SymbolExporting.h ../Topology.h ../Unit.h ../Vec3.h RingFinder.h Solvate.o : Solvate.cpp ../Action.h ../ActionState.h ../Action_AutoImage.h ../ArgList.h ../AssociatedData.h ../Atom.h ../AtomMask.h ../BaseIOtype.h ../Box.h ../CharMask.h ../Constants.h ../CoordinateInfo.h ../CpptrajFile.h ../CpptrajStdio.h ../DataFile.h ../DataFileList.h ../DataSet.h ../DataSetList.h ../DataSet_Coords.h ../DataSet_Coords_REF.h ../Dimension.h ../DispatchObject.h ../FileIO.h ../FileName.h ../FileTypes.h ../Frame.h ../MaskToken.h ../Matrix_3x3.h ../MetaData.h ../ModXNA_Info.h ../Molecule.h ../NameType.h ../Parallel.h ../ParameterTypes.h ../Parm/../AtomType.h ../Parm/../CmapParmHolder.h ../Parm/../Constants.h ../Parm/../FileName.h ../Parm/../NameType.h ../Parm/../ParameterTypes.h ../Parm/../Parm/ParmEnum.h ../Parm/../TypeNameHolder.h ../Parm/DihedralParmHolder.h ../Parm/ImproperParmHolder.h ../Parm/ParameterSet.h ../Parm/ParmEnum.h ../Parm/ParmHolder.h ../Range.h ../ReferenceFrame.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../SymbolExporting.h ../TextFormat.h ../Timer.h ../Topology.h ../Unit.h ../Vec3.h Solvate.h diff --git a/src/Structure/structurefiles b/src/Structure/structurefiles index 3f53f820b1..9ac0f07c5f 100644 --- a/src/Structure/structurefiles +++ b/src/Structure/structurefiles @@ -12,6 +12,7 @@ STRUCTURE_SOURCES= \ InternalCoords.cpp \ LeastSquaresPlane.cpp \ MetalCenterFinder.cpp \ + OldBuilder.cpp \ PdbCleaner.cpp \ RingFinder.cpp \ Solvate.cpp \ diff --git a/src/cpptrajdepend b/src/cpptrajdepend index c633777ac6..6e432c357d 100644 --- a/src/cpptrajdepend +++ b/src/cpptrajdepend @@ -499,6 +499,7 @@ Structure/HisProt.o : Structure/HisProt.cpp ArgList.h Atom.h AtomMask.h Box.h Co Structure/InternalCoords.o : Structure/InternalCoords.cpp Atom.h AtomMask.h Box.h Constants.h CoordinateInfo.h CpptrajStdio.h FileName.h Frame.h MaskToken.h Matrix_3x3.h ModXNA_Info.h Molecule.h NameType.h Parallel.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h Structure/InternalCoords.h SymbolExporting.h Topology.h Unit.h Vec3.h Structure/LeastSquaresPlane.o : Structure/LeastSquaresPlane.cpp Atom.h AtomMask.h Box.h Constants.h CoordinateInfo.h Frame.h MaskToken.h Matrix_3x3.h Molecule.h NameType.h Parallel.h ReplicaDimArray.h Residue.h Segment.h Structure/LeastSquaresPlane.h SymbolExporting.h Unit.h Vec3.h Structure/MetalCenterFinder.o : Structure/MetalCenterFinder.cpp ArgList.h Atom.h AtomMask.h Box.h Constants.h CoordinateInfo.h CpptrajStdio.h DistRoutines.h FileName.h Frame.h ImageOption.h MaskToken.h Matrix_3x3.h ModXNA_Info.h Molecule.h NameType.h Parallel.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h Structure/MetalCenterFinder.h SymbolExporting.h Topology.h Unit.h Vec3.h +Structure/OldBuilder.o : Structure/OldBuilder.cpp Atom.h AtomMask.h Box.h Constants.h CoordinateInfo.h CpptrajStdio.h FileName.h Frame.h MaskToken.h Matrix_3x3.h ModXNA_Info.h Molecule.h NameType.h Parallel.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h Structure/Chirality.h Structure/InternalCoords.h Structure/OldBuilder.h Structure/StructureEnum.h Structure/Zmatrix.h SymbolExporting.h Topology.h Unit.h Vec3.h Structure/PdbCleaner.o : Structure/PdbCleaner.cpp ArgList.h Atom.h AtomMask.h Box.h Constants.h CoordinateInfo.h CpptrajStdio.h FileName.h Frame.h MaskToken.h Matrix_3x3.h ModXNA_Info.h Molecule.h NameType.h Parallel.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h Structure/PdbCleaner.h SymbolExporting.h Topology.h Unit.h Vec3.h Structure/RingFinder.o : Structure/RingFinder.cpp Atom.h AtomMask.h Box.h CharMask.h Constants.h CoordinateInfo.h CpptrajStdio.h FileName.h Frame.h MaskToken.h Matrix_3x3.h ModXNA_Info.h Molecule.h NameType.h Parallel.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h Structure/RingFinder.h SymbolExporting.h Topology.h Unit.h Vec3.h Structure/Solvate.o : Structure/Solvate.cpp Action.h ActionState.h Action_AutoImage.h ArgList.h AssociatedData.h Atom.h AtomMask.h BaseIOtype.h Box.h CharMask.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h DispatchObject.h FileIO.h FileName.h FileTypes.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h ModXNA_Info.h Molecule.h NameType.h Parallel.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h Structure/../Parm/../AtomType.h Structure/../Parm/../CmapParmHolder.h Structure/../Parm/../Constants.h Structure/../Parm/../FileName.h Structure/../Parm/../NameType.h Structure/../Parm/../ParameterTypes.h Structure/../Parm/../Parm/ParmEnum.h Structure/../Parm/../TypeNameHolder.h Structure/../Parm/DihedralParmHolder.h Structure/../Parm/ImproperParmHolder.h Structure/../Parm/ParameterSet.h Structure/../Parm/ParmEnum.h Structure/../Parm/ParmHolder.h Structure/Solvate.h SymbolExporting.h TextFormat.h Timer.h Topology.h Unit.h Vec3.h From ff003837b4dbb3d31bb3900f7cec309588ca570f Mon Sep 17 00:00:00 2001 From: "Daniel R. Roe" Date: Thu, 12 Mar 2026 08:21:54 -0400 Subject: [PATCH 03/19] Add missing include --- src/Structure/OldBuilder.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Structure/OldBuilder.h b/src/Structure/OldBuilder.h index 2bcf49f4d1..7c10f43f3d 100644 --- a/src/Structure/OldBuilder.h +++ b/src/Structure/OldBuilder.h @@ -1,6 +1,7 @@ #ifndef INC_STRUCTURE_OLDBUILDER_H #define INC_STRUCTURE_OLDBUILDER_H #include +#include "StructureEnum.h" class Topology; class Frame; namespace Cpptraj { From 78af50c0a67da2a4bcc810e2c26d77d510c4b853 Mon Sep 17 00:00:00 2001 From: "Daniel R. Roe" Date: Thu, 12 Mar 2026 08:30:49 -0400 Subject: [PATCH 04/19] Add back old model class for modXNA --- src/Structure/Model.cpp | 258 ++++++++++++++++++++++++++++++++++++++++ src/Structure/Model.h | 20 ++++ 2 files changed, 278 insertions(+) create mode 100644 src/Structure/Model.cpp create mode 100644 src/Structure/Model.h diff --git a/src/Structure/Model.cpp b/src/Structure/Model.cpp new file mode 100644 index 0000000000..affbf21f06 --- /dev/null +++ b/src/Structure/Model.cpp @@ -0,0 +1,258 @@ +#include "Model.h" +#include "BuildAtom.h" +#include "../CpptrajStdio.h" +#include "../Topology.h" +#include "../TorsionRoutines.h" +#include "../Constants.h" + +/** Attempt to assign a reasonable value for theta internal coordinate for + * atom i given that atoms j and k have known positions. + */ +int Cpptraj::Structure::Model::AssignTheta(double& theta, int ai, int aj, int ak, Topology const& topIn, Frame const& frameIn, std::vector const& atomPositionKnown, int debug) +{ + // Figure out hybridization and chirality of atom j. + if (debug > 0) + mprintf("DEBUG: AssignTheta for atom j : %s\n", topIn.AtomMaskName(aj).c_str()); + + enum HybridizationType { SP = 0, SP2, SP3, UNKNOWN_HYBRIDIZATION }; + + Atom const& AJ = topIn[aj]; + if (debug > 0) { + mprintf("DEBUG:\t\tI %s Nbonds: %i\n", topIn[ai].ElementName(), topIn[ai].Nbonds()); + mprintf("DEBUG:\t\tJ %s Nbonds: %i\n", AJ.ElementName(), AJ.Nbonds()); + mprintf("DEBUG:\t\tK %s Nbonds: %i\n", topIn[ak].ElementName(), topIn[ak].Nbonds()); + } + // Sanity check + if (AJ.Nbonds() < 2) { + mprinterr("Internal Error: AssignTheta() called for atom J %s with fewer than 2 bonds.\n", topIn.AtomMaskName(aj).c_str()); + return 1; + } + + HybridizationType hybrid = UNKNOWN_HYBRIDIZATION; + // Handle specific elements + switch (AJ.Element()) { + case Atom::CARBON : + switch (AJ.Nbonds()) { + case 2 : hybrid = SP; break; + case 3 : hybrid = SP2; break; + case 4 : hybrid = SP3; break; + } + break; + case Atom::NITROGEN : + switch (AJ.Nbonds()) { + case 2 : hybrid = SP2; break; + case 3 : + // Check for potential SP2. If only 1 of the bonded atoms is + // hydrogen, assume SP2. TODO actually check for aromaticity. + int n_hydrogens = 0; + for (Atom::bond_iterator bat = AJ.bondbegin(); bat != AJ.bondend(); ++bat) + if (topIn[*bat].Element() == Atom::HYDROGEN) + n_hydrogens++; + if (n_hydrogens == 1) + hybrid = SP2; + else + hybrid = SP3; + break; + } + break; + case Atom::OXYGEN : + switch (AJ.Nbonds()) { + case 2 : hybrid = SP3; break; + } + break; + case Atom::SULFUR : + switch (AJ.Nbonds()) { + case 2 : hybrid = SP3; break; + } + break; + default: hybrid = UNKNOWN_HYBRIDIZATION; break; + } + // Fill in what values we can for known atoms +/* std::vector knownTheta( AJ.Nbonds() ); + int knownIdx = -1; + for (int idx = 0; idx < AJ.Nbonds(); idx++) { + int atnum = AJ.Bond(idx); + if (atnum != ak && atomPositionKnown[atnum]) { + knownTheta[idx] = CalcAngle(frameIn.XYZ(atnum), + frameIn.XYZ(aj), + frameIn.XYZ(ak)); + mprintf("DEBUG:\t\tKnown theta for %s = %g\n", topIn.AtomMaskName(atnum).c_str(), knownTheta[idx]*Constants::RADDEG); + if (knownIdx == -1) knownIdx = idx; // FIXME handle more than 1 known + } + } + if (knownIdx == -1) {*/ + //mprintf("DEBUG:\t\tNo known theta.\n"); + if (hybrid == UNKNOWN_HYBRIDIZATION) { + // Assign a theta based on number of bonds + switch (AJ.Nbonds()) { + case 4 : hybrid = SP3; break; + case 3 : hybrid = SP2; break; + case 2 : hybrid = SP; break; + default : mprinterr("Internal Error: AssignTheta(): Unhandled # bonds for %s (%i)\n", topIn.AtomMaskName(aj).c_str(), AJ.Nbonds()); return 1; + } + } + // Assign a theta based on hybridization + switch (hybrid) { + case SP3 : theta = 109.5 * Constants::DEGRAD; break; + case SP2 : theta = 120.0 * Constants::DEGRAD; break; + case SP : theta = 180.0 * Constants::DEGRAD; break; + default : mprinterr("Internal Error: AssignTheta(): Unhandled hybridization for %s (%i)\n", topIn.AtomMaskName(aj).c_str(), AJ.Nbonds()); return 1; + }/* + } else { + theta = knownTheta[knownIdx]; // TODO just use above guess via hybrid? + }*/ + + return 0; +} + +/// Recursive function to return depth from an atom along bonds +static int atom_depth(int& depth, + int at, Topology const& topIn, std::vector& visited, int maxdepth) +{ + if (depth == maxdepth) return 0; + depth++; + visited[at] = true; + int depthFromHere = 1; + for (Atom::bond_iterator bat = topIn[at].bondbegin(); bat != topIn[at].bondend(); ++bat) + { + if (!visited[*bat]) + depthFromHere += atom_depth( depth, *bat, topIn, visited, maxdepth ); + } + return depthFromHere; +} + +static inline double wrap360(double phi) { + if (phi > Constants::PI) + return phi - Constants::TWOPI; + else if (phi < -Constants::PI) + return phi + Constants::TWOPI; + else + return phi; +} + +/** Attempt to assign a reasonable value for phi internal coordinate for atom i + * given that atoms j k and l have known positions. + * j - k + * / \ + * i l + */ +int Cpptraj::Structure::Model::AssignPhi(double& phi, int ai, int aj, int ak, int al, + Topology const& topIn, Frame const& frameIn, + std::vector const& atomPositionKnown, + BuildAtom const& AtomJ, int debug) +{ + // Figure out hybridization and chirality of atom j. + if (debug > 0) + mprintf("DEBUG: AssignPhi for atom j : %s\n", topIn.AtomMaskName(aj).c_str()); + + Atom const& AJ = topIn[aj]; + if (debug > 0) mprintf("DEBUG:\t\tNbonds: %i\n", AJ.Nbonds()); + // If atom J only has 2 bonds, ai-aj-ak-al is the only possibility. + if (AJ.Nbonds() < 3) { + if (debug > 0) + mprintf("DEBUG:\t\tFewer than 3 bonds. Setting phi to -180.\n"); + phi = -180 * Constants::DEGRAD; + return 0; + } + + // TODO check that atom i actually ends up on the list? + std::vector const& priority = AtomJ.Priority(); + if (debug > 0) { + mprintf("DEBUG: Original chirality around J %s is %s\n", topIn.AtomMaskName(aj).c_str(), chiralStr(AtomJ.Chirality())); + mprintf("DEBUG:\t\tPriority around J %s(%i):", + topIn.AtomMaskName(aj).c_str(), (int)atomPositionKnown[aj]); + for (int idx = 0; idx < AJ.Nbonds(); idx++) + mprintf(" %s(%i)", topIn.AtomMaskName(priority[idx]).c_str(), (int)atomPositionKnown[priority[idx]]); + mprintf("\n"); + } + + // Fill in what values we can for known atoms + std::vector knownPhi( AJ.Nbonds() ); + int knownIdx = -1; + for (int idx = 0; idx < AJ.Nbonds(); idx++) { + int atnum = priority[idx]; + if (atnum != ak && atomPositionKnown[atnum] && + atomPositionKnown[aj] && + atomPositionKnown[ak] && + atomPositionKnown[al]) + { + knownPhi[idx] = Torsion(frameIn.XYZ(atnum), + frameIn.XYZ(aj), + frameIn.XYZ(ak), + frameIn.XYZ(al)); + if (debug > 0) + mprintf("DEBUG:\t\tKnown phi for %s = %g\n", topIn.AtomMaskName(atnum).c_str(), knownPhi[idx]*Constants::RADDEG); + if (knownIdx == -1) knownIdx = idx; // FIXME handle more than 1 known + } + } + + // If we have to assign an initial phi, make trans the longer branch + if (knownIdx == -1) { + std::vector visited = atomPositionKnown; + // TODO: Ensure bonded atoms are not yet visited? + visited[aj] = true; + visited[ak] = true; + std::vector depth( AJ.Nbonds() ); + for (int idx = 0; idx < AJ.Nbonds(); idx++) { + int atnum = priority[idx]; + if (atnum != ak) { + int currentDepth = 0; + depth[idx] = atom_depth(currentDepth, atnum, topIn, visited, 10); + if (debug > 0) + mprintf("DEBUG:\t\tAJ %s depth from %s is %i\n", + topIn.AtomMaskName(aj).c_str(), topIn.AtomMaskName(atnum).c_str(), depth[idx]); + if (knownIdx == -1 && depth[idx] < 3) { + knownIdx = idx; + knownPhi[idx] = 0; + } + } + } + } + + // The interval will be 360 / (number of bonds - 1) + double interval = Constants::TWOPI / (AJ.Nbonds() - 1); + + double startPhi; + if (knownIdx == -1) { + startPhi = -180*Constants::DEGRAD; + if (debug > 0) mprintf("DEBUG:\t\tNo known phi. Setting to %g.\n", startPhi*Constants::RADDEG); + knownIdx = 0; + } else + startPhi = knownPhi[knownIdx]; + + if (AtomJ.Chirality() == IS_R) { + startPhi = -startPhi; + interval = -interval; + } + if (debug > 0) { + mprintf("DEBUG:\t\tStart phi is %g degrees\n", startPhi*Constants::RADDEG); + mprintf("DEBUG:\t\tInterval is %g degrees\n", interval * Constants::RADDEG); + } + + // Forward direction + double currentPhi = startPhi; + for (int idx = knownIdx; idx < AJ.Nbonds(); idx++) { + int atnum = priority[idx]; + if (atnum != ak) { + if (atnum == ai) phi = currentPhi; + if (debug > 0) + mprintf("DEBUG:\t\t\t%s phi= %g\n", topIn.AtomMaskName(atnum).c_str(), currentPhi*Constants::RADDEG); + currentPhi += interval; + currentPhi = wrap360(currentPhi); + } + } + // Reverse direction + currentPhi = startPhi - interval; + for (int idx = knownIdx - 1; idx > -1; idx--) { + int atnum = priority[idx]; + if (atnum != ak) { + if (atnum == ai) phi = currentPhi; + if (debug > 0) + mprintf("DEBUG:\t\t\t%s phi= %g\n", topIn.AtomMaskName(atnum).c_str(), currentPhi*Constants::RADDEG); + currentPhi -= interval; + currentPhi = wrap360(currentPhi); + } + } + + return 0; +} diff --git a/src/Structure/Model.h b/src/Structure/Model.h new file mode 100644 index 0000000000..240e64875e --- /dev/null +++ b/src/Structure/Model.h @@ -0,0 +1,20 @@ +#ifndef INC_STRUCTURE_MODEL_H +#define INC_STRUCTURE_MODEL_H +#include +#include "StructureEnum.h" +class Topology; +class Frame; +namespace Cpptraj { +namespace Structure { +class BuildAtom; +/// Routines to generate model parameters +namespace Model { +/// Given atoms J K and L, attempt to assign a reasonable value for phi for atom I +int AssignPhi(double&, int, int, int, int, Topology const&, Frame const&, std::vector const&, BuildAtom const&, int); +/// Given atoms J and K, attempt to assign a reasonable value for theta for atom I +int AssignTheta(double&, int, int, int, Topology const&, Frame const&, std::vector const&, int); + +} // END namespace Model +} // END namespace Structure +} // END namespace Cpptraj +#endif From 8f07df69101e5df54416115e06a9d17424f6d69b Mon Sep 17 00:00:00 2001 From: "Daniel R. Roe" Date: Thu, 12 Mar 2026 08:34:22 -0400 Subject: [PATCH 05/19] Split BuildAtom back out --- src/Structure/BuildAtom.h | 29 +++++++++++++++++++++++++++++ src/Structure/OldBuilder.cpp | 1 + src/Structure/OldBuilder.h | 24 +----------------------- 3 files changed, 31 insertions(+), 23 deletions(-) create mode 100644 src/Structure/BuildAtom.h diff --git a/src/Structure/BuildAtom.h b/src/Structure/BuildAtom.h new file mode 100644 index 0000000000..3fa2b56a0a --- /dev/null +++ b/src/Structure/BuildAtom.h @@ -0,0 +1,29 @@ +#ifndef INC_STRUCTURE_BUILDATOM_H +#define INC_STRUCTURE_BUILDATOM_H +#include "StructureEnum.h" +namespace Cpptraj { +namespace Structure { +/// Old (& ModifyPriority() { return priority_; } + + /// \return Atom chirality + ChiralType Chirality() const { return ctype_; } + /// \return Priority array + std::vector const& Priority() const { return priority_; } + private: + ChiralType ctype_; ///< Chirality around atom + std::vector priority_; ///< Indices of bonded atoms, sorted by priority +}; +} +} +#endif diff --git a/src/Structure/OldBuilder.cpp b/src/Structure/OldBuilder.cpp index d92a8fe5dc..32f1c22412 100644 --- a/src/Structure/OldBuilder.cpp +++ b/src/Structure/OldBuilder.cpp @@ -1,4 +1,5 @@ #include "OldBuilder.h" +#include "BuildAtom.h" #include "Chirality.h" #include "Zmatrix.h" #include "../CpptrajStdio.h" diff --git a/src/Structure/OldBuilder.h b/src/Structure/OldBuilder.h index 7c10f43f3d..b37339376e 100644 --- a/src/Structure/OldBuilder.h +++ b/src/Structure/OldBuilder.h @@ -1,13 +1,12 @@ #ifndef INC_STRUCTURE_OLDBUILDER_H #define INC_STRUCTURE_OLDBUILDER_H #include -#include "StructureEnum.h" class Topology; class Frame; namespace Cpptraj { namespace Structure { /// This is the old (& ModifyPriority() { return priority_; } - - /// \return Atom chirality - ChiralType Chirality() const { return ctype_; } - /// \return Priority array - std::vector const& Priority() const { return priority_; } - private: - ChiralType ctype_; ///< Chirality around atom - std::vector priority_; ///< Indices of bonded atoms, sorted by priority -}; } } From 459c8e3891c0321011601c67882bb0a923ce6c09 Mon Sep 17 00:00:00 2001 From: "Daniel R. Roe" Date: Thu, 12 Mar 2026 08:35:07 -0400 Subject: [PATCH 06/19] Add old Model class to the build --- src/Structure/CMakeLists.txt | 1 + src/Structure/Model.h | 2 +- src/Structure/structuredepend | 3 ++- src/Structure/structurefiles | 1 + src/cpptrajdepend | 3 ++- 5 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Structure/CMakeLists.txt b/src/Structure/CMakeLists.txt index 2a30885687..68d133db81 100644 --- a/src/Structure/CMakeLists.txt +++ b/src/Structure/CMakeLists.txt @@ -12,6 +12,7 @@ target_sources(cpptraj_common_obj PRIVATE ${CMAKE_CURRENT_LIST_DIR}/InternalCoords.cpp ${CMAKE_CURRENT_LIST_DIR}/LeastSquaresPlane.cpp ${CMAKE_CURRENT_LIST_DIR}/MetalCenterFinder.cpp + ${CMAKE_CURRENT_LIST_DIR}/Model.cpp ${CMAKE_CURRENT_LIST_DIR}/OldBuilder.cpp ${CMAKE_CURRENT_LIST_DIR}/PdbCleaner.cpp ${CMAKE_CURRENT_LIST_DIR}/RingFinder.cpp diff --git a/src/Structure/Model.h b/src/Structure/Model.h index 240e64875e..3b1f4fafde 100644 --- a/src/Structure/Model.h +++ b/src/Structure/Model.h @@ -7,7 +7,7 @@ class Frame; namespace Cpptraj { namespace Structure { class BuildAtom; -/// Routines to generate model parameters +/// Routines to generate model parameters TODO needed for modXNA namespace Model { /// Given atoms J K and L, attempt to assign a reasonable value for phi for atom I int AssignPhi(double&, int, int, int, int, Topology const&, Frame const&, std::vector const&, BuildAtom const&, int); diff --git a/src/Structure/structuredepend b/src/Structure/structuredepend index 48cd6e8840..f42ee41234 100644 --- a/src/Structure/structuredepend +++ b/src/Structure/structuredepend @@ -10,7 +10,8 @@ HisProt.o : HisProt.cpp ../ArgList.h ../Atom.h ../AtomMask.h ../Box.h ../Constan InternalCoords.o : InternalCoords.cpp ../Atom.h ../AtomMask.h ../Box.h ../Constants.h ../CoordinateInfo.h ../CpptrajStdio.h ../FileName.h ../Frame.h ../MaskToken.h ../Matrix_3x3.h ../ModXNA_Info.h ../Molecule.h ../NameType.h ../Parallel.h ../ParameterTypes.h ../Range.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../SymbolExporting.h ../Topology.h ../Unit.h ../Vec3.h InternalCoords.h LeastSquaresPlane.o : LeastSquaresPlane.cpp ../Atom.h ../AtomMask.h ../Box.h ../Constants.h ../CoordinateInfo.h ../Frame.h ../MaskToken.h ../Matrix_3x3.h ../Molecule.h ../NameType.h ../Parallel.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../SymbolExporting.h ../Unit.h ../Vec3.h LeastSquaresPlane.h MetalCenterFinder.o : MetalCenterFinder.cpp ../ArgList.h ../Atom.h ../AtomMask.h ../Box.h ../Constants.h ../CoordinateInfo.h ../CpptrajStdio.h ../DistRoutines.h ../FileName.h ../Frame.h ../ImageOption.h ../MaskToken.h ../Matrix_3x3.h ../ModXNA_Info.h ../Molecule.h ../NameType.h ../Parallel.h ../ParameterTypes.h ../Range.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../SymbolExporting.h ../Topology.h ../Unit.h ../Vec3.h MetalCenterFinder.h -OldBuilder.o : OldBuilder.cpp ../Atom.h ../AtomMask.h ../Box.h ../Constants.h ../CoordinateInfo.h ../CpptrajStdio.h ../FileName.h ../Frame.h ../MaskToken.h ../Matrix_3x3.h ../ModXNA_Info.h ../Molecule.h ../NameType.h ../Parallel.h ../ParameterTypes.h ../Range.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../SymbolExporting.h ../Topology.h ../Unit.h ../Vec3.h Chirality.h InternalCoords.h OldBuilder.h StructureEnum.h Zmatrix.h +Model.o : Model.cpp ../Atom.h ../AtomMask.h ../Box.h ../Constants.h ../CoordinateInfo.h ../CpptrajStdio.h ../FileName.h ../Frame.h ../MaskToken.h ../Matrix_3x3.h ../ModXNA_Info.h ../Molecule.h ../NameType.h ../Parallel.h ../ParameterTypes.h ../Range.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../SymbolExporting.h ../Topology.h ../TorsionRoutines.h ../Unit.h ../Vec3.h BuildAtom.h Model.h StructureEnum.h +OldBuilder.o : OldBuilder.cpp ../Atom.h ../AtomMask.h ../Box.h ../Constants.h ../CoordinateInfo.h ../CpptrajStdio.h ../FileName.h ../Frame.h ../MaskToken.h ../Matrix_3x3.h ../ModXNA_Info.h ../Molecule.h ../NameType.h ../Parallel.h ../ParameterTypes.h ../Range.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../SymbolExporting.h ../Topology.h ../Unit.h ../Vec3.h BuildAtom.h Chirality.h InternalCoords.h OldBuilder.h StructureEnum.h Zmatrix.h PdbCleaner.o : PdbCleaner.cpp ../ArgList.h ../Atom.h ../AtomMask.h ../Box.h ../Constants.h ../CoordinateInfo.h ../CpptrajStdio.h ../FileName.h ../Frame.h ../MaskToken.h ../Matrix_3x3.h ../ModXNA_Info.h ../Molecule.h ../NameType.h ../Parallel.h ../ParameterTypes.h ../Range.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../SymbolExporting.h ../Topology.h ../Unit.h ../Vec3.h PdbCleaner.h RingFinder.o : RingFinder.cpp ../Atom.h ../AtomMask.h ../Box.h ../CharMask.h ../Constants.h ../CoordinateInfo.h ../CpptrajStdio.h ../FileName.h ../Frame.h ../MaskToken.h ../Matrix_3x3.h ../ModXNA_Info.h ../Molecule.h ../NameType.h ../Parallel.h ../ParameterTypes.h ../Range.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../SymbolExporting.h ../Topology.h ../Unit.h ../Vec3.h RingFinder.h Solvate.o : Solvate.cpp ../Action.h ../ActionState.h ../Action_AutoImage.h ../ArgList.h ../AssociatedData.h ../Atom.h ../AtomMask.h ../BaseIOtype.h ../Box.h ../CharMask.h ../Constants.h ../CoordinateInfo.h ../CpptrajFile.h ../CpptrajStdio.h ../DataFile.h ../DataFileList.h ../DataSet.h ../DataSetList.h ../DataSet_Coords.h ../DataSet_Coords_REF.h ../Dimension.h ../DispatchObject.h ../FileIO.h ../FileName.h ../FileTypes.h ../Frame.h ../MaskToken.h ../Matrix_3x3.h ../MetaData.h ../ModXNA_Info.h ../Molecule.h ../NameType.h ../Parallel.h ../ParameterTypes.h ../Parm/../AtomType.h ../Parm/../CmapParmHolder.h ../Parm/../Constants.h ../Parm/../FileName.h ../Parm/../NameType.h ../Parm/../ParameterTypes.h ../Parm/../Parm/ParmEnum.h ../Parm/../TypeNameHolder.h ../Parm/DihedralParmHolder.h ../Parm/ImproperParmHolder.h ../Parm/ParameterSet.h ../Parm/ParmEnum.h ../Parm/ParmHolder.h ../Range.h ../ReferenceFrame.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../SymbolExporting.h ../TextFormat.h ../Timer.h ../Topology.h ../Unit.h ../Vec3.h Solvate.h diff --git a/src/Structure/structurefiles b/src/Structure/structurefiles index 9ac0f07c5f..ea2949bf19 100644 --- a/src/Structure/structurefiles +++ b/src/Structure/structurefiles @@ -12,6 +12,7 @@ STRUCTURE_SOURCES= \ InternalCoords.cpp \ LeastSquaresPlane.cpp \ MetalCenterFinder.cpp \ + Model.cpp \ OldBuilder.cpp \ PdbCleaner.cpp \ RingFinder.cpp \ diff --git a/src/cpptrajdepend b/src/cpptrajdepend index 6e432c357d..1480bf2083 100644 --- a/src/cpptrajdepend +++ b/src/cpptrajdepend @@ -499,7 +499,8 @@ Structure/HisProt.o : Structure/HisProt.cpp ArgList.h Atom.h AtomMask.h Box.h Co Structure/InternalCoords.o : Structure/InternalCoords.cpp Atom.h AtomMask.h Box.h Constants.h CoordinateInfo.h CpptrajStdio.h FileName.h Frame.h MaskToken.h Matrix_3x3.h ModXNA_Info.h Molecule.h NameType.h Parallel.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h Structure/InternalCoords.h SymbolExporting.h Topology.h Unit.h Vec3.h Structure/LeastSquaresPlane.o : Structure/LeastSquaresPlane.cpp Atom.h AtomMask.h Box.h Constants.h CoordinateInfo.h Frame.h MaskToken.h Matrix_3x3.h Molecule.h NameType.h Parallel.h ReplicaDimArray.h Residue.h Segment.h Structure/LeastSquaresPlane.h SymbolExporting.h Unit.h Vec3.h Structure/MetalCenterFinder.o : Structure/MetalCenterFinder.cpp ArgList.h Atom.h AtomMask.h Box.h Constants.h CoordinateInfo.h CpptrajStdio.h DistRoutines.h FileName.h Frame.h ImageOption.h MaskToken.h Matrix_3x3.h ModXNA_Info.h Molecule.h NameType.h Parallel.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h Structure/MetalCenterFinder.h SymbolExporting.h Topology.h Unit.h Vec3.h -Structure/OldBuilder.o : Structure/OldBuilder.cpp Atom.h AtomMask.h Box.h Constants.h CoordinateInfo.h CpptrajStdio.h FileName.h Frame.h MaskToken.h Matrix_3x3.h ModXNA_Info.h Molecule.h NameType.h Parallel.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h Structure/Chirality.h Structure/InternalCoords.h Structure/OldBuilder.h Structure/StructureEnum.h Structure/Zmatrix.h SymbolExporting.h Topology.h Unit.h Vec3.h +Structure/Model.o : Structure/Model.cpp Atom.h AtomMask.h Box.h Constants.h CoordinateInfo.h CpptrajStdio.h FileName.h Frame.h MaskToken.h Matrix_3x3.h ModXNA_Info.h Molecule.h NameType.h Parallel.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h Structure/BuildAtom.h Structure/Model.h Structure/StructureEnum.h SymbolExporting.h Topology.h TorsionRoutines.h Unit.h Vec3.h +Structure/OldBuilder.o : Structure/OldBuilder.cpp Atom.h AtomMask.h Box.h Constants.h CoordinateInfo.h CpptrajStdio.h FileName.h Frame.h MaskToken.h Matrix_3x3.h ModXNA_Info.h Molecule.h NameType.h Parallel.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h Structure/BuildAtom.h Structure/Chirality.h Structure/InternalCoords.h Structure/OldBuilder.h Structure/StructureEnum.h Structure/Zmatrix.h SymbolExporting.h Topology.h Unit.h Vec3.h Structure/PdbCleaner.o : Structure/PdbCleaner.cpp ArgList.h Atom.h AtomMask.h Box.h Constants.h CoordinateInfo.h CpptrajStdio.h FileName.h Frame.h MaskToken.h Matrix_3x3.h ModXNA_Info.h Molecule.h NameType.h Parallel.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h Structure/PdbCleaner.h SymbolExporting.h Topology.h Unit.h Vec3.h Structure/RingFinder.o : Structure/RingFinder.cpp Atom.h AtomMask.h Box.h CharMask.h Constants.h CoordinateInfo.h CpptrajStdio.h FileName.h Frame.h MaskToken.h Matrix_3x3.h ModXNA_Info.h Molecule.h NameType.h Parallel.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h Structure/RingFinder.h SymbolExporting.h Topology.h Unit.h Vec3.h Structure/Solvate.o : Structure/Solvate.cpp Action.h ActionState.h Action_AutoImage.h ArgList.h AssociatedData.h Atom.h AtomMask.h BaseIOtype.h Box.h CharMask.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h DispatchObject.h FileIO.h FileName.h FileTypes.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h ModXNA_Info.h Molecule.h NameType.h Parallel.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h Structure/../Parm/../AtomType.h Structure/../Parm/../CmapParmHolder.h Structure/../Parm/../Constants.h Structure/../Parm/../FileName.h Structure/../Parm/../NameType.h Structure/../Parm/../ParameterTypes.h Structure/../Parm/../Parm/ParmEnum.h Structure/../Parm/../TypeNameHolder.h Structure/../Parm/DihedralParmHolder.h Structure/../Parm/ImproperParmHolder.h Structure/../Parm/ParameterSet.h Structure/../Parm/ParmEnum.h Structure/../Parm/ParmHolder.h Structure/Solvate.h SymbolExporting.h TextFormat.h Timer.h Topology.h Unit.h Vec3.h From a8922aab31b1d1fc645b89a18ee0600380faf659 Mon Sep 17 00:00:00 2001 From: "Daniel R. Roe" Date: Thu, 12 Mar 2026 08:37:39 -0400 Subject: [PATCH 07/19] Add old routine back to Zmatrix for modXNA --- src/Structure/Zmatrix.cpp | 207 ++++++++++++++++++++++++++++++++++ src/Structure/Zmatrix.h | 5 + src/Structure/structuredepend | 2 +- src/cpptrajdepend | 2 +- 4 files changed, 214 insertions(+), 2 deletions(-) diff --git a/src/Structure/Zmatrix.cpp b/src/Structure/Zmatrix.cpp index 2d2dab8ad3..fbca3e7493 100644 --- a/src/Structure/Zmatrix.cpp +++ b/src/Structure/Zmatrix.cpp @@ -10,6 +10,8 @@ #include "../DistRoutines.h" #include "../Topology.h" #include "../TorsionRoutines.h" +#include "BuildAtom.h" // TODO needed for modXNA +#include "Model.h" // TODO needed for modXNA using namespace Cpptraj::Structure; @@ -1411,3 +1413,208 @@ int Zmatrix::SetToFrame(Frame& frameOut, Barray& hasPosition) const { */ return 0; } + +// ============================================================================= +/** Given two bonded atoms A and B, where B has a depth of at least 2 + * (i.e., it is possible to have B be atom J where we can form J-K-L), + * set up a complete set of internal coordinates involving A and B in the + * direction of atom A. This means all internal coordinates with A and B + * as I and J (should be only 1), as J and K, and as K and L. + * TODO This routine is included for backwards compatibility with modXNA. + */ +int Zmatrix::SetupICsAroundBond(int atA, int atB, Frame const& frameIn, Topology const& topIn, + std::vector const& atomPositionKnown, + BuildAtom const& AtomA, BuildAtom const& AtomB) +{ + if (debug_ > 0) + mprintf("DEBUG: SetupICsAroundBond: atA= %s (%i) atB= %s (%i)\n", + topIn.AtomMaskName(atA).c_str(), atA+1, + topIn.AtomMaskName(atB).c_str(), atB+1); + IC_.clear(); + + Barray hasIC( topIn.Natom(), false ); + unsigned int nHasIC = 0; + // Mark known atoms as already having IC + for (std::vector::const_iterator it = atomPositionKnown.begin(); + it != atomPositionKnown.end(); ++it) + { + if (*it) MARK( it - atomPositionKnown.begin(), hasIC, nHasIC ); + } + + // First, make sure atom B as a bond depth of at least 2. + // Choose K and L atoms given atA is I and atB is J. + Atom const& AJ = topIn[atB]; + typedef std::pair Apair; + std::vector KLpairs; + for (Atom::bond_iterator kat = AJ.bondbegin(); kat != AJ.bondend(); ++kat) + { + if (*kat != atA) { + //mprintf("DEBUG: kat= %s\n", topIn.AtomMaskName(*kat).c_str()); + Atom const& AK = topIn[*kat]; + for (Atom::bond_iterator lat = AK.bondbegin(); lat != AK.bondend(); ++lat) + { + if (*lat != atB && *lat != atA) { + //mprintf("DEBUG: lat= %s\n", topIn.AtomMaskName(*lat).c_str()); + KLpairs.push_back( Apair(*kat, *lat) ); + } + } + } + } + if (debug_ > 0) { + for (std::vector::const_iterator it = KLpairs.begin(); + it != KLpairs.end(); ++it) + mprintf("DEBUG:\t\tKL pair %s - %s\n", topIn.AtomMaskName(it->first).c_str(), + topIn.AtomMaskName(it->second).c_str()); + } + if (KLpairs.empty()) { + mprinterr("Error: SetFromFrameAroundBond(): Could not find an atom pair bonded to atom %s\n", + topIn.AtomMaskName(atB).c_str()); + return 1; + } + // TODO be smarter about how K and L are selected? + double maxMass = topIn[KLpairs[0].first].Mass() + topIn[KLpairs[0].second].Mass(); + unsigned int maxIdx = 0; + for (unsigned int idx = 1; idx < KLpairs.size(); idx++) { + double sumMass = topIn[KLpairs[idx].first].Mass() + topIn[KLpairs[idx].second].Mass(); + if (sumMass > maxMass) { + maxMass = sumMass; + maxIdx = idx; + } + } + int atk0 = KLpairs[maxIdx].first; + int atl0 = KLpairs[maxIdx].second; + int modelDebug = 0; + if (debug_ > 0) { + mprintf("DEBUG: Chosen KL pair: %s - %s\n",topIn.AtomMaskName(atk0).c_str(), + topIn.AtomMaskName(atl0).c_str()); + modelDebug = debug_ - 1; + } + // ---- I J: Set dist, theta, phi for atA atB K L internal coord --- + if (debug_ > 0) + mprintf("DEBUG: IC (i j) %i - %i - %i - %i\n", atA+1, atB+1, atk0+1, atl0+1); + double newDist = Atom::GetBondLength( topIn[atA].Element(), topIn[atB].Element() ); + if (debug_ > 0) mprintf("DEBUG:\t\tnewDist= %g\n", newDist); + double newTheta = 0; + if (Cpptraj::Structure::Model::AssignTheta(newTheta, atA, atB, atk0, topIn, frameIn, atomPositionKnown, modelDebug)) { + mprinterr("Error: theta (i j) assignment failed.\n"); + return 1; + } + if (debug_ > 0) mprintf("DEBUG:\t\tnewTheta = %g\n", newTheta*Constants::RADDEG); + double newPhi = 0; + if (Cpptraj::Structure::Model::AssignPhi(newPhi, atA, atB, atk0, atl0, topIn, frameIn, + atomPositionKnown, AtomB, modelDebug)) + { + mprinterr("Error: phi (i j) assignment failed.\n"); + return 1; + } + if (debug_ > 0) mprintf("DEBUG:\t\tnewPhi = %g\n", newPhi*Constants::RADDEG); + IC_.push_back(InternalCoords( atA, atB, atk0, atl0, newDist, newTheta*Constants::RADDEG, newPhi*Constants::RADDEG )); + if (debug_ > 0) { + mprintf("DEBUG: MODEL I J IC: "); + IC_.back().printIC(topIn); + } + MARK( atA, hasIC, nHasIC ); + // ----- J K: Set up ICs for X atA atB K --------------------------- + Atom const& AJ1 = topIn[atA]; + int ati = -1; + //Atom const& AK1 = topIn[atB]; + //Atom const& AL1 = topIn[atk0]; + for (Atom::bond_iterator iat = AJ1.bondbegin(); iat != AJ1.bondend(); ++iat) + { + if (*iat != atB) { + if (ati == -1) ati = *iat; + // Use existing dist + newDist = sqrt( DIST2_NoImage(frameIn.XYZ(*iat), frameIn.XYZ(atA)) ); + // Set theta for I atA atB + newTheta = 0; + if (Cpptraj::Structure::Model::AssignTheta(newTheta, *iat, atA, atB, topIn, frameIn, atomPositionKnown, modelDebug)) { + mprinterr("Error: theta (j k) assignment failed.\n"); + return 1; + } + if (debug_ > 0) + mprintf("DEBUG:\t\tnewTheta = %g\n", newTheta*Constants::RADDEG); + // Set phi for I atA atB K + newPhi = 0; + if (Cpptraj::Structure::Model::AssignPhi(newPhi, *iat, atA, atB, atk0, topIn, frameIn, + atomPositionKnown, AtomA, modelDebug)) + { + mprinterr("Error: phi (j k) assignment failed.\n"); + return 1; + } + if (debug_ > 0) + mprintf("DEBUG:\t\tnewPhi = %g\n", newPhi*Constants::RADDEG); + IC_.push_back(InternalCoords( *iat, atA, atB, atk0, newDist, newTheta*Constants::RADDEG, newPhi*Constants::RADDEG )); + if (debug_ > 0) { + mprintf("DEBUG: MODEL J K IC: "); + IC_.back().printIC(topIn); + } + MARK( *iat, hasIC, nHasIC ); + // ----- K L: Set up ICs for X iat atA atB --------------------- + /*Atom const& AJ2 = topIn[*iat]; + for (Atom::bond_iterator i2at = AJ2.bondbegin(); i2at != AJ2.bondend(); ++i2at) + { + if (*i2at != atA && *i2at != atB && !hasIC[*i2at]) { + // Use existing dist and theta + newDist = sqrt( DIST2_NoImage(frameIn.XYZ(*i2at), frameIn.XYZ(*iat)) ); + newTheta = CalcAngle( frameIn.XYZ(*i2at), frameIn.XYZ(*iat), frameIn.XYZ(atA) ); + // Set phi for X iat atA atB + newPhi = 0; + if (Cpptraj::Structure::Model::AssignPhi(newPhi, *i2at, *iat, atA, atB, topIn, frameIn, atomPositionKnown, atomChirality)) { + mprinterr("Error: phi (k l) assignment failed.\n"); + return 1; + } + mprintf("DEBUG:\t\tnewPhi = %g\n", newPhi*Constants::RADDEG); + IC_.push_back(InternalCoords( *i2at, *iat, atA, atB, newDist, newTheta*Constants::RADDEG, newPhi*Constants::RADDEG )); + mprintf("DEBUG: MODEL K L IC: "); + IC_.back().printIC(topIn); + MARK( *i2at, hasIC, nHasIC ); + // Trace from atA *iat *i2at outwards + ToTrace.push_back(atA); + ToTrace.push_back(*iat); + ToTrace.push_back(*i2at); + //if (traceMol(atA, *iat, *i2at, frameIn, topIn, topIn.Natom(), nHasIC, hasIC)) return 1; + } + } */ + } + } + // Handle remaining atoms. + if (AJ1.Nbonds() > 1) { + if (AJ1.Nbonds() == 2) { + if (debug_ > 0) mprintf("DEBUG: 2 bonds to %s.\n", topIn.AtomMaskName(atA).c_str()); + if (traceMol(atB, atA, ati, frameIn, topIn, topIn.Natom(), nHasIC, hasIC)) + return 1; + } else { + // 3 or more bonds + std::vector const& priority = AtomA.Priority(); + int at0 = -1; + int at1 = -1; + std::vector remainingAtoms; + if (debug_ > 0) mprintf("DEBUG: %i bonds to %s\n", AJ1.Nbonds(), topIn.AtomMaskName(atA).c_str()); + for (std::vector::const_iterator it = priority.begin(); it != priority.end(); ++it) { + if (*it != atB) { + if (debug_ > 0) mprintf("DEBUG:\t\t%s\n", topIn.AtomMaskName(*it).c_str()); + if (at0 == -1) + at0 = *it; + else if (at1 == -1) + at1 = *it; + else + remainingAtoms.push_back( *it ); + } + } + // at0 atA at1 + if (traceMol(at1, atA, at0, frameIn, topIn, topIn.Natom(), nHasIC, hasIC)) + return 1; + // at1 atA, at0 + if (traceMol(at0, atA, at1, frameIn, topIn, topIn.Natom(), nHasIC, hasIC)) + return 1; + // Remaining atoms. + for (std::vector::const_iterator it = remainingAtoms.begin(); it != remainingAtoms.end(); ++it) { + if (traceMol(at0, atA, *it, frameIn, topIn, topIn.Natom(), nHasIC, hasIC)) + return 1; + } + } + } + + return 0; +} + diff --git a/src/Structure/Zmatrix.h b/src/Structure/Zmatrix.h index cd11068403..c33b7cf3f9 100644 --- a/src/Structure/Zmatrix.h +++ b/src/Structure/Zmatrix.h @@ -7,6 +7,7 @@ class Topology; class Molecule; namespace Cpptraj { namespace Structure { +class BuildAtom; // TODO needed for modXNA /// Hold internal coordinates for a system. class Zmatrix { typedef std::vector ICarray; @@ -84,6 +85,10 @@ class Zmatrix { static Vec3 AtomIposition(Vec3 const&, Vec3 const&, Vec3 const&, double, double, double); /// \return XYZ position of atom I for given internal coordinate static Vec3 AtomIposition(InternalCoords const&, Frame const&); + + /// Get internal coordinates around bond in one direction. TODO for modXNA + int SetupICsAroundBond(int, int, Frame const&, Topology const&, + std::vector const&, BuildAtom const&, BuildAtom const&); private: typedef std::vector Iarray; /// Set seeds as 3 consecutive atoms with known positions diff --git a/src/Structure/structuredepend b/src/Structure/structuredepend index f42ee41234..219597caff 100644 --- a/src/Structure/structuredepend +++ b/src/Structure/structuredepend @@ -21,4 +21,4 @@ Sugar.o : Sugar.cpp ../Atom.h ../AtomMask.h ../Box.h ../Constants.h ../Coordinat SugarBuilder.o : SugarBuilder.cpp ../ArgList.h ../Atom.h ../AtomMap.h ../AtomMask.h ../Box.h ../CharMask.h ../Constants.h ../CoordinateInfo.h ../CpptrajFile.h ../CpptrajStdio.h ../DistRoutines.h ../FileIO.h ../FileName.h ../Frame.h ../ImageOption.h ../MapAtom.h ../MaskToken.h ../Matrix_3x3.h ../ModXNA_Info.h ../Molecule.h ../NameType.h ../Parallel.h ../ParameterTypes.h ../Range.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../SymbolExporting.h ../Topology.h ../TorsionRoutines.h ../Unit.h ../Vec3.h Chirality.h FunctionalGroup.h FxnGroupBuilder.h LinkAtom.h ResStatArray.h StructureEnum.h StructureRoutines.h Sugar.h SugarBuilder.h SugarLinkAtoms.h SugarToken.h SugarLinkAtoms.o : SugarLinkAtoms.cpp ../Atom.h ../AtomMask.h ../Box.h ../Constants.h ../CoordinateInfo.h ../CpptrajStdio.h ../FileName.h ../Frame.h ../MaskToken.h ../Matrix_3x3.h ../ModXNA_Info.h ../Molecule.h ../NameType.h ../Parallel.h ../ParameterTypes.h ../Range.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../StringRoutines.h ../SymbolExporting.h ../Topology.h ../Unit.h ../Vec3.h LinkAtom.h SugarLinkAtoms.h SugarToken.o : SugarToken.cpp ../ArgList.h ../CpptrajStdio.h SugarToken.h -Zmatrix.o : Zmatrix.cpp ../Atom.h ../AtomMask.h ../Box.h ../Constants.h ../CoordinateInfo.h ../CpptrajStdio.h ../DistRoutines.h ../FileName.h ../Frame.h ../ImageOption.h ../MaskToken.h ../Matrix_3x3.h ../ModXNA_Info.h ../Molecule.h ../NameType.h ../Parallel.h ../ParameterTypes.h ../Range.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../SymbolExporting.h ../Topology.h ../TorsionRoutines.h ../Unit.h ../Vec3.h GenerateConnectivityArrays.h InternalCoords.h Zmatrix.h +Zmatrix.o : Zmatrix.cpp ../Atom.h ../AtomMask.h ../Box.h ../Constants.h ../CoordinateInfo.h ../CpptrajStdio.h ../DistRoutines.h ../FileName.h ../Frame.h ../ImageOption.h ../MaskToken.h ../Matrix_3x3.h ../ModXNA_Info.h ../Molecule.h ../NameType.h ../Parallel.h ../ParameterTypes.h ../Range.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../SymbolExporting.h ../Topology.h ../TorsionRoutines.h ../Unit.h ../Vec3.h BuildAtom.h GenerateConnectivityArrays.h InternalCoords.h Model.h StructureEnum.h Zmatrix.h diff --git a/src/cpptrajdepend b/src/cpptrajdepend index 1480bf2083..f19cc0d14b 100644 --- a/src/cpptrajdepend +++ b/src/cpptrajdepend @@ -510,7 +510,7 @@ Structure/Sugar.o : Structure/Sugar.cpp Atom.h AtomMask.h Box.h Constants.h Coor Structure/SugarBuilder.o : Structure/SugarBuilder.cpp ArgList.h Atom.h AtomMap.h AtomMask.h Box.h CharMask.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DistRoutines.h FileIO.h FileName.h Frame.h ImageOption.h MapAtom.h MaskToken.h Matrix_3x3.h ModXNA_Info.h Molecule.h NameType.h Parallel.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h Structure/Chirality.h Structure/FunctionalGroup.h Structure/FxnGroupBuilder.h Structure/LinkAtom.h Structure/ResStatArray.h Structure/StructureEnum.h Structure/StructureRoutines.h Structure/Sugar.h Structure/SugarBuilder.h Structure/SugarLinkAtoms.h Structure/SugarToken.h SymbolExporting.h Topology.h TorsionRoutines.h Unit.h Vec3.h Structure/SugarLinkAtoms.o : Structure/SugarLinkAtoms.cpp Atom.h AtomMask.h Box.h Constants.h CoordinateInfo.h CpptrajStdio.h FileName.h Frame.h MaskToken.h Matrix_3x3.h ModXNA_Info.h Molecule.h NameType.h Parallel.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h StringRoutines.h Structure/LinkAtom.h Structure/SugarLinkAtoms.h SymbolExporting.h Topology.h Unit.h Vec3.h Structure/SugarToken.o : Structure/SugarToken.cpp ArgList.h CpptrajStdio.h Structure/SugarToken.h -Structure/Zmatrix.o : Structure/Zmatrix.cpp Atom.h AtomMask.h Box.h Constants.h CoordinateInfo.h CpptrajStdio.h DistRoutines.h FileName.h Frame.h ImageOption.h MaskToken.h Matrix_3x3.h ModXNA_Info.h Molecule.h NameType.h Parallel.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h Structure/GenerateConnectivityArrays.h Structure/InternalCoords.h Structure/Zmatrix.h SymbolExporting.h Topology.h TorsionRoutines.h Unit.h Vec3.h +Structure/Zmatrix.o : Structure/Zmatrix.cpp Atom.h AtomMask.h Box.h Constants.h CoordinateInfo.h CpptrajStdio.h DistRoutines.h FileName.h Frame.h ImageOption.h MaskToken.h Matrix_3x3.h ModXNA_Info.h Molecule.h NameType.h Parallel.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h Structure/BuildAtom.h Structure/GenerateConnectivityArrays.h Structure/InternalCoords.h Structure/Model.h Structure/StructureEnum.h Structure/Zmatrix.h SymbolExporting.h Topology.h TorsionRoutines.h Unit.h Vec3.h StructureCheck.o : StructureCheck.cpp Atom.h AtomMask.h Box.h CharMask.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DistRoutines.h ExclusionArray.h FileIO.h FileName.h Frame.h ImageOption.h MaskToken.h Matrix_3x3.h ModXNA_Info.h Molecule.h NameType.h PairList.h Parallel.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h Structure/LeastSquaresPlane.h Structure/RingFinder.h StructureCheck.h SymbolExporting.h Timer.h Topology.h Unit.h Vec3.h StructureMapper.o : StructureMapper.cpp AssociatedData.h Atom.h AtomMap.h AtomMask.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataSet.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h FileIO.h FileName.h Frame.h MapAtom.h MaskToken.h Matrix_3x3.h MetaData.h ModXNA_Info.h Molecule.h NameType.h Parallel.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h Structure/Chirality.h Structure/StructureEnum.h StructureMapper.h SymbolExporting.h TextFormat.h Topology.h TorsionRoutines.h Unit.h Vec3.h SymmetricRmsdCalc.o : SymmetricRmsdCalc.cpp ArrayIterator.h Atom.h AtomMap.h AtomMask.h Box.h Constants.h CoordinateInfo.h CpptrajStdio.h DistRoutines.h FileName.h Frame.h Hungarian.h ImageOption.h MapAtom.h MaskToken.h Matrix.h Matrix_3x3.h ModXNA_Info.h Molecule.h NameType.h Parallel.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h SymmetricRmsdCalc.h Topology.h Unit.h Vec3.h From d8064b26a53dace28d0f38b38276dd6b1d42565d Mon Sep 17 00:00:00 2001 From: "Daniel R. Roe" Date: Thu, 12 Mar 2026 09:16:51 -0400 Subject: [PATCH 08/19] Start adding the old sequence code back for modXNA --- src/Exec_Sequence.cpp | 145 ++++++++++++++++++++++++++++++++++++++++++ src/Exec_Sequence.h | 5 ++ src/cpptrajdepend | 2 +- 3 files changed, 151 insertions(+), 1 deletion(-) diff --git a/src/Exec_Sequence.cpp b/src/Exec_Sequence.cpp index 775dbe0819..74851ec544 100644 --- a/src/Exec_Sequence.cpp +++ b/src/Exec_Sequence.cpp @@ -5,8 +5,153 @@ #include "Parm/AssignParams.h" #include "Parm/GB_Params.h" #include "Structure/Builder.h" +#include "Structure/OldBuilder.h" // TODO needed for modXNA #include "Structure/Creator.h" +/** Get units in the sequence. */ +int Exec_Sequence::get_units(Uarray& Units, + std::string& title, + int& total_natom, + Sarray const& main_sequence, + Cpptraj::Structure::Creator const& creator) +const +{ + // First, get all units in order. + Units.clear(); + Units.reserve( main_sequence.size() ); + + total_natom = 0; + + for (Sarray::const_iterator it = main_sequence.begin(); it != main_sequence.end(); ++it) + { + DataSet_Coords* unit = creator.IdTemplateFromName( *it ); + + if (unit == 0) { + mprinterr("Error: Unit '%s' not found.\n", it->c_str()); + return 1; + } + if (unit->Size() < 1) { + mprinterr("Error: Unit '%s' is empty.\n", unit->legend()); + return 1; + } + if (unit->Size() > 1) { + mprintf("Warning: Unit '%s' has more than 1 frame. Only using first frame.\n", unit->legend()); + } + Units.push_back( unit ); + // Use the first unit name as title to match leap behavior + if (title.empty()) + title = *it; + total_natom += unit->Top().Natom(); + } // END loop over sequence + mprintf("\tFound %zu units.\n", Units.size()); + if (Units.empty()) { + mprinterr("Error: No units.\n"); + return 1; + } + return 0; +} + +/** Old routine for building the specified sequence. TODO needed for modXNA */ +int Exec_Sequence::old_generate_sequence(DataSet_Coords* OUT, + Sarray const& main_sequence, + Cpptraj::Structure::Creator const& creator) +const +{ + // First, get all units in order. + typedef std::vector Uarray; + Uarray Units; + Units.reserve( main_sequence.size() ); + typedef std::vector Iarray; + Iarray connectAt0, connectAt1; + connectAt0.reserve( Units.size() ); + connectAt1.reserve( Units.size() ); + int total_natom = 0; + + for (Sarray::const_iterator it = main_sequence.begin(); it != main_sequence.end(); ++it) + { + DataSet_Coords* unit = creator.IdTemplateFromName( *it ); + + if (unit == 0) { + mprinterr("Error: Unit '%s' not found.\n", it->c_str()); + return 1; + } + if (unit->Size() < 1) { + mprinterr("Error: Unit '%s' is empty.\n", unit->legend()); + return 1; + } + if (unit->Size() > 1) { + mprintf("Warning: Unit '%s' has more than 1 frame. Only using first frame.\n", unit->legend()); + } + + // Needs to have connect associated data + AssociatedData* ad = unit->GetAssociatedData(AssociatedData::CONNECT); + if (ad == 0) { + mprinterr("Error: Unit '%s' does not have CONNECT data.\n", unit->legend()); + return 1; + } + AssociatedData_Connect const& C = static_cast( *ad ); + if (C.NconnectAtoms() < 2) { + mprinterr("Error: Not enough connect atoms in unit '%s'\n", unit->legend()); + return 1; + } + // Update connect atom 1 indices based on their position in the sequence. + // Do not update connect atom 0 indices since they will not yet be connected. + connectAt0.push_back( C.Connect()[0] ); + connectAt1.push_back( C.Connect()[1] + total_natom ); + Units.push_back( unit ); + total_natom += unit->Top().Natom(); + } // END loop over sequence + mprintf("\tFound %zu units.\n", Units.size()); + if (Units.empty()) { + mprinterr("Error: No units.\n"); + return 1; + } + for (unsigned int idx = 0; idx < Units.size(); idx++) + mprintf("\tUnit %s HEAD %i TAIL %i\n", Units[idx]->legend(), connectAt0[idx]+1, connectAt1[idx]+1); + + Topology combinedTop; + combinedTop.SetDebug( debug_ ); + combinedTop.SetParmName( OUT->Meta().Name(), FileName() ); + combinedTop.AppendTop( Units.front()->Top() ); + //combinedTop.SetParmBox( Units // TODO + combinedTop.Brief("Sequence topology:"); + + Frame CombinedFrame = Units.front()->AllocateFrame(); + Units.front()->GetFrame(0, CombinedFrame); + + + using namespace Cpptraj::Structure; + OldBuilder builder; + for (unsigned int idx = 1; idx < Units.size(); idx++) { + mprintf("\tConnect %s atom %i to %s atom %i\n", + Units[idx-1]->legend(), connectAt1[idx-1]+1, + Units[idx]->legend(), connectAt0[idx] +1); + Frame mol1frm = Units[idx]->AllocateFrame(); + Units[idx]->GetFrame(0, mol1frm); + int bondat0 = connectAt1[idx-1]; + int bondat1 = connectAt0[idx]; + if (bondat0 < 0 || bondat1 < 0) { + mprinterr("Error: Invalid connect atom(s) between %s atom %i to %s atom %i\n", + Units[idx-1]->legend(), bondat0+1, Units[idx]->legend(), bondat1+1); + return 1; + } + if (builder.Combine( combinedTop, CombinedFrame, Units[idx]->Top(), mol1frm, + connectAt1[idx-1], connectAt0[idx] )) { + mprinterr("Error: Sequence combine between units %u %s and %u %s failed.\n", + idx, Units[idx-1]->legend(), idx+1, Units[idx]->legend()); + return 1; + } + } + + // FIXME TODO common setup? + + OUT->CoordsSetup(combinedTop, CombinedFrame.CoordsInfo()); + OUT->AddFrame( CombinedFrame ); + + return 0; +} + + /** Generate and build the specified sequence. */ int Exec_Sequence::generate_sequence(DataSet_Coords* OUT, DataSetList const& DSL, diff --git a/src/Exec_Sequence.h b/src/Exec_Sequence.h index 12c71db23b..db6127c29f 100644 --- a/src/Exec_Sequence.h +++ b/src/Exec_Sequence.h @@ -15,6 +15,11 @@ class Exec_Sequence : public Exec { RetType Execute(CpptrajState&, ArgList&); private: typedef std::vector Sarray; + typedef std::vector Uarray; + + int get_units(Uarray&, std::string&, int&, Sarray const&, Cpptraj::Structure::Creator const&) const; + + int old_generate_sequence(DataSet_Coords*, Sarray const&, Cpptraj::Structure::Creator const&) const; int generate_sequence(DataSet_Coords*, DataSetList const&, Sarray const&, Cpptraj::Structure::Creator const&) const; diff --git a/src/cpptrajdepend b/src/cpptrajdepend index f19cc0d14b..225192cf30 100644 --- a/src/cpptrajdepend +++ b/src/cpptrajdepend @@ -364,7 +364,7 @@ Exec_ReadInput.o : Exec_ReadInput.cpp Action.h ActionList.h ActionState.h Analys Exec_RotateDihedral.o : Exec_RotateDihedral.cpp Action.h ActionList.h ActionState.h Analysis.h AnalysisList.h AnalysisState.h ArgList.h AssociatedData.h Atom.h AtomMask.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajState.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h DihedralSearch.h Dimension.h DispatchObject.h EnsembleIn.h EnsembleOutList.h Exec.h Exec_RotateDihedral.h FileIO.h FileName.h FileTypes.h Frame.h FramePtrArray.h InputTrajCommon.h MaskToken.h Matrix_3x3.h MetaData.h ModXNA_Info.h Molecule.h NameType.h Parallel.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h ReplicaInfo.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TorsionRoutines.h TrajFrameCounter.h Trajin.h TrajinList.h TrajoutList.h Unit.h Vec3.h Exec_RunAnalysis.o : Exec_RunAnalysis.cpp Action.h ActionList.h ActionState.h Analysis.h AnalysisList.h AnalysisState.h ArgList.h AssociatedData.h Atom.h AtomMask.h BaseIOtype.h Box.h Cmd.h CmdList.h Command.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajState.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h DispatchObject.h EnsembleIn.h EnsembleOutList.h Exec.h Exec_RunAnalysis.h FileIO.h FileName.h FileTypes.h Frame.h FramePtrArray.h InputTrajCommon.h MaskToken.h Matrix_3x3.h MetaData.h ModXNA_Info.h Molecule.h NameType.h Parallel.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h ReplicaInfo.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TrajFrameCounter.h Trajin.h TrajinList.h TrajoutList.h Unit.h Vec3.h Exec_ScaleDihedralK.o : Exec_ScaleDihedralK.cpp Action.h ActionList.h ActionState.h Analysis.h AnalysisList.h AnalysisState.h ArgList.h AssociatedData.h Atom.h AtomMask.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajState.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h DispatchObject.h EnsembleIn.h EnsembleOutList.h Exec.h Exec_ScaleDihedralK.h FileIO.h FileName.h FileTypes.h Frame.h FramePtrArray.h InputTrajCommon.h MaskToken.h Matrix_3x3.h MetaData.h ModXNA_Info.h Molecule.h NameType.h Parallel.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h ReplicaInfo.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TrajFrameCounter.h Trajin.h TrajinList.h TrajoutList.h Unit.h Vec3.h -Exec_Sequence.o : Exec_Sequence.cpp Action.h ActionList.h ActionState.h Analysis.h AnalysisList.h AnalysisState.h ArgList.h AssociatedData.h AssociatedData_Connect.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h CmapParmHolder.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajState.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_Parameters.h Dimension.h DispatchObject.h EnsembleIn.h EnsembleOutList.h Exec.h Exec_Sequence.h FileIO.h FileName.h FileTypes.h Frame.h FramePtrArray.h InputTrajCommon.h MaskToken.h Matrix_3x3.h MetaData.h ModXNA_Info.h Molecule.h NameType.h Parallel.h ParameterTypes.h Parm/AssignParams.h Parm/DihedralParmHolder.h Parm/GB_Params.h Parm/ImproperParmHolder.h Parm/ParameterSet.h Parm/ParmEnum.h Parm/ParmHolder.h Range.h ReferenceFrame.h ReplicaDimArray.h ReplicaInfo.h Residue.h Segment.h Structure/Builder.h Structure/Creator.h Structure/StructureEnum.h SymbolExporting.h TextFormat.h Timer.h Topology.h TrajFrameCounter.h Trajin.h TrajinList.h TrajoutList.h TypeNameHolder.h Unit.h Vec3.h +Exec_Sequence.o : Exec_Sequence.cpp Action.h ActionList.h ActionState.h Analysis.h AnalysisList.h AnalysisState.h ArgList.h AssociatedData.h AssociatedData_Connect.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h CmapParmHolder.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajState.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_Parameters.h Dimension.h DispatchObject.h EnsembleIn.h EnsembleOutList.h Exec.h Exec_Sequence.h FileIO.h FileName.h FileTypes.h Frame.h FramePtrArray.h InputTrajCommon.h MaskToken.h Matrix_3x3.h MetaData.h ModXNA_Info.h Molecule.h NameType.h Parallel.h ParameterTypes.h Parm/AssignParams.h Parm/DihedralParmHolder.h Parm/GB_Params.h Parm/ImproperParmHolder.h Parm/ParameterSet.h Parm/ParmEnum.h Parm/ParmHolder.h Range.h ReferenceFrame.h ReplicaDimArray.h ReplicaInfo.h Residue.h Segment.h Structure/Builder.h Structure/Creator.h Structure/OldBuilder.h Structure/StructureEnum.h SymbolExporting.h TextFormat.h Timer.h Topology.h TrajFrameCounter.h Trajin.h TrajinList.h TrajoutList.h TypeNameHolder.h Unit.h Vec3.h Exec_SequenceAlign.o : Exec_SequenceAlign.cpp Action.h ActionFrameCounter.h ActionList.h ActionState.h Analysis.h AnalysisList.h AnalysisState.h ArgList.h AssociatedData.h Atom.h AtomMask.h BaseIOtype.h Box.h BufferedLine.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajState.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h DispatchObject.h EnsembleIn.h EnsembleOutList.h Exec.h Exec_SequenceAlign.h FileIO.h FileName.h FileTypes.h Frame.h FramePtrArray.h InputTrajCommon.h MaskToken.h Matrix_3x3.h MetaData.h ModXNA_Info.h Molecule.h NameType.h OutputTrajCommon.h Parallel.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h ReplicaInfo.h Residue.h Segment.h StringRoutines.h SymbolExporting.h TextFormat.h Timer.h Topology.h TrajFrameCounter.h TrajectoryFile.h Trajin.h TrajinList.h TrajoutList.h Trajout_Single.h Unit.h Vec3.h Exec_Set.o : Exec_Set.cpp Action.h ActionList.h ActionState.h Analysis.h AnalysisList.h AnalysisState.h ArgList.h AssociatedData.h Atom.h AtomMask.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajState.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_StringVar.h Dimension.h DispatchObject.h EnsembleIn.h EnsembleOutList.h Exec.h Exec_Set.h FileIO.h FileName.h FileTypes.h Frame.h FramePtrArray.h InputTrajCommon.h MaskToken.h Matrix_3x3.h MetaData.h ModXNA_Info.h Molecule.h NameType.h Parallel.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h ReplicaInfo.h Residue.h Segment.h StringRoutines.h SymbolExporting.h TextFormat.h Timer.h Topology.h TrajFrameCounter.h Trajin.h TrajinList.h TrajoutList.h Unit.h Vec3.h Exec_Show.o : Exec_Show.cpp Action.h ActionList.h ActionState.h Analysis.h AnalysisList.h AnalysisState.h ArgList.h AssociatedData.h Atom.h AtomMask.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajState.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_StringVar.h Dimension.h DispatchObject.h EnsembleIn.h EnsembleOutList.h Exec.h Exec_Show.h FileIO.h FileName.h FileTypes.h Frame.h FramePtrArray.h InputTrajCommon.h MaskToken.h Matrix_3x3.h MetaData.h ModXNA_Info.h Molecule.h NameType.h Parallel.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h ReplicaInfo.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TrajFrameCounter.h Trajin.h TrajinList.h TrajoutList.h Unit.h Vec3.h From 9e813cb891e6143d9200a1d237e522b31fc94c13 Mon Sep 17 00:00:00 2001 From: "Daniel R. Roe" Date: Thu, 12 Mar 2026 09:24:17 -0400 Subject: [PATCH 09/19] Add mode argument. DSL no longer needs to be passed in to the generate sequence function --- src/Exec_Sequence.cpp | 26 ++++++++++++++++++++++++-- src/Exec_Sequence.h | 7 ++++--- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/Exec_Sequence.cpp b/src/Exec_Sequence.cpp index 74851ec544..b21492a46f 100644 --- a/src/Exec_Sequence.cpp +++ b/src/Exec_Sequence.cpp @@ -8,6 +8,9 @@ #include "Structure/OldBuilder.h" // TODO needed for modXNA #include "Structure/Creator.h" +/** CONSTRUCTOR */ +Exec_Sequence::Exec_Sequence() : Exec(COORDS), debug_(0), mode_(UNSPECIFIED) {} + /** Get units in the sequence. */ int Exec_Sequence::get_units(Uarray& Units, std::string& title, @@ -154,7 +157,6 @@ const /** Generate and build the specified sequence. */ int Exec_Sequence::generate_sequence(DataSet_Coords* OUT, - DataSetList const& DSL, Sarray const& main_sequence, Cpptraj::Structure::Creator const& creator) const @@ -392,6 +394,16 @@ Exec::RetType Exec_Sequence::Execute(CpptrajState& State, ArgList& argIn) // Args int verbose = argIn.getKeyInt("verbose", 0); + mode_ = UNSPECIFIED; + std::string modeArg = argIn.GetStringKey("mode"); + if (modeArg == "old") + mode_ = OLD; + else if (modeArg == "new") + mode_ = NEW; + else { + mprinterr("Error: Unrecognized 'mode' argument: %s\n", modeArg.c_str()); + return CpptrajState::ERR; + } // GB radii set. Default to mbondi Cpptraj::Parm::GB_Params gbradii; if (gbradii.Init_GB_Radii(argIn, Cpptraj::Parm::UNKNOWN_GB)) return CpptrajState::ERR; @@ -433,7 +445,17 @@ Exec::RetType Exec_Sequence::Execute(CpptrajState& State, ArgList& argIn) mprintf("\tOutput set name : %s\n", OUT->legend()); // Execute - if (generate_sequence(OUT, State.DSL(), main_sequence, creator)) { + int err = 0; + switch (mode_) { + case UNSPECIFIED : + case NEW: + err = generate_sequence(OUT, main_sequence, creator); + break; + case OLD: + err = old_generate_sequence(OUT, main_sequence, creator); + break; + } + if (err != 0) { mprinterr("Error: Could not generate sequence.\n"); return CpptrajState::ERR; } diff --git a/src/Exec_Sequence.h b/src/Exec_Sequence.h index db6127c29f..ebec31a106 100644 --- a/src/Exec_Sequence.h +++ b/src/Exec_Sequence.h @@ -9,21 +9,22 @@ class Creator; /// Create a molecule from a sequence of units class Exec_Sequence : public Exec { public: - Exec_Sequence() : Exec(COORDS), debug_(0) {} + Exec_Sequence(); void Help() const; DispatchObject* Alloc() const { return (DispatchObject*)new Exec_Sequence(); } RetType Execute(CpptrajState&, ArgList&); private: typedef std::vector Sarray; typedef std::vector Uarray; + enum ModeType { UNSPECIFIED = 0, NEW, OLD }; int get_units(Uarray&, std::string&, int&, Sarray const&, Cpptraj::Structure::Creator const&) const; int old_generate_sequence(DataSet_Coords*, Sarray const&, Cpptraj::Structure::Creator const&) const; - int generate_sequence(DataSet_Coords*, DataSetList const&, - Sarray const&, Cpptraj::Structure::Creator const&) const; + int generate_sequence(DataSet_Coords*, Sarray const&, Cpptraj::Structure::Creator const&) const; int debug_; + ModeType mode_; }; #endif From 0e1645e5133035d0ab202aaab6c088be814e67f7 Mon Sep 17 00:00:00 2001 From: "Daniel R. Roe" Date: Thu, 12 Mar 2026 09:52:46 -0400 Subject: [PATCH 10/19] Only process the arg if it is present --- src/Exec_Sequence.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/Exec_Sequence.cpp b/src/Exec_Sequence.cpp index b21492a46f..1a5e40234d 100644 --- a/src/Exec_Sequence.cpp +++ b/src/Exec_Sequence.cpp @@ -60,6 +60,7 @@ int Exec_Sequence::old_generate_sequence(DataSet_Coords* OUT, Cpptraj::Structure::Creator const& creator) const { + mprintf("\tUsing the old 'sequence' routine compatible with modXNA.\n"); // First, get all units in order. typedef std::vector Uarray; Uarray Units; @@ -396,13 +397,15 @@ Exec::RetType Exec_Sequence::Execute(CpptrajState& State, ArgList& argIn) int verbose = argIn.getKeyInt("verbose", 0); mode_ = UNSPECIFIED; std::string modeArg = argIn.GetStringKey("mode"); - if (modeArg == "old") - mode_ = OLD; - else if (modeArg == "new") - mode_ = NEW; - else { - mprinterr("Error: Unrecognized 'mode' argument: %s\n", modeArg.c_str()); - return CpptrajState::ERR; + if (!modeArg.empty()) { + if (modeArg == "old") + mode_ = OLD; + else if (modeArg == "new") + mode_ = NEW; + else { + mprinterr("Error: Unrecognized 'mode' argument: %s\n", modeArg.c_str()); + return CpptrajState::ERR; + } } // GB radii set. Default to mbondi Cpptraj::Parm::GB_Params gbradii; From a6ab27febd8ed95e0cfa1b8b99e68b2c6acd3ecf Mon Sep 17 00:00:00 2001 From: "Daniel R. Roe" Date: Thu, 12 Mar 2026 10:09:43 -0400 Subject: [PATCH 11/19] To maintain backwards compatibility with modXNA, ensure mol2 files are loaded with default bond REQ parameters --- src/Parm_Mol2.cpp | 4 ++++ src/cpptrajdepend | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Parm_Mol2.cpp b/src/Parm_Mol2.cpp index c32b105a16..b5e90e4403 100644 --- a/src/Parm_Mol2.cpp +++ b/src/Parm_Mol2.cpp @@ -3,6 +3,7 @@ #include "BondSearch.h" #include "CpptrajStdio.h" #include "ModXNA_Info.h" +#include "Parm/Bond_Params.h" // Parm_Mol2::ID_ParmFormat() bool Parm_Mol2::ID_ParmFormat(CpptrajFile& fileIn) { @@ -51,6 +52,9 @@ int Parm_Mol2::ReadParm(FileName const& fname, Topology &parmOut) { bondSearch.FindBonds( parmOut, searchType_, Coords, Offset_, debug_ ); } + // For modXNA backwards-compatibility, generate bond parameters TODO remove + Cpptraj::Parm::GenerateBondParameters(parmOut); + // No box parmOut.SetParmBox( Box() ); diff --git a/src/cpptrajdepend b/src/cpptrajdepend index 225192cf30..053e6367f1 100644 --- a/src/cpptrajdepend +++ b/src/cpptrajdepend @@ -448,7 +448,7 @@ Parm_Amber.o : Parm_Amber.cpp ArgList.h Atom.h AtomMask.h BaseIOtype.h BondSearc Parm_CIF.o : Parm_CIF.cpp ArgList.h Atom.h AtomMask.h BaseIOtype.h BondSearch.h Box.h BufferedLine.h CIFfile.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h FileIO.h FileName.h Frame.h MaskToken.h Matrix_3x3.h ModXNA_Info.h Molecule.h NameType.h Parallel.h ParameterTypes.h ParmIO.h Parm_CIF.h Range.h ReplicaDimArray.h Residue.h Segment.h StringRoutines.h SymbolExporting.h Topology.h Unit.h Vec3.h Parm_CharmmPsf.o : Parm_CharmmPsf.cpp ArgList.h Atom.h AtomMask.h AtomType.h BaseIOtype.h BondSearch.h Box.h BufferedLine.h CharmmParamFile.h CmapParmHolder.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h FileIO.h FileName.h Frame.h MaskToken.h Matrix_3x3.h ModXNA_Info.h Mol.h Molecule.h NameType.h Parallel.h ParameterTypes.h Parm/AssignParams.h Parm/DihedralParmHolder.h Parm/ImproperParmHolder.h Parm/ParameterSet.h Parm/ParmEnum.h Parm/ParmHolder.h ParmIO.h Parm_CharmmPsf.h Range.h ReplicaDimArray.h Residue.h Segment.h StringRoutines.h SymbolExporting.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h Parm_Gromacs.o : Parm_Gromacs.cpp ArgList.h Atom.h AtomMask.h BaseIOtype.h BondSearch.h Box.h BufferedLine.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h FileIO.h FileName.h Frame.h MaskToken.h Matrix_3x3.h ModXNA_Info.h Molecule.h NameType.h Parallel.h ParameterTypes.h ParmIO.h Parm_Gromacs.h Range.h ReplicaDimArray.h Residue.h Segment.h StringRoutines.h SymbolExporting.h Topology.h Unit.h Vec3.h -Parm_Mol2.o : Parm_Mol2.cpp ArgList.h Atom.h AtomMask.h BaseIOtype.h BondSearch.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h FileIO.h FileName.h Frame.h MaskToken.h Matrix_3x3.h ModXNA_Info.h Mol2File.h Molecule.h NameType.h Parallel.h ParameterTypes.h ParmIO.h Parm_Mol2.h Range.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h Topology.h Unit.h Vec3.h +Parm_Mol2.o : Parm_Mol2.cpp ArgList.h Atom.h AtomMask.h BaseIOtype.h BondSearch.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h FileIO.h FileName.h Frame.h MaskToken.h Matrix_3x3.h ModXNA_Info.h Mol2File.h Molecule.h NameType.h Parallel.h ParameterTypes.h Parm/Bond_Params.h ParmIO.h Parm_Mol2.h Range.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h Topology.h Unit.h Vec3.h Parm_PDB.o : Parm_PDB.cpp ArgList.h Atom.h AtomMask.h BaseIOtype.h BondSearch.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h FileIO.h FileName.h Frame.h MaskToken.h Matrix_3x3.h ModXNA_Info.h Molecule.h NameType.h PDBfile.h Parallel.h ParameterTypes.h ParmIO.h Parm_PDB.h Range.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h Timer.h Topology.h Unit.h Vec3.h Parm_SDF.o : Parm_SDF.cpp ArgList.h Atom.h AtomMask.h BaseIOtype.h BondSearch.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h FileIO.h FileName.h Frame.h MaskToken.h Matrix_3x3.h ModXNA_Info.h Molecule.h NameType.h Parallel.h ParameterTypes.h ParmIO.h Parm_SDF.h Range.h ReplicaDimArray.h Residue.h SDFfile.h Segment.h SymbolExporting.h Topology.h Unit.h Vec3.h Parm_Tinker.o : Parm_Tinker.cpp ArgList.h Atom.h AtomMask.h BaseIOtype.h BondSearch.h Box.h BufferedLine.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h FileIO.h FileName.h Frame.h MaskToken.h Matrix_3x3.h ModXNA_Info.h Molecule.h NameType.h Parallel.h ParameterTypes.h ParmIO.h Parm_Tinker.h Range.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TinkerFile.h Topology.h Unit.h Vec3.h From 0771f6d1a84ba22e8cc7e9ce527ec0d86ad4ec65 Mon Sep 17 00:00:00 2001 From: "Daniel R. Roe" Date: Thu, 12 Mar 2026 10:45:05 -0400 Subject: [PATCH 12/19] Ensure modxna metadata is preserved after a strip, and if no title is set for mol2 files write out modxna metadata instead --- src/ModXNA_Info.cpp | 21 +++++++++++++++++++++ src/ModXNA_Info.h | 2 ++ src/Topology.cpp | 3 +++ src/Traj_Mol2File.cpp | 9 +++++++-- 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/ModXNA_Info.cpp b/src/ModXNA_Info.cpp index d08b065f29..526ad2a8c5 100644 --- a/src/ModXNA_Info.cpp +++ b/src/ModXNA_Info.cpp @@ -44,3 +44,24 @@ void ModXNA_Info::PrintModxna() const { printmxna("\tAnchor ", anchor_); printmxna("\tAnchorStrip ", anchorStrip_); } + +/** Generate ModXNA metadata string */ +std::string ModXNA_Info::GenMetadataString() const { + if (fragmentName_.empty()) return std::string(""); + std::string out("modXNA-fragment:" + fragmentName_); + // Base + out.append(":HEAD01:" + head_); + out.append(":HEAD01STRIP:" + headStrip_); + if (!tail_.empty()) { + // BB + out.append(":TAIL01:" + tail_); + out.append(":TAIL01STRIP:" + tailStrip_); + if (!anchor_.empty()) { + // Sugar + out.append(":HEAD03:" + anchor_); + out.append(":HEAD03STRIP:" + anchorStrip_); + } + } + return out; +} + diff --git a/src/ModXNA_Info.h b/src/ModXNA_Info.h index 3b7714163f..73f23eba48 100644 --- a/src/ModXNA_Info.h +++ b/src/ModXNA_Info.h @@ -17,6 +17,8 @@ class ModXNA_Info { bool HasModxna() const { return (!fragmentName_.empty()); } /// Print to stdout void PrintModxna() const; + /// Generate ModXNA metadata string for e.g. writing ModXNA mol2 files + std::string GenMetadataString() const; std::string const& FragmentName() const { return fragmentName_; } std::string const& Head() const { return head_; } diff --git a/src/Topology.cpp b/src/Topology.cpp index e3142ef857..76c75ef1f1 100644 --- a/src/Topology.cpp +++ b/src/Topology.cpp @@ -1932,6 +1932,9 @@ Topology* Topology::ModifyByMap(std::vector const& MapIn, bool setupFullPar // Determine number of extra points newParm->DetermineNumExtraPoints(); + // modXNA + newParm->modxna_ = modxna_; + return newParm; } diff --git a/src/Traj_Mol2File.cpp b/src/Traj_Mol2File.cpp index 98bfbffcd5..4786b82f04 100644 --- a/src/Traj_Mol2File.cpp +++ b/src/Traj_Mol2File.cpp @@ -203,8 +203,13 @@ int Traj_Mol2File::setupTrajout(FileName const& fname, Topology* trajParm, } } // Set Title - if (Title().empty()) - SetTitle("Cpptraj Generated mol2 file."); + if (Title().empty()) { + if (mol2Top_->Modxna().HasModxna()) { + mprintf("\tModXNA data present and no title set; writing ModXNA metadata in title.\n"); + SetTitle(mol2Top_->Modxna().GenMetadataString()); + } else + SetTitle("Cpptraj Generated mol2 file."); + } file_.SetMol2Title( Title() ); // Set up number of bonds file_.SetMol2Nbonds( mol2Top_->Bonds().size() + mol2Top_->BondsH().size() ); From fa97c7a3fe584cb16a46b475377487c83be2c55c Mon Sep 17 00:00:00 2001 From: "Daniel R. Roe" Date: Thu, 12 Mar 2026 10:57:02 -0400 Subject: [PATCH 13/19] Dont do title or natom count when getting units. Report if modxna info is present --- src/Exec_Sequence.cpp | 17 +++++++++-------- src/Exec_Sequence.h | 2 +- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/Exec_Sequence.cpp b/src/Exec_Sequence.cpp index 1a5e40234d..5952cf3b79 100644 --- a/src/Exec_Sequence.cpp +++ b/src/Exec_Sequence.cpp @@ -13,8 +13,6 @@ Exec_Sequence::Exec_Sequence() : Exec(COORDS), debug_(0), mode_(UNSPECIFIED) {} /** Get units in the sequence. */ int Exec_Sequence::get_units(Uarray& Units, - std::string& title, - int& total_natom, Sarray const& main_sequence, Cpptraj::Structure::Creator const& creator) const @@ -23,8 +21,6 @@ const Units.clear(); Units.reserve( main_sequence.size() ); - total_natom = 0; - for (Sarray::const_iterator it = main_sequence.begin(); it != main_sequence.end(); ++it) { DataSet_Coords* unit = creator.IdTemplateFromName( *it ); @@ -40,11 +36,9 @@ const if (unit->Size() > 1) { mprintf("Warning: Unit '%s' has more than 1 frame. Only using first frame.\n", unit->legend()); } + if (unit->Top().Modxna().HasModxna()) + mprintf("\tUnit '%s' has ModXNA info.\n", unit->legend()); Units.push_back( unit ); - // Use the first unit name as title to match leap behavior - if (title.empty()) - title = *it; - total_natom += unit->Top().Natom(); } // END loop over sequence mprintf("\tFound %zu units.\n", Units.size()); if (Units.empty()) { @@ -447,6 +441,13 @@ Exec::RetType Exec_Sequence::Execute(CpptrajState& State, ArgList& argIn) mprintf("\n"); mprintf("\tOutput set name : %s\n", OUT->legend()); + // Get units + Uarray Units; + if ( get_units(Units, main_sequence, creator) ) { + mprinterr("Error: Could not get units.\n"); + return CpptrajState::ERR; + } + // Execute int err = 0; switch (mode_) { diff --git a/src/Exec_Sequence.h b/src/Exec_Sequence.h index ebec31a106..8c7d203b12 100644 --- a/src/Exec_Sequence.h +++ b/src/Exec_Sequence.h @@ -18,7 +18,7 @@ class Exec_Sequence : public Exec { typedef std::vector Uarray; enum ModeType { UNSPECIFIED = 0, NEW, OLD }; - int get_units(Uarray&, std::string&, int&, Sarray const&, Cpptraj::Structure::Creator const&) const; + int get_units(Uarray&, Sarray const&, Cpptraj::Structure::Creator const&) const; int old_generate_sequence(DataSet_Coords*, Sarray const&, Cpptraj::Structure::Creator const&) const; From b57c1692ad36ee4e4432ba680fb7eebc4cadffa3 Mon Sep 17 00:00:00 2001 From: "Daniel R. Roe" Date: Thu, 12 Mar 2026 11:09:05 -0400 Subject: [PATCH 14/19] Pass in unit arrays to the sequence functions --- src/Exec_Sequence.cpp | 63 ++++++++++--------------------------------- src/Exec_Sequence.h | 6 ++--- 2 files changed, 17 insertions(+), 52 deletions(-) diff --git a/src/Exec_Sequence.cpp b/src/Exec_Sequence.cpp index 5952cf3b79..b97c1c0a11 100644 --- a/src/Exec_Sequence.cpp +++ b/src/Exec_Sequence.cpp @@ -49,37 +49,20 @@ const } /** Old routine for building the specified sequence. TODO needed for modXNA */ -int Exec_Sequence::old_generate_sequence(DataSet_Coords* OUT, - Sarray const& main_sequence, - Cpptraj::Structure::Creator const& creator) +int Exec_Sequence::old_generate_sequence(DataSet_Coords* OUT, Uarray const& Units) const { mprintf("\tUsing the old 'sequence' routine compatible with modXNA.\n"); // First, get all units in order. - typedef std::vector Uarray; - Uarray Units; - Units.reserve( main_sequence.size() ); typedef std::vector Iarray; Iarray connectAt0, connectAt1; connectAt0.reserve( Units.size() ); connectAt1.reserve( Units.size() ); int total_natom = 0; - for (Sarray::const_iterator it = main_sequence.begin(); it != main_sequence.end(); ++it) + for (Uarray::const_iterator it = Units.begin(); it != Units.end(); ++it) { - DataSet_Coords* unit = creator.IdTemplateFromName( *it ); - - if (unit == 0) { - mprinterr("Error: Unit '%s' not found.\n", it->c_str()); - return 1; - } - if (unit->Size() < 1) { - mprinterr("Error: Unit '%s' is empty.\n", unit->legend()); - return 1; - } - if (unit->Size() > 1) { - mprintf("Warning: Unit '%s' has more than 1 frame. Only using first frame.\n", unit->legend()); - } + DataSet_Coords* unit = *it; // Needs to have connect associated data AssociatedData* ad = unit->GetAssociatedData(AssociatedData::CONNECT); @@ -96,7 +79,6 @@ const // Do not update connect atom 0 indices since they will not yet be connected. connectAt0.push_back( C.Connect()[0] ); connectAt1.push_back( C.Connect()[1] + total_natom ); - Units.push_back( unit ); total_natom += unit->Top().Natom(); } // END loop over sequence mprintf("\tFound %zu units.\n", Units.size()); @@ -152,37 +134,16 @@ const /** Generate and build the specified sequence. */ int Exec_Sequence::generate_sequence(DataSet_Coords* OUT, - Sarray const& main_sequence, + std::string const& title, + Uarray const& Units, Cpptraj::Structure::Creator const& creator) const { - std::string title; - // First, get all units in order. - typedef std::vector Uarray; - Uarray Units; - Units.reserve( main_sequence.size() ); - + // First, get total atom count. int total_natom = 0; - - for (Sarray::const_iterator it = main_sequence.begin(); it != main_sequence.end(); ++it) + for (Uarray::const_iterator it = Units.begin(); it != Units.end(); ++it) { - DataSet_Coords* unit = creator.IdTemplateFromName( *it ); - - if (unit == 0) { - mprinterr("Error: Unit '%s' not found.\n", it->c_str()); - return 1; - } - if (unit->Size() < 1) { - mprinterr("Error: Unit '%s' is empty.\n", unit->legend()); - return 1; - } - if (unit->Size() > 1) { - mprintf("Warning: Unit '%s' has more than 1 frame. Only using first frame.\n", unit->legend()); - } - Units.push_back( unit ); - // Use the first unit name as title to match leap behavior - if (title.empty()) - title = *it; + DataSet_Coords* unit = *it; total_natom += unit->Top().Natom(); } // END loop over sequence mprintf("\tFound %zu units.\n", Units.size()); @@ -401,6 +362,7 @@ Exec::RetType Exec_Sequence::Execute(CpptrajState& State, ArgList& argIn) return CpptrajState::ERR; } } + std::string title = argIn.GetStringKey("title"); // GB radii set. Default to mbondi Cpptraj::Parm::GB_Params gbradii; if (gbradii.Init_GB_Radii(argIn, Cpptraj::Parm::UNKNOWN_GB)) return CpptrajState::ERR; @@ -440,6 +402,9 @@ Exec::RetType Exec_Sequence::Execute(CpptrajState& State, ArgList& argIn) mprintf(" %s", it->c_str()); mprintf("\n"); mprintf("\tOutput set name : %s\n", OUT->legend()); + // If no title, use first unit name to be consistent with leap + if (title.empty()) + title.assign( main_sequence.front() ); // Get units Uarray Units; @@ -453,10 +418,10 @@ Exec::RetType Exec_Sequence::Execute(CpptrajState& State, ArgList& argIn) switch (mode_) { case UNSPECIFIED : case NEW: - err = generate_sequence(OUT, main_sequence, creator); + err = generate_sequence(OUT, title, Units, creator); break; case OLD: - err = old_generate_sequence(OUT, main_sequence, creator); + err = old_generate_sequence(OUT, Units); break; } if (err != 0) { diff --git a/src/Exec_Sequence.h b/src/Exec_Sequence.h index 8c7d203b12..23ff3d14e2 100644 --- a/src/Exec_Sequence.h +++ b/src/Exec_Sequence.h @@ -15,14 +15,14 @@ class Exec_Sequence : public Exec { RetType Execute(CpptrajState&, ArgList&); private: typedef std::vector Sarray; - typedef std::vector Uarray; + typedef std::vector Uarray; enum ModeType { UNSPECIFIED = 0, NEW, OLD }; int get_units(Uarray&, Sarray const&, Cpptraj::Structure::Creator const&) const; - int old_generate_sequence(DataSet_Coords*, Sarray const&, Cpptraj::Structure::Creator const&) const; + int old_generate_sequence(DataSet_Coords*, Uarray const&) const; - int generate_sequence(DataSet_Coords*, Sarray const&, Cpptraj::Structure::Creator const&) const; + int generate_sequence(DataSet_Coords*, std::string const& title, Uarray const&, Cpptraj::Structure::Creator const&) const; int debug_; ModeType mode_; From 203d354fb8d0327ef9ba66cd8a42dc30fa5179a7 Mon Sep 17 00:00:00 2001 From: "Daniel R. Roe" Date: Thu, 12 Mar 2026 11:12:09 -0400 Subject: [PATCH 15/19] If no other sequence mode specified and modxna info is present, force the old sequence mode --- src/Exec_Sequence.cpp | 8 ++++++-- src/Exec_Sequence.h | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Exec_Sequence.cpp b/src/Exec_Sequence.cpp index b97c1c0a11..6d6683f8da 100644 --- a/src/Exec_Sequence.cpp +++ b/src/Exec_Sequence.cpp @@ -15,7 +15,6 @@ Exec_Sequence::Exec_Sequence() : Exec(COORDS), debug_(0), mode_(UNSPECIFIED) {} int Exec_Sequence::get_units(Uarray& Units, Sarray const& main_sequence, Cpptraj::Structure::Creator const& creator) -const { // First, get all units in order. Units.clear(); @@ -36,8 +35,13 @@ const if (unit->Size() > 1) { mprintf("Warning: Unit '%s' has more than 1 frame. Only using first frame.\n", unit->legend()); } - if (unit->Top().Modxna().HasModxna()) + if (unit->Top().Modxna().HasModxna()) { mprintf("\tUnit '%s' has ModXNA info.\n", unit->legend()); + if (mode_ == UNSPECIFIED) { + mprintf("Warning: No sequence mode specified and ModXNA info detected; using old sequence mode.\n"); + mode_ = OLD; + } + } Units.push_back( unit ); } // END loop over sequence mprintf("\tFound %zu units.\n", Units.size()); diff --git a/src/Exec_Sequence.h b/src/Exec_Sequence.h index 23ff3d14e2..e2e45d8ae5 100644 --- a/src/Exec_Sequence.h +++ b/src/Exec_Sequence.h @@ -18,7 +18,7 @@ class Exec_Sequence : public Exec { typedef std::vector Uarray; enum ModeType { UNSPECIFIED = 0, NEW, OLD }; - int get_units(Uarray&, Sarray const&, Cpptraj::Structure::Creator const&) const; + int get_units(Uarray&, Sarray const&, Cpptraj::Structure::Creator const&); int old_generate_sequence(DataSet_Coords*, Uarray const&) const; From 600e1b73c83a488c7ea5ac656b62b6fae6d36ac9 Mon Sep 17 00:00:00 2001 From: "Daniel R. Roe" Date: Thu, 12 Mar 2026 11:22:08 -0400 Subject: [PATCH 16/19] Add notes to the v7 changelog about changes made specifically to maintain backwards compatbility with modXNA --- doc/ChangeLog.v7.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/doc/ChangeLog.v7.md b/doc/ChangeLog.v7.md index 2665ef855b..21382198e7 100644 --- a/doc/ChangeLog.v7.md +++ b/doc/ChangeLog.v7.md @@ -85,3 +85,17 @@ Not Yet Ready - Introduce the `byatom` keyword to `checkchirality` action to check the chirality of any atoms in specified mask that are chiral centers. - Cannot yet build topology files for polarizable force fields (IPOL > 0). + +ModXNA Compatibility +==================== +The old `sequence` command functionality and some new features have been added to ensure backwards compatibility with ModXNA (V1.9.2 as of right now). + +The following files/classes/functions have been retained from CPPTRAJ V6.31.0 with very few changes: `Structure/BuildAtom.h`, `Structure/Model.h`, `Structure/Model.cpp` + +The `OldBuilder` class in `Structure/OldBuilder.cpp` and `Structure/OldBuilder.h` is the `Builder` class from CPPTRAJ V6.31.0. + +The `Zmatrix::SetupICsAroundBond()` function has been retained from CPPTRAJ V6.31.0 `Zmatrix` class so that `sequence` can be made to work the way it used to. + +Default bond Req parameters are set when reading in mol2 files. This is needed so that the RK/REQ columns are printed for the `bonds` command, which is expected/needed for modxna.sh to determine the name of the H atom bonded to O3' (`--3cap` flag). + +ModXNA metadata (head/tail/anchor atom information) will be read from the title of Mol2 files if present and retained in the Topology. This metadata will be written back out to Mol2 files if another title has not been specified. This allows the `sequence` command to automatically recognized when units have ModXNA information and switch back to the old `sequence` mode automatically. From b2011ec9ab9cc980e7e8c9cb3a16a3512f680ecd Mon Sep 17 00:00:00 2001 From: "Daniel R. Roe" Date: Thu, 12 Mar 2026 11:23:01 -0400 Subject: [PATCH 17/19] Version 7.1.0. Minor version bump since cpptraj will produce different (and backwards compatible) output for ModXNA with 7.1.0 compared to 7.00.0. --- src/Version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Version.h b/src/Version.h index 1fe64fc8a6..09fd3ebeda 100644 --- a/src/Version.h +++ b/src/Version.h @@ -12,7 +12,7 @@ * Whenever a number that precedes is incremented, all subsequent * numbers should be reset to 0. */ -#define CPPTRAJ_INTERNAL_VERSION "V7.00.0" +#define CPPTRAJ_INTERNAL_VERSION "V7.1.0" /// PYTRAJ relies on this #define CPPTRAJ_VERSION_STRING CPPTRAJ_INTERNAL_VERSION #endif From 11613207a7c14099d39f776a7ce91b46df90591b Mon Sep 17 00:00:00 2001 From: "Daniel R. Roe" Date: Thu, 12 Mar 2026 11:52:44 -0400 Subject: [PATCH 18/19] ModXNA test --- test/Test_ModXNA/RunTest.sh | 44 +++++++++++++ test/Test_ModXNA/tmp.BackboneSugar.mol2 | 49 ++++++++++++++ test/Test_ModXNA/tmp.Nucleotide.mol2.save | 79 +++++++++++++++++++++++ test/Test_ModXNA/tmp.base-striped.mol2 | 40 ++++++++++++ test/Test_ModXNA/tmp.bonds.save | 2 + 5 files changed, 214 insertions(+) create mode 100755 test/Test_ModXNA/RunTest.sh create mode 100644 test/Test_ModXNA/tmp.BackboneSugar.mol2 create mode 100644 test/Test_ModXNA/tmp.Nucleotide.mol2.save create mode 100644 test/Test_ModXNA/tmp.base-striped.mol2 create mode 100644 test/Test_ModXNA/tmp.bonds.save diff --git a/test/Test_ModXNA/RunTest.sh b/test/Test_ModXNA/RunTest.sh new file mode 100755 index 0000000000..a076d2389c --- /dev/null +++ b/test/Test_ModXNA/RunTest.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +. ../MasterTest.sh + +TESTNAME='ModXNA tests' + +# These tests will help ensure compatability with the modxna.sh driver script. + +CleanFiles cpptraj.in tmp.bonds tmp.Nucleotide.mol2 + +INPUT='-i cpptraj.in' + +UNITNAME="Ensure 'sequence' works for ModXNA" +CheckFor maxthreads 1 +if [ $? -eq 0 ] ; then + cat > cpptraj.in <MOLECULE +Cpptraj Generated mol2 file. + 19 19 1 0 0 +SMALL +USER_CHARGES + + +@ATOM + 1 P -2.7515 2.5361 1.1902 P 1 AD3 1.165356 + 2 OP1 -3.2333 3.1586 -0.0665 O2 1 AD3 -0.776462 + 3 OP2 -2.2870 3.4684 2.2360 O2 1 AD3 -0.776462 + 4 O5' -1.6064 1.4790 0.8528 OS 1 AD3 -0.495631 + 5 C5' -1.8840 0.8600 -0.4060 CJ 1 AD3 -0.008126 + 6 H5' -1.8990 1.6040 -1.1900 H1 1 AD3 0.062001 + 7 H5'' -2.8510 0.3600 -0.4020 H1 1 AD3 0.062001 + 8 C4' -0.7910 -0.1490 -0.7280 CT 1 AD3 0.133952 + 9 H4' -1.1020 -0.7030 -1.6130 H1 1 AD3 0.096702 + 10 O4' 0.4020 0.5340 -1.0090 OS 1 AD3 -0.434692 + 11 C1' 1.4780 0.0560 -0.2260 CT 1 AD3 0.035441 + 12 C3' -0.4660 -1.1380 0.4090 C7 1 AD3 0.058629 + 13 H3' -1.2760 -1.2130 1.1320 H1 1 AD3 0.080996 + 14 C2' 0.8030 -0.5470 1.0040 CT 1 AD3 -0.100576 + 15 H2' 0.5540 0.2380 1.7080 HC 1 AD3 0.059041 + 16 O3' -0.1480 -2.4180 -0.0780 OH 1 AD3 -0.616176 + 17 HO3' -0.8860 -2.7790 -0.5500 HO 1 AD3 0.348720 + 18 H1' 1.9910 -0.7280 -0.7770 H2 1 AD3 0.151137 + 19 H2'' 1.4000 -1.3010 1.5000 HC 1 AD3 0.059041 +@BOND + 1 1 4 1 + 2 1 2 1 + 3 1 3 1 + 4 5 8 1 + 5 8 10 1 + 6 8 12 1 + 7 10 11 1 + 8 11 14 1 + 9 12 14 1 + 10 12 16 1 + 11 4 5 1 + 12 5 6 1 + 13 5 7 1 + 14 8 9 1 + 15 11 18 1 + 16 12 13 1 + 17 14 15 1 + 18 14 19 1 + 19 16 17 1 +@SUBSTRUCTURE + 1 AD3 1 **** 0 **** **** diff --git a/test/Test_ModXNA/tmp.Nucleotide.mol2.save b/test/Test_ModXNA/tmp.Nucleotide.mol2.save new file mode 100644 index 0000000000..92b484d804 --- /dev/null +++ b/test/Test_ModXNA/tmp.Nucleotide.mol2.save @@ -0,0 +1,79 @@ +@MOLECULE +Cpptraj Generated mol2 file. + 33 35 1 0 0 +SMALL +USER_CHARGES + + +@ATOM + 1 N9 2.7158 0.0933 -1.0181 N* 1 AD3 -0.026798 + 2 C8 2.4424 0.5815 -2.2741 C2 1 AD3 0.160711 + 3 H8 1.4463 0.8516 -2.5490 H5 1 AD3 0.187713 + 4 N7 4.5155 0.1983 -2.3242 NB 1 AD3 -0.617458 + 5 C5 4.8580 -0.2966 -1.0811 CB 1 AD3 0.072505 + 6 C6 6.0644 -0.7292 -0.5214 CA 1 AD3 0.689747 + 7 N6 7.2280 -0.6908 -1.1973 N2 1 AD3 -0.912238 + 8 H61 8.0090 -1.1650 -0.8043 H 1 AD3 0.416728 + 9 H62 7.2128 -0.5332 -2.1787 H 1 AD3 0.416728 + 10 N1 6.0630 -1.1730 0.7300 NC 1 AD3 -0.762348 + 11 C2 4.9178 -1.1767 1.4002 CQ 1 AD3 0.571639 + 12 H2 4.9793 -1.5432 2.4089 H5 1 AD3 0.059804 + 13 N3 3.7288 -0.7952 0.9951 NC 1 AD3 -0.741649 + 14 C4 3.7527 -0.3673 -0.2635 CB 1 AD3 0.380026 + 15 P -2.7515 2.5361 1.1902 P 1 AD3 1.165356 + 16 OP1 -3.2333 3.1586 -0.0665 O2 1 AD3 -0.776462 + 17 OP2 -2.2870 3.4684 2.2360 O2 1 AD3 -0.776462 + 18 O5' -1.6064 1.4790 0.8528 OS 1 AD3 -0.495631 + 19 C5' -1.8840 0.8600 -0.4060 CJ 1 AD3 -0.008126 + 20 H5' -1.8990 1.6040 -1.1900 H1 1 AD3 0.062001 + 21 H5'' -2.8510 0.3600 -0.4020 H1 1 AD3 0.062001 + 22 C4' -0.7910 -0.1490 -0.7280 CT 1 AD3 0.133952 + 23 H4' -1.1020 -0.7030 -1.6130 H1 1 AD3 0.096702 + 24 O4' 0.4020 0.5340 -1.0090 OS 1 AD3 -0.434692 + 25 C1' 1.4780 0.0560 -0.2260 CT 1 AD3 0.035441 + 26 C3' -0.4660 -1.1380 0.4090 C7 1 AD3 0.058629 + 27 H3' -1.2760 -1.2130 1.1320 H1 1 AD3 0.080996 + 28 C2' 0.8030 -0.5470 1.0040 CT 1 AD3 -0.100576 + 29 H2' 0.5540 0.2380 1.7080 HC 1 AD3 0.059041 + 30 O3' -0.1480 -2.4180 -0.0780 OH 1 AD3 -0.400000 + 31 HO3' -0.8860 -2.7790 -0.5500 HO 1 AD3 0.452888 + 32 H1' 1.9910 -0.7280 -0.7770 H2 1 AD3 0.151137 + 33 H2'' 1.4000 -1.3010 1.5000 HC 1 AD3 0.059041 +@BOND + 1 1 2 1 + 2 1 14 1 + 3 2 4 1 + 4 4 5 1 + 5 5 6 1 + 6 5 14 1 + 7 6 7 1 + 8 6 10 1 + 9 10 11 1 + 10 11 13 1 + 11 13 14 1 + 12 15 18 1 + 13 15 16 1 + 14 15 17 1 + 15 19 22 1 + 16 22 24 1 + 17 22 26 1 + 18 24 25 1 + 19 25 28 1 + 20 26 28 1 + 21 26 30 1 + 22 18 19 1 + 23 1 25 1 + 24 2 3 1 + 25 7 8 1 + 26 7 9 1 + 27 11 12 1 + 28 19 20 1 + 29 19 21 1 + 30 22 23 1 + 31 25 32 1 + 32 26 27 1 + 33 28 29 1 + 34 28 33 1 + 35 30 31 1 +@SUBSTRUCTURE + 1 AD3 1 **** 0 **** **** diff --git a/test/Test_ModXNA/tmp.base-striped.mol2 b/test/Test_ModXNA/tmp.base-striped.mol2 new file mode 100644 index 0000000000..b057e0eadd --- /dev/null +++ b/test/Test_ModXNA/tmp.base-striped.mol2 @@ -0,0 +1,40 @@ +@MOLECULE +modXNA-fragment:DAA:HEAD01:@N9:HEAD01STRIP:@C1',H1',O4',HHO4,C2',H2'1,H2'3,H2'2 + 14 15 1 0 0 +SMALL +USER_CHARGES + + +@ATOM + 1 N9 -1.1080 -0.2670 0.1170 N* 1 DAA -0.026798 + 2 C8 -0.8260 -1.6030 -0.0450 C2 1 DAA 0.160711 + 3 H8 -1.6110 -2.3270 -0.0670 H5 1 DAA 0.187713 + 4 N7 0.4250 -1.8610 -0.1380 NB 1 DAA -0.617458 + 5 C5 1.0350 -0.6260 -0.0370 CB 1 DAA 0.072505 + 6 C6 2.3710 -0.2130 -0.0570 CA 1 DAA 0.689747 + 7 N6 3.3900 -1.0750 -0.2320 N2 1 DAA -0.912238 + 8 H61 4.3130 -0.7420 -0.0690 H 1 DAA 0.416728 + 9 H62 3.2170 -2.0510 -0.1560 H 1 DAA 0.416728 + 10 N1 2.6400 1.0800 0.0800 NC 1 DAA -0.762348 + 11 C2 1.6280 1.9270 0.2190 CQ 1 DAA 0.571639 + 12 H2 1.9070 2.9600 0.3220 H5 1 DAA 0.059804 + 13 N3 0.3410 1.6700 0.2480 NC 1 DAA -0.741649 + 14 C4 0.0970 0.3690 0.1220 CB 1 DAA 0.380026 +@BOND + 1 1 2 1 + 2 1 14 1 + 3 2 4 1 + 4 4 5 1 + 5 5 6 1 + 6 5 14 1 + 7 6 7 1 + 8 6 10 1 + 9 10 11 1 + 10 11 13 1 + 11 13 14 1 + 12 2 3 1 + 13 7 8 1 + 14 7 9 1 + 15 11 12 1 +@SUBSTRUCTURE + 1 DAA 1 **** 0 **** **** diff --git a/test/Test_ModXNA/tmp.bonds.save b/test/Test_ModXNA/tmp.bonds.save new file mode 100644 index 0000000000..36707c6afb --- /dev/null +++ b/test/Test_ModXNA/tmp.bonds.save @@ -0,0 +1,2 @@ +#Bnd RK REQ Atom1 Atom2 A1 A2 T1 T2 + 4 0.00 1.090 :1@C1' :1@H1' 11 18 CT H2 From 4513fdea9444f595bf19d33b2bb6ce852368554c Mon Sep 17 00:00:00 2001 From: "Daniel R. Roe" Date: Thu, 12 Mar 2026 11:53:21 -0400 Subject: [PATCH 19/19] Enable modxna test --- test/Makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/Makefile b/test/Makefile index b781b9f8f0..d0859c944d 100644 --- a/test/Makefile +++ b/test/Makefile @@ -567,6 +567,9 @@ test.mutate: test.build: @-cd Test_Build && ./RunTest.sh $(OPT) +test.modxna: + @-cd Test_ModXNA && ./RunTest.sh $(OPT) + # Only GPU-specific tests should go here GPUTESTS=test.closest \ test.solvent \ @@ -753,7 +756,8 @@ COMPLETETESTS=test.general \ test.minmaxdist \ test.watershellclosest \ test.mutate \ - test.build + test.build \ + test.modxna test.all: $(MAKE) test.complete summary